@molgenis/vip-report-template 5.1.6 → 5.2.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/package.json +1 -1
- package/src/assets/sass/main.scss +4 -0
- package/src/components/RecordsPerPage.tsx +29 -0
- package/src/components/Sort.tsx +14 -20
- package/src/components/filter/FilterIntegerDp.tsx +4 -4
- package/src/components/record/Info.tsx +4 -0
- package/src/components/record/info/Hpo.tsx +36 -0
- package/src/views/SampleVariants.tsx +46 -35
- package/src/views/Variants.tsx +51 -39
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Component, For } from "solid-js";
|
|
2
|
+
export type RecordsPerPageEvent = { number: number };
|
|
3
|
+
|
|
4
|
+
export const RecordsPerPage: Component<{
|
|
5
|
+
initialValue: number;
|
|
6
|
+
onChange: (event: RecordsPerPageEvent) => void;
|
|
7
|
+
}> = (props) => {
|
|
8
|
+
const options = [10, 20, 50, 100];
|
|
9
|
+
const onRecordsPerPageChange = (event: Event) => {
|
|
10
|
+
props.onChange({ number: Number((event.target as HTMLInputElement).value) });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div class="control">
|
|
15
|
+
<span class="inline-control-text mr-2">Records per page</span>
|
|
16
|
+
<div class="select">
|
|
17
|
+
<select onChange={onRecordsPerPageChange}>
|
|
18
|
+
<For each={options}>
|
|
19
|
+
{(option) => (
|
|
20
|
+
<option value={option} selected={option == props.initialValue}>
|
|
21
|
+
{option}
|
|
22
|
+
</option>
|
|
23
|
+
)}
|
|
24
|
+
</For>
|
|
25
|
+
</select>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
};
|
package/src/components/Sort.tsx
CHANGED
|
@@ -32,26 +32,20 @@ export const Sort: Component<{
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<div class="
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</option>
|
|
50
|
-
)}
|
|
51
|
-
</For>
|
|
52
|
-
</select>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
35
|
+
<div class="control">
|
|
36
|
+
<span class="inline-control-text mr-2">Sort by</span>
|
|
37
|
+
<div class="select">
|
|
38
|
+
<select onChange={onSortChange}>
|
|
39
|
+
<option value="-1">{"Position"}</option>
|
|
40
|
+
<For each={sortableOptions()}>
|
|
41
|
+
{(option, i) => (
|
|
42
|
+
<option value={i()} selected={option.selected === true}>
|
|
43
|
+
{option.order.field.label || option.order.field.id}{" "}
|
|
44
|
+
{option.order.direction === DIRECTION_ASCENDING ? "(ascending)" : "(descending)"}
|
|
45
|
+
</option>
|
|
46
|
+
)}
|
|
47
|
+
</For>
|
|
48
|
+
</select>
|
|
55
49
|
</div>
|
|
56
50
|
</div>
|
|
57
51
|
);
|
|
@@ -13,7 +13,7 @@ export const FilterIntegerDp: Component<FilterProps> = (props) => {
|
|
|
13
13
|
query: {
|
|
14
14
|
selector: fieldSelector,
|
|
15
15
|
operator: ">=",
|
|
16
|
-
args:
|
|
16
|
+
args: 20,
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
else props.onClear({ key: selectorKey(fieldSelector) });
|
|
@@ -22,9 +22,9 @@ export const FilterIntegerDp: Component<FilterProps> = (props) => {
|
|
|
22
22
|
return (
|
|
23
23
|
<div class="control">
|
|
24
24
|
<Checkbox
|
|
25
|
-
desc="Sequencing depth >=
|
|
26
|
-
label="Depth >=
|
|
27
|
-
checked={props.query && props.query.args ===
|
|
25
|
+
desc="Sequencing depth >= 20"
|
|
26
|
+
label="Depth >= 20"
|
|
27
|
+
checked={props.query && props.query.args === 20}
|
|
28
28
|
onChange={onFilterChange}
|
|
29
29
|
/>
|
|
30
30
|
</div>
|
|
@@ -10,6 +10,7 @@ import { GnomAD } from "./info/GnomAD";
|
|
|
10
10
|
import { isAnyCsqInfo, isCsqInfo } from "../../utils/csqUtils";
|
|
11
11
|
import { Vkgl } from "./info/Vkgl";
|
|
12
12
|
import { InheritanceModes } from "./info/InheritanceModes";
|
|
13
|
+
import { Hpo } from "./info/Hpo";
|
|
13
14
|
|
|
14
15
|
export const Info: Component<{
|
|
15
16
|
info: FieldValue;
|
|
@@ -42,6 +43,9 @@ export const Info: Component<{
|
|
|
42
43
|
<Match when={isCsqInfo(props.infoMeta, "VKGL_CL")}>
|
|
43
44
|
<Vkgl {...props} />
|
|
44
45
|
</Match>
|
|
46
|
+
<Match when={isCsqInfo(props.infoMeta, "HPO")}>
|
|
47
|
+
<Hpo {...props} />
|
|
48
|
+
</Match>
|
|
45
49
|
</Switch>
|
|
46
50
|
);
|
|
47
51
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Component, createMemo, For, Show } from "solid-js";
|
|
2
|
+
import { Anchor } from "../../Anchor";
|
|
3
|
+
import { FieldProps } from "../field/Field";
|
|
4
|
+
import { ValueFlag, ValueString } from "@molgenis/vip-report-vcf/src/ValueParser";
|
|
5
|
+
import { getCsqInfo, getCsqInfoIndex } from "../../../utils/csqUtils";
|
|
6
|
+
import { Abbr } from "../../Abbr";
|
|
7
|
+
import { FieldSingleValue } from "../field/FieldSingleValue";
|
|
8
|
+
import { FieldValueString } from "../field/FieldValueString";
|
|
9
|
+
|
|
10
|
+
type HpoTerm = {
|
|
11
|
+
id: string;
|
|
12
|
+
href: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const Hpo: Component<FieldProps> = (props) => {
|
|
16
|
+
const hpoTerms = (): HpoTerm[] =>
|
|
17
|
+
(props.info.value as string[]).map((hpoTermId) => ({
|
|
18
|
+
id: hpoTermId,
|
|
19
|
+
href: `https://hpo.jax.org/app/browse/term/${encodeURI(hpoTermId)}`,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<For each={hpoTerms()}>
|
|
25
|
+
{(hpoTerm, i) => (
|
|
26
|
+
<>
|
|
27
|
+
{i() !== 0 && <span>, </span>}
|
|
28
|
+
<Anchor href={hpoTerm.href}>
|
|
29
|
+
<FieldValueString value={hpoTerm.id} />
|
|
30
|
+
</Anchor>
|
|
31
|
+
</>
|
|
32
|
+
)}
|
|
33
|
+
</For>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -25,6 +25,7 @@ import { Metadata } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
|
25
25
|
import { getSampleLabel } from "../utils/sample";
|
|
26
26
|
import { arrayEquals } from "../utils/utils";
|
|
27
27
|
import { getAllelicBalanceQuery } from "../components/filter/FilterAllelicBalance";
|
|
28
|
+
import { RecordsPerPage, RecordsPerPageEvent } from "../components/RecordsPerPage";
|
|
28
29
|
|
|
29
30
|
export const SampleVariantsView: Component = () => {
|
|
30
31
|
const { sample } = useRouteData<SampleRouteData>();
|
|
@@ -200,6 +201,8 @@ export const SampleVariants: Component<{
|
|
|
200
201
|
const onFilterClear = (event: FilterClearEvent) => actions.clearSampleVariantsFilterQuery(props.sample, event.key);
|
|
201
202
|
const onSortChange = (event: SortEvent) => actions.setSampleVariantsSort(props.sample, event.order);
|
|
202
203
|
const onSortClear = () => actions.setSampleVariantsSort(props.sample, null);
|
|
204
|
+
const onRecordsPerPageChange = (event: RecordsPerPageEvent) =>
|
|
205
|
+
actions.setSampleVariantsPageSize(props.sample, event.number);
|
|
203
206
|
|
|
204
207
|
const params = (): Params => {
|
|
205
208
|
return {
|
|
@@ -231,7 +234,7 @@ export const SampleVariants: Component<{
|
|
|
231
234
|
]);
|
|
232
235
|
|
|
233
236
|
return (
|
|
234
|
-
<div class="columns">
|
|
237
|
+
<div class="columns is-variable is-1">
|
|
235
238
|
<div class="column is-1-fullhd is-2">
|
|
236
239
|
<SearchBox value={searchQuery()} onInput={onSearchChange} />
|
|
237
240
|
<Filters
|
|
@@ -243,9 +246,13 @@ export const SampleVariants: Component<{
|
|
|
243
246
|
/>
|
|
244
247
|
</div>
|
|
245
248
|
<div class="column">
|
|
246
|
-
<div class="columns">
|
|
249
|
+
<div class="columns is-gapless">
|
|
247
250
|
<div class="column is-offset-1-fullhd is-3-fullhd is-4">
|
|
248
|
-
|
|
251
|
+
<Show when={records()} fallback={<Loader />} keyed>
|
|
252
|
+
{(records) => (
|
|
253
|
+
<span class="is-pulled-left inline-control-text ml-2">{records.page.totalElements} records</span>
|
|
254
|
+
)}
|
|
255
|
+
</Show>
|
|
249
256
|
</div>
|
|
250
257
|
<div class="column is-4">
|
|
251
258
|
<Show when={records()} fallback={<Loader />} keyed>
|
|
@@ -253,41 +260,45 @@ export const SampleVariants: Component<{
|
|
|
253
260
|
</Show>
|
|
254
261
|
</div>
|
|
255
262
|
<div class="column">
|
|
256
|
-
<div class="
|
|
257
|
-
|
|
258
|
-
<
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
</div>
|
|
266
|
-
<div class="column">
|
|
267
|
-
<div class="is-pulled-right">
|
|
268
|
-
<RecordDownload
|
|
269
|
-
recordsMetadata={props.recordsMeta}
|
|
270
|
-
query={params().query}
|
|
271
|
-
samples={[props.sample.data, ...props.pedigreeSamples.map((item) => item.data)]}
|
|
272
|
-
/>
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
263
|
+
<div class="field is-grouped is-grouped-right">
|
|
264
|
+
{infoFields().length > 0 && (
|
|
265
|
+
<Sort options={sortOptions()} onChange={onSortChange} onClear={onSortClear} />
|
|
266
|
+
)}
|
|
267
|
+
<RecordDownload
|
|
268
|
+
recordsMetadata={props.recordsMeta}
|
|
269
|
+
query={params().query}
|
|
270
|
+
samples={[props.sample.data, ...props.pedigreeSamples.map((item) => item.data)]}
|
|
271
|
+
/>
|
|
275
272
|
</div>
|
|
276
273
|
</div>
|
|
277
274
|
</div>
|
|
278
|
-
<div class="columns">
|
|
279
|
-
<
|
|
280
|
-
{(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
275
|
+
<div class="columns is-gapless">
|
|
276
|
+
<div class="column is-full">
|
|
277
|
+
<Show when={records()} fallback={<Loader />} keyed>
|
|
278
|
+
{(records) => (
|
|
279
|
+
<>
|
|
280
|
+
<VariantsSampleTable
|
|
281
|
+
item={props.sample}
|
|
282
|
+
pedigreeSamples={props.pedigreeSamples}
|
|
283
|
+
records={records.items}
|
|
284
|
+
recordsMetadata={props.recordsMeta}
|
|
285
|
+
nestedFields={infoFields()}
|
|
286
|
+
htsFileMeta={props.htsFileMeta}
|
|
287
|
+
/>
|
|
288
|
+
<div class="columns is-gapless">
|
|
289
|
+
<div class="column">
|
|
290
|
+
<div class="field is-grouped is-grouped-right">
|
|
291
|
+
<RecordsPerPage
|
|
292
|
+
initialValue={getStateVariants()?.pageSize || 20}
|
|
293
|
+
onChange={onRecordsPerPageChange}
|
|
294
|
+
/>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
</>
|
|
299
|
+
)}
|
|
300
|
+
</Show>
|
|
301
|
+
</div>
|
|
291
302
|
</div>
|
|
292
303
|
</div>
|
|
293
304
|
</div>
|
package/src/views/Variants.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import { Loader } from "../components/Loader";
|
|
|
16
16
|
import { Metadata } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
17
17
|
import { arrayEquals } from "../utils/utils";
|
|
18
18
|
import { FilterChangeEvent, FilterClearEvent } from "../components/filter/Filters";
|
|
19
|
+
import { RecordsPerPage, RecordsPerPageEvent } from "../components/RecordsPerPage";
|
|
19
20
|
|
|
20
21
|
export const VariantsView: Component = () => {
|
|
21
22
|
const [recordsMeta] = createResource(fetchRecordsMeta);
|
|
@@ -49,7 +50,7 @@ export const Variants: Component<{
|
|
|
49
50
|
const onFilterClear = (event: FilterClearEvent) => actions.clearVariantsFilterQuery(event.key);
|
|
50
51
|
const onSortChange = (event: SortEvent) => actions.setVariantsSort(event.order);
|
|
51
52
|
const onSortClear = () => actions.setVariantsSort(null);
|
|
52
|
-
|
|
53
|
+
const onRecordsPerPageChange = (event: RecordsPerPageEvent) => actions.setVariantsPageSize(event.number);
|
|
53
54
|
const params = (): Params => {
|
|
54
55
|
return {
|
|
55
56
|
query: createQuery(searchQuery(), filterQueries(), props.recordsMeta) || undefined,
|
|
@@ -81,49 +82,60 @@ export const Variants: Component<{
|
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
return (
|
|
84
|
-
<
|
|
85
|
-
<div class="
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<div class="
|
|
96
|
-
<div class="
|
|
97
|
-
<
|
|
85
|
+
<div class="columns is-variable is-1">
|
|
86
|
+
<div class="column is-1-fullhd is-2">
|
|
87
|
+
<SearchBox onInput={onSearchChange} />
|
|
88
|
+
<InfoFilters
|
|
89
|
+
fields={flattenFieldMetadata(props.recordsMeta.info)}
|
|
90
|
+
queries={filterQueries()}
|
|
91
|
+
onChange={onFilterChange}
|
|
92
|
+
onClear={onFilterClear}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
<div class="column">
|
|
96
|
+
<div class="columns is-gapless">
|
|
97
|
+
<div class="column is-offset-1-fullhd is-3-fullhd is-4">
|
|
98
|
+
<Show when={records()} fallback={<Loader />} keyed>
|
|
99
|
+
{(records) => (
|
|
100
|
+
<span class="is-pulled-left inline-control-text ml-2">{records.page.totalElements} records</span>
|
|
101
|
+
)}
|
|
102
|
+
</Show>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="column is-4">
|
|
105
|
+
<Show when={records()} fallback={<Loader />} keyed>
|
|
106
|
+
{(records) => <Pager page={records.page} onPageChange={onPageChange} />}
|
|
107
|
+
</Show>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="column">
|
|
110
|
+
<div class="field is-grouped is-grouped-right">
|
|
98
111
|
<Sort options={sortOptions()} onChange={onSortChange} onClear={onSortClear} />
|
|
99
|
-
|
|
100
|
-
<div class="column is-4">
|
|
101
|
-
<Pager page={records()!.page} onPageChange={onPageChange} />
|
|
102
|
-
</div>
|
|
103
|
-
<div class="column">
|
|
104
|
-
<div class="columns">
|
|
105
|
-
<div class="column is-10">
|
|
106
|
-
<span class="is-pulled-right" style={{ margin: "auto" }}>
|
|
107
|
-
{records()!.page.totalElements} records
|
|
108
|
-
</span>
|
|
109
|
-
</div>
|
|
110
|
-
<div class="column">
|
|
111
|
-
<div class="is-pulled-right">
|
|
112
|
-
<RecordDownload recordsMetadata={props.recordsMeta} query={params().query} />
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
112
|
+
<RecordDownload recordsMetadata={props.recordsMeta} query={params().query} />
|
|
116
113
|
</div>
|
|
117
114
|
</div>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
</div>
|
|
116
|
+
<div class="columns is-gapless">
|
|
117
|
+
<div class="column is-full">
|
|
118
|
+
<Show when={records()} fallback={<Loader />} keyed>
|
|
119
|
+
{(records) => (
|
|
120
|
+
<>
|
|
121
|
+
<VariantsTable
|
|
122
|
+
records={records.items}
|
|
123
|
+
recordsMetadata={props.recordsMeta}
|
|
124
|
+
htsFileMeta={props.htsFileMeta}
|
|
125
|
+
/>
|
|
126
|
+
<div class="columns is-gapless">
|
|
127
|
+
<div class="column">
|
|
128
|
+
<div class="field is-grouped is-grouped-right">
|
|
129
|
+
<RecordsPerPage initialValue={pageSize() || 20} onChange={onRecordsPerPageChange} />
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</>
|
|
134
|
+
)}
|
|
135
|
+
</Show>
|
|
124
136
|
</div>
|
|
125
137
|
</div>
|
|
126
138
|
</div>
|
|
127
|
-
</
|
|
139
|
+
</div>
|
|
128
140
|
);
|
|
129
141
|
};
|