@molgenis/vip-report-template 5.0.0 → 5.1.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/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
+ os: linux
2
+ dist: focal
1
3
  language: node_js
2
4
  node_js:
3
5
  - lts/*
@@ -10,7 +12,7 @@ cache:
10
12
  directories:
11
13
  - "~/.pnpm-store"
12
14
  before_install:
13
- - curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm@7
15
+ - curl -f https://get.pnpm.io/v6.32.js | node - add --global pnpm@7
14
16
  - pnpm config set store-dir ~/.pnpm-store
15
17
  install:
16
18
  - pnpm install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molgenis/vip-report-template",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Report Template for Variant Call Format (VCF) Report Generator",
5
5
  "scripts": {
6
6
  "build": "vite build",
@@ -35,8 +35,8 @@
35
35
  "dependencies": {
36
36
  "@fortawesome/fontawesome-svg-core": "^6.2.0",
37
37
  "@fortawesome/free-solid-svg-icons": "^6.2.0",
38
- "@molgenis/vip-report-api": "^4.0.1",
39
- "@molgenis/vip-report-vcf": "^1.2.7",
38
+ "@molgenis/vip-report-api": "^4.3.1",
39
+ "@molgenis/vip-report-vcf": "^1.3.2",
40
40
  "base64-js": "^1.5.1",
41
41
  "igv": "^2.13.3",
42
42
  "solid-app-router": "^0.4.2",
@@ -39,8 +39,10 @@ export const VariantSampleTable: Component<{
39
39
  formatMetadata={formatField}
40
40
  record={props.record}
41
41
  isAbbreviate={false}
42
- allelicDepth={props.record.data.s[props.samples[i()].index]["AD"] as number[]}
43
- readDepth={props.record.data.s[props.samples[i()].index]["DP"] as number}
42
+ allelicBalance={
43
+ props.record.data.s[props.samples[i()].index]["VIAB"] as number | undefined | null
44
+ }
45
+ readDepth={props.record.data.s[props.samples[i()].index]["DP"] as number | undefined}
44
46
  />
45
47
  </td>
46
48
  )}
@@ -6,7 +6,7 @@ import { Link } from "solid-app-router";
6
6
  import { HtsFileMetadata, Item, Sample } from "@molgenis/vip-report-api/src/Api";
7
7
  import { GenotypeField } from "./record/format/GenotypeField";
8
8
  import { InfoCollapsablePane } from "./InfoCollapsablePane";
9
- import { Component, createMemo, For } from "solid-js";
9
+ import { Component, createMemo, createSignal, For, onMount, Show } from "solid-js";
10
10
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
11
11
  import { FieldHeader } from "./FieldHeader";
12
12
  import { Abbr } from "./Abbr";
@@ -22,6 +22,32 @@ export const VariantsSampleTable: Component<{
22
22
  }> = (props) => {
23
23
  const samples = createMemo(() => [props.item.data, ...props.pedigreeSamples.map((item) => item.data)]);
24
24
 
25
+ const [proband, setProband] = createSignal<Sample | undefined>();
26
+ const [father, setFather] = createSignal<Sample | undefined>();
27
+ const [mother, setMother] = createSignal<Sample | undefined>();
28
+ const [otherFamilyMembers, setOtherFamilyMembers] = createSignal<Sample[]>([]);
29
+
30
+ onMount(() => {
31
+ const familyMembers: Sample[] = [];
32
+ setProband(props.item.data);
33
+ samples().forEach((sample) => {
34
+ if (
35
+ (proband() as Sample).person.maternalId !== "0" &&
36
+ sample.person.individualId === (proband() as Sample).person.maternalId
37
+ ) {
38
+ setMother(sample);
39
+ } else if (
40
+ (proband() as Sample).person.paternalId !== "0" &&
41
+ sample.person.individualId === (proband() as Sample).person.paternalId
42
+ ) {
43
+ setFather(sample);
44
+ } else if (sample.person.individualId !== (proband() as Sample).person.individualId) {
45
+ familyMembers.push(sample);
46
+ }
47
+ });
48
+ setOtherFamilyMembers(familyMembers);
49
+ });
50
+
25
51
  return (
26
52
  <div style={{ display: "grid" }}>
27
53
  {/* workaround for https://github.com/jgthms/bulma/issues/2572#issuecomment-523099776 */}
@@ -31,7 +57,43 @@ export const VariantsSampleTable: Component<{
31
57
  <tr>
32
58
  <th>Position</th>
33
59
  <th>Reference</th>
34
- <For each={samples()}>
60
+ <Show when={proband()} keyed>
61
+ {(proband) => (
62
+ <th>
63
+ <Abbr
64
+ title={`${
65
+ proband.person.individualId
66
+ }: ${proband.person.sex.toLowerCase()}, ${proband.person.affectedStatus.toLowerCase()}`}
67
+ value="Proband"
68
+ />
69
+ </th>
70
+ )}
71
+ </Show>
72
+ <Show when={mother()} keyed>
73
+ {(mother) => (
74
+ <th>
75
+ <Abbr
76
+ title={`${
77
+ mother.person.individualId
78
+ }: ${mother.person.sex.toLowerCase()}, ${mother.person.affectedStatus.toLowerCase()}`}
79
+ value="Mother"
80
+ />
81
+ </th>
82
+ )}
83
+ </Show>
84
+ <Show when={father()} keyed>
85
+ {(father) => (
86
+ <th>
87
+ <Abbr
88
+ title={`${
89
+ father.person.individualId
90
+ }: ${father.person.sex.toLowerCase()}, ${father.person.affectedStatus.toLowerCase()}`}
91
+ value="Father"
92
+ />
93
+ </th>
94
+ )}
95
+ </Show>
96
+ <For each={otherFamilyMembers()}>
35
97
  {(sample: Sample) => (
36
98
  <th>
37
99
  <Abbr
@@ -62,19 +124,63 @@ export const VariantsSampleTable: Component<{
62
124
  <td>
63
125
  <Ref value={record.data.r} isAbbreviate={true} />
64
126
  </td>
65
- <For each={samples()}>
66
- {(sample: Sample) => (
127
+ <Show when={proband()} keyed>
128
+ {(proband) => (
129
+ <td>
130
+ <GenotypeField
131
+ genotype={record.data.s[proband.index]["GT"] as Genotype}
132
+ refAllele={record.data.r}
133
+ altAlleles={record.data.a}
134
+ isAbbreviate={true}
135
+ allelicBalance={record.data.s[proband.index]["VIAB"] as number | undefined | null}
136
+ readDepth={record.data.s[proband.index]["DP"] as number | undefined}
137
+ />
138
+ </td>
139
+ )}
140
+ </Show>
141
+ <Show when={mother()} keyed>
142
+ {(mother) => (
67
143
  <td>
68
144
  <GenotypeField
69
- genotype={record.data.s[sample.index]["GT"] as Genotype}
145
+ genotype={record.data.s[mother.index]["GT"] as Genotype}
70
146
  refAllele={record.data.r}
71
147
  altAlleles={record.data.a}
72
148
  isAbbreviate={true}
73
- allelicDepth={record.data.s[sample.index]["AD"] as number[]}
74
- readDepth={record.data.s[sample.index]["DP"] as number}
149
+ allelicBalance={record.data.s[mother.index]["VIAB"] as number | undefined | null}
150
+ readDepth={record.data.s[mother.index]["DP"] as number | undefined}
75
151
  />
76
152
  </td>
77
153
  )}
154
+ </Show>
155
+ <Show when={father()} keyed>
156
+ {(father) => (
157
+ <td>
158
+ <GenotypeField
159
+ genotype={record.data.s[father.index]["GT"] as Genotype}
160
+ refAllele={record.data.r}
161
+ altAlleles={record.data.a}
162
+ isAbbreviate={true}
163
+ allelicBalance={record.data.s[father.index]["VIAB"] as number | undefined | null}
164
+ readDepth={record.data.s[father.index]["DP"] as number | undefined}
165
+ />
166
+ </td>
167
+ )}
168
+ </Show>
169
+ <For each={otherFamilyMembers()}>
170
+ {(sample: Sample) => (
171
+ <>
172
+ <td>
173
+ <GenotypeField
174
+ genotype={record.data.s[sample.index]["GT"] as Genotype}
175
+ refAllele={record.data.r}
176
+ altAlleles={record.data.a}
177
+ isAbbreviate={true}
178
+ allelicBalance={record.data.s[sample.index]["VIAB"] as number | undefined | null}
179
+ readDepth={record.data.s[sample.index]["DP"] as number | undefined}
180
+ />
181
+ </td>
182
+ </>
183
+ )}
78
184
  </For>
79
185
  <InfoCollapsablePane fields={props.nestedFields} record={record} htsFileMeta={props.htsFileMeta} />
80
186
  </tr>
@@ -2,40 +2,49 @@ import { Component, Match, Switch } from "solid-js";
2
2
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
3
3
  import { FilterCategorical } from "./FilterCategorical";
4
4
  import { FilterIntegerVim } from "./FilterIntegerVim";
5
+ import { FilterIntegerGq } from "./FilterIntegerGq";
5
6
  import { FilterIntegerDp } from "./FilterIntegerDp";
6
7
  import { FilterIntegerVid } from "./FilterIntegerVid";
7
- import { QueryClause, Selector } from "@molgenis/vip-report-api/src/Api";
8
+ import { Item, Query, Sample } from "@molgenis/vip-report-api/src/Api";
8
9
  import { FilterClinVar } from "./FilterClinVar";
9
10
  import { isAnyCsqInfo } from "../../utils/csqUtils";
10
-
11
- export type FilterChangeEvent = { query: QueryClause };
12
- export type FilterClearEvent = { selector: Selector };
11
+ import { FilterChangeEvent, FilterClearEvent } from "./Filters";
12
+ import { FilterAllelicBalance } from "./FilterAllelicBalance";
13
13
 
14
14
  export type FilterProps = {
15
15
  field: FieldMetadata;
16
- query?: QueryClause;
16
+ query?: Query;
17
17
  onChange: (event: FilterChangeEvent) => void;
18
18
  onClear: (event: FilterClearEvent) => void;
19
+ sample?: Item<Sample>;
19
20
  };
20
21
 
21
22
  export const Filter: Component<FilterProps> = (props) => {
22
23
  return (
23
- <Switch>
24
- <Match when={props.field.id === "DP"}>
25
- <FilterIntegerDp {...props} />
26
- </Match>
27
- <Match when={props.field.id === "VID"}>
28
- <FilterIntegerVid {...props} />
29
- </Match>
30
- <Match when={props.field.id === "VIM"}>
31
- <FilterIntegerVim {...props} />
32
- </Match>
33
- <Match when={isAnyCsqInfo(props.field, ["clinVar_CLNSIG", "clinVar_CLNSIGINCL"])}>
34
- <FilterClinVar {...props} />
35
- </Match>
36
- <Match when={props.field.type === "CATEGORICAL"}>
37
- <FilterCategorical {...props} />
38
- </Match>
39
- </Switch>
24
+ <>
25
+ <Switch>
26
+ <Match when={props.field.id === "GQ"}>
27
+ <FilterIntegerGq {...props} />
28
+ </Match>
29
+ <Match when={props.field.id === "DP"}>
30
+ <FilterIntegerDp {...props} />
31
+ </Match>
32
+ <Match when={props.field.id === "VID"}>
33
+ <FilterIntegerVid {...props} />
34
+ </Match>
35
+ <Match when={props.field.id === "VIM"}>
36
+ <FilterIntegerVim {...props} />
37
+ </Match>
38
+ <Match when={props.field.id === "VIAB"}>
39
+ <FilterAllelicBalance {...props} />
40
+ </Match>
41
+ <Match when={isAnyCsqInfo(props.field, ["clinVar_CLNSIG", "clinVar_CLNSIGINCL"])}>
42
+ <FilterClinVar {...props} />
43
+ </Match>
44
+ <Match when={props.field.type === "CATEGORICAL"}>
45
+ <FilterCategorical {...props} />
46
+ </Match>
47
+ </Switch>
48
+ </>
40
49
  );
41
50
  };
@@ -0,0 +1,75 @@
1
+ import { Component } from "solid-js";
2
+ import { ComposedQuery, Item, Query, Sample, Selector } from "@molgenis/vip-report-api/src/Api";
3
+ import { Checkbox, CheckboxEvent } from "../Checkbox";
4
+ import { FilterChangeEvent, FilterClearEvent } from "./Filters";
5
+ import { selector, selectorKey } from "../../utils/query";
6
+ import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
7
+
8
+ export function getAllelicBalanceQuery(sampleIndex: number): ComposedQuery {
9
+ const hetQuery: ComposedQuery = {
10
+ operator: "and",
11
+ args: [
12
+ { selector: ["s", sampleIndex, "GT", "t"], operator: "==", args: "het" },
13
+ {
14
+ operator: "and",
15
+ args: [
16
+ { selector: ["s", sampleIndex, "VIAB"], operator: ">", args: 0.2 },
17
+ { selector: ["s", sampleIndex, "VIAB"], operator: "<", args: 0.8 },
18
+ ],
19
+ },
20
+ ],
21
+ };
22
+ const homQuery: ComposedQuery = {
23
+ operator: "and",
24
+ args: [
25
+ {
26
+ operator: "or",
27
+ args: [
28
+ { selector: ["s", sampleIndex, "GT", "t"], operator: "==", args: "hom_a" },
29
+ { selector: ["s", sampleIndex, "GT", "t"], operator: "==", args: "hom_r" },
30
+ ],
31
+ },
32
+ { selector: ["s", sampleIndex, "VIAB"], operator: "<", args: 0.02 },
33
+ ],
34
+ };
35
+ const otherGtQuery: ComposedQuery = {
36
+ operator: "or",
37
+ args: [
38
+ { selector: ["s", sampleIndex, "GT", "t"], operator: "==", args: "miss" },
39
+ { selector: ["s", sampleIndex, "GT", "t"], operator: "==", args: "part" },
40
+ { selector: ["s", sampleIndex, "VIAB"], operator: "==", args: null },
41
+ { selector: ["s", sampleIndex, "VIAB"], operator: "==", args: undefined },
42
+ ],
43
+ };
44
+ const combinedQuery: ComposedQuery = { operator: "or", args: [hetQuery, homQuery, otherGtQuery] };
45
+
46
+ return combinedQuery;
47
+ }
48
+
49
+ export const FilterAllelicBalance: Component<{
50
+ field: FieldMetadata;
51
+ sample?: Item<Sample>;
52
+ query?: Query;
53
+ onChange: (event: FilterChangeEvent) => void;
54
+ onClear: (event: FilterClearEvent) => void;
55
+ }> = (props) => {
56
+ const onFilterChange = (event: CheckboxEvent) => {
57
+ const fieldSelector: Selector = ["s", (props.sample as Item<Sample>).data.index, ...selector(props.field)];
58
+ if (event.checked) {
59
+ props.onChange({
60
+ query: getAllelicBalanceQuery((props.sample?.data as Sample).index),
61
+ key: selectorKey(fieldSelector),
62
+ });
63
+ } else props.onClear({ key: selectorKey(fieldSelector) });
64
+ };
65
+ return (
66
+ <div class="control">
67
+ <Checkbox
68
+ desc="Filter variants with allelic imbalance; For hetrozygote calls: AB < 0.2 or AB > 0.8 and for homozygote calls: AB > 0.02 are consided allelic imbalance"
69
+ label="No allelic imbalance"
70
+ checked={props.query && props.query.args !== undefined}
71
+ onChange={onFilterChange}
72
+ />
73
+ </div>
74
+ );
75
+ };
@@ -1,7 +1,7 @@
1
1
  import { Component, For } from "solid-js";
2
2
  import { Checkbox, CheckboxEvent } from "../Checkbox";
3
3
  import { FilterProps } from "./Filter";
4
- import { selector } from "../../utils/query";
4
+ import { selector, selectorKey } from "../../utils/query";
5
5
 
6
6
  export type CheckboxGroup = {
7
7
  [key: string]: boolean;
@@ -35,6 +35,7 @@ export const FilterCategorical: Component<
35
35
  .map((key) => (key !== nullValue ? key : null));
36
36
  if (values.length > 0) {
37
37
  props.onChange({
38
+ key: selectorKey(selector(props.field)),
38
39
  query: {
39
40
  selector: selector(props.field),
40
41
  operator: props.field.number.count === 1 ? "has_any" : "any_has_any",
@@ -42,7 +43,7 @@ export const FilterCategorical: Component<
42
43
  },
43
44
  });
44
45
  } else {
45
- props.onClear({ selector: selector(props.field) });
46
+ props.onClear({ key: selectorKey(selector(props.field)) });
46
47
  }
47
48
  };
48
49
 
@@ -1,17 +1,32 @@
1
1
  import { Component } from "solid-js";
2
2
  import { FilterProps } from "./Filter";
3
3
  import { Checkbox, CheckboxEvent } from "../Checkbox";
4
- import { selector } from "../../utils/query";
4
+ import { selector, selectorKey } from "../../utils/query";
5
+ import { Item, Sample, Selector } from "@molgenis/vip-report-api/src/Api";
5
6
 
6
7
  export const FilterIntegerDp: Component<FilterProps> = (props) => {
7
8
  const onFilterChange = (event: CheckboxEvent) => {
8
- if (event.checked) props.onChange({ query: { selector: selector(props.field), operator: ">=", args: 20 } });
9
- else props.onClear({ selector: selector(props.field) });
9
+ const fieldSelector: Selector = ["s", (props.sample as Item<Sample>).data.index, ...selector(props.field)];
10
+ if (event.checked)
11
+ props.onChange({
12
+ key: selectorKey(fieldSelector),
13
+ query: {
14
+ selector: fieldSelector,
15
+ operator: ">=",
16
+ args: 10,
17
+ },
18
+ });
19
+ else props.onClear({ key: selectorKey(fieldSelector) });
10
20
  };
11
21
 
12
22
  return (
13
23
  <div class="control">
14
- <Checkbox label="Read depth >= 20" checked={props.query && props.query.args === 20} onChange={onFilterChange} />
24
+ <Checkbox
25
+ desc="Sequencing depth >= 10"
26
+ label="Depth >= 10"
27
+ checked={props.query && props.query.args === 10}
28
+ onChange={onFilterChange}
29
+ />
15
30
  </div>
16
31
  );
17
32
  };
@@ -0,0 +1,32 @@
1
+ import { Component } from "solid-js";
2
+ import { FilterProps } from "./Filter";
3
+ import { Checkbox, CheckboxEvent } from "../Checkbox";
4
+ import { selector, selectorKey } from "../../utils/query";
5
+ import { Item, Sample, Selector } from "@molgenis/vip-report-api/src/Api";
6
+
7
+ export const FilterIntegerGq: Component<FilterProps> = (props) => {
8
+ const onFilterChange = (event: CheckboxEvent) => {
9
+ const fieldSelector: Selector = ["s", (props.sample as Item<Sample>).data.index, ...selector(props.field)];
10
+ if (event.checked)
11
+ props.onChange({
12
+ key: selectorKey(fieldSelector),
13
+ query: {
14
+ selector: fieldSelector,
15
+ operator: ">=",
16
+ args: 20,
17
+ },
18
+ });
19
+ else props.onClear({ key: selectorKey(fieldSelector) });
20
+ };
21
+
22
+ return (
23
+ <div class="control">
24
+ <Checkbox
25
+ desc="Genotype quality >= 20"
26
+ label="GT quality >= 20"
27
+ checked={props.query && props.query.args === 20}
28
+ onChange={onFilterChange}
29
+ />
30
+ </div>
31
+ );
32
+ };
@@ -1,12 +1,22 @@
1
1
  import { Component } from "solid-js";
2
2
  import { FilterProps } from "./Filter";
3
3
  import { Checkbox, CheckboxEvent } from "../Checkbox";
4
- import { selector } from "../../utils/query";
4
+ import { selector, selectorKey } from "../../utils/query";
5
+ import { Item, Sample, Selector } from "@molgenis/vip-report-api/src/Api";
5
6
 
6
7
  export const FilterIntegerVid: Component<FilterProps> = (props) => {
7
8
  const onFilterChange = (event: CheckboxEvent) => {
8
- if (event.checked) props.onChange({ query: { selector: selector(props.field), operator: "==", args: 1 } });
9
- else props.onClear({ selector: selector(props.field) });
9
+ const fieldSelector: Selector = ["s", (props.sample as Item<Sample>).data.index, ...selector(props.field)];
10
+ if (event.checked)
11
+ props.onChange({
12
+ key: selectorKey(fieldSelector),
13
+ query: {
14
+ selector: fieldSelector,
15
+ operator: "==",
16
+ args: 1,
17
+ },
18
+ });
19
+ else props.onClear({ key: selectorKey(fieldSelector) });
10
20
  };
11
21
 
12
22
  return (
@@ -1,12 +1,22 @@
1
1
  import { Component } from "solid-js";
2
2
  import { FilterProps } from "./Filter";
3
3
  import { Checkbox, CheckboxEvent } from "../Checkbox";
4
- import { selector } from "../../utils/query";
4
+ import { selector, selectorKey } from "../../utils/query";
5
+ import { Item, Sample, Selector } from "@molgenis/vip-report-api/src/Api";
5
6
 
6
7
  export const FilterIntegerVim: Component<FilterProps> = (props) => {
7
8
  const onFilterChange = (event: CheckboxEvent) => {
8
- if (event.checked) props.onChange({ query: { selector: selector(props.field), operator: "==", args: 1 } });
9
- else props.onClear({ selector: selector(props.field) });
9
+ const fieldSelector: Selector = ["s", (props.sample as Item<Sample>).data.index, ...selector(props.field)];
10
+ if (event.checked)
11
+ props.onChange({
12
+ key: selectorKey(fieldSelector),
13
+ query: {
14
+ selector: fieldSelector,
15
+ operator: "==",
16
+ args: 1,
17
+ },
18
+ });
19
+ else props.onClear({ key: selectorKey(fieldSelector) });
10
20
  };
11
21
 
12
22
  return (
@@ -1,11 +1,13 @@
1
1
  import { Component } from "solid-js";
2
2
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
3
- import { Item, Sample } from "@molgenis/vip-report-api/src/Api";
3
+ import { Item, Query, Sample } from "@molgenis/vip-report-api/src/Api";
4
4
  import { InfoFilters } from "./InfoFilters";
5
5
  import { SamplesFilters } from "./SamplesFilters";
6
- import { FilterChangeEvent, FilterClearEvent } from "./Filter";
7
6
  import { FilterQueries } from "../../store";
8
7
 
8
+ export type FilterChangeEvent = { key: string; query: Query };
9
+ export type FilterClearEvent = { key: string };
10
+
9
11
  export const Filters: Component<{
10
12
  fields: FieldMetadata[];
11
13
  samplesFields: { sample: Item<Sample>; fields: FieldMetadata[] }[];
@@ -13,17 +15,14 @@ export const Filters: Component<{
13
15
  onChange: (event: FilterChangeEvent) => void;
14
16
  onClear: (event: FilterClearEvent) => void;
15
17
  }> = (props) => {
16
- const onChange = (event: FilterChangeEvent) => props.onChange(event);
17
- const onClear = (event: FilterClearEvent) => props.onClear(event);
18
-
19
18
  return (
20
19
  <>
21
- <InfoFilters fields={props.fields} queries={props.queries} onChange={onChange} onClear={onClear} />
20
+ <InfoFilters fields={props.fields} queries={props.queries} onChange={props.onChange} onClear={props.onClear} />
22
21
  <SamplesFilters
23
22
  samplesFields={props.samplesFields}
24
23
  queries={props.queries}
25
- onChange={onChange}
26
- onClear={onClear}
24
+ onChange={props.onChange}
25
+ onClear={props.onClear}
27
26
  />
28
27
  </>
29
28
  );
@@ -1,19 +1,25 @@
1
1
  import { Component } from "solid-js";
2
- import { Filter, FilterChangeEvent, FilterClearEvent, FilterProps } from "./Filter";
3
- import { SelectorPart } from "@molgenis/vip-report-api/src/Api";
2
+ import { Filter, FilterProps } from "./Filter";
3
+ import { FilterChangeEvent, FilterClearEvent } from "./Filters";
4
+ import { QueryClause, SelectorPart } from "@molgenis/vip-report-api/src/Api";
5
+ import { selectorKey } from "../../utils/query";
4
6
 
5
7
  export const InfoFilter: Component<FilterProps> = (props) => {
6
8
  const label = () => (props.field.label !== undefined ? props.field.label : props.field.id);
7
9
 
8
10
  const onChange = (event: FilterChangeEvent) => {
9
11
  props.onChange({
10
- query: { ...event.query, selector: ["n", ...(event.query.selector as SelectorPart[])] },
12
+ key: selectorKey(["n", event.key]),
13
+ query: {
14
+ ...(event.query as QueryClause),
15
+ selector: ["n", ...((event.query as QueryClause).selector as SelectorPart[])],
16
+ },
11
17
  });
12
18
  };
13
19
 
14
20
  const onClear = (event: FilterClearEvent) => {
15
21
  props.onClear({
16
- selector: ["n", ...(event.selector as SelectorPart[])],
22
+ key: selectorKey(["n", event.key]),
17
23
  });
18
24
  };
19
25
 
@@ -1,10 +1,10 @@
1
1
  import { Component, For } from "solid-js";
2
2
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
3
- import { FilterChangeEvent, FilterClearEvent } from "./Filter";
4
3
  import { InfoFilter } from "./InfoFilter";
5
4
  import { Value } from "@molgenis/vip-report-vcf/src/ValueParser";
6
5
  import { FilterQueries } from "../../store";
7
6
  import { infoFieldKey } from "../../utils/query";
7
+ import { FilterChangeEvent, FilterClearEvent } from "./Filters";
8
8
 
9
9
  export const InfoFilters: Component<{
10
10
  fields: FieldMetadata[];
@@ -1,9 +1,10 @@
1
1
  import { Component, For } from "solid-js";
2
2
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
3
- import { Item, Sample, SelectorPart } from "@molgenis/vip-report-api/src/Api";
4
- import { Filter, FilterChangeEvent, FilterClearEvent } from "./Filter";
3
+ import { Item, Sample } from "@molgenis/vip-report-api/src/Api";
4
+ import { Filter } from "./Filter";
5
5
  import { FilterQueries } from "../../store";
6
6
  import { sampleFieldKey } from "../../utils/query";
7
+ import { FilterChangeEvent, FilterClearEvent } from "./Filters";
7
8
 
8
9
  export const SampleFilters: Component<{
9
10
  sample: Item<Sample>;
@@ -12,17 +13,9 @@ export const SampleFilters: Component<{
12
13
  onChange: (event: FilterChangeEvent) => void;
13
14
  onClear: (event: FilterClearEvent) => void;
14
15
  }> = (props) => {
15
- const onChange = (event: FilterChangeEvent) => {
16
- props.onChange({
17
- query: { ...event.query, selector: ["s", props.sample.data.index, ...(event.query.selector as SelectorPart[])] },
18
- });
19
- };
20
-
21
- const onClear = (event: FilterClearEvent) => {
22
- props.onClear({
23
- selector: ["s", props.sample.data.index, ...(event.selector as SelectorPart[])],
24
- });
25
- };
16
+ if (props.sample == undefined) {
17
+ throw Error("Cannot create Sample filters without a sample.");
18
+ }
26
19
 
27
20
  return (
28
21
  <>
@@ -30,12 +23,16 @@ export const SampleFilters: Component<{
30
23
  <div class="field">
31
24
  <For each={props.fields}>
32
25
  {(field) => (
33
- <Filter
34
- field={field}
35
- query={props.queries ? props.queries[sampleFieldKey(props.sample, field)] : undefined}
36
- onChange={onChange}
37
- onClear={onClear}
38
- />
26
+ <>
27
+ {" "}
28
+ <Filter
29
+ field={field}
30
+ query={props.queries ? props.queries[sampleFieldKey(props.sample, field)] : undefined}
31
+ onChange={props.onChange}
32
+ onClear={props.onClear}
33
+ sample={props.sample}
34
+ />
35
+ </>
39
36
  )}
40
37
  </For>
41
38
  </div>