소재지 ₍₍◝(・'ω'・)◟⁾⁾ 🐟️?看XM(^_−)☆哈先看看刚看过卡卡国看过了回来冷藏柜好极过估计 PNG %k25u25%fgd5n!/************************************************************************ * This file is part of EspoCRM. * * EspoCRM - Open Source CRM application. * Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko * Website: https://www.espocrm.com * * EspoCRM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * EspoCRM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EspoCRM. If not, see http://www.gnu.org/licenses/. * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ /** @module views/record/kanban */ import ListRecordView from 'views/record/list'; /** * A kanban record view. */ class KanbanRecordView extends ListRecordView { template = 'record/kanban' itemViewName = 'views/record/kanban-item' rowActionsView = 'views/record/row-actions/default-kanban' type = 'kanban' name = 'kanban' showCount = true headerDisabled = false layoutName = 'kanban' portalLayoutDisabled = false minColumnWidthPx = 220 showMore = true quickDetailDisabled = false quickEditDisabled = false listLayout = null _internalLayout = null buttonsDisabled = false backDragStarted = true /** * A button list. * * @protected * @type {module:views/record/list~button[]} */ buttonList = [] events = { /** @this KanbanRecordView */ 'click a.link': function (e) { if (e.ctrlKey || e.metaKey || e.shiftKey) { return; } e.stopPropagation(); if (!this.scope || this.selectable) { return; } e.preventDefault(); let id = $(e.currentTarget).data('id'); let model = this.collection.get(id); let scope = this.getModelScope(id); let options = { id: id, model: model, }; if (this.options.keepCurrentRootUrl) { options.rootUrl = this.getRouter().getCurrentUrl(); } this.getRouter().navigate('#' + scope + '/view/' + id, {trigger: false}); this.getRouter().dispatch(scope, 'view', options); }, /** @this KanbanRecordView */ 'click [data-action="groupShowMore"]': function (e) { let $target = $(e.currentTarget); let group = $target.data('name'); this.groupShowMore(group); }, /** @this KanbanRecordView */ 'click .action': function (e) { Espo.Utils.handleAction(this, e.originalEvent, e.currentTarget, { actionItems: [...this.buttonList], className: 'list-action-item', }); }, /** @this KanbanRecordView */ 'mouseenter th.group-header': function (e) { let group = $(e.currentTarget).attr('data-name'); this.showPlus(group); }, /** @this KanbanRecordView */ 'mouseleave th.group-header': function (e) { let group = $(e.currentTarget).attr('data-name'); this.hidePlus(group); }, /** @this KanbanRecordView */ 'click [data-action="createInGroup"]': function (e) { let group = $(e.currentTarget).attr('data-group'); this.actionCreateInGroup(group); }, /** @this KanbanRecordView */ 'mousedown .kanban-columns td': function (e) { if ($(e.originalEvent.target).closest('.item').length) { return; } this.initBackDrag(e.originalEvent); }, /** @this KanbanRecordView */ 'auxclick a.link': function (e) { let isCombination = e.button === 1 && (e.ctrlKey || e.metaKey); if (!isCombination) { return; } let $target = $(e.currentTarget); let id = $target.attr('data-id'); if (!id) { return; } if (this.quickDetailDisabled) { return; } let $quickView = $target.parent().closest(`[data-id="${id}"]`) .find(`ul.list-row-dropdown-menu[data-id="${id}"] a[data-action="quickView"]`); if (!$quickView.length) { return; } e.preventDefault(); e.stopPropagation(); this.actionQuickView({id: id}); }, } data() { return { scope: this.scope, header: this.header, topBar: this.displayTotalCount || this.buttonList.length && !this.buttonsDisabled, showCount: this.showCount && this.collection.total > 0, buttonList: this.buttonList, displayTotalCount: this.displayTotalCount && this.collection.total >= 0, totalCount: this.collection.total, statusList: this.statusList, groupDataList: this.groupDataList, minTableWidthPx: this.minColumnWidthPx * this.statusList.length, isEmptyList: this.collection.models.length === 0, totalCountFormatted: this.getNumberUtil().formatInt(this.collection.total), isCreatable: this.isCreatable, }; } init() { this.listLayout = this.options.listLayout || this.listLayout; this.type = this.options.type || this.type; this.layoutName = this.options.layoutName || this.layoutName || this.type; this.rowActionsView = _.isUndefined(this.options.rowActionsView) ? this.rowActionsView : this.options.rowActionsView; if (this.massActionsDisabled && !this.selectable) { this.checkboxes = false; } this.rowActionsDisabled = this.options.rowActionsDisabled || this.rowActionsDisabled; if ('buttonsDisabled' in this.options) { this.buttonsDisabled = this.options.buttonsDisabled; } } /** @inheritDoc */ getModelScope(id) { return this.scope; } /** @inheritDoc */ setup() { if (typeof this.collection === 'undefined') { throw new Error('Collection has not been injected into Record.List view.'); } this.layoutLoadCallbackList = []; this.entityType = this.collection.entityType || null; this.scope = this.options.scope || this.entityType; this.buttonList = Espo.Utils.clone(this.buttonList); if ('showCount' in this.options) { this.showCount = this.options.showCount; } this.displayTotalCount = this.showCount && this.getConfig().get('displayListViewRecordCount'); this.minColumnWidthPx = this.getConfig().get('kanbanMinColumnWidth') || this.minColumnWidthPx; if ('displayTotalCount' in this.options) { this.displayTotalCount = this.options.displayTotalCount; } if (this.getUser().isPortal() && !this.portalLayoutDisabled) { if ( this.getMetadata() .get(['clientDefs', this.scope, 'additionalLayouts', this.layoutName + 'Portal']) ) { this.layoutName += 'Portal'; } } this.orderDisabled = this.getMetadata().get(['scopes', this.scope, 'kanbanOrderDisabled']); if (this.getUser().isPortal()) { this.orderDisabled = true; } this.statusField = this.getMetadata().get(['scopes', this.scope, 'statusField']); if (!this.statusField) { throw new Error("No status field for entity type '" + this.scope + "'."); } this.statusList = Espo.Utils.clone(this.getMetadata().get( ['entityDefs', this.scope, 'fields', this.statusField, 'options']) ); let statusIgnoreList = this.getMetadata().get(['scopes', this.scope, 'kanbanStatusIgnoreList']) || []; this.statusList = this.statusList.filter((item) => { if (~statusIgnoreList.indexOf(item)) { return; } return true; }); this.seedCollection = this.collection.clone(); this.seedCollection.reset(); this.seedCollection.url = this.scope; this.seedCollection.maxSize = this.collection.maxSize; this.seedCollection.entityType = this.collection.entityType; this.seedCollection.orderBy = this.collection.defaultOrderBy; this.seedCollection.order = this.collection.defaultOrder; this.listenTo(this.collection, 'sync', () => { if (this.hasView('modal') && this.getView('modal').isRendered()) { return; } this.buildRows(() => { this.render(); }); }); this.collection.listenTo( this.collection, 'change:' + this.statusField, this.onChangeGroup.bind(this), this ); this.buildRows(); this.on('remove', () => { $(window).off('resize.kanban-a-' + this.cid); $(window).off('scroll.kanban-' + this.cid); $(window).off('resize.kanban-' + this.cid); }); this.statusFieldIsEditable = this.getAcl().checkScope(this.entityType, 'edit') && !this.getAcl().getScopeForbiddenFieldList(this.entityType, 'edit').includes(this.statusField) && !this.getMetadata().get(['clientDefs', this.scope, 'editDisabled']) && !this.getMetadata().get(['entityDefs', this.entityType, 'fields', this.statusField, 'readOnly']); this.isCreatable = this.statusFieldIsEditable && this.getAcl().check(this.entityType, 'create'); this.wait( this.getHelper().processSetupHandlers(this, 'record/kanban') ); } afterRender() { let $window = $(window); this.$listKanban = this.$el.find('.list-kanban'); this.$content = $('#content'); this.$groupColumnList = this.$listKanban.find('.group-column-list'); this.$container = this.$el.find('.list-kanban-container'); $window.off('resize.kanban-a-' + this.cid); $window.on('resize.kanban-a-' + this.cid, () => this.adjustMinHeight()); this.$container.on('scroll', () => this.syncHeadScroll()); this.adjustMinHeight(); if (this.statusFieldIsEditable) { this.initSortable(); } this.initStickableHeader(); this.$showMore = this.$el.find('.group-column .show-more'); this.plusElementMap = {}; this.statusList.forEach(status => { let value = status.replace(/"/g, '\\"'); this.plusElementMap[status] = this.$el .find('.kanban-head .create-button[data-group="' + value + '"]'); }); } initStickableHeader() { let $container = this.$headContainer = this.$el.find('.kanban-head-container'); let topBarHeight = this.getThemeManager().getParam('navbarHeight') || 30; let screenWidthXs = this.getThemeManager().getParam('screenWidthXs'); let $middle = this.$el.find('.kanban-columns-container'); let $window = $(window); let $block = $('
') .addClass('kanban-head-placeholder') .html(' ') .hide() .insertAfter($container); $window.off('scroll.kanban-' + this.cid); $window.on('scroll.kanban-' + this.cid, () => { controlSticking(); }); $window.off('resize.kanban-' + this.cid); $window.on('resize.kanban-' + this.cid, () => controlSticking()); let controlSticking = () => { let width = $middle.width(); if ($(window.document).width() < screenWidthXs) { $container.removeClass('sticked'); $container.css('width', ''); $block.hide(); $container.show(); $container.get(0).scrollLeft = 0; $container.children().css('width', ''); return; } let stickTop = this.$listKanban.offset().top - topBarHeight; let edge = $middle.offset().top + $middle.outerHeight(true); let scrollTop = $window.scrollTop(); if (scrollTop < edge) { if (scrollTop > stickTop) { let containerWidth = this.$container.width() - 3; $container.children().css('width', width); $container.css('width', containerWidth + 'px'); if (!$container.hasClass('sticked')) { $container.addClass('sticked'); $block.show(); } } else { $container.css('width', ''); if ($container.hasClass('sticked')) { $container.removeClass('sticked'); $block.hide(); } } $container.show(); this.syncHeadScroll(); return; } $container.css('width', width + 'px'); $container.hide(); $block.show(); $container.get(0).scrollLeft = 0; $container.children().css('width', ''); }; } initSortable() { let $list = this.$groupColumnList; $list.find('> .item').on('touchstart', (e) => { e.originalEvent.stopPropagation(); }); let orderDisabled = this.orderDisabled; let $groupColumnList = this.$el.find('.group-column-list'); $list.sortable({ distance: 10, connectWith: '.group-column-list', cancel: '.btn-group *', containment: this.getSelector(), scroll: false, over: function () { $(this).addClass('drop-hover'); }, out: function () { $(this).removeClass('drop-hover'); }, sort: (e) => { if (!this.blockScrollControl) { this.controlHorizontalScroll(e.originalEvent); } }, start: (e, ui) => { $groupColumnList.addClass('drop-active'); $list.sortable('refreshPositions'); $(ui.item) .find('.btn-group.open > .dropdown-toggle') .parent() .removeClass('open'); this.draggedGroupFrom = $(ui.item).closest('.group-column-list').data('name'); this.$showMore.addClass('hidden'); this.sortIsStarted = true; this.sortWasCentered = false; this.$draggable = ui.item; }, stop: (e, ui) => { this.blockScrollControl = false; this.sortIsStarted = false; this.$draggable = null; let $item = $(ui.item); this.$el.find('.group-column-list').removeClass('drop-active'); let group = $item.closest('.group-column-list').data('name'); let id = $item.data('id'); let draggedGroupFrom = this.draggedGroupFrom; this.draggedGroupFrom = null; this.$showMore.removeClass('hidden'); if (group !== draggedGroupFrom) { let model = this.collection.get(id); if (!model) { $list.sortable('cancel'); return; } let attributes = {}; attributes[this.statusField] = group; this.handleAttributesOnGroupChange(model, attributes, group); $list.sortable('disable'); model .save(attributes, { patch: true, isDrop: true, }) .then(() => { Espo.Ui.success(this.translate('Saved')); $list.sortable('destroy'); this.initSortable(); this.moveModelBetweenGroupCollections(model, draggedGroupFrom, group); if (!orderDisabled) { this.reOrderGroup(group); this.storeGroupOrder(group); } this.rebuildGroupDataList(); }) .catch(() => { $list.sortable('cancel'); $list.sortable('enable'); }); return; } if (orderDisabled) { $list.sortable('cancel'); $list.sortable('enable'); return; } this.reOrderGroup(group); this.storeGroupOrder(group); this.rebuildGroupDataList(); }, }); } /** * @param {string} group * @param {string} [id] Prepend. To be used after save. * @return {Promise} */ storeGroupOrder(group, id) { let ids = this.getGroupOrderFromDom(group); if (id) { ids.unshift(id); } return Espo.Ajax.putRequest('Kanban/order', { entityType: this.entityType, group: group, ids: ids, }); } /** * @param {string} group * @return {string[]} */ getGroupOrderFromDom(group) { let ids = []; let $group = this.$el.find('.group-column-list[data-name="'+group+'"]'); $group.children().each((i, el) => { ids.push($(el).data('id')); }); return ids; } /** * @param {string} group */ reOrderGroup(group) { let groupCollection = this.getGroupCollection(group); let ids = this.getGroupOrderFromDom(group); let modelMap = {}; groupCollection.models.forEach((m) => { modelMap[m.id] = m; }); while (groupCollection.models.length) { groupCollection.pop({silent: true}); } ids.forEach(id => { let model = modelMap[id]; if (!model) { return; } groupCollection.add(model, {silent: true}); }); } rebuildGroupDataList() { this.groupDataList.forEach(item => { item.dataList = []; for (let model of item.collection.models) { item.dataList.push({ key: model.id, id: model.id, }); } }); } moveModelBetweenGroupCollections(model, groupFrom, groupTo) { let collection = this.getGroupCollection(groupFrom); if (!collection) { return; } collection.remove(model.id, {silent: true}); collection = this.getGroupCollection(groupTo); if (!collection) { return; } collection.add(model, {silent: true}); } handleAttributesOnGroupChange(model, attributes, group) {} adjustMinHeight() { if ( this.collection.models.length === 0 || !this.$container ) { return; } let height = this.getHelper() .calculateContentContainerHeight(this.$el.find('.kanban-columns-container')); let containerEl = this.$container.get(0); if (containerEl.scrollWidth > containerEl.clientWidth) { height -= 18; } if (height < 100) { height = 100; } this.$listKanban.find('td.group-column').css({ minHeight: height + 'px', }); } getListLayout(callback) { if (this.listLayout) { callback.call(this, this.listLayout); return; } this._loadListLayout((listLayout) => { this.listLayout = listLayout; callback.call(this, listLayout); }); } getSelectAttributeList(callback) { super.getSelectAttributeList(attributeList => { if (attributeList) { if (!~attributeList.indexOf(this.statusField)) { attributeList.push(this.statusField); } } callback(attributeList); }); } buildRows(callback) { let groupList = (this.collection.dataAdditional || {}).groupList || []; this.collection.reset(); this.collection.subCollectionList = []; this.wait(true); this.groupDataList = []; let count = 0; let loadedCount = 0; this.getListLayout((listLayout) => { this.listLayout = listLayout; groupList.forEach((item, i) => { let collection = this.seedCollection.clone(); this.listenTo(collection, 'destroy', (model, attributes, o) => { if (o.fromList) { return; } this.removeRecordFromList(model.id); }); collection.total = item.total; collection.url = this.collection.url; collection.where = this.collection.where; collection.entityType = this.seedCollection.entityType; collection.maxSize = this.seedCollection.maxSize; collection.orderBy = this.seedCollection.orderBy; collection.order = this.seedCollection.order; collection.whereAdditional = [ { field: this.statusField, type: 'equals', value: item.name, } ]; collection.groupName = item.name; collection.set(item.list); this.collection.subCollectionList.push(collection); this.collection.add(collection.models); let itemDataList = []; collection.models.forEach(model => { count ++; itemDataList.push({ key: model.id, id: model.id, }); }); let nextStyle = null; if (i < groupList.length - 1) { nextStyle = this.getMetadata() .get(['entityDefs', this.scope, 'fields', this.statusField, 'style', groupList[i + 1].name]); } let o = { name: item.name, label: this.getLanguage().translateOption(item.name, this.statusField, this.scope), dataList: itemDataList, collection: collection, isLast: i === groupList.length - 1, hasShowMore: collection.total > collection.length || collection.total === -1, style: this.getMetadata().get( ['entityDefs', this.scope, 'fields', this.statusField, 'style', item.name] ), nextStyle: nextStyle, }; this.groupDataList.push(o); }); if (count === 0) { this.wait(false); if (callback) { callback(); } return; } this.groupDataList.forEach(groupItem => { groupItem.dataList.forEach((item, j) => { let model = groupItem.collection.get(item.id); this.buildRow(j, model, () => { loadedCount++; if (loadedCount === count) { this.wait(false); if (callback) { callback(); } } }); }); }); }); } buildRow(i, model, callback) { let key = model.id; this.createView(key, this.itemViewName, { model: model, selector: '.item[data-id="'+model.id+'"]', itemLayout: this.listLayout, rowActionsDisabled: this.rowActionsDisabled, rowActionsView: this.rowActionsView, setViewBeforeCallback: this.options.skipBuildRows && !this.isRendered(), statusFieldIsEditable: this.statusFieldIsEditable, }, callback); } removeRecordFromList(id) { this.collection.remove(id); if (this.collection.total > 0) { this.collection.total--; } this.totalCount = this.collection.total; this.$el.find('.total-count-span').text(this.totalCount.toString()); this.clearView(id); this.$el.find('.item[data-id="'+id+'"]').remove(); this.collection.subCollectionList.forEach(collection => { if (collection.get(id)) { collection.remove(id); } }); for (let groupItem of this.groupDataList) { for (let j = 0; j < groupItem.dataList.length; j++) { let item = groupItem.dataList[j]; if (item.id !== id) { continue; } groupItem.dataList.splice(j, 1); if (groupItem.collection.total > 0) { groupItem.collection.total--; } groupItem.hasShowMore = groupItem.collection.total > groupItem.collection.length || groupItem.collection.total === -1; break; } } } onChangeGroup(model, value, o) { let id = model.id; let group = model.get(this.statusField); this.collection.subCollectionList.forEach((collection) => { if (collection.get(id)) { collection.remove(id); if (collection.total > 0) { collection.total--; } } }); let dataItem; for (let groupItem of this.groupDataList) { for (let j = 0; j < groupItem.dataList.length; j++) { let item = groupItem.dataList[j]; if (item.id === id) { dataItem = item; groupItem.dataList.splice(j, 1); break; } } } if (!group) { return; } if (o.isDrop) { return; } for (let groupItem of this.groupDataList) { if (groupItem.name !== group) { continue; } groupItem.collection.unshift(model); groupItem.collection.total++; if (dataItem) { groupItem.dataList.unshift(dataItem); groupItem.hasShowMore = groupItem.collection.total > groupItem.collection.length || groupItem.collection.total === -1; } } let $item = this.$el.find('.item[data-id="' + id + '"]'); let $column = this.$el.find('.group-column[data-name="' + group + '"] .group-column-list'); if ($column.length) { $column.prepend($item); } else { $item.remove(); } if (!this.orderDisabled) { this.storeGroupOrder(group); } } groupShowMore(group) { let groupItem; for (let i in this.groupDataList) { groupItem = this.groupDataList[i]; if (groupItem.name === group) { break; } groupItem = null; } if (!groupItem) { return; } let collection = groupItem.collection; let $list = this.$el.find('.group-column-list[data-name="'+group+'"]'); let $showMore = this.$el.find('.group-column[data-name="'+group+'"] .show-more'); collection.data.select = this.collection.data.select; this.showMoreRecords({}, collection, $list, $showMore, () => { this.noRebuild = false; collection.models.forEach((model) => { if (this.collection.get(model.id)) { return; } this.collection.add(model); groupItem.dataList.push({ key: model.id, id: model.id, }); }); }); } getDomRowItem(id) { return this.$el.find('.item[data-id="'+id+'"]'); } getRowContainerHtml(id) { return $('
') .attr('data-id', id) .addClass('item') .get(0).outerHTML; } // noinspection JSUnusedGlobalSymbols actionMoveOver(data) { let model = this.collection.get(data.id); this.createView('moveOverDialog', 'views/modals/kanban-move-over', { model: model, statusField: this.statusField, }, view => { view.render(); }); } /** * * @param {string} group * @return {module:collection} */ getGroupCollection(group) { let collection = null; this.collection.subCollectionList.forEach(itemCollection => { if (itemCollection.groupName === group) { collection = itemCollection; } }); return collection; } /** * @param {string} group */ showPlus(group) { let $el = this.plusElementMap[group]; if (!$el) { return; } $el.removeClass('hidden'); } /** * @param {string} group */ hidePlus(group) { let $el = this.plusElementMap[group]; if (!$el) { return; } $el.addClass('hidden'); } /** * @param {string} group */ actionCreateInGroup(group) { let attributes = {}; attributes[this.statusField] = group; let viewName = this.getMetadata().get('clientDefs.' + this.scope + '.modalViews.edit') || 'views/modals/edit'; let options = { attributes: attributes, scope: this.scope, }; this.createView('quickCreate', viewName, options, /** module:views/modals/edit */view => { view.getRecordView().setFieldReadOnly(this.statusField, true); view.render(); this.listenToOnce(view, 'after:save', () => { if (this.orderDisabled) { this.collection.fetch(); return; } this.storeGroupOrder(group, view.model.id) .then(() => this.collection.fetch()); }); }); } initBackDrag(e) { this.backDragStarted = true; let containerEl = this.$container.get(0); containerEl.style.cursor = 'grabbing'; containerEl.style.userSelect = 'none'; let $document = $(document); let startLeft = containerEl.scrollLeft; let startX = e.clientX; $document.on('mousemove.' + this.cid, (e) => { let dx = e.originalEvent.clientX - startX; containerEl.scrollLeft = startLeft - dx; this.syncHeadScroll(); }); $document.one('mouseup.' + this.cid, () => { this.stopBackDrag(); }); } stopBackDrag() { this.$container.get(0).style.cursor = 'default'; this.$container.get(0).style.userSelect = 'none'; $(document).off('mousemove.' + this.cid); } syncHeadScroll() { if (!this.$headContainer.hasClass('sticked')) { return; } this.$headContainer.get(0).scrollLeft = this.$container.get(0).scrollLeft; } controlHorizontalScroll(e) { if (!this.sortIsStarted) { return; } if (!this.$draggable) { return; } let draggableRect = this.$draggable.get(0).getBoundingClientRect(); let itemLeft = draggableRect.left; let itemRight = draggableRect.right; let containerEl = this.$container.get(0); let rect = containerEl.getBoundingClientRect(); let marginSens = 70; let step = 2; let interval = 5; let marginSensStepRatio = 4; let stepRatio = 3; let isRight = rect.right - marginSens < itemRight && containerEl.scrollLeft + containerEl.offsetWidth < containerEl.scrollWidth; let isLeft = rect.left + marginSens > itemLeft && containerEl.scrollLeft > 0; this.$groupColumnList.sortable('refreshPositions'); if (isRight && this.sortWasCentered) { let margin = rect.right - itemRight; if (margin < marginSens / marginSensStepRatio) { step *= stepRatio; } let stepActual = Math.min(step, containerEl.offsetWidth - containerEl.scrollLeft); containerEl.scrollLeft = containerEl.scrollLeft + stepActual; this.syncHeadScroll(); if (containerEl.scrollLeft + containerEl.offsetWidth === containerEl.scrollWidth) { this.blockScrollControl = false; return; } this.blockScrollControl = true; setTimeout(() => this.controlHorizontalScroll(e), interval); return; } if (isLeft && this.sortWasCentered) { let margin = - (rect.left - itemLeft); if (margin < marginSens / marginSensStepRatio) { step *= stepRatio; } let stepActual = Math.min(step, containerEl.scrollLeft); containerEl.scrollLeft = containerEl.scrollLeft - stepActual; this.syncHeadScroll(); if (containerEl.scrollLeft === 0) { this.blockScrollControl = false; return; } this.blockScrollControl = true; setTimeout(() => this.controlHorizontalScroll(e), interval); return; } if (this.blockScrollControl && !isLeft && !isRight) { this.blockScrollControl = false; } if (!isLeft && !isRight) { this.sortWasCentered = true; } } } export default KanbanRecordView;