summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/widgets
diff options
context:
space:
mode:
authorMathieu Duckerts-Antoine <dam@odoo.com>2018-06-11 15:45:30 +0200
committerGéry Debongnie <ged@odoo.com>2018-06-12 09:22:20 +0200
commite1aac71769c8d07a358b2d8717efa28248e18a34 (patch)
treeba63c14ad7aee42fc1e5fbd9b9b25f31ef1e69cc /addons/web/static/src/js/widgets
parent7bf5dd687be3919f6add10b1ac59a9cdee824632 (diff)
[IMP] web: add support for interval selection in groupbys
In this commit, we extend the search view to allow the selection of some intervals for date or datetime fields in groupby menu. The valid intervals are day, week, month, quarter, and year. It is also possible to add a button 'Group By' in the control panel owned by a graph view in case it is declared 'embedded' (e.g. in a dashboard view). Note that have three new generic reusable widgets have been introduced in this commit: DropdownMenu, GroupByMenu, and FiltersMenu.
Diffstat (limited to 'addons/web/static/src/js/widgets')
-rw-r--r--addons/web/static/src/js/widgets/dropdown_menu.js243
1 files changed, 243 insertions, 0 deletions
diff --git a/addons/web/static/src/js/widgets/dropdown_menu.js b/addons/web/static/src/js/widgets/dropdown_menu.js
new file mode 100644
index 00000000000..d7e4bff32a4
--- /dev/null
+++ b/addons/web/static/src/js/widgets/dropdown_menu.js
@@ -0,0 +1,243 @@
+odoo.define('web.DropdownMenu', function (require) {
+"use strict";
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+
+var QWeb = core.qweb;
+
+// interface IItem {
+// itemId: string;
+// description: string;
+// groupId: string;
+// isActive: boolean; (optional)
+// isOpen: boolean; (optional)
+// isRemovable: boolean; (optional)
+// options: array of objects with 'optionId' and 'description' keys; (optional)
+// defaultOptionId: string refers to an optionId (optional)
+// currentOptionId: string refers to an optionId that is activated if item is active (optional)
+// }
+
+var DropdownMenu = Widget.extend({
+ template: 'web.DropdownMenu',
+ events: {
+ 'click li.o_menu_item': '_onItemClick',
+ 'click li.o_item_option': '_onOptionClick',
+ 'click li.o_menu_item span.o_submenu_switcher': '_openItemOptions',
+ 'click span.o_trash_button': '_onTrashClick',
+ 'hidden.bs.dropdown': '_onBootstrapClose',
+ },
+
+ /**
+ * @param {Widget} parent
+ * @param {Object} dropdowHeader object with keys 'title' and 'icon'
+ * @param {Object} items values are arrays of items (see interface IItems)
+ * @param {Object} itemGenerator
+ */
+ init: function (parent, dropdownHeader, items) {
+ this._super(parent);
+ this.dropdownCategory = dropdownHeader.category;
+ this.dropdownTitle = dropdownHeader.title;
+ this.dropdownIcon = dropdownHeader.icon;
+ this.dropdownSymbol = dropdownHeader.symbol || 'caret';
+ // this parameter fixes the menu style. By default,
+ // the style used is the one used in the search view
+ this.dropdownStyle = dropdownHeader.style || {
+ el: {class: 'btn-group o_dropdown', attrs: {}},
+ mainButton: {class: 'o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle'},
+ };
+ this.items = _.sortBy(items, 'groupId');
+ _.each(this.items, this._prepareItem.bind(this));
+ },
+
+ start: function () {
+ this.$menu = this.$('.o_dropdown_menu');
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * @param {Array[number]} groupIds
+ */
+ unsetGroups: function (groupIds) {
+ var self = this;
+ _.each(self.items, function (item) {
+ if (_.contains(groupIds, item.groupId)) {
+ item.isActive = false;
+ item.currentOptionId = false;
+ }
+ });
+ this._renderMenuItems();
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {string} itemId
+ */
+ _removeItem: function (itemId) {
+ var item, itemIndex;
+ item = _.findWhere(this.items, {itemId: itemId});
+ itemIndex = this.items.indexOf(item);
+ this.items.splice(itemIndex, 1);
+ this._renderMenuItems();
+ var eventData = {
+ category: this.dropdownCategory,
+ itemId: itemId,
+ groupId: item.groupId,
+ };
+ this.trigger_up('menu_item_deleted', eventData);
+ },
+
+ /**
+ * @private
+ */
+ _renderMenuItems: function () {
+ var newMenuItems = QWeb.render('DropdownMenu.MenuItems', {widget: this});
+ this.$el.find('.o_menu_item,.divider[data-removable="1"]').remove();
+ this.$('ul.o_dropdown_menu').prepend($(newMenuItems));
+ },
+ /**
+ * @private
+ * @param {Object} item
+ */
+ _prepareItem: function (item) {
+ item.isOpen = item.isOpen || false;
+ item.isRemovable = item.isRemovable || false;
+ item.hasOptions = item.options && item.options.length !== 0 ? true : false;
+ item.defaultOptionId = item.hasOptions ?
+ (item.defaultOptionId || item.options[0].optionId) :
+ false;
+ item.currentOptionId = item.isActive ? (item.currentOptionId || item.defaultOptionId ) : false;
+ },
+ /**
+ * @private
+ * @param {string} itemId
+ */
+ _toggleMenuItem: function (itemId) {
+ var item = _.findWhere(this.items, {itemId: itemId});
+ item.isActive = !item.isActive;
+ var eventData = {
+ category: this.dropdownCategory,
+ itemId: itemId,
+ isActive: item.isActive,
+ groupId: item.groupId,
+ };
+ if (item.hasOptions) {
+ if (item.isActive) {
+ item.currentOptionId = item.defaultOptionId;
+ eventData.optionId = item.currentOptionId;
+ } else {
+ item.currentOptionId = false;
+ }
+ }
+ this._renderMenuItems();
+ this.trigger_up('menu_item_toggled', eventData);
+ },
+ /**
+ * @private
+ * @param {string} itemId
+ * @param {string} optionId
+ */
+ _toggleItemOption: function (itemId, optionId) {
+ var item = _.findWhere(this.items, {itemId: itemId});
+ var initialState = item.isActive;
+ if (item.currentOptionId === optionId) {
+ item.isActive = false;
+ item.currentOptionId = false;
+ } else {
+ item.isActive = true;
+ item.currentOptionId = optionId;
+ }
+ var eventData = {
+ category: this.dropdownCategory,
+ itemId: itemId,
+ groupId: item.groupId,
+ isActive: item.isActive,
+ optionId: item.currentOptionId,
+ };
+ this._renderMenuItems();
+ if (item.isActive !== initialState) {
+ this.trigger_up('menu_item_toggled', eventData);
+ } else {
+ this.trigger_up('item_option_changed', eventData);
+ }
+ },
+ /**
+ * @private
+ * @param {string} itemId
+ */
+ _toggleMenuOptions: function (itemId) {
+ var item = _.findWhere(this.items, {itemId: itemId});
+ item.isOpen = !item.isOpen;
+ this._renderMenuItems();
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+ /**
+ * This method is called when Bootstrap trigger a 'close' event (for example
+ * when the user clicks outside the dropdown menu).
+ *
+ * @private
+ * @param {jQueryEvent} event
+ */
+ _onBootstrapClose: function () {
+ _.each(this.items, function(item) {
+ item.isOpen = false;
+ });
+ this._renderMenuItems();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onItemClick: function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+ var itemId = $(event.currentTarget).data('id');
+ this._toggleMenuItem(itemId);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onOptionClick: function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+ var optionId = $(event.currentTarget).data('option_id');
+ var itemId = $(event.currentTarget).data('item_id');
+ this._toggleItemOption(itemId, optionId);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onTrashClick: function (event) {
+ event.stopPropagation();
+ var itemId = $(event.currentTarget).data('id');
+ this._removeItem(itemId);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _openItemOptions: function (event) {
+ // we preventdefault the event here to avoid changing the hash # in the
+ // url.
+ event.preventDefault();
+ event.stopPropagation();
+ var itemId = $(event.currentTarget).data('id');
+ this._toggleMenuOptions(itemId);
+ },
+});
+
+return DropdownMenu;
+
+}); \ No newline at end of file