gantt-source_management 3.37.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintrc.json +39 -0
- package/.prettierrc.cjs +5 -0
- package/README.md +129 -0
- package/cypress/e2e/add-rows-items.test.ts +26 -0
- package/cypress/e2e/basic.test.ts +173 -0
- package/cypress/e2e/calculated-zoom-mode.test.ts +163 -0
- package/cypress/e2e/calendar-dates.test.ts +285 -0
- package/cypress/e2e/dst.test.ts +691 -0
- package/cypress/e2e/grid-cells.test.ts +72 -0
- package/cypress/e2e/items-vertical.test.ts +305 -0
- package/cypress/e2e/items.test.ts +501 -0
- package/cypress/e2e/list-columns-toggle.test.ts +124 -0
- package/cypress/e2e/list-header-resize.test.ts +30 -0
- package/cypress/e2e/locale.test.ts +102 -0
- package/cypress/e2e/move-items-outside.test.ts +437 -0
- package/cypress/e2e/rows.test.ts +50 -0
- package/cypress/e2e/scroll-bar.test.ts +357 -0
- package/cypress/e2e/time-bookmarks.test.ts +92 -0
- package/cypress/e2e/utc-mode.test.ts +51 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/helpers.ts +12 -0
- package/cypress/plugins/index.js +22 -0
- package/cypress/support/commands.ts +175 -0
- package/cypress/support/e2e.ts +31 -0
- package/cypress.config.js +24 -0
- package/dist/api/api.d.ts +182 -0
- package/dist/api/helpers.d.ts +9 -0
- package/dist/api/id.d.ts +14 -0
- package/dist/api/locale.d.ts +3 -0
- package/dist/api/main.d.ts +47 -0
- package/dist/api/public.d.ts +32 -0
- package/dist/api/slots.d.ts +22 -0
- package/dist/api/time.d.ts +104 -0
- package/dist/assets/2f1f893a.wasm +0 -0
- package/dist/gstc.d.ts +708 -0
- package/dist/gstc.esm.min.d.ts +708 -0
- package/dist/gstc.esm.min.js +574 -0
- package/dist/gstc.umd.min.d.ts +708 -0
- package/dist/gstc.umd.min.js +701 -0
- package/dist/gstc.wasm.esm.min.d.ts +708 -0
- package/dist/gstc.wasm.esm.min.js +574 -0
- package/dist/gstc.wasm.umd.min.d.ts +708 -0
- package/dist/gstc.wasm.umd.min.js +701 -0
- package/dist/plugins/calendar-scroll.d.ts +15 -0
- package/dist/plugins/calendar-scroll.esm.min.d.ts +15 -0
- package/dist/plugins/calendar-scroll.esm.min.js +13 -0
- package/dist/plugins/calendar-scroll.umd.min.d.ts +15 -0
- package/dist/plugins/calendar-scroll.umd.min.js +13 -0
- package/dist/plugins/dependency-lines.d.ts +47 -0
- package/dist/plugins/dependency-lines.esm.min.d.ts +47 -0
- package/dist/plugins/dependency-lines.esm.min.js +38 -0
- package/dist/plugins/dependency-lines.umd.min.d.ts +47 -0
- package/dist/plugins/dependency-lines.umd.min.js +38 -0
- package/dist/plugins/export-image.d.ts +12 -0
- package/dist/plugins/export-image.esm.min.d.ts +12 -0
- package/dist/plugins/export-image.esm.min.js +28 -0
- package/dist/plugins/export-image.umd.min.d.ts +12 -0
- package/dist/plugins/export-image.umd.min.js +34 -0
- package/dist/plugins/export-pdf.d.ts +12 -0
- package/dist/plugins/export-pdf.esm.min.d.ts +12 -0
- package/dist/plugins/export-pdf.esm.min.js +389 -0
- package/dist/plugins/export-pdf.umd.min.d.ts +12 -0
- package/dist/plugins/export-pdf.umd.min.js +511 -0
- package/dist/plugins/grab-scroll.d.ts +14 -0
- package/dist/plugins/grab-scroll.esm.min.d.ts +14 -0
- package/dist/plugins/grab-scroll.umd.min.d.ts +14 -0
- package/dist/plugins/highlight-weekends.d.ts +12 -0
- package/dist/plugins/highlight-weekends.esm.min.d.ts +12 -0
- package/dist/plugins/highlight-weekends.esm.min.js +14 -0
- package/dist/plugins/highlight-weekends.umd.min.d.ts +12 -0
- package/dist/plugins/highlight-weekends.umd.min.js +14 -0
- package/dist/plugins/item-movement.d.ts +97 -0
- package/dist/plugins/item-movement.esm.min.d.ts +97 -0
- package/dist/plugins/item-movement.esm.min.js +25 -0
- package/dist/plugins/item-movement.umd.min.d.ts +97 -0
- package/dist/plugins/item-movement.umd.min.js +25 -0
- package/dist/plugins/item-resizing.d.ts +102 -0
- package/dist/plugins/item-resizing.esm.min.d.ts +102 -0
- package/dist/plugins/item-resizing.esm.min.js +37 -0
- package/dist/plugins/item-resizing.umd.min.d.ts +102 -0
- package/dist/plugins/item-resizing.umd.min.js +37 -0
- package/dist/plugins/item-types.d.ts +13 -0
- package/dist/plugins/item-types.esm.min.d.ts +13 -0
- package/dist/plugins/item-types.esm.min.js +127 -0
- package/dist/plugins/item-types.umd.min.d.ts +13 -0
- package/dist/plugins/item-types.umd.min.js +127 -0
- package/dist/plugins/progress-bar.d.ts +13 -0
- package/dist/plugins/progress-bar.esm.min.d.ts +13 -0
- package/dist/plugins/progress-bar.esm.min.js +27 -0
- package/dist/plugins/progress-bar.umd.min.d.ts +13 -0
- package/dist/plugins/progress-bar.umd.min.js +27 -0
- package/dist/plugins/selection.d.ts +94 -0
- package/dist/plugins/selection.esm.min.d.ts +94 -0
- package/dist/plugins/selection.esm.min.js +26 -0
- package/dist/plugins/selection.umd.min.d.ts +94 -0
- package/dist/plugins/selection.umd.min.js +26 -0
- package/dist/plugins/time-bookmarks.d.ts +38 -0
- package/dist/plugins/time-bookmarks.esm.min.d.ts +38 -0
- package/dist/plugins/time-bookmarks.esm.min.js +50 -0
- package/dist/plugins/time-bookmarks.umd.min.d.ts +38 -0
- package/dist/plugins/time-bookmarks.umd.min.js +50 -0
- package/dist/plugins/timeline-pointer.d.ts +83 -0
- package/dist/plugins/timeline-pointer.esm.min.d.ts +83 -0
- package/dist/plugins/timeline-pointer.esm.min.js +13 -0
- package/dist/plugins/timeline-pointer.umd.min.d.ts +83 -0
- package/dist/plugins/timeline-pointer.umd.min.js +13 -0
- package/dist/style.css +811 -0
- package/dist/vendor.esm.min.js +128 -0
- package/examples/complex-1/faces/face-1.jpg +0 -0
- package/examples/complex-1/faces/face-10.jpg +0 -0
- package/examples/complex-1/faces/face-11.jpg +0 -0
- package/examples/complex-1/faces/face-12.jpg +0 -0
- package/examples/complex-1/faces/face-13.jpg +0 -0
- package/examples/complex-1/faces/face-14.jpg +0 -0
- package/examples/complex-1/faces/face-15.jpg +0 -0
- package/examples/complex-1/faces/face-16.jpg +0 -0
- package/examples/complex-1/faces/face-17.jpg +0 -0
- package/examples/complex-1/faces/face-18.jpg +0 -0
- package/examples/complex-1/faces/face-19.jpg +0 -0
- package/examples/complex-1/faces/face-2.jpg +0 -0
- package/examples/complex-1/faces/face-20.jpg +0 -0
- package/examples/complex-1/faces/face-21.jpg +0 -0
- package/examples/complex-1/faces/face-22.jpg +0 -0
- package/examples/complex-1/faces/face-23.jpg +0 -0
- package/examples/complex-1/faces/face-24.jpg +0 -0
- package/examples/complex-1/faces/face-25.jpg +0 -0
- package/examples/complex-1/faces/face-26.jpg +0 -0
- package/examples/complex-1/faces/face-27.jpg +0 -0
- package/examples/complex-1/faces/face-28.jpg +0 -0
- package/examples/complex-1/faces/face-29.jpg +0 -0
- package/examples/complex-1/faces/face-3.jpg +0 -0
- package/examples/complex-1/faces/face-30.jpg +0 -0
- package/examples/complex-1/faces/face-31.jpg +0 -0
- package/examples/complex-1/faces/face-32.jpg +0 -0
- package/examples/complex-1/faces/face-33.jpg +0 -0
- package/examples/complex-1/faces/face-34.jpg +0 -0
- package/examples/complex-1/faces/face-35.jpg +0 -0
- package/examples/complex-1/faces/face-36.jpg +0 -0
- package/examples/complex-1/faces/face-37.jpg +0 -0
- package/examples/complex-1/faces/face-38.jpg +0 -0
- package/examples/complex-1/faces/face-39.jpg +0 -0
- package/examples/complex-1/faces/face-4.jpg +0 -0
- package/examples/complex-1/faces/face-40.jpg +0 -0
- package/examples/complex-1/faces/face-41.jpg +0 -0
- package/examples/complex-1/faces/face-42.jpg +0 -0
- package/examples/complex-1/faces/face-43.jpg +0 -0
- package/examples/complex-1/faces/face-44.jpg +0 -0
- package/examples/complex-1/faces/face-45.jpg +0 -0
- package/examples/complex-1/faces/face-46.jpg +0 -0
- package/examples/complex-1/faces/face-47.jpg +0 -0
- package/examples/complex-1/faces/face-48.jpg +0 -0
- package/examples/complex-1/faces/face-49.jpg +0 -0
- package/examples/complex-1/faces/face-5.jpg +0 -0
- package/examples/complex-1/faces/face-50.jpg +0 -0
- package/examples/complex-1/faces/face-6.jpg +0 -0
- package/examples/complex-1/faces/face-7.jpg +0 -0
- package/examples/complex-1/faces/face-8.jpg +0 -0
- package/examples/complex-1/faces/face-9.jpg +0 -0
- package/examples/complex-1/index.html +61 -0
- package/examples/complex-1/index.js +923 -0
- package/examples/index.html +22 -0
- package/examples/reset.css +455 -0
- package/examples/server.js +18 -0
- package/package.json +150 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
import GSTC from '../../dist/gstc.wasm.esm.min.js';
|
|
2
|
+
import { Plugin as TimelinePointer } from '../../dist/plugins/timeline-pointer.esm.min.js';
|
|
3
|
+
import { Plugin as Selection } from '../../dist/plugins/selection.esm.min.js';
|
|
4
|
+
import { Plugin as ItemMovement } from '../../dist/plugins/item-movement.esm.min.js';
|
|
5
|
+
import { Plugin as ItemResizing } from '../../dist/plugins/item-resizing.esm.min.js';
|
|
6
|
+
import { Plugin as CalendarScroll } from '../../dist/plugins/calendar-scroll.esm.min.js';
|
|
7
|
+
import { Plugin as HighlightWeekends } from '../../dist/plugins/highlight-weekends.esm.min.js';
|
|
8
|
+
import { Plugin as ProgressBar } from '../../dist/plugins/progress-bar.esm.min.js';
|
|
9
|
+
import { Plugin as TimeBookmarks } from '../../dist/plugins/time-bookmarks.esm.min.js';
|
|
10
|
+
import { Plugin as DependencyLines } from '../../dist/plugins/dependency-lines.esm.min.js';
|
|
11
|
+
import { Plugin as ExportImage } from '../../dist/plugins/export-image.esm.min.js';
|
|
12
|
+
import { Plugin as ExportPDF } from '../../dist/plugins/export-pdf.esm.min.js';
|
|
13
|
+
|
|
14
|
+
globalThis.GSTC = GSTC;
|
|
15
|
+
|
|
16
|
+
const iterations = 100;
|
|
17
|
+
const GSTCID = GSTC.api.GSTCID;
|
|
18
|
+
const addDays = 30;
|
|
19
|
+
|
|
20
|
+
function getRandomFaceImage() {
|
|
21
|
+
return `./faces/face-${Math.ceil(Math.random() * 50)}.jpg`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const colors = ['#E74C3C', '#DA3C78', '#7E349D', '#0077C0', '#07ABA0', '#0EAC51', '#F1892D'];
|
|
25
|
+
function getRandomColor() {
|
|
26
|
+
return colors[Math.floor(Math.random() * colors.length)];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const startDate = GSTC.api.date('2020-02-01');
|
|
30
|
+
const startTime = startDate.valueOf();
|
|
31
|
+
const endDate = GSTC.api.date('2020-03-31').endOf('day');
|
|
32
|
+
|
|
33
|
+
function getInitialRows() {
|
|
34
|
+
/**
|
|
35
|
+
* @type {import("../../dist/gstc").Rows}
|
|
36
|
+
*/
|
|
37
|
+
const rows = {};
|
|
38
|
+
for (let i = 0; i < iterations; i++) {
|
|
39
|
+
const withParent = i > 0 && i % 2 === 0;
|
|
40
|
+
const id = GSTCID(String(i));
|
|
41
|
+
rows[id] = {
|
|
42
|
+
id,
|
|
43
|
+
label: `John Doe ${i}`,
|
|
44
|
+
parentId: withParent ? GSTCID(String(i - 1)) : undefined,
|
|
45
|
+
expanded: false,
|
|
46
|
+
vacations: [],
|
|
47
|
+
img: getRandomFaceImage(),
|
|
48
|
+
progress: Math.floor(Math.random() * 100),
|
|
49
|
+
visible: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
rows[GSTCID('11')].label = 'NESTED TREE HERE';
|
|
54
|
+
rows[GSTCID('12')].parentId = GSTCID('11');
|
|
55
|
+
rows[GSTCID('13')].parentId = GSTCID('12');
|
|
56
|
+
rows[GSTCID('14')].parentId = GSTCID('13');
|
|
57
|
+
rows[GSTCID('3')].vacations = [
|
|
58
|
+
{ from: startDate.add(5, 'days').startOf('day').valueOf(), to: startDate.add(5, 'days').endOf('day').valueOf() },
|
|
59
|
+
{ from: startDate.add(6, 'days').startOf('day').valueOf(), to: startDate.add(6, 'days').endOf('day').valueOf() },
|
|
60
|
+
];
|
|
61
|
+
rows[GSTCID('7')].birthday = [
|
|
62
|
+
{
|
|
63
|
+
from: startDate.add(3, 'day').startOf('day').valueOf(),
|
|
64
|
+
to: startDate.add(3, 'day').endOf('day').valueOf(),
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
return rows;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function generateItemsForDaysView() {
|
|
71
|
+
/**
|
|
72
|
+
* @type {import("../../dist/gstc").Items}
|
|
73
|
+
*/
|
|
74
|
+
const items = {};
|
|
75
|
+
for (let i = 0; i < iterations; i++) {
|
|
76
|
+
let rowId = GSTCID(i.toString());
|
|
77
|
+
let id = GSTCID(i.toString());
|
|
78
|
+
let startDayjs = GSTC.api
|
|
79
|
+
.date(startTime)
|
|
80
|
+
.startOf('day')
|
|
81
|
+
.add(Math.floor(Math.random() * addDays), 'day');
|
|
82
|
+
let end = startDayjs
|
|
83
|
+
.clone()
|
|
84
|
+
.add(Math.floor(Math.random() * 20) + 4, 'day')
|
|
85
|
+
.endOf('day')
|
|
86
|
+
.valueOf();
|
|
87
|
+
if (end > endDate.valueOf()) end = endDate.valueOf();
|
|
88
|
+
items[id] = {
|
|
89
|
+
id,
|
|
90
|
+
label: `John Doe ${i}`,
|
|
91
|
+
progress: Math.round(Math.random() * 100),
|
|
92
|
+
style: { background: getRandomColor() },
|
|
93
|
+
time: {
|
|
94
|
+
start: startDayjs.startOf('day').valueOf(),
|
|
95
|
+
end,
|
|
96
|
+
},
|
|
97
|
+
rowId,
|
|
98
|
+
img: getRandomFaceImage(),
|
|
99
|
+
classNames: ['additional-custom-class'],
|
|
100
|
+
description: 'Lorem ipsum dolor sit amet',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
items[GSTCID('0')].linkedWith = [GSTCID('1')];
|
|
105
|
+
items[GSTCID('0')].label = 'Task 0 linked with 1';
|
|
106
|
+
items[GSTCID('0')].type = 'task';
|
|
107
|
+
items[GSTCID('1')].label = 'Task 1 linked with 0';
|
|
108
|
+
items[GSTCID('1')].type = 'task';
|
|
109
|
+
items[GSTCID('1')].time = { ...items[GSTCID('0')].time };
|
|
110
|
+
|
|
111
|
+
items[GSTCID('0')].style = { background: colors[3] };
|
|
112
|
+
items[GSTCID('1')].style = { background: colors[3] };
|
|
113
|
+
|
|
114
|
+
items[GSTCID('3')].dependant = [GSTCID('5')];
|
|
115
|
+
items[GSTCID('3')].label = 'Grab and move me into vacation area';
|
|
116
|
+
items[GSTCID('3')].time.start = GSTC.api.date(startTime).add(4, 'day').startOf('day').add(5, 'day').valueOf();
|
|
117
|
+
items[GSTCID('3')].time.end = GSTC.api.date(items[GSTCID('3')].time.start).endOf('day').add(5, 'day').valueOf();
|
|
118
|
+
|
|
119
|
+
items[GSTCID('5')].time.start = GSTC.api.date(items[GSTCID('3')].time.end).startOf('day').add(5, 'day').valueOf();
|
|
120
|
+
items[GSTCID('5')].time.end = GSTC.api.date(items[GSTCID('5')].time.start).endOf('day').add(2, 'day').valueOf();
|
|
121
|
+
items[GSTCID('5')].dependant = [GSTCID('7'), GSTCID('9')];
|
|
122
|
+
|
|
123
|
+
items[GSTCID('7')].time.start = GSTC.api.date(items[GSTCID('5')].time.end).startOf('day').add(3, 'day').valueOf();
|
|
124
|
+
items[GSTCID('7')].time.end = GSTC.api.date(items[GSTCID('7')].time.start).endOf('day').add(2, 'day').valueOf();
|
|
125
|
+
items[GSTCID('9')].time.start = GSTC.api.date(items[GSTCID('5')].time.end).startOf('day').add(2, 'day').valueOf();
|
|
126
|
+
items[GSTCID('9')].time.end = GSTC.api.date(items[GSTCID('9')].time.start).endOf('day').add(3, 'day').valueOf();
|
|
127
|
+
return items;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const columns = {
|
|
131
|
+
data: {
|
|
132
|
+
[GSTCID('id')]: {
|
|
133
|
+
id: GSTCID('id'),
|
|
134
|
+
data: ({ row }) => GSTC.api.sourceID(row.id),
|
|
135
|
+
width: 80,
|
|
136
|
+
sortable: ({ row }) => Number(GSTC.api.sourceID(row.id)),
|
|
137
|
+
header: {
|
|
138
|
+
content: 'ID',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
[GSTCID('label')]: {
|
|
142
|
+
id: GSTCID('label'),
|
|
143
|
+
data: 'label',
|
|
144
|
+
sortable: 'label',
|
|
145
|
+
expander: true,
|
|
146
|
+
isHTML: false,
|
|
147
|
+
width: 315,
|
|
148
|
+
header: {
|
|
149
|
+
content: 'Label',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
[GSTCID('progress')]: {
|
|
153
|
+
id: GSTCID('progress'),
|
|
154
|
+
data({ row, vido }) {
|
|
155
|
+
return vido.html`<div style="text-align:center">${row.progress}</div>`;
|
|
156
|
+
},
|
|
157
|
+
width: 100,
|
|
158
|
+
sortable: 'progress',
|
|
159
|
+
header: {
|
|
160
|
+
content: 'Progress',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @type {import("../../dist/plugins/time-bookmarks").Bookmarks}
|
|
168
|
+
*/
|
|
169
|
+
const bookmarks = {};
|
|
170
|
+
for (let i = 0; i < 3; i++) {
|
|
171
|
+
const id = `Bookmark ${i}`;
|
|
172
|
+
bookmarks[id] = {
|
|
173
|
+
time: startDate
|
|
174
|
+
.add(Math.round(Math.random() * addDays), 'day')
|
|
175
|
+
.startOf('day')
|
|
176
|
+
.valueOf(),
|
|
177
|
+
label: id,
|
|
178
|
+
style: {
|
|
179
|
+
background: getRandomColor(),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function itemSlot(vido, props) {
|
|
185
|
+
const { html, onChange, update } = vido;
|
|
186
|
+
|
|
187
|
+
let imageSrc = '';
|
|
188
|
+
let description = '';
|
|
189
|
+
onChange((newProps) => {
|
|
190
|
+
props = newProps;
|
|
191
|
+
if (!props || !props.item) return;
|
|
192
|
+
imageSrc = props.item.img;
|
|
193
|
+
description = props.item.description;
|
|
194
|
+
update();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
return (content) =>
|
|
198
|
+
html`<div
|
|
199
|
+
class="item-image"
|
|
200
|
+
style="background:url(${imageSrc}),transparent;flex-shrink:0;border-radius:100%;width:34px;height:34px;vertical-align: middle;background-size: 100%;margin: 4px 11px 0px 0px;"
|
|
201
|
+
></div>
|
|
202
|
+
<div class="item-text">
|
|
203
|
+
<div class="item-label">${content}</div>
|
|
204
|
+
<div class="item-description" style="font-size:11px;margin-top:2px;color:#fffffff0;line-height:1em;">
|
|
205
|
+
${description}
|
|
206
|
+
</div>
|
|
207
|
+
</div>`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function rowSlot(vido, props) {
|
|
211
|
+
const { html, onChange, update, api } = vido;
|
|
212
|
+
|
|
213
|
+
let img = '';
|
|
214
|
+
onChange((newProps) => {
|
|
215
|
+
props = newProps;
|
|
216
|
+
if (!props || !props.row) return;
|
|
217
|
+
img = props.row.img;
|
|
218
|
+
update();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return (content) => {
|
|
222
|
+
if (!props || !props.column) return content;
|
|
223
|
+
return api.sourceID(props.column.id) === 'label'
|
|
224
|
+
? html`<div class="row-content-wrapper" style="display:flex">
|
|
225
|
+
<div class="row-content" style="flex-grow:1;">${content}</div>
|
|
226
|
+
<div
|
|
227
|
+
class="row-image"
|
|
228
|
+
style="background:url(${img}),transparent;border-radius:100%;width:34px;height:34px;vertical-align: middle;background-size: 100%;margin: auto 10px;flex-shrink:0;"
|
|
229
|
+
></div>
|
|
230
|
+
</div>`
|
|
231
|
+
: content;
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let snapTime = true;
|
|
236
|
+
function snapStart({ startTime, vido }) {
|
|
237
|
+
if (!snapTime) return startTime;
|
|
238
|
+
const date = vido.api.time.findOrCreateMainDateAtTime(startTime.valueOf());
|
|
239
|
+
return date.leftGlobalDate;
|
|
240
|
+
}
|
|
241
|
+
function snapEnd({ endTime, vido }) {
|
|
242
|
+
if (!snapTime) return endTime;
|
|
243
|
+
const date = vido.api.time.findOrCreateMainDateAtTime(endTime.valueOf());
|
|
244
|
+
return date.rightGlobalDate;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function canMove(item) {
|
|
248
|
+
const row = gstc.api.getRow(item.rowId);
|
|
249
|
+
if (row.vacations) {
|
|
250
|
+
for (const vacation of row.vacations) {
|
|
251
|
+
const vacationStart = vacation.from;
|
|
252
|
+
const vacationEnd = vacation.to;
|
|
253
|
+
// item start time inside vacation
|
|
254
|
+
if (item.time.start >= vacationStart && item.time.start <= vacationEnd) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
// item end time inside vacation
|
|
258
|
+
if (item.time.end >= vacationStart && item.time.end <= vacationEnd) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
// vacation is between item start and end
|
|
262
|
+
if (item.time.start <= vacationStart && item.time.end >= vacationEnd) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
// item start and end time is inside vacation
|
|
266
|
+
if (item.time.start >= vacationStart && item.time.end <= vacationEnd) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @type {import('../../dist/plugins/item-movement').Options}
|
|
276
|
+
*/
|
|
277
|
+
const itemMovementOptions = {
|
|
278
|
+
threshold: {
|
|
279
|
+
horizontal: 25,
|
|
280
|
+
vertical: 25,
|
|
281
|
+
},
|
|
282
|
+
snapToTime: {
|
|
283
|
+
start: snapStart,
|
|
284
|
+
end({ endTime }) {
|
|
285
|
+
return endTime;
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
events: {
|
|
289
|
+
onMove({ items }) {
|
|
290
|
+
for (let i = 0, len = items.after.length; i < len; i++) {
|
|
291
|
+
const item = items.after[i];
|
|
292
|
+
if (!canMove(item)) return items.before;
|
|
293
|
+
}
|
|
294
|
+
return items.after;
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @type {import('../../dist/plugins/item-resizing').Options}
|
|
301
|
+
*/
|
|
302
|
+
const itemResizeOptions = {
|
|
303
|
+
threshold: 25,
|
|
304
|
+
snapToTime: {
|
|
305
|
+
start: snapStart,
|
|
306
|
+
end: snapEnd,
|
|
307
|
+
},
|
|
308
|
+
events: {
|
|
309
|
+
onResize({ items }) {
|
|
310
|
+
for (const item of items.after) {
|
|
311
|
+
if (!canMove(item)) return items.before;
|
|
312
|
+
}
|
|
313
|
+
return items.after;
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
let hideWeekends = false;
|
|
319
|
+
function onLevelDates({ dates, level, format, time }) {
|
|
320
|
+
if (time.period !== 'day') return dates;
|
|
321
|
+
if (format.period !== time.period) return dates;
|
|
322
|
+
if (!hideWeekends) return dates;
|
|
323
|
+
return dates.filter((date) => date.leftGlobalDate.day() !== 0 && date.leftGlobalDate.day() !== 6);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function onItemClick(ev) {
|
|
327
|
+
const itemElement = ev.target.closest('.gstc__chart-timeline-items-row-item');
|
|
328
|
+
const itemId = itemElement.dataset.gstcid;
|
|
329
|
+
const item = gstc.api.getItem(itemId);
|
|
330
|
+
console.log('Item click from template', item);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Typescript usage:
|
|
334
|
+
// import { Template } from 'gantt-schedule-timeline-calendar';
|
|
335
|
+
// const chartTimelineItemsRowItemTemplate: Template = function chartTimelineItemsRowItemTemplate(...);
|
|
336
|
+
/**
|
|
337
|
+
* @type {import("../../dist/gstc").Template} // or {import("gantt-schedule-timeline-calendar").Template}
|
|
338
|
+
*/
|
|
339
|
+
function chartTimelineItemsRowItemTemplate({
|
|
340
|
+
className,
|
|
341
|
+
labelClassName,
|
|
342
|
+
styleMap,
|
|
343
|
+
cache,
|
|
344
|
+
shouldDetach,
|
|
345
|
+
cutterLeft,
|
|
346
|
+
cutterRight,
|
|
347
|
+
getContent,
|
|
348
|
+
actions,
|
|
349
|
+
slots,
|
|
350
|
+
html,
|
|
351
|
+
vido,
|
|
352
|
+
props,
|
|
353
|
+
}) {
|
|
354
|
+
const detach = shouldDetach || !props || !props.item;
|
|
355
|
+
return cache(
|
|
356
|
+
detach
|
|
357
|
+
? null
|
|
358
|
+
: slots.html(
|
|
359
|
+
'outer',
|
|
360
|
+
html`
|
|
361
|
+
<div
|
|
362
|
+
class=${className}
|
|
363
|
+
data-gstcid=${props.item.id}
|
|
364
|
+
data-actions=${actions()}
|
|
365
|
+
style=${styleMap.directive()}
|
|
366
|
+
@click=${onItemClick}
|
|
367
|
+
>
|
|
368
|
+
${slots.html(
|
|
369
|
+
'inner',
|
|
370
|
+
html`
|
|
371
|
+
${cutterLeft()}
|
|
372
|
+
<div class=${labelClassName}>${slots.html('content', getContent())}</div>
|
|
373
|
+
${cutterRight()}
|
|
374
|
+
`
|
|
375
|
+
)}
|
|
376
|
+
</div>
|
|
377
|
+
`
|
|
378
|
+
)
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function myItemSlot(vido, props) {
|
|
383
|
+
const { onChange } = vido;
|
|
384
|
+
|
|
385
|
+
function onClick() {
|
|
386
|
+
console.log('Item click from slot', props.item);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
onChange((changedProps) => {
|
|
390
|
+
// if current element is reused to display other item data just update your data so when you click you will display right alert
|
|
391
|
+
props = changedProps;
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// return render function
|
|
395
|
+
return (content) =>
|
|
396
|
+
vido.html`<div class="my-item-wrapper" @click=${onClick} style="width:100%;display:flex;overflow:hidden;pointer-events:none;">${content}</div>`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function onCellCreateVacation({ time, row, vido, content }) {
|
|
400
|
+
if (!row.vacations) return content;
|
|
401
|
+
let isVacation = false;
|
|
402
|
+
for (const vacation of row.vacations) {
|
|
403
|
+
if (time.leftGlobal >= vacation.from && time.rightGlobal <= vacation.to) {
|
|
404
|
+
isVacation = true;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (isVacation) {
|
|
409
|
+
return vido.html`<div title="🏖️ VACATION" style="height:100%;width:100%;background:#A0A0A010;"></div>${content}`;
|
|
410
|
+
}
|
|
411
|
+
return content;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function myVacationRowSlot(vido, props) {
|
|
415
|
+
const { onChange, html, update, api, state } = vido;
|
|
416
|
+
|
|
417
|
+
let vacationContent = [];
|
|
418
|
+
onChange((changedProps) => {
|
|
419
|
+
props = changedProps;
|
|
420
|
+
if (!props || !props.row || !props.row.vacations) {
|
|
421
|
+
vacationContent = [];
|
|
422
|
+
return update();
|
|
423
|
+
}
|
|
424
|
+
const configTime = state.get('config.chart.time');
|
|
425
|
+
vacationContent = [];
|
|
426
|
+
for (const vacation of props.row.vacations) {
|
|
427
|
+
if (vacation.to < configTime.leftGlobal || vacation.from > configTime.rightGlobal) continue; // birthday date is out of the current view
|
|
428
|
+
const leftPx = api.time.getViewOffsetPxFromDates(api.time.date(vacation.from));
|
|
429
|
+
const rightPx = api.time.getViewOffsetPxFromDates(api.time.date(vacation.to));
|
|
430
|
+
const widthPx = rightPx - leftPx - 1;
|
|
431
|
+
if (widthPx < 0) continue;
|
|
432
|
+
let textAlign = 'left';
|
|
433
|
+
if (widthPx <= 100) textAlign = 'center';
|
|
434
|
+
vacationContent.push(
|
|
435
|
+
html`<div
|
|
436
|
+
style="position:absolute;left:${leftPx}px;width:${widthPx}px;height:14px;white-space: nowrap;text-overflow:ellipsis;overflow:hidden;font-size:11px;background:#A0A0A0;color:white;text-align:${textAlign};"
|
|
437
|
+
>
|
|
438
|
+
Vacation
|
|
439
|
+
</div>`
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
update();
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
return (content) => html`${vacationContent}${content}`;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function onCellCreateBirthday({ time, row, vido, content }) {
|
|
449
|
+
if (!row.birthday) return content;
|
|
450
|
+
let isBirthday = false;
|
|
451
|
+
for (const birthday of row.birthday) {
|
|
452
|
+
if (time.leftGlobal >= birthday.from && time.rightGlobal <= birthday.to) {
|
|
453
|
+
isBirthday = true;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (isBirthday) {
|
|
458
|
+
return vido.html`<div title="🎁 BIRTHDAY" style="height:100%;width:100%;font-size:18px;background:#F9B32F10;"></div>${content}`;
|
|
459
|
+
}
|
|
460
|
+
return content;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function myBirthdayRowSlot(vido, props) {
|
|
464
|
+
const { onChange, html, update, api, state } = vido;
|
|
465
|
+
|
|
466
|
+
let birthdayContent = [];
|
|
467
|
+
onChange((changedProps) => {
|
|
468
|
+
props = changedProps;
|
|
469
|
+
if (!props || !props.row || !props.row.birthday) {
|
|
470
|
+
birthdayContent = [];
|
|
471
|
+
return update();
|
|
472
|
+
}
|
|
473
|
+
const configTime = state.get('config.chart.time');
|
|
474
|
+
birthdayContent = [];
|
|
475
|
+
for (const birthday of props.row.birthday) {
|
|
476
|
+
if (birthday.to < configTime.leftGlobal || birthday.from > configTime.rightGlobal) continue; // birthday date is out of the current view
|
|
477
|
+
const leftPx = api.time.getViewOffsetPxFromDates(api.time.date(birthday.from));
|
|
478
|
+
const rightPx = api.time.getViewOffsetPxFromDates(api.time.date(birthday.to));
|
|
479
|
+
const widthPx = rightPx - leftPx - 1;
|
|
480
|
+
if (widthPx < 0) continue;
|
|
481
|
+
let textAlign = 'left';
|
|
482
|
+
if (widthPx <= 100) textAlign = 'center';
|
|
483
|
+
birthdayContent.push(
|
|
484
|
+
html`<div
|
|
485
|
+
style="position:absolute;left:${leftPx}px;width:${widthPx}px;height:14px;white-space: nowrap;text-overflow:ellipsis;overflow:hidden;font-size:11px;background:#F9B32F;color:white;text-align:${textAlign};"
|
|
486
|
+
>
|
|
487
|
+
🎁 Birthday
|
|
488
|
+
</div>`
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
update();
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
return (content) => html`${birthdayContent}${content}`;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Typescript usage:
|
|
498
|
+
// import { Config } from 'gantt-schedule-timeline-calendar';
|
|
499
|
+
// const config: Config = {...};
|
|
500
|
+
/**
|
|
501
|
+
* @type {import("../../dist/gstc").Config} // or {import("gantt-schedule-timeline-calendar").Config}
|
|
502
|
+
*/
|
|
503
|
+
const config = {
|
|
504
|
+
licenseKey:
|
|
505
|
+
'====BEGIN LICENSE KEY====\nXOfH/lnVASM6et4Co473t9jPIvhmQ/l0X3Ewog30VudX6GVkOB0n3oDx42NtADJ8HjYrhfXKSNu5EMRb5KzCLvMt/pu7xugjbvpyI1glE7Ha6E5VZwRpb4AC8T1KBF67FKAgaI7YFeOtPFROSCKrW5la38jbE5fo+q2N6wAfEti8la2ie6/7U2V+SdJPqkm/mLY/JBHdvDHoUduwe4zgqBUYLTNUgX6aKdlhpZPuHfj2SMeB/tcTJfH48rN1mgGkNkAT9ovROwI7ReLrdlHrHmJ1UwZZnAfxAC3ftIjgTEHsd/f+JrjW6t+kL6Ef1tT1eQ2DPFLJlhluTD91AsZMUg==||U2FsdGVkX1/SWWqU9YmxtM0T6Nm5mClKwqTaoF9wgZd9rNw2xs4hnY8Ilv8DZtFyNt92xym3eB6WA605N5llLm0D68EQtU9ci1rTEDopZ1ODzcqtTVSoFEloNPFSfW6LTIC9+2LSVBeeHXoLEQiLYHWihHu10Xll3KsH9iBObDACDm1PT7IV4uWvNpNeuKJc\npY3C5SG+3sHRX1aeMnHlKLhaIsOdw2IexjvMqocVpfRpX4wnsabNA0VJ3k95zUPS3vTtSegeDhwbl6j+/FZcGk9i+gAy6LuetlKuARjPYn2LH5Be3Ah+ggSBPlxf3JW9rtWNdUoFByHTcFlhzlU9HnpnBUrgcVMhCQ7SAjN9h2NMGmCr10Rn4OE0WtelNqYVig7KmENaPvFT+k2I0cYZ4KWwxxsQNKbjEAxJxrzK4HkaczCvyQbzj4Ppxx/0q+Cns44OeyWcwYD/vSaJm4Kptwpr+L4y5BoSO/WeqhSUQQ85nvOhtE0pSH/ZXYo3pqjPdQRfNm6NFeBl2lwTmZUEuw==\n====END LICENSE KEY====',
|
|
506
|
+
innerHeight: 700,
|
|
507
|
+
//autoInnerHeight: true,
|
|
508
|
+
plugins: [
|
|
509
|
+
HighlightWeekends(),
|
|
510
|
+
TimelinePointer(), // timeline pointer must go first before selection, resizing and movement
|
|
511
|
+
Selection({
|
|
512
|
+
events: {
|
|
513
|
+
onEnd(selected) {
|
|
514
|
+
console.log('Selected', selected);
|
|
515
|
+
return selected;
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
}),
|
|
519
|
+
ItemResizing(itemResizeOptions), // resizing must fo before movement
|
|
520
|
+
ItemMovement(itemMovementOptions),
|
|
521
|
+
CalendarScroll(),
|
|
522
|
+
ProgressBar(),
|
|
523
|
+
TimeBookmarks({
|
|
524
|
+
bookmarks,
|
|
525
|
+
}),
|
|
526
|
+
DependencyLines({
|
|
527
|
+
onLine: [
|
|
528
|
+
(line) => {
|
|
529
|
+
line.type = GSTC.api.sourceID(line.fromItem.id) === '3' ? 'smooth' : 'square';
|
|
530
|
+
return line;
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
}),
|
|
534
|
+
ExportImage(),
|
|
535
|
+
ExportPDF(),
|
|
536
|
+
],
|
|
537
|
+
list: {
|
|
538
|
+
row: {
|
|
539
|
+
height: 68,
|
|
540
|
+
},
|
|
541
|
+
rows: getInitialRows(),
|
|
542
|
+
columns,
|
|
543
|
+
},
|
|
544
|
+
chart: {
|
|
545
|
+
time: {
|
|
546
|
+
from: startDate.valueOf(),
|
|
547
|
+
to: endDate.valueOf(),
|
|
548
|
+
onLevelDates: [onLevelDates],
|
|
549
|
+
},
|
|
550
|
+
item: {
|
|
551
|
+
height: 50,
|
|
552
|
+
gap: {
|
|
553
|
+
top: 14,
|
|
554
|
+
//bottom: 0,
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
items: generateItemsForDaysView(),
|
|
558
|
+
grid: {
|
|
559
|
+
cell: {
|
|
560
|
+
onCreate: [onCellCreateVacation, onCellCreateBirthday],
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
scroll: {
|
|
565
|
+
vertical: { precise: true, byPixels: true },
|
|
566
|
+
horizontal: { precise: true, byPixels: true },
|
|
567
|
+
},
|
|
568
|
+
slots: {
|
|
569
|
+
'chart-timeline-items-row-item': { content: [itemSlot], inner: [myItemSlot] },
|
|
570
|
+
'list-column-row': { content: [rowSlot] },
|
|
571
|
+
'chart-timeline-grid-row': { content: [myBirthdayRowSlot, myVacationRowSlot] },
|
|
572
|
+
},
|
|
573
|
+
templates: {
|
|
574
|
+
'chart-timeline-items-row-item': chartTimelineItemsRowItemTemplate,
|
|
575
|
+
},
|
|
576
|
+
//utcMode: true,
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
let gstc;
|
|
580
|
+
let state;
|
|
581
|
+
function mountGSTC() {
|
|
582
|
+
state = GSTC.api.stateFromConfig(config);
|
|
583
|
+
const element = document.createElement('div');
|
|
584
|
+
element.id = 'gstc';
|
|
585
|
+
document.querySelector('#toolbox')?.after(element);
|
|
586
|
+
gstc = GSTC({
|
|
587
|
+
element,
|
|
588
|
+
state,
|
|
589
|
+
});
|
|
590
|
+
//@ts-ignore
|
|
591
|
+
globalThis.state = state;
|
|
592
|
+
//@ts-ignore
|
|
593
|
+
globalThis.gstc = gstc;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
mountGSTC();
|
|
597
|
+
|
|
598
|
+
// TOOLBOX BUTTONS
|
|
599
|
+
|
|
600
|
+
// Select first two cells
|
|
601
|
+
function selectCells() {
|
|
602
|
+
const api = gstc.api;
|
|
603
|
+
const allCells = api.getGridCells();
|
|
604
|
+
api.plugins.Selection.selectCells([allCells[0].id, allCells[1].id]);
|
|
605
|
+
console.log(api.plugins.Selection.getSelection());
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// scroll to first item
|
|
609
|
+
function scrollToFirstItem() {
|
|
610
|
+
const api = gstc.api;
|
|
611
|
+
const firstItem = gstc.state.get(`config.chart.items.${api.GSTCID('1')}`);
|
|
612
|
+
api.scrollToTime(firstItem.time.start, false);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
globalThis.scrollToFirstItem = scrollToFirstItem;
|
|
616
|
+
|
|
617
|
+
function downloadImage() {
|
|
618
|
+
gstc.api.plugins.ExportImage.download();
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
async function downloadPdf() {
|
|
622
|
+
await gstc.api.plugins.ExportPDF.download('timeline.pdf');
|
|
623
|
+
console.log('PDF downloaded');
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
async function takeShotPdf() {
|
|
627
|
+
const img = await gstc.api.plugins.ExportPDF.takeShot();
|
|
628
|
+
console.log('PDF shot taken', img);
|
|
629
|
+
alert(
|
|
630
|
+
`\nScreenshot taken\n\nYou can add more screenshots and then download them all together with "Get screenshots" button.`
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
async function getPdf() {
|
|
635
|
+
await gstc.api.plugins.ExportPDF.getPDF('timeline.pdf');
|
|
636
|
+
await gstc.api.plugins.ExportPDF.clearPDF(); // don't forget to clear pdf after you are done with it
|
|
637
|
+
console.log('PDF downloaded');
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function downloadPdfFull() {
|
|
641
|
+
gstc.api.plugins.ExportPDF.downloadFull('timeline.pdf');
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
let darkModeEnabled = false;
|
|
645
|
+
function toggleDarkMode(ev) {
|
|
646
|
+
darkModeEnabled = ev.target.checked;
|
|
647
|
+
const el = document.getElementById('gstc');
|
|
648
|
+
if (darkModeEnabled) {
|
|
649
|
+
el?.classList.add('gstc--dark');
|
|
650
|
+
document.body.classList.add('gstc--dark');
|
|
651
|
+
} else {
|
|
652
|
+
el?.classList.remove('gstc--dark');
|
|
653
|
+
document.body.classList.remove('gstc--dark');
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function toggleHideWeekends(ev) {
|
|
658
|
+
hideWeekends = ev.target.checked;
|
|
659
|
+
gstc.api.time.recalculateTime();
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function toggleSnapTime(ev) {
|
|
663
|
+
snapTime = ev.target.checked;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function toggleExpandTime(ev) {
|
|
667
|
+
const expandTime = ev.target.checked;
|
|
668
|
+
const moveOutEl = document.getElementById('move-out');
|
|
669
|
+
if (moveOutEl && expandTime) {
|
|
670
|
+
// @ts-ignore
|
|
671
|
+
moveOutEl.checked = expandTime;
|
|
672
|
+
toggleMoveOut({ target: moveOutEl });
|
|
673
|
+
}
|
|
674
|
+
state.update('config.chart.time.autoExpandTimeFromItems', expandTime);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function toggleMoveOut(ev) {
|
|
678
|
+
const moveOut = ev.target.checked;
|
|
679
|
+
const expandTimeEl = document.getElementById('expand-time');
|
|
680
|
+
if (expandTimeEl && !moveOut) {
|
|
681
|
+
// @ts-ignore
|
|
682
|
+
expandTimeEl.checked = moveOut;
|
|
683
|
+
toggleExpandTime({ target: expandTimeEl });
|
|
684
|
+
}
|
|
685
|
+
state.update('config.plugin.ItemMovement.allowItemsToGoOutsideTheArea', moveOut);
|
|
686
|
+
state.update('config.plugin.ItemResizing.allowItemsToGoOutsideTheArea', moveOut);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function zoomChangeSelect(ev) {
|
|
690
|
+
const period = ev.target.value;
|
|
691
|
+
let zoom = 20;
|
|
692
|
+
let from = gstc.api.time.date('2020-02-01').startOf('day').valueOf();
|
|
693
|
+
let to = gstc.api.time.date('2020-03-01').endOf('month').valueOf();
|
|
694
|
+
switch (period) {
|
|
695
|
+
case 'hours':
|
|
696
|
+
zoom = 16;
|
|
697
|
+
from = gstc.api.time.date('2020-02-01').startOf('day').valueOf();
|
|
698
|
+
to = gstc.api.time.date('2020-03-01').endOf('month').valueOf();
|
|
699
|
+
break;
|
|
700
|
+
case 'days':
|
|
701
|
+
zoom = 20;
|
|
702
|
+
from = gstc.api.time.date('2020-02-01').startOf('day').valueOf();
|
|
703
|
+
to = gstc.api.time.date('2020-03-01').endOf('month').valueOf();
|
|
704
|
+
break;
|
|
705
|
+
case 'weeks':
|
|
706
|
+
zoom = 23;
|
|
707
|
+
from = gstc.api.time.date('2020-02-01').startOf('day').valueOf();
|
|
708
|
+
to = gstc.api.time.date('2020-08-01').endOf('month').valueOf();
|
|
709
|
+
break;
|
|
710
|
+
case 'months':
|
|
711
|
+
zoom = 26;
|
|
712
|
+
from = gstc.api.time.date('2020-01-01').startOf('day').valueOf();
|
|
713
|
+
to = gstc.api.time.date('2024-01-10').endOf('year').valueOf();
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
state.update('config.chart.time', (time) => {
|
|
718
|
+
time.zoom = zoom;
|
|
719
|
+
time.from = from;
|
|
720
|
+
time.to = to;
|
|
721
|
+
return time;
|
|
722
|
+
});
|
|
723
|
+
const zoomRange = document.getElementById('zoom-range');
|
|
724
|
+
//@ts-ignore
|
|
725
|
+
if (zoomRange) zoomRange.value = zoom;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
function zoomChangeRange(ev) {
|
|
729
|
+
const zoom = Number(ev.target.value);
|
|
730
|
+
let period = 'days';
|
|
731
|
+
let from = gstc.api.time.date('2020-02-01').startOf('day');
|
|
732
|
+
let to = gstc.api.time.date('2020-03-01').endOf('month');
|
|
733
|
+
|
|
734
|
+
if (zoom >= 16) {
|
|
735
|
+
period = 'hours';
|
|
736
|
+
from = gstc.api.time.date('2020-02-01').startOf('day');
|
|
737
|
+
to = gstc.api.time.date('2020-03-01').endOf('month');
|
|
738
|
+
}
|
|
739
|
+
if (zoom >= 20) {
|
|
740
|
+
period = 'days';
|
|
741
|
+
from = gstc.api.time.date('2020-02-01').startOf('day');
|
|
742
|
+
to = gstc.api.time.date('2020-03-01').endOf('month');
|
|
743
|
+
}
|
|
744
|
+
if (zoom >= 20) {
|
|
745
|
+
period = 'weeks';
|
|
746
|
+
from = gstc.api.time.date('2020-02-01').startOf('day');
|
|
747
|
+
to = gstc.api.time.date('2020-08-01').endOf('month');
|
|
748
|
+
}
|
|
749
|
+
if (zoom >= 23) {
|
|
750
|
+
period = 'months';
|
|
751
|
+
from = gstc.api.time.date('2020-01-01').startOf('day');
|
|
752
|
+
to = gstc.api.time.date('2024-01-10').endOf('year');
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
gstc.state.update('config.chart.time', (time) => {
|
|
756
|
+
time.zoom = zoom;
|
|
757
|
+
time.from = from.valueOf();
|
|
758
|
+
time.to = to.valueOf();
|
|
759
|
+
return time;
|
|
760
|
+
});
|
|
761
|
+
const zoomSelect = document.getElementById('zoom');
|
|
762
|
+
// @ts-ignore
|
|
763
|
+
if (zoomSelect) zoomSelect.value = period;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function searchRows(event) {
|
|
767
|
+
const copiedRows = getInitialRows();
|
|
768
|
+
const search = String(event.target.value).trim();
|
|
769
|
+
console.log('search', search);
|
|
770
|
+
const regex = new RegExp(`[\s\S]?${search}[\s\S]?`, 'gi');
|
|
771
|
+
const rowsToKeep = [];
|
|
772
|
+
for (const rowId in copiedRows) {
|
|
773
|
+
const row = copiedRows[rowId];
|
|
774
|
+
const rowData = gstc.api.getRowData(rowId);
|
|
775
|
+
if (regex.test(row.label)) {
|
|
776
|
+
rowsToKeep.push(rowId);
|
|
777
|
+
for (const childRowId of rowData.allChildren) {
|
|
778
|
+
rowsToKeep.push(childRowId);
|
|
779
|
+
}
|
|
780
|
+
for (const parentRowId of rowData.parents) {
|
|
781
|
+
rowsToKeep.push(parentRowId);
|
|
782
|
+
if (search) copiedRows[parentRowId].expanded = true;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
regex.lastIndex = 0;
|
|
786
|
+
}
|
|
787
|
+
const uniqueRowsToKeep = [...new Set(rowsToKeep)]; // js way to get only unique row id's- we don't want duplicates here
|
|
788
|
+
for (const rowId in copiedRows) {
|
|
789
|
+
if (uniqueRowsToKeep.includes(rowId)) {
|
|
790
|
+
copiedRows[rowId].visible = true;
|
|
791
|
+
} else {
|
|
792
|
+
copiedRows[rowId].visible = false;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
state.update('config.list.rows', (currentRows) => {
|
|
796
|
+
return copiedRows;
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const historyStates = [];
|
|
801
|
+
globalThis.historyStates = historyStates;
|
|
802
|
+
let currentStateName = '';
|
|
803
|
+
function saveCurrentState(stateName) {
|
|
804
|
+
const items = GSTC.api.merge({}, state.get('config.chart.items'));
|
|
805
|
+
historyStates.push({ name: stateName, state: items });
|
|
806
|
+
currentStateName = stateName;
|
|
807
|
+
updateToolBox();
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function restoreState(stateName) {
|
|
811
|
+
const historyState = historyStates.find((s) => s.name == stateName);
|
|
812
|
+
currentStateName = stateName;
|
|
813
|
+
const clonedState = GSTC.api.merge({}, historyState.state);
|
|
814
|
+
state.update('config.chart.items', clonedState);
|
|
815
|
+
updateToolBox();
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function onRestoreStateChange(ev) {
|
|
819
|
+
const name = ev.target.value;
|
|
820
|
+
restoreState(name);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function openSaveCurrentStateDialog() {
|
|
824
|
+
const stateName = prompt('Enter current state name');
|
|
825
|
+
saveCurrentState(stateName);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
function deleteSelectedItems() {
|
|
829
|
+
const selectedItems = gstc.api.plugins.Selection.getSelected()['chart-timeline-items-row-item']; // cloned items
|
|
830
|
+
gstc.api.plugins.Selection.selectItems([]); // clear selection
|
|
831
|
+
state.update('config.plugin.Selection.lastSelecting.chart-timeline-items-row-item', []);
|
|
832
|
+
state.update('config.chart.items', (items) => {
|
|
833
|
+
for (const item of selectedItems) {
|
|
834
|
+
delete items[item.id];
|
|
835
|
+
}
|
|
836
|
+
return items;
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const html = GSTC.lithtml.html;
|
|
841
|
+
|
|
842
|
+
function updateToolBox() {
|
|
843
|
+
const searchBoxHTML = html`<input type="text" @input=${searchRows} placeholder="Search" />`;
|
|
844
|
+
const historyStateHTML = html`<button @click="${openSaveCurrentStateDialog}">Save items</button>
|
|
845
|
+
<label>Restore items:</label>
|
|
846
|
+
<select @change=${onRestoreStateChange}>
|
|
847
|
+
${historyStates.map(
|
|
848
|
+
(historyState) =>
|
|
849
|
+
html`<option value=${historyState.name} ?selected=${historyState.name === currentStateName}>
|
|
850
|
+
${historyState.name}
|
|
851
|
+
</option>`
|
|
852
|
+
)}
|
|
853
|
+
</select>`;
|
|
854
|
+
|
|
855
|
+
const toolboxButtons = html` <div class="toolbox-row">
|
|
856
|
+
<div class="toolbox-item"><button @click=${selectCells}>Select first cells</button></div>
|
|
857
|
+
<div class="toolbox-item"><button @click=${scrollToFirstItem}>Scroll to first item</button></div>
|
|
858
|
+
<div class="toolbox-item"><button @click=${downloadImage}>Download image</button></div>
|
|
859
|
+
<div class="toolbox-item"><button @click=${downloadPdf}>PDF (current view)</button></div>
|
|
860
|
+
<div class="toolbox-item"><button @click=${downloadPdfFull}>PDF (full)</button></div>
|
|
861
|
+
<div class="toolbox-item"><button @click=${takeShotPdf}>Take screenshot</button></div>
|
|
862
|
+
<div class="toolbox-item">-></div>
|
|
863
|
+
<div class="toolbox-item"><button @click=${getPdf}>Get screenshots</button></div>
|
|
864
|
+
<div class="toolbox-item">${historyStateHTML}</div>
|
|
865
|
+
<div class="toolbox-item">
|
|
866
|
+
<label>Zoom:</label>
|
|
867
|
+
<select @change="${zoomChangeSelect}" id="zoom">
|
|
868
|
+
<option value="hours">Hours</option>
|
|
869
|
+
<option value="days" selected>Days</option>
|
|
870
|
+
<option value="weeks">Weeks</option>
|
|
871
|
+
<option value="months">Months</option>
|
|
872
|
+
</select>
|
|
873
|
+
</div>
|
|
874
|
+
<div class="toolbox-item">
|
|
875
|
+
<button @click=${deleteSelectedItems}>Delete selected items</button>
|
|
876
|
+
</div>
|
|
877
|
+
</div>
|
|
878
|
+
<div class="toolbox-row">
|
|
879
|
+
<div class="toolbox-item">${searchBoxHTML}</div>
|
|
880
|
+
<div class="toolbox-item">
|
|
881
|
+
<input type="checkbox" id="dark-mode" @change=${toggleDarkMode} /> <label for="dark-mode">Dark mode</label>
|
|
882
|
+
</div>
|
|
883
|
+
<div class="toolbox-item">
|
|
884
|
+
<input type="checkbox" id="snap-time" @change=${toggleSnapTime} checked />
|
|
885
|
+
<label for="snap-time">Snap time (item movement)</label>
|
|
886
|
+
</div>
|
|
887
|
+
<div class="toolbox-item">
|
|
888
|
+
<input type="checkbox" id="hide-weekends" @change=${toggleHideWeekends} />
|
|
889
|
+
<label for="hide-weekends">Hide weekends</label>
|
|
890
|
+
</div>
|
|
891
|
+
<div class="toolbox-item">
|
|
892
|
+
<input type="checkbox" id="expand-time" @change=${toggleExpandTime} />
|
|
893
|
+
<label for="expand-time">Expand view when item is outside</label>
|
|
894
|
+
</div>
|
|
895
|
+
<div class="toolbox-item">
|
|
896
|
+
<input type="checkbox" id="move-out" @change=${toggleMoveOut} checked />
|
|
897
|
+
<label for="move-out">Alow items to move outside area</label>
|
|
898
|
+
</div>
|
|
899
|
+
<div class="toolbox-item">
|
|
900
|
+
<label for="zoom">Zoom:</label>
|
|
901
|
+
<input
|
|
902
|
+
id="zoom-range"
|
|
903
|
+
type="range"
|
|
904
|
+
min="16"
|
|
905
|
+
max="26"
|
|
906
|
+
value="20"
|
|
907
|
+
step="0.1"
|
|
908
|
+
@change=${zoomChangeRange}
|
|
909
|
+
style="width:200px"
|
|
910
|
+
/>
|
|
911
|
+
</div>
|
|
912
|
+
</div>
|
|
913
|
+
</div>`;
|
|
914
|
+
// @ts-ignore
|
|
915
|
+
GSTC.lithtml.render(toolboxButtons, document.getElementById('toolbox'));
|
|
916
|
+
}
|
|
917
|
+
updateToolBox();
|
|
918
|
+
|
|
919
|
+
const gstcEl = document.getElementById('gstc');
|
|
920
|
+
gstcEl?.addEventListener('gstc-loaded', () => {
|
|
921
|
+
console.log('GSTC loaded!');
|
|
922
|
+
saveCurrentState('Initial');
|
|
923
|
+
});
|