123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- '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: Storytelling
- * (C) Copyright IBM Corp. 2015, 2020
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define(['baglass/core-client/js/core-client/errors/BaseError', 'baglass/core-client/js/core-client/utils/ClassFactory', 'underscore', 'gemini/app/util/ErrorUtils', 'gemini/app/ui/dialogs/GenericViewDialog', 'react', 'react-dom'
- // PLEASE PLEASE PLEASE - No Storytelling dependencies here.
- // This module is loaded in scope of dashboard and should be as light as possible.
- // Load storytelling modules on-demand, only when used.
- ], function (BaseError, ClassFactory, _, ErrorUtils, Dialog, React, ReactDOM) {
- var getContentView = function getContentView(glassContext) {
- var contentView = null;
- if (glassContext.appController.getCurrentContentView) {
- contentView = glassContext.appController.getCurrentContentView();
- } else if (glassContext.appController.currentAppView.currentContentView) {
- contentView = glassContext.appController.currentAppView.currentContentView;
- }
- return contentView;
- };
- var ActionHandler = function () {
- function ActionHandler() {
- _classCallCheck(this, ActionHandler);
- // This value comes from the dashboardToStory.json file in the perspectives directory
- this._contributionId = 'com.ibm.bi.storytelling';
- }
- /**
- * Handles whether or not to show the menu item(s) we contribued to the save menu.
- * @override
- *
- * @returns {boolean} Returns true if item should be visible or false if not.
- */
- ActionHandler.prototype.isItemVisible = function isItemVisible(context) {
- if (context.target.itemId === this._contributionId + '.exportAsStory') {
- return this._isBoardTypeSupported(context) && ErrorUtils.hasCapability(context.glassContext, 'canAuthorDashboard');
- }
- return false;
- };
- /**
- * Handles the click of the menu item we contributed to the save menu.
- * @override
- *
- * @returns {Promise}
- */
- ActionHandler.prototype.onSelectItem = function onSelectItem(context) {
- if (this._contributionId + '.exportAsStory' === context.target.itemId) {
- var view = getContentView(context.glassContext);
- var segmentType = { type: 'Exported Object' };
- view.getDashboardApi().getFeature('segment').track('exportedToStory', function () {
- return segmentType;
- });
- return this._convertToStory(context);
- }
- return Promise.resolve();
- };
- /**
- * @param {Object} service This is the object that is defined when creating a new SaveAsDialog
- * @param {string} selection This comes from SaveAsDialog's inner workings
- * @param {string} name This comes from SaveAsDialog's inner workings
- * @param {boolean} overwrite This comes from SaveAsDialog's inner workings
- * @param {boolean} loadOnSave Whether to load after a successful export
- *
- * @returns {Promise}
- */
- ActionHandler.prototype.exportAsStory = function exportAsStory(service, selection, name, overwrite, loadOnSave) {
- return this._sendRequest({
- context: service.context,
- url: selection.url,
- name: name,
- overwrite: overwrite
- }).then(this._onExportSuccess.bind(this, service.context, loadOnSave)).catch(this._onExportError.bind(this)).finally(this._exportDialog.hide.bind(this._exportDialog));
- };
- /**
- * Handle the conversion of the board model to a story and displaying the SaveAs dialog
- * @private
- * @param {Object} context The current context of the app that the user has when the export menu item was clicked.
- *
- * @returns {Promise}
- */
- ActionHandler.prototype._convertToStory = function _convertToStory(context) {
- /*
- * Steps in convert to story
- * 1. User clicks "Export as a story"
- * 2. User is prompted to select Story type (and template if selecting GJ)
- * 3. User is prompted to choose a location to save, name the story, and open automatically (default) or not
- * 4a. User is automatically brough to story (if option was chosen)
- * 4b. User is shown the success/green toast about the successful conversion
- * 4c. User is shown a dialog if trying to use the same name asking if she wants to overwrite the existing object
- * 4d. User is shown an error/red toast about any error that is returned during the process
- */
- return this._openStoryTypeSelectionDialog(context).then(this._openSaveAsDialog.bind(this));
- };
- /**
- * Setup and display a dialog to the user to allow her to select the Story Navigation Model type
- * and, in the case of Guided Journey, select the layout template type.
- * @private
- *
- * @returns {Promise}
- */
- ActionHandler.prototype._openStoryTypeSelectionDialog = function _openStoryTypeSelectionDialog(context) {
- var _this = this;
- return Promise.all([ClassFactory.loadModule('storytelling/glass/StoryLayoutPickerView'), ClassFactory.loadModule('storytelling/nls/StringResources')]).then(function (modules) {
- var StoryLayoutPickerView = modules[0];
- var stringResources = modules[1];
- return new Promise(function (resolve) {
- var dialogElement = document.createElement('div');
- dialogElement.classList.add('templatePickerDialog');
- var viewOptions = {
- action: function () {
- this._templateSelectDialog.hide();
- this._templateSelectDialog.view.getSelectedLayoutSpec().then(function (_ref) {
- var layout = _ref.layout;
- // have to do layout.layout because layoutpickerview is made to return layouts
- // but we are now using it to return a layout + widgets
- resolve({
- context: context,
- navModel: layout.layout.type
- });
- });
- }.bind(_this)
- };
- _this._templateSelectDialog = new Dialog({
- id: 'selectTemplateTitle',
- title: stringResources.get('selectTemplateLabel'),
- viewClass: StoryLayoutPickerView,
- viewOptions: viewOptions,
- okCallback: viewOptions.action,
- cancelCallback: function cancelCallback() {
- resolve({
- cancelled: true
- });
- },
- buttons: [{
- text: stringResources.get('selectLabel'),
- handler: viewOptions.action,
- type: 'primary',
- defaultId: 'select_button'
- }, 'cancel'],
- showCloseX: true,
- width: '760px'
- });
- _this._templateSelectDialog.open();
- });
- });
- };
- /**
- * @private
- *
- * @param {Object} options An object of required values
- * @param {boolean} [options.cancelled] Set if the user clicks cancel on the export as a story dialog
- * @param {Object} options.context The current context of the application
- * @param {string} options.navModel The navigation model that was selected in the dialog
- */
- ActionHandler.prototype._openSaveAsDialog = function _openSaveAsDialog(options) {
- var _this2 = this;
- if (options.cancelled && options.cancelled === true) {
- return Promise.resolve();
- }
- var context = options.context;
- var navModel = options.navModel;
- var glassContext = context.glassContext;
- var contentView = getContentView(glassContext);
- var dashboardApi = contentView.getDashboardApi();
- return Promise.all([ClassFactory.loadModule('storytelling/glass/ExportToStoryDialog'), ClassFactory.loadModule('storytelling/nls/StringResources'), ClassFactory.loadModule('storytelling-ui/storytelling-ui.min'), this._createStory(dashboardApi, contentView, navModel), this._getAncestors(context, contentView.getBoardId())]).then(function (_ref2) {
- var ExportDialog = _ref2[0],
- stringResources = _ref2[1],
- StorytellingUI = _ref2[2],
- modelObj = _ref2[3],
- ancestors = _ref2[4];
- var modelJson = modelObj.model;
- _this2._exportDialog = new ExportDialog({
- glassContext: glassContext,
- defaultFileName: stringResources.get('newDefaultStoryName', {
- modelName: contentView.boardModel.name
- }),
- service: {
- context: {
- glassContext: glassContext,
- boardModel: modelJson
- },
- export: _this2.exportAsStory.bind(_this2)
- },
- ancestors: ancestors,
- onHide: _this2._clearToast.bind(_this2)
- });
- _this2._exportDialog.open();
- if (modelObj.status.hasOutOfBoundsWidget) {
- _this2._showToast(StorytellingUI, stringResources.get('outOfBoundsWarningMessage'));
- } else if (modelObj.status.hasEmptyExploreCards) {
- _this2._showToast(StorytellingUI, stringResources.get('emptyExploreCardsWarningMessage'));
- }
- });
- };
- ActionHandler.prototype._createStory = function _createStory(dashboardApi, contentView, navModel) {
- var _this3 = this;
- return Promise.all([ClassFactory.loadModule('storytelling/StoryService')]).then(function (_ref3) {
- var StoryService = _ref3[0];
- var storyService = new StoryService({ dashboardApi: dashboardApi });
- return storyService.createStory({
- boardModel: contentView.boardModel,
- layoutController: contentView.boardController.layoutController,
- targetInfo: {
- type: navModel,
- transition: 'none'
- },
- sourceType: _this3.sourceType
- });
- });
- };
- ActionHandler.prototype._showToast = function _showToast(StorytellingUI, message) {
- var toast = React.createElement(StorytellingUI.Toast, {
- contentString: message,
- statusType: 'warning',
- className: 'db-st-export-toast'
- });
- // Parsing this._exportDialog.$el[0] to render is not ideal
- // In works in this case because the toast is added to the body regardless
- ReactDOM.render(toast, this._exportDialog.$el[0]);
- };
- ActionHandler.prototype._clearToast = function _clearToast() {
- this._exportDialog && ReactDOM.unmountComponentAtNode(this._exportDialog.$el[0]);
- };
- /**
- * @private
- */
- ActionHandler.prototype._getAncestors = function _getAncestors(context, id) {
- var ancestors = function ancestors(id) {
- if (id) {
- return context.glassContext.getSvc('.Content').then(function (oContentService) {
- var server_URL = oContentService.getBaseObjectsURL() + '/' + id;
- return oContentService.get(server_URL, { data: { fields: 'ancestors' } });
- });
- } else {
- return Promise.resolve(null);
- }
- };
- return ancestors(id).then(function (result) {
- return result ? result.data[0].ancestors || null : null;
- });
- };
- /**
- * @private
- */
- ActionHandler.prototype._onExportSuccess = function _onExportSuccess(context, loadOnSave, response) {
- var appController = context.glassContext.appController;
- if (loadOnSave) {
- appController.openAppView('story', {
- perspective: 'story',
- content: {
- perspective: 'story',
- objectUrl: response.jqXHR.getResponseHeader('location'),
- isAuthoringMode: appController.getCurrentContentView().isAuthoringMode
- }
- });
- } else {
- return ClassFactory.loadModule('storytelling/nls/StringResources').then(function (stringResources) {
- var perspective = getContentView(context.glassContext).perspective;
- appController.showToast(stringResources.get(perspective + '_export_success'));
- });
- }
- };
- /**
- * Handle the error that was returned when tyring to save the new story.
- * @private
- * @param {Object} errorObject An object from the rejected promise around the ajax.post in _exportAsStoryRequest
- * @returns {Promise} A rejected promise if it was a duplicate error or resolved promise otherwise
- */
- ActionHandler.prototype._onExportError = function _onExportError(errorObject) {
- var errorCode = ErrorUtils.getErrorCode(errorObject.saveRequest);
- if (errorCode === 'cmDuplicateName') {
- return Promise.reject(new BaseError('duplicate', {
- 'isDuplicate': true
- }));
- } else {
- ErrorUtils.showError(errorObject.glassContext, errorObject.saveRequest, errorObject.cmSpec);
- return Promise.resolve();
- }
- };
- /**
- * Send an ajax post request to create a new story with the converted board model
- * @private
- * @see {@link _exportAsStory} for parameter descriptions
- * @param {Object} context
- * @param {string} url
- * @param {string} name
- * @param {boolean} overwrite
- *
- * @returns {Promise} A Promise that will be resolve when the save is complete or rejected if error during save
- */
- ActionHandler.prototype._sendRequest = function _sendRequest(options) {
- var context = options.context;
- var url = options.url;
- var name = options.name;
- var overwrite = options.overwrite;
- var ajaxSvc = context.glassContext.getCoreSvc('.Ajax');
- var spec = context.boardModel;
- if (name) {
- spec.name = name;
- }
- var cmSpec = this._getCMSpec({
- spec: spec,
- context: context
- });
- url = url + (overwrite ? '?updateAction=replace' : '');
- return ajaxSvc.ajax({
- type: 'post',
- url: url,
- contentType: 'application/json',
- processData: false,
- dataType: 'text',
- data: JSON.stringify(cmSpec)
- }).catch(function (errorObject) {
- return Promise.reject(new BaseError('saving story error', {
- cmSpec: cmSpec,
- glassContext: context.glassContext,
- saveRequest: errorObject.jqXHR
- }));
- });
- };
- /**
- * @private
- */
- ActionHandler.prototype._getCMSpec = function _getCMSpec(options) {
- var spec = options.spec;
- var context = options.context;
- var cmSpec = {
- 'defaultName': spec.name,
- 'type': this._getAssetType(context),
- 'specification': JSON.stringify(spec),
- 'deploymentReferences': getContentView(context.glassContext).dashboardApi.getFeature('dataSources.deprecated').getDeploymentReferences(),
- 'iconURI': '#common-catalog',
- 'defaultScreenTip': 'story',
- 'tags': ['story']
- };
- return cmSpec;
- };
- /**
- * @private
- */
- ActionHandler.prototype._getAssetType = function _getAssetType(context) {
- var assetType = 'exploration'; //default asset type
- var content = getContentView(context.glassContext).getContent();
- if (content.options && content.options.config) {
- var config = content.options.config;
- if (config.hasOwnProperty('assetType')) {
- assetType = config.assetType;
- }
- }
- return assetType;
- };
- ActionHandler.prototype._isBoardTypeSupported = function _isBoardTypeSupported(context) {
- var view = getContentView(context.glassContext);
- this.sourceType = view.getDashboardApi && view.getDashboardApi().getType();
- if (this.sourceType === 'dashboard') {
- // Only support tab layout and ignore infographic from dashboard
- return view.boardModel.layout.type === 'tab';
- } else if (this.sourceType === 'explore') {
- return true;
- }
- return false;
- };
- return ActionHandler;
- }();
- return ActionHandler;
- });
- //# sourceMappingURL=ExportAsStory.js.map
|