@genspectrum/dashboard-components 0.6.19 → 0.7.1

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 (31) hide show
  1. package/custom-elements.json +18 -18
  2. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  3. package/dist/dashboard-components.js +296 -302
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +98 -48
  6. package/package.json +1 -3
  7. package/src/index.ts +1 -0
  8. package/src/preact/aggregatedData/aggregate.tsx +41 -33
  9. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  10. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  11. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  12. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  13. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  14. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  15. package/src/preact/mutationComparison/mutation-comparison.tsx +32 -34
  16. package/src/preact/mutations/mutations.tsx +63 -56
  17. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  18. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
  19. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
  20. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  21. package/src/preact/mutationsOverTime/mutations-over-time.tsx +40 -43
  22. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +46 -64
  23. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +29 -36
  24. package/src/query/queryMutationsOverTime.ts +3 -5
  25. package/src/utils/map2d.spec.ts +52 -13
  26. package/src/utils/map2d.ts +3 -4
  27. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  28. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  29. package/standalone-bundle/dashboard-components.js +14322 -15115
  30. package/standalone-bundle/dashboard-components.js.map +1 -1
  31. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +0 -1
@@ -15,7 +15,7 @@ import { CsvDownloadButton } from '../components/csv-download-button';
15
15
  import { ErrorBoundary } from '../components/error-boundary';
16
16
  import { ErrorDisplay } from '../components/error-display';
17
17
  import { Fullscreen } from '../components/fullscreen';
18
- import Info, { InfoHeadline1, InfoParagraph } from '../components/info';
18
+ import Info, { InfoComponentCode, InfoHeadline1, InfoParagraph } from '../components/info';
19
19
  import { LoadingDisplay } from '../components/loading-display';
20
20
  import { NoDataDisplay } from '../components/no-data-display';
21
21
  import { ResizeContainer } from '../components/resize-container';
@@ -26,12 +26,9 @@ import { useQuery } from '../useQuery';
26
26
 
27
27
  type NumberSequencesOverTimeView = 'bar' | 'line' | 'table';
28
28
 
29
- export interface NumberSequencesOverTimeProps extends NumberSequencesOverTimeInnerProps {
29
+ export interface NumberSequencesOverTimeProps {
30
30
  width: string;
31
31
  height: string;
32
- }
33
-
34
- interface NumberSequencesOverTimeInnerProps {
35
32
  lapisFilter: NamedLapisFilter | NamedLapisFilter[];
36
33
  lapisDateField: string;
37
34
  views: NumberSequencesOverTimeView[];
@@ -40,26 +37,21 @@ interface NumberSequencesOverTimeInnerProps {
40
37
  pageSize: boolean | number;
41
38
  }
42
39
 
43
- export const NumberSequencesOverTime = ({ width, height, ...innerProps }: NumberSequencesOverTimeProps) => {
40
+ export const NumberSequencesOverTime = (componentProps: NumberSequencesOverTimeProps) => {
41
+ const { width, height } = componentProps;
44
42
  const size = { height, width };
45
43
 
46
44
  return (
47
45
  <ErrorBoundary size={size}>
48
46
  <ResizeContainer size={size}>
49
- <NumberSequencesOverTimeInner {...innerProps} />
47
+ <NumberSequencesOverTimeInner {...componentProps} />
50
48
  </ResizeContainer>
51
49
  </ErrorBoundary>
52
50
  );
53
51
  };
54
52
 
55
- const NumberSequencesOverTimeInner = ({
56
- lapisFilter,
57
- granularity,
58
- smoothingWindow,
59
- lapisDateField,
60
- views,
61
- pageSize,
62
- }: NumberSequencesOverTimeInnerProps) => {
53
+ const NumberSequencesOverTimeInner = (componentProps: NumberSequencesOverTimeProps) => {
54
+ const { lapisFilter, lapisDateField, granularity, smoothingWindow } = componentProps;
63
55
  const lapis = useContext(LapisUrlContext);
64
56
 
65
57
  const { data, error, isLoading } = useQuery(
@@ -79,32 +71,15 @@ const NumberSequencesOverTimeInner = ({
79
71
  return <NoDataDisplay />;
80
72
  }
81
73
 
82
- return (
83
- <NumberSequencesOverTimeTabs
84
- views={views}
85
- data={data}
86
- granularity={granularity}
87
- smoothingWindow={smoothingWindow}
88
- pageSize={pageSize}
89
- />
90
- );
74
+ return <NumberSequencesOverTimeTabs data={data} originalComponentProps={componentProps} />;
91
75
  };
92
76
 
93
77
  interface NumberSequencesOverTimeTabsProps {
94
- views: NumberSequencesOverTimeView[];
95
78
  data: NumberOfSequencesDatasets;
96
- granularity: TemporalGranularity;
97
- smoothingWindow: number;
98
- pageSize: boolean | number;
79
+ originalComponentProps: NumberSequencesOverTimeProps;
99
80
  }
100
81
 
101
- const NumberSequencesOverTimeTabs = ({
102
- views,
103
- data,
104
- granularity,
105
- smoothingWindow,
106
- pageSize,
107
- }: NumberSequencesOverTimeTabsProps) => {
82
+ const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }: NumberSequencesOverTimeTabsProps) => {
108
83
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
109
84
 
110
85
  const getTab = (view: NumberSequencesOverTimeView) => {
@@ -122,7 +97,13 @@ const NumberSequencesOverTimeTabs = ({
122
97
  case 'table':
123
98
  return {
124
99
  title: 'Table',
125
- content: <NumberSequencesOverTimeTable data={data} granularity={granularity} pageSize={pageSize} />,
100
+ content: (
101
+ <NumberSequencesOverTimeTable
102
+ data={data}
103
+ granularity={originalComponentProps.granularity}
104
+ pageSize={originalComponentProps.pageSize}
105
+ />
106
+ ),
126
107
  };
127
108
  default:
128
109
  throw new Error(`Unknown view: ${view}`);
@@ -131,15 +112,14 @@ const NumberSequencesOverTimeTabs = ({
131
112
 
132
113
  return (
133
114
  <Tabs
134
- tabs={views.map((view) => getTab(view))}
115
+ tabs={originalComponentProps.views.map((view) => getTab(view))}
135
116
  toolbar={(activeTab) => (
136
117
  <Toolbar
137
118
  activeTab={activeTab}
138
119
  data={data}
139
- granularity={granularity}
140
- smoothingWindow={smoothingWindow}
141
120
  yAxisScaleType={yAxisScaleType}
142
121
  setYAxisScaleType={setYAxisScaleType}
122
+ originalComponentProps={originalComponentProps}
143
123
  />
144
124
  )}
145
125
  />
@@ -149,20 +129,12 @@ const NumberSequencesOverTimeTabs = ({
149
129
  interface ToolbarProps {
150
130
  activeTab: string;
151
131
  data: NumberOfSequencesDatasets;
152
- granularity: TemporalGranularity;
153
132
  yAxisScaleType: ScaleType;
154
133
  setYAxisScaleType: (scaleType: ScaleType) => void;
155
- smoothingWindow: number;
134
+ originalComponentProps: NumberSequencesOverTimeProps;
156
135
  }
157
136
 
158
- const Toolbar = ({
159
- activeTab,
160
- data,
161
- granularity,
162
- yAxisScaleType,
163
- setYAxisScaleType,
164
- smoothingWindow,
165
- }: ToolbarProps) => {
137
+ const Toolbar = ({ activeTab, data, yAxisScaleType, setYAxisScaleType, originalComponentProps }: ToolbarProps) => {
166
138
  return (
167
139
  <>
168
140
  {activeTab !== 'Table' && (
@@ -174,29 +146,39 @@ const Toolbar = ({
174
146
  )}
175
147
  <CsvDownloadButton
176
148
  className='mx-1 btn btn-xs'
177
- getData={() => getNumberOfSequencesOverTimeTableData(data, granularity)}
149
+ getData={() => getNumberOfSequencesOverTimeTableData(data, originalComponentProps.granularity)}
178
150
  filename='number_of_sequences_over_time.csv'
179
151
  />
180
- <NumberSequencesOverTimeInfo granularity={granularity} smoothingWindow={smoothingWindow} />
152
+ <NumberSequencesOverTimeInfo originalComponentProps={originalComponentProps} />
181
153
  <Fullscreen />
182
154
  </>
183
155
  );
184
156
  };
185
157
 
186
158
  type NumberSequencesOverTimeInfoProps = {
187
- granularity: TemporalGranularity;
188
- smoothingWindow: number;
159
+ originalComponentProps: NumberSequencesOverTimeProps;
189
160
  };
190
161
 
191
162
  const NumberSequencesOverTimeInfo: FunctionComponent<NumberSequencesOverTimeInfoProps> = ({
192
- granularity,
193
- smoothingWindow,
194
- }) => (
195
- <Info>
196
- <InfoHeadline1>Number of sequences over time</InfoHeadline1>
197
- <InfoParagraph>
198
- This presents the number of available sequences of a variant per <b>{granularity}</b>
199
- {smoothingWindow > 0 && `, smoothed using a ${smoothingWindow}-${granularity} sliding window`}.
200
- </InfoParagraph>
201
- </Info>
202
- );
163
+ originalComponentProps,
164
+ }) => {
165
+ const lapis = useContext(LapisUrlContext);
166
+
167
+ return (
168
+ <Info>
169
+ <InfoHeadline1>Number of sequences over time</InfoHeadline1>
170
+ <InfoParagraph>
171
+ This presents the number of available sequences of a variant per{' '}
172
+ <b>{originalComponentProps.granularity}</b>
173
+ {originalComponentProps.smoothingWindow > 0 &&
174
+ `, smoothed using a ${originalComponentProps.smoothingWindow}-${originalComponentProps.granularity} sliding window`}
175
+ .
176
+ </InfoParagraph>
177
+ <InfoComponentCode
178
+ componentName='number-sequences-over-time'
179
+ params={originalComponentProps}
180
+ lapisUrl={lapis}
181
+ />
182
+ </Info>
183
+ );
184
+ };
@@ -11,7 +11,7 @@ import { LapisUrlContext } from '../LapisUrlContext';
11
11
  import { ErrorBoundary } from '../components/error-boundary';
12
12
  import { ErrorDisplay } from '../components/error-display';
13
13
  import { Fullscreen } from '../components/fullscreen';
14
- import Info, { InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
14
+ import Info, { InfoComponentCode, InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
15
15
  import { LoadingDisplay } from '../components/loading-display';
16
16
  import { NoDataDisplay } from '../components/no-data-display';
17
17
  import { ResizeContainer } from '../components/resize-container';
@@ -23,12 +23,9 @@ import { useQuery } from '../useQuery';
23
23
 
24
24
  export type View = 'line';
25
25
 
26
- export interface RelativeGrowthAdvantageProps extends RelativeGrowthAdvantagePropsInner {
26
+ export interface RelativeGrowthAdvantageProps {
27
27
  width: string;
28
28
  height: string;
29
- }
30
-
31
- export interface RelativeGrowthAdvantagePropsInner {
32
29
  numeratorFilter: LapisFilter;
33
30
  denominatorFilter: LapisFilter;
34
31
  generationTime: number;
@@ -37,36 +34,28 @@ export interface RelativeGrowthAdvantagePropsInner {
37
34
  yAxisMaxConfig: YAxisMaxConfig;
38
35
  }
39
36
 
40
- export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = ({
41
- width,
42
- height,
43
- ...innerProps
44
- }) => {
37
+ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = (componentProps) => {
38
+ const { width, height } = componentProps;
45
39
  const size = { height, width };
46
40
 
47
41
  return (
48
42
  <ErrorBoundary size={size}>
49
43
  <ResizeContainer size={size}>
50
- <RelativeGrowthAdvantageInner {...innerProps} />
44
+ <RelativeGrowthAdvantageInner {...componentProps} />
51
45
  </ResizeContainer>
52
46
  </ErrorBoundary>
53
47
  );
54
48
  };
55
49
 
56
- export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantagePropsInner> = ({
57
- numeratorFilter,
58
- denominatorFilter,
59
- generationTime,
60
- views,
61
- lapisDateField,
62
- yAxisMaxConfig,
63
- }) => {
50
+ export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantageProps> = (componentProps) => {
64
51
  const lapis = useContext(LapisUrlContext);
52
+ const { numeratorFilter, denominatorFilter, generationTime, lapisDateField } = componentProps;
53
+
65
54
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
66
55
 
67
56
  const { data, error, isLoading } = useQuery(
68
57
  () => queryRelativeGrowthAdvantage(numeratorFilter, denominatorFilter, generationTime, lapis, lapisDateField),
69
- [lapis, numeratorFilter, denominatorFilter, generationTime, views, lapisDateField],
58
+ [lapis, numeratorFilter, denominatorFilter, generationTime, lapisDateField],
70
59
  );
71
60
 
72
61
  if (isLoading) {
@@ -86,9 +75,7 @@ export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvan
86
75
  data={data}
87
76
  yAxisScaleType={yAxisScaleType}
88
77
  setYAxisScaleType={setYAxisScaleType}
89
- views={views}
90
- generationTime={generationTime}
91
- yAxisMaxConfig={yAxisMaxConfig}
78
+ originalComponentProps={componentProps}
92
79
  />
93
80
  );
94
81
  };
@@ -97,18 +84,14 @@ type RelativeGrowthAdvantageTabsProps = {
97
84
  data: NonNullable<RelativeGrowthAdvantageData>;
98
85
  yAxisScaleType: ScaleType;
99
86
  setYAxisScaleType: (scaleType: ScaleType) => void;
100
- views: View[];
101
- generationTime: number;
102
- yAxisMaxConfig: YAxisMaxConfig;
87
+ originalComponentProps: RelativeGrowthAdvantageProps;
103
88
  };
104
89
 
105
90
  const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabsProps> = ({
106
91
  data,
107
92
  yAxisScaleType,
108
93
  setYAxisScaleType,
109
- views,
110
- generationTime,
111
- yAxisMaxConfig,
94
+ originalComponentProps,
112
95
  }) => {
113
96
  const getTab = (view: View) => {
114
97
  switch (view) {
@@ -123,17 +106,17 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
123
106
  params: data.params,
124
107
  }}
125
108
  yAxisScaleType={yAxisScaleType}
126
- yAxisMaxConfig={yAxisMaxConfig}
109
+ yAxisMaxConfig={originalComponentProps.yAxisMaxConfig}
127
110
  />
128
111
  ),
129
112
  };
130
113
  }
131
114
  };
132
115
 
133
- const tabs = views.map((view) => getTab(view));
116
+ const tabs = originalComponentProps.views.map((view) => getTab(view));
134
117
  const toolbar = () => (
135
118
  <RelativeGrowthAdvantageToolbar
136
- generationTime={generationTime}
119
+ originalComponentProps={originalComponentProps}
137
120
  yAxisScaleType={yAxisScaleType}
138
121
  setYAxisScaleType={setYAxisScaleType}
139
122
  />
@@ -145,24 +128,29 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
145
128
  type RelativeGrowthAdvantageToolbarProps = {
146
129
  yAxisScaleType: ScaleType;
147
130
  setYAxisScaleType: (scaleType: ScaleType) => void;
148
- generationTime: number;
131
+ originalComponentProps: RelativeGrowthAdvantageProps;
149
132
  };
150
133
 
151
134
  const RelativeGrowthAdvantageToolbar: FunctionComponent<RelativeGrowthAdvantageToolbarProps> = ({
152
135
  yAxisScaleType,
153
136
  setYAxisScaleType,
154
- generationTime,
137
+ originalComponentProps,
155
138
  }) => {
156
139
  return (
157
140
  <>
158
141
  <ScalingSelector yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
159
- <RelativeGrowthAdvantageInfo generationTime={generationTime} />
142
+ <RelativeGrowthAdvantageInfo originalComponentProps={originalComponentProps} />
160
143
  <Fullscreen />
161
144
  </>
162
145
  );
163
146
  };
164
147
 
165
- const RelativeGrowthAdvantageInfo: FunctionComponent<{ generationTime: number }> = ({ generationTime }) => {
148
+ const RelativeGrowthAdvantageInfo: FunctionComponent<{ originalComponentProps: RelativeGrowthAdvantageProps }> = ({
149
+ originalComponentProps,
150
+ }) => {
151
+ const lapis = useContext(LapisUrlContext);
152
+ const generationTime = originalComponentProps.generationTime;
153
+
166
154
  return (
167
155
  <Info>
168
156
  <InfoHeadline1>Relative growth advantage</InfoHeadline1>
@@ -193,6 +181,11 @@ const RelativeGrowthAdvantageInfo: FunctionComponent<{ generationTime: number }>
193
181
  10.1016/j.epidem.2021.100480
194
182
  </InfoLink>
195
183
  </InfoParagraph>
184
+ <InfoComponentCode
185
+ componentName='relative-growth-advantage'
186
+ params={originalComponentProps}
187
+ lapisUrl={lapis}
188
+ />
196
189
  </Info>
197
190
  );
198
191
  };
@@ -6,6 +6,7 @@ import { MapOperator } from '../operator/MapOperator';
6
6
  import { RenameFieldOperator } from '../operator/RenameFieldOperator';
7
7
  import { SortOperator } from '../operator/SortOperator';
8
8
  import { UserFacingError } from '../preact/components/error-display';
9
+ import { BaseMutationOverTimeDataMap } from '../preact/mutationsOverTime/MutationOverTimeData';
9
10
  import { sortSubstitutionsAndDeletions } from '../preact/shared/sort/sortSubstitutionsAndDeletions';
10
11
  import {
11
12
  type DeletionEntry,
@@ -15,7 +16,7 @@ import {
15
16
  type SubstitutionOrDeletionEntry,
16
17
  type TemporalGranularity,
17
18
  } from '../types';
18
- import { type Map2d, Map2dBase } from '../utils/map2d';
19
+ import { type Map2d } from '../utils/map2d';
19
20
  import {
20
21
  type Deletion,
21
22
  type DeletionClass,
@@ -218,10 +219,7 @@ export function groupByMutation(
218
219
  data: MutationOverTimeData[],
219
220
  overallMutationData: (SubstitutionEntry | DeletionEntry)[],
220
221
  ) {
221
- const dataArray = new Map2dBase<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>(
222
- serializeSubstitutionOrDeletion,
223
- serializeTemporal,
224
- );
222
+ const dataArray = new BaseMutationOverTimeDataMap();
225
223
 
226
224
  const allDates = data.map((mutationData) => mutationData.date);
227
225
 
@@ -4,20 +4,29 @@ import { Map2dBase, Map2dView } from './map2d';
4
4
 
5
5
  describe('Map2dBase', () => {
6
6
  it('should add a value and return it', () => {
7
- const map2d = new Map2dBase<string, string, number>();
7
+ const map2d = new Map2dBase<string, string, number>(
8
+ (value) => value,
9
+ (value) => value,
10
+ );
8
11
  map2d.set('a', 'b', 2);
9
12
  expect(map2d.get('a', 'b')).toBe(2);
10
13
  });
11
14
 
12
15
  it('should update a value', () => {
13
- const map2d = new Map2dBase<string, string, number>();
16
+ const map2d = new Map2dBase<string, string, number>(
17
+ (value) => value,
18
+ (value) => value,
19
+ );
14
20
  map2d.set('a', 'b', 2);
15
21
  map2d.set('a', 'b', 3);
16
22
  expect(map2d.get('a', 'b')).toBe(3);
17
23
  });
18
24
 
19
25
  it('should return the data as an array', () => {
20
- const map2d = new Map2dBase<string, string, number>();
26
+ const map2d = new Map2dBase<string, string, number>(
27
+ (value) => value,
28
+ (value) => value,
29
+ );
21
30
  map2d.set('a', 'b', 1);
22
31
  map2d.set('a', 'd', 2);
23
32
  map2d.set('c', 'b', 3);
@@ -30,7 +39,10 @@ describe('Map2dBase', () => {
30
39
  });
31
40
 
32
41
  it('should fill empty values with the given value', () => {
33
- const map2d = new Map2dBase<string, string, number>();
42
+ const map2d = new Map2dBase<string, string, number>(
43
+ (value) => value,
44
+ (value) => value,
45
+ );
34
46
  map2d.set('a', 'b', 2);
35
47
  map2d.set('c', 'd', 4);
36
48
  expect(map2d.getAsArray(0)).toEqual([
@@ -40,7 +52,10 @@ describe('Map2dBase', () => {
40
52
  });
41
53
 
42
54
  it('should return the keys from the first axis', () => {
43
- const map2d = new Map2dBase<string, string, number>();
55
+ const map2d = new Map2dBase<string, string, number>(
56
+ (value) => value,
57
+ (value) => value,
58
+ );
44
59
  map2d.set('a', 'b', 2);
45
60
  map2d.set('c', 'd', 4);
46
61
 
@@ -48,7 +63,10 @@ describe('Map2dBase', () => {
48
63
  });
49
64
 
50
65
  it('should return the keys from the second axis', () => {
51
- const map2d = new Map2dBase<string, string, number>();
66
+ const map2d = new Map2dBase<string, string, number>(
67
+ (value) => value,
68
+ (value) => value,
69
+ );
52
70
  map2d.set('a', 'b', 2);
53
71
  map2d.set('c', 'd', 4);
54
72
 
@@ -56,7 +74,10 @@ describe('Map2dBase', () => {
56
74
  });
57
75
 
58
76
  it('should work with objects as keys', () => {
59
- const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
77
+ const map2d = new Map2dBase<{ a: string }, { b: string }, number>(
78
+ ({ a }) => a,
79
+ ({ b }) => b,
80
+ );
60
81
  map2d.set({ a: 'a' }, { b: 'b' }, 2);
61
82
  map2d.set({ a: 'second' }, { b: 'second' }, 3);
62
83
 
@@ -65,14 +86,20 @@ describe('Map2dBase', () => {
65
86
  });
66
87
 
67
88
  it('should update a value with objects as keys', () => {
68
- const map2d = new Map2dBase<{ a: string }, { b: string }, number>();
89
+ const map2d = new Map2dBase<{ a: string }, { b: string }, number>(
90
+ ({ a }) => a,
91
+ ({ b }) => b,
92
+ );
69
93
  map2d.set({ a: 'a' }, { b: 'b' }, 2);
70
94
  map2d.set({ a: 'a' }, { b: 'b' }, 3);
71
95
  expect(map2d.get({ a: 'a' }, { b: 'b' })).toBe(3);
72
96
  });
73
97
 
74
98
  it('should return a row by key', () => {
75
- const map2d = new Map2dBase<string, string, number>();
99
+ const map2d = new Map2dBase<string, string, number>(
100
+ (value) => value,
101
+ (value) => value,
102
+ );
76
103
  map2d.set('a', 'b', 2);
77
104
  map2d.set('c', 'd', 4);
78
105
 
@@ -81,14 +108,20 @@ describe('Map2dBase', () => {
81
108
  });
82
109
 
83
110
  it('should return an empty array when the row does not exist', () => {
84
- const map2d = new Map2dBase<string, string, number>();
111
+ const map2d = new Map2dBase<string, string, number>(
112
+ (value) => value,
113
+ (value) => value,
114
+ );
85
115
  map2d.set('a', 'b', 2);
86
116
 
87
117
  expect(map2d.getRow('c', 0)).toEqual([]);
88
118
  });
89
119
 
90
120
  it('should return content as object', () => {
91
- const map2d = new Map2dBase<string, string, number>();
121
+ const map2d = new Map2dBase<string, string, number>(
122
+ (value) => value,
123
+ (value) => value,
124
+ );
92
125
  map2d.set('a', 'b', 2);
93
126
  map2d.set('c', 'd', 4);
94
127
 
@@ -99,7 +132,10 @@ describe('Map2dBase', () => {
99
132
  });
100
133
 
101
134
  it('should use initial data', () => {
102
- const map2d = new Map2dBase<string, string, number>();
135
+ const map2d = new Map2dBase<string, string, number>(
136
+ (value) => value,
137
+ (value) => value,
138
+ );
103
139
  map2d.set('a', 'b', 2);
104
140
  map2d.set('c', 'd', 4);
105
141
 
@@ -174,7 +210,10 @@ describe('Map2dView', () => {
174
210
  });
175
211
 
176
212
  function createBaseContainer() {
177
- const container = new Map2dBase<string, string, number>();
213
+ const container = new Map2dBase<string, string, number>(
214
+ (value) => value,
215
+ (value) => value,
216
+ );
178
217
  container.set('a', 'b', 1);
179
218
  container.set('c', 'b', 3);
180
219
  container.set('c', 'd', 4);
@@ -1,5 +1,3 @@
1
- import hash from 'object-hash';
2
-
3
1
  export interface Map2d<Key1, Key2, Value> {
4
2
  get(keyFirstAxis: Key1, keySecondAxis: Key2): Value | undefined;
5
3
 
@@ -16,6 +14,7 @@ export interface Map2d<Key1, Key2, Value> {
16
14
  getAsArray(fillEmptyWith: Value): Value[][];
17
15
 
18
16
  serializeFirstAxis(key: Key1): string;
17
+
19
18
  serializeSecondAxis(key: Key2): string;
20
19
 
21
20
  readonly keysFirstAxis: Map<string, Key1>;
@@ -36,8 +35,8 @@ export class Map2dBase<Key1 extends object | string, Key2 extends object | strin
36
35
  readonly keysSecondAxis = new Map<string, Key2>();
37
36
 
38
37
  constructor(
39
- readonly serializeFirstAxis: (key: Key1) => string = (key) => (typeof key === 'string' ? key : hash(key)),
40
- readonly serializeSecondAxis: (key: Key2) => string = (key) => (typeof key === 'string' ? key : hash(key)),
38
+ readonly serializeFirstAxis: (key: Key1) => string,
39
+ readonly serializeSecondAxis: (key: Key2) => string,
41
40
  initialContent?: Map2DContents<Key1, Key2, Value>,
42
41
  ) {
43
42
  if (initialContent) {
@@ -9,29 +9,21 @@ import { type DateRangeSelectorProps } from '../../preact/dateRangeSelector/date
9
9
  import './gs-date-range-selector';
10
10
  import '../app';
11
11
  import { toYYYYMMDD } from '../../preact/dateRangeSelector/dateConversion';
12
- import {
13
- PRESET_VALUE_ALL_TIMES,
14
- PRESET_VALUE_CUSTOM,
15
- PRESET_VALUE_LAST_2_MONTHS,
16
- PRESET_VALUE_LAST_2_WEEKS,
17
- PRESET_VALUE_LAST_3_MONTHS,
18
- PRESET_VALUE_LAST_6_MONTHS,
19
- PRESET_VALUE_LAST_MONTH,
20
- } from '../../preact/dateRangeSelector/selectableOptions';
12
+ import { dateRangeOptionPresets } from '../../preact/dateRangeSelector/dateRangeOption';
21
13
  import { withinShadowRoot } from '../withinShadowRoot.story';
22
14
 
23
15
  const codeExample = String.raw`
24
16
  <gs-date-range-selector
25
- customSelectOptions='[{ "label": "Year 2021", "dateFrom": "2021-01-01", "dateTo": "2021-12-31" }]'
17
+ dateRangeOptions='[{ "label": "Year 2021", "dateFrom": "2021-01-01", "dateTo": "2021-12-31" }]'
26
18
  earliestDate="1970-01-01"
27
- initialValue="${PRESET_VALUE_LAST_6_MONTHS}"
19
+ initialValue="Year 2021"
28
20
  initialDateFrom="2020-01-01"
29
21
  initialDateTo="2021-01-01"
30
22
  width="100%"
31
23
  dateColumn="myDateColumn"
32
24
  ></gs-date-range-selector>`;
33
25
 
34
- const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
26
+ const meta: Meta<Required<DateRangeSelectorProps>> = {
35
27
  title: 'Input/DateRangeSelector',
36
28
  component: 'gs-date-range-selector',
37
29
  parameters: withComponentDocs({
@@ -50,19 +42,10 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
50
42
  control: {
51
43
  type: 'select',
52
44
  },
53
- options: [
54
- PRESET_VALUE_CUSTOM,
55
- PRESET_VALUE_ALL_TIMES,
56
- PRESET_VALUE_LAST_2_WEEKS,
57
- PRESET_VALUE_LAST_MONTH,
58
- PRESET_VALUE_LAST_2_MONTHS,
59
- PRESET_VALUE_LAST_3_MONTHS,
60
- PRESET_VALUE_LAST_6_MONTHS,
61
- 'CustomDateRange',
62
- ],
45
+ options: [dateRangeOptionPresets.lastMonth.label, dateRangeOptionPresets.allTimes.label, 'CustomDateRange'],
63
46
  },
64
47
  dateColumn: { control: { type: 'text' } },
65
- customSelectOptions: {
48
+ dateRangeOptions: {
66
49
  control: {
67
50
  type: 'object',
68
51
  },
@@ -79,9 +62,14 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
79
62
  },
80
63
  },
81
64
  args: {
82
- customSelectOptions: [{ label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' }],
65
+ dateRangeOptions: [
66
+ dateRangeOptionPresets.lastMonth,
67
+ dateRangeOptionPresets.last3Months,
68
+ dateRangeOptionPresets.allTimes,
69
+ { label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' },
70
+ ],
83
71
  earliestDate: '1970-01-01',
84
- initialValue: PRESET_VALUE_LAST_6_MONTHS,
72
+ initialValue: dateRangeOptionPresets.lastMonth.label,
85
73
  dateColumn: 'aDateColumn',
86
74
  width: '100%',
87
75
  initialDateFrom: '',
@@ -92,12 +80,12 @@ const meta: Meta<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
92
80
 
93
81
  export default meta;
94
82
 
95
- export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps<'CustomDateRange'>>> = {
83
+ export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps>> = {
96
84
  render: (args) =>
97
85
  html` <gs-app lapis="${LAPIS_URL}">
98
86
  <div class="max-w-screen-lg">
99
87
  <gs-date-range-selector
100
- .customSelectOptions=${args.customSelectOptions}
88
+ .dateRangeOptions=${args.dateRangeOptions}
101
89
  .earliestDate=${args.earliestDate}
102
90
  .initialValue=${args.initialValue}
103
91
  .initialDateFrom=${args.initialDateFrom}
@@ -112,7 +100,7 @@ export const DateRangeSelectorStory: StoryObj<Required<DateRangeSelectorProps<'C
112
100
  const dateTo = () => canvas.getByPlaceholderText('Date to');
113
101
 
114
102
  await step('Expect last 6 months to be selected', async () => {
115
- await expect(canvas.getByRole('combobox')).toHaveValue('last6Months');
103
+ await expect(canvas.getByRole('combobox')).toHaveValue('Last month');
116
104
  await waitFor(() => {
117
105
  expect(dateTo()).toHaveValue(toYYYYMMDD(new Date()));
118
106
  });