@syncfusion/ej2-gantt 19.4.56 → 20.1.47-1460716

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/CHANGELOG.md +1072 -1060
  2. package/README.md +75 -75
  3. package/dist/ej2-gantt.umd.min.js +1 -10
  4. package/dist/ej2-gantt.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-gantt.es2015.js +274 -176
  6. package/dist/es6/ej2-gantt.es2015.js.map +1 -1
  7. package/dist/es6/ej2-gantt.es5.js +642 -534
  8. package/dist/es6/ej2-gantt.es5.js.map +1 -1
  9. package/dist/global/ej2-gantt.min.js +1 -10
  10. package/dist/global/ej2-gantt.min.js.map +1 -1
  11. package/dist/global/index.d.ts +0 -9
  12. package/dist/ts/components.ts +4 -0
  13. package/dist/ts/gantt/actions/actions.ts +18 -0
  14. package/dist/ts/gantt/actions/cell-edit.ts +606 -0
  15. package/dist/ts/gantt/actions/chart-scroll.ts +167 -0
  16. package/dist/ts/gantt/actions/column-menu.ts +35 -0
  17. package/dist/ts/gantt/actions/column-reorder.ts +52 -0
  18. package/dist/ts/gantt/actions/column-resize.ts +52 -0
  19. package/dist/ts/gantt/actions/connector-line-edit.ts +829 -0
  20. package/dist/ts/gantt/actions/context-menu.ts +754 -0
  21. package/dist/ts/gantt/actions/day-markers.ts +80 -0
  22. package/dist/ts/gantt/actions/dependency.ts +692 -0
  23. package/dist/ts/gantt/actions/dialog-edit.ts +2208 -0
  24. package/dist/ts/gantt/actions/edit.ts +3499 -0
  25. package/dist/ts/gantt/actions/excel-export.ts +61 -0
  26. package/dist/ts/gantt/actions/filter.ts +302 -0
  27. package/dist/ts/gantt/actions/keyboard.ts +306 -0
  28. package/dist/ts/gantt/actions/pdf-export.ts +214 -0
  29. package/dist/ts/gantt/actions/rowdragdrop.ts +839 -0
  30. package/dist/ts/gantt/actions/selection.ts +536 -0
  31. package/dist/ts/gantt/actions/sort.ts +98 -0
  32. package/dist/ts/gantt/actions/taskbar-edit.ts +1940 -0
  33. package/dist/ts/gantt/actions/toolbar.ts +489 -0
  34. package/dist/ts/gantt/actions/virtual-scroll.ts +60 -0
  35. package/dist/ts/gantt/base/common.ts +9 -0
  36. package/dist/ts/gantt/base/constant.ts +13 -0
  37. package/dist/ts/gantt/base/css-constants.ts +148 -0
  38. package/dist/ts/gantt/base/date-processor.ts +1257 -0
  39. package/dist/ts/gantt/base/enum.ts +372 -0
  40. package/dist/ts/gantt/base/gantt-chart.ts +1248 -0
  41. package/dist/ts/gantt/base/gantt.ts +4069 -0
  42. package/dist/ts/gantt/base/interface.ts +955 -0
  43. package/dist/ts/gantt/base/splitter.ts +174 -0
  44. package/dist/ts/gantt/base/task-processor.ts +2217 -0
  45. package/dist/ts/gantt/base/tree-grid.ts +694 -0
  46. package/dist/ts/gantt/base/utils.ts +208 -0
  47. package/dist/ts/gantt/export/export-helper.ts +552 -0
  48. package/dist/ts/gantt/export/pdf-base/dictionary.ts +152 -0
  49. package/dist/ts/gantt/export/pdf-base/pdf-borders.ts +277 -0
  50. package/dist/ts/gantt/export/pdf-base/pdf-grid-table.ts +901 -0
  51. package/dist/ts/gantt/export/pdf-base/pdf-style/gantt-theme.ts +131 -0
  52. package/dist/ts/gantt/export/pdf-base/pdf-style/style.ts +91 -0
  53. package/dist/ts/gantt/export/pdf-base/treegrid-layouter.ts +414 -0
  54. package/dist/ts/gantt/export/pdf-connector-line.ts +422 -0
  55. package/dist/ts/gantt/export/pdf-gantt.ts +282 -0
  56. package/dist/ts/gantt/export/pdf-taskbar.ts +395 -0
  57. package/dist/ts/gantt/export/pdf-timeline.ts +202 -0
  58. package/dist/ts/gantt/export/pdf-treegrid.ts +406 -0
  59. package/dist/ts/gantt/models/add-dialog-field-settings.ts +33 -0
  60. package/dist/ts/gantt/models/column.ts +464 -0
  61. package/dist/ts/gantt/models/day-working-time.ts +22 -0
  62. package/dist/ts/gantt/models/edit-dialog-field-settings.ts +33 -0
  63. package/dist/ts/gantt/models/edit-settings.ts +79 -0
  64. package/dist/ts/gantt/models/event-marker.ts +27 -0
  65. package/dist/ts/gantt/models/filter-settings.ts +53 -0
  66. package/dist/ts/gantt/models/holiday.ts +34 -0
  67. package/dist/ts/gantt/models/label-settings.ts +30 -0
  68. package/dist/ts/gantt/models/models.ts +36 -0
  69. package/dist/ts/gantt/models/resource-fields.ts +38 -0
  70. package/dist/ts/gantt/models/search-settings.ts +77 -0
  71. package/dist/ts/gantt/models/selection-settings.ts +56 -0
  72. package/dist/ts/gantt/models/sort-settings.ts +50 -0
  73. package/dist/ts/gantt/models/splitter-settings.ts +47 -0
  74. package/dist/ts/gantt/models/task-fields.ts +171 -0
  75. package/dist/ts/gantt/models/timeline-settings.ts +112 -0
  76. package/dist/ts/gantt/models/tooltip-settings.ts +46 -0
  77. package/dist/ts/gantt/renderer/chart-rows.ts +1838 -0
  78. package/dist/ts/gantt/renderer/connector-line.ts +1025 -0
  79. package/dist/ts/gantt/renderer/edit-tooltip.ts +228 -0
  80. package/dist/ts/gantt/renderer/event-marker.ts +96 -0
  81. package/dist/ts/gantt/renderer/nonworking-day.ts +205 -0
  82. package/dist/ts/gantt/renderer/render.ts +5 -0
  83. package/dist/ts/gantt/renderer/timeline.ts +1397 -0
  84. package/dist/ts/gantt/renderer/tooltip.ts +450 -0
  85. package/dist/ts/gantt/renderer/virtual-content-render.ts +50 -0
  86. package/license +9 -9
  87. package/package.json +80 -80
  88. package/src/gantt/actions/cell-edit.js +2 -1
  89. package/src/gantt/actions/dialog-edit.js +2 -1
  90. package/src/gantt/actions/edit.js +11 -2
  91. package/src/gantt/actions/rowdragdrop.js +37 -15
  92. package/src/gantt/actions/taskbar-edit.js +24 -24
  93. package/src/gantt/base/date-processor.js +0 -1
  94. package/src/gantt/base/gantt-chart.js +9 -4
  95. package/src/gantt/base/gantt-model.d.ts +779 -779
  96. package/src/gantt/base/gantt.d.ts +27 -27
  97. package/src/gantt/base/gantt.js +22 -22
  98. package/src/gantt/base/splitter.js +1 -0
  99. package/src/gantt/base/task-processor.js +13 -13
  100. package/src/gantt/base/tree-grid.js +3 -1
  101. package/src/gantt/export/pdf-base/treegrid-layouter.js +13 -13
  102. package/src/gantt/export/pdf-connector-line.js +11 -11
  103. package/src/gantt/export/pdf-gantt.js +24 -24
  104. package/src/gantt/export/pdf-taskbar.js +11 -11
  105. package/src/gantt/export/pdf-treegrid.js +13 -13
  106. package/src/gantt/models/add-dialog-field-settings-model.d.ts +21 -21
  107. package/src/gantt/models/add-dialog-field-settings.js +19 -19
  108. package/src/gantt/models/day-working-time-model.d.ts +11 -11
  109. package/src/gantt/models/day-working-time.js +19 -19
  110. package/src/gantt/models/edit-dialog-field-settings-model.d.ts +21 -21
  111. package/src/gantt/models/edit-dialog-field-settings.js +19 -19
  112. package/src/gantt/models/edit-settings-model.d.ts +50 -50
  113. package/src/gantt/models/edit-settings.js +19 -19
  114. package/src/gantt/models/event-marker-model.d.ts +16 -16
  115. package/src/gantt/models/event-marker.js +19 -19
  116. package/src/gantt/models/filter-settings-model.d.ts +34 -34
  117. package/src/gantt/models/filter-settings.js +19 -19
  118. package/src/gantt/models/holiday-model.d.ts +21 -21
  119. package/src/gantt/models/holiday.js +19 -19
  120. package/src/gantt/models/label-settings-model.d.ts +16 -16
  121. package/src/gantt/models/label-settings.js +19 -19
  122. package/src/gantt/models/resource-fields-model.d.ts +21 -21
  123. package/src/gantt/models/resource-fields.js +19 -19
  124. package/src/gantt/models/search-settings-model.d.ts +56 -56
  125. package/src/gantt/models/search-settings.js +19 -19
  126. package/src/gantt/models/selection-settings-model.d.ts +35 -35
  127. package/src/gantt/models/selection-settings.js +19 -19
  128. package/src/gantt/models/sort-settings-model.d.ts +24 -24
  129. package/src/gantt/models/sort-settings.js +19 -19
  130. package/src/gantt/models/splitter-settings-model.d.ts +30 -30
  131. package/src/gantt/models/splitter-settings.js +19 -19
  132. package/src/gantt/models/task-fields-model.d.ts +110 -110
  133. package/src/gantt/models/task-fields.js +19 -19
  134. package/src/gantt/models/timeline-settings-model.d.ts +71 -71
  135. package/src/gantt/models/timeline-settings.js +19 -19
  136. package/src/gantt/models/tooltip-settings-model.d.ts +26 -26
  137. package/src/gantt/models/tooltip-settings.js +19 -19
  138. package/src/gantt/renderer/chart-rows.js +49 -37
  139. package/src/gantt/renderer/connector-line.js +22 -18
  140. package/src/gantt/renderer/event-marker.js +1 -0
  141. package/src/gantt/renderer/nonworking-day.js +13 -6
  142. package/src/gantt/renderer/timeline.d.ts +1 -0
  143. package/src/gantt/renderer/timeline.js +48 -12
  144. package/src/gantt/renderer/tooltip.js +11 -3
  145. package/styles/bootstrap-dark.css +442 -427
  146. package/styles/bootstrap.css +442 -433
  147. package/styles/bootstrap4.css +454 -479
  148. package/styles/bootstrap5-dark.css +457 -433
  149. package/styles/bootstrap5.css +457 -433
  150. package/styles/fabric-dark.css +438 -421
  151. package/styles/fabric.css +445 -428
  152. package/styles/fluent-dark.css +1938 -0
  153. package/styles/fluent-dark.scss +1 -0
  154. package/styles/fluent.css +1938 -0
  155. package/styles/fluent.scss +1 -0
  156. package/styles/gantt/_all.scss +2 -2
  157. package/styles/gantt/_bootstrap-dark-definition.scss +210 -156
  158. package/styles/gantt/_bootstrap-definition.scss +211 -157
  159. package/styles/gantt/_bootstrap4-definition.scss +213 -158
  160. package/styles/gantt/_bootstrap5-definition.scss +215 -162
  161. package/styles/gantt/_fabric-dark-definition.scss +211 -157
  162. package/styles/gantt/_fabric-definition.scss +211 -157
  163. package/styles/gantt/_fluent-dark-definition.scss +1 -0
  164. package/styles/gantt/_fluent-definition.scss +215 -162
  165. package/styles/gantt/_fusionnew-definition.scss +214 -0
  166. package/styles/gantt/_highcontrast-definition.scss +211 -157
  167. package/styles/gantt/_highcontrast-light-definition.scss +211 -157
  168. package/styles/gantt/_layout.scss +1446 -1027
  169. package/styles/gantt/_material-dark-definition.scss +212 -157
  170. package/styles/gantt/_material-definition.scss +212 -157
  171. package/styles/gantt/_material3-definition.scss +215 -0
  172. package/styles/gantt/_tailwind-definition.scss +215 -161
  173. package/styles/gantt/_theme.scss +702 -668
  174. package/styles/gantt/bootstrap-dark.css +442 -427
  175. package/styles/gantt/bootstrap.css +442 -433
  176. package/styles/gantt/bootstrap4.css +454 -479
  177. package/styles/gantt/bootstrap5-dark.css +457 -433
  178. package/styles/gantt/bootstrap5.css +457 -433
  179. package/styles/gantt/fabric-dark.css +438 -421
  180. package/styles/gantt/fabric.css +445 -428
  181. package/styles/gantt/fluent-dark.css +1938 -0
  182. package/styles/gantt/fluent-dark.scss +22 -0
  183. package/styles/gantt/fluent.css +1938 -0
  184. package/styles/gantt/fluent.scss +22 -0
  185. package/styles/gantt/highcontrast-light.css +405 -405
  186. package/styles/gantt/highcontrast.css +444 -456
  187. package/styles/gantt/icons/_bootstrap-dark.scss +124 -113
  188. package/styles/gantt/icons/_bootstrap.scss +124 -113
  189. package/styles/gantt/icons/_bootstrap4.scss +124 -113
  190. package/styles/gantt/icons/_bootstrap5.scss +124 -112
  191. package/styles/gantt/icons/_fabric-dark.scss +124 -112
  192. package/styles/gantt/icons/_fabric.scss +124 -112
  193. package/styles/gantt/icons/_fluent-dark.scss +1 -0
  194. package/styles/gantt/icons/_fluent.scss +124 -112
  195. package/styles/gantt/icons/_fusionnew.scss +120 -0
  196. package/styles/gantt/icons/_highcontrast.scss +124 -112
  197. package/styles/gantt/icons/_material-dark.scss +124 -112
  198. package/styles/gantt/icons/_material.scss +124 -112
  199. package/styles/gantt/icons/_material3.scss +124 -0
  200. package/styles/gantt/icons/_tailwind-dark.scss +124 -113
  201. package/styles/gantt/icons/_tailwind.scss +124 -113
  202. package/styles/gantt/material-dark.css +446 -417
  203. package/styles/gantt/material.css +445 -419
  204. package/styles/gantt/tailwind-dark.css +452 -482
  205. package/styles/gantt/tailwind.css +449 -479
  206. package/styles/highcontrast-light.css +405 -405
  207. package/styles/highcontrast.css +444 -456
  208. package/styles/material-dark.css +446 -417
  209. package/styles/material.css +445 -419
  210. package/styles/tailwind-dark.css +452 -482
  211. package/styles/tailwind.css +449 -479
@@ -0,0 +1,3499 @@
1
+ import { isNullOrUndefined, isUndefined, extend, setValue, getValue, deleteObject, createElement } from '@syncfusion/ej2-base';
2
+ import { Gantt } from '../base/gantt';
3
+ import { TaskFieldsModel, EditSettingsModel, ResourceFieldsModel } from '../models/models';
4
+ import { IGanttData, ITaskData, ITaskbarEditedEventArgs, IValidateArgs, IParent, IPredecessor } from '../base/interface';
5
+ import { IActionBeginEventArgs, ITaskAddedEventArgs, ITaskDeletedEventArgs, RowDropEventArgs } from '../base/interface';
6
+ import { ColumnModel, Column as GanttColumn } from '../models/column';
7
+ import { ColumnModel as GanttColumnModel } from '../models/column';
8
+ import { DataManager, DataUtil, Query, AdaptorOptions, ODataAdaptor, WebApiAdaptor } from '@syncfusion/ej2-data';
9
+ import { ReturnType, RecordDoubleClickEventArgs, Row, Column, IEditCell, EJ2Intance, getUid } from '@syncfusion/ej2-grids';
10
+ import { getSwapKey, isScheduledTask, getTaskData, isRemoteData, getIndex, isCountRequired, updateDates } from '../base/utils';
11
+ import { RowPosition } from '../base/enum';
12
+ import { CellEdit } from './cell-edit';
13
+ import { TaskbarEdit } from './taskbar-edit';
14
+ import { DialogEdit } from './dialog-edit';
15
+ import { Dialog } from '@syncfusion/ej2-popups';
16
+ import { NumericTextBoxModel } from '@syncfusion/ej2-inputs';
17
+ import { MultiSelect, CheckBoxSelection, DropDownList } from '@syncfusion/ej2-dropdowns';
18
+ import { ConnectorLineEdit } from './connector-line-edit';
19
+ import { ITreeData } from '@syncfusion/ej2-treegrid';
20
+
21
+
22
+
23
+
24
+ /**
25
+ * The Edit Module is used to handle editing actions.
26
+ *
27
+ */
28
+ export class Edit {
29
+ private parent: Gantt;
30
+ public validatedChildItems: IGanttData[];
31
+ private isFromDeleteMethod: boolean = false;
32
+ private targetedRecords: IGanttData[] = [];
33
+ /**
34
+ * @private
35
+ */
36
+ /** @hidden */
37
+ private ganttData: Object[] | DataManager;
38
+ /** @hidden */
39
+ private treeGridData: ITreeData[];
40
+ /** @hidden */
41
+ private draggedRecord: IGanttData;
42
+ /** @hidden */
43
+ private updateParentRecords: IGanttData[] = [];
44
+ /** @hidden */
45
+ private droppedRecord: IGanttData;
46
+ /** @hidden */
47
+ private isTreeGridRefresh: boolean;
48
+ /** @hidden */
49
+ public isaddtoBottom: boolean = false;
50
+ /** @hidden */
51
+ public addRowPosition: RowPosition;
52
+ /** @hidden */
53
+ public addRowIndex: number;
54
+ /** @hidden */
55
+ private dropPosition: string;
56
+ public confirmDialog: Dialog = null;
57
+ private taskbarMoved: boolean = false;
58
+ private predecessorUpdated: boolean = false;
59
+ public newlyAddedRecordBackup: IGanttData;
60
+ public isBreakLoop: boolean = false;
61
+ public addRowSelectedItem: IGanttData;
62
+ public cellEditModule: CellEdit;
63
+ public taskbarEditModule: TaskbarEdit;
64
+ public dialogModule: DialogEdit;
65
+ constructor(parent?: Gantt) {
66
+ this.parent = parent;
67
+ this.validatedChildItems = [];
68
+ if (this.parent.editSettings.allowEditing && this.parent.editSettings.mode === 'Auto') {
69
+ this.cellEditModule = new CellEdit(this.parent);
70
+ }
71
+ if (this.parent.taskFields.dependency) {
72
+ this.parent.connectorLineEditModule = new ConnectorLineEdit(this.parent);
73
+ }
74
+ if (this.parent.editSettings.allowAdding || (this.parent.editSettings.allowEditing &&
75
+ (this.parent.editSettings.mode === 'Dialog' || this.parent.editSettings.mode === 'Auto'))) {
76
+ this.dialogModule = new DialogEdit(this.parent);
77
+ }
78
+ if (this.parent.editSettings.allowTaskbarEditing) {
79
+ this.taskbarEditModule = new TaskbarEdit(this.parent);
80
+ }
81
+ if (this.parent.editSettings.allowDeleting) {
82
+ const confirmDialog: HTMLElement = createElement('div', {
83
+ id: this.parent.element.id + '_deleteConfirmDialog'
84
+ });
85
+ this.parent.element.appendChild(confirmDialog);
86
+ this.renderDeleteConfirmDialog();
87
+ }
88
+ this.parent.treeGrid.recordDoubleClick = this.recordDoubleClick.bind(this);
89
+ this.parent.treeGrid.editSettings.allowAdding = this.parent.editSettings.allowAdding;
90
+ this.parent.treeGrid.editSettings.allowDeleting = this.parent.editSettings.allowDeleting;
91
+ this.parent.treeGrid.editSettings.showDeleteConfirmDialog = this.parent.editSettings.showDeleteConfirmDialog;
92
+ this.parent.treeGrid.editSettings.allowNextRowEdit = this.parent.editSettings.allowNextRowEdit;
93
+ this.updateDefaultColumnEditors();
94
+ }
95
+
96
+ private getModuleName(): string {
97
+ return 'edit';
98
+ }
99
+
100
+ /**
101
+ * Method to update default edit params and editors for Gantt
102
+ *
103
+ * @returns {void} .
104
+ */
105
+ private updateDefaultColumnEditors(): void {
106
+ const customEditorColumns: string[] =
107
+ [this.parent.taskFields.id, this.parent.taskFields.progress, this.parent.taskFields.resourceInfo, 'taskType'];
108
+ for (let i: number = 0; i < customEditorColumns.length; i++) {
109
+ if (!isNullOrUndefined(customEditorColumns[i]) && customEditorColumns[i].length > 0) {
110
+ // eslint-disable-next-line
111
+ const column: ColumnModel = this.parent.getColumnByField(customEditorColumns[i], this.parent.treeGridModule.treeGridColumns);
112
+ if (column) {
113
+ if (column.field === this.parent.taskFields.id) {
114
+ this.updateIDColumnEditParams(column);
115
+ } else if (column.field === this.parent.taskFields.progress) {
116
+ this.updateProgessColumnEditParams(column);
117
+ } else if (column.field === this.parent.taskFields.resourceInfo) {
118
+ this.updateResourceColumnEditor(column);
119
+ } else if (column.field === 'taskType') {
120
+ this.updateTaskTypeColumnEditor(column);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ /**
127
+ * Method to update editors for id column in Gantt
128
+ *
129
+ * @param {ColumnModel} column .
130
+ * @returns {void} .
131
+ */
132
+ private updateIDColumnEditParams(column: ColumnModel): void {
133
+ const editParam: NumericTextBoxModel = {
134
+ min: 0,
135
+ decimals: 0,
136
+ validateDecimalOnType: true,
137
+ format: 'n0',
138
+ showSpinButton: false
139
+ };
140
+ this.updateEditParams(column, editParam);
141
+ }
142
+
143
+ /**
144
+ * Method to update edit params of default progress column
145
+ *
146
+ * @param {ColumnModel} column .
147
+ * @returns {void} .
148
+ */
149
+ private updateProgessColumnEditParams(column: ColumnModel): void {
150
+ const editParam: NumericTextBoxModel = {
151
+ min: 0,
152
+ decimals: 0,
153
+ validateDecimalOnType: true,
154
+ max: 100,
155
+ format: 'n0'
156
+ };
157
+ this.updateEditParams(column, editParam);
158
+ }
159
+ /**
160
+ * Assign edit params for id and progress columns
161
+ *
162
+ * @param {ColumnModel} column .
163
+ * @param {object} editParam .
164
+ * @returns {void} .
165
+ */
166
+ private updateEditParams(column: ColumnModel, editParam: object): void {
167
+ if (isNullOrUndefined(column.edit)) {
168
+ column.edit = {};
169
+ column.edit.params = {};
170
+ } else if (isNullOrUndefined(column.edit.params)) {
171
+ column.edit.params = {};
172
+ }
173
+ extend(editParam, column.edit.params);
174
+ column.edit.params = editParam;
175
+ const ganttColumn: ColumnModel = this.parent.getColumnByField(column.field, this.parent.ganttColumns);
176
+ ganttColumn.edit = column.edit;
177
+ }
178
+ /**
179
+ * Method to update resource column editor for default resource column
180
+ *
181
+ * @param {ColumnModel} column .
182
+ * @returns {void} .
183
+ */
184
+ private updateResourceColumnEditor(column: ColumnModel): void {
185
+ if (this.parent.editSettings.allowEditing && isNullOrUndefined(column.edit) && this.parent.editSettings.mode === 'Auto') {
186
+ column.editType = 'dropdownedit';
187
+ column.edit = this.getResourceEditor();
188
+ const ganttColumn: ColumnModel = this.parent.getColumnByField(column.field, this.parent.ganttColumns);
189
+ ganttColumn.editType = 'dropdownedit';
190
+ ganttColumn.edit = column.edit;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Method to create resource custom editor
196
+ *
197
+ * @returns {IEditCell} .
198
+ */
199
+ private getResourceEditor(): IEditCell {
200
+ const resourceSettings: ResourceFieldsModel = this.parent.resourceFields;
201
+ const editObject: IEditCell = {};
202
+ let editor: MultiSelect;
203
+ MultiSelect.Inject(CheckBoxSelection);
204
+ editObject.write = (args: { rowData: Object, element: Element, column: GanttColumn, row: HTMLElement, requestType: string }) => {
205
+ this.parent.treeGridModule.currentEditRow = {};
206
+ editor = new MultiSelect({
207
+ dataSource: new DataManager(this.parent.resources),
208
+ fields: { text: resourceSettings.name, value: resourceSettings.id },
209
+ mode: 'CheckBox',
210
+ showDropDownIcon: true,
211
+ popupHeight: '350px',
212
+ delimiterChar: ',',
213
+ value: this.parent.treeGridModule.getResourceIds(args.rowData as IGanttData) as number[]
214
+ });
215
+ editor.appendTo(args.element as HTMLElement);
216
+ };
217
+ editObject.read = (element: HTMLElement): string => {
218
+ let value: Object[] = (<EJ2Intance>element).ej2_instances[0].value;
219
+ const resourcesName: string[] = [];
220
+ if (isNullOrUndefined(value)) {
221
+ value = [];
222
+ }
223
+ for (let i: number = 0; i < value.length; i++) {
224
+ for (let j: number = 0; j < this.parent.resources.length; j++) {
225
+ if (this.parent.resources[j][resourceSettings.id] === value[i]) {
226
+ resourcesName.push(this.parent.resources[j][resourceSettings.name]);
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ this.parent.treeGridModule.currentEditRow[this.parent.taskFields.resourceInfo] = value;
232
+ return resourcesName.join(',');
233
+ };
234
+ editObject.destroy = () => {
235
+ if (editor) {
236
+ editor.destroy();
237
+ }
238
+ };
239
+ return editObject;
240
+ }
241
+ /**
242
+ * Method to update task type column editor for task type
243
+ *
244
+ * @param {ColumnModel} column .
245
+ * @returns {void} .
246
+ */
247
+ private updateTaskTypeColumnEditor(column: ColumnModel): void {
248
+ if (this.parent.editSettings.allowEditing && isNullOrUndefined(column.edit) && this.parent.editSettings.mode === 'Auto') {
249
+ column.editType = 'dropdownedit';
250
+ column.edit = this.getTaskTypeEditor();
251
+ const ganttColumn: ColumnModel = this.parent.getColumnByField(column.field, this.parent.ganttColumns);
252
+ ganttColumn.editType = 'dropdownedit';
253
+ ganttColumn.edit = column.edit;
254
+ }
255
+ }
256
+ /**
257
+ * Method to create task type custom editor
258
+ *
259
+ * @returns {IEditCell} .
260
+ */
261
+ private getTaskTypeEditor(): IEditCell {
262
+ const editObject: IEditCell = {};
263
+ let editor: DropDownList;
264
+ const types: Object[] = [{ 'ID': 1, 'Value': 'FixedUnit' }, { 'ID': 2, 'Value': 'FixedWork' }, { 'ID': 3, 'Value': 'FixedDuration' }];
265
+ editObject.write = (args: { rowData: Object, element: Element, column: GanttColumn, row: HTMLElement, requestType: string }) => {
266
+ this.parent.treeGridModule.currentEditRow = {};
267
+ editor = new DropDownList({
268
+ dataSource: new DataManager(types),
269
+ fields: { value: 'Value' },
270
+ popupHeight: '350px',
271
+ value: getValue('taskType', (args.rowData as IGanttData).ganttProperties)
272
+ });
273
+ editor.appendTo(args.element as HTMLElement);
274
+ };
275
+ editObject.read = (element: HTMLElement): string => {
276
+ const value: string = (<EJ2Intance>element).ej2_instances[0].value;
277
+ const key: string = 'taskType';
278
+ this.parent.treeGridModule.currentEditRow[key] = value;
279
+ return value;
280
+ };
281
+ editObject.destroy = () => {
282
+ if (editor) {
283
+ editor.destroy();
284
+ }
285
+ };
286
+ return editObject;
287
+ }
288
+ /**
289
+ * @returns {void} .
290
+ * @private
291
+ */
292
+ public reUpdateEditModules(): void {
293
+ const editSettings: EditSettingsModel = this.parent.editSettings;
294
+ if (editSettings.allowEditing) {
295
+ if (this.parent.editModule.cellEditModule && editSettings.mode === 'Dialog') {
296
+ this.cellEditModule.destroy();
297
+ this.parent.treeGrid.recordDoubleClick = this.recordDoubleClick.bind(this);
298
+ } else if (isNullOrUndefined(this.parent.editModule.cellEditModule) && editSettings.mode === 'Auto') {
299
+ this.cellEditModule = new CellEdit(this.parent);
300
+ }
301
+ if (this.parent.editModule.dialogModule && editSettings.mode === 'Auto') {
302
+ this.parent.treeGrid.recordDoubleClick = undefined;
303
+ } else if (isNullOrUndefined(this.parent.editModule.dialogModule)) {
304
+ this.dialogModule = new DialogEdit(this.parent);
305
+ }
306
+ } else {
307
+ if (this.cellEditModule) {
308
+ this.cellEditModule.destroy();
309
+ }
310
+ if (this.dialogModule) {
311
+ this.dialogModule.destroy();
312
+ }
313
+ }
314
+
315
+ if (editSettings.allowDeleting && editSettings.showDeleteConfirmDialog) {
316
+ if (isNullOrUndefined(this.confirmDialog)) {
317
+ const confirmDialog: HTMLElement = createElement('div', {
318
+ id: this.parent.element.id + '_deleteConfirmDialog'
319
+ });
320
+ this.parent.element.appendChild(confirmDialog);
321
+ this.renderDeleteConfirmDialog();
322
+ }
323
+ } else if (!editSettings.allowDeleting || !editSettings.showDeleteConfirmDialog) {
324
+ if (this.confirmDialog && !this.confirmDialog.isDestroyed) {
325
+ this.confirmDialog.destroy();
326
+ }
327
+ }
328
+
329
+ if (editSettings.allowTaskbarEditing) {
330
+ if (isNullOrUndefined(this.parent.editModule.taskbarEditModule)) {
331
+ this.taskbarEditModule = new TaskbarEdit(this.parent);
332
+ }
333
+ } else {
334
+ if (this.taskbarEditModule) {
335
+ this.taskbarEditModule.destroy();
336
+ }
337
+ }
338
+ }
339
+
340
+ private recordDoubleClick(args: RecordDoubleClickEventArgs): void {
341
+ if (this.parent.editSettings.allowEditing && this.parent.editSettings.mode === 'Dialog') {
342
+ let ganttData: IGanttData;
343
+ if (args.row) {
344
+ const rowIndex: number = getValue('rowIndex', args.row);
345
+ ganttData = this.parent.currentViewData[rowIndex];
346
+ }
347
+ if (!isNullOrUndefined(ganttData)) {
348
+ this.dialogModule.openEditDialog(ganttData);
349
+ }
350
+ }
351
+ this.parent.ganttChartModule.recordDoubleClick(args);
352
+ }
353
+ /**
354
+ * @returns {void} .
355
+ * @private
356
+ */
357
+ public destroy(): void {
358
+ if (this.cellEditModule) {
359
+ this.cellEditModule.destroy();
360
+ }
361
+ if (this.taskbarEditModule) {
362
+ this.taskbarEditModule.destroy();
363
+ }
364
+ if (this.dialogModule) {
365
+ this.dialogModule.destroy();
366
+ }
367
+ if (this.confirmDialog && !this.confirmDialog.isDestroyed) {
368
+ this.confirmDialog.destroy();
369
+ }
370
+ }
371
+ /**
372
+ * @private
373
+ */
374
+ public deletedTaskDetails: IGanttData[] = [];
375
+ /**
376
+ * Method to update record with new values.
377
+ *
378
+ * @param {Object} data - Defines new data to update.
379
+ * @returns {void} .
380
+ */
381
+ public updateRecordByID(data: Object): void {
382
+ if (!this.parent.readOnly) {
383
+ const tasks: TaskFieldsModel = this.parent.taskFields;
384
+ if (isNullOrUndefined(data) || isNullOrUndefined(data[tasks.id])) {
385
+ return;
386
+ }
387
+ const ganttData: IGanttData = this.parent.viewType === 'ResourceView' ?
388
+ this.parent.flatData[this.parent.getTaskIds().indexOf('T' + data[tasks.id])] : this.parent.getRecordByID(data[tasks.id]);
389
+ if (!isNullOrUndefined(this.parent.editModule) && ganttData) {
390
+ this.parent.isOnEdit = true;
391
+ this.validateUpdateValues(data, ganttData, true);
392
+ const keys: string[] = Object.keys(data);
393
+ if (keys.indexOf(tasks.startDate) !== -1 || keys.indexOf(tasks.endDate) !== -1 ||
394
+ keys.indexOf(tasks.duration) !== -1) {
395
+ this.parent.dataOperation.calculateScheduledValues(ganttData, ganttData.taskData, false);
396
+ }
397
+ this.parent.dataOperation.updateWidthLeft(ganttData);
398
+ if (!isUndefined(data[this.parent.taskFields.dependency]) &&
399
+ data[this.parent.taskFields.dependency] !== ganttData.ganttProperties.predecessorsName) {
400
+ this.parent.connectorLineEditModule.updatePredecessor(
401
+ ganttData, data[this.parent.taskFields.dependency]);
402
+ } else {
403
+ const args: ITaskbarEditedEventArgs = {} as ITaskbarEditedEventArgs;
404
+ args.data = ganttData;
405
+ if (this.parent.viewType === 'ResourceView') {
406
+ args.action = 'methodUpdate';
407
+ }
408
+ this.parent.editModule.initiateUpdateAction(args);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ /**
414
+ *
415
+ * @param {object} data .
416
+ * @param {IGanttData} ganttData .
417
+ * @param {boolean} isFromDialog .
418
+ * @returns {void} .
419
+ * @private
420
+ */
421
+ public validateUpdateValues(data: Object, ganttData: IGanttData, isFromDialog?: boolean): void {
422
+ const ganttObj: Gantt = this.parent;
423
+ const tasks: TaskFieldsModel = ganttObj.taskFields;
424
+ const ganttPropByMapping: Object = getSwapKey(ganttObj.columnMapping);
425
+ const scheduleFieldNames: string[] = [];
426
+ let isScheduleValueUpdated: boolean = false;
427
+ for (const key of Object.keys(data)) {
428
+ if ([tasks.startDate, tasks.endDate, tasks.duration].indexOf(key) !== -1) {
429
+ if (isNullOrUndefined(data[key]) && !ganttObj.allowUnscheduledTasks) {
430
+ continue;
431
+ }
432
+ if (isFromDialog) {
433
+ if (tasks.duration === key) {
434
+ ganttObj.dataOperation.updateDurationValue(data[key], ganttData.ganttProperties);
435
+ if (ganttData.ganttProperties.duration > 0 && ganttData.ganttProperties.isMilestone) {
436
+ this.parent.setRecordValue('isMilestone', false, ganttData.ganttProperties, true);
437
+ }
438
+ ganttObj.dataOperation.updateMappingData(ganttData, ganttPropByMapping[key]);
439
+ } else {
440
+ const tempDate: Date = typeof data[key] === 'string' ? new Date(data[key] as string) : data[key];
441
+ ganttObj.setRecordValue(ganttPropByMapping[key], tempDate, ganttData.ganttProperties, true);
442
+ ganttObj.dataOperation.updateMappingData(ganttData, ganttPropByMapping[key]);
443
+ }
444
+ } else {
445
+ scheduleFieldNames.push(key);
446
+ isScheduleValueUpdated = true;
447
+ }
448
+ } else if (tasks.resourceInfo === key) {
449
+ const resourceData: Object[] = ganttObj.dataOperation.setResourceInfo(data);
450
+ if (this.parent.viewType === 'ResourceView') {
451
+ if (JSON.stringify(resourceData) !== JSON.stringify(ganttData.ganttProperties.resourceInfo)) {
452
+ this.parent.editModule.dialogModule.isResourceUpdate = true;
453
+ this.parent.editModule.dialogModule.previousResource = !isNullOrUndefined(ganttData.ganttProperties.resourceInfo) ?
454
+ [...ganttData.ganttProperties.resourceInfo] : [];
455
+ } else {
456
+ this.parent.editModule.dialogModule.isResourceUpdate = false;
457
+ }
458
+ }
459
+ ganttData.ganttProperties.resourceInfo = resourceData;
460
+ ganttObj.dataOperation.updateMappingData(ganttData, 'resourceInfo');
461
+ } else if (tasks.dependency === key) {
462
+ //..
463
+ } else if ([tasks.progress, tasks.notes, tasks.durationUnit, tasks.expandState,
464
+ tasks.milestone, tasks.name, tasks.baselineStartDate,
465
+ tasks.baselineEndDate, tasks.id, tasks.segments].indexOf(key) !== -1) {
466
+ const column: ColumnModel = ganttObj.columnByField[key];
467
+ /* eslint-disable-next-line */
468
+ let value: any = data[key];
469
+ if (!isNullOrUndefined(column) && (column.editType === 'datepickeredit' || column.editType === 'datetimepickeredit')) {
470
+ value = ganttObj.dataOperation.getDateFromFormat(value);
471
+ }
472
+ let ganttPropKey: string = ganttPropByMapping[key];
473
+ if (key === tasks.id) {
474
+ ganttPropKey = 'taskId';
475
+ } else if (key === tasks.name) {
476
+ ganttPropKey = 'taskName';
477
+ } else if (key === tasks.segments) {
478
+ ganttPropKey = 'segments';
479
+ /* eslint-disable-next-line */
480
+ if (data && !isNullOrUndefined(data[this.parent.taskFields.segments]) && data[this.parent.taskFields.segments].length > 0) {
481
+ let totDuration: number = 0;
482
+ for (let i: number = 0; i < ganttData.ganttProperties.segments.length; i++) {
483
+ totDuration = totDuration + ganttData.ganttProperties.segments[i].duration;
484
+ }
485
+ const sdate: Date = ganttData.ganttProperties.startDate;
486
+ /* eslint-disable-next-line */
487
+ const edate: Date = this.parent.dataOperation.getEndDate(sdate, totDuration, ganttData.ganttProperties.durationUnit, ganttData.ganttProperties, false);
488
+ ganttObj.setRecordValue('endDate', ganttObj.dataOperation.getDateFromFormat(edate), ganttData.ganttProperties, true);
489
+ }
490
+ }
491
+ if (!isNullOrUndefined(ganttPropKey)) {
492
+ ganttObj.setRecordValue(ganttPropKey, value, ganttData.ganttProperties, true);
493
+ }
494
+ if ((key === tasks.baselineStartDate || key === tasks.baselineEndDate) &&
495
+ (ganttData.ganttProperties.baselineStartDate && ganttData.ganttProperties.baselineEndDate)) {
496
+ ganttObj.setRecordValue(
497
+ 'baselineLeft', ganttObj.dataOperation.calculateBaselineLeft(
498
+ ganttData.ganttProperties),
499
+ ganttData.ganttProperties, true);
500
+ ganttObj.setRecordValue(
501
+ 'baselineWidth', ganttObj.dataOperation.calculateBaselineWidth(
502
+ ganttData.ganttProperties),
503
+ ganttData.ganttProperties, true);
504
+ }
505
+ ganttObj.setRecordValue('taskData.' + key, value, ganttData);
506
+ /* eslint-disable-next-line */
507
+ if (key === tasks.segments && data && !isNullOrUndefined(data[this.parent.taskFields.segments]) && data[this.parent.taskFields.segments].length > 0) {
508
+ ganttObj.dataOperation.setSegmentsInfo(ganttData, true);
509
+ }
510
+ ganttObj.setRecordValue(key, value, ganttData);
511
+ } else if (tasks.indicators === key) {
512
+ const value: Object[] = data[key];
513
+ ganttObj.setRecordValue('indicators', value, ganttData.ganttProperties, true);
514
+ ganttObj.setRecordValue('taskData.' + key, value, ganttData);
515
+ ganttObj.setRecordValue(key, value, ganttData);
516
+ } else if (tasks.work === key) {
517
+ ganttObj.setRecordValue('work', data[key], ganttData.ganttProperties, true);
518
+ this.parent.dataOperation.updateMappingData(ganttData, 'work');
519
+ this.parent.dataOperation.updateMappingData(ganttData, 'duration');
520
+ this.parent.dataOperation.updateMappingData(ganttData, 'endDate');
521
+ } else if (key === 'taskType') {
522
+ ganttObj.setRecordValue('taskType', data[key], ganttData.ganttProperties, true);
523
+ //this.parent.dataOperation.updateMappingData(ganttData, 'taskType');
524
+ } else if (ganttObj.customColumns.indexOf(key) !== -1) {
525
+ const column: ColumnModel = ganttObj.columnByField[key];
526
+ /* eslint-disable-next-line */
527
+ let value: any = data[key];
528
+ if (isNullOrUndefined(column.edit)) {
529
+ if (column.editType === 'datepickeredit' || column.editType === 'datetimepickeredit') {
530
+ value = ganttObj.dataOperation.getDateFromFormat(value);
531
+ }
532
+ }
533
+ ganttObj.setRecordValue('taskData.' + key, value, ganttData);
534
+ ganttObj.setRecordValue(key, value, ganttData);
535
+ } else if (tasks.manual === key) {
536
+ ganttObj.setRecordValue('isAutoSchedule', !data[key], ganttData.ganttProperties, true);
537
+ this.parent.setRecordValue(key, data[key], ganttData);
538
+ this.updateTaskScheduleModes(ganttData);
539
+ }
540
+ }
541
+ if (isScheduleValueUpdated) {
542
+ this.validateScheduleValues(scheduleFieldNames, ganttData, data);
543
+ }
544
+ }
545
+
546
+ /**
547
+ * To update duration, work, resource unit
548
+ *
549
+ * @param {IGanttData} currentData .
550
+ * @param {string} column .
551
+ * @returns {void} .
552
+ */
553
+ public updateResourceRelatedFields(currentData: IGanttData, column: string): void {
554
+ const ganttProp: ITaskData = currentData.ganttProperties;
555
+ const taskType: string = ganttProp.taskType;
556
+ let isEffectDriven: boolean;
557
+ const isAutoSchedule: boolean = ganttProp.isAutoSchedule;
558
+ if (!isNullOrUndefined(ganttProp.resourceInfo)) {
559
+ if (ganttProp.work > 0 || column === 'work') {
560
+ switch (taskType) {
561
+ case 'FixedUnit':
562
+ if (ganttProp.resourceInfo.length === 0) {
563
+ return;
564
+ }
565
+ else if (isAutoSchedule && ganttProp.resourceInfo.length &&
566
+ (column === 'work' || (column === 'resource'))) {
567
+ this.parent.dataOperation.updateDurationWithWork(currentData);
568
+ } else if (!isAutoSchedule && column === 'work') {
569
+ this.parent.dataOperation.updateUnitWithWork(currentData);
570
+ } else {
571
+ this.parent.dataOperation.updateWorkWithDuration(currentData);
572
+ }
573
+ break;
574
+ case 'FixedWork':
575
+ if (ganttProp.resourceInfo.length === 0) {
576
+ return;
577
+ } else if (isAutoSchedule) {
578
+ if (column === 'duration' || column === 'endDate') {
579
+ this.parent.dataOperation.updateUnitWithWork(currentData);
580
+ if (ganttProp.duration === 0) {
581
+ this.parent.setRecordValue('work', 0, ganttProp, true);
582
+ if (!isNullOrUndefined(this.parent.taskFields.work)) {
583
+ this.parent.dataOperation.updateMappingData(currentData, 'work');
584
+ }
585
+ }
586
+ } else {
587
+ this.parent.dataOperation.updateDurationWithWork(currentData);
588
+ }
589
+ } else {
590
+ if (column === 'work') {
591
+ this.parent.dataOperation.updateUnitWithWork(currentData);
592
+ } else {
593
+ this.parent.dataOperation.updateWorkWithDuration(currentData);
594
+ }
595
+ }
596
+ break;
597
+ case 'FixedDuration':
598
+ if (ganttProp.resourceInfo.length && (column === 'work' || (isAutoSchedule &&
599
+ isEffectDriven && (column === 'resource')))) {
600
+ this.parent.dataOperation.updateUnitWithWork(currentData);
601
+ } else {
602
+ this.parent.dataOperation.updateWorkWithDuration(currentData);
603
+ }
604
+ break;
605
+ }
606
+ } else {
607
+ this.parent.dataOperation.updateWorkWithDuration(currentData);
608
+ }
609
+ }
610
+ }
611
+
612
+ private validateScheduleValues(fieldNames: string[], ganttData: IGanttData, data: Object): void {
613
+ const ganttObj: Gantt = this.parent;
614
+ if (fieldNames.length > 2) {
615
+ ganttObj.dataOperation.calculateScheduledValues(ganttData, data, false);
616
+ } else if (fieldNames.length > 1) {
617
+ this.validateScheduleByTwoValues(data, fieldNames, ganttData);
618
+ } else {
619
+ this.dialogModule.validateScheduleValuesByCurrentField(fieldNames[0], data[fieldNames[0]], ganttData);
620
+ }
621
+ }
622
+ private validateScheduleByTwoValues(data: Object, fieldNames: string[], ganttData: IGanttData): void {
623
+ const ganttObj: Gantt = this.parent; let startDate: Date; let endDate: Date; let duration: string;
624
+ const tasks: TaskFieldsModel = ganttObj.taskFields; const ganttProp: ITaskData = ganttData.ganttProperties;
625
+ const isUnscheduledTask: boolean = ganttObj.allowUnscheduledTasks;
626
+ if (fieldNames.indexOf(tasks.startDate) !== -1) {
627
+ startDate = data[tasks.startDate];
628
+ }
629
+ if (fieldNames.indexOf(tasks.endDate) !== -1) {
630
+ endDate = data[tasks.endDate];
631
+ }
632
+ if (fieldNames.indexOf(tasks.duration) !== -1) {
633
+ duration = data[tasks.duration];
634
+ }
635
+ if (startDate && endDate || (isUnscheduledTask && (fieldNames.indexOf(tasks.startDate) !== -1) &&
636
+ (fieldNames.indexOf(tasks.endDate) !== -1))) {
637
+ ganttObj.setRecordValue('startDate', ganttObj.dataOperation.getDateFromFormat(startDate), ganttProp, true);
638
+ ganttObj.setRecordValue('endDate', ganttObj.dataOperation.getDateFromFormat(endDate), ganttProp, true);
639
+ ganttObj.dataOperation.calculateDuration(ganttData);
640
+ } else if (endDate && duration || (isUnscheduledTask &&
641
+ (fieldNames.indexOf(tasks.endDate) !== -1) && (fieldNames.indexOf(tasks.duration) !== -1))) {
642
+ ganttObj.setRecordValue('endDate', ganttObj.dataOperation.getDateFromFormat(endDate), ganttProp, true);
643
+ ganttObj.dataOperation.updateDurationValue(duration, ganttProp);
644
+ } else if (startDate && duration || (isUnscheduledTask && (fieldNames.indexOf(tasks.startDate) !== -1)
645
+ && (fieldNames.indexOf(tasks.duration) !== -1))) {
646
+ ganttObj.setRecordValue('startDate', ganttObj.dataOperation.getDateFromFormat(startDate), ganttProp, true);
647
+ ganttObj.dataOperation.updateDurationValue(duration, ganttProp);
648
+ }
649
+ }
650
+
651
+ private isTaskbarMoved(data: IGanttData): boolean {
652
+ let isMoved: boolean = false;
653
+ const taskData: ITaskData = data.ganttProperties;
654
+ const prevData: IGanttData = this.parent.previousRecords &&
655
+ this.parent.previousRecords[data.uniqueID];
656
+ if (prevData && prevData.ganttProperties) {
657
+ const prevStart: Date = getValue('ganttProperties.startDate', prevData) as Date;
658
+ const prevEnd: Date = getValue('ganttProperties.endDate', prevData) as Date;
659
+ const prevDuration: number = getValue('ganttProperties.duration', prevData);
660
+ const prevDurationUnit: string = getValue('ganttProperties.durationUnit', prevData);
661
+ const keys: string[] = Object.keys(prevData.ganttProperties);
662
+ if (keys.indexOf('startDate') !== -1 || keys.indexOf('endDate') !== -1 ||
663
+ keys.indexOf('duration') !== -1 || keys.indexOf('durationUnit') !== -1) {
664
+ if ((isNullOrUndefined(prevStart) && !isNullOrUndefined(taskData.startDate)) ||
665
+ (isNullOrUndefined(prevEnd) && !isNullOrUndefined(taskData.endDate)) ||
666
+ (isNullOrUndefined(taskData.startDate) && !isNullOrUndefined(prevStart)) ||
667
+ (isNullOrUndefined(taskData.endDate) && !isNullOrUndefined(prevEnd)) ||
668
+ (prevStart && prevStart.getTime() !== taskData.startDate.getTime())
669
+ || (prevEnd && prevEnd.getTime() !== taskData.endDate.getTime())
670
+ || (!isNullOrUndefined(prevDuration) && prevDuration !== taskData.duration)
671
+ || (!isNullOrUndefined(prevDuration) && prevDuration === taskData.duration &&
672
+ prevDurationUnit !== taskData.durationUnit)) {
673
+ isMoved = true;
674
+ }
675
+ }
676
+ }
677
+ return isMoved;
678
+ }
679
+
680
+ private isPredecessorUpdated(data: IGanttData): boolean {
681
+ let isPredecessorUpdated: boolean = false;
682
+ const prevData: IGanttData = this.parent.previousRecords[data.uniqueID];
683
+ // eslint-disable-next-line
684
+ if (prevData && prevData.ganttProperties && prevData.ganttProperties.hasOwnProperty('predecessor')) {
685
+ if (data.ganttProperties.predecessorsName !== prevData.ganttProperties.predecessorsName) {
686
+ isPredecessorUpdated = true;
687
+ } else {
688
+ this.parent.setRecordValue('predecessor', prevData.ganttProperties.predecessor, data.ganttProperties, true);
689
+ }
690
+ }
691
+ return isPredecessorUpdated;
692
+ }
693
+
694
+ /**
695
+ * Method to check need to open predecessor validate dialog
696
+ *
697
+ * @param {IGanttData} data .
698
+ * @returns {boolean} .
699
+ */
700
+ private isCheckPredecessor(data: IGanttData): boolean {
701
+ let isValidatePredecessor: boolean = false;
702
+ const prevData: IGanttData = this.parent.previousRecords[data.uniqueID];
703
+
704
+ if (prevData && this.parent.taskFields.dependency && this.parent.isInPredecessorValidation &&
705
+ this.parent.predecessorModule.getValidPredecessor(data).length > 0) {
706
+
707
+ if (this.isTaskbarMoved(data)) {
708
+ isValidatePredecessor = true;
709
+ }
710
+ }
711
+ return isValidatePredecessor;
712
+ }
713
+ /**
714
+ * Method to copy the ganttProperties values
715
+ *
716
+ * @param {IGanttData} data .
717
+ * @param {IGanttData} updateData .
718
+ * @returns {void} .
719
+ * @private
720
+ */
721
+ public updateGanttProperties(data: IGanttData, updateData: IGanttData): void {
722
+ const skipProperty: string[] = ['taskId', 'uniqueID', 'rowUniqueID', 'parentId'];
723
+ Object.keys(data.ganttProperties).forEach((property: string) => {
724
+ if (skipProperty.indexOf(property) === -1) {
725
+ updateData.ganttProperties[property] = data.ganttProperties[property];
726
+ }
727
+ });
728
+ }
729
+ /**
730
+ * Method to update all dependent record on edit action
731
+ *
732
+ * @param {ITaskAddedEventArgs} args .
733
+ * @returns {void} .
734
+ * @private
735
+ */
736
+ public initiateUpdateAction(args: ITaskbarEditedEventArgs): void {
737
+ const isValidatePredecessor: boolean = this.isCheckPredecessor(args.data);
738
+ this.taskbarMoved = this.isTaskbarMoved(args.data);
739
+ this.predecessorUpdated = this.isPredecessorUpdated(args.data);
740
+ if (this.predecessorUpdated) {
741
+ this.parent.isConnectorLineUpdate = true;
742
+ this.parent.connectorLineEditModule.addRemovePredecessor(args.data);
743
+ }
744
+ let validateObject: object = {};
745
+ if (isValidatePredecessor) {
746
+ validateObject = this.parent.connectorLineEditModule.validateTypes(args.data);
747
+ this.parent.isConnectorLineUpdate = true;
748
+ if (!isNullOrUndefined(getValue('violationType', validateObject))) {
749
+ const newArgs: IValidateArgs = this.validateTaskEvent(args);
750
+ if (newArgs.validateMode.preserveLinkWithEditing === false &&
751
+ newArgs.validateMode.removeLink === false &&
752
+ newArgs.validateMode.respectLink === false) {
753
+ this.parent.connectorLineEditModule.openValidationDialog(validateObject);
754
+ } else {
755
+ this.parent.connectorLineEditModule.applyPredecessorOption();
756
+ }
757
+ } else {
758
+ this.updateEditedTask(args);
759
+ }
760
+ } else {
761
+ if (this.taskbarMoved) {
762
+ this.parent.isConnectorLineUpdate = true;
763
+ }
764
+ this.updateEditedTask(args);
765
+ }
766
+ }
767
+
768
+ /**
769
+ *
770
+ * @param {ITaskbarEditedEventArgs} editedEventArgs method to trigger validate predecessor link by dialog
771
+ * @returns {IValidateArgs} .
772
+ */
773
+ private validateTaskEvent(editedEventArgs: ITaskbarEditedEventArgs): IValidateArgs {
774
+ const newArgs: IValidateArgs = {};
775
+ this.resetValidateArgs();
776
+ this.parent.currentEditedArgs = newArgs;
777
+ newArgs.cancel = false;
778
+ newArgs.data = editedEventArgs.data;
779
+ newArgs.requestType = 'validateLinkedTask';
780
+ newArgs.validateMode = this.parent.dialogValidateMode;
781
+ newArgs.editEventArgs = editedEventArgs;
782
+ this.parent.actionBeginTask(newArgs);
783
+ return newArgs;
784
+ }
785
+
786
+ private resetValidateArgs(): void {
787
+ this.parent.dialogValidateMode.preserveLinkWithEditing = true;
788
+ this.parent.dialogValidateMode.removeLink = false;
789
+ this.parent.dialogValidateMode.respectLink = false;
790
+ }
791
+
792
+ /**
793
+ *
794
+ * @param {ITaskAddedEventArgs} args - Edited event args like taskbar editing, dialog editing, cell editing
795
+ * @returns {void} .
796
+ * @private
797
+ */
798
+ public updateEditedTask(args: ITaskbarEditedEventArgs): void {
799
+ const ganttRecord: IGanttData = args.data;
800
+ this.updateParentChildRecord(ganttRecord);
801
+ if (this.parent.isConnectorLineUpdate) {
802
+ /* validating predecessor for updated child items */
803
+ for (let i: number = 0; i < this.validatedChildItems.length; i++) {
804
+ const child: IGanttData = this.validatedChildItems[i];
805
+ if (child.ganttProperties.predecessor && child.ganttProperties.predecessor.length > 0) {
806
+ this.parent.editedTaskBarItem = child;
807
+ this.parent.predecessorModule.validatePredecessor(child, [], '');
808
+ }
809
+ }
810
+ /** validating predecessor for current edited records */
811
+ if (ganttRecord.ganttProperties.predecessor) {
812
+ this.parent.isMileStoneEdited = ganttRecord.ganttProperties.isMilestone;
813
+ if (this.taskbarMoved) {
814
+ this.parent.editedTaskBarItem = ganttRecord;
815
+ }
816
+ this.parent.predecessorModule.validatePredecessor(ganttRecord, [], '');
817
+ }
818
+ this.updateParentItemOnEditing();
819
+ }
820
+ /** Update parent up-to zeroth level */
821
+ if (ganttRecord.parentItem ) {
822
+ this.parent.dataOperation.updateParentItems(ganttRecord, true);
823
+ }
824
+ this.initiateSaveAction(args);
825
+ }
826
+
827
+ private updateParentItemOnEditing(): void {
828
+ const childRecord: object[] = getValue('parentRecord', this.parent.predecessorModule);
829
+ for (let i: number = 0; i < childRecord.length; i++) {
830
+ this.parent.dataOperation.updateParentItems(childRecord[i]);
831
+ }
832
+ setValue('parentRecord', [], this.parent.predecessorModule);
833
+ setValue('parentIds', [], this.parent.predecessorModule);
834
+ }
835
+ /**
836
+ * To update parent records while perform drag action.
837
+ *
838
+ * @param {IGanttData} data .
839
+ * @returns {void} .
840
+ * @private
841
+ */
842
+ public updateParentChildRecord(data: IGanttData): void {
843
+ const ganttRecord: IGanttData = data;
844
+ if (ganttRecord.hasChildRecords && this.taskbarMoved && this.parent.taskMode === 'Auto' && (!isNullOrUndefined(this.parent.editModule.cellEditModule) && !this.parent.editModule.cellEditModule.isResourceCellEdited)) {
845
+ this.updateChildItems(ganttRecord);
846
+ }
847
+ if (!isNullOrUndefined(this.parent.editModule.cellEditModule)) {
848
+ this.parent.editModule.cellEditModule.isResourceCellEdited = false;
849
+ }
850
+ }
851
+ /**
852
+ * To update records while changing schedule mode.
853
+ *
854
+ * @param {IGanttData} data .
855
+ * @returns {void} .
856
+ * @private
857
+ */
858
+ public updateTaskScheduleModes(data: IGanttData): void {
859
+ const currentValue: Date = data[this.parent.taskFields.startDate];
860
+ const ganttProp: ITaskData = data.ganttProperties;
861
+ if (data.hasChildRecords && ganttProp.isAutoSchedule) {
862
+ this.parent.setRecordValue('startDate', ganttProp.autoStartDate, ganttProp, true);
863
+ this.parent.setRecordValue('endDate', ganttProp.autoEndDate, ganttProp, true);
864
+ this.parent.setRecordValue('width', this.parent.dataOperation.calculateWidth(data, true), ganttProp, true);
865
+ this.parent.setRecordValue('left', this.parent.dataOperation.calculateLeft(ganttProp, true), ganttProp, true);
866
+ this.parent.setRecordValue(
867
+ 'progressWidth',
868
+ this.parent.dataOperation.getProgressWidth(ganttProp.width, ganttProp.progress),
869
+ ganttProp,
870
+ true
871
+ );
872
+ this.parent.dataOperation.calculateDuration(data);
873
+ } else if (data.hasChildRecords && !ganttProp.isAutoSchedule) {
874
+ this.parent.dataOperation.updateWidthLeft(data);
875
+ this.parent.dataOperation.calculateDuration(data);
876
+ this.parent.setRecordValue('autoStartDate', ganttProp.startDate, ganttProp, true);
877
+ this.parent.setRecordValue('autoEndDate', ganttProp.endDate, ganttProp, true);
878
+ this.parent.setRecordValue('autoDuration', this.parent.dataOperation.calculateAutoDuration(data), ganttProp, true);
879
+ this.parent.dataOperation.updateAutoWidthLeft(data);
880
+ } else {
881
+ const startDate: Date = this.parent.dateValidationModule.checkStartDate(currentValue, data.ganttProperties);
882
+ this.parent.setRecordValue('startDate', startDate, data.ganttProperties, true);
883
+ this.parent.dataOperation.updateMappingData(data, 'startDate');
884
+ this.parent.dateValidationModule.calculateEndDate(data);
885
+ this.parent.setRecordValue(
886
+ 'taskData.' + this.parent.taskFields.manual,
887
+ data[this.parent.taskFields.manual], data);
888
+ this.parent.dataOperation.updateWidthLeft(data);
889
+ }
890
+ }
891
+
892
+ /**
893
+ *
894
+ * @param {IGanttData} data .
895
+ * @param {Date} newStartDate .
896
+ * @returns {void} .
897
+ */
898
+ private calculateDateByRoundOffDuration(data: IGanttData, newStartDate: Date): void {
899
+ const ganttRecord: IGanttData = data;
900
+ const taskData: ITaskData = ganttRecord.ganttProperties;
901
+ const projectStartDate: Date = new Date(newStartDate.getTime());
902
+ if (!isNullOrUndefined(taskData.endDate) && isNullOrUndefined(taskData.startDate)) {
903
+ const endDate: Date = this.parent.dateValidationModule.checkStartDate(projectStartDate, taskData, null);
904
+ this.parent.setRecordValue(
905
+ 'endDate',
906
+ this.parent.dateValidationModule.checkEndDate(endDate, ganttRecord.ganttProperties),
907
+ taskData,
908
+ true);
909
+ } else {
910
+ this.parent.setRecordValue(
911
+ 'startDate',
912
+ this.parent.dateValidationModule.checkStartDate(projectStartDate, taskData, false),
913
+ taskData,
914
+ true);
915
+ if (!isNullOrUndefined(taskData.duration)) {
916
+ this.parent.dateValidationModule.calculateEndDate(ganttRecord);
917
+ }
918
+ }
919
+ this.parent.dataOperation.updateWidthLeft(data);
920
+ this.parent.dataOperation.updateTaskData(ganttRecord);
921
+ }
922
+
923
+ /**
924
+ * To update progress value of parent tasks
925
+ *
926
+ * @param {IParent} cloneParent .
927
+ * @returns {void} .
928
+ * @private
929
+ */
930
+ public updateParentProgress(cloneParent: IParent): void {
931
+ let parentProgress: number = 0;
932
+ const parent: IGanttData = this.parent.getParentTask(cloneParent);
933
+ const childRecords: IGanttData[] = parent.childRecords;
934
+ const childCount: number = childRecords ? childRecords.length : 0;
935
+ let totalProgress: number = 0;
936
+ let milesStoneCount: number = 0;
937
+ let taskCount: number = 0;
938
+ let totalDuration: number = 0;
939
+ let progressValues: Object = {};
940
+ if (childRecords) {
941
+ for (let i: number = 0; i < childCount; i++) {
942
+ if ((!childRecords[i].ganttProperties.isMilestone || childRecords[i].hasChildRecords) &&
943
+ isScheduledTask(childRecords[i].ganttProperties)) {
944
+ progressValues = this.parent.dataOperation.getParentProgress(childRecords[i]);
945
+ totalProgress += getValue('totalProgress', progressValues);
946
+ totalDuration += getValue('totalDuration', progressValues);
947
+ } else {
948
+ milesStoneCount += 1;
949
+ }
950
+ }
951
+ taskCount = childCount - milesStoneCount;
952
+ parentProgress = taskCount > 0 ? Math.round(totalProgress / totalDuration) : 0;
953
+ if (isNaN(parentProgress)) {
954
+ parentProgress = 0;
955
+ }
956
+ this.parent.setRecordValue(
957
+ 'progressWidth',
958
+ this.parent.dataOperation.getProgressWidth(
959
+ parent.ganttProperties.isAutoSchedule ? parent.ganttProperties.width : parent.ganttProperties.autoWidth,
960
+ parentProgress),
961
+ parent.ganttProperties,
962
+ true);
963
+ this.parent.setRecordValue('progress', Math.floor(parentProgress), parent.ganttProperties, true);
964
+ this.parent.setRecordValue('totalProgress', totalProgress, parent.ganttProperties, true);
965
+ this.parent.setRecordValue('totalDuration', totalDuration, parent.ganttProperties, true);
966
+ }
967
+ this.parent.dataOperation.updateTaskData(parent);
968
+ if (parent.parentItem) {
969
+ this.updateParentProgress(parent.parentItem);
970
+ }
971
+ }
972
+
973
+ /**
974
+ * Method to revert cell edit action
975
+ *
976
+ * @param {object} args .
977
+ * @returns {void} .
978
+ * @private
979
+ */
980
+ // eslint-disable-next-line
981
+ public revertCellEdit(args: object): void {
982
+ this.parent.editModule.reUpdatePreviousRecords(false, true);
983
+ this.resetEditProperties();
984
+ }
985
+
986
+ /**
987
+ * @param {boolean} isRefreshChart .
988
+ * @param {boolean} isRefreshGrid .
989
+ * @returns {void} .
990
+ * @private
991
+ */
992
+ public reUpdatePreviousRecords(isRefreshChart?: boolean, isRefreshGrid?: boolean): void {
993
+ const collection: object = this.parent.previousRecords;
994
+ const keys: string[] = Object.keys(collection);
995
+ for (let i: number = 0; i < keys.length; i++) {
996
+ const uniqueId: string = keys[i];
997
+ const prevTask: IGanttData = collection[uniqueId] as IGanttData;
998
+ const originalData: IGanttData = this.parent.getTaskByUniqueID(uniqueId);
999
+ this.copyTaskData(originalData.taskData, prevTask.taskData);
1000
+ delete prevTask.taskData;
1001
+ this.copyTaskData(originalData.ganttProperties, prevTask.ganttProperties);
1002
+ delete prevTask.ganttProperties;
1003
+ this.copyTaskData(originalData, prevTask);
1004
+ const rowIndex: number = this.parent.currentViewData.indexOf(originalData);
1005
+ if (isRefreshChart) {
1006
+ this.parent.chartRowsModule.refreshRow(rowIndex);
1007
+ }
1008
+ if (isRefreshGrid) {
1009
+ const dataId: number | string = this.parent.viewType === 'ProjectView' ? originalData.ganttProperties.taskId : originalData.ganttProperties.rowUniqueID;
1010
+ this.parent.treeGrid.grid.setRowData(dataId, originalData);
1011
+ const row: Row<Column> = this.parent.treeGrid.grid.getRowObjectFromUID(
1012
+ this.parent.treeGrid.grid.getDataRows()[rowIndex].getAttribute('data-uid'));
1013
+ row.data = originalData;
1014
+ }
1015
+ }
1016
+ }
1017
+ /**
1018
+ * Copy previous task data value to edited task data
1019
+ *
1020
+ * @param {object} existing .
1021
+ * @param {object} newValue .
1022
+ * @returns {void} .
1023
+ */
1024
+ private copyTaskData(existing: Object, newValue: object): void {
1025
+ if (!isNullOrUndefined(newValue)) {
1026
+ extend(existing, newValue);
1027
+ }
1028
+ }
1029
+
1030
+ /**
1031
+ * To update schedule date on editing.
1032
+ *
1033
+ * @param {ITaskbarEditedEventArgs} args .
1034
+ * @returns {void} .
1035
+ * @private
1036
+ */
1037
+ // eslint-disable-next-line
1038
+ private updateScheduleDatesOnEditing(args: ITaskbarEditedEventArgs): void {
1039
+ //..
1040
+ }
1041
+
1042
+ /**
1043
+ *
1044
+ * @param {IGanttData} ganttRecord .
1045
+ * @returns {void} .
1046
+ */
1047
+ private updateChildItems(ganttRecord: IGanttData): void {
1048
+ const previousData: IGanttData = this.parent.previousRecords[ganttRecord.uniqueID];
1049
+ let previousStartDate: Date;
1050
+ if (isNullOrUndefined(previousData) ||
1051
+ (isNullOrUndefined(previousData) && !isNullOrUndefined(previousData.ganttProperties))) {
1052
+ previousStartDate = new Date(ganttRecord.ganttProperties.startDate.getTime());
1053
+ } else {
1054
+ previousStartDate = new Date(previousData.ganttProperties.startDate.getTime());
1055
+ }
1056
+ const currentStartDate: Date = ganttRecord.ganttProperties.startDate;
1057
+ const childRecords: IGanttData[] = [];
1058
+ let validStartDate: Date;
1059
+ let validEndDate: Date;
1060
+ let calcEndDate: Date;
1061
+ let isRightMove: boolean;
1062
+ let durationDiff: number;
1063
+ this.getUpdatableChildRecords(ganttRecord, childRecords);
1064
+ if (childRecords.length === 0) {
1065
+ return;
1066
+ }
1067
+ if (previousStartDate.getTime() > currentStartDate.getTime()) {
1068
+ validStartDate = this.parent.dateValidationModule.checkStartDate(currentStartDate);
1069
+ validEndDate = this.parent.dateValidationModule.checkEndDate(previousStartDate, ganttRecord.ganttProperties);
1070
+ isRightMove = false;
1071
+ } else {
1072
+ validStartDate = this.parent.dateValidationModule.checkStartDate(previousStartDate);
1073
+ validEndDate = this.parent.dateValidationModule.checkEndDate(currentStartDate, ganttRecord.ganttProperties);
1074
+ isRightMove = true;
1075
+ }
1076
+ //Get Duration
1077
+ if (validStartDate.getTime() >= validEndDate.getTime()) {
1078
+ durationDiff = 0;
1079
+ } else {
1080
+ durationDiff = this.parent.dateValidationModule.getDuration(validStartDate, validEndDate, 'minute', true, false);
1081
+ }
1082
+ for (let i: number = 0; i < childRecords.length; i++) {
1083
+ if (childRecords[i].ganttProperties.isAutoSchedule) {
1084
+ if (durationDiff > 0) {
1085
+ const startDate: Date = isScheduledTask(childRecords[i].ganttProperties) ?
1086
+ childRecords[i].ganttProperties.startDate : childRecords[i].ganttProperties.startDate ?
1087
+ childRecords[i].ganttProperties.startDate : childRecords[i].ganttProperties.endDate ?
1088
+ childRecords[i].ganttProperties.endDate : new Date(previousStartDate.toString());
1089
+ if (isRightMove) {
1090
+ calcEndDate = this.parent.dateValidationModule.getEndDate(
1091
+ this.parent.dateValidationModule.checkStartDate(
1092
+ startDate,
1093
+ childRecords[i].ganttProperties,
1094
+ childRecords[i].ganttProperties.isMilestone),
1095
+ durationDiff,
1096
+ 'minute',
1097
+ childRecords[i].ganttProperties,
1098
+ false
1099
+ );
1100
+ } else {
1101
+ calcEndDate = this.parent.dateValidationModule.getStartDate(
1102
+ this.parent.dateValidationModule.checkEndDate(startDate, childRecords[i].ganttProperties),
1103
+ durationDiff,
1104
+ 'minute',
1105
+ childRecords[i].ganttProperties);
1106
+ }
1107
+ this.calculateDateByRoundOffDuration(childRecords[i], calcEndDate);
1108
+ if (this.parent.isOnEdit && this.validatedChildItems.indexOf(childRecords[i]) === -1) {
1109
+ this.validatedChildItems.push(childRecords[i]);
1110
+ }
1111
+ } else if (isNullOrUndefined(previousData)) {
1112
+ calcEndDate = previousStartDate;
1113
+ this.calculateDateByRoundOffDuration(childRecords[i], calcEndDate);
1114
+ if (this.parent.isOnEdit && this.validatedChildItems.indexOf(childRecords[i]) === -1) {
1115
+ this.validatedChildItems.push(childRecords[i]);
1116
+ }
1117
+ }
1118
+ }
1119
+ }
1120
+ if (childRecords.length) {
1121
+ this.parent.dataOperation.updateParentItems(ganttRecord, true);
1122
+ }
1123
+ }
1124
+
1125
+ /**
1126
+ * To get updated child records.
1127
+ *
1128
+ * @param {IGanttData} parentRecord .
1129
+ * @param {IGanttData} childLists .
1130
+ * @returns {void} .
1131
+ */
1132
+ private getUpdatableChildRecords(parentRecord: IGanttData, childLists: IGanttData[]): void {
1133
+ const childRecords: IGanttData[] = parentRecord.childRecords;
1134
+ for (let i: number = 0; i < childRecords.length; i++) {
1135
+ if (childRecords[i].ganttProperties.isAutoSchedule) {
1136
+ childLists.push(childRecords[i]);
1137
+ if (childRecords[i].hasChildRecords) {
1138
+ this.getUpdatableChildRecords(childRecords[i], childLists);
1139
+ }
1140
+ }
1141
+ }
1142
+ }
1143
+
1144
+ /**
1145
+ * @param {ITaskbarEditedEventArgs} args .
1146
+ * @returns {void} .
1147
+ * @private
1148
+ */
1149
+ public initiateSaveAction(args: ITaskbarEditedEventArgs): void {
1150
+ this.parent.showSpinner();
1151
+ let eventArgs: IActionBeginEventArgs = {};
1152
+ eventArgs.requestType = 'beforeSave';
1153
+ eventArgs.data = args.data;
1154
+ eventArgs.cancel = false;
1155
+ eventArgs.modifiedRecords = this.parent.editedRecords;
1156
+ if (!isNullOrUndefined(args.target)) {
1157
+ eventArgs.target = args.target;
1158
+ }
1159
+ eventArgs.modifiedTaskData = getTaskData(this.parent.editedRecords, true);
1160
+ if (args.action && args.action === 'DrawConnectorLine') {
1161
+ eventArgs.action = 'DrawConnectorLine';
1162
+ }
1163
+ this.parent.trigger('actionBegin', eventArgs, (eventArg: IActionBeginEventArgs) => {
1164
+ if (eventArg.cancel) {
1165
+ this.reUpdatePreviousRecords();
1166
+ this.parent.chartRowsModule.refreshRecords([args.data]);
1167
+ this.resetEditProperties(eventArgs);
1168
+ // Trigger action complete event with save canceled request type
1169
+ } else {
1170
+ eventArg.modifiedTaskData = getTaskData(eventArg.modifiedRecords, null, null, this.parent);
1171
+ if (isRemoteData(this.parent.dataSource)) {
1172
+ const data: DataManager = this.parent.dataSource as DataManager;
1173
+ const updatedData: object = {
1174
+ changedRecords: eventArg.modifiedTaskData
1175
+ };
1176
+ const query: Query = this.parent.query instanceof Query ? this.parent.query : new Query();
1177
+ let crud: Promise<Object> = null;
1178
+ const dataAdaptor: AdaptorOptions = data.adaptor;
1179
+ if (!(dataAdaptor instanceof WebApiAdaptor && dataAdaptor instanceof ODataAdaptor) || data.dataSource.batchUrl) {
1180
+ crud = data.saveChanges(updatedData, this.parent.taskFields.id, null, query) as Promise<Object>;
1181
+ } else {
1182
+ const changedRecords: string = 'changedRecords';
1183
+ crud = data.update(this.parent.taskFields.id, updatedData[changedRecords], null, query) as Promise<Object>;
1184
+ }
1185
+ crud.then((e: ReturnType) => this.dmSuccess(e, args))
1186
+ .catch((e: { result: Object[] }) => this.dmFailure(e as { result: Object[] }, args));
1187
+ } else {
1188
+ this.saveSuccess(args);
1189
+ }
1190
+ }
1191
+ });
1192
+ }
1193
+
1194
+ private dmSuccess(e: ReturnType, args: ITaskbarEditedEventArgs): void {
1195
+ this.saveSuccess(args);
1196
+ }
1197
+
1198
+ private dmFailure(e: { result: Object[] }, args: ITaskbarEditedEventArgs): void {// eslint-disable-line
1199
+ if (this.deletedTaskDetails.length) {
1200
+ const deleteRecords: IGanttData[] = this.deletedTaskDetails;
1201
+ for (let d: number = 0; d < deleteRecords.length; d++) {
1202
+ deleteRecords[d].isDelete = false;
1203
+ }
1204
+ this.deletedTaskDetails = [];
1205
+ }
1206
+ this.reUpdatePreviousRecords(true, true);
1207
+ this.resetEditProperties();
1208
+ this.parent.trigger('actionFailure', { error: e });
1209
+ }
1210
+ private updateSharedTask(data: IGanttData): void {
1211
+ const ids: string[] = data.ganttProperties.sharedTaskUniqueIds;
1212
+ for (let i: number = 0; i < ids.length; i++) {
1213
+ const editRecord: IGanttData = this.parent.flatData[this.parent.ids.indexOf(ids[i].toString())];
1214
+ if (editRecord.uniqueID !== data.uniqueID) {
1215
+ this.updateGanttProperties(data, editRecord);
1216
+ this.parent.setRecordValue('taskData', data.taskData, editRecord, true);
1217
+ this.parent.dataOperation.updateTaskData(editRecord);
1218
+ this.parent.dataOperation.updateResourceName(editRecord);
1219
+ if (!isNullOrUndefined(editRecord.parentItem)) {
1220
+ this.parent.dataOperation.updateParentItems(editRecord.parentItem);
1221
+ }
1222
+ }
1223
+ }
1224
+ }
1225
+ /**
1226
+ * Method for save action success for local and remote data
1227
+ *
1228
+ * @param {ITaskAddedEventArgs} args .
1229
+ * @returns {void} .
1230
+ */
1231
+ private saveSuccess(args: ITaskbarEditedEventArgs): void {
1232
+ const eventArgs: IActionBeginEventArgs = {};
1233
+ if (this.parent.timelineSettings.updateTimescaleView) {
1234
+ const tempArray: IGanttData[] = this.parent.editedRecords;
1235
+ this.parent.timelineModule.updateTimeLineOnEditing([tempArray], args.action);
1236
+ }
1237
+ if (this.parent.viewType === 'ResourceView') {
1238
+ if (args.action === 'TaskbarEditing') {
1239
+ this.updateSharedTask(args.data);
1240
+ } else if (args.action === 'DialogEditing' || args.action === 'CellEditing' || args.action === 'methodUpdate') {
1241
+ if (this.parent.editModule.dialogModule.isResourceUpdate) {
1242
+ /* eslint-disable-next-line */
1243
+ this.updateResoures(this.parent.editModule.dialogModule.previousResource, args.data.ganttProperties.resourceInfo, args.data);
1244
+ this.updateSharedTask(args.data);
1245
+ this.isTreeGridRefresh = true;
1246
+ } else {
1247
+ this.updateSharedTask(args.data);
1248
+ }
1249
+ }
1250
+ // method to update the edited parent records
1251
+ for (let k: number = 0; k < this.updateParentRecords.length; k++) {
1252
+ this.parent.dataOperation.updateParentItems(this.updateParentRecords[k]);
1253
+ }
1254
+ this.updateParentRecords = [];
1255
+ this.parent.editModule.dialogModule.isResourceUpdate = false;
1256
+ this.parent.editModule.dialogModule.previousResource = [];
1257
+ }
1258
+ if (!this.isTreeGridRefresh) {
1259
+ this.parent.chartRowsModule.refreshRecords(this.parent.editedRecords);
1260
+ if (this.parent.isConnectorLineUpdate && !isNullOrUndefined(this.parent.connectorLineEditModule)) {
1261
+ this.parent.updatedConnectorLineCollection = [];
1262
+ this.parent.connectorLineIds = [];
1263
+ this.parent.connectorLineEditModule.refreshEditedRecordConnectorLine(this.parent.editedRecords);
1264
+ this.updateScheduleDatesOnEditing(args);
1265
+ }
1266
+ }
1267
+ if (!this.parent.editSettings.allowTaskbarEditing || (this.parent.editSettings.allowTaskbarEditing &&
1268
+ !this.taskbarEditModule.dependencyCancel)) {
1269
+ eventArgs.requestType = 'save';
1270
+ eventArgs.data = args.data;
1271
+ eventArgs.modifiedRecords = this.parent.editedRecords;
1272
+ eventArgs.modifiedTaskData = getTaskData(this.parent.editedRecords, null, null, this.parent);
1273
+ if (!isNullOrUndefined(args.action)) {
1274
+ setValue('action', args.action, eventArgs);
1275
+ }
1276
+ if (args.action === 'TaskbarEditing') {
1277
+ eventArgs.taskBarEditAction = args.taskBarEditAction;
1278
+ }
1279
+ this.endEditAction(args);
1280
+ this.parent.trigger('actionComplete', eventArgs);
1281
+ } else {
1282
+ this.taskbarEditModule.dependencyCancel = false;
1283
+ this.resetEditProperties();
1284
+ }
1285
+ if (this.parent.viewType === 'ResourceView' && this.isTreeGridRefresh) {
1286
+ this.parent.treeGrid.parentData = [];
1287
+ this.parent.treeGrid.refresh();
1288
+ this.isTreeGridRefresh = false;
1289
+ }
1290
+ }
1291
+
1292
+ private updateResoures(prevResource: Object[], currentResource: Object[], updateRecord: IGanttData): void {
1293
+ const flatRecords: IGanttData[] = this.parent.flatData;
1294
+ const currentLength: number = currentResource ? currentResource.length : 0;
1295
+ const previousLength: number = prevResource ? prevResource.length : 0;
1296
+ if (currentLength === 0 && previousLength === 0) {
1297
+ return;
1298
+ }
1299
+ for (let index: number = 0; index < currentLength; index++) {
1300
+ const recordIndex: number[] = [];
1301
+ const resourceID: number = parseInt(currentResource[index][this.parent.resourceFields.id], 10);
1302
+ for (let i: number = 0; i < prevResource.length; i++) {
1303
+ if (parseInt(prevResource[i][this.parent.resourceFields.id], 10) === resourceID) {
1304
+ recordIndex.push(i);
1305
+ break;
1306
+ }
1307
+ }
1308
+ if (recordIndex.length === 0) {
1309
+ const parentRecord: IGanttData = flatRecords[this.parent.getTaskIds().indexOf('R' + resourceID)];
1310
+ if (parentRecord) {
1311
+ this.addNewRecord(updateRecord, parentRecord);
1312
+ }
1313
+ } else {
1314
+ prevResource.splice(parseInt(recordIndex[0].toString(), 10), 1);
1315
+ }
1316
+ }
1317
+ const prevLength: number = prevResource ? prevResource.length : 0;
1318
+ for (let index: number = 0; index < prevLength; index++) {
1319
+ const taskID: string = updateRecord.ganttProperties.taskId;
1320
+ const resourceID: string = prevResource[index][this.parent.resourceFields.id];
1321
+ const record: IGanttData = flatRecords[this.parent.getTaskIds().indexOf('R' + resourceID)];
1322
+ for (let j: number = 0; j < record.childRecords.length; j++) {
1323
+ if (record.childRecords[j].ganttProperties.taskId === taskID) {
1324
+ this.removeChildRecord(record.childRecords[j]);
1325
+ }
1326
+ }
1327
+ }
1328
+ if (currentLength > 0) {
1329
+ const parentTask: IGanttData = this.parent.getParentTask(updateRecord.parentItem);
1330
+ if (parentTask) {
1331
+ if (parentTask.ganttProperties.taskName === this.parent.localeObj.getConstant('unassignedTask')) {
1332
+ this.removeChildRecord(updateRecord);
1333
+ }
1334
+ }
1335
+ }
1336
+ //Assign resource to unassigned task
1337
+ if (currentLength === 0) {
1338
+ this.checkWithUnassignedTask(updateRecord);
1339
+ }
1340
+ }
1341
+ /**
1342
+ * @param {IGanttData} updateRecord .
1343
+ * @returns {void} .
1344
+ * @private
1345
+ */
1346
+ public checkWithUnassignedTask(updateRecord: IGanttData): void {
1347
+ let unassignedTasks: IGanttData = null;
1348
+ // Block for check the unassigned task.
1349
+ for (let i: number = 0; i < this.parent.flatData.length; i++) {
1350
+ if (this.parent.flatData[i].ganttProperties.taskName === this.parent.localeObj.getConstant('unassignedTask')) {
1351
+ unassignedTasks = this.parent.flatData[i];
1352
+ }
1353
+ }
1354
+ if (!isNullOrUndefined(unassignedTasks)) {
1355
+ this.addNewRecord(updateRecord, unassignedTasks);
1356
+ } else {
1357
+ // Block for create the unassigned task.
1358
+ const unassignTaskObj: Object = {};
1359
+ unassignTaskObj[this.parent.taskFields.id] = 0;
1360
+ unassignTaskObj[this.parent.taskFields.name] = this.parent.localeObj.getConstant('unassignedTask');
1361
+ const beforeEditStatus: boolean = this.parent.isOnEdit;
1362
+ this.parent.isOnEdit = false;
1363
+ const cAddedRecord: IGanttData = this.parent.dataOperation.createRecord(unassignTaskObj, 0);
1364
+ this.parent.isOnEdit = beforeEditStatus;
1365
+ this.addRecordAsBottom(cAddedRecord);
1366
+ const parentRecord: IGanttData = this.parent.flatData[this.parent.flatData.length - 1];
1367
+ this.addNewRecord(updateRecord, parentRecord);
1368
+ }
1369
+ }
1370
+
1371
+ private addRecordAsBottom(cAddedRecord: IGanttData): void {
1372
+ const recordIndex1: number = this.parent.flatData.length;
1373
+ this.parent.currentViewData.splice(recordIndex1 + 1, 0, cAddedRecord);
1374
+ this.parent.flatData.splice(recordIndex1 + 1, 0, cAddedRecord);
1375
+ this.parent.ids.splice(recordIndex1 + 1, 0, cAddedRecord.ganttProperties.rowUniqueID.toString());
1376
+ const taskId: string = cAddedRecord.level === 0 ? 'R' + cAddedRecord.ganttProperties.taskId : 'T' + cAddedRecord.ganttProperties.taskId;
1377
+ this.parent.getTaskIds().splice(recordIndex1 + 1, 0, taskId);
1378
+ this.updateTreeGridUniqueID(cAddedRecord, 'add');
1379
+ }
1380
+
1381
+ private addNewRecord(updateRecord: IGanttData, parentRecord: IGanttData): void {
1382
+ let cAddedRecord: IGanttData = null;
1383
+ cAddedRecord = extend({}, {}, updateRecord, true);
1384
+ this.parent.setRecordValue('uniqueID', getUid(this.parent.element.id + '_data_'), cAddedRecord);
1385
+ this.parent.setRecordValue('uniqueID', cAddedRecord.uniqueID, cAddedRecord.ganttProperties, true);
1386
+ const uniqueId: string = cAddedRecord.uniqueID.replace(this.parent.element.id + '_data_', '');
1387
+ this.parent.setRecordValue('rowUniqueID', uniqueId, cAddedRecord);
1388
+ this.parent.setRecordValue('rowUniqueID', uniqueId, cAddedRecord.ganttProperties, true);
1389
+ this.parent.setRecordValue('level', 1, cAddedRecord);
1390
+ if (this.parent.taskFields.parentID) {
1391
+ this.parent.setRecordValue('parentId', parentRecord.ganttProperties.taskId, cAddedRecord.ganttProperties, true);
1392
+ }
1393
+ this.parent.setRecordValue('parentItem', this.parent.dataOperation.getCloneParent(parentRecord), cAddedRecord);
1394
+ const parentUniqId: string = cAddedRecord.parentItem ? cAddedRecord.parentItem.uniqueID : null;
1395
+ this.parent.setRecordValue('parentUniqueID', parentUniqId, cAddedRecord);
1396
+ updateRecord.ganttProperties.sharedTaskUniqueIds.push(uniqueId);
1397
+ cAddedRecord.ganttProperties.sharedTaskUniqueIds = updateRecord.ganttProperties.sharedTaskUniqueIds;
1398
+ this.addRecordAsChild(parentRecord, cAddedRecord);
1399
+ }
1400
+ private removeChildRecord(record: IGanttData): void {
1401
+ const gObj: Gantt = this.parent;
1402
+ let data: IGanttData[] = [];
1403
+ if (this.parent.dataSource instanceof DataManager && this.parent.dataSource.dataSource.json.length > 0) {
1404
+ data = this.parent.dataSource.dataSource.json;
1405
+ } else {
1406
+ data = this.parent.currentViewData;
1407
+ }
1408
+ const dataSource: Object = this.parent.dataSource;
1409
+ const deletedRow: IGanttData = record;
1410
+ const flatParentData: IGanttData = this.parent.getParentTask(deletedRow.parentItem);
1411
+ if (deletedRow) {
1412
+ if (deletedRow.parentItem) {
1413
+ const deleteChildRecords: IGanttData[] = flatParentData ? flatParentData.childRecords : [];
1414
+ let childIndex: number = 0;
1415
+ if (deleteChildRecords && deleteChildRecords.length > 0) {
1416
+ if (deleteChildRecords.length === 1) {
1417
+ //For updating the parent record which has no child reords.
1418
+ this.parent.isOnDelete = true;
1419
+ deleteChildRecords[0].isDelete = true;
1420
+ this.parent.dataOperation.updateParentItems(flatParentData);
1421
+ this.parent.isOnDelete = false;
1422
+ deleteChildRecords[0].isDelete = false;
1423
+ }
1424
+ childIndex = deleteChildRecords.indexOf(deletedRow);
1425
+ flatParentData.childRecords.splice(childIndex, 1);
1426
+ // collection for updating parent record
1427
+ this.updateParentRecords.push(flatParentData);
1428
+ }
1429
+ }
1430
+ if (deletedRow.ganttProperties.sharedTaskUniqueIds.length) {
1431
+ const uniqueIDIndex: number =
1432
+ deletedRow.ganttProperties.sharedTaskUniqueIds.indexOf(deletedRow.ganttProperties.rowUniqueID);
1433
+ deletedRow.ganttProperties.sharedTaskUniqueIds.splice(uniqueIDIndex, 1);
1434
+ }
1435
+ this.updateTreeGridUniqueID(deletedRow, 'delete');
1436
+ //method to delete the record from datasource collection
1437
+ if (!this.parent.taskFields.parentID) {
1438
+ const deleteRecordIDs: string[] = [];
1439
+ deleteRecordIDs.push(deletedRow.ganttProperties.rowUniqueID.toString());
1440
+ this.parent.editModule.removeFromDataSource(deleteRecordIDs);
1441
+ }
1442
+ const flatRecordIndex: number = this.parent.flatData.indexOf(deletedRow);
1443
+ if (gObj.taskFields.parentID) {
1444
+ let idx: number;
1445
+ const ganttData: IGanttData[] = this.parent.currentViewData;
1446
+ for (let i: number = 0; i < ganttData.length; i++) {
1447
+ if (ganttData[i].ganttProperties.rowUniqueID === deletedRow.ganttProperties.rowUniqueID) {
1448
+ idx = i;
1449
+ }
1450
+ }
1451
+ if (idx !== -1) {
1452
+ if ((dataSource as IGanttData[]).length > 0) {
1453
+ (dataSource as IGanttData[]).splice(idx, 1);
1454
+ }
1455
+ data.splice(idx, 1);
1456
+ this.parent.flatData.splice(flatRecordIndex, 1);
1457
+ this.parent.ids.splice(flatRecordIndex, 1);
1458
+ this.parent.getTaskIds().splice(flatRecordIndex, 1);
1459
+ }
1460
+ }
1461
+ const recordIndex: number = data.indexOf(deletedRow);
1462
+ if (!gObj.taskFields.parentID) {
1463
+ const deletedRecordCount: number = this.parent.editModule.getChildCount(deletedRow, 0);
1464
+ data.splice(recordIndex, deletedRecordCount + 1);
1465
+ this.parent.flatData.splice(flatRecordIndex, deletedRecordCount + 1);
1466
+ this.parent.ids.splice(flatRecordIndex, deletedRecordCount + 1);
1467
+ this.parent.getTaskIds().splice(flatRecordIndex, deletedRecordCount + 1);
1468
+ }
1469
+ if (deletedRow.parentItem && flatParentData && flatParentData.childRecords && !flatParentData.childRecords.length) {
1470
+ this.parent.setRecordValue('expanded', false, flatParentData);
1471
+ this.parent.setRecordValue('hasChildRecords', false, flatParentData);
1472
+ }
1473
+ }
1474
+ }
1475
+ // Method to add new record after resource edit
1476
+ private addRecordAsChild(droppedRecord: IGanttData, draggedRecord: IGanttData): void {
1477
+ const gObj: Gantt = this.parent;
1478
+ const recordIndex1: number = this.parent.flatData.indexOf(droppedRecord);
1479
+ const childRecords: number = this.parent.editModule.getChildCount(droppedRecord, 0);
1480
+ let childRecordsLength: number;
1481
+ if (!isNullOrUndefined(this.addRowIndex) && this.addRowPosition && droppedRecord.childRecords && this.addRowPosition !== 'Child') {
1482
+ const dropChildRecord: IGanttData = droppedRecord.childRecords[this.addRowIndex];
1483
+ const position: RowPosition = this.addRowPosition === 'Above' || this.addRowPosition === 'Below' ? this.addRowPosition :
1484
+ 'Child';
1485
+ childRecordsLength = dropChildRecord ? this.addRowIndex + recordIndex1 + 1 :
1486
+ childRecords + recordIndex1 + 1;
1487
+ childRecordsLength = position === 'Above' ? childRecordsLength : childRecordsLength + 1;
1488
+ } else {
1489
+ childRecordsLength = (isNullOrUndefined(childRecords) ||
1490
+ childRecords === 0) ? recordIndex1 + 1 :
1491
+ childRecords + recordIndex1 + 1;
1492
+ }
1493
+ //this.ganttData.splice(childRecordsLength, 0, this.draggedRecord);
1494
+ this.parent.currentViewData.splice(childRecordsLength, 0, draggedRecord);
1495
+ this.parent.flatData.splice(childRecordsLength, 0, draggedRecord);
1496
+ this.parent.ids.splice(childRecordsLength, 0, draggedRecord.ganttProperties.rowUniqueID.toString());
1497
+ this.updateTreeGridUniqueID(draggedRecord, 'add');
1498
+ const recordId: string = draggedRecord.level === 0 ? 'R' + draggedRecord.ganttProperties.taskId : 'T' + draggedRecord.ganttProperties.taskId;
1499
+ this.parent.getTaskIds().splice(childRecordsLength, 0, recordId);
1500
+ if (!droppedRecord.hasChildRecords) {
1501
+ this.parent.setRecordValue('hasChildRecords', true, droppedRecord);
1502
+ this.parent.setRecordValue('expanded', true, droppedRecord);
1503
+ if (!droppedRecord.childRecords.length) {
1504
+ droppedRecord.childRecords = [];
1505
+ if (!gObj.taskFields.parentID && isNullOrUndefined(droppedRecord.taskData[this.parent.taskFields.child])) {
1506
+ droppedRecord.taskData[this.parent.taskFields.child] = [];
1507
+ }
1508
+ }
1509
+ }
1510
+ droppedRecord.childRecords.splice(droppedRecord.childRecords.length, 0, draggedRecord);
1511
+ if (!isNullOrUndefined(draggedRecord) && !this.parent.taskFields.parentID
1512
+ && !isNullOrUndefined(droppedRecord.taskData[this.parent.taskFields.child])) {
1513
+ droppedRecord.taskData[this.parent.taskFields.child].splice(droppedRecord.childRecords.length, 0, draggedRecord.taskData);
1514
+ }
1515
+
1516
+ if (!isNullOrUndefined(draggedRecord.parentItem)) {
1517
+ //collection to update the parent records
1518
+ this.updateParentRecords.push(droppedRecord);
1519
+ }
1520
+ }
1521
+
1522
+ private resetEditProperties(args?: object): void {
1523
+ this.parent.currentEditedArgs = {};
1524
+ this.resetValidateArgs();
1525
+ this.parent.editedTaskBarItem = null;
1526
+ this.parent.isOnEdit = false;
1527
+ this.validatedChildItems = [];
1528
+ this.parent.isConnectorLineUpdate = false;
1529
+ this.parent.editedTaskBarItem = null;
1530
+ this.taskbarMoved = false;
1531
+ this.predecessorUpdated = false;
1532
+ if (!isNullOrUndefined(this.dialogModule) && (isNullOrUndefined(args) ||
1533
+ (!isNullOrUndefined(args) && args['requestType'] === 'beforeSave' && !args['cancel']))) {
1534
+ if (this.dialogModule.dialog && !this.dialogModule.dialogObj.isDestroyed) {
1535
+ this.dialogModule.dialogObj.hide();
1536
+ }
1537
+ this.dialogModule.dialogClose();
1538
+ }
1539
+ this.parent.hideSpinner();
1540
+ this.parent.initiateEditAction(false);
1541
+ }
1542
+ /**
1543
+ * @param {ITaskAddedEventArgs} args .
1544
+ * @returns {void} .
1545
+ * @private
1546
+ */
1547
+ public endEditAction(args: ITaskbarEditedEventArgs): void {
1548
+ this.resetEditProperties();
1549
+ if (args.action === 'TaskbarEditing') {
1550
+ this.parent.trigger('taskbarEdited', args);
1551
+ } else if (args.action === 'CellEditing') {
1552
+ this.parent.trigger('endEdit', args);
1553
+ } else if (args.action === 'DialogEditing') {
1554
+ if (this.dialogModule.dialog && !this.dialogModule.dialogObj.isDestroyed) {
1555
+ this.dialogModule.dialogObj.hide();
1556
+ }
1557
+ this.dialogModule.dialogClose();
1558
+ }
1559
+ }
1560
+ // eslint-disable-next-line
1561
+ private saveFailed(args: ITaskbarEditedEventArgs): void {
1562
+ this.reUpdatePreviousRecords();
1563
+ this.parent.hideSpinner();
1564
+ //action failure event trigger
1565
+ }
1566
+
1567
+ /**
1568
+ * To render delete confirmation dialog
1569
+ *
1570
+ * @returns {void} .
1571
+ */
1572
+ private renderDeleteConfirmDialog(): void {
1573
+ const dialogObj: Dialog = new Dialog({
1574
+ width: '320px',
1575
+ isModal: true,
1576
+ visible: false,
1577
+ content: this.parent.localeObj.getConstant('confirmDelete'),
1578
+ buttons: [
1579
+ {
1580
+ click: this.confirmDeleteOkButton.bind(this),
1581
+ buttonModel: { content: this.parent.localeObj.getConstant('okText'), isPrimary: true }
1582
+ },
1583
+ {
1584
+ click: this.closeConfirmDialog.bind(this),
1585
+ buttonModel: { content: this.parent.localeObj.getConstant('cancel') }
1586
+ }],
1587
+ target: this.parent.element,
1588
+ animationSettings: { effect: 'None' }
1589
+ });
1590
+ dialogObj.appendTo('#' + this.parent.element.id + '_deleteConfirmDialog');
1591
+ this.confirmDialog = dialogObj;
1592
+ }
1593
+
1594
+ private closeConfirmDialog(): void {
1595
+ this.confirmDialog.hide();
1596
+ }
1597
+
1598
+ private confirmDeleteOkButton(): void {
1599
+ this.deleteSelectedItems();
1600
+ this.confirmDialog.hide();
1601
+ const focussedElement: HTMLElement = this.parent.element.querySelector('.e-treegrid');
1602
+ focussedElement.focus();
1603
+ }
1604
+ /**
1605
+ * @returns {void} .
1606
+ * @private
1607
+ */
1608
+ public startDeleteAction(): void {
1609
+ if (this.parent.editSettings.allowDeleting && !this.parent.readOnly) {
1610
+ if (this.parent.editSettings.showDeleteConfirmDialog) {
1611
+ this.confirmDialog.show();
1612
+ } else {
1613
+ this.deleteSelectedItems();
1614
+ }
1615
+ }
1616
+ }
1617
+ /**
1618
+ *
1619
+ * @param {IGanttData[]} selectedRecords - Defines the deleted records
1620
+ * @returns {void} .
1621
+ * Method to delete the records from resource view Gantt.
1622
+ */
1623
+ private deleteResourceRecords(selectedRecords: IGanttData[]): void {
1624
+ const deleteRecords: IGanttData[] = [];
1625
+ for (let i: number = 0; i < selectedRecords.length; i++) {
1626
+ if (selectedRecords[i].parentItem) {
1627
+ const data: IGanttData = selectedRecords[i];
1628
+ const ids: string[] = data.ganttProperties.sharedTaskUniqueIds;
1629
+ for (let j: number = 0; j < ids.length; j++) {
1630
+ deleteRecords.push(this.parent.flatData[this.parent.ids.indexOf(ids[j].toString())]);
1631
+ }
1632
+ }
1633
+ }
1634
+ this.deleteRow(deleteRecords);
1635
+ }
1636
+
1637
+ private deleteSelectedItems(): void {
1638
+ if (!this.isFromDeleteMethod) {
1639
+ let selectedRecords: IGanttData[] = [];
1640
+ if (this.parent.selectionSettings.mode !== 'Cell') {
1641
+ selectedRecords = this.parent.selectionModule.getSelectedRecords();
1642
+ } else if (this.parent.selectionSettings.mode === 'Cell') {
1643
+ selectedRecords = this.parent.selectionModule.getCellSelectedRecords();
1644
+ }
1645
+ if (this.parent.viewType === 'ResourceView') {
1646
+ this.deleteResourceRecords(selectedRecords);
1647
+ } else {
1648
+ this.deleteRow(selectedRecords);
1649
+ }
1650
+ } else {
1651
+ if (this.targetedRecords.length) {
1652
+ if (this.parent.viewType === 'ResourceView') {
1653
+ this.deleteResourceRecords(this.targetedRecords);
1654
+ } else {
1655
+ this.deleteRow(this.targetedRecords);
1656
+ }
1657
+ }
1658
+ this.isFromDeleteMethod = false;
1659
+ }
1660
+ }
1661
+
1662
+ /**
1663
+ * Method to delete record.
1664
+ *
1665
+ * @param {number | string | number[] | string[] | IGanttData | IGanttData[]} taskDetail - Defines the details of data to delete.
1666
+ * @returns {void} .
1667
+ * @public
1668
+ */
1669
+ public deleteRecord(taskDetail: number | string | number[] | string[] | IGanttData | IGanttData[]): void {
1670
+ this.isFromDeleteMethod = true;
1671
+ const variableType: string = typeof (taskDetail);
1672
+ this.targetedRecords = [];
1673
+ switch (variableType) {
1674
+ case 'number':
1675
+ case 'string':
1676
+ {
1677
+ const taskId: string = taskDetail.toString();
1678
+ if (this.parent.viewType === 'ResourceView') {
1679
+ if (!isNullOrUndefined(taskId) && this.parent.getTaskIds().indexOf('T' + taskId) !== -1) {
1680
+ this.targetedRecords.push(this.parent.flatData[this.parent.getTaskIds().indexOf('T' + taskId)]);
1681
+ }
1682
+ } else {
1683
+ if (!isNullOrUndefined(taskId) && this.parent.ids.indexOf(taskId) !== -1) {
1684
+ this.targetedRecords.push(this.parent.getRecordByID(taskId));
1685
+ }
1686
+ }
1687
+ break;
1688
+ }
1689
+ case 'object':
1690
+ if (!Array.isArray(taskDetail)) {
1691
+ this.targetedRecords.push(taskDetail.valueOf());
1692
+ } else {
1693
+ this.updateTargetedRecords(taskDetail as object[]);
1694
+ }
1695
+ break;
1696
+ default:
1697
+ }
1698
+ this.startDeleteAction();
1699
+ }
1700
+ /**
1701
+ * To update 'targetedRecords collection' from given array collection
1702
+ *
1703
+ * @param {object[]} taskDetailArray .
1704
+ * @returns {void} .
1705
+ */
1706
+ private updateTargetedRecords(taskDetailArray: object[]): void {
1707
+ if (taskDetailArray.length) {
1708
+ const variableType: string = typeof (taskDetailArray[0]);
1709
+ if (variableType === 'object') {
1710
+ this.targetedRecords = taskDetailArray;
1711
+ } else {
1712
+ // Get record from array of task ids
1713
+ for (let i: number = 0; i < taskDetailArray.length; i++) {
1714
+ const id: string = taskDetailArray[i].toString();
1715
+ if (this.parent.viewType === 'ResourceView') {
1716
+ if (!isNullOrUndefined(id) && this.parent.getTaskIds().indexOf('T' + id) !== -1) {
1717
+ this.targetedRecords.push(this.parent.flatData[this.parent.getTaskIds().indexOf('T' + id)]);
1718
+ }
1719
+ } else if (!isNullOrUndefined(id) && this.parent.ids.indexOf(id) !== -1) {
1720
+ this.targetedRecords.push(this.parent.getRecordByID(id));
1721
+ }
1722
+ }
1723
+ }
1724
+ }
1725
+ }
1726
+
1727
+ private deleteRow(tasks: IGanttData[]): void {
1728
+ let rowItems: IGanttData[] = tasks && tasks.length ? tasks :
1729
+ this.parent.selectionModule.getSelectedRecords();
1730
+ this.parent.addDeleteRecord = true;
1731
+ if (rowItems.length) {
1732
+ this.parent.isOnDelete = true;
1733
+ rowItems.forEach((item: IGanttData): void => {
1734
+ item.isDelete = true;
1735
+ });
1736
+ if (this.parent.viewType === 'ResourceView' && !tasks.length) {
1737
+ rowItems = [];
1738
+ }
1739
+ for (let i: number = 0; i < rowItems.length; i++) {
1740
+ const deleteRecord: IGanttData = rowItems[i];
1741
+ if (this.deletedTaskDetails.indexOf(deleteRecord) !== -1) {
1742
+ continue;
1743
+ }
1744
+ if (deleteRecord.parentItem) {
1745
+ const childRecord: IGanttData[] = this.parent.getParentTask(deleteRecord.parentItem).childRecords;
1746
+ const filteredRecord: IGanttData[] = childRecord.length === 1 ?
1747
+ childRecord : childRecord.filter((data: IGanttData): boolean => {
1748
+ return !data.isDelete;
1749
+ });
1750
+ if (filteredRecord.length > 0) {
1751
+ this.parent.dataOperation.updateParentItems(deleteRecord.parentItem);
1752
+ }
1753
+ }
1754
+ const predecessor: IPredecessor[] = deleteRecord.ganttProperties.predecessor;
1755
+ if (predecessor && predecessor.length) {
1756
+ this.removePredecessorOnDelete(deleteRecord);
1757
+ }
1758
+ this.deletedTaskDetails.push(deleteRecord);
1759
+ if (deleteRecord.hasChildRecords) {
1760
+ this.deleteChildRecords(deleteRecord);
1761
+ }
1762
+ }
1763
+ if (this.parent.selectionModule && this.parent.allowSelection) {
1764
+ // clear selection
1765
+ this.parent.selectionModule.clearSelection();
1766
+ }
1767
+ const delereArgs: ITaskDeletedEventArgs = {};
1768
+ delereArgs.deletedRecordCollection = this.deletedTaskDetails;
1769
+ delereArgs.updatedRecordCollection = this.parent.editedRecords;
1770
+ delereArgs.cancel = false;
1771
+ delereArgs.action = 'delete';
1772
+ this.initiateDeleteAction(delereArgs);
1773
+ this.parent.isOnDelete = false;
1774
+ }
1775
+ if (!isNullOrUndefined(this.parent.toolbarModule)) {
1776
+ this.parent.toolbarModule.refreshToolbarItems();
1777
+ }
1778
+ }
1779
+
1780
+ public removePredecessorOnDelete(record: IGanttData): void {
1781
+ const predecessors: IPredecessor[] = record.ganttProperties.predecessor;
1782
+ for (let i: number = 0; i < predecessors.length; i++) {
1783
+ const predecessor: IPredecessor = predecessors[i];
1784
+ const recordId: string = this.parent.viewType === 'ResourceView' ? record.ganttProperties.taskId :
1785
+ record.ganttProperties.rowUniqueID;
1786
+ if (predecessor.from.toString() === recordId.toString()) {
1787
+ const toRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(predecessor.to.toString());
1788
+ if (!isNullOrUndefined(toRecord)) {
1789
+ const toRecordPredcessor: IPredecessor[] = extend([], [], toRecord.ganttProperties.predecessor, true) as IPredecessor[];
1790
+ let index: number;
1791
+ for (let t: number = 0; t < toRecordPredcessor.length; t++) {
1792
+ const toId: string = this.parent.viewType === 'ResourceView' ? toRecord.ganttProperties.taskId :
1793
+ toRecord.ganttProperties.rowUniqueID;
1794
+ if (toRecordPredcessor[t].to.toString() === toId.toString()
1795
+ && toRecordPredcessor[t].from.toString() === recordId.toString()) {
1796
+ index = t;
1797
+ break;
1798
+ }
1799
+ }
1800
+ toRecordPredcessor.splice(index, 1);
1801
+ this.updatePredecessorValues(toRecord, toRecordPredcessor);
1802
+ }
1803
+ } else if (predecessor.to.toString() === recordId.toString()) {
1804
+ const fromRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(predecessor.from.toString());
1805
+ if (!isNullOrUndefined(fromRecord)) {
1806
+ const fromRecordPredcessor: IPredecessor[] = extend(
1807
+ [], [], fromRecord.ganttProperties.predecessor, true) as IPredecessor[];
1808
+ let index: number;
1809
+ for (let t: number = 0; t < fromRecordPredcessor.length; t++) {
1810
+ const fromId: string = this.parent.viewType === 'ResourceView' ? fromRecord.ganttProperties.taskId :
1811
+ fromRecord.ganttProperties.rowUniqueID;
1812
+ if (fromRecordPredcessor[t].from.toString() === fromId.toString()
1813
+ && fromRecordPredcessor[t].to.toString() === recordId.toString()) {
1814
+ index = t;
1815
+ break;
1816
+ }
1817
+ }
1818
+ fromRecordPredcessor.splice(index, 1);
1819
+ this.updatePredecessorValues(fromRecord, fromRecordPredcessor);
1820
+ }
1821
+ }
1822
+ }
1823
+ }
1824
+
1825
+ private updatePredecessorValues(record: IGanttData, predcessorArray: IPredecessor[]): void {
1826
+ this.parent.setRecordValue('predecessor', predcessorArray, record.ganttProperties, true);
1827
+ const predecessorString: string = this.parent.predecessorModule.getPredecessorStringValue(record);
1828
+ this.parent.setRecordValue('predecessorsName', predecessorString, record.ganttProperties, true);
1829
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.dependency, predecessorString, record);
1830
+ this.parent.setRecordValue(this.parent.taskFields.dependency, predecessorString, record);
1831
+ }
1832
+
1833
+ /**
1834
+ * Method to update TaskID of a gantt record
1835
+ *
1836
+ * @param {string | number} currentId .
1837
+ * @param {number | string} newId .
1838
+ * @returns {void} .
1839
+ */
1840
+ public updateTaskId(currentId: string | number, newId: number | string): void {
1841
+ if (!this.parent.readOnly) {
1842
+ const cId: string = typeof currentId === 'number' ? currentId.toString() : currentId;
1843
+ const nId: string = typeof newId === 'number' ? newId.toString() : newId;
1844
+ const ids: string[] = this.parent.ids;
1845
+ if (!isNullOrUndefined(cId) && !isNullOrUndefined(nId)) {
1846
+ const cIndex: number = ids.indexOf(cId);
1847
+ const nIndex: number = ids.indexOf(nId);
1848
+ // return false for invalid taskID
1849
+ if (cIndex === -1 || nIndex > -1) {
1850
+ return;
1851
+ }
1852
+ const thisRecord: IGanttData = this.parent.flatData[cIndex];
1853
+ thisRecord.ganttProperties.taskId = thisRecord.ganttProperties.rowUniqueID = nId;
1854
+ thisRecord.taskData[this.parent.taskFields.id] = nId;
1855
+ thisRecord[this.parent.taskFields.id] = nId;
1856
+ ids[cIndex] = nId;
1857
+ if (thisRecord.hasChildRecords && this.parent.taskFields.parentID) {
1858
+ const childRecords: IGanttData[] = thisRecord.childRecords;
1859
+ for (let count: number = 0; count < childRecords.length; count++) {
1860
+ const childRecord: IGanttData = childRecords[count];
1861
+ childRecord[this.parent.taskFields.parentID] = newId;
1862
+ this.parent.chartRowsModule.refreshRecords([childRecord]);
1863
+ }
1864
+ }
1865
+ if (this.parent.taskFields.dependency && !isNullOrUndefined(thisRecord.ganttProperties.predecessor)) {
1866
+ const predecessors: IPredecessor[] = thisRecord.ganttProperties.predecessor;
1867
+ let currentGanttRecord: IGanttData;
1868
+ for (let i: number = 0; i < predecessors.length; i++) {
1869
+ const predecessor: IPredecessor = predecessors[i];
1870
+ if (predecessor.to === cId) {
1871
+ currentGanttRecord = this.parent.flatData[ids.indexOf(predecessor.from)];
1872
+ } else if (predecessor.from === cId) {
1873
+ currentGanttRecord = this.parent.flatData[ids.indexOf(predecessor.to)];
1874
+ }
1875
+ this.updatePredecessorOnUpdateId(currentGanttRecord, cId, nId);
1876
+ }
1877
+ }
1878
+ this.parent.treeGrid.parentData = [];
1879
+ this.parent.treeGrid.refresh();
1880
+ }
1881
+ }
1882
+ }
1883
+ private updatePredecessorOnUpdateId(currentGanttRecord: IGanttData, cId: string, nId: string): void {
1884
+ if (this.parent.flatData.indexOf(currentGanttRecord) > -1) {
1885
+ const pred: IPredecessor[] = currentGanttRecord.ganttProperties.predecessor;
1886
+ for (let j: number = 0; j < pred.length; j++) {
1887
+ const pre: IPredecessor = pred[j];
1888
+ if (pre.to === cId) {
1889
+ pre.to = nId;
1890
+ } else if (pre.from === cId) {
1891
+ pre.from = nId;
1892
+ }
1893
+ }
1894
+ }
1895
+ this.updatePredecessorValues(currentGanttRecord, currentGanttRecord.ganttProperties.predecessor);
1896
+ }
1897
+
1898
+ private deleteChildRecords(record: IGanttData): void {
1899
+ const childRecords: IGanttData[] = record.childRecords;
1900
+ for (let c: number = 0; c < childRecords.length; c++) {
1901
+ const childRecord: IGanttData = childRecords[c];
1902
+ if (this.deletedTaskDetails.indexOf(childRecord) !== -1) {
1903
+ continue;
1904
+ }
1905
+ const predecessor: IPredecessor[] = childRecord.ganttProperties.predecessor;
1906
+ if (predecessor && predecessor.length) {
1907
+ this.removePredecessorOnDelete(childRecord);
1908
+ }
1909
+ this.deletedTaskDetails.push(childRecord);
1910
+ if (childRecord.hasChildRecords) {
1911
+ this.deleteChildRecords(childRecord);
1912
+ }
1913
+ }
1914
+ }
1915
+
1916
+ public removeFromDataSource(deleteRecordIDs: string[]): void {
1917
+ let dataSource: Object[];
1918
+ if (this.parent.dataSource instanceof DataManager) {
1919
+ dataSource = this.parent.dataSource.dataSource.json;
1920
+ } else {
1921
+ dataSource = this.parent.dataSource as Object[];
1922
+ }
1923
+ this.removeData(dataSource, deleteRecordIDs);
1924
+ this.isBreakLoop = false;
1925
+ }
1926
+ private removeData(dataCollection: Object[], record: string[]): boolean | void {
1927
+ for (let i: number = 0; i < dataCollection.length; i++) {
1928
+ if (this.isBreakLoop) {
1929
+ break;
1930
+ }
1931
+ if (record.indexOf(getValue(this.parent.taskFields.id, dataCollection[i]).toString()) !== -1) {
1932
+ if (dataCollection[i][this.parent.taskFields.child]) {
1933
+ const childRecords: ITaskData[] = dataCollection[i][this.parent.taskFields.child];
1934
+ this.removeData(childRecords, record);
1935
+ }
1936
+ record.splice(record.indexOf(getValue(this.parent.taskFields.id, dataCollection[i]).toString()), 1);
1937
+ dataCollection.splice(i, 1);
1938
+ if (record.length === 0) {
1939
+ this.isBreakLoop = true;
1940
+ break;
1941
+ }
1942
+ } else if (dataCollection[i][this.parent.taskFields.child]) {
1943
+ const childRecords: ITaskData[] = dataCollection[i][this.parent.taskFields.child];
1944
+ this.removeData(childRecords, record);
1945
+ }
1946
+ }
1947
+ }
1948
+ private initiateDeleteAction(args: ITaskDeletedEventArgs): void {
1949
+ this.parent.showSpinner();
1950
+ let eventArgs: IActionBeginEventArgs = {};
1951
+ eventArgs.requestType = 'beforeDelete';
1952
+ eventArgs.data = args.deletedRecordCollection;
1953
+ eventArgs.modifiedRecords = args.updatedRecordCollection;
1954
+ eventArgs.modifiedTaskData = getTaskData(args.updatedRecordCollection, null, null, this.parent);
1955
+ this.parent.trigger('actionBegin', eventArgs, (eventArg: IActionBeginEventArgs) => {
1956
+ if (eventArg.cancel) {
1957
+ const deleteRecords: IGanttData[] = this.deletedTaskDetails;
1958
+ for (let d: number = 0; d < deleteRecords.length; d++) {
1959
+ deleteRecords[d].isDelete = false;
1960
+ }
1961
+ this.deletedTaskDetails = [];
1962
+ this.reUpdatePreviousRecords();
1963
+ this.parent.initiateEditAction(false);
1964
+ this.parent.hideSpinner();
1965
+ } else {
1966
+ if (isRemoteData(this.parent.dataSource)) {
1967
+ const data: DataManager = this.parent.dataSource as DataManager;
1968
+ if (this.parent.timezone) {
1969
+ updateDates(eventArg.modifiedTaskData as IGanttData, this.parent);
1970
+ }
1971
+ const updatedData: object = {
1972
+ deletedRecords: getTaskData(eventArg.data as IGanttData[], null, null, this.parent), // to check
1973
+ changedRecords: eventArg.modifiedTaskData
1974
+ };
1975
+ const adaptor: AdaptorOptions = data.adaptor;
1976
+ const query: Query = this.parent.query instanceof Query ? this.parent.query : new Query();
1977
+ if (!(adaptor instanceof WebApiAdaptor && adaptor instanceof ODataAdaptor) || data.dataSource.batchUrl) {
1978
+ const crud: Promise<Object> = data.saveChanges(updatedData, this.parent.taskFields.id, null, query) as Promise<Object>;
1979
+ crud.then(() => this.deleteSuccess(args))
1980
+ .catch((e: { result: Object[] }) => this.dmFailure(e as { result: Object[] }, args));
1981
+ } else {
1982
+ const deletedRecords: string = 'deletedRecords';
1983
+ let deleteCrud: Promise<Object> = null;
1984
+ for (let i: number = 0; i < updatedData[deletedRecords].length; i++) {
1985
+ deleteCrud = data.remove(this.parent.taskFields.id, updatedData[deletedRecords][i],
1986
+ null, query) as Promise<Object>;
1987
+ }
1988
+ deleteCrud.then(() => {
1989
+ const changedRecords: string = 'changedRecords';
1990
+ const updateCrud: Promise<Object> =
1991
+ data.update(this.parent.taskFields.id, updatedData[changedRecords], null, query) as Promise<Object>;
1992
+ updateCrud.then(() => this.deleteSuccess(args))
1993
+ .catch((e: { result: Object[] }) => this.dmFailure(e as { result: Object[] }, args));
1994
+ }).catch((e: { result: Object[] }) => this.dmFailure(e as { result: Object[] }, args));
1995
+ }
1996
+ } else {
1997
+ this.deleteSuccess(args);
1998
+ }
1999
+ }
2000
+ });
2001
+ }
2002
+
2003
+ private deleteSuccess(args: ITaskDeletedEventArgs): void {
2004
+ const flatData: IGanttData[] = this.parent.flatData;
2005
+ const currentData: IGanttData[] = this.parent.currentViewData;
2006
+ const deletedRecords: IGanttData[] = this.parent.getRecordFromFlatdata(args.deletedRecordCollection);
2007
+ const deleteRecordIDs: string[] = [];
2008
+ if (deletedRecords.length > 0) {
2009
+ this.parent.selectedRowIndex = deletedRecords[deletedRecords.length - 1].index;
2010
+ }
2011
+ for (let i: number = 0; i < deletedRecords.length; i++) {
2012
+ const deleteRecord: IGanttData = deletedRecords[i];
2013
+ const currentIndex: number = currentData.indexOf(deleteRecord);
2014
+ const flatIndex: number = flatData.indexOf(deleteRecord);
2015
+ const treeGridParentIndex: number = this.parent.treeGrid.parentData.indexOf(deleteRecord);
2016
+ const tempData: ITaskData[] = getValue('dataOperation.dataArray', this.parent);
2017
+ const dataIndex: number = tempData.indexOf(deleteRecord.taskData);
2018
+ let childIndex: number;
2019
+ if (currentIndex !== -1) { currentData.splice(currentIndex, 1); }
2020
+ if (flatIndex !== -1) { flatData.splice(flatIndex, 1); }
2021
+ if (dataIndex !== -1) { tempData.splice(dataIndex, 1); }
2022
+ if (!isNullOrUndefined(deleteRecord)) {
2023
+ deleteRecordIDs.push(deleteRecord.ganttProperties.taskId.toString());
2024
+ if (flatIndex !== -1) {
2025
+ this.parent.ids.splice(flatIndex, 1);
2026
+ if (this.parent.viewType === 'ResourceView') {
2027
+ this.parent.getTaskIds().splice(flatIndex, 1);
2028
+ }
2029
+ }
2030
+ if (deleteRecord.level === 0 && treeGridParentIndex !== -1) {
2031
+ this.parent.treeGrid.parentData.splice(treeGridParentIndex, 1);
2032
+ }
2033
+ if (deleteRecord.parentItem) {
2034
+ const parentItem: IGanttData = this.parent.getParentTask(deleteRecord.parentItem);
2035
+ if (parentItem) {
2036
+ const childRecords: IGanttData[] = parentItem.childRecords;
2037
+ childIndex = childRecords.indexOf(deleteRecord);
2038
+ if (childIndex !== -1) { childRecords.splice(childIndex, 1); }
2039
+ if (!childRecords.length) {
2040
+ this.parent.setRecordValue('hasChildRecords', false, parentItem);
2041
+ }
2042
+ }
2043
+ }
2044
+ this.updateTreeGridUniqueID(deleteRecord, 'delete');
2045
+ }
2046
+ }
2047
+ if (deleteRecordIDs.length > 0) {
2048
+ this.removeFromDataSource(deleteRecordIDs);
2049
+ }
2050
+ const eventArgs: IActionBeginEventArgs = {};
2051
+ this.parent.updatedConnectorLineCollection = [];
2052
+ this.parent.connectorLineIds = [];
2053
+ this.parent.predecessorModule.createConnectorLinesCollection(this.parent.flatData);
2054
+ this.parent.treeGrid.parentData = [];
2055
+ this.parent.treeGrid.refresh();
2056
+ if (this.parent.enableImmutableMode) {
2057
+ this.refreshRecordInImmutableMode();
2058
+ }
2059
+ // Trigger actioncomplete event for delete action
2060
+ eventArgs.requestType = 'delete';
2061
+ eventArgs.data = args.deletedRecordCollection;
2062
+ eventArgs.modifiedRecords = args.updatedRecordCollection;
2063
+ eventArgs.modifiedTaskData = getTaskData(args.updatedRecordCollection, null, null, this.parent);
2064
+ setValue('action', args.action, eventArgs);
2065
+ this.parent.trigger('actionComplete', eventArgs);
2066
+ this.deletedTaskDetails = [];
2067
+ this.parent.initiateEditAction(false);
2068
+ this.parent.hideSpinner();
2069
+ }
2070
+
2071
+ /**
2072
+ *
2073
+ * @returns {number | string} .
2074
+ * @private
2075
+ */
2076
+ public getNewTaskId(): number | string {
2077
+ const maxId: number = DataUtil.aggregates.max(this.parent.flatData, this.parent.taskFields.id);
2078
+ if (!isNullOrUndefined(maxId)) {
2079
+ return parseInt(maxId.toString(), 10) + 1;
2080
+ } else {
2081
+ return 1;
2082
+ }
2083
+ }
2084
+
2085
+ /**
2086
+ * @param {object} obj .
2087
+ * @param {RowPosition} rowPosition .
2088
+ * @returns {void} .
2089
+ * @private
2090
+ */
2091
+ // eslint-disable-next-line
2092
+ private prepareNewlyAddedData(obj: Object, rowPosition: RowPosition): void {
2093
+ const taskModel: TaskFieldsModel = this.parent.taskFields;
2094
+ let id: string | number;
2095
+ const ids: string[] = this.parent.ids;
2096
+ /*Validate Task Id of data*/
2097
+ if (obj[taskModel.id]) {
2098
+ if (ids.indexOf(obj[taskModel.id].toString()) !== -1) {
2099
+ obj[taskModel.id] = null;
2100
+ } else {
2101
+ obj[taskModel.id] = isNullOrUndefined(obj[taskModel.id]) ? null : parseInt(obj[taskModel.id], 10);
2102
+ }
2103
+ }
2104
+ if (!obj[taskModel.id]) {
2105
+ id = this.getNewTaskId();
2106
+ obj[taskModel.id] = id;
2107
+ }
2108
+ if (!this.parent.allowUnscheduledTasks && !obj[taskModel.startDate]) {
2109
+ obj[taskModel.startDate] = this.parent.projectStartDate;
2110
+ }
2111
+ if (!this.parent.allowUnscheduledTasks && taskModel.duration && isNullOrUndefined(obj[taskModel.duration])) {
2112
+ if (!obj[taskModel.endDate]) {
2113
+ obj[taskModel.duration] = '5';
2114
+ }
2115
+ }
2116
+ if (taskModel.progress) {
2117
+ obj[taskModel.progress] = obj[taskModel.progress] ? (obj[taskModel.progress] > 100 ? 100 : obj[taskModel.progress]) : 0;
2118
+ }
2119
+ if (!this.parent.allowUnscheduledTasks && !obj[taskModel.endDate] && taskModel.endDate) {
2120
+ if (!obj[taskModel.duration]) {
2121
+ const startDate: Date = this.parent.dataOperation.getDateFromFormat(this.parent.projectStartDate);
2122
+ startDate.setDate(startDate.getDate() + 4);
2123
+ obj[taskModel.endDate] = this.parent.getFormatedDate(startDate, this.parent.getDateFormat());
2124
+ }
2125
+ }
2126
+ }
2127
+
2128
+ /**
2129
+ * @param {object} obj .
2130
+ * @param {number} level .
2131
+ * @param {RowPosition} rowPosition .
2132
+ * @param {IGanttData} parentItem .
2133
+ * @returns {IGanttData} .
2134
+ * @private
2135
+ */
2136
+ private updateNewlyAddedDataBeforeAjax(
2137
+ obj: Object, level: number, rowPosition: RowPosition, parentItem?: IGanttData): IGanttData {
2138
+ const cAddedRecord: IGanttData = this.parent.dataOperation.createRecord(obj, level);
2139
+ cAddedRecord.index = parseInt(cAddedRecord.ganttProperties.rowUniqueID.toString(), 10) - 1;
2140
+ if (!isNullOrUndefined(parentItem)) {
2141
+ this.parent.setRecordValue('parentItem', this.parent.dataOperation.getCloneParent(parentItem), cAddedRecord);
2142
+ const pIndex: number = cAddedRecord.parentItem ? cAddedRecord.parentItem.index : null;
2143
+ this.parent.setRecordValue('parentIndex', pIndex, cAddedRecord);
2144
+ const parentUniqId: string = cAddedRecord.parentItem ? cAddedRecord.parentItem.uniqueID : null;
2145
+ this.parent.setRecordValue('parentUniqueID', parentUniqId, cAddedRecord);
2146
+ if (!isNullOrUndefined(this.parent.taskFields.id) &&
2147
+ !isNullOrUndefined(this.parent.taskFields.parentID) && cAddedRecord.parentItem) {
2148
+ if (this.parent.viewType === 'ProjectView') {
2149
+ this.parent.setRecordValue(
2150
+ this.parent.taskFields.parentID, cAddedRecord.parentItem.taskId, cAddedRecord.taskData, true);
2151
+ }
2152
+ this.parent.setRecordValue('parentId', cAddedRecord.parentItem.taskId, cAddedRecord.ganttProperties, true);
2153
+ this.parent.setRecordValue(this.parent.taskFields.parentID, cAddedRecord.parentItem.taskId, cAddedRecord, true);
2154
+ }
2155
+ }
2156
+ this.parent.isOnEdit = true;
2157
+ this.backUpAndPushNewlyAddedRecord(cAddedRecord, rowPosition, parentItem);
2158
+ // need to push in dataSource also.
2159
+ if (this.parent.taskFields.dependency && cAddedRecord.ganttProperties.predecessorsName) {
2160
+ this.parent.predecessorModule.ensurePredecessorCollectionHelper(cAddedRecord, cAddedRecord.ganttProperties);
2161
+ this.parent.predecessorModule.updatePredecessorHelper(cAddedRecord);
2162
+ this.parent.predecessorModule.validatePredecessorDates(cAddedRecord);
2163
+ }
2164
+ if (cAddedRecord.parentItem && this.parent.getParentTask(cAddedRecord.parentItem).ganttProperties.isAutoSchedule) {
2165
+ this.parent.dataOperation.updateParentItems(cAddedRecord.parentItem);
2166
+ }
2167
+ this.parent.isOnEdit = false;
2168
+ return cAddedRecord;
2169
+ }
2170
+
2171
+ /**
2172
+ * @param {IGanttData} record .
2173
+ * @param {number} count .
2174
+ * @returns {number} .
2175
+ * @private
2176
+ */
2177
+ public getChildCount(record: IGanttData, count: number): number {
2178
+ let currentRecord: IGanttData;
2179
+ if (!record.hasChildRecords) {
2180
+ return 0;
2181
+ }
2182
+ for (let i: number = 0; i < record.childRecords.length; i++) {
2183
+ currentRecord = record.childRecords[i];
2184
+ count++;
2185
+ if (currentRecord.hasChildRecords) {
2186
+ count = this.getChildCount(currentRecord, count);
2187
+ }
2188
+ }
2189
+ return count;
2190
+ }
2191
+
2192
+ /**
2193
+ * @param {IGanttData} data .
2194
+ * @param {number} count .
2195
+ * @param {IGanttData[]} collection .
2196
+ * @returns {number} .
2197
+ * @private
2198
+ */
2199
+ private getVisibleChildRecordCount(data: IGanttData, count: number, collection: IGanttData[]): number {
2200
+ let childRecords: IGanttData[];
2201
+ let length: number;
2202
+ if (data.hasChildRecords) {
2203
+ childRecords = data.childRecords;
2204
+ length = childRecords.length;
2205
+ for (let i: number = 0; i < length; i++) {
2206
+ if (collection.indexOf(childRecords[i]) !== -1) {
2207
+ count++;
2208
+ }
2209
+ if (childRecords[i].hasChildRecords) {
2210
+ count = this.getVisibleChildRecordCount(childRecords[i], count, collection);
2211
+ }
2212
+ }
2213
+ } else {
2214
+ if (collection.indexOf(data) !== -1) {
2215
+ count++;
2216
+ }
2217
+ }
2218
+ return count;
2219
+ }
2220
+
2221
+ /**
2222
+ * @param {IGanttData} parentRecord .
2223
+ * @returns {void} .
2224
+ * @private
2225
+ */
2226
+ public updatePredecessorOnIndentOutdent(parentRecord: IGanttData): void {
2227
+ const len: number = parentRecord.ganttProperties.predecessor.length;
2228
+ const parentRecordTaskData: ITaskData = parentRecord.ganttProperties;
2229
+ const predecessorCollection: IPredecessor[] = parentRecordTaskData.predecessor;
2230
+ let childRecord: IGanttData;
2231
+ let predecessorIndex: number;
2232
+ const updatedPredecessor: IPredecessor[] = [];
2233
+ for (let count: number = 0; count < len; count++) {
2234
+ if (predecessorCollection[count].to === parentRecordTaskData.rowUniqueID.toString()) {
2235
+ childRecord = this.parent.getRecordByID(predecessorCollection[count].from);
2236
+ predecessorIndex = getIndex(predecessorCollection[count], 'from', childRecord.ganttProperties.predecessor, 'to');
2237
+ // eslint-disable-next-line
2238
+ let predecessorCollections: IPredecessor[] = (extend([], childRecord.ganttProperties.predecessor, [], true)) as IPredecessor[];
2239
+ predecessorCollections.splice(predecessorIndex, 1);
2240
+ this.parent.setRecordValue('predecessor', predecessorCollections, childRecord.ganttProperties, true);
2241
+ } else if (predecessorCollection[count].from === parentRecordTaskData.rowUniqueID.toString()) {
2242
+ childRecord = this.parent.getRecordByID(predecessorCollection[count].to);
2243
+ const prdcList: string[] = (childRecord.ganttProperties.predecessorsName.toString()).split(',');
2244
+ const str: string = predecessorCollection[count].from + predecessorCollection[count].type;
2245
+ const ind: number = prdcList.indexOf(str);
2246
+ prdcList.splice(ind, 1);
2247
+ this.parent.setRecordValue('predecessorsName', prdcList.join(','), childRecord.ganttProperties, true);
2248
+ this.parent.setRecordValue(this.parent.taskFields.dependency, prdcList.join(','), childRecord);
2249
+ predecessorIndex = getIndex(predecessorCollection[count], 'from', childRecord.ganttProperties.predecessor, 'to');
2250
+ // eslint-disable-next-line
2251
+ const temppredecessorCollection: IPredecessor[] = (extend([], childRecord.ganttProperties.predecessor, [], true)) as IPredecessor[];
2252
+ temppredecessorCollection.splice(predecessorIndex, 1);
2253
+ this.parent.setRecordValue('predecessor', temppredecessorCollection, childRecord.ganttProperties, true);
2254
+ this.parent.predecessorModule.validatePredecessorDates(childRecord);
2255
+ }
2256
+ }
2257
+ this.parent.setRecordValue('predecessor', updatedPredecessor, parentRecord.ganttProperties, true);
2258
+ this.parent.setRecordValue('predecessorsName', '', parentRecord.ganttProperties, true);
2259
+ }
2260
+
2261
+ /**
2262
+ * @param {IPredecessor[]} predecessorCollection .
2263
+ * @param {IGanttData} record .
2264
+ * @returns {string} .
2265
+ * @private
2266
+ */
2267
+ private predecessorToString(predecessorCollection: IPredecessor[], record: IGanttData): string {
2268
+ const predecessorString: string[] = [];
2269
+ let count: number = 0;
2270
+ const length: number = predecessorCollection.length;
2271
+ for (count; count < length; count++) {
2272
+ if (record.ganttProperties.rowUniqueID.toString() !== predecessorCollection[count].from) {
2273
+ let tem: string = predecessorCollection[count].from + predecessorCollection[count].type;
2274
+ predecessorCollection[count].offset =
2275
+ isNaN(predecessorCollection[count].offset) ? 0 : predecessorCollection[count].offset;
2276
+ if (predecessorCollection[count].offset !== 0) {
2277
+ if (predecessorCollection[count].offset < 0) {
2278
+ tem += predecessorCollection[count].offset.toString() + 'd';
2279
+ } else if (predecessorCollection[count].offset > 0) {
2280
+ tem += '+' + predecessorCollection[count].offset.toString() + 'd';
2281
+ }
2282
+ }
2283
+ predecessorString.push(tem);
2284
+ }
2285
+ }
2286
+ return predecessorString.join(',');
2287
+ }
2288
+
2289
+ /**
2290
+ * @param {IGanttData} record .
2291
+ * @param {RowPosition} rowPosition .
2292
+ * @param {IGanttData} parentItem .
2293
+ * @returns {void} .
2294
+ * @private
2295
+ */
2296
+ private backUpAndPushNewlyAddedRecord(
2297
+ record: IGanttData, rowPosition: RowPosition, parentItem?: IGanttData): void {
2298
+ const flatRecords: IGanttData[] = this.parent.flatData;
2299
+ const currentViewData: IGanttData[] = this.parent.currentViewData;
2300
+ const ids: string[] = this.parent.ids;
2301
+ let currentItemIndex: number;
2302
+ let recordIndex: number;
2303
+ let updatedCollectionIndex: number;
2304
+ let childIndex: number;
2305
+ switch (rowPosition) {
2306
+ case 'Top':
2307
+ flatRecords.splice(0, 0, record);
2308
+ currentViewData.splice(0, 0, record);
2309
+ ids.splice(0, 0, record.ganttProperties.rowUniqueID.toString()); // need to check NAN
2310
+ break;
2311
+ case 'Bottom':
2312
+ flatRecords.push(record);
2313
+ currentViewData.push(record);
2314
+ ids.push(record.ganttProperties.rowUniqueID.toString()); // need to check NAN
2315
+ if (this.parent.viewType === 'ResourceView') {
2316
+ const taskId: string = record.level === 0 ? 'R' + record.ganttProperties.taskId : 'T' + record.ganttProperties.taskId;
2317
+ this.parent.getTaskIds().push(taskId);
2318
+ }
2319
+ break;
2320
+ case 'Above':
2321
+ /*Record Updates*/
2322
+ recordIndex = flatRecords.indexOf(this.addRowSelectedItem);
2323
+ updatedCollectionIndex = currentViewData.indexOf(this.addRowSelectedItem);
2324
+ this.recordCollectionUpdate(childIndex, recordIndex, updatedCollectionIndex, record, parentItem, rowPosition);
2325
+ break;
2326
+ case 'Below':
2327
+ currentItemIndex = flatRecords.indexOf(this.addRowSelectedItem);
2328
+ if (this.addRowSelectedItem.hasChildRecords) {
2329
+ const dataChildCount: number = this.getChildCount(this.addRowSelectedItem, 0);
2330
+ recordIndex = currentItemIndex + dataChildCount + 1;
2331
+ updatedCollectionIndex = currentViewData.indexOf(this.addRowSelectedItem) +
2332
+ this.getVisibleChildRecordCount(this.addRowSelectedItem, 0, currentViewData) + 1;
2333
+ } else {
2334
+ recordIndex = currentItemIndex + 1;
2335
+ updatedCollectionIndex = currentViewData.indexOf(this.addRowSelectedItem) + 1;
2336
+ }
2337
+ this.recordCollectionUpdate(childIndex + 1, recordIndex, updatedCollectionIndex, record, parentItem, rowPosition);
2338
+ break;
2339
+ case 'Child':
2340
+ currentItemIndex = flatRecords.indexOf(this.addRowSelectedItem);
2341
+ if (this.addRowSelectedItem.hasChildRecords) {
2342
+ const dataChildCount: number = this.getChildCount(this.addRowSelectedItem, 0);
2343
+ recordIndex = currentItemIndex + dataChildCount + 1;
2344
+ //Expand Add record's parent item for project view
2345
+ if (!this.addRowSelectedItem.expanded && !this.parent.enableMultiTaskbar) {
2346
+ this.parent.expandByID(Number(this.addRowSelectedItem.ganttProperties.rowUniqueID));
2347
+ }
2348
+ updatedCollectionIndex = currentViewData.indexOf(this.addRowSelectedItem) +
2349
+ this.getVisibleChildRecordCount(this.addRowSelectedItem, 0, currentViewData) + 1;
2350
+ } else {
2351
+ this.parent.setRecordValue('hasChildRecords', true, this.addRowSelectedItem);
2352
+ this.parent.setRecordValue('isMilestone', false, this.addRowSelectedItem.ganttProperties, true);
2353
+ this.parent.setRecordValue('expanded', true, this.addRowSelectedItem);
2354
+ this.parent.setRecordValue('childRecords', [], this.addRowSelectedItem);
2355
+ recordIndex = currentItemIndex + 1;
2356
+ updatedCollectionIndex = currentViewData.indexOf(this.addRowSelectedItem) + 1;
2357
+ if (this.addRowSelectedItem.ganttProperties.predecessor) {
2358
+ this.updatePredecessorOnIndentOutdent(this.addRowSelectedItem);
2359
+ }
2360
+ if (!isNullOrUndefined(this.addRowSelectedItem.ganttProperties.segments)) {
2361
+ this.addRowSelectedItem.ganttProperties.segments = null;
2362
+ }
2363
+ }
2364
+ this.recordCollectionUpdate(childIndex + 1, recordIndex, updatedCollectionIndex, record, parentItem, rowPosition);
2365
+ break;
2366
+ }
2367
+ this.newlyAddedRecordBackup = record;
2368
+ }
2369
+
2370
+ /**
2371
+ * @param {number} childIndex .
2372
+ * @param {number} recordIndex .
2373
+ * @param {number} updatedCollectionIndex .
2374
+ * @param {IGanttData} record .
2375
+ * @param {IGanttData} parentItem .
2376
+ * @returns {void} .
2377
+ * @private
2378
+ */
2379
+ private recordCollectionUpdate(
2380
+ childIndex: number, recordIndex: number, updatedCollectionIndex: number, record: IGanttData, parentItem: IGanttData, rowPosition: RowPosition): void {
2381
+ const flatRecords: IGanttData[] = this.parent.flatData;
2382
+ const currentViewData: IGanttData[] = this.parent.currentViewData;
2383
+ const ids: string[] = this.parent.ids;
2384
+ /* Record collection update */
2385
+ flatRecords.splice(recordIndex, 0, record);
2386
+ currentViewData.splice(updatedCollectionIndex, 0, record);
2387
+ ids.splice(recordIndex, 0, record.ganttProperties.rowUniqueID.toString());
2388
+ if (this.parent.viewType === 'ResourceView') {
2389
+ const taskId: string = record.level === 0 ? 'R' + record.ganttProperties.taskId : 'T' + record.ganttProperties.taskId;
2390
+ this.parent.getTaskIds().splice(recordIndex, 0, taskId);
2391
+ }
2392
+ /* data Source update */
2393
+ if (!isNullOrUndefined(parentItem)) {
2394
+ if (rowPosition == 'Above') {
2395
+ childIndex = parentItem.childRecords.indexOf(this.addRowSelectedItem);
2396
+ } else if(rowPosition == 'Below') {
2397
+ childIndex = parentItem.childRecords.indexOf(this.addRowSelectedItem) + 1;
2398
+ } else {
2399
+ childIndex = parentItem.childRecords.length;
2400
+ }
2401
+ /*Child collection update*/
2402
+ parentItem.childRecords.splice(childIndex, 0, record);
2403
+ if ((this.parent.dataSource instanceof DataManager &&
2404
+ isNullOrUndefined(parentItem.taskData[this.parent.taskFields.parentID])) ||
2405
+ !isNullOrUndefined(this.parent.dataSource)) {
2406
+ const child: string = this.parent.taskFields.child;
2407
+ if (parentItem.taskData[child] && parentItem.taskData[child].length > 0) {
2408
+ if (rowPosition === 'Above' || rowPosition === 'Below') {
2409
+ parentItem.taskData[child].splice(childIndex, 0, record.taskData);
2410
+ }
2411
+ else {
2412
+ parentItem.taskData[child].push(record.taskData);
2413
+ }
2414
+ } else {
2415
+ parentItem.taskData[child] = [];
2416
+ parentItem.taskData[child].push(record.taskData);
2417
+ }
2418
+ }
2419
+ }
2420
+ }
2421
+
2422
+ /**
2423
+ * @param {IGanttData} cAddedRecord .
2424
+ * @param {IGanttData} modifiedRecords .
2425
+ * @param {string} event .
2426
+ * @returns {ITaskAddedEventArgs} .
2427
+ * @private
2428
+ */
2429
+ private constructTaskAddedEventArgs(
2430
+ cAddedRecord: IGanttData[], modifiedRecords: IGanttData[], event: string): ITaskAddedEventArgs {
2431
+ const eventArgs: ITaskAddedEventArgs = {};
2432
+ eventArgs.action = eventArgs.requestType = event;
2433
+ if (cAddedRecord.length > 1) {
2434
+ eventArgs.data = [];
2435
+ eventArgs.newTaskData = [];
2436
+ eventArgs.recordIndex = [];
2437
+ for (let i: number = 0; i < cAddedRecord.length; i++) {
2438
+ (eventArgs.data[i] as IGanttData[]) = (cAddedRecord[i] as IGanttData[]);
2439
+ (eventArgs.newTaskData[i]) = (getTaskData([cAddedRecord[i]], eventArgs.data[i] as boolean, eventArgs, this.parent));
2440
+ eventArgs.recordIndex[i] = cAddedRecord[i].index;
2441
+ }
2442
+ }
2443
+ else if (cAddedRecord.length === 1) {
2444
+ for (let i: number = 0; i < cAddedRecord.length; i++) {
2445
+ (eventArgs.data) = (cAddedRecord[i]);
2446
+ (eventArgs.newTaskData) = (getTaskData([cAddedRecord[i]], eventArgs.data as boolean, eventArgs, this.parent));
2447
+ eventArgs.recordIndex = cAddedRecord[i].index;
2448
+ }
2449
+ }
2450
+
2451
+ eventArgs.modifiedRecords = modifiedRecords;
2452
+ eventArgs.modifiedTaskData = getTaskData(modifiedRecords, null, null, this.parent);
2453
+ return eventArgs;
2454
+ }
2455
+
2456
+ /**
2457
+ * @param {ITaskAddedEventArgs} args .
2458
+ * @returns {void} .
2459
+ * @private
2460
+ */
2461
+ // eslint-disable-next-line
2462
+ private addSuccess(args: ITaskAddedEventArgs): void {
2463
+ // let addedRecords: IGanttData = args.addedRecord;
2464
+ // let eventArgs: IActionBeginEventArgs = {};
2465
+ // this.parent.updatedConnectorLineCollection = [];
2466
+ // this.parent.connectorLineIds = [];
2467
+ // this.parent.predecessorModule.createConnectorLinesCollection(this.parent.flatData);
2468
+ this.parent.treeGrid.parentData = [];
2469
+ this.parent.addDeleteRecord = true;
2470
+ this.parent.selectedRowIndex = 0;
2471
+ this.parent.treeGrid.refresh();
2472
+ if (this.parent.enableImmutableMode) {
2473
+ this.parent.modifiedRecords = args.modifiedRecords;
2474
+ this.parent.modifiedRecords.push(args.data as IGanttData);
2475
+ this.refreshRecordInImmutableMode();
2476
+ }
2477
+ }
2478
+
2479
+ private refreshRecordInImmutableMode(): void {
2480
+ for (let i: number = 0; i < this.parent.modifiedRecords.length; i++) {
2481
+ const originalData: IGanttData = this.parent.modifiedRecords[i];
2482
+ let treeIndex: number = this.parent.allowRowDragAndDrop ? 1 : 0;
2483
+ let uniqueTaskID: string = this.parent.taskFields.id;
2484
+ var originalIndex: number = this.parent.currentViewData.findIndex((data: IGanttData) => {
2485
+ return (data[uniqueTaskID] == originalData[uniqueTaskID]);
2486
+ });
2487
+ if (this.parent.treeGrid.getRows()[originalIndex]) {
2488
+ this.parent.treeGrid.renderModule.cellRender({
2489
+ data: originalData, cell: this.parent.treeGrid.getRows()[originalIndex].cells[this.parent.treeColumnIndex + treeIndex],
2490
+ column: this.parent.treeGrid.grid.getColumns()[this.parent.treeColumnIndex],
2491
+ requestType: 'rowDragAndDrop'
2492
+ });
2493
+ this.parent.treeGrid.renderModule.RowModifier({
2494
+ data: originalData, row: this.parent.treeGrid.getRows()[originalIndex], rowHeight: this.parent.rowHeight
2495
+ });
2496
+ }
2497
+ }
2498
+ }
2499
+ /**
2500
+ * @param {IGanttData} addedRecord .
2501
+ * @param {RowPosition} rowPosition .
2502
+ * @returns {void} .
2503
+ * @private
2504
+ */
2505
+ public updateRealDataSource(addedRecord: IGanttData | IGanttData[], rowPosition: RowPosition): void {
2506
+ const taskFields: TaskFieldsModel = this.parent.taskFields;
2507
+ let dataSource: Object[] = isCountRequired(this.parent) ? getValue('result', this.parent.dataSource) :
2508
+ this.parent.dataSource as Object[];
2509
+ if (this.parent.dataSource instanceof DataManager) {
2510
+ dataSource = this.parent.dataSource.dataSource.json;
2511
+ }
2512
+ for (let i: number = 0; i < (addedRecord as IGanttData[]).length; i++) {
2513
+ if (isNullOrUndefined(rowPosition) || isNullOrUndefined(this.addRowSelectedItem)) {
2514
+ rowPosition = rowPosition === 'Bottom' ? 'Bottom' : 'Top';
2515
+ }
2516
+ if (rowPosition === 'Top') {
2517
+ dataSource.splice(0, 0, addedRecord[i].taskData);
2518
+ } else if (rowPosition === 'Bottom') {
2519
+ dataSource.push(addedRecord[i].taskData);
2520
+ } else {
2521
+ if (!isNullOrUndefined(taskFields.id) && !isNullOrUndefined(taskFields.parentID)) {
2522
+ dataSource.push(addedRecord[i].taskData);
2523
+ } else {
2524
+ this.addDataInRealDataSource(dataSource, addedRecord[i].taskData, rowPosition);
2525
+ }
2526
+ }
2527
+ this.isBreakLoop = false;
2528
+ }
2529
+ }
2530
+
2531
+ /**
2532
+ * @param {object[]} dataCollection .
2533
+ * @param {IGanttData} record .
2534
+ * @param {RowPosition} rowPosition .
2535
+ * @returns {void} .
2536
+ * @private
2537
+ */
2538
+ private addDataInRealDataSource(
2539
+ dataCollection: Object[], record: IGanttData, rowPosition?: RowPosition): boolean | void {
2540
+ for (let i: number = 0; i < dataCollection.length; i++) {
2541
+ const child: string = this.parent.taskFields.child;
2542
+ if (this.isBreakLoop) {
2543
+ break;
2544
+ }
2545
+ if (getValue(
2546
+ this.parent.taskFields.id, dataCollection[i]).toString() ===
2547
+ this.addRowSelectedItem.ganttProperties.rowUniqueID.toString()) {
2548
+ if (rowPosition === 'Above') {
2549
+ dataCollection.splice(i, 0, record);
2550
+ } else if (rowPosition === 'Below') {
2551
+ dataCollection.splice(i + 1, 0, record);
2552
+ } else if (rowPosition === 'Child') {
2553
+ if (dataCollection[i][child] && dataCollection[i][child].length > 0) {
2554
+ dataCollection[i][child].push(record);
2555
+ } else {
2556
+ dataCollection[i][child] = [];
2557
+ dataCollection[i][child].push(record);
2558
+ }
2559
+ }
2560
+ this.isBreakLoop = true;
2561
+ break;
2562
+ } else if (dataCollection[i][child]) {
2563
+ const childRecords: ITaskData[] = dataCollection[i][child];
2564
+ this.addDataInRealDataSource(childRecords, record, rowPosition);
2565
+ }
2566
+ }
2567
+ }
2568
+
2569
+ /**
2570
+ * Method to add new record.
2571
+ *
2572
+ * @param {Object[] | Object} data - Defines the new data to add.
2573
+ * @param {RowPosition} rowPosition - Defines the position of row.
2574
+ * @param {number} rowIndex - Defines the row index.
2575
+ * @returns {void} .
2576
+ * @private
2577
+ */
2578
+ public addRecord(data?: Object[] | Object, rowPosition?: RowPosition, rowIndex?: number): void {
2579
+ if (this.parent.editModule && this.parent.editSettings.allowAdding) {
2580
+ this.parent.isDynamicData = true;
2581
+ const cAddedRecord: IGanttData[] = [];
2582
+ if (isNullOrUndefined(data)) {
2583
+ this.validateTaskPosition(data, rowPosition, rowIndex, cAddedRecord);
2584
+ }
2585
+ else if (data instanceof Array) {
2586
+ for (let i: number = 0; i < data.length; i++) {
2587
+ this.validateTaskPosition(data[i], rowPosition, rowIndex, cAddedRecord);
2588
+ }
2589
+ }
2590
+ else if (typeof (data) == 'object') {
2591
+ this.validateTaskPosition(data, rowPosition, rowIndex, cAddedRecord);
2592
+ }
2593
+ else {
2594
+ return;
2595
+ }
2596
+ let args: ITaskAddedEventArgs = {};
2597
+ args = this.constructTaskAddedEventArgs(cAddedRecord, this.parent.editedRecords, 'beforeAdd');
2598
+ this.parent.showSpinner();
2599
+ this.parent.trigger('actionBegin', args, (args: ITaskAddedEventArgs) => {
2600
+ if (!args.cancel) {
2601
+ if (isRemoteData(this.parent.dataSource)) {
2602
+ const data: DataManager = this.parent.dataSource as DataManager;
2603
+ const updatedData: object = {
2604
+ addedRecords: [args.newTaskData], // to check
2605
+ changedRecords: args.modifiedTaskData
2606
+ };
2607
+ const prevID: string = (args.data as IGanttData).ganttProperties.taskId.toString();
2608
+ /* tslint:disable-next-line */
2609
+ const query: Query = this.parent.query instanceof Query ? this.parent.query : new Query();
2610
+ const adaptor: AdaptorOptions = data.adaptor;
2611
+ if (!(adaptor instanceof WebApiAdaptor && adaptor instanceof ODataAdaptor) || data.dataSource.batchUrl) {
2612
+ /* tslint:disable-next-line */
2613
+ const crud: Promise<Object> =
2614
+ data.saveChanges(updatedData, this.parent.taskFields.id, null, query) as Promise<Object>;
2615
+ crud.then((e: { addedRecords: Object[], changedRecords: Object[] }) => {
2616
+ if (this.parent.taskFields.id && !isNullOrUndefined(e.addedRecords[0][this.parent.taskFields.id]) &&
2617
+ e.addedRecords[0][this.parent.taskFields.id].toString() !== prevID) {
2618
+ this.parent.setRecordValue(
2619
+ 'taskId', e.addedRecords[0][this.parent.taskFields.id], (args.data as IGanttData).ganttProperties, true);
2620
+ this.parent.setRecordValue(
2621
+ 'taskData.' + this.parent.taskFields.id, e.addedRecords[0][this.parent.taskFields.id], args.data as IGanttData);
2622
+ this.parent.setRecordValue(
2623
+ this.parent.taskFields.id, e.addedRecords[0][this.parent.taskFields.id], args.data as IGanttData);
2624
+ this.parent.setRecordValue(
2625
+ 'rowUniqueID', e.addedRecords[0][this.parent.taskFields.id].toString(),
2626
+ (args.data as IGanttData).ganttProperties, true);
2627
+ const idsIndex: number = this.parent.ids.indexOf(prevID);
2628
+ if (idsIndex !== -1) {
2629
+ this.parent.ids[idsIndex] = e.addedRecords[0][this.parent.taskFields.id].toString();
2630
+ }
2631
+ }
2632
+ this.updateNewRecord(cAddedRecord, args);
2633
+ }).catch((e: { result: Object[] }) => {
2634
+ this.removeAddedRecord();
2635
+ this.dmFailure(e as { result: Object[] }, args as ITaskbarEditedEventArgs);
2636
+ this._resetProperties();
2637
+ });
2638
+ } else {
2639
+ const addedRecords: string = 'addedRecords';
2640
+ const insertCrud: Promise<Object> = data.insert(updatedData[addedRecords], null, query) as Promise<Object>;
2641
+ insertCrud.then((e: ReturnType) => {
2642
+ const changedRecords: string = 'changedRecords';
2643
+ const addedRecords: Object = e[0];
2644
+ /* tslint:disable-next-line */
2645
+ const updateCrud: Promise<Object> =
2646
+ data.update(this.parent.taskFields.id, updatedData[changedRecords], null, query) as Promise<Object>;
2647
+ updateCrud.then(() => {
2648
+ if (this.parent.taskFields.id && !isNullOrUndefined(addedRecords[this.parent.taskFields.id]) &&
2649
+ addedRecords[this.parent.taskFields.id].toString() !== prevID) {
2650
+ this.parent.setRecordValue(
2651
+ 'taskId', addedRecords[this.parent.taskFields.id], (args.data as IGanttData).ganttProperties, true);
2652
+ this.parent.setRecordValue(
2653
+ 'taskData.' + this.parent.taskFields.id, addedRecords[this.parent.taskFields.id],
2654
+ (args.data as IGanttData));
2655
+ this.parent.setRecordValue(
2656
+ this.parent.taskFields.id, addedRecords[this.parent.taskFields.id], (args.data as IGanttData));
2657
+ this.parent.setRecordValue(
2658
+ 'rowUniqueID', addedRecords[this.parent.taskFields.id].toString(),
2659
+ (args.data as IGanttData).ganttProperties, true);
2660
+ const idIndex: number = this.parent.ids.indexOf(prevID);
2661
+ if (idIndex !== -1) {
2662
+ this.parent.ids[idIndex] = addedRecords[this.parent.taskFields.id].toString();
2663
+ }
2664
+ }
2665
+ this.updateNewRecord(cAddedRecord, args);
2666
+ }).catch((e: { result: Object[] }) => {
2667
+ this.removeAddedRecord();
2668
+ this.dmFailure(e as { result: Object[] }, args as ITaskbarEditedEventArgs);
2669
+ this._resetProperties();
2670
+ });
2671
+ }).catch((e: { result: Object[] }) => {
2672
+ this.removeAddedRecord();
2673
+ this.dmFailure(e as { result: Object[] }, args as ITaskbarEditedEventArgs);
2674
+ this._resetProperties();
2675
+ });
2676
+ }
2677
+ } else {
2678
+ if (this.parent.viewType === 'ProjectView') {
2679
+ if ((rowPosition === 'Top' || rowPosition === 'Bottom') ||
2680
+ ((rowPosition === 'Above' || rowPosition === 'Below' || rowPosition === 'Child') && !(args.data as IGanttData).parentItem)) {
2681
+ if (args.data instanceof Array) {
2682
+ this.updateRealDataSource(args.data as IGanttData, rowPosition);
2683
+ } else {
2684
+ let data: Object[] = [];
2685
+ data.push(args.data);
2686
+ this.updateRealDataSource(data as IGanttData, rowPosition);
2687
+ }
2688
+ }
2689
+ } else {
2690
+ const dataSource: Object[] = isCountRequired(this.parent) ? getValue('result', this.parent.dataSource) :
2691
+ this.parent.dataSource as Object[]; // eslint-disable-line
2692
+ dataSource.push((args.data as IGanttData).taskData);
2693
+ }
2694
+ if ((cAddedRecord as IGanttData).level === 0) {
2695
+ this.parent.treeGrid.parentData.splice(0, 0, cAddedRecord);
2696
+ }
2697
+ this.updateTreeGridUniqueID(cAddedRecord as IGanttData, 'add');
2698
+ this.refreshNewlyAddedRecord(args, cAddedRecord);
2699
+ this._resetProperties();
2700
+ }
2701
+ } else {
2702
+ args = args;
2703
+ this.removeAddedRecord();
2704
+ this.reUpdatePreviousRecords();
2705
+ this._resetProperties();
2706
+ }
2707
+ });
2708
+ }
2709
+ }
2710
+
2711
+ /**
2712
+ * Method to validateTaskPosition.
2713
+ *
2714
+ * @param {Object | object[] } data - Defines the new data to add.
2715
+ * @param {RowPosition} rowPosition - Defines the position of row.
2716
+ * @param {number} rowIndex - Defines the row index.
2717
+ * @param {IGanttData} cAddedRecord - Defines the single data to validate.
2718
+ * @returns {void} .
2719
+ * @private
2720
+ */
2721
+ public createNewRecord(): IGanttData {
2722
+ const tempRecord: IGanttData = {};
2723
+ const ganttColumns: GanttColumnModel[] = this.parent.ganttColumns;
2724
+ const taskSettingsFields: TaskFieldsModel = this.parent.taskFields;
2725
+ const taskId: number | string = this.parent.editModule.getNewTaskId();
2726
+ for (let i: number = 0; i < ganttColumns.length; i++) {
2727
+ const fieldName: string = ganttColumns[i].field;
2728
+ if (fieldName === taskSettingsFields.id) {
2729
+ tempRecord[fieldName] = taskId;
2730
+ } else if (ganttColumns[i].field === taskSettingsFields.startDate) {
2731
+ if (isNullOrUndefined(tempRecord[taskSettingsFields.endDate])) {
2732
+ tempRecord[fieldName] = this.parent.editModule.dialogModule.getMinimumStartDate();
2733
+ } else {
2734
+ tempRecord[fieldName] = new Date(tempRecord[taskSettingsFields.endDate]);
2735
+ }
2736
+ if (this.parent.timezone) {
2737
+ tempRecord[fieldName] = this.parent.dateValidationModule.remove(tempRecord[fieldName], this.parent.timezone);
2738
+ }
2739
+ } else if (ganttColumns[i].field === taskSettingsFields.endDate) {
2740
+ if (isNullOrUndefined(tempRecord[taskSettingsFields.startDate])) {
2741
+ tempRecord[fieldName] = this.parent.editModule.dialogModule.getMinimumStartDate();
2742
+ } else {
2743
+ tempRecord[fieldName] = new Date(tempRecord[taskSettingsFields.startDate]);
2744
+ }
2745
+ if (this.parent.timezone) {
2746
+ tempRecord[fieldName] = this.parent.dateValidationModule.remove(tempRecord[fieldName], this.parent.timezone);
2747
+ }
2748
+ } else if (ganttColumns[i].field === taskSettingsFields.duration) {
2749
+ tempRecord[fieldName] = 1;
2750
+ } else if (ganttColumns[i].field === taskSettingsFields.name) {
2751
+ tempRecord[fieldName] = this.parent.editModule.dialogModule['localeObj'].getConstant('addDialogTitle')+' '+ taskId;
2752
+ } else if (ganttColumns[i].field === taskSettingsFields.progress) {
2753
+ tempRecord[fieldName] = 0;
2754
+ } else if (ganttColumns[i].field === taskSettingsFields.work) {
2755
+ tempRecord[fieldName] = 0;
2756
+ } else if (ganttColumns[i].field === 'taskType') {
2757
+ tempRecord[fieldName] = this.parent.taskType;
2758
+ } else {
2759
+ tempRecord[this.parent.ganttColumns[i].field] = '';
2760
+ }
2761
+ }
2762
+ return tempRecord;
2763
+ }
2764
+ public validateTaskPosition(data?: Object | object[], rowPosition?: RowPosition, rowIndex?: number, cAddedRecord?: IGanttData[]): void {
2765
+ const selectedRowIndex: number = isNullOrUndefined(rowIndex) || isNaN(parseInt(rowIndex.toString(), 10)) ?
2766
+ this.parent.selectionModule ?
2767
+ (this.parent.selectionSettings.mode === 'Row' || this.parent.selectionSettings.mode === 'Both') &&
2768
+ this.parent.selectionModule.selectedRowIndexes.length === 1 ?
2769
+ this.parent.selectionModule.selectedRowIndexes[0] :
2770
+ this.parent.selectionSettings.mode === 'Cell' &&
2771
+ this.parent.selectionModule.getSelectedRowCellIndexes().length === 1 ?
2772
+ this.parent.selectionModule.getSelectedRowCellIndexes()[0].rowIndex : null : null : rowIndex;
2773
+ this.addRowSelectedItem = isNullOrUndefined(selectedRowIndex) ? null : this.parent.updatedRecords[selectedRowIndex];
2774
+ rowPosition = isNullOrUndefined(rowPosition) ? this.parent.editSettings.newRowPosition : rowPosition;
2775
+ data = isNullOrUndefined(data) ? this.createNewRecord() : data;
2776
+ if (((isNullOrUndefined(selectedRowIndex) || selectedRowIndex < 0 ||
2777
+ isNullOrUndefined(this.addRowSelectedItem)) && (rowPosition === 'Above'
2778
+ || rowPosition === 'Below'
2779
+ || rowPosition === 'Child')) || !rowPosition || (rowPosition !== 'Above'
2780
+ && rowPosition !== 'Below'
2781
+ && rowPosition !== 'Child' && rowPosition !== 'Top' &&
2782
+ rowPosition !== 'Bottom')) {
2783
+ rowPosition = 'Top';
2784
+ }
2785
+ let level: number = 0;
2786
+ let parentItem: IGanttData;
2787
+ switch (rowPosition) {
2788
+ case 'Top':
2789
+ case 'Bottom':
2790
+ if (this.parent.viewType === "ResourceView") {
2791
+ level = 1;
2792
+ } else {
2793
+ level = 0;
2794
+ }
2795
+ break;
2796
+ case 'Above':
2797
+ case 'Below':
2798
+ level = this.addRowSelectedItem.level;
2799
+ parentItem = this.parent.getParentTask(this.addRowSelectedItem.parentItem);
2800
+ break;
2801
+ case 'Child':
2802
+ level = this.addRowSelectedItem.level + 1;
2803
+ parentItem = this.addRowSelectedItem;
2804
+ break;
2805
+ }
2806
+ this.prepareNewlyAddedData(data, rowPosition);
2807
+ const AddRecord: IGanttData = (this.updateNewlyAddedDataBeforeAjax(data, level, rowPosition, parentItem));
2808
+ cAddedRecord.push(AddRecord);
2809
+ }
2810
+
2811
+ private updateNewRecord(cAddedRecord: IGanttData[], args: ITaskAddedEventArgs): void {
2812
+ if ((cAddedRecord as IGanttData).level === 0) {
2813
+ this.parent.treeGrid.parentData.splice(0, 0, cAddedRecord);
2814
+ const tempData: ITaskData[] = getValue('dataOperation.dataArray', this.parent);
2815
+ tempData.splice(0, 0, (cAddedRecord as IGanttData).taskData);
2816
+ }
2817
+ this.updateTreeGridUniqueID(cAddedRecord as IGanttData, 'add');
2818
+ this.refreshNewlyAddedRecord(args, cAddedRecord);
2819
+ this._resetProperties();
2820
+ }
2821
+ /**
2822
+ * Method to reset the flag after adding new record
2823
+ *
2824
+ * @returns {void} .
2825
+ */
2826
+ private _resetProperties(): void {
2827
+ this.parent.isOnEdit = false;
2828
+ this.parent.hideSpinner();
2829
+ this.addRowSelectedItem = null;
2830
+ this.newlyAddedRecordBackup = null;
2831
+ this.isBreakLoop = false;
2832
+ this.parent.element.tabIndex = 0;
2833
+ this.parent.initiateEditAction(false);
2834
+ }
2835
+
2836
+ /**
2837
+ * Method to update unique id collection in TreeGrid
2838
+ *
2839
+ * @param {IGanttData} data .
2840
+ * @param {string} action .
2841
+ * @returns {void} .
2842
+ */
2843
+ private updateTreeGridUniqueID(data: IGanttData, action: string): void {
2844
+ if (action === 'add') {
2845
+ setValue('uniqueIDCollection.' + data.uniqueID, data, this.parent.treeGrid);
2846
+ } else if (action === 'delete') {
2847
+ deleteObject(getValue('uniqueIDCollection', this.parent.treeGrid), data.uniqueID);
2848
+ }
2849
+ }
2850
+
2851
+
2852
+ private refreshNewlyAddedRecord(args: ITaskAddedEventArgs, cAddedRecord: IGanttData[]): void {
2853
+ if (this.parent.selectionModule && this.parent.allowSelection &&
2854
+ (this.parent.selectionSettings.mode === 'Row' || this.parent.selectionSettings.mode === 'Both')) {
2855
+ this.parent.staticSelectedRowIndex = this.parent.currentViewData.indexOf(args.data as IGanttData);
2856
+ }
2857
+ if (this.parent.timelineSettings.updateTimescaleView) {
2858
+ let tempArray: IGanttData[] = [];
2859
+ if (args.modifiedRecords.length > 0) {
2860
+ tempArray = (args.data as IGanttData[]).length > 0 ? args.data as IGanttData[] : [args.data as IGanttData];
2861
+ // eslint-disable-next-line
2862
+ tempArray.push.apply(tempArray, args.modifiedRecords);
2863
+ } else {
2864
+ tempArray = (args.data as IGanttData[]).length > 0 ? args.data as IGanttData[] : [args.data as IGanttData];
2865
+ }
2866
+ this.parent.timelineModule.updateTimeLineOnEditing([tempArray], args.action);
2867
+ }
2868
+ this.addSuccess(args);
2869
+ args = this.constructTaskAddedEventArgs(cAddedRecord, args.modifiedRecords, 'add');
2870
+ if (this.dialogModule.isAddNewResource && !this.parent.isEdit && this.parent.taskFields.work){
2871
+ this.parent.dataOperation.updateWorkWithDuration(cAddedRecord[0]);
2872
+ }
2873
+ this.parent.trigger('actionComplete', args);
2874
+ if (this.dialogModule.dialog && !this.dialogModule.dialogObj.isDestroyed) {
2875
+ this.dialogModule.dialogObj.hide();
2876
+ }
2877
+ this.dialogModule.dialogClose();
2878
+ if (this.parent.viewType === 'ResourceView') {
2879
+ if (cAddedRecord.length > 1) {
2880
+ for (let i: number = 0; i < cAddedRecord.length; i++) {
2881
+ (args.data[i] as IGanttData).ganttProperties.sharedTaskUniqueIds.push((args.data[i] as IGanttData)
2882
+ .ganttProperties.rowUniqueID);
2883
+ if ((args.data[i] as IGanttData).ganttProperties.resourceInfo) {
2884
+ // if ((args.data[i] as IGanttData).ganttProperties.resourceInfo.length > 1) {
2885
+ const resources: Object[] =
2886
+ extend([], [], (args.data[i] as IGanttData).ganttProperties.resourceInfo, true) as Object[];
2887
+ resources.splice(0, 1);
2888
+ this.updateResoures([], resources, args.data[i] as IGanttData);
2889
+ // }
2890
+ }
2891
+ else {
2892
+ this.removeChildRecord(args.data[i] as IGanttData);
2893
+ this.parent.editModule.checkWithUnassignedTask(args.data[i] as IGanttData);
2894
+ }
2895
+ for (let k: number = 0; k < this.updateParentRecords.length; k++) {
2896
+ this.parent.dataOperation.updateParentItems(this.updateParentRecords[k]);
2897
+ }
2898
+ this.updateParentRecords = [];
2899
+ }
2900
+ }
2901
+ else {
2902
+ (args.data as IGanttData).ganttProperties.sharedTaskUniqueIds.push((args.data as IGanttData).ganttProperties.rowUniqueID);
2903
+ // eslint-disable-next-line
2904
+ if ((args.data as IGanttData).ganttProperties.resourceInfo && (args.data as IGanttData).ganttProperties.resourceInfo.length) {
2905
+ if ((args.data as IGanttData).ganttProperties.resourceInfo.length > 1) {
2906
+ // eslint-disable-next-line
2907
+ const resources: Object[] = extend([], [], (args.data as IGanttData).ganttProperties.resourceInfo, true) as Object[];
2908
+ resources.splice(0, 1);
2909
+ this.updateResoures([], resources, args.data as IGanttData);
2910
+ }
2911
+ }
2912
+ else {
2913
+ this.removeChildRecord(args.data as IGanttData);
2914
+ this.parent.editModule.checkWithUnassignedTask(args.data as IGanttData);
2915
+ }
2916
+ for (let k: number = 0; k < this.updateParentRecords.length; k++) {
2917
+ this.parent.dataOperation.updateParentItems(this.updateParentRecords[k]);
2918
+ }
2919
+ this.updateParentRecords = [];
2920
+ }
2921
+ }
2922
+ }
2923
+
2924
+ /**
2925
+ *
2926
+ * @returns {void} .
2927
+ * @private
2928
+ */
2929
+ private removeAddedRecord(): void {
2930
+ const flatRecords: IGanttData[] = this.parent.flatData;
2931
+ const currentViewData: IGanttData[] = this.parent.currentViewData;
2932
+ const ids: string[] = this.parent.ids;
2933
+ const flatRecordsIndex: number = flatRecords.indexOf(this.newlyAddedRecordBackup);
2934
+ const currentViewDataIndex: number = currentViewData.indexOf(this.newlyAddedRecordBackup);
2935
+ const idsIndex: number = ids.indexOf(this.newlyAddedRecordBackup.ganttProperties.rowUniqueID.toString());
2936
+ deleteObject(this.parent.previousRecords, flatRecords[flatRecordsIndex].uniqueID);
2937
+ if (this.newlyAddedRecordBackup.parentItem) {
2938
+ const parentItem: IGanttData = this.parent.getParentTask(this.newlyAddedRecordBackup.parentItem);
2939
+ const parentIndex: number = parentItem.childRecords.indexOf(this.newlyAddedRecordBackup);
2940
+ parentItem.childRecords.splice(parentIndex, 1);
2941
+ }
2942
+ flatRecords.splice(flatRecordsIndex, 1);
2943
+ currentViewData.splice(currentViewDataIndex, 1);
2944
+ ids.splice(idsIndex, 1);
2945
+ }
2946
+ private getPrevRecordIndex(): number {
2947
+ const prevRecord: IGanttData = this.parent.updatedRecords[this.parent.selectionModule.getSelectedRowIndexes()[0] - 1];
2948
+ const selectedRecord: IGanttData = this.parent.selectionModule.getSelectedRecords()[0];
2949
+ const parent: IGanttData = this.parent.getRootParent(prevRecord, selectedRecord.level);
2950
+ const prevIndex: number = this.parent.updatedRecords.indexOf(parent);
2951
+ return prevIndex;
2952
+ }
2953
+ /**
2954
+ * indent a selected record
2955
+ *
2956
+ * @returns {void} .
2957
+ */
2958
+ public indent(): void {
2959
+ const index: number = this.parent.selectedRowIndex;
2960
+ const isSelected: boolean = this.parent.selectionModule ? this.parent.selectionModule.selectedRowIndexes.length === 1 ||
2961
+ this.parent.selectionModule.getSelectedRowCellIndexes().length === 1 ? true : false : false;
2962
+ let dropIndex: number;
2963
+ const prevRecord: IGanttData = this.parent.updatedRecords[this.parent.selectionModule.getSelectedRowIndexes()[0] - 1];
2964
+ const selectedRecord: IGanttData = this.parent.selectionModule.getSelectedRecords()[0];
2965
+ if (!this.parent.editSettings.allowEditing || index === 0 || index === -1 || !isSelected ||
2966
+ this.parent.viewType === 'ResourceView' || this.parent.updatedRecords[index].level - prevRecord.level === 1) {
2967
+ return;
2968
+ } else {
2969
+ if (prevRecord.level - selectedRecord.level === 0) {
2970
+ dropIndex = this.parent.selectionModule.getSelectedRowIndexes()[0] - 1;
2971
+ } else {
2972
+ dropIndex = this.getPrevRecordIndex();
2973
+ }
2974
+ this.indentOutdentRow([this.parent.selectionModule.getSelectedRowIndexes()[0]], dropIndex, 'child');
2975
+ }
2976
+ }
2977
+
2978
+ /**
2979
+ * To perform outdent operation for selected row
2980
+ *
2981
+ * @returns {void} .
2982
+ */
2983
+ public outdent(): void {
2984
+ const index: number = this.parent.selectionModule.getSelectedRowIndexes()[0];
2985
+ let dropIndex: number;
2986
+ const isSelected: boolean = this.parent.selectionModule ? this.parent.selectionModule.selectedRowIndexes.length === 1 ||
2987
+ this.parent.selectionModule.getSelectedRowCellIndexes().length === 1 ? true : false : false;
2988
+ if (!this.parent.editSettings.allowEditing || index === -1 || index === 0 || !isSelected ||
2989
+ this.parent.viewType === 'ResourceView' || this.parent.updatedRecords[index].level === 0) {
2990
+ return;
2991
+ } else {
2992
+ const thisParent: IGanttData = this.parent.getTaskByUniqueID((this.parent.selectionModule.getSelectedRecords()[0] as
2993
+ IGanttData).parentItem.uniqueID);
2994
+ dropIndex = this.parent.updatedRecords.indexOf(thisParent);
2995
+ this.indentOutdentRow([index], dropIndex, 'below');
2996
+ }
2997
+ }
2998
+ private indentOutdentRow(fromIndexes: number[], toIndex: number, pos: string): void {
2999
+ // eslint-disable-next-line
3000
+ if (fromIndexes[0] !== toIndex && pos === 'above' || 'below' || 'child') {
3001
+ if (pos === 'above') {
3002
+ this.dropPosition = 'topSegment';
3003
+ }
3004
+ if (pos === 'below') {
3005
+ this.dropPosition = 'bottomSegment';
3006
+ }
3007
+ if (pos === 'child') {
3008
+ this.dropPosition = 'middleSegment';
3009
+ }
3010
+ let action: string;
3011
+ const record: IGanttData[] = [];
3012
+ for (let i: number = 0; i < fromIndexes.length; i++) {
3013
+ record[i] = this.parent.updatedRecords[fromIndexes[i]];
3014
+ }
3015
+ const isByMethod: boolean = true;
3016
+ const args: RowDropEventArgs = {
3017
+ data: record,
3018
+ dropIndex: toIndex,
3019
+ dropPosition: this.dropPosition
3020
+ };
3021
+ if (this.dropPosition === 'middleSegment') {
3022
+ action = 'indenting';
3023
+ } else if (this.dropPosition === 'bottomSegment') {
3024
+ action = 'outdenting';
3025
+ }
3026
+ const actionArgs: IActionBeginEventArgs = {
3027
+ action : action,
3028
+ data: record[0],
3029
+ cancel: false
3030
+ };
3031
+ this.parent.trigger('actionBegin', actionArgs, (actionArg: IActionBeginEventArgs) => {
3032
+ if (!actionArg.cancel) {
3033
+ this.reArrangeRows(args, isByMethod);
3034
+ } else {
3035
+ return;
3036
+ }
3037
+ });
3038
+ } else {
3039
+ return;
3040
+ }
3041
+ }
3042
+ private reArrangeRows(args: RowDropEventArgs, isByMethod?: boolean): void {
3043
+ this.dropPosition = args.dropPosition;
3044
+ if (args.dropPosition !== 'Invalid' && this.parent.editModule) {
3045
+ const obj: Gantt = this.parent; let draggedRec: IGanttData;
3046
+ this.droppedRecord = obj.updatedRecords[args.dropIndex];
3047
+ let dragRecords: IGanttData[] = [];
3048
+ const droppedRec: IGanttData = this.droppedRecord;
3049
+ if (!args.data[0]) {
3050
+ dragRecords.push(args.data as IGanttData);
3051
+ } else {
3052
+ dragRecords = args.data;
3053
+ }
3054
+ let c: number = 0;
3055
+ const dLength: number = dragRecords.length;
3056
+ for (let i: number = 0; i < dLength; i++) {
3057
+ this.parent.isOnEdit = true;
3058
+ draggedRec = dragRecords[i];
3059
+ this.draggedRecord = draggedRec;
3060
+ if (this.dropPosition !== 'Invalid') {
3061
+ if (isByMethod) {
3062
+ this.deleteDragRow();
3063
+ }
3064
+ const recordIndex1: number = this.treeGridData.indexOf(droppedRec);
3065
+ if (this.dropPosition === 'bottomSegment') {
3066
+ if (!droppedRec.hasChildRecords) {
3067
+ if (this.parent.taskFields.parentID && (this.ganttData as IGanttData[]).length > 0) {
3068
+ (this.ganttData as IGanttData[]).splice(recordIndex1 + 1, 0, this.draggedRecord.taskData);
3069
+ }
3070
+ this.treeGridData.splice(recordIndex1 + 1, 0, this.draggedRecord);
3071
+ this.parent.ids.splice(recordIndex1 + 1, 0, this.draggedRecord.ganttProperties.rowUniqueID.toString());
3072
+ } else {
3073
+ c = this.parent.editModule.getChildCount(droppedRec, 0);
3074
+ if (this.parent.taskFields.parentID && (this.ganttData as IGanttData[]).length > 0) {
3075
+ (this.ganttData as IGanttData[]).splice(recordIndex1 + c + 1, 0, this.draggedRecord.taskData);
3076
+ }
3077
+ this.treeGridData.splice(recordIndex1 + c + 1, 0, this.draggedRecord);
3078
+ this.parent.ids.splice(recordIndex1 + c + 1, 0, this.draggedRecord.ganttProperties.rowUniqueID.toString());
3079
+ const idIndex: number = this.parent.ids.indexOf(this.draggedRecord[this.parent.taskFields.id].toString());
3080
+ if (idIndex !== recordIndex1 + c + 1) {
3081
+ this.parent.ids.splice(idIndex, 1);
3082
+ this.parent.ids.splice(recordIndex1 + c + 1, 0, this.draggedRecord[this.parent.taskFields.id].toString());
3083
+ }
3084
+ }
3085
+ this.parent.setRecordValue('parentItem', this.treeGridData[recordIndex1].parentItem, draggedRec);
3086
+ this.parent.setRecordValue('parentUniqueID', this.treeGridData[recordIndex1].parentUniqueID, draggedRec);
3087
+ this.parent.setRecordValue('level', this.treeGridData[recordIndex1].level, draggedRec);
3088
+ if (draggedRec.hasChildRecords) {
3089
+ const level: number = 1;
3090
+ this.updateChildRecordLevel(draggedRec, level);
3091
+ this.updateChildRecord(draggedRec, recordIndex1 + c + 1);
3092
+ }
3093
+ if (droppedRec.parentItem) {
3094
+ const record: IGanttData[] = this.parent.getParentTask(droppedRec.parentItem).childRecords;
3095
+ const childRecords: IGanttData[] = record;
3096
+ const droppedRecordIndex: number = childRecords.indexOf(droppedRec) + 1;
3097
+ childRecords.splice(droppedRecordIndex, 0, draggedRec);
3098
+ }
3099
+ }
3100
+ if (this.dropPosition === 'middleSegment') {
3101
+ this.dropMiddle(recordIndex1);
3102
+ }
3103
+ if (!isNullOrUndefined(draggedRec.parentItem && this.updateParentRecords.indexOf(draggedRec.parentItem) !== -1)) {
3104
+ this.updateParentRecords.push(draggedRec.parentItem);
3105
+ }
3106
+ }
3107
+ if (isNullOrUndefined(draggedRec.parentItem)) {
3108
+ const parentRecords: ITreeData[] = this.parent.treeGrid.parentData;
3109
+ const newParentIndex: number = parentRecords.indexOf(this.droppedRecord);
3110
+ if (this.dropPosition === 'bottomSegment') {
3111
+ parentRecords.splice(newParentIndex + 1, 0, draggedRec);
3112
+ }
3113
+ }
3114
+ this.refreshDataSource();
3115
+ }
3116
+ if (this.dropPosition === 'middleSegment') {
3117
+ if (droppedRec.ganttProperties.predecessor) {
3118
+ this.parent.editModule.removePredecessorOnDelete(droppedRec);
3119
+ droppedRec.ganttProperties.predecessor = null;
3120
+ droppedRec.ganttProperties.predecessorsName = null;
3121
+ droppedRec[this.parent.taskFields.dependency] = null;
3122
+ droppedRec.taskData[this.parent.taskFields.dependency] = null;
3123
+ }
3124
+ if (droppedRec.ganttProperties.isMilestone) {
3125
+ this.parent.setRecordValue('isMilestone', false, droppedRec.ganttProperties, true);
3126
+ if (!isNullOrUndefined(droppedRec.taskData[this.parent.taskFields.milestone])) {
3127
+ if (droppedRec.taskData[this.parent.taskFields.milestone] === true) {
3128
+ droppedRec.taskData[this.parent.taskFields.milestone] = false;
3129
+ }
3130
+ }
3131
+ }
3132
+ }
3133
+ for (let k: number = 0; k < this.updateParentRecords.length; k++) {
3134
+ this.parent.dataOperation.updateParentItems(this.updateParentRecords[k]);
3135
+ }
3136
+ this.updateParentRecords = [];
3137
+ this.parent.isOnEdit = false;
3138
+ }
3139
+ this.refreshRecord(args);
3140
+ }
3141
+ /**
3142
+ * @returns {void} .
3143
+ * @private
3144
+ */
3145
+ public refreshRecord(args: RowDropEventArgs, isDrag?: boolean): void {
3146
+ if (isRemoteData(this.parent.dataSource)) {
3147
+ const data: DataManager = this.parent.dataSource as DataManager;
3148
+ const updatedData: object = {
3149
+ changedRecords: getTaskData(this.parent.editedRecords, null, null, this.parent)
3150
+ };
3151
+ const queryValue: Query = this.parent.query instanceof Query ? this.parent.query : new Query();
3152
+ let crud: Promise<Object> = null;
3153
+ const adaptor: AdaptorOptions = data.adaptor;
3154
+ if (!(adaptor instanceof WebApiAdaptor && adaptor instanceof ODataAdaptor) || data.dataSource.batchUrl) {
3155
+ crud = data.saveChanges(updatedData, this.parent.taskFields.id, null, queryValue) as Promise<Object>;
3156
+ } else {
3157
+ const changedRecords: string = 'changedRecords';
3158
+ crud = data.update(this.parent.taskFields.id, updatedData[changedRecords], null, queryValue) as Promise<Object>;
3159
+ }
3160
+ crud.then((e: ReturnType) => this.indentSuccess(e, args, isDrag))
3161
+ .catch((e: { result: Object[] }) => this.indentFailure(e as { result: Object[] }));
3162
+ } else {
3163
+ this.indentOutdentSuccess(args, isDrag);
3164
+ }
3165
+ }
3166
+ private indentSuccess(e: ReturnType, args: RowDropEventArgs, isDrag: boolean): void {
3167
+ this.indentOutdentSuccess(args, isDrag);
3168
+ }
3169
+ private indentFailure(e: { result: Object[] }): void {
3170
+ this.parent.trigger('actionFailure', { error: e });
3171
+ }
3172
+ private indentOutdentSuccess(args: RowDropEventArgs, isDrag: boolean): void {
3173
+ this.parent.treeGrid.parentData = [];
3174
+ this.parent.treeGrid.refresh();
3175
+ if (this.parent.enableImmutableMode) {
3176
+ this.refreshRecordInImmutableMode();
3177
+ }
3178
+ if (isDrag) {
3179
+ args.requestType = 'rowDropped';
3180
+ } else {
3181
+ if (this.dropPosition === 'middleSegment') {
3182
+ args.requestType = 'indented';
3183
+ } else if (this.dropPosition === 'bottomSegment') {
3184
+ args.requestType = 'outdented';
3185
+ }
3186
+ }
3187
+ args.modifiedRecords = this.parent.editedRecords;
3188
+ if (this.parent.timezone) {
3189
+ for (let i: number = 0; i < args.modifiedRecords.length; i++) {
3190
+ updateDates(args.modifiedRecords[i], this.parent);
3191
+ }
3192
+ }
3193
+ this.parent.trigger('actionComplete', args);
3194
+ this.parent.editedRecords = [];
3195
+ }
3196
+ private refreshDataSource(): void {
3197
+ const draggedRec: IGanttData = this.draggedRecord;
3198
+ const droppedRec: IGanttData = this.droppedRecord;
3199
+ const proxy: Gantt = this.parent;
3200
+ let tempData: Object;
3201
+ let indx: number;
3202
+ if (this.parent.dataSource instanceof DataManager) {
3203
+ tempData = getValue('dataOperation.dataArray', this.parent);
3204
+ } else {
3205
+ tempData = proxy.dataSource;
3206
+ }
3207
+ if ((tempData as IGanttData[]).length > 0 && (!isNullOrUndefined(droppedRec) && !droppedRec.parentItem)) {
3208
+ for (let i: number = 0; i < Object.keys(tempData).length; i++) {
3209
+ if (tempData[i][this.parent.taskFields.child] === droppedRec.taskData[this.parent.taskFields.child]) {
3210
+ indx = i;
3211
+ }
3212
+ }
3213
+ if (this.dropPosition === 'topSegment') {
3214
+ if (!this.parent.taskFields.parentID) {
3215
+ (tempData as IGanttData[]).splice(indx, 0, draggedRec.taskData);
3216
+ }
3217
+ } else if (this.dropPosition === 'bottomSegment') {
3218
+ if (!this.parent.taskFields.parentID) {
3219
+ (tempData as IGanttData[]).splice(indx + 1, 0, draggedRec.taskData);
3220
+ }
3221
+ }
3222
+ } else if (!this.parent.taskFields.parentID && (!isNullOrUndefined(droppedRec) && droppedRec.parentItem)) {
3223
+ if (this.dropPosition === 'topSegment' || this.dropPosition === 'bottomSegment') {
3224
+ const rowPos: RowPosition = this.dropPosition === 'topSegment' ? 'Above' : 'Below';
3225
+ this.parent.editModule.addRowSelectedItem = droppedRec;
3226
+ this.parent.editModule.updateRealDataSource(draggedRec, rowPos);
3227
+ delete this.parent.editModule.addRowSelectedItem;
3228
+ }
3229
+ }
3230
+ if (this.parent.taskFields.parentID) {
3231
+ if (draggedRec.parentItem) {
3232
+ if (this.dropPosition === 'topSegment' || this.dropPosition === 'bottomSegment') {
3233
+ draggedRec[this.parent.taskFields.parentID] = droppedRec[this.parent.taskFields.parentID];
3234
+ draggedRec.taskData[this.parent.taskFields.parentID] = droppedRec[this.parent.taskFields.parentID];
3235
+ draggedRec.ganttProperties['parentId'] = droppedRec[this.parent.taskFields.parentID];
3236
+ } else {
3237
+ draggedRec[this.parent.taskFields.parentID] = droppedRec[this.parent.taskFields.id];
3238
+ draggedRec.taskData[this.parent.taskFields.parentID] = droppedRec[this.parent.taskFields.id];
3239
+ draggedRec.ganttProperties['parentId'] = droppedRec[this.parent.taskFields.id];
3240
+ }
3241
+ } else {
3242
+ draggedRec[this.parent.taskFields.parentID] = null;
3243
+ draggedRec.taskData[this.parent.taskFields.parentID] = null;
3244
+ draggedRec.ganttProperties['parentId'] = null;
3245
+ }
3246
+ }
3247
+ }
3248
+ private deleteDragRow(): void {
3249
+ if (this.parent.dataSource instanceof DataManager) {
3250
+ this.ganttData = getValue('dataOperation.dataArray', this.parent);
3251
+ } else {
3252
+ this.ganttData = isCountRequired(this.parent) ? getValue('result', this.parent.dataSource) :
3253
+ this.parent.dataSource;
3254
+ }
3255
+ this.treeGridData = isCountRequired(this.parent) ?
3256
+ getValue('result', this.parent.treeGrid.dataSource) : this.parent.treeGrid.dataSource;
3257
+ const delRow: IGanttData = this.parent.getTaskByUniqueID(this.draggedRecord.uniqueID);
3258
+ this.removeRecords(delRow);
3259
+ }
3260
+ private updateIndentedChildRecords(indentedRecord: IGanttData) {
3261
+ let createParentItem: IParent = {
3262
+ uniqueID: indentedRecord.uniqueID,
3263
+ expanded: indentedRecord.expanded,
3264
+ level: indentedRecord.level,
3265
+ index: indentedRecord.index,
3266
+ taskId: indentedRecord.ganttProperties.rowUniqueID
3267
+ };
3268
+ for (let i: number = 0; i < indentedRecord.childRecords.length; i++) {
3269
+ this.parent.setRecordValue('parentItem', createParentItem, indentedRecord.childRecords[i]);
3270
+ this.parent.setRecordValue('parentUniqueID', indentedRecord.uniqueID, indentedRecord.childRecords[i]);
3271
+ }
3272
+ if (indentedRecord.hasChildRecords) {
3273
+ (indentedRecord as IGanttData[]) = indentedRecord.childRecords;
3274
+ for (let j = 0; j < indentedRecord['length']; j++) {
3275
+ this.updateIndentedChildRecords(indentedRecord[j]);
3276
+ }
3277
+ }
3278
+ }
3279
+ private dropMiddle(recordIndex1: number): void {
3280
+ const obj: Gantt = this.parent;
3281
+ const childRec: number = this.parent.editModule.getChildCount(this.droppedRecord, 0);
3282
+ const childRecordsLength: number = (isNullOrUndefined(childRec) ||
3283
+ childRec === 0) ? recordIndex1 + 1 :
3284
+ childRec + recordIndex1 + 1;
3285
+ if (this.dropPosition === 'middleSegment') {
3286
+ if (obj.taskFields.parentID && (this.ganttData as IGanttData[]).length > 0) {
3287
+ (this.ganttData as IGanttData[]).splice(childRecordsLength, 0, this.draggedRecord.taskData);
3288
+ }
3289
+ this.treeGridData.splice(childRecordsLength, 0, this.draggedRecord);
3290
+ this.parent.ids.splice(childRecordsLength, 0, this.draggedRecord[this.parent.taskFields.id].toString());
3291
+ this.recordLevel();
3292
+ if (this.draggedRecord.hasChildRecords) {
3293
+ this.updateChildRecord(this.draggedRecord, childRecordsLength, this.droppedRecord.expanded);
3294
+ if (this.parent.enableImmutableMode) {
3295
+ let indentedRecord = this.draggedRecord;
3296
+ this.updateIndentedChildRecords(indentedRecord);
3297
+ }
3298
+ }
3299
+ if (isNullOrUndefined(this.draggedRecord.parentItem &&
3300
+ this.updateParentRecords.indexOf(this.draggedRecord.parentItem) !== -1)) {
3301
+ this.updateParentRecords.push(this.draggedRecord.parentItem);
3302
+ }
3303
+ }
3304
+ }
3305
+ private updateChildRecordLevel(record: IGanttData, levl: number): number {
3306
+ let length: number = 0;
3307
+ let currentRec: IGanttData;
3308
+ levl++;
3309
+ if (!record.hasChildRecords) {
3310
+ return 0;
3311
+ }
3312
+ length = record.childRecords.length;
3313
+ for (let j: number = 0; j < length; j++) {
3314
+ currentRec = record.childRecords[j];
3315
+ let parentData: IGanttData;
3316
+ if (record.parentItem) {
3317
+ const id: string = 'uniqueIDCollection';
3318
+ parentData = this.parent.treeGrid[id][record.parentItem.uniqueID];
3319
+ }
3320
+ currentRec.level = record.parentItem ? parentData.level + levl : record.level + 1;
3321
+ if (currentRec.hasChildRecords) {
3322
+ levl--;
3323
+ levl = this.updateChildRecordLevel(currentRec, levl);
3324
+ }
3325
+ }
3326
+ return levl;
3327
+ }
3328
+ /* eslint-disable-next-line */
3329
+ private updateChildRecord(record: IGanttData, count: number, expanded?: boolean): number {
3330
+ let currentRec: IGanttData;
3331
+ const obj: Gantt = this.parent;
3332
+ let length: number = 0;
3333
+ if (!record.hasChildRecords) {
3334
+ return 0;
3335
+ }
3336
+ length = record.childRecords.length;
3337
+ for (let i: number = 0; i < length; i++) {
3338
+ currentRec = record.childRecords[i];
3339
+ count++;
3340
+ obj.flatData.splice(count, 0, currentRec);
3341
+ this.parent.ids.splice(count, 0, currentRec.ganttProperties.rowUniqueID.toString());
3342
+ if (obj.taskFields.parentID && (this.ganttData as IGanttData[]).length > 0) {
3343
+ (this.ganttData as IGanttData[]).splice(count, 0, currentRec.taskData);
3344
+ }
3345
+ if (currentRec.hasChildRecords) {
3346
+ count = this.updateChildRecord(currentRec, count);
3347
+ }
3348
+ }
3349
+ return count;
3350
+ }
3351
+ private removeRecords(record: IGanttData): void {
3352
+ const obj: Gantt = this.parent;
3353
+ let dataSource: Object;
3354
+ if (this.parent.dataSource instanceof DataManager) {
3355
+ dataSource = getValue('dataOperation.dataArray', this.parent);
3356
+ } else {
3357
+ dataSource = this.parent.dataSource;
3358
+ }
3359
+ const delRow: IGanttData = record;
3360
+ const flatParent: IGanttData = this.parent.getParentTask(delRow.parentItem);
3361
+ if (delRow) {
3362
+ if (delRow.parentItem) {
3363
+ const childRecords: IGanttData[] = flatParent ? flatParent.childRecords : [];
3364
+ let childIndex: number = 0;
3365
+ if (childRecords && childRecords.length > 0) {
3366
+ childIndex = childRecords.indexOf(delRow);
3367
+ flatParent.childRecords.splice(childIndex, 1);
3368
+ if (!this.parent.taskFields.parentID) {
3369
+ flatParent.taskData[this.parent.taskFields.child].splice(childIndex, 1);
3370
+ }
3371
+ // collection for updating parent record
3372
+ this.updateParentRecords.push(flatParent);
3373
+ }
3374
+ }
3375
+ if (obj.taskFields.parentID) {
3376
+ if (delRow.hasChildRecords && delRow.childRecords.length > 0) {
3377
+ this.removeChildItem(delRow);
3378
+ }
3379
+ let indx: number;
3380
+ const ganttData: IGanttData[] = (dataSource as IGanttData[]).length > 0 ?
3381
+ dataSource as IGanttData[] : this.parent.currentViewData;
3382
+ for (let i: number = 0; i < ganttData.length; i++) {
3383
+ if (ganttData[i][this.parent.taskFields.id] === delRow.taskData[this.parent.taskFields.id]) {
3384
+ indx = i;
3385
+ }
3386
+ }
3387
+ if (indx !== -1) {
3388
+ if ((dataSource as IGanttData[]).length > 0) {
3389
+ (dataSource as IGanttData[]).splice(indx, 1);
3390
+ }
3391
+ let gridIndx: number;
3392
+ for (let i: number = 0; i < this.treeGridData.length; i++) {
3393
+ if (this.treeGridData[i][this.parent.taskFields.id] === delRow.taskData[this.parent.taskFields.id]) {
3394
+ gridIndx = i;
3395
+ }
3396
+ }
3397
+ this.treeGridData.splice(gridIndx, 1);
3398
+ this.parent.ids.splice(gridIndx, 1);
3399
+ if (this.parent.treeGrid.parentData.indexOf(delRow) !== -1) {
3400
+ this.parent.treeGrid.parentData.splice(this.parent.treeGrid.parentData.indexOf(delRow), 1);
3401
+ }
3402
+ }
3403
+ }
3404
+ const recordIdx: number = this.treeGridData.indexOf(delRow);
3405
+ if (!obj.taskFields.parentID) {
3406
+ const deletedRecordCount: number = this.getChildCount(delRow, 0);
3407
+ this.treeGridData.splice(recordIdx, deletedRecordCount + 1);
3408
+ this.parent.ids.splice(recordIdx, deletedRecordCount + 1);
3409
+ const parentIndex: number = (this.ganttData as IGanttData[]).indexOf(delRow.taskData);
3410
+ if (parentIndex !== -1) {
3411
+ (this.ganttData as IGanttData[]).splice(parentIndex, 1);
3412
+ this.parent.treeGrid.parentData.splice(parentIndex, 1);
3413
+ }
3414
+ }
3415
+ if (delRow.parentItem && flatParent && flatParent.childRecords && !flatParent.childRecords.length) {
3416
+ this.parent.setRecordValue('expanded', false, flatParent);
3417
+ this.parent.setRecordValue('hasChildRecords', false, flatParent);
3418
+ }
3419
+ }
3420
+ }
3421
+ private removeChildItem(record: IGanttData): void {
3422
+ let currentRec: IGanttData;
3423
+ let indx: number;
3424
+ for (let i: number = 0; i < record.childRecords.length; i++) {
3425
+ currentRec = record.childRecords[i];
3426
+ let data: Object;
3427
+ if (this.parent.dataSource instanceof DataManager) {
3428
+ data = getValue('dataOperation.dataArray', this.parent);
3429
+ } else {
3430
+ data = this.parent.dataSource;
3431
+ }
3432
+ for (let j: number = 0; j < (<IGanttData[]>data).length; j++) {
3433
+ if (data[j][this.parent.taskFields.id] === currentRec.taskData[this.parent.taskFields.id]) {
3434
+ indx = j;
3435
+ }
3436
+ }
3437
+ if (indx !== -1) {
3438
+ if ((data as IGanttData[]).length > 0) {
3439
+ (data as IGanttData[]).splice(indx, 1);
3440
+ }
3441
+ let gridIndx: number;
3442
+ for (let i: number = 0; i < this.treeGridData.length; i++) {
3443
+ if (this.treeGridData[i][this.parent.taskFields.id] === currentRec.taskData[this.parent.taskFields.id]) {
3444
+ gridIndx = i;
3445
+ }
3446
+ }
3447
+ this.treeGridData.splice(gridIndx, 1);
3448
+ this.parent.ids.splice(gridIndx, 1);
3449
+ }
3450
+ if (currentRec.hasChildRecords) {
3451
+ this.removeChildItem(currentRec);
3452
+ }
3453
+ }
3454
+ }
3455
+ private recordLevel(): void {
3456
+ const obj: Gantt = this.parent;
3457
+ const draggedRec: IGanttData = this.draggedRecord;
3458
+ const droppedRec: IGanttData = this.droppedRecord;
3459
+ const childItem: string = obj.taskFields.child;
3460
+ if (!droppedRec.hasChildRecords) {
3461
+ droppedRec.hasChildRecords = true;
3462
+ if (!droppedRec.childRecords.length) {
3463
+ droppedRec.childRecords = [];
3464
+ if (!obj.taskFields.parentID && isNullOrUndefined(droppedRec.taskData[childItem])) {
3465
+ droppedRec.taskData[childItem] = [];
3466
+ }
3467
+ }
3468
+ }
3469
+ if (this.dropPosition === 'middleSegment') {
3470
+ const parentItem: IGanttData = extend({}, droppedRec);
3471
+ delete parentItem.childRecords;
3472
+ const createParentItem: IParent = {
3473
+ uniqueID: parentItem.uniqueID,
3474
+ expanded: parentItem.expanded,
3475
+ level: parentItem.level,
3476
+ index: parentItem.index,
3477
+ taskId: parentItem.ganttProperties.rowUniqueID
3478
+ };
3479
+ this.parent.setRecordValue('parentItem', createParentItem, draggedRec);
3480
+ this.parent.setRecordValue('parentUniqueID', droppedRec.uniqueID, draggedRec);
3481
+ droppedRec.childRecords.splice(droppedRec.childRecords.length, 0, draggedRec);
3482
+ if (!isNullOrUndefined(draggedRec) && !obj.taskFields.parentID && !isNullOrUndefined(droppedRec.taskData[childItem])) {
3483
+ droppedRec.taskData[obj.taskFields.child].splice(droppedRec.childRecords.length, 0, draggedRec.taskData);
3484
+ }
3485
+ if (!isNullOrUndefined(droppedRec.ganttProperties.segments) && droppedRec.ganttProperties.segments.length > 0) {
3486
+ droppedRec.ganttProperties.segments = null;
3487
+ droppedRec.taskData[obj.taskFields.segments] = null;
3488
+ }
3489
+ if (!draggedRec.hasChildRecords) {
3490
+ draggedRec.level = droppedRec.level + 1;
3491
+ } else {
3492
+ const level: number = 1;
3493
+ draggedRec.level = droppedRec.level + 1;
3494
+ this.updateChildRecordLevel(draggedRec, level);
3495
+ }
3496
+ droppedRec.expanded = true;
3497
+ }
3498
+ }
3499
+ }