diff --git a/project_task_subtask/README.rst b/project_task_subtask/README.rst new file mode 100644 index 0000000..b0e0072 --- /dev/null +++ b/project_task_subtask/README.rst @@ -0,0 +1,116 @@ +====================== +Project Task Checklist +====================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:3a3f0575b71186dece7826cf32d1bfc8cbfa7c3076d64352bcca8a09c4fd41a9 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-it--projects--llc%2Fmisc--addons-lightgray.png?logo=github + :target: https://github.com/it-projects-llc/misc-addons/tree/14.0/project_task_subtask + :alt: it-projects-llc/misc-addons + +|badge1| |badge2| |badge3| + +Use subtasks to control your tasks. Be ensure that all your +tasks/subtasks are performed and not missed. + +Features: + +- Added new "Checklist" tab on task's form + +- When new subtask is created\\changed, message is sent to user that + assigned to this subtask + +- Only users related to subtask can change subtask parameters + +- All subtasks have a certain color, informing about their state + +- Each subtask has buttons to switch state: + +- DONE + +- TODO + +- CANCELLED + +- Added new "Checklist" menu + +- default filter: "My", "TODO" + +- optional group by: "Project", "Task", "User", "State" + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +- Create User1 and User2 in the ``Settings >> Users`` menu + +- Login as User1 + + - Go to ``Project >> Project >> All Tasks`` and open the + ``Checklist`` tab + - Create new subtask (Assigned to - User2) + +- Login as User2 + + - See message in Inbox like "TODO: subtask_name" + - Change state of subtask to Cancelled/Done + - You can see a message in Inbox "Cancelled: subtask_name" or "Done: + subtask_name" accordingly. + +- You can see your TODOs on tasks in kanban view in the + ``Project >> Project >> Tasks`` menu + +- The ``Project >> Project >> Checklist`` menu displays ALL subtasks in + state TODO assigned to you and subtasks where you are Reviewer + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* IT-Projects LLC + +Contributors +------------ + +- Ivan Yelizariev (https://github.com/yelizariev) +- Rafael Manaev (https://github.com/manawi) +- Ilmir Karamov (https://github.com/ilmir-k) +- Ildar Nasyrov (https://github.com/iledarn) +- Nicolas Jeudy (https://github.com/njeudy) +- Alexandr Kolushov (https://github.com/KolushovAlexandr) +- Almas Giniatullin (https://github.com/almas50) + +Maintainers +----------- + +This module is part of the `it-projects-llc/misc-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/project_task_subtask/__init__.py b/project_task_subtask/__init__.py new file mode 100644 index 0000000..1d99e04 --- /dev/null +++ b/project_task_subtask/__init__.py @@ -0,0 +1,3 @@ +# License MIT (https://opensource.org/licenses/MIT). + +from . import models diff --git a/project_task_subtask/__manifest__.py b/project_task_subtask/__manifest__.py new file mode 100644 index 0000000..c8bdbc7 --- /dev/null +++ b/project_task_subtask/__manifest__.py @@ -0,0 +1,20 @@ +{ + "name": """Project Task Checklist""", + "summary": """Use checklist to be ensure that all your tasks are performed and to make easy control over them""", # noqa: B950 + "category": """Project Management""", + "images": ["images/checklist_main.png"], + "version": "14.0.1.1.2", + "author": "IT-Projects LLC", + "support": "it@it-projects.info", + "website": "https://github.com/it-projects-llc/misc-addons", + "license": "LGPL-3", + "depends": ["project"], + "data": [ + "security/ir.model.access.csv", + "views/project_task_subtask.xml", + "views/assets.xml", + "data/subscription_template.xml", + ], + "qweb": ["static/src/xml/templates.xml"], + "demo": ["demo/project_task_subtask_demo.xml"], +} diff --git a/project_task_subtask/data/subscription_template.xml b/project_task_subtask/data/subscription_template.xml new file mode 100644 index 0000000..29fefad --- /dev/null +++ b/project_task_subtask/data/subscription_template.xml @@ -0,0 +1,24 @@ + + + + All checklist updates + project.task + + Subscribe to checklist updates of other users. By default you are notified + on checklist items to and from you only. + + + + + All checklist updates + + Subscribe to checklist updates of other users. By default you are notified + on checklist items to and from you only. + + 10 + project.project + + project_id + + + diff --git a/project_task_subtask/demo/project_task_subtask_demo.xml b/project_task_subtask/demo/project_task_subtask_demo.xml new file mode 100644 index 0000000..ce68a9f --- /dev/null +++ b/project_task_subtask/demo/project_task_subtask_demo.xml @@ -0,0 +1,8 @@ + + + + test subtask + + + + diff --git a/project_task_subtask/i18n/es_CR.po b/project_task_subtask/i18n/es_CR.po new file mode 100644 index 0000000..b1e723b --- /dev/null +++ b/project_task_subtask/i18n/es_CR.po @@ -0,0 +1,236 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_subtask +# +# Translators: +# Randall , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-04-30 21:57+0000\n" +"PO-Revision-Date: 2018-04-30 21:57+0000\n" +"Last-Translator: Randall , 2018\n" +"Language-Team: Spanish (Costa Rica) (https://www.transifex.com/it-projects-llc/teams/76080/es_CR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: es_CR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: project_task_subtask +#: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype +msgid "All checklist updates" +msgstr "Todas las actualizaciones de la lista de verificación" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id +msgid "Assigned to" +msgstr "Asignado a" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Cancelled" +msgstr "Cancelado" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to CANCELLED" +msgstr "Cambiar estado a CANCELADO" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to DONE" +msgstr "Cambiar estado a TERMINADO" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to TODO" +msgstr "Cambiar estado a POR HACER" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to WAITING" +msgstr "Cambiar estado a ESPERANDO" + +#. module: project_task_subtask +#: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask +#: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Checklist" +msgstr "Lista de Verificación" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date +msgid "Created on" +msgstr "Creado en" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline +msgid "Deadline" +msgstr "Tiempo Entrega" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user +msgid "Default User" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Description" +msgstr "Descripción" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Done" +msgstr "Terminado" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Filter" +msgstr "Filtro" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Group By" +msgstr "Agrupar por" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button +msgid "Hide Button" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id +msgid "ID" +msgstr "ID" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks +msgid "Kanban Subtasks" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update +msgid "Last Modified on" +msgstr "Última Modificación el" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid +msgid "Last Updated by" +msgstr "Última Modificación por" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date +msgid "Last Updated on" +msgstr "Última Actualización en" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "My" +msgstr "Mi" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:60 +#: code:addons/project_task_subtask/models/project_task_subtask.py:64 +#, python-format +msgid "Only users related to that subtask can change state." +msgstr "" +"Sólo los usuarios relacionados a la sub tarea pueden cambiarla de estado" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id_2779 +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Project" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor +msgid "Recolor" +msgstr "Cambiar Color" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id +msgid "Reviewer" +msgstr "Revisado Por" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "State" +msgstr "Estado" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state +msgid "Status" +msgstr "Estatus" + +#. module: project_task_subtask +#: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype +msgid "" +"Subscribe to checklist updates of other users. By default you are notified " +"on checklist items to and from you only." +msgstr "" +"Suscríbete a las actualizaciones de la lista de verificación de otros " +"usuarios. De forma predeterminada, se le notifica solo en los elementos de " +"la lista de verificación." + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids +msgid "Subtask" +msgstr "Sub tarea" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_id +msgid "Subtask Message" +msgstr "Mensaje Sub tarea" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +#: selection:project.task.subtask,state:0 +msgid "TODO" +msgstr "Por Hacer" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Task" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state +msgid "Task state" +msgstr "Estado tarea" + +#. module: project_task_subtask +#: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 +msgid "To Do" +msgstr "Por Hacer" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "User" +msgstr "Usuario" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Waiting" +msgstr "Esperando" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task_subtask +msgid "project.task.subtask" +msgstr "project.task.subtask" diff --git a/project_task_subtask/i18n/fr.po b/project_task_subtask/i18n/fr.po new file mode 100644 index 0000000..e67e015 --- /dev/null +++ b/project_task_subtask/i18n/fr.po @@ -0,0 +1,242 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_subtask +# +# Translators: +# Translation Bot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-04-20 23:52+0000\n" +"PO-Revision-Date: 2018-04-20 23:52+0000\n" +"Last-Translator: Translation Bot , 2018\n" +"Language-Team: French (https://www.transifex.com/it-projects-llc/teams/76080/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: project_task_subtask +#: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype +msgid "All checklist updates" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id +msgid "Assigned to" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to CANCELLED" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to DONE" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to WAITING" +msgstr "" + +#. module: project_task_subtask +#: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask +#: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Checklist" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date +msgid "Created on" +msgstr "Créé le" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline +msgid "Deadline" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user +msgid "Default user" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Description" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Done" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Filter" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Group By" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button +msgid "Hide button" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id +msgid "ID" +msgstr "ID" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks +msgid "Kanban subtasks" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update +msgid "Last Modified on" +msgstr "Dernière Modification le" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "My" +msgstr "" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:61 +#: code:addons/project_task_subtask/models/project_task_subtask.py:65 +#, python-format +msgid "Only users related to that subtask can change state." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Project" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor +msgid "Recolor" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id +msgid "Reviewer" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "State" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state +msgid "Status" +msgstr "" + +#. module: project_task_subtask +#: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype +msgid "" +"Subscribe to checklist updates of other users. By default you are notified " +"on checklist items to and from you only." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids +msgid "Subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_id +msgid "Subtask Message" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +#: selection:project.task.subtask,state:0 +msgid "TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Task" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Task Work" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state +msgid "Task state" +msgstr "" + +#. module: project_task_subtask +#: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 +msgid "To Do" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "User" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Waiting" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task_subtask +msgid "project.task.subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view +msgid "subtask_list_form" +msgstr "" diff --git a/project_task_subtask/i18n/project_task_subtask.pot b/project_task_subtask/i18n/project_task_subtask.pot new file mode 100644 index 0000000..74413da --- /dev/null +++ b/project_task_subtask/i18n/project_task_subtask.pot @@ -0,0 +1,246 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_subtask +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: project_task_subtask +#: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype +msgid "All checklist updates" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id +msgid "Assigned to" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to CANCELLED" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to DONE" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to Waiting" +msgstr "" + +#. module: project_task_subtask +#: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask +#: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Checklist" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_completion +msgid "Completion" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_completion_xml +msgid "Completion Xml" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id +msgid "Created by" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date +msgid "Created on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_deadline +msgid "Deadline" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user +msgid "Default User" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Description" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name +msgid "Display Name" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Done" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Filter" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Group By" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button +msgid "Hide Button" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id +msgid "ID" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks +msgid "Kanban Subtasks" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update +msgid "Last Modified on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date +msgid "Last Updated on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "My" +msgstr "" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:67 +#: code:addons/project_task_subtask/models/project_task_subtask.py:71 +#, python-format +msgid "Only users related to that subtask can change state." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id_4692 +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Project" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor +msgid "Recolor" +msgstr "" + +#. module: project_task_subtask +#. openerp-web +#: code:addons/project_task_subtask/static/src/xml/templates.xml:6 +#, python-format +msgid "Sort" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "State" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state +msgid "Status" +msgstr "" + +#. module: project_task_subtask +#: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype +msgid "Subscribe to checklist updates of other users. By default you are notified on checklist items to and from you only." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids +msgid "Subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_id +msgid "Subtask Message" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +#: selection:project.task.subtask,state:0 +msgid "TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Task" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state +msgid "Task state" +msgstr "" + +#. module: project_task_subtask +#: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 +msgid "To Do" +msgstr "" + +#. module: project_task_subtask +#. openerp-web +#: code:addons/project_task_subtask/static/src/xml/templates.xml:7 +#, python-format +msgid "Unsort" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "User" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Waiting" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task_subtask +msgid "project.task.subtask" +msgstr "" + diff --git a/project_task_subtask/i18n/ru.po b/project_task_subtask/i18n/ru.po new file mode 100644 index 0000000..6419ed6 --- /dev/null +++ b/project_task_subtask/i18n/ru.po @@ -0,0 +1,231 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_subtask +# +# Translators: +# Dinar , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-11-22 11:27+0000\n" +"PO-Revision-Date: 2017-11-22 11:27+0000\n" +"Last-Translator: Dinar , 2017\n" +"Language-Team: Russian (https://www.transifex.com/it-projects-llc/teams/76080/ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: ru\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" + +#. module: project_task_subtask +#: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype +msgid "All checklist updates" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id +msgid "Assigned to" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to CANCELLED" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to DONE" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask +#: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Checklist" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid +msgid "Created by" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date +msgid "Created on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user +msgid "Default user" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name +msgid "Description" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name +msgid "Display Name" +msgstr "Отображаемое имя" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Done" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Filter" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Group By" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button +msgid "Hide button" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id +msgid "ID" +msgstr "ID" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks +msgid "Kanban subtasks" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update +msgid "Last Modified on" +msgstr "Последний раз редактировалось" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date +msgid "Last Updated on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "My" +msgstr "" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:60 +#: code:addons/project_task_subtask/models/project_task_subtask.py:64 +#, python-format +msgid "Only users related to that subtask can change state." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Project" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor +msgid "Recolor" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id +msgid "Reviewer" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "State" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state +msgid "Status" +msgstr "" + +#. module: project_task_subtask +#: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype +msgid "" +"Subscribe to checklist updates of other users. By default you are notified " +"on checklist items to and from you only." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids +msgid "Subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_id +msgid "Subtask Message" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +#: selection:project.task.subtask,state:0 +msgid "TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Task" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Task Work" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state +msgid "Task state" +msgstr "" + +#. module: project_task_subtask +#: model:project.task.subtask,task_state:project_task_subtask.project_task_subtask_1 +msgid "To Do" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "User" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Waiting" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task_subtask +msgid "project.task.subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view +msgid "subtask_list_form" +msgstr "" diff --git a/project_task_subtask/i18n/sl.po b/project_task_subtask/i18n/sl.po new file mode 100644 index 0000000..946ccc7 --- /dev/null +++ b/project_task_subtask/i18n/sl.po @@ -0,0 +1,226 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_subtask +# +# Translators: +# Translation Bot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-24 07:50+0000\n" +"PO-Revision-Date: 2017-07-24 07:50+0000\n" +"Last-Translator: Translation Bot , 2017\n" +"Language-Team: Slovenian (https://www.transifex.com/it-projects-llc/teams/76080/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#. module: project_task_subtask +#: model:mail.message.subtype,name:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,name:project_task_subtask.subtasks_subtype +msgid "All checklist updates" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_user_id +msgid "Assigned to" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Cancelled" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to CANCELLED" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to DONE" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Change state to TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.actions.act_window,name:project_task_subtask.action_view_subtask +#: model:ir.ui.menu,name:project_task_subtask.menu_action_view_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Checklist" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_uid +msgid "Created by" +msgstr "Ustvaril" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_create_date +msgid "Created on" +msgstr "Ustvarjeno" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_default_user +msgid "Default user" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_name +msgid "Description" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_display_name +msgid "Display Name" +msgstr "" + +#. module: project_task_subtask +#: selection:project.task.subtask,state:0 +msgid "Done" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Filter" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Group By" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_hide_button +msgid "Hide button" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_id +msgid "ID" +msgstr "ID" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_kanban_subtasks +msgid "Kanban subtasks" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask___last_update +msgid "Last Modified on" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_uid +msgid "Last Updated by" +msgstr "Zadnjič posodobil" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_write_date +msgid "Last Updated on" +msgstr "Zadnjič posodobljeno" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "My" +msgstr "" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:62 +#, python-format +msgid "Only reviewer can change description." +msgstr "" + +#. module: project_task_subtask +#: code:addons/project_task_subtask/models/project_task_subtask.py:58 +#, python-format +msgid "Only users related to that subtask can change state." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_project_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Project" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_recolor +msgid "Recolor" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_reviewer_id +msgid "Reviewer" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "State" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_state +msgid "Status" +msgstr "" + +#. module: project_task_subtask +#: model:mail.message.subtype,description:project_task_subtask.all_subtask_subtype +#: model:mail.message.subtype,description:project_task_subtask.subtasks_subtype +msgid "" +"Subscribe to checklist updates of other users. By default you are notified " +"on checklist items to and from you only." +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_ids +msgid "Subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_id +msgid "Subtask Message" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +#: selection:project.task.subtask,state:0 +msgid "TODO" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_id +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "Task" +msgstr "Opravilo" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.view_task_form2 +msgid "Task Work" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model.fields,field_description:project_task_subtask.field_project_task_subtask_task_state +msgid "Task state" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.project_task_subtask_view_search +msgid "User" +msgstr "" + +#. module: project_task_subtask +#: model:ir.model,name:project_task_subtask.model_project_task_subtask +msgid "project.task.subtask" +msgstr "" + +#. module: project_task_subtask +#: model:ir.ui.view,arch_db:project_task_subtask.subtask_list_view +msgid "subtask_list_form" +msgstr "" diff --git a/project_task_subtask/images/checklist_main.png b/project_task_subtask/images/checklist_main.png new file mode 100644 index 0000000..7f126ab Binary files /dev/null and b/project_task_subtask/images/checklist_main.png differ diff --git a/project_task_subtask/models/__init__.py b/project_task_subtask/models/__init__.py new file mode 100644 index 0000000..dfe016f --- /dev/null +++ b/project_task_subtask/models/__init__.py @@ -0,0 +1 @@ +from . import project_task_subtask diff --git a/project_task_subtask/models/project_task_subtask.py b/project_task_subtask/models/project_task_subtask.py new file mode 100644 index 0000000..9e3b66f --- /dev/null +++ b/project_task_subtask/models/project_task_subtask.py @@ -0,0 +1,307 @@ +from odoo import api, fields, models +from odoo.exceptions import Warning as UserError +from odoo.tools import html_escape as escape +from odoo.tools.translate import _ + +SUBTASK_STATES = { + "done": "Done", + "todo": "TODO", + "waiting": "Waiting", + "cancelled": "Cancelled", +} + + +class ProjectTaskSubtask(models.Model): + _name = "project.task.subtask" + _description = "Subtask" + _inherit = ["mail.activity.mixin"] + state = fields.Selection( + [(k, v) for k, v in list(SUBTASK_STATES.items())], + "Status", + required=True, + copy=False, + default="todo", + ) + name = fields.Char(required=True, string="Description") + reviewer_id = fields.Many2one( + "res.users", "Reviewer", readonly=True, default=lambda self: self.env.user + ) + project_id = fields.Many2one( + "project.project", related="task_id.project_id", store=True + ) + user_id = fields.Many2one("res.users", "Assigned to", required=True) + task_id = fields.Many2one( + "project.task", "Task", ondelete="cascade", required=True, index="1" + ) + task_state = fields.Char( + string="Task state", related="task_id.stage_id.name", readonly=True + ) + hide_button = fields.Boolean(compute="_compute_hide_button") + recolor = fields.Boolean(compute="_compute_recolor") + deadline = fields.Datetime(string="Deadline") + + def _compute_recolor(self): + for record in self: + if self.env.user == record.user_id and record.state == "todo": + record.recolor = True + else: + record.recolor = False + + def _compute_hide_button(self): + for record in self: + if self.env.user not in [record.reviewer_id, record.user_id]: + record.hide_button = True + else: + record.hide_button = False + + def _compute_reviewer_id(self): + for record in self: + record.reviewer_id = record.create_uid + + @api.model + def _needaction_domain_get(self): + if self._needaction: + return [("state", "=", "todo"), ("user_id", "=", self.env.uid)] + return [] + + def write(self, vals): + old_names = dict(list(zip(self.mapped("id"), self.mapped("name")))) + result = super(ProjectTaskSubtask, self).write(vals) + for r in self: + if vals.get("state"): + r.task_id.send_subtask_email( + r.name, r.state, r.reviewer_id.id, r.user_id.id + ) + if self.env.user != r.reviewer_id and self.env.user != r.user_id: + raise UserError( + _("Only users related to that subtask can change state.") + ) + if vals.get("name"): + r.task_id.send_subtask_email( + r.name, + r.state, + r.reviewer_id.id, + r.user_id.id, + old_name=old_names[r.id], + ) + if self.env.user != r.reviewer_id and self.env.user != r.user_id: + raise UserError( + _("Only users related to that subtask can change state.") + ) + if vals.get("user_id"): + r.task_id.send_subtask_email( + r.name, r.state, r.reviewer_id.id, r.user_id.id + ) + return result + + @api.model + def create(self, vals): + result = super(ProjectTaskSubtask, self).create(vals) + vals = self._add_missing_default_values(vals) + task = self.env["project.task"].browse(vals.get("task_id")) + task.send_subtask_email( + vals["name"], vals["state"], vals["reviewer_id"], vals["user_id"] + ) + return result + + def change_state_done(self): + for record in self: + record.state = "done" + + def change_state_todo(self): + for record in self: + record.state = "todo" + + def change_state_cancelled(self): + for record in self: + record.state = "cancelled" + + def change_state_waiting(self): + for record in self: + record.state = "waiting" + + +class Task(models.Model): + _inherit = "project.task" + subtask_ids = fields.One2many("project.task.subtask", "task_id", "Subtask") + kanban_subtasks = fields.Text(compute="_compute_kanban_subtasks") + default_user = fields.Many2one("res.users", compute="_compute_default_user") + completion = fields.Integer("Completion", compute="_compute_completion") + completion_xml = fields.Text(compute="_compute_completion_xml") + + def _compute_default_user(self): + for record in self: + if self.env.user != record.user_id and self.env.user != record.create_uid: + record.default_user = record.user_id + else: + if self.env.user != record.user_id: + record.default_user = record.user_id + elif self.env.user != record.create_uid: + record.default_user = record.create_uid + elif ( + self.env.user == record.create_uid + and self.env.user == record.user_id + ): + record.default_user = self.env.user + + def _compute_kanban_subtasks(self): + for record in self: + result_string_td = "" + result_string_wt = "" + if record.subtask_ids: + task_todo_ids = record.subtask_ids.filtered( + lambda x: x.state == "todo" and x.user_id.id == record.env.user.id + ) + task_waiting_ids = record.subtask_ids.filtered( + lambda x: x.state == "waiting" + and x.user_id.id == record.env.user.id + ) + if task_todo_ids: + tmp_string_td = escape(": {}".format(len(task_todo_ids))) + result_string_td += "
  • TODO{}
  • ".format(tmp_string_td) + if task_waiting_ids: + tmp_string_wt = escape(": {}".format(len(task_waiting_ids))) + result_string_wt += "
  • Waiting{}
  • ".format( + tmp_string_wt + ) + record.kanban_subtasks = ( + '
      ' + + result_string_td + + result_string_wt + + "
    " + ) + + def _compute_completion(self): + for record in self: + record.completion = record.task_completion() + + def _compute_completion_xml(self): + for record in self: + active_subtasks = record.subtask_ids and record.subtask_ids.filtered( + lambda x: x.user_id.id == record.env.user.id and x.state != "cancelled" + ) + if not active_subtasks: + record.completion_xml = """ +
    +
    + """ + continue + + completion = record.task_completion() + color = "bg-success-full" + if completion < 50: + color = "bg-danger-full" + record.completion_xml = """ +
    +
    + Your Checklist: +
    +
    +
    +
    +
    +
    +
    +
    {0}%
    +
    + """.format( + int(completion), color + ) + + def task_completion(self): + user_task_ids = self.subtask_ids.filtered( + lambda x: x.user_id.id == self.env.user.id and x.state != "cancelled" + ) + if not user_task_ids: + return 100 + user_done_task_ids = user_task_ids.filtered(lambda x: x.state == "done") + return (len(user_done_task_ids) / len(user_task_ids)) * 100 + + def send_subtask_email( + self, + subtask_name, + subtask_state, + subtask_reviewer_id, + subtask_user_id, + old_name=None, + ): + for r in self: + body = "" + reviewer = self.env["res.users"].browse(subtask_reviewer_id) + user = self.env["res.users"].browse(subtask_user_id) + state = SUBTASK_STATES[subtask_state] + if subtask_state == "done": + state = '' + state + "" + if subtask_state == "todo": + state = '' + state + "" + if subtask_state == "cancelled": + state = '' + state + "" + if subtask_state == "waiting": + state = '' + state + "" + partner_ids = [] + subtype = "project_task_subtask.subtasks_subtype" + if user == self.env.user and reviewer == self.env.user: + body = "

    " + "" + state + ": " + escape(subtask_name) + subtype = False + elif self.env.user == reviewer: + body = ( + "

    " + + escape(user.name) + + ",
    " + + state + + ": " + + escape(subtask_name) + ) + partner_ids = [user.partner_id.id] + elif self.env.user == user: + body = ( + "

    " + + escape(reviewer.name) + + ', I updated checklist item assigned to me:
    ' # noqa: B950 + + state + + ": " + + escape(subtask_name) + ) + partner_ids = [reviewer.partner_id.id] + else: + body = ( + "

    " + + escape(user.name) + + ", " + + escape(reviewer.name) + + ', I updated checklist item, now its assigned to ' + + escape(user.name) + + ":
    " + + state + + ": " + + escape(subtask_name) + ) + partner_ids = [user.partner_id.id, reviewer.partner_id.id] + if old_name: + body = ( + body + + '
    Updated from
    ' + + state + + ": " + + escape(old_name) + + "

    " + ) + else: + body = body + "

    " + r.message_post( + message_type="comment", + subtime_xmlid=subtype, + body=body, + partner_ids=partner_ids, + ) + + def copy(self, default=None): + task = super(Task, self).copy(default) + for subtask in self.subtask_ids: + subtask.copy({"task_id": task.id, "state": subtask.state}) + return task diff --git a/project_task_subtask/readme/CONTRIBUTORS.md b/project_task_subtask/readme/CONTRIBUTORS.md new file mode 100644 index 0000000..66c0a8c --- /dev/null +++ b/project_task_subtask/readme/CONTRIBUTORS.md @@ -0,0 +1,7 @@ +- Ivan Yelizariev (https://github.com/yelizariev) +- Rafael Manaev (https://github.com/manawi) +- Ilmir Karamov (https://github.com/ilmir-k) +- Ildar Nasyrov (https://github.com/iledarn) +- Nicolas Jeudy (https://github.com/njeudy) +- Alexandr Kolushov (https://github.com/KolushovAlexandr) +- Almas Giniatullin (https://github.com/almas50) diff --git a/project_task_subtask/readme/DESCRIPTION.md b/project_task_subtask/readme/DESCRIPTION.md new file mode 100644 index 0000000..59e601e --- /dev/null +++ b/project_task_subtask/readme/DESCRIPTION.md @@ -0,0 +1,18 @@ +Use subtasks to control your tasks. Be ensure that all your tasks/subtasks are performed and not missed. + +Features: + +* Added new "Checklist" tab on task's form +* When new subtask is created\changed, message is sent to user that assigned to this subtask +* Only users related to subtask can change subtask parameters +* All subtasks have a certain color, informing about their state +* Each subtask has buttons to switch state: + + * DONE + * TODO + * CANCELLED + +* Added new "Checklist" menu + + * default filter: "My", "TODO" + * optional group by: "Project", "Task", "User", "State" diff --git a/project_task_subtask/readme/USAGE.md b/project_task_subtask/readme/USAGE.md new file mode 100644 index 0000000..846dd21 --- /dev/null +++ b/project_task_subtask/readme/USAGE.md @@ -0,0 +1,14 @@ +* Create User1 and User2 in the ``Settings >> Users`` menu +* Login as User1 + + * Go to ``Project >> Project >> All Tasks`` and open the ``Checklist`` tab + * Create new subtask (Assigned to - User2) + +* Login as User2 + + * See message in Inbox like "TODO: subtask_name" + * Change state of subtask to Cancelled/Done + * You can see a message in Inbox "Cancelled: subtask_name" or "Done: subtask_name" accordingly. + +* You can see your TODOs on tasks in kanban view in the ``Project >> Project >> Tasks`` menu +* The ``Project >> Project >> Checklist`` menu displays ALL subtasks in state TODO assigned to you and subtasks where you are Reviewer diff --git a/project_task_subtask/security/ir.model.access.csv b/project_task_subtask/security/ir.model.access.csv new file mode 100644 index 0000000..50b38d7 --- /dev/null +++ b/project_task_subtask/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_task_subtask,project.task.subtask,model_project_task_subtask,project.group_project_user,1,1,1,0 diff --git a/project_task_subtask/static/description/checklist.png b/project_task_subtask/static/description/checklist.png new file mode 100644 index 0000000..6127509 Binary files /dev/null and b/project_task_subtask/static/description/checklist.png differ diff --git a/project_task_subtask/static/description/checklist_color.png b/project_task_subtask/static/description/checklist_color.png new file mode 100644 index 0000000..6d91688 Binary files /dev/null and b/project_task_subtask/static/description/checklist_color.png differ diff --git a/project_task_subtask/static/description/checklist_icon.png b/project_task_subtask/static/description/checklist_icon.png new file mode 100644 index 0000000..de7ba86 Binary files /dev/null and b/project_task_subtask/static/description/checklist_icon.png differ diff --git a/project_task_subtask/static/description/checklist_kanban.png b/project_task_subtask/static/description/checklist_kanban.png new file mode 100644 index 0000000..c2c1ca5 Binary files /dev/null and b/project_task_subtask/static/description/checklist_kanban.png differ diff --git a/project_task_subtask/static/description/checklist_mail.png b/project_task_subtask/static/description/checklist_mail.png new file mode 100644 index 0000000..1d7d57c Binary files /dev/null and b/project_task_subtask/static/description/checklist_mail.png differ diff --git a/project_task_subtask/static/description/checklist_menu.png b/project_task_subtask/static/description/checklist_menu.png new file mode 100644 index 0000000..b9f37f0 Binary files /dev/null and b/project_task_subtask/static/description/checklist_menu.png differ diff --git a/project_task_subtask/static/description/icon.png b/project_task_subtask/static/description/icon.png new file mode 100644 index 0000000..b43a0a1 Binary files /dev/null and b/project_task_subtask/static/description/icon.png differ diff --git a/project_task_subtask/static/description/index.html b/project_task_subtask/static/description/index.html new file mode 100644 index 0000000..bc52ba7 --- /dev/null +++ b/project_task_subtask/static/description/index.html @@ -0,0 +1,139 @@ +
    +
    +
    +

    Project Task Checklist

    +

    Use checklist to be ensure that all your tasks are performed and to make easy control over them

    +
    +
    +
    + +
    +
    +
    +

    +

    + Key features: +
      +
    • + + create checklist for any tasks +
    • +
    • + + track all subtasks that should be done and keep them under control +
    • +
    • + + checklist items will be colored depending on their state +
    • +
    • + + only users related to subtask can change subtask parameters +
    • +
    • + + see instant email notifications in task mail thread and your Inbox +
    • +
    +
    +

    +
    +
    +
    + +
    +
    +

    How It Works

    +
    +

    + Go to Project → Tasks menu and create/open a task. Here you can see new "Checklist" tab. + Add items (hereinafter "subtasks") into your checklist.
    + Specify "Description" and select "Assigned to", "Reviewer". +

    +
    +
    + +
    +
    +
    + +
    +
    +
    +

    +

      +
    • if a subtask has state "TODO", it's colored in red for user assigned to subtask
    • +
    • if a subtask has state "DONE", it's colored in green
    • +
    • if a subtask has state "CANCELLED", it's colored in grey
    • +
    +

    +

    + If you mistakenly switch state to "DONE" or "CANCELLED", you will be able to revert state to TODO by clicking on +

    +
    +
    + +
    +
    +
    + +
    +
    +
    +

    + All checklist changes and updates are tracked on task mail thread and you will receive instant email notifications to your Inbox +

    +
    +
    + +
    +
    +
    + +
    +
    +
    +

    + You can see your TODOs on tasks in kanban view +

    +
    +
    + +
    +
    +
    + +
    +
    +
    +

    + Track all your TODOs in one place and keep them under control. Go to the Project → Checklist menu to see them. +

    +
    +
    + +
    +
    +
    + +
    +
    +

    Free Support

    +

    You will get free support and assistance in case of any issues

    +
    +
    + +
    +
    +
    +

    Need our service?

    +

    Contact us by email or fill out request form

    + +
    +
    +
    diff --git a/project_task_subtask/static/src/css/kanban_styles.css b/project_task_subtask/static/src/css/kanban_styles.css new file mode 100644 index 0000000..e2c625c --- /dev/null +++ b/project_task_subtask/static/src/css/kanban_styles.css @@ -0,0 +1,35 @@ +.task_progress { + width: 40%; + display: inline-block; + font-size: 10px; +} + +.task_progress { + width: 40%; + display: inline-block; + font-size: 10px; +} +.task_progress .task_progress_bar { + width: 85%; + display: inline-block; + margin-bottom: 0px; + height: 10px; +} +.task_progress .task_progress_bar_done { + max-width: 100%; + min-width: 3%; +} +.task_progress .task_completion { + width: 10%; + display: inline-block; + height: 13px; +} + +.kanban_subtasks { + width: 55%; + display: inline-block; + font-size: 10px; +} +.kanban_subtasks ul { + -webkit-padding-start: 30px; +} diff --git a/project_task_subtask/static/src/js/one2many_renderer.js b/project_task_subtask/static/src/js/one2many_renderer.js new file mode 100644 index 0000000..ce12f02 --- /dev/null +++ b/project_task_subtask/static/src/js/one2many_renderer.js @@ -0,0 +1,219 @@ +odoo.define("project_task_subtask.one2many_renderer", function (require) { + "use strict"; + var FieldOne2Many = require("web.relational_fields").FieldOne2Many; + var BasicModel = require("web.BasicModel"); + + var core = require("web.core"); + var QWeb = core.qweb; + + FieldOne2Many.include({ + check_task_tree_mode: function () { + if ( + this.view && + this.view.arch.tag === "tree" && + this.record && + this.record.model === "project.task" && + this.name === "subtask_ids" + ) { + return true; + } + return false; + }, + + sort_data: function () { + var user_id = this.record.context.uid; + + var new_rows = _.filter(this.value.data, function (d) { + return !d.res_id; + }); + var data = _.difference(this.value.data, new_rows); + + _.each(data, function (d) { + d.u_name = d.data.user_id.data.display_name; + }); + + var name_index = _.sortBy( + _.uniq( + _.map(data, function (d) { + return d.data.user_id.data.display_name; + }) + ) + ); + + data = _.sortBy(data, "u_name"); + _.each(data, function (d) { + d.deadline = d.data.deadline; + if (d.data.user_id.data.id === user_id) { + d.index = 0; + } else { + d.index = + (_.indexOf(name_index, d.data.user_id.data.display_name) + 1) * + 1000000; + } + }); + + data = _.sortBy(data, "deadline"); + _.each(data, function (d) { + d.index += _.indexOf(data, d); + if (!d.deadline) { + d.index += 90000; + } + if (d.data.state === "todo") { + // Continue + } else if (d.data.state === "waiting") { + d.index += 100000; + } else if (d.data.state === "done") { + d.index += 400000; + } else { + // Makes cancelled subtasks stay last in line + d.index += (name_index.length + 2) * 1000000; + if (d.data.user_id.data.id !== user_id) { + d.index += + (_.indexOf(name_index, d.data.user_id.data.display_name) + + 1) * + 1000000; + } + } + }); + data = _.sortBy(data, "index"); + _.each(new_rows, function (r) { + data.push(r); + }); + this.default_sorting = this.value.data; + this.value.data = data; + }, + + _render: function () { + if (this.check_task_tree_mode() && this.getParent().list_is_sorted) { + this.sort_data(); + } + return this._super(arguments); + }, + + reset: function (record, ev, fieldChanged) { + var self = this; + return this._super.apply(this, arguments).then(function (res) { + if (self.check_task_tree_mode() && self.getParent().list_is_sorted) { + self._render(); + } + }); + }, + + _renderButtons: function () { + var self = this; + if (this.check_task_tree_mode()) { + this.$buttons = $( + QWeb.render("SubtaskSortButtons", { + check_button: this.getParent().list_is_sorted, + }) + ); + this.$buttons.on( + "click", + ".o_pager_sort", + this._update_custom_sort_buttons.bind(this) + ); + this.$buttons.on( + "click", + ".o_pager_unsort", + this._update_custom_unsort_buttons.bind(this) + ); + } + return this._super(arguments); + }, + + _update_custom_sort_buttons: function () { + this.getParent().list_is_sorted = true; + this.default_sorting = this.value.data; + this._render(); + }, + + _update_custom_unsort_buttons: function () { + this.getParent().list_is_sorted = false; + this.value.data = this.default_sorting; + this._render(); + }, + }); + + BasicModel.include({ + _sortList: function (list) { + // Taken from odoo + if (!list.static) { + // Only sort x2many lists + return; + } + var self = this; + // ----- + + if (list.model === "project.task.subtask" && list.orderedResIDs) { + var rows = []; + var new_rows = []; + _.each(list.data, function (d) { + var r = self.localData[d]; + if (Number(r.res_id) === r.res_id) { + rows.push(r); + } else { + new_rows.push(r); + } + }); + rows = this.sort_data(rows, list.context.uid, this); + _.each(new_rows, function (r) { + rows.push(r); + }); + list.orderedResIDs = _.pluck(rows, "res_id"); + return this._setDataInRange(list); + } + + return this._super(list); + }, + + sort_data: function (data, user_id, parent) { + user_id = user_id || 1; + + _.each(data, function (d) { + d.u_name = parent.localData[d.data.user_id].data.display_name; + }); + + var name_index = _.sortBy( + _.uniq( + _.map(data, function (d) { + return parent.localData[d.data.user_id].data.display_name; + }) + ) + ); + + data = _.sortBy(data, "u_name"); + _.each(data, function (d) { + d.deadline = d.data.deadline; + if (parent.localData[d.data.user_id].data.id === user_id) { + d.index = 0; + } else { + d.index = + (_.indexOf( + name_index, + parent.localData[d.data.user_id].data.display_name + ) + + 1) * + 1000000; + } + }); + + data = _.sortBy(data, "deadline"); + _.each(data, function (d) { + d.index += _.indexOf(data, d); + if (!d.deadline) { + d.index += 90000; + } + if (d.data.state === "todo") { + // Continue + } else if (d.data.state === "waiting") { + d.index += 100000; + } else if (d.data.state === "done") { + d.index += 400000; + } else { + d.index += 700000; + } + }); + return _.sortBy(data, "index"); + }, + }); +}); diff --git a/project_task_subtask/static/src/js/tours/tour.js b/project_task_subtask/static/src/js/tours/tour.js new file mode 100644 index 0000000..4d13235 --- /dev/null +++ b/project_task_subtask/static/src/js/tours/tour.js @@ -0,0 +1,60 @@ +odoo.define("project_task_subtask.tour", function (require) { + "use strict"; + + var core = require("web.core"); + var tour = require("web_tour.tour"); + + var _t = core._t; + + var steps = [ + tour.stepUtils.showAppsMenuItem(), + { + trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', + content: _t( + "Want a better way to manage your projects? It starts here." + ), + position: "right", + edition: "community", + }, + { + trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]', + content: _t( + "Want a better way to manage your projects? It starts here." + ), + position: "bottom", + edition: "enterprise", + }, + { + trigger: ".o_project_kanban_main", + content: "open project", + timeout: 10000, + }, + { + trigger: ".o_loading", + content: "waiting for loading to finish", + timeout: 5000, + }, + { + trigger: ".o_content", + content: "just click", + timeout: 1000, + }, + { + trigger: ".oe_kanban_content", + content: "open task", + timeout: 20000, + }, + { + trigger: ".o_pager_sort", + content: "sort", + timeout: 10000, + }, + { + trigger: ".o_pager_unsort", + content: "unsort", + timeout: 10000, + }, + ]; + + tour.register("task_subtask", {url: "/web"}, steps); +}); diff --git a/project_task_subtask/static/src/xml/templates.xml b/project_task_subtask/static/src/xml/templates.xml new file mode 100644 index 0000000..7a61354 --- /dev/null +++ b/project_task_subtask/static/src/xml/templates.xml @@ -0,0 +1,23 @@ + + diff --git a/project_task_subtask/tests/__init__.py b/project_task_subtask/tests/__init__.py new file mode 100644 index 0000000..027ead8 --- /dev/null +++ b/project_task_subtask/tests/__init__.py @@ -0,0 +1,3 @@ +# License MIT (https://opensource.org/licenses/MIT). + +from . import test_subtask_sort_button diff --git a/project_task_subtask/tests/test_subtask_sort_button.py b/project_task_subtask/tests/test_subtask_sort_button.py new file mode 100644 index 0000000..b30b5ce --- /dev/null +++ b/project_task_subtask/tests/test_subtask_sort_button.py @@ -0,0 +1,10 @@ +import odoo.tests + + +@odoo.tests.tagged("at_install", "post_install") +class TestUi(odoo.tests.HttpCase): + def test_01_subtask_sort_button(self): + self.env["ir.module.module"].search( + [("name", "=", "project_task_subtask")], limit=1 + ).state = "installed" + self.start_tour("/web", "task_subtask", login="admin") diff --git a/project_task_subtask/views/assets.xml b/project_task_subtask/views/assets.xml new file mode 100644 index 0000000..393e445 --- /dev/null +++ b/project_task_subtask/views/assets.xml @@ -0,0 +1,32 @@ + + +