improves EntityValidationPage UX

Signed-off-by: Samuel Stadler <samuel.stadler@dynatrace.com>
This commit is contained in:
Samuel Stadler
2023-11-22 18:51:32 +01:00
parent 6d21e0b481
commit 1f70e46680
3 changed files with 148 additions and 29 deletions
@@ -0,0 +1,91 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
import { EntityValidationPage } from './EntityValidationPage';
import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react';
import { MarkdownContent } from '@backstage/core-components';
describe('EntityValidatorPage', () => {
const catalogApi: Partial<CatalogApi> = {
getEntities: () =>
Promise.resolve({
items: [
{
apiVersion: 'backstage.io/v1alpha1',
kind: 'API',
metadata: {
name: 'Entity1',
annotations: {
'backstage.io/view-url': 'viewurl',
'backstage.io/edit-url': 'editurl',
},
},
spec: { type: 'openapi' },
},
],
}),
};
const contentHead = <MarkdownContent content="Content Head" />;
it('should show loation text field', async () => {
const { getByText, getByTestId } = await renderInTestApp(
<TestApiProvider apis={[[catalogApiRef, catalogApi]]}>
<EntityValidationPage />
</TestApiProvider>,
);
const mainGrid = getByTestId('main-grid');
expect(mainGrid.children.length).toBe(2);
expect(getByText('File Location')).toBeInTheDocument();
});
it('should not show loation text field', async () => {
const { queryByText, getByTestId } = await renderInTestApp(
<TestApiProvider apis={[[catalogApiRef, catalogApi]]}>
<EntityValidationPage hideFileLocationField />
</TestApiProvider>,
);
const mainGrid = getByTestId('main-grid');
expect(mainGrid.children.length).toBe(1);
expect(queryByText('File Location')).not.toBeInTheDocument();
});
it('should not show content head', async () => {
const { getByTestId } = await renderInTestApp(
<TestApiProvider apis={[[catalogApiRef, catalogApi]]}>
<EntityValidationPage />
</TestApiProvider>,
);
const mainGrid = getByTestId('main-grid');
expect(mainGrid.children.length).toBe(2);
});
it('should show content head', async () => {
const { getByTestId } = await renderInTestApp(
<TestApiProvider apis={[[catalogApiRef, catalogApi]]}>
<EntityValidationPage contentHead={contentHead} />
</TestApiProvider>,
);
const mainGrid = getByTestId('main-grid');
expect(mainGrid.children.length).toBe(3);
});
});
@@ -15,9 +15,9 @@
*/
import React, { useState } from 'react';
import { Content, Header, LinkButton, Page } from '@backstage/core-components';
import { Content, Header, Page } from '@backstage/core-components';
import { EntityTextArea } from '../EntityTextArea';
import { Grid, TextField } from '@material-ui/core';
import { Button, Grid, TextField } from '@material-ui/core';
import { CatalogProcessorResult } from '../../types';
import { parseEntityYaml } from '../../utils';
import { EntityValidationOutput } from '../EntityValidationOutput';
@@ -40,10 +40,14 @@ spec:
export const EntityValidationPage = (props: {
defaultYaml?: string;
defaultLocation?: string;
hideFileLocationField?: boolean;
contentHead?: React.ReactNode;
}) => {
const {
defaultYaml = EXAMPLE_CATALOG_INFO_YAML,
defaultLocation = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml',
hideFileLocationField = false,
contentHead,
} = props;
const [catalogYaml, setCatalogYaml] = useState(defaultYaml);
@@ -67,8 +71,16 @@ export const EntityValidationPage = (props: {
subtitle="Tool to validate catalog-info.yaml files"
/>
<Content>
<Grid container>
<Grid item md={9} xs={12}>
<Grid
container
direction="column"
style={{ height: '100%' }}
wrap="nowrap"
data-testid="main-grid"
>
{contentHead}
{!hideFileLocationField && (
<TextField
fullWidth
label="File Location"
@@ -77,35 +89,46 @@ export const EntityValidationPage = (props: {
required
value={locationUrl}
placeholder={defaultLocation}
helperText="Location where you catalog-info.yaml file is, or will be, located"
helperText="Location where you catalog-info.yaml file is, or will be, located. This is not the file that is being validated - it only adds location annotations to the entity that is going to be validated."
onChange={e => setLocationUrl(e.target.value)}
/>
</Grid>
<Grid item md={3} xs={12}>
<Grid container alignItems="center" style={{ height: '100%' }}>
<Grid item>
<LinkButton size="large" onClick={parseYaml} to="#">
Validate
</LinkButton>
)}
<Grid container direction="row" style={{ height: '100%' }}>
<Grid item md={6} xs={12}>
<Grid
container
direction="column"
alignItems="flex-end"
style={{ height: '100%' }}
wrap="nowrap"
>
<Grid item style={{ width: '100%', flex: '1 1 auto' }}>
<EntityTextArea
onValidate={parseYaml}
onChange={(value: string) => setCatalogYaml(value)}
catalogYaml={catalogYaml}
/>
</Grid>
<Grid item>
<Button
variant="contained"
color="primary"
onClick={parseYaml}
>
Validate
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="row" style={{ height: '90%' }}>
<Grid item md={6} xs={12}>
<EntityTextArea
onValidate={parseYaml}
onChange={(value: string) => setCatalogYaml(value)}
catalogYaml={catalogYaml}
/>
</Grid>
<Grid item md={6} xs={12}>
<Grid container spacing={3}>
<Grid item xs={12}>
<EntityValidationOutput
processorResults={yamlFiles}
locationUrl={locationUrl}
/>
<Grid item md={6} xs={12}>
<Grid container spacing={3}>
<Grid item xs={12}>
<EntityValidationOutput
processorResults={yamlFiles}
locationUrl={locationUrl}
/>
</Grid>
</Grid>
</Grid>
</Grid>