@molgenis/vip-report-template 6.0.2 → 6.1.1
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/.husky/pre-commit +0 -3
- package/.travis.yml +5 -2
- package/index.html +1 -1
- package/package.json +23 -23
- package/src/App.tsx +14 -65
- package/src/assets/sass/main.scss +12 -47
- package/src/components/Breadcrumb.tsx +3 -4
- package/src/components/InfoCollapsablePane.tsx +4 -4
- package/src/components/SampleTable.tsx +2 -2
- package/src/components/VariantInfoNestedTable.tsx +3 -3
- package/src/components/VariantsSampleTable.tsx +2 -3
- package/src/components/VariantsTable.tsx +2 -3
- package/src/components/filter/Filter.tsx +0 -4
- package/src/components/record/format/GenotypeField.tsx +4 -15
- package/src/index.tsx +43 -1
- package/src/store/index.tsx +1 -6
- package/src/views/Sample.tsx +21 -17
- package/src/views/SampleVariant.tsx +36 -21
- package/src/views/SampleVariantConsequence.tsx +44 -33
- package/src/views/SampleVariants.tsx +7 -7
- package/src/views/Variant.tsx +48 -42
- package/src/views/VariantConsequence.tsx +9 -8
- package/src/views/Variants.tsx +2 -2
- package/src/views/data/data.tsx +7 -0
- package/src/components/filter/FilterIntegerDp.tsx +0 -47
- package/src/views/data/SampleData.tsx +0 -13
- package/src/views/data/SampleVariantConsequenceData.tsx +0 -13
- package/src/views/data/SampleVariantData.tsx +0 -14
- package/src/views/data/VariantConsequenceData.tsx +0 -10
- package/src/views/data/VariantData.tsx +0 -13
package/.husky/pre-commit
CHANGED
package/.travis.yml
CHANGED
|
@@ -27,11 +27,14 @@ deploy:
|
|
|
27
27
|
secure: TxQUU8xNTVTqhQ6pYTR+ic7Crv6rPZ7UbRo8HJJOGlFA30Vb/O36kh3Vgwx3fM5oinC1I38pzmHjJ4WVz2qiUZcgNzDHMorQhErbfSWLO8G7XTsVkMkyozPPtgdCCT2Z7FfdTKmY5an+V4ZJlreM83+vlJmUzMoGahZElESBk94QkTnPAqk46whXAf/zToEw7OJsxd2N3uPyPB8+rgg5VMApRBsCegt3KyetiMBIYWX+kJLxXEGK7OnJmxz1SGrYHR87YEDog7awBIhrXNcBWc4Lj55oWEqp3JQlpLnVDhEUCSO8cmQkyIMTYZ3eIKoyrDk9vfAYYbDsRvagFXKTZGvv0ZQv8s7a1lWAadTyvgbmo3cvX/KHfam5pGf2DFEXWIHZgvoIzq8GY6V4sjOEWRG2sAn+jKiNT5jPgG8sG0faP2JVr55WoN4jRthk5ABckyS8PByWrwcLILTeBPuX7DpiKtzUzzRw/qHAGo59+bFyZiKIc5I+S59fnttJ6Vz4jpjsavOzNsgIGUsTs3y1kosNLYoJVcI3RjpgHQuOfzawKb2l22B5wbJ1/1llhrSqYCtEjAhUuruB3bhy+/WiN4ulKp29Ct7/IEN3ctBXdMBm2xCPlsPSTBeXzwJNeWykTnpFx9qykjtSj3CwS8ZDnY3M+/dLhywrI46EGa03YRw=
|
|
28
28
|
on:
|
|
29
29
|
tags: true
|
|
30
|
-
edge:
|
|
30
|
+
edge:
|
|
31
|
+
branch: v2.0.3-beta.4 # workaround for https://travis-ci.community/t/builds-suddenly-fail-with-error-installing-dpl/14270/3
|
|
31
32
|
- provider: releases
|
|
32
33
|
token:
|
|
33
34
|
secure: rQ19Q5xN6T+dJp4nDT+B4QREJNCc9HpOdipE7jcAP/PVD49kd3AI4joZD9nBn53a091rl7VHviqzyRvHyvBI00VWGhQOmbUqd45c5h4Vn0qUZno2Wl2M7iuUyllvovQHS0C34nLDSBkKhJv0ESit/xiyyVy8JxwO1mgFcLgsY0cKiupwbhepUw5V2S458pNLW9e4RxT7RIaQWUagYp+PJYRKAYn5AAxih65mv2+wSGQPzcOKJDRSTlDtLaCrfZCNJm/7f3iSAOm1CCA1HLxNO2ACFL4bhnghWPS7O6VyTv1POexgwbH0OQxHmO/pdm3geLrTWX7PaHaZNUB1CHoNXC5FE/J9sUSrjClfGL9qFo5WEkBAgH3a5lLwUoCWZecUJPnyeIEFieg5OSjnXFrTECWo5Ut4g5RtzOWQtTLEwOXQgDBtE3NLkH/DRayO9vliEs9/6CnZ8AndH17cj/GmB//2DTjOMr3yCQVuI5ZeANBAUoXAg/C6kQDTdP8oyLay7UBJnX1aEWWLf3Gwo0UBFE83YIuzqVzIvU8HYgFiPgjxFwKBmebS4qu1n9ils2X0nWaY9KZY4lIjzkxsgsZ2pqt1Z6a5AQsEqXv06Tjy6tB7/I9TG7vl4eTBBJBPsRKMNnTfkE6Zr3oHC+ihWIMolAqyaTriOh23Gs/xzEuK+T8=
|
|
34
35
|
file: dist/vip-report-template.html
|
|
35
36
|
on:
|
|
36
37
|
tags: true
|
|
37
|
-
edge:
|
|
38
|
+
edge:
|
|
39
|
+
branch: v2.0.3-beta.4 # workaround for https://travis-ci.community/t/builds-suddenly-fail-with-error-installing-dpl/14270/3
|
|
40
|
+
|
package/index.html
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molgenis/vip-report-template",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "Report Template for Variant Call Format (VCF) Report Generator",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build",
|
|
@@ -9,39 +9,39 @@
|
|
|
9
9
|
"dev": "vite",
|
|
10
10
|
"format": "prettier --write src/**/*.{tsx,ts}",
|
|
11
11
|
"lint": "eslint src/**/*.{tsx,ts}",
|
|
12
|
-
"prepare": "husky
|
|
12
|
+
"prepare": "husky",
|
|
13
13
|
"test": "vitest run",
|
|
14
14
|
"test:watch": "vitest"
|
|
15
15
|
},
|
|
16
16
|
"license": "LGPL-3.0",
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@molgenis/vite-plugin-inline": "^1.0.
|
|
19
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
20
|
-
"@typescript-eslint/parser": "^
|
|
21
|
-
"@vitest/coverage-v8": "^1.
|
|
22
|
-
"bulma": "^0.
|
|
23
|
-
"eslint": "^8.
|
|
18
|
+
"@molgenis/vite-plugin-inline": "^1.0.24",
|
|
19
|
+
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
|
20
|
+
"@typescript-eslint/parser": "^7.12.0",
|
|
21
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
22
|
+
"bulma": "^1.0.1",
|
|
23
|
+
"eslint": "^8.57.0",
|
|
24
24
|
"eslint-config-prettier": "^9.1.0",
|
|
25
25
|
"eslint-plugin-prettier": "^5.1.3",
|
|
26
|
-
"eslint-plugin-solid": "^0.
|
|
27
|
-
"husky": "^9.0.
|
|
28
|
-
"jsdom": "^24.
|
|
29
|
-
"prettier": "^3.
|
|
30
|
-
"sass": "^1.
|
|
31
|
-
"typescript": "^5.
|
|
32
|
-
"vite": "^5.
|
|
33
|
-
"vite-plugin-solid": "^2.
|
|
34
|
-
"vitest": "^1.
|
|
26
|
+
"eslint-plugin-solid": "^0.14.0",
|
|
27
|
+
"husky": "^9.0.11",
|
|
28
|
+
"jsdom": "^24.1.0",
|
|
29
|
+
"prettier": "^3.3.1",
|
|
30
|
+
"sass": "^1.77.4",
|
|
31
|
+
"typescript": "^5.4.5",
|
|
32
|
+
"vite": "^5.2.12",
|
|
33
|
+
"vite-plugin-solid": "^2.10.2",
|
|
34
|
+
"vitest": "^1.6.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@fortawesome/fontawesome-svg-core": "^6.5.
|
|
38
|
-
"@fortawesome/free-solid-svg-icons": "^6.5.
|
|
39
|
-
"@molgenis/vip-report-api": "^5.0.
|
|
40
|
-
"@molgenis/vip-report-vcf": "^2.0.
|
|
41
|
-
"@solidjs/router": "^0.
|
|
37
|
+
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
|
38
|
+
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
|
39
|
+
"@molgenis/vip-report-api": "^5.0.4",
|
|
40
|
+
"@molgenis/vip-report-vcf": "^2.0.2",
|
|
41
|
+
"@solidjs/router": "^0.13.5",
|
|
42
42
|
"base64-js": "^1.5.1",
|
|
43
43
|
"igv": "^2.15.11",
|
|
44
|
-
"solid-js": "^1.8.
|
|
44
|
+
"solid-js": "^1.8.17"
|
|
45
45
|
},
|
|
46
46
|
"lint-staged": {
|
|
47
47
|
"src/**/*.{tsx,ts}": [
|
package/src/App.tsx
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { VariantsView } from "./views/Variants";
|
|
4
|
-
import { Variant } from "./views/Variant";
|
|
5
|
-
import VariantData from "./views/data/VariantData";
|
|
6
|
-
import { Samples } from "./views/Samples";
|
|
7
|
-
import SampleData from "./views/data/SampleData";
|
|
8
|
-
import { Sample } from "./views/Sample";
|
|
9
|
-
import { VariantConsequence } from "./views/VariantConsequence";
|
|
10
|
-
import { SampleVariantConsequenceView } from "./views/SampleVariantConsequence";
|
|
11
|
-
import { SampleVariantsView } from "./views/SampleVariants";
|
|
12
|
-
import { Error } from "./components/Error";
|
|
13
|
-
import SampleVariantData from "./views/data/SampleVariantData";
|
|
14
|
-
import { SampleVariantView } from "./views/SampleVariant";
|
|
15
|
-
import { Home } from "./views/Home";
|
|
1
|
+
import { onMount, ParentComponent } from "solid-js";
|
|
2
|
+
import { useLocation, useNavigate } from "@solidjs/router";
|
|
16
3
|
import api from "./Api";
|
|
17
4
|
import { DatasetDropdown } from "./components/DatasetDropdown";
|
|
18
|
-
import SampleVariantConsequenceData from "./views/data/SampleVariantConsequenceData";
|
|
19
|
-
import VariantConsequenceData from "./views/data/VariantConsequenceData";
|
|
20
|
-
import { Help } from "./views/Help";
|
|
21
5
|
|
|
22
|
-
const App:
|
|
6
|
+
const App: ParentComponent = (props) => {
|
|
23
7
|
const navigate = useNavigate();
|
|
24
8
|
const location = useLocation();
|
|
25
9
|
|
|
@@ -44,23 +28,23 @@ const App: Component = () => {
|
|
|
44
28
|
<>
|
|
45
29
|
<nav class="navbar is-fixed-top is-light" role="navigation" aria-label="main navigation">
|
|
46
30
|
<div class="navbar-brand">
|
|
47
|
-
<
|
|
31
|
+
<a class="navbar-item has-text-weight-semibold" href="/">
|
|
48
32
|
Variant Interpretation Pipeline
|
|
49
|
-
</
|
|
33
|
+
</a>
|
|
50
34
|
</div>
|
|
51
35
|
<div class="navbar-menu">
|
|
52
36
|
<div class="navbar-item has-dropdown is-hoverable">
|
|
53
|
-
<
|
|
37
|
+
<a class="navbar-link" href="/">
|
|
54
38
|
Report
|
|
55
|
-
</
|
|
39
|
+
</a>
|
|
56
40
|
<div class="navbar-dropdown">
|
|
57
|
-
<
|
|
41
|
+
<a class="navbar-item" href="/samples">
|
|
58
42
|
Samples
|
|
59
|
-
</
|
|
43
|
+
</a>
|
|
60
44
|
<hr class="navbar-divider" />
|
|
61
|
-
<
|
|
45
|
+
<a class="navbar-item" href="/variants">
|
|
62
46
|
Variants
|
|
63
|
-
</
|
|
47
|
+
</a>
|
|
64
48
|
</div>
|
|
65
49
|
</div>
|
|
66
50
|
{api.isDatasetSupport() && (
|
|
@@ -69,48 +53,13 @@ const App: Component = () => {
|
|
|
69
53
|
</div>
|
|
70
54
|
)}
|
|
71
55
|
<div class="navbar-end">
|
|
72
|
-
<
|
|
56
|
+
<a class="navbar-item" href="/help">
|
|
73
57
|
Help
|
|
74
|
-
</
|
|
58
|
+
</a>
|
|
75
59
|
</div>
|
|
76
60
|
</div>
|
|
77
61
|
</nav>
|
|
78
|
-
<div class="container is-fluid">
|
|
79
|
-
<ErrorBoundary fallback={(err) => <Error error={err as unknown} />}>
|
|
80
|
-
<Routes>
|
|
81
|
-
<Route path="/" element={<Home />} />
|
|
82
|
-
<Route path="/samples">
|
|
83
|
-
<Route path="/" element={<Samples />} />
|
|
84
|
-
<Route path="/:sampleId" data={SampleData}>
|
|
85
|
-
<Route path="/" element={<Sample />} />
|
|
86
|
-
<Route path="/variants">
|
|
87
|
-
<Route path="/" element={<SampleVariantsView />} />
|
|
88
|
-
<Route path="/:variantId" data={SampleVariantData}>
|
|
89
|
-
<Route path="/" element={<SampleVariantView />} />
|
|
90
|
-
<Route path="/consequences">
|
|
91
|
-
<Route
|
|
92
|
-
path="/:consequenceId"
|
|
93
|
-
element={<SampleVariantConsequenceView />}
|
|
94
|
-
data={SampleVariantConsequenceData}
|
|
95
|
-
/>
|
|
96
|
-
</Route>
|
|
97
|
-
</Route>
|
|
98
|
-
</Route>
|
|
99
|
-
</Route>
|
|
100
|
-
</Route>
|
|
101
|
-
<Route path="/variants">
|
|
102
|
-
<Route path="/" element={<VariantsView />} />
|
|
103
|
-
<Route path="/:variantId" data={VariantData}>
|
|
104
|
-
<Route path="/" element={<Variant />} />
|
|
105
|
-
<Route path="/consequences">
|
|
106
|
-
<Route path="/:consequenceId" element={<VariantConsequence />} data={VariantConsequenceData} />
|
|
107
|
-
</Route>
|
|
108
|
-
</Route>
|
|
109
|
-
</Route>
|
|
110
|
-
<Route path="/help" element={<Help />} />
|
|
111
|
-
</Routes>
|
|
112
|
-
</ErrorBoundary>
|
|
113
|
-
</div>
|
|
62
|
+
<div class="container is-fluid">{props.children}</div>
|
|
114
63
|
</>
|
|
115
64
|
);
|
|
116
65
|
};
|
|
@@ -1,50 +1,9 @@
|
|
|
1
1
|
@charset "utf-8";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
$
|
|
5
|
-
$notification-padding
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@import "bulma/sass/utilities/initial-variables";
|
|
9
|
-
@import "bulma/sass/utilities/functions";
|
|
10
|
-
@import "bulma/sass/utilities/derived-variables";
|
|
11
|
-
@import "bulma/sass/utilities/mixins";
|
|
12
|
-
@import "bulma/sass/utilities/controls";
|
|
13
|
-
@import "bulma/sass/utilities/extends";
|
|
14
|
-
|
|
15
|
-
@import "bulma/sass/base/minireset";
|
|
16
|
-
@import "bulma/sass/base/generic";
|
|
17
|
-
@import "bulma/sass/base/animations";
|
|
18
|
-
|
|
19
|
-
@import "bulma/sass/elements/button";
|
|
20
|
-
@import "bulma/sass/elements/container";
|
|
21
|
-
@import "bulma/sass/elements/icon";
|
|
22
|
-
@import "bulma/sass/elements/notification";
|
|
23
|
-
@import "bulma/sass/elements/table";
|
|
24
|
-
@import "bulma/sass/elements/title";
|
|
25
|
-
|
|
26
|
-
@import "bulma/sass/form/shared";
|
|
27
|
-
@import "bulma/sass/form/input-textarea";
|
|
28
|
-
@import "bulma/sass/form/checkbox-radio";
|
|
29
|
-
@import "bulma/sass/form/select";
|
|
30
|
-
@import "bulma/sass/form/tools";
|
|
31
|
-
|
|
32
|
-
@import "bulma/sass/grid/columns";
|
|
33
|
-
|
|
34
|
-
@import "bulma/sass/components/breadcrumb";
|
|
35
|
-
@import "bulma/sass/components/card";
|
|
36
|
-
@import "bulma/sass/components/navbar";
|
|
37
|
-
@import "bulma/sass/components/pagination";
|
|
38
|
-
|
|
39
|
-
@import "bulma/sass/helpers/color";
|
|
40
|
-
@import "bulma/sass/helpers/flexbox";
|
|
41
|
-
@import "bulma/sass/helpers/float";
|
|
42
|
-
@import "bulma/sass/helpers/other";
|
|
43
|
-
@import "bulma/sass/helpers/overflow";
|
|
44
|
-
@import "bulma/sass/helpers/position";
|
|
45
|
-
@import "bulma/sass/helpers/spacing";
|
|
46
|
-
@import "bulma/sass/helpers/typography";
|
|
47
|
-
@import "bulma/sass/helpers/visibility";
|
|
2
|
+
|
|
3
|
+
@use "bulma/sass" with(
|
|
4
|
+
$gap: 8px,
|
|
5
|
+
$notification-padding: 0.75rem 0.75rem,
|
|
6
|
+
);
|
|
48
7
|
|
|
49
8
|
html {
|
|
50
9
|
font-size: 13px;
|
|
@@ -92,7 +51,7 @@ td {
|
|
|
92
51
|
}
|
|
93
52
|
|
|
94
53
|
.pagination-ellipsis {
|
|
95
|
-
min-width:
|
|
54
|
+
min-width: 2.5em;
|
|
96
55
|
}
|
|
97
56
|
|
|
98
57
|
.container {
|
|
@@ -120,4 +79,10 @@ table.is-borderless td,
|
|
|
120
79
|
|
|
121
80
|
.inline-control-text {
|
|
122
81
|
line-height: 32.5px
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.scrolling-div {
|
|
85
|
+
margin-top: 8px;
|
|
86
|
+
overflow-y: auto;
|
|
87
|
+
max-height: calc(100vh - 78px) !important;
|
|
123
88
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Link } from "@solidjs/router";
|
|
2
1
|
import { Component, For } from "solid-js";
|
|
3
2
|
|
|
4
3
|
export type BreadCrumbItem = { href?: string; text: string };
|
|
@@ -12,17 +11,17 @@ export const Breadcrumb: Component<{
|
|
|
12
11
|
<nav class="breadcrumb has-succeeds-separator">
|
|
13
12
|
<ul>
|
|
14
13
|
<li classList={{ "is-active": props.items.length === 0 }}>
|
|
15
|
-
<
|
|
14
|
+
<a href="/">
|
|
16
15
|
<span class="icon is-small mr-2">
|
|
17
16
|
<i class="fas fa-home" />
|
|
18
17
|
</span>
|
|
19
18
|
<span>Report</span>
|
|
20
|
-
</
|
|
19
|
+
</a>
|
|
21
20
|
</li>
|
|
22
21
|
<For each={props.items}>
|
|
23
22
|
{(link, i) => (
|
|
24
23
|
<li classList={{ "is-active": i() === props.items.length - 1 }}>
|
|
25
|
-
<
|
|
24
|
+
<a href={link.href || "#"}>{link.text}</a>
|
|
26
25
|
</li>
|
|
27
26
|
)}
|
|
28
27
|
</For>
|
|
@@ -6,7 +6,7 @@ import { ValueArray } from "@molgenis/vip-report-vcf/src/ValueParser";
|
|
|
6
6
|
import { Info } from "./record/Info";
|
|
7
7
|
import { FieldValue } from "./record/field/Field";
|
|
8
8
|
import { isCsqInfo } from "../utils/csqUtils";
|
|
9
|
-
import {
|
|
9
|
+
import { useLocation } from "@solidjs/router";
|
|
10
10
|
|
|
11
11
|
export const InfoCollapsablePane: Component<{
|
|
12
12
|
fields: FieldMetadata[];
|
|
@@ -58,8 +58,8 @@ export const InfoCollapsablePane: Component<{
|
|
|
58
58
|
<>
|
|
59
59
|
{j() != 0 && collapsed() && <br />}
|
|
60
60
|
{(j() == 0 || collapsed()) &&
|
|
61
|
-
(isCsqInfo(field, "
|
|
62
|
-
<
|
|
61
|
+
(isCsqInfo(field, "VIPC") ? (
|
|
62
|
+
<a href={`${useLocation().pathname}/${props.record.id}/consequences/${j()}`}>
|
|
63
63
|
<Info
|
|
64
64
|
info={value}
|
|
65
65
|
infoMeta={field}
|
|
@@ -68,7 +68,7 @@ export const InfoCollapsablePane: Component<{
|
|
|
68
68
|
isPossibleCompound: props.isPossibleCompound,
|
|
69
69
|
}}
|
|
70
70
|
/>
|
|
71
|
-
</
|
|
71
|
+
</a>
|
|
72
72
|
) : (
|
|
73
73
|
<Info
|
|
74
74
|
info={value}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useNavigate } from "@solidjs/router";
|
|
2
2
|
import { Component, createMemo, For, Show } from "solid-js";
|
|
3
3
|
import { Item, Phenotype, PhenotypicFeature, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
4
4
|
import { HpoTerm } from "./HpoTerm";
|
|
@@ -66,7 +66,7 @@ export const SampleTable: Component<{
|
|
|
66
66
|
<tr>
|
|
67
67
|
<td>{sample.data.person.familyId}</td>
|
|
68
68
|
<td>
|
|
69
|
-
<
|
|
69
|
+
<a href={`/samples/${sample.id}`}>{getSampleLabel(sample.data)}</a>
|
|
70
70
|
</td>
|
|
71
71
|
<td>{sampleFatherLabel(sample.data)}</td>
|
|
72
72
|
<td>{sampleMotherLabel(sample.data)}</td>
|
|
@@ -6,7 +6,7 @@ import { FieldHeader } from "./FieldHeader";
|
|
|
6
6
|
import { Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
7
7
|
import { Item } from "@molgenis/vip-report-api/src/Api";
|
|
8
8
|
import { isCsqInfo } from "../utils/csqUtils";
|
|
9
|
-
import {
|
|
9
|
+
import { useLocation } from "@solidjs/router";
|
|
10
10
|
|
|
11
11
|
function isNonEmptyNestedInfoItem(nestedInfoField: FieldMetadata, index: number, value: Value[] | Value[][]): boolean {
|
|
12
12
|
const infoField = nestedInfoField.nested?.items[index];
|
|
@@ -87,7 +87,7 @@ export const VariantInfoNestedTable: Component<{
|
|
|
87
87
|
{isNonEmptyNestedInfoItem(props.infoField, i(), props.infoValue) && (
|
|
88
88
|
<td>
|
|
89
89
|
{isCsqInfo(infoFieldItem, "Consequence") ? (
|
|
90
|
-
<
|
|
90
|
+
<a href={`${useLocation().pathname}/consequences/${j()}`}>
|
|
91
91
|
<Info
|
|
92
92
|
info={{
|
|
93
93
|
value: Array.isArray(value) ? value[i()] : null,
|
|
@@ -97,7 +97,7 @@ export const VariantInfoNestedTable: Component<{
|
|
|
97
97
|
infoMeta={infoFieldItem}
|
|
98
98
|
context={{}}
|
|
99
99
|
/>
|
|
100
|
-
</
|
|
100
|
+
</a>
|
|
101
101
|
) : (
|
|
102
102
|
<Info
|
|
103
103
|
info={{
|
|
@@ -2,7 +2,6 @@ import { Genotype, Metadata, Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
|
2
2
|
import { Ref } from "./record/Ref";
|
|
3
3
|
import { Chrom } from "./record/Chrom";
|
|
4
4
|
import { Pos } from "./record/Pos";
|
|
5
|
-
import { Link } from "@solidjs/router";
|
|
6
5
|
import { HtsFileMetadata, Item, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
7
6
|
import { GenotypeField } from "./record/format/GenotypeField";
|
|
8
7
|
import { InfoCollapsablePane } from "./InfoCollapsablePane";
|
|
@@ -93,11 +92,11 @@ export const VariantsSampleTable: Component<{
|
|
|
93
92
|
{(record) => (
|
|
94
93
|
<tr>
|
|
95
94
|
<td>
|
|
96
|
-
<
|
|
95
|
+
<a href={`/samples/${props.item.id}/variants/${record.id}`}>
|
|
97
96
|
<Chrom value={record.data.c} />
|
|
98
97
|
<span>:</span>
|
|
99
98
|
<Pos value={record.data.p} />
|
|
100
|
-
</
|
|
99
|
+
</a>
|
|
101
100
|
</td>
|
|
102
101
|
<td>
|
|
103
102
|
<Ref value={record.data.r} isAbbreviate={true} />
|
|
@@ -9,7 +9,6 @@ import { Qual } from "./record/Qual";
|
|
|
9
9
|
import { Filter } from "./record/Filter";
|
|
10
10
|
import { Info } from "./record/Info";
|
|
11
11
|
import { FieldMetadata } from "@molgenis/vip-report-vcf/src/MetadataParser";
|
|
12
|
-
import { Link } from "@solidjs/router";
|
|
13
12
|
import { HtsFileMetadata, Item } from "@molgenis/vip-report-api/src/Api";
|
|
14
13
|
import { FieldHeader } from "./FieldHeader";
|
|
15
14
|
import { InfoCollapsablePane } from "./InfoCollapsablePane";
|
|
@@ -76,9 +75,9 @@ export const VariantsTable: Component<{
|
|
|
76
75
|
<Chrom value={record.data.c} />
|
|
77
76
|
</td>
|
|
78
77
|
<td>
|
|
79
|
-
<
|
|
78
|
+
<a href={`/variants/${record.id}`}>
|
|
80
79
|
<Pos value={record.data.p} />
|
|
81
|
-
</
|
|
80
|
+
</a>
|
|
82
81
|
</td>
|
|
83
82
|
<td>
|
|
84
83
|
<Id value={record.data.i} />
|
|
@@ -2,7 +2,6 @@ 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 { FilterIntegerGq } from "./FilterIntegerGq";
|
|
5
|
-
import { FilterIntegerDp } from "./FilterIntegerDp";
|
|
6
5
|
import { Item, Query, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
7
6
|
import { FilterClinVar } from "./FilterClinVar";
|
|
8
7
|
import { isAnyCsqInfo } from "../../utils/csqUtils";
|
|
@@ -28,9 +27,6 @@ export const Filter: Component<FilterProps> = (props) => {
|
|
|
28
27
|
<Match when={props.field.id === "GQ"}>
|
|
29
28
|
<FilterIntegerGq {...props} />
|
|
30
29
|
</Match>
|
|
31
|
-
<Match when={props.field.id === "DP"}>
|
|
32
|
-
<FilterIntegerDp {...props} />
|
|
33
|
-
</Match>
|
|
34
30
|
<Match when={props.field.id === "VIAB"}>
|
|
35
31
|
<FilterAllelicBalance {...props} />
|
|
36
32
|
</Match>
|
|
@@ -15,18 +15,8 @@ function isAllelicImbalance(genotype: Genotype, allelicBalance: number | undefin
|
|
|
15
15
|
return false;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function getTitle(
|
|
19
|
-
|
|
20
|
-
if (lowReadDepth) {
|
|
21
|
-
title = "Read depth < 20";
|
|
22
|
-
}
|
|
23
|
-
if (allelicImbalance) {
|
|
24
|
-
if (lowReadDepth) {
|
|
25
|
-
title = `${title}, `;
|
|
26
|
-
}
|
|
27
|
-
title = `${title}Allelic imbalance`;
|
|
28
|
-
}
|
|
29
|
-
return title;
|
|
18
|
+
function getTitle(allelicImbalance: boolean) {
|
|
19
|
+
return allelicImbalance ? `Allelic imbalance` : ``;
|
|
30
20
|
}
|
|
31
21
|
|
|
32
22
|
export const GenotypeField: Component<{
|
|
@@ -38,7 +28,6 @@ export const GenotypeField: Component<{
|
|
|
38
28
|
readDepth: number | undefined | null;
|
|
39
29
|
}> = (props) => {
|
|
40
30
|
const allelicImbalance: boolean = isAllelicImbalance(props.genotype, props.allelicBalance);
|
|
41
|
-
const lowReadDepth = props.readDepth !== undefined && props.readDepth !== null && props.readDepth < 20;
|
|
42
31
|
return (
|
|
43
32
|
<>
|
|
44
33
|
<For each={props.genotype.a}>
|
|
@@ -54,8 +43,8 @@ export const GenotypeField: Component<{
|
|
|
54
43
|
</>
|
|
55
44
|
)}
|
|
56
45
|
</For>
|
|
57
|
-
<Show when={
|
|
58
|
-
<abbr title={getTitle(
|
|
46
|
+
<Show when={allelicImbalance}>
|
|
47
|
+
<abbr title={getTitle(allelicImbalance)} class="ml-1 is-clickable">
|
|
59
48
|
<i class="fas fa-circle-exclamation has-text-danger" />
|
|
60
49
|
</abbr>
|
|
61
50
|
</Show>
|
package/src/index.tsx
CHANGED
|
@@ -18,6 +18,19 @@ import {
|
|
|
18
18
|
faSearch,
|
|
19
19
|
} from "@fortawesome/free-solid-svg-icons";
|
|
20
20
|
import { Provider } from "./store";
|
|
21
|
+
import { ErrorBoundary } from "solid-js";
|
|
22
|
+
import { Error } from "./components/Error";
|
|
23
|
+
import { HashRouter, Route } from "@solidjs/router";
|
|
24
|
+
import { Home } from "./views/Home";
|
|
25
|
+
import { Samples } from "./views/Samples";
|
|
26
|
+
import { Sample } from "./views/Sample";
|
|
27
|
+
import { SampleVariantsView } from "./views/SampleVariants";
|
|
28
|
+
import { SampleVariantView } from "./views/SampleVariant";
|
|
29
|
+
import { SampleVariantConsequenceView } from "./views/SampleVariantConsequence";
|
|
30
|
+
import { VariantsView } from "./views/Variants";
|
|
31
|
+
import { Variant } from "./views/Variant";
|
|
32
|
+
import { VariantConsequence } from "./views/VariantConsequence";
|
|
33
|
+
import { Help } from "./views/Help";
|
|
21
34
|
|
|
22
35
|
library.add(
|
|
23
36
|
faAngleDown,
|
|
@@ -46,7 +59,36 @@ if (document.readyState === "complete") {
|
|
|
46
59
|
render(
|
|
47
60
|
() => (
|
|
48
61
|
<Provider>
|
|
49
|
-
<
|
|
62
|
+
<ErrorBoundary fallback={(err) => <Error error={err as unknown} />}>
|
|
63
|
+
<HashRouter root={App}>
|
|
64
|
+
<Route path="/" component={Home} />
|
|
65
|
+
<Route path="/samples">
|
|
66
|
+
<Route path="/" component={Samples} />
|
|
67
|
+
<Route path="/:sampleId">
|
|
68
|
+
<Route path="/" component={Sample} />
|
|
69
|
+
<Route path="/variants">
|
|
70
|
+
<Route path="/" component={SampleVariantsView} />
|
|
71
|
+
<Route path="/:variantId">
|
|
72
|
+
<Route path="/" component={SampleVariantView} />
|
|
73
|
+
<Route path="/consequences">
|
|
74
|
+
<Route path="/:consequenceId" component={SampleVariantConsequenceView} />
|
|
75
|
+
</Route>
|
|
76
|
+
</Route>
|
|
77
|
+
</Route>
|
|
78
|
+
</Route>
|
|
79
|
+
</Route>
|
|
80
|
+
<Route path="/variants">
|
|
81
|
+
<Route path="/" component={VariantsView} />
|
|
82
|
+
<Route path="/:variantId">
|
|
83
|
+
<Route path="/" component={Variant} />
|
|
84
|
+
<Route path="/consequences">
|
|
85
|
+
<Route path="/:consequenceId" component={VariantConsequence} />
|
|
86
|
+
</Route>
|
|
87
|
+
</Route>
|
|
88
|
+
</Route>
|
|
89
|
+
<Route path="/help" component={Help} />
|
|
90
|
+
</HashRouter>
|
|
91
|
+
</ErrorBoundary>
|
|
50
92
|
</Provider>
|
|
51
93
|
),
|
|
52
94
|
document.body,
|
package/src/store/index.tsx
CHANGED
|
@@ -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() {
|
package/src/views/Sample.tsx
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import { Component, For, Show } from "solid-js";
|
|
2
|
-
import {
|
|
2
|
+
import { createAsync, RouteSectionProps } from "@solidjs/router";
|
|
3
3
|
import { Loader } from "../components/Loader";
|
|
4
4
|
import { Breadcrumb } from "../components/Breadcrumb";
|
|
5
|
-
import {
|
|
5
|
+
import { getSample } from "./data/data";
|
|
6
6
|
|
|
7
|
-
export const Sample: Component = () => {
|
|
8
|
-
const
|
|
7
|
+
export const Sample: Component<RouteSectionProps> = (props) => {
|
|
8
|
+
const sample = createAsync(() => getSample(Number(props.params.sampleId)));
|
|
9
9
|
|
|
10
10
|
return (
|
|
11
|
-
<Show when={
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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 {
|
|
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
|
|
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()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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,13 +1,7 @@
|
|
|
1
1
|
import { Component, createResource, Show } from "solid-js";
|
|
2
|
-
import {
|
|
2
|
+
import { createAsync, RouteSectionProps } from "@solidjs/router";
|
|
3
3
|
import { Loader } from "../components/Loader";
|
|
4
|
-
import {
|
|
5
|
-
fetchDecisionTree,
|
|
6
|
-
fetchHtsFileMetadata,
|
|
7
|
-
fetchPedigreeSamples,
|
|
8
|
-
fetchRecordsMeta,
|
|
9
|
-
getRecordLabel,
|
|
10
|
-
} from "../utils/ApiUtils";
|
|
4
|
+
import { fetchDecisionTree, fetchPedigreeSamples, fetchRecordsMeta, getRecordLabel } from "../utils/ApiUtils";
|
|
11
5
|
import { VariantTable } from "../components/VariantTable";
|
|
12
6
|
import { VariantInfoTable } from "../components/VariantInfoTable";
|
|
13
7
|
import { VariantSampleTable } from "../components/VariantSampleTable";
|
|
@@ -16,41 +10,58 @@ import { ConsequenceTable } from "../components/ConsequenceTable";
|
|
|
16
10
|
import { getRecordSamples, getSpecificConsequence } from "../utils/viewUtils";
|
|
17
11
|
import { DecisionTreePath } from "../components/tree/DecisionTreePath";
|
|
18
12
|
import { getDecisionTreePath } from "../utils/decisionTreeUtils";
|
|
19
|
-
import { SampleVariantConsequenceRouteData } from "./data/SampleVariantConsequenceData";
|
|
20
13
|
import { getSampleLabel } from "../utils/sample";
|
|
21
14
|
import { DecisionTree, Item, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
22
15
|
import { Metadata, Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
23
16
|
import { ValueArray } from "@molgenis/vip-report-vcf/src/ValueParser";
|
|
17
|
+
import { getSample, getVariant } from "./data/data";
|
|
24
18
|
|
|
25
|
-
export const SampleVariantConsequenceView: Component = () => {
|
|
26
|
-
const
|
|
27
|
-
|
|
19
|
+
export const SampleVariantConsequenceView: Component<RouteSectionProps> = (props) => {
|
|
20
|
+
const sample = createAsync(() => getSample(Number(props.params.sampleId)));
|
|
21
|
+
const variant = createAsync(() => getVariant(Number(props.params.variantId)));
|
|
22
|
+
const consequenceId = () => Number(props.params.consequenceId);
|
|
28
23
|
const [pedigreeSamples] = createResource(sample, fetchPedigreeSamples);
|
|
29
24
|
const [recordsMeta] = createResource(fetchRecordsMeta);
|
|
30
25
|
const [decisionTree] = createResource(fetchDecisionTree, { initialValue: null });
|
|
31
|
-
const [htsFileMeta] = createResource(fetchHtsFileMetadata);
|
|
32
26
|
|
|
33
27
|
return (
|
|
34
|
-
<Show when={sample()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
{
|
|
39
|
+
href: `/samples/${sample().id}/variants/${variant().id}`,
|
|
40
|
+
text: getRecordLabel(variant()),
|
|
41
|
+
},
|
|
42
|
+
{ text: `Consequence #${consequenceId()}` },
|
|
43
|
+
]}
|
|
44
|
+
/>
|
|
45
|
+
<Show when={pedigreeSamples()} fallback={<Loader />}>
|
|
46
|
+
{(pedigreeSamples) => (
|
|
47
|
+
<Show when={recordsMeta()} fallback={<Loader />}>
|
|
48
|
+
{(recordsMeta) => (
|
|
49
|
+
<SampleVariantConsequence
|
|
50
|
+
sample={sample()}
|
|
51
|
+
pedigreeSamples={pedigreeSamples().items}
|
|
52
|
+
recordsMeta={recordsMeta()}
|
|
53
|
+
variant={variant()}
|
|
54
|
+
consequenceId={consequenceId()}
|
|
55
|
+
decisionTree={decisionTree()}
|
|
56
|
+
/>
|
|
57
|
+
)}
|
|
58
|
+
</Show>
|
|
59
|
+
)}
|
|
60
|
+
</Show>
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
</Show>
|
|
64
|
+
)}
|
|
54
65
|
</Show>
|
|
55
66
|
);
|
|
56
67
|
};
|
|
@@ -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
|
|
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>
|
package/src/views/Variant.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component, createResource, For, Show } from "solid-js";
|
|
2
|
-
import {
|
|
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 {
|
|
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
|
|
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={
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</
|
|
58
|
-
|
|
59
|
-
|
|
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 {
|
|
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 {
|
|
21
|
+
import { getVariant } from "./data/data";
|
|
22
22
|
|
|
23
|
-
export const VariantConsequence: Component = () => {
|
|
24
|
-
const
|
|
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={
|
|
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
|
)}
|
package/src/views/Variants.tsx
CHANGED
|
@@ -83,7 +83,7 @@ export const Variants: Component<{
|
|
|
83
83
|
|
|
84
84
|
return (
|
|
85
85
|
<div class="columns is-variable is-1">
|
|
86
|
-
<div class="column is-1-fullhd is-2">
|
|
86
|
+
<div class="scrolling-div column is-1-fullhd is-2">
|
|
87
87
|
<SearchBox onInput={onSearchChange} />
|
|
88
88
|
<InfoFilters
|
|
89
89
|
fields={flattenFieldMetadata(props.recordsMeta.info)}
|
|
@@ -92,7 +92,7 @@ export const Variants: Component<{
|
|
|
92
92
|
onClear={onFilterClear}
|
|
93
93
|
/>
|
|
94
94
|
</div>
|
|
95
|
-
<div class="column">
|
|
95
|
+
<div class="scrolling-div column">
|
|
96
96
|
<div class="columns is-gapless">
|
|
97
97
|
<div class="column">
|
|
98
98
|
<p class="title is-3">Reported variants</p>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { cache } from "@solidjs/router";
|
|
2
|
+
import { Item, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
3
|
+
import { Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
4
|
+
import api from "../../Api";
|
|
5
|
+
|
|
6
|
+
export const getSample = cache(async (id: number): Promise<Item<Sample>> => api.getSampleById(id), "sample");
|
|
7
|
+
export const getVariant = cache(async (id: number): Promise<Item<Record>> => api.getRecordById(id), "variant");
|
|
@@ -1,47 +0,0 @@
|
|
|
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 FilterIntegerDp: 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
|
-
operator: "or",
|
|
15
|
-
args: [
|
|
16
|
-
{
|
|
17
|
-
selector: fieldSelector,
|
|
18
|
-
operator: ">=",
|
|
19
|
-
args: 20,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
selector: fieldSelector,
|
|
23
|
-
operator: "==",
|
|
24
|
-
args: null,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
selector: fieldSelector,
|
|
28
|
-
operator: "==",
|
|
29
|
-
args: undefined,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
else props.onClear({ key: selectorKey(fieldSelector) });
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div class="control">
|
|
39
|
-
<Checkbox
|
|
40
|
-
desc="Sequencing depth >= 20"
|
|
41
|
-
label="Depth >= 20"
|
|
42
|
-
checked={props.query && props.query.args !== undefined}
|
|
43
|
-
onChange={onFilterChange}
|
|
44
|
-
/>
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
47
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { createResource, Resource } from "solid-js";
|
|
2
|
-
import { RouteDataFuncArgs } from "@solidjs/router/dist/types";
|
|
3
|
-
import { EMPTY_SAMPLE_ITEM, fetchSampleById } from "../../utils/ApiUtils";
|
|
4
|
-
import { Item, Sample } from "@molgenis/vip-report-api/src/Api";
|
|
5
|
-
|
|
6
|
-
export type SampleParams = { sampleId: string };
|
|
7
|
-
export type SampleRouteData = { sample: Resource<Item<Sample>> };
|
|
8
|
-
|
|
9
|
-
export default function SampleData({ params }: RouteDataFuncArgs): SampleRouteData {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
11
|
-
const [sample] = createResource(() => params.sampleId, fetchSampleById, { initialValue: EMPTY_SAMPLE_ITEM });
|
|
12
|
-
return { sample };
|
|
13
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { RouteDataFuncArgs } from "@solidjs/router/dist/types";
|
|
2
|
-
import { SampleVariantRouteData } from "./SampleVariantData";
|
|
3
|
-
|
|
4
|
-
export type SampleVariantConsequenceRouteData = { consequenceId: number } & SampleVariantRouteData;
|
|
5
|
-
|
|
6
|
-
export default function SampleVariantConsequenceData({
|
|
7
|
-
params,
|
|
8
|
-
data,
|
|
9
|
-
}: RouteDataFuncArgs): SampleVariantConsequenceRouteData {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
|
11
|
-
const consequenceId: number = parseInt(params.consequenceId);
|
|
12
|
-
return { ...(data as SampleVariantRouteData), consequenceId };
|
|
13
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createResource, Resource } from "solid-js";
|
|
2
|
-
import { RouteDataFuncArgs } from "@solidjs/router/dist/types";
|
|
3
|
-
import { fetchRecordById } from "../../utils/ApiUtils";
|
|
4
|
-
import { SampleRouteData } from "./SampleData";
|
|
5
|
-
import { Item } from "@molgenis/vip-report-api/src/Api";
|
|
6
|
-
import { Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
7
|
-
|
|
8
|
-
export type SampleVariantRouteData = SampleRouteData & { variant: Resource<Item<Record> | undefined> };
|
|
9
|
-
|
|
10
|
-
export default function SampleVariantData({ params, data }: RouteDataFuncArgs): SampleVariantRouteData {
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
12
|
-
const [variant] = createResource(() => params.variantId, fetchRecordById);
|
|
13
|
-
return { ...(data as SampleRouteData), variant };
|
|
14
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { RouteDataFuncArgs } from "@solidjs/router/dist/types";
|
|
2
|
-
import { VariantRouteData } from "./VariantData";
|
|
3
|
-
|
|
4
|
-
export type VariantConsequenceRouteData = { consequenceId: number } & VariantRouteData;
|
|
5
|
-
|
|
6
|
-
export default function VariantConsequenceData({ params, data }: RouteDataFuncArgs): VariantConsequenceRouteData {
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
|
8
|
-
const consequenceId: number = parseInt(params.consequenceId);
|
|
9
|
-
return { ...(data as VariantRouteData), consequenceId };
|
|
10
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { createResource, Resource } from "solid-js";
|
|
2
|
-
import { RouteDataFuncArgs } from "@solidjs/router/dist/types";
|
|
3
|
-
import { EMPTY_RECORD_ITEM, fetchRecordById } from "../../utils/ApiUtils";
|
|
4
|
-
import { Item } from "@molgenis/vip-report-api/src/Api";
|
|
5
|
-
import { Record } from "@molgenis/vip-report-vcf/src/Vcf";
|
|
6
|
-
|
|
7
|
-
export type VariantRouteData = { variant: Resource<Item<Record>> };
|
|
8
|
-
|
|
9
|
-
export default function VariantData({ params }: RouteDataFuncArgs): VariantRouteData {
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
11
|
-
const [variant] = createResource(() => params.variantId, fetchRecordById, { initialValue: EMPTY_RECORD_ITEM });
|
|
12
|
-
return { variant };
|
|
13
|
-
}
|