@syncfusion/ej2-gantt 19.4.56 → 20.1.47-1460716

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.
Files changed (211) hide show
  1. package/CHANGELOG.md +1072 -1060
  2. package/README.md +75 -75
  3. package/dist/ej2-gantt.umd.min.js +1 -10
  4. package/dist/ej2-gantt.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-gantt.es2015.js +274 -176
  6. package/dist/es6/ej2-gantt.es2015.js.map +1 -1
  7. package/dist/es6/ej2-gantt.es5.js +642 -534
  8. package/dist/es6/ej2-gantt.es5.js.map +1 -1
  9. package/dist/global/ej2-gantt.min.js +1 -10
  10. package/dist/global/ej2-gantt.min.js.map +1 -1
  11. package/dist/global/index.d.ts +0 -9
  12. package/dist/ts/components.ts +4 -0
  13. package/dist/ts/gantt/actions/actions.ts +18 -0
  14. package/dist/ts/gantt/actions/cell-edit.ts +606 -0
  15. package/dist/ts/gantt/actions/chart-scroll.ts +167 -0
  16. package/dist/ts/gantt/actions/column-menu.ts +35 -0
  17. package/dist/ts/gantt/actions/column-reorder.ts +52 -0
  18. package/dist/ts/gantt/actions/column-resize.ts +52 -0
  19. package/dist/ts/gantt/actions/connector-line-edit.ts +829 -0
  20. package/dist/ts/gantt/actions/context-menu.ts +754 -0
  21. package/dist/ts/gantt/actions/day-markers.ts +80 -0
  22. package/dist/ts/gantt/actions/dependency.ts +692 -0
  23. package/dist/ts/gantt/actions/dialog-edit.ts +2208 -0
  24. package/dist/ts/gantt/actions/edit.ts +3499 -0
  25. package/dist/ts/gantt/actions/excel-export.ts +61 -0
  26. package/dist/ts/gantt/actions/filter.ts +302 -0
  27. package/dist/ts/gantt/actions/keyboard.ts +306 -0
  28. package/dist/ts/gantt/actions/pdf-export.ts +214 -0
  29. package/dist/ts/gantt/actions/rowdragdrop.ts +839 -0
  30. package/dist/ts/gantt/actions/selection.ts +536 -0
  31. package/dist/ts/gantt/actions/sort.ts +98 -0
  32. package/dist/ts/gantt/actions/taskbar-edit.ts +1940 -0
  33. package/dist/ts/gantt/actions/toolbar.ts +489 -0
  34. package/dist/ts/gantt/actions/virtual-scroll.ts +60 -0
  35. package/dist/ts/gantt/base/common.ts +9 -0
  36. package/dist/ts/gantt/base/constant.ts +13 -0
  37. package/dist/ts/gantt/base/css-constants.ts +148 -0
  38. package/dist/ts/gantt/base/date-processor.ts +1257 -0
  39. package/dist/ts/gantt/base/enum.ts +372 -0
  40. package/dist/ts/gantt/base/gantt-chart.ts +1248 -0
  41. package/dist/ts/gantt/base/gantt.ts +4069 -0
  42. package/dist/ts/gantt/base/interface.ts +955 -0
  43. package/dist/ts/gantt/base/splitter.ts +174 -0
  44. package/dist/ts/gantt/base/task-processor.ts +2217 -0
  45. package/dist/ts/gantt/base/tree-grid.ts +694 -0
  46. package/dist/ts/gantt/base/utils.ts +208 -0
  47. package/dist/ts/gantt/export/export-helper.ts +552 -0
  48. package/dist/ts/gantt/export/pdf-base/dictionary.ts +152 -0
  49. package/dist/ts/gantt/export/pdf-base/pdf-borders.ts +277 -0
  50. package/dist/ts/gantt/export/pdf-base/pdf-grid-table.ts +901 -0
  51. package/dist/ts/gantt/export/pdf-base/pdf-style/gantt-theme.ts +131 -0
  52. package/dist/ts/gantt/export/pdf-base/pdf-style/style.ts +91 -0
  53. package/dist/ts/gantt/export/pdf-base/treegrid-layouter.ts +414 -0
  54. package/dist/ts/gantt/export/pdf-connector-line.ts +422 -0
  55. package/dist/ts/gantt/export/pdf-gantt.ts +282 -0
  56. package/dist/ts/gantt/export/pdf-taskbar.ts +395 -0
  57. package/dist/ts/gantt/export/pdf-timeline.ts +202 -0
  58. package/dist/ts/gantt/export/pdf-treegrid.ts +406 -0
  59. package/dist/ts/gantt/models/add-dialog-field-settings.ts +33 -0
  60. package/dist/ts/gantt/models/column.ts +464 -0
  61. package/dist/ts/gantt/models/day-working-time.ts +22 -0
  62. package/dist/ts/gantt/models/edit-dialog-field-settings.ts +33 -0
  63. package/dist/ts/gantt/models/edit-settings.ts +79 -0
  64. package/dist/ts/gantt/models/event-marker.ts +27 -0
  65. package/dist/ts/gantt/models/filter-settings.ts +53 -0
  66. package/dist/ts/gantt/models/holiday.ts +34 -0
  67. package/dist/ts/gantt/models/label-settings.ts +30 -0
  68. package/dist/ts/gantt/models/models.ts +36 -0
  69. package/dist/ts/gantt/models/resource-fields.ts +38 -0
  70. package/dist/ts/gantt/models/search-settings.ts +77 -0
  71. package/dist/ts/gantt/models/selection-settings.ts +56 -0
  72. package/dist/ts/gantt/models/sort-settings.ts +50 -0
  73. package/dist/ts/gantt/models/splitter-settings.ts +47 -0
  74. package/dist/ts/gantt/models/task-fields.ts +171 -0
  75. package/dist/ts/gantt/models/timeline-settings.ts +112 -0
  76. package/dist/ts/gantt/models/tooltip-settings.ts +46 -0
  77. package/dist/ts/gantt/renderer/chart-rows.ts +1838 -0
  78. package/dist/ts/gantt/renderer/connector-line.ts +1025 -0
  79. package/dist/ts/gantt/renderer/edit-tooltip.ts +228 -0
  80. package/dist/ts/gantt/renderer/event-marker.ts +96 -0
  81. package/dist/ts/gantt/renderer/nonworking-day.ts +205 -0
  82. package/dist/ts/gantt/renderer/render.ts +5 -0
  83. package/dist/ts/gantt/renderer/timeline.ts +1397 -0
  84. package/dist/ts/gantt/renderer/tooltip.ts +450 -0
  85. package/dist/ts/gantt/renderer/virtual-content-render.ts +50 -0
  86. package/license +9 -9
  87. package/package.json +80 -80
  88. package/src/gantt/actions/cell-edit.js +2 -1
  89. package/src/gantt/actions/dialog-edit.js +2 -1
  90. package/src/gantt/actions/edit.js +11 -2
  91. package/src/gantt/actions/rowdragdrop.js +37 -15
  92. package/src/gantt/actions/taskbar-edit.js +24 -24
  93. package/src/gantt/base/date-processor.js +0 -1
  94. package/src/gantt/base/gantt-chart.js +9 -4
  95. package/src/gantt/base/gantt-model.d.ts +779 -779
  96. package/src/gantt/base/gantt.d.ts +27 -27
  97. package/src/gantt/base/gantt.js +22 -22
  98. package/src/gantt/base/splitter.js +1 -0
  99. package/src/gantt/base/task-processor.js +13 -13
  100. package/src/gantt/base/tree-grid.js +3 -1
  101. package/src/gantt/export/pdf-base/treegrid-layouter.js +13 -13
  102. package/src/gantt/export/pdf-connector-line.js +11 -11
  103. package/src/gantt/export/pdf-gantt.js +24 -24
  104. package/src/gantt/export/pdf-taskbar.js +11 -11
  105. package/src/gantt/export/pdf-treegrid.js +13 -13
  106. package/src/gantt/models/add-dialog-field-settings-model.d.ts +21 -21
  107. package/src/gantt/models/add-dialog-field-settings.js +19 -19
  108. package/src/gantt/models/day-working-time-model.d.ts +11 -11
  109. package/src/gantt/models/day-working-time.js +19 -19
  110. package/src/gantt/models/edit-dialog-field-settings-model.d.ts +21 -21
  111. package/src/gantt/models/edit-dialog-field-settings.js +19 -19
  112. package/src/gantt/models/edit-settings-model.d.ts +50 -50
  113. package/src/gantt/models/edit-settings.js +19 -19
  114. package/src/gantt/models/event-marker-model.d.ts +16 -16
  115. package/src/gantt/models/event-marker.js +19 -19
  116. package/src/gantt/models/filter-settings-model.d.ts +34 -34
  117. package/src/gantt/models/filter-settings.js +19 -19
  118. package/src/gantt/models/holiday-model.d.ts +21 -21
  119. package/src/gantt/models/holiday.js +19 -19
  120. package/src/gantt/models/label-settings-model.d.ts +16 -16
  121. package/src/gantt/models/label-settings.js +19 -19
  122. package/src/gantt/models/resource-fields-model.d.ts +21 -21
  123. package/src/gantt/models/resource-fields.js +19 -19
  124. package/src/gantt/models/search-settings-model.d.ts +56 -56
  125. package/src/gantt/models/search-settings.js +19 -19
  126. package/src/gantt/models/selection-settings-model.d.ts +35 -35
  127. package/src/gantt/models/selection-settings.js +19 -19
  128. package/src/gantt/models/sort-settings-model.d.ts +24 -24
  129. package/src/gantt/models/sort-settings.js +19 -19
  130. package/src/gantt/models/splitter-settings-model.d.ts +30 -30
  131. package/src/gantt/models/splitter-settings.js +19 -19
  132. package/src/gantt/models/task-fields-model.d.ts +110 -110
  133. package/src/gantt/models/task-fields.js +19 -19
  134. package/src/gantt/models/timeline-settings-model.d.ts +71 -71
  135. package/src/gantt/models/timeline-settings.js +19 -19
  136. package/src/gantt/models/tooltip-settings-model.d.ts +26 -26
  137. package/src/gantt/models/tooltip-settings.js +19 -19
  138. package/src/gantt/renderer/chart-rows.js +49 -37
  139. package/src/gantt/renderer/connector-line.js +22 -18
  140. package/src/gantt/renderer/event-marker.js +1 -0
  141. package/src/gantt/renderer/nonworking-day.js +13 -6
  142. package/src/gantt/renderer/timeline.d.ts +1 -0
  143. package/src/gantt/renderer/timeline.js +48 -12
  144. package/src/gantt/renderer/tooltip.js +11 -3
  145. package/styles/bootstrap-dark.css +442 -427
  146. package/styles/bootstrap.css +442 -433
  147. package/styles/bootstrap4.css +454 -479
  148. package/styles/bootstrap5-dark.css +457 -433
  149. package/styles/bootstrap5.css +457 -433
  150. package/styles/fabric-dark.css +438 -421
  151. package/styles/fabric.css +445 -428
  152. package/styles/fluent-dark.css +1938 -0
  153. package/styles/fluent-dark.scss +1 -0
  154. package/styles/fluent.css +1938 -0
  155. package/styles/fluent.scss +1 -0
  156. package/styles/gantt/_all.scss +2 -2
  157. package/styles/gantt/_bootstrap-dark-definition.scss +210 -156
  158. package/styles/gantt/_bootstrap-definition.scss +211 -157
  159. package/styles/gantt/_bootstrap4-definition.scss +213 -158
  160. package/styles/gantt/_bootstrap5-definition.scss +215 -162
  161. package/styles/gantt/_fabric-dark-definition.scss +211 -157
  162. package/styles/gantt/_fabric-definition.scss +211 -157
  163. package/styles/gantt/_fluent-dark-definition.scss +1 -0
  164. package/styles/gantt/_fluent-definition.scss +215 -162
  165. package/styles/gantt/_fusionnew-definition.scss +214 -0
  166. package/styles/gantt/_highcontrast-definition.scss +211 -157
  167. package/styles/gantt/_highcontrast-light-definition.scss +211 -157
  168. package/styles/gantt/_layout.scss +1446 -1027
  169. package/styles/gantt/_material-dark-definition.scss +212 -157
  170. package/styles/gantt/_material-definition.scss +212 -157
  171. package/styles/gantt/_material3-definition.scss +215 -0
  172. package/styles/gantt/_tailwind-definition.scss +215 -161
  173. package/styles/gantt/_theme.scss +702 -668
  174. package/styles/gantt/bootstrap-dark.css +442 -427
  175. package/styles/gantt/bootstrap.css +442 -433
  176. package/styles/gantt/bootstrap4.css +454 -479
  177. package/styles/gantt/bootstrap5-dark.css +457 -433
  178. package/styles/gantt/bootstrap5.css +457 -433
  179. package/styles/gantt/fabric-dark.css +438 -421
  180. package/styles/gantt/fabric.css +445 -428
  181. package/styles/gantt/fluent-dark.css +1938 -0
  182. package/styles/gantt/fluent-dark.scss +22 -0
  183. package/styles/gantt/fluent.css +1938 -0
  184. package/styles/gantt/fluent.scss +22 -0
  185. package/styles/gantt/highcontrast-light.css +405 -405
  186. package/styles/gantt/highcontrast.css +444 -456
  187. package/styles/gantt/icons/_bootstrap-dark.scss +124 -113
  188. package/styles/gantt/icons/_bootstrap.scss +124 -113
  189. package/styles/gantt/icons/_bootstrap4.scss +124 -113
  190. package/styles/gantt/icons/_bootstrap5.scss +124 -112
  191. package/styles/gantt/icons/_fabric-dark.scss +124 -112
  192. package/styles/gantt/icons/_fabric.scss +124 -112
  193. package/styles/gantt/icons/_fluent-dark.scss +1 -0
  194. package/styles/gantt/icons/_fluent.scss +124 -112
  195. package/styles/gantt/icons/_fusionnew.scss +120 -0
  196. package/styles/gantt/icons/_highcontrast.scss +124 -112
  197. package/styles/gantt/icons/_material-dark.scss +124 -112
  198. package/styles/gantt/icons/_material.scss +124 -112
  199. package/styles/gantt/icons/_material3.scss +124 -0
  200. package/styles/gantt/icons/_tailwind-dark.scss +124 -113
  201. package/styles/gantt/icons/_tailwind.scss +124 -113
  202. package/styles/gantt/material-dark.css +446 -417
  203. package/styles/gantt/material.css +445 -419
  204. package/styles/gantt/tailwind-dark.css +452 -482
  205. package/styles/gantt/tailwind.css +449 -479
  206. package/styles/highcontrast-light.css +405 -405
  207. package/styles/highcontrast.css +444 -456
  208. package/styles/material-dark.css +446 -417
  209. package/styles/material.css +445 -419
  210. package/styles/tailwind-dark.css +452 -482
  211. package/styles/tailwind.css +449 -479
@@ -0,0 +1,692 @@
1
+ /**
2
+ * Predecessor calculation goes here
3
+ */
4
+ import { IGanttData, ITaskData, IPredecessor, IConnectorLineObject, ITaskSegment, IParent } from '../base/interface';
5
+ import { TaskFieldsModel } from '../models/models';
6
+ import { DateProcessor } from '../base/date-processor';
7
+ import { Gantt } from '../base/gantt';
8
+ import { isScheduledTask } from '../base/utils';
9
+ import { getValue, isNullOrUndefined, extend } from '@syncfusion/ej2-base';
10
+
11
+ export class Dependency {
12
+
13
+ private parent: Gantt;
14
+ private dateValidateModule: DateProcessor;
15
+ private parentRecord: IParent[] = [];
16
+ private parentIds: string[] = [];
17
+ constructor(gantt: Gantt) {
18
+ this.parent = gantt;
19
+ this.dateValidateModule = this.parent.dateValidationModule;
20
+ }
21
+ /**
22
+ * Method to populate predecessor collections in records
23
+ *
24
+ * @returns {void} .
25
+ * @private
26
+ */
27
+ public ensurePredecessorCollection(): void {
28
+ const predecessorTasks: IGanttData[] = this.parent.predecessorsCollection;
29
+ const length: number = predecessorTasks.length - 1;
30
+ for (let count: number = length; count >= 0; count--) {
31
+ const ganttData: IGanttData = predecessorTasks[count];
32
+ const ganttProp: ITaskData = ganttData.ganttProperties;
33
+ if (!ganttData.hasChildRecords) {
34
+ this.ensurePredecessorCollectionHelper(ganttData, ganttProp);
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ *
40
+ * @param {IGanttData} ganttData .
41
+ * @param {ITaskData} ganttProp .
42
+ * @returns {void} .
43
+ * @private
44
+ */
45
+ public ensurePredecessorCollectionHelper(ganttData: IGanttData, ganttProp: ITaskData): void {
46
+ const predecessorVal: object[] | string | number = ganttProp.predecessorsName;
47
+ if (predecessorVal && (typeof predecessorVal === 'string' || typeof predecessorVal === 'number')) {
48
+ this.parent.setRecordValue('predecessor', this.calculatePredecessor(predecessorVal, ganttData), ganttProp, true);
49
+ } else if (predecessorVal && typeof predecessorVal === 'object' && predecessorVal.length) {
50
+ const preValues: IPredecessor[] = [];
51
+ for (let c: number = 0; c < predecessorVal.length; c++) {
52
+ const predecessorItem: object = predecessorVal[c];
53
+ const preValue: IPredecessor = {};
54
+ preValue.from = getValue('from', predecessorItem);
55
+ preValue.to = getValue('to', predecessorItem) ? getValue('to', predecessorItem) : ganttProp.rowUniqueID;
56
+ preValue.type = getValue('type', predecessorItem) ? getValue('type', predecessorItem) : 'FS';
57
+ const offsetUnits: Record<string, unknown> = getValue('offset', predecessorItem);
58
+ if (isNullOrUndefined(offsetUnits)) {
59
+ preValue.offset = 0;
60
+ preValue.offsetUnit = this.parent.durationUnit.toLocaleLowerCase();
61
+ } else if (typeof offsetUnits === 'string') {
62
+ const tempOffsetUnits: { duration: number, durationUnit: string } = this.getOffsetDurationUnit(
63
+ getValue('offset', predecessorItem));
64
+ preValue.offset = tempOffsetUnits.duration;
65
+ preValue.offsetUnit = tempOffsetUnits.durationUnit;
66
+ } else {
67
+ preValue.offset = parseFloat(offsetUnits.toString());
68
+ preValue.offsetUnit = this.parent.durationUnit.toLocaleLowerCase();
69
+ }
70
+ const isOwnParent: boolean = this.checkIsParent(preValue.from.toString());
71
+ if (!isOwnParent) {
72
+ preValues.push(preValue);
73
+ }
74
+ }
75
+ this.parent.setRecordValue('predecessor', preValues, ganttProp, true);
76
+ }
77
+ this.parent.setRecordValue('predecessorsName', this.getPredecessorStringValue(ganttData), ganttProp, true);
78
+ this.parent.setRecordValue(
79
+ 'taskData.' + this.parent.taskFields.dependency,
80
+ ganttProp.predecessorsName,
81
+ ganttData);
82
+ this.parent.setRecordValue(
83
+ this.parent.taskFields.dependency,
84
+ ganttProp.predecessorsName,
85
+ ganttData);
86
+ }
87
+
88
+ /**
89
+ * To render unscheduled empty task with 1 day duration during predecessor map
90
+ *
91
+ * @param {IGanttData} data .
92
+ * @returns {void} .
93
+ * @private
94
+ */
95
+ public updateUnscheduledDependency(data: IGanttData): void {
96
+ const task: TaskFieldsModel = this.parent.taskFields;
97
+ const prdList: string[] = !isNullOrUndefined(data[task.dependency]) ?
98
+ data[task.dependency].toString().split(',') : [];
99
+ for (let i: number = 0; i < prdList.length; i++) {
100
+ const predId: number = parseInt(prdList[i], 10);
101
+ if (!isNaN(predId)) {
102
+ const predData: IGanttData = this.parent.getRecordByID(predId.toString());
103
+ const record: ITaskData = !isNullOrUndefined(predData) ?
104
+ extend({}, {}, predData.taskData, true) : null;
105
+ if (!isNullOrUndefined(record) && isNullOrUndefined(record[task.startDate])
106
+ && isNullOrUndefined(record[task.duration]) && isNullOrUndefined(record[task.endDate])) {
107
+ record[task.duration] = 1;
108
+ record[task.startDate] = this.parent.projectStartDate;
109
+ this.parent.updateRecordByID(record);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ *
116
+ * @param {string} fromId .
117
+ * @returns {boolean} .
118
+ */
119
+ private checkIsParent(fromId: string): boolean {
120
+ let boolValue: boolean = false;
121
+ const task: IGanttData = this.parent.connectorLineModule.getRecordByID(fromId);
122
+ if (task.hasChildRecords) {
123
+ boolValue = true;
124
+ }
125
+ return boolValue;
126
+ }
127
+
128
+ /**
129
+ * Get predecessor collection object from predecessor string value
130
+ *
131
+ * @param {string | number} predecessorValue .
132
+ * @param {IGanttData} ganttRecord .
133
+ * @returns {IPredecessor[]} .
134
+ * @private
135
+ */
136
+ public calculatePredecessor(predecessorValue: string | number, ganttRecord?: IGanttData): IPredecessor[] {
137
+ const predecessor: string = predecessorValue.toString();
138
+ const collection: IPredecessor[] = [];
139
+ let match: string[];
140
+ let values: string[];
141
+ let offsetValue: string;
142
+ let predecessorText: string;
143
+
144
+ predecessor.split(',').forEach((el: string): void => {
145
+ values = el.split('+');
146
+ offsetValue = '+';
147
+ if (el.indexOf('-') >= 0) {
148
+ values = el.split('-');
149
+ offsetValue = '-';
150
+ }
151
+ match = values[0].match(/(\d+|[A-z]+)/g);
152
+ const ids: string[] = this.parent.viewType === 'ResourceView' ? this.parent.getTaskIds() : this.parent.ids;
153
+ const isExist: number = this.parent.viewType === 'ResourceView' ? ids.indexOf('T' + match[0]) : ids.indexOf(match[0]);
154
+ /*Validate for appropriate predecessor*/
155
+ if (match[0] && isExist !== -1) {
156
+ if (match.length > 1) {
157
+ const type: string = match[1].toUpperCase();
158
+ if (type === 'FS' || type === 'FF' || type === 'SF' || type === 'SS') {
159
+ predecessorText = type;
160
+ } else {
161
+ predecessorText = 'FS';
162
+ }
163
+ } else {
164
+ predecessorText = 'FS';
165
+ }
166
+ } else {
167
+ return; // exit current loop for invalid id (match[0])
168
+ }
169
+ const tempOffset: string = values.length > 1 ? offsetValue + '' + values[1] : '0';
170
+ const offsetUnits: { duration: number, durationUnit: string } = this.getOffsetDurationUnit(tempOffset);
171
+
172
+ const obj: IPredecessor = {
173
+ from: match[0],
174
+ type: predecessorText,
175
+ isDrawn: false,
176
+ to: this.parent.viewType === 'ResourceView' ? ganttRecord.ganttProperties.taskId.toString()
177
+ : ganttRecord.ganttProperties.rowUniqueID.toString(),
178
+ offsetUnit: offsetUnits.durationUnit,
179
+ offset: offsetUnits.duration
180
+ };
181
+ const isOwnParent: boolean = this.checkIsParent(match[0]);
182
+ if (!isOwnParent) {
183
+ collection.push(obj);
184
+ }
185
+ });
186
+ return collection;
187
+ }
188
+
189
+ /**
190
+ * Get predecessor value as string with offset values
191
+ *
192
+ * @param {IGanttData} data .
193
+ * @returns {string} .
194
+ * @private
195
+ */
196
+ public getPredecessorStringValue(data: IGanttData): string {
197
+ const predecessors: IPredecessor[] = data.ganttProperties.predecessor;
198
+ const durationUnitTexts: Object = this.parent.durationUnitTexts;
199
+ let resultString: string = '';
200
+ if (predecessors) {
201
+ const length: number = predecessors.length;
202
+ for (let i: number = 0; i < length; i++) {
203
+ const currentValue: IPredecessor = predecessors[i];
204
+ let temp: string = '';
205
+ const id: string = this.parent.viewType === 'ResourceView' ? data.ganttProperties.taskId
206
+ : data.ganttProperties.rowUniqueID;
207
+ if (currentValue.from !== id.toString()) {
208
+ temp = currentValue.from + currentValue.type;
209
+ if (currentValue.offset !== 0) {
210
+ temp += currentValue.offset > 0 ? ('+' + currentValue.offset + ' ') : (currentValue.offset + ' ');
211
+ const multiple: boolean = currentValue.offset !== 1;
212
+ if (currentValue.offsetUnit === 'day') {
213
+ temp += multiple ? getValue('days', durationUnitTexts) : getValue('day', durationUnitTexts);
214
+ } else if (currentValue.offsetUnit === 'hour') {
215
+ temp += multiple ? getValue('hours', durationUnitTexts) : getValue('hour', durationUnitTexts);
216
+ } else {
217
+ temp += multiple ? getValue('minutes', durationUnitTexts) : getValue('minute', durationUnitTexts);
218
+ }
219
+ }
220
+ if (resultString.length > 0) {
221
+ resultString = resultString + ',' + temp;
222
+ } else {
223
+ resultString = temp;
224
+ }
225
+ }
226
+ }
227
+ }
228
+ return resultString;
229
+ }
230
+
231
+ /*Get duration and duration unit value from tasks*/
232
+ private getOffsetDurationUnit(val: string | number): { duration: number, durationUnit: string } {
233
+ let duration: number = 0;
234
+ let durationUnit: string = this.parent.durationUnit.toLocaleLowerCase();
235
+ const durationUnitLabels: Object = this.parent.durationUnitEditText;
236
+ if (typeof val === 'string') {
237
+ const values: string[] = val.match(/[^0-9]+|[0-9]+/g);
238
+ for (let x: number = 0; x < values.length; x++) {
239
+ values[x] = (values[x]).trim();
240
+ }
241
+ if (values[0] === '-' && values[1]) {
242
+ values[1] = values[0] + values[1];
243
+ values.shift();
244
+ } else if (values[0] === '+') {
245
+ values.shift();
246
+ }
247
+ if (values[1] === '.' && !isNaN(parseInt(values[2], 10))) {
248
+ values[0] += values[1] + values[2];
249
+ values.splice(1, 2);
250
+ }
251
+ if (values && values.length <= 2) {
252
+ duration = parseFloat(values[0]);
253
+ durationUnit = values[1] ? (values[1].toLowerCase()).trim() : '';
254
+ if (getValue('minute', durationUnitLabels).indexOf(durationUnit) !== -1) {
255
+ durationUnit = 'minute';
256
+ } else if (getValue('hour', durationUnitLabels).indexOf(durationUnit) !== -1) {
257
+ durationUnit = 'hour';
258
+ } else if (getValue('day', durationUnitLabels).indexOf(durationUnit) !== -1) {
259
+ durationUnit = 'day';
260
+ } else {
261
+ durationUnit = this.parent.durationUnit.toLocaleLowerCase();
262
+ }
263
+ }
264
+ } else {
265
+ duration = val;
266
+ durationUnit = this.parent.durationUnit.toLocaleLowerCase();
267
+ }
268
+ if (isNaN(duration)) {
269
+ duration = 0;
270
+ durationUnit = this.parent.durationUnit.toLocaleLowerCase();
271
+ }
272
+ return {
273
+ duration: duration,
274
+ durationUnit: durationUnit
275
+ };
276
+ }
277
+ /**
278
+ * Update predecessor object in both from and to tasks collection
279
+ *
280
+ * @returns {void} .
281
+ * @private
282
+ */
283
+ public updatePredecessors(): void {
284
+ const predecessorsCollection: IGanttData[] = this.parent.predecessorsCollection;
285
+ let ganttRecord: IGanttData;
286
+ const length: number = predecessorsCollection.length;
287
+ for (let count: number = 0; count < length; count++) {
288
+ ganttRecord = predecessorsCollection[count];
289
+ if (!ganttRecord.hasChildRecords) {
290
+ this.updatePredecessorHelper(ganttRecord, predecessorsCollection);
291
+ }
292
+ }
293
+ }
294
+ /**
295
+ * To update predecessor collection to successor tasks
296
+ *
297
+ * @param {IGanttData} ganttRecord .
298
+ * @param {IGanttData[]} predecessorsCollection .
299
+ * @returns {void} .
300
+ * @private
301
+ */
302
+ public updatePredecessorHelper(ganttRecord: IGanttData, predecessorsCollection?: IGanttData[]): void {
303
+ const connectorsCollection: IPredecessor[] = ganttRecord.ganttProperties.predecessor;
304
+ let successorGanttRecord: IGanttData;
305
+ const connectorCount: number = connectorsCollection.length;
306
+ predecessorsCollection = isNullOrUndefined(predecessorsCollection) ? [] : predecessorsCollection;
307
+ for (let i: number = 0; i < connectorCount; i++) {
308
+ const connector: IPredecessor = connectorsCollection[i];
309
+ successorGanttRecord = this.parent.connectorLineModule.getRecordByID(connector.from);
310
+ const id: string = this.parent.viewType === 'ResourceView' ? ganttRecord.ganttProperties.taskId
311
+ : ganttRecord.ganttProperties.rowUniqueID;
312
+ if (connector.from !== id.toString()) {
313
+ if (successorGanttRecord) {
314
+ let predecessorCollection: IPredecessor[];
315
+ if (successorGanttRecord.ganttProperties.predecessor) {
316
+ predecessorCollection = (extend([], successorGanttRecord.ganttProperties.predecessor, [], true)) as IPredecessor[];
317
+ predecessorCollection.push(connector);
318
+ this.parent.setRecordValue('predecessor', predecessorCollection, successorGanttRecord.ganttProperties, true);
319
+ // successorGanttRecord.ganttProperties.predecessor.push(connector);
320
+ } else {
321
+ predecessorCollection = [];
322
+ predecessorCollection.push(connector);
323
+ this.parent.setRecordValue('predecessor', predecessorCollection, successorGanttRecord.ganttProperties, true);
324
+ // this.parent.setRecordValue('predecessor', [], successorGanttRecord.ganttProperties, true);
325
+ // successorGanttRecord.ganttProperties.predecessor.push(connector);
326
+ predecessorsCollection.push(successorGanttRecord);
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Method to validate date of tasks with predecessor values for all records
335
+ *
336
+ * @returns {void} .
337
+ * @private
338
+ */
339
+ public updatedRecordsDateByPredecessor(): void {
340
+ const flatData: IGanttData[] = this.parent.flatData;
341
+ for (let count: number = 0; count < flatData.length; count++) {
342
+ if (flatData[count].ganttProperties.predecessor) {
343
+ this.validatePredecessorDates(flatData[count]);
344
+ }
345
+ }
346
+ }
347
+ /**
348
+ * To validate task date values with dependency
349
+ *
350
+ * @param {IGanttData} ganttRecord .
351
+ * @returns {void} .
352
+ * @private
353
+ */
354
+ public validatePredecessorDates(ganttRecord: IGanttData): void {
355
+ if (ganttRecord.ganttProperties.predecessor) {
356
+ const predecessorsCollection: IPredecessor[] = ganttRecord.ganttProperties.predecessor;
357
+ let count: number;
358
+ let parentGanttRecord: IGanttData;
359
+ let record: IGanttData = null;
360
+ const currentTaskId: string = this.parent.viewType === 'ResourceView' ? ganttRecord.ganttProperties.taskId.toString()
361
+ : ganttRecord.ganttProperties.rowUniqueID.toString();
362
+ const predecessors: IPredecessor[] = predecessorsCollection.filter((data: IPredecessor): IPredecessor => {
363
+ if (data.to === currentTaskId) {
364
+ return data;
365
+ } else {
366
+ return null;
367
+ }
368
+ });
369
+ for (count = 0; count < predecessors.length; count++) {
370
+ const predecessor: IPredecessor = predecessors[count];
371
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor.from);
372
+ record = this.parent.connectorLineModule.getRecordByID(predecessor.to);
373
+ if (record.ganttProperties.isAutoSchedule || this.parent.validateManualTasksOnLinking) {
374
+ this.validateChildGanttRecord(parentGanttRecord, record);
375
+ }
376
+ }
377
+ }
378
+ }
379
+ /**
380
+ * Method to validate task with predecessor
381
+ *
382
+ * @param {IGanttData} parentGanttRecord .
383
+ * @param {IGanttData} childGanttRecord .
384
+ * @returns {void} .
385
+ */
386
+ private validateChildGanttRecord(parentGanttRecord: IGanttData, childGanttRecord: IGanttData): void {
387
+ if (this.parent.editedTaskBarItem === childGanttRecord || isNullOrUndefined(isScheduledTask(parentGanttRecord.ganttProperties))
388
+ || isNullOrUndefined(isScheduledTask(childGanttRecord.ganttProperties))) {
389
+ return;
390
+ }
391
+ if (this.parent.isInPredecessorValidation && (childGanttRecord.ganttProperties.isAutoSchedule ||
392
+ this.parent.validateManualTasksOnLinking)) {
393
+ const childRecordProperty: ITaskData = childGanttRecord.ganttProperties;
394
+ const currentTaskId: string = this.parent.viewType === 'ResourceView' ? childRecordProperty.taskId.toString()
395
+ : childRecordProperty.rowUniqueID.toString();
396
+ const predecessorsCollection: IPredecessor[] = childRecordProperty.predecessor;
397
+ const childPredecessor: IPredecessor[] = predecessorsCollection.filter((data: IPredecessor): IPredecessor => {
398
+ if (data.to === currentTaskId) { return data; } else { return null; }
399
+ });
400
+ const startDate: Date = this.getPredecessorDate(childGanttRecord, childPredecessor);
401
+ this.parent.setRecordValue('startDate', startDate, childRecordProperty, true);
402
+ this.parent.dataOperation.updateMappingData(childGanttRecord, 'startDate');
403
+ const segments: ITaskSegment[] = childGanttRecord.ganttProperties.segments;
404
+ if (isNullOrUndefined(segments)) {
405
+ this.dateValidateModule.calculateEndDate(childGanttRecord);
406
+ }
407
+ this.parent.dataOperation.updateWidthLeft(childGanttRecord);
408
+
409
+ if (childGanttRecord.parentItem && this.parent.getParentTask(childGanttRecord.parentItem).ganttProperties.isAutoSchedule
410
+ && this.parent.isInPredecessorValidation && !this.parent.isLoad) {
411
+ if (this.parentIds.indexOf(childGanttRecord.parentItem.uniqueID) === -1) {
412
+ this.parentIds.push(childGanttRecord.parentItem.uniqueID);
413
+ this.parentRecord.push(childGanttRecord.parentItem);
414
+ }
415
+ }
416
+ }
417
+ }
418
+ /**
419
+ *
420
+ * @param {IGanttData} ganttRecord .
421
+ * @param {IPredecessor[]} predecessorsCollection .
422
+ * @returns {Date} .
423
+ * @private
424
+ */
425
+ public getPredecessorDate(ganttRecord: IGanttData, predecessorsCollection: IPredecessor[]): Date {
426
+ let maxStartDate: Date;
427
+ let tempStartDate: Date;
428
+ let parentGanttRecord: IGanttData;
429
+ let childGanttRecord: IGanttData;
430
+ const validatedPredecessor: IPredecessor[] = predecessorsCollection.filter((data: IPredecessor): IPredecessor => {
431
+ const id: string = this.parent.viewType === 'ResourceView' ? ganttRecord.ganttProperties.taskId
432
+ : ganttRecord.ganttProperties.rowUniqueID;
433
+ if (data.to === id.toString()) {
434
+ return data;
435
+ } else {
436
+ return null;
437
+ }
438
+ });
439
+ if (validatedPredecessor) {
440
+ const length: number = validatedPredecessor.length;
441
+ for (let i: number = 0; i < length; i++) {
442
+ const predecessor: IPredecessor = validatedPredecessor[i];
443
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor.from);
444
+ childGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor.to);
445
+ tempStartDate =
446
+ this.getValidatedStartDate(childGanttRecord.ganttProperties, parentGanttRecord.ganttProperties, predecessor);
447
+ if (maxStartDate == null || this.dateValidateModule.compareDates(tempStartDate, maxStartDate) === 1) {
448
+ maxStartDate = tempStartDate;
449
+ }
450
+ }
451
+ }
452
+ return maxStartDate;
453
+ }
454
+ /**
455
+ * Get validated start date as per predecessor type
456
+ *
457
+ * @param {ITaskData} ganttProperty .
458
+ * @param {ITaskData} parentRecordProperty .
459
+ * @param {IPredecessor} predecessor .
460
+ * @returns {Date} .
461
+ */
462
+ private getValidatedStartDate(ganttProperty: ITaskData, parentRecordProperty: ITaskData, predecessor: IPredecessor): Date {
463
+ const type: string = predecessor.type;
464
+ const offset: number = predecessor.offset;
465
+ let tempDate: Date;
466
+ let returnStartDate: Date;
467
+ switch (type) {
468
+ case 'FS':
469
+ tempDate = this.dateValidateModule.getValidEndDate(parentRecordProperty);
470
+ if (!ganttProperty.isMilestone || offset !== 0) {
471
+ tempDate = this.dateValidateModule.checkStartDate(tempDate, ganttProperty);
472
+ }
473
+ if (offset !== 0) {
474
+ tempDate = this.updateDateByOffset(tempDate, predecessor, ganttProperty);
475
+ }
476
+ if (!ganttProperty.isMilestone) {
477
+ returnStartDate = this.dateValidateModule.checkStartDate(tempDate, ganttProperty);
478
+ } else {
479
+ returnStartDate = tempDate;
480
+ }
481
+ break;
482
+ case 'FF':
483
+ case 'SF':
484
+ tempDate = type === 'FF' ? this.dateValidateModule.getValidEndDate(parentRecordProperty) :
485
+ this.dateValidateModule.getValidStartDate(parentRecordProperty);
486
+ if (offset !== 0) {
487
+ tempDate = this.updateDateByOffset(tempDate, predecessor, ganttProperty);
488
+ }
489
+ if (!ganttProperty.isMilestone) {
490
+ tempDate = this.dateValidateModule.checkEndDate(tempDate, ganttProperty);
491
+ }
492
+ returnStartDate = this.dateValidateModule.getStartDate(
493
+ tempDate, ganttProperty.duration, ganttProperty.durationUnit, ganttProperty);
494
+ break;
495
+ case 'SS':
496
+ tempDate = this.dateValidateModule.getValidStartDate(parentRecordProperty);
497
+ if (offset !== 0) {
498
+ tempDate = this.updateDateByOffset(tempDate, predecessor, ganttProperty);
499
+ }
500
+ if (!ganttProperty.isMilestone) {
501
+ returnStartDate = this.dateValidateModule.checkStartDate(tempDate, ganttProperty);
502
+ } else {
503
+ returnStartDate = tempDate;
504
+ }
505
+ break;
506
+ }
507
+ return returnStartDate;
508
+ }
509
+ /**
510
+ *
511
+ * @param {Date} date .
512
+ * @param {IPredecessor} predecessor .
513
+ * @param {ITaskData} record .
514
+ * @returns {void} .
515
+ */
516
+ private updateDateByOffset(date: Date, predecessor: IPredecessor, record: ITaskData): Date {
517
+ let resultDate: Date;
518
+ const offsetValue: number = predecessor.offset;
519
+ const durationUnit: string = predecessor.offsetUnit;
520
+ if (offsetValue < 0) {
521
+ resultDate = this.dateValidateModule.getStartDate(
522
+ this.dateValidateModule.checkEndDate(date, record), (offsetValue * -1), durationUnit, record);
523
+ } else {
524
+ resultDate = this.dateValidateModule.getEndDate(date, offsetValue, durationUnit, record, false);
525
+ if (!record.isMilestone) {
526
+ resultDate = this.dateValidateModule.checkStartDate(resultDate, record);
527
+ }
528
+ }
529
+ return resultDate;
530
+ }
531
+ /**
532
+ *
533
+ * @param {IGanttData} records .
534
+ * @returns {void} .
535
+ * @private
536
+ */
537
+ public createConnectorLinesCollection(records?: IGanttData[]): void {
538
+ const ganttRecords: IGanttData [] = records ? records : this.parent.currentViewData;
539
+ const recordLength: number = ganttRecords.length;
540
+ let count: number; let ganttRecord: IGanttData;
541
+ let predecessorsCollection: object[];
542
+ this.parent.connectorLineModule.expandedRecords = this.parent.virtualScrollModule && this.parent.enableVirtualization ?
543
+ this.parent.updatedRecords : this.parent.getExpandedRecords(this.parent.updatedRecords);
544
+ for (count = 0; count < recordLength; count++) {
545
+ ganttRecord = ganttRecords[count];
546
+ predecessorsCollection = ganttRecord.ganttProperties.predecessor;
547
+ if (predecessorsCollection) {
548
+ this.addPredecessorsCollection(predecessorsCollection);
549
+ }
550
+ }
551
+ }
552
+ /**
553
+ *
554
+ * @param {object[]} predecessorsCollection .
555
+ * @returns {void} .
556
+ */
557
+ private addPredecessorsCollection(predecessorsCollection: object[]): void {
558
+ let predecessorsLength: number;
559
+ let predecessorCount: number;
560
+ let predecessor: IPredecessor;
561
+ let parentGanttRecord: IGanttData;
562
+ let childGanttRecord: IGanttData;
563
+ if (predecessorsCollection) {
564
+ predecessorsLength = predecessorsCollection.length;
565
+ for (predecessorCount = 0; predecessorCount < predecessorsLength; predecessorCount++) {
566
+ predecessor = predecessorsCollection[predecessorCount];
567
+ const from: string = 'from'; const to: string = 'to';
568
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor[from]);
569
+ childGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor[to]);
570
+ if (this.parent.connectorLineModule.expandedRecords &&
571
+ this.parent.connectorLineModule.expandedRecords.indexOf(parentGanttRecord) !== -1 &&
572
+ this.parent.connectorLineModule.expandedRecords.indexOf(childGanttRecord) !== -1) {
573
+ this.updateConnectorLineObject(parentGanttRecord, childGanttRecord, predecessor);
574
+ }
575
+ }
576
+ }
577
+ }
578
+
579
+ /**
580
+ * To refresh connector line object collections
581
+ *
582
+ * @param {IGanttData} parentGanttRecord .
583
+ * @param {IGanttData} childGanttRecord .
584
+ * @param {IPredecessor} predecessor .
585
+ * @returns {void} .
586
+ * @private
587
+ */
588
+ public updateConnectorLineObject(
589
+ parentGanttRecord: IGanttData,
590
+ childGanttRecord: IGanttData,
591
+ predecessor: IPredecessor): IConnectorLineObject {
592
+ const connectorObj: IConnectorLineObject = this.parent.connectorLineModule.createConnectorLineObject(
593
+ parentGanttRecord, childGanttRecord, predecessor);
594
+ if (connectorObj) {
595
+ if ((this.parent.connectorLineIds.length > 0 && this.parent.connectorLineIds.indexOf(connectorObj.connectorLineId) === -1) ||
596
+ this.parent.connectorLineIds.length === 0) {
597
+ this.parent.updatedConnectorLineCollection.push(connectorObj);
598
+ this.parent.connectorLineIds.push(connectorObj.connectorLineId);
599
+ } else if (this.parent.connectorLineIds.indexOf(connectorObj.connectorLineId) !== -1) {
600
+ const index: number = this.parent.connectorLineIds.indexOf(connectorObj.connectorLineId);
601
+ this.parent.updatedConnectorLineCollection[index] = connectorObj;
602
+ }
603
+ predecessor.isDrawn = true;
604
+ }
605
+ return connectorObj;
606
+ }
607
+ /**
608
+ *
609
+ * @param {IGanttData} childGanttRecord .
610
+ * @param {IPredecessor[]} previousValue .
611
+ * @param {string} validationOn .
612
+ * @returns {void} .
613
+ * @private
614
+ */
615
+ public validatePredecessor(childGanttRecord: IGanttData, previousValue: IPredecessor[], validationOn: string): void {
616
+ if (!this.parent.isInPredecessorValidation) {
617
+ return;
618
+ }
619
+ if (childGanttRecord.ganttProperties.predecessor) {
620
+ const predecessorsCollection: IPredecessor[] = childGanttRecord.ganttProperties.predecessor;
621
+ let parentGanttRecord: IGanttData; let record: IGanttData = null;
622
+ let predecessor: IPredecessor;
623
+ let successor: IPredecessor;
624
+ const currentTaskId: string = this.parent.viewType === 'ResourceView' ? childGanttRecord.ganttProperties.taskId.toString()
625
+ : childGanttRecord.ganttProperties.rowUniqueID.toString();
626
+ const predecessors: IPredecessor[] = predecessorsCollection.filter((data: IPredecessor): IPredecessor => {
627
+ if (data.to === currentTaskId) { return data; } else { return null; }
628
+ });
629
+ const successors: IPredecessor[] = predecessorsCollection.filter((data: IPredecessor): IPredecessor => {
630
+ if (data.from === currentTaskId) { return data; } else { return null; }
631
+ });
632
+ for (let count: number = 0; count < predecessors.length; count++) {
633
+ predecessor = predecessors[count];
634
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor.from);
635
+ record = this.parent.connectorLineModule.getRecordByID(predecessor.to);
636
+ if (this.parent.isInPredecessorValidation && record.ganttProperties.isAutoSchedule) {
637
+ this.parent.isValidationEnabled = true;
638
+ } else {
639
+ this.parent.isValidationEnabled = false;
640
+ }
641
+ const id: string = this.parent.viewType === 'ResourceView' ? childGanttRecord.ganttProperties.taskId
642
+ : childGanttRecord.ganttProperties.rowUniqueID;
643
+ if ((id.toString() === predecessor.to
644
+ || id.toString() === predecessor.from)
645
+ && (!validationOn || validationOn === 'predecessor')) {
646
+ this.validateChildGanttRecord(parentGanttRecord, record);
647
+ }
648
+ }
649
+
650
+ for (let count: number = 0; count < successors.length; count++) {
651
+ successor = successors[count];
652
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(successor.from);
653
+ record = this.parent.connectorLineModule.getRecordByID(successor.to);
654
+ if (this.parent.isInPredecessorValidation && record.ganttProperties.isAutoSchedule) {
655
+ this.parent.isValidationEnabled = true;
656
+ } else {
657
+ this.parent.isValidationEnabled = false;
658
+ }
659
+ if (validationOn !== 'predecessor' && this.parent.isValidationEnabled) {
660
+ this.validateChildGanttRecord(parentGanttRecord, record);
661
+ }
662
+ if (parentGanttRecord.expanded === false || record.expanded === false) {
663
+ if (record) { this.validatePredecessor(record, undefined, 'successor'); }
664
+ continue;
665
+ }
666
+ if (record) { this.validatePredecessor(record, undefined, 'successor'); }
667
+ }
668
+ }
669
+ }
670
+
671
+ /**
672
+ * Method to get validate able predecessor alone from record
673
+ *
674
+ * @param {IGanttData} record .
675
+ * @returns {IPredecessor[]} .
676
+ * @private
677
+ */
678
+ public getValidPredecessor(record: IGanttData): IPredecessor[] {
679
+ let validPredecessor: IPredecessor[] = [];
680
+ if (!isNullOrUndefined(record)) {
681
+ const recPredecessor: IPredecessor[] = record.ganttProperties.predecessor;
682
+ if (recPredecessor && recPredecessor.length > 0) {
683
+ validPredecessor = recPredecessor.filter((value: IPredecessor) => {
684
+ const id: string = this.parent.viewType === 'ResourceView' ? record.ganttProperties.taskId
685
+ : record.ganttProperties.rowUniqueID;
686
+ return value.from !== id.toString();
687
+ });
688
+ }
689
+ }
690
+ return validPredecessor;
691
+ }
692
+ }