@genspectrum/dashboard-components 0.13.7 → 0.14.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 +24 -62
- package/dist/{LineageFilterChangedEvent-GedKNGFI.js → LineageFilterChangedEvent-C9dXOxt6.js} +11 -3
- package/dist/LineageFilterChangedEvent-C9dXOxt6.js.map +1 -0
- package/dist/assets/mutationOverTimeWorker-Dxnxrfe0.js.map +1 -1
- package/dist/components.d.ts +40 -50
- package/dist/components.js +112 -91
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +38 -28
- package/dist/util.js +1 -1
- package/package.json +2 -2
- package/src/lapisApi/lapisApi.ts +1 -1
- package/src/operator/FillMissingOperator.spec.ts +1 -1
- package/src/operator/GroupByAndSumOperator.spec.ts +1 -1
- package/src/operator/GroupByOperator.spec.ts +2 -2
- package/src/operator/MapOperator.spec.ts +1 -1
- package/src/operator/MockOperator.spec.ts +1 -1
- package/src/operator/MockOperator.ts +6 -4
- package/src/operator/SortOperator.spec.ts +1 -1
- package/src/preact/LapisUrlContext.ts +14 -1
- package/src/preact/aggregatedData/aggregate.stories.tsx +4 -4
- package/src/preact/aggregatedData/aggregate.tsx +3 -4
- package/src/preact/components/csv-download-button.stories.tsx +2 -2
- package/src/preact/components/csv-download-button.tsx +1 -1
- package/src/preact/components/error-boundary.stories.tsx +5 -5
- package/src/preact/components/error-boundary.tsx +14 -3
- package/src/preact/components/error-display.stories.tsx +9 -9
- package/src/preact/components/fullscreen.tsx +3 -3
- package/src/preact/components/info.tsx +1 -1
- package/src/preact/components/mutation-type-selector.stories.tsx +1 -1
- package/src/preact/components/table.stories.tsx +3 -3
- package/src/preact/components/table.tsx +1 -1
- package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +34 -20
- package/src/preact/dateRangeSelector/computeInitialValues.ts +25 -21
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +107 -46
- package/src/preact/dateRangeSelector/date-range-selector.tsx +31 -22
- package/src/preact/dateRangeSelector/dateRangeOption.ts +11 -1
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +9 -9
- package/src/preact/lineageFilter/lineage-filter.tsx +3 -4
- package/src/preact/locationFilter/fetchAutocompletionList.ts +1 -1
- package/src/preact/locationFilter/location-filter.stories.tsx +9 -9
- package/src/preact/locationFilter/location-filter.tsx +4 -4
- package/src/preact/map/sequences-by-location.stories.tsx +4 -4
- package/src/preact/map/sequences-by-location.tsx +3 -4
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -3
- package/src/preact/mutationComparison/mutation-comparison.tsx +4 -4
- package/src/preact/mutationFilter/mutation-filter-info.tsx +3 -3
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +7 -7
- package/src/preact/mutations/getMutationsGridData.ts +1 -1
- package/src/preact/mutations/mutations.stories.tsx +3 -3
- package/src/preact/mutations/mutations.tsx +4 -4
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +4 -4
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +5 -4
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +4 -4
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
- package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +4 -4
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +4 -4
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -4
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +4 -4
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -4
- package/src/preact/shared/floating-ui/hooks.ts +1 -1
- package/src/preact/statistic/statistics.stories.tsx +3 -3
- package/src/preact/statistic/statistics.tsx +2 -3
- package/src/preact/textInput/text-input.stories.tsx +7 -7
- package/src/preact/textInput/text-input.tsx +3 -4
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +3 -3
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -4
- package/src/utils/map2d.ts +1 -0
- package/src/web-components/PreactLitAdapter.tsx +3 -3
- package/src/web-components/gs-app.stories.ts +7 -7
- package/src/web-components/gs-app.ts +3 -1
- package/src/web-components/input/gs-date-range-selector.stories.ts +10 -17
- package/src/web-components/input/gs-date-range-selector.tsx +15 -38
- package/src/web-components/input/gs-lineage-filter.stories.ts +1 -1
- package/src/web-components/input/gs-location-filter.stories.ts +1 -1
- package/src/web-components/input/gs-mutation-filter.stories.ts +7 -7
- package/src/web-components/input/gs-text-input.stories.ts +3 -3
- package/src/web-components/visualization/gs-aggregate.tsx +2 -2
- package/standalone-bundle/assets/mutationOverTimeWorker-CmSrq4SZ.js.map +1 -1
- package/standalone-bundle/dashboard-components.js +6068 -6055
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/LineageFilterChangedEvent-GedKNGFI.js.map +0 -1
package/dist/util.d.ts
CHANGED
|
@@ -136,10 +136,20 @@ declare const dateRangeOptionSchema: default_2.ZodObject<{
|
|
|
136
136
|
dateTo?: string | undefined;
|
|
137
137
|
}>;
|
|
138
138
|
|
|
139
|
-
export declare type DateRangeSelectOption =
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
export declare type DateRangeSelectOption = Required<DateRangeValue>;
|
|
140
|
+
|
|
141
|
+
declare type DateRangeValue = default_2.infer<typeof dateRangeValueSchema>;
|
|
142
|
+
|
|
143
|
+
declare const dateRangeValueSchema: default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
|
|
144
|
+
dateFrom: default_2.ZodOptional<default_2.ZodString>;
|
|
145
|
+
dateTo: default_2.ZodOptional<default_2.ZodString>;
|
|
146
|
+
}, "strip", default_2.ZodTypeAny, {
|
|
147
|
+
dateFrom?: string | undefined;
|
|
148
|
+
dateTo?: string | undefined;
|
|
149
|
+
}, {
|
|
150
|
+
dateFrom?: string | undefined;
|
|
151
|
+
dateTo?: string | undefined;
|
|
152
|
+
}>]>;
|
|
143
153
|
|
|
144
154
|
export declare type LapisFilter = default_2.infer<typeof lapisFilterSchema>;
|
|
145
155
|
|
|
@@ -838,7 +848,7 @@ declare global {
|
|
|
838
848
|
|
|
839
849
|
declare global {
|
|
840
850
|
interface HTMLElementTagNameMap {
|
|
841
|
-
'gs-
|
|
851
|
+
'gs-mutations-component': MutationsComponent;
|
|
842
852
|
}
|
|
843
853
|
}
|
|
844
854
|
|
|
@@ -846,7 +856,7 @@ declare global {
|
|
|
846
856
|
declare global {
|
|
847
857
|
namespace JSX {
|
|
848
858
|
interface IntrinsicElements {
|
|
849
|
-
'gs-
|
|
859
|
+
'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
850
860
|
}
|
|
851
861
|
}
|
|
852
862
|
}
|
|
@@ -854,7 +864,7 @@ declare global {
|
|
|
854
864
|
|
|
855
865
|
declare global {
|
|
856
866
|
interface HTMLElementTagNameMap {
|
|
857
|
-
'gs-
|
|
867
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
858
868
|
}
|
|
859
869
|
}
|
|
860
870
|
|
|
@@ -862,7 +872,7 @@ declare global {
|
|
|
862
872
|
declare global {
|
|
863
873
|
namespace JSX {
|
|
864
874
|
interface IntrinsicElements {
|
|
865
|
-
'gs-
|
|
875
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
866
876
|
}
|
|
867
877
|
}
|
|
868
878
|
}
|
|
@@ -902,7 +912,7 @@ declare global {
|
|
|
902
912
|
|
|
903
913
|
declare global {
|
|
904
914
|
interface HTMLElementTagNameMap {
|
|
905
|
-
'gs-
|
|
915
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
906
916
|
}
|
|
907
917
|
}
|
|
908
918
|
|
|
@@ -910,7 +920,7 @@ declare global {
|
|
|
910
920
|
declare global {
|
|
911
921
|
namespace JSX {
|
|
912
922
|
interface IntrinsicElements {
|
|
913
|
-
'gs-
|
|
923
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
914
924
|
}
|
|
915
925
|
}
|
|
916
926
|
}
|
|
@@ -918,7 +928,7 @@ declare global {
|
|
|
918
928
|
|
|
919
929
|
declare global {
|
|
920
930
|
interface HTMLElementTagNameMap {
|
|
921
|
-
'gs-
|
|
931
|
+
'gs-aggregate': AggregateComponent;
|
|
922
932
|
}
|
|
923
933
|
}
|
|
924
934
|
|
|
@@ -926,7 +936,7 @@ declare global {
|
|
|
926
936
|
declare global {
|
|
927
937
|
namespace JSX {
|
|
928
938
|
interface IntrinsicElements {
|
|
929
|
-
'gs-
|
|
939
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
930
940
|
}
|
|
931
941
|
}
|
|
932
942
|
}
|
|
@@ -950,7 +960,7 @@ declare global {
|
|
|
950
960
|
|
|
951
961
|
declare global {
|
|
952
962
|
interface HTMLElementTagNameMap {
|
|
953
|
-
'gs-
|
|
963
|
+
'gs-sequences-by-location': SequencesByLocationComponent;
|
|
954
964
|
}
|
|
955
965
|
}
|
|
956
966
|
|
|
@@ -958,7 +968,7 @@ declare global {
|
|
|
958
968
|
declare global {
|
|
959
969
|
namespace JSX {
|
|
960
970
|
interface IntrinsicElements {
|
|
961
|
-
'gs-
|
|
971
|
+
'gs-sequences-by-location': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
962
972
|
}
|
|
963
973
|
}
|
|
964
974
|
}
|
|
@@ -966,7 +976,7 @@ declare global {
|
|
|
966
976
|
|
|
967
977
|
declare global {
|
|
968
978
|
interface HTMLElementTagNameMap {
|
|
969
|
-
'gs-
|
|
979
|
+
'gs-statistics': StatisticsComponent;
|
|
970
980
|
}
|
|
971
981
|
}
|
|
972
982
|
|
|
@@ -974,7 +984,7 @@ declare global {
|
|
|
974
984
|
declare global {
|
|
975
985
|
namespace JSX {
|
|
976
986
|
interface IntrinsicElements {
|
|
977
|
-
'gs-
|
|
987
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
978
988
|
}
|
|
979
989
|
}
|
|
980
990
|
}
|
|
@@ -1018,10 +1028,10 @@ declare global {
|
|
|
1018
1028
|
|
|
1019
1029
|
declare global {
|
|
1020
1030
|
interface HTMLElementTagNameMap {
|
|
1021
|
-
'gs-
|
|
1031
|
+
'gs-text-input': TextInputComponent;
|
|
1022
1032
|
}
|
|
1023
1033
|
interface HTMLElementEventMap {
|
|
1024
|
-
'gs-
|
|
1034
|
+
'gs-text-input-changed': TextInputChangedEvent;
|
|
1025
1035
|
}
|
|
1026
1036
|
}
|
|
1027
1037
|
|
|
@@ -1029,7 +1039,7 @@ declare global {
|
|
|
1029
1039
|
declare global {
|
|
1030
1040
|
namespace JSX {
|
|
1031
1041
|
interface IntrinsicElements {
|
|
1032
|
-
'gs-
|
|
1042
|
+
'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1033
1043
|
}
|
|
1034
1044
|
}
|
|
1035
1045
|
}
|
|
@@ -1037,10 +1047,10 @@ declare global {
|
|
|
1037
1047
|
|
|
1038
1048
|
declare global {
|
|
1039
1049
|
interface HTMLElementTagNameMap {
|
|
1040
|
-
'gs-
|
|
1050
|
+
'gs-location-filter': LocationFilterComponent;
|
|
1041
1051
|
}
|
|
1042
1052
|
interface HTMLElementEventMap {
|
|
1043
|
-
'gs-
|
|
1053
|
+
'gs-location-changed': LocationChangedEvent;
|
|
1044
1054
|
}
|
|
1045
1055
|
}
|
|
1046
1056
|
|
|
@@ -1048,7 +1058,7 @@ declare global {
|
|
|
1048
1058
|
declare global {
|
|
1049
1059
|
namespace JSX {
|
|
1050
1060
|
interface IntrinsicElements {
|
|
1051
|
-
'gs-
|
|
1061
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1052
1062
|
}
|
|
1053
1063
|
}
|
|
1054
1064
|
}
|
|
@@ -1056,10 +1066,10 @@ declare global {
|
|
|
1056
1066
|
|
|
1057
1067
|
declare global {
|
|
1058
1068
|
interface HTMLElementTagNameMap {
|
|
1059
|
-
'gs-
|
|
1069
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1060
1070
|
}
|
|
1061
1071
|
interface HTMLElementEventMap {
|
|
1062
|
-
'gs-
|
|
1072
|
+
'gs-lineage-filter-changed': LineageFilterChangedEvent;
|
|
1063
1073
|
}
|
|
1064
1074
|
}
|
|
1065
1075
|
|
|
@@ -1067,7 +1077,7 @@ declare global {
|
|
|
1067
1077
|
declare global {
|
|
1068
1078
|
namespace JSX {
|
|
1069
1079
|
interface IntrinsicElements {
|
|
1070
|
-
'gs-
|
|
1080
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1071
1081
|
}
|
|
1072
1082
|
}
|
|
1073
1083
|
}
|
|
@@ -1075,10 +1085,10 @@ declare global {
|
|
|
1075
1085
|
|
|
1076
1086
|
declare global {
|
|
1077
1087
|
interface HTMLElementTagNameMap {
|
|
1078
|
-
'gs-
|
|
1088
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
1079
1089
|
}
|
|
1080
1090
|
interface HTMLElementEventMap {
|
|
1081
|
-
'gs-
|
|
1091
|
+
'gs-mutation-filter-changed': CustomEvent<MutationsFilter>;
|
|
1082
1092
|
}
|
|
1083
1093
|
}
|
|
1084
1094
|
|
|
@@ -1086,7 +1096,7 @@ declare global {
|
|
|
1086
1096
|
declare global {
|
|
1087
1097
|
namespace JSX {
|
|
1088
1098
|
interface IntrinsicElements {
|
|
1089
|
-
'gs-
|
|
1099
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1090
1100
|
}
|
|
1091
1101
|
}
|
|
1092
1102
|
}
|
package/dist/util.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genspectrum/dashboard-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.2",
|
|
4
4
|
"description": "GenSpectrum web components for building dashboards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"types": "dist/genspectrum-components.d.ts",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/GenSpectrum/dashboard-components.git",
|
|
12
|
+
"url": "git+https://github.com/GenSpectrum/dashboard-components.git",
|
|
13
13
|
"directory": "components"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
package/src/lapisApi/lapisApi.ts
CHANGED
|
@@ -146,7 +146,7 @@ async function callLapis(
|
|
|
146
146
|
const handleErrors = async (response: Response, requestedData: string) => {
|
|
147
147
|
if (!response.ok) {
|
|
148
148
|
if (response.status >= 400 && response.status < 500) {
|
|
149
|
-
const json = await response.json();
|
|
149
|
+
const json = (await response.json()) as unknown;
|
|
150
150
|
|
|
151
151
|
const lapisErrorResult = lapisError.safeParse(json);
|
|
152
152
|
if (lapisErrorResult.success) {
|
|
@@ -23,6 +23,6 @@ describe('FillMissingOperator', () => {
|
|
|
23
23
|
(id) => ({ id }),
|
|
24
24
|
);
|
|
25
25
|
const result = await query.evaluate('lapis');
|
|
26
|
-
|
|
26
|
+
expectEqualAfterSorting(result.content, [{ id: 1 }, { id: 2 }, { id: 3 }], (a, b) => a.id - b.id);
|
|
27
27
|
});
|
|
28
28
|
});
|
|
@@ -14,7 +14,7 @@ describe('GroupByAndSumOperator', () => {
|
|
|
14
14
|
|
|
15
15
|
const query = new GroupByAndSumOperator(child, 'lineage', 'n');
|
|
16
16
|
const result = await query.evaluate('lapis');
|
|
17
|
-
|
|
17
|
+
expectEqualAfterSorting(
|
|
18
18
|
result.content,
|
|
19
19
|
[
|
|
20
20
|
{ lineage: 'A', n: 3 },
|
|
@@ -17,7 +17,7 @@ describe('GroupByOperator', () => {
|
|
|
17
17
|
n: values.length,
|
|
18
18
|
}));
|
|
19
19
|
const resultCount = await queryCount.evaluate('lapis');
|
|
20
|
-
|
|
20
|
+
expectEqualAfterSorting(
|
|
21
21
|
resultCount.content,
|
|
22
22
|
[
|
|
23
23
|
{ lineage: 'A', n: 2 },
|
|
@@ -31,7 +31,7 @@ describe('GroupByOperator', () => {
|
|
|
31
31
|
n: values.reduce((a, b) => a + b.n, 0),
|
|
32
32
|
}));
|
|
33
33
|
const resultSum = await querySum.evaluate('lapis');
|
|
34
|
-
|
|
34
|
+
expectEqualAfterSorting(
|
|
35
35
|
resultSum.content,
|
|
36
36
|
[
|
|
37
37
|
{ lineage: 'A', n: 3 },
|
|
@@ -8,6 +8,6 @@ describe('MapOperator', () => {
|
|
|
8
8
|
const child = new MockOperator([1, 2, 3]);
|
|
9
9
|
const query = new MapOperator(child, (x) => x * 2);
|
|
10
10
|
const result = await query.evaluate('lapis');
|
|
11
|
-
|
|
11
|
+
expect(result.content).deep.equal([2, 4, 6]);
|
|
12
12
|
});
|
|
13
13
|
});
|
|
@@ -6,6 +6,6 @@ describe('MockOperator', () => {
|
|
|
6
6
|
it('should be a mock', async () => {
|
|
7
7
|
const query = new MockOperator([1, 2, 3]);
|
|
8
8
|
const result = await query.evaluate();
|
|
9
|
-
|
|
9
|
+
expect(result.content).to.deep.equal([1, 2, 3]);
|
|
10
10
|
});
|
|
11
11
|
});
|
|
@@ -4,9 +4,11 @@ import { type Operator } from './Operator';
|
|
|
4
4
|
export class MockOperator<T> implements Operator<T> {
|
|
5
5
|
constructor(private content: T[]) {}
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
evaluate(): Promise<Dataset<T>> {
|
|
8
|
+
return new Promise((resolve) =>
|
|
9
|
+
resolve({
|
|
10
|
+
content: this.content,
|
|
11
|
+
}),
|
|
12
|
+
);
|
|
11
13
|
}
|
|
12
14
|
}
|
|
@@ -8,6 +8,6 @@ describe('SortOperator', () => {
|
|
|
8
8
|
const child = new MockOperator([3, 1, 2]);
|
|
9
9
|
const query = new SortOperator(child, (a, b) => a - b);
|
|
10
10
|
const result = await query.evaluate('lapis');
|
|
11
|
-
|
|
11
|
+
expect(result.content).deep.equal([1, 2, 3]);
|
|
12
12
|
});
|
|
13
13
|
});
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import { createContext } from 'preact';
|
|
2
|
+
import { useContext } from 'preact/hooks';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
const LapisUrlContext = createContext('');
|
|
5
|
+
|
|
6
|
+
export const LapisUrlContextProvider = LapisUrlContext.Provider;
|
|
7
|
+
|
|
8
|
+
export const useLapisUrl = () => {
|
|
9
|
+
const lapisUrl = useContext(LapisUrlContext);
|
|
10
|
+
|
|
11
|
+
if (lapisUrl.endsWith('/')) {
|
|
12
|
+
return lapisUrl.slice(0, -1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return lapisUrl;
|
|
16
|
+
};
|
|
@@ -4,7 +4,7 @@ import { expect, waitFor, within } from '@storybook/test';
|
|
|
4
4
|
import aggregatedData from './__mockData__/aggregated.json';
|
|
5
5
|
import { Aggregate, type AggregateProps } from './aggregate';
|
|
6
6
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
7
|
-
import {
|
|
7
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
8
8
|
import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
9
9
|
|
|
10
10
|
const meta: Meta<AggregateProps> = {
|
|
@@ -44,9 +44,9 @@ export default meta;
|
|
|
44
44
|
|
|
45
45
|
export const Default: StoryObj<AggregateProps> = {
|
|
46
46
|
render: (args) => (
|
|
47
|
-
<
|
|
47
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
48
48
|
<Aggregate {...args} />
|
|
49
|
-
</
|
|
49
|
+
</LapisUrlContextProvider>
|
|
50
50
|
),
|
|
51
51
|
args: {
|
|
52
52
|
fields: ['division', 'host'],
|
|
@@ -104,7 +104,7 @@ export const WithEmptyFieldString: StoryObj<AggregateProps> = {
|
|
|
104
104
|
fields: [''],
|
|
105
105
|
},
|
|
106
106
|
play: async ({ canvasElement, step }) => {
|
|
107
|
-
step('expect error message', async () => {
|
|
107
|
+
await step('expect error message', async () => {
|
|
108
108
|
await expectInvalidAttributesErrorMessage(canvasElement, 'String must contain at least 1 character(s)');
|
|
109
109
|
});
|
|
110
110
|
},
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
|
-
import { useContext } from 'preact/hooks';
|
|
3
2
|
import z from 'zod';
|
|
4
3
|
|
|
4
|
+
import { useLapisUrl } from '../LapisUrlContext';
|
|
5
5
|
import { AggregateTable } from './aggregate-table';
|
|
6
6
|
import { type AggregateData, queryAggregateData } from '../../query/queryAggregateData';
|
|
7
7
|
import { lapisFilterSchema, views } from '../../types';
|
|
8
|
-
import { LapisUrlContext } from '../LapisUrlContext';
|
|
9
8
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
10
9
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
11
10
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -48,7 +47,7 @@ export const Aggregate: FunctionComponent<AggregateProps> = (componentProps) =>
|
|
|
48
47
|
|
|
49
48
|
export const AggregateInner: FunctionComponent<AggregateProps> = (componentProps) => {
|
|
50
49
|
const { fields, lapisFilter, initialSortField, initialSortDirection } = componentProps;
|
|
51
|
-
const lapis =
|
|
50
|
+
const lapis = useLapisUrl();
|
|
52
51
|
|
|
53
52
|
const { data, error, isLoading } = useQuery(async () => {
|
|
54
53
|
return queryAggregateData(lapisFilter, fields, lapis);
|
|
@@ -129,7 +128,7 @@ type AggregateInfoProps = {
|
|
|
129
128
|
};
|
|
130
129
|
|
|
131
130
|
const AggregateInfo: FunctionComponent<AggregateInfoProps> = ({ originalComponentProps }) => {
|
|
132
|
-
const lapis =
|
|
131
|
+
const lapis = useLapisUrl();
|
|
133
132
|
return (
|
|
134
133
|
<Info>
|
|
135
134
|
<InfoHeadline1>Aggregated data</InfoHeadline1>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type StoryObj } from '@storybook/preact';
|
|
2
2
|
import { type Meta } from '@storybook/web-components';
|
|
3
3
|
|
|
4
|
-
import { CsvDownloadButton, type CsvDownloadButtonProps } from './csv-download-button';
|
|
4
|
+
import { CsvDownloadButton, type CsvDownloadButtonProps, type DataValue } from './csv-download-button';
|
|
5
5
|
|
|
6
6
|
const meta: Meta<CsvDownloadButtonProps> = {
|
|
7
7
|
title: 'Component/CSV Download Button',
|
|
@@ -10,7 +10,7 @@ const meta: Meta<CsvDownloadButtonProps> = {
|
|
|
10
10
|
|
|
11
11
|
export default meta;
|
|
12
12
|
|
|
13
|
-
export const DownloadButton: StoryObj = {
|
|
13
|
+
export const DownloadButton: StoryObj<CsvDownloadButtonProps & { data: Record<string, DataValue>[] }> = {
|
|
14
14
|
render: (args) => {
|
|
15
15
|
return <CsvDownloadButton label={args.label} filename={args.filename} getData={() => args.data} />;
|
|
16
16
|
},
|
|
@@ -4,7 +4,7 @@ type ToStringable = {
|
|
|
4
4
|
toString: () => string;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
type DataValue = string | number | boolean | null | ToStringable;
|
|
7
|
+
export type DataValue = string | number | boolean | null | undefined | ToStringable;
|
|
8
8
|
|
|
9
9
|
export interface CsvDownloadButtonProps {
|
|
10
10
|
label?: string;
|
|
@@ -2,7 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
|
|
|
2
2
|
import { expect, waitFor, within } from '@storybook/test';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
|
|
5
|
-
import { ErrorBoundary } from './error-boundary';
|
|
5
|
+
import { ErrorBoundary, type ErrorBoundaryProps } from './error-boundary';
|
|
6
6
|
import { UserFacingError } from './error-display';
|
|
7
7
|
|
|
8
8
|
const meta: Meta = {
|
|
@@ -28,7 +28,7 @@ const someSchema = z.object({
|
|
|
28
28
|
const someValidProps = { test: 'someValue' };
|
|
29
29
|
const someInvalidProps = { test: '' };
|
|
30
30
|
|
|
31
|
-
export const ErrorBoundaryWithoutErrorStory: StoryObj = {
|
|
31
|
+
export const ErrorBoundaryWithoutErrorStory: StoryObj<ErrorBoundaryProps<typeof someValidProps>> = {
|
|
32
32
|
render: (args) => (
|
|
33
33
|
<ErrorBoundary size={args.size} schema={someSchema} componentProps={someValidProps}>
|
|
34
34
|
<div>Some content</div>
|
|
@@ -41,7 +41,7 @@ export const ErrorBoundaryWithoutErrorStory: StoryObj = {
|
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
export const ErrorBoundaryWithErrorStory: StoryObj = {
|
|
44
|
+
export const ErrorBoundaryWithErrorStory: StoryObj<ErrorBoundaryProps<typeof someValidProps>> = {
|
|
45
45
|
render: (args) => (
|
|
46
46
|
<ErrorBoundary size={args.size} schema={someSchema} componentProps={someValidProps}>
|
|
47
47
|
<ContentThatThrowsError error={() => new Error('Some error')} />
|
|
@@ -55,7 +55,7 @@ export const ErrorBoundaryWithErrorStory: StoryObj = {
|
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
export const ErrorBoundaryWithParsingErrorStory: StoryObj = {
|
|
58
|
+
export const ErrorBoundaryWithParsingErrorStory: StoryObj<ErrorBoundaryProps<typeof someValidProps>> = {
|
|
59
59
|
render: (args) => (
|
|
60
60
|
<ErrorBoundary size={args.size} schema={someSchema} componentProps={someInvalidProps}>
|
|
61
61
|
<ContentThatThrowsError error={() => new Error('Some error')} />
|
|
@@ -69,7 +69,7 @@ export const ErrorBoundaryWithParsingErrorStory: StoryObj = {
|
|
|
69
69
|
},
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
export const ErrorBoundaryWithUserFacingErrorStory: StoryObj = {
|
|
72
|
+
export const ErrorBoundaryWithUserFacingErrorStory: StoryObj<ErrorBoundaryProps<typeof someValidProps>> = {
|
|
73
73
|
render: (args) => (
|
|
74
74
|
<ErrorBoundary size={args.size} schema={someSchema} componentProps={someValidProps}>
|
|
75
75
|
<ContentThatThrowsError error={() => new UserFacingError('Error Headline', 'Some error')} />
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type RenderableProps } from 'preact';
|
|
2
|
-
import { useErrorBoundary, useMemo } from 'preact/hooks';
|
|
2
|
+
import { useEffect, useErrorBoundary, useMemo } from 'preact/hooks';
|
|
3
3
|
import { type ZodSchema } from 'zod';
|
|
4
4
|
|
|
5
5
|
import { ErrorDisplay, type ErrorDisplayProps, InvalidPropsError } from './error-display';
|
|
6
6
|
import { ResizeContainer, type Size } from './resize-container';
|
|
7
7
|
|
|
8
|
-
type ErrorBoundaryProps<T> = {
|
|
8
|
+
export type ErrorBoundaryProps<T> = {
|
|
9
9
|
size: Size;
|
|
10
10
|
componentProps: T;
|
|
11
11
|
schema: ZodSchema<T>;
|
|
@@ -19,13 +19,24 @@ export const ErrorBoundary = <T extends Record<string, unknown>>({
|
|
|
19
19
|
schema,
|
|
20
20
|
children,
|
|
21
21
|
}: RenderableProps<ErrorBoundaryProps<T>>) => {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- useErrorBoundary unfortunately return `[any, ...]`
|
|
22
23
|
const [internalError, resetError] = useErrorBoundary();
|
|
23
24
|
const componentPropsParseError = useCheckComponentProps(schema, componentProps);
|
|
24
25
|
|
|
26
|
+
useEffect(
|
|
27
|
+
() => {
|
|
28
|
+
if (internalError) {
|
|
29
|
+
resetError();
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- this should run if and only if the props of the component change
|
|
33
|
+
[componentProps],
|
|
34
|
+
);
|
|
35
|
+
|
|
25
36
|
if (internalError) {
|
|
26
37
|
return (
|
|
27
38
|
<ResizeContainer size={size}>
|
|
28
|
-
<ErrorDisplay error={internalError} resetError={resetError} layout={layout} />
|
|
39
|
+
<ErrorDisplay error={internalError as Error} resetError={resetError} layout={layout} />
|
|
29
40
|
</ResizeContainer>
|
|
30
41
|
);
|
|
31
42
|
}
|
|
@@ -39,12 +39,12 @@ export const UserFacingErrorStory: StoryObj = {
|
|
|
39
39
|
const error = canvas.getByText('Oops! Something went wrong.', { exact: false });
|
|
40
40
|
const detailMessage = () => canvas.getByText('some message');
|
|
41
41
|
await waitFor(() => expect(error).toBeInTheDocument());
|
|
42
|
-
await waitFor(() => {
|
|
43
|
-
expect(detailMessage()).not.toBeVisible();
|
|
42
|
+
await waitFor(async () => {
|
|
43
|
+
await expect(detailMessage()).not.toBeVisible();
|
|
44
44
|
});
|
|
45
45
|
await userEvent.click(canvas.getByText('Show details.'));
|
|
46
|
-
await waitFor(() => {
|
|
47
|
-
expect(detailMessage()).toBeVisible();
|
|
46
|
+
await waitFor(async () => {
|
|
47
|
+
await expect(detailMessage()).toBeVisible();
|
|
48
48
|
});
|
|
49
49
|
},
|
|
50
50
|
};
|
|
@@ -60,9 +60,9 @@ export const FiresEvent: StoryObj = {
|
|
|
60
60
|
const listenerMock = fn();
|
|
61
61
|
canvasElement.addEventListener('gs-error', listenerMock);
|
|
62
62
|
|
|
63
|
-
await waitFor(() => {
|
|
64
|
-
expect(listenerMock.mock.calls.at(-1)![0].error.name).toStrictEqual('UserFacingError');
|
|
65
|
-
expect(listenerMock.mock.calls.at(-1)![0].error.message).toStrictEqual('some message');
|
|
63
|
+
await waitFor(async () => {
|
|
64
|
+
await expect(listenerMock.mock.calls.at(-1)![0].error.name).toStrictEqual('UserFacingError');
|
|
65
|
+
await expect(listenerMock.mock.calls.at(-1)![0].error.message).toStrictEqual('some message');
|
|
66
66
|
});
|
|
67
67
|
},
|
|
68
68
|
};
|
|
@@ -81,8 +81,8 @@ export const TriggersResetErrorOnReloadButton: StoryObj = {
|
|
|
81
81
|
|
|
82
82
|
await userEvent.click(canvas.getByText('Try again'));
|
|
83
83
|
|
|
84
|
-
await waitFor(() => {
|
|
85
|
-
expect(resetErrorMock).toHaveBeenCalled();
|
|
84
|
+
await waitFor(async () => {
|
|
85
|
+
await expect(resetErrorMock).toHaveBeenCalled();
|
|
86
86
|
});
|
|
87
87
|
},
|
|
88
88
|
};
|
|
@@ -6,14 +6,14 @@ export const Fullscreen = () => {
|
|
|
6
6
|
return (
|
|
7
7
|
<button
|
|
8
8
|
ref={element}
|
|
9
|
-
onClick={
|
|
9
|
+
onClick={() => {
|
|
10
10
|
if (element.current) {
|
|
11
11
|
if (isFullscreen) {
|
|
12
|
-
|
|
12
|
+
void document.exitFullscreen();
|
|
13
13
|
} else {
|
|
14
14
|
const componentRoot = findComponentRoot(element.current);
|
|
15
15
|
if (componentRoot) {
|
|
16
|
-
|
|
16
|
+
void componentRoot.requestFullscreen();
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -97,7 +97,7 @@ function componentParametersToCode(componentName: string, params: object, lapisU
|
|
|
97
97
|
|
|
98
98
|
const attributes = indentLines(
|
|
99
99
|
Object.entries(params)
|
|
100
|
-
.map(([key, value]) => `${key}='${stringifyIfNeeded(value)}'`)
|
|
100
|
+
.map(([key, value]) => `${key}='${stringifyIfNeeded(value) as string}'`)
|
|
101
101
|
.join('\n'),
|
|
102
102
|
4,
|
|
103
103
|
);
|
|
@@ -108,7 +108,7 @@ export const OneTypesSelected: StoryObj<MutationTypeSelectorProps> = {
|
|
|
108
108
|
const canvas = within(canvasElement);
|
|
109
109
|
|
|
110
110
|
await step('Show the selected type as label', async () => {
|
|
111
|
-
const substitutionElements =
|
|
111
|
+
const substitutionElements = canvas.getAllByText('Substitution');
|
|
112
112
|
await expect(substitutionElements.length).toBe(2);
|
|
113
113
|
});
|
|
114
114
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Meta, type StoryObj } from '@storybook/preact';
|
|
2
2
|
import { expect, userEvent, waitFor, within } from '@storybook/test';
|
|
3
3
|
|
|
4
|
-
import { Table } from './table';
|
|
4
|
+
import { Table, type TableProps } from './table';
|
|
5
5
|
|
|
6
6
|
const meta: Meta = {
|
|
7
7
|
title: 'Component/Table',
|
|
@@ -16,7 +16,7 @@ const meta: Meta = {
|
|
|
16
16
|
|
|
17
17
|
export default meta;
|
|
18
18
|
|
|
19
|
-
export const TableStory: StoryObj = {
|
|
19
|
+
export const TableStory: StoryObj<TableProps> = {
|
|
20
20
|
render: (args) => {
|
|
21
21
|
return <Table data={args.data} columns={args.columns} pageSize={args.pageSize} />;
|
|
22
22
|
},
|
|
@@ -49,7 +49,7 @@ export const TableStory: StoryObj = {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
export const TableStoryNoPagination: StoryObj = {
|
|
52
|
+
export const TableStoryNoPagination: StoryObj<TableProps> = {
|
|
53
53
|
render: (args) => {
|
|
54
54
|
return <Table data={args.data} columns={args.columns} pageSize={args.pageSize} />;
|
|
55
55
|
},
|