ThemeDefinition.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2013, 2019
  5. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  6. *
  7. * @module dashboard/data/ThemeDefinition
  8. * @see ThemeDefinition
  9. */
  10. define(['../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../app/nls/StringResources', 'underscore'], function (Class, StringResources, _) {
  11. /*
  12. * The purpose of this object is to hold the theme definition for a widget and provide
  13. * easy access to elements of this definition. Please see public/themes/defaultTheme.json
  14. * for more information of the current definition structure.
  15. */
  16. var ThemeDefinition = null;
  17. var FOREGROUND_PALETTES = ['UserPaletteColor', 'ForegroundUserPaletteColor', 'SecondaryForegroundUserPaletteColor', 'TabTextColor', 'TabSelectedLineColor'];
  18. ThemeDefinition = Class.extend({
  19. init: function init(themeDefinition) {
  20. /*
  21. * Theme properties may be mapped into groups so that they inherit a group
  22. * value. For example, the Y Axis Line Color and X Axis Line color will in most
  23. * instances be the same, so we can map their properties (valAxisLineColor and
  24. * catAxisLineColor) to a group property ID such as axisLineColor. Therefore, if
  25. * a default fo valAxisLineColor, for example, isn't given it will be mapped to
  26. * axisLineColor. The following holds these mappings.
  27. */
  28. this.themeMapping = {};
  29. /*
  30. * The theme definitions may have any number of types of variables. For example,
  31. * there could be a group of variables represented fill colors in the 'Color'
  32. * group. There may also be a number of fonts in the 'Font' group, and so on. The
  33. * following will hold a map of each of these groups. For example, it will map 'Color'
  34. * to its corresponding mapping for each color in its group.
  35. */
  36. this.variableMapping = {};
  37. // The actual JSON representing the theme
  38. this.jsonDefinition = themeDefinition;
  39. this._palettes = {};
  40. // Some of our palettes use r,g,b,a. When creating styles dynamically
  41. // we need the css form rgba(r,g,b,a). Once created cache them
  42. this._cssColors = {};
  43. // We have the description, now update the mappings.
  44. this._mapVariables();
  45. this._fillColor = null;
  46. },
  47. getId: function getId() {
  48. return this.jsonDefinition.id;
  49. },
  50. /*
  51. * Map the different group of variables ('Colors' and 'Fonts' for example)
  52. * to their corresponding map of variables.
  53. */
  54. _mapVariables: function _mapVariables() {
  55. if (this.jsonDefinition && this.jsonDefinition.variables) {
  56. var variables = this.jsonDefinition.variables;
  57. for (var variableType in variables) {
  58. if (variables.hasOwnProperty(variableType)) {
  59. this.variableMapping[variableType] = this._getMapOfVariables(variables[variableType]);
  60. }
  61. }
  62. }
  63. },
  64. /*
  65. * Map each variable (such as 'color1' or 'color2' of a larger section (such as 'Color').
  66. */
  67. _getMapOfVariables: function _getMapOfVariables(variables) {
  68. var mapping = {};
  69. _.each(variables, function (variable) {
  70. mapping[variable.id] = variable;
  71. }.bind(this));
  72. return mapping;
  73. },
  74. /**
  75. * Given the variable type (such as 'Color' or 'Font') and the variable ID
  76. * (such as 'color1' or 'font1') return the value for the corresponding mapping
  77. * @param variableType - Variable type (such as 'Color' or 'Font')
  78. * @param variableId - id of a variable found within the specified variableType (such as 'color1')
  79. * @returns value if the specified variable exists.
  80. */
  81. getValueForVariable: function getValueForVariable(variableType, variableId) {
  82. if (this.variableMapping[variableType]) {
  83. if (variableId) {
  84. if (this.variableMapping[variableType][variableId]) {
  85. return this.variableMapping[variableType][variableId].value;
  86. }
  87. } else {
  88. return this.variableMapping[variableType];
  89. }
  90. }
  91. return undefined;
  92. },
  93. /*
  94. * return the value for the specified property. A value maybe defined with a leading '$' which
  95. * means it should be replaced using its mapping.
  96. */
  97. _getValueForProperty: function _getValueForProperty(prop) {
  98. if (prop && prop.value !== undefined && prop.value !== null) {
  99. // Some properties may have a number as a value and not point to a variable
  100. if (isNaN(prop.value) && prop.value.substr(0, 1) === '$') {
  101. return this.getValueForVariable(prop.type, prop.value.substr(1));
  102. }
  103. return prop.value;
  104. }
  105. return undefined;
  106. },
  107. /*
  108. * The following returns the default palette name
  109. * @param paletteType {string} - the type of palette, currently only options are 'ColorPalette', 'HeatPalette' and 'ConditionalPalette'
  110. * @returns default color palette name ('colroPalette0' for instance)
  111. */
  112. getDefaultPaletteName: function getDefaultPaletteName(paletteType) {
  113. var keys = _.keys(this.variableMapping[paletteType]);
  114. if (keys && keys.length > 0) {
  115. return keys[0];
  116. }
  117. return undefined;
  118. },
  119. getColorValue: function getColorValue(color) {
  120. if (color.pattern) {
  121. return color.pattern;
  122. } else if (color.fill) {
  123. return color.fill;
  124. } else if (color.backgroundColor) {
  125. return color.backgroundColor;
  126. }
  127. return color;
  128. },
  129. getCSSColors: function getCSSColors(variableName) {
  130. var _this = this;
  131. if (!this._cssColors[variableName]) {
  132. var foregroundColors = this.getVariable(variableName);
  133. if (!foregroundColors) {
  134. return {};
  135. }
  136. this._cssColors[variableName] = {};
  137. foregroundColors.forEach(function (color) {
  138. _this._cssColors[variableName][color.id] = _this._convertToCssColor(color.value);
  139. });
  140. }
  141. return this._cssColors[variableName];
  142. },
  143. _convertToCssColor: function _convertToCssColor(color) {
  144. var cssColor = null;
  145. if (this._isColorValue(color)) {
  146. var value = color.r + ',' + color.g + ',' + color.b;
  147. cssColor = color.a !== undefined ? 'rgba(' + value + ',' + color.a + ')' : 'rgb(' + value + ')';
  148. }
  149. return cssColor ? cssColor : color;
  150. },
  151. _isColorValue: function _isColorValue(color) {
  152. return color && color.r !== undefined && color.g !== undefined && color.b !== undefined;
  153. },
  154. getVariable: function getVariable(variableName) {
  155. if (this.jsonDefinition && this.jsonDefinition.variables) {
  156. return this.jsonDefinition.variables[variableName];
  157. }
  158. return null;
  159. },
  160. /**
  161. * Get a specific palette
  162. * @param {string} paletteId - the ID of the palette
  163. * @param {string} paletteVariableName - the theme variable name for the list of palettes ('ColorPalette', 'HeatPalette', 'ContinuousPalette')
  164. * @param {boolen} forProperties - boolean if the response is to be used for the properties.
  165. * @return {array} all palettes defined in the theme
  166. */
  167. getPalette: function getPalette(paletteId, paletteVariableName, forProperties) {
  168. if (paletteId === 'userPaletteColor') {
  169. var userPaletteColor = this._getUserPaletteColor();
  170. return this._createCMPaletteResponse(userPaletteColor, forProperties);
  171. }
  172. var palettes = this.getVariable(paletteVariableName === 'UserPaletteColor' ? 'ColorPalette' : paletteVariableName);
  173. if (!palettes) {
  174. return {};
  175. }
  176. for (var i = 0; i < palettes.length; i++) {
  177. var palette = palettes[i];
  178. if (palette.id === paletteId) {
  179. return this._createCMPaletteResponse(palette, forProperties, i);
  180. }
  181. }
  182. },
  183. _getUserPaletteColor: function _getUserPaletteColor() {
  184. var userPaletteColor = this.getVariable('UserPaletteColor');
  185. var result = {
  186. id: 'userPaletteColor',
  187. fillType: 'simple',
  188. label: StringResources.get('userPaletteColor_' + this.jsonDefinition.id),
  189. labelTranslated: true,
  190. ids: [],
  191. labels: [],
  192. fills: []
  193. };
  194. userPaletteColor.forEach(function (_ref) {
  195. var value = _ref.value,
  196. id = _ref.id,
  197. label = _ref.label;
  198. result.fills.push(value);
  199. if (id) {
  200. result.ids.push(id);
  201. }
  202. if (label) {
  203. result.labels.push(label);
  204. }
  205. });
  206. return result;
  207. },
  208. /**
  209. * Get all the palettes defined in the theme
  210. * @param {string} paletteVariableName - the theme variable name for the list of palettes ('ColorPalette', 'HeatPalette', 'ContinuousPalette')
  211. * @param {boolen} forProperties - boolean if the response is to be used for the properties
  212. * @param {boolean} includePatternPalettes - Should pattern palettes be included in the list of returned palettes.
  213. * @return {array} all palettes defined in the theme
  214. */
  215. getPalettes: function getPalettes(paletteVariableName, forProperties) {
  216. var _this2 = this;
  217. var includePatternPalettes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  218. var colorPalettes = this.getVariable(paletteVariableName);
  219. if (!colorPalettes) {
  220. return [];
  221. }
  222. var palettes = colorPalettes.filter(function (palette) {
  223. return includePatternPalettes || _.find(palette.fills, function (paletteProp) {
  224. return !paletteProp.pattern;
  225. });
  226. }).map(function (palette, index) {
  227. return _this2._createCMPaletteResponse(palette, forProperties, index);
  228. });
  229. return palettes;
  230. },
  231. /**
  232. * Make our system palettes have the same structure as the CM response
  233. * @param {Object} palette
  234. */
  235. _createCMPaletteResponse: function _createCMPaletteResponse(palette, forProperties, index) {
  236. if (!palette) {
  237. return {};
  238. }
  239. var isPatternColor = _.find(palette.fills, function (paletteProp) {
  240. return paletteProp.pattern;
  241. });
  242. var label = palette.labelTranslated ? palette.label : StringResources.get(palette.label, { number: index + 1 });
  243. var content = _.extend(palette, {
  244. label: label,
  245. labelTranslated: true,
  246. fillType: isPatternColor ? 'ImgPath' : palette.fillType
  247. });
  248. if (isPatternColor) {
  249. content.path = 'dashboard-core/images/patterns/';
  250. content.fileType = '.svg';
  251. }
  252. return forProperties ? {
  253. system: true,
  254. id: palette.id,
  255. content: content
  256. } : content;
  257. },
  258. /**
  259. * Get the property value for the UIElement and Property ID specified
  260. * @param uiElement - UIElement as described in the theme
  261. * @param propertyId - property within the specified UIElement
  262. * @returns value for the property if it exists, undefined otherwise
  263. */
  264. getValueForPropertyOfUIElement: function getValueForPropertyOfUIElement(uiElement, propertyId) {
  265. var prop = this.getPropertyForUIElement(uiElement, propertyId);
  266. return this._getValueForProperty(prop);
  267. },
  268. /**
  269. * Get the property for the UIElement and Property ID specified
  270. * @param uiElement - UIElement as described in the theme
  271. * @param propertyId - property within the specified UIElement
  272. * @returns property if it exists, undefined otherwise
  273. */
  274. getPropertyForUIElement: function getPropertyForUIElement(uiElement, propertyId) {
  275. if (this.jsonDefinition && this.jsonDefinition.uiElements[uiElement]) {
  276. var uiElementArray = this.jsonDefinition.uiElements[uiElement];
  277. return _.find(uiElementArray, function (ele) {
  278. var mappedId = this.themeMapping[propertyId] ? this.themeMapping[propertyId] : propertyId;
  279. return ele.id === mappedId;
  280. }.bind(this));
  281. }
  282. return undefined;
  283. },
  284. /**
  285. * When a theme mapping is updated (a new vis type definition is provided) we need to update
  286. * the theme mapping.
  287. * @param themeMapping - json description of which properties map to which super property
  288. * For example:
  289. * {
  290. * "id": "axisLineColor",
  291. * "mapping": [
  292. * "valAxisLineColor",
  293. * "catAxisLineColor"
  294. * ]
  295. * }
  296. */
  297. updateThemeMapping: function updateThemeMapping(themeMapping) {
  298. if (themeMapping) {
  299. _.each(themeMapping, function (themeMap) {
  300. var mapping = themeMap.mapping;
  301. var id = themeMap.id;
  302. _.each(mapping, function (idToMap) {
  303. this.themeMapping[idToMap] = id;
  304. }.bind(this));
  305. }.bind(this));
  306. }
  307. },
  308. getThemeMapping: function getThemeMapping() {
  309. return this.themeMapping;
  310. },
  311. setThemeMapping: function setThemeMapping(themeMapping) {
  312. this.themeMapping = themeMapping;
  313. },
  314. getMappedId: function getMappedId(id) {
  315. return this.themeMapping[id];
  316. },
  317. getForegroundPropertiesForUIElement: function getForegroundPropertiesForUIElement(uiElement) {
  318. var elements = this.jsonDefinition.uiElements[uiElement];
  319. if (!elements) {
  320. return [];
  321. }
  322. return elements.filter(function (element) {
  323. return FOREGROUND_PALETTES.indexOf(element.type) !== -1;
  324. });
  325. },
  326. /*
  327. * return array of id and foreground color pairs that are type is one of FOREGROUND_PALETTES in given elements
  328. */
  329. getForegroundColorPropertiesForUIElement: function getForegroundColorPropertiesForUIElement(bgColor, uiElement) {
  330. var _this3 = this;
  331. var result = [];
  332. var properties = this.getForegroundPropertiesForUIElement(uiElement);
  333. properties.forEach(function (ele) {
  334. var fgColor = _this3._getValueForProperty({
  335. type: ele.type,
  336. value: '$' + bgColor
  337. });
  338. fgColor = ele.alpha ? _this3._convertToRGBA(fgColor, ele.alpha) : fgColor;
  339. result.push({
  340. id: ele.id,
  341. value: fgColor
  342. });
  343. });
  344. return result;
  345. },
  346. /*
  347. * return an object with rgba properties for given color and alpha
  348. */
  349. _convertToRGBA: function _convertToRGBA(color, alpha) {
  350. if (color) {
  351. var r = 0,
  352. g = 0,
  353. b = 0;
  354. if (typeof color === 'string') {
  355. if (color.charAt(0) === '#' && color.length === 7) {
  356. r = parseInt(color.substring(1, 3), 16);
  357. g = parseInt(color.substring(3, 5), 16);
  358. b = parseInt(color.substring(5), 16);
  359. return {
  360. 'a': alpha,
  361. 'r': r,
  362. 'g': g,
  363. 'b': b
  364. };
  365. }
  366. } else {
  367. return _.extend({
  368. 'a': alpha
  369. }, _.omit(color, 'a'));
  370. }
  371. }
  372. return color;
  373. }
  374. });
  375. return ThemeDefinition;
  376. });
  377. //# sourceMappingURL=ThemeDefinition.js.map