@syncfusion/ej2-schedule 30.2.4 → 31.1.17

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 (308) hide show
  1. package/dist/ej2-schedule.min.js +2 -2
  2. package/dist/ej2-schedule.umd.min.js +2 -2
  3. package/dist/ej2-schedule.umd.min.js.map +1 -1
  4. package/dist/es6/ej2-schedule.es2015.js +132 -43
  5. package/dist/es6/ej2-schedule.es2015.js.map +1 -1
  6. package/dist/es6/ej2-schedule.es5.js +132 -43
  7. package/dist/es6/ej2-schedule.es5.js.map +1 -1
  8. package/dist/global/ej2-schedule.min.js +2 -2
  9. package/dist/global/ej2-schedule.min.js.map +1 -1
  10. package/dist/global/index.d.ts +1 -1
  11. package/dist/ts/common/calendar-util.d.ts +92 -0
  12. package/dist/ts/common/calendar-util.ts +261 -0
  13. package/dist/ts/common/index.d.ts +4 -0
  14. package/dist/ts/common/index.ts +4 -0
  15. package/dist/ts/components.d.ts +5 -0
  16. package/dist/ts/components.ts +5 -0
  17. package/dist/ts/index.d.ts +6 -0
  18. package/dist/ts/index.ts +7 -0
  19. package/dist/ts/recurrence-editor/date-generator.d.ts +76 -0
  20. package/dist/ts/recurrence-editor/date-generator.ts +1699 -0
  21. package/dist/ts/recurrence-editor/index.d.ts +6 -0
  22. package/dist/ts/recurrence-editor/index.ts +6 -0
  23. package/dist/ts/recurrence-editor/recurrence-editor-model.d.ts +112 -0
  24. package/dist/ts/recurrence-editor/recurrence-editor.d.ts +245 -0
  25. package/dist/ts/recurrence-editor/recurrence-editor.ts +1257 -0
  26. package/dist/ts/schedule/actions/action-base.d.ts +44 -0
  27. package/dist/ts/schedule/actions/action-base.ts +493 -0
  28. package/dist/ts/schedule/actions/crud.d.ts +41 -0
  29. package/dist/ts/schedule/actions/crud.ts +784 -0
  30. package/dist/ts/schedule/actions/data.d.ts +63 -0
  31. package/dist/ts/schedule/actions/data.ts +128 -0
  32. package/dist/ts/schedule/actions/drag.d.ts +75 -0
  33. package/dist/ts/schedule/actions/drag.ts +1401 -0
  34. package/dist/ts/schedule/actions/keyboard.d.ts +100 -0
  35. package/dist/ts/schedule/actions/keyboard.ts +1435 -0
  36. package/dist/ts/schedule/actions/resize.d.ts +27 -0
  37. package/dist/ts/schedule/actions/resize.ts +602 -0
  38. package/dist/ts/schedule/actions/scroll.d.ts +69 -0
  39. package/dist/ts/schedule/actions/scroll.ts +105 -0
  40. package/dist/ts/schedule/actions/touch.d.ts +32 -0
  41. package/dist/ts/schedule/actions/touch.ts +314 -0
  42. package/dist/ts/schedule/actions/virtual-scroll.d.ts +55 -0
  43. package/dist/ts/schedule/actions/virtual-scroll.ts +596 -0
  44. package/dist/ts/schedule/actions/work-cells.d.ts +14 -0
  45. package/dist/ts/schedule/actions/work-cells.ts +151 -0
  46. package/dist/ts/schedule/base/constant.d.ts +102 -0
  47. package/dist/ts/schedule/base/constant.ts +103 -0
  48. package/dist/ts/schedule/base/css-constant.d.ts +475 -0
  49. package/dist/ts/schedule/base/css-constant.ts +475 -0
  50. package/dist/ts/schedule/base/interface.d.ts +673 -0
  51. package/dist/ts/schedule/base/interface.ts +738 -0
  52. package/dist/ts/schedule/base/resource.d.ts +59 -0
  53. package/dist/ts/schedule/base/resource.ts +1091 -0
  54. package/dist/ts/schedule/base/schedule-model.d.ts +930 -0
  55. package/dist/ts/schedule/base/schedule.d.ts +1967 -0
  56. package/dist/ts/schedule/base/schedule.ts +4221 -0
  57. package/dist/ts/schedule/base/type.d.ts +134 -0
  58. package/dist/ts/schedule/base/type.ts +142 -0
  59. package/dist/ts/schedule/base/util.d.ts +266 -0
  60. package/dist/ts/schedule/base/util.ts +492 -0
  61. package/dist/ts/schedule/event-renderer/agenda-base.d.ts +15 -0
  62. package/dist/ts/schedule/event-renderer/agenda-base.ts +423 -0
  63. package/dist/ts/schedule/event-renderer/event-base.d.ts +101 -0
  64. package/dist/ts/schedule/event-renderer/event-base.ts +1501 -0
  65. package/dist/ts/schedule/event-renderer/inline-edit.d.ts +23 -0
  66. package/dist/ts/schedule/event-renderer/inline-edit.ts +287 -0
  67. package/dist/ts/schedule/event-renderer/month.d.ts +60 -0
  68. package/dist/ts/schedule/event-renderer/month.ts +760 -0
  69. package/dist/ts/schedule/event-renderer/timeline-view.d.ts +51 -0
  70. package/dist/ts/schedule/event-renderer/timeline-view.ts +606 -0
  71. package/dist/ts/schedule/event-renderer/vertical-view.d.ts +57 -0
  72. package/dist/ts/schedule/event-renderer/vertical-view.ts +898 -0
  73. package/dist/ts/schedule/event-renderer/year.d.ts +27 -0
  74. package/dist/ts/schedule/event-renderer/year.ts +623 -0
  75. package/dist/ts/schedule/exports/calendar-export.d.ts +16 -0
  76. package/dist/ts/schedule/exports/calendar-export.ts +160 -0
  77. package/dist/ts/schedule/exports/calendar-import.d.ts +18 -0
  78. package/dist/ts/schedule/exports/calendar-import.ts +277 -0
  79. package/dist/ts/schedule/exports/excel-export.d.ts +14 -0
  80. package/dist/ts/schedule/exports/excel-export.ts +89 -0
  81. package/dist/ts/schedule/exports/index.d.ts +7 -0
  82. package/dist/ts/schedule/exports/index.ts +7 -0
  83. package/dist/ts/schedule/exports/print.d.ts +20 -0
  84. package/dist/ts/schedule/exports/print.ts +233 -0
  85. package/dist/ts/schedule/index.d.ts +26 -0
  86. package/dist/ts/schedule/index.ts +26 -0
  87. package/dist/ts/schedule/models/event-settings-model.d.ts +165 -0
  88. package/dist/ts/schedule/models/event-settings.d.ts +149 -0
  89. package/dist/ts/schedule/models/event-settings.ts +187 -0
  90. package/dist/ts/schedule/models/field-options-model.d.ts +37 -0
  91. package/dist/ts/schedule/models/field-options.d.ts +31 -0
  92. package/dist/ts/schedule/models/field-options.ts +41 -0
  93. package/dist/ts/schedule/models/fields-model.d.ts +129 -0
  94. package/dist/ts/schedule/models/fields.d.ts +117 -0
  95. package/dist/ts/schedule/models/fields.ts +149 -0
  96. package/dist/ts/schedule/models/group-model.d.ts +69 -0
  97. package/dist/ts/schedule/models/group.d.ts +60 -0
  98. package/dist/ts/schedule/models/group.ts +75 -0
  99. package/dist/ts/schedule/models/header-rows-model.d.ts +33 -0
  100. package/dist/ts/schedule/models/header-rows.d.ts +30 -0
  101. package/dist/ts/schedule/models/header-rows.ts +35 -0
  102. package/dist/ts/schedule/models/models.d.ts +14 -0
  103. package/dist/ts/schedule/models/models.ts +15 -0
  104. package/dist/ts/schedule/models/quick-info-templates-model.d.ts +52 -0
  105. package/dist/ts/schedule/models/quick-info-templates.d.ts +47 -0
  106. package/dist/ts/schedule/models/quick-info-templates.ts +56 -0
  107. package/dist/ts/schedule/models/resources-model.d.ts +122 -0
  108. package/dist/ts/schedule/models/resources.d.ts +106 -0
  109. package/dist/ts/schedule/models/resources.ts +138 -0
  110. package/dist/ts/schedule/models/time-scale-model.d.ts +57 -0
  111. package/dist/ts/schedule/models/time-scale.d.ts +50 -0
  112. package/dist/ts/schedule/models/time-scale.ts +61 -0
  113. package/dist/ts/schedule/models/toolbar-model.d.ts +196 -0
  114. package/dist/ts/schedule/models/toolbar.d.ts +176 -0
  115. package/dist/ts/schedule/models/toolbar.ts +196 -0
  116. package/dist/ts/schedule/models/views-model.d.ts +370 -0
  117. package/dist/ts/schedule/models/views.d.ts +335 -0
  118. package/dist/ts/schedule/models/views.ts +408 -0
  119. package/dist/ts/schedule/models/work-hours-model.d.ts +29 -0
  120. package/dist/ts/schedule/models/work-hours.d.ts +24 -0
  121. package/dist/ts/schedule/models/work-hours.ts +31 -0
  122. package/dist/ts/schedule/popups/event-tooltip.d.ts +16 -0
  123. package/dist/ts/schedule/popups/event-tooltip.ts +203 -0
  124. package/dist/ts/schedule/popups/event-window.d.ts +118 -0
  125. package/dist/ts/schedule/popups/event-window.ts +2055 -0
  126. package/dist/ts/schedule/popups/form-validator.d.ts +16 -0
  127. package/dist/ts/schedule/popups/form-validator.ts +110 -0
  128. package/dist/ts/schedule/popups/quick-popups.d.ts +78 -0
  129. package/dist/ts/schedule/popups/quick-popups.ts +1470 -0
  130. package/dist/ts/schedule/renderer/agenda.d.ts +45 -0
  131. package/dist/ts/schedule/renderer/agenda.ts +497 -0
  132. package/dist/ts/schedule/renderer/day.d.ts +20 -0
  133. package/dist/ts/schedule/renderer/day.ts +28 -0
  134. package/dist/ts/schedule/renderer/header-renderer.d.ts +48 -0
  135. package/dist/ts/schedule/renderer/header-renderer.ts +736 -0
  136. package/dist/ts/schedule/renderer/month-agenda.d.ts +29 -0
  137. package/dist/ts/schedule/renderer/month-agenda.ts +184 -0
  138. package/dist/ts/schedule/renderer/month.d.ts +61 -0
  139. package/dist/ts/schedule/renderer/month.ts +766 -0
  140. package/dist/ts/schedule/renderer/renderer.d.ts +13 -0
  141. package/dist/ts/schedule/renderer/renderer.ts +165 -0
  142. package/dist/ts/schedule/renderer/timeline-header-row.d.ts +15 -0
  143. package/dist/ts/schedule/renderer/timeline-header-row.ts +132 -0
  144. package/dist/ts/schedule/renderer/timeline-month.d.ts +29 -0
  145. package/dist/ts/schedule/renderer/timeline-month.ts +184 -0
  146. package/dist/ts/schedule/renderer/timeline-view.d.ts +31 -0
  147. package/dist/ts/schedule/renderer/timeline-view.ts +308 -0
  148. package/dist/ts/schedule/renderer/timeline-year.d.ts +22 -0
  149. package/dist/ts/schedule/renderer/timeline-year.ts +450 -0
  150. package/dist/ts/schedule/renderer/vertical-view.d.ts +63 -0
  151. package/dist/ts/schedule/renderer/vertical-view.ts +911 -0
  152. package/dist/ts/schedule/renderer/view-base.d.ts +83 -0
  153. package/dist/ts/schedule/renderer/view-base.ts +709 -0
  154. package/dist/ts/schedule/renderer/week.d.ts +22 -0
  155. package/dist/ts/schedule/renderer/week.ts +35 -0
  156. package/dist/ts/schedule/renderer/work-week.d.ts +22 -0
  157. package/dist/ts/schedule/renderer/work-week.ts +36 -0
  158. package/dist/ts/schedule/renderer/year.d.ts +46 -0
  159. package/dist/ts/schedule/renderer/year.ts +470 -0
  160. package/dist/ts/schedule/timezone/timezone.d.ts +16 -0
  161. package/dist/ts/schedule/timezone/timezone.ts +313 -0
  162. package/package.json +56 -21
  163. package/src/schedule/actions/action-base.js +3 -0
  164. package/src/schedule/actions/drag.js +11 -4
  165. package/src/schedule/actions/keyboard.js +1 -1
  166. package/src/schedule/actions/resize.js +9 -5
  167. package/src/schedule/actions/virtual-scroll.js +3 -0
  168. package/src/schedule/base/css-constant.d.ts +2 -0
  169. package/src/schedule/base/css-constant.js +2 -0
  170. package/src/schedule/base/schedule.js +15 -1
  171. package/src/schedule/event-renderer/agenda-base.d.ts +1 -1
  172. package/src/schedule/event-renderer/agenda-base.js +5 -4
  173. package/src/schedule/event-renderer/inline-edit.js +11 -6
  174. package/src/schedule/event-renderer/month.js +5 -3
  175. package/src/schedule/event-renderer/vertical-view.js +3 -0
  176. package/src/schedule/event-renderer/year.d.ts +2 -0
  177. package/src/schedule/event-renderer/year.js +28 -4
  178. package/src/schedule/popups/event-tooltip.js +4 -0
  179. package/src/schedule/popups/event-window.js +2 -2
  180. package/src/schedule/popups/quick-popups.js +5 -1
  181. package/src/schedule/renderer/agenda.js +3 -2
  182. package/src/schedule/renderer/month.js +9 -7
  183. package/src/schedule/renderer/vertical-view.js +1 -1
  184. package/src/schedule/renderer/view-base.d.ts +2 -0
  185. package/src/schedule/renderer/view-base.js +9 -0
  186. package/src/schedule/renderer/year.js +3 -2
  187. package/styles/bds-lite.css +11 -8
  188. package/styles/bds.css +11 -8
  189. package/styles/bootstrap-dark-lite.css +12 -9
  190. package/styles/bootstrap-dark.css +12 -9
  191. package/styles/bootstrap-lite.css +12 -9
  192. package/styles/bootstrap.css +12 -9
  193. package/styles/bootstrap4-lite.css +11 -8
  194. package/styles/bootstrap4.css +11 -8
  195. package/styles/bootstrap5-dark-lite.css +11 -8
  196. package/styles/bootstrap5-dark.css +11 -8
  197. package/styles/bootstrap5-lite.css +11 -8
  198. package/styles/bootstrap5.3-lite.css +11 -8
  199. package/styles/bootstrap5.3.css +11 -8
  200. package/styles/bootstrap5.css +11 -8
  201. package/styles/fabric-dark-lite.css +12 -9
  202. package/styles/fabric-dark.css +12 -9
  203. package/styles/fabric-lite.css +12 -9
  204. package/styles/fabric.css +12 -9
  205. package/styles/fluent-dark-lite.css +13 -10
  206. package/styles/fluent-dark.css +13 -10
  207. package/styles/fluent-lite.css +13 -10
  208. package/styles/fluent.css +13 -10
  209. package/styles/fluent2-lite.css +11 -8
  210. package/styles/fluent2.css +11 -8
  211. package/styles/highcontrast-light-lite.css +12 -9
  212. package/styles/highcontrast-light.css +12 -9
  213. package/styles/highcontrast-lite.css +12 -9
  214. package/styles/highcontrast.css +12 -9
  215. package/styles/material-dark-lite.css +12 -9
  216. package/styles/material-dark.css +12 -9
  217. package/styles/material-lite.css +12 -9
  218. package/styles/material.css +12 -9
  219. package/styles/material3-dark-lite.css +11 -8
  220. package/styles/material3-dark.css +11 -8
  221. package/styles/material3-lite.css +11 -8
  222. package/styles/material3.css +11 -8
  223. package/styles/recurrence-editor/_bds-definition.scss +1 -0
  224. package/styles/recurrence-editor/_bootstrap-dark-definition.scss +1 -0
  225. package/styles/recurrence-editor/_bootstrap-definition.scss +1 -0
  226. package/styles/recurrence-editor/_bootstrap4-definition.scss +1 -0
  227. package/styles/recurrence-editor/_bootstrap5-definition.scss +1 -0
  228. package/styles/recurrence-editor/_bootstrap5.3-definition.scss +1 -0
  229. package/styles/recurrence-editor/_fabric-dark-definition.scss +1 -0
  230. package/styles/recurrence-editor/_fabric-definition.scss +1 -0
  231. package/styles/recurrence-editor/_fluent-definition.scss +1 -0
  232. package/styles/recurrence-editor/_fluent2-definition.scss +1 -0
  233. package/styles/recurrence-editor/_fusionnew-definition.scss +1 -0
  234. package/styles/recurrence-editor/_highcontrast-definition.scss +1 -0
  235. package/styles/recurrence-editor/_highcontrast-light-definition.scss +1 -0
  236. package/styles/recurrence-editor/_layout.scss +5 -1
  237. package/styles/recurrence-editor/_material-dark-definition.scss +1 -0
  238. package/styles/recurrence-editor/_material-definition.scss +1 -0
  239. package/styles/recurrence-editor/_material3-definition.scss +1 -0
  240. package/styles/recurrence-editor/_tailwind-definition.scss +1 -0
  241. package/styles/recurrence-editor/_tailwind3-definition.scss +1 -0
  242. package/styles/recurrence-editor/bds.css +3 -0
  243. package/styles/recurrence-editor/bootstrap-dark.css +4 -1
  244. package/styles/recurrence-editor/bootstrap.css +4 -1
  245. package/styles/recurrence-editor/bootstrap4.css +3 -0
  246. package/styles/recurrence-editor/bootstrap5-dark.css +3 -0
  247. package/styles/recurrence-editor/bootstrap5.3.css +3 -0
  248. package/styles/recurrence-editor/bootstrap5.css +3 -0
  249. package/styles/recurrence-editor/fabric-dark.css +4 -1
  250. package/styles/recurrence-editor/fabric.css +4 -1
  251. package/styles/recurrence-editor/fluent-dark.css +4 -1
  252. package/styles/recurrence-editor/fluent.css +4 -1
  253. package/styles/recurrence-editor/fluent2.css +3 -0
  254. package/styles/recurrence-editor/highcontrast-light.css +4 -1
  255. package/styles/recurrence-editor/highcontrast.css +4 -1
  256. package/styles/recurrence-editor/material-dark.css +4 -1
  257. package/styles/recurrence-editor/material.css +4 -1
  258. package/styles/recurrence-editor/material3-dark.css +3 -0
  259. package/styles/recurrence-editor/material3.css +3 -0
  260. package/styles/recurrence-editor/tailwind-dark.css +3 -0
  261. package/styles/recurrence-editor/tailwind.css +3 -0
  262. package/styles/recurrence-editor/tailwind3.css +3 -0
  263. package/styles/schedule/_bds-definition.scss +2 -0
  264. package/styles/schedule/_bootstrap-dark-definition.scss +2 -0
  265. package/styles/schedule/_bootstrap-definition.scss +2 -0
  266. package/styles/schedule/_bootstrap4-definition.scss +2 -0
  267. package/styles/schedule/_bootstrap5-definition.scss +2 -0
  268. package/styles/schedule/_bootstrap5.3-definition.scss +2 -0
  269. package/styles/schedule/_fabric-dark-definition.scss +2 -0
  270. package/styles/schedule/_fabric-definition.scss +2 -0
  271. package/styles/schedule/_fluent-definition.scss +3 -1
  272. package/styles/schedule/_fluent2-definition.scss +2 -0
  273. package/styles/schedule/_fusionnew-definition.scss +2 -0
  274. package/styles/schedule/_highcontrast-definition.scss +2 -0
  275. package/styles/schedule/_highcontrast-light-definition.scss +2 -0
  276. package/styles/schedule/_layout.scss +12 -11
  277. package/styles/schedule/_material-dark-definition.scss +2 -0
  278. package/styles/schedule/_material-definition.scss +2 -0
  279. package/styles/schedule/_material3-definition.scss +2 -0
  280. package/styles/schedule/_tailwind-definition.scss +2 -0
  281. package/styles/schedule/_tailwind3-definition.scss +2 -0
  282. package/styles/schedule/bds.css +8 -8
  283. package/styles/schedule/bootstrap-dark.css +8 -8
  284. package/styles/schedule/bootstrap.css +8 -8
  285. package/styles/schedule/bootstrap4.css +8 -8
  286. package/styles/schedule/bootstrap5-dark.css +8 -8
  287. package/styles/schedule/bootstrap5.3.css +8 -8
  288. package/styles/schedule/bootstrap5.css +8 -8
  289. package/styles/schedule/fabric-dark.css +8 -8
  290. package/styles/schedule/fabric.css +8 -8
  291. package/styles/schedule/fluent-dark.css +9 -9
  292. package/styles/schedule/fluent.css +9 -9
  293. package/styles/schedule/fluent2.css +8 -8
  294. package/styles/schedule/highcontrast-light.css +8 -8
  295. package/styles/schedule/highcontrast.css +8 -8
  296. package/styles/schedule/material-dark.css +8 -8
  297. package/styles/schedule/material.css +8 -8
  298. package/styles/schedule/material3-dark.css +8 -8
  299. package/styles/schedule/material3.css +8 -8
  300. package/styles/schedule/tailwind-dark.css +8 -8
  301. package/styles/schedule/tailwind.css +8 -8
  302. package/styles/schedule/tailwind3.css +8 -8
  303. package/styles/tailwind-dark-lite.css +11 -8
  304. package/styles/tailwind-dark.css +11 -8
  305. package/styles/tailwind-lite.css +11 -8
  306. package/styles/tailwind.css +11 -8
  307. package/styles/tailwind3-lite.css +11 -8
  308. package/styles/tailwind3.css +11 -8
@@ -0,0 +1,1091 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable max-len */
3
+ import { extend, isNullOrUndefined, createElement, EventHandler, addClass, append, removeClass, remove, closest, classList } from '@syncfusion/ej2-base';
4
+ import { DataManager, Query } from '@syncfusion/ej2-data';
5
+ import { TreeView, NodeClickEventArgs } from '@syncfusion/ej2-navigations';
6
+ import { Popup } from '@syncfusion/ej2-popups';
7
+ import { Data } from '../actions/data';
8
+ import { Schedule } from '../base/schedule';
9
+ import { ReturnType } from '../base/type';
10
+ import { TdData, ResourceDetails, NotifyEventArgs, ActionEventArgs, RenderCellEventArgs, CallbackFunction } from '../base/interface';
11
+ import { ResourcesModel } from '../models/resources-model';
12
+ import * as cls from '../base/css-constant';
13
+ import * as events from '../base/constant';
14
+ import * as util from '../base/util';
15
+
16
+ /**
17
+ * Resource and group related common functionalities
18
+ */
19
+
20
+ interface TreeSlotData extends TdData {
21
+ child: TdData[];
22
+ }
23
+
24
+ export class ResourceBase {
25
+ private parent: Schedule;
26
+ public resourceCollection: ResourcesModel[] = [];
27
+ public lastResourceLevel: TdData[];
28
+ public renderedResources: TdData[];
29
+ public expandedResources: TdData[];
30
+ private colorIndex: number;
31
+ private resourceTreeLevel: TdData[];
32
+ private treeViewObj: TreeView;
33
+ private treePopup: Popup;
34
+ private popupOverlay: HTMLElement;
35
+ private leftPixel: number = 25;
36
+ public resourceDateTree: TdData[][] = [];
37
+
38
+ constructor(parent: Schedule) {
39
+ this.parent = parent;
40
+ }
41
+
42
+ public renderResourceHeaderIndent(tr: Element): void {
43
+ const resColTd: Element = createElement('td', { className: cls.RESOURCE_LEFT_TD_CLASS });
44
+ const resColDiv: Element = createElement('div', { className: cls.RESOURCE_TEXT_CLASS });
45
+ if (this.parent.activeViewOptions.headerIndentTemplate) {
46
+ const data: TdData = { className: [resColTd.className], type: 'emptyCells' };
47
+ this.parent.renderHeaderIndentTemplate(data, resColTd);
48
+ } else {
49
+ resColTd.appendChild(resColDiv);
50
+ }
51
+ const args: RenderCellEventArgs = { elementType: 'emptyCells', element: resColTd };
52
+ this.parent.trigger(events.renderCell, args);
53
+ tr.appendChild(resColTd);
54
+ }
55
+
56
+ public hideResourceRows(tBody: Element): void {
57
+ if (this.resourceCollection.length <= 1 || this.parent.virtualScrollModule) {
58
+ return;
59
+ }
60
+ const trCount: number = this.lastResourceLevel.length;
61
+ for (let i: number = 0; i < trCount; i++) {
62
+ const resData: Record<string, any> = this.lastResourceLevel[parseInt(i.toString(), 10)].resourceData;
63
+ const res: ResourcesModel = this.lastResourceLevel[parseInt(i.toString(), 10)].resource;
64
+ if (resData.ClassName === cls.RESOURCE_PARENT_CLASS && !resData[res.expandedField] &&
65
+ !isNullOrUndefined(resData[res.expandedField])) {
66
+ const trCollection: HTMLElement[] = [].slice.call(tBody.children);
67
+ const slicedCollection: HTMLElement[] = trCollection.slice(i + 1, i + (parseInt(resData.Count as string, 10) + 1));
68
+ addClass(slicedCollection, cls.HIDDEN_CLASS);
69
+ }
70
+ }
71
+ }
72
+
73
+ public createResourceColumn(): Element {
74
+ const resColl: ResourcesModel[] = this.resourceCollection;
75
+ const resDiv: Element = createElement('div', { className: cls.RESOURCE_COLUMN_WRAP_CLASS });
76
+ const tbl: Element = this.parent.activeView.createTableLayout(cls.RESOURCE_COLUMN_TABLE_CLASS);
77
+ if (!this.parent.uiStateValues.isGroupAdaptive && this.parent.rowAutoHeight && this.parent.activeView.isTimelineView()
78
+ && this.parent.activeViewOptions.group.resources.length > 0) {
79
+ addClass([tbl], cls.AUTO_HEIGHT);
80
+ }
81
+ const tBody: Element = tbl.querySelector('tbody');
82
+ let resData: TdData[] = this.generateTreeData(true) as TdData[];
83
+ this.countCalculation(resColl.slice(0, -2), resColl.slice(0, -1));
84
+ this.renderedResources = this.lastResourceLevel;
85
+ if (this.parent.virtualScrollModule) {
86
+ const resourceCount: number = this.parent.virtualScrollModule.getRenderedCount();
87
+ this.setExpandedResources();
88
+ resData = this.expandedResources.slice(0, resourceCount);
89
+ this.renderedResources = resData;
90
+ }
91
+ append(this.getContentRows(resData), tBody);
92
+ this.hideResourceRows(tBody);
93
+ tbl.appendChild(tBody);
94
+ resDiv.appendChild(tbl);
95
+ return resDiv;
96
+ }
97
+
98
+ public setRenderedResources(): void {
99
+ const resColl: ResourcesModel[] = this.resourceCollection;
100
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
101
+ const temp: TdData[] = this.generateTreeData(true) as TdData[];
102
+ this.countCalculation(resColl.slice(0, -2), resColl.slice(0, -1));
103
+ this.renderedResources = this.lastResourceLevel;
104
+ }
105
+
106
+ public setExpandedResources(): void {
107
+ const resources: TdData[] = [];
108
+ for (let i: number = 0; i < this.lastResourceLevel.length; i++) {
109
+ const resource: Record<string, any> = this.lastResourceLevel[parseInt(i.toString(), 10)].resourceData;
110
+ const count: number = resource.Count as number;
111
+ resources.push(this.lastResourceLevel[parseInt(i.toString(), 10)]);
112
+ const isExpanded: boolean = resource[this.lastResourceLevel[parseInt(i.toString(), 10)].resource.expandedField] as boolean;
113
+ if (!isNullOrUndefined(isExpanded) && !isExpanded && count > 0) {
114
+ i = i + count;
115
+ }
116
+ }
117
+ this.expandedResources = resources;
118
+ }
119
+
120
+ public getContentRows(resData: TdData[], isVirtualScroll?: boolean): Element[] {
121
+ const resRows: Element[] = [];
122
+ let left: string;
123
+ let rIndex: number;
124
+ const resColl: ResourcesModel[] = this.resourceCollection;
125
+ const tr: Element = createElement('tr');
126
+ const td: Element = createElement('td', { attrs: { tabindex: isVirtualScroll ? '-1' : '0' } });
127
+ const existingGroupIndices: number[] = this.parent.activeView.getGroupIndices();
128
+ for (let i: number = 0; i < resData.length; i++) {
129
+ if (existingGroupIndices.length > 0 && existingGroupIndices.indexOf(resData[parseInt(i.toString(), 10)].groupIndex) > -1) {
130
+ continue;
131
+ }
132
+ const ntd: Element = td.cloneNode() as Element;
133
+ rIndex = util.findIndexInData(<Record<string, any>[]>resColl, 'name', resData[parseInt(i.toString(), 10)].resource.name);
134
+ if (rIndex === resColl.length - 1) {
135
+ extend(resData[parseInt(i.toString(), 10)].resourceData, { ClassName: cls.RESOURCE_CHILD_CLASS });
136
+ this.renderedResources[parseInt(i.toString(), 10)].className = [cls.RESOURCE_CHILD_CLASS];
137
+ } else {
138
+ extend(resData[parseInt(i.toString(), 10)].resourceData, { ClassName: cls.RESOURCE_PARENT_CLASS });
139
+ this.renderedResources[parseInt(i.toString(), 10)].className = [cls.RESOURCE_PARENT_CLASS];
140
+ }
141
+ left = (rIndex * this.leftPixel) + 'px';
142
+ if (resData[parseInt(i.toString(), 10)].resourceData.ClassName as string === cls.RESOURCE_PARENT_CLASS
143
+ && !isNullOrUndefined(resData[parseInt(i.toString(), 10)].resourceData.Count) && (resData[parseInt(i.toString(), 10)].resourceData.Count > 0)) {
144
+ let iconClass: string;
145
+ if (resData[parseInt(i.toString(), 10)].resourceData[resColl[parseInt(rIndex.toString(), 10)].expandedField] ||
146
+ isNullOrUndefined(resData[parseInt(i.toString(), 10)].resourceData[resColl[parseInt(rIndex.toString(), 10)].expandedField])) {
147
+ iconClass = cls.RESOURCE_COLLAPSE_CLASS;
148
+ } else {
149
+ iconClass = cls.RESOURCE_EXPAND_CLASS;
150
+ }
151
+ const iconDiv: HTMLElement = createElement('div');
152
+ addClass([iconDiv], [cls.RESOURCE_TREE_ICON_CLASS, iconClass]);
153
+ this.setMargin(iconDiv, left);
154
+ ntd.appendChild(iconDiv);
155
+ if (this.resourceCollection.length > 1) {
156
+ EventHandler.add(iconDiv, 'click', this.onTreeIconClick, this);
157
+ }
158
+ }
159
+ this.parent.activeView.setResourceHeaderContent(ntd, resData[parseInt(i.toString(), 10)], cls.RESOURCE_TEXT_CLASS);
160
+ ntd.setAttribute('data-group-index', resData[parseInt(i.toString(), 10)].groupIndex.toString());
161
+ ntd.setAttribute('aria-label', (resData[parseInt(i.toString(), 10)].resourceData[resData[parseInt(i.toString(), 10)].resource.textField] as string) + ' resource');
162
+ if (!this.parent.activeViewOptions.resourceHeaderTemplate) {
163
+ this.setMargin(ntd.querySelector('.' + cls.RESOURCE_TEXT_CLASS) as HTMLElement, left);
164
+ }
165
+ const classCollection: string[] = [cls.RESOURCE_CELLS_CLASS, resData[parseInt(i.toString(), 10)].resourceData.ClassName as string];
166
+ addClass([ntd], classCollection);
167
+ const args: RenderCellEventArgs = { elementType: 'resourceHeader', element: ntd, groupIndex: resData[parseInt(i.toString(), 10)].groupIndex };
168
+ this.parent.trigger(events.renderCell, args);
169
+ const ntr: Element = tr.cloneNode() as Element;
170
+ ntr.appendChild(ntd);
171
+ resRows.push(ntr);
172
+ }
173
+ return resRows;
174
+ }
175
+
176
+ private setMargin(element: HTMLElement, value: string): void {
177
+ if (!this.parent.enableRtl) {
178
+ element.style.marginLeft = value;
179
+ } else {
180
+ element.style.marginRight = value;
181
+ }
182
+ }
183
+
184
+ private countCalculation(parentCollection: ResourcesModel[], wholeCollection: ResourcesModel[]): void {
185
+ let collection: Record<string, any>[];
186
+ for (let y: number = 0; y < parentCollection.length; y++) {
187
+ const data: Record<string, any>[] = parentCollection[parentCollection.length - (y + 1)].dataSource as Record<string, any>[];
188
+ for (let x: number = 0; x < data.length; x++) {
189
+ let totalCount: number = 0;
190
+ if (this.parent.activeViewOptions.group.byGroupID) {
191
+ const query: Query =
192
+ new Query().where(wholeCollection[wholeCollection.length - 1].groupIDField, 'equal',
193
+ data[parseInt(x.toString(), 10)][parentCollection[parentCollection.length - (y + 1)].idField] as string);
194
+ collection = new DataManager(wholeCollection[wholeCollection.length - 1].dataSource).executeLocal(query) as Record<string, any>[];
195
+ } else {
196
+ collection = wholeCollection[wholeCollection.length - 1].dataSource as Record<string, any>[];
197
+ }
198
+ for (let z: number = 0; z < collection.length; z++) {
199
+ totalCount = totalCount + parseInt(collection[parseInt(z.toString(), 10)].Count as string, 10);
200
+ }
201
+ totalCount = totalCount + parseInt(data[parseInt(x.toString(), 10)].Count as string, 10);
202
+ extend(data[parseInt(x.toString(), 10)], { Count: totalCount });
203
+ }
204
+ wholeCollection = wholeCollection.slice(0, -1);
205
+ }
206
+ }
207
+
208
+ public onTreeIconClick(e: Event): void {
209
+ if (this.parent.eventTooltip) {
210
+ this.parent.eventTooltip.close();
211
+ }
212
+ const target: Element = <HTMLElement>e.target;
213
+ let hide: boolean;
214
+ const trElement: HTMLTableRowElement = closest(target as Element, '.' + cls.RESOURCE_PARENT_CLASS)
215
+ .parentElement as HTMLTableRowElement;
216
+ const index: number = parseInt(trElement.children[0].getAttribute('data-group-index'), 10);
217
+ let args: ActionEventArgs = {
218
+ cancel: false, event: e, groupIndex: index,
219
+ requestType: !target.classList.contains(cls.RESOURCE_COLLAPSE_CLASS) ? 'resourceExpand' : 'resourceCollapse'
220
+ };
221
+ this.parent.trigger(events.actionBegin, args, (actionArgs: ActionEventArgs) => {
222
+ if (!actionArgs.cancel) {
223
+ if (target.classList.contains(cls.RESOURCE_COLLAPSE_CLASS)) {
224
+ classList(target, [cls.RESOURCE_EXPAND_CLASS], [cls.RESOURCE_COLLAPSE_CLASS]);
225
+ hide = true;
226
+ } else {
227
+ classList(target, [cls.RESOURCE_COLLAPSE_CLASS], [cls.RESOURCE_EXPAND_CLASS]);
228
+ hide = false;
229
+ }
230
+ const eventElements: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.APPOINTMENT_CLASS + ',.' + cls.MORE_INDICATOR_CLASS));
231
+ for (const element of eventElements) {
232
+ remove(element);
233
+ }
234
+ if (this.parent.virtualScrollModule) {
235
+ this.updateVirtualContent(index, hide, e, target);
236
+ } else {
237
+ this.updateContent(index, hide);
238
+ }
239
+ const data: NotifyEventArgs = { cssProperties: this.parent.getCssProperties(), module: 'scroll' };
240
+ this.parent.notify(events.scrollUiUpdate, data);
241
+ args = {
242
+ cancel: false, event: e, groupIndex: index,
243
+ requestType: target.classList.contains(cls.RESOURCE_COLLAPSE_CLASS) ? 'resourceExpanded' : 'resourceCollapsed'
244
+ };
245
+ this.parent.refreshEvents(false);
246
+ this.parent.trigger(events.actionComplete, args);
247
+ }
248
+ });
249
+ }
250
+
251
+ public updateContent(index: number, hide: boolean): void {
252
+ const rowCollection: HTMLTableRowElement[] = [];
253
+ const workCellCollection: HTMLTableRowElement[] = [];
254
+ const headerRowCollection: HTMLTableRowElement[] = [];
255
+ let pNode: boolean;
256
+ const clickedRes: Record<string, any> = this.lastResourceLevel[parseInt(index.toString(), 10)].resourceData as Record<string, any>;
257
+ const resRows: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.RESOURCE_COLUMN_WRAP_CLASS + ' ' + 'tr'));
258
+ const contentRows: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.CONTENT_WRAP_CLASS + ' ' + 'tbody tr'));
259
+ const eventRows: Element[] = [].slice.call(this.parent.element.querySelectorAll('.' + cls.CONTENT_WRAP_CLASS + ' .' + cls.APPOINTMENT_CONTAINER_CLASS));
260
+ for (let j: number = 0; j < clickedRes.Count; j++) {
261
+ rowCollection.push(resRows[index + j + 1] as HTMLTableRowElement);
262
+ workCellCollection.push(contentRows[index + j + 1] as HTMLTableRowElement);
263
+ headerRowCollection.push(eventRows[index + j + 1] as HTMLTableRowElement);
264
+ }
265
+ const clonedCollection: TdData[] = this.lastResourceLevel;
266
+ for (let i: number = 0; i < rowCollection.length; i++) {
267
+ let expanded: boolean = true;
268
+ pNode = rowCollection[parseInt(i.toString(), 10)].children[0].classList.contains(cls.RESOURCE_PARENT_CLASS);
269
+ clonedCollection[parseInt(index.toString(), 10)].resourceData[clonedCollection[parseInt(index.toString(), 10)].resource.expandedField] = !hide;
270
+ if (hide) {
271
+ if (pNode) {
272
+ const trElem: Element = rowCollection[parseInt(i.toString(), 10)].querySelector('.' + cls.RESOURCE_TREE_ICON_CLASS);
273
+ if (trElem) {
274
+ classList(trElem, [cls.RESOURCE_EXPAND_CLASS], [cls.RESOURCE_COLLAPSE_CLASS]);
275
+ }
276
+ }
277
+ if (!rowCollection[parseInt(i.toString(), 10)].classList.contains(cls.HIDDEN_CLASS)) {
278
+ addClass([rowCollection[parseInt(i.toString(), 10)], workCellCollection[parseInt(i.toString(), 10)], headerRowCollection[parseInt(i.toString(), 10)]], cls.HIDDEN_CLASS);
279
+ }
280
+ } else {
281
+ if (pNode) {
282
+ const rowIndex: number = rowCollection[parseInt(i.toString(), 10)].rowIndex;
283
+ if (!clonedCollection[parseInt(rowIndex.toString(), 10)].resourceData[clonedCollection[parseInt(rowIndex.toString(), 10)].resource.expandedField]
284
+ && !isNullOrUndefined(clonedCollection[parseInt(rowIndex.toString(), 10)].resourceData[clonedCollection[parseInt(rowIndex.toString(), 10)].resource.expandedField])) {
285
+ rowCollection.splice(i + 1, (parseInt(clonedCollection[parseInt(rowIndex.toString(), 10)].resourceData.Count as string, 10)));
286
+ workCellCollection.splice(i + 1, (parseInt(clonedCollection[parseInt(rowIndex.toString(), 10)].resourceData.Count as string, 10)));
287
+ headerRowCollection.splice(i + 1, (parseInt(clonedCollection[parseInt(rowIndex.toString(), 10)].resourceData.Count as string, 10)));
288
+ expanded = false;
289
+ }
290
+ if (expanded) {
291
+ const trElem: Element = rowCollection[parseInt(i.toString(), 10)].querySelector('.' + cls.RESOURCE_TREE_ICON_CLASS);
292
+ if (trElem) {
293
+ classList(trElem, [cls.RESOURCE_COLLAPSE_CLASS], [cls.RESOURCE_EXPAND_CLASS]);
294
+ }
295
+ }
296
+ }
297
+ if (rowCollection[parseInt(i.toString(), 10)].classList.contains(cls.HIDDEN_CLASS)) {
298
+ removeClass([rowCollection[parseInt(i.toString(), 10)], workCellCollection[parseInt(i.toString(), 10)], headerRowCollection[parseInt(i.toString(), 10)]], cls.HIDDEN_CLASS);
299
+ }
300
+ }
301
+ }
302
+ }
303
+
304
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
305
+ public updateVirtualContent(index: number, expand: boolean, e: Event, target: Element): void {
306
+ this.lastResourceLevel[parseInt(index.toString(), 10)].resourceData[this.lastResourceLevel[parseInt(index.toString(), 10)].resource.expandedField] = !expand;
307
+ this.setExpandedResources();
308
+ const resourceCount: number = this.parent.virtualScrollModule.getRenderedCount();
309
+ const startIndex: number = this.expandedResources.indexOf(this.renderedResources[0]);
310
+ this.parent.virtualScrollModule.existingDataCollection = this.renderedResources;
311
+ this.renderedResources = this.expandedResources.slice(startIndex, startIndex + resourceCount);
312
+ if (this.renderedResources.length < resourceCount) {
313
+ let sIndex: number = this.expandedResources.length - resourceCount;
314
+ sIndex = (sIndex > 0) ? sIndex : 0;
315
+ this.renderedResources = this.expandedResources.slice(sIndex, this.expandedResources.length);
316
+ }
317
+ const virtualTrack: HTMLElement = this.parent.element.querySelector('.' + cls.VIRTUAL_TRACK_CLASS);
318
+ this.parent.virtualScrollModule.updateVirtualTrackHeight(virtualTrack);
319
+ const resTable: HTMLElement =
320
+ this.parent.element.querySelector('.' + cls.RESOURCE_COLUMN_WRAP_CLASS + ' ' + 'table') as HTMLElement;
321
+ const contentTable: HTMLElement =
322
+ this.parent.element.querySelector('.' + cls.CONTENT_WRAP_CLASS + ' ' + 'table') as HTMLElement;
323
+ const eventTable: HTMLElement = this.parent.element.querySelector('.' + cls.EVENT_TABLE_CLASS) as HTMLElement;
324
+ this.parent.virtualScrollModule.updateContent(resTable, contentTable, eventTable, this.renderedResources);
325
+ const timeIndicator: HTMLElement = this.parent.element.querySelector('.' + cls.CURRENT_TIMELINE_CLASS) as HTMLElement;
326
+ if (!isNullOrUndefined(timeIndicator)) {
327
+ timeIndicator.style.height =
328
+ (this.parent.element.querySelector('.' + cls.CONTENT_TABLE_CLASS) as HTMLElement).offsetHeight + 'px';
329
+ }
330
+ }
331
+
332
+ public renderResourceHeader(): void {
333
+ const resourceWrapper: HTMLElement = createElement('div', { className: cls.RESOURCE_TOOLBAR_CONTAINER });
334
+ resourceWrapper.innerHTML = '<div class="' + cls.RESOURCE_HEADER_TOOLBAR + '"><div class="' + cls.RESOURCE_MENU + '">' +
335
+ '<div class="e-icons ' + cls.RESOURCE_MENU_ICON + '"></div></div><div class="' + cls.RESOURCE_LEVEL_TITLE + '"></div></div>';
336
+ if (this.parent.currentView === 'MonthAgenda') {
337
+ const target: Element = this.parent.activeView.getPanel().querySelector('.' + cls.CONTENT_WRAP_CLASS);
338
+ target.insertBefore(resourceWrapper, target.querySelector('.' + cls.WRAPPER_CONTAINER_CLASS));
339
+ } else {
340
+ this.parent.element.insertBefore(resourceWrapper, this.parent.element.querySelector('.' + cls.TABLE_CONTAINER_CLASS));
341
+ }
342
+ this.renderResourceHeaderText();
343
+ EventHandler.add(resourceWrapper.querySelector('.' + cls.RESOURCE_MENU_ICON), 'click', this.menuClick, this);
344
+ }
345
+
346
+ public renderResourceTree(): void {
347
+ this.popupOverlay = createElement('div', { className: cls.RESOURCE_TREE_POPUP_OVERLAY });
348
+ const treeWrapper: HTMLElement = createElement('div', { className: cls.RESOURCE_TREE_POPUP + ' e-popup-close' });
349
+ if (this.parent.currentView === 'MonthAgenda') {
350
+ const target: Element = this.parent.activeView.getPanel().querySelector('.' + cls.WRAPPER_CONTAINER_CLASS);
351
+ target.insertBefore(treeWrapper, target.children[0]);
352
+ target.appendChild(this.popupOverlay);
353
+ } else {
354
+ this.parent.element.querySelector('.' + cls.TABLE_CONTAINER_CLASS).appendChild(treeWrapper);
355
+ this.parent.element.querySelector('.' + cls.TABLE_CONTAINER_CLASS).appendChild(this.popupOverlay);
356
+ }
357
+ const resourceTree: HTMLElement = createElement('div', { className: cls.RESOURCE_TREE });
358
+ treeWrapper.appendChild(resourceTree);
359
+ this.treeViewObj = new TreeView({
360
+ cssClass: this.parent.cssClass,
361
+ enableRtl: this.parent.enableRtl,
362
+ enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
363
+ fields: {
364
+ dataSource: [].slice.call(this.generateTreeData()) as Record<string, any>[],
365
+ id: 'resourceId',
366
+ text: 'resourceName',
367
+ child: 'resourceChild'
368
+ },
369
+ nodeTemplate: this.parent.resourceHeaderTemplate as any,
370
+ nodeClicked: this.resourceClick.bind(this),
371
+ created: this.resourceTreeCreated.bind(this)
372
+ });
373
+ this.treeViewObj.root = this.parent.root ? this.parent.root : this.parent;
374
+ this.treeViewObj.appendTo(resourceTree);
375
+ this.treeViewObj.expandAll();
376
+ this.treePopup = new Popup(treeWrapper, {
377
+ targetType: 'relative',
378
+ actionOnScroll: 'none',
379
+ content: this.treeViewObj.element,
380
+ relateTo: this.parent.element.querySelector('.' + cls.TABLE_CONTAINER_CLASS) as HTMLElement,
381
+ enableRtl: this.parent.enableRtl,
382
+ hideAnimation: { name: 'SlideLeftOut', duration: 500 },
383
+ showAnimation: { name: 'SlideLeftIn', duration: 500 },
384
+ viewPortElement: this.parent.element.querySelector('.' + (this.parent.currentView === 'MonthAgenda' ?
385
+ cls.WRAPPER_CONTAINER_CLASS : cls.TABLE_CONTAINER_CLASS)) as HTMLElement
386
+ });
387
+ this.parent.on(events.documentClick, this.documentClick, this);
388
+ }
389
+
390
+ private resourceTreeCreated(): void {
391
+ if (this.parent.activeViewOptions.resourceHeaderTemplate && (this as any).parent.portals && (this.treeViewObj as any).portals) {
392
+ (this as any).parent.portals = (this as any).parent.portals.concat((this.treeViewObj as any).portals);
393
+ this.parent.renderTemplates();
394
+ }
395
+ }
396
+
397
+ private generateTreeData(isTimeLine?: boolean): ResourceDetails[] | TdData[] {
398
+ const treeCollection: ResourceDetails[] = [];
399
+ const resTreeColl: TdData[] = [];
400
+ let groupIndex: number = 0;
401
+ for (let i: number = 0, len: number = this.resourceTreeLevel.length; i < len; i++) {
402
+ const treeHandler: CallbackFunction = (treeLevel: TreeSlotData, index: number, levelId: string): ResourceDetails => {
403
+ const resource: ResourcesModel = this.resourceCollection[parseInt(index.toString(), 10)];
404
+ let treeArgs: ResourceDetails;
405
+ let resObj: TdData;
406
+ if (!isTimeLine) {
407
+ treeArgs = {
408
+ resourceId: levelId,
409
+ resourceName: treeLevel.resourceData[resource.textField] as string,
410
+ resource: treeLevel.resource,
411
+ resourceData: treeLevel.resourceData
412
+ };
413
+ } else {
414
+ resObj = {
415
+ type: 'resourceHeader', resource: treeLevel.resource,
416
+ resourceData: treeLevel.resourceData, groupIndex: groupIndex,
417
+ groupOrder: treeLevel.groupOrder
418
+ };
419
+ resTreeColl.push(resObj);
420
+ groupIndex++;
421
+ }
422
+ if (treeLevel.child.length > 0 && !isTimeLine) {
423
+ treeArgs.resourceChild = [];
424
+ }
425
+ let count: number = 1;
426
+ for (const tree of treeLevel.child) {
427
+ if (!isTimeLine) {
428
+ treeArgs.resourceChild.push(treeHandler(tree, index + 1, levelId + '-' + count));
429
+ } else {
430
+ treeHandler(tree, index + 1, levelId + '-' + count);
431
+ }
432
+ count += 1;
433
+ }
434
+ if (isTimeLine) {
435
+ extend(resObj.resourceData, { Count: count - 1 });
436
+ }
437
+ return treeArgs;
438
+ };
439
+ if (!isTimeLine) {
440
+ treeCollection.push(treeHandler(this.resourceTreeLevel[parseInt(i.toString(), 10)], 0, (i + 1).toString()));
441
+ } else {
442
+ treeHandler(this.resourceTreeLevel[parseInt(i.toString(), 10)], 0, (i + 1).toString());
443
+ }
444
+ }
445
+ if (isTimeLine) {
446
+ this.lastResourceLevel = resTreeColl;
447
+ return resTreeColl;
448
+ } else {
449
+ return treeCollection;
450
+ }
451
+ }
452
+
453
+ private renderResourceHeaderText(): void {
454
+ const resource: TdData = this.lastResourceLevel[this.parent.uiStateValues.groupIndex];
455
+ const headerCollection: HTMLElement[] = [];
456
+ for (let i: number = 0, len: number = resource.groupOrder.length; i < len; i++) {
457
+ const resourceLevel: ResourcesModel = this.resourceCollection[parseInt(i.toString(), 10)];
458
+ const resourceText: Record<string, any>[] =
459
+ (resourceLevel.dataSource as Record<string, any>[]).filter((resData: Record<string, any>) =>
460
+ resData[resourceLevel.idField] === resource.groupOrder[parseInt(i.toString(), 10)]);
461
+ const resourceName: HTMLElement = createElement('div', { className: cls.RESOURCE_NAME });
462
+ this.parent.sanitize((<Record<string, any>>resourceText[0])[resourceLevel.textField] as string, resourceName);
463
+ headerCollection.push(resourceName);
464
+ const levelIcon: HTMLElement = createElement('div', { className: 'e-icons e-icon-next' });
465
+ headerCollection.push(levelIcon);
466
+ }
467
+ headerCollection.pop();
468
+ const target: HTMLElement = (this.parent.currentView === 'MonthAgenda') ? this.parent.activeView.getPanel() : this.parent.element;
469
+ const headerWrapper: Element = target.querySelector('.' + cls.RESOURCE_LEVEL_TITLE);
470
+ util.removeChildren(headerWrapper);
471
+ for (const header of headerCollection) {
472
+ headerWrapper.appendChild(header);
473
+ }
474
+ if (this.lastResourceLevel.length === 1) {
475
+ addClass([this.parent.element.querySelector('.' + cls.RESOURCE_MENU)], cls.DISABLE_CLASS);
476
+ }
477
+ }
478
+
479
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
480
+ private menuClick(event: Event): void {
481
+ if (this.parent.element.querySelector('.' + cls.RESOURCE_TREE_POPUP).classList.contains(cls.POPUP_OPEN)) {
482
+ this.treePopup.hide();
483
+ removeClass([this.popupOverlay], cls.ENABLE_CLASS);
484
+ } else {
485
+ const treeNodes: HTMLElement[] = [].slice.call(this.treeViewObj.element.querySelectorAll('.e-list-item:not(.e-has-child)'));
486
+ removeClass(treeNodes, 'e-active');
487
+ addClass([treeNodes[this.parent.uiStateValues.groupIndex]], 'e-active');
488
+ this.treePopup.show();
489
+ addClass([this.popupOverlay], cls.ENABLE_CLASS);
490
+ }
491
+ }
492
+
493
+ public selectResourceByIndex(groupIndex: number): void {
494
+ if (this.lastResourceLevel && groupIndex > -1 && groupIndex < this.lastResourceLevel.length) {
495
+ this.triggerEvents(groupIndex);
496
+ }
497
+ }
498
+
499
+ private resourceClick(event: NodeClickEventArgs): void {
500
+ if (!event.node.classList.contains('e-has-child')) {
501
+ this.treePopup.hide();
502
+ removeClass([this.popupOverlay], cls.ENABLE_CLASS);
503
+ const treeNodes: HTMLLIElement[] = [].slice.call(this.treeViewObj.element.querySelectorAll('.e-list-item:not(.e-has-child)'));
504
+ const groupIndex: number = treeNodes.indexOf(event.node);
505
+ this.triggerEvents(groupIndex, event);
506
+ event.event.preventDefault();
507
+ }
508
+ }
509
+
510
+ private triggerEvents(groupIndex: number, event?: NodeClickEventArgs): void {
511
+ let args: ActionEventArgs = { cancel: false, event: (event) ? event.event : null, groupIndex: groupIndex, requestType: 'resourceChange' };
512
+ this.parent.trigger(events.actionBegin, args, (actionArgs: ActionEventArgs) => {
513
+ if (!actionArgs.cancel) {
514
+ this.parent.uiStateValues.groupIndex = actionArgs.groupIndex;
515
+ this.parent.renderModule.render(this.parent.currentView);
516
+ args = {
517
+ cancel: false, event: (event) ? event.event : null, groupIndex: this.parent.uiStateValues.groupIndex, requestType: 'resourceChanged'
518
+ };
519
+ this.parent.adaptiveGroupIndex = this.parent.uiStateValues.groupIndex;
520
+ this.parent.trigger(events.actionComplete, args);
521
+ }
522
+ });
523
+ }
524
+
525
+ private documentClick(args: { event: Event }): void {
526
+ if (closest(args.event.target as Element, '.' + cls.RESOURCE_TREE_POPUP)) {
527
+ return;
528
+ }
529
+ const treeWrapper: Element = this.parent.element.querySelector('.' + cls.RESOURCE_TREE_POPUP);
530
+ if (treeWrapper && treeWrapper.classList.contains(cls.POPUP_OPEN)) {
531
+ this.treePopup.hide();
532
+ removeClass([this.popupOverlay], cls.ENABLE_CLASS);
533
+ }
534
+ }
535
+
536
+ public bindResourcesData(isSetModel: boolean): void {
537
+ this.parent.showSpinner();
538
+ const promises: Promise<any>[] = [];
539
+ for (const resource of this.parent.resources) {
540
+ const dataModule: Data = new Data(this.parent, resource.dataSource, resource.query);
541
+ promises.push(dataModule.getData(dataModule.generateQuery()));
542
+ }
543
+ Promise.all(promises).then((e: ReturnType[]) => this.dataManagerSuccess(e, isSetModel))
544
+ .catch((e: ReturnType) => this.parent.crudModule.dataManagerFailure(e));
545
+ }
546
+
547
+ private dataManagerSuccess(e: ReturnType[], isSetModel: boolean): void {
548
+ if (!this.parent || this.parent && this.parent.isDestroyed) { return; }
549
+ this.parent.resourceCollection = [];
550
+ for (let i: number = 0, length: number = e.length; i < length; i++) {
551
+ const resource: ResourcesModel = this.parent.resources[parseInt(i.toString(), 10)];
552
+ const resourceObj: ResourcesModel = this.getResourceModel(resource, e[parseInt(i.toString(), 10)].result);
553
+ this.parent.resourceCollection.push(resourceObj);
554
+ }
555
+ this.refreshLayout(isSetModel);
556
+ }
557
+
558
+ private getResourceModel(resource: ResourcesModel, resourceData?: Record<string, any>[]): ResourcesModel {
559
+ const resourceObj: ResourcesModel = {
560
+ field: resource.field,
561
+ title: resource.title,
562
+ name: resource.name,
563
+ allowMultiple: resource.allowMultiple,
564
+ dataSource: resourceData || resource.dataSource,
565
+ idField: resource.idField,
566
+ textField: resource.textField,
567
+ groupIDField: resource.groupIDField,
568
+ colorField: resource.colorField,
569
+ startHourField: resource.startHourField,
570
+ endHourField: resource.endHourField,
571
+ workDaysField: resource.workDaysField,
572
+ expandedField: resource.expandedField,
573
+ cssClassField: resource.cssClassField
574
+ };
575
+ return resourceObj;
576
+ }
577
+
578
+ public refreshLayout(isSetModel: boolean): void {
579
+ if (isNullOrUndefined(this.parent.uiStateValues.groupIndex) || !(this.parent.enablePersistence)) {
580
+ this.parent.uiStateValues.groupIndex = 0;
581
+ }
582
+ this.parent.renderElements(isSetModel);
583
+ }
584
+
585
+ public setResourceCollection(): void {
586
+ let requiredResources: ResourcesModel[] = [];
587
+ this.resourceCollection = [];
588
+ this.colorIndex = null;
589
+ if (this.parent.activeViewOptions.group.resources.length > 0) {
590
+ for (const resource of this.parent.activeViewOptions.group.resources) {
591
+ const index: number = util.findIndexInData(<Record<string, any>[]>this.parent.resourceCollection, 'name', resource);
592
+ if (index >= 0) {
593
+ requiredResources.push(this.parent.resourceCollection[parseInt(index.toString(), 10)]);
594
+ }
595
+ }
596
+ } else if (this.parent.resourceCollection.length > 0) {
597
+ requiredResources = this.parent.resourceCollection;
598
+ }
599
+ let index: number = 0;
600
+ for (const resource of requiredResources) {
601
+ const resources: ResourcesModel = this.getResourceModel(resource);
602
+ if (resource.name === this.parent.eventSettings.resourceColorField) {
603
+ this.colorIndex = index;
604
+ }
605
+ index++;
606
+ this.resourceCollection.push(resources);
607
+ }
608
+ if (isNullOrUndefined(this.colorIndex)) {
609
+ this.colorIndex = this.resourceCollection.length - 1;
610
+ }
611
+ }
612
+
613
+ public generateResourceLevels(innerDates: TdData[], isTimeLine?: boolean): TdData[][] {
614
+ const resources: ResourcesModel[] = this.resourceCollection;
615
+ const resTreeGroup: TdData[][][] = [];
616
+ let lastColumnDates: TdData[] = [];
617
+ const group: CallbackFunction = (resources: ResourcesModel[], index: number, prevResource?: ResourcesModel, prevResourceData?: Record<string, any>, prevOrder?: string[]): TdData[] => {
618
+ const resTree: TdData[] = [];
619
+ const resource: ResourcesModel = resources[0];
620
+ if (resource) {
621
+ let data: Record<string, any>[];
622
+ if (prevResourceData && this.parent.activeViewOptions.group.byGroupID) {
623
+ const id: string = (prevResourceData as Record<string, any>)[prevResource.idField] as string;
624
+ data = (resource.dataSource as Record<string, any>[]).filter((e: Record<string, any>) =>
625
+ e[resource.groupIDField] === id);
626
+ } else {
627
+ data = resource.dataSource as Record<string, any>[];
628
+ }
629
+ for (let i: number = 0; i < data.length; i++) {
630
+ let groupOrder: string[] = [];
631
+ if (prevOrder && prevOrder.length > 0) {
632
+ groupOrder = groupOrder.concat(prevOrder);
633
+ }
634
+ groupOrder.push((data[parseInt(i.toString(), 10)] as Record<string, any>)[resource.idField] as string);
635
+ const items: TdData[] = group(resources.slice(1), index + 1, resource, data[parseInt(i.toString(), 10)], groupOrder);
636
+ // Here validate child item empty top level resource only
637
+ if (index === 0 && items.length === 0 && this.resourceCollection.length > 1) {
638
+ continue;
639
+ }
640
+ let dateCol: TdData[] = [];
641
+ let renderDates: Date[] = this.parent.activeView.renderDates;
642
+ let resWorkDays: number[];
643
+ if (!this.parent.activeViewOptions.group.byDate && index + 1 === this.resourceCollection.length) {
644
+ const workDays: number[] = data[parseInt(i.toString(), 10)][resource.workDaysField] as number[];
645
+ const resStartHour: string = data[parseInt(i.toString(), 10)][resource.startHourField] as string;
646
+ const resEndHour: string = data[parseInt(i.toString(), 10)][resource.endHourField] as string;
647
+ if (workDays && workDays.length > 0) {
648
+ renderDates = this.parent.activeView.getRenderDates(workDays);
649
+ resWorkDays = workDays;
650
+ dateCol = this.parent.activeView.getDateSlots(renderDates, workDays);
651
+ } else {
652
+ resWorkDays = this.parent.activeViewOptions.workDays;
653
+ dateCol = innerDates;
654
+ }
655
+ const dateSlots: TdData[] = this.generateCustomHours(dateCol, resStartHour, resEndHour, groupOrder);
656
+ lastColumnDates = lastColumnDates.concat(dateSlots);
657
+ }
658
+ const resCssClass: string = data[parseInt(i.toString(), 10)][resource.cssClassField] as string;
659
+ const slotData: TreeSlotData = {
660
+ type: 'resourceHeader', className: ['e-resource-cells'],
661
+ resourceLevelIndex: index, groupOrder: groupOrder,
662
+ resource: resource, resourceData: data[parseInt(i.toString(), 10)],
663
+ colSpan: this.parent.activeViewOptions.group.byDate ? 1 : dateCol.length,
664
+ renderDates: renderDates, workDays: resWorkDays, cssClass: resCssClass,
665
+ child: items
666
+ };
667
+ resTree.push(slotData);
668
+ }
669
+ if (!resTreeGroup[parseInt(index.toString(), 10)]) {
670
+ resTreeGroup[parseInt(index.toString(), 10)] = [];
671
+ }
672
+ if (resTree.length > 0) {
673
+ resTreeGroup[parseInt(index.toString(), 10)].push(resTree);
674
+ }
675
+ return resTree;
676
+ }
677
+ return [];
678
+ };
679
+ this.resourceTreeLevel = group(resources, 0);
680
+ return (isTimeLine) ? [] : this.generateHeaderLevels(resTreeGroup, lastColumnDates, innerDates);
681
+ }
682
+
683
+ public generateCustomHours(renderDates: TdData[], startHour: string, endHour: string, groupOrder?: string[]): TdData[] {
684
+ const dateSlots: TdData[] = <TdData[]>extend([], renderDates, null, true);
685
+ for (const dateSlot of dateSlots) {
686
+ if (startHour) {
687
+ dateSlot.startHour = this.parent.getStartEndTime(startHour);
688
+ }
689
+ if (endHour) {
690
+ dateSlot.endHour = this.parent.getStartEndTime(endHour);
691
+ }
692
+ if (groupOrder) {
693
+ dateSlot.groupOrder = groupOrder;
694
+ }
695
+ }
696
+ return dateSlots;
697
+ }
698
+
699
+ private generateHeaderLevels(resTreeGroup: TdData[][][], lastColumnDates: TdData[], headerDates: TdData[]): TdData[][] {
700
+ const headerLevels: TdData[][] = [];
701
+ for (let i: number = resTreeGroup.length - 1; i >= 0; i--) {
702
+ let temp: number = 0;
703
+ for (const currentLevelChilds of resTreeGroup[parseInt(i.toString(), 10)]) {
704
+ for (const currentLevelChild of currentLevelChilds) {
705
+ if (resTreeGroup[i + 1] && resTreeGroup[i + 1].length > 0) {
706
+ const nextLevelChilds: TdData[] = resTreeGroup[parseInt((i + 1).toString(), 10)][parseInt(temp.toString(), 10)];
707
+ if (!nextLevelChilds) { continue; }
708
+ let colSpan: number = 0;
709
+ for (const nextLevelChild of nextLevelChilds) {
710
+ if (!this.parent.activeViewOptions.group.byGroupID || (this.parent.activeViewOptions.group.byGroupID &&
711
+ nextLevelChild.resourceData[nextLevelChild.resource.groupIDField] ===
712
+ currentLevelChild.resourceData[currentLevelChild.resource.idField])) {
713
+ colSpan += nextLevelChild.colSpan;
714
+ }
715
+ }
716
+ currentLevelChild.colSpan = colSpan;
717
+ }
718
+ currentLevelChild.groupIndex = temp;
719
+ temp++;
720
+ headerLevels[currentLevelChild.resourceLevelIndex] = headerLevels[currentLevelChild.resourceLevelIndex] || [];
721
+ headerLevels[currentLevelChild.resourceLevelIndex].push(currentLevelChild);
722
+ }
723
+ }
724
+ }
725
+ this.lastResourceLevel = headerLevels.slice(-1)[0] || [];
726
+ if (!this.parent.activeViewOptions.group.byDate) {
727
+ let index: number = 0;
728
+ for (const lastLevelResource of this.lastResourceLevel) {
729
+ for (let i: number = 0; i < lastLevelResource.colSpan; i++) {
730
+ lastColumnDates[parseInt(index.toString(), 10)].groupIndex = lastLevelResource.groupIndex;
731
+ index++;
732
+ }
733
+ }
734
+ headerLevels.push(lastColumnDates);
735
+ return headerLevels;
736
+ }
737
+ const dateHeaderLevels: TdData[][] = [];
738
+ const levels: TdData[][] = <TdData[][]>extend([], headerLevels, null, true);
739
+ const datesColumn: TdData[] = [];
740
+ if (this.parent.activeViewOptions.group.hideNonWorkingDays) {
741
+ const renderDates: Date[][] = [];
742
+ let dateIndex: number = 0;
743
+ for (const headerDate of headerDates) {
744
+ this.resourceDateTree[parseInt(dateIndex.toString(), 10)] = [];
745
+ const currentDateLevels: TdData[][] = [];
746
+ for (let j: number = 0; j < this.lastResourceLevel.length; j++) {
747
+ let workDays: number[] = this.lastResourceLevel[parseInt(j.toString(), 10)].resourceData[this.lastResourceLevel[parseInt(j.toString(), 10)].resource.workDaysField];
748
+ if (!workDays) {
749
+ workDays = this.parent.activeViewOptions.workDays;
750
+ }
751
+ if (workDays.indexOf(headerDate.date.getDay()) !== -1) {
752
+ const resTd: TdData = <TdData>extend({}, this.lastResourceLevel[parseInt(j.toString(), 10)], null, true);
753
+ resTd.date = headerDate.date;
754
+ this.lastResourceLevel[parseInt(j.toString(), 10)].workDays = workDays;
755
+ resTd.startHour = this.parent.getStartEndTime((resTd.resourceData[resTd.resource.startHourField] as string)) ||
756
+ headerDate.startHour;
757
+ resTd.endHour = this.parent.getStartEndTime((resTd.resourceData[resTd.resource.endHourField] as string)) ||
758
+ headerDate.endHour;
759
+ this.resourceDateTree[parseInt(dateIndex.toString(), 10)].push(resTd);
760
+ for (let k: number = 0; k < resTd.groupOrder.length; k++) {
761
+ if (!currentDateLevels[parseInt(k.toString(), 10)]) {
762
+ currentDateLevels[parseInt(k.toString(), 10)] = [];
763
+ }
764
+ if (k === resTd.groupOrder.length - 1) {
765
+ if (!renderDates[parseInt(j.toString(), 10)]) {
766
+ renderDates[parseInt(j.toString(), 10)] = [];
767
+ }
768
+ const filterDates: Date[] = resTd.renderDates.filter((x: Date) => x.getDay() === headerDate.date.getDay());
769
+ renderDates[parseInt(j.toString(), 10)] = renderDates[parseInt(j.toString(), 10)].concat(filterDates);
770
+ currentDateLevels[parseInt(k.toString(), 10)].push(resTd);
771
+ continue;
772
+ }
773
+ const currentLevel: TdData[] = levels[parseInt(k.toString(), 10)];
774
+ const filteredResource: TdData[] = currentLevel.filter((data: TdData) =>
775
+ data.resourceData[data.resource.idField] === resTd.groupOrder[parseInt(k.toString(), 10)]);
776
+ if (filteredResource && filteredResource.length > 0) {
777
+ const existedResource: TdData[] = currentDateLevels[parseInt(k.toString(), 10)].filter((data: TdData) =>
778
+ data.resourceData[data.resource.idField] === resTd.groupOrder[parseInt(k.toString(), 10)]);
779
+ if (existedResource && existedResource.length > 0) {
780
+ existedResource[0].colSpan += 1;
781
+ }
782
+ else {
783
+ const filteredTd: TdData = <TdData>extend({}, filteredResource[0], null, true);
784
+ filteredTd.colSpan = 1;
785
+ currentDateLevels[parseInt(k.toString(), 10)].push(filteredTd);
786
+ }
787
+ }
788
+ }
789
+ }
790
+ }
791
+ if (currentDateLevels.length > 0) {
792
+ for (let l: number = 0; l < levels.length; l++) {
793
+ if (!dateHeaderLevels[parseInt(l.toString(), 10)]) {
794
+ dateHeaderLevels[parseInt(l.toString(), 10)] = [];
795
+ }
796
+ dateHeaderLevels[parseInt(l.toString(), 10)] = dateHeaderLevels[parseInt(l.toString(), 10)].concat(currentDateLevels[parseInt(l.toString(), 10)]);
797
+ }
798
+ headerDate.colSpan = currentDateLevels[currentDateLevels.length - 1].length;
799
+ datesColumn.push(headerDate);
800
+ }
801
+ dateIndex++;
802
+ }
803
+ this.resourceDateTree = this.resourceDateTree.filter((data: TdData[]) => data.length > 0);
804
+ this.lastResourceLevel.forEach((x: TdData, index: number) => {
805
+ if (renderDates[parseInt(index.toString(), 10)]) {
806
+ x.renderDates = renderDates[parseInt(index.toString(), 10)].sort((a: Date, b: Date) => a.getTime() - b.getTime());
807
+ }
808
+ });
809
+ dateHeaderLevels.unshift(datesColumn);
810
+ return dateHeaderLevels;
811
+ }
812
+ let dateColSpan: number = 0;
813
+ for (const firstRowTd of levels[0]) {
814
+ dateColSpan += firstRowTd.colSpan;
815
+ }
816
+ for (const headerDate of headerDates) {
817
+ headerDate.colSpan = dateColSpan;
818
+ datesColumn.push(headerDate);
819
+ const resGroup: TdData[][] = <TdData[][]>extend([], levels, null, true);
820
+ for (let k: number = 0, length: number = resGroup.length; k < length; k++) {
821
+ if (k === resGroup.length - 1) {
822
+ for (const resTd of resGroup[parseInt(k.toString(), 10)]) {
823
+ resTd.date = headerDate.date;
824
+ resTd.workDays = headerDate.workDays;
825
+ resTd.startHour = this.parent.getStartEndTime((resTd.resourceData[resTd.resource.startHourField] as string)) ||
826
+ headerDate.startHour;
827
+ resTd.endHour = this.parent.getStartEndTime((resTd.resourceData[resTd.resource.endHourField] as string)) ||
828
+ headerDate.endHour;
829
+ }
830
+ }
831
+ if (!dateHeaderLevels[parseInt(k.toString(), 10)]) {
832
+ dateHeaderLevels[parseInt(k.toString(), 10)] = [];
833
+ }
834
+ dateHeaderLevels[parseInt(k.toString(), 10)] = dateHeaderLevels[parseInt(k.toString(), 10)].concat(resGroup[parseInt(k.toString(), 10)]);
835
+ }
836
+ }
837
+ dateHeaderLevels.unshift(datesColumn);
838
+ return dateHeaderLevels;
839
+ }
840
+
841
+ public setResourceValues(eventObj: Record<string, any>, groupIndex?: number): void {
842
+ const setValues: CallbackFunction = (index: number, field: string, value: Record<string, any>) => {
843
+ if (this.resourceCollection[parseInt(index.toString(), 10)].allowMultiple && this.parent.activeViewOptions.group.allowGroupEdit) {
844
+ eventObj[`${field}`] = [value];
845
+ } else {
846
+ eventObj[`${field}`] = value;
847
+ }
848
+ };
849
+ if (groupIndex === void 0) {
850
+ groupIndex = this.parent.uiStateValues.isGroupAdaptive ? this.parent.uiStateValues.groupIndex :
851
+ this.parent.activeCellsData.groupIndex;
852
+ }
853
+ if (this.parent.activeViewOptions.group.resources.length > 0 && !isNullOrUndefined(groupIndex)) {
854
+ const groupOrder: number[] | string[] = this.lastResourceLevel[parseInt(groupIndex.toString(), 10)].groupOrder;
855
+ for (let index: number = 0; index < this.resourceCollection.length; index++) {
856
+ setValues(index, this.resourceCollection[parseInt(index.toString(), 10)].field, groupOrder[parseInt(index.toString(), 10)]);
857
+ }
858
+ } else if (this.parent.resourceCollection.length > 0) {
859
+ for (let index: number = 0; index < this.resourceCollection.length; index++) {
860
+ const data: Record<string, any> = (this.resourceCollection[parseInt(index.toString(), 10)] as Record<string, unknown[]>).dataSource[0] as Record<string, any>;
861
+ if (data) { setValues(index, this.resourceCollection[parseInt(index.toString(), 10)].field, data[this.resourceCollection[parseInt(index.toString(), 10)].idField]); }
862
+ }
863
+ }
864
+ }
865
+
866
+ public getResourceColor(eventObj: Record<string, any>, groupOrder?: string[]): string {
867
+ const colorFieldIndex: number = (!isNullOrUndefined(groupOrder) &&
868
+ this.colorIndex > groupOrder.length - 1) ? groupOrder.length - 1 : this.colorIndex;
869
+ const resource: ResourcesModel = this.resourceCollection[parseInt(colorFieldIndex.toString(), 10)];
870
+ if (isNullOrUndefined(groupOrder) && this.parent.activeViewOptions.group.allowGroupEdit && resource.allowMultiple) {
871
+ return undefined;
872
+ }
873
+ const id: string = isNullOrUndefined(groupOrder) ? <string>eventObj[resource.field] : <string>groupOrder[parseInt(colorFieldIndex.toString(), 10)];
874
+ const data: Record<string, any>[] = this.filterData(resource.dataSource as Record<string, any>[], resource.idField, id);
875
+ if (data.length > 0) {
876
+ return data[0][resource.colorField] as string;
877
+ }
878
+ return undefined;
879
+ }
880
+
881
+ public getCssClass(eventObj: Record<string, any>): string {
882
+ const resource: ResourcesModel = this.resourceCollection.slice(-1)[0];
883
+ if (this.parent.activeViewOptions.group.allowGroupEdit && resource.allowMultiple) {
884
+ return undefined;
885
+ }
886
+ const data: Record<string, any>[] = this.filterData(resource.dataSource as Record<string, any>[], resource.idField, eventObj[resource.field] as string);
887
+ if (data.length > 0) {
888
+ return data[0][resource.cssClassField] as string;
889
+ }
890
+ return undefined;
891
+ }
892
+
893
+ public getResourceRenderDates(): Date[] {
894
+ // eslint-disable-next-line prefer-spread
895
+ const resourceDates: Date[] = [].concat.apply([], this.lastResourceLevel.map((e: TdData) => e.renderDates));
896
+ const time: number[] = resourceDates.map((dateObj: Date) => dateObj.getTime());
897
+ const removeDuplicateDates: CallbackFunction = (dateColl: Date[]) => dateColl.filter((date: Date, index: number) =>
898
+ time.indexOf(date.getTime()) === index);
899
+ const renderDates: Date[] = removeDuplicateDates(resourceDates);
900
+ renderDates.sort((a: Date, b: Date) => a.getTime() - b.getTime());
901
+ return renderDates;
902
+ }
903
+
904
+ private filterData(dataSource: Record<string, any>[], field: string, value: string): Record<string, any>[] {
905
+ return dataSource.filter((data: Record<string, any>) => data[`${field}`] === value);
906
+ }
907
+
908
+ public getResourceData(eventObj: Record<string, any>, index: number, groupEditIndex: number[]): void {
909
+ if (this.parent.activeViewOptions.group.allowGroupEdit) {
910
+ const resourceObj: Record<string, any> = {};
911
+ for (const groupIndex of groupEditIndex) {
912
+ const resourceLevel: Record<string, any>[] = this.lastResourceLevel[parseInt(groupIndex.toString(), 10)].groupOrder as unknown as Record<string, any>[];
913
+ for (let level: number = 0, length: number = resourceLevel.length; level < length; level++) {
914
+ const fieldName: string = this.resourceCollection[parseInt((level as number).toString(), 10)].field;
915
+ if (isNullOrUndefined(resourceObj[`${fieldName}`])) {
916
+ resourceObj[`${fieldName}`] = [];
917
+ }
918
+ (<Record<string, any>[]>resourceObj[`${fieldName}`]).push(resourceLevel[parseInt(level.toString(), 10)]);
919
+ }
920
+ }
921
+ eventObj = extend(eventObj, resourceObj) as Record<string, any>;
922
+ } else {
923
+ for (let level: number = 0, length: number = this.resourceCollection.length; level < length; level++) {
924
+ if (this.lastResourceLevel[parseInt(index.toString(), 10)]) {
925
+ eventObj[this.resourceCollection[parseInt(level.toString(), 10)].field] = this.lastResourceLevel[parseInt(index.toString(), 10)].groupOrder[parseInt(level.toString(), 10)];
926
+ }
927
+ }
928
+ }
929
+ }
930
+
931
+ public addResource(resources: Record<string, any> | Record<string, any>[], name: string, index: number): void {
932
+ const resourceCollection: Record<string, any>[] = (resources instanceof Array) ? resources : [resources];
933
+ for (const resource of this.parent.resourceCollection) {
934
+ if (resource.name === name) {
935
+ resourceCollection.forEach((addObj: Record<string, any>, i: number) =>
936
+ new DataManager({ json: resource.dataSource as Record<string, any>[] }).insert(addObj, null, null, index + i));
937
+ break;
938
+ }
939
+ }
940
+ this.refreshLayout(true);
941
+ }
942
+
943
+ public removeResource(resourceId: string | string[] | number | number[], name: string): void {
944
+ const resourceCollection: (string | number)[] = (resourceId instanceof Array) ? resourceId : [resourceId];
945
+ for (const resource of this.parent.resourceCollection) {
946
+ if (resource.name === name) {
947
+ resourceCollection.forEach((removeObj: string | number) =>
948
+ new DataManager({ json: resource.dataSource as Record<string, any>[] }).remove(resource.idField, removeObj));
949
+ break;
950
+ }
951
+ }
952
+ this.refreshLayout(true);
953
+ }
954
+
955
+ public getIndexFromResourceId(id: string | number, name?: string, resourceData?: ResourcesModel, event?: Record<string, any>, parentField?: string): number {
956
+ name = name || this.parent.resourceCollection.slice(-1)[0].name;
957
+ if (isNullOrUndefined(resourceData)) {
958
+ resourceData = this.resourceCollection.filter((e: ResourcesModel) => e.name === name)[0];
959
+ if (isNullOrUndefined(resourceData)) {
960
+ return null;
961
+ }
962
+ }
963
+ const resource: Record<string, any> = (resourceData.dataSource as Record<string, any>[]).filter((e: Record<string, any>) => {
964
+ if (event && e[resourceData.idField] === id) {
965
+ if (e[resourceData.groupIDField] === event[`${parentField}`]) {
966
+ return e[resourceData.idField] === id;
967
+ }
968
+ return null;
969
+ } else {
970
+ return e[resourceData.idField] === id;
971
+ }
972
+ })[0] as Record<string, any>;
973
+ return (this.lastResourceLevel.map((e: TdData) => e.resourceData).indexOf(resource));
974
+ }
975
+
976
+ public resourceExpand(id: string | number, name: string, hide: boolean): void {
977
+ const resource: ResourcesModel = this.parent.resourceCollection.filter((e: ResourcesModel) => {
978
+ if (e.name === name) {
979
+ return e;
980
+ }
981
+ return null;
982
+ })[0];
983
+ let index: number = 0;
984
+ const resourceData: Record<string, any> = (resource.dataSource as Record<string, any>[]).filter((e: Record<string, any>) => e[resource.idField] === id)[0] as Record<string, any>;
985
+ if (!this.parent.activeViewOptions.group.byGroupID) {
986
+ index = this.getIndexFromResourceId(id, name, resource);
987
+ } else {
988
+ index = this.lastResourceLevel.map((e: TdData) => e.resourceData).indexOf(resourceData);
989
+ }
990
+ const target: HTMLElement =
991
+ this.parent.element.querySelector('.' + cls.RESOURCE_COLUMN_WRAP_CLASS + ' ' + `[data-group-index="${index}"]` +
992
+ ' ' + '.' + cls.RESOURCE_TREE_ICON_CLASS) as HTMLElement;
993
+ if (target) {
994
+ if (target.classList.contains(cls.RESOURCE_EXPAND_CLASS) && !hide) {
995
+ target.click();
996
+ } else if (target.classList.contains(cls.RESOURCE_COLLAPSE_CLASS) && hide) {
997
+ target.click();
998
+ }
999
+ }
1000
+ }
1001
+ public resourceScroll(id: string | number, name: string): void {
1002
+ if (this.parent.isAdaptive || ['Agenda', 'MonthAgenda'].indexOf(this.parent.currentView) > -1) {
1003
+ return;
1004
+ }
1005
+ const levelName: string = name || this.parent.resourceCollection.slice(-1)[0].name;
1006
+ let levelIndex: number = this.parent.resourceCollection.length - 1;
1007
+ const resource: ResourcesModel = this.parent.resourceCollection.filter((e: ResourcesModel, index: number) => {
1008
+ if (e.name === levelName) {
1009
+ levelIndex = index;
1010
+ return e;
1011
+ }
1012
+ return null;
1013
+ })[0];
1014
+ const scrollElement: HTMLElement = this.parent.element.querySelector('.' + cls.CONTENT_WRAP_CLASS) as HTMLElement;
1015
+ let index: number = 0;
1016
+ if (this.parent.activeView.isTimelineView()) {
1017
+ if (!this.parent.activeViewOptions.group.byGroupID) {
1018
+ index = this.getIndexFromResourceId(id, levelName, resource);
1019
+ } else {
1020
+ const resourceData: Record<string, any> = (resource.dataSource as Record<string, any>[]).filter((e: Record<string, any>) =>
1021
+ e[resource.idField] === id)[0] as Record<string, any>;
1022
+ index = this.lastResourceLevel.map((e: TdData) => e.resourceData).indexOf(resourceData);
1023
+ }
1024
+ if (this.parent.virtualScrollModule) {
1025
+ const virtual: HTMLElement = this.parent.element.querySelector('.' + cls.VIRTUAL_TRACK_CLASS) as HTMLElement;
1026
+ const averageRowHeight: number = Math.round(virtual.offsetHeight / this.expandedResources.length);
1027
+ if (this.parent.rowAutoHeight) {
1028
+ scrollElement.scrollTop = 0;
1029
+ this.parent.virtualScrollModule.virtualScrolling();
1030
+ }
1031
+ scrollElement.scrollTop = (index * averageRowHeight) - (((this.parent.virtualScrollModule.bufferCount - 1) * averageRowHeight));
1032
+ this.parent.virtualScrollModule.virtualScrolling();
1033
+ if (this.parent.rowAutoHeight) {
1034
+ const td: HTMLElement =
1035
+ this.parent.element.querySelector(`.${cls.WORK_CELLS_CLASS}[data-group-index="${index}"]`) as HTMLElement;
1036
+ if (td && !td.parentElement.classList.contains(cls.HIDDEN_CLASS)) {
1037
+ scrollElement.scrollTop =
1038
+ (scrollElement.scrollTop < td.offsetTop) ? td.offsetTop : scrollElement.scrollTop + td.offsetTop;
1039
+ }
1040
+ } else {
1041
+ scrollElement.scrollTop = (index * averageRowHeight);
1042
+ }
1043
+ } else {
1044
+ const td: HTMLElement =
1045
+ this.parent.element.querySelector(`.${cls.WORK_CELLS_CLASS}[data-group-index="${index}"]`) as HTMLElement;
1046
+ if (td && !td.parentElement.classList.contains(cls.HIDDEN_CLASS)) {
1047
+ scrollElement.scrollTop = td.offsetTop;
1048
+ }
1049
+ }
1050
+ } else {
1051
+ if (!this.parent.activeViewOptions.group.byGroupID) {
1052
+ index = this.getIndexFromResourceId(id, levelName, resource);
1053
+ } else {
1054
+ if (levelName === this.parent.resourceCollection.slice(-1)[0].name) {
1055
+ index = this.lastResourceLevel.map((e: TdData) => (e.resourceData as Record<string, any>)[resource.idField]).indexOf(id);
1056
+ } else {
1057
+ index = (resource.dataSource as Record<string, any>[]).map((e: Record<string, any>) => e[resource.idField]).indexOf(id);
1058
+ }
1059
+ }
1060
+ const offsetTarget: Element = this.parent.currentView === 'Month' ? this.parent.element.querySelector(`.${cls.DATE_HEADER_WRAP_CLASS} tbody tr:nth-child(${levelIndex + 1})`)
1061
+ : this.parent.element.querySelector(`.${cls.HEADER_ROW_CLASS}:nth-child(${levelIndex + 1})`);
1062
+ const offset: number[] = [].slice.call(offsetTarget.children).map((node: HTMLElement) => node.offsetLeft);
1063
+ scrollElement.scrollLeft = offset[parseInt(index.toString(), 10)];
1064
+ }
1065
+ }
1066
+
1067
+ public destroy(): void {
1068
+ this.parent.off(events.documentClick, this.documentClick);
1069
+ if (this.treeViewObj) {
1070
+ if ((this.treeViewObj as any).portals && (this.treeViewObj as any).portals.length > 0) {
1071
+ const treeViewTemplates: string[] = (this.treeViewObj as any).portals.map((x: any) => x.propName);
1072
+ if (treeViewTemplates.length > 0) {
1073
+ this.parent.resetTemplates(treeViewTemplates);
1074
+ }
1075
+ }
1076
+ this.treeViewObj.destroy();
1077
+ this.treeViewObj = null;
1078
+ }
1079
+ if (this.treePopup) {
1080
+ this.treePopup.destroy();
1081
+ this.treePopup = null;
1082
+ remove(this.parent.element.querySelector('.' + cls.RESOURCE_TREE_POPUP));
1083
+ remove(this.parent.element.querySelector('.' + cls.RESOURCE_TREE_POPUP_OVERLAY));
1084
+ }
1085
+ const resToolBarEle: Element = this.parent.element.querySelector('.' + cls.RESOURCE_TOOLBAR_CONTAINER);
1086
+ if (resToolBarEle) {
1087
+ remove(resToolBarEle);
1088
+ }
1089
+ }
1090
+
1091
+ }