@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,2217 @@
1
+ import { isNullOrUndefined, getValue, extend, setValue } from '@syncfusion/ej2-base';
2
+ import { getUid, ReturnType } from '@syncfusion/ej2-grids';
3
+ import { IGanttData, ITaskData, IParent, IWorkTimelineRanges, IWorkingTimeRange, ITaskSegment } from './interface';
4
+ import { DataManager, Query, Group, ReturnOption } from '@syncfusion/ej2-data';
5
+ import { isCountRequired, isScheduledTask } from './utils';
6
+ import { Gantt } from './gantt';
7
+ import { DateProcessor } from './date-processor';
8
+ import { TaskFieldsModel, ColumnModel, ResourceFieldsModel } from '../models/models';
9
+ import { CObject } from './enum';
10
+
11
+ /**
12
+ * To calculate and update task related values
13
+ */
14
+ export class TaskProcessor extends DateProcessor {
15
+
16
+ private recordIndex: number;
17
+ private dataArray: Object[];
18
+ private taskIds: Object[];
19
+ private segmentCollection: Object[];
20
+ private hierarchyData: Object[];
21
+
22
+ constructor(parent: Gantt) {
23
+ super(parent);
24
+ this.recordIndex = 0;
25
+ this.taskIds = [];
26
+ this.hierarchyData = [];
27
+ this.addEventListener();
28
+ }
29
+ private addEventListener(): void {
30
+ this.parent.on('beforeDataManipulate', this.checkDataBinding.bind(this));
31
+ }
32
+ /**
33
+ * @param {boolean} isChange .
34
+ * @returns {void} .
35
+ * @private
36
+ */
37
+ public checkDataBinding(isChange?: boolean): void {
38
+ if (isChange) {
39
+ this.parent.flatData = [];
40
+ this.parent.currentViewData = [];
41
+ this.parent.updatedRecords = [];
42
+ this.dataArray = [];
43
+ this.taskIds = [];
44
+ this.parent.ids = [];
45
+ this.recordIndex = 0;
46
+ this.hierarchyData = [];
47
+ this.parent.predecessorsCollection = [];
48
+ this.parent.treeGrid.parentData = [];
49
+ this.parent.taskIds = [];
50
+ }
51
+ if (isNullOrUndefined(this.parent.dataSource)) {
52
+ this.parent.dataSource = [];
53
+ this.parent.processTimeline();
54
+ this.parent.renderGantt(isChange);
55
+ } else if (this.parent.dataSource instanceof DataManager) {
56
+ this.initDataSource(isChange);
57
+ } else {
58
+ if (this.parent.dataSource instanceof Object && isCountRequired(this.parent)) {
59
+ const ganttdata: Object[] = getValue('result', this.parent.dataSource);
60
+ this.dataArray = ganttdata;
61
+ } else {
62
+ this.dataArray = this.parent.dataSource as object[];
63
+ }
64
+ this.processTimeline();
65
+ this.cloneDataSource();
66
+ this.parent.renderGantt(isChange);
67
+ }
68
+ }
69
+ private processTimeline(): void {
70
+ this.parent.processTimeline();
71
+ if (!this.parent.enableValidation) {
72
+ this.parent.dataOperation.calculateProjectDatesForValidatedTasks();
73
+ this.parent.timelineModule.validateTimelineProp();
74
+ }
75
+ }
76
+ private initDataSource(isChange?: boolean): void {
77
+ const queryManager: Query = this.parent.query instanceof Query ? this.parent.query : new Query();
78
+ queryManager.requiresCount();
79
+ const dataManager: DataManager = this.parent.dataSource as DataManager;
80
+ dataManager.executeQuery(queryManager).then((e: ReturnOption) => {
81
+ this.dataArray = <Object[]>e.result;
82
+ this.processTimeline();
83
+ this.cloneDataSource();
84
+ this.parent.renderGantt(isChange);
85
+ }).catch((e: ReturnType) => {
86
+ // Trigger action failure event
87
+ this.parent.processTimeline();
88
+ this.parent.renderGantt(isChange);
89
+ this.parent.trigger('actionFailure', { error: e });
90
+ });
91
+ }
92
+ private constructDataSource(dataSource: Object[]): void {
93
+ const mappingData: Object[] = new DataManager(dataSource).executeLocal(new Query()
94
+ .group(this.parent.taskFields.parentID));
95
+ const rootData: Object[] = [];
96
+ for (let i: number = 0; i < mappingData.length; i++) {
97
+ const groupData: Group = mappingData[i];
98
+ if (!isNullOrUndefined(groupData.key)) {
99
+ const index: number = this.taskIds.indexOf(groupData.key.toString());
100
+ if (index > -1) {
101
+ if (!isNullOrUndefined(groupData.key)) {
102
+ dataSource[index][this.parent.taskFields.child] = groupData.items;
103
+ continue;
104
+ }
105
+ }
106
+ }
107
+ rootData.push.apply(rootData, groupData.items); // eslint-disable-line
108
+ }
109
+ this.hierarchyData = this.dataReorder(dataSource, rootData);
110
+ }
111
+ private cloneDataSource(): void {
112
+ const taskIdMapping: string = this.parent.taskFields.id;
113
+ const parentIdMapping: string = this.parent.taskFields.parentID;
114
+ let hierarchicalData: Object[] = [];
115
+ if (!isNullOrUndefined(taskIdMapping) && !isNullOrUndefined(parentIdMapping)) {
116
+ const data: object[] = [];
117
+ for (let i: number = 0; i < this.dataArray.length; i++) {
118
+ const tempData: Object = this.dataArray[i];
119
+ data.push(extend({}, {}, tempData, true));
120
+ if (!isNullOrUndefined(tempData[taskIdMapping])) {
121
+ this.taskIds.push(tempData[taskIdMapping].toString());
122
+ }
123
+ }
124
+ if (!this.parent.taskFields.child) {
125
+ this.parent.taskFields.child = 'Children';
126
+ }
127
+ this.constructDataSource(data);
128
+ hierarchicalData = this.hierarchyData;
129
+ } else {
130
+ hierarchicalData = this.dataArray;
131
+ }
132
+ if (this.parent.taskFields.segmentId) {
133
+ this.segmentCollection = new DataManager(this.parent.segmentData).executeLocal(new Query()
134
+ .group(this.parent.taskFields.segmentId));
135
+ if (!this.parent.taskFields.segments) {
136
+ this.parent.taskFields.segments = 'Segments';
137
+ }
138
+ }
139
+ if (this.parent.viewType !== 'ProjectView') {
140
+ const resources: Object[] = extend([], [], this.parent.resources, true) as Object[];
141
+ const unassignedTasks: Object[] = [];
142
+ this.constructResourceViewDataSource(resources, hierarchicalData, unassignedTasks);
143
+ if (unassignedTasks.length > 0) {
144
+ const record: Object = {};
145
+ record[this.parent.resourceFields.id] = 0;
146
+ record[this.parent.resourceFields.name] = this.parent.localeObj.getConstant('unassignedTask');
147
+ record[this.parent.taskFields.child] = unassignedTasks;
148
+ resources.push(record);
149
+ }
150
+ hierarchicalData = resources;
151
+ }
152
+ this.prepareDataSource(hierarchicalData);
153
+ }
154
+ /**
155
+ * @param {object[]} resources .
156
+ * @param {object[]} data .
157
+ * @param {object[]} unassignedTasks .
158
+ * @returns {void} .
159
+ *
160
+ */
161
+ private constructResourceViewDataSource(resources: Object[], data: Object[], unassignedTasks: Object[]): void {
162
+ for (let i: number = 0; i < data.length; i++) {
163
+ const tempData: Object = data[i];
164
+ const child: string = this.parent.taskFields.child;
165
+ const resourceData: [] = tempData && tempData[this.parent.taskFields.resourceInfo];
166
+ const resourceIdMapping: string = this.parent.resourceFields.id;
167
+ if (!tempData[child] && resourceData && resourceData.length) {
168
+ resourceData.forEach((resource: number | object) => {
169
+ const id: string = (typeof resource === 'object') ? resource[resourceIdMapping] :
170
+ resource;
171
+ for (let j: number = 0; j < resources.length; j++) {
172
+ if (resources[j][resourceIdMapping].toString() === id.toString()) {
173
+ if (resources[j][child]) {
174
+ resources[j][child].push(tempData);
175
+ } else {
176
+ resources[j][child] = [tempData];
177
+ }
178
+ break;
179
+ }
180
+ }
181
+ });
182
+ } else if (!tempData[child]) {
183
+ unassignedTasks.push(tempData);
184
+ }
185
+ if (tempData[this.parent.taskFields.child] && tempData[this.parent.taskFields.child].length) {
186
+ this.constructResourceViewDataSource(resources, tempData[this.parent.taskFields.child], unassignedTasks);
187
+ }
188
+ }
189
+ }
190
+ /**
191
+ * Function to manipulate data-source
192
+ *
193
+ * @param {object[]} data .
194
+ * @returns {void} .
195
+ * @hidden
196
+ */
197
+ private prepareDataSource(data: Object[]): void {
198
+ this.prepareRecordCollection(data, 0);
199
+ // Method to maintain the shared task uniqueIds
200
+ if (this.parent.viewType === 'ResourceView') {
201
+ this.calculateSharedTaskUniqueIds();
202
+ }
203
+ if (this.parent.taskFields.dependency && this.parent.predecessorModule) {
204
+ this.parent.predecessorModule.ensurePredecessorCollection();
205
+ }
206
+ }
207
+
208
+ private calculateSharedTaskUniqueIds(): void {
209
+ for (let i: number = 0; i < this.parent.getTaskIds().length; i++) {
210
+ const value: string[] = this.parent.getTaskIds()[i].match(/(\d+|[A-z]+)/g);
211
+ if (value[0] !== 'R') {
212
+ const sharedRecords: IGanttData[] = [];
213
+ const ids: string[] = [];
214
+ this.parent.flatData.filter((data: IGanttData) => {
215
+ if (data.ganttProperties.taskId.toString() === value[1] && data.level !== 0) {
216
+ ids.push(data.ganttProperties.rowUniqueID);
217
+ sharedRecords.push(data);
218
+ }
219
+ });
220
+ for (let j: number = 0; j < sharedRecords.length; j++) {
221
+ sharedRecords[j].ganttProperties.sharedTaskUniqueIds = ids;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ private prepareRecordCollection(data: Object[], level: number, parentItem?: IGanttData): void {
227
+ const length: number = data.length;
228
+ for (let i: number = 0; i < length; i++) {
229
+ const tempData: Object = data[i];
230
+ if (!isNullOrUndefined(this.parent.taskFields.segmentId)) {
231
+ const segmentData: Object[] = this.segmentCollection.
232
+ filter((x: Group) => x.key === tempData[this.parent.taskFields.id]);
233
+ if (segmentData.length > 0) {
234
+ tempData[this.parent.taskFields.segments] = (segmentData as Group)[0].items;
235
+ }
236
+ }
237
+ const ganttData: IGanttData = this.createRecord(tempData, level, parentItem, true);
238
+ if (!this.parent.enableValidation) {
239
+ this.updateTaskLeftWidth(ganttData);
240
+ }
241
+ ganttData.index = this.recordIndex++;
242
+ this.parent.ids[ganttData.index] = ganttData.ganttProperties.rowUniqueID;
243
+ this.parent.flatData.push(ganttData);
244
+ this.parent.setTaskIds(ganttData);
245
+ const childData: Object[] = tempData[this.parent.taskFields.child];
246
+ if (this.parent.viewType === 'ResourceView' && isNullOrUndefined(childData)
247
+ && isNullOrUndefined(ganttData.parentItem) && ganttData.level === 0) {
248
+ const ganttProp: ITaskData = ganttData.ganttProperties;
249
+ const parentData: IGanttData = ganttData;
250
+ this.parent.setRecordValue(
251
+ ganttProp.isAutoSchedule ? 'startDate' : 'autoStartDate',
252
+ null, parentData.ganttProperties, true);
253
+ this.parent.setRecordValue(
254
+ ganttProp.isAutoSchedule ? 'endDate' : 'autoEndDate',
255
+ null, parentData.ganttProperties, true);
256
+ const parentProgress: number = 0;
257
+ const parentProp: ITaskData = parentData.ganttProperties;
258
+ this.parent.setRecordValue('isMilestone', false, parentProp, true);
259
+ if (parentProp.isAutoSchedule) {
260
+ this.calculateDuration(parentData);
261
+ }
262
+ this.updateWorkWithDuration(parentData);
263
+ const parentWork: number = parentProp.work;
264
+ this.parent.setRecordValue('work', parentWork, parentProp, true);
265
+ this.parent.setRecordValue('taskType', 'FixedDuration', parentProp, true);
266
+ if (!isNullOrUndefined(this.parent.taskFields.type)) {
267
+ this.updateMappingData(parentData, 'type');
268
+ }
269
+ this.parent.setRecordValue('progress', Math.floor(parentProgress), parentProp, true);
270
+ this.parent.setRecordValue('totalProgress', 0, parentProp, true);
271
+ this.parent.setRecordValue('totalDuration', 0, parentProp, true);
272
+ if (!parentProp.isAutoSchedule) {
273
+ this.parent.setRecordValue('autoDuration', this.calculateAutoDuration(parentProp), parentProp, true);
274
+ this.updateAutoWidthLeft(parentData);
275
+ }
276
+ this.resetDependency(parentData);
277
+ this.updateWidthLeft(parentData);
278
+ this.updateTaskData(parentData);
279
+ }
280
+ if (!isNullOrUndefined(childData) && childData.length > 0) {
281
+ this.prepareRecordCollection(childData, ganttData.level + 1, ganttData);
282
+ }
283
+ }
284
+ }
285
+ /**
286
+ * Method to update custom field values in gantt record
287
+ *
288
+ * @param {object} data .
289
+ * @param {IGanttData} ganttRecord .
290
+ * @returns {void} .
291
+ */
292
+ private addCustomFieldValue(data: Object, ganttRecord: IGanttData): void {
293
+ const columns: ColumnModel[] = this.parent.ganttColumns;
294
+ const length: number = columns.length;
295
+ if (length) {
296
+ for (let i: number = 0; i < length; i++) {
297
+ if (ganttRecord[columns[i].field] === undefined) {
298
+ this.parent.setRecordValue(columns[i].field, data[columns[i].field], ganttRecord);
299
+ }
300
+ }
301
+ }
302
+ }
303
+ /**
304
+ * To populate Gantt record
305
+ *
306
+ * @param {object} data .
307
+ * @param {number} level .
308
+ * @param {IGanttData} parentItem .
309
+ * @param {boolean} isLoad .
310
+ * @returns {IGanttData} .
311
+ * @private
312
+ */
313
+ public createRecord(data: Object, level: number, parentItem?: IGanttData, isLoad?: boolean): IGanttData {
314
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
315
+ const resourceFields: ResourceFieldsModel = this.parent.resourceFields;
316
+ let progress: number = data[taskSettings.progress];
317
+ let id: string = null; let name: string = null;
318
+ const notes: string = data[taskSettings.notes];
319
+ progress = progress ? parseFloat(progress.toString()) ? parseFloat(progress.toString()) : 0 : 0;
320
+ const predecessors: string | number | object[] = data[taskSettings.dependency];
321
+ const baselineStartDate: Date = this.getDateFromFormat(data[taskSettings.baselineStartDate], true);
322
+ const baselineEndDate: Date = this.getDateFromFormat(data[taskSettings.baselineEndDate], true);
323
+ const ganttData: IGanttData = {} as IGanttData;
324
+ const ganttProperties: ITaskData = {} as ITaskData;
325
+ const autoSchedule: boolean = (this.parent.taskMode === 'Auto') ? true :
326
+ (this.parent.taskMode === 'Manual') ? false :
327
+ data[taskSettings.manual] === true ? false : true;
328
+ this.parent.setRecordValue('ganttProperties', ganttProperties, ganttData);
329
+ if (!isNullOrUndefined(data[taskSettings.id])) {
330
+ id = data[taskSettings.id];
331
+ name = data[taskSettings.name];
332
+ this.addTaskData(ganttData, data, isLoad);
333
+ } else if (!isNullOrUndefined(data[resourceFields.id])) {
334
+ id = data[resourceFields.id];
335
+ name = data[resourceFields.name];
336
+ this.addTaskData(ganttData, data, false);
337
+ }
338
+ this.parent.setRecordValue('taskId', id, ganttProperties, true);
339
+ this.parent.setRecordValue('taskName', name, ganttProperties, true);
340
+ if (taskSettings.parentID) {
341
+ this.parent.setRecordValue('parentId', data[taskSettings.parentID], ganttProperties, true);
342
+ }
343
+ this.addCustomFieldValue(data, ganttData);
344
+ this.parent.setRecordValue('isAutoSchedule', autoSchedule, ganttProperties, true);
345
+ this.parent.setRecordValue('resourceInfo', this.setResourceInfo(data), ganttProperties, true);
346
+ this.parent.setRecordValue('isMilestone', false, ganttProperties, true);
347
+ this.parent.setRecordValue('indicators', data[taskSettings.indicators], ganttProperties, true);
348
+ this.updateResourceName(ganttData);
349
+ this.calculateScheduledValues(ganttData, data, isLoad);
350
+ this.parent.setRecordValue('baselineStartDate', this.checkBaselineStartDate(baselineStartDate), ganttProperties, true);
351
+ // set default end time, if hour is 0
352
+ if (baselineEndDate && baselineEndDate.getHours() === 0 && this.parent.defaultEndTime !== 86400) {
353
+ this.setTime(this.parent.defaultEndTime, baselineEndDate);
354
+ }
355
+ this.parent.setRecordValue('baselineEndDate', this.checkBaselineEndDate(baselineEndDate), ganttProperties, true);
356
+ this.parent.setRecordValue('progress', progress, ganttProperties, true);
357
+ this.parent.setRecordValue('totalProgress', progress, ganttProperties, true);
358
+ this.parent.setRecordValue('predecessorsName', predecessors, ganttProperties, true);
359
+ this.parent.setRecordValue('notes', notes, ganttProperties, true);
360
+ this.parent.setRecordValue('cssClass', data[taskSettings.cssClass], ganttProperties, true);
361
+ this.parent.setRecordValue('parentItem', this.getCloneParent(parentItem), ganttData);
362
+ const parentUniqId: string = ganttData.parentItem ? ganttData.parentItem.uniqueID : null;
363
+ this.parent.setRecordValue('parentUniqueID', parentUniqId, ganttData);
364
+ if (this.parent.viewType === 'ResourceView' && !isNullOrUndefined(taskSettings.parentID)
365
+ && !isNullOrUndefined(ganttData.parentItem)) {
366
+ this.parent.setRecordValue('parentId', ganttData.parentItem.taskId, ganttProperties, true);
367
+ }
368
+ this.parent.setRecordValue('level', level, ganttData);
369
+ this.parent.setRecordValue('uniqueID', getUid(this.parent.element.id + '_data_'), ganttData);
370
+ this.parent.setRecordValue('uniqueID', ganttData.uniqueID, ganttProperties, true);
371
+ this.parent.setRecordValue('childRecords', [], ganttData);
372
+ if (this.parent.dataSource instanceof Object && isCountRequired(this.parent) &&
373
+ !isNullOrUndefined(taskSettings.child)) {
374
+ this.parent.setRecordValue(taskSettings.child, [], ganttData);
375
+ }
376
+ this.parent.setRecordValue('baselineEndDate', this.checkBaselineEndDate(baselineEndDate), ganttProperties, true);
377
+ if (!isNullOrUndefined(data[taskSettings.child]) && data[taskSettings.child].length > 0) {
378
+ this.parent.setRecordValue('hasChildRecords', true, ganttData);
379
+ this.parent.setRecordValue('isMilestone', false, ganttProperties, true);
380
+ this.resetDependency(ganttData);
381
+ } else {
382
+ this.parent.setRecordValue('hasChildRecords', false, ganttData);
383
+ }
384
+ if (ganttData.hasChildRecords) {
385
+ this.parent.setRecordValue('autoStartDate', ganttData.ganttProperties.startDate, ganttProperties);
386
+ this.parent.setRecordValue('autoEndDate', ganttData.ganttProperties.endDate, ganttProperties);
387
+ this.parent.setRecordValue('autoDuration', ganttData.ganttProperties.duration, ganttProperties);
388
+ }
389
+ this.parent.setRecordValue('expanded', (ganttData.hasChildRecords && this.parent.collapseAllParentTasks) ? false : true, ganttData);
390
+ this.updateExpandStateMappingValue(ganttData, data);
391
+ if (!isLoad) {
392
+ this.parent.setRecordValue('width', this.calculateWidth(ganttData), ganttProperties, true);
393
+ this.parent.setRecordValue('left', this.calculateLeft(ganttProperties), ganttProperties, true);
394
+ this.parent.setRecordValue(
395
+ 'progressWidth',
396
+ this.getProgressWidth(ganttProperties.width, progress),
397
+ ganttProperties,
398
+ true);
399
+ if (ganttProperties.baselineEndDate && ganttProperties.baselineStartDate) {
400
+ this.parent.setRecordValue('baselineLeft', this.calculateBaselineLeft(ganttProperties), ganttProperties, true);
401
+ this.parent.setRecordValue('baselineWidth', this.calculateBaselineWidth(ganttProperties), ganttProperties, true);
402
+ }
403
+ }
404
+ if (isNullOrUndefined(taskSettings.work)) {
405
+ this.updateWorkWithDuration(ganttData);
406
+ }
407
+ if (!isNullOrUndefined(taskSettings.manual)) {
408
+ this.parent.dataOperation.updateMappingData(ganttData, 'manual');
409
+ }
410
+ this.updateTaskData(ganttData);
411
+ if (predecessors) {
412
+ this.parent.predecessorsCollection.push(ganttData);
413
+ }
414
+ if (!isNullOrUndefined(parentItem)) {
415
+ parentItem.childRecords.push(ganttData);
416
+ if (this.parent.dataSource instanceof Object && isCountRequired(this.parent) &&
417
+ !isNullOrUndefined(this.parent.taskFields.child)) {
418
+ parentItem[this.parent.taskFields.child].push(ganttData.taskData);
419
+ }
420
+ }
421
+ if (this.parent.viewType === 'ProjectView') {
422
+ this.parent.setRecordValue('rowUniqueID', ganttProperties.taskId.toString(), ganttProperties, true);
423
+ } else {
424
+ const uniqueId: string = ganttData.uniqueID.replace(this.parent.element.id + '_data_', '');
425
+ this.parent.setRecordValue('rowUniqueID', uniqueId, ganttData);
426
+ this.parent.setRecordValue('rowUniqueID', uniqueId, ganttProperties, true);
427
+ this.parent.setRecordValue('sharedTaskUniqueIds', [], ganttProperties, true);
428
+ }
429
+ if (this.parent.allowUnscheduledTasks && ganttData.ganttProperties.startDate
430
+ && (ganttData.ganttProperties.endDate || ganttData.ganttProperties.duration)) {
431
+ this.parent.setRecordValue('segments', this.setSegmentsInfo(ganttData, true), ganttProperties, true);
432
+ this.parent.dataOperation.updateMappingData(ganttData, 'segments');
433
+ if (!isLoad) {
434
+ this.updateWidthLeft(ganttData);
435
+ }
436
+ }
437
+ return ganttData;
438
+ }
439
+
440
+ private sortSegmentsData(segments: ITaskSegment[], onLoad: boolean, ganttProp: ITaskData): ITaskSegment[] { // eslint-disable-line
441
+ if (onLoad) {
442
+ segments.sort((a: ITaskSegment, b: ITaskSegment) => {
443
+ const startDate: string = this.parent.taskFields.startDate;
444
+ return this.getDateFromFormat(a[startDate]).getTime() - this.getDateFromFormat(b[startDate]).getTime();
445
+ });
446
+ } else {
447
+ segments.sort((a: ITaskSegment, b: ITaskSegment) => {
448
+ return a.startDate.getTime() - b.startDate.getTime();
449
+ });
450
+ }
451
+ return segments;
452
+ }
453
+ public setSegmentsInfo(data: IGanttData, onLoad: boolean): ITaskSegment[] {
454
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
455
+ let ganttSegments: ITaskSegment[] = [];
456
+ let segments: ITaskSegment[];
457
+ let sumOfDuration: number = 0;
458
+ let remainingDuration: number = 0;
459
+ const taskData: object[] = [];
460
+ if (!isNullOrUndefined(this.parent.taskFields.segments)) {
461
+ segments = onLoad ? data.taskData[this.parent.taskFields.segments] : data.ganttProperties.segments;
462
+ if (!isNullOrUndefined(segments) && segments.length > 1) {
463
+ this.sortSegmentsData(segments, onLoad, data.ganttProperties);
464
+ for (let i: number = 0; i < segments.length; i++) {
465
+ let segment: ITaskSegment = segments[i];
466
+ let startDate: Date = onLoad ? segment[taskSettings.startDate] : segment.startDate;
467
+ let endDate: Date = onLoad ? segment[taskSettings.endDate] : segment.endDate;
468
+ let duration: number = onLoad ? segment[taskSettings.duration] : segment.duration;
469
+ startDate = this.getDateFromFormat(startDate);
470
+ startDate = this.checkStartDate(startDate, data.ganttProperties, false);
471
+ if (!isNullOrUndefined(duration)) {
472
+ endDate = this.getEndDate(startDate, duration, data.ganttProperties.durationUnit, data.ganttProperties, false);
473
+ } else {
474
+ endDate = this.getDateFromFormat(endDate);
475
+ endDate = this.checkEndDate(endDate, data.ganttProperties, false);
476
+ duration = this.getDuration(
477
+ startDate, endDate, data.ganttProperties.durationUnit,
478
+ data.ganttProperties.isAutoSchedule, data.ganttProperties.isMilestone);
479
+ }
480
+ if (taskSettings.duration) {
481
+ remainingDuration = data.ganttProperties.duration - sumOfDuration;
482
+ if (remainingDuration <= 0) {
483
+ continue;
484
+ }
485
+ duration = i === segments.length - 1 ? remainingDuration : remainingDuration > 0 &&
486
+ duration > remainingDuration ? remainingDuration : duration;
487
+ endDate = this.getEndDate(startDate, duration, data.ganttProperties.durationUnit, data.ganttProperties, false);
488
+ } else if (!taskSettings.duration && taskSettings.endDate) {
489
+ endDate = (!isNullOrUndefined(data.ganttProperties.endDate)) && endDate.getTime() >
490
+ data.ganttProperties.endDate.getTime() && i !== segments.length - 1 ? endDate : data.ganttProperties.endDate;
491
+ duration = this.getDuration(
492
+ startDate, endDate, data.ganttProperties.durationUnit, data.ganttProperties.isAutoSchedule,
493
+ data.ganttProperties.isMilestone
494
+ );
495
+ if (ganttSegments.length > 0 && endDate.getTime() < startDate.getTime()
496
+ && endDate.getTime() <= data.ganttProperties.endDate.getTime()) {
497
+ ganttSegments[i - 1].duration = this.getDuration(
498
+ ganttSegments[i - 1].startDate, data.ganttProperties.endDate, data.ganttProperties.durationUnit,
499
+ data.ganttProperties.isAutoSchedule, data.ganttProperties.isMilestone);
500
+ continue;
501
+ }
502
+ }
503
+ segment = {};
504
+ if (!(startDate && endDate) || !(startDate && duration)) {
505
+ break;
506
+ }
507
+ sumOfDuration += duration;
508
+ segment.startDate = startDate;
509
+ segment.endDate = endDate;
510
+ segment.duration = duration;
511
+ segment.width = 0;
512
+ segment.left = 0;
513
+ segment.segmentIndex = i;
514
+ ganttSegments.push(segment);
515
+ if (!isNullOrUndefined(ganttSegments[i - 1])) {
516
+ const offsetDuration: number = this.getDuration(
517
+ ganttSegments[i - 1].endDate, ganttSegments[i].startDate, data.ganttProperties.durationUnit,
518
+ data.ganttProperties.isAutoSchedule, data.ganttProperties.isMilestone);
519
+ segment.offsetDuration = offsetDuration;
520
+ if (offsetDuration < 1) {
521
+ segment.startDate = this.getEndDate(
522
+ ganttSegments[i - 1].endDate, 1, data.ganttProperties.durationUnit, data.ganttProperties, false
523
+ );
524
+ segment.startDate = this.checkStartDate(segment.startDate, data.ganttProperties, false);
525
+ segment.endDate = this.getEndDate(
526
+ segment.startDate, segment.duration, data.ganttProperties.durationUnit, data.ganttProperties, false
527
+ );
528
+ segment.endDate = !taskSettings.duration && taskSettings.endDate
529
+ && segment.endDate > data.ganttProperties.endDate ? data.ganttProperties.endDate : segment.endDate;
530
+ segment.offsetDuration = 1;
531
+ }
532
+
533
+ } else {
534
+ segment.offsetDuration = 0;
535
+ }
536
+ taskData.push(this.setSegmentTaskData(segment, segments[i]));
537
+ }
538
+ this.parent.setRecordValue('duration', sumOfDuration, data.ganttProperties, true);
539
+ this.parent.setRecordValue('endDate', ganttSegments[ganttSegments.length - 1].endDate, data.ganttProperties, true);
540
+ if (!isNullOrUndefined(taskSettings.endDate)) {
541
+ this.parent.setRecordValue(this.parent.taskFields.endDate, ganttSegments[ganttSegments.length - 1].endDate, data, true);
542
+ }
543
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.segments, taskData, data);
544
+ }
545
+ }
546
+ if (ganttSegments.length > 1) {
547
+ this.parent.setRecordValue('segments', ganttSegments, data.ganttProperties, true);
548
+ } else {
549
+ ganttSegments = null;
550
+ }
551
+ return ganttSegments;
552
+ }
553
+
554
+ private setSegmentTaskData(segments: ITaskSegment, segmenttaskData: ITaskSegment): ITaskSegment {
555
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
556
+ const taskData: Object = extend({}, {}, segmenttaskData, true);
557
+ if (!isNullOrUndefined(taskSettings.startDate)) {
558
+ taskData[this.parent.taskFields.startDate] = segments.startDate;
559
+ }
560
+ if (!isNullOrUndefined(taskSettings.endDate)) {
561
+ taskData[this.parent.taskFields.endDate] = segments.endDate;
562
+ }
563
+ if (!isNullOrUndefined(taskSettings.duration)) {
564
+ taskData[this.parent.taskFields.duration] = Number(segments.duration);
565
+ }
566
+ return taskData;
567
+ }
568
+
569
+ /**
570
+ * Method to calculate work based on resource unit and duration.
571
+ *
572
+ * @param {IGanttData} ganttData .
573
+ * @returns {void} .
574
+ */
575
+ public updateWorkWithDuration(ganttData: IGanttData): void {
576
+ const resources: Object[] = ganttData.ganttProperties.resourceInfo;
577
+ let work: number = 0;
578
+ if (!isNullOrUndefined(resources)) {
579
+ const resourcesLength: number = resources.length;
580
+ let index: number;
581
+ let resourceUnit: number;
582
+ let resourceOneDayWork: number;
583
+ const actualOneDayWork: number = (this.parent.secondsPerDay) / 3600;
584
+ const durationInDay: number = this.getDurationInDay(ganttData.ganttProperties.duration, ganttData.ganttProperties.durationUnit);
585
+ for (index = 0; index < resourcesLength; index++) {
586
+ resourceUnit = resources[index][this.parent.resourceFields.unit]; //in percentage
587
+ resourceOneDayWork = resourceUnit > 0 ? (actualOneDayWork * resourceUnit) / 100 : actualOneDayWork; //in hours
588
+ work += (resourceOneDayWork * durationInDay);
589
+ }
590
+ //Update work as per defined unit.
591
+ if (ganttData.ganttProperties.workUnit === 'minute') {
592
+ work = work * 60;
593
+ }
594
+ if (ganttData.ganttProperties.workUnit === 'day') {
595
+ work = work / actualOneDayWork;
596
+ }
597
+ //To check the decimal places.
598
+ if (work % 1 !== 0) {
599
+ work = parseFloat(work.toFixed(2));
600
+ }
601
+ }
602
+ this.parent.setRecordValue('work', work, ganttData.ganttProperties, true);
603
+ if (!isNullOrUndefined(this.parent.taskFields.work)) {
604
+ this.parent.dataOperation.updateMappingData(ganttData, 'work');
605
+ }
606
+ }
607
+
608
+ /**
609
+ *
610
+ * @param {IGanttData} parent .
611
+ * @returns {IParent} .
612
+ * @private
613
+ */
614
+ public getCloneParent(parent: IGanttData): IParent {
615
+ if (!isNullOrUndefined(parent)) {
616
+ const cloneParent: IParent = {};
617
+ cloneParent.uniqueID = parent.uniqueID;
618
+ cloneParent.expanded = parent.expanded;
619
+ cloneParent.level = parent.level;
620
+ cloneParent.index = parent.index;
621
+ cloneParent.taskId = parent.ganttProperties.rowUniqueID;
622
+ return cloneParent;
623
+ } else {
624
+ return null;
625
+ }
626
+ }
627
+
628
+ /**
629
+ * @returns {void} .
630
+ * @private
631
+ */
632
+ public reUpdateResources(): void {
633
+ if (this.parent.flatData.length > 0) {
634
+ let data: ITaskData;
635
+ let ganttProperties: ITaskData;
636
+ let ganttData: IGanttData;
637
+ for (let index: number = 0; index < this.parent.flatData.length; index++) {
638
+ data = this.parent.flatData[index].taskData;
639
+ ganttProperties = this.parent.flatData[index].ganttProperties;
640
+ ganttData = this.parent.flatData[index];
641
+ this.parent.setRecordValue('resourceInfo', this.setResourceInfo(data), ganttProperties, true);
642
+ this.updateResourceName(ganttData);
643
+ }
644
+ }
645
+ }
646
+ private addTaskData(ganttData: IGanttData, data: Object, isLoad: boolean): void {
647
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
648
+ const dataManager: Object[] | DataManager | Object = this.parent.dataSource;
649
+ if (isLoad) {
650
+ if (taskSettings.parentID || (dataManager instanceof DataManager &&
651
+ dataManager.dataSource.json && dataManager.dataSource.offline)) {
652
+ if (taskSettings.parentID) {
653
+ const id: string = data[taskSettings.id];
654
+ const index: number = this.taskIds.indexOf(id.toString());
655
+ const tempData: object = (index > -1) ? this.dataArray[index] : {};
656
+ if (!isNullOrUndefined(this.parent.taskFields.segmentId)) {
657
+ const segmentDataCollection: Object[] = this.segmentCollection.
658
+ filter((x: Group) => x.key === tempData[this.parent.taskFields.id]);
659
+ if (segmentDataCollection.length > 0) {
660
+ tempData[this.parent.taskFields.segments] = (segmentDataCollection as Group)[0].items;
661
+ }
662
+ }
663
+ this.parent.setRecordValue('taskData', tempData, ganttData);
664
+ } else {
665
+ this.parent.setRecordValue('taskData', data, ganttData);
666
+ }
667
+ } else {
668
+ this.parent.setRecordValue('taskData', data, ganttData);
669
+ }
670
+ } else {
671
+ this.parent.setRecordValue('taskData', data, ganttData);
672
+ }
673
+ }
674
+
675
+ private updateExpandStateMappingValue(ganttData: IGanttData, data: Object): void {
676
+ const expandStateMapping: string = this.parent.taskFields.expandState;
677
+ const mappingValue: string = data[expandStateMapping];
678
+ let updatableValue: boolean;
679
+ if (expandStateMapping && ganttData.hasChildRecords) {
680
+ if (!isNullOrUndefined(mappingValue)) {
681
+ updatableValue = mappingValue.toString() === 'true' ? true : false;
682
+ } else if (isNullOrUndefined(mappingValue) && !this.parent.collapseAllParentTasks) {
683
+ updatableValue = true;
684
+ } else if (isNullOrUndefined(mappingValue) && this.parent.collapseAllParentTasks) {
685
+ updatableValue = false;
686
+ }
687
+ this.parent.setRecordValue('taskData.' + expandStateMapping, updatableValue, ganttData);
688
+ this.parent.setRecordValue(expandStateMapping, updatableValue, ganttData);
689
+ this.parent.setRecordValue('expanded', updatableValue, ganttData);
690
+ }
691
+ }
692
+ /**
693
+ * @param {IGanttData} ganttData .
694
+ * @param {object} data .
695
+ * @returns {void} .
696
+ */
697
+ private setValidatedDates(ganttData: IGanttData, data: Object): void {
698
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
699
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
700
+ let duration: string = data[taskSettings.duration];
701
+ const startDate: Date = this.getDateFromFormat(data[taskSettings.startDate], true);
702
+ const endDate: Date = this.getDateFromFormat(data[taskSettings.endDate], true);
703
+ duration = isNullOrUndefined(duration) || duration === '' ? null : duration;
704
+ this.parent.setRecordValue('startDate', new Date(startDate.getTime()), ganttProperties, true);
705
+ if (!isNullOrUndefined(duration) && duration !== '') {
706
+ this.updateDurationValue(duration, ganttProperties);
707
+ } else {
708
+ this.calculateDuration(ganttData);
709
+ }
710
+ this.parent.setRecordValue('endDate', new Date((endDate.getTime())), ganttProperties, true);
711
+ }
712
+ /**
713
+ *
714
+ * @param {IGanttData} ganttData .
715
+ * @param {object} data .
716
+ * @param {boolean} isLoad .
717
+ * @returns {void} .
718
+ * @private
719
+ */
720
+ public calculateScheduledValues(ganttData: IGanttData, data: Object, isLoad: boolean): void {
721
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
722
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
723
+ let duration: string = data[taskSettings.duration];
724
+ duration = isNullOrUndefined(duration) || duration === '' ? null : duration;
725
+ let startDate: Date;
726
+ let endDate: Date;
727
+ if (ganttProperties.startDate && ganttProperties.endDate) {
728
+ startDate = this.getDateFromFormat(ganttProperties.startDate, true);
729
+ endDate = this.getDateFromFormat(ganttProperties.endDate, true);
730
+ } else {
731
+ startDate = this.getDateFromFormat(data[taskSettings.startDate], true);
732
+ endDate = this.getDateFromFormat(data[taskSettings.endDate], true);
733
+ }
734
+ const segments: ITaskSegment[] = taskSettings.segments ? (data[taskSettings.segments] ||
735
+ ganttData.taskData[taskSettings.segments]) : null;
736
+ const isMileStone: boolean = taskSettings.milestone ? data[taskSettings.milestone] ? true : false : false;
737
+ const durationMapping: string = data[taskSettings.durationUnit] ? data[taskSettings.durationUnit] : '';
738
+ this.parent.setRecordValue('durationUnit', this.validateDurationUnitMapping(durationMapping), ganttProperties, true);
739
+ const work: number = !isNullOrUndefined(data[taskSettings.work]) ? parseFloat(data[taskSettings.work]) : 0;
740
+ this.parent.setRecordValue('workUnit', this.validateWorkUnitMapping(this.parent.workUnit), ganttProperties, true);
741
+ const taskTypeMapping: string = data[taskSettings.type] ? data[taskSettings.type] : '';
742
+ const tType: string = this.validateTaskTypeMapping(taskTypeMapping);
743
+ this.parent.setRecordValue('taskType', tType, ganttProperties, true);
744
+
745
+ if (isLoad && !this.parent.enableValidation && startDate && endDate) {
746
+ this.setValidatedDates(ganttData, data);
747
+ } else {
748
+ if (!endDate && !startDate && (isNullOrUndefined(duration) || duration === '')) {
749
+ if (this.parent.allowUnscheduledTasks) {
750
+ return;
751
+ } else {
752
+ this.parent.setRecordValue('duration', 1, ganttProperties, true);
753
+ this.parent.setRecordValue('startDate', this.getProjectStartDate(ganttProperties, isLoad), ganttProperties, true);
754
+ this.calculateEndDate(ganttData);
755
+ }
756
+ } else if (startDate) {
757
+ this.calculateDateFromStartDate(startDate, endDate, duration, ganttData, isLoad);
758
+
759
+ } else if (endDate) {
760
+ this.calculateDateFromEndDate(endDate, duration, ganttData);
761
+
762
+ } else if (!isNullOrUndefined(duration) && duration !== '') {
763
+ this.updateDurationValue(duration, ganttProperties);
764
+ if (this.parent.allowUnscheduledTasks) {
765
+ this.parent.setRecordValue('startDate', null, ganttProperties, true);
766
+ this.parent.setRecordValue('endDate', null, ganttProperties, true);
767
+ } else {
768
+ this.parent.setRecordValue('startDate', this.getProjectStartDate(ganttProperties, isLoad), ganttProperties, true);
769
+ this.calculateEndDate(ganttData);
770
+ }
771
+ }
772
+ }
773
+ if (!isNullOrUndefined(segments)) {
774
+ this.parent.setRecordValue('segments', this.setSegmentsInfo(ganttData, true), ganttProperties, true);
775
+ }
776
+ if (ganttProperties.duration === 0) {
777
+ this.parent.setRecordValue('isMilestone', true, ganttProperties, true);
778
+ this.parent.setRecordValue('endDate', ganttProperties.startDate, ganttProperties, true);
779
+ }
780
+ if (!isNullOrUndefined(isMileStone) && isMileStone) {
781
+ this.parent.setRecordValue('duration', 0, ganttProperties, true);
782
+ this.parent.setRecordValue('isMilestone', true, ganttProperties, true);
783
+ this.parent.setRecordValue('endDate', ganttProperties.startDate, ganttProperties, true);
784
+ }
785
+ if (!isNullOrUndefined(taskSettings.work)) {
786
+ this.parent.setRecordValue('durationUnit', this.parent.durationUnit, ganttProperties, true);
787
+ if (isNaN(work) || isNullOrUndefined(work)) {
788
+ this.parent.setRecordValue('work', 0, ganttProperties, true);
789
+ this.parent.setRecordValue('duration', 0, ganttProperties, true);
790
+ this.parent.setRecordValue('isMilestone', true, ganttProperties, true);
791
+ this.parent.setRecordValue('endDate', ganttProperties.startDate, ganttProperties, true);
792
+ } else {
793
+ this.parent.setRecordValue('work', work, ganttProperties, true);
794
+ switch (tType) {
795
+ case 'FixedDuration':
796
+ this.updateUnitWithWork(ganttData);
797
+ break;
798
+ case 'FixedWork':
799
+ this.updateUnitWithWork(ganttData);
800
+ break;
801
+ case 'FixedUnit':
802
+ this.updateDurationWithWork(ganttData);
803
+ break;
804
+ }
805
+ if (!isNullOrUndefined(taskSettings.type)) {
806
+ this.parent.dataOperation.updateMappingData(ganttData, 'type');
807
+ }
808
+ if (ganttProperties.duration === 0) {
809
+ this.parent.setRecordValue('isMilestone', true, ganttProperties, true);
810
+ this.parent.setRecordValue('endDate', ganttProperties.startDate, ganttProperties, true);
811
+ } else if (!isNullOrUndefined(ganttProperties.startDate) && !isNullOrUndefined(ganttProperties.duration)) {
812
+ this.parent.setRecordValue('isMilestone', false, ganttProperties, true);
813
+ this.calculateEndDate(ganttData);
814
+ }
815
+ }
816
+ this.parent.dataOperation.updateMappingData(ganttData, 'work');
817
+ } else if (taskSettings.type && ganttProperties.taskType) {
818
+ this.parent.dataOperation.updateMappingData(ganttData, 'type');
819
+ }
820
+ }
821
+ /**
822
+ * Method to update duration with work value.
823
+ *
824
+ * @param {IGanttData} ganttData .
825
+ * @returns {void} .
826
+ */
827
+ public updateDurationWithWork(ganttData: IGanttData): void {
828
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
829
+ const resources: Object[] = ganttProperties.resourceInfo;
830
+ if (!isNullOrUndefined(resources)) {
831
+ const resourcesLength: number = !isNullOrUndefined(resources) ? resources.length : 0;
832
+ let totalResourceOneDayWork: number = 0;
833
+ const actualOneDayWork: number = (this.parent.secondsPerDay) / 3600;
834
+ let updatedDuration: number = 0;
835
+ let resourceUnit: number;
836
+ let index: number;
837
+ for (index = 0; index < resourcesLength; index++) {
838
+ resourceUnit = resources[index][this.parent.resourceFields.unit]; //in percentage
839
+ totalResourceOneDayWork += (resourceUnit > 0 ? (actualOneDayWork * resourceUnit) / 100 : actualOneDayWork); //in hours
840
+ }
841
+ const totalHours: number = this.getWorkInHour(ganttProperties.work, ganttProperties.workUnit);
842
+ if (resourcesLength > 0) {
843
+ updatedDuration += (totalHours / totalResourceOneDayWork);
844
+ }
845
+
846
+ //Update duration as per defined unit.
847
+ if (ganttProperties.durationUnit === 'minute') {
848
+ updatedDuration = updatedDuration * actualOneDayWork * 60;
849
+ }
850
+ if (ganttProperties.durationUnit === 'hour') {
851
+ updatedDuration = updatedDuration * actualOneDayWork;
852
+ }
853
+ //To check the decimal places.
854
+ if (updatedDuration % 1 !== 0) {
855
+ updatedDuration = parseFloat(updatedDuration.toFixed(2));
856
+ }
857
+ if (!isNullOrUndefined(ganttProperties.duration)) {
858
+ this.parent.setRecordValue('duration', updatedDuration, ganttProperties, true);
859
+ }
860
+ this.parent.dataOperation.updateMappingData(ganttData, 'duration');
861
+ }
862
+ }
863
+ /**
864
+ * Update units of resources with respect to duration and work of a task.
865
+ *
866
+ * @param {IGanttData} ganttData .
867
+ * @returns {void} .
868
+ */
869
+ public updateUnitWithWork(ganttData: IGanttData): void {
870
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
871
+ const resources: Object[] = ganttProperties.resourceInfo;
872
+ const resourcesLength: number = !isNullOrUndefined(resources) ? resources.length : 0;
873
+ const actualOneDayWork: number = (this.parent.secondsPerDay) / 3600;
874
+ if (resourcesLength === 0) {
875
+ return;
876
+ }
877
+ const durationInDay: number = this.getDurationInDay(ganttData.ganttProperties.duration, ganttData.ganttProperties.durationUnit);
878
+ const totalHours: number = this.getWorkInHour(ganttProperties.work, ganttProperties.workUnit);
879
+ const totalUnitInPercentage: number = durationInDay > 0 ? (totalHours / (durationInDay * actualOneDayWork)) * 100 : 0;
880
+ let individualUnit: number = totalUnitInPercentage > 0 ? totalUnitInPercentage / resourcesLength : 100;
881
+ //To check the decimal places.
882
+ if (individualUnit % 1 !== 0) {
883
+ individualUnit = parseFloat(individualUnit.toFixed(2));
884
+ }
885
+ for (let index: number = 0; index < resourcesLength; index++) {
886
+ resources[index][this.parent.resourceFields.unit] = individualUnit;
887
+ }
888
+ //To update the unit value in data source
889
+ this.updateResourceName(ganttData);
890
+ }
891
+ private calculateDateFromEndDate(endDate: Date, duration: string, ganttData: IGanttData): void {
892
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
893
+
894
+ if (endDate.getHours() === 0 && this.parent.defaultEndTime !== 86400) {
895
+ this.setTime(this.parent.defaultEndTime, endDate);
896
+ }
897
+ const validateAsMilestone: boolean = (parseInt(duration, 10) === 0) ? true : null;
898
+ this.parent.setRecordValue('endDate', this.checkEndDate(endDate, ganttData.ganttProperties, validateAsMilestone), ganttProperties, true);
899
+ if (isNullOrUndefined(duration) || duration === '') {
900
+ if (this.parent.allowUnscheduledTasks) {
901
+ this.parent.setRecordValue('startDate', null, ganttProperties, true);
902
+ this.parent.setRecordValue('duration', null, ganttProperties, true);
903
+ } else {
904
+ this.parent.setRecordValue('duration', 1, ganttProperties, true);
905
+ this.parent.setRecordValue(
906
+ 'startDate',
907
+ this.getStartDate(ganttProperties.endDate, ganttProperties.duration, ganttProperties.durationUnit, ganttProperties),
908
+ ganttProperties,
909
+ true);
910
+ }
911
+ } else if (!isNullOrUndefined(duration) && duration !== '') {
912
+ this.updateDurationValue(duration, ganttProperties);
913
+ this.parent.setRecordValue(
914
+ 'startDate',
915
+ this.getStartDate(ganttProperties.endDate, ganttProperties.duration, ganttProperties.durationUnit, ganttProperties),
916
+ ganttProperties,
917
+ true);
918
+ }
919
+ }
920
+ private calculateDateFromStartDate(startDate: Date, endDate: Date, duration: string, ganttData: IGanttData, isLoad: boolean): void {
921
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
922
+ const validateAsMilestone: boolean = (parseInt(duration, 10) === 0 || ((startDate && endDate) &&
923
+ (new Date(startDate.getTime()) === new Date(endDate.getTime())))) ? true : null;
924
+ this.parent.setRecordValue('startDate', this.checkStartDate(startDate, ganttProperties, validateAsMilestone, isLoad), ganttProperties, true);
925
+ if (this.parent.isTreeGridRendered && ganttData) {
926
+ this.updateTaskData(ganttData);
927
+ }
928
+ if (!endDate && (isNullOrUndefined(duration) || duration === '')) {
929
+ if (this.parent.allowUnscheduledTasks) {
930
+ this.parent.setRecordValue('endDate', null, ganttProperties, true);
931
+ this.parent.setRecordValue('duration', null, ganttProperties, true);
932
+ } else {
933
+ this.parent.setRecordValue('duration', 1, ganttProperties, true);
934
+ this.calculateEndDate(ganttData);
935
+ }
936
+ } else if (!isNullOrUndefined(duration) && !endDate) {
937
+ this.updateDurationValue(duration, ganttProperties);
938
+ this.calculateEndDate(ganttData);
939
+ } else if (endDate && (isNullOrUndefined(duration) || duration === '')) {
940
+ if (endDate.getHours() === 0 && this.parent.defaultEndTime !== 86400) {
941
+ this.setTime(this.parent.defaultEndTime, endDate);
942
+ }
943
+ this.parent.setRecordValue('endDate', this.checkEndDate(endDate, ganttData.ganttProperties), ganttProperties, true);
944
+ if (this.compareDates(ganttProperties.startDate, ganttProperties.endDate) === 1) {
945
+ this.parent.setRecordValue('endDate', ganttProperties.startDate, ganttProperties, true);
946
+ this.parent.setRecordValue('isMilestone', true, ganttProperties, true);
947
+ this.parent.setRecordValue('duration', 0, ganttProperties, true);
948
+ } else {
949
+ this.calculateDuration(ganttData);
950
+ }
951
+ } else {
952
+ this.updateDurationValue(duration, ganttProperties);
953
+ this.calculateEndDate(ganttData);
954
+ }
955
+ }
956
+ /**
957
+ *
958
+ * @param {number} parentWidth .
959
+ * @param {number} percent .
960
+ * @returns {number} .
961
+ * @private
962
+ */
963
+ public getProgressWidth(parentWidth: number, percent: number): number {
964
+ return (parentWidth * percent) / 100;
965
+ }
966
+ /**
967
+ *
968
+ * @param {IGanttData} ganttData .
969
+ * @param {boolean} isAuto .
970
+ * @returns {number} .
971
+ * @private
972
+ */
973
+ public calculateWidth(ganttData: IGanttData, isAuto?: boolean): number {
974
+ const ganttProp: ITaskData = ganttData.ganttProperties;
975
+ let sDate: Date = isAuto ? ganttProp.autoStartDate : ganttProp.startDate;
976
+ let eDate: Date = isAuto ? ganttProp.autoEndDate : ganttProp.endDate;
977
+ const unscheduledTaskWidth: number = 3;
978
+ if (isNullOrUndefined(sDate) && isNullOrUndefined(eDate)) {
979
+ sDate = this.getValidStartDate(ganttProp, isAuto);
980
+ eDate = this.getValidEndDate(ganttProp, isAuto);
981
+ }
982
+ if (isNullOrUndefined(sDate) || isNullOrUndefined(eDate)) {
983
+ return unscheduledTaskWidth;
984
+ } else if (ganttProp.isMilestone && (!ganttData.hasChildRecords || ganttProp.isAutoSchedule)) {
985
+ //let taskBarHeight: number = this.getTaskbarHeight();
986
+ return 0;
987
+ } else {
988
+ return this.getTaskWidth(sDate, eDate);
989
+ }
990
+ }
991
+
992
+ private getTaskbarHeight(): number {
993
+ const rowHeight: number = this.parent.rowHeight;
994
+ const taskBarHeight: number = this.parent.taskbarHeight;
995
+ if (taskBarHeight < rowHeight) {
996
+ return taskBarHeight;
997
+ } else {
998
+ return rowHeight;
999
+ }
1000
+ }
1001
+ /**
1002
+ * Method to calculate left
1003
+ *
1004
+ * @param {ITaskData} ganttProp .
1005
+ * @param {boolean} isAuto .
1006
+ * @returns {number} .
1007
+ * @private
1008
+ */
1009
+ public calculateLeft(ganttProp: ITaskData, isAuto?: boolean): number {
1010
+ let sDate: Date = null; let left: number = -300;
1011
+ const startDate: Date = isAuto ? ganttProp.autoStartDate : ganttProp.startDate;
1012
+ const endDate: Date = isAuto ? ganttProp.autoEndDate : ganttProp.endDate;
1013
+ const duration: number = isAuto ? ganttProp.autoDuration : ganttProp.duration; // eslint-disable-line
1014
+ let milestone: boolean = ganttProp.isMilestone;
1015
+ if (startDate) {
1016
+ sDate = new Date(startDate.getTime());
1017
+ } else if (endDate) {
1018
+ sDate = new Date(endDate.getTime());
1019
+ milestone = true;
1020
+ } else {
1021
+ sDate = this.getValidStartDate(ganttProp);
1022
+ }
1023
+ if (!isNullOrUndefined(sDate)) {
1024
+ left = this.getTaskLeft(sDate, milestone);
1025
+ }
1026
+ return left;
1027
+ }
1028
+ /**
1029
+ * calculate the left position of the auto scheduled taskbar
1030
+ *
1031
+ * @param {ITaskData} ganttProperties - Defines the gantt data.
1032
+ * @returns {number} .
1033
+ * @private
1034
+ */
1035
+ public calculateAutoLeft(ganttProperties: ITaskData): number {
1036
+ return this.getTaskLeft(ganttProperties.autoStartDate, ganttProperties.isMilestone);
1037
+ }
1038
+ /**
1039
+ * To calculate duration of Gantt record with auto scheduled start date and auto scheduled end date
1040
+ *
1041
+ * @param {ITaskData} ganttProperties - Defines the gantt data.
1042
+ * @returns {number} .
1043
+ */
1044
+ public calculateAutoDuration(ganttProperties: ITaskData): number {
1045
+ return this.getDuration(
1046
+ ganttProperties.autoStartDate, ganttProperties.autoEndDate, ganttProperties.durationUnit,
1047
+ false, ganttProperties.isMilestone);
1048
+ }
1049
+ /**
1050
+ * calculate the with between auto scheduled start date and auto scheduled end date
1051
+ *
1052
+ * @param {ITaskData} ganttProperties - Defines the gantt data.
1053
+ * @returns {number} .
1054
+ * @private
1055
+ */
1056
+ public calculateAutoWidth(ganttProperties: ITaskData): number {
1057
+ return this.getTaskWidth(ganttProperties.autoStartDate, ganttProperties.autoEndDate);
1058
+ }
1059
+ /**
1060
+ * calculate the left margin of the baseline element
1061
+ *
1062
+ * @param {ITaskData} ganttProperties .
1063
+ * @returns {number} .
1064
+ * @private
1065
+ */
1066
+ public calculateBaselineLeft(ganttProperties: ITaskData): number {
1067
+ const baselineStartDate: Date = this.getDateFromFormat(ganttProperties.baselineStartDate);
1068
+ const baselineEndDate: Date = this.getDateFromFormat(ganttProperties.baselineEndDate);
1069
+ if (baselineStartDate && baselineEndDate) {
1070
+ return (this.getTaskLeft(baselineStartDate, ganttProperties.isMilestone));
1071
+ } else {
1072
+ return 0;
1073
+ }
1074
+ }
1075
+ /**
1076
+ * calculate the width between baseline start date and baseline end date.
1077
+ *
1078
+ * @param {ITaskData} ganttProperties .
1079
+ * @returns {number} .
1080
+ * @private
1081
+ */
1082
+ public calculateBaselineWidth(ganttProperties: ITaskData): number {
1083
+ const baselineStartDate: Date = this.getDateFromFormat(ganttProperties.baselineStartDate);
1084
+ const baselineEndDate: Date = this.getDateFromFormat(ganttProperties.baselineEndDate);
1085
+ if (baselineStartDate && baselineEndDate) {
1086
+ return (this.getTaskWidth(baselineStartDate, baselineEndDate));
1087
+ } else {
1088
+ return 0;
1089
+ }
1090
+ }
1091
+ /**
1092
+ * To get tasks width value
1093
+ *
1094
+ * @param {Date} startDate .
1095
+ * @param {Date} endDate .
1096
+ * @returns {number} .
1097
+ * @private
1098
+ */
1099
+ public getTaskWidth(startDate: Date, endDate: Date): number {
1100
+ const sDate: Date = new Date(startDate.getTime()); const eDate: Date = new Date(endDate.getTime());
1101
+ const tierMode: string = this.parent.timelineModule.bottomTier !== 'None' ? this.parent.timelineModule.bottomTier :
1102
+ this.parent.timelineModule.topTier;
1103
+ if (tierMode === 'Day') {
1104
+ if (this.getSecondsInDecimal(sDate) === this.parent.defaultStartTime) {
1105
+ sDate.setHours(0, 0, 0, 0);
1106
+ }
1107
+ if (this.getSecondsInDecimal(eDate) === this.parent.defaultEndTime) {
1108
+ eDate.setHours(24);
1109
+ }
1110
+ if (this.getSecondsInDecimal(eDate) === this.parent.defaultStartTime) {
1111
+ eDate.setHours(0, 0, 0, 0);
1112
+ }
1113
+ }
1114
+ if ((sDate).getTime() === (eDate).getTime()) {
1115
+ return (this.parent.perDayWidth);
1116
+ } else {
1117
+ return ((this.getTimeDifference(sDate, eDate) / (1000 * 60 * 60 * 24)) * this.parent.perDayWidth);
1118
+ }
1119
+ }
1120
+ /**
1121
+ * Get task left value
1122
+ *
1123
+ * @param {Date} startDate .
1124
+ * @param {boolean} isMilestone .
1125
+ * @returns {number} .
1126
+ * @private
1127
+ */
1128
+ public getTaskLeft(startDate: Date, isMilestone: boolean): number {
1129
+ const date: Date = new Date(startDate.getTime());
1130
+ const tierMode: string = this.parent.timelineModule.bottomTier !== 'None' ? this.parent.timelineModule.bottomTier :
1131
+ this.parent.timelineModule.topTier;
1132
+ if (tierMode === 'Day') {
1133
+ if (this.getSecondsInDecimal(date) === this.parent.defaultStartTime) {
1134
+ date.setHours(0, 0, 0, 0);
1135
+ } else if (isMilestone && this.getSecondsInDecimal(date) === this.parent.defaultEndTime) {
1136
+ date.setHours(24);
1137
+ }
1138
+ }
1139
+ const timelineStartDate: Date = this.parent.timelineModule.timelineStartDate;
1140
+ if (timelineStartDate) {
1141
+ return (date.getTime() - timelineStartDate.getTime()) / (1000 * 60 * 60 * 24) * this.parent.perDayWidth;
1142
+ } else {
1143
+ return 0;
1144
+ }
1145
+ }
1146
+
1147
+ public getSplitTaskWidth(sDate: Date, duration: number, data: IGanttData): number {
1148
+ const startDate: Date = new Date(sDate.getTime());
1149
+ const endDate: Date =
1150
+ new Date((this.getEndDate(startDate, duration, data.ganttProperties.durationUnit, data.ganttProperties, false).getTime()));
1151
+ const tierViewMode: string = this.parent.timelineModule.bottomTier !== 'None' ? this.parent.timelineModule.bottomTier :
1152
+ this.parent.timelineModule.topTier;
1153
+ if (tierViewMode === 'Day') {
1154
+ if (this.getSecondsInDecimal(startDate) === this.parent.defaultStartTime) {
1155
+ startDate.setHours(0, 0, 0, 0);
1156
+ }
1157
+ if (this.getSecondsInDecimal(endDate) === this.parent.defaultEndTime) {
1158
+ endDate.setHours(24);
1159
+ }
1160
+ if (this.getSecondsInDecimal(endDate) === this.parent.defaultStartTime) {
1161
+ endDate.setHours(0, 0, 0, 0);
1162
+ }
1163
+ }
1164
+ return ((this.getTimeDifference(startDate, endDate) / (1000 * 60 * 60 * 24)) * this.parent.perDayWidth);
1165
+ }
1166
+ public getSplitTaskLeft(sDate: Date, segmentTaskStartDate: Date): number {
1167
+ const stDate: Date = new Date(sDate.getTime());
1168
+ const tierViewMode: string = this.parent.timelineModule.bottomTier !== 'None' ? this.parent.timelineModule.bottomTier :
1169
+ this.parent.timelineModule.topTier;
1170
+ if (tierViewMode === 'Day') {
1171
+ if (this.getSecondsInDecimal(stDate) === this.parent.defaultStartTime) {
1172
+ stDate.setHours(0, 0, 0, 0);
1173
+ }
1174
+ if (this.getSecondsInDecimal(segmentTaskStartDate) === this.parent.defaultStartTime) {
1175
+ segmentTaskStartDate.setHours(0, 0, 0, 0);
1176
+ }
1177
+ }
1178
+ if (segmentTaskStartDate) {
1179
+ return (stDate.getTime() - segmentTaskStartDate.getTime()) / (1000 * 60 * 60 * 24) * this.parent.perDayWidth;
1180
+ } else {
1181
+ return 0;
1182
+ }
1183
+ }
1184
+ /**
1185
+ *
1186
+ * @param {IGanttData} ganttData .
1187
+ * @param {string} fieldName .
1188
+ * @returns {void} .
1189
+ * @private
1190
+ */
1191
+ public updateMappingData(ganttData: IGanttData, fieldName: string): void {
1192
+ const columnMapping: Object = this.parent.columnMapping;
1193
+ const ganttProp: ITaskData = ganttData.ganttProperties;
1194
+ if (isNullOrUndefined(columnMapping[fieldName]) && fieldName !== 'taskType' && fieldName !== 'segments') {
1195
+ return;
1196
+ }
1197
+ if (fieldName === 'predecessorName') {
1198
+ //
1199
+ } else if (fieldName === 'resourceInfo') {
1200
+ const resourceData: Object[] = ganttProp.resourceInfo;
1201
+ const resourceSettings: ResourceFieldsModel = this.parent.resourceFields;
1202
+ // eslint-disable-next-line
1203
+ const resourcesId: number[] = []; let resourcesName: string[] = [];
1204
+ if (!isNullOrUndefined(resourceData)) {
1205
+ for (let i: number = 0; i < resourceData.length; i++) {
1206
+ resourcesId.push(resourceData[i][resourceSettings.id]);
1207
+ let resName: string = resourceData[i][resourceSettings.name];
1208
+ const resourceUnit: number = resourceData[i][resourceSettings.unit];
1209
+ if (resourceUnit !== 100) {
1210
+ resName += '[' + resourceUnit + '%' + ']';
1211
+ }
1212
+ resourcesName.push(resName);
1213
+ }
1214
+ }
1215
+ this.parent.setRecordValue('resourceNames', resourcesName.join(','), ganttProp, true);
1216
+ this.updateTaskDataResource(ganttData);
1217
+ this.parent.setRecordValue(columnMapping[fieldName], resourcesName.join(','), ganttData);
1218
+ } else if (fieldName === 'startDate' || fieldName === 'endDate') {
1219
+ this.setRecordDate(ganttData, ganttProp[fieldName], columnMapping[fieldName]);
1220
+ } else if (fieldName === 'duration') {
1221
+ this.setRecordDuration(ganttData, columnMapping[fieldName]);
1222
+ } else if (fieldName === 'work') {
1223
+ this.parent.setRecordValue(
1224
+ 'taskData.' + columnMapping[fieldName],
1225
+ this.getWorkString(ganttProp.work, ganttProp.workUnit), ganttData);
1226
+ this.parent.setRecordValue(columnMapping[fieldName], ganttProp[fieldName], ganttData);
1227
+ } else if (fieldName === 'type') {
1228
+ this.parent.setRecordValue('taskData.' + columnMapping[fieldName], ganttProp[fieldName], ganttData);
1229
+ this.parent.setRecordValue(columnMapping[fieldName], ganttProp[fieldName], ganttData);
1230
+ } else if (fieldName === 'manual') {
1231
+ this.parent.setRecordValue('taskData.' + columnMapping[fieldName], !ganttProp.isAutoSchedule, ganttData);
1232
+ this.parent.setRecordValue(columnMapping[fieldName], !ganttProp.isAutoSchedule, ganttData);
1233
+ } else if (fieldName === 'segments') {
1234
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.segments, this.segmentTaskData(ganttData), ganttData);
1235
+ } else {
1236
+ this.parent.setRecordValue('taskData.' + columnMapping[fieldName], ganttProp[fieldName], ganttData);
1237
+ this.parent.setRecordValue(columnMapping[fieldName], ganttProp[fieldName], ganttData);
1238
+ }
1239
+ }
1240
+
1241
+ private segmentTaskData(data: IGanttData): object[] {
1242
+ const segments: ITaskSegment[] = data.ganttProperties.segments;
1243
+ const taskSettings: TaskFieldsModel = this.parent.taskFields;
1244
+ if (isNullOrUndefined(segments)) {
1245
+ return null;
1246
+ }
1247
+ const taskData: Object[] = <Object[]>extend([], [], data.taskData[taskSettings.segments], true);
1248
+ for (let i: number = 0; i < segments.length; i++) {
1249
+ if (this.parent.isEdit || (this.parent.editModule && this.parent.editModule.dialogModule &&
1250
+ getValue('isEdit', this.parent.editModule.dialogModule)) || (this.parent.contextMenuModule && getValue('isEdit', this.parent.contextMenuModule))) {
1251
+ taskData[i] = {};
1252
+ }
1253
+ if (!isNullOrUndefined(taskSettings.startDate)) {
1254
+ taskData[i][this.parent.taskFields.startDate] = segments[i].startDate;
1255
+ }
1256
+ if (!isNullOrUndefined(taskSettings.endDate)) {
1257
+ taskData[i][this.parent.taskFields.endDate] = segments[i].endDate;
1258
+ }
1259
+ if (!isNullOrUndefined(taskSettings.duration)) {
1260
+ taskData[i][this.parent.taskFields.duration] = Number(segments[i].duration);
1261
+ }
1262
+ }
1263
+ return taskData;
1264
+ }
1265
+ /**
1266
+ * Method to update the task data resource values
1267
+ *
1268
+ * @param {IGanttData} ganttData .
1269
+ * @returns {void} .
1270
+ */
1271
+ private updateTaskDataResource(ganttData: IGanttData): void {
1272
+ const resourceData: Object[] = ganttData.ganttProperties.resourceInfo;
1273
+ const preTaskResources: Object[] = ganttData.taskData[this.parent.taskFields.resourceInfo];
1274
+ const resourceSettings: ResourceFieldsModel = this.parent.resourceFields;
1275
+ if (isNullOrUndefined(preTaskResources)) {
1276
+ ganttData.taskData[this.parent.taskFields.resourceInfo] = resourceData;
1277
+ } else if (resourceData.length) {
1278
+ for (let i: number = 0; i < resourceData.length; i++) {
1279
+ let isAdded: boolean = false;
1280
+ for (let j: number = 0; j < preTaskResources.length; j++) {
1281
+ if (typeof preTaskResources[j] === 'number' || typeof preTaskResources[j] === 'string') {
1282
+ if (parseInt(preTaskResources[j] as string, 10) === parseInt(resourceData[i][resourceSettings.id], 10)) {
1283
+ preTaskResources[j] = resourceData[i];
1284
+ isAdded = true;
1285
+ break;
1286
+ }
1287
+ } else if (preTaskResources[j][resourceSettings.id] === resourceData[i][resourceSettings.id] && typeof preTaskResources[j] !== 'number') {
1288
+ preTaskResources[j] = extend({}, preTaskResources[j], resourceData[i], true);
1289
+ isAdded = true;
1290
+ break;
1291
+ }
1292
+ }
1293
+ if (!isAdded) {
1294
+ preTaskResources.push(resourceData[i]);
1295
+ }
1296
+ }
1297
+ const data: IGanttData[] = [];
1298
+ for (let k: number = 0; k < preTaskResources.length; k++) {
1299
+ resourceData.filter((resourceInfo: Object) => {
1300
+ if (resourceInfo[resourceSettings.id] === preTaskResources[k][resourceSettings.id]) {
1301
+ data.push(preTaskResources[k]);
1302
+ }
1303
+ });
1304
+ }
1305
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.resourceInfo, data, ganttData);
1306
+ } else {
1307
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.resourceInfo, [], ganttData);
1308
+ }
1309
+ }
1310
+
1311
+ private setRecordDate(task: IGanttData, value: Date | string, mapping: string): void {
1312
+ const tempDate: Date = typeof value === 'string' ? new Date(value as string) : value;
1313
+ if (!isNullOrUndefined(value)) {
1314
+ value = new Date(tempDate.getTime());
1315
+ }
1316
+ this.parent.setRecordValue(mapping, value, task);
1317
+ if (!isNullOrUndefined(value)) {
1318
+ value = new Date(tempDate.getTime());
1319
+ }
1320
+ if (!this.parent.isLoad && !this.parent.isDynamicData) {
1321
+ this.parent.setRecordValue('taskData.' + mapping, value, task);
1322
+ }
1323
+ this.parent.isDynamicData = false;
1324
+ }
1325
+
1326
+ private getDurationInDay(duration: number, durationUnit: string): number {
1327
+ if (durationUnit === 'day') {
1328
+ return duration;
1329
+ } else if (durationUnit === 'hour') {
1330
+ return duration / (this.parent.secondsPerDay / 3600);
1331
+ } else {
1332
+ return duration / (this.parent.secondsPerDay / 60);
1333
+ }
1334
+ }
1335
+
1336
+ private setRecordDuration(task: IGanttData, mapping: string): void {
1337
+ const duration: number = task.ganttProperties.duration;
1338
+ const durationUnit: string = task.ganttProperties.durationUnit;
1339
+ if (!isNullOrUndefined(duration)) {
1340
+ this.parent.setRecordValue(mapping, task.ganttProperties.duration, task);
1341
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
1342
+ const durationValue: any = (getValue(mapping, task.taskData));
1343
+ if (isNaN(durationValue) && isNullOrUndefined(this.parent.taskFields.durationUnit) && !isNullOrUndefined(durationValue)) {
1344
+ this.parent.setRecordValue('taskData.' + mapping, this.getDurationString(duration, durationUnit), task);
1345
+ } else {
1346
+ if (typeof durationValue === 'string') {
1347
+ this.parent.setRecordValue('taskData.' + mapping, duration.toString(), task);
1348
+ } else {
1349
+ this.parent.setRecordValue('taskData.' + mapping, duration, task);
1350
+ }
1351
+ }
1352
+ } else {
1353
+ this.parent.setRecordValue(mapping, duration, task);
1354
+ this.parent.setRecordValue('taskData.' + mapping, duration, task);
1355
+ }
1356
+ if (this.parent.taskFields.durationUnit) {
1357
+ task.taskData[this.parent.taskFields.durationUnit] = task.ganttProperties.durationUnit;
1358
+ }
1359
+ }
1360
+ private getWorkInHour(work: number, workUnit: string): number {
1361
+ if (workUnit === 'day') {
1362
+ return work * (this.parent.secondsPerDay / 3600);
1363
+ } else if (workUnit === 'minute') {
1364
+ return work / 60;
1365
+ } else {
1366
+ return work;
1367
+ }
1368
+ }
1369
+ /**
1370
+ *
1371
+ * @param {IGanttData} ganttData .
1372
+ * @returns {void} .
1373
+ * @private
1374
+ */
1375
+ public updateTaskData(ganttData: IGanttData): void {
1376
+ const dataMapping: TaskFieldsModel = this.parent.taskFields;
1377
+ const ganttProperties: ITaskData = ganttData.ganttProperties;
1378
+ if (!isNullOrUndefined(ganttData.taskData)) {
1379
+ const data: Object = ganttData.taskData;
1380
+ if (dataMapping.id) {
1381
+ this.parent.setRecordValue('taskData.' + dataMapping.id, ganttProperties.taskId, ganttData);
1382
+ this.parent.setRecordValue(dataMapping.id, ganttProperties.taskId, ganttData);
1383
+ }
1384
+ if (dataMapping.name) {
1385
+ this.parent.setRecordValue('taskData.' + dataMapping.name, ganttProperties.taskName, ganttData);
1386
+ this.parent.setRecordValue(dataMapping.name, ganttProperties.taskName, ganttData);
1387
+ }
1388
+ if (dataMapping.startDate) {
1389
+ this.setRecordDate(ganttData, ganttProperties.startDate, dataMapping.startDate);
1390
+ }
1391
+ if (dataMapping.endDate) {
1392
+ this.setRecordDate(ganttData, ganttProperties.endDate, dataMapping.endDate);
1393
+ }
1394
+ if (dataMapping.duration) {
1395
+ this.setRecordDuration(ganttData, dataMapping.duration);
1396
+ }
1397
+ if (dataMapping.durationUnit) {
1398
+ data[dataMapping.durationUnit] = ganttProperties.durationUnit;
1399
+ }
1400
+ if (dataMapping.progress) {
1401
+ this.parent.setRecordValue('taskData.' + dataMapping.progress, ganttProperties.progress, ganttData);
1402
+ this.parent.setRecordValue(dataMapping.progress, ganttProperties.progress, ganttData);
1403
+ }
1404
+ if (dataMapping.baselineStartDate) {
1405
+ this.setRecordDate(ganttData, ganttProperties.baselineStartDate, dataMapping.baselineStartDate);
1406
+ }
1407
+ if (dataMapping.baselineEndDate) {
1408
+ this.setRecordDate(ganttData, ganttProperties.baselineEndDate, dataMapping.baselineEndDate);
1409
+ }
1410
+ if (dataMapping.notes) {
1411
+ this.parent.setRecordValue('taskData.' + dataMapping.notes, ganttProperties.notes, ganttData);
1412
+ this.parent.setRecordValue(dataMapping.notes, ganttProperties.notes, ganttData);
1413
+ }
1414
+ if (dataMapping.cssClass) {
1415
+ this.parent.setRecordValue('taskData.' + dataMapping.cssClass, ganttProperties.cssClass, ganttData);
1416
+ this.parent.setRecordValue(dataMapping.cssClass, ganttProperties.cssClass, ganttData);
1417
+ }
1418
+ if (dataMapping.indicators) {
1419
+ this.parent.setRecordValue('taskData.' + dataMapping.indicators, ganttProperties.indicators, ganttData);
1420
+ this.parent.setRecordValue(dataMapping.indicators, ganttProperties.indicators, ganttData);
1421
+ }
1422
+ if (dataMapping.parentID) {
1423
+ const parentID: string = this.parent.viewType === 'ProjectView' ? ganttProperties.parentId : data[dataMapping.parentID];
1424
+ this.parent.setRecordValue('taskData.' + dataMapping.parentID, parentID, ganttData);
1425
+ this.parent.setRecordValue(dataMapping.parentID, ganttProperties.parentId, ganttData);
1426
+ }
1427
+ if (dataMapping.work) {
1428
+ this.parent.setRecordValue(
1429
+ 'taskData.' + dataMapping.work,
1430
+ this.getWorkString(ganttProperties.work, ganttProperties.workUnit), ganttData);
1431
+ this.parent.setRecordValue(dataMapping.work, ganttProperties.work, ganttData);
1432
+ }
1433
+ if (dataMapping.type) {
1434
+ this.parent.setRecordValue('taskData.' + dataMapping.type, ganttProperties.taskType, ganttData);
1435
+ this.parent.setRecordValue(dataMapping.type, ganttProperties.taskType, ganttData);
1436
+ }
1437
+ }
1438
+ }
1439
+ /**
1440
+ * To set resource value in Gantt record
1441
+ *
1442
+ * @param {object} data .
1443
+ * @returns {object[]} .
1444
+ * @private
1445
+ */
1446
+ public setResourceInfo(data: Object): Object[] {
1447
+ // eslint-disable-next-line
1448
+ let resourceIdCollection: object[];
1449
+ if (isNullOrUndefined(data[this.parent.taskFields.resourceInfo])) {
1450
+ return resourceIdCollection;
1451
+ }
1452
+ resourceIdCollection = data[this.parent.taskFields.resourceInfo];
1453
+ let resourceData: Object[];
1454
+ if (!isNullOrUndefined(this.parent.editModule) && !isNullOrUndefined(this.parent.editModule.dialogModule)
1455
+ && this.parent.editModule.dialogModule.isAddNewResource) {
1456
+ resourceData = this.parent.editModule.dialogModule.ganttResources;
1457
+ } else {
1458
+ resourceData = this.parent.resources;
1459
+ }
1460
+ const resourceIDMapping: string = this.parent.resourceFields.id;
1461
+ const resourceUnitMapping: string = this.parent.resourceFields.unit;
1462
+ const resourceGroup: string = this.parent.resourceFields.group;
1463
+ const resources: Object[] = [];
1464
+ for (let count: number = 0; count < resourceIdCollection.length; count++) {
1465
+ const resource: Object[] = resourceData.filter((resourceInfo: Object) => {
1466
+ if (typeof (resourceIdCollection[count]) === 'object' &&
1467
+ resourceIdCollection[count][resourceIDMapping] === resourceInfo[resourceIDMapping]) {
1468
+ return true;
1469
+ } else {
1470
+ return (resourceIdCollection[count] === resourceInfo[resourceIDMapping]);
1471
+ }
1472
+ });
1473
+ const ganttDataResource: Object = extend({}, resource[0]);
1474
+ resources.push(ganttDataResource);
1475
+ if (!isNullOrUndefined(resourceUnitMapping) && !isNullOrUndefined(resourceIdCollection[count][resourceUnitMapping])) {
1476
+ ganttDataResource[resourceUnitMapping] = resourceIdCollection[count][resourceUnitMapping];
1477
+ }
1478
+ if (!isNullOrUndefined(resourceGroup) && !isNullOrUndefined(resourceIdCollection[count][resourceGroup])) {
1479
+ ganttDataResource[resourceGroup] = resourceIdCollection[count][resourceGroup];
1480
+ }
1481
+ }
1482
+ this.updateResourceUnit(resources);
1483
+ return resources;
1484
+ }
1485
+ /**
1486
+ * To set resource unit in Gantt record
1487
+ *
1488
+ * @param {object[]} resourceData .
1489
+ * @returns {void} .
1490
+ * @private
1491
+ */
1492
+ public updateResourceUnit(resourceData: Object[]): void {
1493
+ const resourceUnit: string = this.parent.resourceFields.unit;
1494
+ if (!isNullOrUndefined(resourceUnit)) {
1495
+ const length: number = resourceData.length;
1496
+ let index: number;
1497
+ for (index = 0; index < length; index++) {
1498
+ if (isNullOrUndefined(resourceData[index][resourceUnit])) {
1499
+ resourceData[index][resourceUnit] = 100;
1500
+ }
1501
+ }
1502
+ }
1503
+ }
1504
+
1505
+ /**
1506
+ * @param {IGanttData} data .
1507
+ * @returns {void} .
1508
+ * @private
1509
+ */
1510
+ public updateResourceName(data: IGanttData): void {
1511
+ const resourceInfo: Object[] = data.ganttProperties.resourceInfo;
1512
+ const resourceName: Object[] = [];
1513
+ if (resourceInfo) {
1514
+ const taskResources: Object = extend([], [], data.taskData[this.parent.taskFields.resourceInfo], true);
1515
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.resourceInfo, [], data);
1516
+ for (let i: number = 0; i < resourceInfo.length; i++) {
1517
+ const resource: Object = resourceInfo[i];
1518
+ let resName: string = resource[this.parent.resourceFields.name];
1519
+ const resourceUnit: number = resource[this.parent.resourceFields.unit];
1520
+ if (resourceUnit !== 100) {
1521
+ resName += '[' + resourceUnit + '%' + ']';
1522
+ }
1523
+ resourceName.push(resName);
1524
+ if (data.taskData) {
1525
+ const mapping: string = this.parent.taskFields.resourceInfo;
1526
+ // eslint-disable-next-line
1527
+ if (typeof (taskResources[i] === 'object')) {
1528
+ data.taskData[mapping].push(taskResources[i]);
1529
+ } else {
1530
+ data.taskData[mapping].push(resource[this.parent.resourceFields.id]);
1531
+ }
1532
+ }
1533
+ }
1534
+ this.parent.setRecordValue('resourceNames', resourceName.join(','), data.ganttProperties, true);
1535
+ this.parent.setRecordValue(this.parent.taskFields.resourceInfo, resourceName.join(','), data, true);
1536
+ this.updateTaskDataResource(data);
1537
+ }
1538
+ }
1539
+
1540
+ private dataReorder(flatCollection: Object[], rootCollection: Object[]): Object[] {
1541
+ const result: Object[] = [];
1542
+ while (flatCollection.length > 0 && rootCollection.length > 0) {
1543
+ const index: number = rootCollection.indexOf(flatCollection[0]);
1544
+ if (index === -1) {
1545
+ flatCollection.shift();
1546
+ } else {
1547
+ result.push(flatCollection.shift());
1548
+ rootCollection.splice(index, 1);
1549
+ }
1550
+ }
1551
+ return result;
1552
+ }
1553
+
1554
+ private validateDurationUnitMapping(durationUnit: string): string {
1555
+ let unit: string = durationUnit;
1556
+ if ((unit === 'minute') || (unit === 'minutes') || (unit === 'm') || (unit === 'min')) {
1557
+ unit = 'minute';
1558
+ } else if ((unit === 'hour') || (unit === 'hours') || (unit === 'h') || (unit === 'hr')) {
1559
+ unit = 'hour';
1560
+ } else if ((unit === 'day') || (unit === 'days') || (unit === 'd')) {
1561
+ unit = 'day';
1562
+ } else {
1563
+ unit = this.parent.durationUnit.toLocaleLowerCase();
1564
+ }
1565
+ return unit;
1566
+ }
1567
+
1568
+ private validateTaskTypeMapping(taskType: string): string {
1569
+ let type: string = taskType;
1570
+ if (type === 'FixedDuration') {
1571
+ type = 'FixedDuration';
1572
+ } else if (type === 'FixedUnit') {
1573
+ type = 'FixedUnit';
1574
+ } else if (type === 'FixedWork') {
1575
+ type = 'FixedWork';
1576
+ } else {
1577
+ type = this.parent.taskType;
1578
+ }
1579
+ return type;
1580
+ }
1581
+
1582
+ private validateWorkUnitMapping(workUnit: string): string {
1583
+ let unit: string = workUnit;
1584
+ if (unit === 'minute') {
1585
+ unit = 'minute';
1586
+ } else if (unit === 'hour') {
1587
+ unit = 'hour';
1588
+ } else if (unit === 'day') {
1589
+ unit = 'day';
1590
+ } else {
1591
+ unit = this.parent.workUnit.toLocaleLowerCase();
1592
+ }
1593
+ return unit;
1594
+ }
1595
+ /**
1596
+ * To update duration value in Task
1597
+ *
1598
+ * @param {string} duration .
1599
+ * @param {ITaskData} ganttProperties .
1600
+ * @returns {void} .
1601
+ * @private
1602
+ */
1603
+ public updateDurationValue(duration: string, ganttProperties: ITaskData): void {
1604
+ const tempDuration: Object = this.getDurationValue(duration);
1605
+ if (!isNaN(getValue('duration', tempDuration))) {
1606
+ this.parent.setRecordValue('duration', getValue('duration', tempDuration), ganttProperties, true);
1607
+ }
1608
+ if (!isNullOrUndefined(getValue('durationUnit', tempDuration))) {
1609
+ this.parent.setRecordValue('durationUnit', getValue('durationUnit', tempDuration), ganttProperties, true);
1610
+ }
1611
+ }
1612
+
1613
+ /**
1614
+ * @returns {void} .
1615
+ * @private
1616
+ */
1617
+ public reUpdateGanttData(): void {
1618
+ if (this.parent.flatData.length > 0) {
1619
+ let data: ITaskData;
1620
+ let ganttData: IGanttData;
1621
+ this.parent.secondsPerDay = this.getSecondsPerDay();
1622
+ for (let index: number = 0; index < this.parent.flatData.length; index++) {
1623
+ data = this.parent.flatData[index].taskData;
1624
+ ganttData = this.parent.flatData[index];
1625
+ if (!isNullOrUndefined(this.parent.taskFields.duration)) {
1626
+ this.setRecordDuration(ganttData, this.parent.taskFields.duration);
1627
+ }
1628
+ this.calculateScheduledValues(ganttData, data, false);
1629
+ }
1630
+ this.updateGanttData();
1631
+ }
1632
+ }
1633
+ //check day is fall between from and to date range
1634
+ private _isInStartDateRange(day: Date, from: Date, to: Date): boolean {
1635
+ let isInRange: boolean = false;
1636
+ if (day.getTime() >= from.getTime() && day.getTime() < to.getTime()) {
1637
+ isInRange = true;
1638
+ }
1639
+ return isInRange;
1640
+ }
1641
+ //check day is fall between from and to date range
1642
+ private _isInEndDateRange(day: Date, from: Date, to: Date): boolean {
1643
+ let isInRange: boolean = false;
1644
+ if (day.getTime() > from.getTime() && day.getTime() <= to.getTime()) {
1645
+ isInRange = true;
1646
+ }
1647
+ return isInRange;
1648
+ }
1649
+ /**
1650
+ * Method to find overlapping value of the parent task
1651
+ *
1652
+ * @param {IGanttData} resourceTask .
1653
+ * @returns {void} .
1654
+ * @private
1655
+ */
1656
+ public updateOverlappingValues(resourceTask: IGanttData): void {
1657
+ let tasks: IGanttData[] = resourceTask.childRecords;
1658
+ let currentTask: IGanttData;
1659
+ const ranges: IWorkTimelineRanges[] = [];
1660
+ if (tasks.length <= 1) {
1661
+ resourceTask.ganttProperties.workTimelineRanges = [];
1662
+ return;
1663
+ }
1664
+ tasks = this.setSortedChildTasks(resourceTask);
1665
+ this.updateOverlappingIndex(tasks);
1666
+ for (let count: number = 1; count < tasks.length; count++) {
1667
+ currentTask = tasks[count];
1668
+ const cStartDate: Date = new Date(currentTask.ganttProperties.startDate.getTime());
1669
+ const cEndDate: Date = new Date(currentTask.ganttProperties.endDate.getTime()); //task 2
1670
+ const range: IWorkTimelineRanges[] = [];
1671
+ // eslint-disable-next-line
1672
+ const rangeObj: IWorkTimelineRanges = {};
1673
+ for (let index: number = 0; index < count; index++) {
1674
+ const tStartDate: Date = tasks[index].ganttProperties.startDate;
1675
+ const tEndDate: Date = tasks[index].ganttProperties.endDate; // task 1
1676
+ const rangeObj: IWorkTimelineRanges = {};
1677
+ if (this._isInStartDateRange(cStartDate, tStartDate, tEndDate) || this._isInEndDateRange(cEndDate, tStartDate, tEndDate)) {
1678
+ if ((tStartDate.getTime() > cStartDate.getTime() && tStartDate.getTime() < cEndDate.getTime()
1679
+ && tEndDate.getTime() > cStartDate.getTime() && tEndDate.getTime() > cEndDate.getTime())
1680
+ || (cStartDate.getTime() === tStartDate.getTime() && cEndDate.getTime() <= tEndDate.getTime())) {
1681
+ rangeObj.from = tStartDate;
1682
+ rangeObj.to = cEndDate;
1683
+ } else if (cStartDate.getTime() === tStartDate.getTime() && cEndDate.getTime() > tEndDate.getTime()) {
1684
+ rangeObj.from = tStartDate;
1685
+ rangeObj.to = tEndDate;
1686
+ } else if (cStartDate.getTime() > tStartDate.getTime() && cEndDate.getTime() >= tEndDate.getTime()) {
1687
+ rangeObj.from = cStartDate;
1688
+ rangeObj.to = tEndDate;
1689
+ } else if (cStartDate.getTime() > tStartDate.getTime() && cEndDate.getTime() < tEndDate.getTime()) {
1690
+ rangeObj.from = cStartDate;
1691
+ rangeObj.to = cEndDate;
1692
+ }
1693
+ range.push(rangeObj);
1694
+ }
1695
+ }
1696
+ // eslint-disable-next-line
1697
+ ranges.push.apply(ranges, this.mergeRangeCollections(range));
1698
+ }
1699
+ this.parent.setRecordValue('workTimelineRanges', this.mergeRangeCollections(ranges, true), resourceTask.ganttProperties, true);
1700
+ this.calculateRangeLeftWidth(resourceTask.ganttProperties.workTimelineRanges);
1701
+ }
1702
+ /**
1703
+ * @param {IGanttData[]} tasks .
1704
+ * @returns {void} .
1705
+ * @private
1706
+ */
1707
+ public updateOverlappingIndex(tasks: IGanttData[]): void {
1708
+ for (let i: number = 0; i < tasks.length; i++) {
1709
+ tasks[i].ganttProperties.eOverlapIndex = i;
1710
+ }
1711
+ }
1712
+ /**
1713
+ * Method to calculate the left and width value of oarlapping ranges
1714
+ *
1715
+ * @param {IWorkTimelineRanges[]} ranges .
1716
+ * @returns {void} .
1717
+ * @private
1718
+ */
1719
+ public calculateRangeLeftWidth(ranges: IWorkTimelineRanges[]): void {
1720
+ for (let count: number = 0; count < ranges.length; count++) {
1721
+ ranges[count].left = this.getTaskLeft(ranges[count].from, false);
1722
+ ranges[count].width = this.getTaskWidth(ranges[count].from, ranges[count].to);
1723
+ }
1724
+ }
1725
+ /**
1726
+ * @param {IWorkTimelineRanges[]} ranges .
1727
+ * @param {boolean} isSplit .
1728
+ * @returns {IWorkTimelineRanges[]} .
1729
+ * @private
1730
+ */
1731
+ public mergeRangeCollections(ranges: IWorkTimelineRanges[], isSplit?: boolean): IWorkTimelineRanges[] {
1732
+ let finalRange: IWorkTimelineRanges[] = [];
1733
+ let currentTopRange: IWorkTimelineRanges = {};
1734
+ let cCompareRange: IWorkTimelineRanges = {};
1735
+ let cStartDate: Date;
1736
+ let cEndDate: Date;
1737
+ let tStartDate: Date;
1738
+ let tEndDate: Date;
1739
+ const sortedRanges: IWorkTimelineRanges[] = new DataManager(ranges).executeLocal(new Query()
1740
+ .sortBy(this.parent.taskFields.startDate, 'Ascending'));
1741
+ for (let i: number = 0; i < sortedRanges.length; i++) {
1742
+ if (finalRange.length === 0 && i === 0) {
1743
+ finalRange.push(sortedRanges[i]);
1744
+ continue;
1745
+ }
1746
+ currentTopRange = finalRange[finalRange.length - 1];
1747
+ cStartDate = currentTopRange.from;
1748
+ cEndDate = currentTopRange.to;
1749
+ cCompareRange = sortedRanges[i];
1750
+ tStartDate = cCompareRange.from;
1751
+ tEndDate = cCompareRange.to;
1752
+ if ((cStartDate.getTime() === tStartDate.getTime() && cEndDate.getTime() >= tEndDate.getTime())
1753
+ || (cStartDate.getTime() < tStartDate.getTime() && cEndDate.getTime() >= tEndDate.getTime())
1754
+ ) {
1755
+ continue;
1756
+ }
1757
+ /* eslint-disable-next-line */
1758
+ else if ((cStartDate.getTime() <= tStartDate.getTime() && cEndDate.getTime() >= tStartDate.getTime() && cEndDate.getTime() < tEndDate.getTime())
1759
+ || (cEndDate.getTime() < tStartDate.getTime() && this.checkStartDate(cEndDate).getTime() === tStartDate.getTime())) {
1760
+ currentTopRange.to = tEndDate;
1761
+ } else if (cEndDate.getTime() < tStartDate.getTime() && this.checkStartDate(cEndDate).getTime() !== tStartDate.getTime()) {
1762
+ finalRange.push(sortedRanges[i]);
1763
+ }
1764
+ }
1765
+ if (isSplit) {
1766
+ finalRange = this.splitRangeCollection(finalRange);
1767
+ }
1768
+ return finalRange;
1769
+ }
1770
+ /**
1771
+ * Sort resource child records based on start date
1772
+ *
1773
+ * @param {IGanttData} resourceTask .
1774
+ * @returns {IGanttData} .
1775
+ * @private
1776
+ */
1777
+ public setSortedChildTasks(resourceTask: IGanttData): IGanttData[] {
1778
+ let sortedRecords: IGanttData[] = [];
1779
+ sortedRecords = new DataManager(resourceTask.childRecords).executeLocal(new Query()
1780
+ .sortBy(this.parent.taskFields.startDate, 'Ascending'));
1781
+ return sortedRecords;
1782
+ }
1783
+
1784
+ private splitRangeCollection(rangeCollection: IWorkTimelineRanges[], fromField?: string, toField?: string): IWorkTimelineRanges[] {
1785
+ let splitArray: IWorkTimelineRanges[] = [];
1786
+ let unit: string;
1787
+ if (this.parent.timelineModule.isSingleTier) {
1788
+ unit = this.parent.timelineModule.bottomTier !== 'None' ?
1789
+ this.parent.timelineModule.bottomTier : this.parent.timelineModule.topTier;
1790
+ } else {
1791
+ unit = this.parent.timelineModule.bottomTier;
1792
+ }
1793
+ if (unit === 'Week' || unit === 'Month' || unit === 'Year') {
1794
+ splitArray = rangeCollection;
1795
+ } else if (unit === 'Day') {
1796
+ splitArray = this.getRangeWithWeek(rangeCollection, fromField, toField);
1797
+ } else {
1798
+ if (this.parent.workingTimeRanges[0].from === 0 && this.parent.workingTimeRanges[0].to === 86400) {
1799
+ splitArray = this.getRangeWithWeek(rangeCollection, fromField, toField);
1800
+ } else {
1801
+ splitArray = this.getRangeWithDay(rangeCollection, fromField, toField);
1802
+ }
1803
+ }
1804
+ return splitArray;
1805
+ }
1806
+ private getRangeWithDay(ranges: IWorkTimelineRanges[], fromField: string, toField: string): IWorkTimelineRanges[] {
1807
+ const splitArray: IWorkTimelineRanges[] = [];
1808
+ for (let i: number = 0; i < ranges.length; i++) {
1809
+ // eslint-disable-next-line
1810
+ splitArray.push.apply(splitArray, this.splitRangeForDayMode(ranges[i], fromField, toField));
1811
+ }
1812
+ return splitArray;
1813
+ }
1814
+ private splitRangeForDayMode(range: IWorkTimelineRanges, fromField: string, toField: string): IWorkTimelineRanges[] {
1815
+ const fromString: string = fromField ? fromField : 'from';
1816
+ const toString: string = toField ? toField : 'to';
1817
+ let tempStart: Date = new Date(range[fromString]);
1818
+ const end: Date = new Date(range[toString]);
1819
+ const ranges: IWorkTimelineRanges[] = [];
1820
+ let rangeObject: CObject = {};
1821
+ if (tempStart.getTime() < end.getTime()) {
1822
+ do {
1823
+ const nStart: Date = new Date(tempStart.getTime());
1824
+ const nEndDate: Date = new Date(tempStart.getTime());
1825
+ let nextAvailDuration: number = 0;
1826
+ const sHour: number = this.parent.dataOperation.getSecondsInDecimal(tempStart);
1827
+ let startRangeIndex: number = -1;
1828
+ for (let i: number = 0; i < this.parent.workingTimeRanges.length; i++) {
1829
+ const val: IWorkingTimeRange = this.parent.workingTimeRanges[i];
1830
+ if (sHour >= val.from && sHour <= val.to) {
1831
+ startRangeIndex = i;
1832
+ break;
1833
+ }
1834
+ }
1835
+ if (startRangeIndex !== -1) {
1836
+ nextAvailDuration = Math.round(this.parent.workingTimeRanges[startRangeIndex].to - sHour);
1837
+ nEndDate.setSeconds(nEndDate.getSeconds() + nextAvailDuration);
1838
+ }
1839
+ const taskName: string = 'task';
1840
+ if (nEndDate.getTime() < end.getTime()) {
1841
+ rangeObject = {};
1842
+ if (range.task) {
1843
+ rangeObject[taskName] = extend([], range.task);
1844
+ }
1845
+ rangeObject[fromString] = nStart;
1846
+ rangeObject[toString] = nEndDate;
1847
+ rangeObject.isSplit = true;
1848
+ ranges.push(rangeObject);
1849
+ } else {
1850
+ rangeObject = {};
1851
+ if (range.task) {
1852
+ rangeObject[taskName] = extend([], range.task);
1853
+ }
1854
+ rangeObject[fromString] = nStart;
1855
+ rangeObject[toString] = end;
1856
+ rangeObject.isSplit = true;
1857
+ ranges.push(rangeObject);
1858
+ }
1859
+ tempStart = this.checkStartDate(nEndDate);
1860
+ } while (tempStart.getTime() < end.getTime());
1861
+ } else {
1862
+ ranges.push(range);
1863
+ }
1864
+ return ranges;
1865
+ }
1866
+ private getRangeWithWeek(ranges: IWorkTimelineRanges[], fromField: string, toField: string): IWorkTimelineRanges[] {
1867
+ const splitArray: IWorkTimelineRanges[] = [];
1868
+ for (let i: number = 0; i < ranges.length; i++) {
1869
+ // eslint-disable-next-line
1870
+ splitArray.push.apply(splitArray, this.splitRangeForWeekMode(ranges[i], fromField, toField));
1871
+ }
1872
+ return splitArray;
1873
+ }
1874
+ private splitRangeForWeekMode(range: IWorkTimelineRanges, fromField: string, toField: string): IWorkTimelineRanges[] {
1875
+ const from: string = fromField ? fromField : 'from';
1876
+ const to: string = toField ? toField : 'to';
1877
+ let start: Date = new Date(range[from]);
1878
+ let tempStart: Date = new Date(range[from]);
1879
+ const end: Date = new Date(range[to]);
1880
+ let isInSplit: boolean = false;
1881
+ const ranges: IWorkTimelineRanges[] = [];
1882
+ let rangeObj: CObject = {};
1883
+ tempStart.setDate(tempStart.getDate() + 1);
1884
+ if (tempStart.getTime() < end.getTime()) {
1885
+ do {
1886
+ if (this.parent.dataOperation.isOnHolidayOrWeekEnd(tempStart, null)) {
1887
+ const tempEndDate: Date = new Date(tempStart.getTime());
1888
+ tempEndDate.setDate(tempStart.getDate() - 1);
1889
+ this.setTime(this.parent.defaultEndTime, tempEndDate);
1890
+ rangeObj = {};
1891
+ rangeObj[from] = start;
1892
+ rangeObj.isSplit = true;
1893
+ rangeObj[to] = tempEndDate;
1894
+ if (range.task) {
1895
+ rangeObj.task = extend([], range.task, true);
1896
+ }
1897
+ if (start.getTime() !== tempEndDate.getTime()) {
1898
+ ranges.push(rangeObj);
1899
+ }
1900
+ start = this.checkStartDate(tempEndDate);
1901
+ tempStart = new Date(start.getTime());
1902
+ isInSplit = true;
1903
+ } else {
1904
+ tempStart.setDate(tempStart.getDate() + 1);
1905
+ }
1906
+ } while (tempStart.getTime() < end.getTime());
1907
+ if (isInSplit) {
1908
+ if (start.getTime() !== end.getTime()) {
1909
+ rangeObj = {};
1910
+ if (range.task) {
1911
+ rangeObj.task = extend([], range.task, true);
1912
+ }
1913
+ rangeObj[from] = start;
1914
+ rangeObj[to] = end;
1915
+ rangeObj.isSplit = true;
1916
+ ranges.push(rangeObj);
1917
+ }
1918
+ } else {
1919
+ ranges.push(range);
1920
+ }
1921
+ } else {
1922
+ ranges.push(range);
1923
+ }
1924
+ return ranges;
1925
+ }
1926
+ /**
1927
+ * Update all gantt data collection width, progress width and left value
1928
+ *
1929
+ * @returns {void} .
1930
+ * @private
1931
+ */
1932
+ public updateGanttData(): void {
1933
+ const flatData: IGanttData[] = this.parent.flatData;
1934
+ const length: number = flatData.length;
1935
+
1936
+ for (let i: number = 0; i < length; i++) {
1937
+ const data: IGanttData = flatData[i];
1938
+ this.updateTaskLeftWidth(data);
1939
+ }
1940
+ }
1941
+ /**
1942
+ * Update all gantt data collection width, progress width and left value
1943
+ *
1944
+ * @param {IGanttData} data .
1945
+ * @returns {void} .
1946
+ * @public
1947
+ */
1948
+ private updateTaskLeftWidth(data: IGanttData): void {
1949
+ const task: ITaskData = data.ganttProperties;
1950
+ if (!data.hasChildRecords) {
1951
+ this.updateWidthLeft(data);
1952
+ }
1953
+ this.parent.setRecordValue('baselineLeft', this.calculateBaselineLeft(task), task, true);
1954
+ this.parent.setRecordValue('baselineWidth', this.calculateBaselineWidth(task), task, true);
1955
+ let childData: IGanttData[] = [];
1956
+ let parentItem: IGanttData;
1957
+ if (data.parentItem) {
1958
+ parentItem = this.parent.getParentTask(data.parentItem) as IGanttData;
1959
+ childData = parentItem.childRecords as IGanttData[];
1960
+ }
1961
+ if (parentItem && childData.indexOf(data) === childData.length - 1 && !data.hasChildRecords && this.parent.enableValidation) {
1962
+ this.updateParentItems(parentItem);
1963
+ } else if (parentItem && !this.parent.enableValidation) {
1964
+ this.updateWidthLeft(parentItem);
1965
+ }
1966
+ }
1967
+ /**
1968
+ * @returns {void} .
1969
+ * @private
1970
+ */
1971
+ public reUpdateGanttDataPosition(): void {
1972
+ const flatData: IGanttData[] = this.parent.flatData;
1973
+ const length: number = flatData.length;
1974
+ for (let i: number = 0; i < length; i++) {
1975
+ const data: IGanttData = flatData[i];
1976
+ const task: ITaskData = data.ganttProperties;
1977
+ this.updateWidthLeft(data);
1978
+ if (this.parent.taskMode !== 'Auto' && data.hasChildRecords) {
1979
+ this.updateAutoWidthLeft(data);
1980
+ }
1981
+ this.parent.setRecordValue('baselineLeft', this.calculateBaselineLeft(task), task, true);
1982
+ this.parent.setRecordValue('baselineWidth', this.calculateBaselineWidth(task), task, true);
1983
+ this.parent.dataOperation.updateTaskData(data);
1984
+ }
1985
+ }
1986
+
1987
+ /**
1988
+ * method to update left, width, progress width in record
1989
+ *
1990
+ * @param {IGanttData} data .
1991
+ * @returns {void} .
1992
+ * @private
1993
+ */
1994
+ public updateWidthLeft(data: IGanttData): void {
1995
+ const ganttRecord: ITaskData = data.ganttProperties;
1996
+ // task endDate may be changed in segment calculation so this must be calculated first.
1997
+ // task width calculating was based on endDate
1998
+ if (!isNullOrUndefined(ganttRecord.segments) && ganttRecord.segments.length > 0) {
1999
+ const segments: ITaskSegment[] = ganttRecord.segments;
2000
+ let fixedWidth: boolean = true;
2001
+ const totalTaskWidth: number = this.splitTasksDuration(segments) * this.parent.perDayWidth;
2002
+ let totalProgressWidth: number = this.parent.dataOperation.getProgressWidth(totalTaskWidth, ganttRecord.progress);
2003
+ for (let i: number = 0; i < segments.length; i++) {
2004
+ const segment: ITaskSegment = segments[i];
2005
+ if (i === 0 && !isNullOrUndefined(ganttRecord.startDate) &&
2006
+ segment.startDate.getTime() !== ganttRecord.startDate.getTime()) {
2007
+ segment.startDate = ganttRecord.startDate;
2008
+ const endDate: Date = this.parent.dataOperation.getEndDate(
2009
+ segment.startDate, segment.duration, ganttRecord.durationUnit, ganttRecord, false
2010
+ );
2011
+ segment.endDate = this.parent.dataOperation.checkEndDate(endDate, ganttRecord, false);
2012
+ this.parent.chartRowsModule.incrementSegments(segments, 0, data);
2013
+ }
2014
+ segment.width = this.getSplitTaskWidth(segment.startDate, segment.duration, data);
2015
+ segment.showProgress = false;
2016
+ segment.progressWidth = -1;
2017
+ if (i !== 0) {
2018
+ const pStartDate: Date = new Date(ganttRecord.startDate.getTime());
2019
+ segment.left = this.getSplitTaskLeft(segment.startDate, pStartDate);
2020
+ }
2021
+ if (totalProgressWidth > 0 && totalProgressWidth > segment.width) {
2022
+ totalProgressWidth = totalProgressWidth - segment.width;
2023
+ segment.progressWidth = segment.width;
2024
+ segment.showProgress = false;
2025
+ } else if (fixedWidth) {
2026
+ segment.progressWidth = totalProgressWidth;
2027
+ segment.showProgress = true;
2028
+ totalProgressWidth = totalProgressWidth - segment.width;
2029
+ fixedWidth = false;
2030
+ }
2031
+ }
2032
+ this.parent.setRecordValue('segments', ganttRecord.segments, ganttRecord, true);
2033
+ this.parent.dataOperation.updateMappingData(data, 'segments');
2034
+ }
2035
+ this.parent.setRecordValue('width', this.parent.dataOperation.calculateWidth(data), ganttRecord, true);
2036
+ this.parent.setRecordValue('left', this.parent.dataOperation.calculateLeft(ganttRecord), ganttRecord, true);
2037
+ this.parent.setRecordValue(
2038
+ 'progressWidth',
2039
+ this.parent.dataOperation.getProgressWidth(
2040
+ (ganttRecord.isAutoSchedule || !data.hasChildRecords ? ganttRecord.width : ganttRecord.autoWidth),
2041
+ ganttRecord.progress),
2042
+ ganttRecord,
2043
+ true
2044
+ );
2045
+ }
2046
+ /**
2047
+ * method to update left, width, progress width in record
2048
+ *
2049
+ * @param {IGanttData} data .
2050
+ * @returns {void} .
2051
+ * @private
2052
+ */
2053
+ public updateAutoWidthLeft(data: IGanttData): void {
2054
+ const ganttRecord: ITaskData = data.ganttProperties;
2055
+ this.parent.setRecordValue('autoWidth', this.calculateWidth(data, true), ganttRecord, true);
2056
+ this.parent.setRecordValue('autoLeft', this.calculateLeft(ganttRecord, true), ganttRecord, true);
2057
+ }
2058
+ /**
2059
+ * To calculate parent progress value
2060
+ *
2061
+ * @param {IGanttData} childGanttRecord .
2062
+ * @returns {object} .
2063
+ * @private
2064
+ */
2065
+ public getParentProgress(childGanttRecord: IGanttData): Object {
2066
+ let durationInDay: number = 0;
2067
+ const progressValues: Object = {};
2068
+ switch (childGanttRecord.ganttProperties.durationUnit) {
2069
+ case 'hour':
2070
+ durationInDay = (childGanttRecord.ganttProperties.duration / (this.parent.secondsPerDay / 3600));
2071
+ break;
2072
+ case 'minute':
2073
+ durationInDay = (childGanttRecord.ganttProperties.duration / (this.parent.secondsPerDay / 60));
2074
+ break;
2075
+ default:
2076
+ durationInDay = childGanttRecord.ganttProperties.duration;
2077
+ }
2078
+
2079
+ if (childGanttRecord.hasChildRecords) {
2080
+ setValue('totalProgress', childGanttRecord.ganttProperties.totalProgress, progressValues);
2081
+ setValue('totalDuration', childGanttRecord.ganttProperties.totalDuration, progressValues);
2082
+ } else {
2083
+ setValue('totalProgress', childGanttRecord.ganttProperties.progress * durationInDay, progressValues);
2084
+ setValue('totalDuration', durationInDay, progressValues);
2085
+ }
2086
+ return progressValues;
2087
+ }
2088
+
2089
+ private resetDependency(record: IGanttData): void {
2090
+ const dependency: string = this.parent.taskFields.dependency;
2091
+ if (!isNullOrUndefined(dependency)) {
2092
+ const recordProp: ITaskData = record.ganttProperties;
2093
+ this.parent.setRecordValue('predecessor', [], recordProp, true);
2094
+ this.parent.setRecordValue('predecessorsName', null, recordProp, true);
2095
+ this.parent.setRecordValue('taskData.' + dependency, null, record);
2096
+ this.parent.setRecordValue(dependency, null, record);
2097
+ }
2098
+ }
2099
+
2100
+ /**
2101
+ * @param {IParent | IGanttData} cloneParent .
2102
+ * @param {boolean} isParent .
2103
+ * @returns {void} .
2104
+ * @private
2105
+ */
2106
+ public updateParentItems(cloneParent: IParent | IGanttData, isParent?: boolean): void {
2107
+ const parentData: IGanttData = isParent ? cloneParent : this.parent.getParentTask(cloneParent);
2108
+ let deleteUpdate: boolean = false;
2109
+ const ganttProp: ITaskData = parentData.ganttProperties;
2110
+ if (parentData.childRecords.length > 0) {
2111
+ const previousStartDate: Date = ganttProp.isAutoSchedule ? ganttProp.startDate : ganttProp.autoStartDate;
2112
+ const previousEndDate: Date = ganttProp.isAutoSchedule ? ganttProp.endDate :
2113
+ ganttProp.autoEndDate;
2114
+ const childRecords: Object[] = parentData.childRecords;
2115
+ const childLength: number = childRecords.length;
2116
+ let totalDuration: number = 0;
2117
+ let progressValues: Object = {};
2118
+ let minStartDate: Date = null; let maxEndDate: Date = null;
2119
+ let milestoneCount: number = 0; let totalProgress: number = 0; let childCompletedWorks: number = 0;
2120
+ let childData: IGanttData;
2121
+ for (let count: number = 0; count < childLength; count++) {
2122
+ childData = childRecords[count] as IGanttData;
2123
+ if (this.parent.isOnDelete && childData.isDelete) {
2124
+ if (childLength === 1 && this.parent.viewType === 'ProjectView') {
2125
+ deleteUpdate = true;
2126
+ }
2127
+ continue;
2128
+ }
2129
+ let startDate: Date = this.getValidStartDate(childData.ganttProperties);
2130
+ if(parentData.hasChildRecords && !ganttProp.isAutoSchedule && !isNullOrUndefined( childData.ganttProperties.autoStartDate))
2131
+ {
2132
+ startDate = childData.ganttProperties.autoStartDate;
2133
+ }
2134
+ let endDate: Date = this.getValidEndDate(childData.ganttProperties);
2135
+ if(parentData.hasChildRecords && !ganttProp.isAutoSchedule && !isNullOrUndefined( childData.ganttProperties.autoEndDate))
2136
+ {
2137
+ endDate = childData.ganttProperties.autoEndDate;
2138
+ }
2139
+
2140
+ if (isNullOrUndefined(minStartDate)) {
2141
+ minStartDate = this.getDateFromFormat(startDate);
2142
+ }
2143
+ if (isNullOrUndefined(maxEndDate)) {
2144
+ maxEndDate = this.getDateFromFormat(endDate);
2145
+ }
2146
+ if (!isNullOrUndefined(endDate) && this.compareDates(endDate, maxEndDate) === 1) {
2147
+ maxEndDate = this.getDateFromFormat(endDate);
2148
+ }
2149
+ if (!isNullOrUndefined(startDate) && this.compareDates(startDate, minStartDate) === -1) {
2150
+ minStartDate = this.getDateFromFormat(startDate);
2151
+ }
2152
+ if (!childData.ganttProperties.isMilestone && isScheduledTask(childData.ganttProperties)) {
2153
+ progressValues = this.getParentProgress(childData);
2154
+ totalProgress += getValue('totalProgress', progressValues);
2155
+ totalDuration += getValue('totalDuration', progressValues);
2156
+ } else {
2157
+ milestoneCount++;
2158
+ }
2159
+ childCompletedWorks += childData.ganttProperties.work;
2160
+ }
2161
+ if (!deleteUpdate) {
2162
+ if (this.compareDates(previousStartDate, minStartDate) !== 0) {
2163
+ this.parent.setRecordValue(
2164
+ ganttProp.isAutoSchedule ? 'startDate' : 'autoStartDate',
2165
+ minStartDate, parentData.ganttProperties, true);
2166
+ }
2167
+ if (this.compareDates(previousEndDate, maxEndDate) !== 0) {
2168
+ this.parent.setRecordValue(
2169
+ ganttProp.isAutoSchedule ? 'endDate' : 'autoEndDate',
2170
+ maxEndDate, parentData.ganttProperties, true);
2171
+ }
2172
+ let taskCount: number;
2173
+ if (this.parent.isOnDelete && childData.isDelete) {
2174
+ taskCount = childLength - milestoneCount - 1;
2175
+ } else {
2176
+ taskCount = childLength - milestoneCount;
2177
+ }
2178
+ const parentProgress: number = (taskCount > 0 && totalDuration > 0) ? (totalProgress / totalDuration) : 0;
2179
+ const parentProp: ITaskData = parentData.ganttProperties;
2180
+ const milestone: boolean = (taskCount === 0) && minStartDate && maxEndDate &&
2181
+ minStartDate.getTime() === maxEndDate.getTime() ? true : false;
2182
+ this.parent.setRecordValue('isMilestone', milestone, parentProp, true);
2183
+ if (parentProp.isAutoSchedule) {
2184
+ this.calculateDuration(parentData);
2185
+ }
2186
+ this.updateWorkWithDuration(parentData);
2187
+ let parentWork: number = parentProp.work;
2188
+ parentWork += childCompletedWorks;
2189
+ this.parent.setRecordValue('work', parentWork, parentProp, true);
2190
+ this.parent.setRecordValue('taskType', 'FixedDuration', parentProp, true);
2191
+ if (!isNullOrUndefined(this.parent.taskFields.type)) {
2192
+ this.updateMappingData(parentData, 'type');
2193
+ }
2194
+ this.parent.setRecordValue('progress', Math.floor(parentProgress), parentProp, true);
2195
+ this.parent.setRecordValue('totalProgress', totalProgress, parentProp, true);
2196
+ this.parent.setRecordValue('totalDuration', totalDuration, parentProp, true);
2197
+ if (!parentProp.isAutoSchedule) {
2198
+ this.parent.setRecordValue('autoDuration', this.calculateAutoDuration(parentProp), parentProp, true);
2199
+ this.updateAutoWidthLeft(parentData);
2200
+ }
2201
+ this.resetDependency(parentData);
2202
+ this.updateWidthLeft(parentData);
2203
+ this.updateTaskData(parentData);
2204
+ }
2205
+ }
2206
+ if (deleteUpdate && parentData.childRecords.length === 1 && parentData.ganttProperties.duration === 0) {
2207
+ this.parent.setRecordValue('isMilestone', true, parentData.ganttProperties, true);
2208
+ this.updateWidthLeft(parentData);
2209
+ this.updateTaskData(parentData);
2210
+ }
2211
+ const parentItem: IGanttData = this.parent.getParentTask(parentData.parentItem) as IGanttData;
2212
+ if (parentItem) {
2213
+ this.updateParentItems(parentItem);
2214
+ }
2215
+ deleteUpdate = false;
2216
+ }
2217
+ }