@operato/gantt 7.0.60 → 7.0.69
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 +18 -0
- package/dist/src/draw-time-scale-header.js +1 -1
- package/dist/src/draw-time-scale-header.js.map +1 -1
- package/dist/src/gantt-chart-controller.d.ts +2 -0
- package/dist/src/gantt-chart-controller.js +24 -9
- package/dist/src/gantt-chart-controller.js.map +1 -1
- package/dist/src/ox-gantt-chart.js +38 -36
- package/dist/src/ox-gantt-chart.js.map +1 -1
- package/dist/src/ox-gantt.d.ts +6 -4
- package/dist/src/ox-gantt.js +73 -78
- package/dist/src/ox-gantt.js.map +1 -1
- package/dist/src/ox-resource-chart.d.ts +11 -27
- package/dist/src/ox-resource-chart.js +55 -227
- package/dist/src/ox-resource-chart.js.map +1 -1
- package/dist/src/ox-task-tooltip.js +3 -3
- package/dist/src/ox-task-tooltip.js.map +1 -1
- package/dist/src/resource-chart-controller.d.ts +44 -0
- package/dist/src/resource-chart-controller.js +226 -0
- package/dist/src/resource-chart-controller.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/draw-time-scale-header.ts +1 -1
- package/src/gantt-chart-controller.ts +32 -8
- package/src/ox-gantt-chart.ts +43 -36
- package/src/ox-gantt.ts +71 -78
- package/src/ox-resource-chart.ts +57 -253
- package/src/ox-task-tooltip.ts +3 -3
- package/src/resource-chart-controller.ts +284 -0
package/src/ox-gantt-chart.ts
CHANGED
|
@@ -36,10 +36,10 @@ export class OxGanttChart extends LitElement {
|
|
|
36
36
|
display: block;
|
|
37
37
|
min-width: 100%;
|
|
38
38
|
box-sizing: border-box;
|
|
39
|
-
border-bottom: 1px solid var(--ox-gantt-header-border-color, var(--md-sys-color-on-secondary-container));
|
|
40
39
|
height: 40px;
|
|
41
|
-
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
42
40
|
color: var(--ox-gantt-header-color, var(--md-sys-color-on-secondary-container));
|
|
41
|
+
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
42
|
+
border-bottom: 1px solid var(--ox-gantt-header-border-color, var(--md-sys-color-outline));
|
|
43
43
|
position: sticky;
|
|
44
44
|
top: 0;
|
|
45
45
|
z-index: 1;
|
|
@@ -166,45 +166,52 @@ export class OxGanttChart extends LitElement {
|
|
|
166
166
|
event.preventDefault()
|
|
167
167
|
event.stopPropagation()
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
169
|
+
const deltaModeFactor =
|
|
170
|
+
event.deltaMode === WheelEvent.DOM_DELTA_LINE
|
|
171
|
+
? 16
|
|
172
|
+
: event.deltaMode === WheelEvent.DOM_DELTA_PAGE
|
|
173
|
+
? this.container.clientHeight
|
|
174
|
+
: 1
|
|
175
|
+
|
|
176
|
+
// deltaY 값이 0인 경우, deltaX 값을 사용하여 확대/축소를 처리
|
|
177
|
+
const delta = event.deltaY !== 0 ? event.deltaY : event.deltaX
|
|
178
|
+
const adjustedDelta = delta * deltaModeFactor
|
|
179
|
+
|
|
180
|
+
// 확대/축소 처리
|
|
181
|
+
const zoomFactor = adjustedDelta < 0 ? 1.1 : 0.9
|
|
182
|
+
this.ganttChartController.baseWidth *= zoomFactor
|
|
183
|
+
|
|
184
|
+
if (this.ganttChartController.baseWidth > 40) {
|
|
185
|
+
if (this.ganttChartController.level === 'week-day') {
|
|
186
|
+
this.ganttChartController.baseWidth = 40
|
|
187
|
+
} else {
|
|
188
|
+
this.ganttChartController.level = levelDown(this.ganttChartController.level)
|
|
189
|
+
this.ganttChartController.baseWidth = 30
|
|
188
190
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
} else if (this.ganttChartController.baseWidth < 30) {
|
|
192
|
+
if (this.ganttChartController.level === 'year-quarter') {
|
|
191
193
|
this.ganttChartController.baseWidth = 30
|
|
192
194
|
}
|
|
195
|
+
}
|
|
193
196
|
|
|
194
|
-
|
|
195
|
-
this.
|
|
196
|
-
|
|
197
|
-
// Dispatch custom event to sync with ox-resource-chart
|
|
198
|
-
const customEvent = new CustomEvent('timescale-changed', {
|
|
199
|
-
detail: {
|
|
200
|
-
baseWidth: this.ganttChartController.baseWidth,
|
|
201
|
-
level: this.ganttChartController.level
|
|
202
|
-
},
|
|
203
|
-
bubbles: true,
|
|
204
|
-
composed: true
|
|
205
|
-
})
|
|
206
|
-
this.dispatchEvent(customEvent)
|
|
197
|
+
if (this.ganttChartController.baseWidth < 20) {
|
|
198
|
+
this.ganttChartController.level = levelUp(this.ganttChartController.level)
|
|
199
|
+
this.ganttChartController.baseWidth = 30
|
|
207
200
|
}
|
|
201
|
+
|
|
202
|
+
this.ganttChartController.updateTimeScale()
|
|
203
|
+
this.requestUpdate()
|
|
204
|
+
|
|
205
|
+
// Dispatch custom event to sync with ox-resource-chart
|
|
206
|
+
const customEvent = new CustomEvent('timescale-changed', {
|
|
207
|
+
detail: {
|
|
208
|
+
baseWidth: this.ganttChartController.baseWidth,
|
|
209
|
+
level: this.ganttChartController.level
|
|
210
|
+
},
|
|
211
|
+
bubbles: true,
|
|
212
|
+
composed: true
|
|
213
|
+
})
|
|
214
|
+
this.dispatchEvent(customEvent)
|
|
208
215
|
}
|
|
209
216
|
|
|
210
217
|
handleDateRangeSelected(event: CustomEvent) {
|
package/src/ox-gantt.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LitElement, html, css, PropertyValues, PropertyValueMap, nothing, TemplateResult } from 'lit'
|
|
2
2
|
import * as d3 from 'd3'
|
|
3
|
-
import i18next from 'i18next'
|
|
4
3
|
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
5
4
|
import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles'
|
|
5
|
+
import { i18next, localize } from '@operato/i18n'
|
|
6
6
|
import { ScrollbarStyles } from '@operato/styles'
|
|
7
7
|
|
|
8
8
|
import './ox-gantt-chart.js'
|
|
@@ -13,7 +13,7 @@ import { OxResourceChart } from './ox-resource-chart.js'
|
|
|
13
13
|
import { ColumnConfig, Task, TimeScale, Resource } from './types.js'
|
|
14
14
|
|
|
15
15
|
@customElement('ox-gantt')
|
|
16
|
-
export class OxGantt extends LitElement {
|
|
16
|
+
export class OxGantt extends localize(i18next)(LitElement) {
|
|
17
17
|
static styles = [
|
|
18
18
|
MDTypeScaleStyles,
|
|
19
19
|
ScrollbarStyles,
|
|
@@ -48,14 +48,14 @@ export class OxGantt extends LitElement {
|
|
|
48
48
|
overflow: auto;
|
|
49
49
|
overflow-y: overlay;
|
|
50
50
|
box-sizing: border-box;
|
|
51
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
51
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
.resource-chart-container {
|
|
55
55
|
flex: 1;
|
|
56
56
|
padding: 0;
|
|
57
57
|
box-sizing: border-box;
|
|
58
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
58
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
.task-container {
|
|
@@ -71,20 +71,20 @@ export class OxGantt extends LitElement {
|
|
|
71
71
|
overflow: auto;
|
|
72
72
|
overflow-y: overlay;
|
|
73
73
|
box-sizing: border-box;
|
|
74
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
74
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
.task-chart-container {
|
|
78
78
|
flex: 1;
|
|
79
79
|
padding: 0;
|
|
80
80
|
box-sizing: border-box;
|
|
81
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
81
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
table {
|
|
85
85
|
width: 100%;
|
|
86
86
|
border-collapse: collapse;
|
|
87
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
87
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
88
88
|
margin: -1px;
|
|
89
89
|
margin-right: 0;
|
|
90
90
|
}
|
|
@@ -93,15 +93,15 @@ export class OxGantt extends LitElement {
|
|
|
93
93
|
position: sticky;
|
|
94
94
|
top: -1px;
|
|
95
95
|
z-index: 1;
|
|
96
|
-
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
97
|
-
border-color: var(--ox-gantt-header-border-color, var(--md-sys-color-on-secondary-container));
|
|
98
96
|
color: var(--ox-gantt-header-color, var(--md-sys-color-on-secondary-container));
|
|
97
|
+
background-color: var(--ox-gantt-header-background-color, var(--md-sys-color-secondary-container));
|
|
98
|
+
border-color: var(--ox-gantt-header-border-color, var(--md-sys-color-outline));
|
|
99
99
|
text-transform: capitalize;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
th,
|
|
103
103
|
td {
|
|
104
|
-
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-
|
|
104
|
+
border: 1px solid var(--ox-gantt-border-color, var(--md-sys-color-outline));
|
|
105
105
|
padding: 4px;
|
|
106
106
|
text-align: left;
|
|
107
107
|
}
|
|
@@ -135,54 +135,56 @@ export class OxGantt extends LitElement {
|
|
|
135
135
|
toDate: string = new Date(new Date().getFullYear(), 11, 31).toISOString().split('T')[0] /* end of this year */
|
|
136
136
|
@property({ type: Boolean, attribute: 'extend-grid-lines' }) extendGridLines: boolean = false
|
|
137
137
|
@property({ type: String, attribute: 'time-scale' }) timeScale: TimeScale = 'week-day'
|
|
138
|
-
@property({ type:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
138
|
+
@property({ type: Object }) columnConfigProvider: () => ColumnConfig[] = function () {
|
|
139
|
+
return [
|
|
140
|
+
{ name: 'id', label: i18next.t('label.gantt-task-id') || 'ID', visible: true, width: 50, order: 1 },
|
|
141
|
+
{
|
|
142
|
+
name: 'section',
|
|
143
|
+
label: i18next.t('label.gantt-task-section') || 'section',
|
|
144
|
+
visible: true,
|
|
145
|
+
width: 100,
|
|
146
|
+
order: 2
|
|
147
|
+
},
|
|
148
|
+
{ name: 'title', label: i18next.t('label.gantt-task-title') || 'title', visible: true, width: 150, order: 3 },
|
|
149
|
+
{ name: 'type', label: i18next.t('label.gantt-task-type') || 'type', visible: true, width: 100, order: 4 },
|
|
150
|
+
{
|
|
151
|
+
name: 'startDate',
|
|
152
|
+
label: i18next.t('label.gantt-task-start-date') || 'start date',
|
|
153
|
+
visible: true,
|
|
154
|
+
width: 100,
|
|
155
|
+
order: 5
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'endDate',
|
|
159
|
+
label: i18next.t('label.gantt-task-end-date') || 'end date',
|
|
160
|
+
visible: true,
|
|
161
|
+
width: 100,
|
|
162
|
+
order: 6
|
|
163
|
+
},
|
|
164
|
+
{ name: 'tags', label: i18next.t('label.gantt-task-tags') || 'tags', visible: true, width: 100, order: 7 },
|
|
165
|
+
{
|
|
166
|
+
name: 'progress',
|
|
167
|
+
label: i18next.t('label.gantt-task-progress') || 'progress',
|
|
168
|
+
visible: true,
|
|
169
|
+
width: 100,
|
|
170
|
+
order: 8
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: 'dependsOn',
|
|
174
|
+
label: i18next.t('label.gantt-task-previous') || 'previous',
|
|
175
|
+
visible: true,
|
|
176
|
+
width: 100,
|
|
177
|
+
order: 9
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'resources',
|
|
181
|
+
label: i18next.t('label.gantt-task-resources') || 'resources',
|
|
182
|
+
visible: true,
|
|
183
|
+
width: 100,
|
|
184
|
+
order: 10
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}
|
|
186
188
|
|
|
187
189
|
@state() selectedTaskId?: string
|
|
188
190
|
|
|
@@ -263,12 +265,13 @@ export class OxGantt extends LitElement {
|
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
renderTaskTable() {
|
|
266
|
-
|
|
268
|
+
const columnConfig = this.columnConfigProvider()
|
|
269
|
+
if (!columnConfig) {
|
|
267
270
|
return
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
// Sort columns by the configured order
|
|
271
|
-
const sortedColumns = [...
|
|
274
|
+
const sortedColumns = [...columnConfig].sort((a, b) => a.order - b.order)
|
|
272
275
|
|
|
273
276
|
return html`
|
|
274
277
|
<table class="task-table">
|
|
@@ -280,23 +283,23 @@ export class OxGantt extends LitElement {
|
|
|
280
283
|
</tr>
|
|
281
284
|
</thead>
|
|
282
285
|
<tbody>
|
|
283
|
-
${this.renderTaskRows(this.tasks)}
|
|
286
|
+
${this.renderTaskRows(this.tasks, 0, columnConfig)}
|
|
284
287
|
</tbody>
|
|
285
288
|
</table>
|
|
286
289
|
`
|
|
287
290
|
}
|
|
288
291
|
|
|
289
|
-
renderTaskRows(tasks: Task[], level: number = 0): TemplateResult[] {
|
|
292
|
+
renderTaskRows(tasks: Task[], level: number = 0, columnConfig: ColumnConfig[]): TemplateResult[] {
|
|
290
293
|
return tasks.flatMap(task => [
|
|
291
|
-
this.renderTaskRow(task, level),
|
|
292
|
-
...this.renderTaskRows(task.children || [], level + 1)
|
|
294
|
+
this.renderTaskRow(task, level, columnConfig),
|
|
295
|
+
...this.renderTaskRows(task.children || [], level + 1, columnConfig)
|
|
293
296
|
])
|
|
294
297
|
}
|
|
295
298
|
|
|
296
|
-
renderTaskRow(task: Task, level: number) {
|
|
299
|
+
renderTaskRow(task: Task, level: number, columnConfig: ColumnConfig[]) {
|
|
297
300
|
return html`
|
|
298
301
|
<tr class=${this.selectedTaskId === task.id ? 'selected' : ''} @click=${() => this.selectTask(task.id)}>
|
|
299
|
-
${
|
|
302
|
+
${columnConfig.map(col =>
|
|
300
303
|
col.visible
|
|
301
304
|
? html`<td class="task-row" style="padding-left: ${col.name == 'title' ? level * 8 + 4 : 4}px">
|
|
302
305
|
${this.getTaskFieldValue(task, col.name)}
|
|
@@ -401,31 +404,21 @@ export class OxGantt extends LitElement {
|
|
|
401
404
|
if (target === this.taskTableContainer) {
|
|
402
405
|
const newScrollTop = this.taskTableContainer.scrollTop
|
|
403
406
|
this.ganttChart.setVerticalOffset(newScrollTop)
|
|
404
|
-
|
|
405
|
-
if (this.ganttChart.getVerticalOffset() !== newScrollTop) {
|
|
406
|
-
this.ganttChart.setVerticalOffset(newScrollTop)
|
|
407
|
-
}
|
|
408
407
|
} else if (target === this.ganttChart) {
|
|
409
408
|
const newScrollTop = this.ganttChart.getVerticalOffset()
|
|
410
409
|
this.taskTableContainer.scrollTop = newScrollTop
|
|
411
|
-
this.ganttChart.setVerticalOffset(this.taskTableContainer.scrollTop)
|
|
412
410
|
|
|
413
411
|
const newScrollLeft = this.ganttChart.getHorizontalOffset()
|
|
414
412
|
this.resourceChart.setHorizontalOffset(newScrollLeft)
|
|
415
413
|
} else if (target === this.resourceChart) {
|
|
416
|
-
const newScrollTop = this.
|
|
414
|
+
const newScrollTop = this.resourceChart.getVerticalOffset()
|
|
417
415
|
this.resourceTableContainer.scrollTop = newScrollTop
|
|
418
|
-
this.resourceChart.setVerticalOffset(this.taskTableContainer.scrollTop)
|
|
419
416
|
|
|
420
417
|
const newScrollLeft = this.resourceChart.getHorizontalOffset()
|
|
421
418
|
this.ganttChart.setHorizontalOffset(newScrollLeft)
|
|
422
419
|
} else if (target === this.resourceTableContainer) {
|
|
423
|
-
const newScrollTop = this.
|
|
420
|
+
const newScrollTop = this.resourceTableContainer.scrollTop
|
|
424
421
|
this.resourceChart.setVerticalOffset(newScrollTop)
|
|
425
|
-
|
|
426
|
-
if (this.resourceChart.getVerticalOffset() !== newScrollTop) {
|
|
427
|
-
this.resourceChart.setVerticalOffset(newScrollTop)
|
|
428
|
-
}
|
|
429
422
|
}
|
|
430
423
|
}
|
|
431
424
|
|