123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- 'use strict';
- /**
- * Licensed Materials - Property of IBM
- *
- * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2014, 2019, 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/View', '../../app/nls/StringResources', 'jquery', 'underscore', '../../lib/@waca/core-client/js/core-client/utils/Utils', 'text!./templates/LayoutPickerView.html', 'text!../layout/templates/listing.json', '../../lib/@waca/core-client/js/core-client/utils/Deferred', '../../lib/@waca/core-client/js/core-client/ui/KeyCodes', '../../lib/@waca/core-client/js/core-client/ui/Menu', '../../lib/@waca/core-client/js/core-client/utils/ContentFormatter', '../../lib/@waca/dashboard-common/dist/ui/dialogs/MessageBox', '../../lib/@waca/dashboard-common/dist/lib/@ba-ui-toolkit/ba-graphics/dist/icons-js/overflow-menu--horizontal_16', '../../lib/@waca/dashboard-common/dist/lib/@ba-ui-toolkit/ba-graphics/dist/illustrations-js/connect-images_128'], function (BaseView, stringResources, $, _, Utils, template, templateListing, Deferred, KeyCodes, Menu, ContentFormatter, MessageBox, contextMenuIcon, thumbnailPlaceholderIcon) {
- var LayoutPickerView = BaseView.extend({
- templateString: template,
- events: {
- 'primaryaction .layoutTemplateItem': 'onSelect',
- 'dblclick .layoutTemplateItem': 'onDoubleClick',
- 'keydown .layoutTemplateItem': 'onKeyDown',
- 'click .selected .layoutContextMenuButton': 'onContextMenuButtonClick'
- },
- init: function init(options) {
- options = options || {};
- LayoutPickerView.inherited('init', this, arguments);
- this.stringResources = options.stringResources || stringResources;
- var templates = options.templateListing || templateListing;
- this._showContextMenu = options.showContextMenu;
- this._dashboardTemplatesApi = options.dashboardTemplatesApi;
- // process the templates
- var defaultTemplates = this._processTemplates(JSON.parse(templates));
- // remove items from defaultTemplates that were passed in the excludeTemplates array
- if (options.excludeTemplates) {
- var newList = defaultTemplates.templates.filter(function (element) {
- return !_.contains(options.excludeTemplates, element.name);
- });
- defaultTemplates.templates = newList;
- }
- _.extend(this, _.defaults(options, defaultTemplates));
- this._thumbnailCache = [];
- this._addCustomTemplates(options.customTemplates);
- this._whenReady = new Deferred();
- this.whenReady = this._whenReady.promise;
- },
- _addCustomTemplates: function _addCustomTemplates(customTemplates) {
- var _this = this;
- (customTemplates || []).forEach(function (customTemplate) {
- _this.templates.push({
- label: customTemplate.defaultName,
- ariaLabel: customTemplate.defaultName,
- navigationTemplates: 'custom',
- location: customTemplate.location,
- isSelected: false,
- name: customTemplate.id,
- type: 'custom'
- });
- });
- },
- /**
- * This function takes the template object and sorts the array of templates so that the ones with
- * descriptions are on top as well as translates any labels and descriptions.
- *
- * @param templateListObj: Template object to sort.
- * @private
- * @returns Object: the sorted template object.
- **/
- _processTemplates: function _processTemplates(templateListObj) {
- var templateList = templateListObj.templates;
- var aWithDesc = [];
- var aWithoutDesc = [];
- for (var i = 0; i < templateList.length; i++) {
- // get the next template object
- var template = templateList[i];
- // translate the label
- if (template.label) {
- template.label = this.stringResources.get(template.label);
- }
- if (template.name) {
- template.ariaLabel = this.stringResources.get(template.name);
- }
- // sort by description into separate arrays
- if (template.description) {
- // translate the description and add to the array
- template.description = this.stringResources.get(template.description);
- aWithDesc.push(template);
- } else {
- // no description so just push to that array
- aWithoutDesc.push(template);
- }
- }
- return {
- 'templates': aWithDesc.concat(aWithoutDesc)
- };
- },
- render: function render() {
- this.$el.empty().addClass('layoutPickerView').attr('role', 'listbox').attr('aria-multiselectable', 'false').html(this.dotTemplate(this));
- this.filterTemplates();
- this.generatePreviews();
- },
- onSelect: function onSelect(event) {
- if (event.type === 'keydown' && event.keyCode === 32) {
- // keydown and spacebar
- // Stops the scroll bar from scrolling the page
- event.preventDefault();
- }
- if ((event.type === 'keyup' || event.type === 'keydown') && event.keyCode !== 13 && event.keyCode !== 32) {
- // ignore anything other than enter or space
- return;
- } else {
- event.stopPropagation();
- if (event.keyCode === 13 && $(event.currentTarget).hasClass('selected')) {
- // if the layout was already selected, enter key submits the layout form
- this.action();
- } else {
- this.selectLayout(event.currentTarget.dataset.id);
- if (_.isFunction(this.selectAction)) {
- this.selectAction(event);
- }
- }
- }
- },
- onDoubleClick: function onDoubleClick(event) {
- this.onSelect(event);
- this.action();
- },
- /**
- Enter and Space calling stopPropagation is a very specific fix for defect 255098. Solution with the least risk.
- *call stop propagation when Enter or Space is clicked, so that BaseBoardView.onKeyDown is not called
- *Those are the keys that trigger primaryaction
- *TODO: Please revisit after Endor release
- **/
- onKeyDown: function onKeyDown(event) {
- var items = this.$('.layoutEntry .layoutTemplateItem:not(.filtered)');
- var focusedItem = this.$('.layoutEntry .layoutTemplateItem[tabindex=0]');
- var focusIndex = items.index(focusedItem);
- switch (event.keyCode) {
- case KeyCodes.DOWN_ARROW:
- case KeyCodes.RIGHT_ARROW:
- focusIndex++;
- if (focusIndex >= items.length) {
- focusIndex = items.length - 1;
- }
- break;
- case KeyCodes.UP_ARROW:
- case KeyCodes.LEFT_ARROW:
- focusIndex--;
- if (focusIndex < 0) {
- focusIndex = 0;
- }
- break;
- case KeyCodes.HOME:
- focusIndex = 0;
- break;
- case KeyCodes.END:
- focusIndex = items.length - 1;
- break;
- case KeyCodes.ENTER:
- case KeyCodes.SPACE:
- event.stopPropagation();
- return;
- default:
- return; //For non-matched keys, stop processing immediately.
- }
- //Update tabindex and focus
- event.preventDefault();
- focusedItem.attr('tabindex', -1);
- items.eq(focusIndex).attr('tabindex', 0).focus();
- },
- setNavigationTemplate: function setNavigationTemplate(navTemplate, description) {
- var _this2 = this;
- var result = void 0;
- var animate = this.navTemplate;
- this.navTemplate = navTemplate;
- if (!animate) {
- this.setLabel();
- this.setFooter(description);
- this.filterTemplates();
- result = Promise.resolve();
- } else {
- // TODO: Probably shouldn't use jquery animation anymore. Switch to CSS
- var duration = 300;
- // show some animation if we are switching to a different navigation template
- result = new Promise(function (resolve, reject) {
- try {
- _this2.$el.fadeOut({
- complete: function complete() {
- _this2.setLabel();
- _this2.setFooter(description);
- _this2.filterTemplates();
- _this2.$el.fadeIn({
- complete: function complete() {
- _this2.checkSelection();
- resolve();
- },
- duration: duration
- });
- },
- duration: duration
- });
- } catch (error) {
- reject(error);
- }
- });
- }
- return result;
- },
- setLabel: function setLabel() {
- if (!this.disableHeaderSection) {
- this.layoutLabel = this.stringResources.get(this.navTemplate + 'LayoutLabel');
- var $header = this.$('.layoutHeader');
- $header.text(this.layoutLabel);
- var $view = $header.parent('.layoutPickerView');
- $view.attr('aria-label', this.stringResources.get('selectTemplateLabel'));
- }
- },
- setFooter: function setFooter(description) {
- this.$('.layoutFooter').text(description);
- },
- filterTemplates: function filterTemplates() {
- var posInSet = 1;
- var setSize = 0;
- _.each(this.templates, function (template) {
- var node = this.$('*[data-id=' + template.name + ']');
- if (template.navigationTemplates && template.navigationTemplates.indexOf(this.navTemplate) === -1) {
- node.addClass('filtered');
- node.closest('.layoutEntry').css('display', 'none').find('.layoutTemplateItem').attr('aria-posinset', null);
- if (node.hasClass('selected')) {
- node.removeClass('selected');
- }
- } else {
- node.removeClass('filtered');
- node.closest('.layoutEntry').css('display', '').find('.layoutTemplateItem').attr('aria-posinset', posInSet);
- setSize++;
- posInSet++;
- }
- }.bind(this));
- this.$('.layoutTemplateItem').attr('aria-setsize', setSize);
- this.checkSelection();
- },
- checkSelection: function checkSelection() {
- if (this.$('.selected:not(.filtered)').length === 0) {
- var firstTemplate, template;
- for (var i = 0; i < this.templates.length; i++) {
- template = this.templates[i];
- if (!template.navigationTemplates || template.navigationTemplates.indexOf(this.navTemplate) !== -1) {
- firstTemplate = template.name;
- break;
- }
- }
- this.selectLayout(firstTemplate);
- }
- },
- getNumberOfPossibleTemplates: function getNumberOfPossibleTemplates() {
- var navTemplate = this.navTemplate;
- var count = 0;
- _.each(this.templates, function (template) {
- if (!template.navigationTemplates || template.navigationTemplates.indexOf(navTemplate) !== -1) {
- count++;
- }
- });
- return count;
- },
- selectLayoutNode: function selectLayoutNode(node) {
- var $selected = this.$('.selected');
- $selected.attr('aria-checked', false).attr('tabindex', -1);
- $selected.removeClass('selected');
- $(node).attr('aria-checked', true).attr('tabindex', 0);
- $(node).addClass('selected').focus();
- },
- onOpen: function onOpen() {
- var _this3 = this;
- this.whenReady.then(function () {
- _this3.$('.selected').focus();
- });
- },
- selectLayout: function selectLayout(name) {
- Menu.hideOpenMenus();
- _.each(this.templates, function (template) {
- template.isSelected = template.name === name;
- }.bind(this));
- var selectedTemplate = this.$('.layoutTemplateItem[data-id=' + name + ']')[0];
- this.selectLayoutNode(selectedTemplate);
- if (this.navTemplate === 'custom') {
- this.applyContextMenuPermissions(name, selectedTemplate);
- }
- },
- /**
- * Asynch method that will load and return the selected page layout template
- */
- getSelectedLayoutSpec: function getSelectedLayoutSpec() {
- var selected = this.$('.selected').attr('data-id');
- return this.getLayoutSpecByName(selected);
- },
- getSelectedTemplate: function getSelectedTemplate() {
- return this.$('.layoutTemplateItem.selected');
- },
- getSelectedLayoutId: function getSelectedLayoutId() {
- var $selectedLayoutTemplate = this.$('.selected');
- if ($selectedLayoutTemplate.length > 0) {
- return $selectedLayoutTemplate[0].dataset.id;
- }
- return null;
- },
- _findLayoutByName: function _findLayoutByName(name) {
- return _.find(this.templates, function (template) {
- return template.name === name;
- });
- },
- getLayoutSpecByName: function getLayoutSpecByName(layoutName) {
- var _this4 = this;
- var layout = this._findLayoutByName(layoutName);
- if (!layout) {
- // Error loading the theme. We resolve with no definition.
- this.displayErrorMessage();
- return Promise.resolve();
- }
- return this.getLayoutSpec(layout, function () {
- // Error loading the theme. We resolve with no definition.
- _this4.displayErrorMessage();
- });
- },
- getLayoutSpec: function getLayoutSpec(template, errorHandler) {
- if (template.type === 'custom') {
- return Promise.resolve({ layout: template });
- }
- return new Promise(function (resolve, reject) {
- try {
- var requireFilePath = template.type === 'js' ? '' : 'text!';
- template.type = template.type ? template.type : 'json';
- requireFilePath += template.path + '/' + template.name;
- requireFilePath += template.type === 'js' ? '' : '.' + template.type;
- require([requireFilePath], function (layoutFileContent) {
- var layout = typeof layoutFileContent === 'string' ? JSON.parse(layoutFileContent) : layoutFileContent;
- resolve({
- layout: layout
- });
- }, function () {
- if (errorHandler) {
- errorHandler();
- }
- resolve();
- });
- } catch (error) {
- reject(error);
- }
- });
- },
- displayErrorMessage: function displayErrorMessage() {
- var msgBox = new MessageBox('error', this.stringResources.get('errorMessageTitle'), this.stringResources.get('errorLoadingLayoutFile'));
- msgBox.open();
- },
- generatePreviews: function generatePreviews() {
- var _this5 = this;
- var whenAllLoaded = [];
- _.each(this.templates, function (template) {
- if (template.type === 'custom') {
- var templateLayoutItem = _this5.$('*[data-id=' + template.name + ']').parent();
- ContentFormatter.middleShortenString(templateLayoutItem.find('.layoutLocation')[0]);
- ContentFormatter.middleShortenString(templateLayoutItem.find('.layoutThumbnailLabel')[0]);
- Utils.setIcon(templateLayoutItem.find('.layoutContextMenuButton'), contextMenuIcon.default.id);
- Utils.setIcon(templateLayoutItem.find('.layoutThumbnailContainer'), thumbnailPlaceholderIcon.default.id);
- var cachedThumbnail = _this5._thumbnailCache.find(function (thumbnail) {
- return thumbnail.name == template.name;
- });
- if (cachedThumbnail) {
- _this5._setTemplateThumbnail(template.name, cachedThumbnail.thumbnail);
- } else {
- _this5._dashboardTemplatesApi.getThumbnail(template.name).then(function (thumbnail) {
- _this5._thumbnailCache.push({ name: template.name, thumbnail: thumbnail });
- _this5._setTemplateThumbnail(template.name, thumbnail);
- });
- }
- } else {
- var promise = _this5.getLayoutSpec(template).then(function (_ref) {
- var layout = _ref.layout;
- var previewNode = _this5.$('*[data-id=' + template.name + ']');
- if (!template.label && !template.icon) {
- previewNode.append(_this5.getPreview(layout));
- }
- // set icon - webfont or svg
- if (template.icon) {
- var $templateIcon = _this5.$el.find('[data-id="' + template.name + '"]').find('.layoutIcon');
- Utils.setIcon($templateIcon, template.icon);
- }
- });
- whenAllLoaded.push(promise);
- }
- });
- Promise.all(whenAllLoaded).then(this._whenReady.resolve.bind(this.whenReady));
- },
- getPreview: function getPreview(layout) {
- var style = '';
- if (layout.style) {
- for (var name in layout.style) {
- if (layout.style.hasOwnProperty(name)) {
- style += name + ':' + layout.style[name] + ';';
- }
- }
- }
- var css = layout.css || '';
- css += ' ' + layout.type;
- var preview = '<div class="' + css + ' " style="' + style + '">';
- if (layout.items) {
- for (var i = 0; i < layout.items.length; i++) {
- preview += this.getPreview(layout.items[i]);
- }
- }
- preview += '</div>';
- return preview;
- },
- applyContextMenuPermissions: function applyContextMenuPermissions(templateId, selectedTemplateElement) {
- var _this6 = this;
- this._dashboardTemplatesApi.getTemplate(templateId).then(function (template) {
- _this6._selectedCustomTemplate = template;
- var contextMenuPermissions = ['write', 'execute'];
- if (_.intersection(template.permissions, contextMenuPermissions).length) {
- $(selectedTemplateElement).find('.layoutContextMenuButton').addClass('isVisible');
- }
- });
- },
- _setTemplateThumbnail: function _setTemplateThumbnail(id, image) {
- if (!id || !image) {
- return;
- }
- var templateItem = id && this.$('*[data-id=' + id + ']');
- var thumbnailContainer = templateItem.find('.layoutThumbnailContainer');
- var thumbnailImage = thumbnailContainer && thumbnailContainer.find('.layoutThumbnail');
- if (thumbnailImage && thumbnailImage.length) {
- thumbnailImage.attr('src', 'data:image/png;base64,' + image);
- var thumbnailPlaceholder = thumbnailContainer.find('svg').first();
- thumbnailPlaceholder && thumbnailPlaceholder.remove();
- }
- },
- onDeleteActionDone: function onDeleteActionDone(templateId) {
- var templateItem = templateId && this.$('*[data-id=' + templateId + ']');
- templateItem && templateItem.closest('.layoutEntry').remove();
- this.templates = this.templates.filter(function (template) {
- return template.name !== templateId;
- });
- },
- onContextMenuButtonClick: function onContextMenuButtonClick(event) {
- this._selectedCustomTemplate && this._showContextMenu(this._selectedCustomTemplate, event.pageX, event.pageY);
- },
- addMoreCustomTemplates: function addMoreCustomTemplates(customTemplates) {
- this._addCustomTemplates(customTemplates);
- this.render();
- }
- });
- return LayoutPickerView;
- });
- //# sourceMappingURL=LayoutPickerView.js.map
|