@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.
432 lines (431 loc) • 24.5 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
import { closest, classList, createElement, remove, addClass, removeClass, isNullOrUndefined as isNoU, formatUnit, createInstance, detach } from '@syncfusion/ej2-base';
import { Columns } from '../models/columns';
import * as events from '../base/constant';
import * as cls from '../base/css-constant';
/**
* Action module is used to perform card actions.
*/
var Action = /** @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 = '.' + cls.CARD_CLASS + ',.' + cls.HEADER_ICON_CLASS + ',.' + cls.CONTENT_ROW_CLASS + '.' +
cls.SWIMLANE_ROW_CLASS + ',.' + cls.SHOW_ADD_BUTTON + ',.' + cls.FROZEN_SWIMLANE_ROW_CLASS + ',.' + cls.CONTENT_ROW_CLASS +
':not(.' + cls.SWIMLANE_ROW_CLASS + ') .' + cls.CONTENT_CELLS_CLASS;
var target = closest(e.target, elementSelector);
if (!target) {
return;
}
if (target.classList.contains(cls.CARD_CLASS)) {
if (this.parent.allowKeyboard) {
this.parent.keyboardModule.cardTabIndexRemove();
}
this.cardClick(e);
}
else if (target.classList.contains(cls.HEADER_ICON_CLASS)) {
this.columnExpandCollapse(e);
}
else if (target.classList.contains(cls.CONTENT_ROW_CLASS) && target.classList.contains(cls.SWIMLANE_ROW_CLASS)) {
this.rowExpandCollapse(e);
}
else if (target.classList.contains(cls.SHOW_ADD_BUTTON)) {
this.addButtonClick(target);
}
else if (target.classList.contains(cls.FROZEN_SWIMLANE_ROW_CLASS)) {
var swimlaneRows = [].slice.call(this.parent.element.querySelectorAll('.' + cls.SWIMLANE_ROW_CLASS));
var targetIcon = this.parent.layoutModule.frozenSwimlaneRow.querySelector('.' + cls.ICON_CLASS);
this.rowExpandCollapse(e, swimlaneRows[this.parent.layoutModule.frozenOrder]);
var isCollapsed = targetIcon.classList.contains(cls.SWIMLANE_ROW_COLLAPSE_CLASS) ? true : false;
if (isCollapsed) {
classList(targetIcon, [cls.SWIMLANE_ROW_EXPAND_CLASS], [cls.SWIMLANE_ROW_COLLAPSE_CLASS]);
}
else {
classList(targetIcon, [cls.SWIMLANE_ROW_COLLAPSE_CLASS], [cls.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, '.' + cls.CONTENT_CELLS_CLASS).getAttribute('data-key');
if (this.parent.sortSettings.sortBy === 'Index') {
newData[this.parent.sortSettings.field] = 1;
if (closest(target, '.' + cls.CONTENT_CELLS_CLASS).querySelector('.' + cls.CARD_CLASS)) {
var card = this.parent.sortSettings.direction === 'Ascending' ?
target.nextElementSibling.classList.contains(cls.BORDER_CLASS) ?
target.nextElementSibling.nextElementSibling.lastElementChild : target.nextElementSibling.lastElementChild
: target.nextElementSibling.classList.contains(cls.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, '.' + cls.CONTENT_ROW_CLASS).previousElementSibling) {
newData[this.parent.swimlaneSettings.keyField] =
closest(target, '.' + cls.CONTENT_ROW_CLASS).previousElementSibling.getAttribute('data-key');
}
this.parent.openDialog('Add', newData);
};
Action.prototype.doubleClickHandler = function (e) {
var target = closest(e.target, '.' + cls.CARD_CLASS);
if (target) {
this.cardDoubleClick(e);
}
};
Action.prototype.cardClick = function (e, selectedCard) {
var _this = this;
var target = closest((selectedCard) ? selectedCard : e.target, '.' + cls.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(events.cardClick, args, function (clickArgs) {
if (!clickArgs.cancel) {
if (target.classList.contains(cls.CARD_SELECTION_CLASS) && e.type === 'click') {
removeClass([target], cls.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, '.' + cls.CONTENT_CELLS_CLASS);
if (_this.parent.allowKeyboard) {
var element = [].slice.call(cell.querySelectorAll('.' + cls.CARD_CLASS));
element.forEach(function (e) { e.setAttribute('tabindex', '0'); });
_this.parent.keyboardModule.addRemoveTabIndex('Remove');
}
}
});
}
};
Action.prototype.cardDoubleClick = function (e) {
var _this = this;
var target = closest(e.target, '.' + cls.CARD_CLASS);
var cardDoubleClickObj = this.parent.getCardDetails(target);
this.parent.activeCardData = { data: cardDoubleClickObj, element: target };
this.cardSelection(target, false, false);
var args = { data: cardDoubleClickObj, element: target, cancel: false, event: e };
this.parent.trigger(events.cardDoubleClick, args, function (doubleClickArgs) {
if (!doubleClickArgs.cancel) {
_this.parent.dialogModule.openDialog('Edit', args.data);
}
});
};
Action.prototype.rowExpandCollapse = function (e, isFrozenElem) {
var _this = this;
var headerTarget = (e instanceof HTMLElement) ? e : e.target;
var currentSwimlaneHeader = !isNoU(isFrozenElem) ? isFrozenElem : headerTarget;
var args = { cancel: false, target: headerTarget, requestType: 'rowExpandCollapse' };
this.parent.trigger(events.actionBegin, args, function (actionArgs) {
if (!actionArgs.cancel) {
var target = closest(currentSwimlaneHeader, '.' + cls.SWIMLANE_ROW_CLASS);
var key = target.getAttribute('data-key');
var tgtRow = _this.parent.element.querySelector('.' + cls.CONTENT_ROW_CLASS + (":nth-child(" + (target.rowIndex + 2) + ")"));
var targetIcon = target.querySelector("." + cls.SWIMLANE_ROW_EXPAND_CLASS + ",." + cls.SWIMLANE_ROW_COLLAPSE_CLASS);
var isCollapsed = target.classList.contains(cls.COLLAPSED_CLASS) ? true : false;
var tabIndex_1;
if (isCollapsed) {
removeClass([tgtRow, target], cls.COLLAPSED_CLASS);
classList(targetIcon, [cls.SWIMLANE_ROW_EXPAND_CLASS], [cls.SWIMLANE_ROW_COLLAPSE_CLASS]);
_this.parent.swimlaneToggleArray.splice(_this.parent.swimlaneToggleArray.indexOf(key), 1);
tabIndex_1 = '0';
}
else {
addClass([tgtRow, target], cls.COLLAPSED_CLASS);
classList(targetIcon, [cls.SWIMLANE_ROW_COLLAPSE_CLASS], [cls.SWIMLANE_ROW_EXPAND_CLASS]);
_this.parent.swimlaneToggleArray.push(key);
tabIndex_1 = '-1';
}
targetIcon.setAttribute('aria-label', isCollapsed ? key + ' Expand' : key + ' Collapse');
target.setAttribute('aria-expanded', isCollapsed.toString());
tgtRow.setAttribute('aria-expanded', isCollapsed.toString());
var rows = [].slice.call(tgtRow.querySelectorAll('.' + cls.CONTENT_CELLS_CLASS));
rows.forEach(function (cell) { cell.setAttribute('tabindex', tabIndex_1); });
_this.parent.notify(events.contentReady, {});
_this.parent.trigger(events.actionComplete, { target: headerTarget, requestType: 'rowExpandCollapse' });
}
});
};
Action.prototype.columnExpandCollapse = function (e) {
var _this = this;
var headerTarget = (e instanceof HTMLElement) ? e : e.target;
var args = { cancel: false, target: headerTarget, requestType: 'columnExpandCollapse' };
this.parent.trigger(events.actionBegin, args, function (actionArgs) {
if (!actionArgs.cancel) {
var target = closest(headerTarget, '.' + cls.HEADER_CELLS_CLASS);
var colIndex = target.cellIndex;
_this.columnToggle(target);
var collapsed = _this.parent.element.querySelectorAll("." + cls.HEADER_CELLS_CLASS + "." + cls.COLLAPSED_CLASS).length;
if (collapsed === (_this.parent.columns.length - _this.hideColumnKeys.length)) {
var index = (colIndex + 1 === collapsed) ? 1 : colIndex + 2;
var headerSelector = "." + cls.HEADER_CELLS_CLASS + ":not(." + cls.STACKED_HEADER_CELL_CLASS + "):nth-child(" + index + ")";
var nextCol = _this.parent.element.querySelector(headerSelector);
addClass([nextCol], cls.COLLAPSED_CLASS);
_this.columnToggle(nextCol);
}
_this.parent.notify(events.contentReady, {});
_this.parent.trigger(events.actionComplete, { target: headerTarget, requestType: 'columnExpandCollapse' });
}
});
};
Action.prototype.columnToggle = function (target) {
var _this = this;
var colIndex = target.cellIndex;
var elementSelector = "." + cls.CONTENT_ROW_CLASS + ":not(." + cls.SWIMLANE_ROW_CLASS + ")";
var targetRow = [].slice.call(this.parent.element.querySelectorAll(elementSelector));
var colSelector = "." + cls.TABLE_CLASS + " col:nth-child(" + (colIndex + 1) + ")";
var targetIcon = target.querySelector("." + cls.COLUMN_EXPAND_CLASS + ",." + cls.COLUMN_COLLAPSE_CLASS);
var colGroup = [].slice.call(this.parent.element.querySelectorAll(colSelector));
if (target.classList.contains(cls.COLLAPSED_CLASS)) {
removeClass(colGroup, cls.COLLAPSED_CLASS);
if (this.parent.isAdaptive) {
if (this.parent.enableVirtualization) {
colGroup.forEach(function (col) { return col.style.width = formatUnit(_this.parent.virtualLayoutModule.getWidth()); });
}
else {
colGroup.forEach(function (col) { return col.style.width = formatUnit(_this.parent.layoutModule.getWidth()); });
}
}
classList(targetIcon, [cls.COLUMN_EXPAND_CLASS], [cls.COLUMN_COLLAPSE_CLASS]);
var _loop_1 = function (row) {
var targetCol = row.querySelector("." + cls.CONTENT_CELLS_CLASS + ":nth-child(" + (colIndex + 1) + ")");
removeClass([targetCol, target], cls.COLLAPSED_CLASS);
remove(targetCol.querySelector('.' + cls.COLLAPSE_HEADER_TEXT_CLASS));
target.setAttribute('aria-expanded', 'true');
targetCol.setAttribute('aria-expanded', 'true');
var collapsedCell = [].slice.call(targetCol.parentElement.querySelectorAll('.' + cls.COLLAPSED_CLASS));
collapsedCell.forEach(function (cell) {
var collapasedText = cell.querySelector('.' + cls.COLLAPSE_HEADER_TEXT_CLASS);
collapasedText.style.height = 'auto';
if (collapasedText && targetCol.getBoundingClientRect().height < (collapasedText.getBoundingClientRect().height + 10)) {
collapasedText.style.height = (targetCol.getBoundingClientRect().height - 4) + 'px';
}
});
};
for (var _i = 0, targetRow_1 = targetRow; _i < targetRow_1.length; _i++) {
var row = targetRow_1[_i];
_loop_1(row);
}
if (this.parent.kanbanData.length === 0 && targetRow.length === 0) {
removeClass([target], cls.COLLAPSED_CLASS);
target.setAttribute('aria-expanded', 'true');
}
this.columnToggleArray.splice(this.columnToggleArray.indexOf(target.getAttribute('data-key')), 1);
this.parent.columns[colIndex].setProperties({ isExpanded: true }, true);
target.querySelector('.e-header-icon').setAttribute('aria-label', target.getAttribute('data-key') + ' Expand');
}
else {
addClass(colGroup, cls.COLLAPSED_CLASS);
if (this.parent.isAdaptive) {
colGroup.forEach(function (col) { return col.style.width = formatUnit(events.toggleWidth); });
}
classList(targetIcon, [cls.COLUMN_COLLAPSE_CLASS], [cls.COLUMN_EXPAND_CLASS]);
var key = target.getAttribute('data-key');
var _loop_2 = function (row) {
var targetCol = row.querySelector("." + cls.CONTENT_CELLS_CLASS + "[data-key=\"" + key + "\"]");
var index = targetCol.cellIndex;
var text = void 0;
if (!this_1.parent.enableVirtualization) {
text = (this_1.parent.columns[index].showItemCount ? '[' +
targetCol.querySelectorAll('.' + cls.CARD_CLASS).length + '] ' : '') + this_1.parent.columns[index].headerText;
}
else {
var value = this_1.parent.dataModule.isRemote() ?
this_1.parent.columnDataCount[this_1.parent.columns[index].keyField]
: this_1.parent.virtualLayoutModule.columnData[this_1.parent.columns[index].keyField].length;
text = (this_1.parent.columns[index].showItemCount ? '[' +
value + '] ' : '') + this_1.parent.columns[index].headerText;
}
targetCol.appendChild(createElement('div', { className: cls.COLLAPSE_HEADER_TEXT_CLASS, innerHTML: text }));
addClass([targetCol, target], cls.COLLAPSED_CLASS);
target.setAttribute('aria-expanded', 'false');
targetCol.setAttribute('aria-expanded', 'false');
var collapsedCell = [].slice.call(targetCol.parentElement.querySelectorAll('.' + cls.COLLAPSED_CLASS));
collapsedCell.forEach(function (cell) {
var collapasedText = cell.querySelector('.' + cls.COLLAPSE_HEADER_TEXT_CLASS);
if (collapasedText && targetCol.getBoundingClientRect().height < (collapasedText.getBoundingClientRect().height + 10)) {
collapasedText.style.height = (targetCol.getBoundingClientRect().height - 4) + 'px';
}
});
};
var this_1 = this;
for (var _a = 0, targetRow_2 = targetRow; _a < targetRow_2.length; _a++) {
var row = targetRow_2[_a];
_loop_2(row);
}
if (this.parent.kanbanData.length === 0 && targetRow.length === 0) {
addClass([target], cls.COLLAPSED_CLASS);
target.setAttribute('aria-expanded', 'false');
}
this.columnToggleArray.push(target.getAttribute('data-key'));
this.parent.columns[colIndex].setProperties({ isExpanded: false }, true);
target.querySelector('.e-header-icon').setAttribute('aria-label', key + ' Collapse');
}
};
Action.prototype.cardSelection = function (target, isCtrl, isShift) {
var _this = this;
if (!target) {
return;
}
var cards = this.parent.getSelectedCards();
if (this.parent.cardSettings.selectionType !== 'None') {
var contentRow = closest(target, '.' + cls.CONTENT_ROW_CLASS);
var index = !isNoU(this.lastSelectionRow) ? this.lastSelectionRow.rowIndex : contentRow.rowIndex;
if (index !== contentRow.rowIndex && (isCtrl || isShift) && this.parent.cardSettings.selectionType === 'Multiple') {
return;
}
if (cards.length !== 0 && (!isCtrl || this.parent.cardSettings.selectionType === 'Single')) {
removeClass(cards, cls.CARD_SELECTION_CLASS);
if (this.parent.enableVirtualization) {
this.parent.virtualLayoutModule.disableAttributeSelection(cards);
}
else {
this.parent.layoutModule.disableAttributeSelection(cards);
}
cards.forEach(function (el) {
_this.selectionArray.splice(_this.selectionArray.indexOf(el.getAttribute('data-id')), 1);
_this.selectedCardsElement.splice(_this.selectedCardsElement.indexOf(el), 1);
_this.selectedCardsData.splice(_this.selectedCardsData.indexOf(_this.parent.getCardDetails(el), 1));
});
}
if (cards.length > 0 && isShift && this.parent.cardSettings.selectionType === 'Multiple') {
var curCards_1 = [];
var start = void 0;
var end = void 0;
var i = void 0;
var allCards = [].slice.call(contentRow.querySelectorAll('.' + cls.CARD_CLASS));
allCards.forEach(function (el) { return curCards_1.push(el.getAttribute('data-id')); });
var curId = target.getAttribute('data-id');
var lastId = this.lastCard.getAttribute('data-id');
var curIndex = end = curCards_1.indexOf(curId);
var lastIndex = start = curCards_1.indexOf(lastId);
var select = curIndex > lastIndex ? 'next' : 'prev';
if (select === 'prev') {
start = curIndex;
end = lastIndex;
}
for (i = start; i <= end; i++) {
var card = allCards[i];
addClass([card], cls.CARD_SELECTION_CLASS);
card.setAttribute('aria-selected', 'true');
card.setAttribute('tabindex', '0');
this.selectionArray.push(card.getAttribute('data-id'));
this.selectedCardsElement.push(card);
this.selectedCardsData.push(this.parent.getCardDetails(card));
this.lastCardSelection = card;
if (select === 'prev') {
this.lastCardSelection = allCards[start];
}
}
}
else {
addClass([target], cls.CARD_SELECTION_CLASS);
target.setAttribute('aria-selected', 'true');
target.setAttribute('tabindex', '0');
this.selectionArray.push(target.getAttribute('data-id'));
this.selectedCardsElement.push(target);
this.selectedCardsData.push(this.parent.getCardDetails(target));
this.lastCard = this.lastCardSelection = target;
this.lastSelectionRow = closest(target, '.' + cls.CONTENT_ROW_CLASS);
if (this.lastSelectionRow.previousElementSibling) {
var elementSelector = "." + cls.SWIMLANE_ROW_EXPAND_CLASS + ",." + cls.SWIMLANE_ROW_COLLAPSE_CLASS;
var parentEle = this.lastSelectionRow.previousElementSibling.querySelector(elementSelector);
if (parentEle && parentEle.classList.contains(cls.SWIMLANE_ROW_COLLAPSE_CLASS)) {
this.rowExpandCollapse(parentEle);
}
}
}
}
};
Action.prototype.addColumn = function (columnOptions, index) {
var addColumn = createInstance(Columns, [this.parent, 'columns', columnOptions, true]);
this.parent.columns.splice(index, 0, addColumn);
this.parent.notify(events.dataReady, { processedData: this.parent.kanbanData });
};
Action.prototype.deleteColumn = function (index) {
var listKey = this.parent.element.querySelectorAll('.' + cls.HEADER_CELLS_CLASS).item(index);
if (listKey && listKey.classList.contains(cls.HEADER_ROW_TOGGLE_CLASS)) {
this.columnToggleArray.splice(this.columnToggleArray.indexOf(listKey.getAttribute('data-key'), 0));
}
this.parent.columns.splice(index, 1);
if (this.parent.columns.length === 0) {
detach(this.parent.element.querySelector('.' + cls.HEADER_CLASS));
detach(this.parent.element.querySelector('.' + cls.CONTENT_CLASS));
}
else {
this.parent.notify(events.dataReady, { processedData: this.parent.kanbanData });
}
};
Action.prototype.showColumn = function (key) {
var index = this.hideColumnKeys.indexOf(key.toString());
if (index !== -1) {
this.hideColumnKeys.splice(index, 1);
this.parent.notify(events.dataReady, { processedData: this.parent.kanbanData });
}
};
Action.prototype.hideColumn = function (key) {
this.hideColumnKeys.push(key.toString());
this.parent.notify(events.dataReady, { processedData: this.parent.kanbanData });
};
/**
* Maintain the single card selection
*
* @param {Record<string, any>} data - Specifies the selected card data.
* @returns {void}
* @private
* @hidden
*/
Action.prototype.SingleCardSelection = function (data) {
if (this.parent.cardSettings.selectionType !== 'None' && data[this.parent.cardSettings.headerField]) {
// eslint-disable-next-line no-useless-escape
var card = this.parent.element.querySelector('.e-card[data-id=\"' +
// eslint-disable-next-line no-useless-escape
data[this.parent.cardSettings.headerField].toString() + '"\]');
if (card) {
addClass([card], cls.CARD_SELECTION_CLASS);
card.setAttribute('aria-selected', 'true');
card.setAttribute('tabindex', '0');
}
}
};
return Action;
}());
export { Action };