@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
@@ -21,6 +21,7 @@ import { ResizeContainer } from '../components/resize-container';
21
21
  import { ScalingSelector } from '../components/scaling-selector';
22
22
  import Tabs from '../components/tabs';
23
23
  import { type ConfidenceIntervalMethod } from '../shared/charts/confideceInterval';
24
+ import type { YAxisMaxConfig } from '../shared/charts/getYAxisMax';
24
25
  import { type ScaleType } from '../shared/charts/getYAxisScale';
25
26
  import { useQuery } from '../useQuery';
26
27
 
@@ -33,18 +34,20 @@ export interface PrevalenceOverTimeProps extends PrevalenceOverTimeInnerProps {
33
34
  }
34
35
 
35
36
  export interface PrevalenceOverTimeInnerProps {
36
- numerator: NamedLapisFilter | NamedLapisFilter[];
37
- denominator: LapisFilter;
37
+ numeratorFilter: NamedLapisFilter | NamedLapisFilter[];
38
+ denominatorFilter: LapisFilter;
38
39
  granularity: TemporalGranularity;
39
40
  smoothingWindow: number;
40
41
  views: View[];
41
42
  confidenceIntervalMethods: ConfidenceIntervalMethod[];
42
43
  lapisDateField: string;
44
+ pageSize: boolean | number;
45
+ yAxisMaxConfig: YAxisMaxConfig;
43
46
  }
44
47
 
45
48
  export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
46
- numerator,
47
- denominator,
49
+ numeratorFilter,
50
+ denominatorFilter,
48
51
  granularity,
49
52
  smoothingWindow,
50
53
  views,
@@ -53,6 +56,8 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
53
56
  height,
54
57
  headline = 'Prevalence over time',
55
58
  lapisDateField,
59
+ pageSize,
60
+ yAxisMaxConfig,
56
61
  }) => {
57
62
  const size = { height, width };
58
63
 
@@ -61,13 +66,15 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
61
66
  <ResizeContainer size={size}>
62
67
  <Headline heading={headline}>
63
68
  <PrevalenceOverTimeInner
64
- numerator={numerator}
65
- denominator={denominator}
69
+ numeratorFilter={numeratorFilter}
70
+ denominatorFilter={denominatorFilter}
66
71
  granularity={granularity}
67
72
  smoothingWindow={smoothingWindow}
68
73
  views={views}
69
74
  confidenceIntervalMethods={confidenceIntervalMethods}
70
75
  lapisDateField={lapisDateField}
76
+ pageSize={pageSize}
77
+ yAxisMaxConfig={yAxisMaxConfig}
71
78
  />
72
79
  </Headline>
73
80
  </ResizeContainer>
@@ -76,19 +83,29 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
76
83
  };
77
84
 
78
85
  export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeInnerProps> = ({
79
- numerator,
80
- denominator,
86
+ numeratorFilter,
87
+ denominatorFilter,
81
88
  granularity,
82
89
  smoothingWindow,
83
90
  views,
84
91
  confidenceIntervalMethods,
85
92
  lapisDateField,
93
+ pageSize,
94
+ yAxisMaxConfig,
86
95
  }) => {
87
96
  const lapis = useContext(LapisUrlContext);
88
97
 
89
98
  const { data, error, isLoading } = useQuery(
90
- () => queryPrevalenceOverTime(numerator, denominator, granularity, smoothingWindow, lapis, lapisDateField),
91
- [lapis, numerator, denominator, granularity, smoothingWindow],
99
+ () =>
100
+ queryPrevalenceOverTime(
101
+ numeratorFilter,
102
+ denominatorFilter,
103
+ granularity,
104
+ smoothingWindow,
105
+ lapis,
106
+ lapisDateField,
107
+ ),
108
+ [lapis, numeratorFilter, denominatorFilter, granularity, smoothingWindow],
92
109
  );
93
110
 
94
111
  if (isLoading) {
@@ -109,6 +126,8 @@ export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeInnerP
109
126
  data={data}
110
127
  granularity={granularity}
111
128
  confidenceIntervalMethods={confidenceIntervalMethods}
129
+ pageSize={pageSize}
130
+ yAxisMaxConfig={yAxisMaxConfig}
112
131
  />
113
132
  );
114
133
  };
@@ -118,6 +137,8 @@ type PrevalenceOverTimeTabsProps = {
118
137
  data: PrevalenceOverTimeData;
119
138
  granularity: TemporalGranularity;
120
139
  confidenceIntervalMethods: ConfidenceIntervalMethod[];
140
+ pageSize: boolean | number;
141
+ yAxisMaxConfig: YAxisMaxConfig;
121
142
  };
122
143
 
123
144
  const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = ({
@@ -125,6 +146,8 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
125
146
  data,
126
147
  granularity,
127
148
  confidenceIntervalMethods,
149
+ pageSize,
150
+ yAxisMaxConfig,
128
151
  }) => {
129
152
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
130
153
  const [confidenceIntervalMethod, setConfidenceIntervalMethod] = useState<ConfidenceIntervalMethod>(
@@ -141,6 +164,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
141
164
  data={data}
142
165
  yAxisScaleType={yAxisScaleType}
143
166
  confidenceIntervalMethod={confidenceIntervalMethod}
167
+ yAxisMaxConfig={yAxisMaxConfig}
144
168
  />
145
169
  ),
146
170
  };
@@ -152,18 +176,25 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
152
176
  data={data}
153
177
  yAxisScaleType={yAxisScaleType}
154
178
  confidenceIntervalMethod={confidenceIntervalMethod}
179
+ yAxisMaxConfig={yAxisMaxConfig}
155
180
  />
156
181
  ),
157
182
  };
158
183
  case 'bubble':
159
184
  return {
160
185
  title: 'Bubble',
161
- content: <PrevalenceOverTimeBubbleChart data={data} yAxisScaleType={yAxisScaleType} />,
186
+ content: (
187
+ <PrevalenceOverTimeBubbleChart
188
+ data={data}
189
+ yAxisScaleType={yAxisScaleType}
190
+ yAxisMaxConfig={yAxisMaxConfig}
191
+ />
192
+ ),
162
193
  };
163
194
  case 'table':
164
195
  return {
165
196
  title: 'Table',
166
- content: <PrevalenceOverTimeTable data={data} granularity={granularity} />,
197
+ content: <PrevalenceOverTimeTable data={data} granularity={granularity} pageSize={pageSize} />,
167
198
  };
168
199
  }
169
200
  };
@@ -238,3 +269,6 @@ const PrevalenceOverTimeInfo: FunctionComponent = () => {
238
269
  </Info>
239
270
  );
240
271
  };
272
+
273
+ export const maxInData = (data: PrevalenceOverTimeData) =>
274
+ Math.max(...data.flatMap((variant) => variant.content.map((dataPoint) => dataPoint.prevalence)));
@@ -5,7 +5,9 @@ import GsChart from '../components/chart';
5
5
  import { LogitScale } from '../shared/charts/LogitScale';
6
6
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
7
7
  import { confidenceIntervalDataLabel } from '../shared/charts/confideceInterval';
8
+ import { getYAxisMax, type YAxisMaxConfig } from '../shared/charts/getYAxisMax';
8
9
  import { getYAxisScale, type ScaleType } from '../shared/charts/getYAxisScale';
10
+ import { formatProportion } from '../shared/table/formatProportion';
9
11
 
10
12
  interface RelativeGrowthAdvantageChartData {
11
13
  t: YearMonthDay[];
@@ -25,11 +27,17 @@ interface RelativeGrowthAdvantageChartData {
25
27
  interface RelativeGrowthAdvantageChartProps {
26
28
  data: RelativeGrowthAdvantageChartData;
27
29
  yAxisScaleType: ScaleType;
30
+ yAxisMaxConfig: YAxisMaxConfig;
28
31
  }
29
32
 
30
33
  Chart.register(...registerables, LogitScale);
31
34
 
32
- const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAdvantageChartProps) => {
35
+ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType, yAxisMaxConfig }: RelativeGrowthAdvantageChartProps) => {
36
+ const maxY =
37
+ yAxisScaleType !== 'logit'
38
+ ? getYAxisMax(Math.max(...data.proportion), yAxisMaxConfig?.[yAxisScaleType])
39
+ : undefined;
40
+
33
41
  const config: ChartConfiguration = {
34
42
  type: 'line',
35
43
  data: {
@@ -39,8 +47,9 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAd
39
47
  options: {
40
48
  maintainAspectRatio: false,
41
49
  animation: false,
50
+
42
51
  scales: {
43
- y: getYAxisScale(yAxisScaleType),
52
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY },
44
53
  },
45
54
  plugins: {
46
55
  legend: {
@@ -52,14 +61,37 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAd
52
61
  };
53
62
 
54
63
  return (
55
- <div className='flex flex-col h-full'>
64
+ <div className='flex h-full flex-col'>
65
+ <RelativeGrowthAdvantageDisplay
66
+ relativeAdvantage={data.params.fd.value}
67
+ relativeAdvantageLowerBound={data.params.fd.ciLower}
68
+ relativeAdvantageUpperBound={data.params.fd.ciUpper}
69
+ />
56
70
  <div className='flex-1'>
57
71
  <GsChart configuration={config} />
58
72
  </div>
59
- <p>
60
- Advantage: {(data.params.fd.value * 100).toFixed(2)}% ({(data.params.fd.ciLower * 100).toFixed(2)}% -{' '}
61
- {(data.params.fd.ciUpper * 100).toFixed(2)}%)
62
- </p>
73
+ </div>
74
+ );
75
+ };
76
+
77
+ const RelativeGrowthAdvantageDisplay = ({
78
+ relativeAdvantage,
79
+ relativeAdvantageLowerBound,
80
+ relativeAdvantageUpperBound,
81
+ }: {
82
+ relativeAdvantage: number;
83
+ relativeAdvantageLowerBound: number;
84
+ relativeAdvantageUpperBound: number;
85
+ }) => {
86
+ return (
87
+ <div class='mx-auto flex items-end flex-wrap'>
88
+ <span class='text-[#606060]'>Relative advantage:</span>
89
+ <div>
90
+ <span class='text-2xl ml-3'> {formatProportion(relativeAdvantage)} </span>
91
+ <span class='ml-2.5'>
92
+ ({formatProportion(relativeAdvantageLowerBound)} - {formatProportion(relativeAdvantageUpperBound)})
93
+ </span>
94
+ </div>
63
95
  </div>
64
96
  );
65
97
  };
@@ -1,5 +1,5 @@
1
- import denominator from './__mockData__/denominator.json';
2
- import numerator from './__mockData__/numerator.json';
1
+ import denominator from './__mockData__/denominatorFilter.json';
2
+ import numerator from './__mockData__/numeratorFilter.json';
3
3
  import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './relative-growth-advantage';
4
4
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
5
5
  import { LapisUrlContext } from '../LapisUrlContext';
@@ -21,6 +21,7 @@ export default {
21
21
  width: { control: 'text' },
22
22
  height: { control: 'text' },
23
23
  headline: { control: 'text' },
24
+ yAxisMaxConfig: { control: 'object' },
24
25
  },
25
26
  };
26
27
 
@@ -28,14 +29,15 @@ export const Primary = {
28
29
  render: (args: RelativeGrowthAdvantageProps) => (
29
30
  <LapisUrlContext.Provider value={LAPIS_URL}>
30
31
  <RelativeGrowthAdvantage
31
- numerator={args.numerator}
32
- denominator={args.denominator}
32
+ numeratorFilter={args.numeratorFilter}
33
+ denominatorFilter={args.denominatorFilter}
33
34
  generationTime={args.generationTime}
34
35
  views={args.views}
35
36
  width={args.width}
36
37
  height={args.height}
37
38
  headline={args.headline}
38
39
  lapisDateField={args.lapisDateField}
40
+ yAxisMaxConfig={args.yAxisMaxConfig}
39
41
  />
40
42
  </LapisUrlContext.Provider>
41
43
  ),
@@ -48,6 +50,10 @@ export const Primary = {
48
50
  height: '700px',
49
51
  headline: 'Relative growth advantage',
50
52
  lapisDateField: 'date',
53
+ yAxisMaxConfig: {
54
+ linear: 1,
55
+ logarithmic: 1,
56
+ },
51
57
  },
52
58
  parameters: {
53
59
  fetchMock: {
@@ -17,6 +17,7 @@ import { NoDataDisplay } from '../components/no-data-display';
17
17
  import { ResizeContainer } from '../components/resize-container';
18
18
  import { ScalingSelector } from '../components/scaling-selector';
19
19
  import Tabs from '../components/tabs';
20
+ import { type YAxisMaxConfig } from '../shared/charts/getYAxisMax';
20
21
  import { type ScaleType } from '../shared/charts/getYAxisScale';
21
22
  import { useQuery } from '../useQuery';
22
23
 
@@ -29,22 +30,24 @@ export interface RelativeGrowthAdvantageProps extends RelativeGrowthAdvantagePro
29
30
  }
30
31
 
31
32
  export interface RelativeGrowthAdvantagePropsInner {
32
- numerator: LapisFilter;
33
- denominator: LapisFilter;
33
+ numeratorFilter: LapisFilter;
34
+ denominatorFilter: LapisFilter;
34
35
  generationTime: number;
35
36
  views: View[];
36
37
  lapisDateField: string;
38
+ yAxisMaxConfig: YAxisMaxConfig;
37
39
  }
38
40
 
39
41
  export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = ({
40
42
  views,
41
43
  width,
42
44
  height,
43
- numerator,
44
- denominator,
45
+ numeratorFilter,
46
+ denominatorFilter,
45
47
  generationTime,
46
48
  headline = 'Relative growth advantage',
47
49
  lapisDateField,
50
+ yAxisMaxConfig,
48
51
  }) => {
49
52
  const size = { height, width };
50
53
 
@@ -54,10 +57,11 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
54
57
  <Headline heading={headline}>
55
58
  <RelativeGrowthAdvantageInner
56
59
  views={views}
57
- numerator={numerator}
58
- denominator={denominator}
60
+ numeratorFilter={numeratorFilter}
61
+ denominatorFilter={denominatorFilter}
59
62
  generationTime={generationTime}
60
63
  lapisDateField={lapisDateField}
64
+ yAxisMaxConfig={yAxisMaxConfig}
61
65
  />
62
66
  </Headline>
63
67
  </ResizeContainer>
@@ -66,18 +70,19 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
66
70
  };
67
71
 
68
72
  export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantagePropsInner> = ({
69
- numerator,
70
- denominator,
73
+ numeratorFilter,
74
+ denominatorFilter,
71
75
  generationTime,
72
76
  views,
73
77
  lapisDateField,
78
+ yAxisMaxConfig,
74
79
  }) => {
75
80
  const lapis = useContext(LapisUrlContext);
76
81
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
77
82
 
78
83
  const { data, error, isLoading } = useQuery(
79
- () => queryRelativeGrowthAdvantage(numerator, denominator, generationTime, lapis, lapisDateField),
80
- [lapis, numerator, denominator, generationTime, views],
84
+ () => queryRelativeGrowthAdvantage(numeratorFilter, denominatorFilter, generationTime, lapis, lapisDateField),
85
+ [lapis, numeratorFilter, denominatorFilter, generationTime, views],
81
86
  );
82
87
 
83
88
  if (isLoading) {
@@ -99,6 +104,7 @@ export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvan
99
104
  setYAxisScaleType={setYAxisScaleType}
100
105
  views={views}
101
106
  generationTime={generationTime}
107
+ yAxisMaxConfig={yAxisMaxConfig}
102
108
  />
103
109
  );
104
110
  };
@@ -109,6 +115,7 @@ type RelativeGrowthAdvantageTabsProps = {
109
115
  setYAxisScaleType: (scaleType: ScaleType) => void;
110
116
  views: View[];
111
117
  generationTime: number;
118
+ yAxisMaxConfig: YAxisMaxConfig;
112
119
  };
113
120
 
114
121
  const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabsProps> = ({
@@ -117,6 +124,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
117
124
  setYAxisScaleType,
118
125
  views,
119
126
  generationTime,
127
+ yAxisMaxConfig,
120
128
  }) => {
121
129
  const getTab = (view: View) => {
122
130
  switch (view) {
@@ -131,6 +139,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
131
139
  params: data.params,
132
140
  }}
133
141
  yAxisScaleType={yAxisScaleType}
142
+ yAxisMaxConfig={yAxisMaxConfig}
134
143
  />
135
144
  ),
136
145
  };
@@ -20,10 +20,15 @@ export function wilson95PercentConfidenceInterval(observed: number, sample: numb
20
20
  };
21
21
  }
22
22
 
23
- export const confidenceIntervalDataLabel = (value: number, lowerLimit: number, upperLimit: number, prefix?: string) => {
23
+ export const confidenceIntervalDataLabel = (
24
+ value: number,
25
+ lowerLimit?: number,
26
+ upperLimit?: number,
27
+ prefix?: string,
28
+ ) => {
24
29
  const label = prefix ? `${prefix}: ` : '';
25
30
 
26
- return `${label}${value.toFixed(3)} (${lowerLimit.toFixed(3)} - ${upperLimit.toFixed(3)})`;
31
+ return `${label}${value.toFixed(3)} (${lowerLimit?.toFixed(3)} - ${upperLimit?.toFixed(3)})`;
27
32
  };
28
33
 
29
34
  export type ConfidenceIntervalMethod = 'wilson' | 'none';
@@ -0,0 +1,24 @@
1
+ export interface YAxisMaxConfig {
2
+ linear?: AxisMax;
3
+ logarithmic?: AxisMax;
4
+ }
5
+
6
+ export type AxisMax = 'maxInData' | 'limitTo1' | number;
7
+
8
+ export const getYAxisMax = (maxInData: number, axisMax?: AxisMax) => {
9
+ if (!axisMax) {
10
+ return 1;
11
+ }
12
+
13
+ switch (axisMax) {
14
+ case 'limitTo1': {
15
+ return maxInData > 1 ? 1 : maxInData;
16
+ }
17
+ case 'maxInData': {
18
+ return maxInData;
19
+ }
20
+ default: {
21
+ return axisMax;
22
+ }
23
+ }
24
+ };
@@ -6,11 +6,9 @@ export function getYAxisScale(scaleType: ScaleType) {
6
6
  return { beginAtZero: true, type: 'linear' as const, min: 0, max: 1 };
7
7
  }
8
8
  case 'logarithmic': {
9
- return { type: 'logarithmic' as const };
9
+ return { type: 'logarithmic' as const, max: 1 };
10
10
  }
11
11
  case 'logit':
12
12
  return { type: 'logit' as const };
13
- default:
14
- return { beginAtZero: true, type: 'linear' as const };
15
13
  }
16
14
  }
@@ -20,7 +20,7 @@ const compareAscending = (a: string | null | number, b: string | null | number)
20
20
  };
21
21
 
22
22
  export async function queryAggregateData(
23
- variant: LapisFilter,
23
+ lapisFilter: LapisFilter,
24
24
  fields: string[],
25
25
  lapis: string,
26
26
  initialSort: InitialSort = { field: 'count', direction: 'descending' },
@@ -31,7 +31,7 @@ export async function queryAggregateData(
31
31
  throw new Error(`InitialSort field not in fields. Valid fields are: ${validSortFields.join(', ')}`);
32
32
  }
33
33
 
34
- const fetchData = new FetchAggregatedOperator<Record<string, string | null | number>>(variant, fields);
34
+ const fetchData = new FetchAggregatedOperator<Record<string, string | null | number>>(lapisFilter, fields);
35
35
  const sortData = new SortOperator(fetchData, (a, b) => {
36
36
  return initialSort.direction === 'ascending'
37
37
  ? compareAscending(a[initialSort.field], b[initialSort.field])
@@ -2,8 +2,13 @@ import { FetchInsertionsOperator } from '../operator/FetchInsertionsOperator';
2
2
  import { SortOperator } from '../operator/SortOperator';
3
3
  import { type LapisFilter, type SequenceType } from '../types';
4
4
 
5
- export function queryInsertions(variant: LapisFilter, sequenceType: SequenceType, lapis: string, signal?: AbortSignal) {
6
- const fetchData = new FetchInsertionsOperator(variant, sequenceType);
5
+ export function queryInsertions(
6
+ lapisFilter: LapisFilter,
7
+ sequenceType: SequenceType,
8
+ lapis: string,
9
+ signal?: AbortSignal,
10
+ ) {
11
+ const fetchData = new FetchInsertionsOperator(lapisFilter, sequenceType);
7
12
  const sortData = new SortOperator(fetchData, (a, b) => {
8
13
  if (a.mutation.segment !== b.mutation.segment) {
9
14
  return (a.mutation.segment ?? '').localeCompare(b.mutation.segment ?? '');
@@ -3,12 +3,12 @@ import { SortOperator } from '../operator/SortOperator';
3
3
  import { type LapisFilter, type SequenceType } from '../types';
4
4
 
5
5
  export function querySubstitutionsOrDeletions(
6
- variant: LapisFilter,
6
+ lapisFilter: LapisFilter,
7
7
  sequenceType: SequenceType,
8
8
  lapis: string,
9
9
  signal?: AbortSignal,
10
10
  ) {
11
- const fetchData = new FetchSubstitutionsOrDeletionsOperator(variant, sequenceType, 0);
11
+ const fetchData = new FetchSubstitutionsOrDeletionsOperator(lapisFilter, sequenceType, 0);
12
12
  const sortData = new SortOperator(fetchData, (a, b) => {
13
13
  if (a.mutation.segment !== b.mutation.segment) {
14
14
  return (a.mutation.segment ?? '').localeCompare(b.mutation.segment ?? '');
@@ -91,7 +91,7 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
91
91
  /**
92
92
  * The width of the component.
93
93
  *
94
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
94
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
95
95
  */
96
96
  @property({ type: String })
97
97
  width: string = '100%';
@@ -17,6 +17,7 @@ const codeExample = String.raw`
17
17
  fields='["region", "country"]'
18
18
  initialValue='Europe / Switzerland'
19
19
  width="100%"
20
+ placeholderText="Enter a location"
20
21
  ></gs-location-filter>`;
21
22
 
22
23
  const meta: Meta = {
@@ -48,6 +49,11 @@ const meta: Meta = {
48
49
  type: 'text',
49
50
  },
50
51
  },
52
+ placeholderText: {
53
+ control: {
54
+ type: 'text',
55
+ },
56
+ },
51
57
  },
52
58
  decorators: [withActions],
53
59
  tags: ['autodocs'],
@@ -63,6 +69,7 @@ const Template: StoryObj<LocationFilterProps> = {
63
69
  .fields=${args.fields}
64
70
  initialValue=${ifDefined(args.initialValue)}
65
71
  .width=${args.width}
72
+ placeholderText=${ifDefined(args.placeholderText)}
66
73
  ></gs-location-filter>
67
74
  </div>
68
75
  </gs-app>`;
@@ -71,6 +78,7 @@ const Template: StoryObj<LocationFilterProps> = {
71
78
  fields: ['region', 'country', 'division', 'location'],
72
79
  initialValue: '',
73
80
  width: '100%',
81
+ placeholderText: 'Enter a location',
74
82
  },
75
83
  };
76
84
 
@@ -102,6 +110,9 @@ export const LocationFilter: StoryObj<LocationFilterProps> = {
102
110
  await waitFor(() => {
103
111
  return expect(canvas.getByRole('combobox')).toBeEnabled();
104
112
  });
113
+ await waitFor(() => {
114
+ return expect(canvas.getByPlaceholderText('Enter a location')).toBeInTheDocument();
115
+ });
105
116
  },
106
117
  };
107
118
 
@@ -54,13 +54,26 @@ export class LocationFilterComponent extends PreactLitAdapter {
54
54
  /**
55
55
  * The width of the component.
56
56
  *
57
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
57
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
58
58
  */
59
59
  @property({ type: String })
60
60
  width: string = '100%';
61
61
 
62
+ /**
63
+ * The placeholder text to display in the input field, if it is empty.
64
+ */
65
+ @property()
66
+ placeholderText: string = '';
67
+
62
68
  override render() {
63
- return <LocationFilter initialValue={this.initialValue} fields={this.fields} width={this.width} />;
69
+ return (
70
+ <LocationFilter
71
+ initialValue={this.initialValue}
72
+ fields={this.fields}
73
+ width={this.width}
74
+ placeholderText={this.placeholderText}
75
+ />
76
+ );
64
77
  }
65
78
  }
66
79
 
@@ -86,7 +86,7 @@ export class MutationFilterComponent extends PreactLitAdapter {
86
86
  /**
87
87
  * The width of the component.
88
88
  *
89
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
89
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
90
90
  */
91
91
  @property({ type: String })
92
92
  width: string = '100%';
@@ -45,7 +45,7 @@ export class TextInputComponent extends PreactLitAdapter {
45
45
  /**
46
46
  * The width of the component.
47
47
  *
48
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
48
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
49
49
  */
50
50
  @property({ type: String })
51
51
  width: string = '100%';
@@ -19,6 +19,7 @@ const codeExample = `
19
19
  height='700px'
20
20
  initialSortField="count"
21
21
  initialSortDirection="descending"
22
+ pageSize="10"
22
23
  ></gs-aggregate>`;
23
24
 
24
25
  const meta: Meta<Required<AggregateProps>> = {
@@ -33,6 +34,7 @@ const meta: Meta<Required<AggregateProps>> = {
33
34
  width: { control: 'text' },
34
35
  height: { control: 'text' },
35
36
  headline: { control: 'text' },
37
+ pageSize: { control: 'object' },
36
38
  initialSortField: { control: 'text' },
37
39
  initialSortDirection: {
38
40
  options: ['ascending', 'descending'],
@@ -81,6 +83,7 @@ export const Table: StoryObj<Required<AggregateProps>> = {
81
83
  .headline=${args.headline}
82
84
  .initialSortField=${args.initialSortField}
83
85
  .initialSortDirection=${args.initialSortDirection}
86
+ .pageSize=${args.pageSize}
84
87
  ></gs-aggregate>
85
88
  </gs-app>
86
89
  `,
@@ -95,5 +98,6 @@ export const Table: StoryObj<Required<AggregateProps>> = {
95
98
  headline: 'Aggregate',
96
99
  initialSortField: 'count',
97
100
  initialSortDirection: 'descending',
101
+ pageSize: 10,
98
102
  },
99
103
  };