improves EntityValidationPage UX
Signed-off-by: Samuel Stadler <samuel.stadler@dynatrace.com>
This commit is contained in:
+91
@@ -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);
|
||||
});
|
||||
});
|
||||
+52
-29
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user