diff --git a/fieldservice_timeline/README.rst b/fieldservice_timeline/README.rst new file mode 100644 index 0000000000..86feec2576 --- /dev/null +++ b/fieldservice_timeline/README.rst @@ -0,0 +1,127 @@ +========================== +Field Service Web Timeline +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ffield--service-lightgray.png?logo=github + :target: https://github.com/OCA/field-service/tree/13.0/fieldservice_timeline + :alt: OCA/field-service +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/field-service-13-0/field-service-13-0-fieldservice_timeline + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/264/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module is the display timeline view of the Field Service application in Odoo. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +The Field Service Web Timeline View module can be used with minimal initial configuration. + +Order Stages +~~~~~~~~~~~~ + +The stage of an order is used to monitor its progress. Stages can be configured +based on your company's specific business needs. A basic set of order stages +comes pre-configured for use. + +#. Go to *Field Service > Configuration > Stages* +#. Create or edit a stage +#. Set the name for the stage. +#. Set the sequence order for the stage. +#. Select *Order* type to apply this stage to your orders. +#. Additonally, you can set a color for the stage. + +You need to add attribute mention below with the tag as base element. + +* colors (optional): it allows to set certain specific colors if the expressed + condition (JS syntax) is met. +* custom_color (optional): it allows to set custom color for fsm.stages + example custom_color = "true". And there is minor condition to follow to + implement this as. Define any one stage color condition like + colors="#ffffff:stage_id=='New';" + +Known issues / Roadmap +====================== + +The roadmap of the Field Service application is documented on +`Github `_. + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Open Source Integrators + +Contributors +~~~~~~~~~~~~ + +* Wolfgang Hall +* Maxime Chambreuil +* Serpent Consulting Services Pvt. Ltd. + +Other credits +~~~~~~~~~~~~~ + +The development of this module has been financially supported by: + +* Open Source Integrators + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-wolfhall| image:: https://github.com/wolfhall.png?size=40px + :target: https://github.com/wolfhall + :alt: wolfhall +.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px + :target: https://github.com/max3903 + :alt: max3903 + +Current `maintainers `__: + +|maintainer-wolfhall| |maintainer-max3903| + +This module is part of the `OCA/field-service `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fieldservice_timeline/__init__.py b/fieldservice_timeline/__init__.py new file mode 100644 index 0000000000..77e360b3a9 --- /dev/null +++ b/fieldservice_timeline/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from .hooks import uninstall_hook diff --git a/fieldservice_timeline/__manifest__.py b/fieldservice_timeline/__manifest__.py new file mode 100644 index 0000000000..cb1f23ea87 --- /dev/null +++ b/fieldservice_timeline/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright (C) 2020 Open Source Integrators +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Field Service Web Timeline", + "summary": "This module is a display timeline view of the Field Service" + " order in Odoo.", + "version": "13.0.1.0.0", + "category": "Field Service", + "license": "AGPL-3", + "author": "Open Source Integrators, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/field-service", + "depends": ["fieldservice", "web_timeline"], + "data": ["views/fsm_order.xml", "views/fsm_team.xml"], + "qweb": ["static/src/xml/*.xml"], + "development_status": "Beta", + "maintainers": ["wolfhall", "max3903"], + "uninstall_hook": "uninstall_hook", +} diff --git a/fieldservice_timeline/hooks.py b/fieldservice_timeline/hooks.py new file mode 100644 index 0000000000..d02edf650a --- /dev/null +++ b/fieldservice_timeline/hooks.py @@ -0,0 +1,14 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +def uninstall_hook(cr, registry): + cr.execute( + "UPDATE ir_act_window " + "SET view_mode=replace(view_mode, ',timeline', '')" + "WHERE view_mode LIKE '%,timeline%';" + ) + cr.execute( + "UPDATE ir_act_window " + "SET view_mode=replace(view_mode, 'timeline,', '')" + "WHERE view_mode LIKE '%timeline,%';" + ) diff --git a/fieldservice_timeline/readme/CONFIGURE.rst b/fieldservice_timeline/readme/CONFIGURE.rst new file mode 100644 index 0000000000..521c2ebe41 --- /dev/null +++ b/fieldservice_timeline/readme/CONFIGURE.rst @@ -0,0 +1,24 @@ +The Field Service Web Timeline View module can be used with minimal initial configuration. + +Order Stages +~~~~~~~~~~~~ + +The stage of an order is used to monitor its progress. Stages can be configured +based on your company's specific business needs. A basic set of order stages +comes pre-configured for use. + +#. Go to *Field Service > Configuration > Stages* +#. Create or edit a stage +#. Set the name for the stage. +#. Set the sequence order for the stage. +#. Select *Order* type to apply this stage to your orders. +#. Additonally, you can set a color for the stage. + +You need to add attribute mention below with the tag as base element. + +* colors (optional): it allows to set certain specific colors if the expressed + condition (JS syntax) is met. +* custom_color (optional): it allows to set custom color for fsm.stages + example custom_color = "true". And there is minor condition to follow to + implement this as. Define any one stage color condition like + colors="#ffffff:stage_id=='New';" diff --git a/fieldservice_timeline/readme/CONTRIBUTORS.rst b/fieldservice_timeline/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..dea63c0fc6 --- /dev/null +++ b/fieldservice_timeline/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Wolfgang Hall +* Maxime Chambreuil +* Serpent Consulting Services Pvt. Ltd. diff --git a/fieldservice_timeline/readme/CREDITS.rst b/fieldservice_timeline/readme/CREDITS.rst new file mode 100644 index 0000000000..0eff0acf4e --- /dev/null +++ b/fieldservice_timeline/readme/CREDITS.rst @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +* Open Source Integrators diff --git a/fieldservice_timeline/readme/DESCRIPTION.rst b/fieldservice_timeline/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..b08cb398d8 --- /dev/null +++ b/fieldservice_timeline/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module is the display timeline view of the Field Service application in Odoo. diff --git a/fieldservice_timeline/readme/ROADMAP.rst b/fieldservice_timeline/readme/ROADMAP.rst new file mode 100644 index 0000000000..f607015959 --- /dev/null +++ b/fieldservice_timeline/readme/ROADMAP.rst @@ -0,0 +1,2 @@ +The roadmap of the Field Service application is documented on +`Github `_. diff --git a/fieldservice_timeline/static/description/icon.png b/fieldservice_timeline/static/description/icon.png new file mode 100644 index 0000000000..955674d8f0 Binary files /dev/null and b/fieldservice_timeline/static/description/icon.png differ diff --git a/fieldservice_timeline/static/description/index.html b/fieldservice_timeline/static/description/index.html new file mode 100644 index 0000000000..827993d83c --- /dev/null +++ b/fieldservice_timeline/static/description/index.html @@ -0,0 +1,468 @@ + + + + + + +Field Service Web Timeline View + + + +
+

Field Service Web Timeline View

+ + +

Beta License: AGPL-3 OCA/field-service Translate me on Weblate Try me on Runbot

+

This module is the display timeline view of the Field Service application in Odoo.

+

Table of contents

+ +
+

Configuration

+

The Field Service Web Timeline View module can be used with minimal initial configuration.

+
+

Order Stages

+

The stage of an order is used to monitor its progress. Stages can be configured +based on your company’s specific business needs. A basic set of order stages +comes pre-configured for use.

+
    +
  1. Go to Field Service > Configuration > Stages
  2. +
  3. Create or edit a stage
  4. +
  5. Set the name for the stage.
  6. +
  7. Set the sequence order for the stage.
  8. +
  9. Select Order type to apply this stage to your orders.
  10. +
  11. Additonally, you can set a color for the stage.
  12. +
+

You need to add attribute mention below with the tag <timeline> as base element.

+
    +
  • colors (optional): it allows to set certain specific colors if the expressed +condition (JS syntax) is met.
  • +
  • custom_color (optional): it allows to set custom color for fsm.stages +example custom_color = “true”. And there is minor condition to follow to +implement this as. Define any one stage color condition like +colors=”#ffffff:stage_id==’New’;”
  • +
+
+
+
+

Known issues / Roadmap

+

The roadmap of the Field Service application is documented on +Github.

+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Open Source Integrators
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The development of this module has been financially supported by:

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainers:

+

wolfhall max3903

+

This module is part of the OCA/field-service project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/fieldservice_timeline/static/src/js/fsm_gantt.js b/fieldservice_timeline/static/src/js/fsm_gantt.js new file mode 100644 index 0000000000..cdf368f3cf --- /dev/null +++ b/fieldservice_timeline/static/src/js/fsm_gantt.js @@ -0,0 +1,241 @@ +odoo.define("fieldservice_timeline.fsm_gantt", function(require) { + "use strict"; + + var core = require("web.core"); + var time = require("web.time"); + var session = require("web.session"); + var TimelineRenderer = require("web_timeline.TimelineRenderer"); + var _t = core._t; + + TimelineRenderer.include({ + /** + * Init Overrite + * Parameters: + * @param {Object} parent + * @param {Object} state + * @param {Array} params + */ + init: function(parent, state, params) { + var self = this; + this._super.apply(this, arguments); + this.modelName = params.model; + this.mode = params.mode; + this.options = params.options; + this.permissions = params.permissions; + this.timeline = params.timeline; + this.date_start = params.date_start; + this.date_stop = params.date_stop; + this.date_delay = params.date_delay; + this.colors = params.colors; + this.fieldNames = params.fieldNames; + this.dependency_arrow = params.dependency_arrow; + this.view = params.view; + this.modelClass = this.view.model; + self.res_users = []; + self.res_users_ids = []; + + // Find their matches + this._rpc({ + model: "fsm.person", + method: "get_person_information", + args: [[session.uid], {}], + }).then(function(result) { + self.res_users.push(result); + for (var r in result) { + self.res_users_ids.push(result[r].id); + } + }); + // Find custom color if mentioned + if (params.arch.attrs.custom_color === "true") { + this._rpc({ + model: "fsm.stage", + method: "get_color_information", + args: [[]], + }).then(function(result) { + self.colors = result; + }); + } + }, + + /** + * On data loaded 2 + * Parameters: + * @param {Array} events + * @param {Array} group_bys + * @param {Object} adjust_window + */ + on_data_loaded_2: function(events, group_bys, adjust_window) { + var self = this; + // Make the user filter clear + self.$el.find("#user_filer .o_searchview_extended_prop_field").val(""); + self.$el.find("#user_filer .o_searchview_extended_prop_field").change(); + self.$el + .find("#user_filer .o_searchview_extended_prop_field") + .val("category_id"); + self.$el.find("#user_filer .o_searchview_extended_prop_field").change(); + // Make the user filter clear + var data = []; + var groups = []; + this.grouped_by = group_bys; + _.each(events, function(event) { + if (event[self.date_start]) { + data.push(self.event_data_transform(event)); + } + }); + groups = self.split_groups(events, group_bys); + if (group_bys[0] === "person_id") { + var groups_user_ids = []; + for (var g in groups) { + groups_user_ids.push(groups[g].id); + } + // Find their matches + self._rpc({ + model: "fsm.person", + method: "get_person_information", + args: [[session.uid], {}], + }).then(function(result) { + self.res_users.push(result); + for (var r in result) { + self.res_users_ids.push(result[r].id); + } + for (var u in self.res_users_ids) { + if ( + !(self.res_users_ids[u] in groups_user_ids) || + self.res_users_ids[u] !== -1 + ) { + // Get User Name + var user_name = "-"; + for (var n in self.res_users[0]) { + if (self.res_users[0][n].id === self.res_users_ids[u]) { + user_name = self.res_users[0][n].name; + } + } + var is_available = false; + for (var i in groups) { + if (groups[i].id === self.res_users_ids[u]) { + is_available = true; + } + } + if (!is_available) { + groups.push({ + id: self.res_users_ids[u], + content: _t(user_name), + }); + } + } + } + self.timeline.setGroups(groups); + self.timeline.setItems(data); + var mode = !self.mode || self.mode === "fit"; + var adjust = _.isUndefined(adjust_window) || adjust_window; + self.timeline.setOptions({ + orientation: "top", + }); + if (mode && adjust) { + self.timeline.fit(); + } + }); + } + }, + + /** + * Transform Odoo event object to timeline event object + * Parameters: + * @param {Array} evt + * @returns r + */ + event_data_transform: function(evt) { + var self = this; + var date_start = new moment(); + var date_stop = null; + var date_delay = evt[this.date_delay] || false, + all_day = this.all_day ? evt[this.all_day] : false; + + if (all_day) { + date_start = time.auto_str_to_date( + evt[this.date_start].split(" ")[0], + "start" + ); + if (this.no_period) { + date_stop = date_start; + } else { + date_stop = this.date_stop + ? time.auto_str_to_date( + evt[this.date_stop].split(" ")[0], + "stop" + ) + : null; + } + } else { + date_start = time.auto_str_to_date(evt[this.date_start]); + date_stop = this.date_stop + ? time.auto_str_to_date(evt[this.date_stop]) + : null; + } + + if (!date_stop && date_delay) { + date_stop = moment(date_start) + .add(date_delay, "hours") + .toDate(); + } + + var group = evt[self.last_group_bys[0]]; + if (group && group instanceof Array) { + group = _.first(group); + } else { + group = -1; + } + _.each(self.colors, function(color) { + if ( + eval( + "'" + + evt[color.field] + + "' " + + color.opt + + " '" + + color.value + + "'" + ) + ) { + self.color = color.color; + } else if ( + eval( + "'" + + evt[color.field][1] + + "' " + + color.opt + + " '" + + color.value + + "'" + ) + ) { + self.color = color.color; + } + }); + + var content = _.isUndefined(evt.__name) ? evt.display_name : evt.__name; + if (this.arch.children.length) { + content = this.render_timeline_item(evt); + } + + var r = { + start: date_start, + content: content, + id: evt.id, + group: group, + evt: evt, + style: "background-color: " + self.color + ";", + }; + + /** + * Check if the event is instantaneous, + * if so, display it with a point on the timeline (no 'end') + */ + if (date_stop && !moment(date_start).isSame(date_stop)) { + r.end = date_stop; + } + self.color = null; + return r; + }, + }); +}); diff --git a/fieldservice_timeline/static/src/js/fsm_gantt_person_filter.js b/fieldservice_timeline/static/src/js/fsm_gantt_person_filter.js new file mode 100644 index 0000000000..dfb23e23af --- /dev/null +++ b/fieldservice_timeline/static/src/js/fsm_gantt_person_filter.js @@ -0,0 +1,328 @@ +odoo.define("fsm_gantt.person_filter", function(require) { + "use strict"; + + var TimelineRenderer = require("web_timeline.TimelineRenderer"); + var session = require("web.session"); + var search_filters = require("web.search_filters"); + var core = require("web.core"); + var _t = core._t; + + TimelineRenderer.include({ + /** + * Init + */ + init: function() { + this._super.apply(this, arguments); + + // Initilaize propositions + this.propositions = []; + }, + + /** + * Do Search + * Parameters: + * @param {Array} domains + * @param {Array} contexts + * @param {Array} group_bys + * @returns Array + */ + do_search: function(domains, contexts, group_bys) { + var self = this; + self.last_domains = domains; + self.last_contexts = contexts; + + // Select the group by + var n_group_bys = []; + if (this.arch.attrs.default_group_by) { + n_group_bys = this.arch.attrs.default_group_by.split(","); + } + if (group_bys.length) { + n_group_bys = group_bys; + } + self.last_group_bys = n_group_bys; + + /* Gather the fields to get + */ + var fields = _.compact( + _.map(["date_start", "date_delay", "date_stop", "progress"], function( + key + ) { + return self.arch.attrs[key] || ""; + }) + ); + fields = _.uniq( + fields.concat(_.pluck(this.colors, "field").concat(n_group_bys)) + ); + return this._rpc({ + model: this.modelName, + method: "search_read", + fields: fields, + args: [domains], + kwargs: {context: contexts}, + }).then(function(r) { + return self.on_data_loaded(r, n_group_bys, true); + }); + }, + + /** + * Search data related to user filter + * Parameters: + * @param {Array} domains + * @param {Array} contexts + * @param {Array} group_bys + * @param {Array} user_ids + * @returns Array + */ + do_search_related_user_filter: function( + domains, + contexts, + group_bys, + user_ids + ) { + var self = this; + + /* Select the group by + */ + var n_group_bys = []; + if (this.arch.attrs.default_group_by) { + n_group_bys = this.arch.attrs.default_group_by.split(","); + } + if (group_bys.length) { + n_group_bys = group_bys; + } + + /* Gather the fields to get + */ + var fields = _.compact( + _.map(["date_start", "date_delay", "date_stop", "progress"], function( + key + ) { + return self.arch.attrs[key] || ""; + }) + ); + fields = _.uniq( + fields.concat(_.pluck(this.colors, "field").concat(n_group_bys)) + ); + return this._rpc({ + model: this.modelName, + method: "search_read", + fields: fields, + args: [domains], + kwargs: {context: contexts}, + }).then(function(r) { + return self.on_user_data_loaded(r, n_group_bys, true, user_ids); + }); + }, + + /** + * On user data loaded + * Parameters: + * @param {Array} events + * @param {Array} group_bys + * @param {Object} adjust_window + * @param {Array} user_ids + * @returns Object + */ + on_user_data_loaded: function(events, group_bys, adjust_window, user_ids) { + var self = this; + var ids = _.pluck(events, "id"); + return this._rpc({ + model: this.modelName, + method: "name_get", + args: [ids], + context: this.getSession().user_context, + }).then(function(names) { + var nevents = _.map(events, function(event) { + return _.extend( + { + __name: _.detect(names, function(name) { + return name[0] === event.id; + })[1], + }, + event + ); + }); + return self.on_user_data_loaded_2( + nevents, + group_bys, + adjust_window, + user_ids + ); + }); + }, + + /** + * On user data loaded 2 + * Parameters: + * @param {Array} events + * @param {Array} group_bys + * @param {Object} adjust_window + * @param {Array} user_ids + */ + on_user_data_loaded_2: function(events, group_bys, adjust_window, user_ids) { + var self = this; + var data = []; + var groups = []; + this.grouped_by = group_bys; + _.each(events, function(event) { + if (event[self.date_start]) { + data.push(self.event_data_transform(event)); + } + }); + + /** + * Get the groups + * Parameters: + * @param {Array} events + * @param {Array} group_bys + * @returns events + */ + var split_groups = function(events, group_bys) { + if (group_bys.length === 0) { + return events; + } + groups = []; + groups.push({id: -1, content: _t("-")}); + _.each(events, function(event) { + var group_name = event[_.first(group_bys)]; + if (group_name) { + var group = _.find(groups, function(group) { + return _.isEqual(group.id, group_name[0]); + }); + if (group === undefined) { + group = {id: group_name[0], content: group_name[1]}; + groups.push(group); + } + } + }); + return groups; + }; + groups = split_groups(events, group_bys); + _.each(user_ids, function(user) { + var group = _.find(groups, function(group) { + return _.isEqual(group.id, user.id); + }); + if (group === undefined) { + group = {id: user.id, content: user.name}; + groups.push(group); + } + }); + + this.timeline.setGroups(groups); + this.timeline.setItems(data); + var mode = !this.mode || this.mode === "fit"; + var adjust = _.isUndefined(adjust_window) || adjust_window; + if (mode && adjust) { + this.timeline.fit(); + } + }, + + /** + * Apply/clear User Filter + * @param {Object} clear + */ + apply_clear_user_filter: function(clear) { + var self = this; + if (clear) { + self.user_domains = false; + self.$el.find("#user_filer .o_searchview_extended_prop_field").val(""); + self.$el.find("#user_filer .o_searchview_extended_prop_field").change(); + self.$el + .find("#user_filer .o_searchview_extended_prop_field") + .val("category_id"); + self.$el.find("#user_filer .o_searchview_extended_prop_field").change(); + self.do_search( + self.last_domains, + self.last_contexts, + self.last_group_bys + ); + } else { + var filters = _.invoke(this.propositions, "get_filter"); + var domain = + filters[0] && filters[0].attrs && filters[0].attrs.domain + ? filters[0].attrs.domain + : false; + + /* New method call improved by Sandip on 2018-09-21 */ + if (domain) { + this._rpc({ + model: "fsm.person", + method: "search", + args: [domain], + kwargs: {context: session.user_context}, + }).then(function(user_ids) { + var list_user_ids = []; + $.each(user_ids, function(index, value) { + var id = value; + var name = ""; + for (var i in self.res_users[0]) { + if (self.res_users[0][i].id === id) { + name = self.res_users[0][i].name; + } + } + list_user_ids.push({id: id, name: name}); + }); + var ids = user_ids; + ids.push(false); + self.user_domains = ["person_id", "in", ids]; + var temp_domain = []; + if (self.last_domains) { + temp_domain = _.clone(self.last_domains); + } + temp_domain.push(self.user_domains); + self.do_search_related_user_filter( + temp_domain, + self.last_contexts, + self.last_group_bys, + list_user_ids + ); + }); + } + } + }, + + /** + * On start + * @returns this._super() + */ + start: function() { + var self = this; + + /* Bind User Filter Apply/Clear Click Event */ + this.$el + .find(".oe_timeline_button_apply") + .click($.proxy(this.on_apply_clicked, this)); + this.$el + .find(".oe_timeline_button_clear") + .click($.proxy(this.on_clear_clicked, this)); + + /* Fetch User Fields And Append To Timeline View. */ + self._rpc({ + model: "fsm.person", + method: "fields_get", + }).then(function(fields) { + self.user_filter = true; + var prop = new search_filters.ExtendedSearchProposition(self, fields); + self.propositions.push(prop); + prop.appendTo(self.$el.find("#user_filer")); + self.$el.find("#user_filer .o_searchview_extended_delete_prop").hide(); + self.$el.find("#user_filer .o_or_filter").hide(); + }); + return this._super(); + }, + + /** + * Call apply User Filter + */ + on_apply_clicked: function() { + this.apply_clear_user_filter(false); + }, + + /** + * Call Clear User Filter + */ + on_clear_clicked: function() { + this.apply_clear_user_filter(true); + }, + }); +}); diff --git a/fieldservice_timeline/static/src/scss/fsm_gantt_person_filter.scss b/fieldservice_timeline/static/src/scss/fsm_gantt_person_filter.scss new file mode 100644 index 0000000000..e1aeadc4d1 --- /dev/null +++ b/fieldservice_timeline/static/src/scss/fsm_gantt_person_filter.scss @@ -0,0 +1,13 @@ +/*User Filter Design*/ +#user_filer { + &.o_filter_condition select, + .o_searchview_extended_prop_value, + .o_datepicker, + .o_searchview_extended_prop_value input { + display: inline !important; + width: 150px !important; + } + > li { + list-style: none; + } +} diff --git a/fieldservice_timeline/static/src/xml/fsm_gantt_person_filter.xml b/fieldservice_timeline/static/src/xml/fsm_gantt_person_filter.xml new file mode 100644 index 0000000000..4162bda589 --- /dev/null +++ b/fieldservice_timeline/static/src/xml/fsm_gantt_person_filter.xml @@ -0,0 +1,27 @@ + diff --git a/fieldservice_timeline/views/fsm_order.xml b/fieldservice_timeline/views/fsm_order.xml new file mode 100644 index 0000000000..415aafdb49 --- /dev/null +++ b/fieldservice_timeline/views/fsm_order.xml @@ -0,0 +1,43 @@ + +