@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,61 @@
1
+ import { TreeGrid, ExcelExport as TreeGridExcel } from '@syncfusion/ej2-treegrid';
2
+ import { Gantt } from '../base/gantt';
3
+ import { ExcelExportCompleteArgs, ExcelHeaderQueryCellInfoEventArgs, ExcelQueryCellInfoEventArgs } from '@syncfusion/ej2-grids';
4
+
5
+ /**
6
+ * Gantt Excel Export module
7
+ *
8
+ * @hidden
9
+ */
10
+ export class ExcelExport {
11
+ private parent: Gantt;
12
+ /**
13
+ * Constructor for Excel Export module
14
+ *
15
+ * @param {Gantt} gantt .
16
+ */
17
+ constructor(gantt: Gantt) {
18
+ this.parent = gantt;
19
+ TreeGrid.Inject(TreeGridExcel);
20
+ this.parent.treeGrid.allowExcelExport = this.parent.allowExcelExport;
21
+ this.bindEvents();
22
+ }
23
+ /**
24
+ * For internal use only - Get the module name.
25
+ *
26
+ * @returns {string} .
27
+ * @private
28
+ */
29
+ protected getModuleName(): string {
30
+ return 'excelExport';
31
+ }
32
+ /**
33
+ * To destroy excel export module.
34
+ *
35
+ * @returns {void} .
36
+ * @private
37
+ */
38
+ public destroy(): void {
39
+ // Destroy Method
40
+ }
41
+ /**
42
+ * To bind excel exporting events.
43
+ *
44
+ * @returns {void} .
45
+ * @private
46
+ */
47
+ private bindEvents(): void {
48
+ this.parent.treeGrid.beforeExcelExport = (args: Object) => {
49
+ this.parent.trigger('beforeExcelExport', args);
50
+ };
51
+ this.parent.treeGrid.excelQueryCellInfo = (args: ExcelQueryCellInfoEventArgs) => {
52
+ this.parent.trigger('excelQueryCellInfo', args);
53
+ };
54
+ this.parent.treeGrid.excelHeaderQueryCellInfo = (args: ExcelHeaderQueryCellInfoEventArgs) => {
55
+ this.parent.trigger('excelHeaderQueryCellInfo', args);
56
+ };
57
+ this.parent.treeGrid.excelExportComplete = (args: ExcelExportCompleteArgs) => {
58
+ this.parent.trigger('excelExportComplete', args);
59
+ };
60
+ }
61
+ }
@@ -0,0 +1,302 @@
1
+ import { TreeGrid, Filter as TreeGridFilter, FilterSettingsModel as TreeFilterSettingsModel } from '@syncfusion/ej2-treegrid';
2
+ import { FilterEventArgs, filterAfterOpen, GroupEventArgs, getFilterMenuPostion, ColumnMenuOpenEventArgs } from '@syncfusion/ej2-grids';
3
+ import { getActualProperties, IFilterMUI, Filter as GridFilter, getCustomDateFormat } from '@syncfusion/ej2-grids';
4
+ import { Gantt } from '../base/gantt';
5
+ import { FilterSettingsModel, ColumnModel, TaskFieldsModel } from '../models/models';
6
+ import { getValue, isNullOrUndefined, remove, createElement, addClass, closest } from '@syncfusion/ej2-base';
7
+ import { DropDownList } from '@syncfusion/ej2-dropdowns';
8
+ import { NumericTextBox, TextBox } from '@syncfusion/ej2-inputs';
9
+ import { DatePicker, DateTimePicker } from '@syncfusion/ej2-calendars';
10
+
11
+ /**
12
+ * The Filter module is used to handle filter action.
13
+ */
14
+
15
+ export class Filter {
16
+ public parent: Gantt;
17
+ private filterMenuElement: HTMLElement;
18
+ constructor(gantt: Gantt) {
19
+ this.parent = gantt;
20
+ TreeGrid.Inject(TreeGridFilter);
21
+ this.parent.treeGrid.allowFiltering = this.parent.allowFiltering;
22
+ this.updateCustomFilters();
23
+ this.parent.treeGrid.filterSettings = getActualProperties(this.parent.filterSettings) as TreeFilterSettingsModel;
24
+ this.addEventListener();
25
+ }
26
+
27
+ private getModuleName(): string {
28
+ return 'filter';
29
+ }
30
+ /**
31
+ * Update custom filter for default Gantt columns
32
+ *
33
+ * @returns {void} .
34
+ */
35
+ private updateCustomFilters(): void {
36
+ const settings: TaskFieldsModel = this.parent.taskFields;
37
+ for (let i: number = 0; i < this.parent.ganttColumns.length; i++) {
38
+ const column: ColumnModel = this.parent.ganttColumns[i];
39
+ if (((column.editType === 'datepickeredit' || column.editType === 'datetimepickeredit') &&
40
+ (column.field === settings.startDate || column.field === settings.endDate
41
+ || column.field === settings.baselineStartDate || column.field === settings.baselineEndDate)) ||
42
+ (column.field === settings.duration && column.editType === 'stringedit')) {
43
+ this.initiateFiltering(this.parent.ganttColumns[i]);
44
+ }
45
+ }
46
+ }
47
+
48
+ private updateModel(): void {
49
+ this.parent.filterSettings = this.parent.treeGrid.filterSettings as FilterSettingsModel;
50
+ }
51
+ private addEventListener(): void {
52
+ this.parent.on('updateModel', this.updateModel, this);
53
+ this.parent.on('actionBegin', this.actionBegin, this);
54
+ this.parent.on('actionComplete', this.actionComplete, this);
55
+ this.parent.on('columnMenuOpen', this.columnMenuOpen, this);
56
+ }
57
+
58
+ private initiateFiltering(column: ColumnModel): void {
59
+ const treeColumn: ColumnModel = this.parent.getColumnByField(column.field, this.parent.treeGridModule.treeGridColumns);
60
+ column.allowFiltering = column.allowFiltering === false ? false : true;
61
+ if (column.allowFiltering && this.parent.filterSettings.type === 'Menu' && !column.filter) {
62
+ column.filter = { ui: this.getCustomFilterUi(column) };
63
+ }
64
+ if (treeColumn) {
65
+ treeColumn.allowFiltering = column.allowFiltering;
66
+ treeColumn.filter = column.allowFiltering ? column.filter : {};
67
+ }
68
+ }
69
+
70
+ /**
71
+ * To get filter menu UI
72
+ *
73
+ * @param {ColumnModel} column .
74
+ * @returns {IFilterMUI} .
75
+ */
76
+ private getCustomFilterUi(column: ColumnModel): IFilterMUI {
77
+ const settings: TaskFieldsModel = this.parent.taskFields;
78
+ let filterUI: IFilterMUI = {};
79
+ if (column.editType === 'datepickeredit' && (column.field === settings.startDate || column.field === settings.endDate
80
+ || column.field === settings.baselineStartDate || column.field === settings.baselineEndDate)) {
81
+ filterUI = this.getDatePickerFilter(column.field);
82
+ } else if (column.editType === 'datetimepickeredit' && (column.field === settings.startDate || column.field === settings.endDate
83
+ || column.field === settings.baselineStartDate || column.field === settings.baselineEndDate)) {
84
+ filterUI = this.getDateTimePickerFilter();
85
+ } else if (column.field === settings.duration && column.editType === 'stringedit') {
86
+ filterUI = this.getDurationFilter();
87
+ }
88
+ return filterUI;
89
+ }
90
+
91
+ private getDatePickerFilter(columnName: string): IFilterMUI {
92
+ const parent: Gantt = this.parent;
93
+ const timeValue: number = (columnName === parent.taskFields.startDate) || (columnName === parent.taskFields.baselineStartDate)
94
+ ? parent.defaultStartTime : parent.defaultEndTime;
95
+ let dropDateInstance: DatePicker;
96
+ const filterDateUI: IFilterMUI = {
97
+ create: (args: { target: Element, column: ColumnModel }) => {
98
+ const format: string = getCustomDateFormat(args.column.format, args.column.type);
99
+ const flValInput: HTMLElement = createElement('input', { className: 'flm-input' });
100
+ args.target.appendChild(flValInput);
101
+ dropDateInstance = new DatePicker({ placeholder: this.parent.localeObj.getConstant('enterValue'), format: format });
102
+ dropDateInstance.appendTo(flValInput);
103
+ },
104
+ write: (args: {
105
+ filteredValue: Date
106
+ }) => {
107
+ dropDateInstance.value = args.filteredValue;
108
+ },
109
+ read: (args: { target: Element, column: ColumnModel, operator: string, fltrObj: GridFilter }) => {
110
+ if (dropDateInstance.value) {
111
+ dropDateInstance.value.setSeconds(timeValue);
112
+ }
113
+ args.fltrObj.filterByColumn(args.column.field, args.operator, dropDateInstance.value);
114
+ }
115
+ };
116
+ return filterDateUI;
117
+ }
118
+
119
+ private getDateTimePickerFilter(): IFilterMUI {
120
+ let dropInstance: DateTimePicker;
121
+ const filterDateTimeUI: IFilterMUI = {
122
+ create: (args: { target: Element, column: ColumnModel }) => {
123
+ const format: string = getCustomDateFormat(args.column.format, args.column.type);
124
+ const flValInput: HTMLElement = createElement('input', { className: 'flm-input' });
125
+ args.target.appendChild(flValInput);
126
+ dropInstance = new DateTimePicker({ placeholder: this.parent.localeObj.getConstant('enterValue'), format: format });
127
+ dropInstance.appendTo(flValInput);
128
+ },
129
+ write: (args: {
130
+ filteredValue: Date
131
+ }) => {
132
+ dropInstance.value = args.filteredValue;
133
+ },
134
+ read: (args: { target: Element, column: ColumnModel, operator: string, fltrObj: GridFilter }) => {
135
+ args.fltrObj.filterByColumn(args.column.field, args.operator, dropInstance.value);
136
+ }
137
+ };
138
+ return filterDateTimeUI;
139
+ }
140
+
141
+ private getDurationFilter(): IFilterMUI {
142
+ const parent: Gantt = this.parent;
143
+ let textBoxInstance: TextBox;
144
+ let textValue: string = '';
145
+ const filterDurationUI: IFilterMUI = {
146
+ create: (args: { target: Element, column: Object }) => {
147
+ const flValInput: HTMLElement = createElement('input', { className: 'e-input' });
148
+ flValInput.setAttribute('placeholder', this.parent.localeObj.getConstant('enterValue'));
149
+ args.target.appendChild(flValInput);
150
+ textBoxInstance = new TextBox();
151
+ textBoxInstance.appendTo(flValInput);
152
+ },
153
+ write: (args: {
154
+ filteredValue: string
155
+ }) => {
156
+ textBoxInstance.value = args.filteredValue ? textValue : '';
157
+ },
158
+ read: (args: { element: HTMLInputElement, column: ColumnModel, operator: string, fltrObj: GridFilter }) => {
159
+ const durationObj: object = this.parent.dataOperation.getDurationValue(textBoxInstance.value);
160
+ const intVal: number = getValue('duration', durationObj);
161
+ let unit: string = getValue('durationUnit', durationObj);
162
+ if (intVal >= 0) {
163
+ let dayVal: number;
164
+ if (unit === 'minute') {
165
+ dayVal = (intVal * 60) / parent.secondsPerDay;
166
+ } else if (unit === 'hour') {
167
+ dayVal = (intVal * 60 * 60) / parent.secondsPerDay;
168
+ } else {
169
+ //Consider it as day unit
170
+ dayVal = intVal;
171
+ unit = 'day';
172
+ }
173
+ args.fltrObj.filterByColumn(args.column.field, args.operator, dayVal);
174
+ textValue = this.parent.dataOperation.getDurationString(intVal, unit);
175
+ } else {
176
+ args.fltrObj.filterByColumn(args.column.field, args.operator, null);
177
+ textValue = null;
178
+ }
179
+ }
180
+ };
181
+ return filterDurationUI;
182
+ }
183
+
184
+ /**
185
+ * Remove filter menu while opening column chooser menu
186
+ *
187
+ * @param {ColumnMenuOpenEventArgs} args .
188
+ * @returns {void} .
189
+ */
190
+ private columnMenuOpen(args: ColumnMenuOpenEventArgs): void {// eslint-disable-line
191
+ if (this.filterMenuElement && document.body.contains(this.filterMenuElement)) {
192
+ remove(this.filterMenuElement);
193
+ }
194
+ this.filterMenuElement = null;
195
+ }
196
+ // eslint-disable-next-line
197
+ private actionBegin(args: FilterEventArgs): void {
198
+ // ...
199
+ }
200
+ public closeFilterOnContextClick(element: Element): void {
201
+ if (this.filterMenuElement && document.body.contains(this.filterMenuElement)) {
202
+ const ganttElement: Element = closest(element, '#' + this.parent.element.id)
203
+ || element.querySelector('#' + this.parent.element.id);
204
+ if ((!(this.filterMenuElement.contains(element)) && !isNullOrUndefined(ganttElement)) || element.nodeName === 'HTML'
205
+ || ((element.nodeName === 'DIV') && (!element.classList.contains('e-day')))) {
206
+ remove(this.filterMenuElement);
207
+ this.parent.treeGrid.grid.notify('filter-menu-close', { isOpen: false });
208
+ this.filterMenuElement = null;
209
+ }
210
+ }
211
+ }
212
+ private actionComplete(args: GroupEventArgs): void {
213
+ if (args.requestType === filterAfterOpen) {
214
+ if (this.parent.treeGrid.filterSettings.type === 'Menu') {
215
+ this.filterMenuElement = getValue('filterModel.dlgObj.element', args);
216
+ }
217
+ else {
218
+ this.filterMenuElement = getValue('filterModel.dialogObj.element', args);
219
+ }
220
+ this.updateFilterMenuPosition(this.filterMenuElement, args);
221
+ // To set default values as 'contains' in filter dialog
222
+ const taskID: string = this.parent.taskFields.id;
223
+ const predecessor: string = this.parent.taskFields.dependency;
224
+ const resource: string = this.parent.taskFields.resourceInfo;
225
+ const filterObj: object = this.parent.treeGrid.grid.filterModule;
226
+ const filterValues: object = getValue('values', filterObj);
227
+ if ((args.columnName === predecessor && isNullOrUndefined(getValue(predecessor, filterValues)))
228
+ || (args.columnName === resource && isNullOrUndefined(getValue(resource, filterValues)))) {
229
+ const element: HTMLElement = this.filterMenuElement.querySelector('.e-dropdownlist');
230
+ const instanceObj: DropDownList = getValue('ej2_instances[0]', element);
231
+ instanceObj.index = 2;
232
+ instanceObj.dataBind();
233
+ } else if (args.columnName === taskID && isNullOrUndefined(getValue(taskID, filterValues)) && this.parent.treeGrid.filterSettings.type === 'Menu') {
234
+ const element: HTMLElement = this.filterMenuElement.querySelector('.e-numerictextbox');
235
+ const instanceObj: NumericTextBox = getValue('ej2_instances[0]', element);
236
+ if (!isNullOrUndefined(instanceObj) && isNullOrUndefined(this.parent.columnByField[args.columnName].format)) {
237
+ instanceObj.format = 'n';
238
+ }
239
+ }
240
+ }
241
+ }
242
+ private setPosition(li: Element, ul: HTMLElement): void {
243
+ const gridPos: ClientRect = this.parent.element.getBoundingClientRect();
244
+ const liPos: ClientRect = li.getBoundingClientRect();
245
+ let left: number = liPos.right + window.scrollX;
246
+ const top: number = liPos.top + window.scrollY;
247
+
248
+ if (gridPos.right < (left + ul.offsetWidth)) {
249
+ if ((liPos.left - ul.offsetWidth) > gridPos.left) {
250
+ left = (liPos.left - ul.offsetWidth);
251
+ } else {
252
+ left -= (left + ul.offsetWidth) - gridPos.right;
253
+ }
254
+ }
255
+ ul.style.top = top + 'px';
256
+ ul.style.left = left + 'px';
257
+ }
258
+
259
+ private updateFilterMenuPosition(element: HTMLElement, args: GroupEventArgs): void {
260
+ addClass([element], 'e-gantt');
261
+ document.body.appendChild(element);
262
+ let targetElement: HTMLElement;
263
+ if (this.parent.showColumnMenu) {
264
+ targetElement = document.querySelector('#treeGrid' + this.parent.controlId + '_gridcontrol_colmenu_Filter');
265
+ element.style.zIndex = targetElement.parentElement.style.zIndex;
266
+ if (this.parent.treeGrid.filterSettings.type === 'Menu') {
267
+ this.setPosition(targetElement, getValue('filterModel.dlgObj.element', args));
268
+ }
269
+ else {
270
+ this.setPosition(targetElement, getValue('filterModel.dialogObj.element', args));
271
+ }
272
+ } else {
273
+ targetElement = this.parent.treeGrid.grid.getColumnHeaderByField(args.columnName).querySelector('.e-filtermenudiv');
274
+ if (this.parent.treeGrid.filterSettings.type === 'Menu') {
275
+ getFilterMenuPostion(targetElement, getValue('filterModel.dlgObj', args));
276
+ }
277
+ else {
278
+ getFilterMenuPostion(targetElement, getValue('filterModel.dialogObj', args));
279
+ }
280
+ }
281
+ if (this.parent.treeGrid.filterSettings.type === 'Menu') {
282
+ (element.querySelector('.e-valid-input') as HTMLElement).focus();
283
+ }
284
+ }
285
+ private removeEventListener(): void {
286
+ if (this.parent.isDestroyed) {
287
+ return;
288
+ }
289
+ this.parent.off('updateModel', this.updateModel);
290
+ this.parent.off('actionBegin', this.actionBegin);
291
+ this.parent.off('actionComplete', this.actionComplete);
292
+ this.parent.off('columnMenuOpen', this.columnMenuOpen);
293
+ }
294
+ /**
295
+ * To destroy module
296
+ *
297
+ * @returns {void} .
298
+ */
299
+ public destroy(): void {
300
+ this.removeEventListener();
301
+ }
302
+ }
@@ -0,0 +1,306 @@
1
+ import { Gantt } from '../base/gantt';
2
+ import { KeyboardEventArgs, isNullOrUndefined, getValue } from '@syncfusion/ej2-base';
3
+ import { IKeyPressedEventArgs, IGanttData, ColumnModel, ITaskData } from '..';
4
+ import { TextBox } from '@syncfusion/ej2-inputs';
5
+ import { ISelectedCell, IIndex } from '@syncfusion/ej2-grids';
6
+ import { ContextMenu } from '@syncfusion/ej2-navigations/src/context-menu';
7
+ interface EJ2Instance extends HTMLElement {
8
+ // eslint-disable-next-line
9
+ ej2_instances: Object[];
10
+ }
11
+ /**
12
+ * Focus module is used to handle certain action on focus elements in keyboard navigations.
13
+ */
14
+
15
+ export class FocusModule {
16
+ private parent: Gantt;
17
+ private activeElement: HTMLElement;
18
+ private previousActiveElement: HTMLElement;
19
+ constructor(parent: Gantt) {
20
+ this.parent = parent;
21
+ this.activeElement = null;
22
+ this.previousActiveElement = null;
23
+ }
24
+
25
+ public getActiveElement(isPreviousActiveElement?: boolean): HTMLElement {
26
+ return isPreviousActiveElement ? this.previousActiveElement : this.activeElement;
27
+ }
28
+
29
+ public setActiveElement(element: HTMLElement): void {
30
+ this.previousActiveElement = this.activeElement;
31
+ this.activeElement = element;
32
+ }
33
+
34
+ /**
35
+ * To perform key interaction in Gantt
36
+ *
37
+ * @param {KeyboardEventArgs} e .
38
+ * @returns {void} .
39
+ * @private
40
+ */
41
+ public onKeyPress(e: KeyboardEventArgs): void | boolean {
42
+ const ganttObj: Gantt = this.parent;
43
+ const expandedRecords: IGanttData[] = ganttObj.getExpandedRecords(ganttObj.currentViewData);
44
+ if (isNullOrUndefined(this.parent.focusModule.getActiveElement()) && (e.action === 'expandAll' || e.action === 'collapseAll')) {
45
+ const focussedElement: HTMLElement = this.parent.element.querySelector('.e-treegrid');
46
+ focussedElement.focus();
47
+ }
48
+ const targetElement: Element = this.parent.focusModule.getActiveElement();
49
+ if (e.action === 'home' || e.action === 'end' || e.action === 'downArrow' || e.action === 'upArrow' || e.action === 'delete' ||
50
+ e.action === 'rightArrow' || e.action === 'leftArrow' || e.action === 'focusTask' || e.action === 'focusSearch' ||
51
+ e.action === 'expandAll' || e.action === 'collapseAll') {
52
+ if (!isNullOrUndefined(ganttObj.editModule) && !isNullOrUndefined(ganttObj.editModule.cellEditModule) &&
53
+ ganttObj.editModule.cellEditModule.isCellEdit === true) {
54
+ return;
55
+ }
56
+ }
57
+ if (ganttObj.isAdaptive) {
58
+ if (e.action === 'addRowDialog' || e.action === 'editRowDialog' || e.action === 'delete'
59
+ || e.action === 'addRow') {
60
+ if (ganttObj.selectionModule && ganttObj.selectionSettings.type === 'Multiple') {
61
+ ganttObj.selectionModule.hidePopUp();
62
+ (<HTMLElement>document.getElementsByClassName('e-gridpopup')[0]).style.display = 'none';
63
+ }
64
+ }
65
+ }
66
+ switch (e.action) {
67
+ case 'home':
68
+ if (ganttObj.selectionModule && ganttObj.selectionSettings.mode !== 'Cell') {
69
+ if (ganttObj.selectedRowIndex === 0) {
70
+ return;
71
+ }
72
+ ganttObj.selectionModule.selectRow(0, false, true);
73
+ }
74
+ break;
75
+ case 'end':
76
+ if (ganttObj.selectionModule && ganttObj.selectionSettings.mode !== 'Cell') {
77
+ const currentSelectingRecord: IGanttData = expandedRecords[expandedRecords.length - 1];
78
+ if (ganttObj.selectedRowIndex === ganttObj.flatData.indexOf(currentSelectingRecord)) {
79
+ return;
80
+ }
81
+ ganttObj.selectionModule.selectRow(ganttObj.flatData.indexOf(currentSelectingRecord), false, true);
82
+ }
83
+ break;
84
+ case 'downArrow':
85
+ case 'upArrow':
86
+ {
87
+ const searchElement: HTMLInputElement = ganttObj.element.querySelector('#' + ganttObj.element.id + '_searchbar');
88
+ if (searchElement && searchElement.parentElement.classList.contains('e-input-focus')) {
89
+ ganttObj.selectionModule.clearSelection();
90
+ }
91
+ if (!ganttObj.element.classList.contains('e-scroll-disabled')) {
92
+ this.upDownKeyNavigate(e);
93
+ if (!isNullOrUndefined(targetElement) && !isNullOrUndefined(targetElement.closest('.e-chart-row'))) {
94
+ ganttObj.ganttChartModule.manageFocus(this.getActiveElement(), 'remove', true);
95
+ }
96
+ }
97
+ break;
98
+ }
99
+ case 'expandAll':
100
+ ganttObj.ganttChartModule.expandCollapseAll('expand');
101
+ break;
102
+ case 'collapseAll':
103
+ ganttObj.ganttChartModule.expandCollapseAll('collapse');
104
+ break;
105
+ case 'expandRow':
106
+ case 'collapseRow':
107
+ this.expandCollapseKey(e);
108
+ break;
109
+ case 'saveRequest':
110
+ if (!isNullOrUndefined(ganttObj.editModule) && !isNullOrUndefined(ganttObj.editModule.cellEditModule) &&
111
+ ganttObj.editModule.cellEditModule.isCellEdit) {
112
+ const col: ColumnModel = ganttObj.editModule.cellEditModule.editedColumn;
113
+ if (col.field === ganttObj.columnMapping.duration && !isNullOrUndefined(col.edit) &&
114
+ !isNullOrUndefined(col.edit.read)) {
115
+ const textBox: TextBox = <TextBox>(<EJ2Instance>e.target).ej2_instances[0];
116
+ const textValue: string = (e.target as HTMLInputElement).value;
117
+ const ganttProp: ITaskData = ganttObj.currentViewData[ganttObj.selectedRowIndex].ganttProperties;
118
+ let tempValue: string | Date | number;
119
+ if (col.field === ganttObj.columnMapping.duration) {
120
+ tempValue = !isNullOrUndefined(col.edit) && !isNullOrUndefined(col.edit.read) ? (col.edit.read as Function)() :
121
+ // eslint-disable-next-line
122
+ !isNullOrUndefined(col.valueAccessor) ? (col.valueAccessor as Function)(ganttObj.columnMapping.duration, ganttObj.editedRecords, col) :
123
+ ganttObj.dataOperation.getDurationString(ganttProp.duration, ganttProp.durationUnit);
124
+ if (textValue !== tempValue.toString()) {
125
+ textBox.value = textValue;
126
+ textBox.dataBind();
127
+ }
128
+ }
129
+ }
130
+ if (ganttObj.editModule.dialogModule.dialogObj && getValue('dialogOpen', ganttObj.editModule.dialogModule.dialogObj)) {
131
+ return;
132
+ }
133
+ ganttObj.editModule.cellEditModule.isCellEdit = false;
134
+ ganttObj.treeGrid.grid.saveCell();
135
+ const focussedElement: HTMLElement = <HTMLElement>ganttObj.element.querySelector('.e-treegrid');
136
+ focussedElement.focus();
137
+ }
138
+ if (!isNullOrUndefined(this.parent.onTaskbarClick) && !isNullOrUndefined(targetElement)
139
+ && !isNullOrUndefined(targetElement.closest('.e-chart-row'))) {
140
+ const target: EventTarget = e.target;
141
+ const taskbarElement: Element = targetElement.querySelector('.e-gantt-parent-taskbar,' +
142
+ '.e-gantt-child-taskbar,.e-gantt-milestone');
143
+ if (taskbarElement) {
144
+ this.parent.ganttChartModule.onTaskbarClick(e, target, taskbarElement);
145
+ }
146
+ }
147
+ break;
148
+ case 'cancelRequest':
149
+ if (!isNullOrUndefined(ganttObj.editModule) && !isNullOrUndefined(ganttObj.editModule.cellEditModule)) {
150
+ ganttObj.editModule.cellEditModule.isCellEdit = false;
151
+ if (!isNullOrUndefined(ganttObj.toolbarModule)) {
152
+ ganttObj.toolbarModule.refreshToolbarItems();
153
+ }
154
+ }
155
+ break;
156
+ case 'addRow':
157
+ {
158
+ if (isNullOrUndefined(document.getElementById(this.parent.element.id + '_dialog'))) {
159
+ e.preventDefault();
160
+ ganttObj.addRecord(undefined, this.parent.editSettings.newRowPosition);
161
+ const focussedElement: HTMLElement = <HTMLElement>ganttObj.element;
162
+ focussedElement.focus();
163
+ }
164
+ break;
165
+ }
166
+ case 'addRowDialog':
167
+ e.preventDefault();
168
+ if (ganttObj.editModule && ganttObj.editModule.dialogModule && ganttObj.editSettings.allowAdding) {
169
+ if (ganttObj.editModule.dialogModule.dialogObj && getValue('dialogOpen', ganttObj.editModule.dialogModule.dialogObj)) {
170
+ return;
171
+ }
172
+ ganttObj.editModule.dialogModule.openAddDialog();
173
+ }
174
+ break;
175
+ case 'editRowDialog':
176
+ {
177
+ e.preventDefault();
178
+ const focussedTreeElement: HTMLElement = <HTMLElement>ganttObj.element.querySelector('.e-treegrid');
179
+ focussedTreeElement.focus();
180
+ if (ganttObj.editModule && ganttObj.editModule.dialogModule && ganttObj.editSettings.allowEditing) {
181
+ if (ganttObj.editModule.dialogModule.dialogObj && getValue('dialogOpen', ganttObj.editModule.dialogModule.dialogObj)) {
182
+ return;
183
+ }
184
+ ganttObj.editModule.dialogModule.openToolbarEditDialog();
185
+ }
186
+ break;
187
+ }
188
+ case 'delete':
189
+ if (ganttObj.selectionModule && ganttObj.editModule && (!ganttObj.editModule.dialogModule.dialogObj ||
190
+ (ganttObj.editModule.dialogModule.dialogObj &&
191
+ !ganttObj.editModule.dialogModule.dialogObj.visible)) && (!ganttObj.editSettings.allowTaskbarEditing
192
+ || (ganttObj.editSettings.allowTaskbarEditing && !ganttObj.editModule.taskbarEditModule.touchEdit))) {
193
+ if ((ganttObj.selectionSettings.mode !== 'Cell' && ganttObj.selectionModule.selectedRowIndexes.length)
194
+ || (ganttObj.selectionSettings.mode === 'Cell' && ganttObj.selectionModule.getSelectedRowCellIndexes().length)) {
195
+ ganttObj.editModule.startDeleteAction();
196
+ }
197
+ }
198
+ break;
199
+ case 'focusTask':
200
+ {
201
+ e.preventDefault();
202
+ let selectedId: string;
203
+ if (ganttObj.selectionModule) {
204
+ const currentViewData: IGanttData[] = ganttObj.currentViewData;
205
+ if (ganttObj.selectionSettings.mode !== 'Cell' &&
206
+ !isNullOrUndefined(currentViewData[ganttObj.selectedRowIndex])) {
207
+ selectedId = ganttObj.currentViewData[ganttObj.selectedRowIndex].ganttProperties.rowUniqueID;
208
+ } else if (ganttObj.selectionSettings.mode === 'Cell' &&
209
+ ganttObj.selectionModule.getSelectedRowCellIndexes().length > 0) {
210
+ const selectCellIndex: ISelectedCell[] = ganttObj.selectionModule.getSelectedRowCellIndexes();
211
+ selectedId = currentViewData[selectCellIndex[selectCellIndex.length - 1].rowIndex].ganttProperties.rowUniqueID;
212
+ }
213
+ }
214
+ if (selectedId) {
215
+ ganttObj.scrollToTask(selectedId.toString());
216
+ }
217
+ break;
218
+ }
219
+ case 'focusSearch':
220
+ {
221
+ if (<HTMLInputElement>ganttObj.element.querySelector('#' + ganttObj.element.id + '_searchbar')) {
222
+ const searchElement: HTMLInputElement =
223
+ <HTMLInputElement>ganttObj.element.querySelector('#' + ganttObj.element.id + '_searchbar');
224
+ searchElement.setAttribute('tabIndex', '-1');
225
+ searchElement.focus();
226
+ }
227
+ break;
228
+ }
229
+ case 'tab':
230
+ case 'shiftTab':
231
+ if (!ganttObj.element.classList.contains('e-scroll-disabled')) {
232
+ ganttObj.ganttChartModule.onTabAction(e);
233
+ }
234
+ break;
235
+ case 'contextMenu':
236
+ {
237
+ const contextMenu: ContextMenu = <ContextMenu>(<EJ2Instance>document.getElementById(this.parent.element.id +
238
+ '_contextmenu')).ej2_instances[0];
239
+ const containerPosition: { top: number, left: number, width?: number, height?: number } =
240
+ this.parent.getOffsetRect(e.target as HTMLElement);
241
+ const top: number = containerPosition.top + (containerPosition.height / 2);
242
+ const left: number = containerPosition.left + (containerPosition.width / 2);
243
+ this.setActiveElement(e.target as HTMLElement);
244
+ contextMenu.open(top, left);
245
+ e.preventDefault();
246
+ break;
247
+ }
248
+ default:
249
+ {
250
+ const eventArgs: IKeyPressedEventArgs = {
251
+ requestType: 'keyPressed',
252
+ action: e.action,
253
+ keyEvent: e
254
+ };
255
+ ganttObj.trigger('actionComplete', eventArgs);
256
+ break;
257
+ }
258
+ }
259
+ }
260
+ private upDownKeyNavigate(e: KeyboardEventArgs): void {
261
+ e.preventDefault();
262
+ const ganttObj: Gantt = this.parent;
263
+ const expandedRecords: IGanttData[] = ganttObj.getExpandedRecords(ganttObj.currentViewData);
264
+ if (ganttObj.selectionModule) {
265
+ if (ganttObj.selectionSettings.mode !== 'Cell' && ganttObj.selectedRowIndex !== -1) {
266
+ const selectedItem: IGanttData = ganttObj.currentViewData[ganttObj.selectedRowIndex];
267
+ const focusedRowIndex: number = this.parent.ganttChartModule.focusedRowIndex;
268
+ const selectingRowIndex: number = focusedRowIndex > -1 ? focusedRowIndex : expandedRecords.indexOf(selectedItem);
269
+ const currentSelectingRecord: IGanttData = e.action === 'downArrow' ? expandedRecords[selectingRowIndex + 1] :
270
+ expandedRecords[selectingRowIndex - 1];
271
+ ganttObj.selectionModule.selectRow(ganttObj.currentViewData.indexOf(currentSelectingRecord), false, true);
272
+ } else if (ganttObj.selectionSettings.mode === 'Cell' && ganttObj.selectionModule.getSelectedRowCellIndexes().length > 0) {
273
+ const selectCellIndex: ISelectedCell[] = ganttObj.selectionModule.getSelectedRowCellIndexes();
274
+ const selectedCellItem: ISelectedCell = selectCellIndex[selectCellIndex.length - 1];
275
+ const currentCellIndex: number = selectedCellItem.cellIndexes[selectedCellItem.cellIndexes.length - 1];
276
+ const selectedItem: IGanttData = ganttObj.currentViewData[selectedCellItem.rowIndex];
277
+ const selectingRowIndex: number = expandedRecords.indexOf(selectedItem);
278
+ const currentSelectingRecord: IGanttData = e.action === 'downArrow' ? expandedRecords[selectingRowIndex + 1] :
279
+ expandedRecords[selectingRowIndex - 1];
280
+ const cellInfo: IIndex = {
281
+ rowIndex: ganttObj.currentViewData.indexOf(currentSelectingRecord),
282
+ cellIndex: currentCellIndex
283
+ };
284
+ ganttObj.selectionModule.selectCell(cellInfo);
285
+ }
286
+ this.parent.ganttChartModule.focusedRowIndex = this.parent.selectedRowIndex;
287
+ }
288
+ }
289
+ private expandCollapseKey(e: KeyboardEventArgs): void {
290
+ const ganttObj: Gantt = this.parent;
291
+ if (ganttObj.selectionModule && ganttObj.selectedRowIndex !== -1) {
292
+ let selectedRowIndex: number;
293
+ if (ganttObj.selectionSettings.mode !== 'Cell') {
294
+ selectedRowIndex = ganttObj.selectedRowIndex;
295
+ } else if (ganttObj.selectionSettings.mode === 'Cell' && ganttObj.selectionModule.getSelectedRowCellIndexes().length > 0) {
296
+ const selectCellIndex: ISelectedCell[] = ganttObj.selectionModule.getSelectedRowCellIndexes();
297
+ selectedRowIndex = selectCellIndex[selectCellIndex.length - 1].rowIndex;
298
+ }
299
+ if (e.action === 'expandRow') {
300
+ ganttObj.expandByIndex(selectedRowIndex);
301
+ } else {
302
+ ganttObj.collapseByIndex(selectedRowIndex);
303
+ }
304
+ }
305
+ }
306
+ }