UNPKG

@syncfusion/ej2-kanban

Version:

The Kanban board is an efficient way to visualize the workflow at each stage along its path to completion. The most important features available are Swim lane, filtering, and editing.

1,166 lines (1,156 loc) 359 kB
import { formatUnit, isNullOrUndefined, extend, Property, ChildProperty, closest, classList, removeClass, addClass, createInstance, detach, remove, createElement, SanitizeHtmlHelper, Draggable, EventHandler, append, KeyboardEvents, initializeCSPTemplate, Touch, setStyleAttribute, Browser, debounce, L10n, compile, Collection, Complex, Event, NotifyPropertyChanges, Component } from '@syncfusion/ej2-base'; import { Dialog, Tooltip, Popup, createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups'; import { DataManager, Query, UrlAdaptor, Deferred, Predicate } from '@syncfusion/ej2-data'; import { DropDownList } from '@syncfusion/ej2-dropdowns'; import { TextBox, NumericTextBox, FormValidator } from '@syncfusion/ej2-inputs'; import { Button } from '@syncfusion/ej2-buttons'; import { TreeView } from '@syncfusion/ej2-navigations'; /** * Kanban Constants */ // Constants for public events /** @private */ var actionBegin = 'actionBegin'; /** @private */ var actionComplete = 'actionComplete'; /** @private */ var actionFailure = 'actionFailure'; /** @private */ var cardClick = 'cardClick'; /** @private */ var cardDoubleClick = 'cardDoubleClick'; /** @private */ var cardRendered = 'cardRendered'; /** @private */ var queryCellInfo = 'queryCellInfo'; /** @private */ var dataBinding = 'dataBinding'; /** @private */ var dataBound = 'dataBound'; /** @private */ var dragStart = 'dragStart'; /** @private */ var drag = 'drag'; /** @private */ var dragStop = 'dragStop'; /** @private */ var documentClick = 'document-click'; /** @private */ var dialogOpen = 'dialogOpen'; /** @private */ var dialogClose = 'dialogClose'; // Constants for internal events /** @private */ var contentReady = 'content-ready'; /** @private */ var dataReady = 'data-ready'; /** @private */ var bottomSpace = 25; /** @private */ var cardSpace = 16; /** @private */ var toggleWidth = 50; /** @hidden */ var dataSourceChanged = 'dataSourceChanged'; /** @hidden */ var dataStateChange = 'dataStateChange'; /** @private */ var columnDragStart = 'columnDragStart'; /** @private */ var columnDrag = 'columnDrag'; /** @private */ var columnDrop = 'columnDrop'; /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Kanban data module */ var Data = /** @__PURE__ @class */ (function () { /** * Constructor for data module * * @param {Kanban} parent Accepts the instance of the Kanban */ function Data(parent) { this.initload = false; this.dataState = { isPending: false, resolver: null, isDataChanged: false }; this.parent = parent; this.keyField = this.parent.cardSettings.headerField; this.dataState = { isDataChanged: false }; this.isObservable = false; this.initDataManager(parent.dataSource, parent.query); this.refreshDataManager(); } /** * The function used to initialize dataManager` and query * * @param {Object[] | DataManager} dataSource Accepts the dataSource as collection of objects or Datamanager instance. * @param {Query} query Accepts the query to process the data from collections. * @returns {void} * @private */ Data.prototype.initDataManager = function (dataSource, query) { this.dataManager = dataSource instanceof DataManager ? dataSource : new DataManager(dataSource); this.query = query instanceof Query ? query : new Query(); this.kanbanData = new DataManager(this.parent.kanbanData); }; /** * @returns {boolean} returns whether its remote data * @hidden */ Data.prototype.isRemote = function () { return this.dataManager.dataSource.offline !== true && this.dataManager.dataSource.url !== undefined && this.dataManager.dataSource.url !== ''; }; /** * @returns {boolean} returns the column key fields * @hidden */ Data.prototype.columnKeyFields = function () { var columns = []; for (var _i = 0, _a = this.parent.columns; _i < _a.length; _i++) { var column = _a[_i]; if (column.keyField.toString().split(',').length > 1) { for (var _b = 0, _c = column.keyField.toString().split(','); _b < _c.length; _b++) { var innerColumns = _c[_b]; columns.push(innerColumns.trim()); } } else { columns.push(column.keyField.toString()); } } return columns; }; Data.prototype.parseViewportHeight = function (height) { var heightValue = height.toString().trim(); var viewportMatch = heightValue.match(/^([\d.]+)(vh)?$/i); var viewportBasedHeight = (window.innerHeight * parseFloat(viewportMatch[1])) / 100; return viewportBasedHeight; }; /** * The function used to generate updated Query from schedule model * * @param {string} parameter Accepts the parameter that needs to be sent to the service end. * @returns {void} * @private */ Data.prototype.getQuery = function (parameter) { var query = this.query.clone(); if (this.isRemote() && this.parent.enableVirtualization) { var cardHeight = this.parent.cardHeight === 'auto' ? 100 : parseInt(formatUnit(this.parent.cardHeight).split('px')[0], 10); var kanbanHeight = this.parent.height.toString(); var take = void 0; if (kanbanHeight === 'auto') { take = Math.ceil((window.innerHeight - 50) / cardHeight) * 2; } else if (kanbanHeight.endsWith('px')) { take = (Math.ceil((parseInt(formatUnit(this.parent.height).split('px')[0], 10) - 50) / cardHeight) * 2); } else if (kanbanHeight.endsWith('%')) { take = (Math.ceil((parseInt(formatUnit(this.parent.element.clientHeight).split('px')[0], 10) - 50) / cardHeight) * 2); } else if (kanbanHeight.toLowerCase().endsWith('vh')) { var viewportHeight = this.parseViewportHeight(this.parent.height); take = Math.ceil((viewportHeight - 50) / cardHeight) * 2; } else { take = Math.ceil((this.parent.element.getBoundingClientRect().height - 50) / cardHeight) * 2; } var columns = this.columnKeyFields(); for (var i = 0; i < columns.length; i++) { query.where(this.parent.keyField, 'equal', columns[i]); } query.take(take); if (isNullOrUndefined(parameter)) { parameter = 'KanbanVirtualization'; } query.addParams('KanbanVirtualization', parameter); } return query; }; /** * The function used to get dataSource by executing given Query * * @param {Query} query - A Query that specifies to generate dataSource * @returns {void} * @private */ Data.prototype.getData = function (query) { if (this.parent.dataSource && 'result' in this.parent.dataSource) { var def = this.eventPromise({ requestType: '' }, query); this.isObservable = true; return def.promise; } return this.dataManager.executeQuery(query); }; Data.prototype.setState = function (state) { return this.dataState = state; }; Data.prototype.getStateEventArgument = function (query) { var adaptr = new UrlAdaptor(); var dm = new DataManager({ url: '', adaptor: new UrlAdaptor }); var state = adaptr.processQuery(dm, query); var data = JSON.parse(state.data); return extend(data, state.pvtData); }; Data.prototype.eventPromise = function (args, query, index) { var _this = this; var dataArgs = args; var state = this.getStateEventArgument(query); var def = new Deferred(); var deff = new Deferred(); if (args.requestType !== undefined && this.dataState.isDataChanged !== false) { state.action = args; if (args.requestType === 'cardChanged' || args.requestType === 'cardRemoved' || args.requestType === 'cardCreated') { var editArgs_1 = args; editArgs_1.promise = deff.promise; editArgs_1.state = state; editArgs_1.index = index; this.setState({ isPending: true, resolver: deff.resolve }); dataArgs.endEdit = deff.resolve; dataArgs.cancelEdit = deff.reject; this.parent.trigger(dataSourceChanged, editArgs_1); deff.promise.then(function () { _this.setState({ isPending: true, resolver: def.resolve }); _this.parent.trigger(dataStateChange, state); editArgs_1.addedRecords.forEach(function (data) { _this.parent.kanbanData.push(data); }); editArgs_1.changedRecords.forEach(function (changedRecord) { var cardObj = _this.parent.kanbanData.filter(function (data) { return data[_this.parent.cardSettings.headerField] === changedRecord[_this.parent.cardSettings.headerField]; })[0]; extend(cardObj, changedRecord); }); editArgs_1.deletedRecords.forEach(function (deletedRecord) { var index = _this.parent.kanbanData.findIndex(function (data) { return data[_this.parent.cardSettings.headerField] === deletedRecord[_this.parent.cardSettings.headerField]; }); _this.parent.kanbanData.splice(index, 1); }); }).catch(function () { _this.parent.hideSpinner(); }); } else { this.setState({ isPending: true, resolver: def.resolve }); this.parent.trigger(dataStateChange, state); } } else { this.setState({}); def.resolve(this.parent.dataSource); } return def; }; /** * The function used to get the table name from the given Query * * @returns {string} Returns the table name. * @private */ Data.prototype.getTable = function () { if (this.parent.query) { var query = this.getQuery(); return query.fromTable; } else { return null; } }; /** * The function is used to send the request and get response from datamanager * * @returns {void} * @private */ Data.prototype.refreshDataManager = function () { var _this = this; var dataManager = this.getData(this.getQuery()); dataManager.then(function (e) { return _this.dataManagerSuccess(e); }).catch(function (e) { return _this.dataManagerFailure(e); }); }; /** * The function is used to handle the success response from dataManager * * @param {ReturnType} e Accepts the dataManager success result * @param type * @returns {void} * @private */ // eslint-disable-next-line Data.prototype.dataManagerSuccess = function (e, type, offlineArgs, index) { var _this = this; if (this.parent.isDestroyed) { return; } if (type) { this.updateKanbanData(e); if (this.parent.enableVirtualization && this.isRemote()) { this.parent.virtualLayoutModule.refresh(); } } else { this.parent.trigger(dataBinding, e, function (args) { _this.updateKanbanData(args); _this.parent.notify(dataReady, { processedData: _this.parent.kanbanData }); _this.parent.trigger(dataBound, null, function () { return _this.parent.hideSpinner(); }); }); } if (this.initload) { this.parent.layoutModule.refresh(); this.parent.renderTemplates(); } this.initload = true; }; /** * The function is used to handle the update the column data count for remote, and update kanbanData while perform the CRUD action * * @param {ReturnType} args Accepts the dataManager success result * @returns {void} * @private */ Data.prototype.updateKanbanData = function (args) { var resultData = extend([], !isNullOrUndefined(args.result.result) ? args.result.result : args.result, null, true); if (this.isRemote() && this.parent.enableVirtualization && resultData.length > 0 && !isNullOrUndefined(args.result.count)) { var columnsKeyFields = this.columnKeyFields(); for (var i = 0; i < columnsKeyFields.length; i++) { if (args.result.count[i].Key === columnsKeyFields[i]) { this.parent.columnDataCount[columnsKeyFields[i]] = args.result.count[i].Value; } } } this.parent.kanbanData = resultData; this.kanbanData = new DataManager(this.parent.kanbanData); }; /** * The function is used to handle the failure response from dataManager * * @param {ReturnType} e Accepts the dataManager failure result * @returns {void} * @private */ Data.prototype.dataManagerFailure = function (e) { var _this = this; if (this.parent.isDestroyed) { return; } this.parent.trigger(actionFailure, { error: e }, function () { return _this.parent.hideSpinner(); }); }; /** * The function is used to perform the insert, update, delete and batch actions in datamanager * * @param {string} updateType Accepts the update type action * @param {SaveChanges} params Accepts the savechanges params * @param {string} type Accepts the requestType as string * @param {Object} data Accepts the data to perform crud action * @param {number} index Accepts the index to refresh the data into UI * @param {boolean} isDropped Accepts the boolean value based on based if it is dragged and dropped * @param {string} dataDropIndexKeyFieldValue Accepts the dropped index key field value card * @param {number} draggedKey Accepts the dragged keyfield of the column * @param {number} droppedKey Accepts the dropped keyfield of the column * @param {number} isMultipleDrag Accepts boolean value based on the multiple drag of the cards * @returns {void} * @private */ Data.prototype.updateDataManager = function (updateType, params, type, data, index, isDropped, dataDropIndexKeyFieldValue, draggedKey, droppedKey, isMultipleDrag) { var _this = this; this.parent.showSpinner(); var promise; var actionArgs = { requestType: type, cancel: false, addedRecords: params.addedRecords, changedRecords: params.changedRecords, deletedRecords: params.deletedRecords }; this.setState({ isDataChanged: true }); this.eventPromise(actionArgs, this.query, index); this.parent.trigger(actionComplete, actionArgs, function (offlineArgs) { if (!offlineArgs.cancel) { promise = _this.syncDataSource(_this.dataManager, updateType, params, data, isDropped, dataDropIndexKeyFieldValue); if (_this.dataManager.dataSource.offline) { if (!_this.isObservable) { _this.syncDataSource(_this.kanbanData, updateType, params, data, isDropped, dataDropIndexKeyFieldValue); index = draggedKey === droppedKey && isMultipleDrag ? index - 1 : index; _this.refreshUI(offlineArgs, index, isDropped); if (_this.parent.enableVirtualization) { _this.parent.virtualLayoutModule.refreshColumnData(draggedKey, droppedKey, offlineArgs.requestType, data[_this.parent.keyField]); } } } else { promise.then(function (args) { if (_this.parent.isDestroyed) { return; } var dataManager = _this.getData(_this.getQuery()); dataManager.then(function (e) { return _this.dataManagerSuccess(e, 'DataSourceChange', offlineArgs, index); }).catch(function (e) { return _this.dataManagerFailure(e); }); if (offlineArgs.requestType === 'cardCreated') { if (!Array.isArray(args)) { offlineArgs.addedRecords[0] = extend(offlineArgs.addedRecords[0], args); } else { _this.modifyArrayData(offlineArgs.addedRecords, args); } } else if (offlineArgs.requestType === 'cardChanged') { if (!Array.isArray(args)) { offlineArgs.changedRecords[0] = extend(offlineArgs.changedRecords[0], args); } else { _this.modifyArrayData(offlineArgs.changedRecords, args); } } else if (offlineArgs.requestType === 'cardRemoved') { if (!Array.isArray(args)) { offlineArgs.deletedRecords[0] = extend(offlineArgs.deletedRecords[0], args); } else { _this.modifyArrayData(offlineArgs.deletedRecords, args); } } index = draggedKey === droppedKey && isMultipleDrag ? index - 1 : index; _this.refreshUI(offlineArgs, index, isDropped); if (_this.parent.enableVirtualization) { _this.parent.virtualLayoutModule.refreshColumnData(draggedKey, droppedKey, offlineArgs.requestType, data[_this.parent.keyField]); } }).catch(function (e) { _this.dataManagerFailure(e); }); } } }); }; Data.prototype.syncDataSource = function (dataManager, updateType, params, data, isDropped, dataDropIndexKeyFieldValue) { var _this = this; var promise; switch (updateType) { case 'insert': return dataManager.insert(data, this.getTable(), this.getQuery()); case 'update': if (this.parent.enableVirtualization && !this.parent.dataModule.isRemote() && isDropped) { promise = dataManager.remove(this.keyField, data, this.getTable(), this.getQuery()); promise = dataManager.insert(data, this.getTable(), this.getQuery(), dataManager.dataSource.json.findIndex(function (data) { return data[_this.parent.cardSettings.headerField] === dataDropIndexKeyFieldValue; })); return promise; } else { return dataManager.update(this.keyField, data, this.getTable(), this.getQuery()); } case 'delete': return dataManager.remove(this.keyField, data, this.getTable(), this.getQuery()); case 'batch': if (!this.parent.dataModule.isRemote() && isDropped && this.parent.enableVirtualization && data) { for (var i = 0; i < data.length; i++) { promise = dataManager.remove(this.keyField, data[i], this.getTable(), this.getQuery()); } var currentIndex = dataManager.dataSource.json.findIndex(function (data) { return data[_this.parent.cardSettings.headerField] === dataDropIndexKeyFieldValue; }); for (var i = 0; i < data.length; i++, currentIndex++) { promise = dataManager.insert(data[i], this.getTable(), this.getQuery(), currentIndex); } return promise; } else { return dataManager.saveChanges(params, this.keyField, this.getTable(), this.getQuery()); } default: return promise; } }; Data.prototype.modifyArrayData = function (onLineData, e) { if (onLineData.length === e.length) { for (var i = 0; i < e.length; i++) { onLineData[i] = extend(onLineData[i], e[i]); } } return onLineData; }; /** * The function is used to refresh the UI once the data manager action is completed * * @param {ActionEventArgs} args Accepts the ActionEventArgs to refresh UI. * @param {number} position Accepts the index to refresh UI. * @param {boolean} isDropped Accepts the boolean value based on based if it is dragged and dropped * @returns {void} */ Data.prototype.refreshUI = function (args, position, isDropped) { var _this = this; if (this.parent.enableVirtualization) { this.parent.virtualLayoutModule.columnData = this.parent.virtualLayoutModule.getColumnCards(); args.addedRecords.forEach(function (data, index) { _this.parent.virtualLayoutModule.renderCardBasedOnIndex(data, position + index, isDropped, args.requestType); }); args.changedRecords.forEach(function (data) { _this.parent.virtualLayoutModule.removeCard(data); _this.parent.virtualLayoutModule.renderCardBasedOnIndex(data, position, isDropped, args.requestType); if (_this.parent.virtualLayoutModule.isSelectedCard) { _this.parent.actionModule.SingleCardSelection(data); } if (_this.parent.sortSettings.field && _this.parent.sortSettings.sortBy === 'Index' && _this.parent.sortSettings.direction === 'Descending' && position > 0) { --position; } else { position++; } }); args.deletedRecords.forEach(function (data) { _this.parent.virtualLayoutModule.removeCard(data); }); this.parent.virtualLayoutModule.refresh(); } else { this.parent.layoutModule.columnData = this.parent.layoutModule.getColumnCards(); if (this.parent.swimlaneSettings.keyField) { this.parent.layoutModule.kanbanRows = this.parent.layoutModule.getRows(); this.parent.layoutModule.swimlaneData = this.parent.layoutModule.getSwimlaneCards(); } args.addedRecords.forEach(function (data, index) { if (_this.parent.swimlaneSettings.keyField && !data[_this.parent.swimlaneSettings.keyField]) { data[_this.parent.swimlaneSettings.keyField] = ''; } _this.parent.layoutModule.renderCardBasedOnIndex(data, position + index); }); args.changedRecords.forEach(function (data) { if (_this.parent.swimlaneSettings.keyField && !data[_this.parent.swimlaneSettings.keyField]) { data[_this.parent.swimlaneSettings.keyField] = ''; } _this.parent.layoutModule.removeCard(data); _this.parent.layoutModule.renderCardBasedOnIndex(data, position); if (_this.parent.layoutModule.isSelectedCard) { _this.parent.actionModule.SingleCardSelection(data); } if (_this.parent.sortSettings.field && _this.parent.sortSettings.sortBy === 'Index' && _this.parent.sortSettings.direction === 'Descending' && position > 0) { --position; } else { position++; } }); args.deletedRecords.forEach(function (data) { _this.parent.layoutModule.removeCard(data); }); this.parent.layoutModule.refresh(); } this.parent.renderTemplates(); this.parent.notify(contentReady, {}); this.parent.trigger(dataBound, args, function () { return _this.parent.hideSpinner(); }); }; return Data; }()); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of swimlane settings in kanban board. */ var SwimlaneSettings = /** @__PURE__ @class */ (function (_super) { __extends(SwimlaneSettings, _super); function SwimlaneSettings() { return _super !== null && _super.apply(this, arguments) || this; } __decorate([ Property() ], SwimlaneSettings.prototype, "keyField", void 0); __decorate([ Property() ], SwimlaneSettings.prototype, "textField", void 0); __decorate([ Property(false) ], SwimlaneSettings.prototype, "showEmptyRow", void 0); __decorate([ Property(true) ], SwimlaneSettings.prototype, "showItemCount", void 0); __decorate([ Property(false) ], SwimlaneSettings.prototype, "allowDragAndDrop", void 0); __decorate([ Property() ], SwimlaneSettings.prototype, "template", void 0); __decorate([ Property('Ascending') ], SwimlaneSettings.prototype, "sortDirection", void 0); __decorate([ Property() ], SwimlaneSettings.prototype, "sortComparer", void 0); __decorate([ Property(true) ], SwimlaneSettings.prototype, "showUnassignedRow", void 0); __decorate([ Property(false) ], SwimlaneSettings.prototype, "enableFrozenRows", void 0); return SwimlaneSettings; }(ChildProperty)); var __extends$1 = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of card settings in kanban board. */ var CardSettings = /** @__PURE__ @class */ (function (_super) { __extends$1(CardSettings, _super); function CardSettings() { return _super !== null && _super.apply(this, arguments) || this; } __decorate$1([ Property(true) ], CardSettings.prototype, "showHeader", void 0); __decorate$1([ Property() ], CardSettings.prototype, "headerField", void 0); __decorate$1([ Property() ], CardSettings.prototype, "contentField", void 0); __decorate$1([ Property() ], CardSettings.prototype, "tagsField", void 0); __decorate$1([ Property() ], CardSettings.prototype, "grabberField", void 0); __decorate$1([ Property() ], CardSettings.prototype, "footerCssField", void 0); __decorate$1([ Property() ], CardSettings.prototype, "template", void 0); __decorate$1([ Property('Single') ], CardSettings.prototype, "selectionType", void 0); return CardSettings; }(ChildProperty)); var __extends$2 = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of editor settings. */ var DialogSettings = /** @__PURE__ @class */ (function (_super) { __extends$2(DialogSettings, _super); function DialogSettings() { return _super !== null && _super.apply(this, arguments) || this; } __decorate$2([ Property() ], DialogSettings.prototype, "template", void 0); __decorate$2([ Property([]) ], DialogSettings.prototype, "fields", void 0); __decorate$2([ Property(null) ], DialogSettings.prototype, "model", void 0); return DialogSettings; }(ChildProperty)); var __extends$3 = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of columns in kanban board. */ var Columns = /** @__PURE__ @class */ (function (_super) { __extends$3(Columns, _super); function Columns() { return _super !== null && _super.apply(this, arguments) || this; } __decorate$3([ Property() ], Columns.prototype, "keyField", void 0); __decorate$3([ Property() ], Columns.prototype, "headerText", void 0); __decorate$3([ Property() ], Columns.prototype, "template", void 0); __decorate$3([ Property(false) ], Columns.prototype, "allowToggle", void 0); __decorate$3([ Property(true) ], Columns.prototype, "isExpanded", void 0); __decorate$3([ Property() ], Columns.prototype, "minCount", void 0); __decorate$3([ Property() ], Columns.prototype, "maxCount", void 0); __decorate$3([ Property(true) ], Columns.prototype, "showItemCount", void 0); __decorate$3([ Property(false) ], Columns.prototype, "showAddButton", void 0); __decorate$3([ Property(true) ], Columns.prototype, "allowDrag", void 0); __decorate$3([ Property(true) ], Columns.prototype, "allowDrop", void 0); __decorate$3([ Property([]) ], Columns.prototype, "transitionColumns", void 0); return Columns; }(ChildProperty)); var __extends$4 = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of stacked header settings in kanban board. */ var StackedHeaders = /** @__PURE__ @class */ (function (_super) { __extends$4(StackedHeaders, _super); function StackedHeaders() { return _super !== null && _super.apply(this, arguments) || this; } __decorate$4([ Property() ], StackedHeaders.prototype, "text", void 0); __decorate$4([ Property() ], StackedHeaders.prototype, "keyFields", void 0); return StackedHeaders; }(ChildProperty)); var __extends$5 = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate$5 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Holds the configuration of sort settings in kanban board. */ var SortSettings = /** @__PURE__ @class */ (function (_super) { __extends$5(SortSettings, _super); function SortSettings() { return _super !== null && _super.apply(this, arguments) || this; } __decorate$5([ Property('Index') ], SortSettings.prototype, "sortBy", void 0); __decorate$5([ Property() ], SortSettings.prototype, "field", void 0); __decorate$5([ Property('Ascending') ], SortSettings.prototype, "direction", void 0); return SortSettings; }(ChildProperty)); /** * Kanban CSS Constants */ /** @private */ var ROOT_CLASS = 'e-kanban'; /** @private */ var RTL_CLASS = 'e-rtl'; /** @private */ var DEVICE_CLASS = 'e-device'; /** @private */ var ICON_CLASS = 'e-icons'; /** @private */ var TEMPLATE_CLASS = 'e-template'; /** @private */ var SWIMLANE_CLASS = 'e-swimlane'; /** @private */ var TABLE_CLASS = 'e-kanban-table'; /** @private */ var HEADER_CLASS = 'e-kanban-header'; /** @private */ var HEADER_TABLE_CLASS = 'e-header-table'; /** @private */ var HEADER_CELLS_CLASS = 'e-header-cells'; /** @private */ var HEADER_WRAP_CLASS = 'e-header-wrap'; /** @private */ var HEADER_TITLE_CLASS = 'e-header-title'; /** @private */ var HEADER_TEXT_CLASS = 'e-header-text'; /** @private */ var HEADER_ICON_CLASS = 'e-header-icon'; /** @private */ var STACKED_HEADER_ROW_CLASS = 'e-stacked-header-row'; /** @private */ var STACKED_HEADER_CELL_CLASS = 'e-stacked-header-cell'; /** @private */ var CONTENT_CELLS_CLASS = 'e-content-cells'; /** @private */ var CONTENT_CLASS = 'e-kanban-content'; /** @private */ var CONTENT_TABLE_CLASS = 'e-content-table'; /** @private */ var HEADER_ROW_TOGGLE_CLASS = 'e-toggle-header'; /** @private */ var HEADER_ROW_CLASS = 'e-header-row'; /** @private */ var CONTENT_ROW_CLASS = 'e-content-row'; /** @private */ var SWIMLANE_ROW_CLASS = 'e-swimlane-row'; /** @private */ var SWIMLANE_ROW_EXPAND_CLASS = 'e-swimlane-row-expand'; /** @private */ var SWIMLANE_ROW_COLLAPSE_CLASS = 'e-swimlane-row-collapse'; /** @private */ var SWIMLANE_ROW_TEXT_CLASS = 'e-swimlane-text'; /** @private */ var CARD_ITEM_COUNT_CLASS = 'e-item-count'; /** @private */ var CARD_WRAPPER_CLASS = 'e-card-wrapper'; /** @private */ var CARD_VIRTUAL_WRAPPER_CLASS = 'e-card-virtual-wrapper'; /** @private */ var CARD_CLASS = 'e-card'; /** @private */ var DROPPABLE_CLASS = 'e-droppable'; /** @private */ var DRAG_CLASS = 'e-drag'; /** @private */ var DROP_CLASS = 'e-drop'; /** @private */ var DISABLED_CLASS = 'e-disabled'; /** @private */ var CARD_HEADER_CLASS = 'e-card-header'; /** @private */ var CARD_CONTENT_CLASS = 'e-card-content'; /** @private */ var CARD_HEADER_TEXT_CLASS = 'e-card-header-caption'; /** @private */ var CARD_HEADER_TITLE_CLASS = 'e-card-header-title'; /** @private */ var CARD_TAGS_CLASS = 'e-card-tags'; /** @private */ var CARD_TAG_CLASS = 'e-card-tag'; /** @private */ var CARD_COLOR_CLASS = 'e-card-color'; /** @private */ var CARD_LABEL_CLASS = 'e-card-label'; /** @private */ var CARD_FOOTER_CLASS = 'e-card-footer'; /** @private */ var EMPTY_CARD_CLASS = 'e-empty-card'; /** @private */ var CARD_FOOTER_CSS_CLASS = 'e-card-footer-css'; /** @private */ var COLUMN_EXPAND_CLASS = 'e-column-expand'; /** @private */ var COLUMN_COLLAPSE_CLASS = 'e-column-collapse'; /** @private */ var COLLAPSE_HEADER_TEXT_CLASS = 'e-collapse-header-text'; /** @private */ var COLLAPSED_CLASS = 'e-collapsed'; /** @private */ var DIALOG_CLASS = 'e-kanban-dialog'; /** @private */ var FORM_CLASS = 'e-kanban-form'; /** @private */ var FORM_WRAPPER_CLASS = 'e-kanban-form-wrapper'; /** @private */ var ERROR_VALIDATION_CLASS = 'e-kanban-error'; /** @private */ var FIELD_CLASS = 'e-field'; /** @private */ var DRAGGED_CLONE_CLASS = 'e-target-dragged-clone'; /** @private */ var CLONED_CARD_CLASS = 'e-cloned-card'; /** @private */ var DRAGGED_CARD_CLASS = 'e-kanban-dragged-card'; /** @private */ var DROPPED_CLONE_CLASS = 'e-target-dropped-clone'; /** @private */ var DROPPING_CLASS = 'e-dropping'; /** @private */ var BORDER_CLASS = 'e-kanban-border'; /** @private */ var TOGGLE_VISIBLE_CLASS = 'e-toggle-visible'; /** @private */ var MULTI_CARD_WRAPPER_CLASS = 'e-multi-card-wrapper'; /** @private */ var MULTI_ACTIVE_CLASS = 'e-multi-active'; /** @private */ var TARGET_MULTI_CLONE_CLASS = 'e-target-multi-clone'; /** @private */ var MULTI_COLUMN_KEY_CLASS = 'e-column-key'; /** @private */ var CARD_SELECTION_CLASS = 'e-selection'; /** @private */ var TOOLTIP_CLASS = 'e-kanban-tooltip'; /** @private */ var TOOLTIP_TEXT_CLASS = 'e-tooltip-text'; /** @private */ var SWIMLANE_HEADER_CLASS = 'e-swimlane-header'; /** @private */ var SWIMLANE_HEADER_TOOLBAR_CLASS = 'e-swimlane-header-toolbar'; /** @private */ var TOOLBAR_MENU_CLASS = 'e-toolbar-menu'; /** @private */ var TOOLBAR_MENU_ICON_CLASS = 'e-icon-menu'; /** @private */ var TOOLBAR_LEVEL_TITLE_CLASS = 'e-toolbar-level-title'; /** @private */ var TOOLBAR_SWIMLANE_NAME_CLASS = 'e-toolbar-swimlane-name'; /** @private */ var SWIMLANE_OVERLAY_CLASS = 'e-swimlane-overlay'; /** @private */ var SWIMLANE_CONTENT_CLASS = 'e-swimlane-content'; /** @private */ var SWIMLANE_RESOURCE_CLASS = 'e-swimlane-resource'; /** @private */ var SWIMLANE_TREE_CLASS = 'e-swimlane-tree'; /** @private */ var LIMITS_CLASS = 'e-limits'; /** @private */ var MAX_COUNT_CLASS = 'e-max-count'; /** @private */ var MIN_COUNT_CLASS = 'e-min-count'; /** @private */ var MAX_COLOR_CLASS = 'e-max-color'; /** @private */ var MIN_COLOR_CLASS = 'e-min-color'; /** @private */ var POPUP_HEADER_CLASS = 'e-popup-header'; /** @private */ var CLOSE_CLASS = 'e-close'; /** @private */ var POPUP_CONTENT_CLASS = 'e-popup-content'; /** @private */ var POPUP_WRAPPER_CLASS = 'e-mobile-popup-wrapper'; /** @private */ var CLOSE_ICON_CLASS = 'e-close-icon'; /** @private */ var POPUP_OPEN_CLASS = 'e-popup-open'; /** @private */ var DIALOG_CONTENT_CONTAINER = 'e-kanban-dialog-content'; /** @private */ var SHOW_ADD_BUTTON = 'e-show-add-button'; /** @private */ var SHOW_ADD_ICON = 'e-show-add-icon'; /** @private */ var SHOW_ADD_FOCUS = 'e-show-add-focus'; /** @private */ var FROZEN_SWIMLANE_ROW_CLASS = 'e-frozen-swimlane-row'; /** @private */ var FROZEN_ROW_CLASS = 'e-frozen-row'; /** @private */ var TOOLBAR_SWIMLANE_ITEM_COUNT_CLASS = 'e-toolbar-swimlane-item-count'; /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Action module is used to perform card actions. */ var Action = /** @__PURE__ @class */ (function () { /** * Constructor for action module * * @param {Kanban} parent Accepts the kanban instance * @private */ function Action(parent) { this.parent = parent; this.columnToggleArray = []; this.selectionArray = []; this.lastCardSelection = null; this.lastSelectionRow = null; this.lastCard = null; this.selectedCardsElement = []; this.selectedCardsData = []; this.hideColumnKeys = []; } Action.prototype.clickHandler = function (e) { var elementSelector = '.' + CARD_CLASS + ',.' + HEADER_ICON_CLASS + ',.' + CONTENT_ROW_CLASS + '.' + SWIMLANE_ROW_CLASS + ',.' + SHOW_ADD_BUTTON + ',.' + FROZEN_SWIMLANE_ROW_CLASS + ',.' + CONTENT_ROW_CLASS + ':not(.' + SWIMLANE_ROW_CLASS + ') .' + CONTENT_CELLS_CLASS; var target = closest(e.target, elementSelector); if (!target) { return; } if (target.classList.contains(CARD_CLASS)) { if (this.parent.allowKeyboard) { this.parent.keyboardModule.cardTabIndexRemove(); } this.cardClick(e); } else if (target.classList.contains(HEADER_ICON_CLASS)) { this.columnExpandCollapse(e); } else if (target.classList.contains(CONTENT_ROW_CLASS) && target.classList.contains(SWIMLANE_ROW_CLASS)) { this.rowExpandCollapse(e); } else if (target.classList.contains(SHOW_ADD_BUTTON)) { this.addButtonClick(target); } else if (target.classList.contains(FROZEN_SWIMLANE_ROW_CLASS)) { var swimlaneRows = [].slice.call(this.parent.element.querySelectorAll('.' + SWIMLANE_ROW_CLASS)); var targetIcon = this.parent.layoutModule.frozenSwimlaneRow.querySelector('.' + ICON_CLASS); this.rowExpandCollapse(e, swimlaneRows[this.parent.layoutModule.frozenOrder]); var isCollapsed = targetIcon.classList.contains(SWIMLANE_ROW_COLLAPSE_CLASS) ? true : false; if (isCollapsed) { classList(targetIcon, [SWIMLANE_ROW_EXPAND_CLASS], [SWIMLANE_ROW_COLLAPSE_CLASS]); } else { classList(targetIcon, [SWIMLANE_ROW_COLLAPSE_CLASS], [SWIMLANE_ROW_EXPAND_CLASS]); } } }; Action.prototype.addButtonClick = function (target) { var _this = this; var newData = {}; if (this.parent.kanbanData.length === 0) { newData[this.parent.cardSettings.headerField] = 1; } else if (typeof (this.parent.kanbanData[0])[this.parent.cardSettings.headerField] === 'number') { var id = this.parent.kanbanData.map(function (obj) { return parseInt(obj[_this.parent.cardSettings.headerField], 10); }); newData[this.parent.cardSettings.headerField] = Math.max.apply(Math, id) + 1; } newData[this.parent.keyField] = closest(target, '.' + CONTENT_CELLS_CLASS).getAttribute('data-key'); if (this.parent.sortSettings.sortBy === 'Index') { newData[this.parent.sortSettings.field] = 1; if (closest(target, '.' + CONTENT_CELLS_CLASS).querySelector('.' + CARD_CLASS)) { var card = this.parent.sortSettings.direction === 'Ascending' ? target.nextElementSibling.classList.contains(BORDER_CLASS) ? target.nextElementSibling.nextElementSibling.lastElementChild : target.nextElementSibling.lastElementChild : target.nextElementSibling.classList.contains(BORDER_CLASS) ? target.nextElementSibling.nextElementSibling.firstElementChild : target.nextElementSibling.firstElementChild; var data = this.parent.getCardDetails(card); newData[this.parent.sortSettings.field] = data[this.parent.sortSettings.field] + 1; } } if (this.parent.kanbanData.length !== 0 && this.parent.swimlaneSettings.keyField && closest(target, '.' + CONTENT_ROW_CLASS).previousElementSibling) { newData[this.parent.swimlaneSettings.keyField] = closest(target, '.' + CONTENT_ROW_CLASS).previousElementSibling.getAttribute('data-key'); } this.parent.openDialog('Add', newData); }; Action.prototype.doubleClickHandler = function (e) { var target = closest(e.target, '.' + CARD_CLASS); if (target) { this.cardDoubleClick(e); } }; Action.prototype.cardClick = function (e, selectedCard) { var _this = this; var target = closest((selectedCard) ? selectedCard : e.target, '.' + CARD_CLASS); var cardClickObj = this.parent.getCardDetails(target); if (cardClickObj) { this.parent.activeCardData = { data: cardClickObj, element: target }; var args = { data: cardClickObj, element: target, cancel: false, event: e }; this.parent.trigger(cardClick, args, function (clickArgs) { if (!clickArgs.cancel) { if (target.classList.contains(CARD_SELECTION_CLASS) && e.type === 'click') { removeClass([target], CARD_SELECTION_CLASS); if (_this.parent.enableVirtualization) { _this.parent.virtualLayoutModule.disableAttributeSelection(target); } else { _this.parent.layoutModule.disableAttributeSelection(target); } } else { var isCtrlKey = e.ctrlKey; if (_this.parent.isAdaptive && _this.parent.touchModule) { isCtrlKey = (_this.parent.touchModule.mobilePopup && _this.parent.touchModule.tabHold) || isCtrlKey; } _this.cardSelection(target, isCtrlKey, e.shiftKey); } if (_this.parent.isAdaptive && _this.parent.touchModule) { _this.parent.touchModule.updatePopupContent(); } var cell = closest(target, '.' + CONTENT_CELLS_CLASS); if (_this.parent.allowKeyboard) { var element = [].slice.call(cell.querySelectorAll('.' + CARD_CLASS)); element.forEach(function (e) { e.setAttribute('tabindex', '0')