@genspectrum/dashboard-components 0.18.1 → 0.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +7 -7
- package/dist/{LineageFilterChangedEvent-DkvWdq_G.js → LineageFilterChangedEvent-ixHQkq8y.js} +2 -2
- package/dist/{LineageFilterChangedEvent-DkvWdq_G.js.map → LineageFilterChangedEvent-ixHQkq8y.js.map} +1 -1
- package/dist/components.d.ts +52 -50
- package/dist/components.js +106 -85
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +47 -47
- package/dist/util.js +1 -1
- package/package.json +1 -1
- package/src/preact/dateRangeFilter/computeInitialValues.spec.ts +2 -2
- package/src/preact/dateRangeFilter/computeInitialValues.ts +1 -1
- package/src/preact/dateRangeFilter/date-range-filter.stories.tsx +3 -5
- package/src/preact/dateRangeFilter/date-range-filter.tsx +12 -7
- package/src/preact/dateRangeFilter/dateRangeOption.ts +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.stories.tsx +108 -0
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.tsx +93 -0
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +7 -78
- package/src/web-components/input/gs-date-range-filter.stories.ts +1 -1
- package/src/web-components/input/gs-date-range-filter.tsx +7 -5
- package/standalone-bundle/dashboard-components.js +539 -524
- package/standalone-bundle/dashboard-components.js.map +1 -1
package/dist/util.d.ts
CHANGED
|
@@ -138,7 +138,7 @@ declare const dateRangeOptionSchema: default_2.ZodObject<{
|
|
|
138
138
|
|
|
139
139
|
export declare type DateRangeValue = default_2.infer<typeof dateRangeValueSchema>;
|
|
140
140
|
|
|
141
|
-
declare const dateRangeValueSchema: default_2.
|
|
141
|
+
declare const dateRangeValueSchema: default_2.ZodNullable<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
|
|
142
142
|
dateFrom: default_2.ZodOptional<default_2.ZodString>;
|
|
143
143
|
dateTo: default_2.ZodOptional<default_2.ZodString>;
|
|
144
144
|
}, "strip", default_2.ZodTypeAny, {
|
|
@@ -890,7 +890,7 @@ declare global {
|
|
|
890
890
|
|
|
891
891
|
declare global {
|
|
892
892
|
interface HTMLElementTagNameMap {
|
|
893
|
-
'gs-
|
|
893
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
894
894
|
}
|
|
895
895
|
}
|
|
896
896
|
|
|
@@ -898,7 +898,7 @@ declare global {
|
|
|
898
898
|
declare global {
|
|
899
899
|
namespace JSX {
|
|
900
900
|
interface IntrinsicElements {
|
|
901
|
-
'gs-
|
|
901
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
902
902
|
}
|
|
903
903
|
}
|
|
904
904
|
}
|
|
@@ -906,11 +906,7 @@ declare global {
|
|
|
906
906
|
|
|
907
907
|
declare global {
|
|
908
908
|
interface HTMLElementTagNameMap {
|
|
909
|
-
'gs-
|
|
910
|
-
}
|
|
911
|
-
interface HTMLElementEventMap {
|
|
912
|
-
'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
|
|
913
|
-
'gs-date-range-option-changed': DateRangeOptionChangedEvent;
|
|
909
|
+
'gs-mutations-component': MutationsComponent;
|
|
914
910
|
}
|
|
915
911
|
}
|
|
916
912
|
|
|
@@ -918,7 +914,7 @@ declare global {
|
|
|
918
914
|
declare global {
|
|
919
915
|
namespace JSX {
|
|
920
916
|
interface IntrinsicElements {
|
|
921
|
-
'gs-
|
|
917
|
+
'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
922
918
|
}
|
|
923
919
|
}
|
|
924
920
|
}
|
|
@@ -926,10 +922,7 @@ declare global {
|
|
|
926
922
|
|
|
927
923
|
declare global {
|
|
928
924
|
interface HTMLElementTagNameMap {
|
|
929
|
-
'gs-
|
|
930
|
-
}
|
|
931
|
-
interface HTMLElementEventMap {
|
|
932
|
-
'gs-location-changed': LocationChangedEvent;
|
|
925
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
933
926
|
}
|
|
934
927
|
}
|
|
935
928
|
|
|
@@ -937,7 +930,7 @@ declare global {
|
|
|
937
930
|
declare global {
|
|
938
931
|
namespace JSX {
|
|
939
932
|
interface IntrinsicElements {
|
|
940
|
-
'gs-
|
|
933
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
941
934
|
}
|
|
942
935
|
}
|
|
943
936
|
}
|
|
@@ -945,10 +938,7 @@ declare global {
|
|
|
945
938
|
|
|
946
939
|
declare global {
|
|
947
940
|
interface HTMLElementTagNameMap {
|
|
948
|
-
'gs-
|
|
949
|
-
}
|
|
950
|
-
interface HTMLElementEventMap {
|
|
951
|
-
'gs-text-filter-changed': TextFilterChangedEvent;
|
|
941
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
952
942
|
}
|
|
953
943
|
}
|
|
954
944
|
|
|
@@ -956,7 +946,7 @@ declare global {
|
|
|
956
946
|
declare global {
|
|
957
947
|
namespace JSX {
|
|
958
948
|
interface IntrinsicElements {
|
|
959
|
-
'gs-
|
|
949
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
960
950
|
}
|
|
961
951
|
}
|
|
962
952
|
}
|
|
@@ -964,10 +954,7 @@ declare global {
|
|
|
964
954
|
|
|
965
955
|
declare global {
|
|
966
956
|
interface HTMLElementTagNameMap {
|
|
967
|
-
'gs-
|
|
968
|
-
}
|
|
969
|
-
interface HTMLElementEventMap {
|
|
970
|
-
'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
|
|
957
|
+
'gs-aggregate': AggregateComponent;
|
|
971
958
|
}
|
|
972
959
|
}
|
|
973
960
|
|
|
@@ -975,7 +962,7 @@ declare global {
|
|
|
975
962
|
declare global {
|
|
976
963
|
namespace JSX {
|
|
977
964
|
interface IntrinsicElements {
|
|
978
|
-
'gs-
|
|
965
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
979
966
|
}
|
|
980
967
|
}
|
|
981
968
|
}
|
|
@@ -983,10 +970,7 @@ declare global {
|
|
|
983
970
|
|
|
984
971
|
declare global {
|
|
985
972
|
interface HTMLElementTagNameMap {
|
|
986
|
-
'gs-
|
|
987
|
-
}
|
|
988
|
-
interface HTMLElementEventMap {
|
|
989
|
-
'gs-lineage-filter-changed': LineageFilterChangedEvent;
|
|
973
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
990
974
|
}
|
|
991
975
|
}
|
|
992
976
|
|
|
@@ -994,7 +978,7 @@ declare global {
|
|
|
994
978
|
declare global {
|
|
995
979
|
namespace JSX {
|
|
996
980
|
interface IntrinsicElements {
|
|
997
|
-
'gs-
|
|
981
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
998
982
|
}
|
|
999
983
|
}
|
|
1000
984
|
}
|
|
@@ -1002,7 +986,7 @@ declare global {
|
|
|
1002
986
|
|
|
1003
987
|
declare global {
|
|
1004
988
|
interface HTMLElementTagNameMap {
|
|
1005
|
-
'gs-mutations-
|
|
989
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1006
990
|
}
|
|
1007
991
|
}
|
|
1008
992
|
|
|
@@ -1010,7 +994,7 @@ declare global {
|
|
|
1010
994
|
declare global {
|
|
1011
995
|
namespace JSX {
|
|
1012
996
|
interface IntrinsicElements {
|
|
1013
|
-
'gs-mutations-
|
|
997
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1014
998
|
}
|
|
1015
999
|
}
|
|
1016
1000
|
}
|
|
@@ -1018,7 +1002,7 @@ declare global {
|
|
|
1018
1002
|
|
|
1019
1003
|
declare global {
|
|
1020
1004
|
interface HTMLElementTagNameMap {
|
|
1021
|
-
'gs-
|
|
1005
|
+
'gs-statistics': StatisticsComponent;
|
|
1022
1006
|
}
|
|
1023
1007
|
}
|
|
1024
1008
|
|
|
@@ -1026,7 +1010,7 @@ declare global {
|
|
|
1026
1010
|
declare global {
|
|
1027
1011
|
namespace JSX {
|
|
1028
1012
|
interface IntrinsicElements {
|
|
1029
|
-
'gs-
|
|
1013
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1030
1014
|
}
|
|
1031
1015
|
}
|
|
1032
1016
|
}
|
|
@@ -1034,7 +1018,7 @@ declare global {
|
|
|
1034
1018
|
|
|
1035
1019
|
declare global {
|
|
1036
1020
|
interface HTMLElementTagNameMap {
|
|
1037
|
-
'gs-
|
|
1021
|
+
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
1038
1022
|
}
|
|
1039
1023
|
}
|
|
1040
1024
|
|
|
@@ -1042,7 +1026,7 @@ declare global {
|
|
|
1042
1026
|
declare global {
|
|
1043
1027
|
namespace JSX {
|
|
1044
1028
|
interface IntrinsicElements {
|
|
1045
|
-
'gs-
|
|
1029
|
+
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1046
1030
|
}
|
|
1047
1031
|
}
|
|
1048
1032
|
}
|
|
@@ -1050,7 +1034,11 @@ declare global {
|
|
|
1050
1034
|
|
|
1051
1035
|
declare global {
|
|
1052
1036
|
interface HTMLElementTagNameMap {
|
|
1053
|
-
'gs-
|
|
1037
|
+
'gs-date-range-filter': DateRangeFilterComponent;
|
|
1038
|
+
}
|
|
1039
|
+
interface HTMLElementEventMap {
|
|
1040
|
+
'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
|
|
1041
|
+
'gs-date-range-option-changed': DateRangeOptionChangedEvent;
|
|
1054
1042
|
}
|
|
1055
1043
|
}
|
|
1056
1044
|
|
|
@@ -1058,7 +1046,7 @@ declare global {
|
|
|
1058
1046
|
declare global {
|
|
1059
1047
|
namespace JSX {
|
|
1060
1048
|
interface IntrinsicElements {
|
|
1061
|
-
'gs-
|
|
1049
|
+
'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1062
1050
|
}
|
|
1063
1051
|
}
|
|
1064
1052
|
}
|
|
@@ -1066,7 +1054,10 @@ declare global {
|
|
|
1066
1054
|
|
|
1067
1055
|
declare global {
|
|
1068
1056
|
interface HTMLElementTagNameMap {
|
|
1069
|
-
'gs-
|
|
1057
|
+
'gs-location-filter': LocationFilterComponent;
|
|
1058
|
+
}
|
|
1059
|
+
interface HTMLElementEventMap {
|
|
1060
|
+
'gs-location-changed': LocationChangedEvent;
|
|
1070
1061
|
}
|
|
1071
1062
|
}
|
|
1072
1063
|
|
|
@@ -1074,7 +1065,7 @@ declare global {
|
|
|
1074
1065
|
declare global {
|
|
1075
1066
|
namespace JSX {
|
|
1076
1067
|
interface IntrinsicElements {
|
|
1077
|
-
'gs-
|
|
1068
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1078
1069
|
}
|
|
1079
1070
|
}
|
|
1080
1071
|
}
|
|
@@ -1082,7 +1073,10 @@ declare global {
|
|
|
1082
1073
|
|
|
1083
1074
|
declare global {
|
|
1084
1075
|
interface HTMLElementTagNameMap {
|
|
1085
|
-
'gs-
|
|
1076
|
+
'gs-text-filter': TextFilterComponent;
|
|
1077
|
+
}
|
|
1078
|
+
interface HTMLElementEventMap {
|
|
1079
|
+
'gs-text-filter-changed': TextFilterChangedEvent;
|
|
1086
1080
|
}
|
|
1087
1081
|
}
|
|
1088
1082
|
|
|
@@ -1090,7 +1084,7 @@ declare global {
|
|
|
1090
1084
|
declare global {
|
|
1091
1085
|
namespace JSX {
|
|
1092
1086
|
interface IntrinsicElements {
|
|
1093
|
-
'gs-
|
|
1087
|
+
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1094
1088
|
}
|
|
1095
1089
|
}
|
|
1096
1090
|
}
|
|
@@ -1098,7 +1092,10 @@ declare global {
|
|
|
1098
1092
|
|
|
1099
1093
|
declare global {
|
|
1100
1094
|
interface HTMLElementTagNameMap {
|
|
1101
|
-
'gs-
|
|
1095
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
1096
|
+
}
|
|
1097
|
+
interface HTMLElementEventMap {
|
|
1098
|
+
'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
|
|
1102
1099
|
}
|
|
1103
1100
|
}
|
|
1104
1101
|
|
|
@@ -1106,7 +1103,7 @@ declare global {
|
|
|
1106
1103
|
declare global {
|
|
1107
1104
|
namespace JSX {
|
|
1108
1105
|
interface IntrinsicElements {
|
|
1109
|
-
'gs-
|
|
1106
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1110
1107
|
}
|
|
1111
1108
|
}
|
|
1112
1109
|
}
|
|
@@ -1114,7 +1111,10 @@ declare global {
|
|
|
1114
1111
|
|
|
1115
1112
|
declare global {
|
|
1116
1113
|
interface HTMLElementTagNameMap {
|
|
1117
|
-
'gs-
|
|
1114
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1115
|
+
}
|
|
1116
|
+
interface HTMLElementEventMap {
|
|
1117
|
+
'gs-lineage-filter-changed': LineageFilterChangedEvent;
|
|
1118
1118
|
}
|
|
1119
1119
|
}
|
|
1120
1120
|
|
|
@@ -1122,7 +1122,7 @@ declare global {
|
|
|
1122
1122
|
declare global {
|
|
1123
1123
|
namespace JSX {
|
|
1124
1124
|
interface IntrinsicElements {
|
|
1125
|
-
'gs-
|
|
1125
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1126
1126
|
}
|
|
1127
1127
|
}
|
|
1128
1128
|
}
|
|
@@ -1130,7 +1130,7 @@ declare global {
|
|
|
1130
1130
|
|
|
1131
1131
|
declare global {
|
|
1132
1132
|
interface HTMLElementTagNameMap {
|
|
1133
|
-
'gs-
|
|
1133
|
+
'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
|
|
1134
1134
|
}
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
@@ -1138,7 +1138,7 @@ declare global {
|
|
|
1138
1138
|
declare global {
|
|
1139
1139
|
namespace JSX {
|
|
1140
1140
|
interface IntrinsicElements {
|
|
1141
|
-
'gs-
|
|
1141
|
+
'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1142
1142
|
}
|
|
1143
1143
|
}
|
|
1144
1144
|
}
|
package/dist/util.js
CHANGED
package/package.json
CHANGED
|
@@ -18,8 +18,8 @@ const dateRangeOptions = [
|
|
|
18
18
|
];
|
|
19
19
|
|
|
20
20
|
describe('computeInitialValues', () => {
|
|
21
|
-
it('should return undefined for
|
|
22
|
-
const result = computeInitialValues(
|
|
21
|
+
it('should return undefined for null value', () => {
|
|
22
|
+
const result = computeInitialValues(null, earliestDate, dateRangeOptions);
|
|
23
23
|
|
|
24
24
|
expect(result).toBeUndefined();
|
|
25
25
|
});
|
|
@@ -3,7 +3,7 @@ import { getDatesForSelectorValue, getSelectableOptions } from './selectableOpti
|
|
|
3
3
|
import { UserFacingError } from '../components/error-display';
|
|
4
4
|
|
|
5
5
|
export function computeInitialValues(value: DateRangeValue, earliestDate: string, dateRangeOptions: DateRangeOption[]) {
|
|
6
|
-
if (value ===
|
|
6
|
+
if (value === null) {
|
|
7
7
|
return undefined;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -56,7 +56,7 @@ const meta: Meta<DateRangeFilterProps> = {
|
|
|
56
56
|
args: {
|
|
57
57
|
dateRangeOptions: [dateRangeOptionPresets.lastMonth, dateRangeOptionPresets.allTimes, customDateRange],
|
|
58
58
|
earliestDate,
|
|
59
|
-
value:
|
|
59
|
+
value: null,
|
|
60
60
|
lapisDateField: 'aDateColumn',
|
|
61
61
|
width: '100%',
|
|
62
62
|
placeholder,
|
|
@@ -194,16 +194,14 @@ export const ChangingTheValueProgrammatically: StoryObj<DateRangeFilterProps> =
|
|
|
194
194
|
...Primary,
|
|
195
195
|
render: (args) => {
|
|
196
196
|
const StatefulWrapper = () => {
|
|
197
|
-
const [value, setValue] = useState<DateRangeValue
|
|
197
|
+
const [value, setValue] = useState<DateRangeValue>('Last month');
|
|
198
198
|
const ref = useRef<HTMLDivElement>(null);
|
|
199
199
|
|
|
200
200
|
useEffect(() => {
|
|
201
201
|
ref.current?.addEventListener('gs-date-range-option-changed', (event) => {
|
|
202
|
-
|
|
203
|
-
setValue(newValue ?? undefined);
|
|
202
|
+
setValue(event.detail);
|
|
204
203
|
});
|
|
205
204
|
}, []);
|
|
206
|
-
|
|
207
205
|
return (
|
|
208
206
|
<div ref={ref}>
|
|
209
207
|
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
@@ -179,13 +179,18 @@ export const DateRangeFilterInner = ({
|
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
const fireOptionChangedEvent = (state: DateRangeFilterState) => {
|
|
182
|
-
const eventDetail =
|
|
183
|
-
state
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
182
|
+
const eventDetail = (() => {
|
|
183
|
+
if (state === null) {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
if (state.label === customOption) {
|
|
187
|
+
return {
|
|
188
|
+
dateFrom: state.dateFrom !== undefined ? toYYYYMMDD(state.dateFrom) : undefined,
|
|
189
|
+
dateTo: state.dateTo !== undefined ? toYYYYMMDD(state.dateTo) : undefined,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return state.label;
|
|
193
|
+
})();
|
|
189
194
|
|
|
190
195
|
divRef.current?.dispatchEvent(new DateRangeOptionChangedEvent(eventDetail));
|
|
191
196
|
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type Meta, type StoryObj } from '@storybook/preact';
|
|
2
|
+
import { expect, within } from '@storybook/test';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
MutationsOverTimeGridTooltip,
|
|
6
|
+
type MutationsOverTimeGridTooltipProps,
|
|
7
|
+
} from './mutations-over-time-grid-tooltip';
|
|
8
|
+
|
|
9
|
+
const meta: Meta<MutationsOverTimeGridTooltipProps> = {
|
|
10
|
+
title: 'Component/Mutation over time grid tooltip',
|
|
11
|
+
component: MutationsOverTimeGridTooltip,
|
|
12
|
+
argTypes: {
|
|
13
|
+
mutation: { control: 'object' },
|
|
14
|
+
date: { control: 'object' },
|
|
15
|
+
value: { control: 'object' },
|
|
16
|
+
},
|
|
17
|
+
parameters: {
|
|
18
|
+
fetchMock: {},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
const Template: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
25
|
+
render: (args: MutationsOverTimeGridTooltipProps) => <MutationsOverTimeGridTooltip {...args} />,
|
|
26
|
+
args: {
|
|
27
|
+
mutation: {
|
|
28
|
+
type: 'deletion',
|
|
29
|
+
position: 500,
|
|
30
|
+
code: 'A500-',
|
|
31
|
+
valueAtReference: 'A',
|
|
32
|
+
},
|
|
33
|
+
date: {
|
|
34
|
+
type: 'Year',
|
|
35
|
+
year: 2025,
|
|
36
|
+
dateString: '2025',
|
|
37
|
+
},
|
|
38
|
+
value: null,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const NoValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
43
|
+
...Template,
|
|
44
|
+
play: async ({ canvasElement }) => {
|
|
45
|
+
const canvas = within(canvasElement);
|
|
46
|
+
|
|
47
|
+
await expect(canvas.getByText('2025', { exact: true })).toBeVisible();
|
|
48
|
+
await expect(canvas.getByText('(2025-01-01 - 2025-12-31)')).toBeVisible();
|
|
49
|
+
await expect(canvas.getByText('A500-')).toBeVisible();
|
|
50
|
+
await expect(canvas.getByText('No data')).toBeVisible();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const WithValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
55
|
+
...Template,
|
|
56
|
+
args: {
|
|
57
|
+
...Template.args,
|
|
58
|
+
value: {
|
|
59
|
+
type: 'value',
|
|
60
|
+
proportion: 0.5,
|
|
61
|
+
count: 100,
|
|
62
|
+
totalCount: 300,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
play: async ({ canvasElement }) => {
|
|
66
|
+
const canvas = within(canvasElement);
|
|
67
|
+
|
|
68
|
+
await expect(canvas.getByText('Proportion: 50.00%')).toBeVisible();
|
|
69
|
+
await expect(canvas.getByText('300 samples are in the timeframe')).toBeVisible();
|
|
70
|
+
await expect(canvas.getByText('200 have coverage, of those 100 have the mutation')).toBeVisible();
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const WithValueBelowThreshold: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
75
|
+
...Template,
|
|
76
|
+
args: {
|
|
77
|
+
...Template.args,
|
|
78
|
+
value: {
|
|
79
|
+
type: 'belowThreshold',
|
|
80
|
+
totalCount: 300,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
play: async ({ canvasElement }) => {
|
|
84
|
+
const canvas = within(canvasElement);
|
|
85
|
+
|
|
86
|
+
await expect(canvas.getByText('Proportion: <0.10%')).toBeVisible();
|
|
87
|
+
await expect(canvas.getByText('300 samples are in the timeframe')).toBeVisible();
|
|
88
|
+
await expect(canvas.getByText('none or less than 0.10% have the mutation')).toBeVisible();
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const WithWastewaterValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
93
|
+
...Template,
|
|
94
|
+
args: {
|
|
95
|
+
...Template.args,
|
|
96
|
+
value: {
|
|
97
|
+
type: 'wastewaterValue',
|
|
98
|
+
proportion: 0.5,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
play: async ({ canvasElement }) => {
|
|
102
|
+
const canvas = within(canvasElement);
|
|
103
|
+
|
|
104
|
+
await expect(canvas.getByText('Proportion: 50.00%')).toBeVisible();
|
|
105
|
+
await expect(canvas.queryByText('samples are in the timeframe')).not.toBeInTheDocument();
|
|
106
|
+
await expect(canvas.queryByText('have coverage')).not.toBeInTheDocument();
|
|
107
|
+
},
|
|
108
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { FunctionComponent } from 'preact';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type MutationOverTimeMutationValue,
|
|
5
|
+
MUTATIONS_OVER_TIME_MIN_PROPORTION,
|
|
6
|
+
} from '../../query/queryMutationsOverTime';
|
|
7
|
+
import type { Deletion, Substitution } from '../../utils/mutations';
|
|
8
|
+
import { type Temporal, type TemporalClass, toTemporalClass, YearMonthDayClass } from '../../utils/temporalClass';
|
|
9
|
+
import { formatProportion } from '../shared/table/formatProportion';
|
|
10
|
+
|
|
11
|
+
export type MutationsOverTimeGridTooltipProps = {
|
|
12
|
+
mutation: Substitution | Deletion;
|
|
13
|
+
date: Temporal;
|
|
14
|
+
value: MutationOverTimeMutationValue;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const MutationsOverTimeGridTooltip: FunctionComponent<MutationsOverTimeGridTooltipProps> = ({
|
|
18
|
+
mutation,
|
|
19
|
+
date,
|
|
20
|
+
value,
|
|
21
|
+
}: MutationsOverTimeGridTooltipProps) => {
|
|
22
|
+
const dateClass = toTemporalClass(date);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<p>
|
|
27
|
+
<span className='font-bold'>{dateClass.englishName()}</span>
|
|
28
|
+
</p>
|
|
29
|
+
<p>({timeIntervalDisplay(dateClass)})</p>
|
|
30
|
+
<p>{mutation.code}</p>
|
|
31
|
+
<TooltipValueDescription value={value} />
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const TooltipValueDescription: FunctionComponent<{ value: MutationOverTimeMutationValue }> = ({ value }) => {
|
|
37
|
+
if (value === null) {
|
|
38
|
+
return <p>No data</p>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const proportion =
|
|
42
|
+
value.type === 'belowThreshold'
|
|
43
|
+
? `<${formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)}`
|
|
44
|
+
: formatProportion(value.proportion);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<p>Proportion: {proportion}</p>
|
|
49
|
+
<TooltipValueCountsDescription value={value} />
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const TooltipValueCountsDescription: FunctionComponent<{
|
|
55
|
+
value: NonNullable<MutationOverTimeMutationValue>;
|
|
56
|
+
}> = ({ value }) => {
|
|
57
|
+
switch (value.type) {
|
|
58
|
+
case 'wastewaterValue':
|
|
59
|
+
return;
|
|
60
|
+
case 'belowThreshold':
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
<p>{value.totalCount} samples are in the timeframe</p>
|
|
64
|
+
<p>none or less than {formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)} have the mutation</p>
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
case 'value':
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<p>{value.totalCount} samples are in the timeframe</p>
|
|
71
|
+
<p>
|
|
72
|
+
{totalCountWithCoverage(value.count, value.proportion)} have coverage, of those {value.count}{' '}
|
|
73
|
+
have the mutation
|
|
74
|
+
</p>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function totalCountWithCoverage(count: number, proportion: number) {
|
|
81
|
+
if (count === 0) {
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
return Math.round(count / proportion);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const timeIntervalDisplay = (date: TemporalClass) => {
|
|
88
|
+
if (date instanceof YearMonthDayClass) {
|
|
89
|
+
return date.toString();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
|
|
93
|
+
};
|