Slots.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  4. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  5. /**
  6. * Licensed Materials - Property of IBM
  7. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2018, 2021
  8. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. */
  10. define(['underscore', '../../lib/@waca/dashboard-common/dist/core/APIFactory', './SlotsAPISpec', '../SlotsAPI', './Slot', './MappedDataItem', './model/SlotMappingModel'], function (_, APIFactory, SlotsAPISpec, SlotsAPI, Slot, MappedDataItem, SlotMappingModel) {
  11. var SlotsImpl = function (_SlotsAPISpec) {
  12. _inherits(SlotsImpl, _SlotsAPISpec);
  13. function SlotsImpl(widgetModel, dataModel, visualizationImpl, transaction, locale, filterSupport) {
  14. _classCallCheck(this, SlotsImpl);
  15. var _this = _possibleConstructorReturn(this, _SlotsAPISpec.call(this));
  16. _this.widgetModel = widgetModel;
  17. _this.visualizationImpl = visualizationImpl;
  18. _this.transaction = transaction;
  19. _this.locale = locale;
  20. _this.filterSupport = filterSupport;
  21. _this._dataItemImplMap = {};
  22. _this.dataModel = dataModel;
  23. if (!_this.widgetModel.slotmapping) {
  24. _this.widgetModel.slotmapping = {};
  25. }
  26. _this.slotMappingModel = new SlotMappingModel(_this.widgetModel.slotmapping);
  27. _this._slots = {};
  28. _this._slotAPIList = null;
  29. _this.setDefinition(_this.visualizationImpl.getDefinition());
  30. _this._dataItemImplMap = null;
  31. _this._initializeDataItems();
  32. _this._deleteDataItemsHandlers = []; //An optional list of handlers that will be called before data items are deleted
  33. _this._api = APIFactory.createAPI(_this, [SlotsAPI]);
  34. return _this;
  35. }
  36. SlotsImpl.prototype.destroy = function destroy() {
  37. this.widgetModel = null;
  38. this.visualizationImpl = null;
  39. this.transaction = null;
  40. this.locale = null;
  41. this.filterSupport = null;
  42. this.dataModel = null;
  43. this.slotMappingModel = null;
  44. for (var id in this._slots) {
  45. this._slots[id].destroy();
  46. }
  47. this._slots = null;
  48. this._slotAPIList = null;
  49. for (var _id in this._dataItemImplMap) {
  50. this._dataItemImplMap[_id].destroy();
  51. }
  52. this._dataItemImplMap = null;
  53. this._api = null;
  54. };
  55. SlotsImpl.prototype.getLocalFilters = function getLocalFilters() {
  56. return this.filterSupport.getLocalFilters();
  57. };
  58. SlotsImpl.prototype._initializeDataItems = function _initializeDataItems() {
  59. var _this2 = this;
  60. this._dataItemImplMap = {};
  61. this.dataModel.getDataItemList().forEach(function (dataItemModel) {
  62. _this2._createDataItemImpl(dataItemModel);
  63. });
  64. };
  65. SlotsImpl.prototype._createDataItemImpl = function _createDataItemImpl(model) {
  66. var slotModel = this.slotMappingModel.getMappedSlot(model.id);
  67. var slot = slotModel ? this.getSlot(slotModel.name) : null;
  68. var impl = new MappedDataItem(this.filterSupport, model, slot, this.getDataSource(), this.transaction, this.locale, this.visualizationImpl, this);
  69. APIFactory.setParentChildRelation(this, impl);
  70. this._dataItemImplMap[model.id] = impl;
  71. return impl;
  72. };
  73. SlotsImpl.prototype.setDefinition = function setDefinition(definition) {
  74. this.definition = definition;
  75. this._initializeSlots();
  76. };
  77. SlotsImpl.prototype._initializeSlots = function _initializeSlots() {
  78. var _this3 = this;
  79. var newSlotAPIList = [];
  80. var newSlotsMap = {};
  81. this.definition.getSlotList().forEach(function (slotDefinition) {
  82. var slot = _this3.getSlotImpl(slotDefinition.getId());
  83. if (slot) {
  84. slot.setDefinition(slotDefinition);
  85. } else {
  86. slot = new Slot(slotDefinition, _this3.filterSupport, _this3, _this3.transaction, _this3.locale, _this3.visualizationImpl, _this3.dataModel, _this3.slotMappingModel);
  87. APIFactory.setParentChildRelation(_this3, slot);
  88. }
  89. newSlotsMap[slotDefinition.getId()] = slot;
  90. newSlotAPIList.push(slot.getAPI());
  91. });
  92. var oldSlots = this._slots;
  93. this._slots = newSlotsMap;
  94. this._slotAPIList = newSlotAPIList;
  95. Object.freeze(this._slotAPIList);
  96. // Go over the current list of data items.. and clear the slot for those that are not mapped to a valid slot
  97. for (var id in this._dataItemImplMap) {
  98. var dataItem = this._dataItemImplMap[id];
  99. var slot = this._dataItemImplMap[id].getSlot();
  100. if (slot && !this._slots[slot.getId()]) {
  101. this.slotMappingModel.unmapDataItemsFromSlots([id]);
  102. dataItem.setSlot(null);
  103. }
  104. }
  105. // destoy old slot that are no longer valid after the new definition
  106. for (var _id2 in oldSlots) {
  107. if (!this._slots[_id2]) {
  108. oldSlots[_id2].destroy();
  109. }
  110. }
  111. };
  112. SlotsImpl.prototype.getDataSource = function getDataSource() {
  113. return this.visualizationImpl.getDataSource();
  114. };
  115. SlotsImpl.prototype.createDataItems = function createDataItems(dataItemSpecList) {
  116. var _this4 = this;
  117. var result = [];
  118. if (dataItemSpecList) {
  119. var ids = [];
  120. dataItemSpecList.forEach(function (spec) {
  121. ids.push(spec.id);
  122. var model = _this4.dataModel.addDataItem(spec);
  123. if (!_this4._dataItemImplMap[spec.id]) {
  124. _this4._createDataItemImpl(model);
  125. }
  126. result.push(_this4._dataItemImplMap[spec.id].getAPI());
  127. });
  128. }
  129. return result;
  130. };
  131. SlotsImpl.prototype.deleteDataItems = function deleteDataItems(dataItemIdList, transaction) {
  132. var _this5 = this;
  133. var hasLocalFilter = this.visualizationImpl.getLocalFilters().getFilterList().length > 0;
  134. var result = [];
  135. if (dataItemIdList) {
  136. this._deleteDataItemsHandlers.forEach(function (handler) {
  137. return handler(dataItemIdList, transaction);
  138. });
  139. dataItemIdList.forEach(function (id) {
  140. var dataItem = _this5._dataItemImplMap[id];
  141. if (dataItem) {
  142. result.push({
  143. id: dataItem.getId(),
  144. columnId: dataItem.getColumnId()
  145. });
  146. dataItem.destroy();
  147. delete _this5._dataItemImplMap[id];
  148. _this5.slotMappingModel.unmapDataItemsFromSlots([id]);
  149. _this5.dataModel.removeDataItem(id, hasLocalFilter);
  150. }
  151. });
  152. }
  153. return result;
  154. };
  155. SlotsImpl.prototype.registerDeleteDataItemsHandler = function registerDeleteDataItemsHandler(handler) {
  156. this._deleteDataItemsHandlers.push(handler);
  157. };
  158. SlotsImpl.prototype.getDataItemImpl = function getDataItemImpl(id) {
  159. return this._dataItemImplMap[id] ? this._dataItemImplMap[id] : null;
  160. };
  161. SlotsImpl.prototype.getDataItemImplList = function getDataItemImplList() {
  162. return Object.values(this._dataItemImplMap);
  163. };
  164. SlotsImpl.prototype.getDataItem = function getDataItem(id) {
  165. var impl = this.getDataItemImpl(id);
  166. return impl ? impl.getAPI() : null;
  167. };
  168. SlotsImpl.prototype.getDataItemList = function getDataItemList() {
  169. // TODO - livewidget cleanup - cache and free the list for performance
  170. var result = [];
  171. for (var id in this._dataItemImplMap) {
  172. result.push(this._dataItemImplMap[id].getAPI());
  173. }
  174. return result;
  175. };
  176. /**
  177. * set DataItems@dataItemIds to given slot@slotId (and remove the dataItems from Original slot)
  178. * @param {*} dataItemIds
  179. * @param {*} slotId
  180. * @param {*} options
  181. *
  182. * e.g.
  183. * slotA: item1, item2
  184. * slotB: item3
  185. * if try move item2 from slotA to slotB,
  186. *
  187. * function will be called setDataItems([item2, item3], slotB)
  188. */
  189. SlotsImpl.prototype.setDataItems = function setDataItems(dataItemIds, slotId, transactionToken) {
  190. var _this6 = this;
  191. //step2: set dataItems to target slot
  192. // We use the implementation to access certain slot functionality that is not pubblic API
  193. // We also use the implementation to avoid firing individual slot events when using some slot functions
  194. var targetSlot = this.getSlot(slotId);
  195. if (targetSlot) {
  196. var subTransaction = this.transaction.startTransaction(transactionToken);
  197. //step1:unmap the data items if they are mapped to another slot
  198. _.each(dataItemIds, function (dataItemId) {
  199. var currentMapping = _this6.getMappingInfo(dataItemId);
  200. if (currentMapping && currentMapping.slot && currentMapping.slot.getId() !== slotId) {
  201. currentMapping.slot.removeDataItemsMapping([currentMapping.dataItem.getId()], subTransaction);
  202. }
  203. });
  204. var dataItemsTobeRemoved = [];
  205. var currentDataItemIds = [];
  206. targetSlot.getDataItemList().forEach(function (dataItem) {
  207. var id = dataItem.getId();
  208. currentDataItemIds.push(id);
  209. if (dataItemIds.indexOf(id) === -1) {
  210. dataItemsTobeRemoved.push(dataItem.getId());
  211. }
  212. });
  213. // step2: clear target slot
  214. if (currentDataItemIds.length > 0) {
  215. targetSlot.removeDataItemsMapping(currentDataItemIds, subTransaction);
  216. }
  217. // step3: add the new mappings
  218. if (dataItemIds.length > 0) {
  219. targetSlot.addDataItemsMapping(dataItemIds, null, subTransaction);
  220. }
  221. // TODO livewidget_cleanup - the original implementation did not clean up unmapped items
  222. // we just need to decide the behavior of this API
  223. // step4: remove what used to be in the target slot and not longer mapped.
  224. //this.getAPI().deleteDataItems(dataItemsTobeRemoved, subTransaction);
  225. this.transaction.endTransaction(subTransaction);
  226. }
  227. };
  228. SlotsImpl.prototype.swapSlots = function swapSlots(sourceSlotId, targetSlotId, transactionToken) {
  229. var subTransaction = this.transaction.startTransaction(transactionToken);
  230. var sourceSlot = this.getSlot(sourceSlotId);
  231. var targetSlot = this.getSlot(targetSlotId);
  232. var sourceSlotDataItems = sourceSlot.getDataItemList();
  233. sourceSlot.removeDataItemsMapping(sourceSlotDataItems.map(function (dataItem) {
  234. return dataItem.getId();
  235. }), subTransaction);
  236. var targetSlotDataItems = targetSlot.getDataItemList();
  237. targetSlot.removeDataItemsMapping(targetSlotDataItems.map(function (dataItem) {
  238. return dataItem.getId();
  239. }), subTransaction);
  240. sourceSlot.addDataItemsMapping(targetSlotDataItems.map(function (dataItem) {
  241. return dataItem.getId();
  242. }), null, subTransaction);
  243. targetSlot.addDataItemsMapping(sourceSlotDataItems.map(function (dataItem) {
  244. return dataItem.getId();
  245. }), null, subTransaction);
  246. this.transaction.endTransaction(subTransaction);
  247. };
  248. SlotsImpl.prototype.getSlot = function getSlot(slotId) {
  249. var slots = this.getSlotList();
  250. return _.find(slots, function (slot) {
  251. return slot.getId() === slotId;
  252. });
  253. };
  254. SlotsImpl.prototype.getSlotList = function getSlotList() {
  255. // TODO - livewidget cleanup - cache and free the list for performance
  256. return this._slotAPIList;
  257. };
  258. SlotsImpl.prototype.getMappedSlotList = function getMappedSlotList() {
  259. // TODO - livewidget cleanup - cache and free the list for performance
  260. var slots = this.getSlotList();
  261. var slotsWithDataItems = [];
  262. for (var i = 0; i < slots.length; i++) {
  263. var dataItems = slots[i].getDataItemList() || [];
  264. if (dataItems.length > 0) {
  265. slotsWithDataItems.push(slots[i]);
  266. }
  267. }
  268. return slotsWithDataItems;
  269. };
  270. SlotsImpl.prototype.getMappingInfo = function getMappingInfo(dataItemId) {
  271. var mappingInfoList = this.getMappingInfoList();
  272. return _.find(mappingInfoList, function (mappingInfo) {
  273. return mappingInfo.dataItem.getId() === dataItemId;
  274. });
  275. };
  276. SlotsImpl.prototype.getMappingInfoList = function getMappingInfoList() {
  277. var _this7 = this;
  278. // TODO - livewidget cleanup - cache and free the list for performance
  279. var result = [];
  280. this.definition.getSlotList().forEach(function (slotDefinition) {
  281. var slot = _this7.getSlot(slotDefinition.getId());
  282. var slotImpl = _this7.getSlotImpl(slotDefinition.getId());
  283. slotImpl.getDataItemList().forEach(function (dataItem) {
  284. result.push({
  285. slot: slot,
  286. dataItem: dataItem,
  287. indexInSlot: slot ? slotImpl.getDataItemIndex(dataItem.getId()) : -1
  288. });
  289. });
  290. });
  291. return result;
  292. };
  293. /**
  294. * @implements SlotsAPI#isMappingComplete
  295. */
  296. SlotsImpl.prototype.isMappingComplete = function isMappingComplete(layerId) {
  297. var mappedSlotIds = this.getMappedSlotList().map(function (slot) {
  298. return slot.getDefinition().getId();
  299. });
  300. var requiredSlots = this.getSlotList().filter(function (slot) {
  301. return !slot.getDefinition().isOptional();
  302. });
  303. var datasetList = this.visualizationImpl.getDefinition().getDatasetList();
  304. if (layerId) {
  305. datasetList = [{ id: layerId }];
  306. }
  307. var sharingSlots = this.getSlotList().filter(function (slot) {
  308. return slot.getDefinition().getDatasetIdList().length > 1;
  309. });
  310. // if the slot is sharing in two datasets, it's not multilayer
  311. var isMultilayers = datasetList.length > 1 && !sharingSlots.length > 0;
  312. var mappedDatasetList = datasetList.filter(function (dataset) {
  313. var unmappedRequiredSlots = requiredSlots.filter(function (slot) {
  314. var slotDatasetIdList = slot.getDefinition().getDatasetIdList();
  315. return slotDatasetIdList.indexOf(dataset.id) !== -1 && !(mappedSlotIds.indexOf(slot.getDefinition().getId()) !== -1);
  316. });
  317. return unmappedRequiredSlots.length === 0;
  318. });
  319. // If there is only one layer, all datasets should be mapped.
  320. if (!isMultilayers) {
  321. return datasetList.length === mappedDatasetList.length;
  322. }
  323. return mappedDatasetList.length > 0;
  324. };
  325. SlotsImpl.prototype.clearAllSlots = function clearAllSlots(transactionToken) {
  326. this.getSlotList().forEach(function (slot) {
  327. slot.removeDataItems(slot.getDataItemList().map(function (dataItem) {
  328. return dataItem.getId();
  329. }), transactionToken);
  330. });
  331. };
  332. SlotsImpl.prototype.getSlotImpl = function getSlotImpl(slotId) {
  333. return this._slots[slotId];
  334. };
  335. SlotsImpl.prototype.getAPI = function getAPI() {
  336. return this._api;
  337. };
  338. return SlotsImpl;
  339. }(SlotsAPISpec);
  340. return SlotsImpl;
  341. });
  342. //# sourceMappingURL=Slots.js.map