@molgenis/vip-report-template 6.0.2 → 6.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.
Files changed (37) hide show
  1. package/.husky/pre-commit +0 -3
  2. package/.travis.yml +2 -1
  3. package/index.html +1 -1
  4. package/package.json +23 -23
  5. package/src/App.tsx +14 -65
  6. package/src/assets/sass/main.scss +12 -47
  7. package/src/components/Breadcrumb.tsx +4 -4
  8. package/src/components/DatasetDropdown.tsx +4 -4
  9. package/src/components/InfoCollapsablePane.tsx +4 -4
  10. package/src/components/SampleTable.tsx +2 -2
  11. package/src/components/VariantInfoNestedTable.tsx +3 -3
  12. package/src/components/VariantsSampleTable.tsx +3 -3
  13. package/src/components/VariantsTable.tsx +3 -3
  14. package/src/components/filter/Filter.tsx +0 -4
  15. package/src/components/record/format/GenotypeField.tsx +4 -15
  16. package/src/index.tsx +43 -1
  17. package/src/mocks/GRCh37/sampleTree.json +123 -0
  18. package/src/mocks/GRCh37/static.ts +2 -0
  19. package/src/mocks/GRCh37/vcf/family.vcf.blob +31 -31
  20. package/src/mocks/MockApiClient.ts +6 -0
  21. package/src/store/index.tsx +1 -6
  22. package/src/utils/ApiUtils.ts +4 -0
  23. package/src/utils/decisionTreeUtils.ts +17 -0
  24. package/src/views/Sample.tsx +21 -17
  25. package/src/views/SampleVariant.tsx +36 -21
  26. package/src/views/SampleVariantConsequence.tsx +104 -63
  27. package/src/views/SampleVariants.tsx +7 -7
  28. package/src/views/Variant.tsx +48 -42
  29. package/src/views/VariantConsequence.tsx +9 -8
  30. package/src/views/Variants.tsx +2 -2
  31. package/src/views/data/data.tsx +7 -0
  32. package/src/components/filter/FilterIntegerDp.tsx +0 -47
  33. package/src/views/data/SampleData.tsx +0 -13
  34. package/src/views/data/SampleVariantConsequenceData.tsx +0 -13
  35. package/src/views/data/SampleVariantData.tsx +0 -14
  36. package/src/views/data/VariantConsequenceData.tsx +0 -10
  37. package/src/views/data/VariantData.tsx +0 -13
@@ -18,6 +18,7 @@ import {
18
18
  cram as cramGRCh37,
19
19
  crai as craiGRCh37,
20
20
  decisionTree as decisionTreeGRCh37,
21
+ sampleTree as sampleTreeGRCh37,
21
22
  fastaGz as fastaGzGRCh37,
22
23
  genesGz as genesGzGRCh37,
23
24
  samplesFamily as samplesFamilyGRCh37,
@@ -73,6 +74,10 @@ export class MockApiClient implements Api {
73
74
  return this.apiClient.getDecisionTree();
74
75
  }
75
76
 
77
+ getSampleTree(): Promise<DecisionTree | null> {
78
+ return this.apiClient.getSampleTree();
79
+ }
80
+
76
81
  getHtsFileMetadata(): Promise<HtsFileMetadata> {
77
82
  return this.apiClient.getHtsFileMetadata();
78
83
  }
@@ -144,6 +149,7 @@ export class MockApiClient implements Api {
144
149
  },
145
150
  },
146
151
  decisionTree: decisionTreeGRCh37,
152
+ sampleTree: sampleTreeGRCh37,
147
153
  vcfMeta: vcfMetaGRCh37,
148
154
  };
149
155
 
@@ -1,4 +1,3 @@
1
- import { hashIntegration, Router } from "@solidjs/router";
2
1
  import { Context, createContext, ParentComponent, useContext } from "solid-js";
3
2
  import { createStore } from "solid-js/store";
4
3
  import { Item, Query, Sample, SortOrder } from "@molgenis/vip-report-api/src/Api";
@@ -172,11 +171,7 @@ export const Provider: ParentComponent = (props) => {
172
171
  };
173
172
  const store: AppStore = [state, actions];
174
173
 
175
- return (
176
- <Router source={hashIntegration()}>
177
- <StoreContext.Provider value={store}>{props.children}</StoreContext.Provider>
178
- </Router>
179
- );
174
+ return <StoreContext.Provider value={store}>{props.children}</StoreContext.Provider>;
180
175
  };
181
176
 
182
177
  export function useStore() {
@@ -161,6 +161,10 @@ export async function fetchDecisionTree() {
161
161
  return await api.getDecisionTree();
162
162
  }
163
163
 
164
+ export async function fetchSampleTree() {
165
+ return await api.getSampleTree();
166
+ }
167
+
164
168
  export async function fetchSampleById(id: string) {
165
169
  return await api.getSampleById(Number(id));
166
170
  }
@@ -12,3 +12,20 @@ export function getDecisionTreePath(recordsMetadata: Metadata, variant: Item<Rec
12
12
  recordsMetadata.info.CSQ.nested.items.findIndex((csq) => csq.id === "VIPP")
13
13
  ] as DecisionTreePath;
14
14
  }
15
+
16
+ export function getSampleTreePath(
17
+ recordsMetadata: Metadata,
18
+ sampleIndex: number,
19
+ variant: Item<Record>,
20
+ csqId: number,
21
+ ): DecisionTreePath {
22
+ const vipp_s = variant.data.s[sampleIndex].VIPP_S as ValueArray;
23
+ let sampleTreePath: DecisionTreePath = [];
24
+ if (vipp_s !== undefined) {
25
+ const sampleTreePathString = vipp_s[csqId] as string | null;
26
+ if (sampleTreePathString !== null) {
27
+ sampleTreePath = sampleTreePathString.split("&") as DecisionTreePath;
28
+ }
29
+ }
30
+ return sampleTreePath;
31
+ }
@@ -1,26 +1,30 @@
1
1
  import { Component, For, Show } from "solid-js";
2
- import { Link, useRouteData } from "@solidjs/router";
2
+ import { createAsync, RouteSectionProps, A } from "@solidjs/router";
3
3
  import { Loader } from "../components/Loader";
4
4
  import { Breadcrumb } from "../components/Breadcrumb";
5
- import { SampleRouteData } from "./data/SampleData";
5
+ import { getSample } from "./data/data";
6
6
 
7
- export const Sample: Component = () => {
8
- const { sample } = useRouteData<SampleRouteData>();
7
+ export const Sample: Component<RouteSectionProps> = (props) => {
8
+ const sample = createAsync(() => getSample(Number(props.params.sampleId)));
9
9
 
10
10
  return (
11
- <Show when={!sample.loading} fallback={<Loader />}>
12
- <Breadcrumb items={[{ href: "/samples", text: "Samples" }, { text: sample().data.person.individualId }]} />
13
- <p class="has-text-weight-semibold">Sample</p>
14
- <div class="columns">
15
- <div class="column is-1">
16
- <For each={Object.keys(sample().data.person)}>{(key) => <p>{key}</p>}</For>
17
- </div>
18
- <div class="column is-1">
19
- <For each={Object.values(sample().data.person)}>{(value) => <p>{value}</p>}</For>
20
- </div>
21
- </div>
22
- <br />
23
- <Link href={`/samples/${sample().id}/variants`}>Variants</Link>
11
+ <Show when={sample()} fallback={<Loader />}>
12
+ {(sample) => (
13
+ <>
14
+ <Breadcrumb items={[{ href: "/samples", text: "Samples" }, { text: sample().data.person.individualId }]} />
15
+ <p class="has-text-weight-semibold">Sample</p>
16
+ <div class="columns">
17
+ <div class="column is-1">
18
+ <For each={Object.keys(sample().data.person)}>{(key) => <p>{key}</p>}</For>
19
+ </div>
20
+ <div class="column is-1">
21
+ <For each={Object.values(sample().data.person)}>{(value) => <p>{value}</p>}</For>
22
+ </div>
23
+ </div>
24
+ <br />
25
+ <A href={`/samples/${sample().id}/variants`}>Variants</A>
26
+ </>
27
+ )}
24
28
  </Show>
25
29
  );
26
30
  };
@@ -1,5 +1,5 @@
1
1
  import { Component, createResource, For, Show } from "solid-js";
2
- import { useRouteData } from "@solidjs/router";
2
+ import { createAsync, RouteSectionProps } from "@solidjs/router";
3
3
  import { Loader } from "../components/Loader";
4
4
  import { GenomeBrowser } from "../components/GenomeBrowser";
5
5
  import { fetchPedigreeSamples, fetchRecordsMeta, getRecordLabel } from "../utils/ApiUtils";
@@ -11,36 +11,51 @@ import { getNestedInfoFieldsWithValues } from "../utils/field";
11
11
  import { VariantSampleTable } from "../components/VariantSampleTable";
12
12
  import { Breadcrumb } from "../components/Breadcrumb";
13
13
  import { getRecordSamples } from "../utils/viewUtils";
14
- import { SampleVariantRouteData } from "./data/SampleVariantData";
15
14
  import { getSampleLabel } from "../utils/sample";
16
15
  import { Item, Sample } from "@molgenis/vip-report-api/src/Api";
17
16
  import { Metadata, Record } from "@molgenis/vip-report-vcf/src/Vcf";
18
17
  import { Abbr } from "../components/Abbr";
18
+ import { getSample, getVariant } from "./data/data";
19
19
 
20
- export const SampleVariantView: Component = () => {
21
- const { sample, variant } = useRouteData<SampleVariantRouteData>();
20
+ export const SampleVariantView: Component<RouteSectionProps> = (props) => {
21
+ const sample = createAsync(() => getSample(Number(props.params.sampleId)));
22
+ const variant = createAsync(() => getVariant(Number(props.params.variantId)));
22
23
 
23
24
  const [pedigreeSamples] = createResource(sample, fetchPedigreeSamples);
24
25
  const [recordsMeta] = createResource(fetchRecordsMeta);
25
26
 
26
27
  return (
27
- <Show when={sample() && variant()} fallback={<Loader />}>
28
- <Breadcrumb
29
- items={[
30
- { href: "/samples", text: "Samples" },
31
- { href: `/samples/${sample()!.id}`, text: getSampleLabel(sample()!.data) },
32
- { href: `/samples/${sample()!.id}/variants`, text: "Variants" },
33
- { text: getRecordLabel(variant()!) },
34
- ]}
35
- />
36
- <Show when={pedigreeSamples() && recordsMeta()} fallback={<Loader />}>
37
- <SampleVariant
38
- sample={sample()!}
39
- pedigreeSamples={pedigreeSamples()!.items}
40
- recordsMeta={recordsMeta()!}
41
- record={variant()!}
42
- />
43
- </Show>
28
+ <Show when={sample()} fallback={<Loader />}>
29
+ {(sample) => (
30
+ <Show when={variant()} fallback={<Loader />}>
31
+ {(variant) => (
32
+ <>
33
+ <Breadcrumb
34
+ items={[
35
+ { href: "/samples", text: "Samples" },
36
+ { href: `/samples/${sample().id}`, text: getSampleLabel(sample().data) },
37
+ { href: `/samples/${sample().id}/variants`, text: "Variants" },
38
+ { text: getRecordLabel(variant()) },
39
+ ]}
40
+ />
41
+ <Show when={pedigreeSamples()} fallback={<Loader />}>
42
+ {(pedigreeSamples) => (
43
+ <Show when={recordsMeta()} fallback={<Loader />}>
44
+ {(recordsMeta) => (
45
+ <SampleVariant
46
+ sample={sample()}
47
+ pedigreeSamples={pedigreeSamples().items}
48
+ recordsMeta={recordsMeta()}
49
+ record={variant()}
50
+ />
51
+ )}
52
+ </Show>
53
+ )}
54
+ </Show>
55
+ </>
56
+ )}
57
+ </Show>
58
+ )}
44
59
  </Show>
45
60
  );
46
61
  };
@@ -1,9 +1,9 @@
1
1
  import { Component, createResource, Show } from "solid-js";
2
- import { useRouteData } from "@solidjs/router";
2
+ import { createAsync, RouteSectionProps } from "@solidjs/router";
3
3
  import { Loader } from "../components/Loader";
4
4
  import {
5
+ fetchSampleTree,
5
6
  fetchDecisionTree,
6
- fetchHtsFileMetadata,
7
7
  fetchPedigreeSamples,
8
8
  fetchRecordsMeta,
9
9
  getRecordLabel,
@@ -15,42 +15,61 @@ import { Breadcrumb } from "../components/Breadcrumb";
15
15
  import { ConsequenceTable } from "../components/ConsequenceTable";
16
16
  import { getRecordSamples, getSpecificConsequence } from "../utils/viewUtils";
17
17
  import { DecisionTreePath } from "../components/tree/DecisionTreePath";
18
- import { getDecisionTreePath } from "../utils/decisionTreeUtils";
19
- import { SampleVariantConsequenceRouteData } from "./data/SampleVariantConsequenceData";
18
+ import { getDecisionTreePath, getSampleTreePath } from "../utils/decisionTreeUtils";
20
19
  import { getSampleLabel } from "../utils/sample";
21
20
  import { DecisionTree, Item, Sample } from "@molgenis/vip-report-api/src/Api";
22
21
  import { Metadata, Record } from "@molgenis/vip-report-vcf/src/Vcf";
23
22
  import { ValueArray } from "@molgenis/vip-report-vcf/src/ValueParser";
23
+ import { getSample, getVariant } from "./data/data";
24
24
 
25
- export const SampleVariantConsequenceView: Component = () => {
26
- const { sample, variant, consequenceId } = useRouteData<SampleVariantConsequenceRouteData>();
27
-
25
+ export const SampleVariantConsequenceView: Component<RouteSectionProps> = (props) => {
26
+ const sample = createAsync(() => getSample(Number(props.params.sampleId)));
27
+ const variant = createAsync(() => getVariant(Number(props.params.variantId)));
28
+ const consequenceId = () => Number(props.params.consequenceId);
28
29
  const [pedigreeSamples] = createResource(sample, fetchPedigreeSamples);
29
30
  const [recordsMeta] = createResource(fetchRecordsMeta);
30
31
  const [decisionTree] = createResource(fetchDecisionTree, { initialValue: null });
31
- const [htsFileMeta] = createResource(fetchHtsFileMetadata);
32
+ const [sampleTree] = createResource(fetchSampleTree, { initialValue: null });
32
33
 
33
34
  return (
34
- <Show when={sample() && variant()} fallback={<Loader />}>
35
- <Breadcrumb
36
- items={[
37
- { href: "/samples", text: "Samples" },
38
- { href: `/samples/${sample()!.id}`, text: getSampleLabel(sample()!.data) },
39
- { href: `/samples/${sample()!.id}/variants`, text: "Variants" },
40
- { href: `/samples/${sample()!.id}/variants/${variant()!.id}`, text: getRecordLabel(variant()!) },
41
- { text: `Consequence #${consequenceId}` },
42
- ]}
43
- />
44
- <Show when={pedigreeSamples() && recordsMeta() && htsFileMeta()} fallback={<Loader />}>
45
- <SampleVariantConsequence
46
- sample={sample()!}
47
- pedigreeSamples={pedigreeSamples()!.items}
48
- recordsMeta={recordsMeta()!}
49
- variant={variant()!}
50
- consequenceId={consequenceId}
51
- decisionTree={decisionTree()}
52
- />
53
- </Show>
35
+ <Show when={sample()} fallback={<Loader />}>
36
+ {(sample) => (
37
+ <Show when={variant()} fallback={<Loader />}>
38
+ {(variant) => (
39
+ <>
40
+ <Breadcrumb
41
+ items={[
42
+ { href: "/samples", text: "Samples" },
43
+ { href: `/samples/${sample().id}`, text: getSampleLabel(sample().data) },
44
+ { href: `/samples/${sample().id}/variants`, text: "Variants" },
45
+ {
46
+ href: `/samples/${sample().id}/variants/${variant().id}`,
47
+ text: getRecordLabel(variant()),
48
+ },
49
+ { text: `Consequence #${consequenceId()}` },
50
+ ]}
51
+ />
52
+ <Show when={pedigreeSamples()} fallback={<Loader />}>
53
+ {(pedigreeSamples) => (
54
+ <Show when={recordsMeta()} fallback={<Loader />}>
55
+ {(recordsMeta) => (
56
+ <SampleVariantConsequence
57
+ sample={sample()}
58
+ pedigreeSamples={pedigreeSamples().items}
59
+ recordsMeta={recordsMeta()}
60
+ variant={variant()}
61
+ consequenceId={consequenceId()}
62
+ decisionTree={decisionTree()}
63
+ sampleTree={sampleTree()}
64
+ />
65
+ )}
66
+ </Show>
67
+ )}
68
+ </Show>
69
+ </>
70
+ )}
71
+ </Show>
72
+ )}
54
73
  </Show>
55
74
  );
56
75
  };
@@ -62,52 +81,74 @@ export const SampleVariantConsequence: Component<{
62
81
  variant: Item<Record>;
63
82
  consequenceId: number;
64
83
  decisionTree: DecisionTree | null;
84
+ sampleTree: DecisionTree | null;
65
85
  }> = (props) => {
66
86
  const hasDecisionTreePathMeta = () =>
67
87
  (props.recordsMeta.info.CSQ?.nested?.items || []).findIndex((csq) => csq.id === "VIPP") !== -1;
88
+ const hasSampleTreePathMeta = () => props.recordsMeta.format.VIPP_S != null;
68
89
 
69
90
  return (
70
91
  <>
71
92
  <div class="columns">
72
- <div class="column is-6">
73
- <h1 class="title is-5">Consequence</h1>
74
- <ConsequenceTable
75
- csqMetadata={props.recordsMeta.info.CSQ.nested !== undefined ? props.recordsMeta.info.CSQ.nested.items : []}
76
- csqValues={getSpecificConsequence(props.variant.data.n.CSQ as ValueArray, props.consequenceId)}
77
- record={props.variant}
78
- />
79
- </div>
80
- {props.decisionTree !== null && hasDecisionTreePathMeta() && (
81
- <div class="column">
82
- <h1 class="title is-5">Classification tree path</h1>
83
- <DecisionTreePath
84
- decisionTree={props.decisionTree}
85
- path={getDecisionTreePath(props.recordsMeta, props.variant, props.consequenceId)}
93
+ <div class="column is-4">
94
+ <div>
95
+ <h1 class="title is-5">Info</h1>
96
+ <VariantInfoTable infoFields={props.recordsMeta.info} record={props.variant} />
97
+ </div>
98
+ <div class="mt-3">
99
+ <h1 class="title is-5">Consequence</h1>
100
+ <ConsequenceTable
101
+ csqMetadata={
102
+ props.recordsMeta.info.CSQ.nested !== undefined ? props.recordsMeta.info.CSQ.nested.items : []
103
+ }
104
+ csqValues={getSpecificConsequence(props.variant.data.n.CSQ as ValueArray, props.consequenceId)}
105
+ record={props.variant}
86
106
  />
87
107
  </div>
88
- )}
89
- </div>
90
- <div class="columns">
91
- <div class="column is-3">
92
- <h1 class="title is-5">Record</h1>
93
- <VariantTable variant={props.variant.data} />
94
- </div>
95
- <div class="column is-3">
96
- <h1 class="title is-5">Info</h1>
97
- <VariantInfoTable infoFields={props.recordsMeta.info} record={props.variant} />
108
+ <div class="mt-3">
109
+ <h1 class="title is-5">Record</h1>
110
+ <VariantTable variant={props.variant.data} />
111
+ </div>
98
112
  </div>
99
- <div class="column">
100
- <h1 class="title is-5">Samples</h1>
101
- <VariantSampleTable
102
- formatFields={props.recordsMeta.format}
103
- samples={[props.sample.data, ...props.pedigreeSamples.map((item) => item.data)]}
104
- sampleValues={getRecordSamples(
105
- props.variant.data,
106
- props.sample.data,
107
- props.pedigreeSamples.map((item) => item.data),
113
+ <div class="column is-8">
114
+ <div>
115
+ <h1 class="title is-5">Samples</h1>
116
+ <VariantSampleTable
117
+ formatFields={props.recordsMeta.format}
118
+ samples={[props.sample.data, ...props.pedigreeSamples.map((item) => item.data)]}
119
+ sampleValues={getRecordSamples(
120
+ props.variant.data,
121
+ props.sample.data,
122
+ props.pedigreeSamples.map((item) => item.data),
123
+ )}
124
+ record={props.variant}
125
+ />
126
+ </div>
127
+ <div class="columns mt-3">
128
+ {props.decisionTree !== null && hasDecisionTreePathMeta() && (
129
+ <div class="column is-6">
130
+ <h1 class="title is-5">Variant classification tree path</h1>
131
+ <DecisionTreePath
132
+ decisionTree={props.decisionTree}
133
+ path={getDecisionTreePath(props.recordsMeta, props.variant, props.consequenceId)}
134
+ />
135
+ </div>
108
136
  )}
109
- record={props.variant}
110
- />
137
+ {props.sampleTree !== null && hasSampleTreePathMeta() && (
138
+ <div class="column is-6">
139
+ <h1 class="title is-5">Sample classification tree path</h1>
140
+ <DecisionTreePath
141
+ decisionTree={props.sampleTree}
142
+ path={getSampleTreePath(
143
+ props.recordsMeta,
144
+ props.sample.data.index,
145
+ props.variant,
146
+ props.consequenceId,
147
+ )}
148
+ />
149
+ </div>
150
+ )}
151
+ </div>
111
152
  </div>
112
153
  </div>
113
154
  </>
@@ -1,5 +1,4 @@
1
1
  import { Component, createMemo, createResource, createSignal, onMount, Show } from "solid-js";
2
- import { useRouteData } from "@solidjs/router";
3
2
  import {
4
3
  HtsFileMetadata,
5
4
  Item,
@@ -35,7 +34,6 @@ import { Breadcrumb } from "../components/Breadcrumb";
35
34
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
36
35
  import { FilterChangeEvent, FilterClearEvent, Filters } from "../components/filter/Filters";
37
36
  import { DIRECTION_ASCENDING, DIRECTION_DESCENDING } from "../utils/sortUtils";
38
- import { SampleRouteData } from "./data/SampleData";
39
37
  import { useStore } from "../store";
40
38
  import { Metadata } from "@molgenis/vip-report-vcf/src/Vcf";
41
39
  import {
@@ -49,9 +47,11 @@ import {
49
47
  import { arrayEquals } from "../utils/utils";
50
48
  import { getAllelicBalanceQuery } from "../components/filter/FilterAllelicBalance";
51
49
  import { RecordsPerPage, RecordsPerPageEvent } from "../components/RecordsPerPage";
50
+ import { createAsync, RouteSectionProps } from "@solidjs/router";
51
+ import { getSample } from "./data/data";
52
52
 
53
- export const SampleVariantsView: Component = () => {
54
- const { sample } = useRouteData<SampleRouteData>();
53
+ export const SampleVariantsView: Component<RouteSectionProps> = (props) => {
54
+ const sample = createAsync(() => getSample(Number(props.params.sampleId)));
55
55
 
56
56
  const [pedigreeSamples] = createResource(sample, fetchPedigreeSamples);
57
57
  const [samplePhenotypes] = createResource(sample, fetchPhenotypicFeatures);
@@ -375,8 +375,8 @@ export const SampleVariants: Component<{
375
375
  };
376
376
 
377
377
  return (
378
- <div class="columns is-variable is-1">
379
- <div class="column is-1-fullhd is-2">
378
+ <div class="variants columns is-variable is-1">
379
+ <div class="scrolling-div column is-1-fullhd is-2">
380
380
  <SearchBox value={searchQuery()} onInput={onSearchChange} />
381
381
  <Filters
382
382
  fields={filterInfoFields()}
@@ -386,7 +386,7 @@ export const SampleVariants: Component<{
386
386
  onClear={onFilterClear}
387
387
  />
388
388
  </div>
389
- <div class="column">
389
+ <div class="scrolling-div column">
390
390
  <div class="columns is-gapless">
391
391
  <div class="column">
392
392
  <p class="title is-3">{title()}</p>
@@ -1,5 +1,5 @@
1
1
  import { Component, createResource, For, Show } from "solid-js";
2
- import { useRouteData } from "@solidjs/router";
2
+ import { createAsync, RouteSectionProps } from "@solidjs/router";
3
3
  import { GenomeBrowser } from "../components/GenomeBrowser";
4
4
  import { Loader } from "../components/Loader";
5
5
  import { Value } from "@molgenis/vip-report-vcf/src/ValueParser";
@@ -9,54 +9,60 @@ import { VariantInfoNestedTable } from "../components/VariantInfoNestedTable";
9
9
  import { getNestedInfoFieldsWithValues } from "../utils/field";
10
10
  import { Breadcrumb } from "../components/Breadcrumb";
11
11
  import { EMPTY_RECORDS_METADATA, fetchRecordsMeta, getRecordLabel } from "../utils/ApiUtils";
12
- import { VariantRouteData } from "./data/VariantData";
12
+ import { getVariant } from "./data/data";
13
+ import { Item } from "@molgenis/vip-report-api/src/Api";
14
+ import { Record } from "@molgenis/vip-report-vcf/src/Vcf";
13
15
 
14
- export const Variant: Component = () => {
15
- const { variant } = useRouteData<VariantRouteData>();
16
+ export const Variant: Component<RouteSectionProps<Promise<Item<Record>>>> = (props) => {
17
+ const variant = createAsync(() => getVariant(Number(props.params.variantId)));
16
18
 
17
19
  const [recordsMetadata] = createResource(fetchRecordsMeta, { initialValue: EMPTY_RECORDS_METADATA });
18
20
 
19
21
  return (
20
22
  <>
21
- <Show when={!variant.loading} fallback={<Loader />}>
22
- <Breadcrumb items={[{ href: "/variants", text: "Variants" }, { text: getRecordLabel(variant()) }]} />
23
- <GenomeBrowser contig={variant().data.c} position={variant().data.p} samples={[]} />
24
- <div class="columns">
25
- <div class="column is-3">
26
- <h1 class="title is-5">Record</h1>
27
- <VariantTable variant={variant().data} />
28
- </div>
29
- <Show
30
- when={
31
- Object.values(recordsMetadata().info).filter(
32
- (info) => !info.nested && variant().data.n[info.id] !== undefined,
33
- ).length > 0
34
- }
35
- >
36
- <div class="column is-3">
37
- <h1 class="title is-5">Info</h1>
38
- <VariantInfoTable infoFields={recordsMetadata().info} record={variant()} />
23
+ <Show when={variant()} fallback={<Loader />}>
24
+ {(variant) => (
25
+ <>
26
+ <Breadcrumb items={[{ href: "/variants", text: "Variants" }, { text: getRecordLabel(variant()) }]} />
27
+ <GenomeBrowser contig={variant().data.c} position={variant().data.p} samples={[]} />
28
+ <div class="columns">
29
+ <div class="column is-3">
30
+ <h1 class="title is-5">Record</h1>
31
+ <VariantTable variant={variant().data} />
32
+ </div>
33
+ <Show
34
+ when={
35
+ Object.values(recordsMetadata().info).filter(
36
+ (info) => !info.nested && variant().data.n[info.id] !== undefined,
37
+ ).length > 0
38
+ }
39
+ >
40
+ <div class="column is-3">
41
+ <h1 class="title is-5">Info</h1>
42
+ <VariantInfoTable infoFields={recordsMetadata().info} record={variant()} />
43
+ </div>
44
+ </Show>
39
45
  </div>
40
- </Show>
41
- </div>
42
- <div class="columns">
43
- <div class="column" style={{ "max-width": "100%" }}>
44
- <For each={getNestedInfoFieldsWithValues(recordsMetadata().info, variant().data.n)}>
45
- {(infoField) => (
46
- <>
47
- <h1 class="title is-5">{infoField.id}</h1>
48
- <p class="mb-4">{infoField.description}</p>
49
- <VariantInfoNestedTable
50
- infoValue={variant().data.n[infoField.id] as unknown as Value[][]}
51
- infoField={infoField}
52
- record={variant()}
53
- sample={null}
54
- />
55
- </>
56
- )}
57
- </For>
58
- </div>
59
- </div>
46
+ <div class="columns">
47
+ <div class="column" style={{ "max-width": "100%" }}>
48
+ <For each={getNestedInfoFieldsWithValues(recordsMetadata().info, variant().data.n)}>
49
+ {(infoField) => (
50
+ <>
51
+ <h1 class="title is-5">{infoField.id}</h1>
52
+ <p class="mb-4">{infoField.description}</p>
53
+ <VariantInfoNestedTable
54
+ infoValue={variant().data.n[infoField.id] as unknown as Value[][]}
55
+ infoField={infoField}
56
+ record={variant()}
57
+ sample={null}
58
+ />
59
+ </>
60
+ )}
61
+ </For>
62
+ </div>
63
+ </div>
64
+ </>
65
+ )}
60
66
  </Show>
61
67
  </>
62
68
  );
@@ -1,5 +1,5 @@
1
1
  import { Component, createResource, Show } from "solid-js";
2
- import { useRouteData } from "@solidjs/router";
2
+ import { createAsync, RouteSectionProps } from "@solidjs/router";
3
3
  import { Loader } from "../components/Loader";
4
4
  import { DecisionTree } from "@molgenis/vip-report-api/src/Api";
5
5
  import { VariantTable } from "../components/VariantTable";
@@ -18,10 +18,11 @@ import {
18
18
  } from "../utils/ApiUtils";
19
19
  import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
20
20
  import { ValueArray } from "@molgenis/vip-report-vcf/src/ValueParser";
21
- import { VariantConsequenceRouteData } from "./data/VariantConsequenceData";
21
+ import { getVariant } from "./data/data";
22
22
 
23
- export const VariantConsequence: Component = () => {
24
- const { variant, consequenceId } = useRouteData<VariantConsequenceRouteData>();
23
+ export const VariantConsequence: Component<RouteSectionProps> = (props) => {
24
+ const variant = createAsync(() => getVariant(Number(props.params.variantId)));
25
+ const consequenceId = () => Number(props.params.consequenceId);
25
26
 
26
27
  const [recordsMetadata] = createResource(fetchRecordsMeta, { initialValue: EMPTY_RECORDS_METADATA });
27
28
  const [decisionTree] = createResource(fetchDecisionTree, { initialValue: EMPTY_DECISION_TREE });
@@ -30,14 +31,14 @@ export const VariantConsequence: Component = () => {
30
31
 
31
32
  const hasDecisionTreePathMeta = () => csqFields().findIndex((csq) => csq.id === "VIPP") !== -1;
32
33
  return (
33
- <Show when={!variant.loading && variant()} fallback={<Loader />} keyed>
34
+ <Show when={variant()} fallback={<Loader />} keyed>
34
35
  {(variant) => (
35
36
  <>
36
37
  <Breadcrumb
37
38
  items={[
38
39
  { href: "/variants", text: "Variants" },
39
40
  { href: `/variants/${variant.id}`, text: getRecordLabel(variant) },
40
- { text: `Consequence #${consequenceId}` },
41
+ { text: `Consequence #${consequenceId()}` },
41
42
  ]}
42
43
  />
43
44
  <div class="columns">
@@ -45,7 +46,7 @@ export const VariantConsequence: Component = () => {
45
46
  <h1 class="title is-5">Consequence</h1>
46
47
  <ConsequenceTable
47
48
  csqMetadata={csqFields()}
48
- csqValues={getSpecificConsequence(variant.data.n.CSQ as ValueArray, consequenceId)}
49
+ csqValues={getSpecificConsequence(variant.data.n.CSQ as ValueArray, consequenceId())}
49
50
  record={variant}
50
51
  />
51
52
  </div>
@@ -56,7 +57,7 @@ export const VariantConsequence: Component = () => {
56
57
  <h1 class="title is-5">Classification tree path</h1>
57
58
  <DecisionTreePath
58
59
  decisionTree={decisionTree}
59
- path={getDecisionTreePath(recordsMetadata(), variant, consequenceId)}
60
+ path={getDecisionTreePath(recordsMetadata(), variant, consequenceId())}
60
61
  />
61
62
  </div>
62
63
  )}