ui.scheduler.resource_manager.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /**
  2. * DevExtreme (ui/scheduler/ui.scheduler.resource_manager.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var Class = require("../../core/class");
  11. var arrayUtils = require("../../core/utils/array");
  12. var grep = require("../../core/utils/common").grep;
  13. var isDefined = require("../../core/utils/type").isDefined;
  14. var objectUtils = require("../../core/utils/object");
  15. var iteratorUtils = require("../../core/utils/iterator");
  16. var extend = require("../../core/utils/extend").extend;
  17. var inArray = require("../../core/utils/array").inArray;
  18. var query = require("../../data/query");
  19. var dataCoreUtils = require("../../core/utils/data");
  20. var DataSourceModule = require("../../data/data_source/data_source");
  21. var deferredUtils = require("../../core/utils/deferred");
  22. var when = deferredUtils.when;
  23. var Deferred = deferredUtils.Deferred;
  24. var getValueExpr = function(resource) {
  25. return resource.valueExpr || "id"
  26. };
  27. var getDisplayExpr = function(resource) {
  28. return resource.displayExpr || "text"
  29. };
  30. var ResourceManager = Class.inherit({
  31. _wrapDataSource: function(dataSource) {
  32. if (dataSource instanceof DataSourceModule.DataSource) {
  33. return dataSource
  34. } else {
  35. return new DataSourceModule.DataSource({
  36. store: DataSourceModule.normalizeDataSourceOptions(dataSource).store,
  37. pageSize: 0
  38. })
  39. }
  40. },
  41. _mapResourceData: function(resource, data) {
  42. var valueGetter = dataCoreUtils.compileGetter(getValueExpr(resource));
  43. var displayGetter = dataCoreUtils.compileGetter(getDisplayExpr(resource));
  44. return iteratorUtils.map(data, function(item) {
  45. var result = {
  46. id: valueGetter(item),
  47. text: displayGetter(item)
  48. };
  49. if (item.color) {
  50. result.color = item.color
  51. }
  52. return result
  53. })
  54. },
  55. _isMultipleResource: function(resourceField) {
  56. var result = false;
  57. iteratorUtils.each(this.getResources(), function(_, resource) {
  58. var field = this.getField(resource);
  59. if (field === resourceField) {
  60. result = resource.allowMultiple;
  61. return false
  62. }
  63. }.bind(this));
  64. return result
  65. },
  66. ctor: function(resources) {
  67. this.setResources(resources)
  68. },
  69. getDataAccessors: function(field, type) {
  70. var result = null;
  71. iteratorUtils.each(this._dataAccessors[type], function(accessorName, accessors) {
  72. if (field === accessorName) {
  73. result = accessors;
  74. return false
  75. }
  76. });
  77. return result
  78. },
  79. getField: function(resource) {
  80. return resource.fieldExpr || resource.field
  81. },
  82. setResources: function(resources) {
  83. this._resources = resources;
  84. this._dataAccessors = {
  85. getter: {},
  86. setter: {}
  87. };
  88. this._resourceFields = iteratorUtils.map(resources || [], function(resource) {
  89. var field = this.getField(resource);
  90. this._dataAccessors.getter[field] = dataCoreUtils.compileGetter(field);
  91. this._dataAccessors.setter[field] = dataCoreUtils.compileSetter(field);
  92. return field
  93. }.bind(this))
  94. },
  95. getResources: function() {
  96. return this._resources || []
  97. },
  98. getResourcesData: function() {
  99. return this._resourcesData || []
  100. },
  101. getEditors: function() {
  102. var result = [];
  103. var that = this;
  104. iteratorUtils.each(this.getResources(), function(i, resource) {
  105. var field = that.getField(resource);
  106. var currentResourceItems = that._getResourceDataByField(field);
  107. result.push({
  108. editorOptions: {
  109. dataSource: currentResourceItems.length ? currentResourceItems : that._wrapDataSource(resource.dataSource),
  110. displayExpr: getDisplayExpr(resource),
  111. valueExpr: getValueExpr(resource)
  112. },
  113. dataField: field,
  114. editorType: resource.allowMultiple ? "dxTagBox" : "dxSelectBox",
  115. label: {
  116. text: resource.label || field
  117. }
  118. })
  119. });
  120. return result
  121. },
  122. _resourceLoader: {},
  123. getResourceDataByValue: function(field, value) {
  124. var that = this;
  125. var result = new Deferred;
  126. iteratorUtils.each(this.getResources(), function(_, resource) {
  127. var resourceField = that.getField(resource);
  128. if (resourceField === field) {
  129. var dataSource = that._wrapDataSource(resource.dataSource);
  130. var valueExpr = getValueExpr(resource);
  131. if (!that._resourceLoader[field]) {
  132. that._resourceLoader[field] = dataSource.load()
  133. }
  134. that._resourceLoader[field].done(function(data) {
  135. var filteredData = query(data).filter(valueExpr, value).toArray();
  136. delete that._resourceLoader[field];
  137. result.resolve(filteredData[0])
  138. }).fail(function() {
  139. delete that._resourceLoader[field];
  140. result.reject()
  141. });
  142. return false
  143. }
  144. });
  145. return result.promise()
  146. },
  147. setResourcesToItem: function(itemData, resources) {
  148. var resourcesSetter = this._dataAccessors.setter;
  149. for (var name in resources) {
  150. if (Object.prototype.hasOwnProperty.call(resources, name)) {
  151. var resourceData = resources[name];
  152. resourcesSetter[name](itemData, this._isMultipleResource(name) ? arrayUtils.wrapToArray(resourceData) : resourceData)
  153. }
  154. }
  155. },
  156. getResourcesFromItem: function(itemData, wrapOnlyMultipleResources) {
  157. var that = this;
  158. var result = null;
  159. if (!isDefined(wrapOnlyMultipleResources)) {
  160. wrapOnlyMultipleResources = false
  161. }
  162. iteratorUtils.each(that._resourceFields, function(index, field) {
  163. iteratorUtils.each(itemData, function(fieldName, fieldValue) {
  164. var tmp = {};
  165. tmp[fieldName] = fieldValue;
  166. var resourceData = that.getDataAccessors(field, "getter")(tmp);
  167. if (isDefined(resourceData)) {
  168. if (!result) {
  169. result = {}
  170. }
  171. if (1 === resourceData.length) {
  172. resourceData = resourceData[0]
  173. }
  174. if (!wrapOnlyMultipleResources || wrapOnlyMultipleResources && that._isMultipleResource(field)) {
  175. that.getDataAccessors(field, "setter")(tmp, arrayUtils.wrapToArray(resourceData))
  176. } else {
  177. that.getDataAccessors(field, "setter")(tmp, resourceData)
  178. }
  179. extend(result, tmp);
  180. return true
  181. }
  182. })
  183. });
  184. return result
  185. },
  186. loadResources: function(groups) {
  187. var result = new Deferred;
  188. var that = this;
  189. var deferreds = [];
  190. iteratorUtils.each(this.getResourcesByFields(groups), function(i, resource) {
  191. var deferred = new Deferred;
  192. var field = that.getField(resource);
  193. deferreds.push(deferred);
  194. that._wrapDataSource(resource.dataSource).load().done(function(data) {
  195. deferred.resolve({
  196. name: field,
  197. items: that._mapResourceData(resource, data),
  198. data: data
  199. })
  200. }).fail(function() {
  201. deferred.reject()
  202. })
  203. });
  204. if (!deferreds.length) {
  205. that._resourcesData = [];
  206. return result.resolve([])
  207. }
  208. when.apply(null, deferreds).done(function() {
  209. var data = Array.prototype.slice.call(arguments);
  210. var mapFunction = function(obj) {
  211. return {
  212. name: obj.name,
  213. items: obj.items,
  214. data: obj.data
  215. }
  216. };
  217. that._resourcesData = data;
  218. result.resolve(data.map(mapFunction))
  219. }).fail(function() {
  220. result.reject()
  221. });
  222. return result.promise()
  223. },
  224. getResourcesByFields: function(fields) {
  225. return grep(this.getResources(), function(resource) {
  226. var field = this.getField(resource);
  227. return inArray(field, fields) > -1
  228. }.bind(this))
  229. },
  230. getResourceByField: function(field) {
  231. return this.getResourcesByFields([field])[0] || {}
  232. },
  233. getResourceColor: function(field, value) {
  234. var valueExpr = this.getResourceByField(field).valueExpr || "id";
  235. var valueGetter = dataCoreUtils.compileGetter(valueExpr);
  236. var colorExpr = this.getResourceByField(field).colorExpr || "color";
  237. var colorGetter = dataCoreUtils.compileGetter(colorExpr);
  238. var result = new Deferred;
  239. var resourceData = this._getResourceDataByField(field);
  240. var resourceDataLength = resourceData.length;
  241. var color;
  242. if (resourceDataLength) {
  243. for (var i = 0; i < resourceDataLength; i++) {
  244. if (valueGetter(resourceData[i]) === value) {
  245. color = colorGetter(resourceData[i]);
  246. break
  247. }
  248. }
  249. result.resolve(color)
  250. } else {
  251. this.getResourceDataByValue(field, value).done(function(resourceData) {
  252. if (resourceData) {
  253. color = colorGetter(resourceData)
  254. }
  255. result.resolve(color)
  256. }).fail(function() {
  257. result.reject()
  258. })
  259. }
  260. return result.promise()
  261. },
  262. getResourceForPainting: function(groups) {
  263. var resources = this.getResources();
  264. var result;
  265. iteratorUtils.each(resources, function(index, resource) {
  266. if (resource.useColorAsDefault) {
  267. result = resource;
  268. return false
  269. }
  270. });
  271. if (!result) {
  272. if (Array.isArray(groups) && groups.length) {
  273. resources = this.getResourcesByFields(groups)
  274. }
  275. result = resources[resources.length - 1]
  276. }
  277. return result
  278. },
  279. createResourcesTree: function(groups) {
  280. var leafIndex = 0;
  281. var groupIndex = groupIndex || 0;
  282. function make(group, groupIndex, result, parent) {
  283. result = result || [];
  284. for (var i = 0; i < group.items.length; i++) {
  285. var currentGroupItem = group.items[i];
  286. var resultItem = {
  287. name: group.name,
  288. value: currentGroupItem.id,
  289. title: currentGroupItem.text,
  290. data: group.data && group.data[i],
  291. children: [],
  292. parent: parent ? parent : null
  293. };
  294. result.push(resultItem);
  295. var nextGroupIndex = groupIndex + 1;
  296. if (groups[nextGroupIndex]) {
  297. make.call(this, groups[nextGroupIndex], nextGroupIndex, resultItem.children, resultItem)
  298. }
  299. if (!resultItem.children.length) {
  300. resultItem.leafIndex = leafIndex;
  301. leafIndex++
  302. }
  303. }
  304. return result
  305. }
  306. return make.call(this, groups[0], 0)
  307. },
  308. _hasGroupItem: function(appointmentResources, groupName, itemValue) {
  309. var group = this.getDataAccessors(groupName, "getter")(appointmentResources);
  310. if (group) {
  311. if (inArray(itemValue, group) > -1) {
  312. return true
  313. }
  314. }
  315. return false
  316. },
  317. _getResourceDataByField: function(fieldName) {
  318. var loadedResources = this.getResourcesData();
  319. var currentResourceData = [];
  320. for (var i = 0, resourceCount = loadedResources.length; i < resourceCount; i++) {
  321. if (loadedResources[i].name === fieldName) {
  322. currentResourceData = loadedResources[i].data;
  323. break
  324. }
  325. }
  326. return currentResourceData
  327. },
  328. getResourceTreeLeaves: function(tree, appointmentResources, result) {
  329. result = result || [];
  330. for (var i = 0; i < tree.length; i++) {
  331. if (!this._hasGroupItem(appointmentResources, tree[i].name, tree[i].value)) {
  332. continue
  333. }
  334. if (isDefined(tree[i].leafIndex)) {
  335. result.push(tree[i].leafIndex)
  336. }
  337. if (tree[i].children) {
  338. this.getResourceTreeLeaves(tree[i].children, appointmentResources, result)
  339. }
  340. }
  341. return result
  342. },
  343. groupAppointmentsByResources: function(appointments, resources) {
  344. var tree = this.createResourcesTree(resources);
  345. var result = {};
  346. iteratorUtils.each(appointments, function(_, appointment) {
  347. var appointmentResources = this.getResourcesFromItem(appointment);
  348. var treeLeaves = this.getResourceTreeLeaves(tree, appointmentResources);
  349. for (var i = 0; i < treeLeaves.length; i++) {
  350. if (!result[treeLeaves[i]]) {
  351. result[treeLeaves[i]] = []
  352. }
  353. result[treeLeaves[i]].push(objectUtils.deepExtendArraySafe({}, appointment, true))
  354. }
  355. }.bind(this));
  356. return result
  357. },
  358. reduceResourcesTree: function(tree, existingAppointments, _result) {
  359. _result = _result ? _result.children : [];
  360. var that = this;
  361. tree.forEach(function(node, index) {
  362. var ok = false;
  363. var resourceName = node.name;
  364. var resourceValue = node.value;
  365. var resourceTitle = node.title;
  366. var resourceData = node.data;
  367. var resourceGetter = that.getDataAccessors(resourceName, "getter");
  368. existingAppointments.forEach(function(appointment) {
  369. if (!ok) {
  370. var resourceFromAppointment = resourceGetter(appointment);
  371. if (Array.isArray(resourceFromAppointment)) {
  372. if (resourceFromAppointment.indexOf(resourceValue) > -1) {
  373. _result.push({
  374. name: resourceName,
  375. value: resourceValue,
  376. title: resourceTitle,
  377. data: resourceData,
  378. children: []
  379. });
  380. ok = true
  381. }
  382. } else {
  383. if (resourceFromAppointment === resourceValue) {
  384. _result.push({
  385. name: resourceName,
  386. value: resourceValue,
  387. title: resourceTitle,
  388. data: resourceData,
  389. children: []
  390. });
  391. ok = true
  392. }
  393. }
  394. }
  395. });
  396. if (ok && node.children && node.children.length) {
  397. that.reduceResourcesTree(node.children, existingAppointments, _result[index])
  398. }
  399. });
  400. return _result
  401. }
  402. });
  403. module.exports = ResourceManager;