diff --git a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs
index f0f148db48..34e37f3e7b 100644
--- a/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs
+++ b/packages/cli/templates/default-plugin/src/components/ExampleComponent/ExampleComponent.tsx.hbs
@@ -47,9 +47,7 @@ const ExampleComponent: FC<{}> = () => (
-
-
-
+
diff --git a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs
index a198bfcc3f..2dd54f726e 100644
--- a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs
+++ b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs
@@ -16,20 +16,11 @@
import React, { FC } from 'react';
import { makeStyles } from '@material-ui/core/styles';
-import Table from '@material-ui/core/Table';
-import TableBody from '@material-ui/core/TableBody';
-import TableCell from '@material-ui/core/TableCell';
-import TableContainer from '@material-ui/core/TableContainer';
-import TableHead from '@material-ui/core/TableHead';
-import TableRow from '@material-ui/core/TableRow';
+import { Table, TableColumn, Progress } from '@backstage/core';
import Alert from '@material-ui/lab/Alert';
import { useAsync } from 'react-use';
-import { Progress } from '@backstage/core';
const useStyles = makeStyles({
- table: {
- minWidth: 650,
- },
avatar: {
height: 32,
width: 32,
@@ -66,37 +57,35 @@ type DenseTableProps = {
export const DenseTable: FC = ({ users }) => {
const classes = useStyles();
+ const columns: TableColumn[] = [
+ { title: 'Avatar', field: 'avatar' },
+ { title: 'Name', field: 'name' },
+ { title: 'Email', field: 'email' },
+ { title: 'Nationality', field: 'nationality' },
+ ];
+
+ const data = users.map((user) => {
+ return {
+ avatar: (
+
+ ),
+ name: `${user.name.first} ${user.name.last}`,
+ email: user.email,
+ nationality: user.nat,
+ };
+ });
+
return (
-
-
-
-
- Avatar
- Name
- Email
- Nationality
-
-
-
- {users.map(user => (
-
-
-
-
-
- {user.name.first} {user.name.last}
-
- {user.email}
- {user.nat}
-
- ))}
-
-
-
+
);
};
diff --git a/packages/core/src/components/SortableTable/SortableTable.stories.tsx b/packages/core/src/components/SortableTable/SortableTable.stories.tsx
deleted file mode 100644
index 2a903e1df7..0000000000
--- a/packages/core/src/components/SortableTable/SortableTable.stories.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2020 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 { StatusError, StatusOK, StatusWarning } from 'components/Status';
-import SortableTable from './SortableTable';
-
-export default {
- title: 'Sortable Table',
- component: SortableTable,
-};
-const containerStyle = { width: 600, padding: 20 };
-
-const data = [
- { id: 'buffalos', amount: 1, status: , statusValue: 2 },
- { id: 'milk', amount: 3, status: , statusValue: 1 },
- { id: 'cheese', amount: 8, status: , statusValue: 1 },
- { id: 'bread', amount: 2, status: , statusValue: 0 },
-];
-const columns = [
- { id: 'id', label: 'ID' },
- { id: 'amount', disablePadding: false, numeric: true, label: 'AMOUNT' },
- {
- id: 'status',
- label: 'STATUS',
- sortValue: (row: typeof data[0]) => row.statusValue,
- },
-];
-const footerData = [
- { id: 'total', amount: 4, statusValue: 2, status: },
-];
-
-export const Default = () => (
-
-
-
-);
-
-export const WithFooter = () => (
-
-
-
-);
diff --git a/packages/core/src/components/SortableTable/SortableTable.tsx b/packages/core/src/components/SortableTable/SortableTable.tsx
deleted file mode 100644
index 4db3aee9ff..0000000000
--- a/packages/core/src/components/SortableTable/SortableTable.tsx
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright 2020 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, { FC, CSSProperties, memo, useState, useEffect } from 'react';
-import {
- Table,
- TableBody,
- TableCell,
- TableFooter,
- TableHead,
- TableRow,
- TableSortLabel,
- Tooltip,
-} from '@material-ui/core';
-
-type Column = {
- id: string;
- label: string;
- numeric?: boolean;
- disablePadding: boolean;
- style: CSSProperties;
- // FIXME (@Koroeskohr)
- sortValue: (obj: object) => any;
-};
-
-// XXX (@Koroeskohr): no idea what I did but this typechecks. Need answer for CellContentProps
-type Row = { [name in string]: any };
-
-type SortHandler = (
- event: React.MouseEvent,
- property: string,
-) => void;
-
-type Order = 'asc' | 'desc';
-
-type EnhancedTableHeadProps = {
- columns: Column[];
- onRequestSort: SortHandler;
- order: Order;
- orderBy: string;
-};
-
-/**
- * Table header which supports sorting ascending and desc
- */
-const EnhancedTableHead: FC = ({
- columns,
- onRequestSort,
- order,
- orderBy,
-}) => {
- const createSortHandler = (property: string) => (
- event: React.MouseEvent,
- ) => {
- onRequestSort(event, property);
- };
-
- return (
-
-
- {columns.map(column => (
-
-
-
- {column.label}
-
-
-
- ))}
-
-
- );
-};
-
-type CellContentProps = {
- // XXX (@Koroeskohr): what am I supposed to use here
- data: any | any[];
-};
-
-/**
- * CellContent can be an array or a string
- */
-const CellContent: FC = ({ data }) => {
- if (Array.isArray(data)) {
- return data.map((item, index) => (
-
- {item}
-
-
- ));
- }
- return data;
-};
-
-type DataTableCellProps = {
- column: Column;
- row: Row;
-};
-
-const DataTableCell: FC = ({ column, row }) => {
- return (
-
-
-
- );
-};
-
-const noop = () => {};
-type DataTableRowProps = {
- row: Row;
- columns: Column[];
- handleRowClick?: (event: React.MouseEvent, rowId: string) => void;
- style?: React.CSSProperties;
-};
-const _DataTableRow: FC = ({
- row,
- columns,
- handleRowClick,
- style,
-}) => {
- const onClick: React.MouseEventHandler = event =>
- (handleRowClick || noop)(event, row.id);
- return (
-
- {columns.map(column => (
-
- ))}
-
- );
-};
-const DataTableRow = memo(_DataTableRow);
-
-/**
- * Table with sorting capabilites automatic rendering of cells
- * Note that the objects in props.data needs have an id property
- * The columns array defines which columns from the data to show.
- *
- * @param data A list of data entries, where object properties must
- * be strictly equal to column ids.
- *
- * @param columns A list of columns with the following shape:
- * {
- * // The column identifier must be strictly equal the relevant data entry
- * // key:
- * id: String,
- *
- * // The display label for the column:
- * label: String,
- *
- * // If true, the column contents will be right-aligned:
- * numeric: Boolean,
- *
- * // If true, padding will be disabled for table cells:
- * disablePadding: Boolean,
- *
- * // A function taking a data row and returning a suitable primitive for
- * // sorting:
- * sortValue: (Object) => Any
- * }
- *
- * @param orderBy The column ID initially used for sorting
- *
- * @param dataVersion A version identifier for the data which *must*
- * be updated when the contents of the data changes. This can be used for
- * components where the same SortableTable element will be used to display
- * variable sets of data.
- *
- * @param footerData A list of data entries to be placed in
- * the table footer, which will not be sorted.
- *
- * @param onRowClicked Get notified when a user clicks
- * on the row. The handler will receive the row id as the first argument, and
- * the synthetic click event as the second argument.
- *
- * @example
- * render {
- * const data = [
- * { id: 'buffalos', amount: 1, status: , statusValue: 2 },
- * { id: 'milk', amount: 3, status: , statusValue: 1 }
- * ];
- * const columns = [
- * { id: 'id', label: 'ID' },
- * { id: 'amount', disablePadding: false, numeric: true, label: 'AMOUNT' },
- * { id: 'status', label: 'STATUS', sortValue: row => row.statusValue },
- * ];
- * const footerData = [
- * { id: 'total', amount: 4, statusValue: 2, status: },
- * ];
- * return (
- * {console.log('Row:' + id + ' clicked');
- * ev.preventDefault();}}/>)
- * }
- *
- * // XXX (@koroeskohr): supposedly this is leftover from your internal doc
- * @deprecated use shared/components/DataGrid
- */
-
-type SortableTableProps = {
- data: Row[];
- footerData: Row[];
- orderBy: string;
- columns: Column[];
- onRowClicked?: (
- id: string,
- event: React.MouseEvent,
- ) => void;
- dataVersion: string;
-};
-
-type TableState = {
- orderBy: string;
- order: Order;
- data: Row[];
-};
-
-const SortableTable: FC = props => {
- const [state, setState] = useState({
- orderBy: props.orderBy,
- order: 'asc',
- data: props.data,
- });
-
- const updateData = (data: Row[], orderBy: string, order: Order) => {
- const sortValueFn = (props.columns.find(col => col.id === orderBy) || {})
- .sortValue;
-
- const sortedData = data.slice().sort((a, b) => {
- const valueA = sortValueFn ? sortValueFn(a) : a[orderBy];
- const valueB = sortValueFn ? sortValueFn(b) : b[orderBy];
- const inc = order === 'desc' ? -1 : 1;
- if (valueA === valueB) return 0;
- if (valueA === '' || valueA === null) return inc;
- if (valueB === '' || valueB === null) return -inc;
- return valueA < valueB ? -inc : inc;
- });
- setState({ data: sortedData, order, orderBy });
- };
-
- const handleRequestSort: SortHandler = (event, property) => {
- event.preventDefault();
- const orderBy = property;
- let order: Order = 'desc';
- if (state.orderBy === property && state.order === 'desc') {
- order = 'asc';
- }
- updateData(state.data, orderBy, order);
- };
-
- const handleRowClick = (event: React.MouseEvent, id: string): void => {
- if (props.onRowClicked) {
- props.onRowClicked(id, event);
- }
- };
-
- useEffect(() => {
- const { data } = props;
- const { orderBy, order } = state;
- updateData(data, orderBy, order);
- }, [props.dataVersion]);
-
- const { data, order, orderBy } = state;
- const { columns, dataVersion, footerData } = props;
-
- let tableFoot = null;
- if (footerData && footerData.length > 0) {
- tableFoot = (
-
- {footerData.map(row => (
-
- ))}
-
- );
- }
- return (
-
-
-
- {data.map(row => (
-
- ))}
-
- {tableFoot}
-
- );
-};
-
-export default SortableTable;
diff --git a/packages/core/src/components/SortableTable/index.tsx b/packages/core/src/components/SortableTable/index.tsx
deleted file mode 100644
index 718f582b8f..0000000000
--- a/packages/core/src/components/SortableTable/index.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2020 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 { default } from './SortableTable';
diff --git a/packages/core/src/components/Status/Status.stories.tsx b/packages/core/src/components/Status/Status.stories.tsx
index 0cdc38a10d..33a8e51e65 100644
--- a/packages/core/src/components/Status/Status.stories.tsx
+++ b/packages/core/src/components/Status/Status.stories.tsx
@@ -24,7 +24,7 @@ import {
StatusRunning,
StatusWarning,
} from './Status';
-import SortableTable from 'components/SortableTable';
+import Table from 'components/Table';
import InfoCard from 'layout/InfoCard';
export default {
@@ -71,9 +71,9 @@ const data = [
];
const columns = [
- { id: 'status', label: 'Status' },
- { id: 'label', label: 'Label' },
- { id: 'usage', label: 'Example usage' },
+ { field: 'status', title: 'Status' },
+ { field: 'label', title: 'Label' },
+ { field: 'usage', title: 'Example usage' },
];
const containerStyle = { width: 600 };
@@ -81,7 +81,15 @@ const containerStyle = { width: 600 };
export const Default = () => (
);
diff --git a/packages/core/src/components/TrendLine/TrendLine.stories.tsx b/packages/core/src/components/TrendLine/TrendLine.stories.tsx
index 5263385e1c..562feeff80 100644
--- a/packages/core/src/components/TrendLine/TrendLine.stories.tsx
+++ b/packages/core/src/components/TrendLine/TrendLine.stories.tsx
@@ -16,7 +16,7 @@
import React from 'react';
import TrendLine from '.';
-import SortableTable from 'components/SortableTable';
+import Table from 'components/Table';
import InfoCard from 'layout/InfoCard';
export default {
@@ -58,17 +58,25 @@ const data = [
];
const columns = [
- { id: 'stock', label: 'Stock' },
- { id: 'day', label: 'Day' },
- { id: 'week', label: 'Week' },
- { id: 'month', label: 'Month' },
- { id: 'year', label: 'Year' },
+ { field: 'stock', title: 'Stock' },
+ { field: 'day', title: 'Day' },
+ { field: 'week', title: 'Week' },
+ { field: 'month', title: 'Month' },
+ { field: 'year', title: 'Year' },
];
export const Default = () => (
);
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index 8699034efc..e817ada9c9 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -35,7 +35,8 @@ export { default as Progress } from './components/Progress';
export * from './components/SimpleStepper';
export { AlphaLabel, BetaLabel } from './components/Lifecycle';
export { default as SupportButton } from './components/SupportButton';
-export { default as SortableTable } from './components/SortableTable';
+export { default as Table, SubvalueCell } from './components/Table';
+export type { TableColumn } from './components/Table/Table';
export { default as StructuredMetadataTable } from './components/StructuredMetadataTable';
export { default as TrendLine } from './components/TrendLine';
export { FeatureCalloutCircular } from './components/FeatureDiscovery/FeatureCalloutCircular';
diff --git a/plugins/lighthouse/src/components/Audit/AuditRow.tsx b/plugins/lighthouse/src/components/Audit/AuditRow.tsx
deleted file mode 100644
index 71668138f4..0000000000
--- a/plugins/lighthouse/src/components/Audit/AuditRow.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2020 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, { FC } from 'react';
-import { Link, TableCell, TableRow } from '@material-ui/core';
-import { makeStyles } from '@material-ui/core/styles';
-import { TrendLine } from '@backstage/core';
-import { Website } from '../../api';
-import {
- formatTime,
- CATEGORIES,
- CATEGORY_LABELS,
- SparklinesDataByCategory,
-} from '../../utils';
-import AuditStatusIcon from '../AuditStatusIcon';
-
-const useStyles = makeStyles(theme => ({
- table: {
- minWidth: 650,
- },
- status: {
- textTransform: 'capitalize',
- },
- link: {
- paddingTop: theme.spacing(2),
- paddingBottom: theme.spacing(2),
- display: 'inline-block',
- },
- statusCell: { whiteSpace: 'nowrap' },
- sparklinesCell: { minWidth: 120 },
-}));
-
-export const AuditRow: FC<{
- website: Website;
- categorySparkline: SparklinesDataByCategory;
-}> = ({ website, categorySparkline }) => {
- const classes = useStyles();
-
- return (
-
-
-
- {website.url}
-
-
- {CATEGORIES.map(category => (
-
-
-
- ))}
-
- {' '}
-
- {website.lastAudit.status.toLowerCase()}
-
-
- {formatTime(website.lastAudit.timeCreated)}
-
- );
-};
-
-export default AuditRow;
diff --git a/plugins/lighthouse/src/components/Audit/index.tsx b/plugins/lighthouse/src/components/Audit/index.tsx
deleted file mode 100644
index 349bdf5ee9..0000000000
--- a/plugins/lighthouse/src/components/Audit/index.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2020 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, { FC, useState } from 'react';
-import { useInterval } from 'react-use';
-import { Website, lighthouseApiRef } from '../../api';
-import { useApi } from '@backstage/core';
-import {
- SparklinesDataByCategory,
- buildSparklinesDataForItem,
-} from '../../utils';
-import { AuditRow } from './AuditRow';
-export const LIMIT = 10;
-
-export const Audit: FC<{
- website: Website;
- categorySparkline: SparklinesDataByCategory;
-}> = ({ website, categorySparkline }) => {
- const lighthouseApi = useApi(lighthouseApiRef);
- const [websiteState, setWebsiteState] = useState(website);
- const [sparklineState, setSparklineState] = useState(categorySparkline);
-
- const runRefresh = async () => {
- const response = await lighthouseApi.getWebsiteForAuditId(
- websiteState.lastAudit.id,
- );
- const auditStatus = response.lastAudit.status;
- if (auditStatus === 'COMPLETED' || auditStatus === 'FAILED') {
- setSparklineState(buildSparklinesDataForItem(response));
- setWebsiteState(response);
- }
- };
-
- useInterval(
- runRefresh,
- websiteState?.lastAudit.status === 'RUNNING' ? 5000 : null,
- );
-
- return ;
-};
-
-export default Audit;
diff --git a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx
index 3ab07434d7..cebab93f17 100644
--- a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx
+++ b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx
@@ -55,7 +55,7 @@ describe('AuditListTable', () => {
);
const link = rendered.queryByText('https://anchor.fm');
const website = websiteListResponse.items.find(
- w => w.url === 'https://anchor.fm',
+ (w) => w.url === 'https://anchor.fm',
);
if (!website)
throw new Error('https://anchor.fm must be present in fixture');
@@ -71,7 +71,7 @@ describe('AuditListTable', () => {
wrapInThemedTestApp(auditList(websiteListResponse)),
);
const website = websiteListResponse.items.find(
- w => w.url === 'https://anchor.fm',
+ (w) => w.url === 'https://anchor.fm',
);
if (!website)
throw new Error('https://anchor.fm must be present in fixture');
@@ -85,21 +85,22 @@ describe('AuditListTable', () => {
wrapInThemedTestApp(auditList(websiteListResponse)),
);
- const completed = await rendered.findAllByText('completed');
+ const completed = await rendered.findAllByText('COMPLETED');
expect(completed).toHaveLength(
- websiteListResponse.items.filter(w => w.lastAudit.status === 'COMPLETED')
- .length,
+ websiteListResponse.items.filter(
+ (w) => w.lastAudit.status === 'COMPLETED',
+ ).length,
);
- const failed = await rendered.findAllByText('failed');
+ const failed = await rendered.findAllByText('FAILED');
expect(failed).toHaveLength(
- websiteListResponse.items.filter(w => w.lastAudit.status === 'FAILED')
+ websiteListResponse.items.filter((w) => w.lastAudit.status === 'FAILED')
.length,
);
- const running = await rendered.findAllByText('failed');
+ const running = await rendered.findAllByText('FAILED');
expect(running).toHaveLength(
- websiteListResponse.items.filter(w => w.lastAudit.status === 'RUNNING')
+ websiteListResponse.items.filter((w) => w.lastAudit.status === 'RUNNING')
.length,
);
});
diff --git a/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx b/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx
index 082433a550..20dd1f39f8 100644
--- a/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx
+++ b/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx
@@ -13,81 +13,111 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { FC, useMemo } from 'react';
-import {
- Table,
- TableBody,
- TableCell,
- TableContainer,
- TableHead,
- TableRow,
-} from '@material-ui/core';
-import { makeStyles } from '@material-ui/core/styles';
-import { Website } from '../../api';
+import React, { FC, useState } from 'react';
+import { Table, TableColumn, TrendLine, useApi } from '@backstage/core';
+import { Website, lighthouseApiRef } from '../../api';
+import { useInterval } from 'react-use';
import {
+ formatTime,
CATEGORIES,
CATEGORY_LABELS,
- SparklinesDataByCategory,
buildSparklinesDataForItem,
} from '../../utils';
-import Audit from '../Audit';
+import { Link } from '@material-ui/core';
+import AuditStatusIcon from '../AuditStatusIcon';
-const useStyles = makeStyles(theme => ({
- table: {
- minWidth: 650,
+const columns: TableColumn[] = [
+ {
+ title: 'Website URL',
+ field: 'websiteUrl',
},
- status: {
- textTransform: 'capitalize',
+ ...CATEGORIES.map((category) => ({
+ title: CATEGORY_LABELS[category],
+ field: category,
+ })),
+ {
+ title: 'Last Report',
+ field: 'lastReport',
+ cellStyle: {
+ whiteSpace: 'nowrap',
+ },
},
- link: {
- paddingTop: theme.spacing(2),
- paddingBottom: theme.spacing(2),
- display: 'inline-block',
+ {
+ title: 'Last Audit Triggered',
+ field: 'lastAuditTriggered',
+ cellStyle: {
+ minWidth: 120,
+ },
},
- statusCell: { whiteSpace: 'nowrap' },
- sparklinesCell: { minWidth: 120 },
-}));
+];
export const AuditListTable: FC<{ items: Website[] }> = ({ items }) => {
- const classes = useStyles();
- const categorySparklines: Record = useMemo(
- () =>
- items.reduce(
- (res, item) => ({
- ...res,
- [item.url]: buildSparklinesDataForItem(item),
- }),
- {},
- ),
- [items],
+ const [websiteState, setWebsiteState] = useState(items);
+ const lighthouseApi = useApi(lighthouseApiRef);
+
+ const runRefresh = (websites: Website[]) => {
+ websites.forEach(async (website) => {
+ const response = await lighthouseApi.getWebsiteForAuditId(
+ website.lastAudit.id,
+ );
+ const auditStatus = response.lastAudit.status;
+ if (auditStatus === 'COMPLETED' || auditStatus === 'FAILED') {
+ const newWebsiteData = websiteState.slice(0);
+ newWebsiteData[
+ newWebsiteData.findIndex((w) => w.url === response.url)
+ ] = response;
+ setWebsiteState(newWebsiteData);
+ }
+ });
+ };
+
+ const runningWebsiteAudits = websiteState
+ ? websiteState.filter((website) => website.lastAudit.status === 'RUNNING')
+ : [];
+
+ useInterval(
+ () => runRefresh(runningWebsiteAudits),
+ runningWebsiteAudits.length > 0 ? 5000 : null,
);
+ const data = websiteState.map((website) => {
+ const trendlineData = buildSparklinesDataForItem(website);
+ const trendlines: any = {};
+ CATEGORIES.forEach((category) => {
+ trendlines[category] = (
+
+ );
+ });
+
+ return {
+ websiteUrl: (
+
+ {website.url}
+
+ ),
+ ...trendlines,
+ lastReport: (
+ <>
+ {' '}
+ {website.lastAudit.status.toUpperCase()}
+ >
+ ),
+ lastAuditTriggered: formatTime(website.lastAudit.timeCreated),
+ };
+ });
+
return (
-
-
-
-
- Website URL
- {CATEGORIES.map(category => (
-
- {CATEGORY_LABELS[category]}
-
- ))}
- Last Report
- Last Audit Triggered
-
-
-
- {items.map(website => (
-
- ))}
-
-
-
+
);
};