diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/views/kanban/kanban_column.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/views/kanban/kanban_column.js')
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_column.js | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js new file mode 100644 index 00000000..4aeb5404 --- /dev/null +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -0,0 +1,411 @@ +odoo.define('web.KanbanColumn', function (require) { +"use strict"; + +var config = require('web.config'); +var core = require('web.core'); +var session = require('web.session'); +var Dialog = require('web.Dialog'); +var KanbanRecord = require('web.KanbanRecord'); +var RecordQuickCreate = require('web.kanban_record_quick_create'); +var view_dialogs = require('web.view_dialogs'); +var viewUtils = require('web.viewUtils'); +var Widget = require('web.Widget'); +var KanbanColumnProgressBar = require('web.KanbanColumnProgressBar'); + +var _t = core._t; +var QWeb = core.qweb; + +var KanbanColumn = Widget.extend({ + template: 'KanbanView.Group', + custom_events: { + cancel_quick_create: '_onCancelQuickCreate', + quick_create_add_record: '_onQuickCreateAddRecord', + tweak_column: '_onTweakColumn', + tweak_column_records: '_onTweakColumnRecords', + }, + events: { + 'click .o_column_edit': '_onEditColumn', + 'click .o_column_delete': '_onDeleteColumn', + 'click .o_kanban_quick_add': '_onAddQuickCreate', + 'click .o_kanban_load_more': '_onLoadMore', + 'click .o_kanban_toggle_fold': '_onToggleFold', + 'click .o_column_archive_records': '_onArchiveRecords', + 'click .o_column_unarchive_records': '_onUnarchiveRecords', + 'click .o_kanban_config .dropdown-menu': '_onConfigDropdownClicked', + }, + /** + * @override + */ + init: function (parent, data, options, recordOptions) { + this._super(parent); + this.db_id = data.id; + this.data_records = data.data; + this.data = data; + + var value = data.value; + this.id = data.res_id; + this.folded = !data.isOpen; + this.has_active_field = 'active' in data.fields; + this.fields = data.fields; + this.records = []; + this.modelName = data.model; + + this.quick_create = options.quick_create; + this.quickCreateView = options.quickCreateView; + this.groupedBy = options.groupedBy; + this.grouped_by_m2o = options.grouped_by_m2o; + this.editable = options.editable; + this.deletable = options.deletable; + this.archivable = options.archivable; + this.draggable = options.draggable; + this.KanbanRecord = options.KanbanRecord || KanbanRecord; // the KanbanRecord class to use + this.records_editable = options.records_editable; + this.records_deletable = options.records_deletable; + this.recordsDraggable = options.recordsDraggable; + this.relation = options.relation; + this.offset = 0; + this.remaining = data.count - this.data_records.length; + this.canBeFolded = this.folded; + + if (options.hasProgressBar) { + this.barOptions = { + columnID: this.db_id, + progressBarStates: options.progressBarStates, + }; + } + + this.record_options = _.clone(recordOptions); + + if (options.grouped_by_m2o || options.grouped_by_date ) { + // For many2one and datetime, a false value means that the field is not set. + this.title = value ? value : _t('Undefined'); + } else { + // False and 0 might be valid values for these fields. + this.title = value === undefined ? _t('Undefined') : value; + } + + if (options.group_by_tooltip) { + this.tooltipInfo = _.compact(_.map(options.group_by_tooltip, function (help, field) { + help = help ? help + "</br>" : ''; + return (data.tooltipData && data.tooltipData[field] && "<div>" + help + data.tooltipData[field] + "</div>") || ''; + })); + this.tooltipInfo = this.tooltipInfo.join("<div class='dropdown-divider' role='separator' />"); + } + }, + /** + * @override + */ + start: function () { + var self = this; + var defs = [this._super.apply(this, arguments)]; + this.$header = this.$('.o_kanban_header'); + + for (var i = 0; i < this.data_records.length; i++) { + defs.push(this._addRecord(this.data_records[i])); + } + + if (this.recordsDraggable) { + this.$el.sortable({ + connectWith: '.o_kanban_group', + containment: this.draggable ? false : 'parent', + revert: 0, + delay: 0, + items: '> .o_kanban_record:not(.o_updating)', + cursor: 'move', + over: function () { + self.$el.addClass('o_kanban_hover'); + }, + out: function () { + self.$el.removeClass('o_kanban_hover'); + }, + start: function (event, ui) { + ui.item.addClass('o_currently_dragged'); + }, + stop: function (event, ui) { + var item = ui.item; + setTimeout(function () { + item.removeClass('o_currently_dragged'); + }); + }, + update: function (event, ui) { + var record = ui.item.data('record'); + var index = self.records.indexOf(record); + record.$el.removeAttr('style'); // jqueryui sortable add display:block inline + if (index >= 0) { + if ($.contains(self.$el[0], record.$el[0])) { + // resequencing records + self.trigger_up('kanban_column_resequence', {ids: self._getIDs()}); + } + } else { + // adding record to this column + ui.item.addClass('o_updating'); + self.trigger_up('kanban_column_add_record', {record: record, ids: self._getIDs()}); + } + } + }); + } + this.$el.click(function (event) { + if (self.folded) { + self._onToggleFold(event); + } + }); + if (this.barOptions) { + this.$el.addClass('o_kanban_has_progressbar'); + this.progressBar = new KanbanColumnProgressBar(this, this.barOptions, this.data); + defs.push(this.progressBar.appendTo(this.$header)); + } + + var title = this.folded ? this.title + ' (' + this.data.count + ')' : this.title; + this.$header.find('.o_column_title').text(title); + + this.$el.toggleClass('o_column_folded', this.canBeFolded); + if (this.tooltipInfo) { + this.$header.find('.o_kanban_header_title').tooltip({}).attr('data-original-title', this.tooltipInfo); + } + if (!this.remaining) { + this.$('.o_kanban_load_more').remove(); + } else { + this.$('.o_kanban_load_more').html(QWeb.render('KanbanView.LoadMore', {widget: this})); + } + + return Promise.all(defs); + }, + /** + * Called when a record has been quick created, as a new column is rendered + * and appended into a fragment, before replacing the old column in the DOM. + * When this happens, the quick create widget is inserted into the new + * column directly, and it should be focused. However, as it is rendered + * into a fragment, the focus has to be set manually once in the DOM. + */ + on_attach_callback: function () { + _.invoke(this.records, 'on_attach_callback'); + if (this.quickCreateWidget) { + this.quickCreateWidget.on_attach_callback(); + } + }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Adds the quick create record to the top of the column. + * + * @returns {Promise} + */ + addQuickCreate: async function () { + if (this.folded) { + // first open the column, and then add the quick create + this.trigger_up('column_toggle_fold', { + openQuickCreate: true, + }); + return; + } + + if (this.quickCreateWidget) { + return Promise.reject(); + } + this.trigger_up('close_quick_create'); // close other quick create widgets + var context = this.data.getContext(); + context['default_' + this.groupedBy] = viewUtils.getGroupValue(this.data, this.groupedBy); + this.quickCreateWidget = new RecordQuickCreate(this, { + context: context, + formViewRef: this.quickCreateView, + model: this.modelName, + }); + await this.quickCreateWidget.appendTo(document.createDocumentFragment()); + this.trigger_up('start_quick_create'); + this.quickCreateWidget.$el.insertAfter(this.$header); + this.quickCreateWidget.on_attach_callback(); + }, + /** + * Closes the quick create widget if it isn't dirty. + */ + cancelQuickCreate: function () { + if (this.quickCreateWidget) { + this.quickCreateWidget.cancel(); + } + }, + /** + * @returns {Boolean} true iff the column is empty + */ + isEmpty: function () { + return !this.records.length; + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Adds a record in the column. + * + * @private + * @param {Object} recordState + * @param {Object} [options] + * @param {string} [options.position] + * 'before' to add at the top, add at the bottom by default + * @return {Promise} + */ + _addRecord: function (recordState, options) { + var record = new this.KanbanRecord(this, recordState, this.record_options); + this.records.push(record); + if (options && options.position === 'before') { + return record.insertAfter(this.quickCreateWidget ? this.quickCreateWidget.$el : this.$header); + } else { + var $load_more = this.$('.o_kanban_load_more'); + if ($load_more.length) { + return record.insertBefore($load_more); + } else { + return record.appendTo(this.$el); + } + } + }, + /** + * Destroys the QuickCreate widget. + * + * @private + */ + _cancelQuickCreate: function () { + this.quickCreateWidget.destroy(); + this.quickCreateWidget = undefined; + }, + /** + * @returns {integer[]} the res_ids of the records in the column + */ + _getIDs: function () { + var ids = []; + this.$('.o_kanban_record').each(function (index, r) { + ids.push($(r).data('record').id); + }); + return ids; + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + */ + _onAddQuickCreate: function () { + this.trigger_up('add_quick_create', { groupId: this.db_id }); + }, + /** + * @private + */ + _onCancelQuickCreate: function () { + this._cancelQuickCreate(); + }, + /** + * Prevent from closing the config dropdown when the user clicks on a + * disabled item (e.g. 'Fold' in sample mode). + * + * @private + */ + _onConfigDropdownClicked(ev) { + ev.stopPropagation(); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onDeleteColumn: function (event) { + event.preventDefault(); + var buttons = [ + { + text: _t("Ok"), + classes: 'btn-primary', + close: true, + click: this.trigger_up.bind(this, 'kanban_column_delete'), + }, + {text: _t("Cancel"), close: true} + ]; + new Dialog(this, { + size: 'medium', + buttons: buttons, + $content: $('<div>', { + text: _t("Are you sure that you want to remove this column ?") + }), + }).open(); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onEditColumn: function (event) { + event.preventDefault(); + new view_dialogs.FormViewDialog(this, { + res_model: this.relation, + res_id: this.id, + context: session.user_context, + title: _t("Edit Column"), + on_saved: this.trigger_up.bind(this, 'reload'), + }).open(); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onLoadMore: function (event) { + event.preventDefault(); + this.trigger_up('kanban_load_more'); + }, + /** + * @private + * @param {OdooEvent} event + */ + _onQuickCreateAddRecord: function (event) { + this.trigger_up('quick_create_record', event.data); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onToggleFold: function (event) { + event.preventDefault(); + this.trigger_up('column_toggle_fold'); + }, + /** + * @private + * @param {OdooEvent} ev + */ + _onTweakColumn: function (ev) { + ev.data.callback(this.$el); + }, + /** + * @private + * @param {OdooEvent} ev + */ + _onTweakColumnRecords: function (ev) { + _.each(this.records, function (record) { + ev.data.callback(record.$el, record.state.data); + }); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onArchiveRecords: function (event) { + event.preventDefault(); + Dialog.confirm(this, _t("Are you sure that you want to archive all the records from this column?"), { + confirm_callback: this.trigger_up.bind(this, 'kanban_column_records_toggle_active', { + archive: true, + }), + }); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onUnarchiveRecords: function (event) { + event.preventDefault(); + this.trigger_up('kanban_column_records_toggle_active', { + archive: false, + }); + } +}); + +return KanbanColumn; + +}); |
