@operato/gantt 7.0.21 → 7.0.23

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/src/ox-gantt.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { LitElement, html, css, PropertyValues, PropertyValueMap, nothing, TemplateResult } from 'lit'
2
+ import * as d3 from 'd3'
2
3
  import i18next from 'i18next'
3
4
  import { customElement, property, query, state } from 'lit/decorators.js'
4
5
  import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
@@ -108,6 +109,7 @@ export class OxGantt extends LitElement {
108
109
  th {
109
110
  height: 40px;
110
111
  box-sizing: border-box;
112
+ text-align: center;
111
113
  }
112
114
 
113
115
  td {
@@ -118,6 +120,10 @@ export class OxGantt extends LitElement {
118
120
  tr.selected {
119
121
  background-color: var(--ox-gantt-selected-background-color, var(--md-sys-color-surface-variant));
120
122
  }
123
+
124
+ .resource-table-container th {
125
+ height: 30px;
126
+ }
121
127
  `
122
128
  ]
123
129
 
@@ -182,11 +188,9 @@ export class OxGantt extends LitElement {
182
188
 
183
189
  @query('.task-container') taskContainer!: HTMLDivElement
184
190
  @query('.task-table-container') taskTableContainer!: HTMLDivElement
185
- @query('.task-chart-container') taskChartContainer!: HTMLDivElement
186
191
  @query('.resource-container') resourceContainer!: HTMLDivElement
187
192
  @query('.resource-table-container') resourceTableContainer!: HTMLDivElement
188
- @query('.resource-chart-container') resourceChartContainer!: HTMLDivElement
189
- @query('table') taskTable!: HTMLTableElement
193
+ @query('.task-table') taskTable!: HTMLTableElement
190
194
  @query('ox-gantt-chart') ganttChart!: OxGanttChart
191
195
  @query('ox-resource-chart') resourceChart!: OxResourceChart
192
196
 
@@ -207,10 +211,7 @@ export class OxGantt extends LitElement {
207
211
  ></ox-gantt-resize-splitter>
208
212
  <ox-gantt-chart
209
213
  class="task-chart-container"
210
- @scroll=${(e: CustomEvent) => {
211
- this.syncScroll(e)
212
- this.syncResourceChartScroll(e)
213
- }}
214
+ @scroll=${this.syncScroll}
214
215
  .fromDate=${this.fromDate}
215
216
  .toDate=${this.toDate}
216
217
  .tasks=${this.tasks}
@@ -218,6 +219,7 @@ export class OxGantt extends LitElement {
218
219
  .axisScale=${this.timeScale}
219
220
  ?extend-grid-lines=${this.extendGridLines}
220
221
  @task-clicked=${this.handleTaskClicked}
222
+ @timescale-changed=${(e: CustomEvent) => this.syncTimeScale(e)}
221
223
  ></ox-gantt-chart>
222
224
  </div>
223
225
  <ox-gantt-resize-splitter
@@ -227,12 +229,12 @@ export class OxGantt extends LitElement {
227
229
  @splitter-dragend=${(e: CustomEvent) => this.resizeVerticalEnd(e)}
228
230
  ></ox-gantt-resize-splitter>
229
231
  <div class="resource-container">
230
- <div class="resource-table-container">
232
+ <div class="resource-table-container" @scroll=${this.syncScroll}>
231
233
  <table>
232
234
  <thead>
233
235
  <tr>
234
- <th style="width: 100px">type</th>
235
- <th>allocated</th>
236
+ <th style="width: 100px">${i18next.t('label.gantt-resource-type')}</th>
237
+ <th>${i18next.t('label.gantt-resource-allocated')}</th>
236
238
  </tr>
237
239
  </thead>
238
240
  <tbody>
@@ -250,9 +252,10 @@ export class OxGantt extends LitElement {
250
252
  class="resource-chart-container"
251
253
  .fromDate=${this.fromDate}
252
254
  .toDate=${this.toDate}
255
+ .tasks=${this.tasks}
253
256
  .resources=${this.resources}
254
257
  .axisScale=${this.timeScale}
255
- @scroll=${this.syncTaskChartScroll}
258
+ @scroll=${this.syncScroll}
256
259
  ></ox-resource-chart>
257
260
  </div>
258
261
  </div>
@@ -268,7 +271,7 @@ export class OxGantt extends LitElement {
268
271
  const sortedColumns = [...this.columnConfig].sort((a, b) => a.order - b.order)
269
272
 
270
273
  return html`
271
- <table>
274
+ <table class="task-table">
272
275
  <thead>
273
276
  <tr>
274
277
  ${sortedColumns.map(col =>
@@ -295,7 +298,7 @@ export class OxGantt extends LitElement {
295
298
  <tr class=${this.selectedTaskId === task.id ? 'selected' : ''} @click=${() => this.selectTask(task.id)}>
296
299
  ${this.columnConfig.map(col =>
297
300
  col.visible
298
- ? html`<td class="task-row" style="padding-left: ${col.name == 'id' ? level * 20 : 0}px">
301
+ ? html`<td class="task-row" style="padding-left: ${col.name == 'title' ? level * 8 + 4 : 4}px">
299
302
  ${this.getTaskFieldValue(task, col.name)}
300
303
  </td>`
301
304
  : null
@@ -365,13 +368,19 @@ export class OxGantt extends LitElement {
365
368
  const traverseTasks = (tasks: Task[]) => {
366
369
  tasks.forEach(task => {
367
370
  if (task.resources) {
371
+ const startDate = new Date(task.startDate)
372
+ const endDate = new Date(task.endDate)
373
+ const durationDays = d3.timeDay.count(startDate, d3.timeDay.offset(endDate, 1))
374
+
368
375
  task.resources.forEach(resource => {
376
+ const totalAllocation = resource.allocated * durationDays
369
377
  if (!resourceMap[resource.type]) {
370
378
  resourceMap[resource.type] = 0
371
379
  }
372
- resourceMap[resource.type] += resource.allocated
380
+ resourceMap[resource.type] += totalAllocation
373
381
  })
374
382
  }
383
+
375
384
  if (task.children) {
376
385
  traverseTasks(task.children)
377
386
  }
@@ -388,31 +397,41 @@ export class OxGantt extends LitElement {
388
397
 
389
398
  syncScroll(e: Event) {
390
399
  const target = e.target as HTMLElement
400
+
391
401
  if (target === this.taskTableContainer) {
392
- // Sync chart scroll with table scroll
393
402
  const newScrollTop = this.taskTableContainer.scrollTop
394
403
  this.ganttChart.setVerticalOffset(newScrollTop)
395
404
 
396
- // Ensure chart scroll matches table scroll
397
405
  if (this.ganttChart.getVerticalOffset() !== newScrollTop) {
398
406
  this.ganttChart.setVerticalOffset(newScrollTop)
399
407
  }
400
408
  } else if (target === this.ganttChart) {
401
- // Sync table scroll with chart scroll
402
409
  const newScrollTop = this.ganttChart.getVerticalOffset()
403
410
  this.taskTableContainer.scrollTop = newScrollTop
404
-
405
- // Ensure table scroll matches chart scroll
406
411
  this.ganttChart.setVerticalOffset(this.taskTableContainer.scrollTop)
407
- }
408
- }
409
412
 
410
- syncResourceChartScroll(e: CustomEvent) {
411
- this.resourceChart.renderRoot!.querySelector('div[chart-container]')!.scrollLeft = e.detail.offset
413
+ const newScrollLeft = this.ganttChart.getHorizontalOffset()
414
+ this.resourceChart.setHorizontalOffset(newScrollLeft)
415
+ } else if (target === this.resourceChart) {
416
+ const newScrollTop = this.ganttChart.getVerticalOffset()
417
+ this.resourceTableContainer.scrollTop = newScrollTop
418
+ this.resourceChart.setVerticalOffset(this.taskTableContainer.scrollTop)
419
+
420
+ const newScrollLeft = this.resourceChart.getHorizontalOffset()
421
+ this.ganttChart.setHorizontalOffset(newScrollLeft)
422
+ } else if (target === this.resourceTableContainer) {
423
+ const newScrollTop = this.taskTableContainer.scrollTop
424
+ this.resourceChart.setVerticalOffset(newScrollTop)
425
+
426
+ if (this.resourceChart.getVerticalOffset() !== newScrollTop) {
427
+ this.resourceChart.setVerticalOffset(newScrollTop)
428
+ }
429
+ }
412
430
  }
413
431
 
414
- syncTaskChartScroll(e: CustomEvent) {
415
- this.ganttChart.renderRoot!.querySelector('div[chart-container]')!.scrollLeft = e.detail.offset
432
+ syncTimeScale(e: CustomEvent) {
433
+ const detail = e.detail
434
+ this.resourceChart.syncTimeScale(detail)
416
435
  }
417
436
 
418
437
  resizeHorizontalStart(e: CustomEvent) {
@@ -1,9 +1,12 @@
1
1
  import { LitElement, html, css, PropertyValues } from 'lit'
2
- import { customElement, property } from 'lit/decorators.js'
2
+ import { customElement, property, query } from 'lit/decorators.js'
3
3
  import * as d3 from 'd3'
4
4
 
5
5
  import { ScrollbarStyles } from '@operato/styles'
6
6
 
7
+ import { drawTimeScaleHeader } from './draw-time-scale-header'
8
+ import { Task, TimeScale } from './types'
9
+
7
10
  @customElement('ox-resource-chart')
8
11
  export class OxResourceChart extends LitElement {
9
12
  static styles = [
@@ -14,43 +17,51 @@ export class OxResourceChart extends LitElement {
14
17
  overflow: hidden;
15
18
  position: relative;
16
19
  }
20
+
17
21
  div[chart-container] {
18
- display: block;
22
+ display: flex;
23
+ flex-direction: column;
24
+
19
25
  overflow-x: auto;
20
- overflow-y: hidden;
21
- }
22
- svg {
23
- min-width: 100%;
26
+ overflow-y: auto;
24
27
  }
28
+
25
29
  svg[header] {
26
30
  display: block;
27
31
  min-width: 100%;
28
32
  box-sizing: border-box;
29
33
  border-bottom: 1px solid var(--ox-gantt-header-border-color, var(--md-sys-color-on-secondary-container));
30
- height: 40px;
34
+ height: 30px;
31
35
  background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
32
36
  color: var(--ox-gantt-header-color, var(--md-sys-color-on-secondary-container));
33
37
  position: sticky;
34
38
  top: 0;
35
39
  z-index: 1;
36
40
  }
41
+
37
42
  svg[body] {
43
+ flex: 1;
38
44
  display: block;
39
45
  min-width: 100%;
40
46
  }
47
+
41
48
  .top-axis text,
42
49
  .bottom-axis text {
43
50
  font-size: 12px;
44
51
  }
52
+
45
53
  .grid line {
46
54
  stroke: #e0e0e0;
47
55
  }
56
+
48
57
  .grid path {
49
58
  stroke-width: 0;
50
59
  }
60
+
51
61
  .no-select {
52
62
  user-select: none;
53
63
  }
64
+
54
65
  .selected {
55
66
  stroke-width: 2px;
56
67
  stroke: var(--ox-gantt-selected-color, blue);
@@ -62,10 +73,17 @@ export class OxResourceChart extends LitElement {
62
73
  @property({ type: String }) toDate: string = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0]
63
74
  @property({ type: String }) axisScale: string = 'week-day'
64
75
  @property({ type: Array }) resources: any[] = []
76
+ @property({ type: Array }) tasks: Task[] = []
65
77
 
66
- private _timeScale: any
67
- private _baseWidth: number = 30
68
- private _level: string = 'week-day'
78
+ private timeScale: any
79
+ private baseWidth: number = 30
80
+ private level: TimeScale = 'week-day'
81
+ private fromTime?: Date
82
+ private toTime?: Date
83
+
84
+ @query('[chart-container') container!: HTMLDivElement
85
+ @query('svg[header]') svgHeader!: SVGSVGElement
86
+ @query('svg[body]') svgBody!: SVGSVGElement
69
87
 
70
88
  render() {
71
89
  return html`
@@ -81,7 +99,7 @@ export class OxResourceChart extends LitElement {
81
99
  this.updateTimeScale()
82
100
  }
83
101
 
84
- if (changedProperties.has('resources')) {
102
+ if (changedProperties.has('resources') || changedProperties.has('tasks')) {
85
103
  this.drawBody()
86
104
  }
87
105
 
@@ -89,7 +107,10 @@ export class OxResourceChart extends LitElement {
89
107
  }
90
108
 
91
109
  updateTimeScale() {
92
- this._timeScale = d3
110
+ this.fromTime = new Date(this.fromDate)
111
+ this.toTime = new Date(this.toDate)
112
+
113
+ this.timeScale = d3
93
114
  .scaleTime()
94
115
  .domain([d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1)])
95
116
  .range([0, this.getChartWidth()])
@@ -97,50 +118,50 @@ export class OxResourceChart extends LitElement {
97
118
 
98
119
  getChartWidth() {
99
120
  const totalDays = d3.timeDay.count(new Date(this.fromDate), d3.timeDay.offset(new Date(this.toDate), 1))
100
- return (totalDays * this._baseWidth) / this.getScale()
121
+ return (totalDays * this.baseWidth) / this.getScale()
101
122
  }
102
123
 
103
124
  getScale() {
104
- if (this._level == 'quarter-week') {
125
+ if (this.level == 'quarter-week') {
105
126
  return 7 / 2
106
- } else if (this._level == 'year-month') {
127
+ } else if (this.level == 'year-month') {
107
128
  return 30 / 2
108
- } else if (this._level == 'year-quarter') {
129
+ } else if (this.level === 'year-quarter') {
109
130
  return 90 / 2
110
131
  }
111
132
  return 1
112
133
  }
113
134
 
114
135
  drawAxes() {
115
- const header = d3.select(this.renderRoot.querySelector('svg[header]')!)
116
-
117
- header.selectAll('*').remove()
118
- header.attr('width', this.getChartWidth())
119
-
120
- const axisTop = d3.axisTop(this._timeScale).tickSize(-20)
121
- const axisBottom = d3.axisBottom(this._timeScale).tickSize(-20)
122
-
123
- header.append('g').attr('class', 'top-axis').attr('transform', 'translate(0, 20)').call(axisTop)
124
- header.append('g').attr('class', 'bottom-axis').attr('transform', 'translate(0, 40)').call(axisBottom)
136
+ drawTimeScaleHeader(
137
+ this.svgHeader as any,
138
+ this.timeScale,
139
+ this.fromTime!,
140
+ this.toTime!,
141
+ this.baseWidth,
142
+ this.level,
143
+ false /* 1 level only header */
144
+ )
125
145
  }
126
146
 
127
147
  drawBody() {
128
- const body = d3.select(this.renderRoot.querySelector('svg[body]')!)
148
+ const body = d3.select(this.svgBody)
129
149
 
130
150
  body.selectAll('*').remove()
131
151
  body.attr('width', this.getChartWidth())
132
152
 
133
- // Add grid lines for resource chart
134
153
  if (this.resources.length > 0) {
154
+ const chartHeight = this.resources.length * 30
155
+
135
156
  const addVerticalGridLines = (ticks: Date[]) => {
136
157
  ticks.forEach(tick => {
137
- const startX = this._timeScale(tick)
158
+ const startX = this.timeScale(tick)
138
159
  body
139
160
  .append('line')
140
161
  .attr('x1', startX)
141
162
  .attr('x2', startX)
142
163
  .attr('y1', 0)
143
- .attr('y2', this.resources.length * 30) // Adjust according to the number of resource rows
164
+ .attr('y2', chartHeight) // Ensure vertical lines extend to the bottom
144
165
  .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
145
166
  .attr('stroke-width', 1)
146
167
  })
@@ -158,35 +179,158 @@ export class OxResourceChart extends LitElement {
158
179
  .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
159
180
  .attr('stroke-width', 1)
160
181
  })
182
+
183
+ // Ensure the last horizontal line extends to the bottom of the chart
184
+ body
185
+ .append('line')
186
+ .attr('x1', 0)
187
+ .attr('x2', this.getChartWidth())
188
+ .attr('y1', chartHeight)
189
+ .attr('y2', chartHeight)
190
+ .attr('stroke', 'var(--ox-gantt-color-gridlines, var(--md-sys-color-outline))')
191
+ .attr('stroke-width', 1)
161
192
  }
162
193
 
163
- if (this._level === 'week-day') {
164
- const dayTicks = d3.timeDay
194
+ let ticks
195
+ if (this.level === 'week-day') {
196
+ ticks = d3.timeDay
165
197
  .every(1)!
166
198
  .range(d3.timeDay.floor(new Date(this.fromDate)), d3.timeDay.offset(new Date(this.toDate), 1))
167
- addVerticalGridLines(dayTicks)
168
- } else if (this._level === 'quarter-week') {
169
- const weekTicks = d3.timeWeek
199
+ } else if (this.level === 'quarter-week') {
200
+ ticks = d3.timeWeek
170
201
  .every(1)!
171
202
  .range(d3.timeWeek.floor(new Date(this.fromDate)), d3.timeWeek.offset(new Date(this.toDate), 1))
172
- addVerticalGridLines(weekTicks)
173
- } else if (this._level === 'year-month') {
174
- const monthTicks = d3.timeMonth
203
+ } else if (this.level === 'year-month') {
204
+ ticks = d3.timeMonth
175
205
  .every(1)!
176
206
  .range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 1))
177
- addVerticalGridLines(monthTicks)
178
- } else if (this._level === 'year-quarter') {
179
- const quarterTicks = d3.timeMonth
207
+ } else if (this.level === 'year-quarter') {
208
+ ticks = d3.timeMonth
180
209
  .every(3)!
181
210
  .range(d3.timeMonth.floor(new Date(this.fromDate)), d3.timeMonth.offset(new Date(this.toDate), 3))
182
- addVerticalGridLines(quarterTicks)
183
211
  }
184
212
 
213
+ addVerticalGridLines(ticks!)
185
214
  addHorizontalGridLines()
215
+
216
+ // Render the resource allocations
217
+ this.renderResourceAllocations(body, ticks!)
186
218
  }
187
219
  }
188
220
 
189
- syncScroll(e: CustomEvent) {
190
- this.shadowRoot!.querySelector('div[chart-container]')!.scrollLeft = e.detail.offset
221
+ renderResourceAllocations(body: d3.Selection<SVGSVGElement, unknown, null, undefined>, ticks: Date[]) {
222
+ const resourceAllocations = this.calculateResourceAllocations(ticks)
223
+
224
+ this.resources.forEach((resource, index) => {
225
+ const y = index * 30 + 15 // Center the text vertically in the row
226
+ ticks.forEach(tick => {
227
+ const tickEnd = this.getTickEnd(tick)
228
+ const dateKey = this.formatDateKey(tick, tickEnd)
229
+ const allocation = resourceAllocations[resource.type][dateKey]
230
+ if (allocation > 0) {
231
+ const startX = this.timeScale(tick)
232
+ const tickInterval = this.timeScale(tickEnd) - startX
233
+
234
+ body
235
+ .append('text')
236
+ .attr('x', startX + tickInterval / 2)
237
+ .attr('y', y)
238
+ .attr('text-anchor', 'middle')
239
+ .attr('alignment-baseline', 'middle')
240
+ .attr('dominant-baseline', 'middle')
241
+ .text(allocation)
242
+ .style('font-size', '12px')
243
+ }
244
+ })
245
+ })
246
+ }
247
+
248
+ calculateResourceAllocations(ticks: Date[]) {
249
+ const resourceAllocations: { [key: string]: { [key: string]: number } } = {}
250
+
251
+ // Initialize the resourceAllocations object
252
+ this.resources.forEach(resource => {
253
+ resourceAllocations[resource.type] = {}
254
+ ticks.forEach(tick => {
255
+ const tickEnd = this.getTickEnd(tick)
256
+ const dateKey = this.formatDateKey(tick, tickEnd)
257
+ resourceAllocations[resource.type][dateKey] = 0
258
+ })
259
+ })
260
+
261
+ // Function to process tasks recursively
262
+ const processTask = (task: Task) => {
263
+ const startDate = new Date(task.startDate)
264
+ const endDate = new Date(task.endDate)
265
+ let currentDate = startDate
266
+
267
+ while (currentDate <= endDate) {
268
+ const tick = ticks.find(t => currentDate >= t && currentDate < this.getTickEnd(t))
269
+ if (tick) {
270
+ const tickEnd = this.getTickEnd(tick)
271
+ const dateKey = this.formatDateKey(tick, tickEnd)
272
+
273
+ ;(task.resources || []).forEach(resource => {
274
+ if (resourceAllocations[resource.type][dateKey] !== undefined) {
275
+ resourceAllocations[resource.type][dateKey] += resource.allocated
276
+ }
277
+ })
278
+ }
279
+
280
+ currentDate.setDate(currentDate.getDate() + 1)
281
+ }
282
+
283
+ // Recursively process child tasks
284
+ if (task.children) {
285
+ task.children.forEach(childTask => processTask(childTask))
286
+ }
287
+ }
288
+
289
+ // Process all tasks
290
+ this.tasks.forEach(task => processTask(task))
291
+
292
+ return resourceAllocations
293
+ }
294
+
295
+ getTickEnd(tick: Date) {
296
+ if (this.level === 'week-day') {
297
+ return d3.timeDay.offset(tick, 1)
298
+ } else if (this.level === 'quarter-week') {
299
+ return d3.timeWeek.offset(tick, 1)
300
+ } else if (this.level === 'year-month') {
301
+ return d3.timeMonth.offset(tick, 1)
302
+ } else if (this.level === 'year-quarter') {
303
+ return d3.timeMonth.offset(tick, 3)
304
+ }
305
+ return d3.timeDay.offset(tick, 1)
306
+ }
307
+
308
+ formatDateKey(start: Date, end: Date) {
309
+ return `${start.toISOString().split('T')[0]}_${end.toISOString().split('T')[0]}`
310
+ }
311
+
312
+ syncTimeScale(detail: { baseWidth: number; level: TimeScale }) {
313
+ this.baseWidth = detail.baseWidth
314
+ this.level = detail.level
315
+
316
+ this.updateTimeScale()
317
+ this.drawAxes()
318
+ this.drawBody()
319
+ }
320
+
321
+ setVerticalOffset(offset: number) {
322
+ this.container.scrollTop = offset
323
+ }
324
+
325
+ getVerticalOffset(): number {
326
+ return this.container.scrollTop
327
+ }
328
+
329
+ setHorizontalOffset(offset: number) {
330
+ this.container.scrollLeft = offset
331
+ }
332
+
333
+ getHorizontalOffset(): number {
334
+ return this.container.scrollLeft
191
335
  }
192
336
  }
@@ -78,8 +78,8 @@ const Template: Story<ArgTypes> = ({
78
78
  }
79
79
 
80
80
  ox-gantt {
81
- width: 90%;
82
- height: 500px;
81
+ width: 95%;
82
+ height: 650px;
83
83
  box-sizing: border-box;
84
84
 
85
85
  background-color: var(--md-sys-color-primary-container);
@@ -182,8 +182,8 @@ Regular.args = {
182
182
  progress: 60,
183
183
  dependsOn: '',
184
184
  length: '4d',
185
- tags: ['done'],
186
- resources: [{ type: '창호공', allocated: 6 }],
185
+ tags: ['active'],
186
+ resources: [{ type: '창호공', allocated: 5 }],
187
187
  children: []
188
188
  },
189
189
  {
@@ -196,7 +196,7 @@ Regular.args = {
196
196
  dependsOn: '3-1-1',
197
197
  length: '5d',
198
198
  tags: ['active'],
199
- resources: [{ type: '창호공', allocated: 6 }],
199
+ resources: [{ type: '창호공', allocated: 3 }],
200
200
  children: []
201
201
  }
202
202
  ]
@@ -227,7 +227,7 @@ Regular.args = {
227
227
  dependsOn: '1',
228
228
  length: '1d',
229
229
  tags: ['done'],
230
- resources: [{ type: '방수공', allocated: 6 }],
230
+ resources: [{ type: '방수공', allocated: 5 }],
231
231
  children: []
232
232
  },
233
233
  {
@@ -240,7 +240,7 @@ Regular.args = {
240
240
  dependsOn: '4',
241
241
  length: '1d',
242
242
  tags: ['milestone'],
243
- resources: [{ type: '목공', allocated: 6 }],
243
+ resources: [{ type: '목공', allocated: 3 }],
244
244
  children: []
245
245
  },
246
246
  {
@@ -253,7 +253,7 @@ Regular.args = {
253
253
  dependsOn: '5',
254
254
  length: '1d',
255
255
  tags: ['milestone'],
256
- resources: [{ type: '금속공', allocated: 6 }],
256
+ resources: [{ type: '금속공', allocated: 1 }],
257
257
  children: []
258
258
  },
259
259
  {
@@ -279,7 +279,7 @@ Regular.args = {
279
279
  dependsOn: '7',
280
280
  length: '1d',
281
281
  tags: ['critical'],
282
- resources: [{ type: '창호공', allocated: 6 }],
282
+ resources: [{ type: '창호공', allocated: 7 }],
283
283
  children: []
284
284
  },
285
285
  {
@@ -292,7 +292,7 @@ Regular.args = {
292
292
  dependsOn: '8',
293
293
  length: '1d',
294
294
  tags: ['active'],
295
- resources: [{ type: '도배공', allocated: 6 }],
295
+ resources: [{ type: '도배공', allocated: 8 }],
296
296
  children: []
297
297
  },
298
298
  {
@@ -318,6 +318,7 @@ Regular.args = {
318
318
  dependsOn: '9',
319
319
  length: '1d',
320
320
  tags: ['milestone'],
321
+ resources: [{ type: '철근/형틀공', allocated: 6 }],
321
322
  children: []
322
323
  },
323
324
  {
@@ -329,6 +330,7 @@ Regular.args = {
329
330
  endDate: '2023-01-23',
330
331
  dependsOn: '9',
331
332
  length: '1d',
333
+ resources: [{ type: '방수공', allocated: 6 }],
332
334
  tags: ['milestone'],
333
335
  children: [
334
336
  {
@@ -342,6 +344,7 @@ Regular.args = {
342
344
  dependsOn: '',
343
345
  length: '4d',
344
346
  tags: ['done'],
347
+ resources: [{ type: '방수공', allocated: 6 }],
345
348
  children: []
346
349
  },
347
350
  {
@@ -354,6 +357,7 @@ Regular.args = {
354
357
  dependsOn: '12-1',
355
358
  length: '5d',
356
359
  tags: ['active'],
360
+ resources: [{ type: '조적공', allocated: 6 }],
357
361
  children: []
358
362
  }
359
363
  ]
@@ -380,6 +384,7 @@ Regular.args = {
380
384
  dependsOn: '13',
381
385
  length: '1d',
382
386
  tags: ['milestone'],
387
+ resources: [{ type: '금속공', allocated: 1 }],
383
388
  children: []
384
389
  },
385
390
  {
@@ -403,6 +408,7 @@ Regular.args = {
403
408
  endDate: '2023-02-05',
404
409
  dependsOn: '15',
405
410
  length: '1d',
411
+ resources: [{ type: '창호공', allocated: 1 }],
406
412
  tags: ['active'],
407
413
  children: []
408
414
  },
@@ -440,6 +446,7 @@ Regular.args = {
440
446
  dependsOn: '18',
441
447
  length: '1d',
442
448
  tags: ['milestone'],
449
+ resources: [{ type: '창호공', allocated: 7 }],
443
450
  children: []
444
451
  }
445
452
  ]
@@ -8,5 +8,7 @@
8
8
  "label.gantt-task-tags": "tags",
9
9
  "label.gantt-task-progress": "progress",
10
10
  "label.gantt-task-previous": "previous",
11
- "label.gantt-task-resources": "resources"
11
+ "label.gantt-task-resources": "resources",
12
+ "label.gantt-resource-type": "type",
13
+ "label.gantt-resource-allocated": "allocated"
12
14
  }
@@ -7,5 +7,7 @@
7
7
  "label.gantt-task-end-date": "終了日",
8
8
  "label.gantt-task-tags": "タグ",
9
9
  "label.gantt-task-progress": "進捗",
10
- "label.gantt-task-previous": "前"
10
+ "label.gantt-task-previous": "前",
11
+ "label.gantt-resource-type": "タイプ",
12
+ "label.gantt-resource-allocated": "割り当て"
11
13
  }
@@ -8,5 +8,7 @@
8
8
  "label.gantt-task-tags": "태그",
9
9
  "label.gantt-task-progress": "진행 상황",
10
10
  "label.gantt-task-previous": "이전",
11
- "label.gantt-task-resources": "자원"
11
+ "label.gantt-task-resources": "자원",
12
+ "label.gantt-resource-type": "유형",
13
+ "label.gantt-resource-allocated": "할당"
12
14
  }