@syncfusion/ej2-gantt 19.4.55 → 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 (212) hide show
  1. package/CHANGELOG.md +1072 -1047
  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 +341 -240
  6. package/dist/es6/ej2-gantt.es2015.js.map +1 -1
  7. package/dist/es6/ej2-gantt.es5.js +713 -598
  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 +36 -9
  91. package/src/gantt/actions/rowdragdrop.js +37 -15
  92. package/src/gantt/actions/selection.js +3 -2
  93. package/src/gantt/actions/taskbar-edit.js +24 -24
  94. package/src/gantt/base/date-processor.js +0 -1
  95. package/src/gantt/base/gantt-chart.js +36 -5
  96. package/src/gantt/base/gantt-model.d.ts +779 -779
  97. package/src/gantt/base/gantt.d.ts +27 -27
  98. package/src/gantt/base/gantt.js +35 -76
  99. package/src/gantt/base/splitter.js +1 -0
  100. package/src/gantt/base/task-processor.js +13 -13
  101. package/src/gantt/base/tree-grid.js +3 -1
  102. package/src/gantt/export/pdf-base/treegrid-layouter.js +13 -13
  103. package/src/gantt/export/pdf-connector-line.js +11 -11
  104. package/src/gantt/export/pdf-gantt.js +24 -24
  105. package/src/gantt/export/pdf-taskbar.js +11 -11
  106. package/src/gantt/export/pdf-treegrid.js +13 -13
  107. package/src/gantt/models/add-dialog-field-settings-model.d.ts +21 -21
  108. package/src/gantt/models/add-dialog-field-settings.js +19 -19
  109. package/src/gantt/models/day-working-time-model.d.ts +11 -11
  110. package/src/gantt/models/day-working-time.js +19 -19
  111. package/src/gantt/models/edit-dialog-field-settings-model.d.ts +21 -21
  112. package/src/gantt/models/edit-dialog-field-settings.js +19 -19
  113. package/src/gantt/models/edit-settings-model.d.ts +50 -50
  114. package/src/gantt/models/edit-settings.js +19 -19
  115. package/src/gantt/models/event-marker-model.d.ts +16 -16
  116. package/src/gantt/models/event-marker.js +19 -19
  117. package/src/gantt/models/filter-settings-model.d.ts +34 -34
  118. package/src/gantt/models/filter-settings.js +19 -19
  119. package/src/gantt/models/holiday-model.d.ts +21 -21
  120. package/src/gantt/models/holiday.js +19 -19
  121. package/src/gantt/models/label-settings-model.d.ts +16 -16
  122. package/src/gantt/models/label-settings.js +19 -19
  123. package/src/gantt/models/resource-fields-model.d.ts +21 -21
  124. package/src/gantt/models/resource-fields.js +19 -19
  125. package/src/gantt/models/search-settings-model.d.ts +56 -56
  126. package/src/gantt/models/search-settings.js +19 -19
  127. package/src/gantt/models/selection-settings-model.d.ts +35 -35
  128. package/src/gantt/models/selection-settings.js +19 -19
  129. package/src/gantt/models/sort-settings-model.d.ts +24 -24
  130. package/src/gantt/models/sort-settings.js +19 -19
  131. package/src/gantt/models/splitter-settings-model.d.ts +30 -30
  132. package/src/gantt/models/splitter-settings.js +19 -19
  133. package/src/gantt/models/task-fields-model.d.ts +110 -110
  134. package/src/gantt/models/task-fields.js +19 -19
  135. package/src/gantt/models/timeline-settings-model.d.ts +71 -71
  136. package/src/gantt/models/timeline-settings.js +19 -19
  137. package/src/gantt/models/tooltip-settings-model.d.ts +26 -26
  138. package/src/gantt/models/tooltip-settings.js +19 -19
  139. package/src/gantt/renderer/chart-rows.js +49 -37
  140. package/src/gantt/renderer/connector-line.js +22 -18
  141. package/src/gantt/renderer/event-marker.js +1 -0
  142. package/src/gantt/renderer/nonworking-day.js +13 -6
  143. package/src/gantt/renderer/timeline.d.ts +1 -0
  144. package/src/gantt/renderer/timeline.js +51 -12
  145. package/src/gantt/renderer/tooltip.js +11 -3
  146. package/styles/bootstrap-dark.css +442 -427
  147. package/styles/bootstrap.css +442 -433
  148. package/styles/bootstrap4.css +454 -479
  149. package/styles/bootstrap5-dark.css +457 -433
  150. package/styles/bootstrap5.css +457 -433
  151. package/styles/fabric-dark.css +438 -421
  152. package/styles/fabric.css +445 -428
  153. package/styles/fluent-dark.css +1938 -0
  154. package/styles/fluent-dark.scss +1 -0
  155. package/styles/fluent.css +1938 -0
  156. package/styles/fluent.scss +1 -0
  157. package/styles/gantt/_all.scss +2 -2
  158. package/styles/gantt/_bootstrap-dark-definition.scss +210 -156
  159. package/styles/gantt/_bootstrap-definition.scss +211 -157
  160. package/styles/gantt/_bootstrap4-definition.scss +213 -158
  161. package/styles/gantt/_bootstrap5-definition.scss +215 -162
  162. package/styles/gantt/_fabric-dark-definition.scss +211 -157
  163. package/styles/gantt/_fabric-definition.scss +211 -157
  164. package/styles/gantt/_fluent-dark-definition.scss +1 -0
  165. package/styles/gantt/_fluent-definition.scss +215 -162
  166. package/styles/gantt/_fusionnew-definition.scss +214 -0
  167. package/styles/gantt/_highcontrast-definition.scss +211 -157
  168. package/styles/gantt/_highcontrast-light-definition.scss +211 -157
  169. package/styles/gantt/_layout.scss +1446 -1027
  170. package/styles/gantt/_material-dark-definition.scss +212 -157
  171. package/styles/gantt/_material-definition.scss +212 -157
  172. package/styles/gantt/_material3-definition.scss +215 -0
  173. package/styles/gantt/_tailwind-definition.scss +215 -161
  174. package/styles/gantt/_theme.scss +702 -668
  175. package/styles/gantt/bootstrap-dark.css +442 -427
  176. package/styles/gantt/bootstrap.css +442 -433
  177. package/styles/gantt/bootstrap4.css +454 -479
  178. package/styles/gantt/bootstrap5-dark.css +457 -433
  179. package/styles/gantt/bootstrap5.css +457 -433
  180. package/styles/gantt/fabric-dark.css +438 -421
  181. package/styles/gantt/fabric.css +445 -428
  182. package/styles/gantt/fluent-dark.css +1938 -0
  183. package/styles/gantt/fluent-dark.scss +22 -0
  184. package/styles/gantt/fluent.css +1938 -0
  185. package/styles/gantt/fluent.scss +22 -0
  186. package/styles/gantt/highcontrast-light.css +405 -405
  187. package/styles/gantt/highcontrast.css +444 -456
  188. package/styles/gantt/icons/_bootstrap-dark.scss +124 -113
  189. package/styles/gantt/icons/_bootstrap.scss +124 -113
  190. package/styles/gantt/icons/_bootstrap4.scss +124 -113
  191. package/styles/gantt/icons/_bootstrap5.scss +124 -112
  192. package/styles/gantt/icons/_fabric-dark.scss +124 -112
  193. package/styles/gantt/icons/_fabric.scss +124 -112
  194. package/styles/gantt/icons/_fluent-dark.scss +1 -0
  195. package/styles/gantt/icons/_fluent.scss +124 -112
  196. package/styles/gantt/icons/_fusionnew.scss +120 -0
  197. package/styles/gantt/icons/_highcontrast.scss +124 -112
  198. package/styles/gantt/icons/_material-dark.scss +124 -112
  199. package/styles/gantt/icons/_material.scss +124 -112
  200. package/styles/gantt/icons/_material3.scss +124 -0
  201. package/styles/gantt/icons/_tailwind-dark.scss +124 -113
  202. package/styles/gantt/icons/_tailwind.scss +124 -113
  203. package/styles/gantt/material-dark.css +446 -417
  204. package/styles/gantt/material.css +445 -419
  205. package/styles/gantt/tailwind-dark.css +452 -482
  206. package/styles/gantt/tailwind.css +449 -479
  207. package/styles/highcontrast-light.css +405 -405
  208. package/styles/highcontrast.css +444 -456
  209. package/styles/material-dark.css +446 -417
  210. package/styles/material.css +445 -419
  211. package/styles/tailwind-dark.css +452 -482
  212. 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
+ }