summaryrefslogtreecommitdiffstats
path: root/public/js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:36:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 12:36:40 +0000
commita0901c4b7f2db488cb4fb3be2dd921a0308f4659 (patch)
treefafb393cf330a60df129ff10d0059eb7b14052a7 /public/js
parentInitial commit. (diff)
downloadicingadb-web-a0901c4b7f2db488cb4fb3be2dd921a0308f4659.tar.xz
icingadb-web-a0901c4b7f2db488cb4fb3be2dd921a0308f4659.zip
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'public/js')
-rw-r--r--public/js/action-list.js212
-rw-r--r--public/js/loadmore.js85
-rw-r--r--public/js/migrate.js585
3 files changed, 882 insertions, 0 deletions
diff --git a/public/js/action-list.js b/public/js/action-list.js
new file mode 100644
index 0000000..e980ef3
--- /dev/null
+++ b/public/js/action-list.js
@@ -0,0 +1,212 @@
+/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */
+
+;(function () {
+
+ "use strict";
+
+ /**
+ * Parse the filter query contained in the given URL query string
+ *
+ * @param {string} queryString
+ *
+ * @returns {array}
+ */
+ var parseSelectionQuery = function (queryString) {
+ return queryString.split('|');
+ };
+
+ Icinga.Behaviors = Icinga.Behaviors || {};
+
+ var ActionList = function (icinga) {
+ Icinga.EventListener.call(this, icinga);
+
+ this.on('click', '.action-list [data-action-item]:not(.page-separator), .action-list [data-action-item] a[href]', this.onClick, this);
+ this.on('close-column', this.onColumnClose, this);
+
+ this.on('rendered', '.container', this.onRendered, this);
+ };
+
+ ActionList.prototype = new Icinga.EventListener();
+
+ ActionList.prototype.onClick = function (event) {
+ var _this = event.data.self;
+ var $activeItems;
+ var $target = $(event.currentTarget);
+ var $item = $target.closest('[data-action-item]');
+ var $list = $item.closest('.action-list');
+
+ if ($target.is('a') && (! $target.is('.subject') || event.ctrlKey || event.metaKey)) {
+ return true;
+ }
+
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ event.stopPropagation();
+
+ var container = $list.closest('.container');
+
+ if ($list.is('[data-icinga-multiselect-url]')) {
+ if (event.ctrlKey || event.metaKey) {
+ $item.toggleClass('active');
+ } else if (event.shiftKey) {
+ document.getSelection().removeAllRanges();
+
+ $activeItems = $list.find('[data-action-item].active');
+
+ var $firstActiveItem = $activeItems.first();
+
+ $activeItems.removeClass('active');
+
+ $firstActiveItem.addClass('active');
+ $item.addClass('active');
+
+ if ($item.index() > $firstActiveItem.index()) {
+ $item.prevUntil($firstActiveItem).addClass('active');
+ } else {
+ var $lastActiveItem = $activeItems.last();
+
+ $lastActiveItem.addClass('active');
+ $item.nextUntil($lastActiveItem).addClass('active');
+ }
+ } else {
+ $list.find('[data-action-item].active').removeClass('active');
+ $item.addClass('active');
+ }
+
+ // For items that do not have a bottom status bar like Downtimes, Comments...
+ if (! container.children('.footer').length) {
+ container.append('<div class="footer" data-action-list-automatically-added></div>');
+ }
+ } else {
+ $list.find('[data-action-item].active').removeClass('active');
+ $item.addClass('active');
+ }
+
+ $activeItems = $list.find('[data-action-item].active');
+ var footer = container.children('.footer');
+
+ if ($activeItems.length === 0) {
+ if (footer.length) {
+ if (typeof footer.data('action-list-automatically-added') !== 'undefined') {
+ footer.remove();
+ } else {
+ footer.children('.selection-count').remove();
+ }
+ }
+
+ if (_this.icinga.loader.getLinkTargetFor($target).attr('id') === 'col2') {
+ _this.icinga.ui.layout1col();
+ }
+ } else {
+ var url;
+
+ if ($activeItems.length === 1) {
+ url = $target.is('a') ? $target.attr('href') : $activeItems.find('[href]').first().attr('href');
+ } else {
+ var filters = $activeItems.map(function () {
+ return $(this).attr('data-icinga-multiselect-filter');
+ });
+
+ url = $list.attr('data-icinga-multiselect-url') + '?' + filters.toArray().join('|');
+ }
+
+ if ($list.is('[data-icinga-multiselect-url]')) {
+ if (! footer.children('.selection-count').length) {
+ footer.prepend('<div class="selection-count"></div>');
+ }
+
+ var label = $list.data('icinga-multiselect-count-label').replace('%d', $activeItems.length);
+ var selectedItems = footer.find('.selection-count > .selected-items');
+ if (selectedItems.length) {
+ selectedItems.text(label);
+ } else {
+ footer.children('.selection-count').append('<span class="selected-items">' + label + '</span>');
+ }
+ }
+
+ _this.icinga.loader.loadUrl(
+ url, _this.icinga.loader.getLinkTargetFor($target)
+ );
+ }
+ };
+
+ ActionList.prototype.onColumnClose = function (event) {
+ var $target = $(event.target);
+
+ if ($target.attr('id') !== 'col2') {
+ return;
+ }
+
+ var $list = $('#col1').find('.action-list');
+ if ($list.length && $list.is('[data-icinga-multiselect-url]')) {
+ var _this = event.data.self;
+ var detailUrl = _this.icinga.utils.parseUrl(_this.icinga.history.getCol2State().replace(/^#!/, ''));
+
+ if ($list.attr('data-icinga-multiselect-url') === detailUrl.path) {
+ $.each(parseSelectionQuery(detailUrl.query.slice(1)), function (i, filter) {
+ $list.find(
+ '[data-icinga-multiselect-filter="' + filter + '"]'
+ ).removeClass('active');
+ });
+ } else if ($list.attr('data-icinga-detail-url') === detailUrl.path) {
+ $list.find(
+ '[data-icinga-detail-filter="' + detailUrl.query.slice(1) + '"]'
+ ).removeClass('active');
+ }
+
+ var footer = $list.closest('.container').children('.footer');
+
+ if (footer.length) {
+ if (typeof footer.data('action-list-automatically-added') !== 'undefined') {
+ footer.remove();
+ } else {
+ footer.children('.selection-count').remove();
+ }
+ }
+ }
+ };
+
+ ActionList.prototype.onRendered = function (event) {
+ var $target = $(event.target);
+
+ if ($target.attr('id') !== 'col1') {
+ return;
+ }
+
+ var $list = $target.find('.action-list');
+
+ if ($list.length && $list.is('[data-icinga-multiselect-url], [data-icinga-detail-url]')) {
+ var _this = event.data.self;
+ var detailUrl = _this.icinga.utils.parseUrl(_this.icinga.history.getCol2State().replace(/^#!/, ''));
+
+ if ($list.attr('data-icinga-multiselect-url') === detailUrl.path) {
+ $.each(parseSelectionQuery(detailUrl.query.slice(1)), function (i, filter) {
+ $list.find(
+ '[data-icinga-multiselect-filter="' + filter + '"]'
+ ).addClass('active');
+ });
+ } else if ($list.attr('data-icinga-detail-url') === detailUrl.path) {
+ $list.find(
+ '[data-icinga-detail-filter="' + detailUrl.query.slice(1) + '"]'
+ ).addClass('active');
+ }
+ }
+
+ if ($list.length && $list.is('[data-icinga-multiselect-url]')) {
+ var $activeItems = $list.find('[data-action-item].active');
+
+ if ($activeItems.length) {
+ if (! $target.children('.footer').length) {
+ $target.append('<div class="footer" data-action-list-automatically-added></div>');
+ }
+
+ var label = $list.data('icinga-multiselect-count-label').replace('%d', $activeItems.length);
+ $target.children('.footer').prepend(
+ '<div class="selection-count"><span class="selected-items">' + label + '</span></div>'
+ );
+ }
+ }
+ };
+
+ Icinga.Behaviors.ActionList = ActionList;
+}());
diff --git a/public/js/loadmore.js b/public/js/loadmore.js
new file mode 100644
index 0000000..964a7b5
--- /dev/null
+++ b/public/js/loadmore.js
@@ -0,0 +1,85 @@
+/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */
+
+;(function(Icinga, $) {
+
+ 'use strict';
+
+ Icinga.Behaviors = Icinga.Behaviors || {};
+
+ /**
+ * Icinga DB Load More behavior.
+ *
+ * @param icinga {Icinga} The current Icinga Object
+ */
+ var LoadMore = function(icinga) {
+ Icinga.EventListener.call(this, icinga);
+
+ this.icinga = icinga;
+
+ this.on('click', '.show-more[data-no-icinga-ajax] a', this.onClick, this);
+ this.on('keypress', '.show-more[data-no-icinga-ajax] a', this.onKeyPress, this);
+ };
+
+ LoadMore.prototype = new Icinga.EventListener();
+
+ LoadMore.prototype.onClick = function(event) {
+ var _this = event.data.self;
+ var $anchor = $(event.target);
+ var $showMore = $anchor.parent();
+
+ event.stopPropagation();
+ event.preventDefault();
+
+ var progressTimer = _this.icinga.timer.register(function () {
+ var label = $anchor.html();
+
+ var dots = label.substr(-3);
+ if (dots.slice(0, 1) !== '.') {
+ dots = '. ';
+ } else {
+ label = label.slice(0, -3);
+ if (dots === '...') {
+ dots = '. ';
+ } else if (dots === '.. ') {
+ dots = '...';
+ } else if (dots === '. ') {
+ dots = '.. ';
+ }
+ }
+
+ $anchor.html(label + dots);
+ }, null, 250);
+
+ var url = $anchor.attr('href');
+ var req = _this.icinga.loader.loadUrl(
+ // Add showCompact, we don't want controls in paged results
+ _this.icinga.utils.addUrlFlag(url, 'showCompact'),
+ $showMore.parent(),
+ undefined,
+ undefined,
+ 'append',
+ false,
+ progressTimer
+ );
+ req.addToHistory = false;
+ req.done(function () {
+ $showMore.remove();
+
+ // Set data-icinga-url to make it available for Icinga.History.getCurrentState()
+ req.$target.closest('.container').data('icingaUrl', url);
+
+ _this.icinga.history.replaceCurrentState();
+ });
+
+ return false;
+ };
+
+ LoadMore.prototype.onKeyPress = function(event) {
+ if (event.which === 32) {
+ event.data.self.onClick(event);
+ }
+ };
+
+ Icinga.Behaviors.LoadMore = LoadMore;
+
+})(Icinga, jQuery);
diff --git a/public/js/migrate.js b/public/js/migrate.js
new file mode 100644
index 0000000..4198e16
--- /dev/null
+++ b/public/js/migrate.js
@@ -0,0 +1,585 @@
+/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */
+
+;(function(Icinga, $) {
+
+ 'use strict';
+
+ Icinga.Behaviors = Icinga.Behaviors || {};
+
+ const ANIMATION_LENGTH = 350;
+
+ const POPUP_HTML = '<div class="icinga-module module-icingadb">\n' +
+ ' <div id="migrate-popup">\n' +
+ ' <div class="suggestion-area">\n' +
+ ' <p>Preview this in Icinga DB</p>\n' +
+ ' <ul></ul>\n' +
+ ' <button type="button" class="close">Don\'t show this again</button>\n' +
+ ' </div>\n' +
+ ' <div class="minimizer"><i class="icon-"></i></div>\n' +
+ ' </div>\n' +
+ '</div>';
+
+ const SUGGESTION_HTML = '<li>\n' +
+ ' <button type="button" value="1"></button>\n' +
+ ' <button type="button" value="0"><i class="icon-"></i></button>\n' +
+ '</li>';
+
+ /**
+ * Icinga DB Migration behavior.
+ *
+ * @param icinga {Icinga} The current Icinga Object
+ */
+ var Migrate = function(icinga) {
+ Icinga.EventListener.call(this, icinga);
+
+ this.icinga = icinga;
+ this.knownMigrations = {};
+ this.knownBackendSupport = {};
+ this.urlMigrationReadyState = null;
+ this.backendSupportReadyState = null;
+ this.backendSupportRelated = {};
+ this.$popup = null;
+
+ // Some persistence, we don't want to annoy our users too much
+ this.storage = Icinga.Storage.BehaviorStorage('icingadb.migrate');
+ this.tempStorage = Icinga.Storage.BehaviorStorage('icingadb.migrate');
+ this.tempStorage.setBackend(window.sessionStorage);
+ this.previousMigrations = {};
+
+ // We don't want to ask the server to migrate non-monitoring urls
+ this.isMonitoringUrl = new RegExp('^' + icinga.config.baseUrl + '/monitoring/');
+ this.on('rendered', this.onRendered, this);
+ this.on('close-column', this.onColumnClose, this);
+ this.on('click', '#migrate-popup button.close', this.onClose, this);
+ this.on('click', '#migrate-popup li button', this.onDecision, this);
+ this.on('click', '#migrate-popup .minimizer', this.onHandleClicked, this);
+ this.storage.onChange('minimized', this.onMinimized, this);
+ };
+
+ Migrate.prototype = new Icinga.EventListener();
+
+ Migrate.prototype.update = function (data) {
+ if (data !== 'bogus') {
+ return;
+ }
+
+ $.each(this.backendSupportRelated, (id, _) => {
+ let $container = $('#' + id);
+ let req = this.icinga.loader.loadUrl($container.data('icingaUrl'), $container);
+ req.addToHistory = false;
+ req.scripted = true;
+ });
+ };
+
+ Migrate.prototype.onRendered = function(event) {
+ var _this = event.data.self;
+ var $target = $(event.target);
+
+ if (! $target.is('#main > .container')) {
+ if ($target.is('#main .container')) {
+ var attrUrl = $target.attr('data-icinga-url');
+ var dataUrl = $target.data('icingaUrl');
+ if (!! attrUrl && attrUrl !== dataUrl) {
+ // Search urls are redirected, update any migration suggestions
+ _this.prepareMigration($target);
+ return;
+ }
+ }
+
+ // We are else really only interested in top-level containers
+ return;
+ }
+
+ if (_this.tempStorage.get('closed') || $('#layout.fullscreen-layout').length) {
+ // Don't bother in case the user closed the popup or we're in fullscreen
+ return;
+ }
+
+ var $dashboard = $target.children('.dashboard');
+ if ($dashboard.length) {
+ // After a page load dashlets have no id as `renderContentToContainer()` didn't ran yet
+ _this.icinga.ui.assignUniqueContainerIds();
+
+ $target = $dashboard.children('.container');
+ }
+
+ _this.prepareMigration($target);
+ };
+
+ Migrate.prototype.prepareMigration = function($target) {
+ let urls = {};
+ let modules = {}
+
+ $target.each((_, container) => {
+ let $container = $(container);
+ let href = $container.data('icingaUrl');
+ let containerId = $container.attr('id');
+
+ if (typeof href !== 'undefined' && href.match(this.isMonitoringUrl)) {
+ if (
+ typeof this.previousMigrations[containerId] !== 'undefined'
+ && this.previousMigrations[containerId] === href
+ ) {
+ delete this.previousMigrations[containerId];
+ } else {
+ urls[containerId] = href;
+ }
+ }
+
+ let moduleName = $container.data('icingaModule');
+ if (!! moduleName && moduleName !== 'default' && moduleName !== 'monitoring' && moduleName !== 'icingadb') {
+ modules[containerId] = moduleName;
+ }
+ });
+
+ if (Object.keys(urls).length) {
+ this.setUrlMigrationReadyState(false);
+ this.migrateMonitoringUrls(urls);
+ } else {
+ this.setUrlMigrationReadyState(null);
+ }
+
+ if (Object.keys(modules).length) {
+ this.setBackendSupportReadyState(false);
+ this.prepareBackendCheckboxForm(modules);
+ } else {
+ this.setBackendSupportReadyState(null);
+ }
+
+ if (this.urlMigrationReadyState === null && this.backendSupportReadyState === null) {
+ this.cleanupPopup();
+ }
+ };
+
+ Migrate.prototype.onColumnClose = function(event) {
+ var _this = event.data.self;
+ _this.Popup().find('.suggestion-area > ul li').each(function () {
+ var $suggestion = $(this);
+ var suggestionUrl = $suggestion.data('containerUrl');
+ var $container = $('#' + $suggestion.data('containerId'));
+
+ var containerUrl = '';
+ if ($container.length) {
+ containerUrl = $container.data('icingaUrl');
+ }
+
+ if (suggestionUrl !== containerUrl) {
+ var $newContainer = $('#main > .container').filter(function () {
+ return $(this).data('icingaUrl') === suggestionUrl;
+ });
+ if ($newContainer.length) {
+ // Container moved
+ $suggestion.attr('id', 'suggest-' + $newContainer.attr('id'));
+ $suggestion.data('containerId', $newContainer.attr('id'));
+ }
+ }
+ });
+
+ let backendSupportRelated = { ..._this.backendSupportRelated };
+ $.each(backendSupportRelated, (id, module) => {
+ let $container = $('#' + id);
+ if (! $container.length || $container.data('icingaModule') !== module) {
+ let $newContainer = $('#main > .container').filter(function () {
+ return $(this).data('icingaModule') === module;
+ });
+ if ($newContainer.length) {
+ _this.backendSupportRelated[$newContainer.attr('id')] = module;
+ }
+
+ delete _this.backendSupportRelated[id];
+ }
+ });
+
+ _this.cleanupPopup();
+ };
+
+ Migrate.prototype.onClose = function(event) {
+ var _this = event.data.self;
+ _this.tempStorage.set('closed', true);
+ _this.hidePopup();
+ };
+
+ Migrate.prototype.onDecision = function(event) {
+ var _this = event.data.self;
+ var $button = $(event.target).closest('button');
+ var $suggestion = $button.parent();
+ var $container = $('#' + $suggestion.data('containerId'));
+ var containerUrl = $container.data('icingaUrl');
+
+ if ($button.attr('value') === '1') {
+ // Yes
+ var newHref = _this.knownMigrations[containerUrl];
+ _this.icinga.loader.loadUrl(newHref, $container);
+
+ _this.previousMigrations[$suggestion.data('containerId')] = containerUrl;
+
+ if ($container.parent().is('.dashboard')) {
+ $container.find('h1 a').attr('href', _this.icinga.utils.removeUrlParams(newHref, ['showCompact']));
+ }
+ } else {
+ // No
+ _this.knownMigrations[containerUrl] = false;
+ }
+
+ if (_this.Popup().find('li').length === 1) {
+ _this.hidePopup(function () {
+ // Let the transition finish first, looks cleaner
+ $suggestion.remove();
+ });
+ } else {
+ $suggestion.remove();
+ }
+ };
+
+ Migrate.prototype.onHandleClicked = function(event) {
+ var _this = event.data.self;
+ if (_this.togglePopup()) {
+ _this.storage.set('minimized', true);
+ } else {
+ _this.storage.remove('minimized');
+ }
+ };
+
+ Migrate.prototype.onMinimized = function(isMinimized, oldValue) {
+ if (isMinimized && isMinimized !== oldValue && this.isShown()) {
+ this.minimizePopup();
+ }
+ };
+
+ Migrate.prototype.migrateMonitoringUrls = function(urls) {
+ var _this = this,
+ containerIds = [],
+ containerUrls = [];
+
+ $.each(urls, function (containerId, containerUrl) {
+ if (typeof _this.knownMigrations[containerUrl] === 'undefined') {
+ containerUrls.push(containerUrl);
+ containerIds.push(containerId);
+ }
+ });
+
+ if (containerUrls.length) {
+ var req = $.ajax({
+ context : this,
+ type : 'post',
+ url : this.icinga.config.baseUrl + '/icingadb/migrate/monitoring-url',
+ headers : { 'Accept': 'application/json' },
+ contentType : 'application/json',
+ data : JSON.stringify(containerUrls)
+ });
+
+ req.urls = urls;
+ req.urlIndexToContainerId = containerIds;
+ req.done(this.processUrlMigrationResults);
+ req.always(() => this.changeUrlMigrationReadyState(true));
+ } else {
+ // All urls have already been migrated once, show popup immediately
+ this.addSuggestions(urls);
+ this.changeUrlMigrationReadyState(true);
+ }
+ };
+
+ Migrate.prototype.processUrlMigrationResults = function(data, textStatus, req) {
+ var _this = this;
+ var result, containerId;
+
+ if (data.status === 'success') {
+ result = data.data;
+ } else { // if (data.status === 'fail')
+ result = data.data.result;
+
+ $.each(data.data.errors, function (k, error) {
+ _this.icinga.logger.error('[Migrate] Erroneous url "' + k + '": ' + error[0] + '\n' + error[1]);
+ });
+ }
+
+ $.each(result, function (i, migratedUrl) {
+ containerId = req.urlIndexToContainerId[i];
+ _this.knownMigrations[req.urls[containerId]] = migratedUrl;
+ });
+
+ this.addSuggestions(req.urls);
+ };
+
+ Migrate.prototype.prepareBackendCheckboxForm = function(modules) {
+ let containerIds = [];
+ let moduleNames = [];
+
+ $.each(modules, (id, module) => {
+ if (typeof this.knownBackendSupport[module] === 'undefined') {
+ containerIds.push(id);
+ moduleNames.push(module);
+ }
+ });
+
+ if (moduleNames.length) {
+ let req = $.ajax({
+ context : this,
+ type : 'post',
+ url : this.icinga.config.baseUrl + '/icingadb/migrate/backend-support',
+ headers : { 'Accept': 'application/json' },
+ contentType : 'application/json',
+ data : JSON.stringify(moduleNames)
+ });
+
+ req.modules = modules;
+ req.moduleIndexToContainerId = containerIds;
+ req.done(this.processBackendSupportResults);
+ req.always(() => this.changeBackendSupportReadyState(true));
+ } else {
+ // All modules have already been checked once, show popup immediately
+ this.setupBackendCheckboxForm(modules);
+ this.changeBackendSupportReadyState(true);
+ }
+ };
+
+ Migrate.prototype.processBackendSupportResults = function(data, textStatus, req) {
+ let result = data.data;
+
+ $.each(result, (i, state) => {
+ let containerId = req.moduleIndexToContainerId[i];
+ this.knownBackendSupport[req.modules[containerId]] = state;
+ });
+
+ this.setupBackendCheckboxForm(req.modules);
+ };
+
+ Migrate.prototype.setupBackendCheckboxForm = function(modules) {
+ let supportedModules = {};
+
+ $.each(modules, (id, module) => {
+ if (this.knownBackendSupport[module]) {
+ supportedModules[id] = module;
+ }
+ });
+
+ if (Object.keys(supportedModules).length) {
+ this.backendSupportRelated = { ...this.backendSupportRelated, ...supportedModules };
+
+ let req = $.ajax({
+ context : this,
+ type : 'get',
+ url : this.icinga.config.baseUrl + '/icingadb/migrate/checkbox-state?showCompact'
+ });
+
+ req.done(this.setCheckboxState);
+ }
+ };
+
+ Migrate.prototype.setCheckboxState = function(html, textStatus, req) {
+ let $form = this.Popup().find('.suggestion-area > #setAsBackendForm');
+ if (! $form.length) {
+ $form = $(html);
+ $form.attr('data-base-target', 'migrate-popup-backend-submit-blackhole');
+ $form.append('<div id="migrate-popup-backend-submit-blackhole"></div>');
+
+ this.Popup().find('.suggestion-area > ul').after($form);
+ } else {
+ let $newForm = $(html);
+ $form.find('[name=backend]').prop('checked', $newForm.find('[name=backend]').is(':checked'));
+ }
+
+ this.showPopup();
+ }
+
+ Migrate.prototype.addSuggestions = function(urls) {
+ var _this = this,
+ hasSuggestions = false,
+ $ul = this.Popup().find('.suggestion-area > ul');
+ $.each(urls, function (containerId, containerUrl) {
+ // No urls for which the user clicked "No" or an error occurred and only migrated urls please
+ if (_this.knownMigrations[containerUrl] !== false && _this.knownMigrations[containerUrl] !== containerUrl) {
+ var $container = $('#' + containerId);
+
+ var $suggestion = $ul.find('li#suggest-' + containerId);
+ if ($suggestion.length) {
+ if ($suggestion.data('containerUrl') === containerUrl) {
+ // There's already a suggestion for this exact container and url
+ hasSuggestions = true;
+ return;
+ }
+
+ $suggestion.data('containerUrl', containerUrl);
+ } else {
+ $suggestion = $(SUGGESTION_HTML);
+ $suggestion.attr('id', 'suggest-' + containerId);
+ $suggestion.data('containerId', containerId);
+ $suggestion.data('containerUrl', containerUrl);
+ $ul.append($suggestion);
+ }
+
+ hasSuggestions = true;
+
+ var title;
+ if ($container.data('icingaTitle')) {
+ title = $container.data('icingaTitle').split(' :: ').slice(0, -1).join(' :: ');
+ } else if ($container.parent().is('.dashboard')) {
+ title = $container.find('h1 a').text();
+ } else {
+ title = $container.find('.tabs li.active a').text();
+ }
+
+ $suggestion.find('button:first-of-type').text(title);
+ }
+ });
+
+ if (hasSuggestions) {
+ this.showPopup();
+ }
+ };
+
+ Migrate.prototype.cleanupSuggestions = function() {
+ var _this = this,
+ toBeRemoved = [];
+ this.Popup().find('li').each(function () {
+ var $suggestion = $(this);
+ var $container = $('#' + $suggestion.data('containerId'));
+ var containerUrl = $container.data('icingaUrl');
+ if (
+ // Unknown url, yet
+ typeof _this.knownMigrations[containerUrl] === 'undefined'
+ // User doesn't want to migrate
+ || _this.knownMigrations[containerUrl] === false
+ // Already migrated or no migration necessary
+ || containerUrl === _this.knownMigrations[containerUrl]
+ ) {
+ toBeRemoved.push($suggestion);
+ }
+ });
+
+ return toBeRemoved;
+ };
+
+ Migrate.prototype.cleanupBackendForm = function () {
+ let $form = this.Popup().find('#setAsBackendForm');
+ if (! $form.length) {
+ return false;
+ }
+
+ let stillRelated = {};
+ $.each(this.backendSupportRelated, (id, module) => {
+ let $container = $('#' + id);
+ if ($container.length && $container.data('icingaModule') === module) {
+ stillRelated[id] = module;
+ }
+ });
+
+ this.backendSupportRelated = stillRelated;
+
+ if (Object.keys(stillRelated).length) {
+ return true;
+ }
+
+ return $form;
+ };
+
+ Migrate.prototype.cleanupPopup = function () {
+ let toBeRemoved = this.cleanupSuggestions();
+ let hasBackendForm = this.cleanupBackendForm();
+
+ if (hasBackendForm !== true && this.Popup().find('li').length === toBeRemoved.length) {
+ this.hidePopup(function () {
+ // Let the transition finish first, looks cleaner
+ $.each(toBeRemoved, function (_, $suggestion) {
+ $suggestion.remove();
+ });
+
+ if (typeof hasBackendForm === 'object') {
+ hasBackendForm.remove();
+ }
+ });
+ } else {
+ $.each(toBeRemoved, function (_, $suggestion) {
+ $suggestion.remove();
+ });
+
+ if (typeof hasBackendForm === 'object') {
+ hasBackendForm.remove();
+ }
+ }
+ };
+
+ Migrate.prototype.showPopup = function() {
+ var $popup = this.Popup();
+ if (this.storage.get('minimized')) {
+ $popup.addClass('active minimized hidden');
+ } else {
+ $popup.addClass('active');
+ }
+ };
+
+ Migrate.prototype.hidePopup = function (after) {
+ this.Popup().removeClass('active minimized hidden');
+
+ if (typeof after === 'function') {
+ setTimeout(after, ANIMATION_LENGTH);
+ }
+ };
+
+ Migrate.prototype.isShown = function() {
+ return this.Popup().is('.active');
+ };
+
+ Migrate.prototype.minimizePopup = function() {
+ var $popup = this.Popup();
+ $popup.addClass('minimized');
+ setTimeout(function () {
+ $popup.addClass('hidden');
+ }, ANIMATION_LENGTH);
+ };
+
+ Migrate.prototype.maximizePopup = function() {
+ this.Popup().removeClass('minimized hidden');
+ };
+
+ Migrate.prototype.togglePopup = function() {
+ if (this.Popup().is('.minimized')) {
+ this.maximizePopup();
+ return false;
+ } else {
+ this.minimizePopup();
+ return true;
+ }
+ };
+
+ Migrate.prototype.setUrlMigrationReadyState = function (state) {
+ this.urlMigrationReadyState = state;
+ };
+
+ Migrate.prototype.changeUrlMigrationReadyState = function (state) {
+ this.setUrlMigrationReadyState(state);
+
+ if (this.backendSupportReadyState !== false) {
+ this.backendSupportReadyState = null;
+ this.urlMigrationReadyState = null;
+ this.cleanupPopup();
+ }
+ };
+
+ Migrate.prototype.setBackendSupportReadyState = function (state) {
+ this.backendSupportReadyState = state;
+ };
+
+ Migrate.prototype.changeBackendSupportReadyState = function (state) {
+ this.setBackendSupportReadyState(state);
+
+ if (this.urlMigrationReadyState !== false) {
+ this.backendSupportReadyState = null;
+ this.urlMigrationReadyState = null;
+ this.cleanupPopup();
+ }
+ };
+
+ Migrate.prototype.Popup = function() {
+ // Node.contains() is used due to `?renderLayout`
+ if (this.$popup === null || ! document.body.contains(this.$popup[0])) {
+ $('#layout').append($(POPUP_HTML));
+ this.$popup = $('#migrate-popup');
+ }
+
+ return this.$popup;
+ };
+
+ Icinga.Behaviors.Migrate = Migrate;
+
+})(Icinga, jQuery);