diff --git a/addons/project_todo/__init__.py b/addons/project_todo/__init__.py index c50aeb7438d..227fd68bc85 100644 --- a/addons/project_todo/__init__.py +++ b/addons/project_todo/__init__.py @@ -1,5 +1,6 @@ from . import controllers from . import models +from . import wizard def _todo_uninstall(env): # The record rule project.task_visibility_rule needs to apply to all rights and not just read after uninstallation diff --git a/addons/project_todo/__manifest__.py b/addons/project_todo/__manifest__.py index 85570ed0b78..091cf536d8c 100644 --- a/addons/project_todo/__manifest__.py +++ b/addons/project_todo/__manifest__.py @@ -18,6 +18,7 @@ 'data/todo_template.xml', 'views/project_task_views.xml', 'views/project_todo_menus.xml', + 'wizard/mail_activity_todo_create.xml', ], 'installable': True, 'application': True, diff --git a/addons/project_todo/security/ir.model.access.csv b/addons/project_todo/security/ir.model.access.csv index 452e7f160e7..e584ecee868 100644 --- a/addons/project_todo/security/ir.model.access.csv +++ b/addons/project_todo/security/ir.model.access.csv @@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_project_task_type_user,project.task.type.user,project.model_project_task_type,base.group_user,1,1,1,1 access_task_on_partner,project.task on partners,project.model_project_task,base.group_user,1,1,1,1 access_project_tags_user,project.project_tags_user,project.model_project_tags,base.group_user,1,1,1,1 +access_mail_activity_todo_create,mail.activity.todo.create,model_mail_activity_todo_create,base.group_user,1,1,1,0 diff --git a/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_controller.js b/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_controller.js new file mode 100644 index 00000000000..8f0a60912e1 --- /dev/null +++ b/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_controller.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +import { onMounted } from "@odoo/owl"; +import { FormController } from "@web/views/form/form_controller"; + +export class TodoActivityWizardController extends FormController { + setup() { + super.setup(); + onMounted(() => { + const firstInput = document.querySelector('div.o_field_widget input'); + firstInput.focus(); + }); + } +} diff --git a/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_view.js b/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_view.js new file mode 100644 index 00000000000..9a593be2f4f --- /dev/null +++ b/addons/project_todo/static/src/views/todo_activity_wizard/todo_activity_wizard_view.js @@ -0,0 +1,12 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { formView } from "@web/views/form/form_view"; +import { TodoActivityWizardController } from "./todo_activity_wizard_controller"; + +export const todoActivityWizardView = { + ...formView, + Controller: TodoActivityWizardController, +}; + +registry.category("views").add("todo_activity_wizard", todoActivityWizardView); diff --git a/addons/project_todo/static/src/web/activity/activity_menu_patch.js b/addons/project_todo/static/src/web/activity/activity_menu_patch.js index 0864e1eef09..306f58040a5 100644 --- a/addons/project_todo/static/src/web/activity/activity_menu_patch.js +++ b/addons/project_todo/static/src/web/activity/activity_menu_patch.js @@ -5,13 +5,21 @@ import { onExternalClick } from "@mail/utils/common/hooks"; import { ActivityMenu } from "@mail/core/web/activity_menu"; import { useEffect, useRef, useState } from "@odoo/owl"; import { DateTimeInput } from "@web/core/datetime/datetime_input"; +import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog"; +import { useCommand } from "@web/core/commands/command_hook"; import { useService } from "@web/core/utils/hooks"; import { patch } from "@web/core/utils/patch"; +import { registry } from "@web/core/registry"; + +// Add a to-do category for the command palette +registry.category("command_categories").add("to-do", {}, { sequence: 105 }); patch(ActivityMenu.prototype, { setup() { super.setup(...arguments); this.rpc = useService("rpc"); + this.orm = useService("orm"); + this.dialogService = useService("dialog"); this.state = useState({ addingTodo: false }); this.todoInputRef = useRef("todoInput"); this.addingTodoDate = false; @@ -33,6 +41,18 @@ patch(ActivityMenu.prototype, { } this.state.addingTodo = false; }); + useCommand( + _t("Add a To-Do"), + () => { + document.body.click(); // hack to close command palette + this.createActivityTodo(); + }, + { + category: "to-do", + hotkey: "alt+l", + global: true, + } + ); }, sortActivityGroups() { @@ -53,6 +73,19 @@ patch(ActivityMenu.prototype, { } }, + async createActivityTodo() { + const wizard = await this.orm.call("mail.activity.todo.create", "create", [{ + "user_id": this.userId, + }]); + this.dialogService.add(FormViewDialog, { + title: "Add a To-Do", + resModel: "mail.activity.todo.create", + resId: wizard, + preventCreate: true, + size: "md", + }); + }, + async saveTodo() { const { DateTime } = luxon; const urlRegExp = /http(s)?:\/\/(www\.)?[a-zA-Z0-9@:%_+~#=~#?&/=\-;!.]{3,2000}/g; diff --git a/addons/project_todo/wizard/__init__.py b/addons/project_todo/wizard/__init__.py new file mode 100644 index 00000000000..2bbf540d39c --- /dev/null +++ b/addons/project_todo/wizard/__init__.py @@ -0,0 +1,3 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import mail_activity_todo_create diff --git a/addons/project_todo/wizard/mail_activity_todo_create.py b/addons/project_todo/wizard/mail_activity_todo_create.py new file mode 100644 index 00000000000..929752fab76 --- /dev/null +++ b/addons/project_todo/wizard/mail_activity_todo_create.py @@ -0,0 +1,37 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, _ + +class MailActivityTodoCreate(models.TransientModel): + _name = 'mail.activity.todo.create' + _description = 'Create activity and todo at the same time' + + summary = fields.Char() + date_deadline = fields.Date('Due Date', index=True, required=True, default=fields.Date.context_today) + user_id = fields.Many2one('res.users', 'Assigned to', default=lambda self: self.env.user, required=True, readonly=True) + note = fields.Html(sanitize_style=True) + + def create_todo_activity(self): + todo = self.env['project.task'].create({ + 'name': self.summary, + 'description': self.note, + 'date_deadline': self.date_deadline, + 'user_ids': self.user_id.ids, + }) + self.env['mail.activity'].create({ + 'res_model_id': self.env['ir.model']._get('project.task').id, + 'res_id': todo.id, + 'summary': self.summary, + 'user_id': self.user_id.id, + 'date_deadline': self.date_deadline, + 'activity_type_id': self.env['mail.activity']._default_activity_type_for_model('project.task').id, + }) + + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'type': 'success', + 'message': _("Your to-do has been successfully added to your pipeline."), + }, + } diff --git a/addons/project_todo/wizard/mail_activity_todo_create.xml b/addons/project_todo/wizard/mail_activity_todo_create.xml new file mode 100644 index 00000000000..4d52deb5a1a --- /dev/null +++ b/addons/project_todo/wizard/mail_activity_todo_create.xml @@ -0,0 +1,21 @@ + + + + mail.activity.todo.create.popup + mail.activity.todo.create + +
+ + + + + + + + +
+
+