@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.
@@ -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
- if (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {
170
- this.container.scrollBy({
171
- left: event.shiftKey ? event.deltaX : event.deltaY
172
- })
173
- } else {
174
- const zoomFactor = event.deltaY < 0 ? 1.1 : 0.9
175
- this.ganttChartController.baseWidth *= zoomFactor
176
-
177
- if (this.ganttChartController.baseWidth > 40) {
178
- if (this.ganttChartController.level == 'week-day') {
179
- this.ganttChartController.baseWidth = 40
180
- } else {
181
- this.ganttChartController.level = levelDown(this.ganttChartController.level)
182
- this.ganttChartController.baseWidth = 30
183
- }
184
- } else if (this.ganttChartController.baseWidth < 30) {
185
- if (this.ganttChartController.level == 'year-quarter') {
186
- this.ganttChartController.baseWidth = 30
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
- if (this.ganttChartController.baseWidth < 20) {
190
- this.ganttChartController.level = levelUp(this.ganttChartController.level)
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
- this.ganttChartController.updateTimeScale()
195
- this.requestUpdate()
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-on-surface));
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-on-surface));
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-on-surface));
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-on-surface));
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-on-surface));
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-on-surface));
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: Array }) columnConfig: ColumnConfig[] = [
139
- { name: 'id', label: i18next.t('label.gantt-task-id') || 'ID', visible: true, width: 50, order: 1 },
140
- {
141
- name: 'section',
142
- label: i18next.t('label.gantt-task-section') || 'section',
143
- visible: true,
144
- width: 100,
145
- order: 2
146
- },
147
- { name: 'title', label: i18next.t('label.gantt-task-title') || 'title', visible: true, width: 150, order: 3 },
148
- { name: 'type', label: i18next.t('label.gantt-task-type') || 'type', visible: true, width: 100, order: 4 },
149
- {
150
- name: 'startDate',
151
- label: i18next.t('label.gantt-task-start-date') || 'start date',
152
- visible: true,
153
- width: 100,
154
- order: 5
155
- },
156
- {
157
- name: 'endDate',
158
- label: i18next.t('label.gantt-task-end-date') || 'end date',
159
- visible: true,
160
- width: 100,
161
- order: 6
162
- },
163
- { name: 'tags', label: i18next.t('label.gantt-task-tags') || 'tags', visible: true, width: 100, order: 7 },
164
- {
165
- name: 'progress',
166
- label: i18next.t('label.gantt-task-progress') || 'progress',
167
- visible: true,
168
- width: 100,
169
- order: 8
170
- },
171
- {
172
- name: 'dependsOn',
173
- label: i18next.t('label.gantt-task-previous') || 'previous',
174
- visible: true,
175
- width: 100,
176
- order: 9
177
- },
178
- {
179
- name: 'resources',
180
- label: i18next.t('label.gantt-task-resources') || 'resources',
181
- visible: true,
182
- width: 100,
183
- order: 10
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
- if (!this.columnConfig) {
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 = [...this.columnConfig].sort((a, b) => a.order - b.order)
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
- ${this.columnConfig.map(col =>
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.ganttChart.getVerticalOffset()
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.taskTableContainer.scrollTop
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