123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- 'use strict';
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: BI Cloud (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(['require', '../lib/@waca/core-client/js/core-client/ui/core/Class', '../lib/@waca/core-client/js/core-client/utils/Deferred', 'jquery', 'underscore', '../nls/StringResources'], function (require, Class, Deferred, $, _, stringResources) {
- /**
- * A helper that provides the event handlers typically used to add a widget.
- */
- var WidgetAddUIHelper = Class.extend({
- init: function init(options) {
- WidgetAddUIHelper.inherited('init', this, arguments);
- this.dashboardApi = options.dashboardApi;
- this.requireFn = options.requireFn || require;
- this.logger = this.dashboardApi.getGlassCoreSvc('.Logger');
- },
- fetchWidgetList: function fetchWidgetList(url) {
- var _this = this;
- return this.panelAttributes.glassContext.getCoreSvc('.Ajax').ajax({
- url: url,
- // TODO: For some reason Safari on iOS was caching results, force off for now. This shouldn't be required.
- cache: false
- }).then(function (widgets) {
- return _this.fetchRequiredWidgetAttributes(widgets).then(function () {
- return widgets;
- });
- }).catch(function () {
- var msg = stringResources.get('errorLoadingWidgetList');
- return Promise.reject(msg);
- });
- },
- fetchWidgetListFromPerspective: function fetchWidgetListFromPerspective(collectionId, context) {
- var _this2 = this;
- return context.appController.findCollection(collectionId).then(function (collection) {
- var widgets = {
- list: collection ? JSON.parse(JSON.stringify(collection)) : collection
- };
- return _this2.fetchRequiredWidgetAttributes(widgets).then(function () {
- return widgets;
- });
- }).catch(function () {
- var msg = stringResources.get('errorLoadingWidgetList');
- return Promise.reject(msg);
- });
- },
- fetchRequiredWidgetAttributes: function fetchRequiredWidgetAttributes(widgetList) {
- var _this3 = this;
- var deferredArray = [];
- _.each(widgetList.list, function (w) {
- w.options = w.options || {};
- w.options.ext = _this3._hasExtensionTemplate(w);
- // extension templates are already localized from the perspective level
- if (!w.title && w.name) {
- w.title = w.options.ext ? w.name : stringResources.get(w.name);
- }
- if (!w.name) {
- w.name = w.title;
- }
- if (w.options.templatePath && !w.options.template) {
- deferredArray.push(_this3._loadTemplate(w));
- } else if (w.options.imageLink) {
- deferredArray.push(_this3._loadImage(w));
- } else {
- // ensure the deferred array maps with the widget list
- deferredArray.push(true);
- }
- if (w.url) {
- w.getEntries = _this3.fetchWidgetList.bind(_this3, w.url);
- }
- });
- if (deferredArray.length) {
- return Promise.all(deferredArray).then(function (isLoaded) {
- // filter out any widgets that has failed to load
- widgetList.list = _.filter(widgetList.list, function (w, i) {
- return isLoaded[i];
- });
- });
- }
- return Promise.resolve();
- },
- _loadImage: function _loadImage(widget) {
- return new Promise(function (resolve) {
- // eslint-disable-next-line no-undef
- var img = new Image();
- img.onload = function () {
- resolve(true);
- };
- img.onerror = function () {
- resolve(false);
- };
- img.src = widget.options.imageLink;
- });
- },
- _loadTemplate: function _loadTemplate(widget) {
- var _this4 = this;
- var cdnUrl = '';
- var extensionTemplate = this._hasExtensionTemplate(widget);
- if (!extensionTemplate) {
- cdnUrl = this.panelAttributes.cdnUrl || '';
- }
- return new Promise(function (resolve) {
- _this4.requireFn(['text!' + cdnUrl + widget.options.templatePath], function (template) {
- if (extensionTemplate) {
- var xml = $.parseXML(template);
- var svgRoot = $(xml).find('svg');
- if (svgRoot.length > 0) {
- if (typeof widget.options.viewBox === 'undefined') {
- // respect the viewbox defined in the svg
- var viewbox = svgRoot.attr('viewBox');
- if (viewbox) {
- widget.options.viewBox = viewbox;
- widget.options.previewBox = widget.options.viewBox;
- } else {
- // create a viewbox based on the size
- var width = parseInt(svgRoot.attr('width'), 10) || 100;
- var height = parseInt(svgRoot.attr('height'), 10) || 100;
- widget.options.viewBox = '0 0 ' + width + ' ' + height;
- widget.options.previewBox = '-10 -10 ' + width * 1.2 + ' ' + height * 1.2;
- }
- }
- template = '';
- var content = svgRoot.children();
- _.each(content, function (node) {
- // eslint-disable-next-line no-undef
- template += new XMLSerializer().serializeToString(node);
- });
- }
- }
- widget.options.template = template;
- // resolve as succeeded
- resolve(true);
- }, function (error) {
- _this4.logger.error('Failed to load widget', error);
- // resolve as failed - don't reject since we want continue with other successful widgets
- resolve(false);
- });
- });
- },
- _hasExtensionTemplate: function _hasExtensionTemplate(widget) {
- if (widget && widget.options) {
- var ext = new RegExp('^v[0-9]+/ext/.+$');
- return ext.test(widget.options.templatePath);
- }
- return false;
- },
- _getDefaultSpec: function _getDefaultSpec(Widget, widget) {
- if (Widget.getDefaultSpec) {
- if (widget.options) {
- widget.options.dashboardApi = this.dashboardApi;
- }
- /** getDefaultSpec() is expected to return a promise that will be resolved with the default spec. for the widget. */
- return Widget.getDefaultSpec(widget.name, widget.options);
- } else {
- var copyDefaultSpec = widget.defaultSpec ? JSON.parse(JSON.stringify(widget.defaultSpec)) : {};
- return Promise.resolve(copyDefaultSpec);
- }
- },
- _addFillAndBorderToAvatarIfNeeded: function _addFillAndBorderToAvatarIfNeeded(Widget, avatar, spec) {
- if (Widget.addFillAndBorderToAvatarIfNeeded) {
- Widget.addFillAndBorderToAvatarIfNeeded(avatar, spec);
- }
- },
- addWidgetBySelection: function addWidgetBySelection(widget, ev, options) {
- var _this5 = this;
- options = options || {};
- if (ev.gesture) {
- // prevent simulated click if we have a touch gesture.
- ev.gesture.preventDefault();
- }
- var sWidget = widget.widget;
- var dndManagerFeature = this.dashboardApi.getFeature('DashboardDnd.internal');
- return new Promise(function (resolve) {
- var api = _this5.dashboardApi.getCanvas();
- var onAddDone = function onAddDone(id) {
- if (id) {
- api.selectWidget(id, {
- isTouch: ev.type === 'tap',
- options: options.selectOptions ? options.selectOptions : undefined
- });
- }
- // Computers click very quickly (during functional tests). This call to
- // resetDragging() needs to happen *after* the call to startDrag() in
- // addWidgetByDrag, or else the drag started there won't be cancelled
- // and you can end up with a dragging widget hanging on the mouse after
- // clicking on a widget in a panel.
- dndManagerFeature.resetDragging();
- resolve(id);
- };
- // we are adding a dashboard fragment
- if (widget.fragment) {
- // add a copy of the fragment
- var id = api.addFragment({ model: JSON.parse(JSON.stringify(widget.fragment)) });
- onAddDone(id);
- return;
- }
- _this5.requireFn([sWidget], function (Widget) {
- var id = null;
- if (!api.hasMaximizedWidget()) {
- _this5._getDefaultSpec(Widget, widget).then(function (spec) {
- // Remove properties piggy-backed on spec
- spec.model.avatarHtml = undefined;
- spec.model.visTypeLocked = true; //On create widget of specific type, lock that type in
- var content = {
- spec: spec.model
- };
- if (spec.layoutProperties) {
- //liveWidget does not have layoutProperties in defaultSpec
- content.layout = spec.layoutProperties.style;
- }
- var transactionApi = _this5.dashboardApi.getFeature('Transaction');
- var transactionToken = transactionApi.startTransaction();
- api.addContent(content, transactionToken).then(function (content) {
- onAddDone(content.getId());
- resolve(content.getId());
- }).finally(transactionApi.endTransaction.bind(transactionApi, transactionToken));
- }).catch(function (e) {
- _this5.logger.error(e);
- resolve(id);
- });
- } else {
- resolve(id);
- }
- });
- });
- },
- addWidgetByDrag: function addWidgetByDrag(widget, ev) {
- var _this6 = this;
- if (widget.fragment || widget.widget) {
- ev.stopPropagation();
- var dndManagerFeature = this.dashboardApi.getFeature('DashboardDnd.internal');
- return new Promise(function (resolve, reject) {
- var prepareDrag = function prepareDrag(type, dropInfo, ev, widget, spec, avatarStyle) {
- var avatar = $('<div>');
- var moveX, moveY;
- moveX = moveY = ev.showAvatarImmediately ? 0 : 20;
- avatar.addClass('avatar');
- avatar.addClass('widget');
- // if avatarHtml is provided, it should take precedence
- if (spec) {
- if (spec.model.avatarHtml) {
- avatar.html(spec.model.avatarHtml);
- // Don't store the avatar HTML
- spec.model.avatarHtml = undefined;
- } else if (spec.model.content) {
- avatar.html(spec.model.content);
- }
- avatar.addClass(spec.model.type + 'Widget');
- }
- if (widget) {
- _this6._addFillAndBorderToAvatarIfNeeded(widget, avatar, spec);
- }
- var style = avatarStyle || spec && spec.layoutProperties && spec.layoutProperties.style;
- if (style) {
- avatar.css(style);
- }
- // TODO: having widgetType and widgetSpec seems redundant since this information is is in the dropInfo
- // We need to revisit and cleanu the DnD payload
- var dragInfo = {
- event: ev,
- type: type,
- data: dropInfo,
- widgetSpec: spec || null,
- widgetType: spec && spec.model.type || null,
- avatar: avatar,
- moveXThreshold: moveX,
- moveYThreshold: moveY,
- showAvatarImmediately: ev.showAvatarImmediately || false
- };
- return dragInfo;
- };
- // wW are dragging a fragment
- // piggy back on the pin drag payload since it uses a fragment.
- // TODO: ideally we should make the fragment drag to be generic and not related to just pins.
- var fragment = widget.fragment;
- if (fragment) {
- var dropInfo = {
- operation: 'new',
- pinSpec: {
- contentType: 'boardFragment',
- content: JSON.parse(JSON.stringify(fragment))
- }
- };
- var dragInfo = prepareDrag('pin', dropInfo, ev, null, null, fragment.layout && fragment.layout.style);
- dndManagerFeature.startDrag(dragInfo);
- resolve(dragInfo);
- return;
- }
- _this6.requireFn([widget.widget], function (Widget) {
- _this6._getDefaultSpec(Widget, widget).then(function (spec) {
- //On create widget of specific type, lock that type in
- spec.model.visTypeLocked = true;
- var dropInfo = _.extend(spec, {
- operation: 'new'
- });
- var dragInfo = prepareDrag('widget', dropInfo, ev, Widget, spec);
- dndManagerFeature.startDrag(dragInfo);
- resolve(dragInfo);
- }).catch(reject);
- });
- });
- }
- return Promise.reject();
- }
- });
- return WidgetAddUIHelper;
- });
- //# sourceMappingURL=WidgetAddUIHelper.js.map
|