'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Licensed Materials - Property of IBM * IBM Cognos Products: Dashboard * (C) Copyright IBM Corp. 2013, 2021 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * * VisActionHelper * The VisActionHelper is responsible for loading and executing interactive actions that affect the vismodel. * */ define(['jquery', 'underscore', '../../widgets/livewidget/nls/StringResources', '../../DynamicFileLoader', './VisActionSlotSupport', '../../dataSources/utils/DatasourceUtil', '../../apiHelpers/SlotAPIHelper'], function ($, _, resources, DynamicFileLoader, VisActionSlotSupport, DatasourceUtil, SlotAPIHelper) { 'use strict'; var SlotAction = function () { function SlotAction(spec) { _classCallCheck(this, SlotAction); this.spec = spec; } SlotAction.prototype.getActionId = function getActionId() { return this.spec.ACTION_ID; }; SlotAction.prototype.getAvailableActions = function getAvailableActions() { return [this.spec]; }; return SlotAction; }(); var VisActionHelper = function () { function VisActionHelper(attributes) { _classCallCheck(this, VisActionHelper); this._visModel = attributes.visModel; this.selectionController = attributes.selectionController; this.pageContext = attributes.pageContext; this.ownerWidget = attributes.ownerWidget; this.content = attributes.content; this.dashboardApi = attributes.ownerWidget.getDashboardApi(); //Any dynamically loaded actions (eg: FilterLocalExcludeAction) should be saved here for cleanup on remove. this._registeredActions = {}; this.logger = attributes.ownerWidget.logger; this._visActionSlotSupport = new VisActionSlotSupport(attributes); } VisActionHelper.prototype.remove = function remove() { var _this = this; if (this.toolbar) { this.toolbar.remove(); this.toolbar = null; } this._visModel = null; this.selectionController = null; this.pageContext = null; this.ownerWidget = null; this.visualization = null; this.dashboardApi = null; this.logger = null; // cleanup registered actions (eg FilterLocalKeep, FilterLocalExclude, FilterAllKeep). _.each(_.keys(this._registeredActions), function (action) { delete _this._registeredActions[action]; }); }; VisActionHelper.prototype._supportsSortAction = function _supportsSortAction() { return this._visModel && this._visModel.supportsSortAction(); }; VisActionHelper.prototype._supportsContextualTopBottomAction = function _supportsContextualTopBottomAction() { return this.getVisualization().getDefinition().getProperty('supportsContextualTopBottomAction'); }; VisActionHelper.prototype._supportsNonContextualTopBottomAction = function _supportsNonContextualTopBottomAction() { return this.getVisualization().getDefinition().getProperty('supportsNonContextualTopBottomAction'); }; VisActionHelper.prototype._supportsFormatAction = function _supportsFormatAction() { return this._visModel && this._visModel.supportsFormatAction(); }; VisActionHelper.prototype._supportsBinAction = function _supportsBinAction() { return this._visModel && this._visModel.supportsBinAction(); }; /** * Show the actions/labels tooltip for the current selection * * @param selections - Array of selections * @param position - Container node or bounds information where the tooltip should appear * @param {boolean} includeApplyFilter - whether to include the 'filter' (apply filter) action * @param {boolean} noFilter - true - hide all options on hover or used by grid/crosstab to turn off the filter option * @param {boolean} drillOnly * @param {boolean} noDrillthrough - whether to include the 'Drill through' (JumpToAction) action * @param {options} */ VisActionHelper.prototype.showDataPointActions = function showDataPointActions(selections, position, includeApplyFilter, noFilters, drillOnly, noDrillthrough, options) { var _this2 = this; options = options || {}; var actionOptions = { includeApplyFilter: includeApplyFilter, noFilters: noFilters, drillOnly: drillOnly, noDrillthrough: noDrillthrough, selections: selections, isHovering: options.isHover, area: options.area, isAreaSelected: options.isAreaSelected }; var availableActions = []; var fRegisterAction = function fRegisterAction(action) { availableActions = availableActions.concat(action.getAvailableActions()); }; return this._getExtraDatapointActions(options).then(function (actions) { _.each(actions, fRegisterAction); var labels = _this2.selectionController.getToolbarLabelsForSelections(selections); var sTitle = _this2.selectionController.getToolbarTitleForSelections(selections); if (!options.isHover) { var _availableActions; (_availableActions = availableActions).push.apply(_availableActions, _this2._getDataPointActionList(selections, actionOptions, options)); } if (labels.length > 0 || sTitle.length > 0) { var eventOptions = { 'targetNode': position ? position.targetNode : null, 'targetBounds': position ? position.bounds : null, 'actions': availableActions, 'labels': labels, 'title': sTitle, 'options': options, 'tooltipContext': { /* This is not used in for now. It is here for the custom tooltip extension */ content: _this2.content, context: _this2._convertOldSelectionToNewSpec(selections) } }; eventOptions.toolbarOptions = { iconOnly: true, isTextEditorOnly: false }; if (availableActions.length === 1) { eventOptions.toolbarOptions['isTextEditorOnly'] = true; } _this2.dashboardApi.triggerDashboardEvent('widget:availableActions', eventOptions); } }); }; /** * As agreed, the final selections payload is the union of brushing and pending filters. * @example of the payload: * { * 'area': 'visualization', * 'dataPoints': [{ * 'categories': [{ * 'dataItemId': 'item0_id', * 'columnId': 'item0', * 'value': 'value1', * 'label': 'value1_label' * }, { * 'dataItemId': 'item1_id', * 'columnId': 'item1', * 'value': 'value2', * 'label': 'value2_label' * }], * 'facts': [{ * 'dataItemId': 'fact2_id', * 'columnId': 'fact2', * 'value': 1000 * }] * }, { * 'categories': [{ * 'dataItemId': 'item0_id', * 'columnId': 'item0', * 'value': 'value3', * 'label': 'value3_label' * }, { * 'dataItemId': 'item1_id', * 'columnId': 'item1', * 'value': 'value2', * 'label': 'value2_label' * }] * } */ VisActionHelper.prototype._getDataPointActionList = function _getDataPointActionList(selections, actionOptions, options) { var newSelections = this._getBrushingAndPendingSelections(selections, this.content, options); return this.content.getFeature('DataPointActions').getDataPointActionList(newSelections, actionOptions); }; VisActionHelper.prototype._convertOldSelectionToNewSpec = function _convertOldSelectionToNewSpec(selections) { var _this3 = this; var dataPoints = []; var categorySelections = selections && selections.getCategorySelections() || []; var selectionEntry = {}; var categories = []; categorySelections.forEach(function (category) { categories.push(_this3._toPayLoadValue(category.value, category.slotDataItem.getColumnId(), category.slotDataItem.getId())); }); var ordinalSelections = selections && selections.getOrdinalSelections() || []; var facts = _.map(ordinalSelections, function (factItem) { return { dataItemId: factItem.slotDataItem.getId(), columnId: factItem.slotDataItem.getColumnId(), value: factItem.value instanceof Object ? factItem.value.value : factItem.value }; }); if (categories.length) { selectionEntry.categories = categories; } if (facts.length) { selectionEntry.facts = facts; } dataPoints.push(selectionEntry); return { dataPoints: dataPoints }; }; VisActionHelper.prototype._getBrushingAndPendingSelections = function _getBrushingAndPendingSelections(selections, content, options) { var _this4 = this; var dataPoints = []; var categorySelections = selections && selections._aCategorySelections || []; var selectionEntry = {}; var categories = []; categorySelections.forEach(function (category) { if (!category.isEdgeSelection) { categories.push(_this4._toPayLoadValue(category.value, category.slotDataItem.getColumnId(), category.slotDataItem.getId())); } }); var ordinalSelections = selections && selections._aOrdinalSelections || []; var facts = _.map(ordinalSelections, function (factItem) { return { dataItemId: factItem.slotDataItem.getId(), columnId: factItem.slotDataItem.getColumnId(), value: factItem.value /* TODO - fix the value here. It should just be the value, but it is a json {value:1234, v:1234} */ }; }); if (categories.length) { selectionEntry.categories = categories; } if (facts.length) { selectionEntry.facts = facts; } dataPoints.push(selectionEntry); var selectedDataItemList = selections._aCategorySelections ? selections._aCategorySelections.map(function (selection) { return selection.slotDataItem; }) : []; var pageContextSelections = content.getFeature('DataPointSelections').getSelections(selectedDataItemList); var pendingSelections = content.getFeature('DataPointSelections.pending').getSelections(selectedDataItemList); // Check if current selection is in pageContext selections var selectionInPageContext = false; var currentCategoryKey = _.pluck(categories, 'columnId').join(); pageContextSelections.forEach(function (selection) { var categoryKey = _.pluck(selection.categories, 'columnId').join(); // if current selection is in pageContext selections, use combined selections // OR if edge selection, and current selection is in pageContext if (currentCategoryKey === categoryKey || currentCategoryKey === '' && _this4._compareCategorySelections(categorySelections, selection.categories)) { pageContextSelections = pageContextSelections.concat(pendingSelections); selectionInPageContext = true; } }); if (!selectionInPageContext) { pageContextSelections = pendingSelections; } dataPoints = dataPoints.concat(pageContextSelections); dataPoints = this._uniqueValues(dataPoints); return { area: options && options.area, dataPoints: dataPoints }; }; VisActionHelper.prototype._compareCategorySelections = function _compareCategorySelections(categorySelections, categories) { var values = _.pluck(categorySelections, 'value'); var categoryKeys = _.pluck(categories, 'value'); var contains = true; values.forEach(function (value) { if (!(categoryKeys.indexOf(value.u) !== -1)) { contains = false; } }); return values && categoryKeys && contains; }; VisActionHelper.prototype._toPayLoadValue = function _toPayLoadValue(value, columnId, dataItemId) { var resultPayLoad = { dataItemId: dataItemId, columnId: columnId, value: value.u, label: value.d }; if (value.pu || value.p) { resultPayLoad.parentId = value.pu || value.p.u; } return resultPayLoad; }; VisActionHelper.prototype._uniqueValues = function _uniqueValues() { var dataPointSelections = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var uniqueValues = []; var valuesMap = {}; dataPointSelections.forEach(function (dataPoint) { var categoryKey = _.pluck(dataPoint.categories, 'value').join(); if (!valuesMap[categoryKey]) { valuesMap[categoryKey] = 1; uniqueValues.push(dataPoint); } }); return uniqueValues; }; VisActionHelper.prototype._getExtraDatapointActions = function _getExtraDatapointActions(options) { var result = void 0; if (!(options && options.slots && options.mapIndex !== undefined)) { result = Promise.resolve([]); } else { options.actions && options.actions.actionOptions && (options.actions.actionOptions.JumpToAction = { area: options.area }); result = this.getActionsForSlots(options.slots, options.mapIndex, null, options.actions); } return result; }; VisActionHelper.prototype.hideToolbarActions = function hideToolbarActions() { this.dashboardApi.triggerDashboardEvent('widget:hideToolbar'); }; /** * @param FilterAction - the class of the filter action. * @param slot - the data slot associated with this filter action. * @param index - the index of the data item in the slot. * @returns a new filter action associated with the passed in data slot. */ VisActionHelper.prototype.getNewFilterActionForSlot = function getNewFilterActionForSlot(FilterAction, slot, index) { // This method assumes that the required FilterAction object is loaded. //TODO: This action should probably be called FilterSlotAction (and separated from FilterAction) // since it is specific to filtering items assigned to visible slots. return new FilterAction(this.getVisualization(), slot, index, this.ownerWidget.getDashboardApi(), this.logger); }; /** * @param FilterAction - the class of the filter action * @param visColumn - the column to create this context filter for. * @returns a FilterAction associated with the passed in context visColumn. * Note: Use getNewFilterActionForSlot when possible because a slot * can override the usage of a column (eg: an attribute column assigned to an ordinal slot becomes a count). */ VisActionHelper.prototype.getNewFilterActionForContextColumn = function getNewFilterActionForContextColumn(FilterDropAction, metadataColumn) { // This method assumes that the required FilterAction object is loaded. return new FilterDropAction(this.getVisualization(), metadataColumn, this.pageContext, this.ownerWidget.getDashboardApi(), this.logger); }; VisActionHelper.prototype.getActionsForLocalFilter = function getActionsForLocalFilter(metadataColumn, filterId) { var _this5 = this; var availableActions = []; //The set of all availableActions for this context return DynamicFileLoader.load(['dashboard-analytics/visualizations/interactions/FilterDropAction', 'dashboard-analytics/visualizations/interactions/DeleteFilterAction']).then(function (modules) { var FilterDropAction = modules[0]; var DeleteFilterAction = modules[1]; var existingFilterEntry = filterId && _this5._visModel.localFilters.getFilterEntry({ id: filterId }); if (existingFilterEntry && _this5._visModel.isFilterEditable(existingFilterEntry)) { availableActions.push(_this5.getNewFilterActionForContextColumn(FilterDropAction, metadataColumn)); } availableActions.push(new DeleteFilterAction(_this5._visModel, metadataColumn, filterId)); return availableActions; }); }; VisActionHelper.prototype._getSingleSlot = function _getSingleSlot(slots, mapIndex) { //if slots length is not 1, return null if (slots.length !== 1) { return null; } //if mapIndex exists and its an array of length > 1, return null if (mapIndex && mapIndex instanceof Array && mapIndex.length > 1) { return null; } //otherwise, return slots[0] return slots[0]; }; /** * Collect action information for slots that can be used to * determine which actions are available for the slots. * @param slots {Array} - an array of up to two slots * @param mapIndex integer or array of integers corresponding to indices of data items in a slot * @param selectionObj selected DOM representing the selected dataItem * @param options specifies the additional options necessary to get the actions * @return action information for slot * * @note the case where mapIndex can be an array: * (1) create a croostab vis * (2) Rows: Revenue, Product Line * Values: Order method type, Quantity * (3) multi-select two column, and right click on it. */ VisActionHelper.prototype._getActionInfoForSlots = function _getActionInfoForSlots(slots, mapIndex, selectionObj, options) { var singleSlot = this._getSingleSlot(slots, mapIndex); var focusMode = options && options.focusMode != undefined ? options.focusMode : true; var itemsArea = options && options.itemsArea ? options.itemsArea : undefined; //DEFECT 253869 //Verify if mapIndex is defined to differentiate when we're selecting specific data item that is a multi measure or multiple data items (get actions for y axis) var isMultiMeasure = singleSlot && mapIndex == undefined ? SlotAPIHelper.isMultiMeasuresSeriesSlot(singleSlot) || SlotAPIHelper.isMultiMeasuresValueSlot(singleSlot) : false; var slotState = { selectionObj: selectionObj, slots: slots, singleSlot: singleSlot, dataItems: [], mapIndex: mapIndex, isAuthoringMode: this._visModel.ownerWidget.isAuthoringMode, isCalculationEnabled: false, isMultiMeasure: isMultiMeasure, isEditCalculation: false, isMappedToUnavailableSourceColumn: false, isFocusMode: focusMode, supportsSortAction: this._supportsSortAction(), supportsContextualTopBottomAction: this._supportsContextualTopBottomAction(), supportsNonContextualTopBottomAction: this._supportsNonContextualTopBottomAction(), supportsFormatAction: this._supportsFormatAction(), supportsBinAction: this._supportsBinAction(), area: itemsArea }; if (mapIndex === undefined || mapIndex === null) { mapIndex = 0; } if (mapIndex && Array.isArray(mapIndex)) { _.each(mapIndex, function (index) { slotState.dataItems.push(slots[0].getDataItemList()[index]); }); } else { slotState.dataItems.push(slots[0].getDataItemList()[mapIndex]); } slotState.isMappedToUnavailableSourceColumn = _.every(slotState.dataItems, function (dataItem) { return dataItem.isColumnUnavailable(); }); if (!slotState.isMappedToUnavailableSourceColumn) { var slot = slots[0]; var dataItemList = slot.getDataItemList(); // [todo] livewidget_cleanup: need to revisit this and test crosstab multiselection again... if (mapIndex && Array.isArray(mapIndex)) { slotState.isCalculationEnabled = dataItemList[mapIndex[0]].getType() === 'fact'; } else { slotState.isCalculationEnabled = dataItemList[mapIndex].getType() === 'fact'; } var metadataColumn = void 0; if (singleSlot) { // if singleSlot is defined, mapIndex wont be an array. See _getSingleSlot() metadataColumn = dataItemList[mapIndex].getMetadataColumn(); slotState.isEditCalculation = metadataColumn ? metadataColumn.isEditableCalculation() : false; } // For the grid, we need to check if the data items selected are type 'fact' to determine if calculation should be enabled if (!slotState.isCalculationEnabled && slot.getDefinition().getType() === 'any' && mapIndex && mapIndex.length < 3) { slotState.isCalculationEnabled = _.every(mapIndex, function (index) { return dataItemList[index].getType() === 'fact'; }); } } return { state: slotState, actions: this._enableSupportedSlotActions(slotState) }; }; /** * Enable / disable slot actions * @param {Object} slotState - state object of the slot information * @return array of enabled / disabled actions */ VisActionHelper.prototype._enableSupportedSlotActions = function _enableSupportedSlotActions(slotState) { var _this6 = this; var actions = {}; var actionExt = slotState.singleSlot ? slotState.singleSlot.getDefinition().getProperty('actions') : null; // 1. Default state of each action // Actions defined in the slot takes priority. // If no actions are defined (null or undefined) in the slot, // all actions are considered as available by default. _.each(_.keys(VisActionSlotSupport.SLOT_ACTIONS), function (action) { actions[action] = actionExt ? actionExt.indexOf(action) >= 0 : true; }); // 2. Enable / Disable actions for slots _.each(_.keys(VisActionSlotSupport.SLOT_ACTIONS), function (action) { // Check if the enabled action is available for slot if (actions[action]) { var slotSupport = _this6._visActionSlotSupport.getInterface(action); // action without a validator (supports???Action) is considered enabled actions[action] = slotSupport.isSupported ? slotSupport.isSupported(slotState) : true; } }); return actions; }; /** * Get the list module paths to be loaded * @param actionInfo action info object * @see {@link _getActionInfoForSlots} */ VisActionHelper.prototype._getActionModules = function _getActionModules(actionInfo) { var availableActionModules = []; var singleSlot = actionInfo.state.singleSlot; if (!actionInfo.state.isMappedToUnavailableSourceColumn) { _.each(actionInfo.actions, function (active, action) { var actionIndex = VisActionSlotSupport.SLOT_ACTIONS[action]; availableActionModules[actionIndex] = active ? action : ''; }); } // defect 246203 & 262087 - if the number of slots is one in the visualization, don't show filter and calculation actions // since the filter action is determined by the ordinal slot var numberOfSlots = this.getVisualization().getSlots().getSlotList().length; //if there are any disallowed actions as defined for a single slot in the vis definition/viprConfig, then remove them here if (numberOfSlots == 1) { var disallowedActionsForSingleSlot = singleSlot.getDefinition().getProperty('disallowedActions'); // If we are putting a category into an ordinal slot type then we need to // restrict actions since the filters are confused. The user will still be able // to apply a filter by dragging a category filter to local filter slots. // Note that this affects multiple visualizations and not just Summary widget. var dataItem = actionInfo.state.dataItems.length === 1 && actionInfo.state.dataItems[0]; if (DatasourceUtil.isOrdinalAttribute(singleSlot, dataItem)) { if (!disallowedActionsForSingleSlot) { disallowedActionsForSingleSlot = []; } disallowedActionsForSingleSlot = disallowedActionsForSingleSlot.concat(['FilterAction']); } if (disallowedActionsForSingleSlot) { _.each(availableActionModules, function (actionModule, key, availableActionModulesArray) { if (disallowedActionsForSingleSlot.indexOf(actionModule) > -1) { availableActionModulesArray[key] = ''; } }); } } // prepend modules with full path return availableActionModules.map(function (sModule) { return sModule ? 'dashboard-analytics/visualizations/interactions/' + sModule : ''; }); }; /** * Load the action modules and instantiate the action objects * @param slots {Array} - an array of up to two slots * @param mapIndex integer or array of integers corresponding to indices of data items in a slot * @param selectionObj selected DOM representing the selected dataItem * @param actionModules array of action module path * @param actionInfo action info object * @see {@link _getActionInfoForSlots} */ VisActionHelper.prototype._loadActionModules = function _loadActionModules(slots, actionModules, actionInfo, options) { var _this7 = this; var slotState = actionInfo.state; var actions = options || {}; return DynamicFileLoader.load(actionModules).then(function (modules) { var availableActions = []; //The set of all availableActions for this context _.each(modules, function (Module, index) { if (Module) { var action = void 0; var slotSupport = _this7._visActionSlotSupport.getInterface(index); if (slotSupport.get) { action = slotSupport.get(Module, slotState, _this7.dashboardApi); } if (action) { availableActions.push(action); } } }); var slotId = slotState.singleSlot ? slotState.singleSlot.getId() : slotState.slots[0].getId(); var actionExt = slotState.singleSlot ? slotState.singleSlot.getDefinition().getProperty('actions') : null; if (actions.actionsToKeep && actions.actionsToKeep.length > 0 && actionExt && actionExt.length > 0) { // there might not be a real usecase for this scenario, but it is here in case the caller provides // its own list of actionsToKeep and we need to intersect it with the list that comes from the viz definition actions.actionsToKeep = _.intersection(actions.actionsToKeep, actionExt); } else if (actionExt && actionExt.length > 0) { actions.actionsToKeep = actionExt; } var specs = _this7.content.getFeature('SlotActions').getSlotActionList(slotId, slotState.mapIndex, actions); _.each(specs, function (spec) { spec.text = spec.label; availableActions.push(new SlotAction(spec)); }); return availableActions; }); }; /** * Gets the actions for an array of up to slots based on the number and types of the slots * @param slots {Array} - an array of up to two slots * @param mapIndex integer or array of integers corresponding to indices of data items in a slot * @param selectionObj selected DOM representing the selected dataItem * @param options specifies the additional options necessary to get the actions * @returns jquery promise */ VisActionHelper.prototype.getActionsForSlots = function getActionsForSlots(slots, mapIndex, selectionObj, options) { // 1. get he summarized information of actions for the slots var actionInfo = this._getActionInfoForSlots(slots, mapIndex, selectionObj, options); // 2. get the list of modules to load for each actions var availableActionModules = this._getActionModules(actionInfo); // If there is an `actionsToKeep` array, don't bother loading these availableActions, they will be filtered out in the end. // `actionsToKeep` is currently only used for sortAction (rank column). When all actions are refactored to be loaded // via _loadActionModules, we will not need this following line here. var actions = options && options.actions || options; if (actions && actions.actionsToKeep && actions.actionsToKeep.length) { availableActionModules = []; } // 3. load the modules in to an array of action instances return this._loadActionModules(slots, availableActionModules, actionInfo, actions); }; /** * Load (and display) any available actions that should be rendered on selection * of a category column * @param slots An array of the category columns of up to two columns * @param position an optional object that contains the target node and/or the target bounds which can be set to improve context menu placement. * @param selectionObj Selected DOM representing the selected dataItem * @param mapIndex An optional integer or array of integers corresponding to indices of data items in a slot * @param itemsArea The clicked area of the target items. The area could be of values: visualization, legend, or none * @param actions Optional object containing actionsToKeep (array of action ids), and actionOptions (object). * When actionsToKeep exists, we will only return those actions. actionOptions contain extra options for each action. * @returns promise which is resolved when all actions are loaded. */ VisActionHelper.prototype.showTitleActions = function showTitleActions(slots, position, selectionObj, mapIndex, itemsArea, actions) { var _this8 = this; if (!slots || slots.length === 0) { return Promise.resolve(); } var options = { iconOnly: true, focusMode: false, itemsArea: itemsArea, actions: actions }; // Don't show title when multiple selected if (slots.length === 1 && mapIndex && mapIndex.length === 1) { var index = Array.isArray(mapIndex) ? mapIndex[0] : mapIndex; options.toolbarName = slots[0].getDataItemList()[index].getLabel(); } var availableActions = []; //The set of all availableActions for this context var fRegisterAction = function fRegisterAction(action) { availableActions = availableActions.concat(action.getAvailableActions()); _this8._registeredActions[action.getActionId()] = action; }; return this.getActionsForSlots(slots, mapIndex, selectionObj, options).then(function (actions) { _.each(actions, fRegisterAction); slots = slots.length === 1 ? slots[0] : null; //When there is only one slot in the slots, pass constructToolar the single slot in order to show the toolbar menu title _this8._constructToolbar(availableActions, position, slots, options); }); }; /* Constructs the toolbar needed * @param options : Additional options for the toolbar such as showing only text or icons */ VisActionHelper.prototype._constructToolbar = function _constructToolbar(availableActions, oPosition, slot, options) { if (availableActions.length !== 0) { //Add additional actions for category column selections here.. var position = oPosition || {}; var mapping = slot && slot.mapping; var toolbarName = mapping ? this._visModel.getLabelByMapping(mapping) : options.toolbarName ? options.toolbarName : undefined; if (position.bounds) { var visBounds = this._visModel.ownerWidget.el.getBoundingClientRect(); var visChart_center_x = visBounds.left + visBounds.width / 2; var visElement_center_x = position.bounds.left + position.bounds.width / 2; if (visElement_center_x > visChart_center_x) { // The element is on the right side of the chart, so try to show the Flyout on the right to avoid hiding the chart. position.placement = 'right auto'; } } var eventOptions = { targetNode: position.targetNode || null, targetBounds: position.bounds || null, placement: position.placement || 'left auto', actions: availableActions, toolbarName: toolbarName }; if (options) { eventOptions.toolbarOptions = options; } this.dashboardApi.triggerDashboardEvent('widget:availableActions', eventOptions); } }; /** * Brings up the UI to edit an existing filter * @param filterId - the Id of the filter to edit. * @param node - the node to guide placement of the dialog. */ VisActionHelper.prototype.editLocalFilter = function editLocalFilter(filterId, node) { var _this9 = this; var visualization = this.getVisualization(); var filterEntry = _.find(visualization.getLocalFilters().getFilterList(), function (filter) { return filter.id === filterId; }); var filterDesc = _.find(visualization.getLocalFilters().getFiltersDesc(), function (filter) { return filter.dataId === filterId; }); if (!node || !filterDesc || !filterDesc.editEnabled) { return Promise.resolve(); } //If this filterEntry has a matching slot dataItem, load the dataItem filter module and launch the editor with the appropriate slot and index defined. //otherwise, load the contextFilter module and launch that editor with the metadata column information. var matchingSlotDataItem = null; if (filterEntry) { matchingSlotDataItem = _.find(visualization.getSlots().getMappingInfoList(), function (mapping) { var match = mapping.dataItem.getColumnId() === filterEntry.columnId; if (match && filterEntry.aggregationType) { match = mapping.dataItem.getAggregation() === filterEntry.aggregationType; } return match; }); } //If there's a matchingSlotDataItem, load the slot filter action, otherwise, load the context filter action. var actionToLoad = matchingSlotDataItem ? 'dashboard-analytics/visualizations/interactions/FilterAction' : 'dashboard-analytics/visualizations/interactions/FilterDropAction'; return DynamicFileLoader.load([actionToLoad]).then(function (modules) { var FilterAction = modules[0]; var fAction = matchingSlotDataItem ? _this9.getNewFilterActionForSlot(FilterAction, matchingSlotDataItem.slot, matchingSlotDataItem.indexInSlot) : _this9.getNewFilterActionForContextColumn(FilterAction, visualization.getDataSource().getMetadataColumn(filterEntry.columnId)); return _this9.renderFilterDialog(fAction.getEditorModuleName(), fAction.getViewOptions(), node); }); }; VisActionHelper.prototype.renderFilterDialog = function renderFilterDialog(sDialogModuleName, viewOptions, node, launchView, backButtonCallback) { var _this10 = this; return DynamicFileLoader.load([sDialogModuleName]).then(function (modules) { var FilterDialog = modules[0]; var view = new FilterDialog(viewOptions); var preloadDone = view.preload ? view.preload() : Promise.resolve(); var title = viewOptions.title || resources.get('toolbarActionFilter'); return preloadDone.then(_this10._createContext.bind(_this10, view, node, title, launchView, backButtonCallback)).then(view.renderCallBack.bind(view)); }); }; VisActionHelper.prototype.resetActionState = function resetActionState(actionName, slot, index) { var slotAction = this._getSlotActionByNameOrGroup(slot, actionName, index); if (slotAction && slotAction.actions && slotAction.actions.reset) { slotAction.actions.reset(slot.getId(), index); } }; VisActionHelper.prototype.showAction = function showAction(actionName, slot, node, index) { var _this11 = this; var slotAction = this._getSlotActionByNameOrGroup(slot, actionName, index); if (slotAction) { var viewModule = slotAction.view && slotAction.view.module; return DynamicFileLoader.load([viewModule]).then(function (modules) { var Dialog = modules[0]; var view = new Dialog({ state: slotAction.view.state, actions: slotAction.actions }); return _this11._createContext(view, node, resources.get(slotAction.text)); }); } return Promise.resolve(); }; VisActionHelper.prototype._getSlotActionByNameOrGroup = function _getSlotActionByNameOrGroup(slot, actionName, index) { var specs = this.content.getFeature('SlotActions').getSlotActionList(slot.getId(), index); return specs.find(function (spec) { return spec.name === actionName || spec.group === actionName; }); }; VisActionHelper.prototype._createContext = function _createContext(view, node, toolbarLabel, launchView, backButtonCallback) { var actions = [{ responsive: false, editable: false, changedAction: null, subView: view, type: 'SubView' }]; return this._setToolbarForEditor(actions, node, toolbarLabel, launchView, backButtonCallback); }; VisActionHelper.prototype._setToolbarForEditor = function _setToolbarForEditor(aActions, node, sLabel, launchView, backButtonCallback) { var _this12 = this; return DynamicFileLoader.load(['dashboard-analytics/lib/@waca/dashboard-common/dist/ui/AuthoringToolbar']).then(function (modules) { var Toolbar = modules[0]; if (_this12.toolbar) { _this12.toolbar.remove(); } _this12.toolbar = new Toolbar({ container: $('body'), placement: launchView && launchView.getPlacement ? launchView.getPlacement() : 'right auto', calculateBoundingRect: true, launchView: launchView, backButtonCallback: backButtonCallback }); if (sLabel) { _this12.toolbar.setName(sLabel); } _this12.toolbar.addItems(aActions); _this12.toolbar.setSelectionContext([node]); _this12.toolbar.show(); return _this12.toolbar; }); }; VisActionHelper.prototype.getVisualization = function getVisualization() { //@todo After the old visAPI is removed, not need to have this function //Instead the constructor of this class can just set this.visualization = this.widgetAPI.getFeature('Visualization') //Right now is is not possible due to deprecated old apis dependencies on //visAPI.getUITestApi visAPI.and selectData if (!this.visualization) { this.visualization = this.content.getFeature('Visualization'); } return this.visualization; }; return VisActionHelper; }(); return VisActionHelper; }); //# sourceMappingURL=VisActionHelper.js.map