"use strict"; /** * Licensed Materials - Property of IBM * * IBM Cognos Products: ADMIN * * Copyright IBM Corp. 2017 * * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['jquery', 'underscore', 'moment-timezone', 'rave2', 'q', "bi/schedule/service/service", 'bi/commons/utils/BidiUtil', 'text!bi/admin/subscriptions/templates/SubscriptionManagementLoading.html', 'text!bi/admin/subscriptions/templates/SubscriptionManagement.html', 'text!bi/admin/subscriptions/templates/emptyMessageList.html', 'bi/glass/app/ContentView', 'doT', 'bi/admin/nls/StringResource', 'bi/schedule/utils/CadenceLabelGenerator', 'bi/commons/ui/properties/CheckBox', 'bi/commons/utils/Utils', 'bi/admin/common/visualizations/VizBar', 'datatables'], function ($, _, moment, rave, Q, ShareService, BidiUtil, loadingViewTemplate, viewTemplate, emptyListTemplate, ContentView, dot, StringResource, cadence, CheckBox, Utils, BarChart) { var DEFAULT_DELAY = 500; var __STANDARD_DATE_TIME_FORMAT = 'lll'; var view = ContentView.extend({ shareService: ShareService, init: function init(options) { view.inherited('init', this, arguments); // Initialise default values this.subscriptionsCount = 0; this.enabledCount = 0; this.disabledCount = 0; this.windowWidth = 0; this.timezone = options.glassContext.services.userProfile.preferences.timeZoneID; this.contentLocale = this.glassContext.services.userProfile.preferences.contentLocale || "en-us"; $.extend(this, options); this._id = _.uniqueId("smv_"); this.$subscriptionsListDiv = null; this.$noSubscriptionsDiv = null; }, activate: function activate() { return this.updateView(); }, // nothing to do, but needs to be present for AppView.js logic from Glass deactivate: function deactivate() {}, getContent: function getContent() { return {}; }, getTitle: function getTitle() { return StringResource.get("subscribe_mgmt_label"); }, getIcon: function getIcon() { return 'common-subscribe_icon'; }, render: function render() { var subscribe_graph_title = StringResource.get("subscribe_graph_title"); var subscribe_last_refresh_label = StringResource.get("subscribe_last_refresh_label"); // Set up the Subscription Management Loading template // I don't like this but it works (for now) var loadingHtmlGenerator = dot.template(loadingViewTemplate); var currentTime = moment(new Date()).locale(this.contentLocale).tz(this.timezone).format(__STANDARD_DATE_TIME_FORMAT); var attributes = { subscribe_graph_title: subscribe_graph_title, subscribe_last_refresh_label: subscribe_last_refresh_label, current_time: currentTime }; this.$el.html(loadingHtmlGenerator(attributes)); var loadingAnimation = Utils.getLoadingAnimation(2); this.$el.find('div.s10n_loading').html(loadingAnimation); this.shareService.getSubscriptions(this.glassContext).then(function (data) { var subscriptions = []; this.enabledCount = 0; var dataLength = data.length; for (var i = 0; i < dataLength; i++) { var name = _.escape(data[i].name.substr(0, 3) + BidiUtil.enforceTextDirection(data[i].name.substr(3))) || ""; var nameInAttr = _.escape(data[i].name) || ""; var cadenceLabel = cadence.getLabelFor(data[i].scheduleInfo, this.timezone, this.contentLocale); var ownerName = data[i].scheduleInfo ? _.escape(data[i].scheduleInfo.ownerName) || "" : ""; var lastModified = data[i].scheduleInfo ? data[i].scheduleInfo.modificationTime || "" : ""; lastModified = moment(lastModified).locale(this.contentLocale).tz(this.timezone).format(__STANDARD_DATE_TIME_FORMAT); data[i].checkbox_aria_label = StringResource.get("subscribe_mgmt_checkbox_description", { 'subscription_name': nameInAttr }); var isEnabled = data[i].scheduleInfo.active || false; if (isEnabled) { this.enabledCount++; } subscriptions.push({ id: data[i].id, name: name, owner: ownerName, active: isEnabled, modifiedTime: lastModified, cadence_label: cadenceLabel, // "Every Wednesday at 5pm" context_menu_description: StringResource.get("subs_mgmt_context_menu_description", { 'subscription_name': nameInAttr }) }); } this.subscriptionsCount = subscriptions.length; this.disabledCount = subscriptions.length - this.enabledCount; var htmlGenerator = dot.template(viewTemplate); var currentTime = moment(new Date()).locale(this.contentLocale).tz(this.timezone).format(__STANDARD_DATE_TIME_FORMAT); var attributes = { id: this._id, subscribe_graph_title: subscribe_graph_title, subscribe_last_refresh_label: subscribe_last_refresh_label, current_time: currentTime, ariaLabel: StringResource.get("subscriptions_table_accessible_label"), chartDescription: StringResource.get("subscribe_graph_description", { enabled: this.enabledCount, disabled: this.disabledCount }), columns: this._tableColumnHeaders(), subs: subscriptions }; this.$el.html(htmlGenerator(attributes)); // By default both are displayed. We choose which to hide later this.$subscriptionsListDiv = this.$el.find('.subscriptions_list'); this.$noSubscriptionsDiv = this.$el.find('.no_subscriptions_message'); var emptyTemplate = dot.template(emptyListTemplate); this.$noSubscriptionsDiv.html(emptyTemplate({ 'text': StringResource.get("subscription_list_is_empty") })); this._setSvg(); this._renderChart(); this._renderCheckBoxes(data); if (this.subscriptionsCount > 0) { this.$subscriptionsListDiv.find('.subscriptions_list_table').dataTable({ paging: false, searching: false, info: false, aaSorting: [[1, 'asc']], scrollY: '60vh', scrollX: 'auto', width: '100%' }); this.$noSubscriptionsDiv.hide(); } else { this.$subscriptionsListDiv.hide(); } this._fixTableBodyHeight(); this._setEvents(); }.bind(this)); return Promise.resolve(this); ; }, updateView: function updateView() { this.$el.empty(); return this.render(); }, _createChart: function _createChart(el, data, pw) { return new BarChart({ el: el, data: data, parentWidth: pw }); }, _renderChart: function _renderChart() { var chartData = [{ name: 'enabled', value: this.enabledCount }, { name: 'disabled', value: this.disabledCount }]; var width = this.$el.width(); var $svgEl = this.$el.find('svg.chart'); $svgEl.css("width", "100%"); // This initialises AND draws the chart this._chart = this._createChart($svgEl[0], chartData, width); }, _updateChart: function _updateChart(data) { this._chart._draw(data); }, _createCheckbox: function _createCheckbox(opts) { return new CheckBox(opts); }, _renderCheckBoxes: function _renderCheckBoxes(data) { for (var i = 0; i < data.length; i++) { var stateToggler = this._createCheckbox({ 'id': 'subscription_' + data[i].id, 'el': this.$el.find("[data-subscription-id='" + data[i].id + "'] > td:first"), 'name': data[i].id, 'label': '', 'ariaLabel': data[i].checkbox_aria_label, 'checked': data[i].scheduleInfo.active, 'onChange': function (name, value) { this._handleCheckBoxes({ subscriptionId: name, state: value, $checkbox: stateToggler.getPropertyNode() // 'this' is CheckBox NOT SubMgmtView }); }.bind(this) }); stateToggler.doRender(); } }, _handleCheckBoxes: function _handleCheckBoxes(properties) { var subscriptionId = properties.subscriptionId; var state = properties.state; var $checkbox = properties.$checkbox; $checkbox.addClass('disabled'); this.shareService.getSubscriptionDetails(subscriptionId, this.glassContext).then(function (data) { subscriptionDescriptor = data; subscriptionDescriptor.scheduleInfo.active = state; this._toggleSingleSubscriptionStatus(subscriptionDescriptor).then(function () { $checkbox.removeClass('disabled'); }); }.bind(this)); }, _toggleSingleSubscriptionStatus: function _toggleSingleSubscriptionStatus(descriptor) { var deferred = Q.defer(); this.shareService.updateSubscription(descriptor, this.glassContext).done(function (data) { this._updateSubscriptionList().then(function () { deferred.resolve(); }); }.bind(this)); return deferred.promise; }, _fixTableBodyHeight: function _fixTableBodyHeight() { var contentHeight = this.$el.find('div.s10n_main').height(); // this is height of pane minus top and bottom padding var topHeight = this.$el.find('div.s10n_header').height() + this.$el.find('svg.chart').height(); // The magic number 40 is for the padding in the content view from the css class s10n_container this.$el.find('div.dataTables_scrollBody').height(contentHeight - topHeight - 40); }, _setEvents: function _setEvents() { var _self = this; window.onresize = function () { if (_self.$el.find('svg.chart').css('visibility') !== 'hidden' && $(window).width() !== _self.windowWidth) { _self.windowWidth = $(window).width(); _self._updateChart(); } // Fix height of datatable container _self._fixTableBodyHeight(); }; $('button.btnContextMenu').on('clicktap', function (event) { var menuProperties = { 'menuId': 'com.ibm.bi.subscribe_mgmt.contextMenu', 'position': { pageX: event.pageX, pageY: event.pageY }, 'activeObject': { currentTarget: event.currentTarget, subscriptionId: $(event.currentTarget).closest('tr').data('subscription-id'), updateCallback: _self.updateView.bind(_self), deleteCallbacks: { hideRow: _self._hideDeleteRow.bind(_self), undoDelete: _self._undoDeleteAndShowRow.bind(_self), complete: _self._completeSubscriptionDelete.bind(_self) } } }; _self.glassContext.appController.showContextMenu(menuProperties); }); }, _hideDeleteRow: function _hideDeleteRow($subscriptionRow) { var deferred = Q.defer(); var _self = this; $subscriptionRow.hide(DEFAULT_DELAY, function () { if (_self.subscriptionsCount == 1) { _self.$noSubscriptionsDiv.show(); _self.$subscriptionsListDiv.hide(); } deferred.resolve(); }); return deferred.promise; }, _undoDeleteAndShowRow: function _undoDeleteAndShowRow($subscriptionRow) { var _self = this; // An undo should show right away that is the reason for zero $subscriptionRow.show(0, function () { if (_self.subscriptionsCount == 1) { _self.$noSubscriptionsDiv.hide(); _self.$subscriptionsListDiv.show(); } }); }, _completeSubscriptionDelete: function _completeSubscriptionDelete(options) { if (options.pending) { this.shareService.deleteSubscription(options.subscriptionId, this.glassContext).done(function () { this._updateSubscriptionList(); }.bind(this)); } }, _updateSubscriptionList: function _updateSubscriptionList() { var deferred = Q.defer(); this.shareService.getSubscriptions(this.glassContext).done(function (data) { this.subscriptionsCount = data.length; var enabled = _.countBy(data, function (s) { if (s.scheduleInfo.active) return "enabled"; }); if (!enabled.enabled) { enabled.enabled = 0; } this.enabledCount = enabled.enabled; this.disabledCount = this.subscriptionsCount - enabled.enabled; if (this.subscriptionsCount === 0) { this.$noSubscriptionsDiv.show(); this.$subscriptionsListDiv.hide(); } var chartData = [{ name: 'enabled', value: this.enabledCount }, { name: 'disabled', value: this.disabledCount }]; this._updateChart(chartData); deferred.resolve(); }.bind(this)); return deferred.promise; }, _setSvg: function _setSvg() { var $icons = this.$el.find('.common_icon'); for (var i = 0; i < $icons.length; i++) { var $icon = $($icons[i]); Utils.setIcon($icon, 'common-' + $icon.data('icon'), StringResource.get('svg_menu_icon')); } }, _tableColumnHeaders: function _tableColumnHeaders() { return [{ 'name': 'enable', 'label': StringResource.get("subscribe_status_header"), 'class': 's10n_status_col' }, // Subscription name column { 'name': 'name', 'label': StringResource.get("subscribe_header"), 'sort': true }, // Owner column { 'name': 'owner', 'label': StringResource.get("subscribe_owner_header"), 'sort': true }, // Modified column { 'name': 'modified', 'label': StringResource.get("subscribe_modified_header"), 'sort': true }, // Context Menu column to modify/view history/delete { 'name': 'context' }]; } }); return view; });