UNPKG

gantt-source_management

Version:

Gantt, Schedule,

1,251 lines (1,247 loc) 556 kB
import { d as A, u as g, a as I, S as B, A as C, h as Q, l as E, v as t, D as i, _ as e, m as o, b as a, c as s, p as c, P as n, e as l, f as D, J as h, V as w } from "./vendor.esm.min.js"; /** * Gantt-Schedule-Timeline-Calendar Time api * * @copyright NEURONET - Rafal Pospiech * @author Rafal Pospiech <neuronet.io@gmail.com> * @module gantt-schedule-timeline-calendar * @link https://github.com/neuronetio/gantt-schedule-timeline-calendar * @link https://gantt-schedule-timeline-calendar.neuronet.io * @version 3.37.5 * @released 2024-07-19 * @license SEE LICENSE IN LICENSE FILE */ class r { constructor(B, C) { this.utcMode = !1, this.unsubs = [], this.currentDateLastCheck = 0, this.state = B, this.api = C, this.dayjs = A, this.dayjs.extend(g), this.dayjs.extend(I), this.unsubs.push(B.subscribe("config.utcMode", (A => { this.utcMode = A }))), this.unsubs.push(B.subscribe("config.locale", (A => { if (!A.name) throw new Error("Locale must have a name property."); this.locale = A, this.dayjs.locale(this.locale, null, !0) }))) } destroy() { for (const A of this.unsubs) A() } date(g = void 0) { return this.utcMode ? A.utc(g).locale(this.locale.name) : g ? A(g).locale(this.locale.name) : A().locale(this.locale.name) } recalculateTime() { this.api.main.recalculateTimes([{ name: "all" }]) } recalculateFromTo(A, g = !1) { const I = A.period; if ((A = Object.assign({}, A)).from = +A.from, A.to = +A.to, A.fromDate = this.date(A.from).startOf(I), A.from = A.fromDate.valueOf(), A.toDate = this.date(A.to).endOf(I), A.to = A.toDate.valueOf(), !A.autoExpandTimeFromItems || A.calculatedZoomMode) return A; let B = Number.MAX_SAFE_INTEGER, C = 0; const Q = this.state.get("config.chart.items"); if (Object.keys(Q).length > 0 && (0 === A.from || 0 === A.to || g)) { for (const A in Q) { const g = Q[A]; g.time.start < B && g.time.start && (B = g.time.start), g.time.end > C && (C = g.time.end) } B < A.from && (A.fromDate = this.date(B).startOf(I), A.from = A.fromDate.valueOf()), C > A.to && (A.toDate = this.date(C).endOf(I), A.to = A.toDate.valueOf()) } return A } getCenter(A) { return A.leftGlobal + Math.round((A.rightGlobal - A.leftGlobal) / 2) } isInCurrentView(A, g = this.state.get("$data.chart.time")) { const I = A.valueOf(); return !(I < g.leftGlobal || I > g.rightGlobal) } recalculateDatesWidths(A, g = this.state.get("$data.chart.time")) { if (!g.timePerPixel) throw new Error("[gantt-schedule-timeline-calendar] No timePerPixel"); for (const I of A) { if (!I.leftGlobal || !I.rightGlobal) throw new Error("[gantt-schedule-timeline-calendar] No date leftGlobal or rightGlobal."); I.width = (I.rightGlobal + 1 - I.leftGlobal) / g.timePerPixel } return A } recalculateDatesPositions(A, g = this.state.get("$data.chart.time"), I = !0, B = !1) { let C = 0; if (I) for (const I of A) { if (I.leftGlobal >= g.leftGlobal) break; if (isNaN(I.width)) throw new Error("[gantt-schedule-timeline-calendar] NaN date width."); C -= I.width } for (let I of A) { if (B && (I = this.api.mergeDeep({}, I)), I.leftPx = C, I.rightPx = C + I.width, isNaN(I.leftPx) || isNaN(I.rightPx)) throw new Error("[gantt-schedule-timeline-calendar] Date leftPx or rightPx is a NaN."); I.currentView && (I.currentView.leftPx = I.leftPx - g.leftPx, I.currentView.rightPx = I.rightPx - g.leftPx, I.currentView.width = I.currentView.rightPx - I.currentView.leftPx), C += I.width } return A } setDatesCacheLevel(A, g, I = this.state.get("$data.chart.time")) { if (!g.length) return; I.datesCache || (I.datesCache = { timePerPixel: 0, levels: [] }), I.datesCache.timePerPixel = I.timePerPixel, I.datesCache.levels[A] || (I.datesCache.levels[A] = { leftTime: 0, rightTime: 0, dates: [] }); const B = I.datesCache.levels[A]; B.leftTime = g[0].leftGlobal, B.rightTime = g[g.length - 1].rightGlobal, B.dates = [...g] } addDatesToCacheLevel(A, g, I = this.state.get("$data.chart.time")) { if (!g.length) return; if (!I.datesCache) return; if (I.datesCache.timePerPixel !== I.timePerPixel) return g; const B = g[0], C = g[g.length - 1], Q = I.datesCache.levels[A]; if (!Q) return g; if (Q.leftTime <= B.leftGlobal && Q.rightTime >= C.rightGlobal) return Q.dates; if (Q.dates.length >= 1e6) throw new Error("[gantt-schedule-timeline-calendar] To many dates."); const E = []; if (B.leftGlobal < Q.leftTime) { for (const A of g) { if (!(A.leftGlobal < Q.leftTime)) break; E.push(A) } Q.leftTime = E[0].leftGlobal } for (const A of Q.dates) E.push(A); if (C.rightGlobal > Q.rightTime) { for (const A of g) A.rightGlobal > Q.rightTime && E.push(A); Q.rightTime = E[E.length - 1].rightGlobal } return Q.dates = E, Q.dates } isLevelDateInCache(A, g, I = this.state.get("$data.chart.time")) { if (!I.datesCache) return !1; if (I.datesCache.timePerPixel !== I.timePerPixel) return !1; const B = I.datesCache.levels[A]; return !(!B || !B.dates.length) && (g >= B.leftTime && g <= B.rightTime) } getLevelDatesFromCache(A, g, I, B = this.state.get("$data.chart.time")) { if (B.datesCache.timePerPixel !== B.timePerPixel) return []; const C = B.datesCache.levels[A]; if (!C) return []; if (!(g >= C.leftTime && I <= C.rightTime)) return []; let Q = 0, E = 0, t = !1; const i = C.dates.length; for (; E < i; E++) { const A = C.dates[E]; if (A.rightGlobal >= g && (t = !0), A.rightGlobal >= I) break; t || Q++ } return { [Symbol.iterator]() { let A = Q; return { next: () => A <= E ? { value: C.dates[A++], done: !1 } : (A = Q, { done: !0 }) } }, length: E - Q + 1 } } getLevelDateFromCache(A, g, I = this.state.get("$data.chart.time")) { if (!this.isLevelDateInCache(A, g, I)) return null; for (const B of I.datesCache.levels[A].dates) if (B.rightGlobal >= g) return B; return null } getAllLevelDatesFromCache(A, g = this.state.get("$data.chart.time")) { return g.datesCache.levels[A].dates } findOrCreateMainDateAtTime(A, g = this.state.get("$data.chart.time")) { if (this.isLevelDateInCache(g.level, A, g)) return this.getLevelDateFromCache(g.level, A, g); let I = []; g.datesCache.levels[g.level] && (I = g.datesCache.levels[g.level].dates), I = this.addMissingDates(I, this.date(A), g); for (const g of I) if (g.rightGlobal >= A) return g; return null } addMissingDates(A, g, I = this.state.get("$data.chart.time"), B = !0) { if (!A.length) return []; const C = A[0], Q = A[A.length - 1]; if (!(g.valueOf() < C.leftGlobal || g.valueOf() > Q.rightGlobal)) return A; if (this.isLevelDateInCache(I.level, g.valueOf(), I)) return this.getAllLevelDatesFromCache(I.level, I); const E = A.length; let t = A; if (B) { t = new Array(E); for (let g = 0; g < E; g++) t[g] = this.api.mergeDeep({}, A[g]) } const i = this.state.get(`config.chart.calendarLevels.${I.level}`), e = this.getCurrentFormatForLevel(i, I); let o = 1; if ("number" == typeof e.periodIncrement && (o = e.periodIncrement), g.valueOf() < C.leftGlobal) { if ("function" == typeof e.periodIncrement) return A; const Q = C.leftGlobalDate.subtract(1, "ms"); let E = C.leftGlobalDate.subtract(o, I.period).startOf(I.period); for (; g.valueOf() < E.valueOf();) E = E.subtract(o, I.period).startOf(I.period); let i = []; do { i = this.generatePeriodDates({ leftDate: E, rightDate: Q, period: I.period, level: this.state.get(`config.chart.calendarLevels.${I.level}`), levelIndex: I.level, callOnDate: !0, callOnLevelDates: !0, time: I }), E = E.subtract(1, I.period) } while (!i.length || i[0].leftGlobal > g.valueOf()); return i = i.filter((A => !t.find((g => g.leftGlobal === A.leftGlobal)))), A = [...i, ...t], A = this.recalculateDatesWidths(A, I), A = this.recalculateDatesPositions(A, I, !0, B), this.addDatesToCacheLevel(I.level, A, I) } if (g.valueOf() > Q.rightGlobal) { let C = Q.rightGlobalDate.add(o, I.period).endOf(I.period); for (; g.valueOf() > C.valueOf();) C = C.add(o, I.period).endOf(I.period); let E = this.generatePeriodDates({ leftDate: Q.rightGlobalDate.add(1, "ms"), rightDate: C, period: I.period, level: this.state.get(`config.chart.calendarLevels.${I.level}`), levelIndex: I.level, callOnDate: !0, callOnLevelDates: !0, time: I }); return E = E.filter((A => !t.find((g => g.leftGlobal === A.leftGlobal)))), A = [...t, ...E], A = this.recalculateDatesWidths(A, I), A = this.recalculateDatesPositions(A, I, !0, B), this.addDatesToCacheLevel(I.level, A, I) } return t } getGlobalOffsetPxFromDates(A, g = !0, I = this.state.get("$data.chart.time"), B = void 0) { const C = A.valueOf(); if (!I.allDates || 0 === I.allDates.length) return -100; if (void 0 === B && (B = I.allDates[I.level]), g && (B = this.addMissingDates(B, A, I)), !B || 0 === B.length) return -1; let Q; for (let A = 0, g = B.length; A < g; A++) { const g = B[A]; if (C <= g.rightGlobal + 1) { Q = g; break } } return Q ? C < Q.leftGlobal ? Q.leftPx : Q.rightPx - (Q.rightGlobal - C) / I.timePerPixel : C <= I.leftGlobal ? 0 : C >= I.rightGlobal ? I.totalViewDurationPx + (C - I.rightGlobal + 1) / I.timePerPixel : -1 } getViewOffsetPxFromDates(A, g = !0, I = this.state.get("$data.chart.time"), B = void 0, C = !0) { B || (B = I.allDates[I.level]), C && (B = this.addMissingDates(B, A, I)); const Q = this.getDatesDiffPx(I.leftGlobalDate, A, I, !0, B); return g ? this.limitOffsetPxToView(Q) : Q } limitOffsetPxToView(A, g = this.state.get("$data.chart.time")) { if (A < 0) return 0; if (!g.levels.length) return g.width; const I = g.levels[g.level]; if (!I.length) return g.width; const B = I[I.length - 1]; return A > B.currentView.rightPx ? B.currentView.rightPx : A } findDateAtViewOffsetPx(A, g) { return g.find((g => g.currentView.rightPx >= A)) } findDateIndex(A, g) { let I = 0; for (const B of g) { if (B.rightGlobal >= A) return I; I++ } return -1 } findDateAtTime(A, g = void 0) { if (!g) { const A = this.state.get("$data.chart.time"); g = A.allDates[A.level] } return g.find((g => g.rightGlobal >= A)) } getMainDateFromRelativePosition(A, g) { const I = A.leftPx + g, B = this.state.get("$data.chart.time"), C = B.allDates[B.level]; for (const A of C) if (A.rightPx > I) return A } getTimeFromOffsetPx(A, g = !0, I = this.state.get("$data.chart.time"), B = void 0) { let C = A; g && (C += I.leftPx), B || (B = I.allDates[I.level]); const Q = this.state.get(`config.chart.calendarLevels.${I.level}`), E = this.getCurrentFormatForLevel(Q, I); let t = 1; if ("number" == typeof E.periodIncrement && (t = E.periodIncrement), C < 0) { if ("function" == typeof E.periodIncrement) return I.from; let A, g = I.fromDate.subtract(t, I.period).startOf(I.period), B = 0; for (let Q = 0; Q < 1e3; Q++) { const Q = this.generatePeriodDates({ leftDate: g, rightDate: g.add(t, I.period).subtract(1, "ms"), period: I.period, time: I, level: this.state.get(`config.chart.calendarLevels.${I.level}`), levelIndex: I.level, callOnDate: !0, callOnLevelDates: !0, expandIfMissing: !1 }); if (Q.length && (A = Q[0], B -= A.width, B <= C)) return A.leftGlobal + (C - B) * I.timePerPixel; g = g.subtract(t, I.period).startOf(I.period) } } else if (C > I.totalViewDurationPx) { let A, g = I.toDate.add(1, I.period).startOf(I.period), B = I.totalViewDurationPx; for (let Q = 0; Q < 1e3; Q++) { const Q = this.generatePeriodDates({ leftDate: g, rightDate: g.add(t, I.period).subtract(1, "ms"), period: I.period, time: I, level: this.state.get(`config.chart.calendarLevels.${I.level}`), levelIndex: I.level, callOnDate: !0, callOnLevelDates: !0, expandIfMissing: !1 }); if (Q.length && (A = Q[0], B += A.width, B > C)) return A.rightGlobal + 1 - (B - C) * I.timePerPixel; g = g.add(t, I.period).startOf(I.period) } } for (let A = 0, g = B.length; A < g; A++) { const g = B[A]; if (g.rightPx > C) { const A = (g.rightPx - C) * I.timePerPixel; return g.rightGlobal + 1 - A } } const i = B[B.length - 1]; return i.rightGlobal + 1 - (i.rightPx - C) * I.timePerPixel } getCurrentFormatForLevel(A, g) { return A.find((A => +g.zoom <= +A.zoomTo)) } alignLevelToMain(A, g, I = this.state.get("$data.chart.time")) { if (A === I.level) return g; if (!this.state.get("config.chart.time.alignLevelsToMain")) return g; const B = I.allDates[I.level]; if (!B || !B.length) return g; if (!g || !g.length) return g; const C = g.length; for (let A = 0; A < C; A++) { const C = g[A]; let Q, E = !1, t = 0; for (const A of B) { if (A.rightGlobal >= C.leftGlobal) { if (!E) if (A.leftGlobal >= C.leftGlobal) C.leftGlobal = A.leftGlobal, C.leftGlobalDate = this.date(C.leftGlobal), C.leftPx = A.leftPx; else { const g = (A.rightGlobal - C.leftGlobal) / I.timePerPixel; t = -(A.width - g) } E = !0 } if (A.leftGlobal > C.rightGlobal) break; E && (t += A.width, Q = A) } if (Q) if (Q.rightGlobal <= C.rightGlobal) C.rightGlobal = Q.rightGlobal, C.rightGlobalDate = this.date(C.rightGlobal), C.width = t, C.rightPx = C.leftPx + C.width; else { const A = (Q.rightGlobal - C.rightGlobal) / I.timePerPixel; C.width = t - A, C.rightPx = C.leftPx + C.width } } return g } stopCheckingCurrentDates() { this.checkCurrentDateTimeoutId && clearTimeout(this.checkCurrentDateTimeoutId) } checkCurrentDates(A = !1, g = this.state.get("$data.chart.time")) { const I = this.date().valueOf(), B = g.checkCurrentDateInterval; if (this.stopCheckingCurrentDates(), A && (this.checkCurrentDateTimeoutId = setTimeout((() => { this.checkCurrentDates(A, g) }), B)), I - this.currentDateLastCheck < B) return; const C = g.allDates; let Q = !1; for (const A of C) { const g = A.length; for (let B = 0; B < g; B++) { const C = A[B], E = C.current; C.current = !1, C.previous = !1, C.next = !1, C.leftGlobal <= I && C.rightGlobal >= I && (!0 !== E && (Q = !0), C.current = !0, B > 0 && (A[B - 1].previous = !0), B + 1 < g && (A[B + 1].next = !0)) } } this.currentDateLastCheck = I, Q && this.state.update("$data.chart.time.levels", (A => A), { data: "current-time" }), this.api.render() } getDSTDiffForLevel(A, g, I, B = this.state.get("$data.chart.time")) { const C = this.api.time.getLevelDatesFromCache(A, g, I, B); let Q = 0; for (const A of C) A.DST.diffMs && g <= A.DST.afterTime && I > A.DST.afterTime && (Q += A.DST.diffMs); return Q } setDatesDST(A) { for (const g of A) { const A = g.rightGlobal - g.leftGlobal, I = g.rightGlobalDate.utc(!0).valueOf() - g.leftGlobalDate.utc(!0).valueOf(); if (A !== I) { g.DST = { diffMs: A - I, afterTime: 0, afterDate: null }; for (let A = 0; A < 9216; A++) if (g.leftGlobalDate.add(A, "hour").hour() !== g.leftGlobalDate.utc(!0).add(A, "hour").hour()) { g.DST.afterDate = g.leftGlobalDate.add(A, "hour").subtract(1, "ms"), g.DST.afterTime = g.DST.afterDate.valueOf(); break } } } return A } _generatePeriodDates(A) { const g = []; A = Object.assign({}, A); const { datesCount: I, rightDate: B, period: C, level: Q, levelIndex: E, time: t, originalLeftDate: i, format: e } = A; let o = A.leftDate; const a = this.date().valueOf(); for (let A = 0; A < I; A++) { let A = e.periodIncrement || 1; "function" == typeof A && (A = A({ currentDates: g, date: o, leftDate: i, rightDate: B, period: C, level: Q, levelIndex: E, time: t, vido: this.api.vido, api: this.api })); const I = o.add(A - 1, C).endOf(C), s = o.valueOf() <= a && I.valueOf() >= a, c = { id: `gstcid-${o.valueOf()}`, leftGlobal: o.valueOf(), leftGlobalDate: o, rightGlobalDate: I, rightGlobal: I.valueOf(), width: 0, leftPx: 0, rightPx: 0, period: C, formatted: null, current: s, previous: !1, next: !1, periodIncrementedBy: A, DST: { diffMs: 0, afterTime: 0, afterDate: null } }; s && g.length && (g[g.length - 1].previous = !0), g.length && g[g.length - 1].current && (c.next = !0); const n = c.rightGlobal + 1 - c.leftGlobal; c.width = n / t.timePerPixel, g.push(c), o = o.add(A || 1, C) } return this.setDatesDST(g) } generatePeriodDates({ leftDate: A, rightDate: g, period: I, level: B, levelIndex: C, time: Q, callOnDate: E, callOnLevelDates: t, expandIfMissing: i = !0 }) { if (!Q.timePerPixel) return []; const e = this.getCurrentFormatForLevel(B, Q); A = A.startOf(I), g = g.endOf(I); const o = Math.ceil(g.diff(A, I, !0)), a = A.clone(); let s = this._generatePeriodDates({ datesCount: o, leftDate: A, rightDate: g, period: I, level: B, levelIndex: C, time: Q, originalLeftDate: a, format: e }); if (E) { const A = []; for (let g = 0; g < s.length; g++) { let I = s[g]; if (I) { for (let A = 0, g = Q.onDate.length; A < g; A++) I = Q.onDate[A]({ date: I, format: e, time: Q, level: B, levelIndex: C }); I && A.push(I) } } s = A } if (t) for (let A = 0, g = Q.onLevelDates.length; A < g; A++) s = Q.onLevelDates[A]({ dates: s, format: e, time: Q, level: B, levelIndex: C }); if ((!s.length || s[s.length - 1].rightGlobal < g.valueOf()) && i) { let i = this._generatePeriodDates({ datesCount: o + 100, leftDate: A, rightDate: g, period: I, level: B, levelIndex: C, time: Q, originalLeftDate: a, format: e }); if (E) { const A = []; for (let g = 0; g < i.length; g++) { let I = i[g]; if (I) { for (let A = 0, g = Q.onDate.length; A < g; A++) I = Q.onDate[A]({ date: I, format: e, time: Q, level: B, levelIndex: C }); I && A.push(I) } } i = A } if (t) for (let A = 0, g = Q.onLevelDates.length; A < g; A++) i = Q.onLevelDates[A]({ dates: i, format: e, time: Q, level: B, levelIndex: C }); const s = []; for (const A of i) if (s.push(A), A.rightGlobal >= g.valueOf()) return s } this.addDatesToCacheLevel(C, s, Q); const c = []; for (const A of s) if (c.push(A), A.rightGlobal >= g.valueOf()) return c; return c } getDatesDiffPx(A, g, I, B = !0, C = void 0) { if (A.valueOf() === g.valueOf()) return 0; let Q, E, t = 0, i = !1; if (g.valueOf() < A.valueOf()) { const I = A; A = g, g = I, i = !0 } if (void 0 === C) { if (!I.allDates || !I.allDates.length || !I.allDates[I.level]) return 0; C = I.allDates[I.level] } if (0 === C.length) return 0; if (this.isLevelDateInCache(I.level, A.valueOf(), I) ? C = this.getAllLevelDatesFromCache(I.level, I) : A.valueOf() < C[0].leftGlobal && (C = this.addMissingDates(C, A, I)), this.isLevelDateInCache(I.level, g.valueOf(), I)) C = this.getAllLevelDatesFromCache(I.level, I); else { const A = C[C.length - 1].rightGlobalDate.clone(); g.valueOf() > A.valueOf() && (C = this.addMissingDates(C, g, I)) } this.addDatesToCacheLevel(I.level, C, I); let e = !1, o = 0; for (const I of C) if (I.rightGlobal + 1 >= A.valueOf() && !e && (e = !0, E = I), e && (t += I.width), I.rightGlobal + 1 >= g.valueOf()) { Q = I, o = I.width; break } if (B) { let B = A.valueOf() - E.leftGlobal; A.valueOf() < E.leftGlobal && (B = 0); let C = Q.rightGlobal + 1 - g.valueOf(); Q.leftGlobal > g.valueOf() && (C = Q.rightGlobal + 1 - Q.leftGlobal); const e = (C + B) / I.timePerPixel; return i ? -(t - e) : t - e } return t -= o, i ? -t : t } getDatesDiffMs(A, g, I, B = !0, C = void 0) { if (A.valueOf() === g.valueOf()) return 0; let Q, E, t = 0, i = !1; if (g.valueOf() < A.valueOf()) { const I = A; A = g, g = I, i = !0 } if (void 0 === C) { if (!I.allDates || !I.allDates.length || !I.allDates[I.level]) return 0; C = I.allDates[I.level] } if (0 === C.length) return 0; if (this.isLevelDateInCache(I.level, A.valueOf(), I) ? C = this.getAllLevelDatesFromCache(I.level, I) : A.valueOf() < C[0].leftGlobal && (C = this.addMissingDates(C, A, I)), this.isLevelDateInCache(I.level, g.valueOf(), I)) C = this.getAllLevelDatesFromCache(I.level, I); else { const A = C[C.length - 1].rightGlobalDate.clone(); g.valueOf() > A.valueOf() && (C = this.addMissingDates(C, g, I)) } this.addDatesToCacheLevel(I.level, C, I); let e = !1, o = 0; for (const I of C) if (I.rightGlobal + 1 >= A.valueOf() && !e && (e = !0, E = I), e && (t += I.rightGlobal + 1 - I.leftGlobal), I.rightGlobal + 1 >= g.valueOf()) { Q = I, o = I.rightGlobal + 1 - I.leftGlobal; break } if (B) { let I = A.valueOf() - E.leftGlobal; A.valueOf() < E.leftGlobal && (I = 0); let B = Q.rightGlobal + 1 - g.valueOf(); Q.leftGlobal > g.valueOf() && (B = Q.rightGlobal + 1 - Q.leftGlobal); const C = B + I; return i ? -(t - C) : t - C } return t -= o, i ? -t : t } addTimeFromDates(A, g, I = this.state.get("$data.chart.time")) { if (!I.allDates || !I.allDates.length || !I.allDates[I.level]) return A + g; if (!g) return A; let B = this.getAllLevelDatesFromCache(I.level, I); const C = this.date(A); B = this.addMissingDates(B, C, I, !0); let Q = this.findDateIndex(A, B), E = A - B[Q].leftGlobal; E < 0 && (E = 0); let t = 0; if (g > 0) { for (; t < g;) { const A = B[Q]; if (t += A.rightGlobal + 1 - A.leftGlobal, E && (t -= E, E = 0), t >= g) break; Q++, B[Q] || (B = this.addMissingDates(B, A.leftGlobalDate.add(1, I.period), I, !0)) } return B[Q].rightGlobal + 1 - (t - g) } for (; t > g;) { let A = B[Q]; if (t -= E, E && (E = 0), t <= g) break; if (Q--, Q < 0 && (B = this.addMissingDates(B, A.leftGlobalDate.subtract(1, I.period), I, !0), Q = 0), A = B[Q], t -= A.rightGlobal + 1 - A.leftGlobal, t <= g) break } return B[Q].leftGlobal + (-t + g) } getLeftViewDate(A = this.state.get("$data.chart.time")) { if (!A.levels || !A.levels.length) return null; const g = A.levels[A.level]; return g.length ? g[0] : null } getRightViewDate(A = this.state.get("$data.chart.time")) { if (!A.levels || !A.levels.length || !A.levels[A.level]) return null; const g = A.levels[A.level]; return g.length ? g[g.length - 1] : null } getLowerPeriod(A) { switch (A) { case "year": return "month"; case "month": case "week": return "day"; case "day": return "hour"; case "hour": return "minute"; case "minute": return "second"; case "second": return "millisecond"; default: return A } } getHigherPeriod(A) { switch (A) { case "month": return "year"; case "week": case "day": return "month"; case "hour": return "day"; case "minute": return "hour"; case "second": return "minute"; case "millisecond": return "second"; default: return A } } } /** * Gantt-Schedule-Timeline-Calendar IDApi * * @copyright NEURONET - Rafal Pospiech * @author Rafal Pospiech <neuronet.io@gmail.com> * @module gantt-schedule-timeline-calendar * @link https://github.com/neuronetio/gantt-schedule-timeline-calendar * @link https://gantt-schedule-timeline-calendar.neuronet.io * @version 3.37.5 * @released 2024-07-19 * @license SEE LICENSE IN LICENSE FILE */ var G = new class { constructor() { this.GSTCID = this.GSTCID.bind(this), this.isGSTCID = this.isGSTCID.bind(this), this.sourceID = this.sourceID.bind(this) } GSTCID(A) { return this.isGSTCID(A) ? A : `gstcid-${A}` } isGSTCID(A) { return String(A).startsWith("gstcid-") } sourceID(A) { return this.isGSTCID(A) ? A.substring(7) : A } }; /** * Gantt-Schedule-Timeline-Calendar Slots * * @copyright NEURONET - Rafal Pospiech * @author Rafal Pospiech <neuronet.io@gmail.com> * @module gantt-schedule-timeline-calendar * @link https://github.com/neuronetio/gantt-schedule-timeline-calendar * @link https://gantt-schedule-timeline-calendar.neuronet.io * @version 3.37.5 * @released 2024-07-19 * @license SEE LICENSE IN LICENSE FILE */ class d extends B { constructor(A, g, I) { super(g, I), this.subs = [], this.name = A, this.subs.push(g.state.subscribe(`config.slots.${A}`, this.setComponents, { queue: !0 })) } destroy() { this.subs.forEach((A => A())), super.destroy() } getName() { return this.name } } function M(A, g, I) { return new d(A, g, I) } /** * Gantt-Schedule-Timeline-Calendar helpers * * @copyright NEURONET - Rafal Pospiech * @author Rafal Pospiech <neuronet.io@gmail.com> * @module gantt-schedule-timeline-calendar * @link https://github.com/neuronetio/gantt-schedule-timeline-calendar * @link https://gantt-schedule-timeline-calendar.neuronet.io * @version 3.37.5 * @released 2024-07-19 * @license SEE LICENSE IN LICENSE FILE */ const N = "gstc"; function y(A, g = "") { let I = `${N}__${A}`; return A === N && (I = N), g ? `${I} ${I}--${g.replace(":","-")}` : I } function k(A, g) { let I = `${N}__${A}`; return A === N && (I = N), `${I}--${g}` } /** * Api functions * * @copyright NEURONET - Rafal Pospiech * @author Rafal Pospiech <neuronet.io@gmail.com> * @module gantt-schedule-timeline-calendar * @link https://github.com/neuronetio/gantt-schedule-timeline-calendar * @link https://gantt-schedule-timeline-calendar.neuronet.io * @version 3.37.5 * @released 2024-07-19 * @license SEE LICENSE IN LICENSE FILE */ let F = 0; const R = new Map; function Y(A) { return R.get(A.apiId) } class m { constructor(A) { this.apiId = 0, this.name = N, this.debug = !1, this.plugins = {}, this.iconsCache = {}, this.unsubscribes = [], this.mutedMethods = new Set, this.mergeDeep = null, this.generateSlots = M, this.getClass = y, this.getId = k, this.GSTCID = G.GSTCID, this.isGSTCID = G.isGSTCID, this.sourceID = G.sourceID, this.allActions = [], this.keysToKeep = ["id", "parents", "children", "allChildren", "parentId"], this.apiId = ++F, R.set(this.apiId, { rowsDataWithParentsExpanded: [], rowsIdsWithParentsExpanded: [], rowsWithParentsExpanded: [], rowsWithParentsExpandedAsMap: new Map, rowsPositionsMap: { id: "", dataIndex: 0, keys: [] }, allRowsIds: [], allRowsAsArray: [], rowsWithParentsExpandedDataIndexMap: new Map, itemsAsArray: [], itemsDataAsArray: [] }), this.state = A, this.time = new r(this.state, this), this.unsubscribes.push(this.state.subscribe("config.debug", (A => this.debug = A))), this.debug && (window.state = A) } render() { return this.vido.update() } getListenerPosition(A) { for (const g of this.state.getListeners().values()) for (const I of g.listeners) if (I[1].fn === A) return I[0] } setVido(A) { this.vido = A } clone(A) { return this.mergeDeep({}, A) } setMergeDeep(A) { this.mergeDeep = A } log(...A) { this.debug && console.log.call(console, ...A) } getInitializedPlugins() { return this.state.get("$data.initializedPlugins") } pluginInitialized(A) { this.getInitializedPlugins().add(A) } pluginDestroyed(A) { this.getInitializedPlugins().delete(A) } clearPluginsPositions() { this.getInitializedPlugins().clear() } isPluginInitialized(A) { return this.getInitializedPlugins().has(A) } getPluginPosition(A) { return [...this.getInitializedPlugins()].indexOf(A) } getPluginsPositions() { const A = {}; let g = 0; for (const I of this.getInitializedPlugins()) A[I] = g++; return A } isPluginInitializedBefore(A, g) { return this.getPluginPosition(A) < this.getPluginPosition(g) } getActions(A) { this.allActions.includes(A) || this.allActions.push(A); let g = this.state.get("config.actions." + A); return void 0 === g && (g = []), g.slice() } isItemInViewport(A, g = void 0, I = void 0) { if (!g || !I) { const A = this.state.get("config.chart.time"); g = A.leftGlobal, I = A.rightGlobal } return A.time.start <= I && A.time.end >= g } getChildrenLinkedItemsIds(A, g, I = []) { const B = g[A]; if (B.linkedWith && B.linkedWith.length) { I.includes(A) || I.push(A); for (const A of B.linkedWith) { if (I.includes(A)) continue; I.push(A); const B = g[A]; B.linkedWith && B.linkedWith.length && this.getChildrenLinkedItemsIds(A, g, I) } } return I } collectAllLinkedItems(A, g) { const I = Object.keys(A), B = Object.keys(g), C = I.filter((A => !B.includes(A))); if (C.length) throw new Error(`Items with id [${C.join(", ")}] 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).`); for (const I in A) { const B = A[I]; g[B.id].linkedWith = B.linkedWith || [] } const Q = new Map; for (const A in g) { if (Q.has(A)) continue; const I = this.getChildrenLinkedItemsIds(A, g); g[A].linkedWith.splice(g[A].linkedWith.length, 0, ...I); const B = Array.from(new Set(g[A].linkedWith)); g[A].linkedWith = B.filter((g => g !== A)), Q.set(A, !0); for (const A of B) g[A].linkedWith = B.filter((g => g !== A)), Q.set(A, !0) } } getChildrenDependantItemsIds(A, g, I = []) { if (A.dependant && A.dependant.length) for (const B of A.dependant) { if (I.includes(B)) continue; I.push(B); const C = g[B]; if (!C) throw new Error(`Dependant item not found [id:'${B}'] found in item [id:'${A.id}']`); C.dependant && C.dependant.length && this.getChildrenDependantItemsIds(C, g, I) } return I } calculateItemVerticalPosition(A, g = null, I = null, B = null) { if (B || (B = this.getItem(A)), g || (g = this.getItemData(A)), I || (I = this.getRowData(B.rowId)), B.gap && g || (this.prepareItem(B), g = this.getItemData(A)), !I) return g.position; const C = I.position.top + B.gap.top, Q = g.position.rowTop + B.gap.top, E = this.getRowViewTop(I.id); let t = E + g.position.actualRowTop; return E === 1 / 0 ? t = 1 / 0 : -1 === E && (t = -1), g.position.top = C, g.position.actualRowTop = Q, g.position.viewTop = t, g.position } setItemDataOutOfView(A, g = this.state.get("$data.chart.time")) { A.outOfView || (A.outOfView = { left: !1, right: !1, whole: !1 }); const I = A.time.startDate.valueOf(), B = A.time.endDate.valueOf(); return A.outOfView.left = I < g.leftGlobal || I >= g.rightGlobal, A.outOfView.right = B > g.rightGlobal || B <= g.leftGlobal, A.outOfView.whole = B <= g.leftGlobal || I >= g.rightGlobal, A } calculateItemHorizontalPosition(A, g = null, I = null, B = this.state.get("$data.chart.time"), C = null) { if (C || (C = this.getItem(A)), g || (g = this.getItemData(A)), I || (I = this.getRowData(C.rowId)), !I) return g.position; if (this.state.get("$data.chart.allItemsOnTheLeftOrRight")) return; const Q = g.time.startDate.valueOf() === C.time.start ? g.time.startDate : this.time.date(C.time.start), E = g.time.endDate.valueOf() === C.time.end ? g.time.endDate : this.time.date(C.time.end), t = this.time.getViewOffsetPxFromDates(Q, !1, B), i = this.time.getViewOffsetPxFromDates(E.add(1, "ms"), !1, B); g.position.left = t, g.position.actualLeft = this.time.limitOffsetPxToView(t, B), g.position.right = i, g.position.actualRight = this.time.limitOffsetPxToView(i, B), g.width = i - t; let e = this.time.getViewOffsetPxFromDates(E, !1, B); e === i && (e -= 1 / B.timePerPixel), g.timeWidth = e - t, g.actualWidth = g.position.actualRight - g.position.actualLeft; const o = this.state.get("config.chart.item.minWidth"); return "number" == typeof o && g.actualWidth < o && (g.actualWidth = o), this.setItemDataOutOfView(g, B), g.position } calculateItemPosition(A, g = null, I = null, B = this.state.get("$data.chart.time"), C = null) { return g || (g = this.state.get(`$data.chart.items.${A}`)), C || (C = this.state.get(`config.chart.items.${A}`)), I || (I = this.state.get(`$data.list.rows.${C.rowId}`)), this.calculateItemHorizontalPosition(A, g, I, B, C), this.calculateItemVerticalPosition(A, g, I, C), g.position } getItemPosition(A, g = null, I = null, B = this.state.get("$data.chart.time"), C = null) { return C || (C = this.getItem(A)), g || (g = this.getItemData(A)), 0 === g.position.left && 0 === g.position.right && this.calculateItemPosition(A, g, I, B, C), g.position } getRow(A) { return this.state.get(`config.list.rows.${A}`) } getRows(A) { if (!A.length) return []; const g = this.getAllRows(), I = []; for (const B of A) g[B] && I.push(g[B]); return I } getAllRows() { return this.state.get("config.list.rows") } getVisibleRowsId() { return this.state.get("$data.list.visibleRows") } getRowsData() { return this.state.get("$data.list.rows") } setRowsData(A) { this.state.update("$data.list.rows", A) } getRowData(A) { return this.state.get(`$data.list.rows.${A}`) } setRowData(A, g) { this.state.update(`$data.list.rows.${A}`, g) } getItem(A) { return this.state.get(`config.chart.items.${A}`) } getItems(A = []) { const g = [], I = this.getAllItems(); for (const B of A) I[B] && g.push(I[B]); return g } getAllItemsAsArray() { return Y(this).itemsAsArray } getAllItemsDataAsArray() { return Y(this).itemsDataAsArray } getAllItems() { return this.state.get("config.chart.items") } getItemData(A) { return this.state.get(`$data.chart.items.${A}`) } getItemsData() { return this.state.get("$data.chart.items") } setItemData(A, g) { this.state.update(`$data.chart.items.${A}`, (A => { for (const I in g) A[I] = g[I]; return A })) } setItemsData(A) { this.state.update("$data.chart.items", A) } prepareDependantItems(A, g) { return this.getChildrenDependantItemsIds(A, g).filter((g => g !== A.id)) } prepareItem(A, g = this.state.get("config.chart.item.height"), I = this.getItemsData(), B = this.getAllItems(), C = this.getAllRows()) { let Q = A.id; if (Q = String(Q), A.id = Q, I[A.id] || (I[A.id] = { id: A.id, actualHeight: 0, outerHeight: 0, time: null, position: { left: 0, actualLeft: 0, right: 0, actualRight: 0, rowTop: A.rowTop || 0, actualRowTop: A.actualRowTop || 0, top: 0, viewTop: 0 }, outOfView: { left: !1, right: !1, whole: !1 }, width: -1, actualWidth: -1, timeWidth: -1, detached: !1, linkedWith: [], dependant: this.getChildrenDependantItemsIds(A, B) }), A.time || console.error("There is something wrong with this item.", A), "number" != typeof A.time.start || "number" != typeof A.time.end) throw new Error('[gantt-schedule-timeline-calendar] Item "time.start" and "time.end" values should be a number (unix epoch milliseconds).'); const E = A.rowId; if ("string" != typeof E) throw new Error('[gantt-schedule-timeline-calendar] Item "rowId" should be a string.'); if (!E.startsWith("gstcid-")) throw new Error('[gantt-schedule-timeline-calendar] Item "rowId" should start with "gstcid-".'); if (!C[E]) throw new Error(`[gantt-schedule-timeline-calendar] Row for item "${A.id}" does not exists ("${E}"). TIP: Try updating the rows first to make sure the rows for the items exist.`); A.time.start = +A.time.start, A.time.end = +A.time.end, A.id = String(A.id); const t = this.state.get("config.chart.item"); "number" != typeof A.height && (A.height = g), I[A.id].time = { startDate: this.time.date(A.time.start), endDate: this.time.date(A.time.end) }, I[A.id].actualHeight = A.height, void 0 === A.overlap && (A.overlap = t.overlap), "number" != typeof A.top && (A.top = 0), A.gap || (A.gap = {}), "number" != typeof A.gap.top && (A.gap.top = t.gap.top), "number" != typeof A.gap.bottom && (A.gap.bottom = t.gap.bottom), "number" != typeof A.minWidth && (A.minWidth = t.minWidth), I[A.id].outerHeight = I[A.id].actualHeight + A.gap.top + A.gap.bottom, I[A.id].position.actualRowTop = I[A.id].position.rowTop + A.gap.top } prepareItems(A) { const g = this.state.get("config.chart.item.height"), I = this.getItemsData(), B = Y(this); B.itemsAsArray.length = 0, B.itemsDataAsArray.length = 0; for (const C in A) { const Q = A[C]; this.prepareItem(Q, g, I, A), B.itemsAsArray.push(A[C]), B.itemsDataAsArray.push(I[C]) } return this.collectAllLinkedItems(A, I), A } sortRowsByChildren(A, g = {}, I = this.state.get("config.list.rows"), B = this.state.get("$data.list.rows")) { for (const C of A) { const A = I[C], Q = B[C], E = A.parentId && g[A.parentId] || !A.parentId; !g[C] && E && (g[C] = A), Q.children.length && this.sortRowsByChildren(Q.children, g, I, B) } return g } getSortableValue(A, g) { return "string" == typeof A ? g[A] : "function" == typeof A ? A({ row: g, vido: this.vido }) : "" } sortRowsByColumn(A, g = !0) { const I = this.state.get("config.list.sort.compare"); let B = this.getAllRows(); const C = Y(this); if (0 === C.allRowsIds.length) return B; const Q = C.allRowsAsArray; I ? Q.sort(I(A)) : Q.sort(((I, B) => { const C = this.getSortableValue(A.sortable, I), Q = this.getSortableValue(A.sortable, B); return "number" == typeof C ? g ? C - Q : Q - C : "string" == typeof C ? g ? C.localeCompare(Q) : Q.localeCompare(C) : void 0 })); const E = Q.map((A => A.id)), t = this.getRowsData(); for (const A of E) { const g = t[A]; g.children && g.children.length && g.children.sort(((A, g) => E.indexOf(A) - E.indexOf(g))) } B = this.sortRowsByChildren(E), this.state.update("config.list.rows", B, { data: "sortRowsByColumn" }); const i = this.getScrollTop(); return this.state.get("config.scroll.vertical.byPixels") ? this.setScrollTop(i.absolutePosPx) : this.setScrollTop(i.dataIndex, i.preciseOffset), B } fillEmptyRowValues(A) { const g = this.state.get("config.list.row.height"), I = this.getRowsData(); let B = 0; for (let C in A) { const Q = A[C]; let E = I[C]; if (C = String(C), Q.id = C, "string" != typeof C) throw new Error('[gantt-schedule-timeline-calendar] Row "id" must be a string.'); if (!C.startsWith("gstcid-")) throw new Error(`[gantt-schedule-timeline-calendar] Row "id" should start with "gstcid-" (your row id: "${C}").`); if (C.startsWith("gstcid-gstcid-")) throw new Error(`[gantt-schedule-timeline-calendar] Your row "id" is wrapped more than once. It should look like this "gstcid-something" and it looks like this: "${C}".`); I[C] || (E = { id: Q.id, parentId: Q.parentId, parents: [], children: [], allChildren: [], position: { top: 0, bottom: 0 }, items: [], itemsOrder: [], actualHeight: 0, outerHeight: 0, parentsExpanded: !0, inView: !0 }), "number" != typeof Q.height && (Q.height = g), E.actualHeight = Q.height, "boolean" != typeof Q.expanded && (Q.expanded = !1), E.position.top = B, "object" != typeof Q.gap && (Q.gap = {}), "number" != typeof Q.gap.top && (Q.gap.top = 0), "number" != typeof Q.gap.bottom && (Q.gap.bottom = 0), void 0 === Q.visible && (Q.visible = !0), E.outerHeight = E.actualHeight + Q.gap.top + Q.gap.bottom, I[C] = E, B += E.outerHeight } return A } itemsOnTheSameLevel(A, g) { const I = this.getItemData(A.id), B = this.getItemData(g.id), C = I.position.rowTop + I.outerHeight, Q = B.position.rowTop + B.outerHeight; return B.position.rowTop <= I.position.rowTop && Q > I.position.rowTop || (B.position.rowTop >= I.position.rowTop && B.position.rowTop < C || B.position.rowTop >= I.position.rowTop && Q < C) } itemsTimeOverlaps(A, g) { return g.time.start >= A.time.start && g.time.start <= A.time.end || (g.time.end >= A.time.start && g.time.end <= A.time.end || (g.time.start >= A.time.start && g.time.end <= A.time.end || g.time.start <= A.time.start && g.time.end >= A.time.end)) } itemOverlapsWithOthers(A, g) { for (let I = 0, B = g.length; I < B; I++) { const B = g[I], C = B.time.start && A.time.start && B.time.end && A.time.end; if (A.id !== B.id && this.itemsOnTheSameLevel(A, B) && this.itemsTimeOverlaps(A, B) && C) return B } return null } fixOverlappedItems(A) { if (this.isMutedMethod("fixOverlapped")) return; if (0 === A.length) return; const g = this.getItemsData(); for (const I of A) { if (I.overlap) continue; const A = g[I.id]; A && (A.position.rowTop = I.top) } for (let I = 0; I < A.length; I++) { const B = A[I]; if (B.overlap) continue; const C = g[B.id]; if (!C) continue; C.position.actualRowTop = C.position.rowTop + B.gap.top; let Q = this.itemOverlapsWithOthers(B, A); if (Q) for (; Q = this.itemOverlapsWithOthers(B, A);) { const g = this.getItemData(Q.id), E = A.findIndex((A => A.id === Q.id)); E < I ? (C.position.rowTop += g.outerHeight, C.position.actualRowTop = C.position.rowTop + B.gap.top) : (g.position.rowTop += C.outerHeight, g.position.actualRowTop = g.position.rowTop + Q.gap.top) } } } makeChildren(A, g = { parents: [] }) { if ("object" != typeof A) return []; A.children || (A.children = []), A.allChildren || (A.allChildren = []), A.parents || (A.parents = [...g.parents]), A.parentId && "undefined" !== A.parentId && A.parents.push(A.parentId); for (const g in A) if ("id" !== g && "parentId" !== g && "children" !== g && "allChildren" !== g && "parents" !== g) { "undefined" !== g && (A.children.push(g), A.allChildren.push(g)); const I = A[g]; if ("object" != typeof I) continue; const B = this.makeChildren(I, A); A.allChildren.splice(A.allChildren.length, 0, ...B) } return A.allChildren } clearNested(A) { for (const g in A) "object" != typeof A[g] || Array.isArray(A[g]) || this.clearNested(A[g]), this.keysToKeep.includes(g) || delete A[g], "parentId" === g && "undefined" === A[g] && (A[g] = void 0); return A } fastTree(A, g = null) { var I, B; if (!g) { g = { undefined: {}, id: "undefined" }; for (const B in A) { const C = A[B]; g[C.id] || (g[C.id] = { parentId: null !== (I = C.parentId) && void 0 !== I ? I : "undefined", id: C.id }) } } for (const A in g) { const I = g[A]; g[null !== (B = I.parentId) && void 0 !== B ? B : "undefined"][I.id] = I } this.makeChildren(g[void 0]), delete g[void 0], delete g.id, delete g.parents, delete g.children, delete g.allChildren; for (const A in g) g[A] = this.clearNested(g[A]); return g } updateItemRowMapForItem(A, g, I = this.state.get("$data.itemRowMap"), B = this.state.get("$data.list.rows")) { if (!B