@molgenis/vip-report-template 6.0.1 → 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 +27 -68
- package/src/__tests__/sample.test.ts +184 -0
- package/src/assets/sass/main.scss +12 -47
- package/src/components/Breadcrumb.tsx +6 -6
- package/src/components/InfoCollapsablePane.tsx +4 -4
- package/src/components/SampleTable.tsx +37 -46
- package/src/components/VariantInfoNestedTable.tsx +3 -3
- package/src/components/VariantsSampleTable.tsx +21 -44
- 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 +7 -10
- package/src/utils/sample.ts +63 -3
- package/src/views/Help.tsx +131 -6
- package/src/views/Home.tsx +24 -112
- 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 +81 -10
- package/src/views/Samples.tsx +35 -33
- package/src/views/Variant.tsx +48 -42
- package/src/views/VariantConsequence.tsx +9 -8
- package/src/views/Variants.tsx +8 -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,63 +28,38 @@ 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
|
-
<
|
|
48
|
-
|
|
49
|
-
</
|
|
31
|
+
<a class="navbar-item has-text-weight-semibold" href="/">
|
|
32
|
+
Variant Interpretation Pipeline
|
|
33
|
+
</a>
|
|
50
34
|
</div>
|
|
51
35
|
<div class="navbar-menu">
|
|
52
|
-
<div class="navbar-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
</
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
36
|
+
<div class="navbar-item has-dropdown is-hoverable">
|
|
37
|
+
<a class="navbar-link" href="/">
|
|
38
|
+
Report
|
|
39
|
+
</a>
|
|
40
|
+
<div class="navbar-dropdown">
|
|
41
|
+
<a class="navbar-item" href="/samples">
|
|
42
|
+
Samples
|
|
43
|
+
</a>
|
|
44
|
+
<hr class="navbar-divider" />
|
|
45
|
+
<a class="navbar-item" href="/variants">
|
|
46
|
+
Variants
|
|
47
|
+
</a>
|
|
48
|
+
</div>
|
|
60
49
|
</div>
|
|
50
|
+
{api.isDatasetSupport() && (
|
|
51
|
+
<div class="navbar-start">
|
|
52
|
+
<DatasetDropdown />
|
|
53
|
+
</div>
|
|
54
|
+
)}
|
|
61
55
|
<div class="navbar-end">
|
|
62
|
-
<
|
|
56
|
+
<a class="navbar-item" href="/help">
|
|
63
57
|
Help
|
|
64
|
-
</
|
|
58
|
+
</a>
|
|
65
59
|
</div>
|
|
66
60
|
</div>
|
|
67
61
|
</nav>
|
|
68
|
-
<div class="container is-fluid">
|
|
69
|
-
<ErrorBoundary fallback={(err) => <Error error={err as unknown} />}>
|
|
70
|
-
<Routes>
|
|
71
|
-
<Route path="/" element={<Home />} />
|
|
72
|
-
<Route path="/samples">
|
|
73
|
-
<Route path="/" element={<Samples />} />
|
|
74
|
-
<Route path="/:sampleId" data={SampleData}>
|
|
75
|
-
<Route path="/" element={<Sample />} />
|
|
76
|
-
<Route path="/variants">
|
|
77
|
-
<Route path="/" element={<SampleVariantsView />} />
|
|
78
|
-
<Route path="/:variantId" data={SampleVariantData}>
|
|
79
|
-
<Route path="/" element={<SampleVariantView />} />
|
|
80
|
-
<Route path="/consequences">
|
|
81
|
-
<Route
|
|
82
|
-
path="/:consequenceId"
|
|
83
|
-
element={<SampleVariantConsequenceView />}
|
|
84
|
-
data={SampleVariantConsequenceData}
|
|
85
|
-
/>
|
|
86
|
-
</Route>
|
|
87
|
-
</Route>
|
|
88
|
-
</Route>
|
|
89
|
-
</Route>
|
|
90
|
-
</Route>
|
|
91
|
-
<Route path="/variants">
|
|
92
|
-
<Route path="/" element={<VariantsView />} />
|
|
93
|
-
<Route path="/:variantId" data={VariantData}>
|
|
94
|
-
<Route path="/" element={<Variant />} />
|
|
95
|
-
<Route path="/consequences">
|
|
96
|
-
<Route path="/:consequenceId" element={<VariantConsequence />} data={VariantConsequenceData} />
|
|
97
|
-
</Route>
|
|
98
|
-
</Route>
|
|
99
|
-
</Route>
|
|
100
|
-
<Route path="/help" element={<Help />} />
|
|
101
|
-
</Routes>
|
|
102
|
-
</ErrorBoundary>
|
|
103
|
-
</div>
|
|
62
|
+
<div class="container is-fluid">{props.children}</div>
|
|
104
63
|
</>
|
|
105
64
|
);
|
|
106
65
|
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
getSampleAffectedStatusLabel,
|
|
4
|
+
getSampleFamilyMembersWithoutParents,
|
|
5
|
+
getSampleFather,
|
|
6
|
+
getSampleLabel,
|
|
7
|
+
getSampleMother,
|
|
8
|
+
getSampleSexLabel,
|
|
9
|
+
} from "../utils/sample";
|
|
10
|
+
import { Sample } from "@molgenis/vip-report-api/src/Api";
|
|
11
|
+
|
|
12
|
+
describe("sample utilities", () => {
|
|
13
|
+
const sample = {
|
|
14
|
+
person: {
|
|
15
|
+
familyId: "fam0",
|
|
16
|
+
individualId: "0",
|
|
17
|
+
maternalId: "1",
|
|
18
|
+
paternalId: "2",
|
|
19
|
+
},
|
|
20
|
+
} as Sample;
|
|
21
|
+
const motherSample = {
|
|
22
|
+
person: {
|
|
23
|
+
familyId: "fam0",
|
|
24
|
+
individualId: "1",
|
|
25
|
+
},
|
|
26
|
+
} as Sample;
|
|
27
|
+
const fatherSample = {
|
|
28
|
+
person: {
|
|
29
|
+
familyId: "fam0",
|
|
30
|
+
individualId: "2",
|
|
31
|
+
},
|
|
32
|
+
} as Sample;
|
|
33
|
+
const siblingSample = {
|
|
34
|
+
person: {
|
|
35
|
+
familyId: "fam0",
|
|
36
|
+
individualId: "3",
|
|
37
|
+
maternalId: "1",
|
|
38
|
+
paternalId: "2",
|
|
39
|
+
},
|
|
40
|
+
} as Sample;
|
|
41
|
+
const otherMotherSample = {
|
|
42
|
+
person: {
|
|
43
|
+
familyId: "fam1",
|
|
44
|
+
individualId: "1",
|
|
45
|
+
},
|
|
46
|
+
} as Sample;
|
|
47
|
+
const otherFatherSample = {
|
|
48
|
+
person: {
|
|
49
|
+
familyId: "fam1",
|
|
50
|
+
individualId: "2",
|
|
51
|
+
},
|
|
52
|
+
} as Sample;
|
|
53
|
+
const otherSiblingSample = {
|
|
54
|
+
person: {
|
|
55
|
+
familyId: "fam1",
|
|
56
|
+
individualId: "3",
|
|
57
|
+
maternalId: "1",
|
|
58
|
+
paternalId: "2",
|
|
59
|
+
},
|
|
60
|
+
} as Sample;
|
|
61
|
+
|
|
62
|
+
test("getSampleLabel", () => {
|
|
63
|
+
const individualId = "sample_label";
|
|
64
|
+
const sample = {
|
|
65
|
+
person: {
|
|
66
|
+
individualId: individualId,
|
|
67
|
+
},
|
|
68
|
+
} as Sample;
|
|
69
|
+
expect(getSampleLabel(sample)).toBe(individualId);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("getSampleSexLabel:FEMALE", () => {
|
|
73
|
+
const sample = {
|
|
74
|
+
person: {
|
|
75
|
+
sex: "FEMALE",
|
|
76
|
+
},
|
|
77
|
+
} as Sample;
|
|
78
|
+
expect(getSampleSexLabel(sample)).toBe("female");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("getSampleSexLabel:MALE", () => {
|
|
82
|
+
const sample = {
|
|
83
|
+
person: {
|
|
84
|
+
sex: "MALE",
|
|
85
|
+
},
|
|
86
|
+
} as Sample;
|
|
87
|
+
expect(getSampleSexLabel(sample)).toBe("male");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("getSampleSexLabel:OTHER_SEX", () => {
|
|
91
|
+
const sample = {
|
|
92
|
+
person: {
|
|
93
|
+
sex: "OTHER_SEX",
|
|
94
|
+
},
|
|
95
|
+
} as Sample;
|
|
96
|
+
expect(getSampleSexLabel(sample)).toBe("?");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("getSampleSexLabel:UNKNOWN_SEX", () => {
|
|
100
|
+
const sample = {
|
|
101
|
+
person: {
|
|
102
|
+
sex: "UNKNOWN_SEX",
|
|
103
|
+
},
|
|
104
|
+
} as Sample;
|
|
105
|
+
expect(getSampleSexLabel(sample)).toBe("?");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("getSampleAffectedStatusLabel:AFFECTED", () => {
|
|
109
|
+
const sample = {
|
|
110
|
+
person: {
|
|
111
|
+
affectedStatus: "AFFECTED",
|
|
112
|
+
},
|
|
113
|
+
} as Sample;
|
|
114
|
+
expect(getSampleAffectedStatusLabel(sample)).toBe("affected");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("getSampleAffectedStatusLabel:UNAFFECTED", () => {
|
|
118
|
+
const sample = {
|
|
119
|
+
person: {
|
|
120
|
+
affectedStatus: "UNAFFECTED",
|
|
121
|
+
},
|
|
122
|
+
} as Sample;
|
|
123
|
+
expect(getSampleAffectedStatusLabel(sample)).toBe("unaffected");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("getSampleAffectedStatusLabel:MISSING", () => {
|
|
127
|
+
const sample = {
|
|
128
|
+
person: {
|
|
129
|
+
affectedStatus: "MISSING",
|
|
130
|
+
},
|
|
131
|
+
} as Sample;
|
|
132
|
+
expect(getSampleAffectedStatusLabel(sample)).toBe("?");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("getSampleMother", () => {
|
|
136
|
+
expect(
|
|
137
|
+
getSampleMother(sample, [
|
|
138
|
+
sample,
|
|
139
|
+
otherSiblingSample,
|
|
140
|
+
otherFatherSample,
|
|
141
|
+
otherMotherSample,
|
|
142
|
+
siblingSample,
|
|
143
|
+
fatherSample,
|
|
144
|
+
motherSample,
|
|
145
|
+
]),
|
|
146
|
+
).toStrictEqual(motherSample);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("getSampleMother:undefined", () => {
|
|
150
|
+
expect(getSampleMother(sample, [sample, otherSiblingSample, otherFatherSample, otherMotherSample])).toBeUndefined();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("getSampleFather", () => {
|
|
154
|
+
expect(
|
|
155
|
+
getSampleFather(sample, [
|
|
156
|
+
sample,
|
|
157
|
+
otherSiblingSample,
|
|
158
|
+
otherMotherSample,
|
|
159
|
+
otherFatherSample,
|
|
160
|
+
siblingSample,
|
|
161
|
+
motherSample,
|
|
162
|
+
fatherSample,
|
|
163
|
+
]),
|
|
164
|
+
).toStrictEqual(fatherSample);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("getSampleFather:undefined", () => {
|
|
168
|
+
expect(getSampleFather(sample, [sample, otherSiblingSample, otherMotherSample, otherFatherSample])).toBeUndefined();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("getSampleFamilyMembersWithoutParents", () => {
|
|
172
|
+
expect(
|
|
173
|
+
getSampleFamilyMembersWithoutParents(sample, [
|
|
174
|
+
sample,
|
|
175
|
+
otherSiblingSample,
|
|
176
|
+
otherMotherSample,
|
|
177
|
+
otherFatherSample,
|
|
178
|
+
siblingSample,
|
|
179
|
+
motherSample,
|
|
180
|
+
fatherSample,
|
|
181
|
+
]),
|
|
182
|
+
).toStrictEqual([siblingSample]);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
@@ -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 };
|
|
@@ -9,19 +8,20 @@ export const Breadcrumb: Component<{
|
|
|
9
8
|
return (
|
|
10
9
|
<div class="columns is-gapless">
|
|
11
10
|
<div class="column">
|
|
12
|
-
<nav class="breadcrumb">
|
|
11
|
+
<nav class="breadcrumb has-succeeds-separator">
|
|
13
12
|
<ul>
|
|
14
13
|
<li classList={{ "is-active": props.items.length === 0 }}>
|
|
15
|
-
<
|
|
16
|
-
<span class="icon">
|
|
14
|
+
<a href="/">
|
|
15
|
+
<span class="icon is-small mr-2">
|
|
17
16
|
<i class="fas fa-home" />
|
|
18
17
|
</span>
|
|
19
|
-
|
|
18
|
+
<span>Report</span>
|
|
19
|
+
</a>
|
|
20
20
|
</li>
|
|
21
21
|
<For each={props.items}>
|
|
22
22
|
{(link, i) => (
|
|
23
23
|
<li classList={{ "is-active": i() === props.items.length - 1 }}>
|
|
24
|
-
<
|
|
24
|
+
<a href={link.href || "#"}>{link.text}</a>
|
|
25
25
|
</li>
|
|
26
26
|
)}
|
|
27
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,40 +1,15 @@
|
|
|
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";
|
|
5
5
|
import { Anchor } from "./Anchor";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
case "UNAFFECTED":
|
|
14
|
-
label = "Unaffected";
|
|
15
|
-
break;
|
|
16
|
-
default:
|
|
17
|
-
label = "?";
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
return label;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function getSexLabel(sex: string) {
|
|
24
|
-
let label;
|
|
25
|
-
switch (sex) {
|
|
26
|
-
case "MALE":
|
|
27
|
-
label = "Male";
|
|
28
|
-
break;
|
|
29
|
-
case "FEMALE":
|
|
30
|
-
label = "Female";
|
|
31
|
-
break;
|
|
32
|
-
default:
|
|
33
|
-
label = "?";
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
return label;
|
|
37
|
-
}
|
|
6
|
+
import {
|
|
7
|
+
getSampleAffectedStatusLabel,
|
|
8
|
+
getSampleFather,
|
|
9
|
+
getSampleLabel,
|
|
10
|
+
getSampleMother,
|
|
11
|
+
getSampleSexLabel,
|
|
12
|
+
} from "../utils/sample";
|
|
38
13
|
|
|
39
14
|
function mapPhenotypes(phenotypes: Item<Phenotype>[]) {
|
|
40
15
|
const phenoMap: { [key: string]: PhenotypicFeature[] } = {};
|
|
@@ -48,11 +23,23 @@ export const SampleTable: Component<{
|
|
|
48
23
|
samples: Item<Sample>[];
|
|
49
24
|
phenotypes: Item<Phenotype>[];
|
|
50
25
|
}> = (props) => {
|
|
26
|
+
const navigate = useNavigate();
|
|
27
|
+
const samples = createMemo(() => props.samples.map((item) => item.data));
|
|
51
28
|
const phenoMap = createMemo(() => mapPhenotypes(props.phenotypes));
|
|
52
29
|
|
|
53
|
-
|
|
54
|
-
return phenoMap()[
|
|
55
|
-
}
|
|
30
|
+
const samplePhenotypes = (sample: Sample): PhenotypicFeature[] => {
|
|
31
|
+
return phenoMap()[sample.person.individualId] ?? [];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const sampleFatherLabel = (sample: Sample): string => {
|
|
35
|
+
const sampleFather = getSampleFather(sample, samples());
|
|
36
|
+
return sampleFather ? getSampleLabel(sampleFather) : "";
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const sampleMotherLabel = (sample: Sample): string => {
|
|
40
|
+
const sampleMother = getSampleMother(sample, samples());
|
|
41
|
+
return sampleMother ? getSampleLabel(sampleMother) : "";
|
|
42
|
+
};
|
|
56
43
|
|
|
57
44
|
return (
|
|
58
45
|
<div style={{ display: "grid" }}>
|
|
@@ -70,6 +57,7 @@ export const SampleTable: Component<{
|
|
|
70
57
|
<th>Affected</th>
|
|
71
58
|
<th>Phenotypes</th>
|
|
72
59
|
<th>VIBE</th>
|
|
60
|
+
<th />
|
|
73
61
|
</tr>
|
|
74
62
|
</thead>
|
|
75
63
|
<tbody>
|
|
@@ -78,15 +66,15 @@ export const SampleTable: Component<{
|
|
|
78
66
|
<tr>
|
|
79
67
|
<td>{sample.data.person.familyId}</td>
|
|
80
68
|
<td>
|
|
81
|
-
<
|
|
69
|
+
<a href={`/samples/${sample.id}`}>{getSampleLabel(sample.data)}</a>
|
|
82
70
|
</td>
|
|
83
|
-
<td>{sample.data
|
|
84
|
-
<td>{sample.data
|
|
71
|
+
<td>{sampleFatherLabel(sample.data)}</td>
|
|
72
|
+
<td>{sampleMotherLabel(sample.data)}</td>
|
|
85
73
|
<td>{sample.data.proband === true ? "True" : "False"}</td>
|
|
86
|
-
<td>{
|
|
87
|
-
<td>{
|
|
74
|
+
<td>{getSampleSexLabel(sample.data)}</td>
|
|
75
|
+
<td>{getSampleAffectedStatusLabel(sample.data)}</td>
|
|
88
76
|
<td>
|
|
89
|
-
<For each={
|
|
77
|
+
<For each={samplePhenotypes(sample.data)}>
|
|
90
78
|
{(phenotypicFeature: PhenotypicFeature, i) => (
|
|
91
79
|
<>
|
|
92
80
|
{i() > 0 ? ", " : ""}
|
|
@@ -96,11 +84,9 @@ export const SampleTable: Component<{
|
|
|
96
84
|
</For>
|
|
97
85
|
</td>
|
|
98
86
|
<td>
|
|
99
|
-
<Show when={
|
|
87
|
+
<Show when={samplePhenotypes(sample.data).length > 0}>
|
|
100
88
|
<Anchor
|
|
101
|
-
href={`https://vibe.molgeniscloud.org/?phenotypes=${
|
|
102
|
-
sample.data.person.individualId,
|
|
103
|
-
)
|
|
89
|
+
href={`https://vibe.molgeniscloud.org/?phenotypes=${samplePhenotypes(sample.data)
|
|
104
90
|
.map((feature) => feature.type.id)
|
|
105
91
|
.join(",")}`}
|
|
106
92
|
>
|
|
@@ -108,6 +94,11 @@ export const SampleTable: Component<{
|
|
|
108
94
|
</Anchor>
|
|
109
95
|
</Show>
|
|
110
96
|
</td>
|
|
97
|
+
<td>
|
|
98
|
+
<button class="button is-primary py-1" onClick={() => navigate(`/samples/${sample.id}/variants`)}>
|
|
99
|
+
Explore Variants
|
|
100
|
+
</button>
|
|
101
|
+
</td>
|
|
111
102
|
</tr>
|
|
112
103
|
)}
|
|
113
104
|
</For>
|