@genspectrum/dashboard-components 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +107 -12
- package/dist/dashboard-components.js +186 -145
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +24 -0
- package/package.json +1 -1
- package/src/preact/aggregatedData/aggregate-table.tsx +3 -2
- package/src/preact/aggregatedData/aggregate.stories.tsx +2 -0
- package/src/preact/aggregatedData/aggregate.tsx +8 -3
- package/src/preact/components/table.stories.tsx +51 -1
- package/src/preact/components/table.tsx +4 -3
- package/src/preact/locationFilter/location-filter.stories.tsx +12 -1
- package/src/preact/locationFilter/location-filter.tsx +10 -3
- package/src/preact/mutationComparison/mutation-comparison-table.tsx +7 -2
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -0
- package/src/preact/mutationComparison/mutation-comparison.tsx +25 -3
- package/src/preact/mutations/mutations-grid.tsx +8 -2
- package/src/preact/mutations/mutations-insertions-table.tsx +3 -2
- package/src/preact/mutations/mutations-table.tsx +3 -2
- package/src/preact/mutations/mutations.stories.tsx +3 -0
- package/src/preact/mutations/mutations.tsx +16 -6
- package/src/preact/prevalenceOverTime/prevalence-over-time-table.tsx +3 -2
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -0
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +8 -1
- package/src/web-components/input/gs-location-filter.stories.ts +11 -0
- package/src/web-components/input/gs-location-filter.tsx +14 -1
- package/src/web-components/visualization/gs-aggregate.stories.ts +4 -0
- package/src/web-components/visualization/gs-aggregate.tsx +8 -0
- package/src/web-components/visualization/gs-mutation-comparison.stories.ts +4 -0
- package/src/web-components/visualization/gs-mutation-comparison.tsx +8 -0
- package/src/web-components/visualization/gs-mutations.stories.ts +4 -0
- package/src/web-components/visualization/gs-mutations.tsx +8 -0
- package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +5 -0
- package/src/web-components/visualization/gs-prevalence-over-time.tsx +12 -4
|
@@ -66,6 +66,11 @@ export declare class AggregateComponent extends PreactLitAdapterWithGridJsStyles
|
|
|
66
66
|
* The initial sort direction of the table.
|
|
67
67
|
*/
|
|
68
68
|
initialSortDirection: 'ascending' | 'descending';
|
|
69
|
+
/**
|
|
70
|
+
* The maximum number of rows to display in the table view.
|
|
71
|
+
* Set to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).
|
|
72
|
+
*/
|
|
73
|
+
pageSize: boolean | number;
|
|
69
74
|
render(): JSX_2.Element;
|
|
70
75
|
}
|
|
71
76
|
|
|
@@ -228,6 +233,10 @@ export declare class LocationFilterComponent extends PreactLitAdapter {
|
|
|
228
233
|
* Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
|
|
229
234
|
*/
|
|
230
235
|
width: string;
|
|
236
|
+
/**
|
|
237
|
+
* The placeholder text to display in the input field, if it is empty.
|
|
238
|
+
*/
|
|
239
|
+
placeholderText: string;
|
|
231
240
|
render(): JSX_2.Element;
|
|
232
241
|
}
|
|
233
242
|
|
|
@@ -296,6 +305,11 @@ export declare class MutationComparisonComponent extends PreactLitAdapterWithGri
|
|
|
296
305
|
* The headline of the component. Set to an empty string to hide the headline.
|
|
297
306
|
*/
|
|
298
307
|
headline: string;
|
|
308
|
+
/**
|
|
309
|
+
* The maximum number of rows to display in the table view.
|
|
310
|
+
* Set to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).
|
|
311
|
+
*/
|
|
312
|
+
pageSize: boolean | number;
|
|
299
313
|
render(): JSX_2.Element;
|
|
300
314
|
}
|
|
301
315
|
|
|
@@ -433,6 +447,11 @@ export declare class MutationsComponent extends PreactLitAdapterWithGridJsStyles
|
|
|
433
447
|
* The headline of the component. Set to an empty string to hide the headline.
|
|
434
448
|
*/
|
|
435
449
|
headline: string;
|
|
450
|
+
/**
|
|
451
|
+
* The maximum number of rows to display in the table view.
|
|
452
|
+
* Set to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).
|
|
453
|
+
*/
|
|
454
|
+
pageSize: boolean | number;
|
|
436
455
|
render(): JSX_2.Element;
|
|
437
456
|
}
|
|
438
457
|
|
|
@@ -555,6 +574,11 @@ export declare class PrevalenceOverTimeComponent extends PreactLitAdapterWithGri
|
|
|
555
574
|
* Must be a field of type `date` in LAPIS.
|
|
556
575
|
*/
|
|
557
576
|
lapisDateField: string;
|
|
577
|
+
/**
|
|
578
|
+
* The maximum number of rows to display in the table view.
|
|
579
|
+
* Set to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).
|
|
580
|
+
*/
|
|
581
|
+
pageSize: boolean | number;
|
|
558
582
|
render(): JSX_2.Element;
|
|
559
583
|
}
|
|
560
584
|
|
package/package.json
CHANGED
|
@@ -7,9 +7,10 @@ import { formatProportion } from '../shared/table/formatProportion';
|
|
|
7
7
|
type AggregateTableProps = {
|
|
8
8
|
fields: string[];
|
|
9
9
|
data: AggregateData;
|
|
10
|
+
pageSize: boolean | number;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
|
-
export const AggregateTable: FunctionComponent<AggregateTableProps> = ({ data, fields }) => {
|
|
13
|
+
export const AggregateTable: FunctionComponent<AggregateTableProps> = ({ data, fields, pageSize }) => {
|
|
13
14
|
const headers = [
|
|
14
15
|
...fields.map((field) => {
|
|
15
16
|
return {
|
|
@@ -28,5 +29,5 @@ export const AggregateTable: FunctionComponent<AggregateTableProps> = ({ data, f
|
|
|
28
29
|
},
|
|
29
30
|
];
|
|
30
31
|
|
|
31
|
-
return <Table data={data} columns={headers}
|
|
32
|
+
return <Table data={data} columns={headers} pageSize={pageSize} />;
|
|
32
33
|
};
|
|
@@ -15,6 +15,7 @@ const meta: Meta<AggregateProps> = {
|
|
|
15
15
|
headline: { control: 'text' },
|
|
16
16
|
initialSortField: { control: 'text' },
|
|
17
17
|
initialSortDirection: { control: 'radio', options: ['ascending', 'descending'] },
|
|
18
|
+
pageSize: { control: 'object' },
|
|
18
19
|
},
|
|
19
20
|
parameters: {
|
|
20
21
|
fetchMock: {
|
|
@@ -57,5 +58,6 @@ export const Default: StoryObj<AggregateProps> = {
|
|
|
57
58
|
headline: 'Aggregate',
|
|
58
59
|
initialSortField: 'count',
|
|
59
60
|
initialSortDirection: 'descending',
|
|
61
|
+
pageSize: 10,
|
|
60
62
|
},
|
|
61
63
|
};
|
|
@@ -31,6 +31,7 @@ export interface AggregateInnerProps {
|
|
|
31
31
|
views: View[];
|
|
32
32
|
initialSortField: string;
|
|
33
33
|
initialSortDirection: 'ascending' | 'descending';
|
|
34
|
+
pageSize: boolean | number;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
export const Aggregate: FunctionComponent<AggregateProps> = ({
|
|
@@ -40,6 +41,7 @@ export const Aggregate: FunctionComponent<AggregateProps> = ({
|
|
|
40
41
|
headline = 'Mutations',
|
|
41
42
|
filter,
|
|
42
43
|
fields,
|
|
44
|
+
pageSize,
|
|
43
45
|
initialSortField,
|
|
44
46
|
initialSortDirection,
|
|
45
47
|
}) => {
|
|
@@ -55,6 +57,7 @@ export const Aggregate: FunctionComponent<AggregateProps> = ({
|
|
|
55
57
|
views={views}
|
|
56
58
|
initialSortField={initialSortField}
|
|
57
59
|
initialSortDirection={initialSortDirection}
|
|
60
|
+
pageSize={pageSize}
|
|
58
61
|
/>
|
|
59
62
|
</Headline>
|
|
60
63
|
</ResizeContainer>
|
|
@@ -68,6 +71,7 @@ export const AggregateInner: FunctionComponent<AggregateInnerProps> = ({
|
|
|
68
71
|
filter,
|
|
69
72
|
initialSortField,
|
|
70
73
|
initialSortDirection,
|
|
74
|
+
pageSize,
|
|
71
75
|
}) => {
|
|
72
76
|
const lapis = useContext(LapisUrlContext);
|
|
73
77
|
|
|
@@ -87,22 +91,23 @@ export const AggregateInner: FunctionComponent<AggregateInnerProps> = ({
|
|
|
87
91
|
return <NoDataDisplay />;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
return <AggregatedDataTabs data={data} views={views} fields={fields} />;
|
|
94
|
+
return <AggregatedDataTabs data={data} views={views} fields={fields} pageSize={pageSize} />;
|
|
91
95
|
};
|
|
92
96
|
|
|
93
97
|
type AggregatedDataTabsProps = {
|
|
94
98
|
data: AggregateData;
|
|
95
99
|
fields: string[];
|
|
96
100
|
views: View[];
|
|
101
|
+
pageSize: boolean | number;
|
|
97
102
|
};
|
|
98
103
|
|
|
99
|
-
const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data, views, fields }) => {
|
|
104
|
+
const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data, views, fields, pageSize }) => {
|
|
100
105
|
const getTab = (view: View) => {
|
|
101
106
|
switch (view) {
|
|
102
107
|
case 'table':
|
|
103
108
|
return {
|
|
104
109
|
title: 'Table',
|
|
105
|
-
content: <AggregateTable data={data} fields={fields} />,
|
|
110
|
+
content: <AggregateTable data={data} fields={fields} pageSize={pageSize} />,
|
|
106
111
|
};
|
|
107
112
|
}
|
|
108
113
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Meta, type StoryObj } from '@storybook/preact';
|
|
2
|
+
import { expect, userEvent, waitFor, within } from '@storybook/test';
|
|
2
3
|
|
|
3
4
|
import { Table } from './table';
|
|
4
5
|
|
|
@@ -6,13 +7,51 @@ const meta: Meta = {
|
|
|
6
7
|
title: 'Component/Table',
|
|
7
8
|
component: Table,
|
|
8
9
|
parameters: { fetchMock: {} },
|
|
10
|
+
argTypes: {
|
|
11
|
+
data: { control: 'object' },
|
|
12
|
+
columns: { control: 'object' },
|
|
13
|
+
pageSize: { control: 'object' },
|
|
14
|
+
},
|
|
9
15
|
};
|
|
10
16
|
|
|
11
17
|
export default meta;
|
|
12
18
|
|
|
13
19
|
export const TableStory: StoryObj = {
|
|
14
20
|
render: (args) => {
|
|
15
|
-
return <Table data={args.data} columns={args.columns}
|
|
21
|
+
return <Table data={args.data} columns={args.columns} pageSize={args.pageSize} />;
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
data: [
|
|
25
|
+
['John Do', 'john@example.com', '123-456-7890'],
|
|
26
|
+
['Jane Doe', 'jane@example.com', '098-765-4321'],
|
|
27
|
+
],
|
|
28
|
+
columns: [{ name: 'Name' }, { name: 'Email', sort: true }, { name: 'Phone Number' }],
|
|
29
|
+
pageSize: 1,
|
|
30
|
+
},
|
|
31
|
+
play: async ({ canvasElement, step }) => {
|
|
32
|
+
const canvas = within(canvasElement);
|
|
33
|
+
|
|
34
|
+
const firstRow = () => canvas.queryByText('John Do', { exact: true });
|
|
35
|
+
const secondRow = () => canvas.queryByText('Jane Doe', { exact: true });
|
|
36
|
+
|
|
37
|
+
await step('Expect first row to be visible and not second row', async () => {
|
|
38
|
+
await waitFor(() => expect(firstRow()).toBeVisible());
|
|
39
|
+
await expect(secondRow()).toBeNull();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await step('Expect second row to be visible and not first row after clicking next', async () => {
|
|
43
|
+
const nextButton = canvas.getByRole('button', { name: 'Next' });
|
|
44
|
+
await userEvent.click(nextButton);
|
|
45
|
+
|
|
46
|
+
await waitFor(() => expect(secondRow()).toBeVisible());
|
|
47
|
+
await expect(firstRow()).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const TableStoryNoPagination: StoryObj = {
|
|
53
|
+
render: (args) => {
|
|
54
|
+
return <Table data={args.data} columns={args.columns} pageSize={args.pageSize} />;
|
|
16
55
|
},
|
|
17
56
|
args: {
|
|
18
57
|
data: [
|
|
@@ -20,5 +59,16 @@ export const TableStory: StoryObj = {
|
|
|
20
59
|
['Jane Doe', 'jane@example.com', '098-765-4321'],
|
|
21
60
|
],
|
|
22
61
|
columns: [{ name: 'Name' }, { name: 'Email', sort: true }, { name: 'Phone Number' }],
|
|
62
|
+
pageSize: false,
|
|
63
|
+
},
|
|
64
|
+
play: async ({ canvasElement }) => {
|
|
65
|
+
const canvas = within(canvasElement);
|
|
66
|
+
|
|
67
|
+
const firstRow = () => canvas.queryByText('John Do', { exact: true });
|
|
68
|
+
const secondRow = () => canvas.queryByText('Jane Doe', { exact: true });
|
|
69
|
+
|
|
70
|
+
await waitFor(() => expect(firstRow()).toBeVisible());
|
|
71
|
+
await expect(secondRow()).toBeVisible();
|
|
72
|
+
await waitFor(() => expect(canvas.queryByText('Next')).toBeNull());
|
|
23
73
|
},
|
|
24
74
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Grid } from 'gridjs';
|
|
2
2
|
import { type OneDArray, type TColumn, type TData } from 'gridjs/dist/src/types';
|
|
3
|
-
import { type PaginationConfig } from 'gridjs/dist/src/view/plugin/pagination';
|
|
4
3
|
import { type ComponentChild } from 'preact';
|
|
5
4
|
import { useEffect, useRef } from 'preact/hooks';
|
|
6
5
|
|
|
@@ -26,10 +25,12 @@ export const tableStyle = {
|
|
|
26
25
|
interface TableProps {
|
|
27
26
|
data: TData;
|
|
28
27
|
columns: OneDArray<TColumn | string | ComponentChild>;
|
|
29
|
-
|
|
28
|
+
pageSize: number | boolean;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
export const Table = ({ data, columns,
|
|
31
|
+
export const Table = ({ data, columns, pageSize }: TableProps) => {
|
|
32
|
+
const pagination = typeof pageSize === 'number' ? { limit: pageSize } : pageSize;
|
|
33
|
+
|
|
33
34
|
const wrapper = useRef(null);
|
|
34
35
|
|
|
35
36
|
useEffect(() => {
|
|
@@ -35,6 +35,7 @@ const meta: Meta<LocationFilterProps> = {
|
|
|
35
35
|
width: '100%',
|
|
36
36
|
fields: ['region', 'country', 'division', 'location'],
|
|
37
37
|
initialValue: 'Europe',
|
|
38
|
+
placeholderText: 'Enter a location',
|
|
38
39
|
},
|
|
39
40
|
argTypes: {
|
|
40
41
|
fields: {
|
|
@@ -52,6 +53,11 @@ const meta: Meta<LocationFilterProps> = {
|
|
|
52
53
|
type: 'text',
|
|
53
54
|
},
|
|
54
55
|
},
|
|
56
|
+
placeholderText: {
|
|
57
|
+
control: {
|
|
58
|
+
type: 'text',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
55
61
|
},
|
|
56
62
|
decorators: [withActions],
|
|
57
63
|
};
|
|
@@ -61,7 +67,12 @@ export default meta;
|
|
|
61
67
|
export const Primary: StoryObj<LocationFilterProps> = {
|
|
62
68
|
render: (args) => (
|
|
63
69
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
64
|
-
<LocationFilter
|
|
70
|
+
<LocationFilter
|
|
71
|
+
fields={args.fields}
|
|
72
|
+
initialValue={args.initialValue}
|
|
73
|
+
width={args.width}
|
|
74
|
+
placeholderText={args.placeholderText}
|
|
75
|
+
/>
|
|
65
76
|
</LapisUrlContext.Provider>
|
|
66
77
|
),
|
|
67
78
|
};
|
|
@@ -12,6 +12,7 @@ import { useQuery } from '../useQuery';
|
|
|
12
12
|
|
|
13
13
|
export interface LocationFilterInnerProps {
|
|
14
14
|
initialValue?: string;
|
|
15
|
+
placeholderText?: string;
|
|
15
16
|
fields: string[];
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -19,19 +20,24 @@ export interface LocationFilterProps extends LocationFilterInnerProps {
|
|
|
19
20
|
width: string;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export const LocationFilter: FunctionComponent<LocationFilterProps> = ({
|
|
23
|
+
export const LocationFilter: FunctionComponent<LocationFilterProps> = ({
|
|
24
|
+
width,
|
|
25
|
+
initialValue,
|
|
26
|
+
fields,
|
|
27
|
+
placeholderText,
|
|
28
|
+
}) => {
|
|
23
29
|
const size = { width, height: '3rem' };
|
|
24
30
|
|
|
25
31
|
return (
|
|
26
32
|
<ErrorBoundary size={size}>
|
|
27
33
|
<ResizeContainer size={size}>
|
|
28
|
-
<LocationFilterInner initialValue={initialValue} fields={fields} />
|
|
34
|
+
<LocationFilterInner initialValue={initialValue} fields={fields} placeholderText={placeholderText} />
|
|
29
35
|
</ResizeContainer>
|
|
30
36
|
</ErrorBoundary>
|
|
31
37
|
);
|
|
32
38
|
};
|
|
33
39
|
|
|
34
|
-
export const LocationFilterInner = ({ initialValue, fields }: LocationFilterInnerProps) => {
|
|
40
|
+
export const LocationFilterInner = ({ initialValue, fields, placeholderText }: LocationFilterInnerProps) => {
|
|
35
41
|
const lapis = useContext(LapisUrlContext);
|
|
36
42
|
|
|
37
43
|
const [value, setValue] = useState(initialValue ?? '');
|
|
@@ -77,6 +83,7 @@ export const LocationFilterInner = ({ initialValue, fields }: LocationFilterInne
|
|
|
77
83
|
value={value}
|
|
78
84
|
onInput={onInput}
|
|
79
85
|
list='countries'
|
|
86
|
+
placeholder={placeholderText}
|
|
80
87
|
/>
|
|
81
88
|
<datalist id='countries'>
|
|
82
89
|
{data?.map((v) => {
|
|
@@ -12,9 +12,14 @@ import { formatProportion } from '../shared/table/formatProportion';
|
|
|
12
12
|
export interface MutationsTableProps {
|
|
13
13
|
data: Dataset<MutationData>;
|
|
14
14
|
proportionInterval: ProportionInterval;
|
|
15
|
+
pageSize: boolean | number;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export const MutationComparisonTable: FunctionComponent<MutationsTableProps> = ({
|
|
18
|
+
export const MutationComparisonTable: FunctionComponent<MutationsTableProps> = ({
|
|
19
|
+
data,
|
|
20
|
+
proportionInterval,
|
|
21
|
+
pageSize,
|
|
22
|
+
}) => {
|
|
18
23
|
const headers = [
|
|
19
24
|
{
|
|
20
25
|
name: 'Mutation',
|
|
@@ -37,5 +42,5 @@ export const MutationComparisonTable: FunctionComponent<MutationsTableProps> = (
|
|
|
37
42
|
|
|
38
43
|
const tableData = getMutationComparisonTableData(data, proportionInterval).map((row) => Object.values(row));
|
|
39
44
|
|
|
40
|
-
return <Table data={tableData} columns={headers}
|
|
45
|
+
return <Table data={tableData} columns={headers} pageSize={pageSize} />;
|
|
41
46
|
};
|
|
@@ -30,6 +30,7 @@ const meta: Meta<MutationComparisonProps> = {
|
|
|
30
30
|
width: { control: 'text' },
|
|
31
31
|
height: { control: 'text' },
|
|
32
32
|
headline: { control: 'text' },
|
|
33
|
+
pageSize: { control: 'object' },
|
|
33
34
|
},
|
|
34
35
|
parameters: {
|
|
35
36
|
fetchMock: {
|
|
@@ -85,6 +86,7 @@ const Template: StoryObj<MutationComparisonProps> = {
|
|
|
85
86
|
width={args.width}
|
|
86
87
|
height={args.height}
|
|
87
88
|
headline={args.headline}
|
|
89
|
+
pageSize={args.pageSize}
|
|
88
90
|
/>
|
|
89
91
|
</ReferenceGenomeContext.Provider>
|
|
90
92
|
</LapisUrlContext.Provider>
|
|
@@ -114,6 +116,7 @@ export const TwoVariants: StoryObj<MutationComparisonProps> = {
|
|
|
114
116
|
width: '100%',
|
|
115
117
|
height: '700px',
|
|
116
118
|
headline: 'Mutation comparison',
|
|
119
|
+
pageSize: 10,
|
|
117
120
|
},
|
|
118
121
|
};
|
|
119
122
|
|
|
@@ -34,6 +34,7 @@ export interface MutationComparisonInnerProps {
|
|
|
34
34
|
variants: NamedLapisFilter[];
|
|
35
35
|
sequenceType: SequenceType;
|
|
36
36
|
views: View[];
|
|
37
|
+
pageSize: boolean | number;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
|
|
@@ -43,6 +44,7 @@ export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
|
|
|
43
44
|
width,
|
|
44
45
|
height,
|
|
45
46
|
headline = 'Mutation comparison',
|
|
47
|
+
pageSize,
|
|
46
48
|
}) => {
|
|
47
49
|
const size = { height, width };
|
|
48
50
|
|
|
@@ -50,7 +52,12 @@ export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
|
|
|
50
52
|
<ErrorBoundary size={size} headline={headline}>
|
|
51
53
|
<ResizeContainer size={size}>
|
|
52
54
|
<Headline heading={headline}>
|
|
53
|
-
<MutationComparisonInner
|
|
55
|
+
<MutationComparisonInner
|
|
56
|
+
variants={variants}
|
|
57
|
+
sequenceType={sequenceType}
|
|
58
|
+
views={views}
|
|
59
|
+
pageSize={pageSize}
|
|
60
|
+
/>
|
|
54
61
|
</Headline>
|
|
55
62
|
</ResizeContainer>
|
|
56
63
|
</ErrorBoundary>
|
|
@@ -61,6 +68,7 @@ export const MutationComparisonInner: FunctionComponent<MutationComparisonInnerP
|
|
|
61
68
|
variants,
|
|
62
69
|
sequenceType,
|
|
63
70
|
views,
|
|
71
|
+
pageSize,
|
|
64
72
|
}) => {
|
|
65
73
|
const lapis = useContext(LapisUrlContext);
|
|
66
74
|
|
|
@@ -80,16 +88,29 @@ export const MutationComparisonInner: FunctionComponent<MutationComparisonInnerP
|
|
|
80
88
|
return <NoDataDisplay />;
|
|
81
89
|
}
|
|
82
90
|
|
|
83
|
-
return
|
|
91
|
+
return (
|
|
92
|
+
<MutationComparisonTabs
|
|
93
|
+
data={data.mutationData}
|
|
94
|
+
sequenceType={sequenceType}
|
|
95
|
+
views={views}
|
|
96
|
+
pageSize={pageSize}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
84
99
|
};
|
|
85
100
|
|
|
86
101
|
type MutationComparisonTabsProps = {
|
|
87
102
|
data: MutationData[];
|
|
88
103
|
views: View[];
|
|
89
104
|
sequenceType: SequenceType;
|
|
105
|
+
pageSize: boolean | number;
|
|
90
106
|
};
|
|
91
107
|
|
|
92
|
-
const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = ({
|
|
108
|
+
const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = ({
|
|
109
|
+
data,
|
|
110
|
+
views,
|
|
111
|
+
sequenceType,
|
|
112
|
+
pageSize,
|
|
113
|
+
}) => {
|
|
93
114
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.5, max: 1 });
|
|
94
115
|
const [displayedMutationTypes, setDisplayedMutationTypes] = useState<DisplayedMutationType[]>([
|
|
95
116
|
{ label: 'Substitutions', checked: true, type: 'substitution' },
|
|
@@ -111,6 +132,7 @@ const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = (
|
|
|
111
132
|
<MutationComparisonTable
|
|
112
133
|
data={{ content: filteredData }}
|
|
113
134
|
proportionInterval={proportionInterval}
|
|
135
|
+
pageSize={pageSize}
|
|
114
136
|
/>
|
|
115
137
|
),
|
|
116
138
|
};
|
|
@@ -13,6 +13,7 @@ interface MutationsGridProps {
|
|
|
13
13
|
data: SubstitutionOrDeletionEntry[];
|
|
14
14
|
sequenceType: SequenceType;
|
|
15
15
|
proportionInterval: ProportionInterval;
|
|
16
|
+
pageSize: boolean | number;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export type BaseCell = {
|
|
@@ -20,7 +21,12 @@ export type BaseCell = {
|
|
|
20
21
|
isReference: boolean;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
export const MutationsGrid: FunctionComponent<MutationsGridProps> = ({
|
|
24
|
+
export const MutationsGrid: FunctionComponent<MutationsGridProps> = ({
|
|
25
|
+
data,
|
|
26
|
+
sequenceType,
|
|
27
|
+
proportionInterval,
|
|
28
|
+
pageSize,
|
|
29
|
+
}) => {
|
|
24
30
|
const getHeaders = () => {
|
|
25
31
|
return [
|
|
26
32
|
{
|
|
@@ -80,5 +86,5 @@ export const MutationsGrid: FunctionComponent<MutationsGridProps> = ({ data, seq
|
|
|
80
86
|
|
|
81
87
|
const tableData = getMutationsGridData(data, sequenceType, proportionInterval).map((row) => Object.values(row));
|
|
82
88
|
|
|
83
|
-
return <Table data={tableData} columns={getHeaders()}
|
|
89
|
+
return <Table data={tableData} columns={getHeaders()} pageSize={pageSize} />;
|
|
84
90
|
};
|
|
@@ -8,9 +8,10 @@ import { sortInsertions } from '../shared/sort/sortInsertions';
|
|
|
8
8
|
|
|
9
9
|
export interface InsertionsTableProps {
|
|
10
10
|
data: InsertionEntry[];
|
|
11
|
+
pageSize: boolean | number;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export const InsertionsTable: FunctionComponent<InsertionsTableProps> = ({ data }) => {
|
|
14
|
+
export const InsertionsTable: FunctionComponent<InsertionsTableProps> = ({ data, pageSize }) => {
|
|
14
15
|
const getHeaders = () => {
|
|
15
16
|
return [
|
|
16
17
|
{
|
|
@@ -31,5 +32,5 @@ export const InsertionsTable: FunctionComponent<InsertionsTableProps> = ({ data
|
|
|
31
32
|
|
|
32
33
|
const tableData = getInsertionsTableData(data).map((row) => Object.values(row));
|
|
33
34
|
|
|
34
|
-
return <Table data={tableData} columns={getHeaders()}
|
|
35
|
+
return <Table data={tableData} columns={getHeaders()} pageSize={pageSize} />;
|
|
35
36
|
};
|
|
@@ -11,9 +11,10 @@ import { formatProportion } from '../shared/table/formatProportion';
|
|
|
11
11
|
export interface MutationsTableProps {
|
|
12
12
|
data: SubstitutionOrDeletionEntry[];
|
|
13
13
|
proportionInterval: ProportionInterval;
|
|
14
|
+
pageSize: boolean | number;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
const MutationsTable: FunctionComponent<MutationsTableProps> = ({ data, proportionInterval }) => {
|
|
17
|
+
const MutationsTable: FunctionComponent<MutationsTableProps> = ({ data, proportionInterval, pageSize }) => {
|
|
17
18
|
const getHeaders = () => {
|
|
18
19
|
return [
|
|
19
20
|
{
|
|
@@ -43,7 +44,7 @@ const MutationsTable: FunctionComponent<MutationsTableProps> = ({ data, proporti
|
|
|
43
44
|
|
|
44
45
|
const tableData = getMutationsTableData(data, proportionInterval).map((row) => Object.values(row));
|
|
45
46
|
|
|
46
|
-
return <Table data={tableData} columns={getHeaders()}
|
|
47
|
+
return <Table data={tableData} columns={getHeaders()} pageSize={pageSize} />;
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
export default MutationsTable;
|
|
@@ -25,6 +25,7 @@ const meta: Meta<MutationsProps> = {
|
|
|
25
25
|
width: { control: 'text' },
|
|
26
26
|
height: { control: 'text' },
|
|
27
27
|
headline: { control: 'text' },
|
|
28
|
+
pageSize: { control: 'object' },
|
|
28
29
|
},
|
|
29
30
|
};
|
|
30
31
|
|
|
@@ -41,6 +42,7 @@ const Template = {
|
|
|
41
42
|
width={args.width}
|
|
42
43
|
height={args.height}
|
|
43
44
|
headline={args.headline}
|
|
45
|
+
pageSize={args.pageSize}
|
|
44
46
|
/>
|
|
45
47
|
</ReferenceGenomeContext.Provider>
|
|
46
48
|
</LapisUrlContext.Provider>
|
|
@@ -56,6 +58,7 @@ export const Default: StoryObj<MutationsProps> = {
|
|
|
56
58
|
width: '100%',
|
|
57
59
|
height: '700px',
|
|
58
60
|
headline: 'Mutations',
|
|
61
|
+
pageSize: 10,
|
|
59
62
|
},
|
|
60
63
|
parameters: {
|
|
61
64
|
fetchMock: {
|
|
@@ -35,6 +35,7 @@ export interface MutationsInnerProps {
|
|
|
35
35
|
variant: LapisFilter;
|
|
36
36
|
sequenceType: SequenceType;
|
|
37
37
|
views: View[];
|
|
38
|
+
pageSize: boolean | number;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export interface MutationsProps extends MutationsInnerProps {
|
|
@@ -50,6 +51,7 @@ export const Mutations: FunctionComponent<MutationsProps> = ({
|
|
|
50
51
|
width,
|
|
51
52
|
height,
|
|
52
53
|
headline = 'Mutations',
|
|
54
|
+
pageSize,
|
|
53
55
|
}) => {
|
|
54
56
|
const size = { height, width };
|
|
55
57
|
|
|
@@ -57,14 +59,14 @@ export const Mutations: FunctionComponent<MutationsProps> = ({
|
|
|
57
59
|
<ErrorBoundary size={size} headline={headline}>
|
|
58
60
|
<ResizeContainer size={size}>
|
|
59
61
|
<Headline heading={headline}>
|
|
60
|
-
<MutationsInner variant={variant} sequenceType={sequenceType} views={views} />
|
|
62
|
+
<MutationsInner variant={variant} sequenceType={sequenceType} views={views} pageSize={pageSize} />
|
|
61
63
|
</Headline>
|
|
62
64
|
</ResizeContainer>
|
|
63
65
|
</ErrorBoundary>
|
|
64
66
|
);
|
|
65
67
|
};
|
|
66
68
|
|
|
67
|
-
export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant, sequenceType, views }) => {
|
|
69
|
+
export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant, sequenceType, views, pageSize }) => {
|
|
68
70
|
const lapis = useContext(LapisUrlContext);
|
|
69
71
|
const { data, error, isLoading } = useQuery(async () => {
|
|
70
72
|
return queryMutationsData(variant, sequenceType, lapis);
|
|
@@ -82,16 +84,17 @@ export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant
|
|
|
82
84
|
return <NoDataDisplay />;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
return <MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} />;
|
|
87
|
+
return <MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} pageSize={pageSize} />;
|
|
86
88
|
};
|
|
87
89
|
|
|
88
90
|
type MutationTabsProps = {
|
|
89
91
|
mutationsData: { insertions: InsertionEntry[]; substitutionsOrDeletions: SubstitutionOrDeletionEntry[] };
|
|
90
92
|
sequenceType: SequenceType;
|
|
91
93
|
views: View[];
|
|
94
|
+
pageSize: boolean | number;
|
|
92
95
|
};
|
|
93
96
|
|
|
94
|
-
const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, sequenceType, views }) => {
|
|
97
|
+
const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, sequenceType, views, pageSize }) => {
|
|
95
98
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 1 });
|
|
96
99
|
|
|
97
100
|
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
|
|
@@ -107,7 +110,13 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
|
|
|
107
110
|
case 'table':
|
|
108
111
|
return {
|
|
109
112
|
title: 'Table',
|
|
110
|
-
content:
|
|
113
|
+
content: (
|
|
114
|
+
<MutationsTable
|
|
115
|
+
data={filteredData.tableData}
|
|
116
|
+
proportionInterval={proportionInterval}
|
|
117
|
+
pageSize={pageSize}
|
|
118
|
+
/>
|
|
119
|
+
),
|
|
111
120
|
};
|
|
112
121
|
case 'grid':
|
|
113
122
|
return {
|
|
@@ -117,13 +126,14 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
|
|
|
117
126
|
data={filteredData.gridData}
|
|
118
127
|
sequenceType={sequenceType}
|
|
119
128
|
proportionInterval={proportionInterval}
|
|
129
|
+
pageSize={pageSize}
|
|
120
130
|
/>
|
|
121
131
|
),
|
|
122
132
|
};
|
|
123
133
|
case 'insertions':
|
|
124
134
|
return {
|
|
125
135
|
title: 'Insertions',
|
|
126
|
-
content: <InsertionsTable data={filteredData.insertions} />,
|
|
136
|
+
content: <InsertionsTable data={filteredData.insertions} pageSize={pageSize} />,
|
|
127
137
|
};
|
|
128
138
|
}
|
|
129
139
|
};
|
|
@@ -7,9 +7,10 @@ import { formatProportion } from '../shared/table/formatProportion';
|
|
|
7
7
|
interface PrevalenceOverTimeTableProps {
|
|
8
8
|
data: PrevalenceOverTimeData;
|
|
9
9
|
granularity: TemporalGranularity;
|
|
10
|
+
pageSize: boolean | number;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const PrevalenceOverTimeTable = ({ data, granularity }: PrevalenceOverTimeTableProps) => {
|
|
13
|
+
const PrevalenceOverTimeTable = ({ data, granularity, pageSize }: PrevalenceOverTimeTableProps) => {
|
|
13
14
|
const getSplitColumns = (data: PrevalenceOverTimeData) => {
|
|
14
15
|
return data.map((dataset) => ({
|
|
15
16
|
name: dataset.displayName,
|
|
@@ -40,7 +41,7 @@ const PrevalenceOverTimeTable = ({ data, granularity }: PrevalenceOverTimeTableP
|
|
|
40
41
|
return Object.values(dataByHeader).map((row) => Object.values(row));
|
|
41
42
|
};
|
|
42
43
|
|
|
43
|
-
return <Table data={getData(data, granularity)} columns={getColumns(data)}
|
|
44
|
+
return <Table data={getData(data, granularity)} columns={getColumns(data)} pageSize={pageSize} />;
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
export default PrevalenceOverTimeTable;
|