@genspectrum/dashboard-components 0.19.8 → 0.20.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 +32 -14
- package/dist/{NumberRangeFilterChangedEvent-RZ8haPHq.js → NumberRangeFilterChangedEvent-RqWinxhE.js} +50 -41
- package/dist/NumberRangeFilterChangedEvent-RqWinxhE.js.map +1 -0
- package/dist/assets/mutationOverTimeWorker-BzmkceEA.js.map +1 -0
- package/dist/components.d.ts +35 -35
- package/dist/components.js +5 -7
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +46 -64
- package/dist/util.js +1 -1
- package/package.json +1 -1
- package/src/preact/dateRangeFilter/date-range-filter.stories.tsx +3 -3
- package/src/preact/dateRangeFilter/dateRangeOption.ts +71 -45
- package/src/web-components/input/gs-date-range-filter.stories.ts +4 -4
- package/src/web-components/input/introduction.mdx +57 -2
- package/src/web-components/tutorials/CreateYourFirstOwnDashboard.mdx +85 -0
- package/src/web-components/tutorials/UseTheComponentsWithPlainJavaScript.mdx +140 -0
- package/src/web-components/tutorials/UseTheComponentsWithReact.mdx +166 -0
- package/src/web-components/visualization/gs-mutations.tsx +2 -2
- package/src/web-components/visualization/introduction.mdx +51 -0
- package/standalone-bundle/assets/mutationOverTimeWorker-jUeItsGM.js.map +1 -0
- package/standalone-bundle/dashboard-components.js +7088 -7112
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/NumberRangeFilterChangedEvent-RZ8haPHq.js.map +0 -1
- package/dist/assets/mutationOverTimeWorker-CBXsEsiT.js.map +0 -1
- package/src/web-components/visualization/data_visualization_statistical_analysis.mdx +0 -26
- package/standalone-bundle/assets/mutationOverTimeWorker-CN4SJC7C.js.map +0 -1
- /package/src/web-components/{MutationAnnotations.mdx → mutationAnnotations.mdx} +0 -0
- /package/src/web-components/{ResizeContainer.mdx → sizeOfComponents.mdx} +0 -0
package/dist/util.d.ts
CHANGED
|
@@ -77,38 +77,20 @@ export declare class DateRangeOptionChangedEvent extends CustomEvent<DateRangeVa
|
|
|
77
77
|
constructor(detail: DateRangeValue);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
declare type DateRangeOptionPresets = {
|
|
81
|
+
last2Weeks: DateRangeOption;
|
|
82
|
+
lastMonth: DateRangeOption;
|
|
83
|
+
last2Months: DateRangeOption;
|
|
84
|
+
last3Months: DateRangeOption;
|
|
85
|
+
last6Months: DateRangeOption;
|
|
86
|
+
lastYear: DateRangeOption;
|
|
87
|
+
allTimes: DateRangeOption;
|
|
88
|
+
};
|
|
89
|
+
|
|
80
90
|
/**
|
|
81
91
|
* Presets for the `gs-date-range-filter` component that can be used as `dateRangeOptions`.
|
|
82
92
|
*/
|
|
83
|
-
export declare const dateRangeOptionPresets:
|
|
84
|
-
last2Weeks: {
|
|
85
|
-
label: string;
|
|
86
|
-
dateFrom: string;
|
|
87
|
-
};
|
|
88
|
-
lastMonth: {
|
|
89
|
-
label: string;
|
|
90
|
-
dateFrom: string;
|
|
91
|
-
};
|
|
92
|
-
last2Months: {
|
|
93
|
-
label: string;
|
|
94
|
-
dateFrom: string;
|
|
95
|
-
};
|
|
96
|
-
last3Months: {
|
|
97
|
-
label: string;
|
|
98
|
-
dateFrom: string;
|
|
99
|
-
};
|
|
100
|
-
last6Months: {
|
|
101
|
-
label: string;
|
|
102
|
-
dateFrom: string;
|
|
103
|
-
};
|
|
104
|
-
lastYear: {
|
|
105
|
-
label: string;
|
|
106
|
-
dateFrom: string;
|
|
107
|
-
};
|
|
108
|
-
allTimes: {
|
|
109
|
-
label: string;
|
|
110
|
-
};
|
|
111
|
-
};
|
|
93
|
+
export declare const dateRangeOptionPresets: () => DateRangeOptionPresets;
|
|
112
94
|
|
|
113
95
|
/**
|
|
114
96
|
* A date range option that can be used in the `gs-date-range-filter` component.
|
|
@@ -970,7 +952,7 @@ declare global {
|
|
|
970
952
|
|
|
971
953
|
declare global {
|
|
972
954
|
interface HTMLElementTagNameMap {
|
|
973
|
-
'gs-mutations
|
|
955
|
+
'gs-mutations': MutationsComponent;
|
|
974
956
|
}
|
|
975
957
|
}
|
|
976
958
|
|
|
@@ -978,7 +960,7 @@ declare global {
|
|
|
978
960
|
declare global {
|
|
979
961
|
namespace JSX {
|
|
980
962
|
interface IntrinsicElements {
|
|
981
|
-
'gs-mutations
|
|
963
|
+
'gs-mutations': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
982
964
|
}
|
|
983
965
|
}
|
|
984
966
|
}
|
|
@@ -1002,7 +984,7 @@ declare global {
|
|
|
1002
984
|
|
|
1003
985
|
declare global {
|
|
1004
986
|
interface HTMLElementTagNameMap {
|
|
1005
|
-
'gs-
|
|
987
|
+
'gs-aggregate': AggregateComponent;
|
|
1006
988
|
}
|
|
1007
989
|
}
|
|
1008
990
|
|
|
@@ -1010,7 +992,7 @@ declare global {
|
|
|
1010
992
|
declare global {
|
|
1011
993
|
namespace JSX {
|
|
1012
994
|
interface IntrinsicElements {
|
|
1013
|
-
'gs-
|
|
995
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1014
996
|
}
|
|
1015
997
|
}
|
|
1016
998
|
}
|
|
@@ -1018,7 +1000,7 @@ declare global {
|
|
|
1018
1000
|
|
|
1019
1001
|
declare global {
|
|
1020
1002
|
interface HTMLElementTagNameMap {
|
|
1021
|
-
'gs-
|
|
1003
|
+
'gs-relative-growth-advantage': RelativeGrowthAdvantageComponent;
|
|
1022
1004
|
}
|
|
1023
1005
|
}
|
|
1024
1006
|
|
|
@@ -1026,7 +1008,7 @@ declare global {
|
|
|
1026
1008
|
declare global {
|
|
1027
1009
|
namespace JSX {
|
|
1028
1010
|
interface IntrinsicElements {
|
|
1029
|
-
'gs-
|
|
1011
|
+
'gs-relative-growth-advantage': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1030
1012
|
}
|
|
1031
1013
|
}
|
|
1032
1014
|
}
|
|
@@ -1034,7 +1016,7 @@ declare global {
|
|
|
1034
1016
|
|
|
1035
1017
|
declare global {
|
|
1036
1018
|
interface HTMLElementTagNameMap {
|
|
1037
|
-
'gs-
|
|
1019
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1038
1020
|
}
|
|
1039
1021
|
}
|
|
1040
1022
|
|
|
@@ -1042,7 +1024,7 @@ declare global {
|
|
|
1042
1024
|
declare global {
|
|
1043
1025
|
namespace JSX {
|
|
1044
1026
|
interface IntrinsicElements {
|
|
1045
|
-
'gs-
|
|
1027
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1046
1028
|
}
|
|
1047
1029
|
}
|
|
1048
1030
|
}
|
|
@@ -1050,7 +1032,7 @@ declare global {
|
|
|
1050
1032
|
|
|
1051
1033
|
declare global {
|
|
1052
1034
|
interface HTMLElementTagNameMap {
|
|
1053
|
-
'gs-
|
|
1035
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1054
1036
|
}
|
|
1055
1037
|
}
|
|
1056
1038
|
|
|
@@ -1058,7 +1040,7 @@ declare global {
|
|
|
1058
1040
|
declare global {
|
|
1059
1041
|
namespace JSX {
|
|
1060
1042
|
interface IntrinsicElements {
|
|
1061
|
-
'gs-
|
|
1043
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1062
1044
|
}
|
|
1063
1045
|
}
|
|
1064
1046
|
}
|
|
@@ -1082,11 +1064,7 @@ declare global {
|
|
|
1082
1064
|
|
|
1083
1065
|
declare global {
|
|
1084
1066
|
interface HTMLElementTagNameMap {
|
|
1085
|
-
'gs-
|
|
1086
|
-
}
|
|
1087
|
-
interface HTMLElementEventMap {
|
|
1088
|
-
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
1089
|
-
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
1067
|
+
'gs-statistics': StatisticsComponent;
|
|
1090
1068
|
}
|
|
1091
1069
|
}
|
|
1092
1070
|
|
|
@@ -1094,7 +1072,7 @@ declare global {
|
|
|
1094
1072
|
declare global {
|
|
1095
1073
|
namespace JSX {
|
|
1096
1074
|
interface IntrinsicElements {
|
|
1097
|
-
'gs-
|
|
1075
|
+
'gs-statistics': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1098
1076
|
}
|
|
1099
1077
|
}
|
|
1100
1078
|
}
|
|
@@ -1102,10 +1080,7 @@ declare global {
|
|
|
1102
1080
|
|
|
1103
1081
|
declare global {
|
|
1104
1082
|
interface HTMLElementTagNameMap {
|
|
1105
|
-
'gs-
|
|
1106
|
-
}
|
|
1107
|
-
interface HTMLElementEventMap {
|
|
1108
|
-
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
1083
|
+
'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
|
|
1109
1084
|
}
|
|
1110
1085
|
}
|
|
1111
1086
|
|
|
@@ -1113,7 +1088,7 @@ declare global {
|
|
|
1113
1088
|
declare global {
|
|
1114
1089
|
namespace JSX {
|
|
1115
1090
|
interface IntrinsicElements {
|
|
1116
|
-
'gs-
|
|
1091
|
+
'gs-wastewater-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1117
1092
|
}
|
|
1118
1093
|
}
|
|
1119
1094
|
}
|
|
@@ -1121,7 +1096,11 @@ declare global {
|
|
|
1121
1096
|
|
|
1122
1097
|
declare global {
|
|
1123
1098
|
interface HTMLElementTagNameMap {
|
|
1124
|
-
'gs-
|
|
1099
|
+
'gs-date-range-filter': DateRangeFilterComponent;
|
|
1100
|
+
}
|
|
1101
|
+
interface HTMLElementEventMap {
|
|
1102
|
+
[gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
|
|
1103
|
+
[gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
|
|
1125
1104
|
}
|
|
1126
1105
|
}
|
|
1127
1106
|
|
|
@@ -1129,7 +1108,7 @@ declare global {
|
|
|
1129
1108
|
declare global {
|
|
1130
1109
|
namespace JSX {
|
|
1131
1110
|
interface IntrinsicElements {
|
|
1132
|
-
'gs-
|
|
1111
|
+
'gs-date-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1133
1112
|
}
|
|
1134
1113
|
}
|
|
1135
1114
|
}
|
|
@@ -1137,10 +1116,10 @@ declare global {
|
|
|
1137
1116
|
|
|
1138
1117
|
declare global {
|
|
1139
1118
|
interface HTMLElementTagNameMap {
|
|
1140
|
-
'gs-
|
|
1119
|
+
'gs-location-filter': LocationFilterComponent;
|
|
1141
1120
|
}
|
|
1142
1121
|
interface HTMLElementEventMap {
|
|
1143
|
-
[gsEventNames.
|
|
1122
|
+
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
1144
1123
|
}
|
|
1145
1124
|
}
|
|
1146
1125
|
|
|
@@ -1148,7 +1127,7 @@ declare global {
|
|
|
1148
1127
|
declare global {
|
|
1149
1128
|
namespace JSX {
|
|
1150
1129
|
interface IntrinsicElements {
|
|
1151
|
-
'gs-
|
|
1130
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1152
1131
|
}
|
|
1153
1132
|
}
|
|
1154
1133
|
}
|
|
@@ -1156,10 +1135,10 @@ declare global {
|
|
|
1156
1135
|
|
|
1157
1136
|
declare global {
|
|
1158
1137
|
interface HTMLElementTagNameMap {
|
|
1159
|
-
'gs-
|
|
1138
|
+
'gs-text-filter': TextFilterComponent;
|
|
1160
1139
|
}
|
|
1161
1140
|
interface HTMLElementEventMap {
|
|
1162
|
-
[gsEventNames.
|
|
1141
|
+
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
1163
1142
|
}
|
|
1164
1143
|
}
|
|
1165
1144
|
|
|
@@ -1167,7 +1146,7 @@ declare global {
|
|
|
1167
1146
|
declare global {
|
|
1168
1147
|
namespace JSX {
|
|
1169
1148
|
interface IntrinsicElements {
|
|
1170
|
-
'gs-
|
|
1149
|
+
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1171
1150
|
}
|
|
1172
1151
|
}
|
|
1173
1152
|
}
|
|
@@ -1194,11 +1173,10 @@ declare global {
|
|
|
1194
1173
|
|
|
1195
1174
|
declare global {
|
|
1196
1175
|
interface HTMLElementTagNameMap {
|
|
1197
|
-
'gs-
|
|
1176
|
+
'gs-lineage-filter': LineageFilterComponent;
|
|
1198
1177
|
}
|
|
1199
1178
|
interface HTMLElementEventMap {
|
|
1200
|
-
[gsEventNames.
|
|
1201
|
-
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1179
|
+
[gsEventNames.lineageFilterChanged]: LineageFilterChangedEvent;
|
|
1202
1180
|
}
|
|
1203
1181
|
}
|
|
1204
1182
|
|
|
@@ -1206,7 +1184,7 @@ declare global {
|
|
|
1206
1184
|
declare global {
|
|
1207
1185
|
namespace JSX {
|
|
1208
1186
|
interface IntrinsicElements {
|
|
1209
|
-
'gs-
|
|
1187
|
+
'gs-lineage-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1210
1188
|
}
|
|
1211
1189
|
}
|
|
1212
1190
|
}
|
|
@@ -1214,7 +1192,11 @@ declare global {
|
|
|
1214
1192
|
|
|
1215
1193
|
declare global {
|
|
1216
1194
|
interface HTMLElementTagNameMap {
|
|
1217
|
-
'gs-
|
|
1195
|
+
'gs-number-range-filter': NumberRangeFilterComponent;
|
|
1196
|
+
}
|
|
1197
|
+
interface HTMLElementEventMap {
|
|
1198
|
+
[gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
|
|
1199
|
+
[gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
|
|
1218
1200
|
}
|
|
1219
1201
|
}
|
|
1220
1202
|
|
|
@@ -1222,7 +1204,7 @@ declare global {
|
|
|
1222
1204
|
declare global {
|
|
1223
1205
|
namespace JSX {
|
|
1224
1206
|
interface IntrinsicElements {
|
|
1225
|
-
'gs-
|
|
1207
|
+
'gs-number-range-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1226
1208
|
}
|
|
1227
1209
|
}
|
|
1228
1210
|
}
|
package/dist/util.js
CHANGED
package/package.json
CHANGED
|
@@ -55,7 +55,7 @@ const meta: Meta<DateRangeFilterProps> = {
|
|
|
55
55
|
},
|
|
56
56
|
},
|
|
57
57
|
args: {
|
|
58
|
-
dateRangeOptions: [dateRangeOptionPresets.lastMonth, dateRangeOptionPresets.allTimes, customDateRange],
|
|
58
|
+
dateRangeOptions: [dateRangeOptionPresets().lastMonth, dateRangeOptionPresets().allTimes, customDateRange],
|
|
59
59
|
earliestDate,
|
|
60
60
|
value: null,
|
|
61
61
|
lapisDateField: 'aDateColumn',
|
|
@@ -150,7 +150,7 @@ export const SetsValueOnBlur: StoryObj<DateRangeFilterProps> = {
|
|
|
150
150
|
...Primary,
|
|
151
151
|
args: {
|
|
152
152
|
...Primary.args,
|
|
153
|
-
value: dateRangeOptionPresets.lastMonth.label,
|
|
153
|
+
value: dateRangeOptionPresets().lastMonth.label,
|
|
154
154
|
},
|
|
155
155
|
play: async ({ canvasElement, step }) => {
|
|
156
156
|
const { canvas, filterChangedListenerMock, optionChangedListenerMock } = await prepare(canvasElement, step);
|
|
@@ -211,7 +211,7 @@ export const ChangingTheValueProgrammatically: StoryObj<DateRangeFilterProps> =
|
|
|
211
211
|
<button className='btn' onClick={() => setValue(customDateRange.label)}>
|
|
212
212
|
Set to Custom
|
|
213
213
|
</button>
|
|
214
|
-
<button className='btn' onClick={() => setValue(dateRangeOptionPresets.lastMonth.label)}>
|
|
214
|
+
<button className='btn' onClick={() => setValue(dateRangeOptionPresets().lastMonth.label)}>
|
|
215
215
|
Set to Last month
|
|
216
216
|
</button>
|
|
217
217
|
</div>
|
|
@@ -45,55 +45,81 @@ export class DateRangeOptionChangedEvent extends CustomEvent<DateRangeValue> {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
type DateRangeOptionPresets = {
|
|
49
|
+
last2Weeks: DateRangeOption;
|
|
50
|
+
lastMonth: DateRangeOption;
|
|
51
|
+
last2Months: DateRangeOption;
|
|
52
|
+
last3Months: DateRangeOption;
|
|
53
|
+
last6Months: DateRangeOption;
|
|
54
|
+
lastYear: DateRangeOption;
|
|
55
|
+
allTimes: DateRangeOption;
|
|
56
|
+
};
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
let dateRangeOptionsPresetsCacheDate: string | null = null;
|
|
59
|
+
let dateRangeOptionPresetsCache: DateRangeOptionPresets | null = null;
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Presets for the `gs-date-range-filter` component that can be used as `dateRangeOptions`.
|
|
63
|
+
*/
|
|
64
|
+
export const dateRangeOptionPresets = (): DateRangeOptionPresets => {
|
|
65
|
+
const today = new Date();
|
|
66
|
+
const todayString = new Date().toISOString().slice(0, 10);
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
if (
|
|
69
|
+
dateRangeOptionPresetsCache === null ||
|
|
70
|
+
dateRangeOptionsPresetsCacheDate === null ||
|
|
71
|
+
dateRangeOptionsPresetsCacheDate !== todayString
|
|
72
|
+
) {
|
|
73
|
+
dateRangeOptionsPresetsCacheDate = todayString;
|
|
58
74
|
|
|
59
|
-
const
|
|
60
|
-
|
|
75
|
+
const twoWeeksAgo = new Date();
|
|
76
|
+
twoWeeksAgo.setDate(today.getDate() - 14);
|
|
61
77
|
|
|
62
|
-
const
|
|
63
|
-
|
|
78
|
+
const lastMonth = new Date(today);
|
|
79
|
+
lastMonth.setMonth(today.getMonth() - 1);
|
|
64
80
|
|
|
65
|
-
const
|
|
66
|
-
|
|
81
|
+
const last2Months = new Date(today);
|
|
82
|
+
last2Months.setMonth(today.getMonth() - 2);
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
const last3Months = new Date(today);
|
|
85
|
+
last3Months.setMonth(today.getMonth() - 3);
|
|
86
|
+
|
|
87
|
+
const last6Months = new Date(today);
|
|
88
|
+
last6Months.setMonth(today.getMonth() - 6);
|
|
89
|
+
|
|
90
|
+
const lastYear = new Date(today);
|
|
91
|
+
lastYear.setFullYear(today.getFullYear() - 1);
|
|
92
|
+
|
|
93
|
+
dateRangeOptionPresetsCache = {
|
|
94
|
+
last2Weeks: {
|
|
95
|
+
label: 'Last 2 weeks',
|
|
96
|
+
dateFrom: toYYYYMMDD(twoWeeksAgo),
|
|
97
|
+
},
|
|
98
|
+
lastMonth: {
|
|
99
|
+
label: 'Last month',
|
|
100
|
+
dateFrom: toYYYYMMDD(lastMonth),
|
|
101
|
+
},
|
|
102
|
+
last2Months: {
|
|
103
|
+
label: 'Last 2 months',
|
|
104
|
+
dateFrom: toYYYYMMDD(last2Months),
|
|
105
|
+
},
|
|
106
|
+
last3Months: {
|
|
107
|
+
label: 'Last 3 months',
|
|
108
|
+
dateFrom: toYYYYMMDD(last3Months),
|
|
109
|
+
},
|
|
110
|
+
last6Months: {
|
|
111
|
+
label: 'Last 6 months',
|
|
112
|
+
dateFrom: toYYYYMMDD(last6Months),
|
|
113
|
+
},
|
|
114
|
+
lastYear: {
|
|
115
|
+
label: 'Last year',
|
|
116
|
+
dateFrom: toYYYYMMDD(lastYear),
|
|
117
|
+
},
|
|
118
|
+
allTimes: {
|
|
119
|
+
label: 'All times',
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return dateRangeOptionPresetsCache;
|
|
125
|
+
};
|
|
@@ -59,14 +59,14 @@ const meta: Meta<Required<DateRangeFilterProps>> = {
|
|
|
59
59
|
},
|
|
60
60
|
args: {
|
|
61
61
|
dateRangeOptions: [
|
|
62
|
-
dateRangeOptionPresets.lastMonth,
|
|
63
|
-
dateRangeOptionPresets.last3Months,
|
|
64
|
-
dateRangeOptionPresets.allTimes,
|
|
62
|
+
dateRangeOptionPresets().lastMonth,
|
|
63
|
+
dateRangeOptionPresets().last3Months,
|
|
64
|
+
dateRangeOptionPresets().allTimes,
|
|
65
65
|
{ label: '2021', dateFrom: '2021-01-01', dateTo: '2021-12-31' },
|
|
66
66
|
customDateRange,
|
|
67
67
|
],
|
|
68
68
|
earliestDate: '1970-01-01',
|
|
69
|
-
value: dateRangeOptionPresets.lastMonth.label,
|
|
69
|
+
value: dateRangeOptionPresets().lastMonth.label,
|
|
70
70
|
lapisDateField: 'aDateColumn',
|
|
71
71
|
width: '100%',
|
|
72
72
|
placeholder: 'Date range',
|
|
@@ -7,5 +7,60 @@ import { Meta } from '@storybook/blocks';
|
|
|
7
7
|
The components in this section let the user specify values for LAPIS filters.
|
|
8
8
|
The filters can then be used as input to the visualization components.
|
|
9
9
|
|
|
10
|
-
Every component fires `CustomEvent`s when the user interacts with it
|
|
11
|
-
|
|
10
|
+
Every component fires `CustomEvent`s when the user interacts with it.
|
|
11
|
+
`event.detail` contains the payload of the event.
|
|
12
|
+
|
|
13
|
+
Every component fires an event that can be used to update the LAPIS filters.
|
|
14
|
+
It is supposed to be used in the style of:
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
component.addEventListener('gs-example-event', (event) => {
|
|
18
|
+
setNewLapisFilter({
|
|
19
|
+
...previousLapisFilter,
|
|
20
|
+
...event.detail,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Controlled Input Components
|
|
26
|
+
|
|
27
|
+
HTML input components can be controlled or uncontrolled.
|
|
28
|
+
In a controlled component, the value is controlled by surrounding Javascript code.
|
|
29
|
+
In an uncontrolled component, the value is controlled by the DOM and the surrounding Javascript code only reads the value
|
|
30
|
+
(e.g. by listening to events).
|
|
31
|
+
|
|
32
|
+
All our input components can be used in both ways.
|
|
33
|
+
Every component fires one or two events.
|
|
34
|
+
If the event details can be used to update the LAPIS filter
|
|
35
|
+
_and_ the value then the component will only fire one event,
|
|
36
|
+
otherwise it will fire one event to update the LAPIS filter and one to update the value of the component.
|
|
37
|
+
Refer to the documentation of the individual components for details on which event you can use for which purpose.
|
|
38
|
+
|
|
39
|
+
**Example**: A controlled input component in a React app could conceptually look like this:
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
import { useEffect, useRef, useState } from 'react';
|
|
43
|
+
|
|
44
|
+
const ExampleInput = () => {
|
|
45
|
+
const [value, setValue] = useState('foo');
|
|
46
|
+
const inputRef = useRef(null);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!inputRef.current) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const eventListener = (event) => {
|
|
54
|
+
setValue(event.detail);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
inputRef.current.addEventListener('gs-input', eventListener);
|
|
58
|
+
|
|
59
|
+
return () => {
|
|
60
|
+
inputRef.current.removeEventListener('gs-input', eventListener);
|
|
61
|
+
};
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
return <gs-example-input ref={inputRef} value={value} />;
|
|
65
|
+
};
|
|
66
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title='Tutorials/Create your first own dashboard' />
|
|
4
|
+
|
|
5
|
+
# Create your first own dashboard
|
|
6
|
+
|
|
7
|
+
In this tutorial, you’ll learn how to integrate our `visualization` components into your HTML page.
|
|
8
|
+
We’ll walk through building a simple dashboard that displays the number of sequences over time, along with some general statistics.
|
|
9
|
+
This example serves as a foundation for your own dashboards—you can easily extend it by adding more components as needed.
|
|
10
|
+
The data for these components must be provided by a LAPIS instance.
|
|
11
|
+
For this tutorial, we’ll use one of our own [LAPIS](https://lapis.cov-spectrum.org/open/v2/docs/) instances, but you’re free to use any LAPIS instance that supplies the required data.
|
|
12
|
+
|
|
13
|
+
## Create your HTML page
|
|
14
|
+
|
|
15
|
+
Let's start by creating a simple HTML page. If you already have one, you can skip this step.
|
|
16
|
+
Name the file `index.html` and add the following code. This will be the main file for your dashboard.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<!doctype html>
|
|
20
|
+
<html lang="en">
|
|
21
|
+
<head>
|
|
22
|
+
<meta charset="UTF-8" />
|
|
23
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
24
|
+
<title>My dashboard</title>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
We will fill this section later
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Include the dashboard components
|
|
33
|
+
|
|
34
|
+
To use the components, you need to include the dashboard bundle in your HTML file.
|
|
35
|
+
Add the following code to the `head` section:
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<script
|
|
39
|
+
type="module"
|
|
40
|
+
src="https://unpkg.com/@genspectrum/dashboard-components@latest/standalone-bundle/dashboard-components.js"
|
|
41
|
+
></script>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This approach uses a standalone bundle, which includes all the code for the components in a single step.
|
|
45
|
+
It is the easiest way to get started, although the bundle size is larger.
|
|
46
|
+
Alternatively, you can use the components as modules, but this requires a build step.
|
|
47
|
+
For more information, see the "Use the Components with Plain JavaScript" tutorial.
|
|
48
|
+
|
|
49
|
+
## Add the dashboard components to your HTML file
|
|
50
|
+
|
|
51
|
+
We are now ready to add the components to our HTML file.
|
|
52
|
+
You can do this by adding the following code to the `body` section of your HTML file:
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<gs-app lapis="https://lapis.genspectrum.org/open/v2">
|
|
56
|
+
<h2>Statistics</h2>
|
|
57
|
+
<gs-statistics numeratorFilter='{"pangoLineage": "EG*"}' denominatorFilter="{}" width="100%"></gs-statistics>
|
|
58
|
+
<h2>Number of sequences over time</h2>
|
|
59
|
+
<gs-number-sequences-over-time
|
|
60
|
+
lapisFilters='[{ "displayName": "EG", "lapisFilter": { "pangoLineage": "EG*" } }]'
|
|
61
|
+
lapisDateField="date"
|
|
62
|
+
views='["bar", "line", "table"]'
|
|
63
|
+
width="100%"
|
|
64
|
+
granularity="month"
|
|
65
|
+
smoothingWindow="0"
|
|
66
|
+
pageSize="10"
|
|
67
|
+
></gs-number-sequences-over-time>
|
|
68
|
+
</gs-app>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Here, we are using three components:
|
|
72
|
+
|
|
73
|
+
- `gs-app`: This is the main component that wraps all the other components. It is used to provide the context for the other components. Each of our components needs to be wrapped in this component.
|
|
74
|
+
It provides the `lapis` attribute, which is the URL of the LAPIS server. This is the server that provides the data for the components. In this example, we are using the LAPIS server for open SARS-CoV-2 data.
|
|
75
|
+
- `gs-statistics` and `gs-number-sequences-over-time`: Visualization components that display data from the LAPIS server.
|
|
76
|
+
|
|
77
|
+
You can find more examples and detailed descriptions of each component in our documentation.
|
|
78
|
+
|
|
79
|
+
You now have your first dashboard. Open the `index.html` file in your browser to see it in action.
|
|
80
|
+
Feel free to change some parameters to see how they affect the dashboard, or explore our Storybook for more examples.
|
|
81
|
+
|
|
82
|
+
The parameters are currently fixed in the HTML file.
|
|
83
|
+
If you want users to be able to change them—especially the filters—we also provide input components.
|
|
84
|
+
To use them, add the input components to your HTML and connect them with JavaScript.
|
|
85
|
+
For more information, see the "Use the Components with Plain JavaScript" tutorial.
|