Merge pull request #7208 from nixocio/ui_issue_7016

Add error feedback in Preview Step

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
softwarefactory-project-zuul[bot] 2020-06-04 19:04:43 +00:00 committed by GitHub
commit 61a1cfa35a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 26 deletions

View File

@ -1,11 +1,29 @@
import React from 'react';
import React, { Fragment } from 'react';
import styled from 'styled-components';
import { ExclamationCircleIcon as PFExclamationCircleIcon } from '@patternfly/react-icons';
import { Tooltip } from '@patternfly/react-core';
import { t } from '@lingui/macro';
import { useFormikContext } from 'formik';
import { withI18n } from '@lingui/react';
import yaml from 'js-yaml';
import PromptDetail from '../../PromptDetail';
import mergeExtraVars, { maskPasswords } from '../mergeExtraVars';
import getSurveyValues from '../getSurveyValues';
import PromptDetail from '../../PromptDetail';
function PreviewStep({ resource, config, survey, formErrors }) {
const ExclamationCircleIcon = styled(PFExclamationCircleIcon)`
margin-left: 10px;
margin-top: -2px;
`;
const ErrorMessageWrapper = styled.div`
align-items: center;
color: var(--pf-global--danger-color--200);
display: flex;
font-weight: var(--pf-global--FontWeight--bold);
margin-bottom: 10px;
`;
function PreviewStep({ resource, config, survey, formErrors, i18n }) {
const { values } = useFormikContext();
const surveyValues = getSurveyValues(values);
@ -29,21 +47,26 @@ function PreviewStep({ resource, config, survey, formErrors }) {
}
return (
<>
<Fragment>
{formErrors.length > 0 && (
<ErrorMessageWrapper>
{i18n._(t`Some of the previous step(s) have errors`)}
<Tooltip
position="right"
content={i18n._(t`See errors on the left`)}
trigger="click mouseenter focus"
>
<ExclamationCircleIcon />
</Tooltip>
</ErrorMessageWrapper>
)}
<PromptDetail
resource={resource}
launchConfig={config}
overrides={overrides}
/>
{formErrors && (
<ul css="color: red">
{Object.keys(formErrors).map(
field => `${field}: ${formErrors[field]}`
)}
</ul>
)}
</>
</Fragment>
);
}
export default PreviewStep;
export default withI18n()(PreviewStep);

View File

@ -24,6 +24,10 @@ const survey = {
],
};
const formErrors = {
inventory: 'An inventory must be selected',
};
describe('PreviewStep', () => {
test('should render PromptDetail', async () => {
let wrapper;
@ -37,6 +41,7 @@ describe('PreviewStep', () => {
survey_enabled: true,
}}
survey={survey}
formErrors={formErrors}
/>
</Formik>
);
@ -62,6 +67,7 @@ describe('PreviewStep', () => {
config={{
ask_limit_on_launch: true,
}}
formErrors={formErrors}
/>
</Formik>
);
@ -85,6 +91,7 @@ describe('PreviewStep', () => {
config={{
ask_variables_on_launch: true,
}}
formErrors={formErrors}
/>
</Formik>
);

View File

@ -19,7 +19,8 @@ export default function useCredentialsStep(
initialValues: getInitialValues(config, resource),
validate,
isReady: true,
error: null,
contentError: null,
formError: null,
setTouched: setFieldsTouched => {
setFieldsTouched({
credentials: true,

View File

@ -27,7 +27,8 @@ export default function useInventoryStep(config, resource, visitedSteps, i18n) {
initialValues: getInitialValues(config, resource),
validate,
isReady: true,
error: null,
contentError: null,
formError: stepErrors,
setTouched: setFieldsTouched => {
setFieldsTouched({
inventory: true,

View File

@ -24,7 +24,8 @@ export default function useOtherPrompt(config, resource, visitedSteps, i18n) {
initialValues: getInitialValues(config, resource),
validate,
isReady: true,
error: null,
contentError: null,
formError: stepErrors,
setTouched: setFieldsTouched => {
setFieldsTouched({
job_type: true,

View File

@ -54,7 +54,8 @@ export default function useSurveyStep(config, resource, visitedSteps, i18n) {
validate,
survey,
isReady: !isLoading && !!survey,
error,
contentError: error,
formError: stepErrors,
setTouched: setFieldsTouched => {
if (!survey || !survey.spec) {
return;

View File

@ -13,14 +13,13 @@ export default function useSteps(config, resource, i18n) {
useOtherPromptsStep(config, resource, visited, i18n),
useSurveyStep(config, resource, visited, i18n),
];
const formErrorsContent = steps
.filter(s => s?.formError && Object.keys(s.formError).length > 0)
.map(({ formError }) => formError);
steps.push(
usePreviewStep(
config,
resource,
steps[3].survey,
{}, // TODO: formErrors ?
i18n
)
usePreviewStep(config, resource, steps[3].survey, formErrorsContent, i18n)
);
const pfSteps = steps.map(s => s.step).filter(s => s != null);
@ -31,8 +30,9 @@ export default function useSteps(config, resource, i18n) {
};
}, {});
const isReady = !steps.some(s => !s.isReady);
const stepWithError = steps.find(s => s.error);
const contentError = stepWithError ? stepWithError.error : null;
const stepWithError = steps.find(s => s.contentError);
const contentError = stepWithError ? stepWithError.contentError : null;
const validate = values => {
const errors = steps.reduce((acc, cur) => {