From 3e9512b57cddbbfd70735b37b3c0b08b3e0a106a Mon Sep 17 00:00:00 2001 From: "Hugo Carlier (Huca)" Date: Wed, 15 Mar 2023 17:56:55 +0100 Subject: [PATCH] [IMP] todo: make the name of a to-do editable from the breadcrumbs In the module note, the name of a note was automatically computed based on the begining of its content. Fot the module todo, we want the name to be editable in the form view, while still keeping a clean interface for the form. This commit makes therefore the name of a to-do directly editable in the breadcrumbs. The behavior is a mix between the editable breadcrumb name in Spreadsheet and the classical edition behavior for a field in a form view, i.e: - When creating a new to-do, a placeholder for the name is set to _Untitled to-do_. A name must be entered before saving the record. - A name entered in the Breadcrumb will be saved either if the save button is pressed, either when the form view is quit. - The discard button allows to go back to the last saved name. The implementation relies, for its biggest part, on a new component inheriting _CharField_ that copies some functions from the component _SpreadsheetName_ used in Spreadsheet (see task-2621549) for the edition part and use the autoResize hook from discuss recently moved into the framework (see https://github.com/odoo/odoo/pull/117355). The rest of the implementation consists of overrides of _FormControlPanel_, _FormController_ and _formView_ to adapt the use of this input field in the context of a form view (>< Spreadsheet). task-3085077 --- addons/todo/__manifest__.py | 1 + .../todo_editable_breadcrumb_name.js | 57 +++++++++++++++++++ .../todo_editable_breadcrumb_name.scss | 30 ++++++++++ .../todo_editable_breadcrumb_name.xml | 14 +++++ .../todo_form/todo_form_control_panel.js | 7 +++ .../todo_form/todo_form_control_panel.xml | 20 +++++++ .../views/todo_form/todo_form_controller.js | 14 +++++ .../views/todo_form/todo_form_controller.xml | 18 ++++++ .../src/views/todo_form/todo_form_view.js | 14 +++++ addons/todo/views/project_task_views.xml | 1 + 10 files changed, 176 insertions(+) create mode 100644 addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.js create mode 100644 addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.scss create mode 100644 addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.xml create mode 100644 addons/todo/static/src/views/todo_form/todo_form_control_panel.js create mode 100644 addons/todo/static/src/views/todo_form/todo_form_control_panel.xml create mode 100644 addons/todo/static/src/views/todo_form/todo_form_controller.js create mode 100644 addons/todo/static/src/views/todo_form/todo_form_controller.xml create mode 100644 addons/todo/static/src/views/todo_form/todo_form_view.js diff --git a/addons/todo/__manifest__.py b/addons/todo/__manifest__.py index ba50ea0aaf5..401bb97f71e 100644 --- a/addons/todo/__manifest__.py +++ b/addons/todo/__manifest__.py @@ -23,6 +23,7 @@ 'uninstall_hook': '_todo_uninstall', 'assets': { 'web.assets_backend': [ + 'todo/static/src/components/**/*', 'todo/static/src/scss/todo.scss', 'todo/static/src/views/**/*', 'todo/static/src/web/**/*', diff --git a/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.js b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.js new file mode 100644 index 00000000000..cbc7bc72c06 --- /dev/null +++ b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.js @@ -0,0 +1,57 @@ +/** @odoo-module */ + +import { useState, onRendered, useRef } from "@odoo/owl"; + +import { _lt } from "@web/core/l10n/translation"; +import { CharField } from "@web/views/fields/char/char_field"; +import { useAutoresize } from "@web/core/utils/autoresize"; + +export class TodoEditableBreadcrumbName extends CharField { + setup() { + super.setup(); + this.placeholder = _lt("Untitled to-do");; + this.input = useRef("input"); + + this.stateTodo = useState({ + isUntitled: true, + }); + + onRendered(() => { + this.stateTodo.isUntitled = this._isUntitled(this.props.record.data[this.props.name]); + }); + useAutoresize(this.input); + } + + /** + * Check if the name is empty or is the generic name + * for untitled todos. + * @param {string} name + * @returns {boolean} + */ + _isUntitled(name) { + name = name && name.trim(); + return !name || name === this.placeholder.toString(); + } + + /** + * @private + * @param {InputEvent} ev + */ + _onFocus(ev) { + if (this._isUntitled(ev.target.value)) { + ev.target.value = this.placeholder; + ev.target.select(); + } + } + + /** + * @private + * @param {InputEvent} ev + */ + _onInput(ev) { + const value = ev.target.value; + this.stateTodo.isUntitled = this._isUntitled(value); + } +} + +TodoEditableBreadcrumbName.template = 'todo.TodoEditableBreadcrumbName'; diff --git a/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.scss b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.scss new file mode 100644 index 00000000000..6d70e1dab9c --- /dev/null +++ b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.scss @@ -0,0 +1,30 @@ +.o_todo_breadcrumb_name_input{ + width: 100%; + text-overflow: clip; + overflow: hidden; + border: none; + padding: 0px 5px 0px 2px; + color: $o-brand-secondary; + + &:focus { + outline: 1px solid #ccc; + outline-offset: -1px; + color: $dark; + } + + &.o-todo-untitled { + font-style: italic; + } + + &.o-todo-untitled:focus { + font-style: normal; + } + + &:disabled { + background-color: inherit; + } +} + +.o_todo_breadcrumb_name_input:hover { + border-bottom: $input-border-width solid $o-brand-primary; +} diff --git a/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.xml b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.xml new file mode 100644 index 00000000000..2f38217d305 --- /dev/null +++ b/addons/todo/static/src/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name.xml @@ -0,0 +1,14 @@ + + + + + + o_input o_todo_breadcrumb_name_input + _onFocus + placeholder + _onInput + stateTodo.isUntitled ? 'o-todo-untitled' : '' + + + + diff --git a/addons/todo/static/src/views/todo_form/todo_form_control_panel.js b/addons/todo/static/src/views/todo_form/todo_form_control_panel.js new file mode 100644 index 00000000000..469abf2149d --- /dev/null +++ b/addons/todo/static/src/views/todo_form/todo_form_control_panel.js @@ -0,0 +1,7 @@ +/** @odoo-module **/ + +import { ControlPanel } from "@web/search/control_panel/control_panel"; + +export class TodoFormControlPanel extends ControlPanel { + static template = "todo.TodoFormControlPanel"; +} diff --git a/addons/todo/static/src/views/todo_form/todo_form_control_panel.xml b/addons/todo/static/src/views/todo_form/todo_form_control_panel.xml new file mode 100644 index 00000000000..521e7c6c4ef --- /dev/null +++ b/addons/todo/static/src/views/todo_form/todo_form_control_panel.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/addons/todo/static/src/views/todo_form/todo_form_controller.js b/addons/todo/static/src/views/todo_form/todo_form_controller.js new file mode 100644 index 00000000000..2efa8b70bd8 --- /dev/null +++ b/addons/todo/static/src/views/todo_form/todo_form_controller.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +import { FormController } from "@web/views/form/form_controller"; +import { TodoEditableBreadcrumbName } from "@todo/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name"; + +/** + * The FormController is overridden to be able to manage the edition of the name of a to-do directly + * in the breadcrumb. + */ + +export class TodoFormController extends FormController {} + +Object.assign(TodoFormController.components, { TodoEditableBreadcrumbName }); +TodoFormController.template = 'todo.TodoFormView'; diff --git a/addons/todo/static/src/views/todo_form/todo_form_controller.xml b/addons/todo/static/src/views/todo_form/todo_form_controller.xml new file mode 100644 index 00000000000..f06b173bfd0 --- /dev/null +++ b/addons/todo/static/src/views/todo_form/todo_form_controller.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/addons/todo/static/src/views/todo_form/todo_form_view.js b/addons/todo/static/src/views/todo_form/todo_form_view.js new file mode 100644 index 00000000000..533f6f7dded --- /dev/null +++ b/addons/todo/static/src/views/todo_form/todo_form_view.js @@ -0,0 +1,14 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { formView } from "@web/views/form/form_view"; +import { TodoFormControlPanel } from "./todo_form_control_panel"; +import { TodoFormController } from "./todo_form_controller"; + +export const todoFormView = { + ...formView, + ControlPanel: TodoFormControlPanel, + Controller: TodoFormController, +}; + +registry.category("views").add("todo_form", todoFormView); diff --git a/addons/todo/views/project_task_views.xml b/addons/todo/views/project_task_views.xml index b562fe527df..7b519af5573 100644 --- a/addons/todo/views/project_task_views.xml +++ b/addons/todo/views/project_task_views.xml @@ -98,6 +98,7 @@
+