VIPRProperties.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. 'use strict';
  2. /**
  3. *+------------------------------------------------------------------------+
  4. *| Licensed Materials - Property of IBM
  5. *| IBM Cognos Products: Dashboard
  6. *| (C) Copyright IBM Corp. 2017, 2021
  7. *|
  8. *| US Government Users Restricted Rights - Use, duplication or disclosure
  9. *| restricted by GSA ADP Schedule Contract with IBM Corp.
  10. *+------------------------------------------------------------------------+
  11. */
  12. define(['underscore', 'jquery', '../../../widgets/livewidget/nls/StringResources', '../VIPRUtils', './VIPRPropertiesOrderer', 'com/ibm/vipr/VIPR', '../VIPRConfig', 'dashboard-analytics/visualizations/properties/PropertiesCreator', 'dashboard-analytics/visualizations/vipr/properties/ColorPropertiesCreator', 'dashboard-analytics/visualizations/properties/PropertySectioner', 'dashboard-analytics/util/FontFamilyOptions', './PropertiesHelper', '../../../apiHelpers/SlotAPIHelper'], function (_, $, StringResources, VIPRUtils, Orderer, VIPR, VIPRConfig, PropertiesCreator, ColorPropertiesCreator, PropertySectioner, fontFamilyOptions, PropertiesHelper, SlotAPIHelper) {
  13. 'use strict';
  14. var supportedPropPanelFont = ['widget.legend.font', 'itemAxis.title.font', 'itemAxis.ticks.labels.font', 'valueAxis.title.font', 'valueAxis.ticks.labels.font', 'valueAxis.column.ticks.labels.font', 'valueAxis.column.title.font', 'valueAxis.line.title.font'];
  15. var allowedGroups = ['widget.legend.color', 'valueAxis.column.ticks.labels.color', 'valueAxis.column.ticks.labels.font'];
  16. // Avoid conflict with dashboard tab ids
  17. var customVisGroupNamePrefix = 'customVis-';
  18. var customVisSupportedPropPanelFont = [];
  19. var customVisAllowedGroups = [];
  20. /*
  21. * This object represents the VIPR Properties management. It is built to be a singleton.
  22. * Its purpose is to create the current runtime properties list in a JSON form
  23. * consumable by the current properties panel. Its built as a singleton as it
  24. * does not need to hold any state
  25. */
  26. var VIPRProperties = function () {
  27. /**
  28. * Instance stores a reference to the Singleton
  29. * @type {object}
  30. */
  31. var instance = null;
  32. function init() {
  33. return {
  34. /**
  35. * @param id - vis id of interest
  36. * @returns the vipr configuration (bundle + our overrides) for the given id
  37. */
  38. _getConfiguration: function _getConfiguration(id) {
  39. return VIPRConfig.getConfig(id) || {};
  40. },
  41. // Added for unit test purposes to hide the Orderer.
  42. _orderProperties: function _orderProperties(mappedItems) {
  43. Orderer.getInstance().orderProperties(mappedItems);
  44. },
  45. _filterToActiveProperties: function _filterToActiveProperties(fullSetOfProperties) {
  46. return _.filter(fullSetOfProperties, function (prop) {
  47. return prop.active === true;
  48. });
  49. },
  50. /**
  51. * Vida has added new properties. We only support a few right now but
  52. * they need to be added to the correct layers. Because they are of types
  53. * that we support they are initially created. We must find them and
  54. * organize them into layers before we send them to the properties panel.
  55. */
  56. _moveLayersProperties: function _moveLayersProperties(visId, mappedItems) {
  57. var configuration = instance._getConfiguration(visId);
  58. // If the bundle supports layers then we need to create color props for each layer
  59. if (configuration && configuration.supportsLayers) {
  60. configuration.layerDescriptions.forEach(function (layerDesc) {
  61. var collapsibleSection = mappedItems[layerDesc.id];
  62. if (collapsibleSection) {
  63. layerDesc.visibleLayerProps.forEach(function (visiblePropId) {
  64. var mappedProp = mappedItems[visiblePropId];
  65. if (mappedProp) {
  66. // We have a prop to move to a layer. Add it to the correct
  67. // layer and remove it from the main mapped items (which also
  68. // contains the collapsible section)
  69. collapsibleSection.items.push(mappedProp);
  70. delete mappedItems[visiblePropId];
  71. }
  72. });
  73. }
  74. });
  75. }
  76. },
  77. _addColorRelatedProperties: function _addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId) {
  78. ColorPropertiesCreator.getInstance().addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId);
  79. },
  80. _getPropertyDescriptionForProperty: function _getPropertyDescriptionForProperty(property, PropCreatorInstance) {
  81. var propDesc = null;
  82. if (property.type === 'boolean') {
  83. propDesc = PropCreatorInstance.createCheckboxProperty(property);
  84. } else if (property.type === 'enum') {
  85. propDesc = PropCreatorInstance.createEnumProperty(property);
  86. } else if (property.type === 'string') {
  87. propDesc = PropCreatorInstance.createTextInputProperty(property);
  88. } else if (property.type === 'number' || property.type === 'length') {
  89. propDesc = PropCreatorInstance.createNumberProperty(property);
  90. } else if (property.type === 'font') {
  91. propDesc = PropCreatorInstance.createFontSizeProperty(property);
  92. } else if (property.type === 'color') {
  93. propDesc = ColorPropertiesCreator.getInstance().createColorProperty(property);
  94. }
  95. return propDesc;
  96. },
  97. _doesConfigSupportProp: function _doesConfigSupportProp(visId, propName, value) {
  98. return VIPRUtils.doesConfigPropertyMatchExpected(visId, propName, value);
  99. },
  100. _addMaintainAxisScalePropIfNeeded: function _addMaintainAxisScalePropIfNeeded(visId, PropCreatorInstance, mappedItems) {
  101. if (instance._doesConfigSupportProp(visId, 'supportsMaintainAxisScale', true)) {
  102. mappedItems['maintainAxisScales'] = PropCreatorInstance.getMaintainAxisScaleProperty();
  103. }
  104. },
  105. _addDonutRadiusIfNeeded: function _addDonutRadiusIfNeeded(viprProperties, PropCreatorInstance, mappedItems) {
  106. // If the vipr bundle supports donut radius, create the property.
  107. var donutRadiusProp = viprProperties.get('donutRadius');
  108. if (donutRadiusProp) {
  109. mappedItems['donutRadius'] = PropCreatorInstance.getDonutRadius(donutRadiusProp);
  110. }
  111. },
  112. _addAggTypeIfNeeded: function _addAggTypeIfNeeded(mappedItems, possibleDataSlots) {
  113. var mappedItem = {
  114. id: 'widget.legend.aggregateTypeVisible',
  115. type: 'ToggleButton',
  116. propertyType: 'CheckBox',
  117. label: StringResources.get('aggregateTypeToggler'),
  118. ariaLabel: StringResources.get('aggregateTypeToggler'),
  119. public: true,
  120. name: 'widget.legend.aggregateTypeVisible',
  121. displayPos: 38,
  122. checked: false,
  123. defaultValue: false,
  124. active: _.some(possibleDataSlots, function (slot) {
  125. return SlotAPIHelper.isMultiMeasuresValueSlot(slot) === true;
  126. }) && mappedItems['widget.legend.titleVisible'].active
  127. };
  128. mappedItems['widget.legend.aggregateTypeVisible'] = mappedItem;
  129. },
  130. /**
  131. * Add a specified color set property
  132. * @param {Object} viprProperties
  133. * @param {Object} mappedItems - mapping of properties to their JSON description
  134. * @param {String} propId - property ID to be added.
  135. */
  136. _addColorSetProperty: function _addColorSetProperty(viprProperties, mappedItems, propId, config, visId) {
  137. var colorProp = VIPRUtils.isPropertyIncluded(visId, propId) ? viprProperties.get(propId) : undefined;
  138. var propConfig = config.properties[propId];
  139. var isCustomVis = this._isCustomVis(visId);
  140. if (colorProp) {
  141. mappedItems[propId] = _.extend({
  142. showHexValue: true,
  143. paletteType: 'DashboardColorSet',
  144. id: propId,
  145. label: isCustomVis && propConfig.caption ? propConfig.caption : propConfig.caption ? StringResources.get(propConfig.caption) : colorProp.caption,
  146. type: 'ColorPicker',
  147. open: false,
  148. originalGroupName: isCustomVis && this._hasVisPropertyValue(propId, 'originalGroupName', mappedItems) ? mappedItems[propId].originalGroupName : null,
  149. groupName: isCustomVis && this._hasVisPropertyValue(propId, 'groupName', mappedItems) ? mappedItems[propId].groupName : null,
  150. groupCaption: isCustomVis && this._hasVisPropertyValue(propId, 'groupCaption', mappedItems) ? mappedItems[propId].groupCaption : null,
  151. sectionName: StringResources.get('sectionName_colorPalette'),
  152. tabName: StringResources.get('tabName_visualization'),
  153. ariaLabel: isCustomVis ? this._hasVisPropertyValue(propId, 'name', mappedItems) : propConfig.caption ? StringResources.get(propConfig.caption) : config.caption,
  154. public: colorProp.public === undefined ? true : colorProp.public,
  155. active: colorProp.active === undefined ? true : colorProp.active
  156. }, _.pick(config.properties[propId], 'addButton', 'displayPos'));
  157. }
  158. },
  159. _hasVisPropertyValue: function _hasVisPropertyValue(propId, name, mappedItems) {
  160. return mappedItems[propId] && mappedItems[propId][name];
  161. },
  162. isTargetThicknessInputValid: function isTargetThicknessInputValid(value) {
  163. // Remove px if need be.
  164. var valueWithoutUnit = value && value.endsWith && value.endsWith('px') ? Number(value.slice(0, -2)) : Number(value);
  165. return Number.isInteger(valueWithoutUnit) && valueWithoutUnit >= 2 && valueWithoutUnit <= 20;
  166. },
  167. _addTargetMarkerThicknessIfNeeded: function _addTargetMarkerThicknessIfNeeded(viprProperties, PropCreatorInstance, mappedItems, visId) {
  168. // If the vipr bundle supports target markers, create the property.
  169. var targetThicknessProp = VIPRUtils.isPropertyIncluded(visId, 'target.marker.thickness') ? viprProperties.get('target.marker.thickness') : undefined;
  170. if (targetThicknessProp) {
  171. var numberProp = PropCreatorInstance.createNumberProperty(targetThicknessProp);
  172. var minPx = 2;
  173. var maxPx = 20;
  174. numberProp.handleReturnKey = true;
  175. numberProp.placeHolderText = StringResources.get('targetThicknessPlaceHolder', {
  176. min: minPx,
  177. max: maxPx
  178. });
  179. numberProp.showInlineError = true;
  180. numberProp.customValidatorCallback = function (value) {
  181. return {
  182. isValid: instance.isTargetThicknessInputValid(value),
  183. message: StringResources.get('targetThicknessErrorMsg', {
  184. min: minPx,
  185. max: maxPx
  186. })
  187. };
  188. };
  189. mappedItems['target.marker.thickness'] = numberProp;
  190. }
  191. },
  192. _addPropsFromVIPR: function _addPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId) {
  193. var _this = this;
  194. // Use only known properties and get the properties from Vida.
  195. var configuration = instance._getConfiguration(visId);
  196. configuration.config && configuration.config.include.forEach(function (propertyName) {
  197. _this._addPropertyFromVIPR(viprProperties, propertyName, PropCreatorInstance, mappedItems, visId);
  198. });
  199. },
  200. _addCustomVisPropsFromVIPR: function _addCustomVisPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId) {
  201. var _this2 = this;
  202. customVisSupportedPropPanelFont = [];
  203. customVisAllowedGroups = [];
  204. var groupProperties = this._getGroupProperties(visId);
  205. _.forEach(groupProperties, function (properties, groupName) {
  206. properties.forEach(function (property) {
  207. _this2._addPropertyFromVIPR(viprProperties, property, PropCreatorInstance, mappedItems, visId, groupName, true);
  208. });
  209. });
  210. },
  211. _addPropertyFromVIPR: function _addPropertyFromVIPR(viprProperties, propertyName, PropCreatorInstance, mappedItems, visId, groupName, isCustomVis) {
  212. var property = viprProperties.get(propertyName);
  213. if (property) {
  214. var overridenProp = VIPRUtils.overrideProperty(visId, property, propertyName);
  215. if (overridenProp.hidden !== true) {
  216. var propDesc = instance._getPropertyDescriptionForProperty(overridenProp, PropCreatorInstance);
  217. if (propDesc) {
  218. //We want to use our known property ids so replace them here.
  219. propDesc.name = propertyName;
  220. propDesc.id = propertyName;
  221. if (groupName) {
  222. var groupCaption = viprProperties.get(groupName).caption;
  223. propDesc.groupName = customVisGroupNamePrefix + $.escapeSelector(groupName);
  224. propDesc.originalGroupName = groupName;
  225. propDesc.groupCaption = groupCaption;
  226. if (isCustomVis) {
  227. if (!viprProperties.get(groupName).active) {
  228. // if the group is inactive, all it's child properties should be inactive
  229. propDesc.active = false;
  230. }
  231. this._addCustomVisAllowedGroups(propDesc, property);
  232. }
  233. }
  234. mappedItems[propertyName] = propDesc;
  235. }
  236. }
  237. }
  238. },
  239. _addCustomVisAllowedGroups: function _addCustomVisAllowedGroups(propDesc, property) {
  240. if (propDesc.propertyType === 'font') {
  241. if (!(customVisAllowedGroups.indexOf(this._getFontColorGroupName(propDesc.id, 'font')) !== -1)) {
  242. customVisAllowedGroups.push(this._getFontColorGroupName(propDesc.id, 'font'));
  243. }
  244. customVisSupportedPropPanelFont.push(propDesc.name);
  245. } else if (propDesc.propertyType === 'Color') {
  246. if (!(customVisAllowedGroups.indexOf(this._getFontColorGroupName(propDesc.id, 'color')) !== -1)) {
  247. customVisAllowedGroups.push(this._getFontColorGroupName(propDesc.id, 'color'));
  248. propDesc.caption = property.caption;
  249. }
  250. }
  251. },
  252. _getFontColorGroupName: function _getFontColorGroupName(groupName, type) {
  253. return groupName + '.' + type;
  254. },
  255. _isCustomVisAllowedGroups: function _isCustomVisAllowedGroups(id) {
  256. var customVisFontAllowedGroups = customVisAllowedGroups.indexOf(this._getFontColorGroupName(id, 'font')) !== -1;
  257. var customVisColorAllowedGroups = customVisAllowedGroups.indexOf(this._getFontColorGroupName(id, 'color')) !== -1;
  258. return customVisFontAllowedGroups || customVisColorAllowedGroups;
  259. },
  260. _filterListonToActiveProperties: function _filterListonToActiveProperties(activeProps, visId) {
  261. var listenForPropChanges = this._getListenForPropChangesFromVIPRConfig(visId);
  262. var propChanges = listenForPropChanges.slice();
  263. listenForPropChanges.forEach(function (propName) {
  264. var props = activeProps.filter(function (prop) {
  265. return prop.name === propName;
  266. });
  267. if (!props.length) {
  268. var indexToRemove = propChanges.indexOf(propName);
  269. if (indexToRemove !== -1) {
  270. propChanges.splice(indexToRemove, 1);
  271. }
  272. }
  273. });
  274. this._setListenForPropChangesForVIPRConfig(visId, propChanges);
  275. },
  276. _getPropertyListFromVIPRConfig: function _getPropertyListFromVIPRConfig(visId) {
  277. var configuration = instance._getConfiguration(visId);
  278. return configuration && configuration.propertyList;
  279. },
  280. _getListenForPropChangesFromVIPRConfig: function _getListenForPropChangesFromVIPRConfig(visId) {
  281. var configuration = instance._getConfiguration(visId);
  282. return configuration && configuration.listenForPropChanges;
  283. },
  284. _setListenForPropChangesForVIPRConfig: function _setListenForPropChangesForVIPRConfig(visId, listenForPropChanges) {
  285. var configuration = instance._getConfiguration(visId);
  286. configuration.listenForPropChanges = listenForPropChanges;
  287. },
  288. _isCustomVis: function _isCustomVis(visId) {
  289. var configuration = instance._getConfiguration(visId);
  290. return configuration && configuration.isCustomVis;
  291. },
  292. _getGroupProperties: function _getGroupProperties(visId) {
  293. var configuration = instance._getConfiguration(visId);
  294. return configuration && configuration.groupedProperty;
  295. },
  296. /**
  297. * Add Color set Properties from the include list
  298. * @param {Object} viprProperties
  299. * @param {Object} mappedItems - mapping of properties to their JSON description
  300. */
  301. _addColorSetProps: function _addColorSetProps(viprProperties, mappedItems, visId) {
  302. var configuration = instance._getConfiguration(visId);
  303. configuration.config && configuration.config.include.forEach(function (propertyName) {
  304. var property = viprProperties.get(propertyName);
  305. if (property) {
  306. var overridenProp = VIPRUtils.overrideProperty(visId, property, propertyName);
  307. // If the property configuration has been enhanced with the colorClass flag, add it.
  308. if (overridenProp.colorClass) {
  309. instance._addColorSetProperty(viprProperties, mappedItems, propertyName, configuration, visId);
  310. }
  311. }
  312. });
  313. },
  314. /**
  315. * Get the properties for the VIPR Widget in a form that is consumeable by
  316. * the properties panel.
  317. * @param viprProperties raw properties from vida bundle or widget
  318. * @param possibleDataSlots - all possible slots for the current vis type
  319. * @returns array of properties panel mapped properties
  320. */
  321. getProperties: function getProperties(viprProperties, possibleDataSlots, visId) {
  322. var mappedItems = {};
  323. var PropCreatorInstance = PropertiesCreator.getInstance();
  324. var isCustomVis = this._isCustomVis(visId);
  325. if (isCustomVis) {
  326. instance._addCustomVisPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId);
  327. } else {
  328. instance._addPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId);
  329. }
  330. instance._addMaintainAxisScalePropIfNeeded(visId, PropCreatorInstance, mappedItems);
  331. instance._addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId);
  332. instance._addAggTypeIfNeeded(mappedItems, possibleDataSlots);
  333. instance._addDonutRadiusIfNeeded(viprProperties, PropCreatorInstance, mappedItems);
  334. instance._addTargetMarkerThicknessIfNeeded(viprProperties, PropCreatorInstance, mappedItems, visId);
  335. instance._addColorSetProps(viprProperties, mappedItems, visId);
  336. instance._moveLayersProperties(visId, mappedItems);
  337. instance._orderProperties(mappedItems);
  338. var allProps = _.toArray(mappedItems);
  339. //only return active properties.
  340. var filteredProps = instance._filterToActiveProperties(allProps);
  341. if (isCustomVis) {
  342. instance._filterListonToActiveProperties(allProps, visId);
  343. }
  344. return instance._sectionalizeProperties(filteredProps);
  345. },
  346. getPropertyList: function getPropertyList(viprProperties, possibleDataSlots, content) {
  347. var definition = content.getFeature('Visualization').getDefinition();
  348. if (definition.getState().getError()) {
  349. return [];
  350. }
  351. var visId = definition.getId();
  352. var properties = this.getProperties(viprProperties, possibleDataSlots, visId);
  353. var propertieslist = instance._getPropertyListFromVIPRConfig(visId);
  354. if (propertieslist && !_.isEmpty(propertieslist)) {
  355. properties = properties.concat(propertieslist); //Merge customized property list from viprConfig
  356. }
  357. return this._toUIControlProperties(properties);
  358. },
  359. getPropertyLayoutList: function getPropertyLayoutList(viprProperties, possibleDataSlots, content, dashboard) {
  360. var _this3 = this;
  361. var visId = content.getFeature('Visualization').getDefinition().getId();
  362. var isCustomVis = this._isCustomVis(visId);
  363. var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {};
  364. var layouts = {};
  365. var extraEditors = [];
  366. // filter out any non-public properties
  367. var properties = this.getProperties(viprProperties, possibleDataSlots, visId);
  368. // Use the map to ensure entries are unique
  369. _.each(properties, function (prop) {
  370. // collect the tab (group) layouts
  371. layouts[prop.tabId] = {
  372. type: 'Group',
  373. id: prop.tabId,
  374. label: prop.tabName
  375. };
  376. // collect the section layouts (optional)
  377. var sectioner = PropertySectioner.getInstance();
  378. if (prop.sectionId) {
  379. var sectionIds = [];
  380. PropertiesHelper.splitEscapedString(prop.sectionId, '.', sectionIds);
  381. sectionIds.forEach(function (sectionId, index) {
  382. //The first sectionId has its info on the prop object
  383. var sectionInfo = {
  384. type: 'Section',
  385. id: sectionId,
  386. label: prop.sectionName,
  387. position: prop.sectionPosition
  388. };
  389. if (index != 0) {
  390. sectionInfo = sectioner.getSection(sectionId);
  391. if (!sectionInfo) {
  392. throw new Error('section info not found');
  393. }
  394. }
  395. layouts[sectionId] = sectionInfo;
  396. });
  397. }
  398. var supportGrouping = allowedGroups.indexOf(prop.id) !== -1 || _this3._isCustomVisAllowedGroups(prop.id);
  399. var customVisGroup = [];
  400. if (isCustomVis && supportGrouping && prop.originalGroupName) {
  401. customVisGroup = groupedProperty[prop.originalGroupName];
  402. }
  403. if (supportedPropPanelFont.indexOf(prop.id) !== -1 || customVisSupportedPropPanelFont.indexOf(prop.id) !== -1) {
  404. extraEditors = extraEditors.concat(_this3._getFontPropertyLayout(prop, content, VIPRUtils, dashboard, isCustomVis));
  405. } else if ((isCustomVis && customVisGroup.indexOf(prop.id) !== -1 || groupedProperty[prop.id]) && supportGrouping) {
  406. extraEditors = extraEditors.concat(_this3._getGroupedPropertyLayout(prop, content, dashboard));
  407. }
  408. });
  409. return _.values(layouts).concat(extraEditors);
  410. },
  411. _sectionalizeProperties: function _sectionalizeProperties(props) {
  412. var sectioner = PropertySectioner.getInstance();
  413. var lastSectionPosition = 100;
  414. props.forEach(function (prop) {
  415. var propInfo = sectioner.getSectionInformationForPropertyId(prop.id);
  416. if (propInfo) {
  417. prop.sectionId = prop.groupName || propInfo.sectionId || prop.sectionId;
  418. prop.sectionName = prop.groupCaption || propInfo.sectionName || prop.sectionName;
  419. prop.tabId = propInfo.tabId || prop.tabId;
  420. prop.tabName = propInfo.tabName || prop.tabName;
  421. prop.sectionPosition = propInfo.sectionPosition || lastSectionPosition;
  422. }
  423. });
  424. return props;
  425. },
  426. _toUIControlProperties: function _toUIControlProperties(properties) {
  427. var _this4 = this;
  428. return _.map(properties, function (property) {
  429. var entry = _.pick(property, 'id');
  430. entry.editor = {
  431. // @todo support for Split?
  432. sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId,
  433. uiControl: _this4._getPropertyUIControl(property)
  434. };
  435. if (_.isNumber(property.displayPos)) {
  436. entry.editor.position = property.displayPos;
  437. }
  438. // non public property is visually hidden
  439. var isPrivateProp = property.public === false;
  440. //A non default font properties UI is contributed via getPropertyLayoutList. Hide the default.
  441. var isSupportedPropPanelFont = supportedPropPanelFont.indexOf(entry.id) !== -1 || customVisSupportedPropPanelFont.indexOf(entry.id) !== -1;
  442. //A non default group properties UI is contributed via getPropertyLayoutList. Hide the default.
  443. var isGroupedProperty = allowedGroups.indexOf(entry.id) !== -1 || _this4._isCustomVisAllowedGroups(entry.id);
  444. if (isPrivateProp || isSupportedPropPanelFont || isGroupedProperty) {
  445. entry.editor.hidden = true;
  446. }
  447. return entry;
  448. });
  449. },
  450. _getLegendFontSizeOptions: function _getLegendFontSizeOptions() {
  451. return [{ value: 'auto', label: StringResources.get('automaticTypeCaption') }, { value: '11px', label: '11px' }, { value: '14px', label: '14px' }, { value: '16px', label: '16px' }];
  452. },
  453. _getNonLegendFontSizeOptions: function _getNonLegendFontSizeOptions() {
  454. return [{ value: 'auto', label: StringResources.get('automaticTypeCaption') }, { value: '12px', label: '12px' }, { value: '14px', label: '14px' }, { value: '16px', label: '16px' }, { value: '24px', label: '24px' }];
  455. },
  456. _getGroupedPropertyLayout: function _getGroupedPropertyLayout(property, content, dashboard) {
  457. var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {};
  458. return [{
  459. id: property.id,
  460. editor: {
  461. position: property.displayPos,
  462. sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId,
  463. uiControl: this._getPropertyUIControl(_.extend(property, {
  464. onChange: function onChange(propertyID, value) {
  465. if (property.type === 'ColorPicker') {
  466. value = value.name;
  467. }
  468. var propertyList = [propertyID];
  469. _.each(groupedProperty[propertyID], function (prop) {
  470. return propertyList.push(prop);
  471. });
  472. var transactionToken = dashboard.getFeature('Transaction').startTransaction();
  473. propertyList.forEach(function (prop) {
  474. return content.setPropertyValue(prop, value, transactionToken);
  475. });
  476. dashboard.getFeature('Transaction').endTransaction(transactionToken);
  477. }
  478. }))
  479. }
  480. }];
  481. },
  482. _getFontPropertyLayout: function _getFontPropertyLayout(property, content, viprUtils, dashboard, isCustomVis) {
  483. var _fontFamilyOptions = [].concat(fontFamilyOptions);
  484. _fontFamilyOptions.unshift({ value: 'auto', label: StringResources.get('automaticTypeCaption') });
  485. var fontFamily = {
  486. id: 'font.xdashboardx.' + property.id,
  487. editor: {
  488. position: property.displayPos,
  489. sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId,
  490. uiControl: this._getPropertyUIControl({
  491. name: 'font.xdashboardx.' + property.id,
  492. active: true,
  493. options: _fontFamilyOptions,
  494. public: true,
  495. ariaLabel: StringResources.get('fontPropLabel'),
  496. label: isCustomVis && property.label ? property.label + ' ' + StringResources.get('fontFamily') : StringResources.get('fontPropLabel'),
  497. type: 'DropDown',
  498. onChange: this._getSetFontProperty('font', property.id, content, viprUtils, dashboard),
  499. value: viprUtils.getVidaFontPropertiesPart('family', content.getPropertyValue(property.id)) || StringResources.get('automaticTypeCaption')
  500. })
  501. }
  502. };
  503. var fontSize = {
  504. id: 'fontSize.xdashboardx.' + property.id,
  505. editor: {
  506. position: property.displayPos + 1,
  507. sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId,
  508. uiControl: this._getPropertyUIControl(_.extend(property, {
  509. ariaLabel: StringResources.get('fontSizePropLabel'),
  510. label: isCustomVis && property.label ? property.label + ' ' + StringResources.get('fontSize') : StringResources.get('fontSizePropLabel'),
  511. options: property.id === 'widget.legend.font' ? this._getLegendFontSizeOptions() : this._getNonLegendFontSizeOptions(),
  512. onChange: this._getSetFontProperty('fontSize', property.id, content, viprUtils, dashboard),
  513. value: viprUtils.getVidaFontPropertiesPart('size', content.getPropertyValue(property.id)) || StringResources.get('automaticTypeCaption')
  514. }))
  515. }
  516. };
  517. return [fontFamily, fontSize];
  518. },
  519. _getSetFontProperty: function _getSetFontProperty(fontPart, propertyID, content, viprUtils, dashboard) {
  520. return function (psuedoPropertyID, value) {
  521. var _viprUtils$buildVidaF;
  522. var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {};
  523. if (value === 'auto') {
  524. value = null;
  525. }
  526. var fontProperty = viprUtils.buildVidaFontPropertiesFromParts((_viprUtils$buildVidaF = {}, _viprUtils$buildVidaF[fontPart] = value, _viprUtils$buildVidaF), content.getPropertyValue(propertyID));
  527. var propertyList = [propertyID];
  528. if (allowedGroups.indexOf(propertyID) !== -1) {
  529. _.each(groupedProperty[propertyID], function (prop) {
  530. return propertyList.push(prop);
  531. });
  532. }
  533. var transactionToken = dashboard.getFeature('Transaction').startTransaction();
  534. propertyList.forEach(function (prop) {
  535. return content.setPropertyValue(prop, fontProperty, transactionToken);
  536. });
  537. dashboard.getFeature('Transaction').endTransaction(transactionToken);
  538. }.bind(this);
  539. },
  540. _getPropertyUIControl: function _getPropertyUIControl(property) {
  541. // exclude all general and layout properties
  542. return _.omit(property, 'id', 'public', 'displayPos', 'tabId', 'tabName', 'sectionPosition', 'sectionId', 'sectionName');
  543. },
  544. /**
  545. * An abstraction layer to hide how we set the properties in VIPR. This will
  546. * get more complicated as we add color property support.
  547. * @param widget - The vipr widget
  548. * @param info - property description
  549. * id - property id
  550. * value - value to set the property to.
  551. */
  552. setProperty: function setProperty(widget, info) {
  553. widget.setProperty(info.id, info.value);
  554. },
  555. /**
  556. * FredIsRed is a term/service that is used to describe various methods that assign colours
  557. * to data values in automatic and user-defined ways.
  558. * VIPR implements a callback on the categorical paletteResolver that allows a callback to be invoked.
  559. * Provide a function to Massage the VIPR-specific tuple into a generic form and call the fredIsRed service.
  560. * @param fredIsRedAPI - the fredIsRed interface.
  561. * @param categoricalPaletteResolver - the VIDA categorical paletteResolver
  562. * @param defaultIndex - the default colour index for this palette.
  563. */
  564. _initializeFredIsRedPalette: function _initializeFredIsRedPalette(fredIsRedAPI, categoricalPaletteResolver, defaultIndex) {
  565. var paletteInfo = {
  566. defaultIndex: defaultIndex || 0,
  567. colors: categoricalPaletteResolver.colors,
  568. colorCallback: VIPR.util.Color.rgb
  569. };
  570. var viprGetColor = function viprGetColor(tuple, dataItem, level) {
  571. //Convert the VIPR tuple to a labelArray (or undefined for defaultIndex) and call the generic fredIsRed getColor API.
  572. var labelArray = [];
  573. if (typeof tuple !== 'undefined' && typeof dataItem !== 'undefined' && typeof level !== 'undefined' && level >= 0) {
  574. // hierarchical visulizations such as treemap asks color for the Item on a specfic level
  575. // e.g. level = 0 , tuple:{items:[{source:{unformattedValue:{'Fall'}}},{source:{unformattedValue:{'2018'}}}]};
  576. // returns labelArray as ['Fall']
  577. var tupleItem = tuple && tuple.items[level];
  578. labelArray.push(tupleItem && tupleItem.source && tupleItem.source.unformattedValue || '');
  579. } else {
  580. // most visulizations(non-hierarchical) request colors for Typle Objects
  581. // e.g. level = -1 , tuple:{items:[{source:{unformattedValue:{'Fall'}}}]};
  582. // returns labelArray as ['Fall']
  583. labelArray = tuple && _.map(tuple.items, function (tupleItem) {
  584. return tupleItem.source && tupleItem.source.unformattedValue || '';
  585. });
  586. }
  587. return fredIsRedAPI.getColor(paletteInfo, labelArray, dataItem);
  588. };
  589. var resolverToString = categoricalPaletteResolver.toString();
  590. var viprToString = function viprToString() {
  591. return 'fredIsRed(' + resolverToString + ')';
  592. };
  593. //Provide the callback as an override to VIPR.
  594. categoricalPaletteResolver.getColor = viprGetColor;
  595. categoricalPaletteResolver.toString = viprToString;
  596. },
  597. /**
  598. * Palettes are handled in VIPR by implementing 'resolvers'. Luckily
  599. * for our needs we can use the VIPR default resolvers for categorical
  600. * and continuous.
  601. * @param palette - vipr property object
  602. * @param paletteDef - Definition describing all the info needed for the resolvers.
  603. * @param possibleDataSlots - all possible slots for the current vis type
  604. * @param fredIsRedAPI - the FredIsRed API object
  605. */
  606. setPaletteResolvers: function setPaletteResolvers(palette, paletteDef, possibleDataSlots, fredIsRedAPI) {
  607. var dataLayerId = ColorPropertiesCreator.getInstance().getDataLayerIdFromPaletteAndSlots(palette, possibleDataSlots);
  608. if (palette.paletteType === paletteDef.type && (!paletteDef.dataLayerId || dataLayerId === paletteDef.dataLayerId)) {
  609. var paletteResolver = null;
  610. if (paletteDef.colors) {
  611. switch (paletteDef.type) {
  612. case 'cat':
  613. paletteResolver = new VIPR.util.CatPalette(paletteDef.colors, paletteDef.defaultIndex);
  614. if (fredIsRedAPI) {
  615. instance._initializeFredIsRedPalette(fredIsRedAPI, paletteResolver, paletteDef.defaultIndex);
  616. }
  617. break;
  618. case 'customcat':
  619. paletteResolver = new VIPR.util.CustomCatPalette(paletteDef.colors);
  620. // @todo is it necessary to support FredIsRed for customcat?
  621. break;
  622. case 'cont':
  623. paletteResolver = new VIPR.util.ContPalette(paletteDef.colors, null);
  624. break;
  625. case 'customcont':
  626. paletteResolver = new VIPR.util.CustomContPalette(paletteDef.colors, null);
  627. break;
  628. default:
  629. paletteResolver = null;
  630. }
  631. if (paletteResolver) {
  632. var currentPaletteValue = palette.getValue && palette.getValue() ? palette.getValue() : {};
  633. if (currentPaletteValue.toString() !== paletteResolver.toString() || currentPaletteValue.defaultIndex !== paletteResolver.defaultIndex) {
  634. palette.setValue(paletteResolver);
  635. }
  636. }
  637. }
  638. }
  639. },
  640. /**
  641. * Set the Single Palette resolver
  642. * Single palettes are handled differently than categorical or continuous
  643. * For one, there may be one or two of them. Secondly, both the single palette
  644. * resolvers must use the same categorical palette (or at least same colors)
  645. * @param viprWidget - the vipr visualization controller
  646. * @param catPaletteDesc - Info needed to createthe categorical palette used
  647. * for both the single palettes.
  648. */
  649. setSinglePaletteResolvers: function setSinglePaletteResolvers(viprWidget, catPaletteDesc) {
  650. var catPalette = new VIPR.util.CatPalette(catPaletteDesc.colors);
  651. /* We need to know the number of colors in the palette so that the first and
  652. * second colors for the single palette can be calculated.
  653. */
  654. var numColors = catPaletteDesc.colors.length;
  655. // We use the ordinal of the categorical palette to determine the first and second colors.
  656. // Set it to the default index we get from the default palette index property.
  657. catPalette.ordinal = catPaletteDesc.defaultIndex;
  658. /*
  659. * Single palettes are a special case. There maybe one or two and there is
  660. * never (for now) any other type of palettes.
  661. * We need to take care how we set the first and second color. If we changed
  662. * from a palette that had 30 colors, for example, and the 28th color was selected
  663. * to a palette that has 20 colors then we must map the first and second
  664. * colors we use to index 0 and 1 in the palette. If the selected color is
  665. * the last in the color palette then we should use the first color in
  666. * the palette as the second color.
  667. */
  668. var firstColor = catPalette.ordinal < numColors ? catPalette.ordinal : 0;
  669. var palette = VIPRUtils.getPalettes(viprWidget.properties, viprWidget._currentId)[0];
  670. if (palette) {
  671. palette.setValue(catPalette.getSingleColor(catPalette.defaultIndex + firstColor));
  672. }
  673. palette = VIPRUtils.getPalettes(viprWidget.properties, viprWidget._currentId)[1];
  674. if (palette) {
  675. var secondColor = catPaletteDesc.secondaryColorIndex;
  676. secondColor = secondColor >= numColors ? 0 : secondColor;
  677. palette.setValue(catPalette.getSingleColor(catPalette.defaultIndex + secondColor));
  678. }
  679. }
  680. };
  681. }
  682. return {
  683. // Get the Singleton instance if one exists
  684. // or create one if it doesn't
  685. getInstance: function getInstance() {
  686. if (!instance) {
  687. instance = init();
  688. }
  689. return instance;
  690. }
  691. };
  692. }();
  693. return VIPRProperties;
  694. });
  695. //# sourceMappingURL=VIPRProperties.js.map