123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>JSDoc: Source: glass/views/ShareView.js</title>
- <script src="scripts/prettify/prettify.js"> </script>
- <script src="scripts/prettify/lang-css.js"> </script>
- <!--[if lt IE 9]>
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
- <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
- <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
- </head>
- <body>
- <div id="main">
- <h1 class="page-title">Source: glass/views/ShareView.js</h1>
-
-
- <section>
- <article>
- <pre class="prettyprint source linenums"><code>/**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: Collaboration
- * (C) Copyright IBM Corp. 2017, 2020
- *
- * US Government Users Restricted Rights - Use, duplication or disclosure
- * restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define([
- 'underscore',
- 'jquery',
- 'react',
- 'react-dom',
- 'ca-ui-toolkit',
- '../../lib/@waca/core-client/js/core-client/ui/AccessibleView',
- '../../lib/@waca/core-client/js/core-client/utils/BrowserUtils',
- '../../lib/@waca/core-client/js/core-client/utils/DateTimeUtils',
- '../../nls/StringResources',
- '../../api/sharing/ShareController',
- '../utils/GlassUtil'
- ], function (_, $, React, ReactDOM, Toolkit, AccessibleView, BrowserUtils, DateTimeUtils, StringResources, ShareController, GlassUtil) {
- 'use strict';
- const SHARE_VIEW_CLASS = 'share-view ba-collab-fill-space ba-theme-default';
- var ShareView = AccessibleView.extend( /** @lends ShareView */ {
- /**
- * @desc Constructor for ShareView.
- * @constructs ShareView
- * @extends AccessibleView
- * @public
- * @param options {Object} Options
- * @param options.glassContext {Object} The glass context
- */
- init: function (options) {
- _.extend(options, {
- enableTabLooping: true,
- className: 'ba-collab-fill-space'
- });
- ShareView.inherited('init', this, arguments);
- this.glassContext = options.glassContext;
- this.shareController = new ShareController(_.extend({
- errorHandler: this.displayError.bind(this),
- slideout: this.slideout
- }, options));
- this._panel = null;
- this.link = options.slideout.content.link;
- this.embedVisible = this._isEmbedEnabled() && options.slideout.content.embedVisible !== false;
- this.imageVisible = !!options.slideout.content.imageVisible;
- this._eventHandlers = this.slideout && [
- this.slideout.on('show', this.onSlideShow.bind(this)),
- this.slideout.on('hide', this.onSlideHide.bind(this))
- ];
- this._logger = options.logger;
- try {
- this._instrumentationService = this.glassContext.getCoreSvc('.Instrumentation');
- } catch (e) {
- // just swallow it if the instrumentation service isn't available for some reason.
- void (e);
- }
- this.onSlideShow(); // event is not being called when slide is opened for the first time.
- this.reactContainer = null;
- this.shareStore = null;
- this.imageStore = null;
- },
- /**
- * It will be called after slideout is shown
- * @callback
- */
- setFocus: function () {
- if (this._panel) {
- this._panel.setFocus();
- }
- },
- _onIframeFocus: function (e) {
- e.stopPropagation();
- const activeElement = document.activeElement;
- if (activeElement instanceof HTMLIFrameElement
- && !activeElement.classList.contains('cke_panel_frame')
- && !this.$el.get(0).contains(activeElement)
- && this.slideout.isOpen()) {
- this.close();
- }
- },
- onSlideShow: function () {
- var $iframe = $('iframe');
- if ($iframe.length > 0 && this.slideout) {
- this._onIframeFocusFunc = this._onIframeFocus.bind(this);
- $(window).on('blur', this._onIframeFocusFunc);
- }
- if (this._panel) {
- const assetStrings = this.shareController.getAssetStrings();
- this.shareStore.setAssetType(assetStrings.assetType);
- this.shareStore.setAssetTitle(assetStrings.assetTitle);
- this.shareStore.setIsDirty(this._isDirty());
- return Promise.all([ this.refreshLink(), this.refreshIncludeImage() ])
- .then(results => {
- const link = results[0];
- // if cannot send, don't need to get connectors
- if (!this.canSend()) {
- this.shareStore.setConnectors([]);
- this.imageStore.setImageLoaded(false);
- return link;
- }
- // refresh connectors
- return this.getConnectors()
- .then((connectors) => {
- this.shareStore.setConnectors(connectors);
- this.imageStore.setImageLoaded(false);
- return link;
- });
- });
- }
- return Promise.resolve(null);
- },
- onSlideHide: function () {
- var $iframe = $('iframe');
- if ($iframe.length > 0 && this.slideout && this._onIframeFocusFunc) {
- this._onIframeFocusFunc = null;
- $(window).off('blur', this._onIframeFocusFunc);
- }
- return this.shareController.leaveShareState();
- },
- /**
- * Sets the current perspective's link URL.
- * @param link
- */
- setLink: function (link) {
- if (this.shareStore) {
- this.shareStore.setLink(link);
- }
- },
- /**
- * Refresh the current perspective's link URL.
- * @instance
- * @returns {Promise} resolved as an object that contains shareUrl and embedUrl
- */
- refreshLink: function () {
- return new Promise((resolve, reject) => {
- if (this.link) {
- this.setLink(this.link);
- resolve(this.link);
- } else {
- this.shareController.getLink(this.glassContext)
- .then((link) => {
- this.setLink(link);
- resolve(link);
- })
- .catch((error) => {
- this.setLink(null);
- reject(error);
- });
- }
- });
- },
- /**
- * Fetch user's configured product locale and Product version.
- * @instance
- * @returns {Promise} with the user's browser language.
- */
- getConfig: function () {
- // The passed in version number is of the form "11.1 RX", but the knowledge center
- // uses the form "11.1.X". Until glass provides consistent versioning with the knowlege
- // center, we will hard-code the version here.
- return this.glassContext.getSvc('.UserProfile')
- .then(userProfile => {
- const language = userProfile.preferences.productLocale ? userProfile.preferences.productLocale : 'en';
- return {
- language,
- version: '11.1.0'
- };
- });
- },
- /**
- * Capture the current perspective's screenshot image.
- * @instance
- * @returns {Promise} with an image string as URL.
- */
- refreshImage: function () {
- return new Promise((resolve, reject) => {
- if (this._panel && this._panel.state.connector) {
- if (this._panel.state.connector.isImageSupported()) {
- this.shareController
- .getScreenshot(this.glassContext)
- .then((item) => {
- var img = new Image();
- img.onload = () => {
- this.imageStore.setImage(item.image, item.label, img.width, img.height);
- resolve(item);
- };
- img.src = item.image;
- })
- .catch((error) => {
- this.glassContext.showToast(StringResources.get('error_no_screenshot'), {
- type: 'error'
- });
- this.imageStore.setImage('', '', 0, 0);
- reject(error);
- });
- } else {
- var errorTxt = StringResources.get('error_screenshot_unsupported');
- this.glassContext.showToast(errorTxt, {
- type: 'warning'
- });
- reject(new Error(errorTxt));
- }
- } else {
- resolve(); // We're not trying to load a screenshot yet.
- }
- });
- },
- /**
- * Returns if the content supports export to pdf
- * @returns Promise
- */
- canExportToPDF: function () {
- return this.shareController.canExportToPDF(this.glassContext).then((result) => {
- // when link is set, we were called from My/Team Content navigation.
- return result && !this.link && this.features.includes(GlassUtil.feature.EXPORT);
- });
- },
- /**
- * Returns whether "Include image" option should be visible or hidden.
- *
- * @returns {Promise} that resolves to a boolean value.
- */
- includeImage: function () {
- if (!this.imageVisible) {
- return Promise.resolve(false);
- }
- // Authoring perspective supports image capture but requires an extra check
- // of the current report format. Image capture should be enabled for HTML reports;
- // disabled for PDF reports.
- return this.shareController.canCaptureImage(this.glassContext);
- },
- /**
- * Update "Include image" flags in the ImageStore.
- *
- * One use case where it's necessary:
- * 1. Run HTML report.
- * 2. Open Share / Email panel ==> "Include image" should be enabled
- * 3. Hide Share slideout.
- * 4. Run the same report as PDF in the report viewer.
- * 5. Open Share panel ==> "Include image" should be disabled.
- */
- refreshIncludeImage: function() {
- if (!this.imageStore) {
- return Promise.resolve();
- }
- return this.includeImage().then(result => {
- this.imageStore.setShowIncludeImage(result);
- return result;
- });
- },
- _checkLinkShareable: function (link) {
- var pathQuery = 'pathRef';
- if (!!this.type && this.type.assetType === 'folder') {
- pathQuery = 'folder';
- }
- return !!(link && link.shareUrl && link.shareUrl.search(pathQuery + '=.my_folders') === -1);
- },
- isLinkShareable: function (link) {
- return this._isLinkEnabled() && this._checkLinkShareable(link);
- },
- canSend: function () {
- return this._isSendEnabled() && (!this.link ? true : this._checkLinkShareable(this.link));
- },
- /**
- * Render the view.
- * @instance
- */
- render: function () {
- // tell html2canvas to ignore our panel when capturing the image.
- this.$el.closest('.flyoutPane').attr('data-html2canvas-ignore', 'true');
- // 1. render a spinner
- ReactDOM.render(React.createElement(Toolkit.ProgressIndicator, {
- className: 'initialCollaborationSlideoutSpinner',
- id: 'initialCollaborationSlideoutSpinner',
- size: 'large',
- style: { left: '50%', top: '50%', position: 'absolute', transform: 'translate(-50%, -50%)' }
- }), this.$el.get(0));
- return new Promise(function (resolve, reject) {
- // 2. load modules
- require(['collaboration/canvaseditor/CanvasEditor', 'collaboration-ui/collaboration-ui.min', 'ckeditor'], function (CanvasEditor, CollaborationUI) {
- // 3. get language and version, connectors and more
- Promise.all([this.getConfig(), this.getConnectors(), this.canExportToPDF(), this.refreshLink(), this.includeImage()])
- .then(([config, connectors, canExport, link, showIncludeImage]) => {
- // 4. remove the spinner
- ReactDOM.unmountComponentAtNode(this.$el.get(0));
- // 5. create the stores
- this.createStores(
- CollaborationUI.ShareStore,
- CollaborationUI.ImageStore,
- CanvasEditor,
- connectors,
- config,
- canExport,
- link,
- showIncludeImage);
- // 6. render react
- this.renderReact(CollaborationUI.CollaborationPanel);
- // all done!
- resolve();
- })
- .catch(reject);
- }.bind(this));
- }.bind(this));
- },
- _isSendEnabled: function () {
- return this.features.includes(GlassUtil.feature.SEND);
- },
- _isLinkEnabled: function () {
- return this.features.includes(GlassUtil.feature.LINK);
- },
- _isEmbedEnabled: function () {
- return this.features.includes(GlassUtil.feature.EMBED);
- },
- _isEmailLinkEnabled: function () {
- return this.features.includes(GlassUtil.feature.EMAIL_LINK) && this.glassContext.hasCapability('canIncludeLinkInEmail');
- },
- _isDirty: function() {
- return this.glassContext.currentAppView.isDirty();
- },
- createStores: function (ShareStore, ImageStore, CanvasEditor, connectors, config, canExport, link, showIncludeImage) {
- const assetStrings = this.shareController.getAssetStrings();
- const shareStore = ShareStore.create({
- isIE11: BrowserUtils.isIE11(),
- language: config.language,
- version: config.version,
- assetTitle: assetStrings.assetTitle,
- assetType: assetStrings.assetType,
- isDirty: this._isDirty(),
- objectType: this.objectType || null,
- objectId: this.objectId || null
- }, {
- CanvasEditor,
- glassContext: this.glassContext,
- $root: this.$el,
- isLinkShareable: this.isLinkShareable.bind(this),
- send: this.send.bind(this),
- generatePDF: this.generatePDF.bind(this),
- displayError: this.displayError.bind(this),
- instrument: this.instrument.bind(this),
- features: this.features,
- glassFeature: GlassUtil.feature,
- dateTimeUtils: DateTimeUtils
- });
- shareStore.enableSend(this._isSendEnabled());
- shareStore.enableLink(this._isLinkEnabled());
- shareStore.enableEmailLink(this._isEmailLinkEnabled());
- shareStore.enableEmbed(this._isEmbedEnabled());
- shareStore.enableExport(canExport);
- shareStore.setConnectors(connectors);
- shareStore.setLink(link);
- this.shareStore = shareStore;
- const imageStore = ImageStore.create({
- showIncludeImage: showIncludeImage,
- includeImage: showIncludeImage,
- image: '',
- imageLoaded: false,
- imageLabel: '',
- imageWidth: 0,
- imageHeight: 0
- }, {
- refreshImage: this.refreshImage.bind(this)
- });
- this.imageStore = imageStore;
- },
- createReactPanel: function (CollaborationPanel, options) {
- this._panel = ReactDOM.render(React.createElement(CollaborationPanel, options), this.reactContainer);
- },
- renderReact: function (CollaborationPanel) {
- const $container = $(`<div class="${SHARE_VIEW_CLASS}" tabIndex="-1"></div>`).appendTo(this.$el);
- this.enableLooping($container);
- const options = {
- shareStore: this.shareStore,
- imageStore: this.imageStore,
- nls: StringResources.get,
- panel: 'main',
- cancel: this.close.bind(this),
- embedVisible: this.embedVisible,
- contentMenuShare: !!this.link
- };
- // render the view with options
- this.reactContainer = $container.get(0);
- this.createReactPanel(CollaborationPanel, options);
- this.$el.on('escapeaction', (event) => {
- event.preventDefault();
- event.stopPropagation();
- });
- // The slideout has 'transition' css in its root DOM element, and it relies on these events to calculate animation.
- // Stop propagation to avoid issues.
- var animEvents = 'transitionend webkitTransitionEnd oTransitionEnd';
- $(this.reactContainer).off(animEvents).on(animEvents, function (event) {
- event.stopPropagation();
- });
- },
- generatePDF: function (pageSize, includeFilter) {
- if (this.shareStore && this.shareStore.canExport) {
- this.shareController.exportToPDF(this.glassContext, pageSize, includeFilter);
- }
- },
- instrument: function (action, shareType) {
- if (this._instrumentationService && this._instrumentationService.enabled) {
- return this.shareController.getInstrumentation(this.glassContext)
- .then((event) => {
- event.action = action;
- event['custom.shareType'] = shareType;
- event.type = 'Shared Object';
- event.objectType = event.objectType || this.objectType;
- // If neither of those worked, try to get the type from glass.
- if (!event.objectType && typeof this.glassContext.getCurrentContentView === 'function') {
- event.objectType = this.glassContext.getCurrentContentView().getType();
- }
- event.milestoneName = `${action}_${event.objectType}`;
- this._instrumentationService.track(event);
- });
- }
- return Promise.resolve();
- },
- getConnectors: function () {
- // don't need to load connectors if cannot send
- if (!this.canSend()) {
- return Promise.resolve([]);
- }
- return this.shareController.getConnectors()
- .catch(function (error) {
- if (this._logger) {
- this._logger.error('Error fetching connectors: ' + error);
- }
- this.glassContext.showToast(StringResources.get('error_retrieving_platforms'), {
- type: 'error'
- });
- throw error;
- }.bind(this));
- },
- /**
- * Sends the message.
- * @instance
- * @param {object} payload
- * @param {object} payload.connector
- * @param {object} payload.data
- * @returns {Promise}
- */
- send: function (payload) {
- return this.shareController.send(payload.connector, payload.data)
- .then((result) => {
- // success
- void (result);
- const message = (payload.type === 'email') ? StringResources.get('toast_success_email') : StringResources.get('toast_success', {
- connector: payload.connector.getLabel()
- });
- this.glassContext.showToast(message, { type: 'success' });
- }).then(() => this.close());
- },
- /**
- * Close the panel.
- * @instance
- * @returns {Promise}
- */
- close: function () {
- return this.shareController.close()
- .then(function () {
- return this.slideout.hide({
- force: true,
- hideOnly: this.slideout.hideOnly
- });
- }.bind(this))
- .then(function () {
- var launchPoint = this.getLaunchPoint();
- if (launchPoint) {
- $(launchPoint).focus();
- }
- }.bind(this));
- },
- /**
- * Display errors as toast message.
- * @instance
- * @param {object} error
- * @throws {error}
- */
- displayError: function (error) {
- var msg = error.message;
- if (error.connector) {
- const connectorType = error.connector.getType();
- var toastStringId = (connectorType === 'email') ? 'toast_failure_email' : 'toast_failure';
- var toastMessageData = {
- connector: error.connector.getLabel(),
- error: error.message
- };
- if (error.showContactAdmin) {
- toastStringId = (connectorType === 'email') ? 'toast_failure_detailed_email' : 'toast_failure_detailed';
- toastMessageData.contactAdmin = StringResources.get('message_contact_administrator');
- }
- msg = StringResources.get(toastStringId, toastMessageData);
- }
- this.glassContext.showToast(msg, {
- type: 'error'
- });
- throw error;
- },
- /**
- * Cleaning up events
- * @override
- */
- remove: function () {
- if (this._eventHandlers) {
- this._eventHandlers.forEach(function (handler) {
- if (handler) {
- handler.remove();
- }
- });
- }
- if (this.reactContainer) {
- ReactDOM.unmountComponentAtNode(this.reactContainer);
- }
- }
- });
- return ShareView;
- });
- </code></pre>
- </article>
- </section>
- </div>
- <nav>
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ConnectorBase.html">ConnectorBase</a></li><li><a href="Connectors.html">Connectors</a></li><li><a href="EmailClient.html">EmailClient</a></li><li><a href="EmailConnector.html">EmailConnector</a></li><li><a href="MSTeamsAuth.html">MSTeamsAuth</a></li><li><a href="MSTeamsClient.html">MSTeamsClient</a></li><li><a href="MSTeamsConnector.html">MSTeamsConnector</a></li><li><a href="ShareableItems.html">ShareableItems</a></li><li><a href="ShareController.html">ShareController</a></li><li><a href="ShareView.html">ShareView</a></li><li><a href="SlackAuth.html">SlackAuth</a></li><li><a href="SlackClient.html">SlackClient</a></li><li><a href="SlackConnector.html">SlackConnector</a></li></ul><h3>Interfaces</h3><ul><li><a href="ShareInterface.html">ShareInterface</a></li></ul>
- </nav>
- <br class="clear">
- <footer>
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed May 25 2022 13:54:53 GMT+0000 (UTC)
- </footer>
- <script> prettyPrint(); </script>
- <script src="scripts/linenumber.js"> </script>
- </body>
- </html>
|