VisModelManager.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: Dashboard
  5. * (C) Copyright IBM Corp. 2013, 2020
  6. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  7. *
  8. * VisModelManager
  9. * INTENT: VisModelManager object is a top-level manager for the LiveWidgetModel and its sub-managers.
  10. * It has an api for use by external callers and the renderer.
  11. * TODO: The functionality in this class should be investigated and moved into more focused sub-objects.
  12. *
  13. * The VisModelManager owns VisDataSlots and VisProperties that the renderer pieces render,
  14. * interactivity modifies and save persists.
  15. *
  16. * It also has utilities to ease access for Visualization items to data-oriented actions
  17. * (like querying/filtering).
  18. */
  19. define(['underscore', './VisModelManagerWrappedAPI', './VisMetadataManager', '../../../../data/models/VisPropertyCollection', '../../../../filters/Filters', '../../../../lib/@waca/core-client/js/core-client/ui/core/Events', '../../../../data/models/Conditions'], function (_, VisModelManagerWrappedAPI, VisMetadataManager, VisPropertyCollection, FilterCollection, Events, ConditionsModel) {
  20. 'use strict';
  21. var VisModelManager = null; // class declaration
  22. VisModelManager = Events.extend([VisModelManagerWrappedAPI], {
  23. CHANCE_MAPPING_TYPES: {
  24. TRANSITION_NORMAL_MAPPING: 0,
  25. TRANSITION_INCOMPLETE_MAPPING: 1,
  26. TRANSITION_COMPLETE_MAPPING: 2,
  27. TRANSITION_UNDO_MAPPING_COMPLETE: 3,
  28. TRANSITION_REPLACE_NORMAL_MAPPING: 4
  29. },
  30. init: function init(options) {
  31. VisModelManager.inherited('init', this, arguments);
  32. this.localFilters = options.localFilters;
  33. this.searchFilters = options.searchFilters;
  34. this.logger = options.logger;
  35. this.visDefinitions = options.visDefinitions;
  36. this.widgetModel = options.widgetModel;
  37. this.dashboardApi = options.dashboardApi;
  38. this.transaction = this.dashboardApi.getFeature('Transaction');
  39. this.boardModel = options.boardModel;
  40. this.colors = options.colors;
  41. this.content = options.content;
  42. this.visMetadataManager = new VisMetadataManager({
  43. widgetModel: this.widgetModel,
  44. dashboardApi: this.dashboardApi,
  45. visualizationFeature: options.visualizationFeature
  46. });
  47. },
  48. initialize: function initialize(options) {
  49. options = options || {};
  50. this.propertySupport = options.propertySupport;
  51. this.filterSupport = options.filterSupport;
  52. this.displayTypeManager = options.displayTypeManager;
  53. this._pendingFiltersActive = false;
  54. this._suppressViewAnimations = false;
  55. },
  56. isFilterEditable: function isFilterEditable(filterEntry) {
  57. return this.filterSupport.isFilterEditable(filterEntry);
  58. },
  59. _convertTransactionTokenToLegacyOptions: function _convertTransactionTokenToLegacyOptions(transactionToken) {
  60. var oldOptions = {};
  61. if (transactionToken) {
  62. oldOptions.payloadData = {
  63. transactionToken: transactionToken
  64. };
  65. if (transactionToken.transactionId) {
  66. oldOptions.payloadData.undoRedoTransactionId = transactionToken.transactionId;
  67. }
  68. }
  69. return oldOptions;
  70. },
  71. /**
  72. *Swap data items between the two slots that are identified by their IDs
  73. *the operation should be one transaction
  74. *
  75. *@param {String} sourceSlotId the ID of the source slot
  76. *@param {String} targetSlotID the ID of the target slot
  77. **/
  78. swapSlots: function swapSlots(sourceSlotId, targetSlotId, transactionToken) {
  79. var subTransaction = this.transaction.startTransaction(transactionToken);
  80. var options = this._convertTransactionTokenToLegacyOptions(subTransaction);
  81. var targetSlotAPI = this.getDataSlotById(targetSlotId);
  82. var sourceSlotAPI = this.getDataSlotById(sourceSlotId);
  83. var aSourceDataItemRefs = _.clone(sourceSlotAPI.getDataItemRefs());
  84. var aTargetDataItemRefs = _.clone(targetSlotAPI.getDataItemRefs());
  85. targetSlotAPI.assignItemsToSlot(aSourceDataItemRefs, options);
  86. sourceSlotAPI.assignItemsToSlot(aTargetDataItemRefs, options);
  87. this.transaction.endTransaction(subTransaction);
  88. },
  89. // TODO livewidget_cleanup -- move this to the widget model
  90. getConditions: function getConditions(createNew) {
  91. var conditions = this.widgetModel.get('conditions');
  92. if (!conditions && createNew) {
  93. //@todo Not ideal fix until a new ConditionalFormatAPI is imlemented
  94. conditions = new ConditionsModel({ palette: { colors: [] } });
  95. this.widgetModel.set({
  96. 'conditions': conditions
  97. }, { silent: true });
  98. }
  99. return conditions;
  100. },
  101. getPossibleKeyDrivers: function getPossibleKeyDrivers() {
  102. var possibleKeyDrivers = this.widgetModel.get('possibleKeyDrivers');
  103. //If possibleKeyDrivers, clone them so the undo/redo manager stack can access changes
  104. return possibleKeyDrivers ? JSON.parse(JSON.stringify(possibleKeyDrivers)) : {};
  105. },
  106. setPossibleKeyDrivers: function setPossibleKeyDrivers(drivers, options) {
  107. this.widgetModel.set({
  108. 'possibleKeyDrivers': drivers
  109. }, options);
  110. },
  111. getTitle: function getTitle() {
  112. return this.widgetModel.get('name') || null;
  113. },
  114. setTitle: function setTitle(title, titleHtml, options) {
  115. this.widgetModel.set({
  116. 'name': title,
  117. 'titleHtml': titleHtml
  118. }, options);
  119. },
  120. getShowTitle: function getShowTitle() {
  121. var titleMode = this.widgetModel.get('titleMode');
  122. if (titleMode) {
  123. return titleMode !== 'noTitle';
  124. } else {
  125. return this.widgetModel.get('showTitle') || null;
  126. }
  127. },
  128. getAnnotations: function getAnnotations() {
  129. return this.widgetModel.get('annotations') || {};
  130. },
  131. setAnnotations: function setAnnotations(annotations, options) {
  132. this.widgetModel.set({
  133. 'annotations': annotations
  134. }, options);
  135. },
  136. getDefinition: function getDefinition() {
  137. try {
  138. return this.visDefinitions.getRawDefinition(this.getVisId());
  139. } catch (error) {
  140. // Show error should be handled in other places.
  141. this.logger.error(error);
  142. }
  143. },
  144. //TODO: It should be possible for a model manager to manager multiple modules.
  145. getMetadataAPI: function getMetadataAPI() {
  146. return this.visMetadataManager;
  147. },
  148. changeAggregationType: function changeAggregationType() {
  149. this.logger.error('ENDOR: VisModelManager: ChangeAggregationType is not yet implemented for live widget.');
  150. },
  151. //========================================================================================================
  152. /**
  153. * @returns the visId as is in the current definition.
  154. * The exception is during display type changes, this would be the visId 'post-change'.
  155. */
  156. getVisId: function getVisId() {
  157. return this.widgetModel.get('visId');
  158. },
  159. supportsSortAction: function supportsSortAction() {
  160. return this.getDefinition() && this.getDefinition().supportsSortAction;
  161. },
  162. supportsFormatAction: function supportsFormatAction() {
  163. return this.getDefinition() && this.getDefinition().supportsFormatAction;
  164. },
  165. supportsBinAction: function supportsBinAction() {
  166. return this.getDefinition() && this.getDefinition().canApplyBinning;
  167. },
  168. supportsCustomGroupAction: function supportsCustomGroupAction() {
  169. return this.getDefinition() && this.getDefinition().supportsCustomGroupAction;
  170. },
  171. /**
  172. * @returns {boolean} `true` iff vis supports maintainAxisScale
  173. */
  174. supportsMaintainAxisScale: function supportsMaintainAxisScale() {
  175. return !!(this.getDefinition() && this.getDefinition().supportsMaintainAxisScale);
  176. },
  177. /**
  178. * @returns {array} listenForPropChanges specified in the vizdef.An array of string for prop names.
  179. */
  180. getListenForPropChangesFromDefinition: function getListenForPropChangesFromDefinition() {
  181. return this.getDefinition() && this.getDefinition().listenForPropChanges;
  182. },
  183. /**
  184. * @return {boolean} `true` iff vis type is locked
  185. */
  186. isVisLocked: function isVisLocked() {
  187. var isLocked = this.widgetModel.get('visTypeLocked');
  188. return !!isLocked;
  189. },
  190. getPreferredSize: function getPreferredSize() {
  191. return this.getDefinition().preferredSize;
  192. },
  193. /**
  194. * Allocate a new filter collection...for test purposes.
  195. * @returns {FilterCollection}
  196. */
  197. _makeFilterCollection: function _makeFilterCollection() {
  198. return new FilterCollection();
  199. },
  200. /**
  201. * Set a visDataSlot to a new mapping
  202. * (eg: map slot XAxis to column { name: REVENUE, type: 'fact', ... })
  203. * @param propId The property ID (as defined in VisDefinitions)
  204. * (see: smart-viz/ws/src/main/webapp/WEB-INF/localGallery)
  205. * @param value The new value.
  206. */
  207. setDataSlotMapping: function setDataSlotMapping(slotId, mapping) {
  208. var slot = this.getDataSlotById(slotId);
  209. if (slot) {
  210. slot.setMapping(mapping);
  211. }
  212. },
  213. clearModelInvalid: function clearModelInvalid() {
  214. this._invalidReason = null;
  215. },
  216. setInvalidReason: function setInvalidReason(oError) {
  217. this._invalidReason = oError;
  218. },
  219. getInvalidReason: function getInvalidReason() {
  220. return this._invalidReason;
  221. },
  222. /**
  223. * @returns a specification for this particular visualization subtype
  224. * as a path to a template file.
  225. * (In the case of RAVE, this would be the RAVE template specification for the
  226. * specific visualization...eg: bubblechart.json or bars.json)
  227. */
  228. getSpecification: function getSpecification() {
  229. return this.getDefinition() ? this.getDefinition().specification : null;
  230. },
  231. /**
  232. * @returns the renderer for this VisModelManager as a path and name as defined in vis definitions.
  233. * (see: smart-viz/ws/src/main/webapp/WEB-INF/localGallery)
  234. */
  235. getRenderer: function getRenderer() {
  236. return this.getDefinition() ? this.getDefinition().renderer : null;
  237. },
  238. /**
  239. * @params moduleRef (optional) - a reference to a module. If not specified, the default module associated with this model is returned.
  240. * @returns a module with the specified moduleRef (or the default module if no moduleRef is specified)
  241. */
  242. getModule: function getModule(moduleRef) {
  243. return this.visMetadataManager ? this.visMetadataManager.getModule(moduleRef) : this.getCanvas().getDataSource();
  244. },
  245. getMetadataManager: function getMetadataManager() {
  246. return this.visMetadataManager;
  247. },
  248. getMetadataColumn: function getMetadataColumn(columnId, moduleRef) {
  249. return this.visMetadataManager ? this.visMetadataManager.getMetadataColumn(columnId, moduleRef) : null;
  250. },
  251. /**
  252. * @return array of metadata columns which are being used in the model
  253. */
  254. getUsedMetadataColumns: function getUsedMetadataColumns() {
  255. return this.visMetadataManager ? this.visMetadataManager.getMetadataColumns() : null;
  256. },
  257. /**
  258. * @returns the module id for this VisModelManager.
  259. */
  260. getModuleId: function getModuleId() {
  261. // TODO currently only one data view is supported. When we support multiple dataViews, dataItemId should be used to get correct module Id.
  262. return this.getModule() ? this.getModule().getSourceId() : null;
  263. },
  264. /**
  265. * TEMPORARY METHOD: The VisCanvas is being deprecated but is still created in the original board.
  266. * Until the canvas is completely removed, callers can call getCanvas() as normal
  267. * and will either return
  268. * 1) the canvas object (if a VisCanvas has been created)
  269. * 2) a temporary object with a getDataSource() method that returns the module member of visModel.
  270. */
  271. getCanvas: function getCanvas() {
  272. if (this.canvas) {
  273. return this.canvas;
  274. }
  275. return {
  276. module: this.getModule(),
  277. getDataSource: function getDataSource() {
  278. return this.getModule();
  279. }
  280. };
  281. },
  282. getLocalFilters: function getLocalFilters() {
  283. return this.localFilters;
  284. },
  285. setSuppressViewAnimations: function setSuppressViewAnimations(suppress) {
  286. this._suppressViewAnimations = suppress;
  287. },
  288. getSuppressViewAnimations: function getSuppressViewAnimations() {
  289. return this._suppressViewAnimations;
  290. },
  291. doLocalSort: function doLocalSort() {
  292. return this.getDefinition() && this.getDefinition().clientSort;
  293. },
  294. hasBinnedDataItems: function hasBinnedDataItems() {
  295. return this.mappingAPI.hasBinnedDataItems();
  296. },
  297. getMetaDataValue: function getMetaDataValue(name) {
  298. var definition = this.getDefinition();
  299. if (definition && definition.metaDataEntries) {
  300. var foundEntry = _.find(definition.metaDataEntries, function (metaDataEntry) {
  301. return metaDataEntry.name === name;
  302. });
  303. return foundEntry ? foundEntry.value : null;
  304. }
  305. return null;
  306. },
  307. cleanUpMissingFilters: function cleanUpMissingFilters() {
  308. this.localFilters.cleanUpMissingFilterEntries(this.visMetadataManager);
  309. },
  310. isIgnoreDefaultSlotSort: function isIgnoreDefaultSlotSort(dataItem) {
  311. return this.mappingAPI.isIgnoreDefaultSlotSort(dataItem);
  312. }
  313. });
  314. return VisModelManager;
  315. });
  316. //# sourceMappingURL=VisModelManager.js.map