gantt-canvas-chart 1.3.1 → 1.5.0
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/dist/index.cjs.js +30 -12
- package/dist/index.css +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.es.js +30 -12
- package/dist/index.umd.js +30 -12
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.
|
|
2
|
+
* gantt-canvas-chart v1.5.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -121,6 +121,9 @@ class GanttChart {
|
|
|
121
121
|
onDataLoad = null;
|
|
122
122
|
scrollLoadTimer = null;
|
|
123
123
|
constructor(rootContainer, data, config = {}) {
|
|
124
|
+
if (rootContainer.querySelector(".__gantt-chart-container")) {
|
|
125
|
+
throw new Error("GanttChart already exists in this container");
|
|
126
|
+
}
|
|
124
127
|
const container = document.createElement("div");
|
|
125
128
|
const scrollEl = document.createElement("div");
|
|
126
129
|
const headerCanvas = document.createElement("canvas");
|
|
@@ -157,6 +160,7 @@ class GanttChart {
|
|
|
157
160
|
todayColor: "#ff4d4f",
|
|
158
161
|
offsetTop: 0,
|
|
159
162
|
offsetLeft: 0,
|
|
163
|
+
scrollEdgeThresholds: 10,
|
|
160
164
|
enabledLoadMore: [],
|
|
161
165
|
viewFactors: { Day: 80, Week: 20, Month: 15, Year: 6 },
|
|
162
166
|
planBorderColor: "#C1EFCF",
|
|
@@ -201,8 +205,8 @@ class GanttChart {
|
|
|
201
205
|
}
|
|
202
206
|
init() {
|
|
203
207
|
this.buildTaskMap();
|
|
204
|
-
this.calculateFullTimeline();
|
|
205
208
|
this.updatePixelsPerDay();
|
|
209
|
+
this.calculateFullTimeline();
|
|
206
210
|
this.setupEvents();
|
|
207
211
|
this.handleResize();
|
|
208
212
|
}
|
|
@@ -274,6 +278,9 @@ class GanttChart {
|
|
|
274
278
|
maxDate = DateUtils.addDays(/* @__PURE__ */ new Date(), 60);
|
|
275
279
|
} else {
|
|
276
280
|
this.taskMap.forEach(({ task }) => {
|
|
281
|
+
if (task.hide) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
277
284
|
const pStart = new Date(task.planStart);
|
|
278
285
|
const pEnd = new Date(task.planEnd);
|
|
279
286
|
if (pStart < minDate) minDate = pStart;
|
|
@@ -307,8 +314,8 @@ class GanttChart {
|
|
|
307
314
|
break;
|
|
308
315
|
case "Day":
|
|
309
316
|
default:
|
|
310
|
-
this.timelineStart = DateUtils.addDays(minDate,
|
|
311
|
-
this.timelineEnd = DateUtils.addDays(maxDate,
|
|
317
|
+
this.timelineStart = DateUtils.addDays(minDate, 3);
|
|
318
|
+
this.timelineEnd = DateUtils.addDays(maxDate, -5);
|
|
312
319
|
break;
|
|
313
320
|
}
|
|
314
321
|
}
|
|
@@ -372,9 +379,10 @@ class GanttChart {
|
|
|
372
379
|
const viewportHeight = this.viewportHeight;
|
|
373
380
|
const totalWidth = this.totalWidth;
|
|
374
381
|
const totalHeight = this.totalHeight;
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
const
|
|
382
|
+
const thresholds = this.config.scrollEdgeThresholds;
|
|
383
|
+
const atLeftEdge = scrollLeft <= thresholds;
|
|
384
|
+
const atRightEdge = scrollLeft + viewportWidth >= totalWidth - thresholds;
|
|
385
|
+
const atBottomEdge = scrollTop + viewportHeight >= totalHeight - thresholds;
|
|
378
386
|
try {
|
|
379
387
|
if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
|
|
380
388
|
await this.loadMoreData("left");
|
|
@@ -390,9 +398,7 @@ class GanttChart {
|
|
|
390
398
|
}
|
|
391
399
|
// Add this method to reset scroll loading state
|
|
392
400
|
resetScrollLoadingState() {
|
|
393
|
-
this.
|
|
394
|
-
this.hasMoreDataRight = true;
|
|
395
|
-
this.hasMoreDataBottom = true;
|
|
401
|
+
this.updateLoadMoreConf();
|
|
396
402
|
this.lastScrollLeft = 0;
|
|
397
403
|
this.lastScrollTop = 0;
|
|
398
404
|
if (this.scrollLoadTimer !== null) {
|
|
@@ -475,7 +481,7 @@ class GanttChart {
|
|
|
475
481
|
if (this.scrollTop !== scrollTop) this.container.scrollTop = scrollTop;
|
|
476
482
|
}
|
|
477
483
|
updateVirtualRanges() {
|
|
478
|
-
const buffer =
|
|
484
|
+
const buffer = 100;
|
|
479
485
|
this.visibleDateRange = {
|
|
480
486
|
start: this.xToDate(this.scrollLeft - buffer),
|
|
481
487
|
end: this.xToDate(this.scrollLeft + this.viewportWidth + buffer)
|
|
@@ -505,8 +511,14 @@ class GanttChart {
|
|
|
505
511
|
this.taskPositions.clear();
|
|
506
512
|
for (let i = 0; i < this.data.length; i++) {
|
|
507
513
|
const row = this.data[i];
|
|
514
|
+
if (row.hide) {
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
508
517
|
const y = i * this.config.rowHeight;
|
|
509
518
|
row.tasks.forEach((task) => {
|
|
519
|
+
if (task.hide) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
510
522
|
const x_plan_start = this.dateToX(new Date(task.planStart));
|
|
511
523
|
const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
|
|
512
524
|
let x_actual_start = null, x_actual_end = null;
|
|
@@ -514,19 +526,25 @@ class GanttChart {
|
|
|
514
526
|
let offset_x_actual_start = null, offset_x_actual_end = null;
|
|
515
527
|
let x_plan_width = 0;
|
|
516
528
|
let x_actual_width = 0;
|
|
529
|
+
let isValidPlanTask = false, isValidActualTask = false;
|
|
517
530
|
const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
|
|
518
531
|
const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
|
|
519
|
-
if (x_plan_start && x_plan_end) {
|
|
532
|
+
if (x_plan_start && x_plan_end && x_plan_start < x_plan_end) {
|
|
520
533
|
x_plan_width = x_plan_end - x_plan_start;
|
|
521
534
|
offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
|
|
522
535
|
x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
|
|
536
|
+
isValidPlanTask = true;
|
|
523
537
|
}
|
|
524
538
|
if (task.actualStart) {
|
|
525
539
|
x_actual_start = this.dateToX(new Date(task.actualStart));
|
|
540
|
+
isValidActualTask = true;
|
|
526
541
|
}
|
|
527
542
|
if (task.actualEnd) {
|
|
528
543
|
x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
|
|
529
544
|
}
|
|
545
|
+
if (!isValidPlanTask && !isValidActualTask) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
530
548
|
if (x_actual_start) {
|
|
531
549
|
x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
|
|
532
550
|
offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
|
package/dist/index.css
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare function firstValidValue(...args: any[]): any;
|
|
|
23
23
|
export declare class GanttChart {
|
|
24
24
|
private rootContainer;
|
|
25
25
|
container: HTMLElement;
|
|
26
|
-
|
|
26
|
+
data: GanttData;
|
|
27
27
|
private config;
|
|
28
28
|
private headerCanvas;
|
|
29
29
|
private mainCanvas;
|
|
@@ -142,6 +142,7 @@ export declare interface GanttConfig {
|
|
|
142
142
|
todayColor?: string;
|
|
143
143
|
offsetTop?: number;
|
|
144
144
|
offsetLeft?: number;
|
|
145
|
+
scrollEdgeThresholds?: number;
|
|
145
146
|
enabledLoadMore?: [LoadMoreDirection?, LoadMoreDirection?, LoadMoreDirection?];
|
|
146
147
|
viewFactors?: {
|
|
147
148
|
Day: number;
|
|
@@ -159,13 +160,14 @@ export declare type LoadMoreDirection = 'left' | 'right' | 'bottom';
|
|
|
159
160
|
export declare interface Row {
|
|
160
161
|
id: string;
|
|
161
162
|
name: string;
|
|
163
|
+
hide?: boolean;
|
|
162
164
|
tasks: Task[];
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
export declare interface Task {
|
|
166
168
|
id: string;
|
|
167
169
|
name: string;
|
|
168
|
-
type?: 'task' | 'leave';
|
|
170
|
+
type?: 'task' | 'leave' | 'overtime' | string;
|
|
169
171
|
planStart?: string;
|
|
170
172
|
planEnd?: string;
|
|
171
173
|
actualStart?: string;
|
|
@@ -177,6 +179,7 @@ export declare interface Task {
|
|
|
177
179
|
styleClass?: string;
|
|
178
180
|
planBorderColor?: string;
|
|
179
181
|
actualBgColor?: string;
|
|
182
|
+
hide?: boolean;
|
|
180
183
|
_data?: any;
|
|
181
184
|
planOffsetPercent?: [number, number];
|
|
182
185
|
actualOffsetPercent?: [number, number];
|
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.
|
|
2
|
+
* gantt-canvas-chart v1.5.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -119,6 +119,9 @@ class GanttChart {
|
|
|
119
119
|
onDataLoad = null;
|
|
120
120
|
scrollLoadTimer = null;
|
|
121
121
|
constructor(rootContainer, data, config = {}) {
|
|
122
|
+
if (rootContainer.querySelector(".__gantt-chart-container")) {
|
|
123
|
+
throw new Error("GanttChart already exists in this container");
|
|
124
|
+
}
|
|
122
125
|
const container = document.createElement("div");
|
|
123
126
|
const scrollEl = document.createElement("div");
|
|
124
127
|
const headerCanvas = document.createElement("canvas");
|
|
@@ -155,6 +158,7 @@ class GanttChart {
|
|
|
155
158
|
todayColor: "#ff4d4f",
|
|
156
159
|
offsetTop: 0,
|
|
157
160
|
offsetLeft: 0,
|
|
161
|
+
scrollEdgeThresholds: 10,
|
|
158
162
|
enabledLoadMore: [],
|
|
159
163
|
viewFactors: { Day: 80, Week: 20, Month: 15, Year: 6 },
|
|
160
164
|
planBorderColor: "#C1EFCF",
|
|
@@ -199,8 +203,8 @@ class GanttChart {
|
|
|
199
203
|
}
|
|
200
204
|
init() {
|
|
201
205
|
this.buildTaskMap();
|
|
202
|
-
this.calculateFullTimeline();
|
|
203
206
|
this.updatePixelsPerDay();
|
|
207
|
+
this.calculateFullTimeline();
|
|
204
208
|
this.setupEvents();
|
|
205
209
|
this.handleResize();
|
|
206
210
|
}
|
|
@@ -272,6 +276,9 @@ class GanttChart {
|
|
|
272
276
|
maxDate = DateUtils.addDays(/* @__PURE__ */ new Date(), 60);
|
|
273
277
|
} else {
|
|
274
278
|
this.taskMap.forEach(({ task }) => {
|
|
279
|
+
if (task.hide) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
275
282
|
const pStart = new Date(task.planStart);
|
|
276
283
|
const pEnd = new Date(task.planEnd);
|
|
277
284
|
if (pStart < minDate) minDate = pStart;
|
|
@@ -305,8 +312,8 @@ class GanttChart {
|
|
|
305
312
|
break;
|
|
306
313
|
case "Day":
|
|
307
314
|
default:
|
|
308
|
-
this.timelineStart = DateUtils.addDays(minDate,
|
|
309
|
-
this.timelineEnd = DateUtils.addDays(maxDate,
|
|
315
|
+
this.timelineStart = DateUtils.addDays(minDate, 3);
|
|
316
|
+
this.timelineEnd = DateUtils.addDays(maxDate, -5);
|
|
310
317
|
break;
|
|
311
318
|
}
|
|
312
319
|
}
|
|
@@ -370,9 +377,10 @@ class GanttChart {
|
|
|
370
377
|
const viewportHeight = this.viewportHeight;
|
|
371
378
|
const totalWidth = this.totalWidth;
|
|
372
379
|
const totalHeight = this.totalHeight;
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
const
|
|
380
|
+
const thresholds = this.config.scrollEdgeThresholds;
|
|
381
|
+
const atLeftEdge = scrollLeft <= thresholds;
|
|
382
|
+
const atRightEdge = scrollLeft + viewportWidth >= totalWidth - thresholds;
|
|
383
|
+
const atBottomEdge = scrollTop + viewportHeight >= totalHeight - thresholds;
|
|
376
384
|
try {
|
|
377
385
|
if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
|
|
378
386
|
await this.loadMoreData("left");
|
|
@@ -388,9 +396,7 @@ class GanttChart {
|
|
|
388
396
|
}
|
|
389
397
|
// Add this method to reset scroll loading state
|
|
390
398
|
resetScrollLoadingState() {
|
|
391
|
-
this.
|
|
392
|
-
this.hasMoreDataRight = true;
|
|
393
|
-
this.hasMoreDataBottom = true;
|
|
399
|
+
this.updateLoadMoreConf();
|
|
394
400
|
this.lastScrollLeft = 0;
|
|
395
401
|
this.lastScrollTop = 0;
|
|
396
402
|
if (this.scrollLoadTimer !== null) {
|
|
@@ -473,7 +479,7 @@ class GanttChart {
|
|
|
473
479
|
if (this.scrollTop !== scrollTop) this.container.scrollTop = scrollTop;
|
|
474
480
|
}
|
|
475
481
|
updateVirtualRanges() {
|
|
476
|
-
const buffer =
|
|
482
|
+
const buffer = 100;
|
|
477
483
|
this.visibleDateRange = {
|
|
478
484
|
start: this.xToDate(this.scrollLeft - buffer),
|
|
479
485
|
end: this.xToDate(this.scrollLeft + this.viewportWidth + buffer)
|
|
@@ -503,8 +509,14 @@ class GanttChart {
|
|
|
503
509
|
this.taskPositions.clear();
|
|
504
510
|
for (let i = 0; i < this.data.length; i++) {
|
|
505
511
|
const row = this.data[i];
|
|
512
|
+
if (row.hide) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
506
515
|
const y = i * this.config.rowHeight;
|
|
507
516
|
row.tasks.forEach((task) => {
|
|
517
|
+
if (task.hide) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
508
520
|
const x_plan_start = this.dateToX(new Date(task.planStart));
|
|
509
521
|
const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
|
|
510
522
|
let x_actual_start = null, x_actual_end = null;
|
|
@@ -512,19 +524,25 @@ class GanttChart {
|
|
|
512
524
|
let offset_x_actual_start = null, offset_x_actual_end = null;
|
|
513
525
|
let x_plan_width = 0;
|
|
514
526
|
let x_actual_width = 0;
|
|
527
|
+
let isValidPlanTask = false, isValidActualTask = false;
|
|
515
528
|
const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
|
|
516
529
|
const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
|
|
517
|
-
if (x_plan_start && x_plan_end) {
|
|
530
|
+
if (x_plan_start && x_plan_end && x_plan_start < x_plan_end) {
|
|
518
531
|
x_plan_width = x_plan_end - x_plan_start;
|
|
519
532
|
offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
|
|
520
533
|
x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
|
|
534
|
+
isValidPlanTask = true;
|
|
521
535
|
}
|
|
522
536
|
if (task.actualStart) {
|
|
523
537
|
x_actual_start = this.dateToX(new Date(task.actualStart));
|
|
538
|
+
isValidActualTask = true;
|
|
524
539
|
}
|
|
525
540
|
if (task.actualEnd) {
|
|
526
541
|
x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
|
|
527
542
|
}
|
|
543
|
+
if (!isValidPlanTask && !isValidActualTask) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
528
546
|
if (x_actual_start) {
|
|
529
547
|
x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
|
|
530
548
|
offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
|
package/dist/index.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* gantt-canvas-chart v1.
|
|
2
|
+
* gantt-canvas-chart v1.5.0
|
|
3
3
|
* (c) 2025-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -123,6 +123,9 @@
|
|
|
123
123
|
onDataLoad = null;
|
|
124
124
|
scrollLoadTimer = null;
|
|
125
125
|
constructor(rootContainer, data, config = {}) {
|
|
126
|
+
if (rootContainer.querySelector(".__gantt-chart-container")) {
|
|
127
|
+
throw new Error("GanttChart already exists in this container");
|
|
128
|
+
}
|
|
126
129
|
const container = document.createElement("div");
|
|
127
130
|
const scrollEl = document.createElement("div");
|
|
128
131
|
const headerCanvas = document.createElement("canvas");
|
|
@@ -159,6 +162,7 @@
|
|
|
159
162
|
todayColor: "#ff4d4f",
|
|
160
163
|
offsetTop: 0,
|
|
161
164
|
offsetLeft: 0,
|
|
165
|
+
scrollEdgeThresholds: 10,
|
|
162
166
|
enabledLoadMore: [],
|
|
163
167
|
viewFactors: { Day: 80, Week: 20, Month: 15, Year: 6 },
|
|
164
168
|
planBorderColor: "#C1EFCF",
|
|
@@ -203,8 +207,8 @@
|
|
|
203
207
|
}
|
|
204
208
|
init() {
|
|
205
209
|
this.buildTaskMap();
|
|
206
|
-
this.calculateFullTimeline();
|
|
207
210
|
this.updatePixelsPerDay();
|
|
211
|
+
this.calculateFullTimeline();
|
|
208
212
|
this.setupEvents();
|
|
209
213
|
this.handleResize();
|
|
210
214
|
}
|
|
@@ -276,6 +280,9 @@
|
|
|
276
280
|
maxDate = DateUtils.addDays(/* @__PURE__ */ new Date(), 60);
|
|
277
281
|
} else {
|
|
278
282
|
this.taskMap.forEach(({ task }) => {
|
|
283
|
+
if (task.hide) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
279
286
|
const pStart = new Date(task.planStart);
|
|
280
287
|
const pEnd = new Date(task.planEnd);
|
|
281
288
|
if (pStart < minDate) minDate = pStart;
|
|
@@ -309,8 +316,8 @@
|
|
|
309
316
|
break;
|
|
310
317
|
case "Day":
|
|
311
318
|
default:
|
|
312
|
-
this.timelineStart = DateUtils.addDays(minDate,
|
|
313
|
-
this.timelineEnd = DateUtils.addDays(maxDate,
|
|
319
|
+
this.timelineStart = DateUtils.addDays(minDate, 3);
|
|
320
|
+
this.timelineEnd = DateUtils.addDays(maxDate, -5);
|
|
314
321
|
break;
|
|
315
322
|
}
|
|
316
323
|
}
|
|
@@ -374,9 +381,10 @@
|
|
|
374
381
|
const viewportHeight = this.viewportHeight;
|
|
375
382
|
const totalWidth = this.totalWidth;
|
|
376
383
|
const totalHeight = this.totalHeight;
|
|
377
|
-
const
|
|
378
|
-
const
|
|
379
|
-
const
|
|
384
|
+
const thresholds = this.config.scrollEdgeThresholds;
|
|
385
|
+
const atLeftEdge = scrollLeft <= thresholds;
|
|
386
|
+
const atRightEdge = scrollLeft + viewportWidth >= totalWidth - thresholds;
|
|
387
|
+
const atBottomEdge = scrollTop + viewportHeight >= totalHeight - thresholds;
|
|
380
388
|
try {
|
|
381
389
|
if (this.hasMoreDataLeft && atLeftEdge && scrollLeft < this.lastScrollLeft) {
|
|
382
390
|
await this.loadMoreData("left");
|
|
@@ -392,9 +400,7 @@
|
|
|
392
400
|
}
|
|
393
401
|
// Add this method to reset scroll loading state
|
|
394
402
|
resetScrollLoadingState() {
|
|
395
|
-
this.
|
|
396
|
-
this.hasMoreDataRight = true;
|
|
397
|
-
this.hasMoreDataBottom = true;
|
|
403
|
+
this.updateLoadMoreConf();
|
|
398
404
|
this.lastScrollLeft = 0;
|
|
399
405
|
this.lastScrollTop = 0;
|
|
400
406
|
if (this.scrollLoadTimer !== null) {
|
|
@@ -477,7 +483,7 @@
|
|
|
477
483
|
if (this.scrollTop !== scrollTop) this.container.scrollTop = scrollTop;
|
|
478
484
|
}
|
|
479
485
|
updateVirtualRanges() {
|
|
480
|
-
const buffer =
|
|
486
|
+
const buffer = 100;
|
|
481
487
|
this.visibleDateRange = {
|
|
482
488
|
start: this.xToDate(this.scrollLeft - buffer),
|
|
483
489
|
end: this.xToDate(this.scrollLeft + this.viewportWidth + buffer)
|
|
@@ -507,8 +513,14 @@
|
|
|
507
513
|
this.taskPositions.clear();
|
|
508
514
|
for (let i = 0; i < this.data.length; i++) {
|
|
509
515
|
const row = this.data[i];
|
|
516
|
+
if (row.hide) {
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
510
519
|
const y = i * this.config.rowHeight;
|
|
511
520
|
row.tasks.forEach((task) => {
|
|
521
|
+
if (task.hide) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
512
524
|
const x_plan_start = this.dateToX(new Date(task.planStart));
|
|
513
525
|
const x_plan_end = this.dateToX(DateUtils.addDays(task.planEnd, 1));
|
|
514
526
|
let x_actual_start = null, x_actual_end = null;
|
|
@@ -516,19 +528,25 @@
|
|
|
516
528
|
let offset_x_actual_start = null, offset_x_actual_end = null;
|
|
517
529
|
let x_plan_width = 0;
|
|
518
530
|
let x_actual_width = 0;
|
|
531
|
+
let isValidPlanTask = false, isValidActualTask = false;
|
|
519
532
|
const [offsetX_actual, percent_actual] = this.config.viewMode === "Day" && task.actualOffsetPercent ? task.actualOffsetPercent : [0, 1];
|
|
520
533
|
const [offsetX, percent_plan] = this.config.viewMode === "Day" && task.planOffsetPercent ? task.planOffsetPercent : [0, 1];
|
|
521
|
-
if (x_plan_start && x_plan_end) {
|
|
534
|
+
if (x_plan_start && x_plan_end && x_plan_start < x_plan_end) {
|
|
522
535
|
x_plan_width = x_plan_end - x_plan_start;
|
|
523
536
|
offset_x_plan_start = x_plan_start + x_plan_width * offsetX;
|
|
524
537
|
x_plan_end && (offset_x_plan_end = offset_x_plan_start + x_plan_width * percent_plan);
|
|
538
|
+
isValidPlanTask = true;
|
|
525
539
|
}
|
|
526
540
|
if (task.actualStart) {
|
|
527
541
|
x_actual_start = this.dateToX(new Date(task.actualStart));
|
|
542
|
+
isValidActualTask = true;
|
|
528
543
|
}
|
|
529
544
|
if (task.actualEnd) {
|
|
530
545
|
x_actual_end = this.dateToX(DateUtils.addDays(task.actualEnd, 1));
|
|
531
546
|
}
|
|
547
|
+
if (!isValidPlanTask && !isValidActualTask) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
532
550
|
if (x_actual_start) {
|
|
533
551
|
x_actual_width = (x_actual_end ? x_actual_end : this.dateToX(this.today)) - x_actual_start;
|
|
534
552
|
offset_x_actual_start = Math.round(x_actual_start + x_actual_width * offsetX_actual);
|