@molgenis/vip-report-template 7.1.3 → 8.0.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/.gitattributes +3 -1
- package/README.md +13 -0
- package/eslint.config.mjs +6 -1
- package/package.json +6 -5
- package/scripts/validateConfig/README.txt +5 -0
- package/scripts/validateConfig/compileValidator.ts +17 -0
- package/scripts/validateConfig/createSchema.ts +6 -0
- package/scripts/validateConfig/schema.ts +370 -0
- package/src/App.tsx +2 -1
- package/src/components/DatasetDropdown.tsx +1 -1
- package/src/components/GenomeBrowser.tsx +14 -4
- package/src/components/RecordsTable.tsx +23 -6
- package/src/components/VariantConsequenceContainer.tsx +9 -2
- package/src/components/VariantInfoTable.tsx +1 -1
- package/src/components/VariantsContainer.tsx +47 -9
- package/src/components/VariantsContainerHeader.tsx +1 -8
- package/src/components/field/composed/FieldGenotype.tsx +1 -1
- package/src/components/field/composed/FieldGenotypeStr.tsx +18 -10
- package/src/components/field/composed/FieldGnomAd.tsx +1 -1
- package/src/components/field/composed/FieldInheritanceModes.tsx +1 -4
- package/src/components/field/composed/FieldVkgl.tsx +1 -1
- package/src/components/field/typed/FieldCategorical.tsx +1 -1
- package/src/components/field/typed/FieldCharacter.tsx +1 -1
- package/src/components/field/typed/FieldFlag.tsx +1 -1
- package/src/components/field/typed/FieldFloat.tsx +1 -1
- package/src/components/field/typed/FieldInteger.tsx +1 -1
- package/src/components/field/typed/FieldString.tsx +1 -1
- package/src/components/filter/Filter.tsx +1 -0
- package/src/components/filter/composed/FilterAllelicImbalance.tsx +1 -0
- package/src/components/filter/composed/FilterComposed.tsx +7 -0
- package/src/components/filter/composed/FilterDeNovo.tsx +1 -0
- package/src/components/filter/composed/FilterHpo.tsx +1 -0
- package/src/components/filter/composed/FilterInheritance.tsx +1 -0
- package/src/components/filter/composed/FilterLocus.tsx +17 -3
- package/src/components/filter/composed/FilterPick.tsx +30 -0
- package/src/components/filter/composed/FilterVipC.tsx +1 -0
- package/src/components/filter/composed/FilterVipCS.tsx +1 -0
- package/src/components/filter/fixed/FilterFixed.tsx +7 -0
- package/src/components/filter/typed/FilterCategorical.tsx +18 -1
- package/src/components/filter/typed/FilterFlag.tsx +2 -0
- package/src/components/filter/typed/FilterInterval.tsx +29 -1
- package/src/components/filter/typed/FilterString.tsx +8 -1
- package/src/components/filter/typed/FilterTyped.tsx +1 -0
- package/src/components/form/ButtonApply.tsx +6 -2
- package/src/mocks/GRCh38/README.txt +15 -0
- package/src/mocks/GRCh38/decisionTree.json +201 -0
- package/src/mocks/GRCh38/family.ped +6 -0
- package/src/mocks/GRCh38/field_metadata.json +36 -11
- package/src/mocks/GRCh38/sample1.ped +1 -0
- package/src/mocks/GRCh38/static.ts +36 -148
- package/src/mocks/GRCh38/str.ped +1 -0
- package/src/mocks/GRCh38/vcf/family.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/family.vcf +312 -0
- package/src/mocks/GRCh38/vcf/fixPaths.sql +7 -0
- package/src/mocks/GRCh38/vcf/no_vep.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/{no_vep.vcf.blob → no_vep.vcf} +1 -1
- package/src/mocks/GRCh38/vcf/samples_0.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/samples_1.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/samples_100.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/{samples_100.vcf.blob → samples_100.vcf} +6 -6
- package/src/mocks/GRCh38/vcf/str.db.blob +0 -0
- package/src/mocks/GRCh38/vcf/{str.vcf.blob → str.vcf} +17 -17
- package/src/mocks/MockApiClient.ts +60 -226
- package/src/mocks/config_cram.json +4 -0
- package/src/mocks/config_default_values.json +722 -0
- package/src/mocks/config_vcf.json +15 -1
- package/src/mocks/sql-wasm.wasm.blob +0 -0
- package/src/types/config.d.ts +9 -5
- package/src/types/configCells.d.ts +1 -0
- package/src/types/configFilter.d.ts +1 -0
- package/src/types/configFilterComposed.d.ts +3 -0
- package/src/utils/api.ts +21 -49
- package/src/utils/config/configCellsComposed.ts +1 -1
- package/src/utils/config/configCellsField.ts +2 -0
- package/src/utils/config/configFiltersComposed.ts +7 -0
- package/src/utils/config/configFiltersField.ts +3 -2
- package/src/utils/config/configFiltersFixed.ts +7 -0
- package/src/utils/config/configValidator.precompiled.ts +83402 -0
- package/src/utils/config/configValidator.ts +3 -368
- package/src/utils/csq.ts +5 -10
- package/src/utils/decisionTree.ts +8 -9
- package/src/utils/query/query.ts +3 -2
- package/src/utils/query/queryFilter.ts +2 -3
- package/src/utils/query/queryFilterComposed.ts +12 -12
- package/src/utils/query/queryFilterField.ts +14 -7
- package/src/utils/query/queryFilterFixed.ts +5 -5
- package/src/utils/query/querySample.ts +15 -4
- package/src/utils/query/selector.ts +5 -20
- package/src/utils/query/sort.ts +4 -4
- package/src/utils/vcf.ts +20 -11
- package/src/views/Help.tsx +2 -2
- package/src/views/SampleVariant.tsx +4 -1
- package/src/views/Samples.tsx +10 -3
- package/src/views/data/data.tsx +2 -2
- package/tests/utils/config/configFiltersComposed.test.ts +2 -0
- package/tests/utils/config/configFiltersField.test.ts +4 -2
- package/tests/utils/config/configFiltersFixed.test.ts +23 -6
- package/tests/utils/query/query.test.ts +34 -6
- package/tests/utils/query/queryFilter.test.ts +4 -31
- package/tests/utils/query/queryFilterComposed.test.ts +13 -13
- package/tests/utils/query/queryFilterField.test.ts +5 -5
- package/tests/utils/query/queryFilterFixed.test.ts +5 -5
- package/tests/utils/query/querySample.test.ts +50 -10
- package/tests/utils/query/sort.test.ts +1 -1
- package/tests/utils/vcf.test.ts +1 -0
- package/vite.config.mts +2 -1
- package/src/mocks/GRCh37/alignment.cram.blob +0 -0
- package/src/mocks/GRCh37/alignment.cram.crai.blob +0 -0
- package/src/mocks/GRCh37/decisionTree.json +0 -355
- package/src/mocks/GRCh37/fasta/1-10042288-10042788.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-152520538-152521038.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-16375333-16375833.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-16376162-16376662.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-17348965-17349469.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-17348969-17349469.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/1-17354844-17355344.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/10-126091249-126091749.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/11-134013975-134014475.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/13-77569878-77570378.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/14-105167610-105168110.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/14-89307588-89308088.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/14-89309945-89310445.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/14-89336157-89336657.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/17-29555814-29556314.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/17-29585172-29585672.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/17-29663629-29664129.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/17-29675976-29676476.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/17-29683733-29684233.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/19-11215896-11216396.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/19-11223801-11224301.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/19-17449149-17449649.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/19-17451747-17452247.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/2-47635417-47635917.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/20-62326742-62327242.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/22-50627343-50627843.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/22-50721296-50721796.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/4-106320044-106320544.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/7-42017061-42017561.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/7-42064707-42065207.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/8-145140250-145140750.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/8-61764893-61765393.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/9-107546383-107546883.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/9-107584614-107585114.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/MT-15076-15576.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/X-48932771-48933271.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/fasta/Y-2655391-2655891.fasta.gz.blob +0 -0
- package/src/mocks/GRCh37/field_metadata.json +0 -794
- package/src/mocks/GRCh37/genes.gff.gz.blob +0 -0
- package/src/mocks/GRCh37/sampleTree.json +0 -143
- package/src/mocks/GRCh37/static.ts +0 -189
- package/src/mocks/GRCh37/vcf/family.vcf.blob +0 -134
- package/src/mocks/GRCh38/vcf/family.vcf.blob +0 -272
- package/src/mocks/static.ts +0 -1636
- /package/src/mocks/GRCh38/vcf/{samples_0.vcf.blob → samples_0.vcf} +0 -0
- /package/src/mocks/GRCh38/vcf/{samples_1.vcf.blob → samples_1.vcf} +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { VariantFilters } from "./VariantFilters";
|
|
2
|
-
import {
|
|
2
|
+
import { HtsFileMetadata, RecordParams } from "@molgenis/vip-report-api";
|
|
3
3
|
import { Component, createResource, Show } from "solid-js";
|
|
4
4
|
import { VariantType } from "../utils/variantType.ts";
|
|
5
5
|
import { useNavigate } from "@solidjs/router";
|
|
6
6
|
import { initConfig } from "../utils/config/config.ts";
|
|
7
7
|
import { createQuery } from "../utils/query/query.ts";
|
|
8
8
|
import { PageChangeEvent } from "./Pager";
|
|
9
|
-
import { writeVcf } from "@molgenis/vip-report-vcf";
|
|
10
|
-
import { fetchRecords, MetadataContainer, SampleContainer } from "../utils/api.ts";
|
|
9
|
+
import { InfoOrder, VariantRecords, writeVcf } from "@molgenis/vip-report-vcf";
|
|
10
|
+
import { fetchInfoOrder, fetchRecords, MetadataContainer, SampleContainer } from "../utils/api.ts";
|
|
11
11
|
import { createVcfDownloadFilename } from "../utils/download.ts";
|
|
12
12
|
import { RecordsPerPageChangeEvent } from "./RecordsPerPage";
|
|
13
13
|
import { SortChangeEvent } from "./Sort";
|
|
@@ -33,7 +33,8 @@ export const VariantsContainer: Component<{
|
|
|
33
33
|
|
|
34
34
|
const config = () => initConfig(props.config, props.variantType, props.metadata, props.sample);
|
|
35
35
|
const variantTypeIds = () => (props.sample !== null ? props.sample.variantTypeIds : props.metadata.variantTypeIds);
|
|
36
|
-
const query = () =>
|
|
36
|
+
const query = () =>
|
|
37
|
+
createQuery(config(), props.metadata, props.variantType, props.sample, props.store.getFilterValues());
|
|
37
38
|
|
|
38
39
|
const defaultSort = () => config().variants.sorts.find((configSort) => configSort.selected);
|
|
39
40
|
const sort = () => createSort(props.store.getSort(), defaultSort()) || undefined;
|
|
@@ -41,12 +42,31 @@ export const VariantsContainer: Component<{
|
|
|
41
42
|
const recordsPerPage = () =>
|
|
42
43
|
props.store.getPageSize() !== null ? props.store.getPageSize()! : defaultRecordsPerPage();
|
|
43
44
|
|
|
45
|
+
const sampleIds = () => {
|
|
46
|
+
let sampleIds: number[] | undefined;
|
|
47
|
+
if (props.sample !== null) {
|
|
48
|
+
sampleIds = [props.sample.item.id];
|
|
49
|
+
if (props.sample.maternalSample !== null && props.sample.maternalSample !== undefined) {
|
|
50
|
+
sampleIds.push(props.sample.maternalSample.id);
|
|
51
|
+
}
|
|
52
|
+
if (props.sample.paternalSample !== null && props.sample.paternalSample !== undefined) {
|
|
53
|
+
sampleIds.push(props.sample.paternalSample.id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return sampleIds;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const hasSvTypeField = () => {
|
|
60
|
+
return Object.hasOwn(props.metadata.records.info, "SVTYPE");
|
|
61
|
+
};
|
|
62
|
+
|
|
44
63
|
const [records] = createResource(
|
|
45
|
-
():
|
|
64
|
+
(): RecordParams => ({
|
|
46
65
|
query: query() || undefined,
|
|
47
66
|
page: props.store.getPageNumber() || 0,
|
|
48
67
|
size: recordsPerPage(),
|
|
49
68
|
sort: sort(),
|
|
69
|
+
sampleIds: sampleIds(),
|
|
50
70
|
}),
|
|
51
71
|
fetchRecords,
|
|
52
72
|
);
|
|
@@ -64,15 +84,33 @@ export const VariantsContainer: Component<{
|
|
|
64
84
|
const onRecordsDownload = async () => {
|
|
65
85
|
const samples = props.sample ? getPedigreeSamples(props.sample) : [];
|
|
66
86
|
const filter = samples ? { samples: samples.map((sample) => sample.data.person.individualId) } : undefined;
|
|
87
|
+
const sampleIds = samples ? samples.map((sample) => sample.id) : ([] as number[]);
|
|
67
88
|
|
|
68
89
|
// create vcf using all records that match filters, use default sort to ensure valid vcf ordering
|
|
69
|
-
const records = await fetchRecords({
|
|
70
|
-
|
|
90
|
+
const records = await fetchRecords({
|
|
91
|
+
query: query() || undefined,
|
|
92
|
+
page: 0,
|
|
93
|
+
size: Number.MAX_SAFE_INTEGER,
|
|
94
|
+
sampleIds: sampleIds,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const infoOrder: InfoOrder = await fetchInfoOrder();
|
|
98
|
+
const vcf = writeVcf(
|
|
99
|
+
{
|
|
100
|
+
metadata: props.metadata.records,
|
|
101
|
+
data: records.items.reduce((acc, item) => {
|
|
102
|
+
acc[item.id] = item.data;
|
|
103
|
+
return acc;
|
|
104
|
+
}, {} as VariantRecords),
|
|
105
|
+
infoOrder: infoOrder,
|
|
106
|
+
},
|
|
107
|
+
filter,
|
|
108
|
+
);
|
|
71
109
|
|
|
72
110
|
const url = window.URL.createObjectURL(new Blob([vcf]));
|
|
73
111
|
const link = document.createElement("a");
|
|
74
112
|
link.href = url;
|
|
75
|
-
link.setAttribute("download", createVcfDownloadFilename(props.metadata.htsFile));
|
|
113
|
+
link.setAttribute("download", createVcfDownloadFilename(props.metadata.app.htsFile as HtsFileMetadata));
|
|
76
114
|
document.body.appendChild(link);
|
|
77
115
|
link.click();
|
|
78
116
|
document.body.removeChild(link);
|
|
@@ -101,7 +139,7 @@ export const VariantsContainer: Component<{
|
|
|
101
139
|
</div>
|
|
102
140
|
<div class="columns is-1">
|
|
103
141
|
<div class="column is-2-fullhd is-3">
|
|
104
|
-
<Show when={variantTypeIds().size > 1}>
|
|
142
|
+
<Show when={variantTypeIds().size > 1 && hasSvTypeField()}>
|
|
105
143
|
<div class="columns">
|
|
106
144
|
<div class="column">
|
|
107
145
|
<VariantTypeSelect
|
|
@@ -32,9 +32,8 @@ export const VariantsContainerHeader: Component<{
|
|
|
32
32
|
if (props.sample) {
|
|
33
33
|
const sampleFather = props.sample.paternalSample;
|
|
34
34
|
const sampleMother = props.sample.maternalSample;
|
|
35
|
-
const sampleOtherFamilyMembers = props.sample.otherPedigreeSamples;
|
|
36
35
|
|
|
37
|
-
if (
|
|
36
|
+
if (sampleFather !== null || sampleMother !== null) {
|
|
38
37
|
const tokens: string[] = [];
|
|
39
38
|
if (sampleMother !== null) {
|
|
40
39
|
tokens.push(`mother (${getTitleAffectedStatusLabel(sampleMother)})`);
|
|
@@ -43,12 +42,6 @@ export const VariantsContainerHeader: Component<{
|
|
|
43
42
|
tokens.push(`father (${getTitleAffectedStatusLabel(sampleFather)})`);
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
for (const familyMember of sampleOtherFamilyMembers) {
|
|
47
|
-
tokens.push(
|
|
48
|
-
`${getSampleLabel(familyMember)} (${getTitleSampleSexLabel(familyMember)} ${getTitleAffectedStatusLabel(familyMember)})`,
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
45
|
let str = tokens.pop() as string;
|
|
53
46
|
if (tokens.length > 0) str = `${tokens.join(", ")} and ${str}`;
|
|
54
47
|
subtitle = `Includes genotypes for ${str}`;
|
|
@@ -12,7 +12,7 @@ export const FieldGenotype: Component<{
|
|
|
12
12
|
const value = props.value.svType;
|
|
13
13
|
|
|
14
14
|
let variantType: VariantTypeId;
|
|
15
|
-
if (value === null) {
|
|
15
|
+
if (value === null || value === undefined) {
|
|
16
16
|
variantType = "snv";
|
|
17
17
|
} else if (value === "STR") {
|
|
18
18
|
variantType = "str";
|
|
@@ -6,20 +6,17 @@ import { FieldGenotypeSnvSv } from "./FieldGenotypeSnvSv.tsx";
|
|
|
6
6
|
export const FieldGenotypeStr: Component<{
|
|
7
7
|
value: CellValueGenotype;
|
|
8
8
|
}> = (props) => {
|
|
9
|
-
const showGenotype = () =>
|
|
10
|
-
props.value.displayRepeatUnit !== undefined &&
|
|
11
|
-
props.value.repeatUnitValue !== undefined &&
|
|
12
|
-
props.value.repeatCount !== undefined &&
|
|
13
|
-
props.value.repeatUnitMatch !== undefined;
|
|
9
|
+
const showGenotype = () => props.value.repeatUnitValue != null && props.value.repeatCount != null;
|
|
14
10
|
|
|
15
11
|
return (
|
|
16
12
|
<Show when={showGenotype()} fallback={<FieldGenotypeSnvSv value={props.value} />}>
|
|
17
|
-
<
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
<Show when={props.value.displayRepeatUnit != null} fallback={<AlleleStr value={props.value.repeatUnitValue!} />}>
|
|
14
|
+
<abbr title={`display repeat unit familiar to clinician: ${props.value.displayRepeatUnit!}`}>
|
|
15
|
+
<AlleleStr value={props.value.repeatUnitValue!} />
|
|
16
|
+
</abbr>
|
|
17
|
+
</Show>
|
|
21
18
|
<span class="ml-1">{`(n=${props.value.repeatCount!})`}</span>
|
|
22
|
-
<Show when={
|
|
19
|
+
<Show when={props.value.repeatUnitMatch === false}>
|
|
23
20
|
<abbr
|
|
24
21
|
title={"the called repeat unit does not match the repeat unit in the loci bed file"}
|
|
25
22
|
class="ml-1 is-clickable"
|
|
@@ -30,3 +27,14 @@ export const FieldGenotypeStr: Component<{
|
|
|
30
27
|
</Show>
|
|
31
28
|
);
|
|
32
29
|
};
|
|
30
|
+
|
|
31
|
+
const AlleleStr: Component<{
|
|
32
|
+
value: string;
|
|
33
|
+
}> = (props) => {
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<Allele value={props.value} isAbbreviate={false} />
|
|
37
|
+
<sub>n</sub>
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -11,10 +11,7 @@ export const FieldInheritanceModes: Component<{ value: CellValueInheritanceModes
|
|
|
11
11
|
(inheritanceModesGene() !== undefined && inheritanceModesGene().length === 0) ||
|
|
12
12
|
inheritanceModesGene().findIndex((category) => category?.value === "AR") !== -1
|
|
13
13
|
) {
|
|
14
|
-
isArInheritance =
|
|
15
|
-
props.value.isPossibleCompound !== undefined &&
|
|
16
|
-
props.value.isPossibleCompound !== null &&
|
|
17
|
-
props.value.isPossibleCompound;
|
|
14
|
+
isArInheritance = props.value.isPossibleCompound != null && props.value.isPossibleCompound;
|
|
18
15
|
}
|
|
19
16
|
return isArInheritance;
|
|
20
17
|
};
|
|
@@ -20,7 +20,7 @@ export const FieldVkgl: Component<{ value: CellValueVkgl }> = (props) => {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
const descriptions = Object.entries(labValues)
|
|
23
|
-
.filter(([, value]) => value
|
|
23
|
+
.filter(([, value]) => value != null)
|
|
24
24
|
.map(([key, value]) => `${key}:${value?.label}`);
|
|
25
25
|
|
|
26
26
|
return descriptions.length > 0 ? descriptions.join(", ") : null;
|
|
@@ -8,7 +8,7 @@ export const FieldCategorical: Component<{
|
|
|
8
8
|
metadata: FieldMetadata;
|
|
9
9
|
}> = (props) => {
|
|
10
10
|
return (
|
|
11
|
-
<Show when={props.value
|
|
11
|
+
<Show when={props.value != null}>
|
|
12
12
|
<Show when={props.value!.description} fallback={<span>{props.value!.label}</span>}>
|
|
13
13
|
{(description) => <Abbr title={description()} value={props.value!.label} />}
|
|
14
14
|
</Show>
|
|
@@ -5,7 +5,7 @@ export const FieldFlag: Component<{
|
|
|
5
5
|
value: ValueFlag | undefined;
|
|
6
6
|
}> = (props) => {
|
|
7
7
|
return (
|
|
8
|
-
<Show when={props.value
|
|
8
|
+
<Show when={props.value != null}>
|
|
9
9
|
<span>{(props.value as boolean).toString()}</span>
|
|
10
10
|
</Show>
|
|
11
11
|
);
|
|
@@ -6,7 +6,7 @@ export const FieldFloat: Component<{
|
|
|
6
6
|
value: ValueFloat | undefined;
|
|
7
7
|
}> = (props) => {
|
|
8
8
|
return (
|
|
9
|
-
<Show when={props.value
|
|
9
|
+
<Show when={props.value != null}>
|
|
10
10
|
<Show
|
|
11
11
|
when={(props.value as number).toString().length > 6}
|
|
12
12
|
fallback={<span>{(props.value as number).toString()}</span>}
|
|
@@ -6,7 +6,7 @@ export const FieldString: Component<{
|
|
|
6
6
|
value: ValueString | undefined;
|
|
7
7
|
}> = (props) => {
|
|
8
8
|
return (
|
|
9
|
-
<Show when={props.value
|
|
9
|
+
<Show when={props.value != null}>
|
|
10
10
|
<Show when={(props.value as string).length > 20} fallback={<span>{props.value as string}</span>}>
|
|
11
11
|
<Abbr title={props.value as string} value={(props.value as string).substring(0, 20)} />
|
|
12
12
|
</Show>
|
|
@@ -24,6 +24,7 @@ export type FilterValueClearCallback = () => void;
|
|
|
24
24
|
export interface FilterProps<C extends ConfigFilterBase, FilterValueType> {
|
|
25
25
|
config: C;
|
|
26
26
|
value?: FilterValueType;
|
|
27
|
+
defaultValue?: string;
|
|
27
28
|
onValueChange: FilterValueChangeCallback<FilterValueType>;
|
|
28
29
|
onValueClear: FilterValueClearCallback;
|
|
29
30
|
}
|
|
@@ -35,6 +35,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
35
35
|
<FilterHpo
|
|
36
36
|
config={props.config as ConfigFilterHpo}
|
|
37
37
|
value={props.value as FilterValueHpo | undefined}
|
|
38
|
+
defaultValue={props.defaultValue}
|
|
38
39
|
onValueChange={props.onValueChange}
|
|
39
40
|
onValueClear={props.onValueClear}
|
|
40
41
|
/>
|
|
@@ -43,6 +44,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
43
44
|
<FilterLocus
|
|
44
45
|
config={props.config as ConfigFilterLocus}
|
|
45
46
|
value={props.value as FilterValueLocus | undefined}
|
|
47
|
+
defaultValue={props.defaultValue}
|
|
46
48
|
onValueChange={props.onValueChange}
|
|
47
49
|
onValueClear={props.onValueClear}
|
|
48
50
|
/>
|
|
@@ -51,6 +53,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
51
53
|
<FilterAllelicImbalance
|
|
52
54
|
config={props.config as ConfigFilterAllelicImbalance}
|
|
53
55
|
value={props.value as FilterValueAllelicImbalance | undefined}
|
|
56
|
+
defaultValue={props.defaultValue}
|
|
54
57
|
onValueChange={props.onValueChange}
|
|
55
58
|
onValueClear={props.onValueClear}
|
|
56
59
|
/>
|
|
@@ -59,6 +62,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
59
62
|
<FilterInheritance
|
|
60
63
|
config={props.config as ConfigFilterInheritanceMatch}
|
|
61
64
|
value={props.value as FilterValueInheritanceMatch | undefined}
|
|
65
|
+
defaultValue={props.defaultValue}
|
|
62
66
|
onValueChange={props.onValueChange}
|
|
63
67
|
onValueClear={props.onValueClear}
|
|
64
68
|
/>
|
|
@@ -67,6 +71,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
67
71
|
<FilterDeNovo
|
|
68
72
|
config={props.config as ConfigFilterDeNovo}
|
|
69
73
|
value={props.value as FilterValueDeNovo | undefined}
|
|
74
|
+
defaultValue={props.defaultValue}
|
|
70
75
|
onValueChange={props.onValueChange}
|
|
71
76
|
onValueClear={props.onValueClear}
|
|
72
77
|
/>
|
|
@@ -75,6 +80,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
75
80
|
<FilterVipC
|
|
76
81
|
config={props.config as ConfigFilterVipC}
|
|
77
82
|
value={props.value as FilterValueVipC | undefined}
|
|
83
|
+
defaultValue={props.defaultValue}
|
|
78
84
|
onValueChange={props.onValueChange}
|
|
79
85
|
onValueClear={props.onValueClear}
|
|
80
86
|
/>
|
|
@@ -83,6 +89,7 @@ export const FilterComposed: Component<FilterProps<ConfigFilterComposed, FilterV
|
|
|
83
89
|
<FilterVipCS
|
|
84
90
|
config={props.config as ConfigFilterVipCS}
|
|
85
91
|
value={props.value as FilterValueVipCS | undefined}
|
|
92
|
+
defaultValue={props.defaultValue}
|
|
86
93
|
onValueChange={props.onValueChange}
|
|
87
94
|
onValueClear={props.onValueClear}
|
|
88
95
|
/>
|
|
@@ -28,6 +28,7 @@ export const FilterDeNovo: Component<FilterProps<ConfigFilterDeNovo, FilterValue
|
|
|
28
28
|
<FilterCategorical
|
|
29
29
|
config={config()}
|
|
30
30
|
value={props.value as FilterValueCategorical}
|
|
31
|
+
defaultValue={props.defaultValue}
|
|
31
32
|
onValueChange={props.onValueChange}
|
|
32
33
|
onValueClear={props.onValueClear}
|
|
33
34
|
/>
|
|
@@ -9,6 +9,7 @@ export const FilterHpo: Component<FilterProps<ConfigFilterHpo, FilterValueHpo>>
|
|
|
9
9
|
<FilterTyped
|
|
10
10
|
config={props.config as ConfigFilterField}
|
|
11
11
|
value={props.value as FilterValueCategorical}
|
|
12
|
+
defaultValue={props.defaultValue}
|
|
12
13
|
onValueChange={props.onValueChange as FilterValueChangeCallback<FilterValueField>}
|
|
13
14
|
onValueClear={props.onValueClear}
|
|
14
15
|
/>
|
|
@@ -35,6 +35,7 @@ export const FilterInheritance: Component<FilterProps<ConfigFilterInheritanceMat
|
|
|
35
35
|
<FilterCategorical
|
|
36
36
|
config={config()}
|
|
37
37
|
value={props.value as FilterValueCategorical}
|
|
38
|
+
defaultValue={props.defaultValue}
|
|
38
39
|
onValueChange={props.onValueChange}
|
|
39
40
|
onValueClear={props.onValueClear}
|
|
40
41
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createEffect, createSignal } from "solid-js";
|
|
1
|
+
import { Component, createEffect, createSignal, onMount } from "solid-js";
|
|
2
2
|
import { FilterWrapper } from "../FilterWrapper";
|
|
3
3
|
import { ButtonApply } from "../../form/ButtonApply";
|
|
4
4
|
import { ButtonReset } from "../../form/ButtonReset";
|
|
@@ -23,6 +23,21 @@ export const FilterLocus: Component<FilterProps<ConfigFilterLocus, FilterValueLo
|
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
onMount(() => {
|
|
27
|
+
const pattern = /^(\w+):(\w+)-(\w+)$/;
|
|
28
|
+
if (props.config.defaultValue !== undefined) {
|
|
29
|
+
const match = (props.config.defaultValue as string).match(pattern);
|
|
30
|
+
if (!match) {
|
|
31
|
+
throw new Error(`Invalid region format: ${props.config.defaultValue}`);
|
|
32
|
+
}
|
|
33
|
+
const [, chrom, start, end] = match;
|
|
34
|
+
setChromosome(chrom);
|
|
35
|
+
setStartPosition(start);
|
|
36
|
+
setEndPosition(end);
|
|
37
|
+
onApply();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
26
41
|
const onApply = () => {
|
|
27
42
|
const chr = chromosome();
|
|
28
43
|
if (chr === undefined) return;
|
|
@@ -47,7 +62,6 @@ export const FilterLocus: Component<FilterProps<ConfigFilterLocus, FilterValueLo
|
|
|
47
62
|
|
|
48
63
|
props.onValueClear();
|
|
49
64
|
};
|
|
50
|
-
|
|
51
65
|
return (
|
|
52
66
|
<FilterWrapper config={props.config} error={error()}>
|
|
53
67
|
<div class="field is-grouped">
|
|
@@ -66,7 +80,7 @@ export const FilterLocus: Component<FilterProps<ConfigFilterLocus, FilterValueLo
|
|
|
66
80
|
<Input placeholder="End" value={endPosition()} onValueChange={(e) => setEndPosition(e.value)} />
|
|
67
81
|
</div>
|
|
68
82
|
<div class="control">
|
|
69
|
-
<ButtonApply onClick={onApply} />
|
|
83
|
+
<ButtonApply onClick={onApply} isEnabled={() => chromosome() !== undefined && chromosome() !== ""} />
|
|
70
84
|
</div>
|
|
71
85
|
</div>
|
|
72
86
|
<ButtonReset onClick={() => onReset()} />
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Component } from "solid-js";
|
|
2
|
+
import { ConfigFilterPick, FilterValuePick } from "../../../types/configFilterComposed";
|
|
3
|
+
import { FilterProps } from "../Filter.tsx";
|
|
4
|
+
import { ConfigFilterField, FilterValueCategorical } from "../../../types/configFilter";
|
|
5
|
+
import { FilterCategorical } from "../typed/FilterCategorical";
|
|
6
|
+
|
|
7
|
+
export const FilterPick: Component<FilterProps<ConfigFilterPick, FilterValuePick>> = (props) => {
|
|
8
|
+
const config = (): ConfigFilterField => ({
|
|
9
|
+
...props.config,
|
|
10
|
+
field: {
|
|
11
|
+
...props.config.field,
|
|
12
|
+
categories: {
|
|
13
|
+
true: {
|
|
14
|
+
label: "True",
|
|
15
|
+
description: "VEP Picked transcript.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<FilterCategorical
|
|
23
|
+
config={config()}
|
|
24
|
+
value={props.value as FilterValueCategorical}
|
|
25
|
+
defaultValue={props.defaultValue}
|
|
26
|
+
onValueChange={props.onValueChange}
|
|
27
|
+
onValueClear={props.onValueClear}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
@@ -9,6 +9,7 @@ export const FilterVipC: Component<FilterProps<ConfigFilterVipC, FilterValueVipC
|
|
|
9
9
|
<FilterTyped
|
|
10
10
|
config={props.config as ConfigFilterField}
|
|
11
11
|
value={props.value as FilterValueCategorical}
|
|
12
|
+
defaultValue={props.defaultValue}
|
|
12
13
|
onValueChange={props.onValueChange as FilterValueChangeCallback<FilterValueField>}
|
|
13
14
|
onValueClear={props.onValueClear}
|
|
14
15
|
/>
|
|
@@ -9,6 +9,7 @@ export const FilterVipCS: Component<FilterProps<ConfigFilterVipCS, FilterValueVi
|
|
|
9
9
|
<FilterTyped
|
|
10
10
|
config={props.config as ConfigFilterField}
|
|
11
11
|
value={props.value as FilterValueCategorical}
|
|
12
|
+
defaultValue={props.defaultValue}
|
|
12
13
|
onValueChange={props.onValueChange as FilterValueChangeCallback<FilterValueField>}
|
|
13
14
|
onValueClear={props.onValueClear}
|
|
14
15
|
/>
|
|
@@ -39,6 +39,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
39
39
|
<FilterChrom
|
|
40
40
|
config={props.config as ConfigFilterChrom}
|
|
41
41
|
value={props.value as FilterValueChrom}
|
|
42
|
+
defaultValue={props.defaultValue}
|
|
42
43
|
onValueChange={props.onValueChange}
|
|
43
44
|
onValueClear={props.onValueClear}
|
|
44
45
|
/>
|
|
@@ -47,6 +48,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
47
48
|
<FilterPos
|
|
48
49
|
config={props.config as ConfigFilterPos}
|
|
49
50
|
value={props.value as FilterValuePos}
|
|
51
|
+
defaultValue={props.defaultValue}
|
|
50
52
|
onValueChange={props.onValueChange}
|
|
51
53
|
onValueClear={props.onValueClear}
|
|
52
54
|
/>
|
|
@@ -55,6 +57,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
55
57
|
<FilterId
|
|
56
58
|
config={props.config as ConfigFilterId}
|
|
57
59
|
value={props.value as FilterValueId}
|
|
60
|
+
defaultValue={props.defaultValue}
|
|
58
61
|
onValueChange={props.onValueChange}
|
|
59
62
|
onValueClear={props.onValueClear}
|
|
60
63
|
/>
|
|
@@ -63,6 +66,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
63
66
|
<FilterRef
|
|
64
67
|
config={props.config as ConfigFilterRef}
|
|
65
68
|
value={props.value as FilterValueRef}
|
|
69
|
+
defaultValue={props.defaultValue}
|
|
66
70
|
onValueChange={props.onValueChange}
|
|
67
71
|
onValueClear={props.onValueClear}
|
|
68
72
|
/>
|
|
@@ -71,6 +75,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
71
75
|
<FilterAlt
|
|
72
76
|
config={props.config as ConfigFilterAlt}
|
|
73
77
|
value={props.value as FilterValueAlt}
|
|
78
|
+
defaultValue={props.defaultValue}
|
|
74
79
|
onValueChange={props.onValueChange}
|
|
75
80
|
onValueClear={props.onValueClear}
|
|
76
81
|
/>
|
|
@@ -79,6 +84,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
79
84
|
<FilterQual
|
|
80
85
|
config={props.config as ConfigFilterQual}
|
|
81
86
|
value={props.value as FilterValueQual}
|
|
87
|
+
defaultValue={props.defaultValue}
|
|
82
88
|
onValueChange={props.onValueChange}
|
|
83
89
|
onValueClear={props.onValueClear}
|
|
84
90
|
/>
|
|
@@ -87,6 +93,7 @@ export const FilterFixed: Component<FilterProps<ConfigFilterFixed, FilterValue>>
|
|
|
87
93
|
<FilterFilter
|
|
88
94
|
config={props.config as ConfigFilterFilter}
|
|
89
95
|
value={props.value as FilterValueFilter}
|
|
96
|
+
defaultValue={props.defaultValue}
|
|
90
97
|
onValueChange={props.onValueChange}
|
|
91
98
|
onValueClear={props.onValueClear}
|
|
92
99
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createEffect, createSignal, For, JSX, Show } from "solid-js";
|
|
1
|
+
import { Component, createEffect, createSignal, For, JSX, onMount, Show } from "solid-js";
|
|
2
2
|
import { FilterWrapper } from "../FilterWrapper";
|
|
3
3
|
import {
|
|
4
4
|
ConfigFilterField,
|
|
@@ -88,6 +88,23 @@ export const FilterCategorical: Component<FilterProps<ConfigFilterField, FilterV
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
+
function validateValues(values: string[], filterCategories: FilterCategory[]) {
|
|
92
|
+
const invalidValues = values.filter((v) => !filterCategories.map((fc) => fc.id).includes(v));
|
|
93
|
+
if (invalidValues.length > 0) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Invalid default values ('${invalidValues.join(", ")}') found for filter '${props.config.field.id}'.`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
onMount(() => {
|
|
101
|
+
if (props.config.defaultValue !== undefined) {
|
|
102
|
+
const values = props.config.defaultValue.split(",");
|
|
103
|
+
validateValues(values, categories());
|
|
104
|
+
props.onValueChange({ value: values as FilterValueCategorical });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
91
108
|
return (
|
|
92
109
|
<FilterWrapper config={props.config} tooltipContentElement={tooltipContentElement()}>
|
|
93
110
|
<div class="field">
|
|
@@ -9,6 +9,7 @@ export const FilterFlag: Component<FilterProps<ConfigFilterField, FilterValueFla
|
|
|
9
9
|
field: {
|
|
10
10
|
...props.config.field,
|
|
11
11
|
categories: { true: { label: "True" }, false: { label: "False" } },
|
|
12
|
+
required: true, //Missing == false for flags
|
|
12
13
|
},
|
|
13
14
|
});
|
|
14
15
|
|
|
@@ -16,6 +17,7 @@ export const FilterFlag: Component<FilterProps<ConfigFilterField, FilterValueFla
|
|
|
16
17
|
<FilterCategorical
|
|
17
18
|
config={config()}
|
|
18
19
|
value={props.value as FilterValueCategorical}
|
|
20
|
+
defaultValue={props.defaultValue}
|
|
19
21
|
onValueChange={props.onValueChange}
|
|
20
22
|
onValueClear={props.onValueClear}
|
|
21
23
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createEffect, createSignal } from "solid-js";
|
|
1
|
+
import { Component, createEffect, createSignal, onMount } from "solid-js";
|
|
2
2
|
import { FilterWrapper } from "../FilterWrapper";
|
|
3
3
|
import { ConfigFilterField, FilterValueInterval } from "../../../types/configFilter";
|
|
4
4
|
import { Input } from "../../form/Input";
|
|
@@ -24,6 +24,34 @@ export const FilterInterval: Component<FilterProps<ConfigFilterField, FilterValu
|
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
onMount(() => {
|
|
28
|
+
if (props.config.defaultValue !== undefined) {
|
|
29
|
+
const split = props.config.defaultValue.split(",");
|
|
30
|
+
if (split.length >= 1) {
|
|
31
|
+
if (split[0] !== undefined && split[0] !== "") {
|
|
32
|
+
if (Number.isNaN(Number(split[0]))) {
|
|
33
|
+
throw new TypeError(
|
|
34
|
+
`'${props.config.defaultValue}' is not a valid default value for field '${props.config.field.id}'.`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
setLeftInputValue(split[0]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (split.length === 2) {
|
|
41
|
+
if (split[1] !== undefined && split[1] !== "") {
|
|
42
|
+
if (Number.isNaN(Number(split[1]))) {
|
|
43
|
+
throw new TypeError(
|
|
44
|
+
`'${props.config.defaultValue}' is not a valid default value for field '${props.config.field.id}'.`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
console.log("7");
|
|
48
|
+
setRightInputValue(split[1]);
|
|
49
|
+
}
|
|
50
|
+
onApply();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
27
55
|
const onApply = () => {
|
|
28
56
|
const validationResult = validateIntervalInput(props.config.id, leftInputValue(), rightInputValue());
|
|
29
57
|
if (validationResult !== undefined) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, createEffect, createSignal } from "solid-js";
|
|
1
|
+
import { Component, createEffect, createSignal, onMount } from "solid-js";
|
|
2
2
|
import { FilterWrapper } from "../FilterWrapper";
|
|
3
3
|
import { ConfigFilterField, FilterValueString } from "../../../types/configFilter";
|
|
4
4
|
import { Input } from "../../form/Input";
|
|
@@ -23,6 +23,13 @@ export const FilterString: Component<FilterProps<ConfigFilterField, FilterValueS
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
onMount(() => {
|
|
27
|
+
if (props.config.defaultValue !== undefined) {
|
|
28
|
+
setInputValue(props.config.defaultValue);
|
|
29
|
+
onApply();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
26
33
|
return (
|
|
27
34
|
<FilterWrapper config={props.config}>
|
|
28
35
|
<div class="field is-grouped">
|
|
@@ -31,6 +31,7 @@ export const FilterTyped: Component<FilterProps<ConfigFilterField, FilterValueFi
|
|
|
31
31
|
<FilterString
|
|
32
32
|
config={props.config}
|
|
33
33
|
value={props.value as FilterValueString}
|
|
34
|
+
defaultValue={props.defaultValue}
|
|
34
35
|
onValueChange={props.onValueChange}
|
|
35
36
|
onValueClear={props.onValueClear}
|
|
36
37
|
/>
|