PropertyListUtil.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. 'use strict';
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. /*
  4. *+------------------------------------------------------------------------+
  5. *| Licensed Materials - Property of IBM
  6. *| IBM Cognos Products: Dashboard
  7. *| (C) Copyright IBM Corp. 2017, 2020
  8. *|
  9. *| US Government Users Restricted Rights - Use, duplication or disclosure
  10. *| restricted by GSA ADP Schedule Contract with IBM Corp.
  11. *+------------------------------------------------------------------------+
  12. */
  13. define(['jquery', 'underscore', '../../lib/@waca/core-client/js/core-client/utils/UniqueId', '../../app/nls/StringResources'], function ($, _, UniqueId, StringResources) {
  14. var PropertiesUtil = function () {
  15. function PropertiesUtil() {
  16. _classCallCheck(this, PropertiesUtil);
  17. }
  18. /**
  19. * Loops through an array of properties to add appropriate callbacks and default values
  20. * @param {object} properties - the array of properties to process
  21. * @param {ContentAPI} contentApi - content which wants to display these properties
  22. * @return {Promise} resolved once all the properties have been processed
  23. */
  24. PropertiesUtil.prototype.processProperties = function processProperties(properties, contentApi, dashboardApi) {
  25. var _this = this;
  26. if (!properties) {
  27. return false;
  28. }
  29. var translationService = dashboardApi.getDashboardCoreSvc('TranslationService');
  30. var removeTranslationIcon = function removeTranslationIcon(property) {
  31. // if the property has a tanslationIconNode defined then we were showing the missing translation dot.
  32. // Since we're just changed the property make sure the dot gets removed.
  33. if (translationService && property.translationIconNode) {
  34. translationService.removeTranslationIcon(property.translationIconNode);
  35. property.translationIconNode = null;
  36. }
  37. };
  38. var onChangeCallback = function onChangeCallback(property, propertyName, propertyValue) {
  39. if (property.displayMultiplier) {
  40. propertyValue = Math.round(propertyValue / property.displayMultiplier);
  41. }
  42. this._callPropertyOnChangeCallback(property, propertyName, propertyValue);
  43. contentApi.setPropertyValue(propertyName, propertyValue);
  44. removeTranslationIcon(property);
  45. };
  46. var promises = [];
  47. var removedItems = 0;
  48. properties.slice().forEach(function (property, i) {
  49. var customOnChangeCallback = typeof property['onChange'] === 'function' ? property.onChange.bind(property) : null;
  50. // Ignore hidden properties or the banner
  51. if (property.public === false || property.type === 'Banner') {
  52. return;
  53. }
  54. var propertiesOverride = _this._getPropertiesOverride(property, contentApi);
  55. if (propertiesOverride.removeProperty === true) {
  56. properties.splice(i - removedItems, 1);
  57. removedItems++;
  58. return;
  59. }
  60. // Replace any overriden properties
  61. $.extend(property, propertiesOverride);
  62. // Property UI Controls always need a name property
  63. if (property.id && !property.name) {
  64. property.name = property.id;
  65. }
  66. // list of container types. Each section (ie. left, right) of a split has no type (undefined)
  67. var containerCtrlTypes = ['Group', 'CollapsibleSection', 'SingleLineLinks', 'Split', undefined];
  68. // list of static placeholders
  69. var staticCtrlTypes = ['text', 'icon', 'Separator', 'SectionLabel'];
  70. if (!_this._isValidPropertyId(property.id) && containerCtrlTypes.indexOf(property.type) > -1) {
  71. // id with spaces doesn't work in core-client/CollapsibleSection.js
  72. // remove all special characters and generate a unique id
  73. var prefix = property.id.replace(/[^a-zA-Z]/g, '');
  74. property.id = UniqueId.get(prefix);
  75. property.name = property.id;
  76. }
  77. // child properties
  78. if (property.type === 'ColorPicker' && property.paletteType) {
  79. promises.push(_this.handleColorPickerProperty(property, contentApi, dashboardApi));
  80. } else if (property.type === 'NewPalette' || property.type === 'Palette') {
  81. property.type = 'NewPalette';
  82. promises.push(_this.handleNewPaletteProperty(property, contentApi, dashboardApi));
  83. } else if (property.type === 'ToggledCombo') {
  84. _this._handleToggledComboProperty(property, contentApi);
  85. } else if (property.type === 'IconPicker') {
  86. _this._handleIconPickerProperty(property, contentApi);
  87. } else if (property.module && property.module.indexOf('UiSlider') >= 0) {
  88. _this._handleUISlider(property, contentApi);
  89. } else if (property.name === 'pageSizeWidth' || property.name === 'pageSizeHeight') {
  90. _this._getPropertyDisplayValueWithUnits(contentApi, property);
  91. } else if (containerCtrlTypes.indexOf(property.type) > -1) {
  92. promises.push(_this.processProperties(property.items, contentApi, dashboardApi));
  93. } else if (_this._isALayoutPositionProperty(property.name)) {
  94. _this._handleLayoutPositionalProperty(contentApi, property);
  95. } else if (property.id === 'rotateAngle') {
  96. var currentPropValue = contentApi.getPropertyValue(property.id);
  97. property.value = _this.getRotateDisplayString(currentPropValue);
  98. } else if (staticCtrlTypes.indexOf(property.type) < 0) {
  99. var _currentPropValue = contentApi.getPropertyValue(property.id);
  100. if (_currentPropValue === null || _currentPropValue === undefined) {
  101. _currentPropValue = property.value;
  102. }
  103. if (property.type === 'CheckBox' || property.type === 'ToggleButton') {
  104. if (_currentPropValue === false) {
  105. property.checked = false;
  106. } else {
  107. property.checked = _currentPropValue === true || property.defaultValue === true || _currentPropValue && _currentPropValue === property.defaultValue;
  108. }
  109. } else {
  110. if (property.type === 'DropDown') {
  111. var valueToUse = void 0;
  112. /*
  113. * Enums - Dropdowns, are difficult because of Vida. Basically, we want
  114. * to check if the the current value returned is a valid. If it isn't,
  115. * use the property default. If it is, then we should check if it is an
  116. * object with property called 'name', which Vida enums do. If it does,
  117. * then use the name prop. All else fails, use the current prop value.
  118. */
  119. if (_currentPropValue !== null && _currentPropValue !== undefined) {
  120. if (_currentPropValue.hasOwnProperty('name')) {
  121. valueToUse = _currentPropValue.name;
  122. } else {
  123. valueToUse = _currentPropValue;
  124. }
  125. } else {
  126. valueToUse = property.defaultValue;
  127. }
  128. property.defaultValue = valueToUse;
  129. } else {
  130. property.value = _currentPropValue || _currentPropValue === 0 ? _currentPropValue : '';
  131. }
  132. }
  133. if (property.displayMultiplier && property.value) {
  134. var scaledValue = property.value * property.displayMultiplier;
  135. property.value = property.decimalPlaces ? scaledValue.toFixed(property.decimalPlaces) : Math.round(scaledValue);
  136. }
  137. property.onChange = property.onChange || onChangeCallback.bind(_this, property);
  138. }
  139. if (customOnChangeCallback) {
  140. property.onChange = function (property, propertyName, propertyValue, options) {
  141. customOnChangeCallback(propertyName, propertyValue, options);
  142. removeTranslationIcon(property);
  143. }.bind(_this, property);
  144. }
  145. // Replace any overriden properties once again in case we set defaults
  146. $.extend(property, propertiesOverride);
  147. });
  148. return Promise.all(promises);
  149. };
  150. /**
  151. * Identifies if property name is top, left, width or height
  152. * @param {String} property - the property name to be searched
  153. * @return {boolean} - returns true or false based on property name
  154. */
  155. PropertiesUtil.prototype._isALayoutPositionProperty = function _isALayoutPositionProperty(propertyName) {
  156. var positionNames = ['left', 'top', 'width', 'height'];
  157. return positionNames.indexOf(propertyName) !== -1;
  158. };
  159. /**
  160. * If the property object defines a 'preRenderCallback' property then call it to get any dynamic properties
  161. * that should be applied to the property UI control
  162. * @param {object} property - the property object for which to get any dynamically generated member variables
  163. * @param {object} contentApi - the widget instance which wants to display these properties
  164. *
  165. * @return {object} - returns the member variables (properties) to override
  166. */
  167. PropertiesUtil.prototype._getPropertiesOverride = function _getPropertiesOverride(property, contentApi) {
  168. var propertiesOverride = {};
  169. // Call the callback to get any dynamic property info
  170. if (typeof property['preRenderCallback'] === 'function') {
  171. propertiesOverride = property.preRenderCallback(property, contentApi);
  172. }
  173. return propertiesOverride;
  174. };
  175. /**
  176. * A property can define a custom onChange callback. This is mostly used when one property change effects other properties,
  177. * for example the show/hide legend property to hide/show the legened position property.
  178. * @param {object} property - the property object for which to get any dynamically generated member variables
  179. * @param {string} propertyName - the name of the property
  180. * @param {object} propertyValue - the value of the property
  181. */
  182. PropertiesUtil.prototype._callPropertyOnChangeCallback = function _callPropertyOnChangeCallback(property, propertyName, propertyValue) {
  183. if (property.onChangeCallback) {
  184. property.onChangeCallback(propertyName, propertyValue);
  185. }
  186. };
  187. /**
  188. * Handles setting the callbacks and dynamic properties of a slider property control
  189. * @param {object} property - the property object for which to get any dynamically generated member variables
  190. * @param {object} contentApi - the widget instance which wants to display these properties
  191. */
  192. PropertiesUtil.prototype._handleUISlider = function _handleUISlider(property, contentApi) {
  193. var currentPropValue = contentApi.getPropertyValue(property.name);
  194. if (currentPropValue || currentPropValue === 0 && property.sliderType === 'percentage') {
  195. currentPropValue = parseInt(currentPropValue * 100, 10);
  196. }
  197. property.start = currentPropValue || currentPropValue === 0 ? [currentPropValue] : [property.defaultValue];
  198. property.startLabels = [property.description || property.label];
  199. property.onChange = function (sliderValues) {
  200. // All our sliders currently only have one 'slide'
  201. var value = sliderValues[0];
  202. // The value with have the postfix at the end, for example 75%
  203. if (property.format && property.format.postfix) {
  204. value = value.substring(0, value.indexOf(property.format.postfix));
  205. }
  206. if (property.sliderType === 'percentage') {
  207. value = value * 0.01;
  208. }
  209. this._callPropertyOnChangeCallback(property, property.name, value);
  210. contentApi.setPropertyValue(property.name, value);
  211. }.bind(this);
  212. };
  213. /**
  214. * Handles setting the callbacks and dynamic properties of a toggleCombo (auto refresh) property
  215. * @param {object} property - the property object for which to get any dynamically generated member variables
  216. * @param {object} contentApi - the widget instance which wants to display these properties
  217. */
  218. PropertiesUtil.prototype._handleToggledComboProperty = function _handleToggledComboProperty(property, contentApi) {
  219. var propInfo = contentApi.getPropertyValue(property.name);
  220. if (!property.inputOptions) {
  221. property.inputOptions = {};
  222. }
  223. if (!property.checkBoxOptions) {
  224. property.checkBoxOptions = {};
  225. }
  226. if (!property.dropDownOptions) {
  227. property.dropDownOptions = {};
  228. }
  229. property.useToggleButton = true;
  230. if (propInfo) {
  231. property.dropDownOptions.defaultValue = propInfo.unit;
  232. property.inputOptions.value = propInfo.value;
  233. property.checkBoxOptions.checked = propInfo.autoRefresh;
  234. } else {
  235. property.inputOptions.value = property.inputOptions.defaultValue || '';
  236. property.checkBoxOptions.checked = false;
  237. }
  238. property.validateInput = this._validateToggleComboProperty.bind(this);
  239. property.onChange = function (propertyName, propertyValue) {
  240. this._callPropertyOnChangeCallback(property, propertyName, propertyValue);
  241. contentApi.setPropertyValue(propertyName, propertyValue);
  242. }.bind(this);
  243. };
  244. /**
  245. * Handles setting the callbacks and dynamic properties of a IconPickerproperty
  246. * @param {object} property - the property object for which to get any dynamically generated member variables
  247. * @param {object} contentApi - the widget instance which wants to display these properties
  248. */
  249. PropertiesUtil.prototype._handleIconPickerProperty = function _handleIconPickerProperty(property, contentApi) {
  250. if (!property.values) {
  251. var currentPropValue = contentApi.getPropertyValue(property.name);
  252. if (currentPropValue !== null && currentPropValue !== undefined) {
  253. property.values = currentPropValue;
  254. } else if (property.defaultValue !== undefined) {
  255. property.values = property.defaultValue;
  256. }
  257. }
  258. if (!property.onChange) {
  259. property.onChange = function (propertyName, propertyValue) {
  260. var values = propertyValue;
  261. if (propertyValue.length && propertyValue.length === 1) {
  262. values = propertyValue[0].name;
  263. } else if (propertyValue.length) {
  264. values = [];
  265. propertyValue.forEach(function (value) {
  266. values.push(value.name);
  267. });
  268. }
  269. this._callPropertyOnChangeCallback(property, propertyName, values);
  270. contentApi.setPropertyValue(propertyName, values);
  271. }.bind(this);
  272. }
  273. };
  274. /**
  275. * @param timeUnit - 'seconds', 'minutes', 'hours'
  276. * @returns a structure stating the min and max of the specified timeUnit
  277. */
  278. PropertiesUtil.prototype._getMaxMinRefreshValuesForUnits = function _getMaxMinRefreshValuesForUnits(timeUnit) {
  279. /**
  280. * The browser method used to provide a timed delay between refresh calls has
  281. * a max size of a signed integer. We must ensure we stay below this number
  282. * depending on the time unit
  283. */
  284. var maxIntervalInSeconds = (Math.pow(2, 31) - 1) / 1000;
  285. var maxForTimeUnit = void 0;
  286. var values = {};
  287. switch (timeUnit) {
  288. case 'minutes':
  289. values.min = 1;
  290. maxForTimeUnit = maxIntervalInSeconds / 60;
  291. values.max = Math.ceil(maxForTimeUnit - 1);
  292. break;
  293. case 'hours':
  294. values.min = 1;
  295. maxForTimeUnit = maxIntervalInSeconds / 3600;
  296. values.max = Math.ceil(maxForTimeUnit - 1);
  297. break;
  298. default:
  299. // includes seconds
  300. values.min = 5;
  301. values.max = Math.ceil(maxIntervalInSeconds - 1);
  302. }
  303. return values;
  304. };
  305. /**
  306. * Called when the toggleCombo (auto refresh) property changes
  307. * @param {string} valueOfInput
  308. * @param {string} valueOfDropDown
  309. */
  310. PropertiesUtil.prototype._validateToggleComboProperty = function _validateToggleComboProperty(valueOfInput, valueOfDropDown) {
  311. if (!valueOfInput || !valueOfDropDown) {
  312. return false;
  313. }
  314. var isValid = $.isNumeric(valueOfInput);
  315. if (isValid) {
  316. var maxMinValuesForUnit = this._getMaxMinRefreshValuesForUnits(valueOfDropDown);
  317. // ensure the valueOfInput is between our current min and max.
  318. isValid = valueOfInput >= maxMinValuesForUnit.min && valueOfInput <= maxMinValuesForUnit.max;
  319. }
  320. return isValid;
  321. };
  322. /**
  323. * Handles setting the callbacks and dynamic properties of a Palette property
  324. * @param {object} property - the property object for which to get any dynamically generated member variables
  325. * @param {object} contentApi - the widget instance which wants to display these properties
  326. * @param {object} dashboardApi
  327. * @param {function} [onChangeCallback] - optional to override the default onchange behavior
  328. */
  329. PropertiesUtil.prototype.handleNewPaletteProperty = function handleNewPaletteProperty(property, contentApi, dashboardApi, onChangeCallback) {
  330. var _this2 = this;
  331. if (!property.paletteType) {
  332. throw new Error('Palette property needs a "paletteType"', property);
  333. }
  334. var colorsService = dashboardApi.getFeature('Colors');
  335. var getPaletteId = property.getPaletteId ? property.getPaletteId : function () {
  336. var paletteId = contentApi.getPropertyValue(property.name);
  337. paletteId = paletteId || property.defaultValue || colorsService.getDefaultPaletteName(property.paletteType);
  338. return paletteId;
  339. };
  340. var paletteId = getPaletteId();
  341. var allowPaletteReverse = property.allowPaletteReverse !== false && (property.paletteType === 'HeatPalette' || property.paletteType === 'ConditionalPalette');
  342. var createPaletteType = property.paletteType === 'HeatPalette' ? 'continuous' : 'standard';
  343. var isReverse = property.isReversed ? property.isReversed : function () {
  344. var currentOrder = property.reversePalettePropName && contentApi.getPropertyValue(property.reversePalettePropName);
  345. return currentOrder === 'DarkerForLowerValue' && allowPaletteReverse;
  346. };
  347. property.menuItems = [];
  348. if (allowPaletteReverse) {
  349. property.menuItems.push('reverse');
  350. }
  351. property.reverse = isReverse();
  352. property.createPaletteType = createPaletteType;
  353. return colorsService.getPalette({
  354. paletteId: paletteId,
  355. type: property.paletteType,
  356. defaultPaletteId: property.defaultValue,
  357. addMissingBaseColors: property.addMissingBaseColors,
  358. defaultIfNotFound: true,
  359. forProperties: true
  360. }).then(function (selPalette) {
  361. property.palette = selPalette;
  362. property.hasSection = true;
  363. property.readOnly = true;
  364. if (selPalette.my && !selPalette.public) {
  365. property.menuItems.push('edit');
  366. }
  367. if (!property.onChangePalette) {
  368. property.onChangePalette = onChangeCallback ? onChangeCallback : function (propertyName, paletteItem) {
  369. _this2._callPropertyOnChangeCallback(property, propertyName, paletteItem.id);
  370. contentApi.setPropertyValue(propertyName, paletteItem.id);
  371. };
  372. }
  373. // Handle selection when creating a palette
  374. var onCreatePalette = function onCreatePalette(paletteId) {
  375. var prefixCMId = '__CM__';
  376. var cmId = prefixCMId + paletteId;
  377. property.onChangePalette(property.name, { id: cmId });
  378. return cmId;
  379. };
  380. property.onCreatePalette = onCreatePalette;
  381. if (property.onReversePalette) {
  382. property.onChange = property.onReversePalette;
  383. } else {
  384. property.onChange = function (propertyName, paletteItem) {
  385. var orderValue = paletteItem.reverse === true ? 'DarkerForLowerValue' : 'DarkerForHigherValue';
  386. _this2._callPropertyOnChangeCallback(property, property.reversePalettePropName, orderValue);
  387. contentApi.setPropertyValue(property.reversePalettePropName, orderValue);
  388. };
  389. }
  390. property.changePaletteCb = function () {
  391. dashboardApi.getDashboardSvc('propertiesManager').then(function (propertyManager) {
  392. var options = {
  393. label: property.linkLabel,
  394. overlay: true,
  395. width: '320px',
  396. content: {
  397. module: 'authoring-common/changePaletteView',
  398. selectedId: paletteId,
  399. onCreatePalette: onCreatePalette,
  400. createPaletteType: createPaletteType,
  401. name: property.name,
  402. getPalettes: function getPalettes() {
  403. return colorsService.getPalettes({
  404. type: property.paletteType,
  405. includeUserColorPalette: property.includeUserColorPalette,
  406. forProperties: true,
  407. includePatternPalettes: property.includePatternPalettes
  408. });
  409. },
  410. getPaletteId: property.getPaletteId ? property.getPaletteId : contentApi.getPropertyValue.bind(contentApi, property.id),
  411. reverse: isReverse(),
  412. onChange: property.onChangePalette,
  413. component: 'dashboard'
  414. }
  415. };
  416. dashboardApi.prepareGlassOptions(options);
  417. propertyManager.addChild(options);
  418. });
  419. };
  420. return property;
  421. });
  422. };
  423. /**
  424. * Builds the payload needed for the property change event
  425. * @param {string} propName - the name of the property changing
  426. * @param {object} propValue - the new value for the property
  427. */
  428. PropertiesUtil.prototype.buildPropChangePayload = function buildPropChangePayload(propName, propValue) {
  429. return {
  430. 'category': propName,
  431. 'item': propValue,
  432. 'transactionId': _.uniqueId('prop_change')
  433. };
  434. };
  435. /**
  436. * Add the ability to a color picker to handle custom colors
  437. * @param {object} property - Property object
  438. * @param {object} colorsService - ref to the color service
  439. */
  440. PropertiesUtil.prototype.addCustomColorCapability = function addCustomColorCapability(property, colorsService) {
  441. property.createCustomColor = function (hex) {
  442. var className = colorsService.addCustomColor(hex);
  443. var colorProp = colorsService.createColorDefinition(className, hex, hex);
  444. colorProp.type = 'ColorCode';
  445. colorProp.hidden = true;
  446. return colorProp;
  447. };
  448. if (colorsService.isCustomColor(property.selectedName) && property.items) {
  449. var hex = colorsService.getHexColorFromClassName(property.selectedName);
  450. var colorProp = colorsService.createColorDefinition(property.selectedName, hex, hex);
  451. colorProp.hidden = true;
  452. property.items.push(colorProp);
  453. }
  454. return property;
  455. };
  456. /**
  457. * Checks to see if the palette property is set in the model, if it isn't will return the default palette name for the type
  458. * of palette being asked for
  459. * @param {object} contentApi - the widget instance which wants to display these properties
  460. * @param {object} dashboardApi
  461. * @param {string} palettePropertyName - the name of the property which contains the palette name
  462. * @param {string} paletteType - the type of palette being asked for
  463. */
  464. PropertiesUtil.prototype._getColorPalettePropertyValue = function _getColorPalettePropertyValue(contentApi, colorsService, palettePropertyName, paletteType) {
  465. var propertyValue = contentApi.getPropertyValue(palettePropertyName);
  466. return propertyValue || colorsService.getDefaultPaletteName(paletteType);
  467. };
  468. /**
  469. * Handles setting the callbacks and dynamic properties of a ColorPicker property
  470. * @param {object} property - the property object for which to get any dynamically generated member variables
  471. * @param {object} contentApi - the widget instance which wants to display these properties
  472. * @param {object} dashboardApi
  473. */
  474. PropertiesUtil.prototype.handleColorPickerProperty = function handleColorPickerProperty(property, contentApi, dashboardApi) {
  475. var _this3 = this;
  476. if (!property.paletteType) {
  477. throw new Error('Color picker property needs a "paletteType"', property);
  478. }
  479. var colorsService = dashboardApi.getFeature('Colors');
  480. property.onChange = function (propertyName, propertyValueInfo) {
  481. this._callPropertyOnChangeCallback(property, property.propertyName, propertyValueInfo.name);
  482. contentApi.setPropertyValue(propertyName, propertyValueInfo.name);
  483. }.bind(this);
  484. var currentValue = contentApi.getPropertyValue(property.name);
  485. if (!property.selectedName) {
  486. // when current value is 0, it should keep it
  487. property.selectedName = !currentValue && currentValue !== 0 && property.defaultValue ? property.defaultValue : currentValue;
  488. }
  489. return this._getColorPickerColors(property, contentApi, dashboardApi).then(function (colors) {
  490. // If the colors being show are based off another property, then we need to tweak to payload for backwards compatibility
  491. if (property.palettePropertyName) {
  492. property.items = [];
  493. colors.forEach(function (color, index) {
  494. property.items.push({
  495. 'id': index,
  496. 'name': index,
  497. 'value': color.hexValue,
  498. 'type': 'ColorCode',
  499. 'label': color.label
  500. });
  501. });
  502. } else if (!property.items) {
  503. property.items = colors;
  504. }
  505. //
  506. if (property.addButton) {
  507. property = _this3.addCustomColorCapability(property, colorsService);
  508. }
  509. // If the current value saved in the model is higher then the number of colors available, default
  510. // back to the first color
  511. if (property.selectedName > colors.length) {
  512. property.selectedName = 0;
  513. } else if (!property.selectedName && property.selectedName !== 0 && property.defaultColorIndex !== undefined) {
  514. // when selectedName value is 0, it should keep it
  515. property.selectedName = property.defaultColorIndex;
  516. }
  517. return property;
  518. });
  519. };
  520. PropertiesUtil.prototype._getColorPickerColors = function _getColorPickerColors(property, contentApi, dashboardApi) {
  521. var colorsService = dashboardApi.getFeature('Colors');
  522. if (property.paletteType === 'DashboardColorSet') {
  523. return Promise.resolve(colorsService.getDashboardColorSet().slice(0));
  524. }
  525. var paletteId = property.palettePropertyName ? this._getColorPalettePropertyValue(contentApi, colorsService, property.palettePropertyName, property.paletteType) : colorsService.getColorSetId();
  526. return colorsService.getPaletteColors({
  527. paletteId: paletteId,
  528. type: property.paletteType,
  529. addMissingBaseColors: property.addMissingBaseColors
  530. }).then(function (colors) {
  531. return colors.slice(0);
  532. });
  533. };
  534. /**
  535. * Currently only being called by the custom widget since it doesn't use contributions like our other widgets.
  536. * Returns the default properties to show on the general property tab.
  537. */
  538. PropertiesUtil.prototype.getGeneralProperties = function getGeneralProperties(contentApi, dashboardApi) {
  539. var properties = [{
  540. 'id': 'fillColor',
  541. 'type': 'ColorPicker',
  542. 'label': StringResources.get('propFillColor'),
  543. 'showHexValue': true,
  544. 'addButton': true,
  545. 'open': false,
  546. 'ariaLabel': StringResources.get('propFillColor'),
  547. 'paletteType': 'ColorPalette',
  548. 'defaultValue': 'color1',
  549. 'tabName': StringResources.get('tabName_general'),
  550. 'sectionName': StringResources.get('sectionName_appearance')
  551. }, {
  552. 'id': 'borderColor',
  553. 'type': 'ColorPicker',
  554. 'label': StringResources.get('propBorderColor'),
  555. 'open': false,
  556. 'showHexValue': true,
  557. 'addButton': true,
  558. 'ariaLabel': StringResources.get('propBorderColor'),
  559. 'paletteType': 'ColorPalette',
  560. 'defaultValue': 'transparent',
  561. 'tabName': StringResources.get('tabName_general'),
  562. 'sectionName': StringResources.get('sectionName_appearance')
  563. }];
  564. if (contentApi) {
  565. return this.processProperties(properties, contentApi, dashboardApi).then(function () {
  566. return properties;
  567. });
  568. } else {
  569. return Promise.resolve(properties);
  570. }
  571. };
  572. /**
  573. * Method that takes our propertyUIControl spec and generates properties for our public API. This is temporary until
  574. * we clean up our properties logic throughout the code
  575. * @param {*} properties
  576. * @param {*} contentApi
  577. * @param {*} dashboardApi
  578. */
  579. PropertiesUtil.prototype.propertyUIControlToPublicAPI = function propertyUIControlToPublicAPI(properties, contentApi, dashboardApi) {
  580. var _this4 = this;
  581. var propertiesList = [];
  582. var setValue = function setValue(property, value) {
  583. if (dashboardApi.getMode() !== 'authoring') {
  584. dashboardApi.getGlassCoreSvc('.Logger').error('Trying to set a property without being in authoring mode.');
  585. return false;
  586. }
  587. if (property.customValidatorCallback) {
  588. var validInfo = property.customValidatorCallback(value);
  589. if (validInfo && validInfo.isValid === false) {
  590. dashboardApi.getGlassCoreSvc('.Logger').error(validInfo.message);
  591. return false;
  592. }
  593. }
  594. if (property.onChange) {
  595. if (property.module && property.module.indexOf('UiSlider') >= 0) {
  596. property.onChange([value]);
  597. } else if (property.type === 'ColorPicker') {
  598. var valueToSet = value && value.startsWith('#') ? dashboardApi.getFeature('Colors').addCustomColor(value) : value;
  599. property.onChange(property.name, {
  600. name: valueToSet
  601. });
  602. } else if (property.type === 'NewPalette') {
  603. property.onChangePalette(property.name, {
  604. id: value
  605. });
  606. } else {
  607. property.onChange(property.name, value);
  608. }
  609. return true;
  610. }
  611. };
  612. var getValue = function getValue(property, contentApi) {
  613. var propValue = contentApi.getPropertyValue(property.name);
  614. if (propValue) {
  615. return propValue;
  616. }
  617. return property.defaultValue !== undefined ? property.defaultValue : null;
  618. };
  619. properties.forEach(function (property) {
  620. // For now guard against not having an onChange property. This currently happens with complex property where the onChange is
  621. // buried inside of the items property.
  622. if (property.type === 'Banner' || property.public === false || !property.onChange) {
  623. return null;
  624. }
  625. // Currently only expose the minimum needed for system tests. Once this starts being used for our UI we'll
  626. // need to augment what's exposed in the API
  627. var propertyApi = {
  628. name: property.name,
  629. getValue: getValue.bind(_this4, property, contentApi),
  630. setValue: setValue.bind(_this4, property)
  631. };
  632. propertiesList.push(propertyApi);
  633. });
  634. return propertiesList;
  635. };
  636. /**
  637. * Creates a string using the value and units, intended for display. Appends a space if required. All other units except 'px' get a decimal place of 2
  638. * @param {*} numericValue The value
  639. * @param {*} units The units
  640. * @param {*} addSpace Flag indicating if a space should be added
  641. * @return {String} Returns a string, either empty or the value appended with the units
  642. */
  643. PropertiesUtil.prototype.getPropertyDisplayString = function getPropertyDisplayString(numericValue, units, addSpace) {
  644. if (numericValue !== null && numericValue !== undefined) {
  645. if (units) {
  646. units = units.trim();
  647. if (addSpace) {
  648. units = ' ' + units;
  649. }
  650. }
  651. return String(Number(numericValue.toFixed(units === StringResources.get('pixelUnit') ? 0 : 2))) + units;
  652. }
  653. return '';
  654. };
  655. /**
  656. * Gets the display value for a property
  657. * @param {*} contentApi The content API, used to retrieve the property value
  658. * @param {*} property The property
  659. */
  660. PropertiesUtil.prototype._getPropertyDisplayValueWithUnits = function _getPropertyDisplayValueWithUnits(contentApi, property) {
  661. var currentPropValue = contentApi.getPropertyValue(property.id);
  662. property.value = this.getPropertyDisplayString(currentPropValue, StringResources.get('pixelUnit'), true);
  663. };
  664. /**
  665. * Gets the display value for a property with space
  666. * @param {ContentAPI} contentApi The content API, used to retrieve the property value
  667. * @param {Property} property The property
  668. */
  669. PropertiesUtil.prototype._handleLayoutPositionalProperty = function _handleLayoutPositionalProperty(contentApi, property) {
  670. var currentPropValue = contentApi.getPropertyValue(property.id);
  671. var numericValue = parseFloat(currentPropValue);
  672. property.value = this.getPropertyDisplayString(numericValue, currentPropValue.replace(/[\d.-]/g, ''), true);
  673. };
  674. /**
  675. * Creates a string using the value, intended for display. Appends a space and units for rotation
  676. * @param {propertyValue} propertyValue propertyValue
  677. * @return {String} Returns rotate value formatted for display
  678. */
  679. PropertiesUtil.prototype.getRotateDisplayString = function getRotateDisplayString(propertyValue) {
  680. var degreeUnit = String.fromCharCode(176);
  681. if (propertyValue !== null && propertyValue !== undefined) {
  682. return propertyValue + ' ' + degreeUnit;
  683. }
  684. return '';
  685. };
  686. PropertiesUtil.prototype._isValidPropertyId = function _isValidPropertyId(id) {
  687. return (/^[a-zA-Z0-9]*$/.test(id)
  688. );
  689. };
  690. return PropertiesUtil;
  691. }();
  692. return new PropertiesUtil();
  693. });
  694. //# sourceMappingURL=PropertyListUtil.js.map