Move local concerns into CatalogTable

This commit is contained in:
Fredrik Adelöw
2020-06-27 20:52:18 +02:00
parent d341129e05
commit 6a8e975c85
6 changed files with 94 additions and 101 deletions
+22 -22
View File
@@ -14,18 +14,8 @@
* limitations under the License.
*/
import React, { FC, forwardRef } from 'react';
import MTable, {
MTableCell,
MTableHeader,
MTableToolbar,
MaterialTableProps,
Options,
Column,
} from 'material-table';
import { BackstageTheme } from '@backstage/theme';
import { makeStyles, useTheme, Typography } from '@material-ui/core';
import { makeStyles, Typography, useTheme } from '@material-ui/core';
// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51
import AddBox from '@material-ui/icons/AddBox';
import ArrowUpward from '@material-ui/icons/ArrowUpward';
@@ -42,6 +32,15 @@ import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';
import MTable, {
Column,
MaterialTableProps,
MTableCell,
MTableHeader,
MTableToolbar,
Options,
} from 'material-table';
import React, { forwardRef } from 'react';
const tableIcons = {
Add: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
@@ -131,10 +130,10 @@ const useToolbarStyles = makeStyles<BackstageTheme>(theme => ({
},
}));
const convertColumns = (
columns: TableColumn[],
function convertColumns<T extends object>(
columns: TableColumn<T>[],
theme: BackstageTheme,
): TableColumn[] => {
): TableColumn<T>[] {
return columns.map(column => {
const headerStyle: React.CSSProperties = {};
const cellStyle: React.CSSProperties = {};
@@ -150,25 +149,26 @@ const convertColumns = (
cellStyle,
};
});
};
}
export interface TableColumn extends Column<{}> {
export interface TableColumn<T extends object = {}> extends Column<T> {
highlight?: boolean;
width?: string;
}
export interface TableProps extends MaterialTableProps<{}> {
columns: TableColumn[];
export interface TableProps<T extends object = {}>
extends MaterialTableProps<T> {
columns: TableColumn<T>[];
subtitle?: string;
}
export const Table: FC<TableProps> = ({
export function Table<T extends object = {}>({
columns,
options,
title,
subtitle,
...props
}) => {
}: TableProps<T>) {
const cellClasses = useCellStyles();
const headerClasses = useHeaderStyles();
const toolbarClasses = useToolbarStyles();
@@ -183,7 +183,7 @@ export const Table: FC<TableProps> = ({
};
return (
<MTable
<MTable<T>
components={{
Cell: cellProps => (
<MTableCell className={cellClasses.root} {...cellProps} />
@@ -211,4 +211,4 @@ export const Table: FC<TableProps> = ({
{...props}
/>
);
};
}
+1 -1
View File
@@ -15,5 +15,5 @@
*/
export { Table } from './Table';
export type { TableColumn } from './Table';
export type { TableColumn, TableProps } from './Table';
export { SubvalueCell } from './SubvalueCell';
@@ -42,7 +42,7 @@ import {
import { FilterGroup, useEntityFilterGroup } from '../../filter';
import { useStarredEntities } from '../../hooks/useStarredEntites';
type CatalogFilterItem = {
export type CatalogFilterItem = {
id: EntityGroup;
label: string;
icon?: IconComponent;
@@ -88,6 +88,9 @@ type Props = {
initiallySelected?: EntityGroup;
};
/**
* The main filter group in the sidebar, toggling owned/starred/all.
*/
export const CatalogFilter = ({
filterGroups,
onChange,
@@ -14,20 +14,13 @@
* limitations under the License.
*/
import { Entity, LocationSpec } from '@backstage/catalog-model';
import { Content, ContentHeader, SupportButton } from '@backstage/core';
import { rootRoute as scaffolderRootRoute } from '@backstage/plugin-scaffolder';
import { Button, makeStyles, withStyles } from '@material-ui/core';
import Edit from '@material-ui/icons/Edit';
import GitHub from '@material-ui/icons/GitHub';
import Star from '@material-ui/icons/Star';
import StarOutline from '@material-ui/icons/StarBorder';
import { Button, makeStyles } from '@material-ui/core';
import React, { useState } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { EntityGroup, filterGroups } from '../../data/filters';
import { findLocationForEntityMeta } from '../../data/utils';
import { EntityFilterGroupsProvider, useFilteredEntities } from '../../filter';
import { useStarredEntities } from '../../hooks/useStarredEntites';
import { CatalogFilter } from '../CatalogFilter/CatalogFilter';
import { CatalogTable } from '../CatalogTable/CatalogTable';
import CatalogLayout from './CatalogLayout';
@@ -45,61 +38,10 @@ const useStyles = makeStyles(theme => ({
const CatalogPageContents = () => {
const styles = useStyles();
const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
const { loading, error, matchingEntities } = useFilteredEntities();
const [selectedTab, setSelectedTab] = useState<string>();
const [selectedSidebarItem, setSelectedSidebarItem] = useState<string>();
const YellowStar = withStyles({
root: {
color: '#f3ba37',
},
})(Star);
const actions = [
(rowData: Entity) => {
const location = findLocationForEntityMeta(rowData.metadata);
return {
icon: GitHub,
tooltip: 'View on GitHub',
onClick: () => {
if (!location) return;
window.open(location.target, '_blank');
},
hidden: location?.type !== 'github',
};
},
(rowData: Entity) => {
const createEditLink = (location: LocationSpec): string => {
switch (location.type) {
case 'github':
return location.target.replace('/blob/', '/edit/');
default:
return location.target;
}
};
const location = findLocationForEntityMeta(rowData.metadata);
return {
icon: Edit,
tooltip: 'Edit',
iconProps: { size: 'small' },
onClick: () => {
if (!location) return;
window.open(createEditLink(location), '_blank');
},
hidden: location?.type !== 'github',
};
},
(rowData: Entity) => {
const isStarred = isStarredEntity(rowData);
return {
icon: isStarred ? YellowStar : StarOutline,
tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',
onClick: () => toggleStarredEntity(rowData),
};
},
];
return (
<CatalogLayout>
<CatalogTabs onChange={({ label }) => setSelectedTab(label)} />
@@ -129,7 +71,6 @@ const CatalogPageContents = () => {
entities={matchingEntities}
loading={loading}
error={error}
actions={actions}
/>
</div>
</Content>
@@ -16,7 +16,7 @@
import { Entity } from '@backstage/catalog-model';
import { wrapInTestApp } from '@backstage/test-utils';
import { render } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import * as React from 'react';
import { CatalogTable } from './CatalogTable';
@@ -66,11 +66,11 @@ describe('CatalogTable component', () => {
/>,
),
);
expect(
await rendered.findByText(`Owned (${entites.length})`),
).toBeInTheDocument();
expect(await rendered.findByText('component1')).toBeInTheDocument();
expect(await rendered.findByText('component2')).toBeInTheDocument();
expect(await rendered.findByText('component3')).toBeInTheDocument();
waitFor(() => {
expect(rendered.queryByText(/Owned \(3\)/)).toBeInTheDocument();
expect(rendered.queryByText(/component1/)).toBeInTheDocument();
expect(rendered.queryByText(/component2/)).toBeInTheDocument();
expect(rendered.queryByText(/component3/)).toBeInTheDocument();
});
});
});
@@ -13,16 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Entity } from '@backstage/catalog-model';
import { Table, TableColumn } from '@backstage/core';
import { Entity, LocationSpec } from '@backstage/catalog-model';
import { Table, TableColumn, TableProps } from '@backstage/core';
import { Link } from '@material-ui/core';
import Edit from '@material-ui/icons/Edit';
import GitHub from '@material-ui/icons/GitHub';
import Star from '@material-ui/icons/Star';
import StarOutline from '@material-ui/icons/StarBorder';
import { Alert } from '@material-ui/lab';
import React, { FC } from 'react';
import React from 'react';
import { generatePath, Link as RouterLink } from 'react-router-dom';
import { findLocationForEntityMeta } from '../../data/utils';
import { useStarredEntities } from '../../hooks/useStarredEntites';
import { entityRoute } from '../../routes';
const columns: TableColumn[] = [
const columns: TableColumn<Entity>[] = [
{
title: 'Name',
field: 'metadata.name',
@@ -63,16 +68,16 @@ type CatalogTableProps = {
titlePreamble: string;
loading: boolean;
error?: any;
actions?: any;
};
export const CatalogTable: FC<CatalogTableProps> = ({
export const CatalogTable = ({
entities,
loading,
error,
titlePreamble,
actions,
}) => {
}: CatalogTableProps) => {
const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
if (error) {
return (
<div>
@@ -83,8 +88,52 @@ export const CatalogTable: FC<CatalogTableProps> = ({
);
}
const actions: TableProps<Entity>['actions'] = [
(rowData: Entity) => {
const location = findLocationForEntityMeta(rowData.metadata);
return {
icon: GitHub,
tooltip: 'View on GitHub',
onClick: () => {
if (!location) return;
window.open(location.target, '_blank');
},
hidden: location?.type !== 'github',
};
},
(rowData: Entity) => {
const createEditLink = (location: LocationSpec): string => {
switch (location.type) {
case 'github':
return location.target.replace('/blob/', '/edit/');
default:
return location.target;
}
};
const location = findLocationForEntityMeta(rowData.metadata);
return {
icon: Edit,
tooltip: 'Edit',
// iconProps: { size: 'small' },
onClick: () => {
if (!location) return;
window.open(createEditLink(location), '_blank');
},
hidden: location?.type !== 'github',
};
},
(rowData: Entity) => {
const isStarred = isStarredEntity(rowData);
return {
icon: isStarred ? () => <Star htmlColor="#f3ba37" /> : StarOutline,
tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',
onClick: () => toggleStarredEntity(rowData),
};
},
];
return (
<Table
<Table<Entity>
isLoading={loading}
columns={columns}
options={{