'use strict'; /** *+------------------------------------------------------------------------+ *| Licensed Materials - Property of IBM *| IBM Cognos Products: Dashboard *| (C) Copyright IBM Corp. 2017, 2021 *| *| US Government Users Restricted Rights - Use, duplication or disclosure *| restricted by GSA ADP Schedule Contract with IBM Corp. *+------------------------------------------------------------------------+ */ 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) { 'use strict'; 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']; var allowedGroups = ['widget.legend.color', 'valueAxis.column.ticks.labels.color', 'valueAxis.column.ticks.labels.font']; // Avoid conflict with dashboard tab ids var customVisGroupNamePrefix = 'customVis-'; var customVisSupportedPropPanelFont = []; var customVisAllowedGroups = []; /* * This object represents the VIPR Properties management. It is built to be a singleton. * Its purpose is to create the current runtime properties list in a JSON form * consumable by the current properties panel. Its built as a singleton as it * does not need to hold any state */ var VIPRProperties = function () { /** * Instance stores a reference to the Singleton * @type {object} */ var instance = null; function init() { return { /** * @param id - vis id of interest * @returns the vipr configuration (bundle + our overrides) for the given id */ _getConfiguration: function _getConfiguration(id) { return VIPRConfig.getConfig(id) || {}; }, // Added for unit test purposes to hide the Orderer. _orderProperties: function _orderProperties(mappedItems) { Orderer.getInstance().orderProperties(mappedItems); }, _filterToActiveProperties: function _filterToActiveProperties(fullSetOfProperties) { return _.filter(fullSetOfProperties, function (prop) { return prop.active === true; }); }, /** * Vida has added new properties. We only support a few right now but * they need to be added to the correct layers. Because they are of types * that we support they are initially created. We must find them and * organize them into layers before we send them to the properties panel. */ _moveLayersProperties: function _moveLayersProperties(visId, mappedItems) { var configuration = instance._getConfiguration(visId); // If the bundle supports layers then we need to create color props for each layer if (configuration && configuration.supportsLayers) { configuration.layerDescriptions.forEach(function (layerDesc) { var collapsibleSection = mappedItems[layerDesc.id]; if (collapsibleSection) { layerDesc.visibleLayerProps.forEach(function (visiblePropId) { var mappedProp = mappedItems[visiblePropId]; if (mappedProp) { // We have a prop to move to a layer. Add it to the correct // layer and remove it from the main mapped items (which also // contains the collapsible section) collapsibleSection.items.push(mappedProp); delete mappedItems[visiblePropId]; } }); } }); } }, _addColorRelatedProperties: function _addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId) { ColorPropertiesCreator.getInstance().addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId); }, _getPropertyDescriptionForProperty: function _getPropertyDescriptionForProperty(property, PropCreatorInstance) { var propDesc = null; if (property.type === 'boolean') { propDesc = PropCreatorInstance.createCheckboxProperty(property); } else if (property.type === 'enum') { propDesc = PropCreatorInstance.createEnumProperty(property); } else if (property.type === 'string') { propDesc = PropCreatorInstance.createTextInputProperty(property); } else if (property.type === 'number' || property.type === 'length') { propDesc = PropCreatorInstance.createNumberProperty(property); } else if (property.type === 'font') { propDesc = PropCreatorInstance.createFontSizeProperty(property); } else if (property.type === 'color') { propDesc = ColorPropertiesCreator.getInstance().createColorProperty(property); } return propDesc; }, _doesConfigSupportProp: function _doesConfigSupportProp(visId, propName, value) { return VIPRUtils.doesConfigPropertyMatchExpected(visId, propName, value); }, _addMaintainAxisScalePropIfNeeded: function _addMaintainAxisScalePropIfNeeded(visId, PropCreatorInstance, mappedItems) { if (instance._doesConfigSupportProp(visId, 'supportsMaintainAxisScale', true)) { mappedItems['maintainAxisScales'] = PropCreatorInstance.getMaintainAxisScaleProperty(); } }, _addDonutRadiusIfNeeded: function _addDonutRadiusIfNeeded(viprProperties, PropCreatorInstance, mappedItems) { // If the vipr bundle supports donut radius, create the property. var donutRadiusProp = viprProperties.get('donutRadius'); if (donutRadiusProp) { mappedItems['donutRadius'] = PropCreatorInstance.getDonutRadius(donutRadiusProp); } }, _addAggTypeIfNeeded: function _addAggTypeIfNeeded(mappedItems, possibleDataSlots) { var mappedItem = { id: 'widget.legend.aggregateTypeVisible', type: 'ToggleButton', propertyType: 'CheckBox', label: StringResources.get('aggregateTypeToggler'), ariaLabel: StringResources.get('aggregateTypeToggler'), public: true, name: 'widget.legend.aggregateTypeVisible', displayPos: 38, checked: false, defaultValue: false, active: _.some(possibleDataSlots, function (slot) { return SlotAPIHelper.isMultiMeasuresValueSlot(slot) === true; }) && mappedItems['widget.legend.titleVisible'].active }; mappedItems['widget.legend.aggregateTypeVisible'] = mappedItem; }, /** * Add a specified color set property * @param {Object} viprProperties * @param {Object} mappedItems - mapping of properties to their JSON description * @param {String} propId - property ID to be added. */ _addColorSetProperty: function _addColorSetProperty(viprProperties, mappedItems, propId, config, visId) { var colorProp = VIPRUtils.isPropertyIncluded(visId, propId) ? viprProperties.get(propId) : undefined; var propConfig = config.properties[propId]; var isCustomVis = this._isCustomVis(visId); if (colorProp) { mappedItems[propId] = _.extend({ showHexValue: true, paletteType: 'DashboardColorSet', id: propId, label: isCustomVis && propConfig.caption ? propConfig.caption : propConfig.caption ? StringResources.get(propConfig.caption) : colorProp.caption, type: 'ColorPicker', open: false, originalGroupName: isCustomVis && this._hasVisPropertyValue(propId, 'originalGroupName', mappedItems) ? mappedItems[propId].originalGroupName : null, groupName: isCustomVis && this._hasVisPropertyValue(propId, 'groupName', mappedItems) ? mappedItems[propId].groupName : null, groupCaption: isCustomVis && this._hasVisPropertyValue(propId, 'groupCaption', mappedItems) ? mappedItems[propId].groupCaption : null, sectionName: StringResources.get('sectionName_colorPalette'), tabName: StringResources.get('tabName_visualization'), ariaLabel: isCustomVis ? this._hasVisPropertyValue(propId, 'name', mappedItems) : propConfig.caption ? StringResources.get(propConfig.caption) : config.caption, public: colorProp.public === undefined ? true : colorProp.public, active: colorProp.active === undefined ? true : colorProp.active }, _.pick(config.properties[propId], 'addButton', 'displayPos')); } }, _hasVisPropertyValue: function _hasVisPropertyValue(propId, name, mappedItems) { return mappedItems[propId] && mappedItems[propId][name]; }, isTargetThicknessInputValid: function isTargetThicknessInputValid(value) { // Remove px if need be. var valueWithoutUnit = value && value.endsWith && value.endsWith('px') ? Number(value.slice(0, -2)) : Number(value); return Number.isInteger(valueWithoutUnit) && valueWithoutUnit >= 2 && valueWithoutUnit <= 20; }, _addTargetMarkerThicknessIfNeeded: function _addTargetMarkerThicknessIfNeeded(viprProperties, PropCreatorInstance, mappedItems, visId) { // If the vipr bundle supports target markers, create the property. var targetThicknessProp = VIPRUtils.isPropertyIncluded(visId, 'target.marker.thickness') ? viprProperties.get('target.marker.thickness') : undefined; if (targetThicknessProp) { var numberProp = PropCreatorInstance.createNumberProperty(targetThicknessProp); var minPx = 2; var maxPx = 20; numberProp.handleReturnKey = true; numberProp.placeHolderText = StringResources.get('targetThicknessPlaceHolder', { min: minPx, max: maxPx }); numberProp.showInlineError = true; numberProp.customValidatorCallback = function (value) { return { isValid: instance.isTargetThicknessInputValid(value), message: StringResources.get('targetThicknessErrorMsg', { min: minPx, max: maxPx }) }; }; mappedItems['target.marker.thickness'] = numberProp; } }, _addPropsFromVIPR: function _addPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId) { var _this = this; // Use only known properties and get the properties from Vida. var configuration = instance._getConfiguration(visId); configuration.config && configuration.config.include.forEach(function (propertyName) { _this._addPropertyFromVIPR(viprProperties, propertyName, PropCreatorInstance, mappedItems, visId); }); }, _addCustomVisPropsFromVIPR: function _addCustomVisPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId) { var _this2 = this; customVisSupportedPropPanelFont = []; customVisAllowedGroups = []; var groupProperties = this._getGroupProperties(visId); _.forEach(groupProperties, function (properties, groupName) { properties.forEach(function (property) { _this2._addPropertyFromVIPR(viprProperties, property, PropCreatorInstance, mappedItems, visId, groupName, true); }); }); }, _addPropertyFromVIPR: function _addPropertyFromVIPR(viprProperties, propertyName, PropCreatorInstance, mappedItems, visId, groupName, isCustomVis) { var property = viprProperties.get(propertyName); if (property) { var overridenProp = VIPRUtils.overrideProperty(visId, property, propertyName); if (overridenProp.hidden !== true) { var propDesc = instance._getPropertyDescriptionForProperty(overridenProp, PropCreatorInstance); if (propDesc) { //We want to use our known property ids so replace them here. propDesc.name = propertyName; propDesc.id = propertyName; if (groupName) { var groupCaption = viprProperties.get(groupName).caption; propDesc.groupName = customVisGroupNamePrefix + $.escapeSelector(groupName); propDesc.originalGroupName = groupName; propDesc.groupCaption = groupCaption; if (isCustomVis) { if (!viprProperties.get(groupName).active) { // if the group is inactive, all it's child properties should be inactive propDesc.active = false; } this._addCustomVisAllowedGroups(propDesc, property); } } mappedItems[propertyName] = propDesc; } } } }, _addCustomVisAllowedGroups: function _addCustomVisAllowedGroups(propDesc, property) { if (propDesc.propertyType === 'font') { if (!(customVisAllowedGroups.indexOf(this._getFontColorGroupName(propDesc.id, 'font')) !== -1)) { customVisAllowedGroups.push(this._getFontColorGroupName(propDesc.id, 'font')); } customVisSupportedPropPanelFont.push(propDesc.name); } else if (propDesc.propertyType === 'Color') { if (!(customVisAllowedGroups.indexOf(this._getFontColorGroupName(propDesc.id, 'color')) !== -1)) { customVisAllowedGroups.push(this._getFontColorGroupName(propDesc.id, 'color')); propDesc.caption = property.caption; } } }, _getFontColorGroupName: function _getFontColorGroupName(groupName, type) { return groupName + '.' + type; }, _isCustomVisAllowedGroups: function _isCustomVisAllowedGroups(id) { var customVisFontAllowedGroups = customVisAllowedGroups.indexOf(this._getFontColorGroupName(id, 'font')) !== -1; var customVisColorAllowedGroups = customVisAllowedGroups.indexOf(this._getFontColorGroupName(id, 'color')) !== -1; return customVisFontAllowedGroups || customVisColorAllowedGroups; }, _filterListonToActiveProperties: function _filterListonToActiveProperties(activeProps, visId) { var listenForPropChanges = this._getListenForPropChangesFromVIPRConfig(visId); var propChanges = listenForPropChanges.slice(); listenForPropChanges.forEach(function (propName) { var props = activeProps.filter(function (prop) { return prop.name === propName; }); if (!props.length) { var indexToRemove = propChanges.indexOf(propName); if (indexToRemove !== -1) { propChanges.splice(indexToRemove, 1); } } }); this._setListenForPropChangesForVIPRConfig(visId, propChanges); }, _getPropertyListFromVIPRConfig: function _getPropertyListFromVIPRConfig(visId) { var configuration = instance._getConfiguration(visId); return configuration && configuration.propertyList; }, _getListenForPropChangesFromVIPRConfig: function _getListenForPropChangesFromVIPRConfig(visId) { var configuration = instance._getConfiguration(visId); return configuration && configuration.listenForPropChanges; }, _setListenForPropChangesForVIPRConfig: function _setListenForPropChangesForVIPRConfig(visId, listenForPropChanges) { var configuration = instance._getConfiguration(visId); configuration.listenForPropChanges = listenForPropChanges; }, _isCustomVis: function _isCustomVis(visId) { var configuration = instance._getConfiguration(visId); return configuration && configuration.isCustomVis; }, _getGroupProperties: function _getGroupProperties(visId) { var configuration = instance._getConfiguration(visId); return configuration && configuration.groupedProperty; }, /** * Add Color set Properties from the include list * @param {Object} viprProperties * @param {Object} mappedItems - mapping of properties to their JSON description */ _addColorSetProps: function _addColorSetProps(viprProperties, mappedItems, visId) { var configuration = instance._getConfiguration(visId); configuration.config && configuration.config.include.forEach(function (propertyName) { var property = viprProperties.get(propertyName); if (property) { var overridenProp = VIPRUtils.overrideProperty(visId, property, propertyName); // If the property configuration has been enhanced with the colorClass flag, add it. if (overridenProp.colorClass) { instance._addColorSetProperty(viprProperties, mappedItems, propertyName, configuration, visId); } } }); }, /** * Get the properties for the VIPR Widget in a form that is consumeable by * the properties panel. * @param viprProperties raw properties from vida bundle or widget * @param possibleDataSlots - all possible slots for the current vis type * @returns array of properties panel mapped properties */ getProperties: function getProperties(viprProperties, possibleDataSlots, visId) { var mappedItems = {}; var PropCreatorInstance = PropertiesCreator.getInstance(); var isCustomVis = this._isCustomVis(visId); if (isCustomVis) { instance._addCustomVisPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId); } else { instance._addPropsFromVIPR(viprProperties, PropCreatorInstance, mappedItems, visId); } instance._addMaintainAxisScalePropIfNeeded(visId, PropCreatorInstance, mappedItems); instance._addColorRelatedProperties(mappedItems, viprProperties, possibleDataSlots, visId); instance._addAggTypeIfNeeded(mappedItems, possibleDataSlots); instance._addDonutRadiusIfNeeded(viprProperties, PropCreatorInstance, mappedItems); instance._addTargetMarkerThicknessIfNeeded(viprProperties, PropCreatorInstance, mappedItems, visId); instance._addColorSetProps(viprProperties, mappedItems, visId); instance._moveLayersProperties(visId, mappedItems); instance._orderProperties(mappedItems); var allProps = _.toArray(mappedItems); //only return active properties. var filteredProps = instance._filterToActiveProperties(allProps); if (isCustomVis) { instance._filterListonToActiveProperties(allProps, visId); } return instance._sectionalizeProperties(filteredProps); }, getPropertyList: function getPropertyList(viprProperties, possibleDataSlots, content) { var definition = content.getFeature('Visualization').getDefinition(); if (definition.getState().getError()) { return []; } var visId = definition.getId(); var properties = this.getProperties(viprProperties, possibleDataSlots, visId); var propertieslist = instance._getPropertyListFromVIPRConfig(visId); if (propertieslist && !_.isEmpty(propertieslist)) { properties = properties.concat(propertieslist); //Merge customized property list from viprConfig } return this._toUIControlProperties(properties); }, getPropertyLayoutList: function getPropertyLayoutList(viprProperties, possibleDataSlots, content, dashboard) { var _this3 = this; var visId = content.getFeature('Visualization').getDefinition().getId(); var isCustomVis = this._isCustomVis(visId); var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {}; var layouts = {}; var extraEditors = []; // filter out any non-public properties var properties = this.getProperties(viprProperties, possibleDataSlots, visId); // Use the map to ensure entries are unique _.each(properties, function (prop) { // collect the tab (group) layouts layouts[prop.tabId] = { type: 'Group', id: prop.tabId, label: prop.tabName }; // collect the section layouts (optional) var sectioner = PropertySectioner.getInstance(); if (prop.sectionId) { var sectionIds = []; PropertiesHelper.splitEscapedString(prop.sectionId, '.', sectionIds); sectionIds.forEach(function (sectionId, index) { //The first sectionId has its info on the prop object var sectionInfo = { type: 'Section', id: sectionId, label: prop.sectionName, position: prop.sectionPosition }; if (index != 0) { sectionInfo = sectioner.getSection(sectionId); if (!sectionInfo) { throw new Error('section info not found'); } } layouts[sectionId] = sectionInfo; }); } var supportGrouping = allowedGroups.indexOf(prop.id) !== -1 || _this3._isCustomVisAllowedGroups(prop.id); var customVisGroup = []; if (isCustomVis && supportGrouping && prop.originalGroupName) { customVisGroup = groupedProperty[prop.originalGroupName]; } if (supportedPropPanelFont.indexOf(prop.id) !== -1 || customVisSupportedPropPanelFont.indexOf(prop.id) !== -1) { extraEditors = extraEditors.concat(_this3._getFontPropertyLayout(prop, content, VIPRUtils, dashboard, isCustomVis)); } else if ((isCustomVis && customVisGroup.indexOf(prop.id) !== -1 || groupedProperty[prop.id]) && supportGrouping) { extraEditors = extraEditors.concat(_this3._getGroupedPropertyLayout(prop, content, dashboard)); } }); return _.values(layouts).concat(extraEditors); }, _sectionalizeProperties: function _sectionalizeProperties(props) { var sectioner = PropertySectioner.getInstance(); var lastSectionPosition = 100; props.forEach(function (prop) { var propInfo = sectioner.getSectionInformationForPropertyId(prop.id); if (propInfo) { prop.sectionId = prop.groupName || propInfo.sectionId || prop.sectionId; prop.sectionName = prop.groupCaption || propInfo.sectionName || prop.sectionName; prop.tabId = propInfo.tabId || prop.tabId; prop.tabName = propInfo.tabName || prop.tabName; prop.sectionPosition = propInfo.sectionPosition || lastSectionPosition; } }); return props; }, _toUIControlProperties: function _toUIControlProperties(properties) { var _this4 = this; return _.map(properties, function (property) { var entry = _.pick(property, 'id'); entry.editor = { // @todo support for Split? sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId, uiControl: _this4._getPropertyUIControl(property) }; if (_.isNumber(property.displayPos)) { entry.editor.position = property.displayPos; } // non public property is visually hidden var isPrivateProp = property.public === false; //A non default font properties UI is contributed via getPropertyLayoutList. Hide the default. var isSupportedPropPanelFont = supportedPropPanelFont.indexOf(entry.id) !== -1 || customVisSupportedPropPanelFont.indexOf(entry.id) !== -1; //A non default group properties UI is contributed via getPropertyLayoutList. Hide the default. var isGroupedProperty = allowedGroups.indexOf(entry.id) !== -1 || _this4._isCustomVisAllowedGroups(entry.id); if (isPrivateProp || isSupportedPropPanelFont || isGroupedProperty) { entry.editor.hidden = true; } return entry; }); }, _getLegendFontSizeOptions: function _getLegendFontSizeOptions() { return [{ value: 'auto', label: StringResources.get('automaticTypeCaption') }, { value: '11px', label: '11px' }, { value: '14px', label: '14px' }, { value: '16px', label: '16px' }]; }, _getNonLegendFontSizeOptions: function _getNonLegendFontSizeOptions() { return [{ value: 'auto', label: StringResources.get('automaticTypeCaption') }, { value: '12px', label: '12px' }, { value: '14px', label: '14px' }, { value: '16px', label: '16px' }, { value: '24px', label: '24px' }]; }, _getGroupedPropertyLayout: function _getGroupedPropertyLayout(property, content, dashboard) { var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {}; return [{ id: property.id, editor: { position: property.displayPos, sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId, uiControl: this._getPropertyUIControl(_.extend(property, { onChange: function onChange(propertyID, value) { if (property.type === 'ColorPicker') { value = value.name; } var propertyList = [propertyID]; _.each(groupedProperty[propertyID], function (prop) { return propertyList.push(prop); }); var transactionToken = dashboard.getFeature('Transaction').startTransaction(); propertyList.forEach(function (prop) { return content.setPropertyValue(prop, value, transactionToken); }); dashboard.getFeature('Transaction').endTransaction(transactionToken); } })) } }]; }, _getFontPropertyLayout: function _getFontPropertyLayout(property, content, viprUtils, dashboard, isCustomVis) { var _fontFamilyOptions = [].concat(fontFamilyOptions); _fontFamilyOptions.unshift({ value: 'auto', label: StringResources.get('automaticTypeCaption') }); var fontFamily = { id: 'font.xdashboardx.' + property.id, editor: { position: property.displayPos, sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId, uiControl: this._getPropertyUIControl({ name: 'font.xdashboardx.' + property.id, active: true, options: _fontFamilyOptions, public: true, ariaLabel: StringResources.get('fontPropLabel'), label: isCustomVis && property.label ? property.label + ' ' + StringResources.get('fontFamily') : StringResources.get('fontPropLabel'), type: 'DropDown', onChange: this._getSetFontProperty('font', property.id, content, viprUtils, dashboard), value: viprUtils.getVidaFontPropertiesPart('family', content.getPropertyValue(property.id)) || StringResources.get('automaticTypeCaption') }) } }; var fontSize = { id: 'fontSize.xdashboardx.' + property.id, editor: { position: property.displayPos + 1, sectionId: property.sectionId ? property.tabId + '.' + property.sectionId : property.tabId, uiControl: this._getPropertyUIControl(_.extend(property, { ariaLabel: StringResources.get('fontSizePropLabel'), label: isCustomVis && property.label ? property.label + ' ' + StringResources.get('fontSize') : StringResources.get('fontSizePropLabel'), options: property.id === 'widget.legend.font' ? this._getLegendFontSizeOptions() : this._getNonLegendFontSizeOptions(), onChange: this._getSetFontProperty('fontSize', property.id, content, viprUtils, dashboard), value: viprUtils.getVidaFontPropertiesPart('size', content.getPropertyValue(property.id)) || StringResources.get('automaticTypeCaption') })) } }; return [fontFamily, fontSize]; }, _getSetFontProperty: function _getSetFontProperty(fontPart, propertyID, content, viprUtils, dashboard) { return function (psuedoPropertyID, value) { var _viprUtils$buildVidaF; var groupedProperty = content.getFeature('Visualization').getDefinition().getProperty('groupedProperty') || {}; if (value === 'auto') { value = null; } var fontProperty = viprUtils.buildVidaFontPropertiesFromParts((_viprUtils$buildVidaF = {}, _viprUtils$buildVidaF[fontPart] = value, _viprUtils$buildVidaF), content.getPropertyValue(propertyID)); var propertyList = [propertyID]; if (allowedGroups.indexOf(propertyID) !== -1) { _.each(groupedProperty[propertyID], function (prop) { return propertyList.push(prop); }); } var transactionToken = dashboard.getFeature('Transaction').startTransaction(); propertyList.forEach(function (prop) { return content.setPropertyValue(prop, fontProperty, transactionToken); }); dashboard.getFeature('Transaction').endTransaction(transactionToken); }.bind(this); }, _getPropertyUIControl: function _getPropertyUIControl(property) { // exclude all general and layout properties return _.omit(property, 'id', 'public', 'displayPos', 'tabId', 'tabName', 'sectionPosition', 'sectionId', 'sectionName'); }, /** * An abstraction layer to hide how we set the properties in VIPR. This will * get more complicated as we add color property support. * @param widget - The vipr widget * @param info - property description * id - property id * value - value to set the property to. */ setProperty: function setProperty(widget, info) { widget.setProperty(info.id, info.value); }, /** * FredIsRed is a term/service that is used to describe various methods that assign colours * to data values in automatic and user-defined ways. * VIPR implements a callback on the categorical paletteResolver that allows a callback to be invoked. * Provide a function to Massage the VIPR-specific tuple into a generic form and call the fredIsRed service. * @param fredIsRedAPI - the fredIsRed interface. * @param categoricalPaletteResolver - the VIDA categorical paletteResolver * @param defaultIndex - the default colour index for this palette. */ _initializeFredIsRedPalette: function _initializeFredIsRedPalette(fredIsRedAPI, categoricalPaletteResolver, defaultIndex) { var paletteInfo = { defaultIndex: defaultIndex || 0, colors: categoricalPaletteResolver.colors, colorCallback: VIPR.util.Color.rgb }; var viprGetColor = function viprGetColor(tuple, dataItem, level) { //Convert the VIPR tuple to a labelArray (or undefined for defaultIndex) and call the generic fredIsRed getColor API. var labelArray = []; if (typeof tuple !== 'undefined' && typeof dataItem !== 'undefined' && typeof level !== 'undefined' && level >= 0) { // hierarchical visulizations such as treemap asks color for the Item on a specfic level // e.g. level = 0 , tuple:{items:[{source:{unformattedValue:{'Fall'}}},{source:{unformattedValue:{'2018'}}}]}; // returns labelArray as ['Fall'] var tupleItem = tuple && tuple.items[level]; labelArray.push(tupleItem && tupleItem.source && tupleItem.source.unformattedValue || ''); } else { // most visulizations(non-hierarchical) request colors for Typle Objects // e.g. level = -1 , tuple:{items:[{source:{unformattedValue:{'Fall'}}}]}; // returns labelArray as ['Fall'] labelArray = tuple && _.map(tuple.items, function (tupleItem) { return tupleItem.source && tupleItem.source.unformattedValue || ''; }); } return fredIsRedAPI.getColor(paletteInfo, labelArray, dataItem); }; var resolverToString = categoricalPaletteResolver.toString(); var viprToString = function viprToString() { return 'fredIsRed(' + resolverToString + ')'; }; //Provide the callback as an override to VIPR. categoricalPaletteResolver.getColor = viprGetColor; categoricalPaletteResolver.toString = viprToString; }, /** * Palettes are handled in VIPR by implementing 'resolvers'. Luckily * for our needs we can use the VIPR default resolvers for categorical * and continuous. * @param palette - vipr property object * @param paletteDef - Definition describing all the info needed for the resolvers. * @param possibleDataSlots - all possible slots for the current vis type * @param fredIsRedAPI - the FredIsRed API object */ setPaletteResolvers: function setPaletteResolvers(palette, paletteDef, possibleDataSlots, fredIsRedAPI) { var dataLayerId = ColorPropertiesCreator.getInstance().getDataLayerIdFromPaletteAndSlots(palette, possibleDataSlots); if (palette.paletteType === paletteDef.type && (!paletteDef.dataLayerId || dataLayerId === paletteDef.dataLayerId)) { var paletteResolver = null; if (paletteDef.colors) { switch (paletteDef.type) { case 'cat': paletteResolver = new VIPR.util.CatPalette(paletteDef.colors, paletteDef.defaultIndex); if (fredIsRedAPI) { instance._initializeFredIsRedPalette(fredIsRedAPI, paletteResolver, paletteDef.defaultIndex); } break; case 'customcat': paletteResolver = new VIPR.util.CustomCatPalette(paletteDef.colors); // @todo is it necessary to support FredIsRed for customcat? break; case 'cont': paletteResolver = new VIPR.util.ContPalette(paletteDef.colors, null); break; case 'customcont': paletteResolver = new VIPR.util.CustomContPalette(paletteDef.colors, null); break; default: paletteResolver = null; } if (paletteResolver) { var currentPaletteValue = palette.getValue && palette.getValue() ? palette.getValue() : {}; if (currentPaletteValue.toString() !== paletteResolver.toString() || currentPaletteValue.defaultIndex !== paletteResolver.defaultIndex) { palette.setValue(paletteResolver); } } } } }, /** * Set the Single Palette resolver * Single palettes are handled differently than categorical or continuous * For one, there may be one or two of them. Secondly, both the single palette * resolvers must use the same categorical palette (or at least same colors) * @param viprWidget - the vipr visualization controller * @param catPaletteDesc - Info needed to createthe categorical palette used * for both the single palettes. */ setSinglePaletteResolvers: function setSinglePaletteResolvers(viprWidget, catPaletteDesc) { var catPalette = new VIPR.util.CatPalette(catPaletteDesc.colors); /* We need to know the number of colors in the palette so that the first and * second colors for the single palette can be calculated. */ var numColors = catPaletteDesc.colors.length; // We use the ordinal of the categorical palette to determine the first and second colors. // Set it to the default index we get from the default palette index property. catPalette.ordinal = catPaletteDesc.defaultIndex; /* * Single palettes are a special case. There maybe one or two and there is * never (for now) any other type of palettes. * We need to take care how we set the first and second color. If we changed * from a palette that had 30 colors, for example, and the 28th color was selected * to a palette that has 20 colors then we must map the first and second * colors we use to index 0 and 1 in the palette. If the selected color is * the last in the color palette then we should use the first color in * the palette as the second color. */ var firstColor = catPalette.ordinal < numColors ? catPalette.ordinal : 0; var palette = VIPRUtils.getPalettes(viprWidget.properties, viprWidget._currentId)[0]; if (palette) { palette.setValue(catPalette.getSingleColor(catPalette.defaultIndex + firstColor)); } palette = VIPRUtils.getPalettes(viprWidget.properties, viprWidget._currentId)[1]; if (palette) { var secondColor = catPaletteDesc.secondaryColorIndex; secondColor = secondColor >= numColors ? 0 : secondColor; palette.setValue(catPalette.getSingleColor(catPalette.defaultIndex + secondColor)); } } }; } return { // Get the Singleton instance if one exists // or create one if it doesn't getInstance: function getInstance() { if (!instance) { instance = init(); } return instance; } }; }(); return VIPRProperties; }); //# sourceMappingURL=VIPRProperties.js.map