Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert settings details tab to use carbon components #9270

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions app/javascript/components/miq-data-table/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
</TableHeader>
Expand Down Expand Up @@ -148,15 +150,17 @@ const MiqDataTable = ({
stickyHeader={stickyHeader}
>
{({
rows, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
rows, headers, getTableProps, getHeaderProps, getRowProps, getSelectionProps,
}) => (
<Table {...getTableProps()}>
<TableHead>
<TableRow>
{rowCheckBox && selectAll(getSelectionProps)}
{renderHeaders(getHeaderProps)}
</TableRow>
</TableHead>
{headers[0] && headers[0].header !== '' ? (
<TableHead>
<TableRow>
{rowCheckBox && selectAll(getSelectionProps)}
{renderHeaders(getHeaderProps)}
</TableRow>
</TableHead>
) : undefined}
<TableBody>
{sortableRows(rows).map((row, index) => {
const item = propRows[index];
Expand Down
72 changes: 72 additions & 0 deletions app/javascript/components/settings-details-tab/index.jsx
Original file line number Diff line number Diff line change
@@ -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--CirclePacking',
},
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 (
<div>
{rows.find((row) => row.id === '0') === undefined && (
<RegionForm maxDescLen={255} id={region.id.toString()} />
)}
<MiqDataTable rows={rows} headers={headers} onCellClick={(selectedRow) => onSelect(selectedRow)} />
</div>
);
};

export default settingsDetailsTab;
2 changes: 2 additions & 0 deletions app/javascript/packs/component-definitions-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SettingsDetailsTab Component should render settings details tab 1`] = `
<settingsDetailsTab
miqSchedulesCount={0}
region={
Object {
"description": "Region 3",
"id": 1,
"maintenance_zone_id": 1,
"region": 0,
}
}
scanItemsCount={3}
zonesCount={1}
/>
`;
Original file line number Diff line number Diff line change
@@ -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(<settingsDetailsTab
region={region}
scanItemsCount={scanItemsCount}
zonesCount={zonesCount}
miqSchedulesCount={miqSchedulesCount}
/>);

await new Promise((resolve) => {
setImmediate(() => {
wrapper.update();
expect(toJson(wrapper)).toMatchSnapshot();
resolve();
});
});
});
});
4 changes: 4 additions & 0 deletions app/stylesheet/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@
color: red;
}
}

.bx--front-line {
margin-left: 10px;
}
35 changes: 6 additions & 29 deletions app/views/ops/_settings_details_tab.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Original file line number Diff line number Diff line change
@@ -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');
});
});
});