'use strict'; /** * Licensed Materials - Property of IBM * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2016, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['../../lib/@waca/core-client/js/core-client/ui/core/Class', 'underscore', '../nls/StringResources', '../../lib/@waca/dashboard-common/dist/core/MultilingualAttribute'], function (Class, _, resources, MultilingualAttribute) { // Static map of the slotIds used for labels in the smart names // Note that Data player (list) doesn't have an archetype. var chartInfo = { // Crosstab 'crosstab': { 'requiredMappings': ['values', 'row_level1'], 'optionalMapping': 'column_level1' }, // Grid 'JQGrid': { 'requiredMappings': ['grid_cols'] }, // Hierarchy 'hierarchy': { 'requiredMappings': ['level1'] }, // Legacy map 'map': { 'requiredMappings': ['categories'] }, // Infographic summary 'infographicSummary': { 'requiredMappings': ['actual'] }, // Summary 'summary': { 'requiredMappings': ['actual'] }, // Kpi 'kpi': { 'requiredMappings': ['actual'], 'optionalMapping': 'sparkline.time' }, // New live widget mappings 'LIVE_bubble_chart': { 'requiredMappings': ['x', 'y', 'size'] }, 'LIVE_line_column': { 'requiredMappings': ['columnValue', 'lineValue'], 'optionalMapping': 'categories' }, 'LIVE_decision_tree': { 'requiredMappings': ['values'] }, 'LIVE_heatmap': { 'requiredMappings': ['color'] }, 'LIVE_pie': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_pie_as_donut': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_point': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_line': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_map': { 'requiredMappings': ['locations'] }, 'LIVE_network': { 'requiredMappings': ['categories', 'series'], 'optionalMapping': 'values' }, 'LIVE_bar': { 'requiredMappings': ['values'], 'optionalMapping': 'categories' }, 'LIVE_bullet': { 'requiredMappings': ['actual'] }, 'LIVE_stacked_bar': { 'requiredMappings': ['values'], 'optionalMapping': 'categories' }, 'LIVE_column': { 'requiredMappings': ['values'], 'optionalMapping': 'categories' }, 'LIVE_stacked_column': { 'requiredMappings': ['values'], 'optionalMapping': 'categories' }, 'LIVE_packed_bubble': { 'requiredMappings': ['categories'] }, 'LIVE_hierarchy_packed_bubble': { 'requiredMappings': ['categories'] }, 'LIVE_marimekko': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_sunburst': { 'requiredMappings': ['values'] }, 'LIVE_decision_analysis': { 'requiredMappings': ['values'] }, 'LIVE_data_player': { 'requiredMappings': ['category'] }, 'LIVE_radial_bar': { 'requiredMappings': ['values'], 'optionalMapping': 'categories' }, 'LIVE_spiral': { 'requiredMappings': ['values'] }, 'LIVE_treemap': { 'requiredMappings': ['categories', 'size'] }, 'LIVE_wordcloud': { 'requiredMappings': ['categories'] }, 'LIVE_area': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_area_as_stacked_percent': { 'requiredMappings': ['categories', 'values'] }, 'LIVE_scatter': { 'requiredMappings': ['x', 'y'], 'optionalMapping': 'categories' }, 'LIVE_waterfall': { 'requiredMappings': ['values'] } }; // Map of archetype to visId. This only includes the ones where // the visId and archetype are different. // Many of them (like all the RAVE2 ones) are the same. var archetypeToVisIdMap = { // Grid 'grid': 'JQGrid', // Data player 'player': 'dataPlayer', // Summary(live) 'summaryChart': 'summary' }; /** Sometimes the visId of a widget changes depending upon how many slots are used, * because of course they do. */ var visIdSubstitution = { // Hierarchy(live) 'list': 'hierarchy', 'hierarchy2': 'hierarchy', 'hierarchy3': 'hierarchy', // Legacy map 'map1measure': 'map', 'map2measure': 'map', 'map3measure': 'map', //New Live vis widgets 'com.ibm.vis.rave2polygonmap': 'map', 'com.ibm.vis.rave2bundlearea': 'LIVE_area', 'com.ibm.vis.rave2bundlebar': 'LIVE_bar', 'com.ibm.vis.rave2bundlebullet': 'LIVE_bullet', 'com.ibm.vis.rave2bundlecomposite': 'LIVE_line_column', 'com.ibm.vis.rave2bundlepackedbubble': 'LIVE_packed_bubble', 'com.ibm.vis.rave2bundlehierarchicalpackedbubble': 'LIVE_hierarchy_packed_bubble', 'com.ibm.vis.rave2marimekko': 'LIVE_marimekko', 'com.ibm.vis.sunburst': 'LIVE_sunburst', 'com.ibm.vis.rave2comet': 'LIVE_decision_analysis', 'com.ibm.vis.rave2bundlepie': 'LIVE_pie', 'com.ibm.vis.rave2bundleradialbar': 'LIVE_radial_bar', 'com.ibm.vis.rave2bundletreemap': 'LIVE_treemap', 'com.ibm.vis.rave2bundlewordcloud': 'LIVE_wordcloud', 'com.ibm.vis.ravebubble': 'LIVE_bubble_chart', 'com.ibm.vis.decisiontree': 'LIVE_decision_tree', 'com.ibm.vis.rave2heat': 'LIVE_heatmap', 'com.ibm.vis.rave2line': 'LIVE_line', 'com.ibm.vis.rave2network': 'LIVE_network', 'com.ibm.vis.spiral': 'LIVE_spiral', 'com.ibm.vis.rave2bundletiledmap': 'LIVE_map', 'com.ibm.vis.rave2bundlecolumn': 'LIVE_column', 'com.ibm.vis.rave2bundlestackedbar': 'LIVE_stacked_bar', 'com.ibm.vis.rave2bundlestackedcolumn': 'LIVE_stacked_column', 'com.ibm.vis.rave2point': 'LIVE_point', 'com.ibm.vis.ravescatter': 'LIVE_scatter', 'com.ibm.vis.rave2bundlewaterfall': 'LIVE_waterfall', 'dataPlayer': 'LIVE_data_player', 'pieExpressedAsDonut': 'LIVE_pie_as_donut', 'areaExpressedAsStackedPercent': 'LIVE_area_as_stacked_percent' }; var Svc = Class.extend({ init: function init(widgetRegistry, boardModel) { this._widgetRegistry = widgetRegistry; this._boardModel = boardModel; }, /** Returns a display name for a pin spec, generated based on the content of a pin spec. * @param pinSpec - a pin specification * @returns a generated display name for the pin spec. */ getPinName: function getPinName(pinSpec) { // Count and sort our widgets, to get the most prevalent one. var count = 1; var typeCount = 1; var mostType; var widgets = []; if (pinSpec.content && pinSpec.content.widgets) { widgets = pinSpec.content.widgets; count = pinSpec.content.widgets.length; var widgetTypes = pinSpec.content.widgets.reduce(function (accumulator, elem) { var type = this._getWidgetType(elem); if (type in accumulator) { accumulator[type]++; } else { accumulator[type] = 1; } return accumulator; }.bind(this), {}); mostType = Object.keys(widgetTypes).reverse(function (a, b) { return widgetTypes[a] > widgetTypes[b]; })[0]; typeCount = Object.keys(widgetTypes).length; } return this._getName(count, typeCount, mostType, widgets); }, /** Generates a smart name for a single widget based on the widget's specification. * @param widgetSpec - the specification of a single widget. * @param existingNames - an optional object whose properties are existing names. If a * generated name exists in it, then the generated name will be unique-ified until it doesn't * exist in existingNames. * @returns the generated smart name. */ getWidgetName: function getWidgetName(widgetSpec, existingNames) { var type = this._getWidgetType(widgetSpec); var widgets = [widgetSpec]; return this._getName(1, 1, type, widgets, existingNames); }, getLocalizedWidgetType: function getLocalizedWidgetType(widgetSpec) { var type = this._getWidgetType(widgetSpec); return resources.get(type + '_label'); }, _getWidgetType: function _getWidgetType(widgetSpec) { var type = widgetSpec.type; if (type === 'media' && widgetSpec.mediaType) { type = widgetSpec.mediaType; } else if (widgetSpec.placeholder && !this._getTextContent(widgetSpec).length) { type = widgetSpec.type === 'text' || widgetSpec.placeholder.text ? 'placeholder_text' : 'placeholder_vis'; } return type; }, _getCountKey: function _getCountKey(count, unknown) { if (count === 1) { return unknown ? 'one_unknown' : 'one'; } else if (count > 1 && count < 5) { return unknown ? 'few_unknown' : 'few'; } else { return unknown ? 'many_unknown' : 'many'; } }, _getLabelsFromMappings: function _getLabelsFromMappings(prev, curr) { prev[curr.slotId] = curr.label; return prev; }, _isInfographics: function _isInfographics(widget) { return widget && widget.hasGraphic; }, /** Returns the visId of the specified widget, as far as the SmartNamingSvc is concerned. */ getWidgetVisId: function getWidgetVisId(widget) { var visId = widget.visId; // While editing charts (notably crosstabs), sometimes the visId is undefined, so try to use the archetype instead if (!visId && widget.archetype) { visId = archetypeToVisIdMap[widget.archetype] || widget.archetype; } // Special case for infograpics if (visId === 'summary' && this._isInfographics(widget)) { visId = 'infographicSummary'; } // Some chart types(Pie and area) can change display from the properties // Check the properties for displaying reasonable names if (['com.ibm.vis.rave2bundlepie', 'com.ibm.vis.rave2bundlearea'].indexOf(visId) !== -1 && widget.properties) { visId = this._getExpressedVisId(visId, widget.properties); } // visId substitutions. if (visIdSubstitution[visId]) { visId = visIdSubstitution[visId]; } return visId; }, _getExpressedVisId: function _getExpressedVisId(visId, properties) { switch (visId) { case 'com.ibm.vis.rave2bundlepie': _.each(properties, function (property) { if (property.id === 'pie.has.hole' && property.value === true) { visId = 'pieExpressedAsDonut'; } }.bind(this)); break; case 'com.ibm.vis.rave2bundlearea': _.each(properties, function (property) { if (property.id === 'stacked.percent' && property.value === true) { visId = 'areaExpressedAsStackedPercent'; } }.bind(this)); break; default: break; } return visId; }, _getKeyFromDataLabels: function _getKeyFromDataLabels(visId, labels) { if (!chartInfo[visId]) { return 'one_unknown_live'; } var hasRequiredLabels = _.every(chartInfo[visId].requiredMappings, function (mapping) { return labels[mapping]; }); // Handle the optional mapping if there is any. var hasOptionalLabel = chartInfo[visId].optionalMapping && labels[chartInfo[visId].optionalMapping]; if (hasOptionalLabel && hasRequiredLabels) { return visId + '_opt_mapping'; } else if (hasRequiredLabels) { return visId + '_has_mapping'; } else { return visId + '_no_mapping'; } }, _getName: function _getName(count, typeCount, mostType, widgets, existingNames) { var counts = this._getCountKey(count, false); var nameInfo = { count: count, resource_key: counts + '_' + mostType }; var firstWidget = widgets[0]; if (count === 1 && firstWidget) { switch (mostType) { case 'text': this._getTextName(nameInfo, firstWidget); break; case 'live': this._getLiveName(nameInfo, firstWidget); break; case 'filter': this._getFilterName(nameInfo, firstWidget); break; case 'shape': this._getShapeName(nameInfo, firstWidget); break; case 'image': case 'webpage': case 'youtube': case 'embedMedia': case 'media': case 'multipurpose': this._getStaticName(nameInfo, firstWidget, mostType); break; case 'placeholder_text': case 'placeholder_vis': this._getPlaceholderName(nameInfo, mostType); break; default: // Look it up in the registry this._getRegistryName(nameInfo, firstWidget, mostType, counts); break; } } else if (typeCount > 1) { nameInfo.resource_key = count < 5 ? 'few_unknown' : 'many_unknown'; } // Make sure we return something reasonable in case new widget types are added and no one updates this code. var name = resources.get(nameInfo.resource_key, nameInfo); if (name === nameInfo.resource_key) { nameInfo.resource_key = this._getCountKey(count, true); name = resources.get(nameInfo.resource_key, nameInfo); } // Make sure the name is unique. if (existingNames && existingNames[name]) { nameInfo.resource_key = nameInfo.resource_key + '_numbered'; // Assuming no one will ever have more than 500 widgets with the same name on single frame, // break to avoid getting into an infinite loop. for (var number = 1; number < 501 && existingNames[name]; number++) { nameInfo.number = number; name = resources.get(nameInfo.resource_key, nameInfo); } } return name; }, _getTextContent: function _getTextContent(widgetSpec) { return new MultilingualAttribute(widgetSpec.name, this._boardModel.getLanguageModelOptions()).getValue(); }, _getTextName: function _getTextName(nameInfo, firstWidget) { // If content exists, use that var textContent = this._getTextContent(firstWidget); if (textContent) { nameInfo.name = textContent; nameInfo.resource_key = 'one_name'; } else { if (firstWidget.placeholder) { nameInfo.resource_key = 'one_placeholder_text'; } else { nameInfo.resource_key = 'noExtraText_text'; } } }, _getLiveName: function _getLiveName(nameInfo, firstWidget) { var visId = this.getWidgetVisId(firstWidget); var widgetTitle = null; if (firstWidget.name) { var multilingualAttribute = new MultilingualAttribute(firstWidget.name, this._boardModel.getLanguageModelOptions()); widgetTitle = multilingualAttribute.getValue().trim(); } if (widgetTitle && widgetTitle.length > 0) { nameInfo.name = widgetTitle; nameInfo.resource_key = visId + '_named'; var name = resources.get(nameInfo.resource_key, nameInfo); // We do this check here so that we at least know that it is a named chart of some sort. if (name === nameInfo.resource_key) { nameInfo.resource_key = 'one_named_live'; } } else { var slotsInfo = []; var slots = firstWidget.slotmapping && firstWidget.slotmapping.slots; var items = this._getAllDataItemsFromData(firstWidget.data); _.each(items, function (item) { var iteminfo = { label: item.itemLabel }; _.each(slots, function (slot) { if (slot.dataItems.indexOf(item.id) >= 0) { iteminfo.slotId = slot.name; } }.bind(this)); slotsInfo.push(iteminfo); }.bind(this)); _.extend(nameInfo, slotsInfo.reduce(this._getLabelsFromMappings, {})); nameInfo.resource_key = this._getKeyFromDataLabels(visId, nameInfo); } }, _getAllDataItemsFromData: function _getAllDataItemsFromData(data) { var items = []; if (data && data.dataViews) { data.dataViews.forEach(function (dataView) { items.push.apply(items, dataView.dataItems); }); } return items; }, _getFilterName: function _getFilterName(nameInfo, firstWidget) { if (firstWidget.properties.itemName) { nameInfo.name = firstWidget.properties.itemName.trim(); var name = resources.get(nameInfo.resource_key, nameInfo); if (name === nameInfo.resource_key) { nameInfo.resource_key = 'one_named_filter'; } } else { nameInfo.resource_key = 'one_unknown_filter'; } }, _getShapeName: function _getShapeName(nameInfo, firstWidget) { if (firstWidget.name) { nameInfo.name = firstWidget.name.trim(); nameInfo.resource_key = 'one_name'; } else { nameInfo.resource_key = 'noExtraText_shape'; } }, _getStaticName: function _getStaticName(nameInfo, firstWidget, mostType) { var multilingualKey; if (mostType === 'image') { multilingualKey = firstWidget.altText; } else { multilingualKey = firstWidget.title; } var textContent = null; if (multilingualKey) { var multilingualAttribute = new MultilingualAttribute(multilingualKey, this._boardModel.getLanguageModelOptions()); textContent = multilingualAttribute.getValue(); } if (textContent) { nameInfo.text = textContent.trim(); nameInfo.resource_key = 'one_' + mostType; } else { nameInfo.resource_key = 'noExtraText_' + mostType; } }, _getRegistryName: function _getRegistryName(nameInfo, firstWidget, mostType, counts) { if (this._widgetRegistry && this._widgetRegistry[mostType] && !this._widgetRegistry[mostType].builtin) { if (firstWidget.name) { var multilingualAttribute = new MultilingualAttribute(firstWidget.name, this._boardModel.getLanguageModelOptions()); nameInfo.name = multilingualAttribute.getValue().trim(); nameInfo.resource_key = 'one_custom_named'; } else { nameInfo.resource_key = 'one_custom'; } } else { nameInfo.resource_key = counts + '_' + mostType; } }, _getPlaceholderName: function _getPlaceholderName(nameInfo, mostType) { nameInfo.resource_key = 'one_' + mostType; } }); return Svc; }); //# sourceMappingURL=SmartNamingSvc.js.map