Table component with filter and search (#600)

* Initial table component with storybook example

* Moved dependencies to package/core

* Removed dependency to @backstage/core from base package.json

* Clean up some examples and remove type from columns, replacing with property align instead

* Removed more unused stuff and added toggle for filter input

* Fixed some lint issues

* Added example with material-table

* Convert column array passed into MaterialTable Backstage component into MT column array. Allow multiple values in one cell

* Removed subheader from MT

* Nicer double value cell

* Added custom sorting to example

* Cleaned up stories a bit

* Setting field instead of customSort

* Improve styling. Still needs better theme integration

* Using more colors from theme

* Fixed typing issue

* Removed react-table implementation and cleaned up material-table implementation

* Fixed some type issues

* Fixed lint issues
This commit is contained in:
Sebastian Qvarfordt
2020-05-04 11:10:35 +02:00
committed by GitHub
parent 031a4356f1
commit 190f11c8f7
25 changed files with 649 additions and 52 deletions
+1 -1
View File
@@ -84,7 +84,7 @@ const Root: FC<{}> = ({ children }) => (
<SidebarItem icon={HomeIcon} to="/" text="Home" />
<SidebarItem icon={ExploreIcon} to="/explore" text="Explore" />
<SidebarItem icon={CreateComponentIcon} to="/scaffolder" text="Create" />
<SidebarDivider />
<SidebarDivider />
<SidebarItem icon={AccountTreeIcon} to="/inventory" text="Inventory" />
<SidebarItem icon={AccountCircle} to="/login" text="Login" />
<SidebarDivider />
+1
View File
@@ -45,6 +45,7 @@
"classnames": "^2.2.6",
"clsx": "^1.1.0",
"lodash": "^4.17.15",
"material-table": "^1.57.2",
"prop-types": "^15.7.2",
"rc-progress": "^2.5.2",
"react": "^16.12.0",
+1 -1
View File
@@ -118,7 +118,7 @@ export default class AppBuilder {
<Switch>
{routes}
<Route
render={props => (
render={(props) => (
<ErrorPage {...props} status="404" statusMessage="PAGE NOT FOUND" />
)}
/>
@@ -19,7 +19,7 @@ import { BackstageTheme } from '@backstage/theme';
import classNames from 'classnames';
import React, { FC } from 'react';
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>((theme) => ({
status: {
width: 12,
height: 12,
@@ -55,7 +55,7 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
},
}));
export const StatusOK: FC<{}> = props => {
export const StatusOK: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -66,7 +66,7 @@ export const StatusOK: FC<{}> = props => {
);
};
export const StatusWarning: FC<{}> = props => {
export const StatusWarning: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -77,7 +77,7 @@ export const StatusWarning: FC<{}> = props => {
);
};
export const StatusError: FC<{}> = props => {
export const StatusError: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -88,13 +88,13 @@ export const StatusError: FC<{}> = props => {
);
};
export const StatusNA: FC<{}> = props => (
export const StatusNA: FC<{}> = (props) => (
<span aria-label="Status N/A" {...props}>
N/A
</span>
);
export const StatusPending: FC<{}> = props => {
export const StatusPending: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -105,7 +105,7 @@ export const StatusPending: FC<{}> = props => {
);
};
export const StatusRunning: FC<{}> = props => {
export const StatusRunning: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -116,7 +116,7 @@ export const StatusRunning: FC<{}> = props => {
);
};
export const StatusFailed: FC<{}> = props => {
export const StatusFailed: FC<{}> = (props) => {
const classes = useStyles(props);
return (
<span
@@ -0,0 +1,47 @@
/*
* 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 { BackstageTheme } from '@backstage/theme';
import { makeStyles } from '@material-ui/core';
const useSubvalueCellStyles = makeStyles<BackstageTheme>(theme => ({
value: {
marginBottom: '6px',
},
subvalue: {
color: theme.palette.textSubtle,
fontWeight: 'normal',
},
}));
type SubvalueCellProps = {
value: React.ReactNode;
subvalue: React.ReactNode;
};
const SubvalueCell: FC<SubvalueCellProps> = ({ value, subvalue }) => {
const classes = useSubvalueCellStyles();
return (
<>
<div className={classes.value}>{value}</div>
<div className={classes.subvalue}>{subvalue}</div>
</>
);
};
export default SubvalueCell;
@@ -0,0 +1,143 @@
/*
* 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 Table, { SubvalueCell, TableColumn } from './';
export default {
title: 'Table',
component: Table,
};
const generateTestData: (number: number) => Array<{}> = (rows = 20) => {
const data: Array<{}> = [];
while (data.length <= rows) {
data.push({
col1: `Some value ${data.length}`,
col2: `More data ${data.length}`,
subvalue: `Subvalue ${data.length}`,
number: Math.floor(Math.random() * 1000),
date: new Date(Math.random() * 10000000000000),
});
}
return data;
};
const testData100 = generateTestData(100);
export const DefaultTable = () => {
const columns: TableColumn[] = [
{
title: 'Column 1',
field: 'col1',
highlight: true,
},
{
title: 'Column 2',
field: 'col2',
},
{
title: 'Numeric value',
field: 'number',
type: 'numeric',
},
{
title: 'A Date',
field: 'date',
type: 'date',
},
];
return (
<Table
options={{ paging: false }}
data={testData100}
columns={columns}
title="Backstage Table"
/>
);
};
export const HiddenSearchTable = () => {
const columns: TableColumn[] = [
{
title: 'Column 1',
field: 'col1',
highlight: true,
},
{
title: 'Column 2',
field: 'col2',
},
{
title: 'Numeric value',
field: 'number',
type: 'numeric',
},
{
title: 'A Date',
field: 'date',
type: 'date',
},
];
return (
<Table
options={{ paging: false, search: false }}
data={testData100}
columns={columns}
/>
);
};
export const SubvalueTable = () => {
const columns: TableColumn[] = [
{
title: 'Column 1',
customFilterAndSearch: (
query,
row: any, // Only needed if you want subvalue searchable
) =>
`${row.col1} ${row.subvalue}`
.toUpperCase()
.includes(query.toUpperCase()),
field: 'col1',
highlight: true,
render: (row: any): React.ReactNode => (
<SubvalueCell value={row.col1} subvalue={row.subvalue} />
),
},
{
title: 'Column 2',
field: 'col2',
},
{
title: 'Numeric value',
field: 'number',
type: 'numeric',
},
{
title: 'A Date',
field: 'date',
type: 'date',
},
];
return (
<Table options={{ paging: false }} data={testData100} columns={columns} />
);
};
@@ -0,0 +1,50 @@
/*
* 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 { render } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import Table from './';
const minProps = {
columns: [
{
title: 'Column 1',
field: 'col1',
},
{
title: 'Column 2',
field: 'col2',
},
],
data: [
{
col1: 'first value, first row',
col2: 'second value, first row',
},
{
col1: 'first value, second row',
col2: 'second value, second row',
},
],
};
describe('<Table />', () => {
it('renders without exploding', () => {
const rendered = render(wrapInTestApp(<Table {...minProps} />));
expect(rendered.getByText('second value, second row')).toBeInTheDocument();
});
});
@@ -0,0 +1,192 @@
/*
* 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, forwardRef } from 'react';
import MTable, {
MTableCell,
MTableHeader,
MTableToolbar,
MaterialTableProps,
Options,
Column,
} from 'material-table';
import { BackstageTheme } from '@backstage/theme';
import { makeStyles } 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,
ArrowUpward,
Check,
ChevronLeft,
ChevronRight,
Clear,
DeleteOutline,
Edit,
FilterList,
FirstPage,
LastPage,
Remove,
SaveAlt,
Search,
ViewColumn,
} from '@material-ui/icons';
const tableIcons = {
Add: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<AddBox {...props} ref={ref} />
)),
Check: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Check {...props} ref={ref} />
)),
Clear: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Clear {...props} ref={ref} />
)),
Delete: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<DeleteOutline {...props} ref={ref} />
)),
DetailPanel: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<ChevronRight {...props} ref={ref} />
)),
Edit: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Edit {...props} ref={ref} />
)),
Export: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<SaveAlt {...props} ref={ref} />
)),
Filter: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<FilterList {...props} ref={ref} />
)),
FirstPage: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<FirstPage {...props} ref={ref} />
)),
LastPage: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<LastPage {...props} ref={ref} />
)),
NextPage: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<ChevronRight {...props} ref={ref} />
)),
PreviousPage: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<ChevronLeft {...props} ref={ref} />
)),
ResetSearch: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Clear {...props} ref={ref} />
)),
Search: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Search {...props} ref={ref} />
)),
SortArrow: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<ArrowUpward {...props} ref={ref} />
)),
ThirdStateCheck: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<Remove {...props} ref={ref} />
)),
ViewColumn: forwardRef((props, ref: React.Ref<SVGSVGElement>) => (
<ViewColumn {...props} ref={ref} />
)),
};
const useCellStyles = makeStyles<BackstageTheme>(theme => ({
root: {
color: theme.palette.grey[500],
padding: theme.spacing(0, 2, 0, 2.5),
height: '56px',
},
}));
const useHeaderStyles = makeStyles<BackstageTheme>(theme => ({
header: {
padding: theme.spacing(1, 2, 1, 2.5),
borderTop: `1px solid ${theme.palette.grey.A100}`,
borderBottom: `1px solid ${theme.palette.grey.A100}`,
color: theme.palette.textSubtle,
fontWeight: 'bold',
position: 'static',
},
}));
const useToolbarStyles = makeStyles<BackstageTheme>(theme => ({
root: {
padding: theme.spacing(3, 0, 2.5, 2.5),
},
title: {
'& > h6': {
fontWeight: 'bold',
},
},
}));
const convertColumns = (columns: TableColumn[]): TableColumn[] => {
return columns.map(column => {
const headerStyle: React.CSSProperties = {};
const cellStyle: React.CSSProperties = {};
if (column.highlight) {
headerStyle.color = '#000000';
cellStyle.fontWeight = 'bold';
}
return {
...column,
headerStyle,
cellStyle,
};
});
};
export interface TableColumn extends Column<{}> {
highlight?: boolean;
}
export interface TableProps extends MaterialTableProps<{}> {
columns: TableColumn[];
}
const Table: FC<TableProps> = ({ columns, options, ...props }) => {
const cellClasses = useCellStyles();
const headerClasses = useHeaderStyles();
const toolbarClasses = useToolbarStyles();
const MTColumns = convertColumns(columns);
const defaultOptions: Options = {
headerStyle: {
textTransform: 'uppercase',
},
};
return (
<MTable
components={{
Cell: cellProps => (
<MTableCell className={cellClasses.root} {...cellProps} />
),
Header: headerProps => (
<MTableHeader classes={headerClasses} {...headerProps} />
),
Toolbar: toolbarProps => (
<MTableToolbar classes={toolbarClasses} {...toolbarProps} />
),
}}
options={{ ...defaultOptions, ...options }}
columns={MTColumns}
icons={tableIcons}
{...props}
/>
);
};
export default Table;
@@ -0,0 +1,18 @@
/*
* 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, TableColumn } from './Table';
export { default as SubvalueCell } from './SubvalueCell';
@@ -28,7 +28,7 @@ interface IErrorPageProps {
};
}
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>((theme) => ({
container: {
padding: theme.spacing(8),
},
@@ -27,18 +27,18 @@ import {
import ErrorBoundary from 'layout/ErrorBoundary/ErrorBoundary';
import BottomLink, { Props as BottomLinkProps } from '../BottomLink';
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
header: {
padding: theme.spacing(2, 2, 2, 2.5),
},
}));
const BoldHeader = withStyles(theme => ({
const BoldHeader = withStyles((theme) => ({
title: { fontWeight: 700 },
subheader: { paddingTop: theme.spacing(1) },
}))(CardHeader);
const CardActionsTopRight = withStyles(theme => ({
const CardActionsTopRight = withStyles((theme) => ({
root: {
display: 'inline-block',
padding: theme.spacing(8, 8, 0, 0),
@@ -154,7 +154,7 @@ const InfoCard: FC<Props> = ({
if (variant) {
const variants = variant.split(/[\s]+/g);
variants.forEach(name => {
variants.forEach((name) => {
calculatedStyle = {
...calculatedStyle,
...VARIANT_STYLES.card[name as keyof typeof VARIANT_STYLES['card']],
+1 -1
View File
@@ -11,7 +11,7 @@ module.exports = {
'@storybook/addon-storysource',
'storybook-dark-mode/register',
],
webpackFinal: async config => {
webpackFinal: async (config) => {
const coreSrc = path.resolve(__dirname, '../../core/src');
config.resolve.alias = {
@@ -28,7 +28,7 @@ import {
} from '@material-ui/core';
import { BackstageTheme } from '@backstage/theme';
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>((theme) => ({
card: {
display: 'flex',
flexDirection: 'column',
@@ -27,7 +27,7 @@ import {
import ExploreCard, { CardData } from './ExploreCard';
import { BackstageTheme } from '@backstage/theme';
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>((theme) => ({
container: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, 296px)',
@@ -24,7 +24,7 @@ import { BackstageTheme } from '@backstage/theme';
const GraphiQL = React.lazy(() => import('graphiql'));
const useStyles = makeStyles<BackstageTheme>(theme => ({
const useStyles = makeStyles<BackstageTheme>((theme) => ({
root: {
height: '100%',
display: 'flex',
@@ -20,13 +20,13 @@ export class AggregatorInventory implements Inventory {
inventories: Inventory[] = [];
list(): Promise<Array<Component>> {
return Promise.all(this.inventories.map(i => i.list())).then(lists =>
return Promise.all(this.inventories.map((i) => i.list())).then((lists) =>
lists.flat(),
);
}
item(id: string): Promise<Component | undefined> {
return this.list().then(items => items.find(i => i.id === id));
return this.list().then((items) => items.find((i) => i.id === id));
}
enlist(inventory: Inventory) {
@@ -24,6 +24,6 @@ export class StaticInventory implements Inventory {
}
item(id: string): Promise<Component | undefined> {
return this.list().then(items => items.find(i => i.id === id));
return this.list().then((items) => items.find((i) => i.id === id));
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ startServer({
? Boolean(process.env.PLUGIN_CORS)
: false,
logger: getRootLogger(),
}).catch(err => {
}).catch((err) => {
getRootLogger().error(err);
process.exit(1);
});
@@ -14,17 +14,16 @@
* limitations under the License.
*/
import React, { FC } from 'react';
import {
Link,
TableCell,
TableRow,
} from '@material-ui/core';
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 {
Website,
} from '../../api';
import { formatTime, CATEGORIES, CATEGORY_LABELS, SparklinesDataByCategory } from '../../utils';
formatTime,
CATEGORIES,
CATEGORY_LABELS,
SparklinesDataByCategory,
} from '../../utils';
import AuditStatusIcon from '../AuditStatusIcon';
const useStyles = makeStyles(theme => ({
@@ -76,9 +75,7 @@ export const AuditRow: FC<{
{website.lastAudit.status.toLowerCase()}
</span>
</TableCell>
<TableCell>
{formatTime(website.lastAudit.timeCreated)}
</TableCell>
<TableCell>{formatTime(website.lastAudit.timeCreated)}</TableCell>
</TableRow>
);
};
@@ -23,11 +23,14 @@ import {
TableRow,
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { Website } from '../../api';
import {
Website,
} from '../../api';
import { CATEGORIES, CATEGORY_LABELS, SparklinesDataByCategory, buildSparklinesDataForItem } from '../../utils';
import Audit from '../Audit'
CATEGORIES,
CATEGORY_LABELS,
SparklinesDataByCategory,
buildSparklinesDataForItem,
} from '../../utils';
import Audit from '../Audit';
const useStyles = makeStyles(theme => ({
table: {
@@ -51,7 +54,7 @@ export const AuditListTable: FC<{ items: Website[] }> = ({ items }) => {
() =>
items.reduce(
(res, item) => ({
...res,
...res,
[item.url]: buildSparklinesDataForItem(item),
}),
{},
@@ -84,7 +84,14 @@ const CreateAudit: FC<{}> = () => {
} finally {
setSubmitting(false);
}
}, [url, emulatedFormFactor, lighthouseApi, setSubmitting, errorApi, history]);
}, [
url,
emulatedFormFactor,
lighthouseApi,
setSubmitting,
errorApi,
history,
]);
return (
<Page theme={pageTheme.tool}>
+5 -3
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { useLocation } from 'react-router-dom';
import {Website, Audit, LighthouseCategoryId, AuditCompleted} from './api'
import { Website, Audit, LighthouseCategoryId, AuditCompleted } from './api';
export function useQuery(): URLSearchParams {
return new URLSearchParams(useLocation().search);
}
@@ -45,7 +45,9 @@ export const CATEGORY_LABELS: Record<LighthouseCategoryId, string> = {
};
export type SparklinesDataByCategory = Record<LighthouseCategoryId, number[]>;
export function buildSparklinesDataForItem(item: Website): SparklinesDataByCategory {
export function buildSparklinesDataForItem(
item: Website,
): SparklinesDataByCategory {
return item.audits
.filter(
(audit: Audit): audit is AuditCompleted => audit.status === 'COMPLETED',
@@ -63,4 +65,4 @@ export function buildSparklinesDataForItem(item: Website): SparklinesDataByCateg
return scores;
}, {} as SparklinesDataByCategory);
}
}
@@ -20,7 +20,7 @@ export default class MyDocument extends Document {
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App: any) => props =>
enhanceApp: (App: any) => (props) =>
sheet.collectStyles(<App {...props} />),
});
@@ -33,7 +33,7 @@ const ScaffolderPage: React.FC<{}> = () => {
<Header title="Create a new component" subtitle="All your stuff" />
<Content>
<div style={{ display: 'flex' }}>
{STATIC_DATA.map(item => {
{STATIC_DATA.map((item) => {
return (
<InfoCard
title={item.name}
+144 -7
View File
@@ -926,6 +926,14 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-typescript" "^7.9.0"
"@babel/runtime-corejs2@^7.4.4":
version "7.9.2"
resolved "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.9.2.tgz#f11d074ff99b9b4319b5ecf0501f12202bf2bf4d"
integrity sha512-ayjSOxuK2GaSDJFCtLgHnYjuMyIpViNujWrZo8GUpN60/n7juzJKK5yOo6RFVb0zdU9ACJFK+MsZrUnj3OmXMw==
dependencies:
core-js "^2.6.5"
regenerator-runtime "^0.13.4"
"@babel/runtime-corejs3@^7.7.4", "@babel/runtime-corejs3@^7.8.3":
version "7.9.2"
resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz#26fe4aa77e9f1ecef9b776559bbb8e84d34284b7"
@@ -941,7 +949,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.9.2"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06"
integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==
@@ -1178,6 +1186,18 @@
debug "^3.1.0"
lodash.once "^4.1.1"
"@date-io/core@1.x", "@date-io/core@^1.3.13":
version "1.3.13"
resolved "https://registry.npmjs.org/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa"
integrity sha512-AlEKV7TxjeK+jxWVKcCFrfYAk8spX9aCyiToFIiLPtfQbsjmRGLIhb5VZgptQcJdHtLXo7+m0DuurwFgUToQuA==
"@date-io/date-fns@^1.1.0":
version "1.3.13"
resolved "https://registry.npmjs.org/@date-io/date-fns/-/date-fns-1.3.13.tgz#7798844041640ab393f7e21a7769a65d672f4735"
integrity sha512-yXxGzcRUPcogiMj58wVgFjc9qUYrCnnU9eLcyNbsQCmae4jPuZCDoIBR21j8ZURsM7GRtU62VOw5yNd4dDHunA==
dependencies:
"@date-io/core" "^1.3.13"
"@emotion/cache@^10.0.27":
version "10.0.29"
resolved "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0"
@@ -2468,6 +2488,18 @@
prop-types "^15.7.2"
react-is "^16.8.0"
"@material-ui/pickers@^3.2.2":
version "3.2.10"
resolved "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae"
integrity sha512-B8G6Obn5S3RCl7hwahkQj9sKUapwXWFjiaz/Bsw1fhYFdNMnDUolRiWQSoKPb1/oKe37Dtfszoywi1Ynbo3y8w==
dependencies:
"@babel/runtime" "^7.6.0"
"@date-io/core" "1.x"
"@types/styled-jsx" "^2.2.8"
clsx "^1.0.2"
react-transition-group "^4.0.0"
rifm "^0.7.0"
"@material-ui/styles@^4.9.6":
version "4.9.6"
resolved "https://registry.npmjs.org/@material-ui/styles/-/styles-4.9.6.tgz#924a30bf7c9b91af9c8f19c12c8573b8a4ecd085"
@@ -4387,6 +4419,13 @@
resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/styled-jsx@^2.2.8":
version "2.2.8"
resolved "https://registry.npmjs.org/@types/styled-jsx/-/styled-jsx-2.2.8.tgz#b50d13d8a3c34036282d65194554cf186bab7234"
integrity sha512-Yjye9VwMdYeXfS71ihueWRSxrruuXTwKCbzue4+5b2rjnQ//AtyM7myZ1BEhNhBQ/nL/RE7bdToUoLln2miKvg==
dependencies:
"@types/react" "*"
"@types/superagent@*":
version "4.1.7"
resolved "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.7.tgz#a7d92d98c490ee0f802a127fdf149b9a114f77a5"
@@ -7215,7 +7254,7 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1:
resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a"
integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==
core-js@^2.4.0, core-js@^2.5.0:
core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5:
version "2.6.11"
resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
@@ -7398,6 +7437,13 @@ css-blank-pseudo@^0.1.4:
dependencies:
postcss "^7.0.5"
css-box-model@^1.1.2:
version "1.2.0"
resolved "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.0.tgz#3a26377b4162b3200d2ede4b064ec5b6a75186d0"
integrity sha512-lri0br+jSNV0kkkiGEp9y9y3Njq2PmpqbeGWRFQJuZteZzY9iC9GZhQ8Y4WpPwM/2YocjHePxy14igJY7YKzkA==
dependencies:
tiny-invariant "^1.0.6"
css-color-names@0.0.4, css-color-names@^0.0.4:
version "0.0.4"
resolved "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
@@ -7834,11 +7880,21 @@ date-fns@^1.27.2:
resolved "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
date-fns@^2.0.0-alpha.27:
version "2.12.0"
resolved "https://registry.npmjs.org/date-fns/-/date-fns-2.12.0.tgz#01754c8a2f3368fc1119cf4625c3dad8c1845ee6"
integrity sha512-qJgn99xxKnFgB1qL4jpxU7Q2t0LOn1p8KMIveef3UZD7kqjT3tpFNNdXJelEHhE+rUgffriXriw/sOSU+cS1Hw==
dateformat@^3.0.0:
version "3.0.3"
resolved "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
debounce@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -9258,7 +9314,7 @@ extsprintf@^1.2.0:
resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^2.0.1:
fast-deep-equal@2.0.1, fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
@@ -9430,6 +9486,11 @@ file-uri-to-path@1.0.0:
resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filefy@0.1.10:
version "0.1.10"
resolved "https://registry.npmjs.org/filefy/-/filefy-0.1.10.tgz#174677c8e2fa5bc39a3af0ed6fb492f16b8fbf42"
integrity sha512-VgoRVOOY1WkTpWH+KBy8zcU1G7uQTVsXqhWEgzryB9A5hg2aqCyZ6aQ/5PSzlqM5+6cnVrX6oYV0XqD3HZSnmQ==
filesize@3.6.1:
version "3.6.1"
resolved "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
@@ -13915,6 +13976,22 @@ marked@^0.8.0:
resolved "https://registry.npmjs.org/marked/-/marked-0.8.1.tgz#a233f39572fab15ede53a3c3be8a139bff86d2dd"
integrity sha512-tZfJS8uE0zpo7xpTffwFwYRfW9AzNcdo04Qcjs+C9+oCy8MSRD2reD5iDVtYx8mtLaqsGughw/YLlcwNxAHA1g==
material-table@^1.57.2:
version "1.57.2"
resolved "https://registry.npmjs.org/material-table/-/material-table-1.57.2.tgz#8854cb4d623b294138c83a0c7ff9f2900267c81f"
integrity sha512-hiJdRTrqu8pyYwSxzmcG1TnR4KWG2gtXrFB3XL9h4ij3A68EOJmlss6VH/LXh3NLlUce1TteK6W7fGa7YcnKGg==
dependencies:
"@date-io/date-fns" "^1.1.0"
"@material-ui/pickers" "^3.2.2"
classnames "^2.2.6"
date-fns "^2.0.0-alpha.27"
debounce "^1.2.0"
fast-deep-equal "2.0.1"
filefy "0.1.10"
prop-types "^15.6.2"
react-beautiful-dnd "11.0.3"
react-double-scrollbar "0.0.15"
md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -13972,6 +14049,11 @@ mem@^4.0.0:
mimic-fn "^2.0.0"
p-is-promise "^2.0.0"
memoize-one@^5.0.4:
version "5.1.1"
resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
memoizerific@^1.11.3:
version "1.11.3"
resolved "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a"
@@ -16973,6 +17055,11 @@ qw@~1.0.1:
resolved "https://registry.npmjs.org/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4"
integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=
raf-schd@^4.0.0:
version "4.0.2"
resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0"
integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -17063,6 +17150,20 @@ react-app-polyfill@^1.0.6:
regenerator-runtime "^0.13.3"
whatwg-fetch "^3.0.0"
react-beautiful-dnd@11.0.3:
version "11.0.3"
resolved "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-11.0.3.tgz#5678bb3e725d8b56cb7cf57f56e952105fc4f2af"
integrity sha512-2FX2SnOlKMmfn90xUHCav7cxRWXwY7FeRa6TzdxWeX7DdP5JTvVQcsWgiOkdbJSj+J+1q1nA9QO4/HQ52D0DAA==
dependencies:
"@babel/runtime-corejs2" "^7.4.4"
css-box-model "^1.1.2"
memoize-one "^5.0.4"
raf-schd "^4.0.0"
react-redux "^7.0.3"
redux "^4.0.1"
tiny-invariant "^1.0.4"
use-memo-one "^1.1.0"
react-clientside-effect@^1.2.2:
version "1.2.2"
resolved "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837"
@@ -17155,6 +17256,11 @@ react-dom@16.13.1, react-dom@^16.12.0, react-dom@^16.13.1, react-dom@^16.8.3:
prop-types "^15.6.2"
scheduler "^0.19.1"
react-double-scrollbar@0.0.15:
version "0.0.15"
resolved "https://registry.npmjs.org/react-double-scrollbar/-/react-double-scrollbar-0.0.15.tgz#e915ab8cb3b959877075f49436debfdb04288fe4"
integrity sha1-6RWrjLO5WYdwdfSUNt6/2wQoj+Q=
react-draggable@^4.0.3:
version "4.2.0"
resolved "https://registry.npmjs.org/react-draggable/-/react-draggable-4.2.0.tgz#40cc5209082ca7d613104bf6daf31372cc0e1114"
@@ -17222,7 +17328,7 @@ react-inspector@^4.0.0:
is-dom "^1.0.9"
prop-types "^15.6.1"
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -17267,6 +17373,17 @@ react-popper@^1.3.6:
typed-styles "^0.0.7"
warning "^4.0.2"
react-redux@^7.0.3:
version "7.2.0"
resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==
dependencies:
"@babel/runtime" "^7.5.5"
hoist-non-react-statics "^3.3.0"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.9.0"
react-router-dom@5.1.2, react-router-dom@^5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
@@ -17399,7 +17516,7 @@ react-textarea-autosize@^7.1.0:
"@babel/runtime" "^7.1.2"
prop-types "^15.6.0"
react-transition-group@^4.3.0:
react-transition-group@^4.0.0, react-transition-group@^4.3.0:
version "4.3.0"
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683"
integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==
@@ -17703,6 +17820,14 @@ redeyed@~2.1.0:
dependencies:
esprima "~4.0.0"
redux@^4.0.1:
version "4.0.5"
resolved "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
referrer-policy@1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e"
@@ -18132,6 +18257,13 @@ rgba-regex@^1.0.0:
resolved "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
rifm@^0.7.0:
version "0.7.0"
resolved "https://registry.npmjs.org/rifm/-/rifm-0.7.0.tgz#debe951a9c83549ca6b33e5919f716044c2230be"
integrity sha512-DSOJTWHD67860I5ojetXdEQRIBvF6YcpNe53j0vn1vp9EUb9N80EiZTxgP+FkDKorWC8PZw052kTF4C1GOivCQ==
dependencies:
"@babel/runtime" "^7.3.1"
right-pad@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/right-pad/-/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0"
@@ -19599,7 +19731,7 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
symbol-observable@^1.1.0:
symbol-observable@^1.1.0, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -19889,7 +20021,7 @@ tiny-emitter@^2.0.0:
resolved "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tiny-invariant@^1.0.2:
tiny-invariant@^1.0.2, tiny-invariant@^1.0.4, tiny-invariant@^1.0.6:
version "1.1.0"
resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
@@ -20538,6 +20670,11 @@ use-callback-ref@^1.2.1:
resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.1.tgz#898759ccb9e14be6c7a860abafa3ffbd826c89bb"
integrity sha512-C3nvxh0ZpaOxs9RCnWwAJ+7bJPwQI8LHF71LzbQ3BvzH5XkdtlkMadqElGevg5bYBDFip4sAnD4m06zAKebg1w==
use-memo-one@^1.1.0:
version "1.1.1"
resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c"
integrity sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==
use-sidecar@^1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.2.tgz#e72f582a75842f7de4ef8becd6235a4720ad8af6"