Skip to content

Commit 8c73066

Browse files
Merge pull request #9270 from liu-samuel/settings-region-table-carbon
Convert settings details tab to use carbon components
2 parents 3fada58 + 256b5f6 commit 8c73066

File tree

8 files changed

+197
-39
lines changed

8 files changed

+197
-39
lines changed

app/javascript/components/miq-data-table/index.jsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ const MiqDataTable = ({
100100
isSortable={isSortable}
101101
isSortHeader={sortHeader}
102102
sortDirection={sortDirection}
103-
className={
104-
classNames('miq-data-table-header', (header.contentButton ? 'header-button' : ''), (header.actionCell ? 'action-cell-holder' : ''))
105-
}
103+
className={classNames(
104+
'miq-data-table-header',
105+
header.contentButton ? 'header-button' : '',
106+
header.actionCell ? 'action-cell-holder' : ''
107+
)}
106108
>
107109
{headerLabel(header.header)}
108110
</TableHeader>
@@ -148,15 +150,17 @@ const MiqDataTable = ({
148150
stickyHeader={stickyHeader}
149151
>
150152
{({
151-
rows, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
153+
rows, headers, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
152154
}) => (
153155
<Table {...getTableProps()}>
154-
<TableHead>
155-
<TableRow>
156-
{rowCheckBox && selectAll(getSelectionProps)}
157-
{renderHeaders(getHeaderProps)}
158-
</TableRow>
159-
</TableHead>
156+
{headers[0] && headers[0].header !== '' ? (
157+
<TableHead>
158+
<TableRow>
159+
{rowCheckBox && selectAll(getSelectionProps)}
160+
{renderHeaders(getHeaderProps)}
161+
</TableRow>
162+
</TableHead>
163+
) : undefined}
160164
<TableBody>
161165
{sortableRows(rows).map((row, index) => {
162166
const item = propRows[index];
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { useState } from 'react';
2+
import MiqDataTable from '../miq-data-table';
3+
import RegionForm from '../region-form';
4+
5+
const settingsDetailsTab = ({
6+
region, scanItemsCount, zonesCount, miqSchedulesCount,
7+
}) => {
8+
const [rows, setRows] = useState([
9+
{
10+
id: '0',
11+
region: {
12+
text: `${region.description} [${region.region}]`,
13+
icon: 'carbon--Db2Database',
14+
},
15+
treeBox: 'settings_tree',
16+
},
17+
{
18+
id: '1',
19+
region: {
20+
text: `${__('Analysis Profiles')} (${scanItemsCount})`,
21+
icon: 'carbon--Search',
22+
},
23+
treeBox: 'settings_tree',
24+
nodeKey: 'xx-sis',
25+
},
26+
{
27+
id: '2',
28+
region: {
29+
text: `${__('Zones')} (${zonesCount})`,
30+
icon: 'carbon--CirclePacking',
31+
},
32+
treeBox: 'settings_tree',
33+
nodeKey: 'xx-z',
34+
},
35+
{
36+
id: '3',
37+
region: {
38+
text: `${__('Schedules')} (${miqSchedulesCount})`,
39+
icon: 'carbon--Time',
40+
},
41+
treeBox: 'settings_tree',
42+
nodeKey: 'xx-msc',
43+
},
44+
]);
45+
46+
const headers = [
47+
{
48+
key: 'region',
49+
header: '',
50+
},
51+
];
52+
53+
const onSelect = (selectedRow) => {
54+
const selected = rows.find((row) => row.id === selectedRow.id);
55+
if (selected.nodeKey) {
56+
miqTreeActivateNode(selected.treeBox, selected.nodeKey);
57+
} else {
58+
setRows((prevRows) => prevRows.filter((row) => row.id !== '0'));
59+
}
60+
};
61+
62+
return (
63+
<div>
64+
{rows.find((row) => row.id === '0') === undefined && (
65+
<RegionForm maxDescLen={255} id={region.id.toString()} />
66+
)}
67+
<MiqDataTable rows={rows} headers={headers} onCellClick={(selectedRow) => onSelect(selectedRow)} />
68+
</div>
69+
);
70+
};
71+
72+
export default settingsDetailsTab;

app/javascript/packs/component-definitions-common.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ import SettingsCategoryForm from '../components/settings-category-form';
134134
import SettingsCompanyCategories from '../components/settings-company-categories';
135135
import SettingsCompanyTags from '../components/settings-company-tags';
136136
import SettingsCompanyTagsEntryForm from '../components/settings-company-tags-entry-form';
137+
import SettingsDetailsTab from '../components/settings-details-tab';
137138
import SettingsLabelTagMapping from '../components/settings-label-tag-mapping';
138139
import SettingsTasksForm from '../components/settings-tasks-form';
139140
import SettingsTimeProfileForm from '../components/settings-time-profile-form';
@@ -315,6 +316,7 @@ ManageIQ.component.addReact('SettingsCategoryForm', SettingsCategoryForm);
315316
ManageIQ.component.addReact('SettingsCompanyCategories', SettingsCompanyCategories);
316317
ManageIQ.component.addReact('SettingsCompanyTags', SettingsCompanyTags);
317318
ManageIQ.component.addReact('SettingsCompanyTagsEntryForm', SettingsCompanyTagsEntryForm);
319+
ManageIQ.component.addReact('SettingsDetailsTab', SettingsDetailsTab);
318320
ManageIQ.component.addReact('SettingsLabelTagMapping', SettingsLabelTagMapping);
319321
ManageIQ.component.addReact('SettingsTasksForm', SettingsTasksForm);
320322
ManageIQ.component.addReact('SettingsTimeProfileForm', SettingsTimeProfileForm);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`SettingsDetailsTab Component should render settings details tab 1`] = `
4+
<settingsDetailsTab
5+
miqSchedulesCount={0}
6+
region={
7+
Object {
8+
"description": "Region 3",
9+
"id": 1,
10+
"maintenance_zone_id": 1,
11+
"region": 0,
12+
}
13+
}
14+
scanItemsCount={3}
15+
zonesCount={1}
16+
/>
17+
`;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import fetchMock from 'fetch-mock';
3+
import { shallow } from 'enzyme';
4+
import toJson from 'enzyme-to-json';
5+
import settingsDetailsTab from '../../components/settings-details-tab';
6+
7+
describe('SettingsDetailsTab Component', () => {
8+
const region = {
9+
id: 1,
10+
region: 0,
11+
description: 'Region 3',
12+
maintenance_zone_id: 1,
13+
};
14+
15+
const scanItemsCount = 3;
16+
const zonesCount = 1;
17+
const miqSchedulesCount = 0;
18+
19+
afterEach(() => {
20+
fetchMock.reset();
21+
fetchMock.restore();
22+
});
23+
24+
it('should render settings details tab', async() => {
25+
const wrapper = shallow(<settingsDetailsTab
26+
region={region}
27+
scanItemsCount={scanItemsCount}
28+
zonesCount={zonesCount}
29+
miqSchedulesCount={miqSchedulesCount}
30+
/>);
31+
32+
await new Promise((resolve) => {
33+
setImmediate(() => {
34+
wrapper.update();
35+
expect(toJson(wrapper)).toMatchSnapshot();
36+
resolve();
37+
});
38+
});
39+
});
40+
});

app/stylesheet/settings.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@
4545
color: red;
4646
}
4747
}
48+
49+
.bx--front-line {
50+
margin-left: 10px;
51+
}

app/views/ops/_settings_details_tab.html.haml

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,9 @@
77

88
%table.table.table-striped.table-bordered.table-hover
99
%tbody
10-
- unless @edit
11-
%tr
12-
%td.table-view-pf-select{:onclick => remote_function(:url => {:action => 'region_edit', :id => region.id},
13-
:loading => "miqSparkle(true);"),
14-
:title => _("Edit this Region")}
15-
%i.pficon.pficon-regions
16-
%td{:onclick => remote_function(:url => {:action => 'region_edit', :id => region.id},
17-
:loading => "miqSparkle(true);"),
18-
:title => _("Edit this Region")}
19-
= h(region.description)
20-
[#{h(region.region)}]
21-
%tr
22-
%td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-sis');", :title => _("View Analysis Profiles")}
23-
%i.fa.fa-search
24-
%td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-sis');", :title => _("View Analysis Profiles")}
25-
= _("Analysis Profiles")
26-
(#{h(@scan_items.size)})
27-
%tr
28-
%td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-z');", :title => _("View Zones")}
29-
%i.pficon.pficon-zone
30-
%td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-z');", :title => _("View Zones")}
31-
= _("Zones")
32-
(#{h(@zones.size)})
33-
%tr
34-
%td.table-view-pf-select{:onclick => "miqTreeActivateNode('settings_tree', 'xx-msc');", :title => _("View Schedules")}
35-
%i.fa.fa-clock-o
36-
%td{:onclick => "miqTreeActivateNode('settings_tree', 'xx-msc');", :title => _("View Schedules")}
37-
= _("Schedules")
38-
(#{h(@miq_schedules.size)})
10+
= react('SettingsDetailsTab',
11+
:region => region,
12+
:scanItemsCount => @scan_items.size,
13+
:zonesCount => @zones.size,
14+
:miqSchedulesCount => @miq_schedules.size)
15+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint-disable no-undef */
2+
3+
describe('Settings > Application Settings > Details', () => {
4+
beforeEach(() => {
5+
cy.login();
6+
cy.intercept('POST', '/ops/accordion_select?id=rbac_accord').as('accordion');
7+
cy.menu('Settings', 'Application Settings');
8+
cy.get('[data-nodeid="0.0"].node-treeview-settings_tree').contains('ManageIQ Region').click();
9+
cy.get('#explorer_title_text');
10+
});
11+
12+
describe('Settings Details Tab', () => {
13+
it('Region row is replaced by region form when clicked', () => {
14+
cy.get('.bx--front-line').contains('Region 0').click({force: true});
15+
cy.get('.bx--label').contains('Description').should('exist');
16+
});
17+
it('Clicks on analysis profiles row and reroutes', () => {
18+
cy.get('.bx--front-line').contains('Analysis Profiles').click({force: true});
19+
cy.get('#explorer_title_text').contains('Settings Analysis Profiles').should('exist');
20+
});
21+
it('Clicks on zones row and reroutes', () => {
22+
cy.get('.bx--front-line').contains('Zones').click({force: true});
23+
cy.get('#explorer_title_text').contains('Settings Zones').should('exist');
24+
});
25+
it('Clicks on schedules row and reroutes', () => {
26+
cy.get('.bx--front-line').contains('Schedules').click({force: true});
27+
cy.get('#explorer_title_text').contains('Settings Schedules').should('exist');
28+
});
29+
it('Updates region name when changed', () => {
30+
cy.get('.bx--front-line').contains('Region 0').click({force: true});
31+
cy.get('#description').clear().type('Region 1');
32+
cy.get('button.bx--btn.bx--btn--primary').contains('Save').should('not.be.disabled').click();
33+
cy.get('.bx--front-line').contains('Region 1').should('exist');
34+
35+
// Clean up
36+
cy.get('.bx--front-line').contains('Region 1').click({force: true});
37+
cy.get('#description').clear().type('Region 0');
38+
cy.get('button.bx--btn.bx--btn--primary').contains('Save').should('not.be.disabled').click();
39+
cy.get('.bx--front-line').contains('Region 0').should('exist');
40+
});
41+
});
42+
});

0 commit comments

Comments
 (0)