@genspectrum/dashboard-components 0.18.2 → 0.18.3
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 +2 -2
- package/dist/assets/{mutationOverTimeWorker-ChQTFL68.js.map → mutationOverTimeWorker--b8ZHlji.js.map} +1 -1
- package/dist/components.d.ts +16 -287
- package/dist/components.js +114 -39
- package/dist/components.js.map +1 -1
- package/dist/style.css +2 -2
- package/dist/util.d.ts +24 -291
- package/package.json +3 -3
- package/src/preact/MutationAnnotationsContext.spec.tsx +103 -34
- package/src/preact/MutationAnnotationsContext.tsx +49 -7
- package/src/preact/components/annotated-mutation.stories.tsx +0 -5
- package/src/preact/components/annotated-mutation.tsx +6 -2
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -1
- package/src/preact/mutations/mutations.stories.tsx +4 -1
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +3 -1
- package/src/preact/sequencesByLocation/leafletStyleModifications.css +5 -0
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +25 -0
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +65 -13
- package/src/web-components/MutationAnnotations.mdx +8 -0
- package/src/web-components/gs-app.stories.ts +2 -0
- package/src/web-components/gs-app.ts +4 -2
- package/src/web-components/mutation-annotations-context.ts +6 -2
- package/standalone-bundle/assets/mutationOverTimeWorker-jChgWnwp.js.map +1 -1
- package/standalone-bundle/dashboard-components.js +5699 -5643
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
package/dist/util.d.ts
CHANGED
|
@@ -208,40 +208,52 @@ declare const mutationAnnotationSchema: default_2.ZodObject<{
|
|
|
208
208
|
name: default_2.ZodString;
|
|
209
209
|
description: default_2.ZodString;
|
|
210
210
|
symbol: default_2.ZodString;
|
|
211
|
-
nucleotideMutations: default_2.ZodArray<default_2.ZodString, "many"
|
|
212
|
-
|
|
211
|
+
nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
212
|
+
nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
213
|
+
aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
214
|
+
aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
213
215
|
}, "strip", default_2.ZodTypeAny, {
|
|
214
216
|
symbol: string;
|
|
215
217
|
name: string;
|
|
216
218
|
description: string;
|
|
217
|
-
nucleotideMutations
|
|
218
|
-
|
|
219
|
+
nucleotideMutations?: string[] | undefined;
|
|
220
|
+
nucleotidePositions?: string[] | undefined;
|
|
221
|
+
aminoAcidMutations?: string[] | undefined;
|
|
222
|
+
aminoAcidPositions?: string[] | undefined;
|
|
219
223
|
}, {
|
|
220
224
|
symbol: string;
|
|
221
225
|
name: string;
|
|
222
226
|
description: string;
|
|
223
|
-
nucleotideMutations
|
|
224
|
-
|
|
227
|
+
nucleotideMutations?: string[] | undefined;
|
|
228
|
+
nucleotidePositions?: string[] | undefined;
|
|
229
|
+
aminoAcidMutations?: string[] | undefined;
|
|
230
|
+
aminoAcidPositions?: string[] | undefined;
|
|
225
231
|
}>;
|
|
226
232
|
|
|
227
233
|
declare const mutationAnnotationsSchema: default_2.ZodArray<default_2.ZodObject<{
|
|
228
234
|
name: default_2.ZodString;
|
|
229
235
|
description: default_2.ZodString;
|
|
230
236
|
symbol: default_2.ZodString;
|
|
231
|
-
nucleotideMutations: default_2.ZodArray<default_2.ZodString, "many"
|
|
232
|
-
|
|
237
|
+
nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
238
|
+
nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
239
|
+
aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
240
|
+
aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
|
|
233
241
|
}, "strip", default_2.ZodTypeAny, {
|
|
234
242
|
symbol: string;
|
|
235
243
|
name: string;
|
|
236
244
|
description: string;
|
|
237
|
-
nucleotideMutations
|
|
238
|
-
|
|
245
|
+
nucleotideMutations?: string[] | undefined;
|
|
246
|
+
nucleotidePositions?: string[] | undefined;
|
|
247
|
+
aminoAcidMutations?: string[] | undefined;
|
|
248
|
+
aminoAcidPositions?: string[] | undefined;
|
|
239
249
|
}, {
|
|
240
250
|
symbol: string;
|
|
241
251
|
name: string;
|
|
242
252
|
description: string;
|
|
243
|
-
nucleotideMutations
|
|
244
|
-
|
|
253
|
+
nucleotideMutations?: string[] | undefined;
|
|
254
|
+
nucleotidePositions?: string[] | undefined;
|
|
255
|
+
aminoAcidMutations?: string[] | undefined;
|
|
256
|
+
aminoAcidPositions?: string[] | undefined;
|
|
245
257
|
}>, "many">;
|
|
246
258
|
|
|
247
259
|
export declare type MutationComparisonProps = default_2.infer<typeof mutationComparisonPropsSchema>;
|
|
@@ -865,285 +877,6 @@ declare const yAxisMaxConfigSchema: default_2.ZodObject<{
|
|
|
865
877
|
export { }
|
|
866
878
|
|
|
867
879
|
|
|
868
|
-
declare global {
|
|
869
|
-
interface HTMLElementEventMap {
|
|
870
|
-
'gs-error': ErrorEvent;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
declare global {
|
|
876
|
-
interface HTMLElementTagNameMap {
|
|
877
|
-
'gs-app': AppComponent;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
declare global {
|
|
883
|
-
namespace JSX {
|
|
884
|
-
interface IntrinsicElements {
|
|
885
|
-
'gs-app': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
declare global {
|
|
892
|
-
interface HTMLElementTagNameMap {
|
|
893
|
-
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
declare global {
|
|
899
|
-
namespace JSX {
|
|
900
|
-
interface IntrinsicElements {
|
|
901
|
-
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
declare global {
|
|
908
|
-
interface HTMLElementTagNameMap {
|
|
909
|
-
'gs-mutations-component': MutationsComponent;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
declare global {
|
|
915
|
-
namespace JSX {
|
|
916
|
-
interface IntrinsicElements {
|
|
917
|
-
'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
declare global {
|
|
924
|
-
interface HTMLElementTagNameMap {
|
|
925
|
-
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
declare global {
|
|
931
|
-
namespace JSX {
|
|
932
|
-
interface IntrinsicElements {
|
|
933
|
-
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
declare global {
|
|
940
|
-
interface HTMLElementTagNameMap {
|
|
941
|
-
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
declare global {
|
|
947
|
-
namespace JSX {
|
|
948
|
-
interface IntrinsicElements {
|
|
949
|
-
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
declare global {
|
|
956
|
-
interface HTMLElementTagNameMap {
|
|
957
|
-
'gs-aggregate': AggregateComponent;
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
declare global {
|
|
963
|
-
namespace JSX {
|
|
964
|
-
interface IntrinsicElements {
|
|
965
|
-
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
declare global {
|
|
972
|
-
interface HTMLElementTagNameMap {
|
|
973
|
-
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
declare global {
|
|
979
|
-
namespace JSX {
|
|
980
|
-
interface IntrinsicElements {
|
|
981
|
-
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
declare global {
|
|
988
|
-
interface HTMLElementTagNameMap {
|
|
989
|
-
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
declare global {
|
|
995
|
-
namespace JSX {
|
|
996
|
-
interface IntrinsicElements {
|
|
997
|
-
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
declare global {
|
|
1004
|
-
interface HTMLElementTagNameMap {
|
|
1005
|
-
'gs-statistics': StatisticsComponent;
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
declare global {
|
|
1011
|
-
namespace JSX {
|
|
1012
|
-
interface IntrinsicElements {
|
|
1013
|
-
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
declare global {
|
|
1020
|
-
interface HTMLElementTagNameMap {
|
|
1021
|
-
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
declare global {
|
|
1027
|
-
namespace JSX {
|
|
1028
|
-
interface IntrinsicElements {
|
|
1029
|
-
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
declare global {
|
|
1036
|
-
interface HTMLElementTagNameMap {
|
|
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;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
declare global {
|
|
1047
|
-
namespace JSX {
|
|
1048
|
-
interface IntrinsicElements {
|
|
1049
|
-
'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
declare global {
|
|
1056
|
-
interface HTMLElementTagNameMap {
|
|
1057
|
-
'gs-location-filter': LocationFilterComponent;
|
|
1058
|
-
}
|
|
1059
|
-
interface HTMLElementEventMap {
|
|
1060
|
-
'gs-location-changed': LocationChangedEvent;
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
declare global {
|
|
1066
|
-
namespace JSX {
|
|
1067
|
-
interface IntrinsicElements {
|
|
1068
|
-
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
declare global {
|
|
1075
|
-
interface HTMLElementTagNameMap {
|
|
1076
|
-
'gs-text-filter': TextFilterComponent;
|
|
1077
|
-
}
|
|
1078
|
-
interface HTMLElementEventMap {
|
|
1079
|
-
'gs-text-filter-changed': TextFilterChangedEvent;
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
declare global {
|
|
1085
|
-
namespace JSX {
|
|
1086
|
-
interface IntrinsicElements {
|
|
1087
|
-
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
declare global {
|
|
1094
|
-
interface HTMLElementTagNameMap {
|
|
1095
|
-
'gs-mutation-filter': MutationFilterComponent;
|
|
1096
|
-
}
|
|
1097
|
-
interface HTMLElementEventMap {
|
|
1098
|
-
'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
declare global {
|
|
1104
|
-
namespace JSX {
|
|
1105
|
-
interface IntrinsicElements {
|
|
1106
|
-
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
declare global {
|
|
1113
|
-
interface HTMLElementTagNameMap {
|
|
1114
|
-
'gs-lineage-filter': LineageFilterComponent;
|
|
1115
|
-
}
|
|
1116
|
-
interface HTMLElementEventMap {
|
|
1117
|
-
'gs-lineage-filter-changed': LineageFilterChangedEvent;
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
declare global {
|
|
1123
|
-
namespace JSX {
|
|
1124
|
-
interface IntrinsicElements {
|
|
1125
|
-
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
declare global {
|
|
1132
|
-
interface HTMLElementTagNameMap {
|
|
1133
|
-
'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
declare global {
|
|
1139
|
-
namespace JSX {
|
|
1140
|
-
interface IntrinsicElements {
|
|
1141
|
-
'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
880
|
declare module 'chart.js' {
|
|
1148
881
|
interface CartesianScaleTypeRegistry {
|
|
1149
882
|
logit: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genspectrum/dashboard-components",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "GenSpectrum web components for building dashboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"@storybook/preact": "^8.0.9",
|
|
113
113
|
"@storybook/preact-vite": "^8.0.9",
|
|
114
114
|
"@storybook/test": "^8.0.0",
|
|
115
|
-
"@storybook/test-runner": "^0.
|
|
115
|
+
"@storybook/test-runner": "^0.22.0",
|
|
116
116
|
"@storybook/types": "^8.0.9",
|
|
117
117
|
"@storybook/web-components": "^8.0.9",
|
|
118
118
|
"@storybook/web-components-vite": "^8.0.9",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"storybook": "^8.0.9",
|
|
144
144
|
"storybook-addon-fetch-mock": "^2.0.0",
|
|
145
145
|
"tailwindcss": "^4.0.9",
|
|
146
|
-
"typescript": "
|
|
146
|
+
"typescript": "^5.8.2",
|
|
147
147
|
"vite": "^6.0.3",
|
|
148
148
|
"vite-plugin-dts": "^4.0.3",
|
|
149
149
|
"vitest": "^3.0.2"
|
|
@@ -3,56 +3,125 @@ import { type FunctionalComponent } from 'preact';
|
|
|
3
3
|
import { describe, expect, it } from 'vitest';
|
|
4
4
|
|
|
5
5
|
import { MutationAnnotationsContextProvider, useMutationAnnotationsProvider } from './MutationAnnotationsContext';
|
|
6
|
+
import { SubstitutionClass } from '../utils/mutations';
|
|
6
7
|
import { type MutationAnnotations } from '../web-components/mutation-annotations-context';
|
|
7
8
|
|
|
8
9
|
describe('useMutationAnnotation', () => {
|
|
9
|
-
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
nucleotideMutations: ['A123', 'A456'],
|
|
15
|
-
aminoAcidMutations: ['B123'],
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
name: 'Annotation 2',
|
|
19
|
-
description: 'Description 2',
|
|
20
|
-
symbol: 'A2',
|
|
21
|
-
nucleotideMutations: ['A456', 'A789'],
|
|
22
|
-
aminoAcidMutations: ['B456', 'B789'],
|
|
23
|
-
},
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const wrapper: FunctionalComponent = ({ children }) => (
|
|
27
|
-
<MutationAnnotationsContextProvider value={mockAnnotations}>{children}</MutationAnnotationsContextProvider>
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
function renderAnnotationsHook() {
|
|
10
|
+
function renderAnnotationsHook(mockAnnotations: MutationAnnotations) {
|
|
11
|
+
const wrapper: FunctionalComponent = ({ children }) => (
|
|
12
|
+
<MutationAnnotationsContextProvider value={mockAnnotations}>{children}</MutationAnnotationsContextProvider>
|
|
13
|
+
);
|
|
14
|
+
|
|
31
15
|
const { result } = renderHook(() => useMutationAnnotationsProvider(), { wrapper });
|
|
32
16
|
return result.current;
|
|
33
17
|
}
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
const
|
|
19
|
+
describe('annotations for nucleotide mutations', () => {
|
|
20
|
+
const mockAnnotations: MutationAnnotations = [
|
|
21
|
+
{
|
|
22
|
+
name: 'Annotation 1',
|
|
23
|
+
description: 'Description 1',
|
|
24
|
+
symbol: 'A1',
|
|
25
|
+
nucleotideMutations: ['A123', 'A456'],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'Annotation 2',
|
|
29
|
+
description: 'Description 2',
|
|
30
|
+
symbol: 'A2',
|
|
31
|
+
nucleotideMutations: ['A456', 'A789'],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
it('should return the correct annotation for a given mutation', () => {
|
|
36
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123')!, 'nucleotide');
|
|
37
|
+
|
|
38
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
39
|
+
});
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
it('should return the correct annotations if multiple contain a mutation', () => {
|
|
42
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A456')!, 'nucleotide');
|
|
43
|
+
|
|
44
|
+
expect(result).toEqual([mockAnnotations[0], mockAnnotations[1]]);
|
|
45
|
+
});
|
|
39
46
|
});
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
const
|
|
48
|
+
describe('annotations for amino acid mutations', () => {
|
|
49
|
+
const mockAnnotations: MutationAnnotations = [
|
|
50
|
+
{
|
|
51
|
+
name: 'Annotation 1',
|
|
52
|
+
description: 'Description 1',
|
|
53
|
+
symbol: 'A1',
|
|
54
|
+
aminoAcidMutations: ['B456', 'B789'],
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
it('should return the correct mutation annotation for a given mutations', () => {
|
|
59
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('B456')!, 'amino acid');
|
|
43
60
|
|
|
44
|
-
|
|
61
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
62
|
+
});
|
|
45
63
|
});
|
|
46
64
|
|
|
47
|
-
|
|
48
|
-
const
|
|
65
|
+
describe('annotations for nucleotide positions', () => {
|
|
66
|
+
const mockAnnotations: MutationAnnotations = [
|
|
67
|
+
{
|
|
68
|
+
name: 'Annotation 1',
|
|
69
|
+
description: 'Description 1',
|
|
70
|
+
symbol: 'A1',
|
|
71
|
+
nucleotideMutations: ['A321T', 'A432T'],
|
|
72
|
+
nucleotidePositions: ['321', '543'],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Annotation 2',
|
|
76
|
+
description: 'Description 2',
|
|
77
|
+
symbol: 'A2',
|
|
78
|
+
nucleotidePositions: ['432'],
|
|
79
|
+
},
|
|
80
|
+
];
|
|
49
81
|
|
|
50
|
-
|
|
82
|
+
it('should return the correct mutation annotation covered by position only', () => {
|
|
83
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A543T')!, 'nucleotide');
|
|
84
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return the correct mutation annotation covered both by position and mutation', () => {
|
|
88
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A321T')!, 'nucleotide');
|
|
89
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should return both annotations if one matches the mutations and the other the position', () => {
|
|
93
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A432T')!, 'nucleotide');
|
|
94
|
+
expect(result).toEqual([mockAnnotations[1], mockAnnotations[0]]);
|
|
95
|
+
});
|
|
51
96
|
});
|
|
52
97
|
|
|
53
|
-
|
|
54
|
-
const
|
|
98
|
+
describe('annotations for amino acid positions', () => {
|
|
99
|
+
const mockAnnotations: MutationAnnotations = [
|
|
100
|
+
{
|
|
101
|
+
name: 'Annotation 1',
|
|
102
|
+
description: 'Description 1',
|
|
103
|
+
symbol: 'A1',
|
|
104
|
+
aminoAcidMutations: ['Gene:B321C', 'Gene:B432G'],
|
|
105
|
+
aminoAcidPositions: ['Gene:432', 'Gene:543'],
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
it('should return the correct mutation annotation covered both by position and mutation', () => {
|
|
110
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('Gene:B432G')!, 'amino acid');
|
|
111
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should return the correct mutation annotation covered both by position only', () => {
|
|
115
|
+
const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('Gene:B543G')!, 'amino acid');
|
|
116
|
+
expect(result).toEqual([mockAnnotations[0]]);
|
|
117
|
+
});
|
|
55
118
|
|
|
56
|
-
|
|
119
|
+
it('should return no mutation annotation for an amino acid position of wrong gene', () => {
|
|
120
|
+
const result = renderAnnotationsHook(mockAnnotations)(
|
|
121
|
+
SubstitutionClass.parse('NotTheGene:B543G')!,
|
|
122
|
+
'amino acid',
|
|
123
|
+
);
|
|
124
|
+
expect(result).toBeUndefined();
|
|
125
|
+
});
|
|
57
126
|
});
|
|
58
127
|
});
|
|
@@ -9,10 +9,22 @@ import {
|
|
|
9
9
|
} from '../web-components/mutation-annotations-context';
|
|
10
10
|
import { ErrorDisplay } from './components/error-display';
|
|
11
11
|
import { ResizeContainer } from './components/resize-container';
|
|
12
|
+
import { type Mutation } from '../utils/mutations';
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
type MutationAnnotationPerSequenceType = {
|
|
15
|
+
mutation: Map<string, MutationAnnotations>;
|
|
16
|
+
position: Map<string, MutationAnnotations>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const MutationAnnotationsContext = createContext<Record<SequenceType, MutationAnnotationPerSequenceType>>({
|
|
20
|
+
nucleotide: {
|
|
21
|
+
mutation: new Map(),
|
|
22
|
+
position: new Map(),
|
|
23
|
+
},
|
|
24
|
+
'amino acid': {
|
|
25
|
+
mutation: new Map(),
|
|
26
|
+
position: new Map(),
|
|
27
|
+
},
|
|
16
28
|
});
|
|
17
29
|
|
|
18
30
|
export const MutationAnnotationsContextProvider: FunctionalComponent<
|
|
@@ -26,7 +38,9 @@ export const MutationAnnotationsContextProvider: FunctionalComponent<
|
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
const nucleotideMap = new Map<string, MutationAnnotations>();
|
|
41
|
+
const nucleotidePositions = new Map<string, MutationAnnotations>();
|
|
29
42
|
const aminoAcidMap = new Map<string, MutationAnnotations>();
|
|
43
|
+
const aminoAcidPositions = new Map<string, MutationAnnotations>();
|
|
30
44
|
|
|
31
45
|
value.forEach((annotation) => {
|
|
32
46
|
new Set(annotation.nucleotideMutations).forEach((code) => {
|
|
@@ -35,13 +49,19 @@ export const MutationAnnotationsContextProvider: FunctionalComponent<
|
|
|
35
49
|
new Set(annotation.aminoAcidMutations).forEach((code) => {
|
|
36
50
|
addAnnotationToMap(aminoAcidMap, code, annotation);
|
|
37
51
|
});
|
|
52
|
+
new Set(annotation.nucleotidePositions).forEach((position) => {
|
|
53
|
+
addAnnotationToMap(nucleotidePositions, position, annotation);
|
|
54
|
+
});
|
|
55
|
+
new Set(annotation.aminoAcidPositions).forEach((position) => {
|
|
56
|
+
addAnnotationToMap(aminoAcidPositions, position, annotation);
|
|
57
|
+
});
|
|
38
58
|
});
|
|
39
59
|
|
|
40
60
|
return {
|
|
41
61
|
success: true as const,
|
|
42
62
|
value: {
|
|
43
|
-
nucleotide: nucleotideMap,
|
|
44
|
-
'amino acid': aminoAcidMap,
|
|
63
|
+
nucleotide: { mutation: nucleotideMap, position: nucleotidePositions },
|
|
64
|
+
'amino acid': { mutation: aminoAcidMap, position: aminoAcidPositions },
|
|
45
65
|
},
|
|
46
66
|
};
|
|
47
67
|
}, [value]);
|
|
@@ -67,6 +87,28 @@ function addAnnotationToMap(map: Map<string, MutationAnnotations>, code: string,
|
|
|
67
87
|
export function useMutationAnnotationsProvider() {
|
|
68
88
|
const mutationAnnotations = useContext(MutationAnnotationsContext);
|
|
69
89
|
|
|
70
|
-
return (
|
|
71
|
-
|
|
90
|
+
return (mutation: Mutation, sequenceType: SequenceType) => {
|
|
91
|
+
const position =
|
|
92
|
+
mutation.segment === undefined
|
|
93
|
+
? `${mutation.position}`
|
|
94
|
+
: `${mutation.segment.toUpperCase()}:${mutation.position}`;
|
|
95
|
+
|
|
96
|
+
const possiblePositionAnnotations = mutationAnnotations[sequenceType].position.get(position);
|
|
97
|
+
const possibleExactAnnotations = mutationAnnotations[sequenceType].mutation.get(mutation.code.toUpperCase());
|
|
98
|
+
|
|
99
|
+
const annotations =
|
|
100
|
+
possiblePositionAnnotations && possibleExactAnnotations
|
|
101
|
+
? [...possiblePositionAnnotations, ...possibleExactAnnotations]
|
|
102
|
+
: (possiblePositionAnnotations ?? possibleExactAnnotations);
|
|
103
|
+
|
|
104
|
+
const uniqueNames = new Set<string>();
|
|
105
|
+
|
|
106
|
+
return annotations?.filter((item) => {
|
|
107
|
+
if (uniqueNames.has(item.name)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
uniqueNames.add(item.name);
|
|
111
|
+
return true;
|
|
112
|
+
});
|
|
113
|
+
};
|
|
72
114
|
}
|
|
@@ -46,7 +46,6 @@ export const MutationWithoutAnnotationEntry: StoryObj<AnnotatedMutationProps & {
|
|
|
46
46
|
description: 'This is a test annotation',
|
|
47
47
|
symbol: '*',
|
|
48
48
|
nucleotideMutations: ['123T'],
|
|
49
|
-
aminoAcidMutations: [],
|
|
50
49
|
},
|
|
51
50
|
],
|
|
52
51
|
},
|
|
@@ -69,7 +68,6 @@ export const MutationWithAnnotationEntry: StoryObj<AnnotatedMutationProps & { an
|
|
|
69
68
|
description: 'This is a test annotation <a class="link" href="/">with a link.</a>',
|
|
70
69
|
symbol: '*',
|
|
71
70
|
nucleotideMutations: ['A23403G'],
|
|
72
|
-
aminoAcidMutations: [],
|
|
73
71
|
},
|
|
74
72
|
],
|
|
75
73
|
},
|
|
@@ -97,14 +95,12 @@ export const MutationWithMultipleAnnotationEntries: StoryObj<
|
|
|
97
95
|
description: 'This is a test annotation',
|
|
98
96
|
symbol: '*',
|
|
99
97
|
nucleotideMutations: ['A23403G'],
|
|
100
|
-
aminoAcidMutations: [],
|
|
101
98
|
},
|
|
102
99
|
{
|
|
103
100
|
name: 'Another test annotation',
|
|
104
101
|
description: 'This is a test annotation',
|
|
105
102
|
symbol: '+',
|
|
106
103
|
nucleotideMutations: ['A23403G'],
|
|
107
|
-
aminoAcidMutations: [],
|
|
108
104
|
},
|
|
109
105
|
],
|
|
110
106
|
},
|
|
@@ -139,7 +135,6 @@ export const AminoAcidMutationWithAnnotationEntry: StoryObj<
|
|
|
139
135
|
name: 'Test annotation',
|
|
140
136
|
description: 'This is a test annotation',
|
|
141
137
|
symbol: '*',
|
|
142
|
-
nucleotideMutations: [],
|
|
143
138
|
aminoAcidMutations: ['S:A501G'],
|
|
144
139
|
},
|
|
145
140
|
],
|
|
@@ -45,7 +45,7 @@ const AnnotatedMutationWithoutContext: FunctionComponent<AnnotatedMutationWithou
|
|
|
45
45
|
annotationsProvider,
|
|
46
46
|
modalRef,
|
|
47
47
|
}) => {
|
|
48
|
-
const mutationAnnotations = annotationsProvider(mutation
|
|
48
|
+
const mutationAnnotations = annotationsProvider(mutation, sequenceType);
|
|
49
49
|
|
|
50
50
|
if (mutationAnnotations === undefined || mutationAnnotations.length === 0) {
|
|
51
51
|
return mutation.code;
|
|
@@ -67,7 +67,11 @@ const AnnotatedMutationWithoutContext: FunctionComponent<AnnotatedMutationWithou
|
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
return (
|
|
70
|
-
<ButtonWithModalDialog
|
|
70
|
+
<ButtonWithModalDialog
|
|
71
|
+
buttonClassName={'select-text cursor-pointer'}
|
|
72
|
+
modalContent={modalContent}
|
|
73
|
+
modalRef={modalRef}
|
|
74
|
+
>
|
|
71
75
|
{mutation.code}
|
|
72
76
|
<sup>
|
|
73
77
|
{mutationAnnotations
|