[IMP] todo: integrate mark as done in To-do app
A new field component is designed to offer a simple usage of mark as done (i.e. only 'done' and 'not done'). This component is used in the Todo app (in both form and kanban view) to change the state of todos (private tasks). Behavior details: - When the button is checked, the state of the todo is changed to 01_done - When the button is unchecked, the state is restored to its initial value if it is different to '01_done' or to '01_in_progress' instead. task-3085077
This commit is contained in:
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="todo.TodoDoneCheckmark" owl="1">
|
||||
<t t-if="!env.isSmall">
|
||||
<a title="Mark as done"
|
||||
t-on-click.stop="onDoneToggled"
|
||||
t-on-mouseleave="actualizeDoneState"
|
||||
t-on-mouseover="freezeDoneState"
|
||||
t-attf-class="o_todo_done_button fa fa-lg fa-check-circle{{!stateDone.isDone ? '-o' : ' done_button_enabled'}}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<a title="Mark as done"
|
||||
t-on-click.stop="onDoneToggled"
|
||||
t-attf-class="o_todo_done_button_mobile fa fa-lg fa-check-circle{{!stateDone.isDone ? '-o' : ' done_button_enabled'}}"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -13,8 +13,8 @@
|
||||
<t t-name="todo.TodoBreadcrumbs" t-inherit="web.Breadcrumbs" t-inherit-mode="primary" owl="1">
|
||||
<xpath expr="//div[hasclass('o_last_breadcrumb_item')]//span" position="replace">
|
||||
<t t-slot="control-panel-todo-name" />
|
||||
<t t-slot="todo-mark-as-done-button" />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
id="'name'"
|
||||
/>
|
||||
</t>
|
||||
<t t-set-slot="todo-mark-as-done-button">
|
||||
<t t-set="record" t-value="model.root"/>
|
||||
<TodoDoneCheckmark
|
||||
name="'state'"
|
||||
record="record"
|
||||
id="'state'"
|
||||
viewType="'form'"
|
||||
/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
editable="bottom"
|
||||
multi_edit="1"
|
||||
js_class="todo_list">
|
||||
<field name="state" widget="todo_done_checkmark" nolabel="1" options="{'hide_label': 1}"/>
|
||||
<field name="name"/>
|
||||
<field name="user_ids" optional="show" widget="many2many_avatar_user" options="{'no_quick_create': True}"/>
|
||||
<field name="tag_ids" optional="show" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
|
||||
@@ -118,6 +119,7 @@
|
||||
widget="statusbar"
|
||||
options="{'clickable': '1', 'fold_field': 'fold'}"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
</header>
|
||||
<sheet class="o_todo_form_sheet_bg">
|
||||
<widget name="web_ribbon" class="todo_archived" title="Archived" bg_color="text-bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
|
||||
Reference in New Issue
Block a user