@operato/gantt 7.0.20 → 7.0.22
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/CHANGELOG.md +20 -0
- package/dist/src/draw-time-scale-header.d.ts +5 -0
- package/dist/src/draw-time-scale-header.js +154 -0
- package/dist/src/draw-time-scale-header.js.map +1 -0
- package/dist/src/gantt-chart-controller.d.ts +1 -1
- package/dist/src/gantt-chart-controller.js +6 -161
- package/dist/src/gantt-chart-controller.js.map +1 -1
- package/dist/src/ox-gantt-chart.d.ts +6 -1
- package/dist/src/ox-gantt-chart.js +39 -8
- package/dist/src/ox-gantt-chart.js.map +1 -1
- package/dist/src/ox-gantt-resize-splitter.js +8 -7
- package/dist/src/ox-gantt-resize-splitter.js.map +1 -1
- package/dist/src/ox-gantt.d.ts +24 -15
- package/dist/src/ox-gantt.js +224 -82
- package/dist/src/ox-gantt.js.map +1 -1
- package/dist/src/ox-resource-chart.d.ts +42 -0
- package/dist/src/ox-resource-chart.js +317 -0
- package/dist/src/ox-resource-chart.js.map +1 -0
- package/dist/src/types.d.ts +5 -0
- package/dist/src/types.js.map +1 -1
- package/dist/stories/ox-gantt.stories.js +75 -4
- package/dist/stories/ox-gantt.stories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/draw-time-scale-header.ts +192 -0
- package/src/gantt-chart-controller.ts +6 -189
- package/src/ox-gantt-chart.ts +46 -9
- package/src/ox-gantt-resize-splitter.ts +8 -7
- package/src/ox-gantt.ts +231 -86
- package/src/ox-resource-chart.ts +328 -0
- package/src/types.ts +6 -0
- package/stories/ox-gantt.stories.ts +75 -4
- package/translations/en.json +4 -1
- package/translations/ja.json +3 -1
- package/translations/ko.json +4 -1
- package/translations/ms.json +3 -1
- package/translations/zh.json +3 -1
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html, css } from 'lit';
|
|
3
|
+
import { customElement, property, query } from 'lit/decorators.js';
|
|
4
|
+
import * as d3 from 'd3';
|
|
5
|
+
import { ScrollbarStyles } from '@operato/styles';
|
|
6
|
+
import { drawTimeScaleHeader } from './draw-time-scale-header';
|
|
7
|
+
let OxResourceChart = class OxResourceChart extends LitElement {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.fromDate = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0];
|
|
11
|
+
this.toDate = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0];
|
|
12
|
+
this.axisScale = 'week-day';
|
|
13
|
+
this.resources = [];
|
|
14
|
+
this.tasks = [];
|
|
15
|
+
this.baseWidth = 30;
|
|
16
|
+
this.level = 'week-day';
|
|
17
|
+
}
|
|
18
|
+
static { this.styles = [
|
|
19
|
+
ScrollbarStyles,
|
|
20
|
+
css `
|
|
21
|
+
:host {
|
|
22
|
+
display: flex;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
div[chart-container] {
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-direction: column;
|
|
30
|
+
|
|
31
|
+
overflow-x: auto;
|
|
32
|
+
overflow-y: auto;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
svg[header] {
|
|
36
|
+
display: block;
|
|
37
|
+
min-width: 100%;
|
|
38
|
+
box-sizing: border-box;
|
|
39
|
+
border-bottom: 1px solid var(--ox-gantt-header-border-color, var(--md-sys-color-on-secondary-container));
|
|
40
|
+
height: 40px;
|
|
41
|
+
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
42
|
+
color: var(--ox-gantt-header-color, var(--md-sys-color-on-secondary-container));
|
|
43
|
+
position: sticky;
|
|
44
|
+
top: 0;
|
|
45
|
+
z-index: 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
svg[body] {
|
|
49
|
+
flex: 1;
|
|
50
|
+
display: block;
|
|
51
|
+
min-width: 100%;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.top-axis text,
|
|
55
|
+
.bottom-axis text {
|
|
56
|
+
font-size: 12px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.grid line {
|
|
60
|
+
stroke: #e0e0e0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.grid path {
|
|
64
|
+
stroke-width: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.no-select {
|
|
68
|
+
user-select: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.selected {
|
|
72
|
+
stroke-width: 2px;
|
|
73
|
+
stroke: var(--ox-gantt-selected-color, blue);
|
|
74
|
+
}
|
|
75
|
+
`
|
|
76
|
+
]; }
|
|
77
|
+
render() {
|
|
78
|
+
return html `
|
|
79
|
+
<div chart-container>
|
|
80
|
+
<svg header></svg>
|
|
81
|
+
<svg body></svg>
|
|
82
|
+
</div>
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
updated(changedProperties) {
|
|
86
|
+
if (changedProperties.has('fromDate') || changedProperties.has('toDate') || changedProperties.has('axisScale')) {
|
|
87
|
+
this.updateTimeScale();
|
|
88
|
+
}
|
|
89
|
+
if (changedProperties.has('resources') || changedProperties.has('tasks')) {
|
|
90
|
+
this.drawBody();
|
|
91
|
+
}
|
|
92
|
+
this.drawAxes();
|
|
93
|
+
}
|
|
94
|
+
updateTimeScale() {
|
|
95
|
+
this.fromTime = new Date(this.fromDate);
|
|
96
|
+
this.toTime = new Date(this.toDate);
|
|
97
|
+
this.timeScale = d3
|
|
98
|
+
.scaleTime()
|
|
99
|
+
.domain([d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1)])
|
|
100
|
+
.range([0, this.getChartWidth()]);
|
|
101
|
+
}
|
|
102
|
+
getChartWidth() {
|
|
103
|
+
const totalDays = d3.timeDay.count(new Date(this.fromDate), d3.timeDay.offset(new Date(this.toDate), 1));
|
|
104
|
+
return (totalDays * this.baseWidth) / this.getScale();
|
|
105
|
+
}
|
|
106
|
+
getScale() {
|
|
107
|
+
if (this.level == 'quarter-week') {
|
|
108
|
+
return 7 / 2;
|
|
109
|
+
}
|
|
110
|
+
else if (this.level == 'year-month') {
|
|
111
|
+
return 30 / 2;
|
|
112
|
+
}
|
|
113
|
+
else if (this.level === 'year-quarter') {
|
|
114
|
+
return 90 / 2;
|
|
115
|
+
}
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
drawAxes() {
|
|
119
|
+
drawTimeScaleHeader(this.svgHeader, this.timeScale, this.fromTime, this.toTime, this.baseWidth, this.level);
|
|
120
|
+
}
|
|
121
|
+
drawBody() {
|
|
122
|
+
const body = d3.select(this.svgBody);
|
|
123
|
+
body.selectAll('*').remove();
|
|
124
|
+
body.attr('width', this.getChartWidth());
|
|
125
|
+
if (this.resources.length > 0) {
|
|
126
|
+
const chartHeight = this.resources.length * 30;
|
|
127
|
+
const addVerticalGridLines = (ticks) => {
|
|
128
|
+
ticks.forEach(tick => {
|
|
129
|
+
const startX = this.timeScale(tick);
|
|
130
|
+
body
|
|
131
|
+
.append('line')
|
|
132
|
+
.attr('x1', startX)
|
|
133
|
+
.attr('x2', startX)
|
|
134
|
+
.attr('y1', 0)
|
|
135
|
+
.attr('y2', chartHeight) // Ensure vertical lines extend to the bottom
|
|
136
|
+
.attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
|
|
137
|
+
.attr('stroke-width', 1);
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
const addHorizontalGridLines = () => {
|
|
141
|
+
this.resources.forEach((_, index) => {
|
|
142
|
+
const y = (index + 1) * 30;
|
|
143
|
+
body
|
|
144
|
+
.append('line')
|
|
145
|
+
.attr('x1', 0)
|
|
146
|
+
.attr('x2', this.getChartWidth())
|
|
147
|
+
.attr('y1', y)
|
|
148
|
+
.attr('y2', y)
|
|
149
|
+
.attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
|
|
150
|
+
.attr('stroke-width', 1);
|
|
151
|
+
});
|
|
152
|
+
// Ensure the last horizontal line extends to the bottom of the chart
|
|
153
|
+
body
|
|
154
|
+
.append('line')
|
|
155
|
+
.attr('x1', 0)
|
|
156
|
+
.attr('x2', this.getChartWidth())
|
|
157
|
+
.attr('y1', chartHeight)
|
|
158
|
+
.attr('y2', chartHeight)
|
|
159
|
+
.attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
|
|
160
|
+
.attr('stroke-width', 1);
|
|
161
|
+
};
|
|
162
|
+
let ticks;
|
|
163
|
+
if (this.level === 'week-day') {
|
|
164
|
+
ticks = d3.timeDay
|
|
165
|
+
.every(1)
|
|
166
|
+
.range(d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1));
|
|
167
|
+
}
|
|
168
|
+
else if (this.level === 'quarter-week') {
|
|
169
|
+
ticks = d3.timeWeek
|
|
170
|
+
.every(1)
|
|
171
|
+
.range(d3.timeWeek.floor(new Date(this.fromDate)), d3.timeWeek.offset(new Date(this.toDate), 1));
|
|
172
|
+
}
|
|
173
|
+
else if (this.level === 'year-month') {
|
|
174
|
+
ticks = d3.timeMonth
|
|
175
|
+
.every(1)
|
|
176
|
+
.range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 1));
|
|
177
|
+
}
|
|
178
|
+
else if (this.level === 'year-quarter') {
|
|
179
|
+
ticks = d3.timeMonth
|
|
180
|
+
.every(3)
|
|
181
|
+
.range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 3));
|
|
182
|
+
}
|
|
183
|
+
addVerticalGridLines(ticks);
|
|
184
|
+
addHorizontalGridLines();
|
|
185
|
+
// Render the resource allocations
|
|
186
|
+
this.renderResourceAllocations(body, ticks);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
renderResourceAllocations(body, ticks) {
|
|
190
|
+
const resourceAllocations = this.calculateResourceAllocations(ticks);
|
|
191
|
+
this.resources.forEach((resource, index) => {
|
|
192
|
+
const y = index * 30 + 15; // Center the text vertically in the row
|
|
193
|
+
ticks.forEach(tick => {
|
|
194
|
+
const tickEnd = this.getTickEnd(tick);
|
|
195
|
+
const dateKey = this.formatDateKey(tick, tickEnd);
|
|
196
|
+
const allocation = resourceAllocations[resource.type][dateKey];
|
|
197
|
+
if (allocation > 0) {
|
|
198
|
+
const startX = this.timeScale(tick);
|
|
199
|
+
const tickInterval = this.timeScale(tickEnd) - startX;
|
|
200
|
+
body
|
|
201
|
+
.append('text')
|
|
202
|
+
.attr('x', startX + tickInterval / 2)
|
|
203
|
+
.attr('y', y)
|
|
204
|
+
.attr('text-anchor', 'middle')
|
|
205
|
+
.attr('alignment-baseline', 'middle')
|
|
206
|
+
.attr('dominant-baseline', 'middle')
|
|
207
|
+
.text(allocation)
|
|
208
|
+
.style('font-size', '12px');
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
calculateResourceAllocations(ticks) {
|
|
214
|
+
const resourceAllocations = {};
|
|
215
|
+
// Initialize the resourceAllocations object
|
|
216
|
+
this.resources.forEach(resource => {
|
|
217
|
+
resourceAllocations[resource.type] = {};
|
|
218
|
+
ticks.forEach(tick => {
|
|
219
|
+
const tickEnd = this.getTickEnd(tick);
|
|
220
|
+
const dateKey = this.formatDateKey(tick, tickEnd);
|
|
221
|
+
resourceAllocations[resource.type][dateKey] = 0;
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
// Function to process tasks recursively
|
|
225
|
+
const processTask = (task) => {
|
|
226
|
+
const startDate = new Date(task.startDate);
|
|
227
|
+
const endDate = new Date(task.endDate);
|
|
228
|
+
let currentDate = startDate;
|
|
229
|
+
while (currentDate <= endDate) {
|
|
230
|
+
const tick = ticks.find(t => currentDate >= t && currentDate < this.getTickEnd(t));
|
|
231
|
+
if (tick) {
|
|
232
|
+
const tickEnd = this.getTickEnd(tick);
|
|
233
|
+
const dateKey = this.formatDateKey(tick, tickEnd);
|
|
234
|
+
(task.resources || []).forEach(resource => {
|
|
235
|
+
if (resourceAllocations[resource.type][dateKey] !== undefined) {
|
|
236
|
+
resourceAllocations[resource.type][dateKey] += resource.allocated;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
currentDate.setDate(currentDate.getDate() + 1);
|
|
241
|
+
}
|
|
242
|
+
// Recursively process child tasks
|
|
243
|
+
if (task.children) {
|
|
244
|
+
task.children.forEach(childTask => processTask(childTask));
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
// Process all tasks
|
|
248
|
+
this.tasks.forEach(task => processTask(task));
|
|
249
|
+
return resourceAllocations;
|
|
250
|
+
}
|
|
251
|
+
getTickEnd(tick) {
|
|
252
|
+
if (this.level === 'week-day') {
|
|
253
|
+
return d3.timeDay.offset(tick, 1);
|
|
254
|
+
}
|
|
255
|
+
else if (this.level === 'quarter-week') {
|
|
256
|
+
return d3.timeWeek.offset(tick, 1);
|
|
257
|
+
}
|
|
258
|
+
else if (this.level === 'year-month') {
|
|
259
|
+
return d3.timeMonth.offset(tick, 1);
|
|
260
|
+
}
|
|
261
|
+
else if (this.level === 'year-quarter') {
|
|
262
|
+
return d3.timeMonth.offset(tick, 3);
|
|
263
|
+
}
|
|
264
|
+
return d3.timeDay.offset(tick, 1);
|
|
265
|
+
}
|
|
266
|
+
formatDateKey(start, end) {
|
|
267
|
+
return `${start.toISOString().split('T')[0]}_${end.toISOString().split('T')[0]}`;
|
|
268
|
+
}
|
|
269
|
+
syncTimeScale(detail) {
|
|
270
|
+
this.baseWidth = detail.baseWidth;
|
|
271
|
+
this.level = detail.level;
|
|
272
|
+
this.updateTimeScale();
|
|
273
|
+
this.drawAxes();
|
|
274
|
+
this.drawBody();
|
|
275
|
+
}
|
|
276
|
+
setVerticalOffset(offset) {
|
|
277
|
+
this.container.scrollTop = offset;
|
|
278
|
+
}
|
|
279
|
+
getVerticalOffset() {
|
|
280
|
+
return this.container.scrollTop;
|
|
281
|
+
}
|
|
282
|
+
setHorizontalOffset(offset) {
|
|
283
|
+
this.container.scrollLeft = offset;
|
|
284
|
+
}
|
|
285
|
+
getHorizontalOffset() {
|
|
286
|
+
return this.container.scrollLeft;
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
__decorate([
|
|
290
|
+
property({ type: String })
|
|
291
|
+
], OxResourceChart.prototype, "fromDate", void 0);
|
|
292
|
+
__decorate([
|
|
293
|
+
property({ type: String })
|
|
294
|
+
], OxResourceChart.prototype, "toDate", void 0);
|
|
295
|
+
__decorate([
|
|
296
|
+
property({ type: String })
|
|
297
|
+
], OxResourceChart.prototype, "axisScale", void 0);
|
|
298
|
+
__decorate([
|
|
299
|
+
property({ type: Array })
|
|
300
|
+
], OxResourceChart.prototype, "resources", void 0);
|
|
301
|
+
__decorate([
|
|
302
|
+
property({ type: Array })
|
|
303
|
+
], OxResourceChart.prototype, "tasks", void 0);
|
|
304
|
+
__decorate([
|
|
305
|
+
query('[chart-container')
|
|
306
|
+
], OxResourceChart.prototype, "container", void 0);
|
|
307
|
+
__decorate([
|
|
308
|
+
query('svg[header]')
|
|
309
|
+
], OxResourceChart.prototype, "svgHeader", void 0);
|
|
310
|
+
__decorate([
|
|
311
|
+
query('svg[body]')
|
|
312
|
+
], OxResourceChart.prototype, "svgBody", void 0);
|
|
313
|
+
OxResourceChart = __decorate([
|
|
314
|
+
customElement('ox-resource-chart')
|
|
315
|
+
], OxResourceChart);
|
|
316
|
+
export { OxResourceChart };
|
|
317
|
+
//# sourceMappingURL=ox-resource-chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-resource-chart.js","sourceRoot":"","sources":["../../src/ox-resource-chart.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, PropertyValues } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport * as d3 from 'd3'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { drawTimeScaleHeader } from './draw-time-scale-header'\nimport { Task, TimeScale } from './types'\n\n@customElement('ox-resource-chart')\nexport class OxResourceChart extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n overflow: hidden;\n position: relative;\n }\n\n div[chart-container] {\n display: flex;\n flex-direction: column;\n\n overflow-x: auto;\n overflow-y: auto;\n }\n\n svg[header] {\n display: block;\n min-width: 100%;\n box-sizing: border-box;\n border-bottom: 1px solid var(--ox-gantt-header-border-color, var(--md-sys-color-on-secondary-container));\n height: 40px;\n background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));\n color: var(--ox-gantt-header-color, var(--md-sys-color-on-secondary-container));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n svg[body] {\n flex: 1;\n display: block;\n min-width: 100%;\n }\n\n .top-axis text,\n .bottom-axis text {\n font-size: 12px;\n }\n\n .grid line {\n stroke: #e0e0e0;\n }\n\n .grid path {\n stroke-width: 0;\n }\n\n .no-select {\n user-select: none;\n }\n\n .selected {\n stroke-width: 2px;\n stroke: var(--ox-gantt-selected-color, blue);\n }\n `\n ]\n\n @property({ type: String }) fromDate: string = new Date(new Date().getFullYear(), 0, 1).toISOString().split('T')[0]\n @property({ type: String }) toDate: string = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0]\n @property({ type: String }) axisScale: string = 'week-day'\n @property({ type: Array }) resources: any[] = []\n @property({ type: Array }) tasks: Task[] = []\n\n private timeScale: any\n private baseWidth: number = 30\n private level: TimeScale = 'week-day'\n private fromTime?: Date\n private toTime?: Date\n\n @query('[chart-container') container!: HTMLDivElement\n @query('svg[header]') svgHeader!: SVGSVGElement\n @query('svg[body]') svgBody!: SVGSVGElement\n\n render() {\n return html`\n <div chart-container>\n <svg header></svg>\n <svg body></svg>\n </div>\n `\n }\n\n updated(changedProperties: PropertyValues<this>) {\n if (changedProperties.has('fromDate') || changedProperties.has('toDate') || changedProperties.has('axisScale')) {\n this.updateTimeScale()\n }\n\n if (changedProperties.has('resources') || changedProperties.has('tasks')) {\n this.drawBody()\n }\n\n this.drawAxes()\n }\n\n updateTimeScale() {\n this.fromTime = new Date(this.fromDate)\n this.toTime = new Date(this.toDate)\n\n this.timeScale = d3\n .scaleTime()\n .domain([d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1)])\n .range([0, this.getChartWidth()])\n }\n\n getChartWidth() {\n const totalDays = d3.timeDay.count(new Date(this.fromDate), d3.timeDay.offset(new Date(this.toDate), 1))\n return (totalDays * this.baseWidth) / this.getScale()\n }\n\n getScale() {\n if (this.level == 'quarter-week') {\n return 7 / 2\n } else if (this.level == 'year-month') {\n return 30 / 2\n } else if (this.level === 'year-quarter') {\n return 90 / 2\n }\n return 1\n }\n\n drawAxes() {\n drawTimeScaleHeader(this.svgHeader as any, this.timeScale, this.fromTime!, this.toTime!, this.baseWidth, this.level)\n }\n\n drawBody() {\n const body = d3.select(this.svgBody)\n\n body.selectAll('*').remove()\n body.attr('width', this.getChartWidth())\n\n if (this.resources.length > 0) {\n const chartHeight = this.resources.length * 30\n\n const addVerticalGridLines = (ticks: Date[]) => {\n ticks.forEach(tick => {\n const startX = this.timeScale(tick)\n body\n .append('line')\n .attr('x1', startX)\n .attr('x2', startX)\n .attr('y1', 0)\n .attr('y2', chartHeight) // Ensure vertical lines extend to the bottom\n .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')\n .attr('stroke-width', 1)\n })\n }\n\n const addHorizontalGridLines = () => {\n this.resources.forEach((_, index) => {\n const y = (index + 1) * 30\n body\n .append('line')\n .attr('x1', 0)\n .attr('x2', this.getChartWidth())\n .attr('y1', y)\n .attr('y2', y)\n .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')\n .attr('stroke-width', 1)\n })\n\n // Ensure the last horizontal line extends to the bottom of the chart\n body\n .append('line')\n .attr('x1', 0)\n .attr('x2', this.getChartWidth())\n .attr('y1', chartHeight)\n .attr('y2', chartHeight)\n .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')\n .attr('stroke-width', 1)\n }\n\n let ticks\n if (this.level === 'week-day') {\n ticks = d3.timeDay\n .every(1)!\n .range(d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1))\n } else if (this.level === 'quarter-week') {\n ticks = d3.timeWeek\n .every(1)!\n .range(d3.timeWeek.floor(new Date(this.fromDate)), d3.timeWeek.offset(new Date(this.toDate), 1))\n } else if (this.level === 'year-month') {\n ticks = d3.timeMonth\n .every(1)!\n .range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 1))\n } else if (this.level === 'year-quarter') {\n ticks = d3.timeMonth\n .every(3)!\n .range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 3))\n }\n\n addVerticalGridLines(ticks!)\n addHorizontalGridLines()\n\n // Render the resource allocations\n this.renderResourceAllocations(body, ticks!)\n }\n }\n\n renderResourceAllocations(body: d3.Selection<SVGSVGElement, unknown, null, undefined>, ticks: Date[]) {\n const resourceAllocations = this.calculateResourceAllocations(ticks)\n\n this.resources.forEach((resource, index) => {\n const y = index * 30 + 15 // Center the text vertically in the row\n ticks.forEach(tick => {\n const tickEnd = this.getTickEnd(tick)\n const dateKey = this.formatDateKey(tick, tickEnd)\n const allocation = resourceAllocations[resource.type][dateKey]\n if (allocation > 0) {\n const startX = this.timeScale(tick)\n const tickInterval = this.timeScale(tickEnd) - startX\n\n body\n .append('text')\n .attr('x', startX + tickInterval / 2)\n .attr('y', y)\n .attr('text-anchor', 'middle')\n .attr('alignment-baseline', 'middle')\n .attr('dominant-baseline', 'middle')\n .text(allocation)\n .style('font-size', '12px')\n }\n })\n })\n }\n\n calculateResourceAllocations(ticks: Date[]) {\n const resourceAllocations: { [key: string]: { [key: string]: number } } = {}\n\n // Initialize the resourceAllocations object\n this.resources.forEach(resource => {\n resourceAllocations[resource.type] = {}\n ticks.forEach(tick => {\n const tickEnd = this.getTickEnd(tick)\n const dateKey = this.formatDateKey(tick, tickEnd)\n resourceAllocations[resource.type][dateKey] = 0\n })\n })\n\n // Function to process tasks recursively\n const processTask = (task: Task) => {\n const startDate = new Date(task.startDate)\n const endDate = new Date(task.endDate)\n let currentDate = startDate\n\n while (currentDate <= endDate) {\n const tick = ticks.find(t => currentDate >= t && currentDate < this.getTickEnd(t))\n if (tick) {\n const tickEnd = this.getTickEnd(tick)\n const dateKey = this.formatDateKey(tick, tickEnd)\n\n ;(task.resources || []).forEach(resource => {\n if (resourceAllocations[resource.type][dateKey] !== undefined) {\n resourceAllocations[resource.type][dateKey] += resource.allocated\n }\n })\n }\n\n currentDate.setDate(currentDate.getDate() + 1)\n }\n\n // Recursively process child tasks\n if (task.children) {\n task.children.forEach(childTask => processTask(childTask))\n }\n }\n\n // Process all tasks\n this.tasks.forEach(task => processTask(task))\n\n return resourceAllocations\n }\n\n getTickEnd(tick: Date) {\n if (this.level === 'week-day') {\n return d3.timeDay.offset(tick, 1)\n } else if (this.level === 'quarter-week') {\n return d3.timeWeek.offset(tick, 1)\n } else if (this.level === 'year-month') {\n return d3.timeMonth.offset(tick, 1)\n } else if (this.level === 'year-quarter') {\n return d3.timeMonth.offset(tick, 3)\n }\n return d3.timeDay.offset(tick, 1)\n }\n\n formatDateKey(start: Date, end: Date) {\n return `${start.toISOString().split('T')[0]}_${end.toISOString().split('T')[0]}`\n }\n\n syncTimeScale(detail: { baseWidth: number; level: TimeScale }) {\n this.baseWidth = detail.baseWidth\n this.level = detail.level\n\n this.updateTimeScale()\n this.drawAxes()\n this.drawBody()\n }\n\n setVerticalOffset(offset: number) {\n this.container.scrollTop = offset\n }\n\n getVerticalOffset(): number {\n return this.container.scrollTop\n }\n\n setHorizontalOffset(offset: number) {\n this.container.scrollLeft = offset\n }\n\n getHorizontalOffset(): number {\n return this.container.scrollLeft\n }\n}\n"]}
|
package/dist/src/types.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface Task {
|
|
|
12
12
|
length: string;
|
|
13
13
|
tags?: TaskTag[];
|
|
14
14
|
children?: Task[];
|
|
15
|
+
resources?: Resource[];
|
|
15
16
|
}
|
|
16
17
|
export interface Section {
|
|
17
18
|
name: string;
|
|
@@ -24,3 +25,7 @@ export interface ColumnConfig {
|
|
|
24
25
|
order: number;
|
|
25
26
|
}
|
|
26
27
|
export type TimeScale = 'year-quarter' | 'year-month' | 'quarter-week' | 'week-day';
|
|
28
|
+
export interface Resource {
|
|
29
|
+
type: string;
|
|
30
|
+
allocated: number;
|
|
31
|
+
}
|
package/dist/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type TaskTag = 'done' | 'active' | 'critical' | 'milestone'\nexport type TaskType = 'task' | 'milestone' | 'phase'\n\nexport interface Task {\n id: string\n title: string\n type: TaskType\n section?: Section\n startDate: Date | string\n endDate: Date | string\n progress?: number\n dependsOn?: string\n length: string\n tags?: TaskTag[]\n children?: Task[]\n}\n\nexport interface Section {\n name: string\n}\n\nexport interface ColumnConfig {\n name: string\n label: string\n visible: boolean\n width: number\n order: number\n}\n\nexport type TimeScale = 'year-quarter' | 'year-month' | 'quarter-week' | 'week-day'\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type TaskTag = 'done' | 'active' | 'critical' | 'milestone'\nexport type TaskType = 'task' | 'milestone' | 'phase'\n\nexport interface Task {\n id: string\n title: string\n type: TaskType\n section?: Section\n startDate: Date | string\n endDate: Date | string\n progress?: number\n dependsOn?: string\n length: string\n tags?: TaskTag[]\n children?: Task[]\n resources?: Resource[]\n}\n\nexport interface Section {\n name: string\n}\n\nexport interface ColumnConfig {\n name: string\n label: string\n visible: boolean\n width: number\n order: number\n}\n\nexport type TimeScale = 'year-quarter' | 'year-month' | 'quarter-week' | 'week-day'\n\nexport interface Resource {\n type: string\n allocated: number\n}\n"]}
|
|
@@ -53,8 +53,8 @@ const Template = ({ tasks, fromDate, toDate, extendGridLines, timeScale = 'week-
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
ox-gantt {
|
|
56
|
-
width:
|
|
57
|
-
height:
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 800px;
|
|
58
58
|
box-sizing: border-box;
|
|
59
59
|
|
|
60
60
|
background-color: var(--md-sys-color-primary-container);
|
|
@@ -102,6 +102,7 @@ Regular.args = {
|
|
|
102
102
|
dependsOn: '',
|
|
103
103
|
length: '5d',
|
|
104
104
|
tags: ['active'],
|
|
105
|
+
resources: [{ type: '철근/형틀공', allocated: 6 }],
|
|
105
106
|
children: []
|
|
106
107
|
},
|
|
107
108
|
{
|
|
@@ -115,6 +116,7 @@ Regular.args = {
|
|
|
115
116
|
dependsOn: '1',
|
|
116
117
|
length: '1d',
|
|
117
118
|
tags: ['milestone'],
|
|
119
|
+
resources: [{ type: '철근/형틀공', allocated: 6 }],
|
|
118
120
|
children: []
|
|
119
121
|
},
|
|
120
122
|
{
|
|
@@ -140,7 +142,35 @@ Regular.args = {
|
|
|
140
142
|
dependsOn: '',
|
|
141
143
|
length: '4d',
|
|
142
144
|
tags: ['done'],
|
|
143
|
-
children: [
|
|
145
|
+
children: [
|
|
146
|
+
{
|
|
147
|
+
id: '3-1-1',
|
|
148
|
+
title: 'Coding-A',
|
|
149
|
+
type: 'task',
|
|
150
|
+
// section: developmentSection,
|
|
151
|
+
startDate: '2023-01-07',
|
|
152
|
+
endDate: '2023-01-10',
|
|
153
|
+
progress: 60,
|
|
154
|
+
dependsOn: '',
|
|
155
|
+
length: '4d',
|
|
156
|
+
tags: ['active'],
|
|
157
|
+
resources: [{ type: '창호공', allocated: 5 }],
|
|
158
|
+
children: []
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: '3-1-2',
|
|
162
|
+
title: 'Coding-B',
|
|
163
|
+
type: 'task',
|
|
164
|
+
// section: developmentSection,
|
|
165
|
+
startDate: '2023-01-11',
|
|
166
|
+
endDate: '2023-01-15',
|
|
167
|
+
dependsOn: '3-1-1',
|
|
168
|
+
length: '5d',
|
|
169
|
+
tags: ['active'],
|
|
170
|
+
resources: [{ type: '창호공', allocated: 3 }],
|
|
171
|
+
children: []
|
|
172
|
+
}
|
|
173
|
+
]
|
|
144
174
|
},
|
|
145
175
|
{
|
|
146
176
|
id: '3-2',
|
|
@@ -152,6 +182,7 @@ Regular.args = {
|
|
|
152
182
|
dependsOn: '3-1',
|
|
153
183
|
length: '5d',
|
|
154
184
|
tags: ['active'],
|
|
185
|
+
resources: [{ type: '창호공', allocated: 6 }],
|
|
155
186
|
children: []
|
|
156
187
|
}
|
|
157
188
|
]
|
|
@@ -167,6 +198,7 @@ Regular.args = {
|
|
|
167
198
|
dependsOn: '1',
|
|
168
199
|
length: '1d',
|
|
169
200
|
tags: ['done'],
|
|
201
|
+
resources: [{ type: '방수공', allocated: 5 }],
|
|
170
202
|
children: []
|
|
171
203
|
},
|
|
172
204
|
{
|
|
@@ -179,6 +211,7 @@ Regular.args = {
|
|
|
179
211
|
dependsOn: '4',
|
|
180
212
|
length: '1d',
|
|
181
213
|
tags: ['milestone'],
|
|
214
|
+
resources: [{ type: '목공', allocated: 3 }],
|
|
182
215
|
children: []
|
|
183
216
|
},
|
|
184
217
|
{
|
|
@@ -191,6 +224,7 @@ Regular.args = {
|
|
|
191
224
|
dependsOn: '5',
|
|
192
225
|
length: '1d',
|
|
193
226
|
tags: ['milestone'],
|
|
227
|
+
resources: [{ type: '금속공', allocated: 1 }],
|
|
194
228
|
children: []
|
|
195
229
|
},
|
|
196
230
|
{
|
|
@@ -203,6 +237,7 @@ Regular.args = {
|
|
|
203
237
|
dependsOn: '6',
|
|
204
238
|
length: '1d',
|
|
205
239
|
tags: ['milestone'],
|
|
240
|
+
resources: [{ type: '타일공', allocated: 6 }],
|
|
206
241
|
children: []
|
|
207
242
|
},
|
|
208
243
|
{
|
|
@@ -215,6 +250,7 @@ Regular.args = {
|
|
|
215
250
|
dependsOn: '7',
|
|
216
251
|
length: '1d',
|
|
217
252
|
tags: ['critical'],
|
|
253
|
+
resources: [{ type: '창호공', allocated: 7 }],
|
|
218
254
|
children: []
|
|
219
255
|
},
|
|
220
256
|
{
|
|
@@ -227,6 +263,7 @@ Regular.args = {
|
|
|
227
263
|
dependsOn: '8',
|
|
228
264
|
length: '1d',
|
|
229
265
|
tags: ['active'],
|
|
266
|
+
resources: [{ type: '도배공', allocated: 8 }],
|
|
230
267
|
children: []
|
|
231
268
|
},
|
|
232
269
|
{
|
|
@@ -239,6 +276,7 @@ Regular.args = {
|
|
|
239
276
|
dependsOn: '9',
|
|
240
277
|
length: '1d',
|
|
241
278
|
tags: ['critical'],
|
|
279
|
+
resources: [{ type: '조적공', allocated: 6 }],
|
|
242
280
|
children: []
|
|
243
281
|
},
|
|
244
282
|
{
|
|
@@ -251,6 +289,7 @@ Regular.args = {
|
|
|
251
289
|
dependsOn: '9',
|
|
252
290
|
length: '1d',
|
|
253
291
|
tags: ['milestone'],
|
|
292
|
+
resources: [{ type: '철근/형틀공', allocated: 6 }],
|
|
254
293
|
children: []
|
|
255
294
|
},
|
|
256
295
|
{
|
|
@@ -262,8 +301,37 @@ Regular.args = {
|
|
|
262
301
|
endDate: '2023-01-23',
|
|
263
302
|
dependsOn: '9',
|
|
264
303
|
length: '1d',
|
|
304
|
+
resources: [{ type: '방수공', allocated: 6 }],
|
|
265
305
|
tags: ['milestone'],
|
|
266
|
-
children: [
|
|
306
|
+
children: [
|
|
307
|
+
{
|
|
308
|
+
id: '12-1',
|
|
309
|
+
title: 'Coding-A',
|
|
310
|
+
type: 'task',
|
|
311
|
+
// section: developmentSection,
|
|
312
|
+
startDate: '2023-01-07',
|
|
313
|
+
endDate: '2023-01-10',
|
|
314
|
+
progress: 60,
|
|
315
|
+
dependsOn: '',
|
|
316
|
+
length: '4d',
|
|
317
|
+
tags: ['done'],
|
|
318
|
+
resources: [{ type: '방수공', allocated: 6 }],
|
|
319
|
+
children: []
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: '12-2',
|
|
323
|
+
title: 'Coding-B',
|
|
324
|
+
type: 'task',
|
|
325
|
+
// section: developmentSection,
|
|
326
|
+
startDate: '2023-01-11',
|
|
327
|
+
endDate: '2023-01-15',
|
|
328
|
+
dependsOn: '12-1',
|
|
329
|
+
length: '5d',
|
|
330
|
+
tags: ['active'],
|
|
331
|
+
resources: [{ type: '조적공', allocated: 6 }],
|
|
332
|
+
children: []
|
|
333
|
+
}
|
|
334
|
+
]
|
|
267
335
|
},
|
|
268
336
|
{
|
|
269
337
|
id: '13',
|
|
@@ -287,6 +355,7 @@ Regular.args = {
|
|
|
287
355
|
dependsOn: '13',
|
|
288
356
|
length: '1d',
|
|
289
357
|
tags: ['milestone'],
|
|
358
|
+
resources: [{ type: '금속공', allocated: 1 }],
|
|
290
359
|
children: []
|
|
291
360
|
},
|
|
292
361
|
{
|
|
@@ -310,6 +379,7 @@ Regular.args = {
|
|
|
310
379
|
endDate: '2023-02-05',
|
|
311
380
|
dependsOn: '15',
|
|
312
381
|
length: '1d',
|
|
382
|
+
resources: [{ type: '창호공', allocated: 1 }],
|
|
313
383
|
tags: ['active'],
|
|
314
384
|
children: []
|
|
315
385
|
},
|
|
@@ -347,6 +417,7 @@ Regular.args = {
|
|
|
347
417
|
dependsOn: '18',
|
|
348
418
|
length: '1d',
|
|
349
419
|
tags: ['milestone'],
|
|
420
|
+
resources: [{ type: '창호공', allocated: 7 }],
|
|
350
421
|
children: []
|
|
351
422
|
}
|
|
352
423
|
]
|