@genspectrum/dashboard-components 0.6.18 → 0.7.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 (118) hide show
  1. package/README.md +5 -12
  2. package/custom-elements.json +22 -22
  3. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  4. package/dist/dashboard-components.js +301 -302
  5. package/dist/dashboard-components.js.map +1 -1
  6. package/dist/genspectrum-components.d.ts +60 -10
  7. package/dist/style.css +3 -2
  8. package/package.json +13 -4
  9. package/src/index.ts +1 -0
  10. package/src/operator/FetchInsertionsOperator.ts +2 -2
  11. package/src/operator/FetchSubstitutionsOrDeletionsOperator.ts +3 -3
  12. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  13. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  14. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  15. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  16. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  17. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  18. package/src/preact/mutationComparison/fetchMutationData.spec.ts +3 -3
  19. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +11 -11
  20. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +4 -4
  21. package/src/preact/mutationComparison/mutation-comparison-table.tsx +2 -2
  22. package/src/preact/mutationFilter/mutation-filter.tsx +27 -18
  23. package/src/preact/mutationFilter/parseAndValidateMutation.ts +4 -4
  24. package/src/preact/mutationFilter/parseMutation.spec.ts +17 -17
  25. package/src/preact/mutations/getInsertionsTableData.spec.ts +3 -3
  26. package/src/preact/mutations/getMutationsGridData.spec.ts +9 -9
  27. package/src/preact/mutations/getMutationsTableData.spec.ts +7 -7
  28. package/src/preact/mutations/mutations-insertions-table.tsx +3 -3
  29. package/src/preact/mutations/mutations-table.tsx +3 -3
  30. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  31. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +45686 -0
  32. package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +58989 -0
  33. package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +103991 -0
  34. package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +54 -0
  35. package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +63690 -0
  36. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +177 -161
  37. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +17 -59
  38. package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +27 -0
  39. package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +29 -0
  40. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +13 -14
  41. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +9 -334
  42. package/src/preact/mutationsOverTime/mutations-over-time.tsx +59 -54
  43. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +3 -3
  44. package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.spec.ts +5 -5
  45. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -1
  46. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +2 -2
  47. package/src/preact/shared/sort/sortInsertions.spec.ts +11 -11
  48. package/src/preact/shared/sort/sortInsertions.ts +2 -2
  49. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +13 -13
  50. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +7 -4
  51. package/src/preact/webWorkers/useWebWorker.ts +51 -0
  52. package/src/preact/webWorkers/workerFunction.ts +14 -0
  53. package/src/query/queryAggregatedDataOverTime.ts +3 -3
  54. package/src/query/queryMutationsOverTime.spec.ts +272 -51
  55. package/src/query/queryMutationsOverTime.ts +114 -47
  56. package/src/query/queryPrevalenceOverTime.ts +2 -2
  57. package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
  58. package/src/types.ts +25 -5
  59. package/src/utils/map2d.spec.ts +79 -12
  60. package/src/utils/map2d.ts +25 -5
  61. package/src/utils/mutations.spec.ts +20 -20
  62. package/src/utils/mutations.ts +80 -17
  63. package/src/utils/sort.ts +5 -2
  64. package/src/utils/temporal.spec.ts +27 -24
  65. package/src/utils/{temporal.ts → temporalClass.ts} +170 -72
  66. package/src/utils/temporalTestHelpers.ts +3 -3
  67. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  68. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  69. package/src/web-components/introduction.mdx +46 -0
  70. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +6 -699
  71. package/src/web-components/visualization/gs-mutations-over-time.tsx +2 -2
  72. package/standalone-bundle/dashboard-components.js +12011 -12778
  73. package/standalone-bundle/dashboard-components.js.map +1 -1
  74. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_01.json +0 -13
  75. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_02.json +0 -13
  76. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_03.json +0 -13
  77. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_04.json +0 -13
  78. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_05.json +0 -13
  79. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_06.json +0 -13
  80. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_07.json +0 -13
  81. package/src/preact/mutationsOverTime/__mockData__/aggregated_20_01_2024.json +0 -13
  82. package/src/preact/mutationsOverTime/__mockData__/aggregated_21_01_2024.json +0 -13
  83. package/src/preact/mutationsOverTime/__mockData__/aggregated_22_01_2024.json +0 -13
  84. package/src/preact/mutationsOverTime/__mockData__/aggregated_23_01_2024.json +0 -13
  85. package/src/preact/mutationsOverTime/__mockData__/aggregated_24_01_2024.json +0 -13
  86. package/src/preact/mutationsOverTime/__mockData__/aggregated_25_01_2024.json +0 -13
  87. package/src/preact/mutationsOverTime/__mockData__/aggregated_26_01_2024.json +0 -13
  88. package/src/preact/mutationsOverTime/__mockData__/aggregated_byDay.json +0 -38
  89. package/src/preact/mutationsOverTime/__mockData__/aggregated_byWeek.json +0 -122
  90. package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +0 -642
  91. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations.json +0 -1470
  92. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations_total.json +0 -13
  93. package/src/preact/mutationsOverTime/__mockData__/aggregated_week3_2024.json +0 -13
  94. package/src/preact/mutationsOverTime/__mockData__/aggregated_week4_2024.json +0 -13
  95. package/src/preact/mutationsOverTime/__mockData__/aggregated_week5_2024.json +0 -13
  96. package/src/preact/mutationsOverTime/__mockData__/aggregated_week6_2024.json +0 -13
  97. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_20_01_2024.json +0 -6778
  98. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_21_01_2024.json +0 -7129
  99. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_22_01_2024.json +0 -4681
  100. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_23_01_2024.json +0 -10738
  101. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_24_01_2024.json +0 -11710
  102. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_25_01_2024.json +0 -11557
  103. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_26_01_2024.json +0 -8596
  104. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_byDayOverall.json +0 -4726
  105. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +0 -1747
  106. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +0 -1774
  107. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +0 -1819
  108. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +0 -1864
  109. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +0 -1927
  110. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +0 -1864
  111. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +0 -9
  112. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byMonthOverall.json +0 -11143
  113. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byWeekOverall.json +0 -9154
  114. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_tooManyMutations.json +0 -16453
  115. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week3_2024.json +0 -8812
  116. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week4_2024.json +0 -9730
  117. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week5_2024.json +0 -9865
  118. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week6_2024.json +0 -11314
@@ -4,33 +4,28 @@ import { useEffect, useRef, useState } from 'preact/hooks';
4
4
 
5
5
  import { computeInitialValues } from './computeInitialValues';
6
6
  import { toYYYYMMDD } from './dateConversion';
7
- import {
8
- type CustomSelectOption,
9
- getDatesForSelectorValue,
10
- getSelectableOptions,
11
- type PresetOptionValues,
12
- } from './selectableOptions';
7
+ import { type DateRangeOption } from './dateRangeOption';
8
+ import { getDatesForSelectorValue, getSelectableOptions } from './selectableOptions';
13
9
  import { ErrorBoundary } from '../components/error-boundary';
14
10
  import { Select } from '../components/select';
15
11
  import type { ScaleType } from '../shared/charts/getYAxisScale';
16
12
 
17
- export interface DateRangeSelectorProps<CustomLabel extends string> extends DateRangeSelectorPropsInner<CustomLabel> {
13
+ const customOption = 'Custom';
14
+
15
+ export interface DateRangeSelectorProps extends DateRangeSelectorPropsInner {
18
16
  width: string;
19
17
  }
20
18
 
21
- export interface DateRangeSelectorPropsInner<CustomLabel extends string> {
22
- customSelectOptions: CustomSelectOption<CustomLabel>[];
19
+ export interface DateRangeSelectorPropsInner {
20
+ dateRangeOptions: DateRangeOption[];
23
21
  earliestDate: string;
24
- initialValue: PresetOptionValues | CustomLabel;
22
+ initialValue: string | undefined;
25
23
  initialDateFrom: string;
26
24
  initialDateTo: string;
27
25
  dateColumn: string;
28
26
  }
29
27
 
30
- export const DateRangeSelector = <CustomLabel extends string>({
31
- width,
32
- ...innerProps
33
- }: DateRangeSelectorProps<CustomLabel>) => {
28
+ export const DateRangeSelector = ({ width, ...innerProps }: DateRangeSelectorProps) => {
34
29
  const size = { width, height: '3rem' };
35
30
 
36
31
  return (
@@ -42,20 +37,20 @@ export const DateRangeSelector = <CustomLabel extends string>({
42
37
  );
43
38
  };
44
39
 
45
- export const DateRangeSelectorInner = <CustomLabel extends string>({
46
- customSelectOptions,
40
+ export const DateRangeSelectorInner = ({
41
+ dateRangeOptions,
47
42
  earliestDate = '1900-01-01',
48
43
  initialValue,
49
44
  dateColumn,
50
45
  initialDateFrom,
51
46
  initialDateTo,
52
- }: DateRangeSelectorPropsInner<CustomLabel>) => {
47
+ }: DateRangeSelectorPropsInner) => {
53
48
  const initialValues = computeInitialValues(
54
49
  initialValue,
55
50
  initialDateFrom,
56
51
  initialDateTo,
57
52
  earliestDate,
58
- customSelectOptions,
53
+ dateRangeOptions,
59
54
  );
60
55
 
61
56
  const fromDatePickerRef = useRef<HTMLInputElement>(null);
@@ -64,7 +59,7 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
64
59
  const [dateFromPicker, setDateFromPicker] = useState<flatpickr.Instance | null>(null);
65
60
  const [dateToPicker, setDateToPicker] = useState<flatpickr.Instance | null>(null);
66
61
 
67
- const [selectedDateRange, setSelectedDateRange] = useState<CustomLabel | PresetOptionValues>(
62
+ const [selectedDateRange, setSelectedDateRange] = useState<string | undefined>(
68
63
  initialValues.initialSelectedDateRange,
69
64
  );
70
65
 
@@ -104,10 +99,10 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
104
99
  // eslint-disable-next-line react-hooks/exhaustive-deps
105
100
  }, [fromDatePickerRef, toDatePickerRef]);
106
101
 
107
- const onSelectChange = (value: CustomLabel | PresetOptionValues) => {
102
+ const onSelectChange = (value: string) => {
108
103
  setSelectedDateRange(value);
109
104
 
110
- const dateRange = getDatesForSelectorValue(value, customSelectOptions, earliestDate);
105
+ const dateRange = getDatesForSelectorValue(value, dateRangeOptions, earliestDate);
111
106
 
112
107
  dateToPicker?.set('minDate', dateRange.dateFrom);
113
108
  dateFromPicker?.set('maxDate', dateRange.dateTo);
@@ -130,7 +125,7 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
130
125
 
131
126
  selectedDates.dateFrom = dateFromPicker?.selectedDates[0] || new Date();
132
127
  dateToPicker?.set('minDate', dateFromPicker?.selectedDates[0]);
133
- setSelectedDateRange('custom');
128
+ setSelectedDateRange(customOption);
134
129
 
135
130
  submit();
136
131
  };
@@ -142,7 +137,7 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
142
137
 
143
138
  selectedDates.dateTo = dateToPicker?.selectedDates[0] || new Date();
144
139
  dateFromPicker?.set('maxDate', dateToPicker?.selectedDates[0]);
145
- setSelectedDateRange('custom');
140
+ setSelectedDateRange(customOption);
146
141
 
147
142
  submit();
148
143
  };
@@ -168,14 +163,17 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
168
163
  return (
169
164
  <div class='flex flex-wrap' ref={divRef}>
170
165
  <Select
171
- items={getSelectableOptions(customSelectOptions)}
172
- selected={selectedDateRange}
166
+ items={[
167
+ ...getSelectableOptions(dateRangeOptions),
168
+ { label: customOption, value: customOption, disabled: true },
169
+ ]}
170
+ selected={selectedDateRange ?? customOption}
173
171
  selectStyle='select-bordered rounded-none flex-grow min-w-[7.5rem]'
174
172
  onChange={(event: Event) => {
175
173
  event.preventDefault();
176
174
  const select = event.target as HTMLSelectElement;
177
175
  const value = select.value as ScaleType;
178
- onSelectChange(value as CustomLabel | PresetOptionValues);
176
+ onSelectChange(value);
179
177
  }}
180
178
  />
181
179
  <div className={'flex flex-wrap flex-grow'}>
@@ -0,0 +1,65 @@
1
+ import { toYYYYMMDD } from './dateConversion';
2
+
3
+ /**
4
+ * A date range option that can be used in the `gs-date-range-selector` component.
5
+ */
6
+ export type DateRangeOption = {
7
+ /** The label of the date range option that will be shown to the user */
8
+ label: string;
9
+ /**
10
+ * The start date of the date range in the format `YYYY-MM-DD`.
11
+ * If not set, the date range selector will default to the `earliestDate` property.
12
+ */
13
+ dateFrom?: string;
14
+ /**
15
+ * The end date of the date range in the format `YYYY-MM-DD`.
16
+ * If not set, the date range selector will default to the current date.
17
+ */
18
+ dateTo?: string;
19
+ };
20
+
21
+ const today = new Date();
22
+
23
+ const twoWeeksAgo = new Date();
24
+ twoWeeksAgo.setDate(today.getDate() - 14);
25
+
26
+ const lastMonth = new Date(today);
27
+ lastMonth.setMonth(today.getMonth() - 1);
28
+
29
+ const last2Months = new Date(today);
30
+ last2Months.setMonth(today.getMonth() - 2);
31
+
32
+ const last3Months = new Date(today);
33
+ last3Months.setMonth(today.getMonth() - 3);
34
+
35
+ const last6Months = new Date(today);
36
+ last6Months.setMonth(today.getMonth() - 6);
37
+
38
+ /**
39
+ * Presets for the `gs-date-range-selector` component that can be used as `dateRangeOptions`.
40
+ */
41
+ export const dateRangeOptionPresets = {
42
+ last2Weeks: {
43
+ label: 'Last 2 weeks',
44
+ dateFrom: toYYYYMMDD(twoWeeksAgo),
45
+ },
46
+ lastMonth: {
47
+ label: 'Last month',
48
+ dateFrom: toYYYYMMDD(lastMonth),
49
+ },
50
+ last2Months: {
51
+ label: 'Last 2 months',
52
+ dateFrom: toYYYYMMDD(last2Months),
53
+ },
54
+ last3Months: {
55
+ label: 'Last 3 months',
56
+ dateFrom: toYYYYMMDD(last3Months),
57
+ },
58
+ last6Months: {
59
+ label: 'Last 6 months',
60
+ dateFrom: toYYYYMMDD(last6Months),
61
+ },
62
+ allTimes: {
63
+ label: 'All times',
64
+ },
65
+ } satisfies Record<string, DateRangeOption>;
@@ -1,79 +1,30 @@
1
- export const PRESET_VALUE_CUSTOM = 'custom';
2
- export const PRESET_VALUE_ALL_TIMES = 'allTimes';
3
- export const PRESET_VALUE_LAST_2_WEEKS = 'last2Weeks';
4
- export const PRESET_VALUE_LAST_MONTH = 'lastMonth';
5
- export const PRESET_VALUE_LAST_2_MONTHS = 'last2Months';
6
- export const PRESET_VALUE_LAST_3_MONTHS = 'last3Months';
7
- export const PRESET_VALUE_LAST_6_MONTHS = 'last6Months';
1
+ import { type DateRangeOption } from './dateRangeOption';
8
2
 
9
- export const presets = {
10
- [PRESET_VALUE_CUSTOM]: { label: 'Custom' },
11
- [PRESET_VALUE_ALL_TIMES]: { label: 'All times' },
12
- [PRESET_VALUE_LAST_2_WEEKS]: { label: 'Last 2 weeks' },
13
- [PRESET_VALUE_LAST_MONTH]: { label: 'Last month' },
14
- [PRESET_VALUE_LAST_2_MONTHS]: { label: 'Last 2 months' },
15
- [PRESET_VALUE_LAST_3_MONTHS]: { label: 'Last 3 months' },
16
- [PRESET_VALUE_LAST_6_MONTHS]: { label: 'Last 6 months' },
17
- };
18
-
19
- export type PresetOptionValues = keyof typeof presets;
20
-
21
- export type CustomSelectOption<CustomLabel extends string> = { label: CustomLabel; dateFrom: string; dateTo: string };
22
-
23
- export const getSelectableOptions = <Label extends string>(customSelectOptions: CustomSelectOption<Label>[]) => {
24
- const presetOptions = Object.entries(presets).map(([key, value]) => {
25
- return { label: value.label, value: key };
26
- });
27
-
28
- const customOptions = customSelectOptions.map((customSelectOption) => {
3
+ export const getSelectableOptions = (dateRangeOptions: DateRangeOption[]) => {
4
+ return dateRangeOptions.map((customSelectOption) => {
29
5
  return { label: customSelectOption.label, value: customSelectOption.label };
30
6
  });
31
-
32
- return [...presetOptions, ...customOptions];
33
7
  };
34
8
 
35
- export const getDatesForSelectorValue = <Label extends string>(
36
- selectorValue: string,
37
- customSelectOptions: CustomSelectOption<Label>[],
9
+ export const getDatesForSelectorValue = (
10
+ initialSelectedDateRange: string | undefined,
11
+ dateRangeOptions: DateRangeOption[],
38
12
  earliestDate: string,
39
13
  ) => {
40
14
  const today = new Date();
15
+ const defaultDates = { dateFrom: new Date(earliestDate), dateTo: today };
41
16
 
42
- const customSelectOption = customSelectOptions.find((option) => option.label === selectorValue);
43
- if (customSelectOption) {
44
- return { dateFrom: new Date(customSelectOption.dateFrom), dateTo: new Date(customSelectOption.dateTo) };
17
+ if (initialSelectedDateRange === undefined) {
18
+ return defaultDates;
45
19
  }
46
20
 
47
- switch (selectorValue) {
48
- case PRESET_VALUE_LAST_2_WEEKS: {
49
- const twoWeeksAgo = new Date(today);
50
- twoWeeksAgo.setDate(today.getDate() - 14);
51
- return { dateFrom: twoWeeksAgo, dateTo: today };
52
- }
53
- case PRESET_VALUE_LAST_MONTH: {
54
- const lastMonth = new Date(today);
55
- lastMonth.setMonth(today.getMonth() - 1);
56
- return { dateFrom: lastMonth, dateTo: today };
57
- }
58
- case PRESET_VALUE_LAST_2_MONTHS: {
59
- const twoMonthsAgo = new Date(today);
60
- twoMonthsAgo.setMonth(today.getMonth() - 2);
61
- return { dateFrom: twoMonthsAgo, dateTo: today };
62
- }
63
- case PRESET_VALUE_LAST_3_MONTHS: {
64
- const threeMonthsAgo = new Date(today);
65
- threeMonthsAgo.setMonth(today.getMonth() - 3);
66
- return { dateFrom: threeMonthsAgo, dateTo: today };
67
- }
68
- case PRESET_VALUE_LAST_6_MONTHS: {
69
- const sixMonthsAgo = new Date(today);
70
- sixMonthsAgo.setMonth(today.getMonth() - 6);
71
- return { dateFrom: sixMonthsAgo, dateTo: today };
72
- }
73
- case PRESET_VALUE_ALL_TIMES: {
74
- return { dateFrom: new Date(earliestDate), dateTo: today };
75
- }
76
- default:
77
- return { dateFrom: today, dateTo: today };
21
+ const dateRangeOption = dateRangeOptions.find((option) => option.label === initialSelectedDateRange);
22
+ if (dateRangeOption) {
23
+ return {
24
+ dateFrom: new Date(dateRangeOption.dateFrom ?? earliestDate),
25
+ dateTo: new Date(dateRangeOption.dateTo ?? today),
26
+ };
78
27
  }
28
+
29
+ return defaultDates;
79
30
  };
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
2
2
 
3
3
  import { filterMutationData } from './queryMutationData';
4
4
  import { type SubstitutionOrDeletion, type SubstitutionOrDeletionEntry } from '../../types';
5
- import { Deletion, Substitution } from '../../utils/mutations';
5
+ import { DeletionClass, SubstitutionClass } from '../../utils/mutations';
6
6
 
7
7
  const segment = 'testSegment';
8
8
  const displayedSegment = { segment, label: 'label', checked: true };
@@ -19,14 +19,14 @@ describe('filterMutationData', () => {
19
19
  case 'substitution':
20
20
  return {
21
21
  type: 'substitution',
22
- mutation: new Substitution(segment, 'A', 'B', 0),
22
+ mutation: new SubstitutionClass(segment, 'A', 'B', 0),
23
23
  count: 0,
24
24
  proportion: 0,
25
25
  };
26
26
  case 'deletion':
27
27
  return {
28
28
  type: 'deletion',
29
- mutation: new Deletion(segment, 'A', 0),
29
+ mutation: new DeletionClass(segment, 'A', 0),
30
30
  count: 0,
31
31
  proportion: 0,
32
32
  };
@@ -4,7 +4,7 @@ import { getMutationComparisonTableData } from './getMutationComparisonTableData
4
4
  import { type MutationData } from './queryMutationData';
5
5
  import { type Dataset } from '../../operator/Dataset';
6
6
  import { type SubstitutionEntry } from '../../types';
7
- import { Substitution } from '../../utils/mutations';
7
+ import { SubstitutionClass } from '../../utils/mutations';
8
8
 
9
9
  describe('getPrevalenceOverTimeTableData', () => {
10
10
  it('should flatten the data to CSV format', () => {
@@ -15,13 +15,13 @@ describe('getPrevalenceOverTimeTableData', () => {
15
15
  data: [
16
16
  {
17
17
  type: 'substitution',
18
- mutation: new Substitution(undefined, 'A', 'T', 123),
18
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 123),
19
19
  count: 1,
20
20
  proportion: 0.123,
21
21
  },
22
22
  {
23
23
  type: 'substitution',
24
- mutation: new Substitution(undefined, 'G', 'A', 234),
24
+ mutation: new SubstitutionClass(undefined, 'G', 'A', 234),
25
25
  count: 2,
26
26
  proportion: 0.567,
27
27
  },
@@ -32,13 +32,13 @@ describe('getPrevalenceOverTimeTableData', () => {
32
32
  data: [
33
33
  {
34
34
  type: 'substitution',
35
- mutation: new Substitution(undefined, 'A', 'T', 123),
35
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 123),
36
36
  count: 3,
37
37
  proportion: 0.345,
38
38
  },
39
39
  {
40
40
  type: 'substitution',
41
- mutation: new Substitution(undefined, 'G', 'A', 234),
41
+ mutation: new SubstitutionClass(undefined, 'G', 'A', 234),
42
42
  count: 4,
43
43
  proportion: 0.789,
44
44
  },
@@ -51,12 +51,12 @@ describe('getPrevalenceOverTimeTableData', () => {
51
51
 
52
52
  expect(result).toEqual([
53
53
  {
54
- mutation: new Substitution(undefined, 'A', 'T', 123),
54
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 123),
55
55
  'Test 1 prevalence': 0.123,
56
56
  'Test 2 prevalence': 0.345,
57
57
  },
58
58
  {
59
- mutation: new Substitution(undefined, 'G', 'A', 234),
59
+ mutation: new SubstitutionClass(undefined, 'G', 'A', 234),
60
60
  'Test 1 prevalence': 0.567,
61
61
  'Test 2 prevalence': 0.789,
62
62
  },
@@ -67,7 +67,7 @@ describe('getPrevalenceOverTimeTableData', () => {
67
67
  function makeSubstitutionWithProportionAtPosition(proportion: number, position: number): SubstitutionEntry {
68
68
  return {
69
69
  type: 'substitution',
70
- mutation: new Substitution(undefined, 'A', 'T', position),
70
+ mutation: new SubstitutionClass(undefined, 'A', 'T', position),
71
71
  count: 1,
72
72
  proportion,
73
73
  };
@@ -106,17 +106,17 @@ describe('getPrevalenceOverTimeTableData', () => {
106
106
 
107
107
  expect(result).toEqual([
108
108
  {
109
- mutation: new Substitution(undefined, 'A', 'T', 200),
109
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 200),
110
110
  'Test 1 prevalence': inRange,
111
111
  'Test 2 prevalence': belowRange,
112
112
  },
113
113
  {
114
- mutation: new Substitution(undefined, 'A', 'T', 300),
114
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 300),
115
115
  'Test 1 prevalence': inRange,
116
116
  'Test 2 prevalence': inRange,
117
117
  },
118
118
  {
119
- mutation: new Substitution(undefined, 'A', 'T', 400),
119
+ mutation: new SubstitutionClass(undefined, 'A', 'T', 400),
120
120
  'Test 1 prevalence': inRange,
121
121
  'Test 2 prevalence': aboveRange,
122
122
  },
@@ -1,6 +1,6 @@
1
1
  import { type MutationData } from './queryMutationData';
2
2
  import { type Dataset } from '../../operator/Dataset';
3
- import { type Deletion, type Substitution } from '../../utils/mutations';
3
+ import { type DeletionClass, type SubstitutionClass } from '../../utils/mutations';
4
4
  import { type ProportionInterval } from '../components/proportion-selector';
5
5
 
6
6
  type Proportions = {
@@ -8,7 +8,7 @@ type Proportions = {
8
8
  };
9
9
 
10
10
  type MutationComparisonRow = {
11
- mutation: Substitution | Deletion;
11
+ mutation: SubstitutionClass | DeletionClass;
12
12
  proportions: Proportions;
13
13
  };
14
14
 
@@ -47,7 +47,7 @@ export function getMutationComparisonTableData(data: Dataset<MutationData>, prop
47
47
  };
48
48
  })
49
49
  .reduce((acc, val) => ({ ...acc, ...val }), {}),
50
- } as { mutation: Substitution | Deletion } & Proportions;
50
+ } as { mutation: SubstitutionClass | DeletionClass } & Proportions;
51
51
  })
52
52
  .filter((row) =>
53
53
  Object.values(row).some(
@@ -58,7 +58,7 @@ export function getMutationComparisonTableData(data: Dataset<MutationData>, prop
58
58
  }
59
59
 
60
60
  function initializeMutationRow(
61
- mutation: Substitution | Deletion,
61
+ mutation: SubstitutionClass | DeletionClass,
62
62
  displayName: string,
63
63
  proportion: number,
64
64
  ): MutationComparisonRow {
@@ -3,7 +3,7 @@ import { type FunctionComponent } from 'preact';
3
3
  import { getMutationComparisonTableData } from './getMutationComparisonTableData';
4
4
  import { type MutationData } from './queryMutationData';
5
5
  import { type Dataset } from '../../operator/Dataset';
6
- import { type Deletion, type Substitution } from '../../utils/mutations';
6
+ import { type DeletionClass, type SubstitutionClass } from '../../utils/mutations';
7
7
  import { type ProportionInterval } from '../components/proportion-selector';
8
8
  import { Table } from '../components/table';
9
9
  import { sortSubstitutionsAndDeletions } from '../shared/sort/sortSubstitutionsAndDeletions';
@@ -26,7 +26,7 @@ export const MutationComparisonTable: FunctionComponent<MutationsTableProps> = (
26
26
  sort: {
27
27
  compare: sortSubstitutionsAndDeletions,
28
28
  },
29
- formatter: (cell: Substitution | Deletion) => cell.toString(),
29
+ formatter: (cell: SubstitutionClass | DeletionClass) => cell.toString(),
30
30
  },
31
31
  {
32
32
  name: 'Prevalence',
@@ -4,7 +4,12 @@ import { useContext, useRef, useState } from 'preact/hooks';
4
4
  import { MutationFilterInfo } from './mutation-filter-info';
5
5
  import { parseAndValidateMutation } from './parseAndValidateMutation';
6
6
  import { type ReferenceGenome } from '../../lapisApi/ReferenceGenome';
7
- import { type Deletion, type Insertion, type Mutation, type Substitution } from '../../utils/mutations';
7
+ import {
8
+ type DeletionClass,
9
+ type InsertionClass,
10
+ type MutationClass,
11
+ type SubstitutionClass,
12
+ } from '../../utils/mutations';
8
13
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
9
14
  import { ErrorBoundary } from '../components/error-boundary';
10
15
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
@@ -18,10 +23,10 @@ export interface MutationFilterProps extends MutationFilterInnerProps {
18
23
  }
19
24
 
20
25
  export type SelectedFilters = {
21
- nucleotideMutations: (Substitution | Deletion)[];
22
- aminoAcidMutations: (Substitution | Deletion)[];
23
- nucleotideInsertions: Insertion[];
24
- aminoAcidInsertions: Insertion[];
26
+ nucleotideMutations: (SubstitutionClass | DeletionClass)[];
27
+ aminoAcidMutations: (SubstitutionClass | DeletionClass)[];
28
+ nucleotideInsertions: InsertionClass[];
29
+ aminoAcidInsertions: InsertionClass[];
25
30
  };
26
31
 
27
32
  export type SelectedMutationFilterStrings = {
@@ -199,14 +204,18 @@ const SelectedMutationDisplay: FunctionComponent<{
199
204
  <SelectedNucleotideMutation
200
205
  key={mutation.toString()}
201
206
  mutation={mutation}
202
- onDelete={(mutation: Substitution | Deletion) => onSelectedRemoved(mutation, 'nucleotideMutations')}
207
+ onDelete={(mutation: SubstitutionClass | DeletionClass) =>
208
+ onSelectedRemoved(mutation, 'nucleotideMutations')
209
+ }
203
210
  />
204
211
  ))}
205
212
  {selectedFilters.aminoAcidMutations.map((mutation) => (
206
213
  <SelectedAminoAcidMutation
207
214
  key={mutation.toString()}
208
215
  mutation={mutation}
209
- onDelete={(mutation: Substitution | Deletion) => onSelectedRemoved(mutation, 'aminoAcidMutations')}
216
+ onDelete={(mutation: SubstitutionClass | DeletionClass) =>
217
+ onSelectedRemoved(mutation, 'aminoAcidMutations')
218
+ }
210
219
  />
211
220
  ))}
212
221
  {selectedFilters.nucleotideInsertions.map((insertion) => (
@@ -220,7 +229,7 @@ const SelectedMutationDisplay: FunctionComponent<{
220
229
  <SelectedAminoAcidInsertion
221
230
  key={insertion.toString()}
222
231
  insertion={insertion}
223
- onDelete={(insertion: Insertion) => onSelectedRemoved(insertion, 'aminoAcidInsertions')}
232
+ onDelete={(insertion: InsertionClass) => onSelectedRemoved(insertion, 'aminoAcidInsertions')}
224
233
  />
225
234
  ))}
226
235
  </>
@@ -228,8 +237,8 @@ const SelectedMutationDisplay: FunctionComponent<{
228
237
  };
229
238
 
230
239
  const SelectedAminoAcidInsertion: FunctionComponent<{
231
- insertion: Insertion;
232
- onDelete: (insertion: Insertion) => void;
240
+ insertion: InsertionClass;
241
+ onDelete: (insertion: InsertionClass) => void;
233
242
  }> = ({ insertion, onDelete }) => {
234
243
  const backgroundColor = singleGraphColorRGBByName('teal', 0.3);
235
244
  const textColor = singleGraphColorRGBByName('teal', 1);
@@ -244,8 +253,8 @@ const SelectedAminoAcidInsertion: FunctionComponent<{
244
253
  };
245
254
 
246
255
  const SelectedAminoAcidMutation: FunctionComponent<{
247
- mutation: Substitution | Deletion;
248
- onDelete: (mutation: Substitution | Deletion) => void;
256
+ mutation: SubstitutionClass | DeletionClass;
257
+ onDelete: (mutation: SubstitutionClass | DeletionClass) => void;
249
258
  }> = ({ mutation, onDelete }) => {
250
259
  const backgroundColor = singleGraphColorRGBByName('rose', 0.3);
251
260
  const textColor = singleGraphColorRGBByName('rose', 1);
@@ -260,8 +269,8 @@ const SelectedAminoAcidMutation: FunctionComponent<{
260
269
  };
261
270
 
262
271
  const SelectedNucleotideMutation: FunctionComponent<{
263
- mutation: Substitution | Deletion;
264
- onDelete: (insertion: Substitution | Deletion) => void;
272
+ mutation: SubstitutionClass | DeletionClass;
273
+ onDelete: (insertion: SubstitutionClass | DeletionClass) => void;
265
274
  }> = ({ mutation, onDelete }) => {
266
275
  const backgroundColor = singleGraphColorRGBByName('indigo', 0.3);
267
276
  const textColor = singleGraphColorRGBByName('indigo', 1);
@@ -276,8 +285,8 @@ const SelectedNucleotideMutation: FunctionComponent<{
276
285
  };
277
286
 
278
287
  const SelectedNucleotideInsertion: FunctionComponent<{
279
- insertion: Insertion;
280
- onDelete: (insertion: Insertion) => void;
288
+ insertion: InsertionClass;
289
+ onDelete: (insertion: InsertionClass) => void;
281
290
  }> = ({ insertion, onDelete }) => {
282
291
  const backgroundColor = singleGraphColorRGBByName('green', 0.3);
283
292
  const textColor = singleGraphColorRGBByName('green', 1);
@@ -292,14 +301,14 @@ const SelectedNucleotideInsertion: FunctionComponent<{
292
301
  );
293
302
  };
294
303
 
295
- type SelectedFilterProps<MutationType extends Mutation> = {
304
+ type SelectedFilterProps<MutationType extends MutationClass> = {
296
305
  mutation: MutationType;
297
306
  onDelete: (mutation: MutationType) => void;
298
307
  backgroundColor: string;
299
308
  textColor: string;
300
309
  };
301
310
 
302
- const SelectedFilter = <MutationType extends Mutation>({
311
+ const SelectedFilter = <MutationType extends MutationClass>({
303
312
  mutation,
304
313
  onDelete,
305
314
  backgroundColor,
@@ -1,7 +1,7 @@
1
1
  import { type SelectedFilters } from './mutation-filter';
2
2
  import { sequenceTypeFromSegment } from './sequenceTypeFromSegment';
3
3
  import type { ReferenceGenome } from '../../lapisApi/ReferenceGenome';
4
- import { Deletion, Insertion, Substitution } from '../../utils/mutations';
4
+ import { DeletionClass, InsertionClass, SubstitutionClass } from '../../utils/mutations';
5
5
 
6
6
  type ParsedMutationFilter = {
7
7
  [MutationType in keyof SelectedFilters]: { type: MutationType; value: SelectedFilters[MutationType][number] };
@@ -11,7 +11,7 @@ export const parseAndValidateMutation = (
11
11
  value: string,
12
12
  referenceGenome: ReferenceGenome,
13
13
  ): ParsedMutationFilter | null => {
14
- const possibleInsertion = Insertion.parse(value);
14
+ const possibleInsertion = InsertionClass.parse(value);
15
15
  if (possibleInsertion !== null) {
16
16
  const sequenceType = sequenceTypeFromSegment(possibleInsertion.segment, referenceGenome);
17
17
  switch (sequenceType) {
@@ -24,7 +24,7 @@ export const parseAndValidateMutation = (
24
24
  }
25
25
  }
26
26
 
27
- const possibleDeletion = Deletion.parse(value);
27
+ const possibleDeletion = DeletionClass.parse(value);
28
28
  if (possibleDeletion !== null) {
29
29
  const sequenceType = sequenceTypeFromSegment(possibleDeletion.segment, referenceGenome);
30
30
  switch (sequenceType) {
@@ -37,7 +37,7 @@ export const parseAndValidateMutation = (
37
37
  }
38
38
  }
39
39
 
40
- const possibleSubstitution = Substitution.parse(value);
40
+ const possibleSubstitution = SubstitutionClass.parse(value);
41
41
  if (possibleSubstitution !== null) {
42
42
  const sequenceType = sequenceTypeFromSegment(possibleSubstitution.segment, referenceGenome);
43
43
  switch (sequenceType) {