@genspectrum/dashboard-components 1.10.3 → 1.11.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.
- package/custom-elements.json +38 -3
- package/dist/components.d.ts +61 -53
- package/dist/components.js +83 -56
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +66 -53
- package/package.json +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.stories.tsx +15 -10
- package/src/preact/mutationsOverTime/mutations-over-time-grid-tooltip.tsx +49 -43
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +34 -6
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +27 -0
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +3 -1
- package/src/utilEntrypoint.ts +1 -0
- package/src/web-components/input/gs-lineage-filter.stories.ts +9 -1
- package/src/web-components/visualization/gs-mutations-over-time.spec-d.ts +3 -0
- package/src/web-components/visualization/gs-mutations-over-time.stories.ts +21 -0
- package/src/web-components/visualization/gs-mutations-over-time.tsx +8 -0
- package/standalone-bundle/dashboard-components.js +1225 -1204
- package/standalone-bundle/dashboard-components.js.map +1 -1
package/dist/util.d.ts
CHANGED
|
@@ -71,6 +71,19 @@ export declare type ConfidenceIntervalMethod = default_2.infer<typeof confidence
|
|
|
71
71
|
|
|
72
72
|
declare const confidenceIntervalMethodSchema: default_2.ZodUnion<[default_2.ZodLiteral<"wilson">, default_2.ZodLiteral<"none">]>;
|
|
73
73
|
|
|
74
|
+
export declare type CustomColumn = default_2.infer<typeof customColumnSchema>;
|
|
75
|
+
|
|
76
|
+
declare const customColumnSchema: default_2.ZodObject<{
|
|
77
|
+
header: default_2.ZodString;
|
|
78
|
+
values: default_2.ZodRecord<default_2.ZodString, default_2.ZodUnion<[default_2.ZodString, default_2.ZodNumber]>>;
|
|
79
|
+
}, "strip", default_2.ZodTypeAny, {
|
|
80
|
+
values: Record<string, string | number>;
|
|
81
|
+
header: string;
|
|
82
|
+
}, {
|
|
83
|
+
values: Record<string, string | number>;
|
|
84
|
+
header: string;
|
|
85
|
+
}>;
|
|
86
|
+
|
|
74
87
|
export declare type DateRangeOption = default_2.infer<typeof dateRangeOptionSchema>;
|
|
75
88
|
|
|
76
89
|
export declare class DateRangeOptionChangedEvent extends CustomEvent<DateRangeValue> {
|
|
@@ -958,7 +971,11 @@ declare global {
|
|
|
958
971
|
|
|
959
972
|
declare global {
|
|
960
973
|
interface HTMLElementTagNameMap {
|
|
961
|
-
'gs-
|
|
974
|
+
'gs-date-range-filter': DateRangeFilterComponent;
|
|
975
|
+
}
|
|
976
|
+
interface HTMLElementEventMap {
|
|
977
|
+
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
978
|
+
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
962
979
|
}
|
|
963
980
|
}
|
|
964
981
|
|
|
@@ -966,7 +983,7 @@ declare global {
|
|
|
966
983
|
declare global {
|
|
967
984
|
namespace JSX {
|
|
968
985
|
interface IntrinsicElements {
|
|
969
|
-
'gs-
|
|
986
|
+
'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
970
987
|
}
|
|
971
988
|
}
|
|
972
989
|
}
|
|
@@ -974,7 +991,10 @@ declare global {
|
|
|
974
991
|
|
|
975
992
|
declare global {
|
|
976
993
|
interface HTMLElementTagNameMap {
|
|
977
|
-
'gs-
|
|
994
|
+
'gs-location-filter': LocationFilterComponent;
|
|
995
|
+
}
|
|
996
|
+
interface HTMLElementEventMap {
|
|
997
|
+
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
978
998
|
}
|
|
979
999
|
}
|
|
980
1000
|
|
|
@@ -982,7 +1002,7 @@ declare global {
|
|
|
982
1002
|
declare global {
|
|
983
1003
|
namespace JSX {
|
|
984
1004
|
interface IntrinsicElements {
|
|
985
|
-
'gs-
|
|
1005
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
986
1006
|
}
|
|
987
1007
|
}
|
|
988
1008
|
}
|
|
@@ -990,7 +1010,10 @@ declare global {
|
|
|
990
1010
|
|
|
991
1011
|
declare global {
|
|
992
1012
|
interface HTMLElementTagNameMap {
|
|
993
|
-
'gs-
|
|
1013
|
+
'gs-text-filter': TextFilterComponent;
|
|
1014
|
+
}
|
|
1015
|
+
interface HTMLElementEventMap {
|
|
1016
|
+
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
994
1017
|
}
|
|
995
1018
|
}
|
|
996
1019
|
|
|
@@ -998,7 +1021,7 @@ declare global {
|
|
|
998
1021
|
declare global {
|
|
999
1022
|
namespace JSX {
|
|
1000
1023
|
interface IntrinsicElements {
|
|
1001
|
-
'gs-
|
|
1024
|
+
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1002
1025
|
}
|
|
1003
1026
|
}
|
|
1004
1027
|
}
|
|
@@ -1006,7 +1029,11 @@ declare global {
|
|
|
1006
1029
|
|
|
1007
1030
|
declare global {
|
|
1008
1031
|
interface HTMLElementTagNameMap {
|
|
1009
|
-
'gs-
|
|
1032
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1033
|
+
}
|
|
1034
|
+
interface HTMLElementEventMap {
|
|
1035
|
+
[gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
|
|
1036
|
+
[gsEventNames.lineageFilterMultiChanged]: LineageMultiFilterChangedEvent;
|
|
1010
1037
|
}
|
|
1011
1038
|
}
|
|
1012
1039
|
|
|
@@ -1014,7 +1041,7 @@ declare global {
|
|
|
1014
1041
|
declare global {
|
|
1015
1042
|
namespace JSX {
|
|
1016
1043
|
interface IntrinsicElements {
|
|
1017
|
-
'gs-
|
|
1044
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1018
1045
|
}
|
|
1019
1046
|
}
|
|
1020
1047
|
}
|
|
@@ -1022,7 +1049,10 @@ declare global {
|
|
|
1022
1049
|
|
|
1023
1050
|
declare global {
|
|
1024
1051
|
interface HTMLElementTagNameMap {
|
|
1025
|
-
'gs-
|
|
1052
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
1053
|
+
}
|
|
1054
|
+
interface HTMLElementEventMap {
|
|
1055
|
+
[gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
|
|
1026
1056
|
}
|
|
1027
1057
|
}
|
|
1028
1058
|
|
|
@@ -1030,7 +1060,7 @@ declare global {
|
|
|
1030
1060
|
declare global {
|
|
1031
1061
|
namespace JSX {
|
|
1032
1062
|
interface IntrinsicElements {
|
|
1033
|
-
'gs-
|
|
1063
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1034
1064
|
}
|
|
1035
1065
|
}
|
|
1036
1066
|
}
|
|
@@ -1038,7 +1068,11 @@ declare global {
|
|
|
1038
1068
|
|
|
1039
1069
|
declare global {
|
|
1040
1070
|
interface HTMLElementTagNameMap {
|
|
1041
|
-
'gs-
|
|
1071
|
+
'gs-number-range-filter': NumberRangeFilterComponent;
|
|
1072
|
+
}
|
|
1073
|
+
interface HTMLElementEventMap {
|
|
1074
|
+
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
1075
|
+
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1042
1076
|
}
|
|
1043
1077
|
}
|
|
1044
1078
|
|
|
@@ -1046,7 +1080,7 @@ declare global {
|
|
|
1046
1080
|
declare global {
|
|
1047
1081
|
namespace JSX {
|
|
1048
1082
|
interface IntrinsicElements {
|
|
1049
|
-
'gs-
|
|
1083
|
+
'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1050
1084
|
}
|
|
1051
1085
|
}
|
|
1052
1086
|
}
|
|
@@ -1054,7 +1088,7 @@ declare global {
|
|
|
1054
1088
|
|
|
1055
1089
|
declare global {
|
|
1056
1090
|
interface HTMLElementTagNameMap {
|
|
1057
|
-
'gs-
|
|
1091
|
+
'gs-genome-data-viewer': GenomeDataViewerComponent;
|
|
1058
1092
|
}
|
|
1059
1093
|
}
|
|
1060
1094
|
|
|
@@ -1062,7 +1096,7 @@ declare global {
|
|
|
1062
1096
|
declare global {
|
|
1063
1097
|
namespace JSX {
|
|
1064
1098
|
interface IntrinsicElements {
|
|
1065
|
-
'gs-
|
|
1099
|
+
'gs-genome-data-viewer': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1066
1100
|
}
|
|
1067
1101
|
}
|
|
1068
1102
|
}
|
|
@@ -1070,7 +1104,7 @@ declare global {
|
|
|
1070
1104
|
|
|
1071
1105
|
declare global {
|
|
1072
1106
|
interface HTMLElementTagNameMap {
|
|
1073
|
-
'gs-
|
|
1107
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
1074
1108
|
}
|
|
1075
1109
|
}
|
|
1076
1110
|
|
|
@@ -1078,7 +1112,7 @@ declare global {
|
|
|
1078
1112
|
declare global {
|
|
1079
1113
|
namespace JSX {
|
|
1080
1114
|
interface IntrinsicElements {
|
|
1081
|
-
'gs-
|
|
1115
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1082
1116
|
}
|
|
1083
1117
|
}
|
|
1084
1118
|
}
|
|
@@ -1086,7 +1120,7 @@ declare global {
|
|
|
1086
1120
|
|
|
1087
1121
|
declare global {
|
|
1088
1122
|
interface HTMLElementTagNameMap {
|
|
1089
|
-
'gs-
|
|
1123
|
+
'gs-mutations': MutationsComponent;
|
|
1090
1124
|
}
|
|
1091
1125
|
}
|
|
1092
1126
|
|
|
@@ -1094,7 +1128,7 @@ declare global {
|
|
|
1094
1128
|
declare global {
|
|
1095
1129
|
namespace JSX {
|
|
1096
1130
|
interface IntrinsicElements {
|
|
1097
|
-
'gs-
|
|
1131
|
+
'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1098
1132
|
}
|
|
1099
1133
|
}
|
|
1100
1134
|
}
|
|
@@ -1102,11 +1136,7 @@ declare global {
|
|
|
1102
1136
|
|
|
1103
1137
|
declare global {
|
|
1104
1138
|
interface HTMLElementTagNameMap {
|
|
1105
|
-
'gs-
|
|
1106
|
-
}
|
|
1107
|
-
interface HTMLElementEventMap {
|
|
1108
|
-
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
1109
|
-
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
1139
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
1110
1140
|
}
|
|
1111
1141
|
}
|
|
1112
1142
|
|
|
@@ -1114,7 +1144,7 @@ declare global {
|
|
|
1114
1144
|
declare global {
|
|
1115
1145
|
namespace JSX {
|
|
1116
1146
|
interface IntrinsicElements {
|
|
1117
|
-
'gs-
|
|
1147
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1118
1148
|
}
|
|
1119
1149
|
}
|
|
1120
1150
|
}
|
|
@@ -1122,7 +1152,7 @@ declare global {
|
|
|
1122
1152
|
|
|
1123
1153
|
declare global {
|
|
1124
1154
|
interface HTMLElementTagNameMap {
|
|
1125
|
-
'gs-
|
|
1155
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
1126
1156
|
}
|
|
1127
1157
|
}
|
|
1128
1158
|
|
|
@@ -1130,7 +1160,7 @@ declare global {
|
|
|
1130
1160
|
declare global {
|
|
1131
1161
|
namespace JSX {
|
|
1132
1162
|
interface IntrinsicElements {
|
|
1133
|
-
'gs-
|
|
1163
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1134
1164
|
}
|
|
1135
1165
|
}
|
|
1136
1166
|
}
|
|
@@ -1138,10 +1168,7 @@ declare global {
|
|
|
1138
1168
|
|
|
1139
1169
|
declare global {
|
|
1140
1170
|
interface HTMLElementTagNameMap {
|
|
1141
|
-
'gs-
|
|
1142
|
-
}
|
|
1143
|
-
interface HTMLElementEventMap {
|
|
1144
|
-
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
1171
|
+
'gs-aggregate': AggregateComponent;
|
|
1145
1172
|
}
|
|
1146
1173
|
}
|
|
1147
1174
|
|
|
@@ -1149,7 +1176,7 @@ declare global {
|
|
|
1149
1176
|
declare global {
|
|
1150
1177
|
namespace JSX {
|
|
1151
1178
|
interface IntrinsicElements {
|
|
1152
|
-
'gs-
|
|
1179
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1153
1180
|
}
|
|
1154
1181
|
}
|
|
1155
1182
|
}
|
|
@@ -1157,10 +1184,7 @@ declare global {
|
|
|
1157
1184
|
|
|
1158
1185
|
declare global {
|
|
1159
1186
|
interface HTMLElementTagNameMap {
|
|
1160
|
-
'gs-
|
|
1161
|
-
}
|
|
1162
|
-
interface HTMLElementEventMap {
|
|
1163
|
-
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
1187
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1164
1188
|
}
|
|
1165
1189
|
}
|
|
1166
1190
|
|
|
@@ -1168,7 +1192,7 @@ declare global {
|
|
|
1168
1192
|
declare global {
|
|
1169
1193
|
namespace JSX {
|
|
1170
1194
|
interface IntrinsicElements {
|
|
1171
|
-
'gs-
|
|
1195
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1172
1196
|
}
|
|
1173
1197
|
}
|
|
1174
1198
|
}
|
|
@@ -1176,10 +1200,7 @@ declare global {
|
|
|
1176
1200
|
|
|
1177
1201
|
declare global {
|
|
1178
1202
|
interface HTMLElementTagNameMap {
|
|
1179
|
-
'gs-
|
|
1180
|
-
}
|
|
1181
|
-
interface HTMLElementEventMap {
|
|
1182
|
-
[gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
|
|
1203
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1183
1204
|
}
|
|
1184
1205
|
}
|
|
1185
1206
|
|
|
@@ -1187,7 +1208,7 @@ declare global {
|
|
|
1187
1208
|
declare global {
|
|
1188
1209
|
namespace JSX {
|
|
1189
1210
|
interface IntrinsicElements {
|
|
1190
|
-
'gs-
|
|
1211
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1191
1212
|
}
|
|
1192
1213
|
}
|
|
1193
1214
|
}
|
|
@@ -1195,11 +1216,7 @@ declare global {
|
|
|
1195
1216
|
|
|
1196
1217
|
declare global {
|
|
1197
1218
|
interface HTMLElementTagNameMap {
|
|
1198
|
-
'gs-
|
|
1199
|
-
}
|
|
1200
|
-
interface HTMLElementEventMap {
|
|
1201
|
-
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
1202
|
-
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1219
|
+
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
1203
1220
|
}
|
|
1204
1221
|
}
|
|
1205
1222
|
|
|
@@ -1207,7 +1224,7 @@ declare global {
|
|
|
1207
1224
|
declare global {
|
|
1208
1225
|
namespace JSX {
|
|
1209
1226
|
interface IntrinsicElements {
|
|
1210
|
-
'gs-
|
|
1227
|
+
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1211
1228
|
}
|
|
1212
1229
|
}
|
|
1213
1230
|
}
|
|
@@ -1215,11 +1232,7 @@ declare global {
|
|
|
1215
1232
|
|
|
1216
1233
|
declare global {
|
|
1217
1234
|
interface HTMLElementTagNameMap {
|
|
1218
|
-
'gs-
|
|
1219
|
-
}
|
|
1220
|
-
interface HTMLElementEventMap {
|
|
1221
|
-
[gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
|
|
1222
|
-
[gsEventNames.lineageFilterMultiChanged]: LineageMultiFilterChangedEvent;
|
|
1235
|
+
'gs-statistics': StatisticsComponent;
|
|
1223
1236
|
}
|
|
1224
1237
|
}
|
|
1225
1238
|
|
|
@@ -1227,7 +1240,7 @@ declare global {
|
|
|
1227
1240
|
declare global {
|
|
1228
1241
|
namespace JSX {
|
|
1229
1242
|
interface IntrinsicElements {
|
|
1230
|
-
'gs-
|
|
1243
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1231
1244
|
}
|
|
1232
1245
|
}
|
|
1233
1246
|
}
|
package/package.json
CHANGED
|
@@ -45,7 +45,7 @@ export const NoValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
|
45
45
|
const canvas = within(canvasElement);
|
|
46
46
|
|
|
47
47
|
await expect(canvas.getByText('2025', { exact: true })).toBeVisible();
|
|
48
|
-
await expect(canvas.getByText('
|
|
48
|
+
await expect(canvas.getByText('2025-01-01 - 2025-12-31')).toBeVisible();
|
|
49
49
|
await expect(canvas.getByText('A500-')).toBeVisible();
|
|
50
50
|
await expect(canvas.getByText('No data')).toBeVisible();
|
|
51
51
|
},
|
|
@@ -65,9 +65,13 @@ export const WithValue: StoryObj<MutationsOverTimeGridTooltipProps> = {
|
|
|
65
65
|
play: async ({ canvasElement }) => {
|
|
66
66
|
const canvas = within(canvasElement);
|
|
67
67
|
|
|
68
|
-
await expect(canvas.getByText('
|
|
69
|
-
await expect(canvas.getByText('
|
|
70
|
-
await expect(canvas.getByText('
|
|
68
|
+
await expect(canvas.getByText('50.00%')).toBeVisible();
|
|
69
|
+
await expect(canvas.getByText('100')).toBeVisible();
|
|
70
|
+
await expect(canvas.getByText('have the mutation A500- out of')).toBeVisible();
|
|
71
|
+
await expect(canvas.getByText('200')).toBeVisible();
|
|
72
|
+
await expect(canvas.getByText('with coverage at position 500.')).toBeVisible();
|
|
73
|
+
await expect(canvas.getByText('300')).toBeVisible();
|
|
74
|
+
await expect(canvas.getByText('total in this date range.')).toBeVisible();
|
|
71
75
|
},
|
|
72
76
|
};
|
|
73
77
|
|
|
@@ -83,9 +87,10 @@ export const WithValueBelowThreshold: StoryObj<MutationsOverTimeGridTooltipProps
|
|
|
83
87
|
play: async ({ canvasElement }) => {
|
|
84
88
|
const canvas = within(canvasElement);
|
|
85
89
|
|
|
86
|
-
await expect(canvas.getByText('
|
|
87
|
-
await expect(canvas.getByText('
|
|
88
|
-
await expect(canvas.getByText('
|
|
90
|
+
await expect(canvas.getByText('<0.10%')).toBeVisible();
|
|
91
|
+
await expect(canvas.getByText('None or less than 0.10% have the mutation.')).toBeVisible();
|
|
92
|
+
await expect(canvas.getByText('300')).toBeVisible();
|
|
93
|
+
await expect(canvas.getByText('total in this date range.')).toBeVisible();
|
|
89
94
|
},
|
|
90
95
|
};
|
|
91
96
|
|
|
@@ -101,8 +106,8 @@ export const WithWastewaterValue: StoryObj<MutationsOverTimeGridTooltipProps> =
|
|
|
101
106
|
play: async ({ canvasElement }) => {
|
|
102
107
|
const canvas = within(canvasElement);
|
|
103
108
|
|
|
104
|
-
await expect(canvas.getByText('
|
|
105
|
-
await expect(canvas.queryByText('
|
|
106
|
-
await expect(canvas.queryByText('
|
|
109
|
+
await expect(canvas.getByText('50.00%')).toBeVisible();
|
|
110
|
+
await expect(canvas.queryByText('total in this date range.')).not.toBeInTheDocument();
|
|
111
|
+
await expect(canvas.queryByText('coverage')).not.toBeInTheDocument();
|
|
107
112
|
},
|
|
108
113
|
};
|
|
@@ -21,60 +21,66 @@ export const MutationsOverTimeGridTooltip: FunctionComponent<MutationsOverTimeGr
|
|
|
21
21
|
}: MutationsOverTimeGridTooltipProps) => {
|
|
22
22
|
const dateClass = toTemporalClass(date);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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);
|
|
24
|
+
const proportionText =
|
|
25
|
+
value === null
|
|
26
|
+
? 'No data'
|
|
27
|
+
: value.type === 'belowThreshold'
|
|
28
|
+
? `<${formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)}`
|
|
29
|
+
: formatProportion(value.proportion);
|
|
45
30
|
|
|
46
31
|
return (
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
32
|
+
<div>
|
|
33
|
+
<div className='flex flex-row justify-between gap-4 items-baseline'>
|
|
34
|
+
<div className='flex flex-col text-left'>
|
|
35
|
+
<span className='font-bold'>{mutation.code}</span>
|
|
36
|
+
<span>{proportionText}</span>
|
|
37
|
+
</div>
|
|
38
|
+
<div className='flex flex-col text-right'>
|
|
39
|
+
<span className='font-bold'>{dateClass.englishName()}</span>
|
|
40
|
+
<span className='text-gray-600'>{timeIntervalDisplay(dateClass)}</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
{value !== null && (
|
|
44
|
+
<TooltipValueCountsDescription
|
|
45
|
+
value={value}
|
|
46
|
+
mutationCode={mutation.code}
|
|
47
|
+
mutationPosition={mutation.position}
|
|
48
|
+
/>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
51
|
);
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const TooltipValueCountsDescription: FunctionComponent<{
|
|
55
55
|
value: NonNullable<MutationOverTimeMutationValue>;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
mutationCode: string;
|
|
57
|
+
mutationPosition: number;
|
|
58
|
+
}> = ({ value, mutationCode, mutationPosition }) => {
|
|
59
|
+
if (value.type === 'wastewaterValue') {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
return (
|
|
63
|
+
<div className='mt-2'>
|
|
64
|
+
{value.type === 'belowThreshold' ? (
|
|
65
|
+
<p className='text-gray-600'>
|
|
66
|
+
None or less than {formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)} have the mutation.
|
|
67
|
+
</p>
|
|
68
|
+
) : (
|
|
69
69
|
<>
|
|
70
|
-
<p>{value.totalCount} samples are in the timeframe</p>
|
|
71
70
|
<p>
|
|
72
|
-
{
|
|
73
|
-
|
|
71
|
+
{value.count} <span className='text-gray-600'>have the mutation {mutationCode} out of</span>
|
|
72
|
+
</p>
|
|
73
|
+
<p>
|
|
74
|
+
{totalCountWithCoverage(value.count, value.proportion)}{' '}
|
|
75
|
+
<span className='text-gray-600'>with coverage at position {mutationPosition}.</span>
|
|
74
76
|
</p>
|
|
75
77
|
</>
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
+
)}
|
|
79
|
+
<p>
|
|
80
|
+
{value.totalCount} <span className='text-gray-600'>total in this date range.</span>
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
78
84
|
};
|
|
79
85
|
|
|
80
86
|
function totalCountWithCoverage(count: number, proportion: number) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
2
|
import { useMemo } from 'preact/hooks';
|
|
3
|
+
import z from 'zod';
|
|
3
4
|
|
|
4
5
|
import { type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
5
6
|
import { MutationsOverTimeGridTooltip } from './mutations-over-time-grid-tooltip';
|
|
@@ -24,29 +25,45 @@ import {
|
|
|
24
25
|
|
|
25
26
|
const NON_BREAKING_SPACE = '\u00A0';
|
|
26
27
|
|
|
28
|
+
export const customColumnSchema = z.object({
|
|
29
|
+
header: z.string(),
|
|
30
|
+
values: z.record(z.string(), z.union([z.string(), z.number()])),
|
|
31
|
+
});
|
|
32
|
+
export type CustomColumn = z.infer<typeof customColumnSchema>;
|
|
33
|
+
|
|
27
34
|
export interface MutationsOverTimeGridProps {
|
|
28
35
|
data: MutationOverTimeDataMap;
|
|
29
36
|
colorScale: ColorScale;
|
|
30
37
|
sequenceType: SequenceType;
|
|
31
38
|
pageSizes: PageSizes;
|
|
39
|
+
customColumns?: CustomColumn[];
|
|
32
40
|
tooltipPortalTarget: HTMLElement | null;
|
|
33
41
|
}
|
|
34
42
|
|
|
35
|
-
type RowType = {
|
|
43
|
+
type RowType = {
|
|
44
|
+
mutation: Substitution | Deletion;
|
|
45
|
+
values: (MutationOverTimeMutationValue | undefined)[];
|
|
46
|
+
customValues: (string | number | undefined)[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const EMPTY_COLUMNS: CustomColumn[] = [];
|
|
36
50
|
|
|
37
51
|
const MutationsOverTimeGrid: FunctionComponent<MutationsOverTimeGridProps> = ({
|
|
38
52
|
data,
|
|
39
53
|
colorScale,
|
|
40
54
|
sequenceType,
|
|
41
55
|
pageSizes,
|
|
56
|
+
customColumns = EMPTY_COLUMNS,
|
|
42
57
|
tooltipPortalTarget,
|
|
43
58
|
}) => {
|
|
44
59
|
const tableData = useMemo(() => {
|
|
45
60
|
const allMutations = data.getFirstAxisKeys();
|
|
46
|
-
return data.getAsArray().map((row, index) => {
|
|
47
|
-
|
|
61
|
+
return data.getAsArray().map((row, index): RowType => {
|
|
62
|
+
const mutation = allMutations[index];
|
|
63
|
+
const customValues = customColumns.map((col) => col.values[mutation.code]);
|
|
64
|
+
return { mutation, values: [...row], customValues };
|
|
48
65
|
});
|
|
49
|
-
}, [data]);
|
|
66
|
+
}, [data, customColumns]);
|
|
50
67
|
|
|
51
68
|
const columns = useMemo(() => {
|
|
52
69
|
const columnHelper = createColumnHelper<RowType>();
|
|
@@ -65,6 +82,17 @@ const MutationsOverTimeGrid: FunctionComponent<MutationsOverTimeGridProps> = ({
|
|
|
65
82
|
},
|
|
66
83
|
});
|
|
67
84
|
|
|
85
|
+
const customColumnHeaders = customColumns.map((customCol, index) => {
|
|
86
|
+
return columnHelper.accessor((row) => row.customValues[index], {
|
|
87
|
+
id: `custom-${index}`,
|
|
88
|
+
header: () => <span>{customCol.header}</span>,
|
|
89
|
+
cell: ({ getValue }) => {
|
|
90
|
+
const value = getValue();
|
|
91
|
+
return <div className={'text-center'}>{value ?? ''}</div>;
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
68
96
|
const dateHeaders = dates.map((date, index) => {
|
|
69
97
|
return columnHelper.accessor((row) => row.values[index], {
|
|
70
98
|
id: `date-${index}`,
|
|
@@ -102,8 +130,8 @@ const MutationsOverTimeGrid: FunctionComponent<MutationsOverTimeGridProps> = ({
|
|
|
102
130
|
});
|
|
103
131
|
});
|
|
104
132
|
|
|
105
|
-
return [mutationHeader, ...dateHeaders];
|
|
106
|
-
}, [colorScale, data, sequenceType, tooltipPortalTarget]);
|
|
133
|
+
return [mutationHeader, ...customColumnHeaders, ...dateHeaders];
|
|
134
|
+
}, [colorScale, data, sequenceType, customColumns, tooltipPortalTarget]);
|
|
107
135
|
|
|
108
136
|
const { pageSize } = usePageSizeContext();
|
|
109
137
|
const table = usePreactTable({
|
|
@@ -38,6 +38,7 @@ const meta: Meta<MutationsOverTimeProps> = {
|
|
|
38
38
|
hideGaps: { control: 'boolean' },
|
|
39
39
|
pageSizes: { control: 'object' },
|
|
40
40
|
useNewEndpoint: { control: 'boolean' },
|
|
41
|
+
customColumns: { control: 'object' },
|
|
41
42
|
},
|
|
42
43
|
parameters: {
|
|
43
44
|
fetchMock: {},
|
|
@@ -196,6 +197,32 @@ export const UsesMutationFilter: StoryObj<MutationsOverTimeProps> = {
|
|
|
196
197
|
},
|
|
197
198
|
};
|
|
198
199
|
|
|
200
|
+
export const WithCustomColumns: StoryObj<MutationsOverTimeProps> = {
|
|
201
|
+
...Default,
|
|
202
|
+
args: {
|
|
203
|
+
...Default.args,
|
|
204
|
+
displayMutations: ['A19722G', 'G21641T', 'T21653-'],
|
|
205
|
+
customColumns: [
|
|
206
|
+
{
|
|
207
|
+
header: 'Jaccard Index',
|
|
208
|
+
values: {
|
|
209
|
+
A19722G: 0.75,
|
|
210
|
+
G21641T: 'Foobar',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
play: async ({ canvas }) => {
|
|
216
|
+
await waitFor(() => expect(canvas.getByText('Jaccard Index')).toBeVisible(), {
|
|
217
|
+
timeout: 5000,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
await waitFor(() => expect(canvas.getByText('0.75')).toBeVisible());
|
|
221
|
+
|
|
222
|
+
await waitFor(() => expect(canvas.getByText('Foobar')).toBeVisible());
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
|
|
199
226
|
async function expectMutationOnPage(canvas: Canvas, mutation: string) {
|
|
200
227
|
await waitFor(async () => {
|
|
201
228
|
const mutationOnFirstPage = canvas.getAllByText(mutation)[0];
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type MutationFilter,
|
|
12
12
|
} from './getFilteredMutationsOverTimeData';
|
|
13
13
|
import { type MutationOverTimeWorkerResponse } from './mutationOverTimeWorker';
|
|
14
|
-
import MutationsOverTimeGrid from './mutations-over-time-grid';
|
|
14
|
+
import MutationsOverTimeGrid, { customColumnSchema } from './mutations-over-time-grid';
|
|
15
15
|
import { type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
|
|
16
16
|
import {
|
|
17
17
|
lapisFilterSchema,
|
|
@@ -66,6 +66,7 @@ const mutationOverTimeSchema = z.object({
|
|
|
66
66
|
width: z.string(),
|
|
67
67
|
height: z.string().optional(),
|
|
68
68
|
pageSizes: pageSizesSchema,
|
|
69
|
+
customColumns: z.array(customColumnSchema).optional(),
|
|
69
70
|
});
|
|
70
71
|
export type MutationsOverTimeProps = z.infer<typeof mutationOverTimeSchema>;
|
|
71
72
|
|
|
@@ -204,6 +205,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
204
205
|
colorScale={colorScale}
|
|
205
206
|
sequenceType={originalComponentProps.sequenceType}
|
|
206
207
|
pageSizes={originalComponentProps.pageSizes}
|
|
208
|
+
customColumns={originalComponentProps.customColumns}
|
|
207
209
|
tooltipPortalTarget={tooltipPortalTarget}
|
|
208
210
|
/>
|
|
209
211
|
),
|
package/src/utilEntrypoint.ts
CHANGED