diff --git a/project_ux/models/project_task.py b/project_ux/models/project_task.py index 7b44724d..5e23329e 100644 --- a/project_ux/models/project_task.py +++ b/project_ux/models/project_task.py @@ -79,6 +79,24 @@ def _compute_display_name(self): if task.project_id.show_task_id and task.id and task.display_name: task.display_name = f"{task.display_name} (#{task.id})" + def onchange(self, values, field_names, fields_spec): + result = super().onchange(values, field_names, fields_spec) + # In the quick-create (My Tasks, project kanban) the "Task Title" input + # is bound to display_name and is only inversed into `name` on save. + # Because this module makes display_name depend on project_id (to append + # the task id), changing the project recomputes display_name from the + # still-empty `name`, blanking the title the user just typed. Restore the + # typed value in the onchange result so it survives the project change. + typed_title = values.get("display_name") + if ( + "project_id" in (field_names or []) + and typed_title + and not values.get("name") + and not result.get("value", {}).get("display_name") + ): + result.setdefault("value", {})["display_name"] = typed_title + return result + @api.model def _search_display_name(self, operator, value): domain = super()._search_display_name(operator, value) diff --git a/project_ux/tests/__init__.py b/project_ux/tests/__init__.py index 7a25d85b..41f2124c 100644 --- a/project_ux/tests/__init__.py +++ b/project_ux/tests/__init__.py @@ -1,2 +1,3 @@ from . import test_project_task from . import test_project_task_type +from . import test_project_project diff --git a/project_ux/tests/test_project_project.py b/project_ux/tests/test_project_project.py new file mode 100644 index 00000000..99921169 --- /dev/null +++ b/project_ux/tests/test_project_project.py @@ -0,0 +1,28 @@ +from odoo.tests.common import TransactionCase + + +class TestProjectProject(TransactionCase): + def setUp(self): + super().setUp() + self.Project = self.env["project.project"] + + def test_create_project_modal_button_opens_form(self): + """The "Create project" button of the New modal must open the project + form (via the standard get_formview_action), not the task pipeline + (action_view_tasks). + """ + view = self.env.ref("project.project_project_view_form_simplified_footer") + combined_arch = view.get_combined_arch() + self.assertIn('name="get_formview_action"', combined_arch) + self.assertNotIn('name="action_view_tasks"', combined_arch) + + def test_get_formview_action_lands_on_project_form(self): + """get_formview_action opens the created project's own form.""" + project = self.Project.create({"name": "New Project"}) + + action = project.get_formview_action() + + self.assertEqual(action["res_model"], "project.project") + self.assertEqual(action["res_id"], project.id) + self.assertEqual(action["target"], "current") + self.assertTrue(any(view_type == "form" for __, view_type in action["views"])) diff --git a/project_ux/tests/test_project_task.py b/project_ux/tests/test_project_task.py index be4e4477..24f9a75f 100644 --- a/project_ux/tests/test_project_task.py +++ b/project_ux/tests/test_project_task.py @@ -1,3 +1,4 @@ +from odoo.tests import Form from odoo.tests.common import TransactionCase @@ -94,3 +95,24 @@ def test_name_search_does_not_find_task_by_id_when_disabled_on_project(self): result_ids = [task_id for task_id, __ in self.Task.name_search(str(self.test_task.id), limit=20)] self.assertNotIn(self.test_task.id, result_ids) + + def _check_quick_create_keeps_title(self, title): + """Quick-create binds the "Task Title" to display_name (not name). + Selecting/changing the project must not wipe a title already typed. + """ + with Form(self.Task, view="project.quick_create_task_form") as task_form: + task_form.display_name = title + task_form.project_id = self.test_project + self.assertEqual(task_form.display_name, title) + task = task_form.record + self.assertEqual(task.name, title) + self.assertEqual(task.project_id, self.test_project) + + def test_quick_create_keeps_title_when_selecting_project(self): + self._check_quick_create_keeps_title("My Title") + + def test_quick_create_keeps_title_when_project_shows_task_id(self): + # The title must survive the project onchange even though display_name + # depends on project_id.show_task_id. + self.test_project.show_task_id = True + self._check_quick_create_keeps_title("Another Title") diff --git a/project_ux/views/project_project_views.xml b/project_ux/views/project_project_views.xml index 8bbc9cac..3d19129f 100644 --- a/project_ux/views/project_project_views.xml +++ b/project_ux/views/project_project_views.xml @@ -60,4 +60,19 @@ + + + project.project.view.form.simplified.open.form + project.project + + + + get_formview_action + + + +