@genspectrum/dashboard-components 0.10.1 → 0.10.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 +23 -23
- package/dist/assets/{mutationOverTimeWorker-CvZg52rf.js.map → mutationOverTimeWorker-Di6yP1e6.js.map} +1 -1
- package/dist/components.d.ts +50 -48
- package/dist/components.js +151 -62
- package/dist/components.js.map +1 -1
- package/dist/{utilEntrypoint-g4DsyhU7.js → dateRangeOption-du8H7LWu.js} +33 -2
- package/dist/dateRangeOption-du8H7LWu.js.map +1 -0
- package/dist/util.d.ts +101 -59
- package/dist/util.js +3 -2
- package/package.json +1 -1
- package/src/preact/components/color-scale-selector.tsx +7 -3
- package/src/preact/components/error-boundary.tsx +39 -5
- package/src/preact/components/error-display.tsx +40 -5
- package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +8 -2
- package/src/preact/dateRangeSelector/computeInitialValues.ts +6 -0
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +16 -2
- package/src/preact/dateRangeSelector/date-range-selector.tsx +20 -15
- package/src/preact/dateRangeSelector/dateRangeOption.ts +10 -5
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +18 -4
- package/src/preact/lineageFilter/lineage-filter.tsx +15 -10
- package/src/preact/locationFilter/location-filter.stories.tsx +14 -0
- package/src/preact/locationFilter/location-filter.tsx +15 -10
- package/src/preact/mutationComparison/mutation-comparison-venn.tsx +17 -18
- package/src/preact/mutationComparison/mutation-comparison.tsx +18 -12
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +1326 -9341
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +615 -4920
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +2203 -17624
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +16 -8
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +1 -3
- package/src/preact/shared/stories/expectInvalidAttributesErrorMessage.ts +13 -0
- package/src/preact/webWorkers/useWebWorker.ts +8 -4
- package/src/query/queryMutationsOverTime.spec.ts +12 -27
- package/src/query/queryMutationsOverTime.ts +2 -6
- package/src/types.ts +19 -6
- package/src/utilEntrypoint.ts +8 -0
- package/src/utils/map2d.spec.ts +10 -10
- package/src/utils/map2d.ts +10 -10
- package/src/web-components/input/gs-date-range-selector.stories.ts +2 -2
- package/src/web-components/input/gs-date-range-selector.tsx +3 -3
- package/src/web-components/input/gs-lineage-filter.tsx +1 -1
- package/src/web-components/input/gs-location-filter.tsx +2 -2
- package/src/web-components/visualization/gs-aggregate.tsx +2 -2
- package/standalone-bundle/assets/{mutationOverTimeWorker-CypX_PYM.js.map → mutationOverTimeWorker-cIyshfj_.js.map} +1 -1
- package/standalone-bundle/dashboard-components.js +6668 -6580
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/utilEntrypoint-g4DsyhU7.js.map +0 -1
|
@@ -1,7 +1,33 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
const lapisFilterSchema = z.record(z.union([z.string(), z.number(), z.null(), z.boolean()]));
|
|
3
|
+
const namedLapisFilterSchema = z.object({
|
|
4
|
+
lapisFilter: lapisFilterSchema,
|
|
5
|
+
displayName: z.string()
|
|
6
|
+
});
|
|
7
|
+
const sequenceTypeSchema = z.union([z.literal("nucleotide"), z.literal("amino acid")]);
|
|
8
|
+
const views = {
|
|
9
|
+
table: "table",
|
|
10
|
+
venn: "venn"
|
|
11
|
+
};
|
|
12
|
+
const mutationComparisonViewSchema = z.union([z.literal(views.table), z.literal(views.venn)]);
|
|
1
13
|
const toYYYYMMDD = (date) => {
|
|
2
14
|
const options = { year: "numeric", month: "2-digit", day: "2-digit" };
|
|
3
15
|
return date.toLocaleDateString("en-CA", options);
|
|
4
16
|
};
|
|
17
|
+
const dateRangeOptionSchema = z.object({
|
|
18
|
+
/** The label of the date range option that will be shown to the user */
|
|
19
|
+
label: z.string(),
|
|
20
|
+
/**
|
|
21
|
+
* The start date of the date range in the format `YYYY-MM-DD`.
|
|
22
|
+
* If not set, the date range selector will default to the `earliestDate` property.
|
|
23
|
+
*/
|
|
24
|
+
dateFrom: z.string().date().optional(),
|
|
25
|
+
/**
|
|
26
|
+
* The end date of the date range in the format `YYYY-MM-DD`.
|
|
27
|
+
* If not set, the date range selector will default to the current date.
|
|
28
|
+
*/
|
|
29
|
+
dateTo: z.string().date().optional()
|
|
30
|
+
});
|
|
5
31
|
class DateRangeOptionChangedEvent extends CustomEvent {
|
|
6
32
|
constructor(detail) {
|
|
7
33
|
super("gs-date-range-option-changed", {
|
|
@@ -55,7 +81,12 @@ const dateRangeOptionPresets = {
|
|
|
55
81
|
};
|
|
56
82
|
export {
|
|
57
83
|
DateRangeOptionChangedEvent as D,
|
|
84
|
+
dateRangeOptionSchema as a,
|
|
58
85
|
dateRangeOptionPresets as d,
|
|
59
|
-
|
|
86
|
+
mutationComparisonViewSchema as m,
|
|
87
|
+
namedLapisFilterSchema as n,
|
|
88
|
+
sequenceTypeSchema as s,
|
|
89
|
+
toYYYYMMDD as t,
|
|
90
|
+
views as v
|
|
60
91
|
};
|
|
61
|
-
//# sourceMappingURL=
|
|
92
|
+
//# sourceMappingURL=dateRangeOption-du8H7LWu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dateRangeOption-du8H7LWu.js","sources":["../src/types.ts","../src/preact/dateRangeSelector/dateConversion.ts","../src/preact/dateRangeSelector/dateRangeOption.ts"],"sourcesContent":["import z from 'zod';\n\nimport {\n type Deletion,\n type DeletionClass,\n type Insertion,\n type InsertionClass,\n type Substitution,\n type SubstitutionClass,\n} from './utils/mutations';\n\nexport const lapisFilterSchema = z.record(z.union([z.string(), z.number(), z.null(), z.boolean()]));\nexport type LapisFilter = z.infer<typeof lapisFilterSchema>;\n\nexport const namedLapisFilterSchema = z.object({\n lapisFilter: lapisFilterSchema,\n displayName: z.string(),\n});\nexport type NamedLapisFilter = z.infer<typeof namedLapisFilterSchema>;\n\nexport type TemporalGranularity = 'day' | 'week' | 'month' | 'year';\n\nexport const sequenceTypeSchema = z.union([z.literal('nucleotide'), z.literal('amino acid')]);\nexport type SequenceType = z.infer<typeof sequenceTypeSchema>;\n\nexport type SubstitutionOrDeletion = 'substitution' | 'deletion';\n\nexport type MutationType = SubstitutionOrDeletion | 'insertion';\n\nexport type SubstitutionEntry<T extends Substitution = SubstitutionClass> = {\n type: 'substitution';\n mutation: T;\n count: number;\n proportion: number;\n};\n\nexport type DeletionEntry<T extends Deletion = DeletionClass> = {\n type: 'deletion';\n mutation: T;\n count: number;\n proportion: number;\n};\n\nexport type InsertionEntry<T extends Insertion = InsertionClass> = { type: 'insertion'; mutation: T; count: number };\n\nexport type SubstitutionOrDeletionEntry<\n S extends Substitution = SubstitutionClass,\n D extends Deletion = DeletionClass,\n> = SubstitutionEntry<S> | DeletionEntry<D>;\n\nexport type MutationEntry = SubstitutionEntry | DeletionEntry | InsertionEntry;\n\nexport const views = {\n table: 'table',\n venn: 'venn',\n} as const;\n\nexport const mutationComparisonViewSchema = z.union([z.literal(views.table), z.literal(views.venn)]);\nexport type MutationComparisonView = z.infer<typeof mutationComparisonViewSchema>;\n","export const toYYYYMMDD = (date: Date) => {\n const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };\n return date.toLocaleDateString('en-CA', options);\n};\n","import z from 'zod';\n\nimport { toYYYYMMDD } from './dateConversion';\n\n/**\n * A date range option that can be used in the `gs-date-range-selector` component.\n */\nexport const dateRangeOptionSchema = z.object({\n /** The label of the date range option that will be shown to the user */\n label: z.string(),\n /**\n * The start date of the date range in the format `YYYY-MM-DD`.\n * If not set, the date range selector will default to the `earliestDate` property.\n */\n dateFrom: z.string().date().optional(),\n /**\n * The end date of the date range in the format `YYYY-MM-DD`.\n * If not set, the date range selector will default to the current date.\n */\n dateTo: z.string().date().optional(),\n});\n\nexport type DateRangeOption = z.infer<typeof dateRangeOptionSchema>;\n\nexport type DateRangeSelectOption = string | { dateFrom: string; dateTo: string };\n\nexport class DateRangeOptionChangedEvent extends CustomEvent<DateRangeSelectOption> {\n constructor(detail: DateRangeSelectOption) {\n super('gs-date-range-option-changed', {\n detail,\n bubbles: true,\n composed: true,\n });\n }\n}\n\nconst today = new Date();\n\nconst twoWeeksAgo = new Date();\ntwoWeeksAgo.setDate(today.getDate() - 14);\n\nconst lastMonth = new Date(today);\nlastMonth.setMonth(today.getMonth() - 1);\n\nconst last2Months = new Date(today);\nlast2Months.setMonth(today.getMonth() - 2);\n\nconst last3Months = new Date(today);\nlast3Months.setMonth(today.getMonth() - 3);\n\nconst last6Months = new Date(today);\nlast6Months.setMonth(today.getMonth() - 6);\n\nconst lastYear = new Date(today);\nlastYear.setFullYear(today.getFullYear() - 1);\n\n/**\n * Presets for the `gs-date-range-selector` component that can be used as `dateRangeOptions`.\n */\nexport const dateRangeOptionPresets = {\n last2Weeks: {\n label: 'Last 2 weeks',\n dateFrom: toYYYYMMDD(twoWeeksAgo),\n },\n lastMonth: {\n label: 'Last month',\n dateFrom: toYYYYMMDD(lastMonth),\n },\n last2Months: {\n label: 'Last 2 months',\n dateFrom: toYYYYMMDD(last2Months),\n },\n last3Months: {\n label: 'Last 3 months',\n dateFrom: toYYYYMMDD(last3Months),\n },\n last6Months: {\n label: 'Last 6 months',\n dateFrom: toYYYYMMDD(last6Months),\n },\n lastYear: {\n label: 'Last year',\n dateFrom: toYYYYMMDD(lastYear),\n },\n allTimes: {\n label: 'All times',\n },\n} satisfies Record<string, DateRangeOption>;\n"],"names":[],"mappings":";AAWO,MAAM,oBAAoB,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,KAAK,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGrF,MAAA,yBAAyB,EAAE,OAAO;AAAA,EAC3C,aAAa;AAAA,EACb,aAAa,EAAE,OAAO;AAC1B,CAAC;AAKM,MAAM,qBAAqB,EAAE,MAAM,CAAC,EAAE,QAAQ,YAAY,GAAG,EAAE,QAAQ,YAAY,CAAC,CAAC;AA8BrF,MAAM,QAAQ;AAAA,EACjB,OAAO;AAAA,EACP,MAAM;AACV;AAEO,MAAM,+BAA+B,EAAE,MAAM,CAAC,EAAE,QAAQ,MAAM,KAAK,GAAG,EAAE,QAAQ,MAAM,IAAI,CAAC,CAAC;ACzDtF,MAAA,aAAa,CAAC,SAAe;AACtC,QAAM,UAAsC,EAAE,MAAM,WAAW,OAAO,WAAW,KAAK;AAC/E,SAAA,KAAK,mBAAmB,SAAS,OAAO;AACnD;ACIa,MAAA,wBAAwB,EAAE,OAAO;AAAA;AAAA,EAE1C,OAAO,EAAE,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKhB,UAAU,EAAE,OAAS,EAAA,KAAA,EAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrC,QAAQ,EAAE,OAAS,EAAA,KAAA,EAAO,SAAS;AACvC,CAAC;AAMM,MAAM,oCAAoC,YAAmC;AAAA,EAChF,YAAY,QAA+B;AACvC,UAAM,gCAAgC;AAAA,MAClC;AAAA,MACA,SAAS;AAAA,MACT,UAAU;AAAA,IAAA,CACb;AAAA,EACL;AACJ;AAEA,MAAM,4BAAY;AAElB,MAAM,kCAAkB;AACxB,YAAY,QAAQ,MAAM,QAAQ,IAAI,EAAE;AAExC,MAAM,YAAY,IAAI,KAAK,KAAK;AAChC,UAAU,SAAS,MAAM,SAAS,IAAI,CAAC;AAEvC,MAAM,cAAc,IAAI,KAAK,KAAK;AAClC,YAAY,SAAS,MAAM,SAAS,IAAI,CAAC;AAEzC,MAAM,cAAc,IAAI,KAAK,KAAK;AAClC,YAAY,SAAS,MAAM,SAAS,IAAI,CAAC;AAEzC,MAAM,cAAc,IAAI,KAAK,KAAK;AAClC,YAAY,SAAS,MAAM,SAAS,IAAI,CAAC;AAEzC,MAAM,WAAW,IAAI,KAAK,KAAK;AAC/B,SAAS,YAAY,MAAM,YAAY,IAAI,CAAC;AAKrC,MAAM,yBAAyB;AAAA,EAClC,YAAY;AAAA,IACR,OAAO;AAAA,IACP,UAAU,WAAW,WAAW;AAAA,EACpC;AAAA,EACA,WAAW;AAAA,IACP,OAAO;AAAA,IACP,UAAU,WAAW,SAAS;AAAA,EAClC;AAAA,EACA,aAAa;AAAA,IACT,OAAO;AAAA,IACP,UAAU,WAAW,WAAW;AAAA,EACpC;AAAA,EACA,aAAa;AAAA,IACT,OAAO;AAAA,IACP,UAAU,WAAW,WAAW;AAAA,EACpC;AAAA,EACA,aAAa;AAAA,IACT,OAAO;AAAA,IACP,UAAU,WAAW,WAAW;AAAA,EACpC;AAAA,EACA,UAAU;AAAA,IACN,OAAO;AAAA,IACP,UAAU,WAAW,QAAQ;AAAA,EACjC;AAAA,EACA,UAAU;AAAA,IACN,OAAO;AAAA,EACX;AACJ;"}
|
package/dist/util.d.ts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare type DateRangeOption = {
|
|
5
|
-
/** The label of the date range option that will be shown to the user */
|
|
6
|
-
label: string;
|
|
7
|
-
/**
|
|
8
|
-
* The start date of the date range in the format `YYYY-MM-DD`.
|
|
9
|
-
* If not set, the date range selector will default to the `earliestDate` property.
|
|
10
|
-
*/
|
|
11
|
-
dateFrom?: string;
|
|
12
|
-
/**
|
|
13
|
-
* The end date of the date range in the format `YYYY-MM-DD`.
|
|
14
|
-
* If not set, the date range selector will default to the current date.
|
|
15
|
-
*/
|
|
16
|
-
dateTo?: string;
|
|
17
|
-
};
|
|
1
|
+
import { default as default_2 } from 'zod';
|
|
2
|
+
|
|
3
|
+
export declare type DateRangeOption = default_2.infer<typeof dateRangeOptionSchema>;
|
|
18
4
|
|
|
19
5
|
export declare class DateRangeOptionChangedEvent extends CustomEvent<DateRangeSelectOption> {
|
|
20
6
|
constructor(detail: DateRangeSelectOption);
|
|
@@ -53,11 +39,67 @@ export declare const dateRangeOptionPresets: {
|
|
|
53
39
|
};
|
|
54
40
|
};
|
|
55
41
|
|
|
42
|
+
/**
|
|
43
|
+
* A date range option that can be used in the `gs-date-range-selector` component.
|
|
44
|
+
*/
|
|
45
|
+
declare const dateRangeOptionSchema: default_2.ZodObject<{
|
|
46
|
+
/** The label of the date range option that will be shown to the user */
|
|
47
|
+
label: default_2.ZodString;
|
|
48
|
+
/**
|
|
49
|
+
* The start date of the date range in the format `YYYY-MM-DD`.
|
|
50
|
+
* If not set, the date range selector will default to the `earliestDate` property.
|
|
51
|
+
*/
|
|
52
|
+
dateFrom: default_2.ZodOptional<default_2.ZodString>;
|
|
53
|
+
/**
|
|
54
|
+
* The end date of the date range in the format `YYYY-MM-DD`.
|
|
55
|
+
* If not set, the date range selector will default to the current date.
|
|
56
|
+
*/
|
|
57
|
+
dateTo: default_2.ZodOptional<default_2.ZodString>;
|
|
58
|
+
}, "strip", default_2.ZodTypeAny, {
|
|
59
|
+
label: string;
|
|
60
|
+
dateFrom?: string | undefined;
|
|
61
|
+
dateTo?: string | undefined;
|
|
62
|
+
}, {
|
|
63
|
+
label: string;
|
|
64
|
+
dateFrom?: string | undefined;
|
|
65
|
+
dateTo?: string | undefined;
|
|
66
|
+
}>;
|
|
67
|
+
|
|
56
68
|
export declare type DateRangeSelectOption = string | {
|
|
57
69
|
dateFrom: string;
|
|
58
70
|
dateTo: string;
|
|
59
71
|
};
|
|
60
72
|
|
|
73
|
+
export declare type LapisFilter = default_2.infer<typeof lapisFilterSchema>;
|
|
74
|
+
|
|
75
|
+
declare const lapisFilterSchema: default_2.ZodRecord<default_2.ZodString, default_2.ZodUnion<[default_2.ZodString, default_2.ZodNumber, default_2.ZodNull, default_2.ZodBoolean]>>;
|
|
76
|
+
|
|
77
|
+
export declare type MutationComparisonView = default_2.infer<typeof mutationComparisonViewSchema>;
|
|
78
|
+
|
|
79
|
+
declare const mutationComparisonViewSchema: default_2.ZodUnion<[default_2.ZodLiteral<"table">, default_2.ZodLiteral<"venn">]>;
|
|
80
|
+
|
|
81
|
+
export declare type NamedLapisFilter = default_2.infer<typeof namedLapisFilterSchema>;
|
|
82
|
+
|
|
83
|
+
declare const namedLapisFilterSchema: default_2.ZodObject<{
|
|
84
|
+
lapisFilter: default_2.ZodRecord<default_2.ZodString, default_2.ZodUnion<[default_2.ZodString, default_2.ZodNumber, default_2.ZodNull, default_2.ZodBoolean]>>;
|
|
85
|
+
displayName: default_2.ZodString;
|
|
86
|
+
}, "strip", default_2.ZodTypeAny, {
|
|
87
|
+
lapisFilter: Record<string, string | number | boolean | null>;
|
|
88
|
+
displayName: string;
|
|
89
|
+
}, {
|
|
90
|
+
lapisFilter: Record<string, string | number | boolean | null>;
|
|
91
|
+
displayName: string;
|
|
92
|
+
}>;
|
|
93
|
+
|
|
94
|
+
export declare type SequenceType = default_2.infer<typeof sequenceTypeSchema>;
|
|
95
|
+
|
|
96
|
+
declare const sequenceTypeSchema: default_2.ZodUnion<[default_2.ZodLiteral<"nucleotide">, default_2.ZodLiteral<"amino acid">]>;
|
|
97
|
+
|
|
98
|
+
export declare const views: {
|
|
99
|
+
readonly table: "table";
|
|
100
|
+
readonly venn: "venn";
|
|
101
|
+
};
|
|
102
|
+
|
|
61
103
|
export { }
|
|
62
104
|
|
|
63
105
|
|
|
@@ -86,7 +128,11 @@ declare global {
|
|
|
86
128
|
|
|
87
129
|
declare global {
|
|
88
130
|
interface HTMLElementTagNameMap {
|
|
89
|
-
'gs-
|
|
131
|
+
'gs-date-range-selector': DateRangeSelectorComponent;
|
|
132
|
+
}
|
|
133
|
+
interface HTMLElementEventMap {
|
|
134
|
+
'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
|
|
135
|
+
'gs-date-range-option-changed': DateRangeOptionChangedEvent;
|
|
90
136
|
}
|
|
91
137
|
}
|
|
92
138
|
|
|
@@ -94,7 +140,7 @@ declare global {
|
|
|
94
140
|
declare global {
|
|
95
141
|
namespace JSX {
|
|
96
142
|
interface IntrinsicElements {
|
|
97
|
-
'gs-
|
|
143
|
+
'gs-date-range-selector': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
98
144
|
}
|
|
99
145
|
}
|
|
100
146
|
}
|
|
@@ -102,7 +148,10 @@ declare global {
|
|
|
102
148
|
|
|
103
149
|
declare global {
|
|
104
150
|
interface HTMLElementTagNameMap {
|
|
105
|
-
'gs-
|
|
151
|
+
'gs-location-filter': LocationFilterComponent;
|
|
152
|
+
}
|
|
153
|
+
interface HTMLElementEventMap {
|
|
154
|
+
'gs-location-changed': CustomEvent<Record<string, string>>;
|
|
106
155
|
}
|
|
107
156
|
}
|
|
108
157
|
|
|
@@ -110,7 +159,7 @@ declare global {
|
|
|
110
159
|
declare global {
|
|
111
160
|
namespace JSX {
|
|
112
161
|
interface IntrinsicElements {
|
|
113
|
-
'gs-
|
|
162
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
114
163
|
}
|
|
115
164
|
}
|
|
116
165
|
}
|
|
@@ -118,7 +167,10 @@ declare global {
|
|
|
118
167
|
|
|
119
168
|
declare global {
|
|
120
169
|
interface HTMLElementTagNameMap {
|
|
121
|
-
'gs-
|
|
170
|
+
'gs-text-input': TextInputComponent;
|
|
171
|
+
}
|
|
172
|
+
interface HTMLElementEventMap {
|
|
173
|
+
'gs-text-input-changed': CustomEvent<Record<string, string>>;
|
|
122
174
|
}
|
|
123
175
|
}
|
|
124
176
|
|
|
@@ -126,7 +178,7 @@ declare global {
|
|
|
126
178
|
declare global {
|
|
127
179
|
namespace JSX {
|
|
128
180
|
interface IntrinsicElements {
|
|
129
|
-
'gs-
|
|
181
|
+
'gs-text-input': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
130
182
|
}
|
|
131
183
|
}
|
|
132
184
|
}
|
|
@@ -134,7 +186,10 @@ declare global {
|
|
|
134
186
|
|
|
135
187
|
declare global {
|
|
136
188
|
interface HTMLElementTagNameMap {
|
|
137
|
-
'gs-
|
|
189
|
+
'gs-mutation-filter': MutationFilterComponent;
|
|
190
|
+
}
|
|
191
|
+
interface HTMLElementEventMap {
|
|
192
|
+
'gs-mutation-filter-changed': CustomEvent<SelectedMutationFilterStrings>;
|
|
138
193
|
}
|
|
139
194
|
}
|
|
140
195
|
|
|
@@ -142,7 +197,7 @@ declare global {
|
|
|
142
197
|
declare global {
|
|
143
198
|
namespace JSX {
|
|
144
199
|
interface IntrinsicElements {
|
|
145
|
-
'gs-
|
|
200
|
+
'gs-mutation-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
146
201
|
}
|
|
147
202
|
}
|
|
148
203
|
}
|
|
@@ -150,7 +205,10 @@ declare global {
|
|
|
150
205
|
|
|
151
206
|
declare global {
|
|
152
207
|
interface HTMLElementTagNameMap {
|
|
153
|
-
'gs-
|
|
208
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
209
|
+
}
|
|
210
|
+
interface HTMLElementEventMap {
|
|
211
|
+
'gs-lineage-filter-changed': CustomEvent<Record<string, string>>;
|
|
154
212
|
}
|
|
155
213
|
}
|
|
156
214
|
|
|
@@ -158,7 +216,7 @@ declare global {
|
|
|
158
216
|
declare global {
|
|
159
217
|
namespace JSX {
|
|
160
218
|
interface IntrinsicElements {
|
|
161
|
-
'gs-
|
|
219
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
162
220
|
}
|
|
163
221
|
}
|
|
164
222
|
}
|
|
@@ -166,7 +224,7 @@ declare global {
|
|
|
166
224
|
|
|
167
225
|
declare global {
|
|
168
226
|
interface HTMLElementTagNameMap {
|
|
169
|
-
'gs-
|
|
227
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
170
228
|
}
|
|
171
229
|
}
|
|
172
230
|
|
|
@@ -174,7 +232,7 @@ declare global {
|
|
|
174
232
|
declare global {
|
|
175
233
|
namespace JSX {
|
|
176
234
|
interface IntrinsicElements {
|
|
177
|
-
'gs-
|
|
235
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
178
236
|
}
|
|
179
237
|
}
|
|
180
238
|
}
|
|
@@ -182,7 +240,7 @@ declare global {
|
|
|
182
240
|
|
|
183
241
|
declare global {
|
|
184
242
|
interface HTMLElementTagNameMap {
|
|
185
|
-
'gs-mutations-
|
|
243
|
+
'gs-mutations-component': MutationsComponent;
|
|
186
244
|
}
|
|
187
245
|
}
|
|
188
246
|
|
|
@@ -190,7 +248,7 @@ declare global {
|
|
|
190
248
|
declare global {
|
|
191
249
|
namespace JSX {
|
|
192
250
|
interface IntrinsicElements {
|
|
193
|
-
'gs-mutations-
|
|
251
|
+
'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
194
252
|
}
|
|
195
253
|
}
|
|
196
254
|
}
|
|
@@ -198,7 +256,7 @@ declare global {
|
|
|
198
256
|
|
|
199
257
|
declare global {
|
|
200
258
|
interface HTMLElementTagNameMap {
|
|
201
|
-
'gs-
|
|
259
|
+
'gs-prevalence-over-time': PrevalenceOverTimeComponent;
|
|
202
260
|
}
|
|
203
261
|
}
|
|
204
262
|
|
|
@@ -206,7 +264,7 @@ declare global {
|
|
|
206
264
|
declare global {
|
|
207
265
|
namespace JSX {
|
|
208
266
|
interface IntrinsicElements {
|
|
209
|
-
'gs-
|
|
267
|
+
'gs-prevalence-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
210
268
|
}
|
|
211
269
|
}
|
|
212
270
|
}
|
|
@@ -214,11 +272,7 @@ declare global {
|
|
|
214
272
|
|
|
215
273
|
declare global {
|
|
216
274
|
interface HTMLElementTagNameMap {
|
|
217
|
-
'gs-
|
|
218
|
-
}
|
|
219
|
-
interface HTMLElementEventMap {
|
|
220
|
-
'gs-date-range-filter-changed': CustomEvent<Record<string, string>>;
|
|
221
|
-
'gs-date-range-option-changed': DateRangeOptionChangedEvent;
|
|
275
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
222
276
|
}
|
|
223
277
|
}
|
|
224
278
|
|
|
@@ -226,7 +280,7 @@ declare global {
|
|
|
226
280
|
declare global {
|
|
227
281
|
namespace JSX {
|
|
228
282
|
interface IntrinsicElements {
|
|
229
|
-
'gs-
|
|
283
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
230
284
|
}
|
|
231
285
|
}
|
|
232
286
|
}
|
|
@@ -234,10 +288,7 @@ declare global {
|
|
|
234
288
|
|
|
235
289
|
declare global {
|
|
236
290
|
interface HTMLElementTagNameMap {
|
|
237
|
-
'gs-
|
|
238
|
-
}
|
|
239
|
-
interface HTMLElementEventMap {
|
|
240
|
-
'gs-location-changed': CustomEvent<Record<string, string>>;
|
|
291
|
+
'gs-aggregate': AggregateComponent;
|
|
241
292
|
}
|
|
242
293
|
}
|
|
243
294
|
|
|
@@ -245,7 +296,7 @@ declare global {
|
|
|
245
296
|
declare global {
|
|
246
297
|
namespace JSX {
|
|
247
298
|
interface IntrinsicElements {
|
|
248
|
-
'gs-
|
|
299
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
249
300
|
}
|
|
250
301
|
}
|
|
251
302
|
}
|
|
@@ -253,10 +304,7 @@ declare global {
|
|
|
253
304
|
|
|
254
305
|
declare global {
|
|
255
306
|
interface HTMLElementTagNameMap {
|
|
256
|
-
'gs-
|
|
257
|
-
}
|
|
258
|
-
interface HTMLElementEventMap {
|
|
259
|
-
'gs-text-input-changed': CustomEvent<Record<string, string>>;
|
|
307
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
260
308
|
}
|
|
261
309
|
}
|
|
262
310
|
|
|
@@ -264,7 +312,7 @@ declare global {
|
|
|
264
312
|
declare global {
|
|
265
313
|
namespace JSX {
|
|
266
314
|
interface IntrinsicElements {
|
|
267
|
-
'gs-
|
|
315
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
268
316
|
}
|
|
269
317
|
}
|
|
270
318
|
}
|
|
@@ -272,10 +320,7 @@ declare global {
|
|
|
272
320
|
|
|
273
321
|
declare global {
|
|
274
322
|
interface HTMLElementTagNameMap {
|
|
275
|
-
'gs-
|
|
276
|
-
}
|
|
277
|
-
interface HTMLElementEventMap {
|
|
278
|
-
'gs-mutation-filter-changed': CustomEvent<SelectedMutationFilterStrings>;
|
|
323
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
279
324
|
}
|
|
280
325
|
}
|
|
281
326
|
|
|
@@ -283,7 +328,7 @@ declare global {
|
|
|
283
328
|
declare global {
|
|
284
329
|
namespace JSX {
|
|
285
330
|
interface IntrinsicElements {
|
|
286
|
-
'gs-
|
|
331
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
287
332
|
}
|
|
288
333
|
}
|
|
289
334
|
}
|
|
@@ -291,10 +336,7 @@ declare global {
|
|
|
291
336
|
|
|
292
337
|
declare global {
|
|
293
338
|
interface HTMLElementTagNameMap {
|
|
294
|
-
'gs-
|
|
295
|
-
}
|
|
296
|
-
interface HTMLElementEventMap {
|
|
297
|
-
'gs-lineage-filter-changed': CustomEvent<Record<string, string>>;
|
|
339
|
+
'gs-statistics': StatisticsComponent;
|
|
298
340
|
}
|
|
299
341
|
}
|
|
300
342
|
|
|
@@ -302,7 +344,7 @@ declare global {
|
|
|
302
344
|
declare global {
|
|
303
345
|
namespace JSX {
|
|
304
346
|
interface IntrinsicElements {
|
|
305
|
-
'gs-
|
|
347
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
306
348
|
}
|
|
307
349
|
}
|
|
308
350
|
}
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { D, d } from "./
|
|
1
|
+
import { D, d, v } from "./dateRangeOption-du8H7LWu.js";
|
|
2
2
|
export {
|
|
3
3
|
D as DateRangeOptionChangedEvent,
|
|
4
|
-
d as dateRangeOptionPresets
|
|
4
|
+
d as dateRangeOptionPresets,
|
|
5
|
+
v as views
|
|
5
6
|
};
|
|
6
7
|
//# sourceMappingURL=util.js.map
|
package/package.json
CHANGED
|
@@ -54,7 +54,11 @@ export const ColorScaleSelector: FunctionComponent<ColorScaleSelectorProps> = ({
|
|
|
54
54
|
);
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export const getColorWithingScale = (value: number, colorScale: ColorScale) => {
|
|
57
|
+
export const getColorWithingScale = (value: number | undefined, colorScale: ColorScale) => {
|
|
58
|
+
if (value === undefined) {
|
|
59
|
+
return 'lightgrey';
|
|
60
|
+
}
|
|
61
|
+
|
|
58
62
|
if (colorScale.min === colorScale.max) {
|
|
59
63
|
return singleGraphColorRGBByName(colorScale.color, 0);
|
|
60
64
|
}
|
|
@@ -66,8 +70,8 @@ export const getColorWithingScale = (value: number, colorScale: ColorScale) => {
|
|
|
66
70
|
return singleGraphColorRGBByName(colorScale.color, alpha);
|
|
67
71
|
};
|
|
68
72
|
|
|
69
|
-
export const getTextColorForScale = (value: number, colorScale: ColorScale) => {
|
|
70
|
-
if (colorScale.min === colorScale.max) {
|
|
73
|
+
export const getTextColorForScale = (value: number | undefined, colorScale: ColorScale) => {
|
|
74
|
+
if (value === undefined || colorScale.min === colorScale.max) {
|
|
71
75
|
return 'black';
|
|
72
76
|
}
|
|
73
77
|
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { useErrorBoundary } from 'preact/hooks';
|
|
1
|
+
import { type RenderableProps } from 'preact';
|
|
2
|
+
import { useErrorBoundary, useMemo } from 'preact/hooks';
|
|
3
|
+
import { type ZodSchema } from 'zod';
|
|
3
4
|
|
|
4
|
-
import { ErrorDisplay, type ErrorDisplayProps } from './error-display';
|
|
5
|
+
import { ErrorDisplay, type ErrorDisplayProps, InvalidPropsError } from './error-display';
|
|
5
6
|
import { ResizeContainer, type Size } from './resize-container';
|
|
6
7
|
|
|
7
|
-
type ErrorBoundaryProps = {
|
|
8
|
+
type ErrorBoundaryProps<T> = {
|
|
8
9
|
size: Size;
|
|
9
10
|
layout?: ErrorDisplayProps['layout'];
|
|
11
|
+
componentProps?: T;
|
|
12
|
+
schema?: ZodSchema<T>;
|
|
10
13
|
};
|
|
11
14
|
|
|
12
|
-
export const ErrorBoundary
|
|
15
|
+
export const ErrorBoundary = <T extends Record<string, unknown>>({
|
|
16
|
+
size,
|
|
17
|
+
layout,
|
|
18
|
+
componentProps,
|
|
19
|
+
schema,
|
|
20
|
+
children,
|
|
21
|
+
}: RenderableProps<ErrorBoundaryProps<T>>) => {
|
|
13
22
|
const [internalError, resetError] = useErrorBoundary();
|
|
23
|
+
const componentPropsParseError = useCheckComponentProps(schema, componentProps);
|
|
14
24
|
|
|
15
25
|
if (internalError) {
|
|
16
26
|
return (
|
|
@@ -20,5 +30,29 @@ export const ErrorBoundary: FunctionComponent<ErrorBoundaryProps> = ({ size, lay
|
|
|
20
30
|
);
|
|
21
31
|
}
|
|
22
32
|
|
|
33
|
+
if (componentPropsParseError !== undefined) {
|
|
34
|
+
return (
|
|
35
|
+
<ResizeContainer size={size}>
|
|
36
|
+
<ErrorDisplay error={componentPropsParseError} layout={layout} />
|
|
37
|
+
</ResizeContainer>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
23
41
|
return <>{children}</>;
|
|
24
42
|
};
|
|
43
|
+
|
|
44
|
+
// TODO #554 - make both arguments required once all components validate their props
|
|
45
|
+
function useCheckComponentProps<T extends Record<string, unknown>>(schema?: ZodSchema<T>, componentProps?: T) {
|
|
46
|
+
return useMemo(() => {
|
|
47
|
+
if (schema === undefined || componentProps === undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const parseResult = schema.safeParse(componentProps);
|
|
52
|
+
if (parseResult.success) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return new InvalidPropsError(parseResult.error, componentProps);
|
|
57
|
+
}, [componentProps, schema]);
|
|
58
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
2
|
import { useEffect, useRef } from 'preact/hooks';
|
|
3
|
+
import { type ZodError } from 'zod';
|
|
3
4
|
|
|
4
5
|
import { LapisError, UnknownLapisError } from '../../lapisApi/lapisApi';
|
|
5
6
|
|
|
@@ -24,9 +25,19 @@ export class UserFacingError extends Error {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
export class InvalidPropsError extends Error {
|
|
29
|
+
constructor(
|
|
30
|
+
public readonly zodError: ZodError,
|
|
31
|
+
public readonly componentProps: Record<string, unknown>,
|
|
32
|
+
) {
|
|
33
|
+
super(zodError.message);
|
|
34
|
+
this.name = 'InvalidPropsError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
export type ErrorDisplayProps = {
|
|
28
39
|
error: Error;
|
|
29
|
-
resetError
|
|
40
|
+
resetError?: () => void;
|
|
30
41
|
layout?: 'horizontal' | 'vertical';
|
|
31
42
|
};
|
|
32
43
|
|
|
@@ -76,10 +87,12 @@ export const ErrorDisplay: FunctionComponent<ErrorDisplayProps> = ({ error, rese
|
|
|
76
87
|
)}
|
|
77
88
|
</div>
|
|
78
89
|
</div>
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
{resetError !== undefined && (
|
|
91
|
+
<button onClick={resetError} className='btn btn-sm flex items-center m-4'>
|
|
92
|
+
<span className='iconify mdi--reload text-lg' />
|
|
93
|
+
Try again
|
|
94
|
+
</button>
|
|
95
|
+
)}
|
|
83
96
|
</div>
|
|
84
97
|
);
|
|
85
98
|
};
|
|
@@ -115,5 +128,27 @@ function getDisplayedErrorMessage(error: Error) {
|
|
|
115
128
|
};
|
|
116
129
|
}
|
|
117
130
|
|
|
131
|
+
if (error instanceof InvalidPropsError) {
|
|
132
|
+
const firstError = error.zodError.errors[0];
|
|
133
|
+
let message = error.zodError.issues
|
|
134
|
+
.map((issue) => {
|
|
135
|
+
const actual =
|
|
136
|
+
issue.path[0] in error.componentProps
|
|
137
|
+
? ` '${JSON.stringify(error.componentProps[issue.path[0]])}'`
|
|
138
|
+
: '';
|
|
139
|
+
return `Unexpected value${actual} for "${issue.path.join('.')}": ${issue.message}`;
|
|
140
|
+
})
|
|
141
|
+
.join(' - ');
|
|
142
|
+
|
|
143
|
+
if (firstError.code === 'invalid_type' && firstError.received === 'null') {
|
|
144
|
+
message = `Is the "${firstError.path[0]}" attribute in the HTML of the correct type? ${message}`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
headline: 'Error - Invalid component attributes',
|
|
149
|
+
details: { headline: 'Invalid component attributes', message },
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
118
153
|
return { headline: 'Error', details: undefined };
|
|
119
154
|
}
|
|
@@ -50,9 +50,15 @@ describe('computeInitialValues', () => {
|
|
|
50
50
|
expectDateMatches(result.initialSelectedDateTo, today);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
it('should
|
|
53
|
+
it('should throw when initial value is unknown', () => {
|
|
54
|
+
expect(() =>
|
|
55
|
+
computeInitialValues('not a known value', undefined, undefined, earliestDate, dateRangeOptions),
|
|
56
|
+
).toThrowError(/Invalid initialValue "not a known value", It must be one of/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should throw when initial value is set but no options are provided', () => {
|
|
54
60
|
expect(() => computeInitialValues('not a known value', undefined, undefined, earliestDate, [])).toThrowError(
|
|
55
|
-
/
|
|
61
|
+
/There are no selectable options/,
|
|
56
62
|
);
|
|
57
63
|
});
|
|
58
64
|
|
|
@@ -18,6 +18,12 @@ export function computeInitialValues(
|
|
|
18
18
|
const initialSelectedDateRange = selectableOptions.find((option) => option.value === initialValue)?.value;
|
|
19
19
|
|
|
20
20
|
if (initialValue !== undefined && initialSelectedDateRange === undefined) {
|
|
21
|
+
if (selectableOptions.length === 0) {
|
|
22
|
+
throw new UserFacingError(
|
|
23
|
+
'Invalid initialValue',
|
|
24
|
+
'There are no selectable options, but initialValue is set.',
|
|
25
|
+
);
|
|
26
|
+
}
|
|
21
27
|
throw new UserFacingError(
|
|
22
28
|
'Invalid initialValue',
|
|
23
29
|
`Invalid initialValue "${initialValue}", It must be one of ${selectableOptions.map((option) => `'${option.value}'`).join(', ')}`,
|
|
@@ -8,6 +8,7 @@ import { previewHandles } from '../../../.storybook/preview';
|
|
|
8
8
|
import { LAPIS_URL } from '../../constants';
|
|
9
9
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
10
10
|
import { dateRangeOptionPresets } from './dateRangeOption';
|
|
11
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectInvalidAttributesErrorMessage';
|
|
11
12
|
|
|
12
13
|
const earliestDate = '1970-01-01';
|
|
13
14
|
|
|
@@ -55,8 +56,8 @@ const meta: Meta<DateRangeSelectorProps> = {
|
|
|
55
56
|
initialValue: dateRangeOptionPresets.lastMonth.label,
|
|
56
57
|
dateColumn: 'aDateColumn',
|
|
57
58
|
width: '100%',
|
|
58
|
-
initialDateFrom:
|
|
59
|
-
initialDateTo:
|
|
59
|
+
initialDateFrom: undefined,
|
|
60
|
+
initialDateTo: undefined,
|
|
60
61
|
},
|
|
61
62
|
};
|
|
62
63
|
|
|
@@ -221,6 +222,19 @@ export const HandlesInvalidInitialDateFrom: StoryObj<DateRangeSelectorProps> = {
|
|
|
221
222
|
},
|
|
222
223
|
};
|
|
223
224
|
|
|
225
|
+
export const WithNoDateColumn: StoryObj<DateRangeSelectorProps> = {
|
|
226
|
+
...Primary,
|
|
227
|
+
args: {
|
|
228
|
+
...Primary.args,
|
|
229
|
+
dateColumn: '',
|
|
230
|
+
},
|
|
231
|
+
play: async ({ canvasElement, step }) => {
|
|
232
|
+
step('expect error message', async () => {
|
|
233
|
+
await expectInvalidAttributesErrorMessage(canvasElement, 'String must contain at least 1 character(s)');
|
|
234
|
+
});
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
|
|
224
238
|
async function prepare(canvasElement: HTMLElement, step: StepFunction<PreactRenderer, unknown>) {
|
|
225
239
|
const canvas = within(canvasElement);
|
|
226
240
|
|