UNPKG

@mhmdaljefri/revogrid

Version:

Virtual reactive data grid component - RevoGrid.

179 lines (178 loc) 6.18 kB
import size from 'lodash/size'; import { setStore } from '../../utils/store.utils'; import ColumnDataProvider from '../../services/column.data.provider'; import BasePlugin from '../basePlugin'; /** * lifecycle * 1) @event beforesorting - sorting just started, nothing happened yet * 2) @metod updateColumnSorting - column sorting icon applied to grid and column get updated, data still untiuched * 3) @event beforesortingapply - before we applied sorting data to data source, you can prevent data apply from here * 4) @event afterSortingApply - sorting applied, just finished event * * If you prevent event it'll not reach farther steps */ export default class SortingPlugin extends BasePlugin { constructor(revogrid) { super(revogrid); this.revogrid = revogrid; this.sorting = null; this.sortingFunc = null; const beforesourceset = ({ detail }) => { if (this.hasSorting) { // is sorting allowed const event = this.emit('beforesourcesortingapply'); // sorting prevented if (event.defaultPrevented) { return; } } const data = this.setData(detail.source, detail.type); if (data) { detail.source = data; } }; const aftercolumnsset = async ({ detail: { order } }) => { const columns = await this.revogrid.getColumns(); const sortingFunc = {}; for (let prop in order) { const column = ColumnDataProvider.getColumnByProp(columns, prop); const cmp = (column === null || column === void 0 ? void 0 : column.cellCompare) || this.defaultCellCompare; sortingFunc[prop] = order[prop] == 'desc' ? this.descCellCompare(cmp) : cmp; } this.sort(order, sortingFunc); }; const headerclick = async (e) => { var _a, _b; if (e.defaultPrevented) { return; } if (!e.detail.column.sortable) { return; } this.headerclick(e.detail.column, e.detail.index, (_b = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.originalEvent) === null || _b === void 0 ? void 0 : _b.shiftKey); }; this.addEventListener('beforesourceset', beforesourceset); this.addEventListener('aftercolumnsset', aftercolumnsset); this.addEventListener('initialHeaderClick', headerclick); } get hasSorting() { return !!this.sorting; } async headerclick(column, index, additive) { let order = this.getNextOrder(column.order); const beforeEvent = this.emit('beforesorting', { column, order, additive }); if (beforeEvent.defaultPrevented) { return; } order = beforeEvent.detail.order; const newCol = await this.revogrid.updateColumnSorting(beforeEvent.detail.column, index, order, additive); // apply sort data const beforeApplyEvent = this.emit('beforesortingapply', { column: newCol, order, additive }); if (beforeApplyEvent.defaultPrevented) { return; } order = beforeApplyEvent.detail.order; const cellCmp = (column === null || column === void 0 ? void 0 : column.cellCompare) || this.defaultCellCompare; const cmp = order == 'asc' ? cellCmp : order == 'desc' ? this.descCellCompare(cellCmp) : undefined; if (additive && this.sorting) { const sorting = {}; const sortingFunc = {}; Object.assign(sorting, this.sorting); Object.assign(sortingFunc, this.sortingFunc); if (column.prop in sorting && size(sorting) > 1 && order === undefined) { delete sorting[column.prop]; delete sortingFunc[column.prop]; } else { sorting[column.prop] = order; sortingFunc[column.prop] = cmp; } this.sort(sorting, sortingFunc); } else { this.sort({ [column.prop]: order }, { [column.prop]: cmp }); } } setData(data, type) { // sorting available for rgRow type only if (type === 'rgRow' && this.sortingFunc) { return this.sortItems(data, this.sortingFunc); } } /** * Sorting apply, available for rgRow type only * @param sorting - per column sorting * @param data - this.stores['rgRow'].store.get('source') */ async sort(sorting, sortingFunc) { if (!size(sorting)) { this.sorting = null; this.sortingFunc = null; return; } this.sorting = sorting; this.sortingFunc = sortingFunc; const store = await this.revogrid.getSourceStore(); const source = store.get('source'); const proxyItems = this.sortIndexByItems([...store.get('proxyItems')], source, this.sortingFunc); setStore(store, { proxyItems, source: [...source], }); this.emit('afterSortingApply'); } defaultCellCompare(prop, a, b) { var _a, _b; const av = (_a = a[prop]) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase(); const bv = (_b = b[prop]) === null || _b === void 0 ? void 0 : _b.toString().toLowerCase(); return av == bv ? 0 : av > bv ? 1 : -1; } descCellCompare(cmp) { return (prop, a, b) => { return -1 * cmp(prop, a, b); }; } sortIndexByItems(indexes, source, sortingFunc) { // TODO - is there a situation where multiple kvps in the `sorting` object would cause this to break? for (let prop in sortingFunc) { if (typeof sortingFunc[prop] === 'undefined') { // Unsort indexes return [...Array(indexes.length).keys()]; } } return indexes.sort((a, b) => { let sorted = 0; for (let prop in sortingFunc) { const cmp = sortingFunc[prop]; const itemA = source[a]; const itemB = source[b]; sorted = cmp(prop, itemA, itemB); if (sorted) { break; } } return sorted; }); } sortItems(source, sortingFunc) { return source.sort((a, b) => { let sorted = 0; for (let prop in sortingFunc) { const cmp = sortingFunc[prop]; sorted = cmp(prop, a, b); if (sorted) { break; } } return sorted; }); } getNextOrder(currentOrder) { switch (currentOrder) { case undefined: return 'asc'; case 'asc': return 'desc'; case 'desc': return undefined; } } }