Wizard: Improve in-page wizard cosmetically

This commit:
1. Removes the header from the Data Driven Forms wizard
2. Adds padding around the in-page wizard so it is visually consistent
   with the images table
3. Refactors the images table header into a re-usable component that is
   now used in both the images table and the wizard
4. Allows the repositories table to fill the available vertical space in
   the wizard
5. Adjusts the package dual list selectors so that they fill the
   available horizontal space in the wizard
This commit is contained in:
lucasgarfield 2023-10-20 09:34:24 +02:00 committed by Lucas Garfield
parent 1c1290f7ed
commit c4d411efa4
9 changed files with 169 additions and 174 deletions

View file

@ -34,7 +34,7 @@ import {
import isRhel from '../../Utilities/isRhel';
import { resolveRelPath } from '../../Utilities/path';
import { useGetEnvironment } from '../../Utilities/useGetEnvironment';
import DocumentationButton from '../sharedComponents/DocumentationButton';
import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader';
const handleKeyDown = (e, handleClose) => {
if (e.key === 'Escape') {
@ -597,75 +597,73 @@ const CreateImageWizard = () => {
const currentDate = new Date();
return (
<ImageCreator
onClose={handleClose}
onSubmit={async ({ values, setIsSaving }) => {
setIsSaving(true);
const requests = onSave(values);
await Promise.allSettled(
requests.map((composeRequest) => composeImage({ composeRequest }))
);
navigate(resolveRelPath(''));
}}
defaultArch="x86_64"
customValidatorMapper={{
fileSystemConfigurationValidator,
targetEnvironmentValidator,
}}
schema={{
fields: [
{
component: componentTypes.WIZARD,
name: 'image-builder-wizard',
className: 'imageBuilder',
isDynamic: true,
inModal: false,
onKeyDown: (e) => {
handleKeyDown(e, handleClose);
},
buttonLabels: {
submit: 'Create image',
},
showTitles: true,
title: 'Image Builder',
crossroads: [
'target-environment',
'release',
'payload-repositories',
],
description: (
<>
Image builder allows you to create a custom image and push it to
target environments. <DocumentationButton />
</>
),
// order in this array does not reflect order in wizard nav, this order is managed inside
// of each step by `nextStep` property!
<>
<ImageBuilderHeader />
<section className="pf-l-page__main-section pf-c-page__main-section">
<ImageCreator
onClose={handleClose}
onSubmit={async ({ values, setIsSaving }) => {
setIsSaving(true);
const requests = onSave(values);
await Promise.allSettled(
requests.map((composeRequest) => composeImage({ composeRequest }))
);
navigate(resolveRelPath(''));
}}
defaultArch="x86_64"
customValidatorMapper={{
fileSystemConfigurationValidator,
targetEnvironmentValidator,
}}
schema={{
fields: [
imageOutput,
awsTarget,
googleCloudTarget,
msAzureTarget,
registration,
packages,
packagesContentSources,
repositories,
fileSystemConfiguration,
imageName,
review,
oscap,
{
component: componentTypes.WIZARD,
name: 'image-builder-wizard',
className: 'imageBuilder',
isDynamic: true,
inModal: false,
onKeyDown: (e) => {
handleKeyDown(e, handleClose);
},
buttonLabels: {
submit: 'Create image',
},
showTitles: true,
crossroads: [
'target-environment',
'release',
'payload-repositories',
],
// order in this array does not reflect order in wizard nav, this order is managed inside
// of each step by `nextStep` property!
fields: [
imageOutput,
awsTarget,
googleCloudTarget,
msAzureTarget,
registration,
packages,
packagesContentSources,
repositories,
fileSystemConfiguration,
imageName,
review,
oscap,
],
initialState: {
activeStep: initialStep || 'image-output', // name of the active step
activeStepIndex: stepHistory.length, // active index
maxStepIndex: stepHistory.length, // max achieved index
prevSteps: stepHistory, // array with names of previously visited steps
},
},
],
initialState: {
activeStep: initialStep || 'image-output', // name of the active step
activeStepIndex: stepHistory.length, // active index
maxStepIndex: stepHistory.length, // max achieved index
prevSteps: stepHistory, // array with names of previously visited steps
},
},
],
}}
initialValues={initialState}
/>
}}
initialValues={initialState}
/>
</section>
</>
);
};

View file

@ -10,7 +10,7 @@
.pf-c-dual-list-selector {
--pf-c-dual-list-selector__menu--MinHeight: 18rem;
--pf-c-dual-list-selector__menu--MaxHeight: 18rem;
--pf-c-dual-list-selector--GridTemplateColumns--pane--MinMax--max: 100vw;
}
.pf-c-form {
@ -59,20 +59,3 @@ ul.pf-m-plain {
padding-left: 0;
margin-left: 0;
}
// [2023-09] Wizard height should not be limited see
// https://github.com/data-driven-forms/react-forms/issues/1402
// TODO remove me after DDF is not used anymore
.pf-c-wizard__main {
overflow-x: unset;
overflow-y: unset;
}
// TODO remove me after DDF is not used anymore
.pf-c-wizard__footer {
z-index: unset;
}
// [2023-10] Wizard closing cross shouldn't get displayed
// TODO remove me after DDF is not used anymore
.pf-c-wizard__header .pf-c-button.pf-m-plain {
display: none;
}

View file

@ -399,7 +399,7 @@ const Repositories = (props) => {
</ToolbarItem>
</ToolbarContent>
</Toolbar>
<Panel isScrollable>
<Panel>
<PanelMain>
<RepositoryUnavailable />
<TableComposable

View file

@ -1,7 +1,3 @@
.title {
display: inline;
}
.pf-c-form__group-label-help {
color: var(--pf-global--icon--Color--light);
}
@ -10,10 +6,6 @@
color: var(--pf-global--icon--Color--dark);
}
.header-button {
padding-right: 0;
}
.expand-section {
background-color: var(--pf-global--palette--white);
}
}

View file

@ -12,12 +12,6 @@ import {
TabAction,
} from '@patternfly/react-core';
import { ExternalLinkAltIcon, HelpIcon } from '@patternfly/react-icons';
// eslint-disable-next-line rulesdir/disallow-fec-relative-imports
import {
OpenSourceBadge,
PageHeader,
PageHeaderTitle,
} from '@redhat-cloud-services/frontend-components';
import { useFlag } from '@unleash/proxy-client-react';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
@ -29,6 +23,7 @@ import { manageEdgeImagesUrlName } from '../../Utilities/edge';
import { resolveRelPath } from '../../Utilities/path';
import EdgeImagesTable from '../edge/ImagesTable';
import ImagesTable from '../ImagesTable/ImagesTable';
import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader';
export const LandingPage = () => {
const { pathname } = useLocation();
@ -61,65 +56,7 @@ export const LandingPage = () => {
);
return (
<>
{/*@ts-ignore*/}
<PageHeader>
<PageHeaderTitle className="title" title="Image Builder" />
<Popover
minWidth="35rem"
headerContent={'About image builder'}
bodyContent={
<TextContent>
<Text>
Image builder is a tool for creating deployment-ready customized
system images: installation disks, virtual machines, cloud
vendor-specific images, and others. By using image builder, you
can make these images faster than manual procedures because it
eliminates the specific configurations required for each output
type.
</Text>
<Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={
'https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/creating_customized_rhel_images_using_the_image_builder_service'
}
>
Image builder for RPM-DNF documentation
</Button>
</Text>
<Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={
'https://access.redhat.com/documentation/en-us/edge_management/2022/html/create_rhel_for_edge_images_and_configure_automated_management/index'
}
>
Image builder for OSTree documentation
</Button>
</Text>
</TextContent>
}
>
<Button
variant="plain"
aria-label="About image builder"
className="pf-u-pl-sm header-button"
>
<HelpIcon />
</Button>
</Popover>
<OpenSourceBadge repositoriesURL="https://www.osbuild.org/guides/image-builder-service/architecture.html" />
</PageHeader>
<ImageBuilderHeader />
{edgeParityFlag ? (
<Tabs
className="pf-c-tabs pf-c-page-header pf-c-table"

View file

@ -0,0 +1,7 @@
.title {
display: inline;
}
.header-button {
padding-right: 0;
}

View file

@ -0,0 +1,78 @@
import React from 'react';
import { Button, Popover, Text, TextContent } from '@patternfly/react-core';
import { ExternalLinkAltIcon, HelpIcon } from '@patternfly/react-icons';
// eslint-disable-next-line rulesdir/disallow-fec-relative-imports
import {
OpenSourceBadge,
PageHeader,
PageHeaderTitle,
} from '@redhat-cloud-services/frontend-components';
import './ImageBuilderHeader.scss';
export const ImageBuilderHeader = () => {
return (
<>
{/*@ts-ignore*/}
<PageHeader>
<PageHeaderTitle className="title" title="Image Builder" />
<Popover
minWidth="35rem"
headerContent={'About image builder'}
bodyContent={
<TextContent>
<Text>
Image builder is a tool for creating deployment-ready customized
system images: installation disks, virtual machines, cloud
vendor-specific images, and others. By using image builder, you
can make these images faster than manual procedures because it
eliminates the specific configurations required for each output
type.
</Text>
<Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={
'https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/creating_customized_rhel_images_using_the_image_builder_service'
}
>
Image builder for RPM-DNF documentation
</Button>
</Text>
<Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={
'https://access.redhat.com/documentation/en-us/edge_management/2022/html/create_rhel_for_edge_images_and_configure_automated_management/index'
}
>
Image builder for OSTree documentation
</Button>
</Text>
</TextContent>
}
>
<Button
variant="plain"
aria-label="About image builder"
className="pf-u-pl-sm header-button"
>
<HelpIcon />
</Button>
</Popover>
<OpenSourceBadge repositoriesURL="https://www.osbuild.org/guides/image-builder-service/architecture.html" />
</PageHeader>
</>
);
};

View file

@ -85,9 +85,9 @@ describe('Step Upload to Azure', () => {
await clickNext();
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(
'Target environment - Microsoft Azure'
);
await screen.findByRole('heading', {
name: 'Target environment - Microsoft Azure',
});
};
test('clicking Next loads Registration', async () => {

View file

@ -143,9 +143,7 @@ describe('Step Image output', () => {
// select aws as upload destination
await user.click(await screen.findByTestId('upload-aws'));
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(
'Image output'
);
await screen.findByRole('heading', { name: 'Image output' });
};
test('clicking Next loads Upload to AWS', async () => {
@ -282,9 +280,9 @@ describe('Step Upload to AWS', () => {
await clickNext();
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(
'Target environment - Amazon Web Services'
);
await screen.findByRole('heading', {
name: 'Target environment - Amazon Web Services',
});
};
test('clicking Next loads Registration', async () => {
@ -450,9 +448,9 @@ describe('Step Upload to Google', () => {
await clickNext();
expect(screen.getByRole('heading', { level: 1 })).toHaveTextContent(
'Target environment - Google Cloud Platform'
);
await screen.findByRole('heading', {
name: 'Target environment - Google Cloud Platform',
});
};
test('clicking Next loads Registration', async () => {
@ -549,7 +547,9 @@ describe('Step Registration', () => {
await clickNext();
screen.getByRole('heading', { name: /file system configuration/i });
await screen.findByRole('heading', {
name: 'File system configuration',
});
});
test('clicking Back loads Upload to AWS', async () => {