diff --git a/app/assets/javascripts/controllers/toolbar_controller.js b/app/assets/javascripts/controllers/toolbar_controller.js
deleted file mode 100644
index 9d26d0cd541..00000000000
--- a/app/assets/javascripts/controllers/toolbar_controller.js
+++ /dev/null
@@ -1,214 +0,0 @@
-(function() {
- function isButton(item) {
- return item.type === 'button';
- }
-
- function isButtonTwoState(item) {
- return item.type === 'buttonTwoState' && item.id.indexOf('view') === -1;
- }
-
- /**
- * Private method for subscribing to rxSubject.
- * For success functuon @see ToolbarController#onRowSelect()
- * @returns {undefined}
- */
- function subscribeToSubject() {
- listenToRx(function(event) {
- if (event.eventType === 'updateToolbarCount') {
- this.MiQToolbarSettingsService.setCount(event.countSelected);
- } else if (event.rowSelect) {
- this.onRowSelect(event.rowSelect);
- } else if (event.redrawToolbar) {
- this.onUpdateToolbar(event.redrawToolbar);
- } else if (event.update) {
- this.onUpdateItem(event);
- } else if (typeof event.setCount !== 'undefined') {
- this.onSetCount(event.setCount);
- }
-
- // sync changes
- if (!this.$scope.$$phase) {
- this.$scope.$digest();
- }
- }.bind(this),
- function(err) {
- console.error('Angular RxJs Error: ', err);
- },
- function() {
- console.debug('Angular RxJs subject completed, no more events to catch.');
- });
- }
-
- /**
- * Private method for setting rootPoint of MiQEndpointsService.
- * @param {Object} MiQEndpointsService service responsible for endpoits.
- * @returns {undefined}
- */
- function initEndpoints(MiQEndpointsService) {
- var urlPrefix = '/' + location.pathname.split('/')[1];
- MiQEndpointsService.rootPoint = urlPrefix;
- }
-
- /**
- * Constructor of angular's miqToolbarController.
- * @param {Object} MiQToolbarSettingsService toolbarSettings service from ui-components.
- * @param {Object} MiQEndpointsService endpoits service from ui-components.
- * @param {Object} $scope service for managing $scope (for apply and digest reasons).
- * @param {Object} $location service for managing browser's location.
- * this contructor will assign all params to `this`, it will init endpoits, set if toolbar is used on list page.
- * @returns {undefined}
- */
- var ToolbarController = function(MiQToolbarSettingsService, MiQEndpointsService, $scope, $location) {
- this.MiQToolbarSettingsService = MiQToolbarSettingsService;
- this.MiQEndpointsService = MiQEndpointsService;
- this.$scope = $scope;
- this.$location = $location;
- initEndpoints(this.MiQEndpointsService);
- this.isList = location.pathname.includes('show_list');
- };
-
- /**
- * Public method which is executed after row in gtl is selected.
- * @param {Object} data selected row
- * @returns {undefined}
- */
- ToolbarController.prototype.onRowSelect = function(data) {
- this.MiQToolbarSettingsService.checkboxClicked(data.checked);
- };
-
- /**
- * Public method for setting up url of data views, based on last path param (e.g. /show_list).
- * @returns {undefined}
- */
- ToolbarController.prototype.defaultViewUrl = function() {
- this.dataViews.forEach(function(item) {
- if (item.url === '') {
- var lastSlash = location.pathname.lastIndexOf('/');
- item.url = (lastSlash !== -1) ? location.pathname.substring(lastSlash) : '';
- }
- });
- };
-
- /**
- * Method which will retrieves toolbar settings from server.
- * @see MiQToolbarSettingsService#getSettings for more info.
- * Settings is called with this.isList and $location search object with value of `type`.
- * No need to worry about multiple search params and no complicated function for parsing is needed.
- * @param {function} getData callbalc for retireving toolbar data
- * @returns {undefined}
- */
- ToolbarController.prototype.fetchData = function(getData) {
- return this.MiQToolbarSettingsService
- .getSettings(getData)
- .then(function(toolbarItems) {
- this.toolbarItems = toolbarItems.items;
- this.dataViews = toolbarItems.dataViews;
- }.bind(this));
- };
-
- ToolbarController.prototype.onSetCount = function(count) {
- this.MiQToolbarSettingsService.setCount(count);
- if (!this.$scope.$$phase) {
- this.$scope.$digest();
- }
- };
-
- ToolbarController.prototype.setClickHandler = function() {
- _.chain(this.toolbarItems)
- .flatten()
- .map(function(item) {
- return (item && item.hasOwnProperty('items')) ? item.items : item;
- })
- .flatten()
- .filter(function(item) {
- return item.type &&
- (isButton(item) || isButtonTwoState(item));
- })
- .each(function(item) {
- item.eventFunction = function($event) {
- // clicking on disabled or hidden things shouldn't do anything
- if (item.hidden === true || item.enabled === false) {
- return;
- }
-
- sendDataWithRx({toolbarEvent: 'itemClicked'});
- Promise.resolve(miqToolbarOnClick.bind($event.delegateTarget)($event)).then(function(data) {
- sendDataWithRx({type: 'TOOLBAR_CLICK_FINISH', payload: data});
- });
- };
- })
- .value();
- };
-
- /**
- * Public method for changing view over data.
- * @param {Object} item clicked view object
- * @param {Object} $event angular synthetic mouse event
- * @returns {undefined}
- */
- ToolbarController.prototype.onViewClick = function(item, $event) {
- if (item.url.indexOf('/') === 0) {
- var delimiter = (item.url === '/') ? '' : '/';
- var tail = (ManageIQ.record.recordId) ? delimiter + ManageIQ.record.recordId : '';
-
- location.replace('/' + ManageIQ.controller + item.url + tail + item.url_parms);
- } else {
- miqToolbarOnClick.bind($event.delegateTarget)($event);
- }
- };
-
- ToolbarController.prototype.initObject = function(toolbarString) {
- subscribeToSubject.bind(this)();
- this.updateToolbar(JSON.parse(toolbarString));
- };
-
- ToolbarController.prototype.onUpdateToolbar = function(toolbarObject) {
- this.updateToolbar(toolbarObject);
- };
-
- ToolbarController.prototype.onUpdateItem = function(updateData) {
- var toolbarItem = _.find(_.flatten(this.toolbarItems), {id: updateData.update});
- if (toolbarItem && toolbarItem.hasOwnProperty(updateData.type)) {
- toolbarItem[updateData.type] = updateData.value;
- }
- };
-
- ToolbarController.prototype.updateToolbar = function(toolbarObject) {
- var toolbarItems = this.MiQToolbarSettingsService.generateToolbarObject(toolbarObject);
- this.toolbarItems = toolbarItems.items;
- this.dataViews = toolbarItems.dataViews;
- this.defaultViewUrl();
- this.setClickHandler();
- this.showOrHide();
- };
-
- ToolbarController.prototype.anyToolbarVisible = function() {
- if (!this.toolbarItems || !this.toolbarItems.length) {
- return false;
- }
-
- var nonEmpty = this.toolbarItems.filter(function(ary) {
- if (!ary || !ary.length) {
- return false;
- }
-
- return _.some(ary, function(item) {
- return !item.hidden;
- });
- });
-
- return !!nonEmpty.length;
- };
-
- ToolbarController.prototype.showOrHide = function() {
- if (this.anyToolbarVisible()) {
- $('#toolbar').show();
- } else {
- $('#toolbar').hide();
- }
- };
-
- ToolbarController.$inject = ['MiQToolbarSettingsService', 'MiQEndpointsService', '$scope', '$location'];
-
- angular.module('ManageIQ').controller('miqToolbarController', ToolbarController);
-})();
diff --git a/app/assets/javascripts/miq_application.js b/app/assets/javascripts/miq_application.js
index 60bd1ed7e03..067c1a212fb 100644
--- a/app/assets/javascripts/miq_application.js
+++ b/app/assets/javascripts/miq_application.js
@@ -20,11 +20,6 @@ function miqOnLoad() {
miqBuildCalendar();
- // Init the toolbars
- if (typeof miqInitToolbars === 'function') {
- miqInitToolbars();
- }
-
// Initialize the dashboard widget pulldown
if (miqDomElementExists('widget_select_div')) {
miqInitWidgetPulldown();
@@ -61,12 +56,6 @@ function miqPrepRightCellForm(tree) {
miqDimDiv(tree + '_div', true);
}
-// Initialize the widget pulldown on the dashboard
-function miqInitWidgetPulldown() {
- $('#dashboard_dropdown button:not(.dropdown-toggle), #toolbar ul.dropdown-menu > li > a').off('click');
- $('#dashboard_dropdown button:not(.dropdown-toggle), #toolbar ul.dropdown-menu > li > a').on('click', miqWidgetToolbarClick);
-}
-
function miqCalendarDateConversion(server_offset) {
return moment().utcOffset(Number(server_offset) / 60).toDate();
}
@@ -1316,186 +1305,6 @@ function miqAccordionSwap(_collapse, expand) {
ManageIQ.noCollapseEvent = false;
}
-// This function is called in miqOnLoad
-function miqInitToolbars() {
- $('#toolbar:not(.miq-toolbar-menu) button:not(.dropdown-toggle), ' +
- '#toolbar:not(.miq-toolbar-menu) ul.dropdown-menu > li > a, ' +
- '#toolbar:not(.miq-toolbar-menu) .toolbar-pf-view-selector > ul.list-inline > li > a'
- ).off('click');
- $('#toolbar:not(.miq-toolbar-menu) button:not(.dropdown-toggle), ' +
- '#toolbar:not(.miq-toolbar-menu) ul.dropdown-menu > li > a, ' +
- '#toolbar:not(.miq-toolbar-menu) .toolbar-pf-view-selector > ul.list-inline > li > a'
- ).click(function() {
- miqToolbarOnClick.bind(this)();
- return false;
- });
-}
-
-// Function to run transactions when toolbar button is clicked
-function miqToolbarOnClick(_e) {
- var tb_url;
- var button = $(this);
- var popup = false;
-
- // If it's a dropdown, collapse the parent container
- var parent = button.parents('div.btn-group.dropdown.open');
- parent.removeClass('open');
- parent.children('button.dropdown-toggle').attr('aria-expanded', 'false');
-
- if (button.hasClass('disabled') || button.parent().hasClass('disabled')) {
- return;
- }
-
- if (button.parents('#dashboard_dropdown').length > 0) {
- return;
- }
-
- if (button.data('confirm-tb') && !button.data('popup')) {
- if (!confirm(button.data('confirm-tb'))) {
- return;
- }
- }
-
- if (button.data('popup')) {
- if (!button.data('confirm-tb') || confirm(button.data('confirm-tb'))) {
- // popup windows are only supported for urls starting with '/' (non-ajax)
- popup = true;
- }
- }
-
- if (button.data('url')) {
- // See if a url is defined
- if (button.data('url').indexOf('/') === 0) {
- // If url starts with / it is non-ajax
- tb_url = '/' + ManageIQ.controller + button.data('url');
- if (ManageIQ.record.recordId !== null) {
- // remove last '/' if exist
- tb_url = tb_url.replace(/\/$/, '');
- tb_url += '/' + ManageIQ.record.recordId;
- }
- if (button.data('url_parms')) {
- tb_url += button.data('url_parms');
- }
- if (popup) {
- window.open(tb_url);
- } else {
- DoNav(encodeURI(tb_url));
- }
- return;
- }
-
- // An ajax url was defined
- tb_url = '/' + ManageIQ.controller + '/' + button.data('url');
- if (button.data('url').indexOf('x_history') !== 0) {
- // If not an explorer history button
- if (ManageIQ.record.recordId !== null) {
- tb_url += '/' + ManageIQ.record.recordId;
- }
- }
- } else if (button.data('function')) {
- // support data-function and data-function-data
- var fn = new Function('return ' + button.data('function')); // eval - returns a function returning the right function
- fn().call(button, button.data('functionData'));
- return false;
- } else {
- // No url specified, run standard button ajax transaction
- if (typeof button.data('explorer') !== 'undefined' && button.data('explorer')) {
- // Use x_button method for explorer ajax
- tb_url = '/' + ManageIQ.controller + '/x_button';
- } else {
- tb_url = '/' + ManageIQ.controller + '/button';
- }
- if (ManageIQ.record.recordId !== null) {
- tb_url += '/' + ManageIQ.record.recordId;
- }
- tb_url += '?pressed=';
- if (typeof button.data('pressed') === 'undefined' && button.data('click')) {
- tb_url += button.data('click').split('__').pop();
- } else {
- tb_url += button.data('pressed');
- }
- }
-
- if (button.data('prompt')) {
- tb_url = miqSupportCasePrompt(tb_url);
- if (!tb_url) {
- return false;
- }
- }
-
- // put url_parms into params var, if defined
- var paramstring = getParams(button.data('url_parms'), !!button.data('send_checked'));
-
- // TODO:
- // Checking for perf_reload button to not turn off spinning Q (will be done after charts are drawn).
- // Checking for Report download button to allow controller method to turn off spinner
- // Need to design this feature into the toolbar button support at a later time.
- var no_complete = _.includes([
- 'perf_reload',
- 'vm_perf_reload',
- 'download_choice__render_report_csv',
- 'download_choice__render_report_pdf',
- 'download_choice__render_report_txt',
- 'custom_button_vmdb_choice__ab_button_simulate',
- 'catalogitem_button_vmdb_choice__ab_button_simulate',
- ], button.attr('name')) || button.attr('name').match(/_console$/);
-
- var options = {
- beforeSend: true,
- complete: !no_complete,
- data: paramstring,
- };
-
- return miqJqueryRequest(tb_url, options);
-
- function getParams(urlParms, sendChecked) {
- var params = [];
-
- if (urlParms && (urlParms[0] === '?')) {
- params.push( urlParms.slice(1) );
- }
-
- // FIXME - don't depend on length
- // (but then params[:miq_grid_checks] || params[:id] does the wrong thing)
- if (sendChecked && ManageIQ.gridChecks.length) {
- params.push('miq_grid_checks=' + ManageIQ.gridChecks.join(','));
- }
-
- if (urlParms && urlParms.match('_div$')) {
- params.push(miqSerializeForm(urlParms));
- }
-
- return _.filter(params).join('&') || undefined;
- }
-}
-
-function miqSupportCasePrompt(tb_url) {
- var supportCase = prompt(__('Enter Support Case:'), '');
- if (supportCase === null) {
- return false;
- } else if (supportCase.trim() === '') {
- alert(__('Support Case must be provided to collect logs'));
- return false;
- }
-
- var url = tb_url + '&support_case=' + encodeURIComponent(supportCase);
- return url;
-}
-
-// Handle chart context menu clicks
-function miqWidgetToolbarClick(_e) {
- var itemId = $(this).data('click');
- if (itemId === 'reset') {
- if (confirm(__("Are you sure you want to reset this Dashboard's Widgets to the defaults?"))) {
- miqAjax('/dashboard/reset_widgets');
- }
- } else if (itemId === 'add_widget') {
- return;
- } else {
- miqJqueryRequest('/dashboard/widget_add?widget=' + itemId, {beforeSend: true});
- }
-}
-
function miqInitAccordions() {
var height = $('#left_div').height() - $('#toolbar').outerHeight() - $('#breadcrumbs').outerHeight();
var panel = $('#left_div .panel-heading').outerHeight();
diff --git a/app/assets/javascripts/miq_explorer.js b/app/assets/javascripts/miq_explorer.js
index 4c5939fc5e3..d2bd040d076 100644
--- a/app/assets/javascripts/miq_explorer.js
+++ b/app/assets/javascripts/miq_explorer.js
@@ -1,5 +1,5 @@
/* global miqAccordionSwap miqAddNodeChildren miqAsyncAjax miqBuildCalendar miqButtons miqDeleteTreeCookies miqDomElementExists miqExpandParentNodes miqInitDashboardCols
- * miqInitAccordions miqInitMainContent miqInitToolbars miqRemoveNodeChildren miqSparkle miqSparkleOff miqTreeActivateNode miqTreeActivateNodeSilently miqTreeFindNodeByKey miqTreeObject load_c3_charts miqGtlSetExtraClasses */
+ * miqInitAccordions miqInitMainContent miqRemoveNodeChildren miqSparkle miqSparkleOff miqTreeActivateNode miqTreeActivateNodeSilently miqTreeFindNodeByKey miqTreeObject load_c3_charts miqGtlSetExtraClasses */
ManageIQ.explorer = {};
ManageIQ.explorer.updateElement = function(element, options) {
@@ -296,7 +296,6 @@ ManageIQ.explorer.processReplaceRightCell = function(data) {
_.forEach(data.reloadToolbars, function(content, element) {
$('#' + element).html(content);
});
- miqInitToolbars();
}
ManageIQ.record = data.record;
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index a630091f027..06aaffa9b65 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -42,6 +42,7 @@ $login-container-details-border-color-rgba: rgba(0, 0, 0, 0.5);
@import "codemirror_editor";
@import "dynamic_prefix_form_input";
@import "report-data-table";
+@import "topology-toolbar";
.login-pf #brand img { // sets size of brand.svg on login screen (upstream only)
height: 38px;
diff --git a/app/assets/stylesheets/topology-toolbar.scss b/app/assets/stylesheets/topology-toolbar.scss
new file mode 100644
index 00000000000..7c258cc1ecd
--- /dev/null
+++ b/app/assets/stylesheets/topology-toolbar.scss
@@ -0,0 +1,11 @@
+.topology-tb .has-clear .clear {
+ background: rgba(255, 255, 255, 0);
+ border-width: 0;
+ height: 25px;
+ line-height: 1;
+ padding: 0;
+ position: absolute;
+ right: 1px;
+ top: 1px;
+ width: 28px;
+}
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index debfd2df7fd..0e242e064f9 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -432,7 +432,7 @@ def db_to_controller(db, action = "show")
# Method to create the center toolbar XML
def build_toolbar(tb_name)
- _toolbar_builder.call(tb_name)
+ _toolbar_builder.build_toolbar(tb_name)
end
def _toolbar_builder
diff --git a/app/helpers/application_helper/button/basic.rb b/app/helpers/application_helper/button/basic.rb
index ee3976a8892..e32ec6cfb90 100644
--- a/app/helpers/application_helper/button/basic.rb
+++ b/app/helpers/application_helper/button/basic.rb
@@ -30,7 +30,7 @@ def localized(key, value = nil)
self[key] = value if value
case self[key]
- when NilClass then ''
+ when NilClass then nil
when Proc then instance_eval(&self[key])
else _(self[key])
end
diff --git a/app/helpers/application_helper/toolbar/base.rb b/app/helpers/application_helper/toolbar/base.rb
index aa0ea7353ec..1b099a27c98 100644
--- a/app/helpers/application_helper/toolbar/base.rb
+++ b/app/helpers/application_helper/toolbar/base.rb
@@ -3,8 +3,8 @@ class ApplicationHelper::Toolbar::Base
extend SingleForwardable
delegate %i[api_button button select twostate separator definition button_group custom_content] => :instance
- def custom_content(name, args)
- @definition[name] = ApplicationHelper::Toolbar::Custom.new(name, args)
+ def custom_content(name, props = nil)
+ @definition[name] = ApplicationHelper::Toolbar::Custom.new(name, props)
end
def button_group(name, buttons)
diff --git a/app/helpers/application_helper/toolbar/catalogitem_button_center.rb b/app/helpers/application_helper/toolbar/catalogitem_button_center.rb
index b26d90ad0a7..a9dec75d7b6 100644
--- a/app/helpers/application_helper/toolbar/catalogitem_button_center.rb
+++ b/app/helpers/application_helper/toolbar/catalogitem_button_center.rb
@@ -29,9 +29,10 @@ class ApplicationHelper::Toolbar::CatalogitemButtonCenter < ApplicationHelper::T
'fa fa-play-circle-o fa-lg',
N_('Simulate using Button details'),
N_('Simulate'),
- :klass => ApplicationHelper::Button::CatalogItemButton,
- :url => "resolve",
- :url_parms => "?button=simulate"),
+ :keepSpinner => true,
+ :klass => ApplicationHelper::Button::CatalogItemButton,
+ :url => "resolve",
+ :url_parms => "?button=simulate"),
]
),
])
diff --git a/app/helpers/application_helper/toolbar/cloud/instance_operations_button_group_mixin.rb b/app/helpers/application_helper/toolbar/cloud/instance_operations_button_group_mixin.rb
index 5623b265e38..e7776d2e795 100644
--- a/app/helpers/application_helper/toolbar/cloud/instance_operations_button_group_mixin.rb
+++ b/app/helpers/application_helper/toolbar/cloud/instance_operations_button_group_mixin.rb
@@ -112,15 +112,17 @@ def self.included(included_class)
'pficon pficon-screen fa-lg',
N_('Open a web-based HTML5 console for this VM'),
N_('VM Console'),
- :url => "html5_console",
- :klass => ApplicationHelper::Button::VmHtml5Console),
+ :keepSpinner => true,
+ :url => "html5_console",
+ :klass => ApplicationHelper::Button::VmHtml5Console),
included_class.button(
:cockpit_console,
'pficon pficon-screen fa-lg',
N_('Open a new browser window with Cockpit for this VM. This requires that Cockpit is pre-configured on the VM.'),
N_('Web Console'),
- :url => "launch_cockpit",
- :klass => ApplicationHelper::Button::CockpitConsole
+ :keepSpinner => true,
+ :url => "launch_cockpit",
+ :klass => ApplicationHelper::Button::CockpitConsole
),
]
),
diff --git a/app/helpers/application_helper/toolbar/container_node_center.rb b/app/helpers/application_helper/toolbar/container_node_center.rb
index f543e3c20c3..07c485baae2 100644
--- a/app/helpers/application_helper/toolbar/container_node_center.rb
+++ b/app/helpers/application_helper/toolbar/container_node_center.rb
@@ -77,8 +77,9 @@ class ApplicationHelper::Toolbar::ContainerNodeCenter < ApplicationHelper::Toolb
'pficon pficon-screen fa-lg',
N_('Open a new browser window with Cockpit for this VM. This requires that Cockpit is pre-configured on the VM.'),
N_('Web Console'),
- :url => "launch_cockpit",
- :klass => ApplicationHelper::Button::CockpitConsole
+ :keepSpinner => true,
+ :url => "launch_cockpit",
+ :klass => ApplicationHelper::Button::CockpitConsole
),
])
end
diff --git a/app/helpers/application_helper/toolbar/custom.rb b/app/helpers/application_helper/toolbar/custom.rb
index 786d18d5c81..ad4e3a5b2aa 100644
--- a/app/helpers/application_helper/toolbar/custom.rb
+++ b/app/helpers/application_helper/toolbar/custom.rb
@@ -1,8 +1,6 @@
-ApplicationHelper::Toolbar::Custom = Struct.new(:name, :args) do
- def render(view_context)
- # FIXME: assigns? locals? view_binding? instance_data?
- @content = view_context.render :partial => args[:partial]
+ApplicationHelper::Toolbar::Custom = Struct.new(:name, :props) do
+ def evaluate(view_context)
+ # Collect properties for the React toolbar component from controller (view_context).
+ props ? view_context.instance_eval(&props) : {}
end
-
- attr_reader :content
end
diff --git a/app/helpers/application_helper/toolbar/custom_button_center.rb b/app/helpers/application_helper/toolbar/custom_button_center.rb
index 1daeeb11ef0..6b020da822f 100644
--- a/app/helpers/application_helper/toolbar/custom_button_center.rb
+++ b/app/helpers/application_helper/toolbar/custom_button_center.rb
@@ -27,8 +27,9 @@ class ApplicationHelper::Toolbar::CustomButtonCenter < ApplicationHelper::Toolba
'fa fa-play-circle-o fa-lg',
N_('Simulate using Button details'),
N_('Simulate'),
- :url => "resolve",
- :url_parms => "?button=simulate"),
+ :keepSpinner => true,
+ :url => "resolve",
+ :url_parms => "?button=simulate"),
]
),
])
diff --git a/app/helpers/application_helper/toolbar/dashboard_center.rb b/app/helpers/application_helper/toolbar/dashboard_center.rb
index b23e1cc80e0..feb03bbc8b0 100644
--- a/app/helpers/application_helper/toolbar/dashboard_center.rb
+++ b/app/helpers/application_helper/toolbar/dashboard_center.rb
@@ -1,3 +1,13 @@
class ApplicationHelper::Toolbar::DashboardCenter < ApplicationHelper::Toolbar::Basic
- custom_content('custom', :partial => 'dashboard/dropdownbar')
+ custom_content(
+ 'dashboard',
+ proc do
+ {
+ :allowAdd => @widgets_menu[:allow_add],
+ :allowReset => @widgets_menu[:allow_reset],
+ :locked => !!@widgets_menu[:locked],
+ :items => @widgets_menu[:items],
+ }
+ end
+ )
end
diff --git a/app/helpers/application_helper/toolbar/ems_physical_infra_center.rb b/app/helpers/application_helper/toolbar/ems_physical_infra_center.rb
index 4a6dee6e7ab..87566eed4bb 100644
--- a/app/helpers/application_helper/toolbar/ems_physical_infra_center.rb
+++ b/app/helpers/application_helper/toolbar/ems_physical_infra_center.rb
@@ -89,10 +89,11 @@ class ApplicationHelper::Toolbar::EmsPhysicalInfraCenter < ApplicationHelper::To
'pficon pficon-screen fa-lg',
N_('Open a web-based console for this provider'),
N_('Management Console'),
- :url => "launch_console",
- :confirm => N_("Open management console for this provider"),
- :klass => ApplicationHelper::Button::PhysicalInfraConsole,
- :options => {:feature => :console})
+ :keepSpinner => true,
+ :url => "launch_console",
+ :confirm => N_("Open management console for this provider"),
+ :klass => ApplicationHelper::Button::PhysicalInfraConsole,
+ :options => {:feature => :console})
]
),
])
diff --git a/app/helpers/application_helper/toolbar/logs_center.rb b/app/helpers/application_helper/toolbar/logs_center.rb
index eaab70528a5..11d3b53daff 100644
--- a/app/helpers/application_helper/toolbar/logs_center.rb
+++ b/app/helpers/application_helper/toolbar/logs_center.rb
@@ -3,9 +3,7 @@ class ApplicationHelper::Toolbar::LogsCenter < ApplicationHelper::Toolbar::Basic
button(
:refresh_log,
'fa fa-refresh fa-lg',
- proc do
- _('Refresh this page')
- end,
+ N_('Refresh this page'),
nil),
button(
:fetch_log,
diff --git a/app/helpers/application_helper/toolbar/physical_server_center.rb b/app/helpers/application_helper/toolbar/physical_server_center.rb
index c2b947eea41..2bb801bd785 100644
--- a/app/helpers/application_helper/toolbar/physical_server_center.rb
+++ b/app/helpers/application_helper/toolbar/physical_server_center.rb
@@ -75,7 +75,6 @@ class ApplicationHelper::Toolbar::PhysicalServerCenter < ApplicationHelper::Tool
:url => "provision",
:url_parms => "main_div",
:enabled => true,
- :onwhen => "0+",
:klass => ApplicationHelper::Button::ConfiguredSystemProvision
)
]
@@ -120,10 +119,11 @@ class ApplicationHelper::Toolbar::PhysicalServerCenter < ApplicationHelper::Tool
'pficon pficon-screen fa-lg',
N_('Open a remote console for this Physical Server'),
N_('Physical Server Console'),
- :url => "console",
- :method => :get,
- :enabled => true,
- :options => {:feature => :physical_server_remote_access}
+ :keepSpinner => true,
+ :url => "console",
+ :method => :get,
+ :enabled => true,
+ :options => {:feature => :physical_server_remote_access}
)
],
),
diff --git a/app/helpers/application_helper/toolbar/report_view.rb b/app/helpers/application_helper/toolbar/report_view.rb
index 82185a71bf4..99292de9993 100644
--- a/app/helpers/application_helper/toolbar/report_view.rb
+++ b/app/helpers/application_helper/toolbar/report_view.rb
@@ -46,22 +46,25 @@ class ApplicationHelper::Toolbar::ReportView < ApplicationHelper::Toolbar::Basic
'fa fa-file-text-o fa-lg',
N_('Download this report in text format'),
N_('Download as Text'),
- :url_parms => "?render_type=txt",
- :klass => ApplicationHelper::Button::RenderReport),
+ :keepSpinner => true,
+ :url_parms => "?render_type=txt",
+ :klass => ApplicationHelper::Button::RenderReport),
button(
:render_report_csv,
'fa fa-file-text-o fa-lg',
N_('Download this report in CSV format'),
N_('Download as CSV'),
- :url_parms => "?render_type=csv",
- :klass => ApplicationHelper::Button::RenderReport),
+ :keepSpinner => true,
+ :url_parms => "?render_type=csv",
+ :klass => ApplicationHelper::Button::RenderReport),
button(
:render_report_pdf,
'pficon pficon-print fa-lg',
N_('Print or export this report in PDF format'),
N_('Print or export as PDF'),
- :klass => ApplicationHelper::Button::RenderReport,
- :url_parms => "?render_type=pdf"),
+ :keepSpinner => true,
+ :klass => ApplicationHelper::Button::RenderReport,
+ :url_parms => "?render_type=pdf"),
]
),
])
diff --git a/app/helpers/application_helper/toolbar/topology_center.rb b/app/helpers/application_helper/toolbar/topology_center.rb
index 72b0e6153ce..7975dad59a0 100644
--- a/app/helpers/application_helper/toolbar/topology_center.rb
+++ b/app/helpers/application_helper/toolbar/topology_center.rb
@@ -1,3 +1,3 @@
class ApplicationHelper::Toolbar::TopologyCenter < ApplicationHelper::Toolbar::Basic
- custom_content('custom', :partial => 'shared/topology_header_toolbar')
+ custom_content('topology')
end
diff --git a/app/helpers/application_helper/toolbar/vm_performance.rb b/app/helpers/application_helper/toolbar/vm_performance.rb
index a1d95f1085d..c2424f6e54c 100644
--- a/app/helpers/application_helper/toolbar/vm_performance.rb
+++ b/app/helpers/application_helper/toolbar/vm_performance.rb
@@ -12,6 +12,7 @@ class ApplicationHelper::Toolbar::VmPerformance < ApplicationHelper::Toolbar::Ba
'fa fa-repeat fa-lg',
N_('Reload the charts from the most recent C&U data'),
nil,
- :klass => ApplicationHelper::Button::PerfRefresh),
+ :keepSpinner => true,
+ :klass => ApplicationHelper::Button::PerfRefresh),
])
end
diff --git a/app/helpers/application_helper/toolbar/x_vm_center.rb b/app/helpers/application_helper/toolbar/x_vm_center.rb
index 67b6e5e0af4..f4d678de680 100644
--- a/app/helpers/application_helper/toolbar/x_vm_center.rb
+++ b/app/helpers/application_helper/toolbar/x_vm_center.rb
@@ -267,23 +267,26 @@ class ApplicationHelper::Toolbar::XVmCenter < ApplicationHelper::Toolbar::Basic
'pficon pficon-screen fa-lg',
N_('Open a web-based HTML5 console for this VM'),
N_('VM Console'),
- :url => "html5_console",
- :klass => ApplicationHelper::Button::VmHtml5Console),
+ :keepSpinner => true,
+ :url => "html5_console",
+ :klass => ApplicationHelper::Button::VmHtml5Console),
button(
:vm_vmrc_console,
'pficon pficon-screen fa-lg',
N_('Open a VMRC console for this VM. This requires that VMRC is installed and pre-configured to work in your browser.'),
N_('VMRC Console'),
- :url => "vmrc_console",
- :confirm => N_("Opening a VMRC console requires that VMRC is installed and pre-configured to work in your browser. Are you sure?"),
+ :keepSpinner => true,
+ :url => "vmrc_console",
+ :confirm => N_("Opening a VMRC console requires that VMRC is installed and pre-configured to work in your browser. Are you sure?"),
:klass => ApplicationHelper::Button::VmVmrcConsole),
button(
:cockpit_console,
'pficon pficon-screen fa-lg',
N_('Open a new browser window with Cockpit for this VM. This requires that Cockpit is pre-configured on the VM.'),
N_('Web Console'),
- :url => "launch_cockpit",
- :klass => ApplicationHelper::Button::CockpitConsole
+ :keepSpinner => true,
+ :url => "launch_cockpit",
+ :klass => ApplicationHelper::Button::CockpitConsole
),
]
),
diff --git a/app/helpers/application_helper/toolbar/x_vm_performance.rb b/app/helpers/application_helper/toolbar/x_vm_performance.rb
index 28cc23458e3..d3f3e1b0757 100644
--- a/app/helpers/application_helper/toolbar/x_vm_performance.rb
+++ b/app/helpers/application_helper/toolbar/x_vm_performance.rb
@@ -12,6 +12,7 @@ class ApplicationHelper::Toolbar::XVmPerformance < ApplicationHelper::Toolbar::B
'fa fa-repeat fa-lg',
N_('Reload the charts from the most recent C&U data'),
nil,
- :klass => ApplicationHelper::Button::PerfRefresh),
+ :keepSpinner => true,
+ :klass => ApplicationHelper::Button::PerfRefresh),
])
end
diff --git a/app/helpers/application_helper/toolbar_builder.rb b/app/helpers/application_helper/toolbar_builder.rb
index e222e4477e9..739638d8f8b 100644
--- a/app/helpers/application_helper/toolbar_builder.rb
+++ b/app/helpers/application_helper/toolbar_builder.rb
@@ -3,10 +3,6 @@ class ApplicationHelper::ToolbarBuilder
include RestfulControllerMixin
include ApplicationHelper::Toolbar::Mixins::CustomButtonToolbarMixin
- def call(toolbar_name)
- build_toolbar(toolbar_name)
- end
-
# Loads the toolbar sent in parameter `toolbar_name`, and builds the buttons
# in the toolbar, unless the group of buttons is meant to be skipped.
#
@@ -121,12 +117,11 @@ def apply_common_props(button, input)
:icon => input[:icon],
:name => button[:id],
:onwhen => input[:onwhen],
- :pressed => input[:pressed],
:send_checked => input[:send_checked],
)
- button[:enabled] = input[:enabled]
- %i[title text confirm enabled].each do |key|
+ button[:enabled] = !!input[:enabled] if input.key?(:enabled)
+ %i[title text confirm].each do |key|
if input[key].present?
button[key] = button.localized(key, input[key])
end
@@ -454,9 +449,7 @@ def build_toolbar_from_class(toolbar_class, record)
build_button(bgi, group_index)
end
when ApplicationHelper::Toolbar::Custom
- rendered_html = group.render(@view_context).tr('\'', '"')
- group[:args][:html] = ERB::Util.html_escape(rendered_html).html_safe
- @toolbar << group
+ @toolbar << { :custom => true, :name => group.name, :props => group.evaluate(@view_context) }
end
end
diff --git a/app/helpers/toolbar_helper.rb b/app/helpers/toolbar_helper.rb
index 43e008d44d5..32dbd25b86b 100644
--- a/app/helpers/toolbar_helper.rb
+++ b/app/helpers/toolbar_helper.rb
@@ -5,6 +5,6 @@ module ToolbarHelper
def toolbar_from_hash
calculate_toolbars.collect do |_div_id, toolbar_name|
toolbar_name ? build_toolbar(toolbar_name) : nil
- end
+ end.compact
end
end
diff --git a/app/javascript/components/dashboard_toolbar.jsx b/app/javascript/components/dashboard_toolbar.jsx
new file mode 100644
index 00000000000..4b5a24359db
--- /dev/null
+++ b/app/javascript/components/dashboard_toolbar.jsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Dropdown, MenuItem } from 'patternfly-react';
+
+const addClick = item =>
+ window.miqJqueryRequest(`widget_add?widget=${item.id}`, { beforeSend: true, complete: true });
+
+const resetClick = () => {
+ /* eslint no-alert: off */
+ if (window.confirm(__("Are you sure you want to reset this Dashboard's Widgets to the defaults?"))) {
+ window.miqJqueryRequest('reset_widgets', { beforeSend: true });
+ }
+};
+
+const resetButton = () => (
+
+);
+
+const addMenu = (items, locked) => {
+ const title = locked
+ ? __('Cannot add a Widget, this Dashboard has been locked by the Administrator')
+ : __('Add a widget');
+
+ return (
+