@genspectrum/dashboard-components 0.5.0 → 0.5.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/dist/dashboard-components.js +174 -162
- package/dist/dashboard-components.js.map +1 -1
- package/dist/style.css +19 -6
- package/package.json +1 -1
- package/src/preact/aggregatedData/aggregate-table.tsx +4 -2
- package/src/preact/dateRangeSelector/date-range-selector.tsx +3 -5
- package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +26 -17
- package/src/query/queryAggregateData.ts +1 -1
- package/src/query/queryPrevalenceOverTime.ts +8 -1
package/dist/style.css
CHANGED
|
@@ -836,7 +836,11 @@ html {
|
|
|
836
836
|
}
|
|
837
837
|
|
|
838
838
|
* {
|
|
839
|
-
scrollbar-color: currentColor transparent;
|
|
839
|
+
scrollbar-color: color-mix(in oklch, currentColor 35%, transparent) transparent;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
*:hover {
|
|
843
|
+
scrollbar-color: color-mix(in oklch, currentColor 60%, transparent) transparent;
|
|
840
844
|
}
|
|
841
845
|
|
|
842
846
|
:root {
|
|
@@ -1846,6 +1850,9 @@ input.tab:checked + .tab-content,
|
|
|
1846
1850
|
margin-bottom: 0px;
|
|
1847
1851
|
margin-inline-start: -1px;
|
|
1848
1852
|
}
|
|
1853
|
+
.join > :where(*:not(:first-child)):is(.btn) {
|
|
1854
|
+
margin-inline-start: calc(var(--border-btn) * -1);
|
|
1855
|
+
}
|
|
1849
1856
|
.loading {
|
|
1850
1857
|
pointer-events: none;
|
|
1851
1858
|
display: inline-block;
|
|
@@ -2596,11 +2603,17 @@ input.tab:checked + .tab-content,
|
|
|
2596
2603
|
margin-right: 0px;
|
|
2597
2604
|
margin-top: -1px;
|
|
2598
2605
|
}
|
|
2606
|
+
.join.join-vertical > :where(*:not(:first-child)):is(.btn) {
|
|
2607
|
+
margin-top: calc(var(--border-btn) * -1);
|
|
2608
|
+
}
|
|
2599
2609
|
.join.join-horizontal > :where(*:not(:first-child)) {
|
|
2600
2610
|
margin-top: 0px;
|
|
2601
2611
|
margin-bottom: 0px;
|
|
2602
2612
|
margin-inline-start: -1px;
|
|
2603
2613
|
}
|
|
2614
|
+
.join.join-horizontal > :where(*:not(:first-child)):is(.btn) {
|
|
2615
|
+
margin-inline-start: calc(var(--border-btn) * -1);
|
|
2616
|
+
}
|
|
2604
2617
|
.modal-top :where(.modal-box) {
|
|
2605
2618
|
width: 100%;
|
|
2606
2619
|
max-width: none;
|
|
@@ -2854,12 +2867,12 @@ input.tab:checked + .tab-content,
|
|
|
2854
2867
|
.w-32 {
|
|
2855
2868
|
width: 8rem;
|
|
2856
2869
|
}
|
|
2857
|
-
.w-40 {
|
|
2858
|
-
width: 10rem;
|
|
2859
|
-
}
|
|
2860
2870
|
.w-64 {
|
|
2861
2871
|
width: 16rem;
|
|
2862
2872
|
}
|
|
2873
|
+
.w-\[7\.5rem\] {
|
|
2874
|
+
width: 7.5rem;
|
|
2875
|
+
}
|
|
2863
2876
|
.w-full {
|
|
2864
2877
|
width: 100%;
|
|
2865
2878
|
}
|
|
@@ -2867,8 +2880,8 @@ input.tab:checked + .tab-content,
|
|
|
2867
2880
|
width: -moz-max-content;
|
|
2868
2881
|
width: max-content;
|
|
2869
2882
|
}
|
|
2870
|
-
.min-w
|
|
2871
|
-
min-width:
|
|
2883
|
+
.min-w-\[7\.5rem\] {
|
|
2884
|
+
min-width: 7.5rem;
|
|
2872
2885
|
}
|
|
2873
2886
|
.max-w-screen-lg {
|
|
2874
2887
|
max-width: 1024px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
2
|
|
|
3
|
-
import { type AggregateData } from '../../query/queryAggregateData';
|
|
3
|
+
import { type AggregateData, compareAscending } from '../../query/queryAggregateData';
|
|
4
4
|
import { Table } from '../components/table';
|
|
5
5
|
import { formatProportion } from '../shared/table/formatProportion';
|
|
6
6
|
|
|
@@ -15,7 +15,9 @@ export const AggregateTable: FunctionComponent<AggregateTableProps> = ({ data, f
|
|
|
15
15
|
...fields.map((field) => {
|
|
16
16
|
return {
|
|
17
17
|
name: field,
|
|
18
|
-
sort:
|
|
18
|
+
sort: {
|
|
19
|
+
compare: compareAscending,
|
|
20
|
+
},
|
|
19
21
|
};
|
|
20
22
|
}),
|
|
21
23
|
{
|
|
@@ -182,7 +182,7 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
|
|
|
182
182
|
<Select
|
|
183
183
|
items={getSelectableOptions(customSelectOptions)}
|
|
184
184
|
selected={selectedDateRange}
|
|
185
|
-
selectStyle='select-bordered rounded-none flex-grow w-
|
|
185
|
+
selectStyle='select-bordered rounded-none flex-grow min-w-[7.5rem]'
|
|
186
186
|
onChange={(event: Event) => {
|
|
187
187
|
event.preventDefault();
|
|
188
188
|
const select = event.target as HTMLSelectElement;
|
|
@@ -192,18 +192,16 @@ export const DateRangeSelectorInner = <CustomLabel extends string>({
|
|
|
192
192
|
/>
|
|
193
193
|
<div className={'flex flex-wrap flex-grow'}>
|
|
194
194
|
<input
|
|
195
|
-
class='input input-bordered rounded-none flex-grow
|
|
195
|
+
class='input input-bordered rounded-none flex-grow w-[7.5rem]'
|
|
196
196
|
type='text'
|
|
197
|
-
size={10}
|
|
198
197
|
placeholder='Date from'
|
|
199
198
|
ref={fromDatePickerRef}
|
|
200
199
|
onChange={onChangeDateFrom}
|
|
201
200
|
onBlur={onChangeDateFrom}
|
|
202
201
|
/>
|
|
203
202
|
<input
|
|
204
|
-
class='input input-bordered rounded-none flex-grow
|
|
203
|
+
class='input input-bordered rounded-none flex-grow w-[7.5rem]'
|
|
205
204
|
type='text'
|
|
206
|
-
size={10}
|
|
207
205
|
placeholder='Date to'
|
|
208
206
|
ref={toDatePickerRef}
|
|
209
207
|
onChange={onChangeDateTo}
|
|
@@ -2,7 +2,11 @@ import { Chart, type ChartConfiguration, registerables, type TooltipItem } from
|
|
|
2
2
|
import { BarWithErrorBar, BarWithErrorBarsController } from 'chartjs-chart-error-bars';
|
|
3
3
|
|
|
4
4
|
import { maxInData } from './prevalence-over-time';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type PrevalenceOverTimeData,
|
|
7
|
+
type PrevalenceOverTimeVariantData,
|
|
8
|
+
type PrevalenceOverTimeVariantDataPoint,
|
|
9
|
+
} from '../../query/queryPrevalenceOverTime';
|
|
6
10
|
import type { Temporal } from '../../utils/temporal';
|
|
7
11
|
import GsChart from '../components/chart';
|
|
8
12
|
import { LogitScale } from '../shared/charts/LogitScale';
|
|
@@ -84,32 +88,37 @@ const getDataset = (
|
|
|
84
88
|
index: number,
|
|
85
89
|
confidenceIntervalMethod: ConfidenceIntervalMethod,
|
|
86
90
|
) => {
|
|
87
|
-
|
|
91
|
+
return {
|
|
88
92
|
borderWidth: 1,
|
|
89
93
|
pointRadius: 0,
|
|
90
94
|
label: prevalenceOverTimeVariant.displayName,
|
|
91
95
|
backgroundColor: singleGraphColorRGBAById(index, 0.3),
|
|
92
96
|
borderColor: singleGraphColorRGBAById(index),
|
|
97
|
+
data: prevalenceOverTimeVariant.content.map(mapDataPoint(confidenceIntervalMethod)),
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const mapDataPoint = (confidenceIntervalMethod: ConfidenceIntervalMethod) => {
|
|
102
|
+
return (dataPoint: PrevalenceOverTimeVariantDataPoint) => {
|
|
103
|
+
const confidenceInterval = getConfidenceInterval(dataPoint, confidenceIntervalMethod);
|
|
104
|
+
return {
|
|
105
|
+
y: dataPoint.prevalence,
|
|
106
|
+
yMin: confidenceInterval.lowerLimit,
|
|
107
|
+
yMax: confidenceInterval.upperLimit,
|
|
108
|
+
x: dataPoint.dateRange?.toString() ?? 'Unknown',
|
|
109
|
+
};
|
|
93
110
|
};
|
|
111
|
+
};
|
|
94
112
|
|
|
113
|
+
const getConfidenceInterval = (
|
|
114
|
+
dataPoint: PrevalenceOverTimeVariantDataPoint,
|
|
115
|
+
confidenceIntervalMethod: ConfidenceIntervalMethod,
|
|
116
|
+
) => {
|
|
95
117
|
switch (confidenceIntervalMethod) {
|
|
96
118
|
case 'wilson':
|
|
97
|
-
return
|
|
98
|
-
...generalConfig,
|
|
99
|
-
data: prevalenceOverTimeVariant.content.map((dataPoint) => ({
|
|
100
|
-
y: dataPoint.prevalence,
|
|
101
|
-
yMin: wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total).lowerLimit,
|
|
102
|
-
yMax: wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total).upperLimit,
|
|
103
|
-
x: dataPoint.dateRange?.toString() ?? 'Unknown',
|
|
104
|
-
})),
|
|
105
|
-
};
|
|
119
|
+
return wilson95PercentConfidenceInterval(dataPoint.count, dataPoint.total);
|
|
106
120
|
default:
|
|
107
|
-
return {
|
|
108
|
-
...generalConfig,
|
|
109
|
-
data: prevalenceOverTimeVariant.content.map((dataPoint) => {
|
|
110
|
-
return { y: dataPoint.prevalence, x: dataPoint.dateRange };
|
|
111
|
-
}),
|
|
112
|
-
};
|
|
121
|
+
return { lowerLimit: undefined, upperLimit: undefined };
|
|
113
122
|
}
|
|
114
123
|
};
|
|
115
124
|
|
|
@@ -8,7 +8,7 @@ export type AggregateData = (Record<string, string | null | number | boolean> &
|
|
|
8
8
|
proportion: number;
|
|
9
9
|
})[];
|
|
10
10
|
|
|
11
|
-
const compareAscending = (a: string | null | number, b: string | null | number) => {
|
|
11
|
+
export const compareAscending = (a: string | null | number, b: string | null | number) => {
|
|
12
12
|
if (typeof a === 'number' && typeof b === 'number') {
|
|
13
13
|
return a - b;
|
|
14
14
|
}
|
|
@@ -19,7 +19,14 @@ export type PrevalenceOverTimeData = PrevalenceOverTimeVariantData[];
|
|
|
19
19
|
|
|
20
20
|
export type PrevalenceOverTimeVariantData = {
|
|
21
21
|
displayName: string;
|
|
22
|
-
content:
|
|
22
|
+
content: PrevalenceOverTimeVariantDataPoint[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type PrevalenceOverTimeVariantDataPoint = {
|
|
26
|
+
count: number;
|
|
27
|
+
prevalence: number;
|
|
28
|
+
total: number;
|
|
29
|
+
dateRange: Temporal | null;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
32
|
export function queryPrevalenceOverTime(
|