diff --git a/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.js b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.js
new file mode 100644
index 00000000000..829bcd58e17
--- /dev/null
+++ b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.js
@@ -0,0 +1,75 @@
+/** @odoo-module */
+
+import { useState, onRendered, onMounted } from "@odoo/owl";
+import { registry } from "@web/core/registry";
+import { StateSelectionField, stateSelectionField } from "@web/views/fields/state_selection/state_selection_field";
+
+export class TodoDoneCheckmark extends StateSelectionField {
+ setup() {
+ super.setup();
+ this.stateDone = useState({
+ isDone: false, //This state determines the appearance of the done checkmark and should only be actualized when the mouse leaves it (and atfer the form is loaded)
+ notReloadState: false, //used to avoid a change of the checkmark when re-rendering the form
+ });
+ onMounted(() => {
+ const fieldValue = this.props.record.data[this.props.name]
+ this.notDoneState = fieldValue == '1_done' ? '01_in_progress' : fieldValue;
+ });
+ onRendered(() => {
+ if (!this.stateDone.notReloadState) {
+ this.stateDone.isDone = this.props.record.data[this.props.name] == '1_done';
+ }
+ });
+ }
+
+ /**
+ * @private
+ * @param {InputEvent} ev
+ */
+ actualizeDoneState(ev) {
+ this.stateDone.notReloadState = false;
+ }
+
+ /**
+ * @private
+ * @param {InputEvent} ev
+ */
+ freezeDoneState(ev) {
+ this.stateDone.notReloadState = true;
+ }
+
+ /**
+ * @private
+ * @param {InputEvent} ev
+ */
+ async onDoneToggled(ev) {
+ const value = this.props.record.data[this.props.name] != '1_done' ? '1_done' : this.notDoneState;
+ if (['kanban', 'list'].includes(this.props.viewType)) {
+ await super.updateRecord(value);
+ }
+ else {
+ await this.props.record.update({
+ [this.props.name]: value,
+ });
+ }
+ }
+}
+
+TodoDoneCheckmark.template = 'todo.TodoDoneCheckmark';
+
+TodoDoneCheckmark.props = {
+ ...stateSelectionField.component.props,
+ viewType: { type: String },
+}
+
+export const todoDoneCheckmark = {
+ ...stateSelectionField,
+ component: TodoDoneCheckmark,
+ extractProps: (fieldInfo, dynamicInfo) => {
+ const props = stateSelectionField.extractProps(fieldInfo, dynamicInfo);
+ props.viewType = fieldInfo.viewType;
+ return props;
+ },
+}
+
+registry.category("fields").add("todo_done_checkmark", todoDoneCheckmark);
diff --git a/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.scss b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.scss
new file mode 100644
index 00000000000..0957347f0e7
--- /dev/null
+++ b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.scss
@@ -0,0 +1,27 @@
+a.o_todo_done_button {
+ margin: 0px 5px;
+ @include o-hover-text-color($gray-400, $o-success);
+ &:hover:before {
+ content: "\f058";
+ }
+
+ &.done_button_enabled {
+ text-color: $o-success;
+ @include o-hover-text-color($o-success, $gray-400);
+ &:hover:before {
+ content: "\f05d";
+ }
+ }
+}
+
+a.o_todo_done_button_mobile {
+ margin: 0px 5px;
+ color: $gray-400;
+ &.done_button_enabled {
+ color: $o-success;
+ }
+}
+
+.o_todo_done_checkmark_cell {
+ width: 40px;
+}
diff --git a/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.xml b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.xml
new file mode 100644
index 00000000000..f0029bddd9c
--- /dev/null
+++ b/addons/todo/static/src/components/todo_done_checkmark/todo_done_checkmark.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
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
index 521e7c6c4ef..3710373f78e 100644
--- 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
@@ -13,8 +13,8 @@
+
-
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
index 7aed69c4da0..cc72fcb495f 100644
--- a/addons/todo/static/src/views/todo_form/todo_form_controller.js
+++ b/addons/todo/static/src/views/todo_form/todo_form_controller.js
@@ -2,11 +2,13 @@
import { FormController } from "@web/views/form/form_controller";
import { TodoEditableBreadcrumbName } from "@todo/components/todo_editable_breadcrumb_name/todo_editable_breadcrumb_name";
+import { TodoDoneCheckmark } from "@todo/components/todo_done_checkmark/todo_done_checkmark";
+
import { onWillStart } from "@odoo/owl";
/**
* The FormController is overridden to be able to manage the edition of the name of a to-do directly
- * in the breadcrumb.
+ * in the breadcrumb as well as the mark as done button next to it.
*/
export class TodoFormController extends FormController {
@@ -48,4 +50,5 @@ export class TodoFormController extends FormController {
Object.assign(TodoFormController.components, {
TodoEditableBreadcrumbName,
+ TodoDoneCheckmark,
});
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
index f06b173bfd0..9dc48203f31 100644
--- a/addons/todo/static/src/views/todo_form/todo_form_controller.xml
+++ b/addons/todo/static/src/views/todo_form/todo_form_controller.xml
@@ -12,6 +12,15 @@
id="'name'"
/>
+
+
+
+
diff --git a/addons/todo/views/project_task_views.xml b/addons/todo/views/project_task_views.xml
index 1b4b4584ed2..69d6c3c9c49 100644
--- a/addons/todo/views/project_task_views.xml
+++ b/addons/todo/views/project_task_views.xml
@@ -81,6 +81,7 @@
editable="bottom"
multi_edit="1"
js_class="todo_list">
+
@@ -118,6 +119,7 @@
widget="statusbar"
options="{'clickable': '1', 'fold_field': 'fold'}"/>
+