@syncfusion/ej2-gantt 19.4.55 → 20.1.47-1460716

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +1072 -1047
  2. package/README.md +75 -75
  3. package/dist/ej2-gantt.umd.min.js +1 -10
  4. package/dist/ej2-gantt.umd.min.js.map +1 -1
  5. package/dist/es6/ej2-gantt.es2015.js +341 -240
  6. package/dist/es6/ej2-gantt.es2015.js.map +1 -1
  7. package/dist/es6/ej2-gantt.es5.js +713 -598
  8. package/dist/es6/ej2-gantt.es5.js.map +1 -1
  9. package/dist/global/ej2-gantt.min.js +1 -10
  10. package/dist/global/ej2-gantt.min.js.map +1 -1
  11. package/dist/global/index.d.ts +0 -9
  12. package/dist/ts/components.ts +4 -0
  13. package/dist/ts/gantt/actions/actions.ts +18 -0
  14. package/dist/ts/gantt/actions/cell-edit.ts +606 -0
  15. package/dist/ts/gantt/actions/chart-scroll.ts +167 -0
  16. package/dist/ts/gantt/actions/column-menu.ts +35 -0
  17. package/dist/ts/gantt/actions/column-reorder.ts +52 -0
  18. package/dist/ts/gantt/actions/column-resize.ts +52 -0
  19. package/dist/ts/gantt/actions/connector-line-edit.ts +829 -0
  20. package/dist/ts/gantt/actions/context-menu.ts +754 -0
  21. package/dist/ts/gantt/actions/day-markers.ts +80 -0
  22. package/dist/ts/gantt/actions/dependency.ts +692 -0
  23. package/dist/ts/gantt/actions/dialog-edit.ts +2208 -0
  24. package/dist/ts/gantt/actions/edit.ts +3499 -0
  25. package/dist/ts/gantt/actions/excel-export.ts +61 -0
  26. package/dist/ts/gantt/actions/filter.ts +302 -0
  27. package/dist/ts/gantt/actions/keyboard.ts +306 -0
  28. package/dist/ts/gantt/actions/pdf-export.ts +214 -0
  29. package/dist/ts/gantt/actions/rowdragdrop.ts +839 -0
  30. package/dist/ts/gantt/actions/selection.ts +536 -0
  31. package/dist/ts/gantt/actions/sort.ts +98 -0
  32. package/dist/ts/gantt/actions/taskbar-edit.ts +1940 -0
  33. package/dist/ts/gantt/actions/toolbar.ts +489 -0
  34. package/dist/ts/gantt/actions/virtual-scroll.ts +60 -0
  35. package/dist/ts/gantt/base/common.ts +9 -0
  36. package/dist/ts/gantt/base/constant.ts +13 -0
  37. package/dist/ts/gantt/base/css-constants.ts +148 -0
  38. package/dist/ts/gantt/base/date-processor.ts +1257 -0
  39. package/dist/ts/gantt/base/enum.ts +372 -0
  40. package/dist/ts/gantt/base/gantt-chart.ts +1248 -0
  41. package/dist/ts/gantt/base/gantt.ts +4069 -0
  42. package/dist/ts/gantt/base/interface.ts +955 -0
  43. package/dist/ts/gantt/base/splitter.ts +174 -0
  44. package/dist/ts/gantt/base/task-processor.ts +2217 -0
  45. package/dist/ts/gantt/base/tree-grid.ts +694 -0
  46. package/dist/ts/gantt/base/utils.ts +208 -0
  47. package/dist/ts/gantt/export/export-helper.ts +552 -0
  48. package/dist/ts/gantt/export/pdf-base/dictionary.ts +152 -0
  49. package/dist/ts/gantt/export/pdf-base/pdf-borders.ts +277 -0
  50. package/dist/ts/gantt/export/pdf-base/pdf-grid-table.ts +901 -0
  51. package/dist/ts/gantt/export/pdf-base/pdf-style/gantt-theme.ts +131 -0
  52. package/dist/ts/gantt/export/pdf-base/pdf-style/style.ts +91 -0
  53. package/dist/ts/gantt/export/pdf-base/treegrid-layouter.ts +414 -0
  54. package/dist/ts/gantt/export/pdf-connector-line.ts +422 -0
  55. package/dist/ts/gantt/export/pdf-gantt.ts +282 -0
  56. package/dist/ts/gantt/export/pdf-taskbar.ts +395 -0
  57. package/dist/ts/gantt/export/pdf-timeline.ts +202 -0
  58. package/dist/ts/gantt/export/pdf-treegrid.ts +406 -0
  59. package/dist/ts/gantt/models/add-dialog-field-settings.ts +33 -0
  60. package/dist/ts/gantt/models/column.ts +464 -0
  61. package/dist/ts/gantt/models/day-working-time.ts +22 -0
  62. package/dist/ts/gantt/models/edit-dialog-field-settings.ts +33 -0
  63. package/dist/ts/gantt/models/edit-settings.ts +79 -0
  64. package/dist/ts/gantt/models/event-marker.ts +27 -0
  65. package/dist/ts/gantt/models/filter-settings.ts +53 -0
  66. package/dist/ts/gantt/models/holiday.ts +34 -0
  67. package/dist/ts/gantt/models/label-settings.ts +30 -0
  68. package/dist/ts/gantt/models/models.ts +36 -0
  69. package/dist/ts/gantt/models/resource-fields.ts +38 -0
  70. package/dist/ts/gantt/models/search-settings.ts +77 -0
  71. package/dist/ts/gantt/models/selection-settings.ts +56 -0
  72. package/dist/ts/gantt/models/sort-settings.ts +50 -0
  73. package/dist/ts/gantt/models/splitter-settings.ts +47 -0
  74. package/dist/ts/gantt/models/task-fields.ts +171 -0
  75. package/dist/ts/gantt/models/timeline-settings.ts +112 -0
  76. package/dist/ts/gantt/models/tooltip-settings.ts +46 -0
  77. package/dist/ts/gantt/renderer/chart-rows.ts +1838 -0
  78. package/dist/ts/gantt/renderer/connector-line.ts +1025 -0
  79. package/dist/ts/gantt/renderer/edit-tooltip.ts +228 -0
  80. package/dist/ts/gantt/renderer/event-marker.ts +96 -0
  81. package/dist/ts/gantt/renderer/nonworking-day.ts +205 -0
  82. package/dist/ts/gantt/renderer/render.ts +5 -0
  83. package/dist/ts/gantt/renderer/timeline.ts +1397 -0
  84. package/dist/ts/gantt/renderer/tooltip.ts +450 -0
  85. package/dist/ts/gantt/renderer/virtual-content-render.ts +50 -0
  86. package/license +9 -9
  87. package/package.json +80 -80
  88. package/src/gantt/actions/cell-edit.js +2 -1
  89. package/src/gantt/actions/dialog-edit.js +2 -1
  90. package/src/gantt/actions/edit.js +36 -9
  91. package/src/gantt/actions/rowdragdrop.js +37 -15
  92. package/src/gantt/actions/selection.js +3 -2
  93. package/src/gantt/actions/taskbar-edit.js +24 -24
  94. package/src/gantt/base/date-processor.js +0 -1
  95. package/src/gantt/base/gantt-chart.js +36 -5
  96. package/src/gantt/base/gantt-model.d.ts +779 -779
  97. package/src/gantt/base/gantt.d.ts +27 -27
  98. package/src/gantt/base/gantt.js +35 -76
  99. package/src/gantt/base/splitter.js +1 -0
  100. package/src/gantt/base/task-processor.js +13 -13
  101. package/src/gantt/base/tree-grid.js +3 -1
  102. package/src/gantt/export/pdf-base/treegrid-layouter.js +13 -13
  103. package/src/gantt/export/pdf-connector-line.js +11 -11
  104. package/src/gantt/export/pdf-gantt.js +24 -24
  105. package/src/gantt/export/pdf-taskbar.js +11 -11
  106. package/src/gantt/export/pdf-treegrid.js +13 -13
  107. package/src/gantt/models/add-dialog-field-settings-model.d.ts +21 -21
  108. package/src/gantt/models/add-dialog-field-settings.js +19 -19
  109. package/src/gantt/models/day-working-time-model.d.ts +11 -11
  110. package/src/gantt/models/day-working-time.js +19 -19
  111. package/src/gantt/models/edit-dialog-field-settings-model.d.ts +21 -21
  112. package/src/gantt/models/edit-dialog-field-settings.js +19 -19
  113. package/src/gantt/models/edit-settings-model.d.ts +50 -50
  114. package/src/gantt/models/edit-settings.js +19 -19
  115. package/src/gantt/models/event-marker-model.d.ts +16 -16
  116. package/src/gantt/models/event-marker.js +19 -19
  117. package/src/gantt/models/filter-settings-model.d.ts +34 -34
  118. package/src/gantt/models/filter-settings.js +19 -19
  119. package/src/gantt/models/holiday-model.d.ts +21 -21
  120. package/src/gantt/models/holiday.js +19 -19
  121. package/src/gantt/models/label-settings-model.d.ts +16 -16
  122. package/src/gantt/models/label-settings.js +19 -19
  123. package/src/gantt/models/resource-fields-model.d.ts +21 -21
  124. package/src/gantt/models/resource-fields.js +19 -19
  125. package/src/gantt/models/search-settings-model.d.ts +56 -56
  126. package/src/gantt/models/search-settings.js +19 -19
  127. package/src/gantt/models/selection-settings-model.d.ts +35 -35
  128. package/src/gantt/models/selection-settings.js +19 -19
  129. package/src/gantt/models/sort-settings-model.d.ts +24 -24
  130. package/src/gantt/models/sort-settings.js +19 -19
  131. package/src/gantt/models/splitter-settings-model.d.ts +30 -30
  132. package/src/gantt/models/splitter-settings.js +19 -19
  133. package/src/gantt/models/task-fields-model.d.ts +110 -110
  134. package/src/gantt/models/task-fields.js +19 -19
  135. package/src/gantt/models/timeline-settings-model.d.ts +71 -71
  136. package/src/gantt/models/timeline-settings.js +19 -19
  137. package/src/gantt/models/tooltip-settings-model.d.ts +26 -26
  138. package/src/gantt/models/tooltip-settings.js +19 -19
  139. package/src/gantt/renderer/chart-rows.js +49 -37
  140. package/src/gantt/renderer/connector-line.js +22 -18
  141. package/src/gantt/renderer/event-marker.js +1 -0
  142. package/src/gantt/renderer/nonworking-day.js +13 -6
  143. package/src/gantt/renderer/timeline.d.ts +1 -0
  144. package/src/gantt/renderer/timeline.js +51 -12
  145. package/src/gantt/renderer/tooltip.js +11 -3
  146. package/styles/bootstrap-dark.css +442 -427
  147. package/styles/bootstrap.css +442 -433
  148. package/styles/bootstrap4.css +454 -479
  149. package/styles/bootstrap5-dark.css +457 -433
  150. package/styles/bootstrap5.css +457 -433
  151. package/styles/fabric-dark.css +438 -421
  152. package/styles/fabric.css +445 -428
  153. package/styles/fluent-dark.css +1938 -0
  154. package/styles/fluent-dark.scss +1 -0
  155. package/styles/fluent.css +1938 -0
  156. package/styles/fluent.scss +1 -0
  157. package/styles/gantt/_all.scss +2 -2
  158. package/styles/gantt/_bootstrap-dark-definition.scss +210 -156
  159. package/styles/gantt/_bootstrap-definition.scss +211 -157
  160. package/styles/gantt/_bootstrap4-definition.scss +213 -158
  161. package/styles/gantt/_bootstrap5-definition.scss +215 -162
  162. package/styles/gantt/_fabric-dark-definition.scss +211 -157
  163. package/styles/gantt/_fabric-definition.scss +211 -157
  164. package/styles/gantt/_fluent-dark-definition.scss +1 -0
  165. package/styles/gantt/_fluent-definition.scss +215 -162
  166. package/styles/gantt/_fusionnew-definition.scss +214 -0
  167. package/styles/gantt/_highcontrast-definition.scss +211 -157
  168. package/styles/gantt/_highcontrast-light-definition.scss +211 -157
  169. package/styles/gantt/_layout.scss +1446 -1027
  170. package/styles/gantt/_material-dark-definition.scss +212 -157
  171. package/styles/gantt/_material-definition.scss +212 -157
  172. package/styles/gantt/_material3-definition.scss +215 -0
  173. package/styles/gantt/_tailwind-definition.scss +215 -161
  174. package/styles/gantt/_theme.scss +702 -668
  175. package/styles/gantt/bootstrap-dark.css +442 -427
  176. package/styles/gantt/bootstrap.css +442 -433
  177. package/styles/gantt/bootstrap4.css +454 -479
  178. package/styles/gantt/bootstrap5-dark.css +457 -433
  179. package/styles/gantt/bootstrap5.css +457 -433
  180. package/styles/gantt/fabric-dark.css +438 -421
  181. package/styles/gantt/fabric.css +445 -428
  182. package/styles/gantt/fluent-dark.css +1938 -0
  183. package/styles/gantt/fluent-dark.scss +22 -0
  184. package/styles/gantt/fluent.css +1938 -0
  185. package/styles/gantt/fluent.scss +22 -0
  186. package/styles/gantt/highcontrast-light.css +405 -405
  187. package/styles/gantt/highcontrast.css +444 -456
  188. package/styles/gantt/icons/_bootstrap-dark.scss +124 -113
  189. package/styles/gantt/icons/_bootstrap.scss +124 -113
  190. package/styles/gantt/icons/_bootstrap4.scss +124 -113
  191. package/styles/gantt/icons/_bootstrap5.scss +124 -112
  192. package/styles/gantt/icons/_fabric-dark.scss +124 -112
  193. package/styles/gantt/icons/_fabric.scss +124 -112
  194. package/styles/gantt/icons/_fluent-dark.scss +1 -0
  195. package/styles/gantt/icons/_fluent.scss +124 -112
  196. package/styles/gantt/icons/_fusionnew.scss +120 -0
  197. package/styles/gantt/icons/_highcontrast.scss +124 -112
  198. package/styles/gantt/icons/_material-dark.scss +124 -112
  199. package/styles/gantt/icons/_material.scss +124 -112
  200. package/styles/gantt/icons/_material3.scss +124 -0
  201. package/styles/gantt/icons/_tailwind-dark.scss +124 -113
  202. package/styles/gantt/icons/_tailwind.scss +124 -113
  203. package/styles/gantt/material-dark.css +446 -417
  204. package/styles/gantt/material.css +445 -419
  205. package/styles/gantt/tailwind-dark.css +452 -482
  206. package/styles/gantt/tailwind.css +449 -479
  207. package/styles/highcontrast-light.css +405 -405
  208. package/styles/highcontrast.css +444 -456
  209. package/styles/material-dark.css +446 -417
  210. package/styles/material.css +445 -419
  211. package/styles/tailwind-dark.css +452 -482
  212. package/styles/tailwind.css +449 -479
@@ -0,0 +1,829 @@
1
+ import { isNullOrUndefined, isUndefined, addClass} from '@syncfusion/ej2-base';
2
+ import { removeClass, getValue, createElement, extend } from '@syncfusion/ej2-base';
3
+ import { Gantt } from '../base/gantt';
4
+ import * as cls from '../base/css-constants';
5
+ import { parentsUntil, formatString, isScheduledTask, getIndex } from '../base/utils';
6
+ import { IGanttData, IPredecessor, IConnectorLineObject, ITaskData, ITaskbarEditedEventArgs, IValidateArgs } from '../base/interface';
7
+ import { Dialog } from '@syncfusion/ej2-popups';
8
+ import { DateProcessor } from '../base/date-processor';
9
+ /**
10
+ * File for handling connector line edit operation in Gantt.
11
+ *
12
+ */
13
+ export class ConnectorLineEdit {
14
+ private parent: Gantt;
15
+ private connectorLineElement: Element;
16
+ /**
17
+ * @private
18
+ */
19
+ public validationPredecessor: IPredecessor[] = null;
20
+ /** @private */
21
+ public confirmPredecessorDialog: Dialog = null;
22
+ /** @private */
23
+ public predecessorIndex: number = null;
24
+ /** @private */
25
+ public childRecord: IGanttData = null;
26
+ private dateValidateModule: DateProcessor;
27
+ constructor(ganttObj?: Gantt) {
28
+ this.parent = ganttObj;
29
+ this.dateValidateModule = this.parent.dateValidationModule;
30
+ this.parent.on('initPredessorDialog', this.initPredecessorValidationDialog, this);
31
+ }
32
+
33
+ /**
34
+ * To update connector line edit element.
35
+ *
36
+ * @param {PointerEvent} e .
37
+ * @returns {void} .
38
+ * @private
39
+ */
40
+ public updateConnectorLineEditElement(e: PointerEvent): void {
41
+ const element: Element = this.getConnectorLineHoverElement(e.target);
42
+ if (!getValue('editModule.taskbarEditModule.taskBarEditAction', this.parent)) {
43
+ this.highlightConnectorLineElements(element);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * To get hovered connector line element.
49
+ *
50
+ * @param {EventTarget} target .
51
+ * @returns {void} .
52
+ * @private
53
+ */
54
+ private getConnectorLineHoverElement(target: EventTarget): Element {
55
+ const isOnLine: Element = parentsUntil(target as Element, cls.connectorLine);
56
+ const isOnRightArrow: Element = parentsUntil(target as Element, cls.connectorLineRightArrow);
57
+ const isOnLeftArrow: Element = parentsUntil(target as Element, cls.connectorLineLeftArrow);
58
+ if (isOnLine || isOnRightArrow || isOnLeftArrow) {
59
+ return parentsUntil(target as Element, cls.connectorLineContainer);
60
+ } else {
61
+ return null;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * To highlight connector line while hover.
67
+ *
68
+ * @param {Element} element .
69
+ * @returns {void} .
70
+ * @private
71
+ */
72
+ private highlightConnectorLineElements(element: Element): void {
73
+ if (element) {
74
+ if (element !== this.connectorLineElement) {
75
+ this.removeHighlight();
76
+ this.addHighlight(element);
77
+ }
78
+ } else {
79
+ this.removeHighlight();
80
+ }
81
+ }
82
+
83
+ /**
84
+ * To add connector line highlight class.
85
+ *
86
+ * @param {Element} element .
87
+ * @returns {void} .
88
+ * @private
89
+ */
90
+ private addHighlight(element: Element): void {
91
+ this.connectorLineElement = element;
92
+ addClass([element], [cls.connectorLineHoverZIndex]);
93
+ addClass(element.querySelectorAll('.' + cls.connectorLine), [cls.connectorLineHover]);
94
+ addClass(element.querySelectorAll('.' + cls.connectorLineRightArrow), [cls.connectorLineRightArrowHover]);
95
+ addClass(element.querySelectorAll('.' + cls.connectorLineLeftArrow), [cls.connectorLineLeftArrowHover]);
96
+ }
97
+
98
+ /**
99
+ * To remove connector line highlight class.
100
+ *
101
+ * @returns {void} .
102
+ * @private
103
+ */
104
+ private removeHighlight(): void {
105
+ if (!isNullOrUndefined(this.connectorLineElement)) {
106
+ removeClass([this.connectorLineElement], [cls.connectorLineHoverZIndex]);
107
+ removeClass(this.connectorLineElement.querySelectorAll('.' + cls.connectorLine), [cls.connectorLineHover]);
108
+ removeClass(this.connectorLineElement.querySelectorAll('.' + cls.connectorLineRightArrow), [cls.connectorLineRightArrowHover]);
109
+ removeClass(this.connectorLineElement.querySelectorAll('.' + cls.connectorLineLeftArrow), [cls.connectorLineLeftArrowHover]);
110
+ this.connectorLineElement = null;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * To remove connector line highlight class.
116
+ *
117
+ * @param {IGanttData[]} records .
118
+ * @returns {string} .
119
+ * @private
120
+ */
121
+ public getEditedConnectorLineString(records: IGanttData[]): string {
122
+ let ganttRecord: IGanttData;
123
+ let predecessorsCollection: IPredecessor[];
124
+ let predecessor: IPredecessor;
125
+ let parentGanttRecord: IGanttData;
126
+ let childGanttRecord: IGanttData;
127
+ let connectorObj: IConnectorLineObject;
128
+ const idArray: string[] = [];
129
+ const lineArray: string[] = [];
130
+ let editedConnectorLineString: string = '';
131
+ for (let count: number = 0; count < records.length; count++) {
132
+ ganttRecord = records[count];
133
+ predecessorsCollection = ganttRecord.ganttProperties.predecessor;
134
+ if (predecessorsCollection) {
135
+ for (let predecessorCount: number = 0; predecessorCount < predecessorsCollection.length; predecessorCount++) {
136
+ predecessor = predecessorsCollection[predecessorCount];
137
+ const from: string = 'from'; const to: string = 'to';
138
+ this.parent.connectorLineModule.removeConnectorLineById('parent' + predecessor[from] + 'child' + predecessor[to]);
139
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor[from]);
140
+ childGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor[to]);
141
+ if ((parentGanttRecord && parentGanttRecord.expanded === true) ||
142
+ (childGanttRecord && childGanttRecord.expanded === true)) {
143
+ connectorObj =
144
+ this.parent.predecessorModule.updateConnectorLineObject(parentGanttRecord, childGanttRecord, predecessor);
145
+ if (!isNullOrUndefined(connectorObj)) {
146
+ const lineIndex: number = idArray.indexOf(connectorObj.connectorLineId);
147
+ const lineString: string = this.parent.connectorLineModule.getConnectorLineTemplate(connectorObj);
148
+ if (lineIndex !== -1) {
149
+ lineArray[lineIndex] = lineString;
150
+ } else {
151
+ idArray.push(connectorObj.connectorLineId);
152
+ lineArray.push(lineString);
153
+ }
154
+ }
155
+ }
156
+ }
157
+ editedConnectorLineString = lineArray.join('');
158
+ }
159
+ }
160
+ return editedConnectorLineString;
161
+ }
162
+ /**
163
+ * Tp refresh connector lines of edited records
164
+ *
165
+ * @param {IGanttData[]} editedRecord .
166
+ * @returns {void} .
167
+ * @private
168
+ */
169
+ public refreshEditedRecordConnectorLine(editedRecord: IGanttData[]): void {
170
+ this.parent.connectorLineModule.removePreviousConnectorLines(this.parent.previousRecords);
171
+ this.parent.connectorLineModule.expandedRecords = this.parent.virtualScrollModule && this.parent.enableVirtualization ?
172
+ this.parent.updatedRecords : this.parent.getExpandedRecords(this.parent.updatedRecords);
173
+ const editedConnectorLineString: string = this.getEditedConnectorLineString(editedRecord);
174
+ this.parent.connectorLineModule.dependencyViewContainer.innerHTML =
175
+ this.parent.connectorLineModule.dependencyViewContainer.innerHTML + editedConnectorLineString;
176
+ }
177
+
178
+ private idFromPredecessor(pre: string): string[] {
179
+ const preArray: string[] = pre.split(',');
180
+ const preIdArray: string[] = [];
181
+ for (let j: number = 0; j < preArray.length; j++) {
182
+ const strArray: string[] = [];
183
+ for (let i: number = 0; i < preArray[j].length; i++) {
184
+ if (!isNullOrUndefined(preArray[j].charAt(i)) && parseInt(preArray[j].charAt(i), 10).toString() !== 'NaN') {
185
+ strArray.push(preArray[j].charAt(i));
186
+ } else {
187
+ break;
188
+ }
189
+ }
190
+ preIdArray.push((strArray.join('')));
191
+ }
192
+ return preIdArray;
193
+ }
194
+
195
+ private predecessorValidation(predecessor: string[], record: ITaskData): boolean {
196
+
197
+ const recordId: string = record.rowUniqueID;
198
+ let currentId: string;
199
+ let currentRecord: ITaskData;
200
+ for (let count: number = 0; count < predecessor.length; count++) {
201
+ currentId = predecessor[count];
202
+ const visitedIdArray: string[] = [];
203
+ const predecessorCollection: string[] = predecessor.slice(0);
204
+ predecessorCollection.splice(count, 1);
205
+
206
+ while (currentId !== null) {
207
+ const currentIdArray: string[] = [];
208
+ if (visitedIdArray.indexOf(currentId) === -1) {
209
+ //Predecessor id not in records collection
210
+ if (isNullOrUndefined(this.parent.connectorLineModule.getRecordByID(currentId))) {
211
+ return false;
212
+ }
213
+ currentRecord = this.parent.connectorLineModule.getRecordByID(currentId).ganttProperties;
214
+
215
+ if (!isNullOrUndefined(currentRecord.predecessor) && currentRecord.predecessor.length > 0) {
216
+ currentRecord.predecessor.forEach((value: IPredecessor) => {
217
+ if (currentRecord.rowUniqueID.toString() !== value.from) {
218
+ currentIdArray.push(value.from.toString());
219
+ }
220
+ });
221
+ }
222
+ /* eslint-disable-next-line */
223
+ if (recordId.toString() === currentRecord.rowUniqueID.toString() || currentIdArray.indexOf(recordId.toString()) !== -1) {
224
+ return false;
225
+ }
226
+ visitedIdArray.push(currentId);
227
+ if (!isNullOrUndefined(currentRecord.predecessor) && currentRecord.predecessor.length > 0) {
228
+ currentId = currentRecord.predecessor[0].from;
229
+ } else {
230
+ break;
231
+ }
232
+ } else {
233
+ break;
234
+ }
235
+ }
236
+ }
237
+ return true;
238
+
239
+ }
240
+ /**
241
+ * To validate predecessor relations
242
+ *
243
+ * @param {IGanttData} ganttRecord .
244
+ * @param {string} predecessorString .
245
+ * @returns {boolean} .
246
+ * @private
247
+ */
248
+ public validatePredecessorRelation(ganttRecord: IGanttData, predecessorString: string): boolean {
249
+ const flag: boolean = true;
250
+ const recordId: string = this.parent.viewType === 'ResourceView' ? ganttRecord.ganttProperties.taskId
251
+ : ganttRecord.ganttProperties.rowUniqueID;
252
+ let predecessorIdArray: string[];
253
+ let currentId: string;
254
+ if (!isNullOrUndefined(predecessorString) && predecessorString.length > 0) {
255
+ predecessorIdArray = this.idFromPredecessor(predecessorString);
256
+ for (let count: number = 0; count < predecessorIdArray.length; count++) {
257
+ //Check edited item has parent item in predecessor collection
258
+ const checkParent: boolean = this.checkParentRelation(ganttRecord, predecessorIdArray);
259
+ if (!checkParent) {
260
+ return false;
261
+ }
262
+ // Check if predecessor exist more then one
263
+ const tempIdArray: string[] = predecessorIdArray.slice(0);
264
+ const checkArray: string[] = [];
265
+ let countFlag: boolean = true;
266
+ tempIdArray.forEach((value: string) => {
267
+ if (checkArray.indexOf(value) === -1) {
268
+ checkArray.push(value);
269
+ } else {
270
+ countFlag = false;
271
+ }
272
+ });
273
+ if (!countFlag) {
274
+ return false;
275
+ }
276
+ //Cyclick check
277
+ currentId = predecessorIdArray[count];
278
+ const visitedIdArray: string[] = [];
279
+ const predecessorCollection: string[] = predecessorIdArray.slice(0);
280
+ predecessorCollection.splice(count, 1);
281
+
282
+ while (currentId !== null) {
283
+ const currentIdArray: string[] = [];
284
+ let currentIdIndex: number;
285
+ let currentRecord: ITaskData;
286
+ if (visitedIdArray.indexOf(currentId) === -1) {
287
+ //Predecessor id not in records collection
288
+ if (isNullOrUndefined(this.parent.connectorLineModule.getRecordByID(currentId.toString()))) {
289
+ return false;
290
+ }
291
+ currentRecord = this.parent.connectorLineModule.getRecordByID(currentId.toString()).ganttProperties;
292
+ // let currentPredecessor='';
293
+ if (!isNullOrUndefined(currentRecord.predecessor) && currentRecord.predecessor.length > 0) {
294
+ currentRecord.predecessor.forEach((value: IPredecessor, index: number) => {
295
+ if (currentRecord.rowUniqueID.toString() !== value.from) {
296
+ currentIdArray.push(value.from.toString());
297
+ currentIdIndex = index;
298
+ }
299
+ });
300
+ // currentPredecessor=currentRecord.predecessor[0].from
301
+ }
302
+ if (recordId.toString() === currentRecord.rowUniqueID.toString() ||
303
+ currentIdArray.indexOf(recordId.toString()) !== -1) {
304
+ //cycylic occurs//break;
305
+ return false;
306
+ }
307
+ visitedIdArray.push(currentId);
308
+ if (!isNullOrUndefined(currentRecord.predecessor) && currentRecord.predecessor.length > 0) {
309
+ let result: boolean;
310
+ if (currentIdArray.length > 1) {
311
+ result = this.predecessorValidation(currentIdArray, ganttRecord.ganttProperties);
312
+ } else if (currentIdArray.length === 1) {
313
+ currentId = currentRecord.predecessor[currentIdIndex].from;
314
+ }
315
+ if (result === false) {
316
+ return false;
317
+ }
318
+ } else {
319
+ break;
320
+ }
321
+ } else {
322
+ break;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ return flag;
328
+ }
329
+ /**
330
+ * To add dependency for Task
331
+ *
332
+ * @param {IGanttData} ganttRecord .
333
+ * @param {string} predecessorString .
334
+ * @returns {void} .
335
+ * @private
336
+ */
337
+ public addPredecessor(ganttRecord: IGanttData, predecessorString: string): void {
338
+ const tempPredecessorString: string = isNullOrUndefined(ganttRecord.ganttProperties.predecessorsName) ||
339
+ ganttRecord.ganttProperties.predecessorsName === '' ?
340
+ predecessorString : (ganttRecord.ganttProperties.predecessorsName + ',' + predecessorString);
341
+ this.updatePredecessorHelper(ganttRecord, tempPredecessorString);
342
+ }
343
+ /**
344
+ * To remove dependency from task
345
+ *
346
+ * @param {IGanttData} ganttRecord .
347
+ * @returns {void} .
348
+ * @private
349
+ */
350
+ public removePredecessor(ganttRecord: IGanttData): void {
351
+ this.updatePredecessorHelper(ganttRecord, null);
352
+ }
353
+ /**
354
+ * To modify current dependency values of Task
355
+ *
356
+ * @param {IGanttData} ganttRecord .
357
+ * @param {string} predecessorString .
358
+ * @param {ITaskbarEditedEventArgs} editedArgs .
359
+ * @returns {boolean} .
360
+ * @private
361
+ */
362
+ public updatePredecessor(ganttRecord: IGanttData, predecessorString: string, editedArgs?: ITaskbarEditedEventArgs): boolean {
363
+ return this.updatePredecessorHelper(ganttRecord, predecessorString, editedArgs);
364
+ }
365
+
366
+ private updatePredecessorHelper(ganttRecord: IGanttData, predecessorString: string, editedArgs?: ITaskbarEditedEventArgs): boolean {
367
+ if (isUndefined(predecessorString) || this.validatePredecessorRelation(ganttRecord, predecessorString)) {
368
+ this.parent.isOnEdit = true;
369
+ let predecessorCollection: IPredecessor[] = [];
370
+ if (!isNullOrUndefined(predecessorString) && predecessorString !== '') {
371
+ predecessorCollection = this.parent.predecessorModule.calculatePredecessor(predecessorString, ganttRecord);
372
+ }
373
+ this.parent.setRecordValue(
374
+ 'predecessor',
375
+ predecessorCollection,
376
+ ganttRecord.ganttProperties,
377
+ true);
378
+ const stringValue: string = this.parent.predecessorModule.getPredecessorStringValue(ganttRecord);
379
+ this.parent.setRecordValue(
380
+ 'predecessorsName',
381
+ stringValue,
382
+ ganttRecord.ganttProperties,
383
+ true);
384
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.dependency, stringValue, ganttRecord);
385
+ this.parent.setRecordValue(this.parent.taskFields.dependency, stringValue, ganttRecord);
386
+ const args: ITaskbarEditedEventArgs = {} as ITaskbarEditedEventArgs;
387
+ args.action = editedArgs && editedArgs.action && editedArgs.action === 'CellEditing' ? editedArgs.action : 'DrawConnectorLine';
388
+ args.data = ganttRecord;
389
+ this.parent.editModule.initiateUpdateAction(args);
390
+ return true;
391
+ } else {
392
+ return false;
393
+ }
394
+ }
395
+
396
+ private checkParentRelation(ganttRecord: IGanttData, predecessorIdArray: string[]): boolean {
397
+ const editingData: IGanttData = ganttRecord;
398
+ const checkParent: boolean = true;
399
+ if (editingData && editingData.parentItem) {
400
+ if (predecessorIdArray.indexOf(editingData.parentItem.taskId.toString()) !== -1) {
401
+ return false;
402
+ }
403
+ }
404
+ for (let p: number = 0; p < predecessorIdArray.length; p++) {
405
+ const record: IGanttData[] = this.parent.currentViewData.filter((item: IGanttData) => {
406
+ return item && item.ganttProperties.rowUniqueID.toString() === predecessorIdArray[p].toString();
407
+ });
408
+ if (record[0] && record[0].hasChildRecords) {
409
+ return false;
410
+ }
411
+ }
412
+ return checkParent;
413
+ }
414
+
415
+ private initPredecessorValidationDialog(): void {
416
+ if (this.parent.taskFields.dependency && this.parent.isInPredecessorValidation) {
417
+ const dialogElement: HTMLElement = createElement('div', {
418
+ id: this.parent.element.id + '_dialogValidationRule'
419
+ });
420
+ this.parent.element.appendChild(dialogElement);
421
+ this.renderValidationDialog();
422
+ }
423
+ }
424
+
425
+ /**
426
+ * To render validation dialog
427
+ *
428
+ * @returns {void} .
429
+ * @private
430
+ */
431
+ public renderValidationDialog(): void {
432
+ const validationDialog: Dialog = new Dialog({
433
+ header: 'Validate Editing',
434
+ isModal: true,
435
+ visible: false,
436
+ width: '50%',
437
+ showCloseIcon: true,
438
+ close: this.validationDialogClose.bind(this),
439
+ content: '',
440
+ buttons: [
441
+ {
442
+ click: this.validationDialogOkButton.bind(this),
443
+ buttonModel: { content: this.parent.localeObj.getConstant('okText'), isPrimary: true }
444
+ },
445
+ {
446
+ click: this.validationDialogCancelButton.bind(this),
447
+ buttonModel: { content: this.parent.localeObj.getConstant('cancel') }
448
+ }],
449
+ target: this.parent.element,
450
+ animationSettings: { effect: 'None' }
451
+ });
452
+ document.getElementById(this.parent.element.id + '_dialogValidationRule').innerHTML = '';
453
+ validationDialog.isStringTemplate = true;
454
+ validationDialog.appendTo('#' + this.parent.element.id + '_dialogValidationRule');
455
+ this.parent.validationDialogElement = validationDialog;
456
+ }
457
+
458
+ private validationDialogOkButton(): void {
459
+ const currentArgs: IValidateArgs = this.parent.currentEditedArgs;
460
+ currentArgs.validateMode.preserveLinkWithEditing =
461
+ (document.getElementById(this.parent.element.id + '_ValidationAddlineOffset') as HTMLInputElement).checked;
462
+ currentArgs.validateMode.removeLink =
463
+ (document.getElementById(this.parent.element.id + '_ValidationRemoveline') as HTMLInputElement).checked;
464
+ currentArgs.validateMode.respectLink =
465
+ (document.getElementById(this.parent.element.id + '_ValidationCancel') as HTMLInputElement).checked;
466
+ this.applyPredecessorOption();
467
+ this.parent.validationDialogElement.hide();
468
+ }
469
+
470
+ private validationDialogCancelButton(): void {
471
+ this.parent.currentEditedArgs.validateMode.respectLink = true;
472
+ this.applyPredecessorOption();
473
+ this.parent.validationDialogElement.hide();
474
+ }
475
+
476
+ private validationDialogClose(e: object): void {
477
+ if (getValue('isInteraction', e)) {
478
+ this.parent.currentEditedArgs.validateMode.respectLink = true;
479
+ this.applyPredecessorOption();
480
+ }
481
+ }
482
+ /**
483
+ * Validate and apply the predecessor option from validation dialog
484
+ *
485
+ * @returns {void} .
486
+ * @private
487
+ */
488
+ public applyPredecessorOption(): void {
489
+ const args: IValidateArgs = this.parent.currentEditedArgs;
490
+ const ganttRecord: IGanttData = args.data;
491
+ if (args.validateMode.respectLink) {
492
+ this.parent.editModule.reUpdatePreviousRecords();
493
+ this.parent.chartRowsModule.refreshRecords([args.data]);
494
+ } else if (args.validateMode.removeLink) {
495
+ this.removePredecessors(ganttRecord, this.validationPredecessor);
496
+ this.parent.editModule.updateEditedTask(args.editEventArgs);
497
+ } else if (args.validateMode.preserveLinkWithEditing) {
498
+ this.calculateOffset(ganttRecord);
499
+ this.parent.editModule.updateEditedTask(args.editEventArgs);
500
+ }
501
+ }
502
+
503
+ private calculateOffset(record: IGanttData): void {
504
+ const prevPredecessor: IPredecessor[] = extend([], record.ganttProperties.predecessor, [], true) as IPredecessor[];
505
+ const validPredecessor: IPredecessor[] = this.parent.predecessorModule.getValidPredecessor(record);
506
+ for (let i: number = 0; i < validPredecessor.length; i++) {
507
+ const predecessor: IPredecessor = validPredecessor[i];
508
+ const parentTask: IGanttData = this.parent.connectorLineModule.getRecordByID(predecessor.from);
509
+ let offset: number;
510
+ if (isScheduledTask(parentTask.ganttProperties) && isScheduledTask(record.ganttProperties)) {
511
+ let tempStartDate: Date;
512
+ let tempEndDate: Date;
513
+ let tempDuration: number;
514
+ let isNegativeOffset: boolean;
515
+ switch (predecessor.type) {
516
+ case 'FS':
517
+ tempStartDate = new Date(parentTask.ganttProperties.endDate.getTime());
518
+ tempEndDate = new Date(record.ganttProperties.startDate.getTime());
519
+ break;
520
+ case 'SS':
521
+ tempStartDate = new Date(parentTask.ganttProperties.startDate.getTime());
522
+ tempEndDate = new Date(record.ganttProperties.startDate.getTime());
523
+ break;
524
+ case 'SF':
525
+ tempStartDate = new Date(parentTask.ganttProperties.startDate.getTime());
526
+ tempEndDate = new Date(record.ganttProperties.endDate.getTime());
527
+ break;
528
+ case 'FF':
529
+ tempStartDate = new Date(parentTask.ganttProperties.endDate.getTime());
530
+ tempEndDate = new Date(record.ganttProperties.endDate.getTime());
531
+ break;
532
+ }
533
+
534
+ if (tempStartDate.getTime() < tempEndDate.getTime()) {
535
+ tempStartDate = this.dateValidateModule.checkStartDate(tempStartDate);
536
+ tempEndDate = this.dateValidateModule.checkEndDate(tempEndDate, null);
537
+ isNegativeOffset = false;
538
+ } else {
539
+ const tempDate: Date = new Date(tempStartDate.getTime());
540
+ tempStartDate = this.dateValidateModule.checkStartDate(tempEndDate);
541
+ tempEndDate = this.dateValidateModule.checkEndDate(tempDate, null);
542
+ isNegativeOffset = true;
543
+ }
544
+ if (tempStartDate.getTime() < tempEndDate.getTime()) {
545
+ tempDuration = this.dateValidateModule.getDuration(tempStartDate, tempEndDate, predecessor.offsetUnit, true, false);
546
+ offset = isNegativeOffset ? (tempDuration * -1) : tempDuration;
547
+ } else {
548
+ offset = 0;
549
+ }
550
+ } else {
551
+ offset = 0;
552
+ }
553
+ const preIndex: number = getIndex (predecessor, 'from', prevPredecessor, 'to');
554
+ prevPredecessor[preIndex].offset = offset;
555
+ // Update predecessor in predecessor task
556
+ const parentPredecessors: IPredecessor = extend([], parentTask.ganttProperties.predecessor, [], true);
557
+ const parentPreIndex: number = getIndex(predecessor, 'from', parentPredecessors, 'to');
558
+ parentPredecessors[parentPreIndex].offset = offset;
559
+ this.parent.setRecordValue('predecessor', parentPredecessors, parentTask.ganttProperties, true);
560
+ }
561
+ this.parent.setRecordValue('predecessor', prevPredecessor, record.ganttProperties, true);
562
+ const predecessorString: string = this.parent.predecessorModule.getPredecessorStringValue(record);
563
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.dependency, predecessorString, record);
564
+ this.parent.setRecordValue(this.parent.taskFields.dependency, predecessorString, record);
565
+ this.parent.setRecordValue('predecessorsName', predecessorString, record.ganttProperties, true);
566
+ }
567
+ /**
568
+ * Update predecessor value with user selection option in predecessor validation dialog
569
+ *
570
+ * @param {IGanttData} ganttRecord .
571
+ * @param {IPredecessor[]} predecessor .
572
+ * @returns {void} .
573
+ */
574
+ private removePredecessors(ganttRecord: IGanttData, predecessor: IPredecessor[]): void {
575
+ const prevPredecessor: IPredecessor[] =
576
+ extend([], [], ganttRecord.ganttProperties.predecessor, true) as IPredecessor[];
577
+ const preLength: number = predecessor.length;
578
+ for (let i: number = 0; i < preLength; i++) {
579
+ const parentGanttRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(predecessor[i].from);
580
+ const parentPredecessor: IPredecessor[] =
581
+ extend([], [], parentGanttRecord.ganttProperties.predecessor, true) as IPredecessor[];
582
+ const index: number = getIndex(predecessor[i], 'from', prevPredecessor, 'to');
583
+ prevPredecessor.splice(index, 1);
584
+ const parentIndex: number = getIndex(predecessor[i], 'from', parentPredecessor, 'to');
585
+ parentPredecessor.splice(parentIndex, 1);
586
+ this.parent.setRecordValue('predecessor', parentPredecessor, parentGanttRecord.ganttProperties, true);
587
+ }
588
+ if (prevPredecessor.length !== ganttRecord.ganttProperties.predecessor.length) {
589
+ this.parent.setRecordValue('predecessor', prevPredecessor, ganttRecord.ganttProperties, true);
590
+ const predecessorString: string = this.parent.predecessorModule.getPredecessorStringValue(ganttRecord);
591
+ this.parent.setRecordValue('predecessorsName', predecessorString, ganttRecord.ganttProperties, true);
592
+ this.parent.setRecordValue('taskData.' + this.parent.taskFields.dependency, predecessorString, ganttRecord);
593
+ this.parent.setRecordValue(this.parent.taskFields.dependency, predecessorString, ganttRecord);
594
+ }
595
+ }
596
+
597
+ /**
598
+ * To open predecessor validation dialog
599
+ *
600
+ * @param {object} args .
601
+ * @returns {void} .
602
+ * @private
603
+ */
604
+ public openValidationDialog(args: object): void {
605
+ const contentTemplate: HTMLElement = this.validationDialogTemplate(args);
606
+ this.parent.validationDialogElement.setProperties({ content: contentTemplate });
607
+ this.parent.validationDialogElement.show();
608
+ }
609
+
610
+ /**
611
+ * Predecessor link validation dialog template
612
+ *
613
+ * @param {object} args .
614
+ * @returns {HTMLElement} .
615
+ * @private
616
+ */
617
+ public validationDialogTemplate(args: object): HTMLElement {
618
+ const ganttId: string = this.parent.element.id;
619
+ const contentdiv: HTMLElement = createElement('div', {
620
+ className: 'e-ValidationContent'
621
+ });
622
+ const taskData: IGanttData = getValue('task', args);
623
+ const parenttaskData: IGanttData = getValue('parentTask', args);
624
+ const violationType: string = getValue('violationType', args);
625
+ const recordName: string = taskData.ganttProperties.taskName;
626
+ const recordNewStartDate: string = this.parent.getFormatedDate(taskData.ganttProperties.startDate, 'MM/dd/yyyy');
627
+ const parentName: string = parenttaskData.ganttProperties.taskName;
628
+ const recordArgs: string[] = [recordName, parentName];
629
+ let topContentText: string;
630
+ if (violationType === 'taskBeforePredecessor_FS') {
631
+ topContentText = this.parent.localeObj.getConstant('taskBeforePredecessor_FS');
632
+ } else if (violationType === 'taskAfterPredecessor_FS') {
633
+ topContentText = this.parent.localeObj.getConstant('taskAfterPredecessor_FS');
634
+ } else if (violationType === 'taskBeforePredecessor_SS') {
635
+ topContentText = this.parent.localeObj.getConstant('taskBeforePredecessor_SS');
636
+ } else if (violationType === 'taskAfterPredecessor_SS') {
637
+ topContentText = this.parent.localeObj.getConstant('taskAfterPredecessor_SS');
638
+ } else if (violationType === 'taskBeforePredecessor_FF') {
639
+ topContentText = this.parent.localeObj.getConstant('taskBeforePredecessor_FF');
640
+ } else if (violationType === 'taskAfterPredecessor_FF') {
641
+ topContentText = this.parent.localeObj.getConstant('taskAfterPredecessor_FF');
642
+ } else if (violationType === 'taskBeforePredecessor_SF') {
643
+ topContentText = this.parent.localeObj.getConstant('taskBeforePredecessor_SF');
644
+ } else if (violationType === 'taskAfterPredecessor_SF') {
645
+ topContentText = this.parent.localeObj.getConstant('taskAfterPredecessor_SF');
646
+ }
647
+ topContentText = formatString(topContentText, recordArgs);
648
+ const topContent: string = '<div id="' + ganttId + '_ValidationText">' + topContentText + '<div>';
649
+ const innerTable: string = '<table>' +
650
+ '<tr><td><input type="radio" id="' + ganttId + '_ValidationCancel" name="ValidationRule" checked/><label for="'
651
+ + ganttId + '_ValidationCancel" id= "' + ganttId + '_cancelLink">Cancel, keep the existing link</label></td></tr>' +
652
+ '<tr><td><input type="radio" id="' + ganttId + '_ValidationRemoveline" name="ValidationRule"/><label for="'
653
+ + ganttId + '_ValidationRemoveline" id="' + ganttId + '_removeLink">Remove the link and move <b>'
654
+ + recordName + '</b> to start on <b>' + recordNewStartDate + '</b>.</label></td></tr>' +
655
+ '<tr><td><input type="radio" id="' + ganttId + '_ValidationAddlineOffset" name="ValidationRule"/><label for="'
656
+ + ganttId + '_ValidationAddlineOffset" id="' + ganttId + '_preserveLink">Move the <b>'
657
+ + recordName + '</b> to start on <b>' + recordNewStartDate + '</b> and keep the link.</label></td></tr></table>';
658
+ contentdiv.innerHTML = topContent + innerTable;
659
+ return contentdiv;
660
+ }
661
+
662
+ /**
663
+ * To validate the types while editing the taskbar
664
+ *
665
+ * @param {IGanttData} ganttRecord .
666
+ * @returns {boolean} .
667
+ * @private
668
+ */
669
+ public validateTypes(ganttRecord: IGanttData): object {
670
+ const predecessor: IPredecessor[] = this.parent.predecessorModule.getValidPredecessor(ganttRecord);
671
+ let parentGanttRecord: IGanttData;
672
+ this.validationPredecessor = [];
673
+ let violatedParent: IGanttData;
674
+ let violateType: string;
675
+ const startDate: Date = this.parent.predecessorModule.getPredecessorDate(ganttRecord, predecessor);
676
+ const ganttTaskData: ITaskData = ganttRecord.ganttProperties;
677
+ const endDate: Date = this.parent.allowUnscheduledTasks && isNullOrUndefined(startDate) ?
678
+ ganttTaskData.endDate :
679
+ this.dateValidateModule.getEndDate(startDate, ganttTaskData.duration, ganttTaskData.durationUnit, ganttTaskData, false);
680
+ for (let i: number = 0; i < predecessor.length; i++) {
681
+ parentGanttRecord = this.parent.connectorLineModule.getRecordByID(predecessor[i].from);
682
+ let violationType: string = null;
683
+ if (predecessor[i].type === 'FS') {
684
+ if (ganttTaskData.startDate < startDate) {
685
+ this.validationPredecessor.push(predecessor[i]);
686
+ violationType = 'taskBeforePredecessor_FS';
687
+ } else if (ganttTaskData.startDate > startDate) {
688
+ this.validationPredecessor.push(predecessor[i]);
689
+ violationType = 'taskAfterPredecessor_FS';
690
+ }
691
+ } else if (predecessor[i].type === 'SS') {
692
+ if (ganttTaskData.startDate < startDate) {
693
+ this.validationPredecessor.push(predecessor[i]);
694
+ violationType = 'taskBeforePredecessor_SS';
695
+ } else if (ganttTaskData.startDate > startDate) {
696
+ this.validationPredecessor.push(predecessor[i]);
697
+ violationType = 'taskAfterPredecessor_SS';
698
+ }
699
+ } else if (predecessor[i].type === 'FF') {
700
+ if (endDate <= parentGanttRecord.ganttProperties.endDate) {
701
+ this.validationPredecessor.push(predecessor[i]);
702
+ violationType = 'taskBeforePredecessor_FF';
703
+ } else if (endDate > parentGanttRecord.ganttProperties.endDate) {
704
+ this.validationPredecessor.push(predecessor[i]);
705
+ violationType = 'taskAfterPredecessor_FF';
706
+ }
707
+ } else if (predecessor[i].type === 'SF') {
708
+ if (endDate < parentGanttRecord.ganttProperties.startDate) {
709
+ this.validationPredecessor.push(predecessor[i]);
710
+ violationType = 'taskBeforePredecessor_SF';
711
+ } else if (endDate >= parentGanttRecord.ganttProperties.startDate) {
712
+ this.validationPredecessor.push(predecessor[i]);
713
+ violationType = 'taskAfterPredecessor_SF';
714
+ }
715
+ }
716
+ if (!isNullOrUndefined(violationType) && isNullOrUndefined(violateType)) {
717
+ violatedParent = parentGanttRecord;
718
+ violateType = violationType;
719
+ }
720
+ }
721
+ const validateArgs: object = {
722
+ parentTask: violatedParent,
723
+ task: ganttRecord,
724
+ violationType: violateType
725
+ };
726
+ return validateArgs;
727
+ }
728
+
729
+ /**
730
+ * Method to remove and update new predecessor collection in successor record
731
+ *
732
+ * @param {IGanttData} data .
733
+ * @returns {void} .
734
+ * @private
735
+ */
736
+ public addRemovePredecessor(data: IGanttData): void {
737
+ const prevData: IGanttData = this.parent.previousRecords[data.uniqueID];
738
+ const newPredecessor: IPredecessor[] = data.ganttProperties.predecessor.slice();
739
+ // eslint-disable-next-line
740
+ if (prevData && prevData.ganttProperties && prevData.ganttProperties.hasOwnProperty('predecessor')) {
741
+ const prevPredecessor: IPredecessor[] = prevData.ganttProperties.predecessor;
742
+ if (!isNullOrUndefined(prevPredecessor)) {
743
+ for (let p: number = 0; p < prevPredecessor.length; p++) {
744
+ const parentGanttRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(prevPredecessor[p].from);
745
+ if (parentGanttRecord === data) {
746
+ data.ganttProperties.predecessor.push(prevPredecessor[p]);
747
+ } else {
748
+ const parentPredecessor: IPredecessor[] =
749
+ extend([], [], parentGanttRecord.ganttProperties.predecessor, true) as IPredecessor[];
750
+ const parentIndex: number = getIndex(prevPredecessor[p], 'from', parentPredecessor, 'to');
751
+ if (parentIndex !== -1) {
752
+ parentPredecessor.splice(parentIndex, 1);
753
+ this.parent.setRecordValue('predecessor', parentPredecessor, parentGanttRecord.ganttProperties, true);
754
+ }
755
+ }
756
+ }
757
+ }
758
+ if (!isNullOrUndefined(newPredecessor)) {
759
+ for (let n: number = 0; n < newPredecessor.length; n++) {
760
+ const parentGanttRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(newPredecessor[n].from);
761
+ const parentPredecessor: IPredecessor[] =
762
+ extend([], [], parentGanttRecord.ganttProperties.predecessor, true) as IPredecessor[];
763
+ parentPredecessor.push(newPredecessor[n]);
764
+ this.parent.setRecordValue('predecessor', parentPredecessor, parentGanttRecord.ganttProperties, true);
765
+ }
766
+ }
767
+ }
768
+ }
769
+
770
+ /**
771
+ * Method to remove a predecessor from a record.
772
+ *
773
+ * @param {IGanttData} childRecord .
774
+ * @param {number} index .
775
+ * @returns {void} .
776
+ * @private
777
+ */
778
+ public removePredecessorByIndex(childRecord: IGanttData, index: number): void {
779
+ const childPredecessor: IPredecessor[] = childRecord.ganttProperties.predecessor;
780
+ const predecessor: IPredecessor = childPredecessor.splice(index, 1) as IPredecessor;
781
+ const parentRecord: IGanttData = this.parent.connectorLineModule.getRecordByID(predecessor[0].from);
782
+ const parentPredecessor: IPredecessor[] = parentRecord.ganttProperties.predecessor;
783
+ const parentIndex: number = getIndex(predecessor[0], 'from', parentPredecessor, 'to');
784
+ parentPredecessor.splice(parentIndex, 1);
785
+ const predecessorString: string = this.parent.predecessorModule.getPredecessorStringValue(childRecord);
786
+ childPredecessor.push(predecessor[0]);
787
+ this.parent.connectorLineEditModule.updatePredecessor(childRecord, predecessorString);
788
+ }
789
+
790
+ /**
791
+ * To render predecessor delete confirmation dialog
792
+ *
793
+ * @returns {void} .
794
+ * @private
795
+ */
796
+ public renderPredecessorDeleteConfirmDialog(): void {
797
+ this.confirmPredecessorDialog = new Dialog({
798
+ width: '320px',
799
+ isModal: true,
800
+ content: this.parent.localeObj.getConstant('confirmPredecessorDelete'),
801
+ buttons: [
802
+ {
803
+ click: this.confirmOkDeleteButton.bind(this),
804
+ buttonModel: { content: this.parent.localeObj.getConstant('okText'), isPrimary: true }
805
+ },
806
+ {
807
+ click: this.confirmCloseDialog.bind(this),
808
+ buttonModel: { content: this.parent.localeObj.getConstant('cancel') }
809
+ }],
810
+ target: this.parent.element,
811
+ animationSettings: { effect: 'None' }
812
+ });
813
+ const confirmDialog: HTMLElement = createElement('div', {
814
+ id: this.parent.element.id + '_deletePredecessorConfirmDialog'
815
+ });
816
+ this.parent.element.appendChild(confirmDialog);
817
+ this.confirmPredecessorDialog.isStringTemplate = true;
818
+ this.confirmPredecessorDialog.appendTo(confirmDialog);
819
+ }
820
+
821
+ private confirmCloseDialog(): void {
822
+ this.confirmPredecessorDialog.destroy();
823
+ }
824
+
825
+ private confirmOkDeleteButton(): void {
826
+ this.removePredecessorByIndex(this.childRecord, this.predecessorIndex);
827
+ this.confirmPredecessorDialog.destroy();
828
+ }
829
+ }