diff --git a/app/javascript/components/miq-data-table/index.jsx b/app/javascript/components/miq-data-table/index.jsx
index a9d1332861d..cb2c3af58bd 100644
--- a/app/javascript/components/miq-data-table/index.jsx
+++ b/app/javascript/components/miq-data-table/index.jsx
@@ -100,9 +100,11 @@ const MiqDataTable = ({
isSortable={isSortable}
isSortHeader={sortHeader}
sortDirection={sortDirection}
- className={
- classNames('miq-data-table-header', (header.contentButton ? 'header-button' : ''), (header.actionCell ? 'action-cell-holder' : ''))
- }
+ className={classNames(
+ 'miq-data-table-header',
+ header.contentButton ? 'header-button' : '',
+ header.actionCell ? 'action-cell-holder' : ''
+ )}
>
{headerLabel(header.header)}
@@ -148,15 +150,17 @@ const MiqDataTable = ({
stickyHeader={stickyHeader}
>
{({
- rows, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
+ rows, headers, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
}) => (
-
-
- {rowCheckBox && selectAll(getSelectionProps)}
- {renderHeaders(getHeaderProps)}
-
-
+ {headers[0] && headers[0].header !== '' ? (
+
+
+ {rowCheckBox && selectAll(getSelectionProps)}
+ {renderHeaders(getHeaderProps)}
+
+
+ ) : undefined}
{sortableRows(rows).map((row, index) => {
const item = propRows[index];
diff --git a/app/javascript/components/settings-details-tab/index.jsx b/app/javascript/components/settings-details-tab/index.jsx
new file mode 100644
index 00000000000..15d0f3f5cba
--- /dev/null
+++ b/app/javascript/components/settings-details-tab/index.jsx
@@ -0,0 +1,72 @@
+import React, { useState } from 'react';
+import MiqDataTable from '../miq-data-table';
+import RegionForm from '../region-form';
+
+const settingsDetailsTab = ({
+ region, scanItemsCount, zonesCount, miqSchedulesCount,
+}) => {
+ const [rows, setRows] = useState([
+ {
+ id: '0',
+ region: {
+ text: `${region.description} [${region.region}]`,
+ icon: 'carbon--Db2Database',
+ },
+ treeBox: 'settings_tree',
+ },
+ {
+ id: '1',
+ region: {
+ text: `${__('Analysis Profiles')} (${scanItemsCount})`,
+ icon: 'carbon--Search',
+ },
+ treeBox: 'settings_tree',
+ nodeKey: 'xx-sis',
+ },
+ {
+ id: '2',
+ region: {
+ text: `${__('Zones')} (${zonesCount})`,
+ icon: 'carbon--ChartVennDiagram',
+ },
+ treeBox: 'settings_tree',
+ nodeKey: 'xx-z',
+ },
+ {
+ id: '3',
+ region: {
+ text: `${__('Schedules')} (${miqSchedulesCount})`,
+ icon: 'carbon--Time',
+ },
+ treeBox: 'settings_tree',
+ nodeKey: 'xx-msc',
+ },
+ ]);
+
+ const headers = [
+ {
+ key: 'region',
+ header: '',
+ },
+ ];
+
+ const onSelect = (selectedRow) => {
+ const selected = rows.find((row) => row.id === selectedRow.id);
+ if (selected.nodeKey) {
+ miqTreeActivateNode(selected.treeBox, selected.nodeKey);
+ } else {
+ setRows((prevRows) => prevRows.filter((row) => row.id !== '0'));
+ }
+ };
+
+ return (
+
+ {rows.find((row) => row.id === '0') === undefined && (
+
+ )}
+ onSelect(selectedRow)} />
+
+ );
+};
+
+export default settingsDetailsTab;
diff --git a/app/javascript/packs/component-definitions-common.js b/app/javascript/packs/component-definitions-common.js
index f56709a0b77..a196a68e5cd 100644
--- a/app/javascript/packs/component-definitions-common.js
+++ b/app/javascript/packs/component-definitions-common.js
@@ -134,6 +134,7 @@ import SettingsCategoryForm from '../components/settings-category-form';
import SettingsCompanyCategories from '../components/settings-company-categories';
import SettingsCompanyTags from '../components/settings-company-tags';
import SettingsCompanyTagsEntryForm from '../components/settings-company-tags-entry-form';
+import SettingsDetailsTab from '../components/settings-details-tab';
import SettingsLabelTagMapping from '../components/settings-label-tag-mapping';
import SettingsTasksForm from '../components/settings-tasks-form';
import SettingsTimeProfileForm from '../components/settings-time-profile-form';
@@ -315,6 +316,7 @@ ManageIQ.component.addReact('SettingsCategoryForm', SettingsCategoryForm);
ManageIQ.component.addReact('SettingsCompanyCategories', SettingsCompanyCategories);
ManageIQ.component.addReact('SettingsCompanyTags', SettingsCompanyTags);
ManageIQ.component.addReact('SettingsCompanyTagsEntryForm', SettingsCompanyTagsEntryForm);
+ManageIQ.component.addReact('SettingsDetailsTab', SettingsDetailsTab);
ManageIQ.component.addReact('SettingsLabelTagMapping', SettingsLabelTagMapping);
ManageIQ.component.addReact('SettingsTasksForm', SettingsTasksForm);
ManageIQ.component.addReact('SettingsTimeProfileForm', SettingsTimeProfileForm);
diff --git a/app/javascript/spec/settings-details-tab/__snapshots__/settings-details-tab.spec.js.snap b/app/javascript/spec/settings-details-tab/__snapshots__/settings-details-tab.spec.js.snap
new file mode 100644
index 00000000000..e9b53ac45e4
--- /dev/null
+++ b/app/javascript/spec/settings-details-tab/__snapshots__/settings-details-tab.spec.js.snap
@@ -0,0 +1,17 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`SettingsDetailsTab Component should render settings details tab 1`] = `
+
+`;
diff --git a/app/javascript/spec/settings-details-tab/settings-details-tab.spec.js b/app/javascript/spec/settings-details-tab/settings-details-tab.spec.js
new file mode 100644
index 00000000000..a9771d0be75
--- /dev/null
+++ b/app/javascript/spec/settings-details-tab/settings-details-tab.spec.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import fetchMock from 'fetch-mock';
+import { shallow } from 'enzyme';
+import toJson from 'enzyme-to-json';
+import settingsDetailsTab from '../../components/settings-details-tab';
+
+describe('SettingsDetailsTab Component', () => {
+ const region = {
+ id: 1,
+ region: 0,
+ description: 'Region 3',
+ maintenance_zone_id: 1,
+ };
+
+ const scanItemsCount = 3;
+ const zonesCount = 1;
+ const miqSchedulesCount = 0;
+
+ afterEach(() => {
+ fetchMock.reset();
+ fetchMock.restore();
+ });
+
+ it('should render settings details tab', async() => {
+ const wrapper = shallow();
+
+ await new Promise((resolve) => {
+ setImmediate(() => {
+ wrapper.update();
+ expect(toJson(wrapper)).toMatchSnapshot();
+ resolve();
+ });
+ });
+ });
+});
diff --git a/app/stylesheet/settings.scss b/app/stylesheet/settings.scss
index 36dcfeadbab..d55ecf4e42a 100644
--- a/app/stylesheet/settings.scss
+++ b/app/stylesheet/settings.scss
@@ -45,3 +45,7 @@
color: red;
}
}
+
+.bx--front-line {
+ margin-left: 10px;
+}
diff --git a/app/views/ops/_settings_details_tab.html.haml b/app/views/ops/_settings_details_tab.html.haml
index a32d1a740c1..d607edca29d 100644
--- a/app/views/ops/_settings_details_tab.html.haml
+++ b/app/views/ops/_settings_details_tab.html.haml
@@ -7,32 +7,9 @@
%table.table.table-striped.table-bordered.table-hover
%tbody
- - unless @edit
- %tr
- %td.table-view-pf-select{:onclick => remote_function(:url => {:action => 'region_edit', :id => region.id},
- :loading => "miqSparkle(true);"),
- :title => _("Edit this Region")}
- %i.pficon.pficon-regions
- %td{:onclick => remote_function(:url => {:action => 'region_edit', :id => region.id},
- :loading => "miqSparkle(true);"),
- :title => _("Edit this Region")}
- = h(region.description)
- [#{h(region.region)}]
- %tr
- %td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-sis');", :title => _("View Analysis Profiles")}
- %i.fa.fa-search
- %td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-sis');", :title => _("View Analysis Profiles")}
- = _("Analysis Profiles")
- (#{h(@scan_items.size)})
- %tr
- %td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-z');", :title => _("View Zones")}
- %i.pficon.pficon-zone
- %td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-z');", :title => _("View Zones")}
- = _("Zones")
- (#{h(@zones.size)})
- %tr
- %td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-msc');", :title => _("View Schedules")}
- %i.fa.fa-clock-o
- %td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-msc');", :title => _("View Schedules")}
- = _("Schedules")
- (#{h(@miq_schedules.size)})
+ = react('SettingsDetailsTab',
+ :region => region,
+ :scanItemsCount => @scan_items.size,
+ :zonesCount => @zones.size,
+ :miqSchedulesCount => @miq_schedules.size)
+
\ No newline at end of file
diff --git a/cypress/e2e/ui/Settings/Application-Settings/settings_details_tab.cy.js b/cypress/e2e/ui/Settings/Application-Settings/settings_details_tab.cy.js
new file mode 100644
index 00000000000..1d6a0b2e116
--- /dev/null
+++ b/cypress/e2e/ui/Settings/Application-Settings/settings_details_tab.cy.js
@@ -0,0 +1,42 @@
+/* eslint-disable no-undef */
+
+describe('Settings > Application Settings > Details', () => {
+ beforeEach(() => {
+ cy.login();
+ cy.intercept('POST', '/ops/accordion_select?id=rbac_accord').as('accordion');
+ cy.menu('Settings', 'Application Settings');
+ cy.get('[data-nodeid="0.0"].node-treeview-settings_tree').contains('ManageIQ Region').click();
+ cy.get('#explorer_title_text');
+ });
+
+ describe('Settings Details Tab', () => {
+ it('Region row is replaced by region form when clicked', () => {
+ cy.get('.bx--front-line').contains('Region 0').click({force: true});
+ cy.get('.bx--label').contains('Description').should('exist');
+ });
+ it('Clicks on analysis profiles row and reroutes', () => {
+ cy.get('.bx--front-line').contains('Analysis Profiles').click({force: true});
+ cy.get('#explorer_title_text').contains('Settings Analysis Profiles').should('exist');
+ });
+ it('Clicks on zones row and reroutes', () => {
+ cy.get('.bx--front-line').contains('Zones').click({force: true});
+ cy.get('#explorer_title_text').contains('Settings Zones').should('exist');
+ });
+ it('Clicks on schedules row and reroutes', () => {
+ cy.get('.bx--front-line').contains('Schedules').click({force: true});
+ cy.get('#explorer_title_text').contains('Settings Schedules').should('exist');
+ });
+ it('Updates region name when changed', () => {
+ cy.get('.bx--front-line').contains('Region 0').click({force: true});
+ cy.get('#description').clear().type('Region 1');
+ cy.get('button.bx--btn.bx--btn--primary').contains('Save').should('not.be.disabled').click();
+ cy.get('.bx--front-line').contains('Region 1').should('exist');
+
+ // Clean up
+ cy.get('.bx--front-line').contains('Region 1').click({force: true});
+ cy.get('#description').clear().type('Region 0');
+ cy.get('button.bx--btn.bx--btn--primary').contains('Save').should('not.be.disabled').click();
+ cy.get('.bx--front-line').contains('Region 0').should('exist');
+ });
+ });
+});