use custom columns

Signed-off-by: Andrew Johnson <ajohnson@gocardless.com>
This commit is contained in:
Andrew Johnson
2021-04-08 14:22:10 +01:00
parent a1c46265e9
commit 1229d8377f
7 changed files with 197 additions and 98 deletions
@@ -22,16 +22,11 @@ import {
ConfigReader,
ConfigApi,
OAuthApi,
TableColumn,
} from '@backstage/core';
import { fireEvent } from '@testing-library/react';
import { msw, renderInTestApp } from '@backstage/test-utils';
import {
GithubDeployment,
GithubDeploymentsApiClient,
githubDeploymentsApiRef,
} from '../api';
import { GithubDeploymentsApiClient, githubDeploymentsApiRef } from '../api';
import { githubDeploymentsPlugin } from '../plugin';
import { GithubDeploymentsCard } from './GithubDeploymentsCard';
@@ -44,6 +39,7 @@ import {
import { setupServer } from 'msw/node';
import { graphql } from 'msw';
import { GithubDeploymentsTable } from './GithubDeploymentsTable';
jest.mock('@backstage/plugin-catalog-react', () => ({
useEntity: () => {
@@ -164,28 +160,35 @@ describe('github-deployments', () => {
).toBeInTheDocument();
expect(await rendered.findByText('failure')).toBeInTheDocument();
});
});
it('should display extra columns', async () => {
worker.use(
graphql.query('deployments', (_, res, ctx) =>
res(ctx.data(responseStub)),
),
);
it('should display extra columns', async () => {
worker.use(
graphql.query('deployments', (_, res, ctx) =>
res(ctx.data(responseStub)),
),
);
const extraColumns: TableColumn<GithubDeployment>[] = [
{
title: 'Creator',
field: 'creator.login',
},
];
const renderTargetFromPayload = (payload: string) => {
const parsedPayload = JSON.parse(payload);
return parsedPayload?.target || 'unknown';
};
const rendered = await renderInTestApp(
<ApiProvider apis={apis}>
<GithubDeploymentsCard extraColumns={extraColumns} />
</ApiProvider>,
);
const columns = [
...GithubDeploymentsTable.defaultDeploymentColumns,
GithubDeploymentsTable.columns.createPayloadColumn(
'Target',
renderTargetFromPayload,
),
];
expect(await rendered.findByText('robot-user-001')).toBeInTheDocument();
const rendered = await renderInTestApp(
<ApiProvider apis={apis}>
<GithubDeploymentsCard columns={columns} />
</ApiProvider>,
);
expect(await rendered.findByText('moon')).toBeInTheDocument();
expect(await rendered.findByText('sun')).toBeInTheDocument();
});
});
});
@@ -27,16 +27,16 @@ import {
GITHUB_PROJECT_SLUG_ANNOTATION,
isGithubDeploymentsAvailable,
} from '../Router';
import GithubDeploymentsTable from './GithubDeploymentsTable/GithubDeploymentsTable';
import { GithubDeploymentsTable } from './GithubDeploymentsTable/GithubDeploymentsTable';
const GithubDeploymentsComponent = ({
projectSlug,
last,
extraColumns,
columns,
}: {
projectSlug: string;
last: number;
extraColumns: TableColumn<GithubDeployment>[];
columns: TableColumn<GithubDeployment>[];
}) => {
const api = useApi(githubDeploymentsApiRef);
const [owner, repo] = projectSlug.split('/');
@@ -54,17 +54,17 @@ const GithubDeploymentsComponent = ({
deployments={value || []}
isLoading={loading}
reload={reload}
extraColumns={extraColumns}
columns={columns}
/>
);
};
export const GithubDeploymentsCard = ({
last,
extraColumns,
columns,
}: {
last?: number;
extraColumns?: TableColumn<GithubDeployment>[];
columns?: TableColumn<GithubDeployment>[];
}) => {
const { entity } = useEntity();
@@ -76,7 +76,7 @@ export const GithubDeploymentsCard = ({
entity?.metadata.annotations?.[GITHUB_PROJECT_SLUG_ANNOTATION] || ''
}
last={last || 10}
extraColumns={extraColumns || []}
columns={columns || GithubDeploymentsTable.defaultDeploymentColumns}
/>
);
};
@@ -14,19 +14,12 @@
* limitations under the License.
*/
import React from 'react';
import {
StatusPending,
StatusRunning,
StatusOK,
Table,
TableColumn,
StatusAborted,
StatusError,
} from '@backstage/core';
import { Table, TableColumn } from '@backstage/core';
import { GithubDeployment } from '../../api';
import { DateTime } from 'luxon';
import { Box, Typography, Link, makeStyles } from '@material-ui/core';
import { Typography, makeStyles } from '@material-ui/core';
import SyncIcon from '@material-ui/icons/Sync';
import * as columnFactories from './columns';
import { defaultDeploymentColumns } from './presets';
const useStyles = makeStyles(theme => ({
empty: {
@@ -36,70 +29,24 @@ const useStyles = makeStyles(theme => ({
},
}));
const statusIndicator = (value: string): React.ReactNode => {
switch (value) {
case 'PENDING':
return <StatusPending />;
case 'IN_PROGRESS':
return <StatusRunning />;
case 'ACTIVE':
return <StatusOK />;
case 'ERROR':
case 'FAILURE':
return <StatusError />;
default:
return <StatusAborted />;
}
};
const columns: TableColumn<GithubDeployment>[] = [
{
title: 'Environment',
field: 'environment',
highlight: true,
},
{
title: 'Status',
render: (row: GithubDeployment): React.ReactNode => (
<Box display="flex" alignItems="center">
{statusIndicator(row.state)}
<Typography variant="caption">{row.state}</Typography>
</Box>
),
},
{
title: 'Commit',
render: (row: GithubDeployment): React.ReactNode => (
<Link href={row.commit.commitUrl} target="_blank" rel="noopener">
{row.commit.abbreviatedOid}
</Link>
),
},
{
title: 'Last Updated',
render: (row: GithubDeployment): React.ReactNode =>
DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' }),
},
];
type GithubDeploymentsTableProps = {
deployments: GithubDeployment[];
isLoading: boolean;
reload: () => void;
extraColumns: TableColumn<GithubDeployment>[];
columns: TableColumn<GithubDeployment>[];
};
const GithubDeploymentsTable = ({
export function GithubDeploymentsTable({
deployments,
isLoading,
reload,
extraColumns,
}: GithubDeploymentsTableProps) => {
columns,
}: GithubDeploymentsTableProps) {
const classes = useStyles();
return (
<Table
columns={[...columns, ...extraColumns]}
columns={columns}
options={{ padding: 'dense', paging: true, search: false, pageSize: 5 }}
title="GitHub Deployments"
data={deployments}
@@ -121,6 +68,8 @@ const GithubDeploymentsTable = ({
}
/>
);
};
}
export default GithubDeploymentsTable;
GithubDeploymentsTable.columns = columnFactories;
GithubDeploymentsTable.defaultDeploymentColumns = defaultDeploymentColumns;
@@ -0,0 +1,99 @@
/*
* Copyright 2021 Spotify AB
*
* 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 {
StatusPending,
StatusRunning,
StatusOK,
TableColumn,
StatusAborted,
StatusError,
} from '@backstage/core';
import { GithubDeployment } from '../../api';
import { DateTime } from 'luxon';
import { Box, Typography, Link } from '@material-ui/core';
const statusIndicator = (value: string): React.ReactNode => {
switch (value) {
case 'PENDING':
return <StatusPending />;
case 'IN_PROGRESS':
return <StatusRunning />;
case 'ACTIVE':
return <StatusOK />;
case 'ERROR':
case 'FAILURE':
return <StatusError />;
default:
return <StatusAborted />;
}
};
export function createEnvironmentColumn(): TableColumn<GithubDeployment> {
return {
title: 'Environment',
field: 'environment',
highlight: true,
};
}
export function createStatusColumn(): TableColumn<GithubDeployment> {
return {
title: 'Status',
render: (row: GithubDeployment): React.ReactNode => (
<Box display="flex" alignItems="center">
{statusIndicator(row.state)}
<Typography variant="caption">{row.state}</Typography>
</Box>
),
};
}
export function createCommitColumn(): TableColumn<GithubDeployment> {
return {
title: 'Commit',
render: (row: GithubDeployment): React.ReactNode => (
<Link href={row.commit.commitUrl} target="_blank" rel="noopener">
{row.commit.abbreviatedOid}
</Link>
),
};
}
export function createCreatorColumn(): TableColumn<GithubDeployment> {
return {
title: 'Creator',
field: 'creator.login',
};
}
export function createLastUpdatedColumn(): TableColumn<GithubDeployment> {
return {
title: 'Last Updated',
render: (row: GithubDeployment): React.ReactNode =>
DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' }),
};
}
export function createPayloadColumn(
title: string,
render: (payload: string) => React.ReactNode,
): TableColumn<GithubDeployment> {
return {
title: title,
render: (deployment: GithubDeployment) => render(deployment.payload),
};
}
@@ -0,0 +1,16 @@
/*
* Copyright 2021 Spotify AB
*
* 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.
*/
export { GithubDeploymentsTable } from './GithubDeploymentsTable';
@@ -0,0 +1,32 @@
/*
* Copyright 2021 Spotify AB
*
* 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 { TableColumn } from '@backstage/core';
import { GithubDeployment } from '../../api';
import {
createEnvironmentColumn,
createStatusColumn,
createCommitColumn,
createLastUpdatedColumn,
createCreatorColumn,
} from './columns';
export const defaultDeploymentColumns: TableColumn<GithubDeployment>[] = [
createEnvironmentColumn(),
createStatusColumn(),
createCommitColumn(),
createCreatorColumn(),
createLastUpdatedColumn(),
];
@@ -52,7 +52,7 @@ export const responseStub: QueryResponse = {
creator: {
login: 'robot-user-001',
},
payload: '',
payload: '{"target":"moon"}',
},
{
state: 'pending',
@@ -65,7 +65,7 @@ export const responseStub: QueryResponse = {
creator: {
login: 'robot-user-002',
},
payload: '',
payload: '{"target":"sun"}',
},
],
},