@genspectrum/dashboard-components 0.4.4 → 0.5.0

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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/custom-elements.json +279 -108
  3. package/dist/dashboard-components.js +495 -283
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +115 -55
  6. package/dist/style.css +34 -7
  7. package/package.json +5 -5
  8. package/src/preact/aggregatedData/aggregate-table.tsx +3 -2
  9. package/src/preact/aggregatedData/aggregate.stories.tsx +2 -0
  10. package/src/preact/aggregatedData/aggregate.tsx +8 -3
  11. package/src/preact/components/table.stories.tsx +51 -1
  12. package/src/preact/components/table.tsx +4 -3
  13. package/src/preact/locationFilter/location-filter.stories.tsx +12 -1
  14. package/src/preact/locationFilter/location-filter.tsx +10 -3
  15. package/src/preact/mutationComparison/mutation-comparison-table.tsx +7 -2
  16. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +1 -1
  17. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +21 -18
  18. package/src/preact/mutationComparison/mutation-comparison.tsx +30 -8
  19. package/src/preact/mutationComparison/queryMutationData.ts +4 -4
  20. package/src/preact/mutations/mutations-grid.tsx +8 -2
  21. package/src/preact/mutations/mutations-insertions-table.tsx +3 -2
  22. package/src/preact/mutations/mutations-table.tsx +3 -2
  23. package/src/preact/mutations/mutations.stories.tsx +6 -3
  24. package/src/preact/mutations/mutations.tsx +30 -10
  25. package/src/preact/mutations/queryMutations.ts +3 -3
  26. package/src/preact/prevalenceOverTime/__mockData__/{denominatorOneVariant.json → denominatorFilterOneDataset.json} +1 -1
  27. package/src/preact/prevalenceOverTime/__mockData__/{numeratorOneVariant.json → numeratorFilterOneDataset.json} +1 -1
  28. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +42 -5
  29. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +26 -7
  30. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +62 -28
  31. package/src/preact/prevalenceOverTime/prevalence-over-time-table.tsx +3 -2
  32. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +30 -16
  33. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +46 -12
  34. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +39 -7
  35. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +10 -4
  36. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +19 -10
  37. package/src/preact/shared/charts/confideceInterval.ts +7 -2
  38. package/src/preact/shared/charts/getYAxisMax.ts +24 -0
  39. package/src/preact/shared/charts/getYAxisScale.ts +1 -3
  40. package/src/query/queryAggregateData.ts +2 -2
  41. package/src/query/queryInsertions.ts +7 -2
  42. package/src/query/querySubstitutionsOrDeletions.ts +2 -2
  43. package/src/web-components/input/gs-date-range-selector.tsx +1 -1
  44. package/src/web-components/input/gs-location-filter.stories.ts +11 -0
  45. package/src/web-components/input/gs-location-filter.tsx +15 -2
  46. package/src/web-components/input/gs-mutation-filter.tsx +1 -1
  47. package/src/web-components/input/gs-text-input.tsx +1 -1
  48. package/src/web-components/visualization/gs-aggregate.stories.ts +4 -0
  49. package/src/web-components/visualization/gs-aggregate.tsx +10 -2
  50. package/src/web-components/visualization/gs-mutation-comparison.stories.ts +16 -12
  51. package/src/web-components/visualization/gs-mutation-comparison.tsx +26 -19
  52. package/src/web-components/visualization/gs-mutations.stories.ts +8 -4
  53. package/src/web-components/visualization/gs-mutations.tsx +18 -11
  54. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +51 -35
  55. package/src/web-components/visualization/gs-prevalence-over-time.tsx +66 -24
  56. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +32 -18
  57. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +51 -13
  58. /package/src/preact/mutationComparison/__mockData__/{nucleotideMutationsOtherVariant.json → nucleotideMutationsOtherDataset.json} +0 -0
  59. /package/src/preact/mutationComparison/__mockData__/{nucleotideMutationsSomeVariant.json → nucleotideMutationsSomeDataset.json} +0 -0
  60. /package/src/preact/prevalenceOverTime/__mockData__/{denominator.json → denominatorFilter.json} +0 -0
  61. /package/src/preact/prevalenceOverTime/__mockData__/{numeratorEG.json → numeratorFilterEG.json} +0 -0
  62. /package/src/preact/prevalenceOverTime/__mockData__/{numeratorJN1.json → numeratorFilterJN1.json} +0 -0
  63. /package/src/preact/relativeGrowthAdvantage/__mockData__/{denominator.json → denominatorFilter.json} +0 -0
  64. /package/src/preact/relativeGrowthAdvantage/__mockData__/{numerator.json → numeratorFilter.json} +0 -0
@@ -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} pagination={false} />;
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
- pagination: PaginationConfig | boolean;
28
+ pageSize: number | boolean;
30
29
  }
31
30
 
32
- export const Table = ({ data, columns, pagination }: TableProps) => {
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 fields={args.fields} initialValue={args.initialValue} width={args.width} />
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> = ({ width, initialValue, fields }) => {
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> = ({ data, proportionInterval }) => {
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} pagination={true} />;
45
+ return <Table data={tableData} columns={headers} pageSize={pageSize} />;
41
46
  };
@@ -111,7 +111,7 @@ export const MutationComparisonVenn: FunctionComponent<MutationComparisonVennPro
111
111
  );
112
112
 
113
113
  if (data.content.length > 5) {
114
- return <div>Too many variants to display. Maximum are five. </div>;
114
+ return <div>Too many datasets to display. Maximum are five. </div>;
115
115
  }
116
116
 
117
117
  return (
@@ -1,24 +1,24 @@
1
1
  import { type Meta, type StoryObj } from '@storybook/preact';
2
2
  import { expect, userEvent, waitFor, within } from '@storybook/test';
3
3
 
4
- import nucleotideMutationsOtherVariant from './__mockData__/nucleotideMutationsOtherVariant.json';
5
- import nucleotideMutationsSomeVariant from './__mockData__/nucleotideMutationsSomeVariant.json';
4
+ import nucleotideMutationsOtherDataset from './__mockData__/nucleotideMutationsOtherDataset.json';
5
+ import nucleotideMutationsSomeDataset from './__mockData__/nucleotideMutationsSomeDataset.json';
6
6
  import { MutationComparison, type MutationComparisonProps } from './mutation-comparison';
7
7
  import { LAPIS_URL, NUCLEOTIDE_MUTATIONS_ENDPOINT } from '../../constants';
8
8
  import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
9
9
  import { LapisUrlContext } from '../LapisUrlContext';
10
10
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
11
11
 
12
- const dateToSomeVariant = '2022-01-01';
12
+ const dateToSomeDataset = '2022-01-01';
13
13
 
14
- const dateFromOtherVariant = '2021-01-01';
15
- const dateToOtherVariant = '2022-01-02';
14
+ const dateFromOtherDataset = '2021-01-01';
15
+ const dateToOtherDataset = '2022-01-02';
16
16
 
17
17
  const meta: Meta<MutationComparisonProps> = {
18
18
  title: 'Visualization/Mutation comparison',
19
19
  component: MutationComparison,
20
20
  argTypes: {
21
- variants: [{ control: 'object' }],
21
+ lapisFilters: [{ control: 'object' }],
22
22
  sequenceType: {
23
23
  options: ['nucleotide', 'amino acid'],
24
24
  control: { type: 'radio' },
@@ -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: {
@@ -41,13 +42,13 @@ const meta: Meta<MutationComparisonProps> = {
41
42
  body: {
42
43
  country: 'Switzerland',
43
44
  pangoLineage: 'B.1.1.7',
44
- dateTo: dateToSomeVariant,
45
+ dateTo: dateToSomeDataset,
45
46
  minProportion: 0,
46
47
  },
47
48
  },
48
49
  response: {
49
50
  status: 200,
50
- body: nucleotideMutationsSomeVariant,
51
+ body: nucleotideMutationsSomeDataset,
51
52
  },
52
53
  },
53
54
  {
@@ -57,14 +58,14 @@ const meta: Meta<MutationComparisonProps> = {
57
58
  body: {
58
59
  country: 'Switzerland',
59
60
  pangoLineage: 'B.1.1.7',
60
- dateFrom: dateFromOtherVariant,
61
- dateTo: dateToOtherVariant,
61
+ dateFrom: dateFromOtherDataset,
62
+ dateTo: dateToOtherDataset,
62
63
  minProportion: 0,
63
64
  },
64
65
  },
65
66
  response: {
66
67
  status: 200,
67
- body: nucleotideMutationsOtherVariant,
68
+ body: nucleotideMutationsOtherDataset,
68
69
  },
69
70
  },
70
71
  ],
@@ -79,12 +80,13 @@ const Template: StoryObj<MutationComparisonProps> = {
79
80
  <LapisUrlContext.Provider value={LAPIS_URL}>
80
81
  <ReferenceGenomeContext.Provider value={referenceGenome}>
81
82
  <MutationComparison
82
- variants={args.variants}
83
+ lapisFilters={args.lapisFilters}
83
84
  sequenceType={args.sequenceType}
84
85
  views={args.views}
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>
@@ -94,18 +96,18 @@ const Template: StoryObj<MutationComparisonProps> = {
94
96
  export const TwoVariants: StoryObj<MutationComparisonProps> = {
95
97
  ...Template,
96
98
  args: {
97
- variants: [
99
+ lapisFilters: [
98
100
  {
99
- displayName: 'Some variant',
100
- lapisFilter: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: dateToSomeVariant },
101
+ displayName: 'Some dataset',
102
+ lapisFilter: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: dateToSomeDataset },
101
103
  },
102
104
  {
103
- displayName: 'Other variant',
105
+ displayName: 'Other dataset',
104
106
  lapisFilter: {
105
107
  country: 'Switzerland',
106
108
  pangoLineage: 'B.1.1.7',
107
- dateFrom: dateFromOtherVariant,
108
- dateTo: dateToOtherVariant,
109
+ dateFrom: dateFromOtherDataset,
110
+ dateTo: dateToOtherDataset,
109
111
  },
110
112
  },
111
113
  ],
@@ -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
 
@@ -31,18 +31,20 @@ export interface MutationComparisonProps extends MutationComparisonInnerProps {
31
31
  }
32
32
 
33
33
  export interface MutationComparisonInnerProps {
34
- variants: NamedLapisFilter[];
34
+ lapisFilters: NamedLapisFilter[];
35
35
  sequenceType: SequenceType;
36
36
  views: View[];
37
+ pageSize: boolean | number;
37
38
  }
38
39
 
39
40
  export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
40
- variants,
41
+ lapisFilters,
41
42
  sequenceType,
42
43
  views,
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 variants={variants} sequenceType={sequenceType} views={views} />
55
+ <MutationComparisonInner
56
+ lapisFilters={lapisFilters}
57
+ sequenceType={sequenceType}
58
+ views={views}
59
+ pageSize={pageSize}
60
+ />
54
61
  </Headline>
55
62
  </ResizeContainer>
56
63
  </ErrorBoundary>
@@ -58,15 +65,16 @@ export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
58
65
  };
59
66
 
60
67
  export const MutationComparisonInner: FunctionComponent<MutationComparisonInnerProps> = ({
61
- variants,
68
+ lapisFilters,
62
69
  sequenceType,
63
70
  views,
71
+ pageSize,
64
72
  }) => {
65
73
  const lapis = useContext(LapisUrlContext);
66
74
 
67
75
  const { data, error, isLoading } = useQuery(async () => {
68
- return queryMutationData(variants, sequenceType, lapis);
69
- }, [variants, sequenceType, lapis]);
76
+ return queryMutationData(lapisFilters, sequenceType, lapis);
77
+ }, [lapisFilters, sequenceType, lapis]);
70
78
 
71
79
  if (isLoading) {
72
80
  return <LoadingDisplay />;
@@ -80,16 +88,29 @@ export const MutationComparisonInner: FunctionComponent<MutationComparisonInnerP
80
88
  return <NoDataDisplay />;
81
89
  }
82
90
 
83
- return <MutationComparisonTabs data={data.mutationData} sequenceType={sequenceType} views={views} />;
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> = ({ data, views, sequenceType }) => {
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
  };
@@ -9,15 +9,15 @@ export type MutationData = {
9
9
  };
10
10
 
11
11
  export async function queryMutationData(
12
- variants: NamedLapisFilter[],
12
+ lapisFilters: NamedLapisFilter[],
13
13
  sequenceType: 'nucleotide' | 'amino acid',
14
14
  lapis: string,
15
15
  ) {
16
16
  const mutationData = await Promise.all(
17
- variants.map(async (variant) => {
17
+ lapisFilters.map(async (filter) => {
18
18
  return {
19
- displayName: variant.displayName,
20
- data: (await querySubstitutionsOrDeletions(variant.lapisFilter, sequenceType, lapis)).content,
19
+ displayName: filter.displayName,
20
+ data: (await querySubstitutionsOrDeletions(filter.lapisFilter, sequenceType, lapis)).content,
21
21
  };
22
22
  }),
23
23
  );
@@ -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> = ({ data, sequenceType, proportionInterval }) => {
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()} pagination={true} />;
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()} pagination={true} />;
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()} pagination={true} />;
47
+ return <Table data={tableData} columns={getHeaders()} pageSize={pageSize} />;
47
48
  };
48
49
 
49
50
  export default MutationsTable;
@@ -13,7 +13,7 @@ const meta: Meta<MutationsProps> = {
13
13
  title: 'Visualization/Mutations',
14
14
  component: Mutations,
15
15
  argTypes: {
16
- variant: { control: 'object' },
16
+ lapisFilter: { control: 'object' },
17
17
  sequenceType: {
18
18
  options: ['nucleotide', 'amino acid'],
19
19
  control: { type: 'radio' },
@@ -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
 
@@ -35,12 +36,13 @@ const Template = {
35
36
  <LapisUrlContext.Provider value={LAPIS_URL}>
36
37
  <ReferenceGenomeContext.Provider value={referenceGenome}>
37
38
  <Mutations
38
- variant={args.variant}
39
+ lapisFilter={args.lapisFilter}
39
40
  sequenceType={args.sequenceType}
40
41
  views={args.views}
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>
@@ -50,12 +52,13 @@ const Template = {
50
52
  export const Default: StoryObj<MutationsProps> = {
51
53
  ...Template,
52
54
  args: {
53
- variant: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
55
+ lapisFilter: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
54
56
  sequenceType: 'nucleotide',
55
57
  views: ['grid', 'table', 'insertions'],
56
58
  width: '100%',
57
59
  height: '700px',
58
60
  headline: 'Mutations',
61
+ pageSize: 10,
59
62
  },
60
63
  parameters: {
61
64
  fetchMock: {
@@ -32,9 +32,10 @@ import { useQuery } from '../useQuery';
32
32
  export type View = 'table' | 'grid' | 'insertions';
33
33
 
34
34
  export interface MutationsInnerProps {
35
- variant: LapisFilter;
35
+ lapisFilter: LapisFilter;
36
36
  sequenceType: SequenceType;
37
37
  views: View[];
38
+ pageSize: boolean | number;
38
39
  }
39
40
 
40
41
  export interface MutationsProps extends MutationsInnerProps {
@@ -44,12 +45,13 @@ export interface MutationsProps extends MutationsInnerProps {
44
45
  }
45
46
 
46
47
  export const Mutations: FunctionComponent<MutationsProps> = ({
47
- variant,
48
+ lapisFilter,
48
49
  sequenceType,
49
50
  views,
50
51
  width,
51
52
  height,
52
53
  headline = 'Mutations',
54
+ pageSize,
53
55
  }) => {
54
56
  const size = { height, width };
55
57
 
@@ -57,18 +59,28 @@ 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
63
+ lapisFilter={lapisFilter}
64
+ sequenceType={sequenceType}
65
+ views={views}
66
+ pageSize={pageSize}
67
+ />
61
68
  </Headline>
62
69
  </ResizeContainer>
63
70
  </ErrorBoundary>
64
71
  );
65
72
  };
66
73
 
67
- export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant, sequenceType, views }) => {
74
+ export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({
75
+ lapisFilter,
76
+ sequenceType,
77
+ views,
78
+ pageSize,
79
+ }) => {
68
80
  const lapis = useContext(LapisUrlContext);
69
81
  const { data, error, isLoading } = useQuery(async () => {
70
- return queryMutationsData(variant, sequenceType, lapis);
71
- }, [variant, sequenceType, lapis]);
82
+ return queryMutationsData(lapisFilter, sequenceType, lapis);
83
+ }, [lapisFilter, sequenceType, lapis]);
72
84
 
73
85
  if (isLoading) {
74
86
  return <LoadingDisplay />;
@@ -82,16 +94,17 @@ export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant
82
94
  return <NoDataDisplay />;
83
95
  }
84
96
 
85
- return <MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} />;
97
+ return <MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} pageSize={pageSize} />;
86
98
  };
87
99
 
88
100
  type MutationTabsProps = {
89
101
  mutationsData: { insertions: InsertionEntry[]; substitutionsOrDeletions: SubstitutionOrDeletionEntry[] };
90
102
  sequenceType: SequenceType;
91
103
  views: View[];
104
+ pageSize: boolean | number;
92
105
  };
93
106
 
94
- const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, sequenceType, views }) => {
107
+ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, sequenceType, views, pageSize }) => {
95
108
  const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 1 });
96
109
 
97
110
  const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
@@ -107,7 +120,13 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
107
120
  case 'table':
108
121
  return {
109
122
  title: 'Table',
110
- content: <MutationsTable data={filteredData.tableData} proportionInterval={proportionInterval} />,
123
+ content: (
124
+ <MutationsTable
125
+ data={filteredData.tableData}
126
+ proportionInterval={proportionInterval}
127
+ pageSize={pageSize}
128
+ />
129
+ ),
111
130
  };
112
131
  case 'grid':
113
132
  return {
@@ -117,13 +136,14 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
117
136
  data={filteredData.gridData}
118
137
  sequenceType={sequenceType}
119
138
  proportionInterval={proportionInterval}
139
+ pageSize={pageSize}
120
140
  />
121
141
  ),
122
142
  };
123
143
  case 'insertions':
124
144
  return {
125
145
  title: 'Insertions',
126
- content: <InsertionsTable data={filteredData.insertions} />,
146
+ content: <InsertionsTable data={filteredData.insertions} pageSize={pageSize} />,
127
147
  };
128
148
  }
129
149
  };