UNPKG

gantt-source_management

Version:

Gantt, Schedule,

799 lines (793 loc) 26.9 kB
const t = "chart-timeline-grid-row-cell", e = "chart-timeline-items-row-item"; const i = "config.plugin.Selection"; function s(i) { return Object.assign( { enabled: !0, showOverlay: !0, isSelecting: !1, pointerState: "up", selectKey: "", multiKey: "shift", multipleSelection: !0, targetType: "", targetData: null, initialPosition: { x: 0, y: 0 }, currentPosition: { x: 0, y: 0 }, selectionAreaLocal: { x: 0, y: 0, width: 0, height: 0 }, selectionAreaGlobal: { x: 0, y: 0, width: 0, height: 0 }, selecting: { [e]: [], [t]: [] }, selected: { [e]: [], [t]: [] }, lastSelected: { [e]: [], [t]: [] }, lastSelecting: { [e]: [], [t]: [] }, automaticallySelected: { [e]: [], [t]: [] }, events: { onStart() {}, onSelecting: (t) => t, onEnd: (t) => t }, pointerEvents: { down: null, move: null, up: null }, }, i, ); } class a { constructor(a, l) { (this.onDestroy = []), (this.started = !1), (this.lastAllEvents = { down: null, move: null, up: null }), (this.vido = a), (this.state = a.state), (this.api = a.api), (this.merge = this.state.get("config.merge")), this.state.update(i, s(l)), (this.data = s(l)), (this.slotClassName = this.api.getClass("chart-selection")), (this.slotStyleMap = new a.StyleMap({ display: "none" })), (this.html = a.html), (this.slot = this.slot.bind(this)), (this.destroy = this.destroy.bind(this)), this.setSlot(), (this.onCellCreate = this.onCellCreate.bind(this)), (this.apiGetSelection = this.apiGetSelection.bind(this)), (this.apiGetSelecting = this.apiGetSelecting.bind(this)), (this.apiGetSelected = this.apiGetSelected.bind(this)), (this.apiSetSelection = this.apiSetSelection.bind(this)), (this.apiSelectCells = this.apiSelectCells.bind(this)), (this.apiSelectItems = this.apiSelectItems.bind(this)), (this.api.plugins.Selection = { ITEM: e, CELL: t, getSelection: this.apiGetSelection, getSelected: this.apiGetSelected, getSelecting: this.apiGetSelecting, setSelection: this.apiSetSelection, selectCells: this.apiSelectCells, selectItems: this.apiSelectItems, }), this.state.update( "config.chart.grid.cell.onCreate", (t) => (t.includes(this.onCellCreate) || t.push(this.onCellCreate), t), ), this.updateData(), this.onDestroy.push( this.state.subscribe(i, (t) => { this.data = t; }), ), (this.updateSelectionClassName = this.updateSelectionClassName.bind(this)), (this.selectedAction = this.selectedAction.bind(this)), this.state.update( "config.actions.chart-timeline-grid-row-cell", (t) => ( t.includes(this.selectedAction) || t.push(this.selectedAction), t ), ), this.state.update( "config.actions.chart-timeline-items-row-item", (t) => ( t.includes(this.selectedAction) || t.push(this.selectedAction), t ), ), this.onDestroy.push( this.state.subscribe( "config.chart.items.*;", () => { const t = this.api.getAllItems(); (this.data.selected[e] = this.data.selected[e].filter( (e) => !!t[e], )), (this.data.selecting[e] = this.data.selecting[e].filter( (e) => !!t[e], )); const i = this.api.getItemsData(); for (const t in i) { const s = i[t]; (s.selected = this.data.selected[e].includes(t)), (s.selecting = this.data.selecting[e].includes(t)); } }, { bulk: !0, bulkValue: !1 }, ), ), (this.onTimelinePointerDown = this.onTimelinePointerDown.bind(this)), (this.onTimelinePointerMove = this.onTimelinePointerMove.bind(this)), (this.onTimelinePointerUp = this.onTimelinePointerUp.bind(this)), this.api.plugins.TimelinePointer.addPointerListener( "move", this.onTimelinePointerMove, ), this.api.plugins.TimelinePointer.addPointerListener( "down", this.onTimelinePointerDown, ), this.api.plugins.TimelinePointer.addPointerListener( "up", this.onTimelinePointerUp, ); } setSlot() { this.state.update( "config.slots.chart-timeline-items.outer", (t) => (t.includes(this.slot) || t.push(this.slot), t), ); } destroy() { this.api.plugins.TimelinePointer.removePointerListener( "move", this.onTimelinePointerMove, ), this.api.plugins.TimelinePointer.removePointerListener( "down", this.onTimelinePointerDown, ), this.api.plugins.TimelinePointer.removePointerListener( "up", this.onTimelinePointerUp, ), this.state.update("config.slots.chart-timeline-items.outer", (t) => t.filter((t) => t !== this.slot), ), this.state.update("config.actions.chart-timeline-grid-row-cell", (t) => t.filter((t) => t !== this.selectedAction), ), this.state.update("config.actions.chart-timeline-items-row-item", (t) => t.filter((t) => t !== this.selectedAction), ), this.state.update("config.chart.grid.cell.onCreate", (t) => t.filter((t) => t !== this.onCellCreate), ), this.onDestroy.forEach((t) => t()); } updateData() { this.state.update(i, Object.assign({}, this.data)), this.vido.update(); } apiSetSelection(t) { this.data.selected = this.api.mergeDeep({}, t); let e = this.state.multi(!0); (e = this.updateCells(e)), (e = this.updateItems(e)), e.done(), this.updateData(); } apiSelectCells(e) { this.data.selected[t] = [...e]; let i = this.state.multi(!0); (i = this.updateCells(i)), i.done(), this.updateData(); } apiSelectItems(t) { this.data.selected[e] = [...t]; let i = this.state.multi(!0); (i = this.updateItems(i)), i.done(), this.updateData(); } apiGetSelection() { return { selecting: this.getSelectionWithData(this.data.selecting), selected: this.getSelectionWithData(this.data.selected), }; } apiGetSelecting() { return this.getSelectionWithData(this.data.selecting); } apiGetSelected() { return this.getSelectionWithData(this.data.selected); } modKeyPressed(t, e) { switch (t) { case "shift": return e.shiftKey; case "alt": return e.altKey; case "ctrl": return e.ctrlKey; } } canSelect() { let t = this.data.enabled; const e = this.lastAllEvents.down; return ( e && this.data.selectKey && (t = t && this.modKeyPressed(this.data.selectKey, e)), t && (this.data.cells || this.data.items) ); } getSelectionAreaLocal(t) { const e = { x: 0, y: 0, width: 0, height: 0 }, i = Object.assign({}, t.initialPosition), s = Object.assign({}, t.currentPosition), a = s.x - i.x, l = s.y - i.y; return ( a >= 0 ? ((e.x = i.x), (e.width = a)) : ((e.x = s.x), (e.width = Math.abs(a))), l >= 0 ? ((e.y = i.y), (e.height = l)) : ((e.y = s.y), (e.height = Math.abs(l))), e ); } translateAreaLocalToGlobal(t) { const e = this.state.get("$data.chart.time.leftPx"), i = this.state.get("$data.scroll.vertical.absolutePosPx"); return Object.assign(Object.assign({}, t), { x: t.x + e, y: t.y + i }); } collectLinkedItems(t, e = this.api.getItemsData()) { if (!e[t]) throw ( (console.error( '"config.chart.items"', this.state.get("config.chart.items"), ), console.error( '"$data.chart.items"', this.state.get("$data.chart.items"), ), new Error(`Item with id"${t}"does not exists in"$data.chart.items".`)) ); return [t, ...e[t].linkedWith]; } getSelectedItem(t) { let i, s = this.data.automaticallySelected[e].slice(); const a = this.collectLinkedItems(t.id); if (this.data.selected[e].find((e) => e === t.id)) if (((i = this.data.selected[e]), s.find((e) => e === t.id))) { const e = s, a = i.find((i) => t.linkedWith.includes(i) && !e.includes(i)); (s = s.filter((e) => e !== t.id)), s.push(a); } else s = this.data.automaticallySelected[e]; else (i = this.isMulti() ? Array.from(new Set([...this.data.selected[e], ...a])) : a), (s = a.filter((e) => e !== t.id)); return ( (i = i.map((e) => ((t = this.api.getItem(e)), e))), { selected: i, automaticallySelected: s } ); } isItemVerticallyInsideArea(t, e) { if (!e.width || !e.height) return !1; const i = e.y + e.height, s = t.position.viewTop, a = s + t.actualHeight; return ( (s >= e.y && s <= i) || (a >= e.y && a <= i) || (s >= e.y && a <= i) || (s <= e.y && a >= i) ); } isItemHorizontallyInsideArea(t, e) { if (!e.width || !e.height) return !1; const i = e.x + e.width; return ( (t.position.actualLeft >= e.x && t.position.actualLeft <= i) || (t.position.actualRight >= e.x && t.position.actualRight <= i) || (t.position.actualLeft <= e.x && t.position.actualRight >= i) || (t.position.actualLeft >= e.x && t.position.actualRight <= i) ); } isMulti() { const t = this.lastAllEvents.move; return t && this.data.multiKey && this.modKeyPressed(this.data.multiKey, t); } getItemsUnderSelectionArea(t) { const e = this.state.get("$data.chart.visibleItems"), i = this.api.getItems(e), s = [], a = []; for (let e of i) { e = this.merge({}, e); const i = this.api.getItemData(e.id); if ( this.isItemVerticallyInsideArea(i, t) && this.isItemHorizontallyInsideArea(i, t) ) { s.find((t) => t === e.id) || s.push(e.id); const t = this.collectLinkedItems(e.id); for (const e of t) { const t = this.api.getItem(e); s.find((e) => e === t.id) || (s.push(t.id), a.push(t.id)); } } } return { selectedItems: s, automaticallySelectedItems: a }; } isCellVerticallyInsideArea(t, e) { if (!e.width || !e.height) return !1; const i = e.y + e.height, s = t.top, a = s + t.rowData.actualHeight; return ( (s >= e.y && s <= i) || (a >= e.y && a <= i) || (s >= e.y && a <= i) || (s <= e.y && a >= i) ); } isCellHorizontallyInsideArea(t, e) { if (!e.width || !e.height) return !1; const i = e.x + e.width, s = t.time.currentView.leftPx, a = t.time.currentView.rightPx; return ( (s >= e.x && s <= i) || (a >= e.x && a <= i) || (s <= e.x && a >= i) || (s >= e.x && a <= i) ); } getCellsUnderSelectionArea(t) { const e = this.state.get("$data.chart.grid.cells"), i = []; for (const s in e) { const a = e[s]; this.isCellVerticallyInsideArea(a, t) && this.isCellHorizontallyInsideArea(a, t) && (i.find((t) => t === a.id) || i.push(a.id)); } return { selectedCells: i }; } updateItems(t) { if (!this.data.items) return t; const i = this.api.getAllItems(), s = Array.from( new Set([...this.data.selecting[e], ...this.data.selected[e]]), ); return (t = t.update( "$data.chart.items", (t) => { for (const a in t) if (a in i) if (s.includes(a)) { const i = this.data.selecting[e].includes(a), s = this.data.selected[e].includes(a); (t[a].selected = s), (t[a].selecting = i); } else (t[a].selected = !1), (t[a].selecting = !1); return t; }, { data: "selection" }, )); } updateCurrentItems(t) { if (!this.data.items) return t; const i = this.state.get("$data.chart.items"), s = Array.from( new Set([ ...this.data.lastSelecting[e], ...this.data.selecting[e], ...this.data.selected[e], ]), ); for (const t of s) (i[t].selecting = this.data.selecting[e].includes(t)), (i[t].selected = this.data.selected[e].includes(t)); return t; } updateCells(e) { if (!this.data.cells) return e; const i = this.api.getAllGridCells(); return ( e.update("$data.chart.grid.cells", (e) => { for (const s in e) { if (!(s in i)) continue; const a = e[s]; a && ((a.selected = this.data.selected[t].includes(a.id)), (a.selecting = this.data.selecting[t].includes(a.id))); } return e; }), e ); } updateCurrentCells(e) { if (!this.data.items) return e; const i = Array.from( new Set([ ...this.data.lastSelecting[t], ...this.data.selecting[t], ...this.data.selected[t], ]), ); for (const s of i) { this.state.get(`$data.chart.grid.cells.${s}`) && (e = e.update( `$data.chart.grid.cells.${s}`, (e) => ( (e.selected = this.data.selected[t].includes(s)), (e.selecting = this.data.selecting[t].includes(s)), e ), )); } return e; } deselectItems() { if (!this.data.items) return; (this.data.selected[e].length = 0), (this.data.selecting[e].length = 0); let t = this.state.multi(!0); (t = this.updateItems(t)), t.done(); } deselectCells() { if (!this.data.cells) return; (this.data.selecting[t].length = 0), (this.data.selected[t].length = 0); let e = this.state.multi(!0); (e = this.updateCells(e)), e.done(); } getSelectionWithData(i) { const s = this.state.get("config.chart.items"), a = this.state.get("$data.chart.grid.cells"); return { [t]: i[t].map((t) => (a[t] ? a[t] : t)), [e]: i[e].map((t) => (s[t] ? s[t] : t)), }; } onSelecting(i, s) { const a = this.getSelectionWithData(i), l = this.getSelectionWithData(s); this.started || (this.data.events.onStart(l), (this.started = !0), this.api.muteMethod("fullReload"), this.api.muteMethod("prepareExpanded"), this.api.muteMethod("calculateRowsHeight"), this.api.muteMethod("recalculateRowPercents"), this.api.muteMethod("getLastPageRowsHeight"), this.api.muteMethod("calculateVerticalScrollArea"), this.api.muteMethod("calculateVisibleRowsHeights"), this.api.muteMethod("generateVisibleRowsAndItems"), this.api.muteMethod("recalculateTimes"), this.api.muteMethod("heightChange")); const n = this.data.events.onSelecting(a, l); return { [t]: n[t].map((t) => ("string" != typeof t ? t.id : t)), [e]: n[e].map((t) => ("string" != typeof t ? t.id : t)), }; } onSelected(i, s) { const a = this.getSelectionWithData(i), l = this.getSelectionWithData(s), n = this.data.events.onEnd(a, l); return ( (this.started = !1), this.api.unmuteMethod("heightChange"), this.api.unmuteMethod("recalculateTimes"), this.api.unmuteMethod("generateVisibleRowsAndItems"), this.api.unmuteMethod("calculateVisibleRowsHeights"), this.api.unmuteMethod("calculateVerticalScrollArea"), this.api.unmuteMethod("getLastPageRowsHeight"), this.api.unmuteMethod("recalculateRowPercents"), this.api.unmuteMethod("calculateRowsHeight"), this.api.unmuteMethod("prepareExpanded"), this.api.unmuteMethod("fullReload"), { [t]: n[t].map((t) => ("string" != typeof t ? t.id : t)), [e]: n[e].map((t) => ("string" != typeof t ? t.id : t)), } ); } updateBodyClass() { this.data.isSelecting ? document.body.classList.add(this.data.bodySelectingClassName) : document.body.classList.remove(this.data.bodySelectingClassName), this.data.selected[t].length || this.data.selected[e].length ? document.body.classList.add(this.data.bodySelectedClassName) : document.body.classList.remove(this.data.bodySelectedClassName); } selectMultipleCellsAndItems(i) { if (!this.canSelect()) return; if (!this.data.multipleSelection) return this.deselectItems(), this.deselectCells(), void this.updateData(); (this.data.isSelecting = !0), (this.data.selectionAreaLocal = this.getSelectionAreaLocal(i)), (this.data.selectionAreaGlobal = this.translateAreaLocalToGlobal( this.data.selectionAreaLocal, )); const s = { [t]: [], [e]: [] }, a = this.isMulti(); if (this.data.cells) { const { selectedCells: e } = this.getCellsUnderSelectionArea( this.data.selectionAreaLocal, ); 0 === e.length ? ((s[t].length = 0), a || (this.data.selected[t].length = 0)) : (s[t] = e); } if (this.data.items) { const { selectedItems: t, automaticallySelectedItems: i } = this.getItemsUnderSelectionArea(this.data.selectionAreaLocal); (this.data.automaticallySelected[e] = i), 0 === t.length ? ((s[e].length = 0), a || (this.data.selected[e].length = 0)) : (s[e] = t); } if (this.data.cells || this.data.items) { (this.data.lastSelecting = { [e]: [...this.data.selecting[e]], [t]: [...this.data.selecting[t]], }), (this.data.selecting = this.onSelecting( s, this.api.mergeDeep({}, this.data.lastSelected), )); let i = this.state.multi(!0); this.data.cells && (i = this.updateCurrentCells(i)), this.data.items && (i = this.updateCurrentItems(i)), i.done(); } } selectItemsIndividually(i) { if ( ((this.data.isSelecting = !1), (this.data.selectionAreaLocal = this.getSelectionAreaLocal(i)), (this.data.currentPosition = i.currentPosition), (this.data.initialPosition = i.initialPosition), !this.data.items || i.type !== 'down' ) ) return; if (!this.canSelect()) return; if (!i.targetData) return; const s = this.merge({}, i.targetData), a = this.api.getItemData(s.id); if (!a) throw ( (console.error( '"config.chart.items"', this.state.get("config.chart.items"), ), console.error( '"$data.chart.items"', this.state.get("$data.chart.items"), ), new Error( `Item with id"${s.id}"does not exists in"$data.chart.items".TIP:For performance reasons,state is mutable,so try not to modify items from the"state.get"method before you copy them(with"gstc.api.clone(items)"for example).`, )) ); if (this.data.selected[e].includes(s.id)){ if (this.isMulti()) { // 多选模式下,从已选择列表中移除该项目 this.data.selected[e] = this.data.selected[e].filter((itemId) => itemId !== s.id); this.data.automaticallySelected[e] = this.data.automaticallySelected[e].filter((itemId) => itemId !== s.id); } else { // 单选模式下,清空已选择列表 this.data.selected[e] = []; this.data.selected[t] = []; this.data.automaticallySelected[e] = []; } // 记录最后一次选择的状态 this.data.lastSelecting = { [e]: [...this.data.selected[e]], [t]: [...this.data.selected[t]], }; // 更新状态 let c = this.state.multi(true); c = this.updateCells(c); c = this.updateItems(c); c.done(); return; } let { selected: l, automaticallySelected: n } = this.getSelectedItem(s); l.length > 1 && !this.data.multipleSelection && ((l = [s.id]), (n = [])), this.isMulti() ? a.selected ? (this.data.selected[e] = l.filter( (t) => t !== s.id && !n.includes(t), )) : (this.data.selected[e] = l) : ((this.data.selected[e] = l), (this.data.selected[t].length = 0)), (this.data.automaticallySelected[e] = n), (this.data.lastSelecting = { [e]: [], [t]: [], }), (this.data.selected = this.onSelected( this.api.mergeDeep({}, this.data.selected), this.api.mergeDeep({}, this.data.lastSelected), ) ); // this.data.selected[e] = []; this.data.selected[t] = []; this.data.automaticallySelected[e] = []; //////// let c = this.state.multi(!0); (c = this.updateCells(c)), (c = this.updateItems(c)), c.done(); } removeMultiUnselected(t) { const e = this.data.selected[t].filter((e) => this.data.selecting[t].includes(e), ), i = [...this.data.selected[t], ...this.data.selecting[t]]; return Array.from(new Set(i.filter((t) => !e.includes(t)))); } finishSelection() { if (!this.canSelect()) return; let i; (i = this.isMulti() ? { [t]: this.data.cells ? this.removeMultiUnselected(t) : [], [e]: this.data.items ? this.removeMultiUnselected(e) : [], } : { [t]: this.data.cells ? [...this.data.selecting[t]] : [], [e]: this.data.items ? [...this.data.selecting[e]] : [], }), (this.data.selected = this.onSelected( i, this.api.mergeDeep({}, this.data.lastSelected), )), (this.data.lastSelected = this.api.mergeDeep({}, this.data.selected)), this.data.cells && (this.data.selecting[t].length = 0), this.data.items && (this.data.selecting[e].length = 0); let s = this.state.multi(!0); (s = this.updateItems(s)), (s = this.updateCells(s)), s.done(); } onPointerData(i) { if (this.eventsCheck(i) && ((this.lastAllEvents = i.allEvents), i.isMoving && i.targetType === t && this.data.rectangularSelection ? this.selectMultipleCellsAndItems(i) : i.isMoving && i.targetType === t && !this.data.rectangularSelection ? this.deselectItems() : i.targetType === e ? this.selectItemsIndividually(i) : i.isMoving || (this.data.isSelecting && this.finishSelection(), (this.data.isSelecting = !1)), i.isMoving && i.targetType !== t && i.targetType !== e && this.deselectItems(), (this.data.pointerState = i.type), (this.data.targetType = i.targetType), (this.data.targetData = i.targetData), "down" === this.data.pointerState) ) { let t = this.state.multi(!0); (t = this.updateItems(t)), (t = this.updateCells(t)), t.done(); } this.updateData(), this.updateBodyClass(); } eventsCheck(i) { if (i && i.allEvents) { if (i.allEvents.down && i.allEvents.down.button === 2) { return false; } } return true; } onTimelinePointerDown(t) { this.data.enabled && this.onPointerData(t); } onTimelinePointerMove(t) { this.data.enabled && this.onPointerData(t); } onTimelinePointerUp(t) { this.data.enabled && this.onPointerData(t); } slot() { let t, e = !0; return (i) => ( (e = !0), this.canSelect() && this.data.isSelecting && this.data.showOverlay && this.data.multipleSelection && this.data.rectangularSelection && ((this.slotStyleMap.style.display = "block"), (this.slotStyleMap.style.left = this.data.selectionAreaLocal.x + "px"), (this.slotStyleMap.style.top = this.data.selectionAreaLocal.y + "px"), (this.slotStyleMap.style.width = this.data.selectionAreaLocal.width + "px"), (this.slotStyleMap.style.height = this.data.selectionAreaLocal.height + "px"), (e = !1)), (t = this .html`<div class=${this.slotClassName}style=${this.slotStyleMap.directive()}></div>`), this.html`${i}${e ? null : t}` ); } updateSelectionClassName(t, e) { if (!e && !e.itemData) return; const i = "boolean" == typeof e.selected ? e.selected : e.itemData.selected, s = "boolean" == typeof e.selecting ? e.selecting : e.itemData.selecting; i ? (t.classList.contains(this.data.selectedClassName) || t.classList.add(this.data.selectedClassName), t.classList.contains(this.data.selectingClassName) && t.classList.remove(this.data.selectingClassName)) : t.classList.contains(this.data.selectedClassName) && t.classList.remove(this.data.selectedClassName), s ? (t.classList.contains(this.data.selectingClassName) || t.classList.add(this.data.selectingClassName), t.classList.contains(this.data.selectedClassName) && t.classList.remove(this.data.selectedClassName)) : t.classList.contains(this.data.selectingClassName) && t.classList.remove(this.data.selectingClassName); } selectedAction(t, e) { this.updateSelectionClassName(t, e); const i = this; return { update(t, e) { i.updateSelectionClassName(t, e); }, destroy(t, e) { i.updateSelectionClassName(t, e); }, }; } onCellCreate(e) { return ( (e.selected = !!this.data.selected[t].find((t) => t === e.id)), (e.selecting = !!this.data.selecting[t].find((t) => t === e.id)), e.content ); } } function l(t = {}) { return ( (t = (function (t) { !(function (t) { t.events || (t.events = {}), t.onStart && (t.events.onStart = t.onStart), t.onSelecting && (t.events.onSelecting = t.onSelecting), t.onSelected && (t.events.onEnd = t.onSelected); })(t); const e = { enabled: !0, cells: !0, items: !0, showOverlay: !0, rectangularSelection: !0, multipleSelection: !0, selectedClassName: "gstc__selected", selectingClassName: "gstc__selecting", bodySelectedClassName: "gstc__is-selected", bodySelectingClassName: "gstc__is-selecting", events: { onStart() {}, onSelecting: (t) => t, onEnd: (t) => t }, }; return ( (t.events = Object.assign(Object.assign({}, e.events), t.events)), Object.assign(Object.assign({}, e), t) ); })(t)), function (e) { const s = e.api.mergeDeep, l = e.api; if (!l.isPluginInitialized("TimelinePointer")) throw new Error( "TimelinePointer plugin must be initialized before Selection plugin.", ); const n = e.state.get(i); n && (t = s({}, t, n)); const c = new a(e, t); return l.pluginInitialized("Selection"), c.destroy; } ); } export { l as Plugin };