@molgenis/vip-report-template 3.1.2 → 3.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molgenis/vip-report-template",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "description": "Report Template for Variant Call Format (VCF) Report Generator",
5
5
  "scripts": {
6
6
  "build": "vite build",
@@ -15,32 +15,32 @@
15
15
  },
16
16
  "license": "LGPL-3.0",
17
17
  "devDependencies": {
18
- "@molgenis/vite-plugin-inline": "^1.0.7",
19
- "@typescript-eslint/eslint-plugin": "^5.28.0",
20
- "@typescript-eslint/parser": "^5.28.0",
18
+ "@molgenis/vite-plugin-inline": "^1.0.8",
19
+ "@typescript-eslint/eslint-plugin": "^5.35.1",
20
+ "@typescript-eslint/parser": "^5.35.1",
21
+ "@vitest/coverage-c8": "^0.22.1",
21
22
  "bulma": "^0.9.4",
22
- "c8": "^7.11.3",
23
- "eslint": "^8.17.0",
23
+ "eslint": "^8.22.0",
24
24
  "eslint-config-prettier": "^8.5.0",
25
- "eslint-plugin-prettier": "^4.0.0",
26
- "eslint-plugin-solid": "^0.7.0",
25
+ "eslint-plugin-prettier": "^4.2.1",
26
+ "eslint-plugin-solid": "^0.7.1",
27
27
  "husky": "^8.0.1",
28
- "prettier": "^2.7.0",
29
- "sass": "^1.52.3",
30
- "typescript": "^4.7.3",
31
- "vite": "^2.9.12",
32
- "vite-plugin-solid": "^2.2.6",
33
- "vitest": "^0.14.2"
28
+ "prettier": "^2.7.1",
29
+ "sass": "^1.54.5",
30
+ "typescript": "^4.7.4",
31
+ "vite": "^3.0.9",
32
+ "vite-plugin-solid": "^2.3.0",
33
+ "vitest": "^0.22.1"
34
34
  },
35
35
  "dependencies": {
36
- "@fortawesome/fontawesome-svg-core": "^6.1.1",
37
- "@fortawesome/free-solid-svg-icons": "^6.1.1",
38
- "@molgenis/vip-report-api": "^3.5.2",
39
- "@molgenis/vip-report-vcf": "^1.2.2",
36
+ "@fortawesome/fontawesome-svg-core": "^6.1.2",
37
+ "@fortawesome/free-solid-svg-icons": "^6.1.2",
38
+ "@molgenis/vip-report-api": "^3.5.4",
39
+ "@molgenis/vip-report-vcf": "^1.2.3",
40
40
  "base64-js": "^1.5.1",
41
- "igv": "^2.12.6",
42
- "solid-app-router": "^0.3.3",
43
- "solid-js": "^1.4.4"
41
+ "igv": "^2.13.1",
42
+ "solid-app-router": "^0.4.2",
43
+ "solid-js": "^1.4.8"
44
44
  },
45
45
  "lint-staged": {
46
46
  "src/**/*.{tsx,ts}": [
@@ -56,9 +56,12 @@ export const VariantsTable: Component<{
56
56
  <tr>
57
57
  <For each={infoFieldsNested()}>
58
58
  {(infoField) => (
59
- <For each={infoField.nested?.items}>
60
- {(nestedInfoField) => <FieldHeader field={nestedInfoField} />}
61
- </For>
59
+ <>
60
+ {infoField.number.count !== 1 && <th />}
61
+ <For each={infoField.nested?.items}>
62
+ {(nestedInfoField) => <FieldHeader field={nestedInfoField} />}
63
+ </For>
64
+ </>
62
65
  )}
63
66
  </For>
64
67
  </tr>
@@ -1,13 +1,18 @@
1
1
  import { Component } from "solid-js";
2
- import { Query, Sample } from "@molgenis/vip-report-api/src/Api";
2
+ import { HtsFileMetadata, Query, Sample } from "@molgenis/vip-report-api/src/Api";
3
3
  import { Metadata } from "@molgenis/vip-report-vcf/src/Vcf";
4
4
  import api from "../../Api";
5
5
  import { Filter, writeVcf } from "@molgenis/vip-report-vcf/src/VcfWriter";
6
6
 
7
+ const DOWNLOAD_POSTFIX = "_report.vcf";
7
8
  export const RecordDownload: Component<{ recordsMetadata: Metadata; query?: Query; samples?: Sample[] }> = (props) => {
8
9
  const filter = (): Filter | undefined =>
9
10
  props.samples ? { samples: props.samples.map((sample) => sample.person.individualId) } : undefined;
10
11
 
12
+ function parseFilename(htsFile: HtsFileMetadata) {
13
+ return htsFile.uri.split("\\").pop()?.split("/").pop()?.split(".").shift();
14
+ }
15
+
11
16
  function onClick() {
12
17
  const handler = async () => {
13
18
  const records = await api.getRecords({ query: props.query, size: Number.MAX_SAFE_INTEGER });
@@ -16,7 +21,9 @@ export const RecordDownload: Component<{ recordsMetadata: Metadata; query?: Quer
16
21
  const url = window.URL.createObjectURL(new Blob([vcf]));
17
22
  const link = document.createElement("a");
18
23
  link.href = url;
19
- link.setAttribute("download", "data.vcf");
24
+ const htsFile = await api.getHtsFileMetadata();
25
+ const filename = parseFilename(htsFile) as string;
26
+ link.setAttribute("download", filename + DOWNLOAD_POSTFIX);
20
27
  document.body.appendChild(link);
21
28
  link.click();
22
29
  document.body.removeChild(link);
@@ -26,7 +33,11 @@ export const RecordDownload: Component<{ recordsMetadata: Metadata; query?: Quer
26
33
 
27
34
  return (
28
35
  <div class="control">
29
- <button class="button is-info" onClick={onClick}>
36
+ <button
37
+ class="button is-info"
38
+ onClick={onClick}
39
+ title="Download vcf file with records matching filters and search queries"
40
+ >
30
41
  <span class="icon is-small">
31
42
  <i class="fas fa-download" />
32
43
  </span>
@@ -45,9 +45,9 @@ export const Gene: Component<FieldProps> = (props) => {
45
45
  <span>{symbol}</span>
46
46
  </Anchor>
47
47
  {incompletePenetrance() && (
48
- <sup class="ml-1">
48
+ <span class="ml-1">
49
49
  <Abbr title="gene is known for incomplete penetrance" value="IP" />
50
- </sup>
50
+ </span>
51
51
  )}
52
52
  </>
53
53
  )}
@@ -80,8 +80,8 @@
80
80
  1 16375583 . GA G . PASS CSQ=-|intron_variant|MODIFIER|CLCNKB|1188|Transcript|NM_000085.5|protein_coding||7/19|NM_000085.5:c.656-31del|||||||rs751608665|1||1||1|EntrezGene||||||||uncertain_significance&pathogenic||1||||||||20|45|-14|-45|0.05|0.00|0.00|0.00|CLCNKB|VUS|0.032507|HP:0000951||AR|LP||||1:16375584-16375585|0.000548455|0|638508|Conflicting_interpretations_of_pathogenicity||criteria_provided&_conflicting_interpretations|LP|filter&vkgl&exit_lp|,-|frameshift_variant|HIGH|CLCNKB|1188|Transcript|NM_001165945.2|protein_coding|1/13||NM_001165945.2:c.118del|NP_001159417.2:p.Arg40GlyfsTer4|328/2174|118/1554|40/517|R/X|Agg/gg|rs751608665|1||1|||EntrezGene||||||||uncertain_significance&pathogenic||1||||||||20|45|-14|-45|0.05|0.00|0.00|0.00|CLCNKB|VUS|0.9770811|HP:0000951||AR|LP||||1:16375584-16375585|0.000548455|0|638508|Conflicting_interpretations_of_pathogenicity||criteria_provided&_conflicting_interpretations|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM:VIS 1|0:25,25:50:AR:1_16376412_G_A,1_16376412_G_N:0:1188:1:AR_C 1|0:25,25:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:.
81
81
  1 16376412 n_alt G N . PASS CSQ=N|splice_donor_variant|HIGH|CLCNKB|1188|Transcript|NM_000085.5|protein_coding||10/19||||||||CS1211892&CS971662|1||1||1|EntrezGene||||||||||1&1|||||||||||||||||VUS|0.373989|HP:0000951||AR||||||||||||LP|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_lp|,N|splice_donor_variant|HIGH|CLCNKB|1188|Transcript|NM_001165945.2|protein_coding||3/12||||||||CS1211892&CS971662|1||1|||EntrezGene||||||||||1&1|||||||||||||||||VUS|0.373989|HP:0000951||AR||||||||||||LP|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM:VIS 1|0:5,45:50:AR,AD:1_16376412_G_A,1_16375583_GA_G:1:1188:1:AR_C 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:.
82
82
  1 16376412 . G A . PASS CSQ=A|splice_donor_variant|HIGH|CLCNKB|1188|Transcript|NM_000085.5|protein_coding||10/19|NM_000085.5:c.968+1G>A|||||||rs201204502&CS1211892&CS971662|1||1||1|EntrezGene||||||||||0&1&1||||||||17|-36|-28|-1|0.00|0.00|0.03|0.97|CLCNKB|VUS|0.9855972|HP:0000951||AR|LP||||1:16376412-16376412|6.38086e-05|0|1285112|Pathogenic/Likely_pathogenic||no_assertion_criteria_provided|LP|filter&vkgl&exit_lp|,A|splice_donor_variant|HIGH|CLCNKB|1188|Transcript|NM_001165945.2|protein_coding||3/12|NM_001165945.2:c.461+1G>A|||||||rs201204502&CS1211892&CS971662|1||1|||EntrezGene||||||||||0&1&1||||||||17|-36|-28|-1|0.00|0.00|0.03|0.97|CLCNKB|VUS|0.9855972|HP:0000951||AR|LP||||1:16376412-16376412|6.38086e-05|0|1285112|Pathogenic/Likely_pathogenic||no_assertion_criteria_provided|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM:VIS 0|1:50:50:AR:1_16375583_GA_G,1_16376412_G_N:0:1188:1:AR_C 0|0:50,0:50:.:.:.:.:.:. 1|0:25,25:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.:.
83
- 1 17349219 g_ref G A . PASS CSQ=A|missense_variant|MODERATE|SDHB|6390|Transcript|NM_003000.3|protein_coding|7/8||NM_003000.3:c.649C>T|NP_002991.2:p.Arg217Cys|662/1015|649/843|217/280|R/C|Cgc/Tgc|rs200245469&CM094752&CM1210440&COSV64965760|1||-1||1|EntrezGene|||||0|1||likely_pathogenic|0&0&0&1|1&1&1&1||||||||28|6|6|5|0.00|0.00|0.00|0.00|SDHB|VUS|0.89070946|HP:0000951||AD&AR|LP|||||||183735|Pathogenic/Likely_pathogenic||criteria_provided&_multiple_submitters&_no_conflicts|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|1:0,50:50:AR:.:1:6390:1 1|0:45,5:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 1|0:25,25:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.
84
- 1 17355094 . C T . PASS CSQ=T|splice_donor_variant|HIGH|SDHB|6390|Transcript|NM_003000.3|protein_coding||4/7|NM_003000.3:c.423+1G>A|||||||rs398122805&CS056774&CS062098&COSV64965540|1||-1||1|EntrezGene||||||||pathogenic|0&0&0&1|1&1&1&1|21348866&17667967&17804857&16405730&21565294&15383933|||||||-49|12|26|1|0.00|0.00|0.14|0.97|SDHB|VUS|0.9641474|HP:0000951||AD&AR|LP||||1:17355094-17355094|1.19344e-05|0|29896|Pathogenic||criteria_provided&_multiple_submitters&_no_conflicts|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|0:5,45:50:AD:.:1:6390:1 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.
83
+ 1 17349219 g_ref G A . PASS CSQ=A|missense_variant|MODERATE|SDHB|6390|Transcript|NM_003000.3|protein_coding|7/8||NM_003000.3:c.649C>T|NP_002991.2:p.Arg217Cys|662/1015|649/843|217/280|R/C|Cgc/Tgc|rs200245469&CM094752&CM1210440&COSV64965760|1||-1||1|EntrezGene|||||0|1||likely_pathogenic|0&0&0&1|1&1&1&1||||||||28|6|6|5|0.00|0.00|0.00|0.00|SDHB|VUS|0.89070946|HP:0000951&HP:0003124||AD&AR|LP|||||||183735|Pathogenic/Likely_pathogenic||criteria_provided&_multiple_submitters&_no_conflicts|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|1:0,50:50:AR:.:1:6390:1 1|0:45,5:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 1|0:25,25:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.
84
+ 1 17355094 . C T . PASS CSQ=T|splice_donor_variant|HIGH|SDHB|6390|Transcript|NM_003000.3|protein_coding||4/7|NM_003000.3:c.423+1G>A|||||||rs398122805&CS056774&CS062098&COSV64965540|1||-1||1|EntrezGene||||||||pathogenic|0&0&0&1|1&1&1&1|21348866&17667967&17804857&16405730&21565294&15383933|||||||-49|12|26|1|0.00|0.00|0.14|0.97|SDHB|VUS|0.9641474|HP:0003124||AD&AR|LP||||1:17355094-17355094|1.19344e-05|0|29896|Pathogenic||criteria_provided&_multiple_submitters&_no_conflicts|LP|filter&vkgl&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|0:5,45:50:AD:.:1:6390:1 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.
85
85
  1 152520788 symbolic1 A <DEL> . PASS CSQ=deletion|transcript_ablation|HIGH|LCE3D|84648|Transcript|NM_032563.2|protein_coding|||||||||||1||-1||1|EntrezGene|||||||||||||||||||||||||||||||||||||||||||LP|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_lp|,deletion|transcript_ablation|HIGH|LCE3E|353145|Transcript|NM_178435.4|protein_coding|||||||||||1||-1|||EntrezGene|||||||||||||||||||||||||||||||||||||||||||LP|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_lp|,deletion|TFBS_ablation&TF_binding_site_variant|MODERATE|||MotifFeature|ENSM00701519957||||||||||||1||||||||||||||||||||||||||||||||||||||||||||||||VUS|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_vus|,deletion|TFBS_ablation&TF_binding_site_variant|MODERATE|||MotifFeature|ENSM00905971885||||||||||||1||||||||||||||||||||||||||||||||||||||||||||||||VUS|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_vus|,deletion|TFBS_ablation&TF_binding_site_variant|MODERATE|||MotifFeature|ENSM00522719201||||||||||||1||||||||||||||||||||||||||||||||||||||||||||||||VUS|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_vus|;SVLEN=-49314;SVTYPE=DEL GT:AD:DP:VI:VIC:VID:VIM 1|1:0,50:50:AR:.:1:0 0|0:50,0:50:.:.:.:. 0|0:50,0:50:.:.:.:. 0|0:50,0:50:.:.:.:. 0|0:50,0:50:.:.:.:. 1|0:25,25:50:.:.:.:.
86
86
  4 106320294 . G A . PASS CSQ=A|missense_variant|MODERATE|PPA2|27068|Transcript|NM_006903.4|protein_coding|7/11||NM_006903.4:c.596C>T|NP_008834.3:p.Pro199Leu|616/1586|596/918|199/305|P/L|cCg/cTg|rs138215926&CM1610192&COSV58994362|1||-1|||EntrezGene|||||0|0.985||pathogenic|0&0&1|1&1&1|27523597|||||||-34|27|-2|-43|0.00|0.00|0.00|0.00|PPA2|VUS|0.8097311|||AR|LP||||4:106320294-106320294|0.000211803|0|372226|Likely_pathogenic||criteria_provided&_single_submitter|LP|filter&vkgl&exit_lp|,A|missense_variant|MODERATE|PPA2|27068|Transcript|NM_176866.2|protein_coding|4/8||NM_176866.2:c.377C>T|NP_789842.2:p.Pro126Leu|397/1367|377/699|126/232|P/L|cCg/cTg|rs138215926&CM1610192&COSV58994362|1||-1|||EntrezGene|||||0|0.992||pathogenic|0&0&1|1&1&1|27523597|||||||-34|27|-2|-43|0.00|0.00|0.00|0.00|PPA2|VUS|0.7550335|||AR|LP||||4:106320294-106320294|0.000211803|0|372226|Likely_pathogenic||criteria_provided&_single_submitter|LP|filter&vkgl&exit_lp|,A|missense_variant|MODERATE|PPA2|27068|Transcript|NM_176867.3|protein_coding|2/6||NM_176867.3:c.185C>T|NP_789843.2:p.Pro62Leu|205/1175|185/507|62/168|P/L|cCg/cTg|rs138215926&CM1610192&COSV58994362|1||-1|||EntrezGene|||||0|0.995||pathogenic|0&0&1|1&1&1|27523597|||||||-34|27|-2|-43|0.00|0.00|0.00|0.00|PPA2|VUS|0.8145551|||AR|LP||||4:106320294-106320294|0.000211803|0|372226|Likely_pathogenic||criteria_provided&_single_submitter|LP|filter&vkgl&exit_lp|,A|missense_variant|MODERATE|PPA2|27068|Transcript|NM_176869.3|protein_coding|8/12||NM_176869.3:c.683C>T|NP_789845.1:p.Pro228Leu|695/1665|683/1005|228/334|P/L|cCg/cTg|rs138215926&CM1610192&COSV58994362|1||-1||1|EntrezGene|||||0|0.993||pathogenic|0&0&1|1&1&1|27523597|||||||-34|27|-2|-43|0.00|0.00|0.00|0.00|PPA2|VUS|0.76490384|||AR|LP||||4:106320294-106320294|0.000211803|0|372226|Likely_pathogenic||criteria_provided&_single_submitter|LP|filter&vkgl&exit_lp|,A|regulatory_region_variant|MODIFIER|||RegulatoryFeature|ENSR00001994744|promoter_flanking_region||||||||||rs138215926&CM1610192&COSV58994362|1|||||||||||||pathogenic|0&0&1|1&1&1|27523597|||||||||||||||||||||||||4:106320294-106320294|0.000211803|0|372226|Likely_pathogenic||criteria_provided&_single_submitter|LP|filter&vkgl&clinVar&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|1:0,50:50:AR:.:1:27068:1 1|0:25,25:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 1|1:0,50:50:.:.:.:.:.
87
87
  9 107546633 . AAAGAT A . PASS CSQ=-|frameshift_variant|HIGH|ABCA1|19|Transcript|NM_005502.4|protein_coding|50/50||NM_005502.4:c.6744_6748del|NP_005493.2:p.Phe2250ThrfsTer3|7057-7061/10408|6744-6748/6786|2248-2250/2261|TSF/TX|acATCTTtt/actt||1||-1||1|EntrezGene|||||||||||||||||||||||||||VUS|0.9823047|HP:0000951||AD&AR||||||||||||LP|filter&vkgl&clinVar&gnomad&effect&spliceAI&annotSV&impact&exit_lp| GT:AD:DP:VI:VIC:VID:VIG:VIM 1|1:0,10:10:AR:.:0:19:1 0|1:1,49:50:.:.:.:.:. 1|0:0,50:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:. 0|0:50,0:50:.:.:.:.:.
@@ -9,7 +9,7 @@
9
9
  ##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
10
10
  ##HPO=List of HPO terms for the gene
11
11
  ##INFO=<ID=BND_DEPTH,Number=1,Type=Integer,Description="Read depth at local translocation breakend">
12
- ##INFO=<ID=CSQ,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: Allele|Consequence|IMPACT|SYMBOL|Gene|Feature_type|Feature|BIOTYPE|EXON|INTRON|HGVSc|HGVSp|cDNA_position|CDS_position|Protein_position|Amino_acids|Codons|Existing_variation|ALLELE_NUM|DISTANCE|STRAND|FLAGS|PICK|SYMBOL_SOURCE|HGNC_ID|REFSEQ_MATCH|REFSEQ_OFFSET|SOURCE|SIFT|PolyPhen|HGVS_OFFSET|CLIN_SIG|SOMATIC|PHENO|PUBMED|CHECK_REF|MOTIF_NAME|MOTIF_POS|HIGH_INF_POS|MOTIF_SCORE_CHANGE|TRANSCRIPTION_FACTORS|SpliceAI_pred_DP_AG|SpliceAI_pred_DP_AL|SpliceAI_pred_DP_DG|SpliceAI_pred_DP_DL|SpliceAI_pred_DS_AG|SpliceAI_pred_DS_AL|SpliceAI_pred_DS_DG|SpliceAI_pred_DS_DL|SpliceAI_pred_SYMBOL|CAPICE_CL|CAPICE_SC|HPO|IncompletePenetrance|InheritanceModesGene|VKGL_CL|ASV_ACMG_class|ASV_AnnotSV_ranking_criteria|ASV_AnnotSV_ranking_score|gnomAD|gnomAD_AF|gnomAD_HN|VIPC|VIPP|VIPL">
12
+ ##INFO=<ID=CSQ,Number=.,Type=String,Description="Consequence annotations from Ensembl VEP. Format: Allele|Consequence|IMPACT|SYMBOL|Gene|Feature_type|Feature|BIOTYPE|EXON|INTRON|HGVSc|HGVSp|cDNA_position|CDS_position|Protein_position|Amino_acids|Codons|Existing_variation|ALLELE_NUM|DISTANCE|STRAND|FLAGS|PICK|SYMBOL_SOURCE|HGNC_ID|REFSEQ_MATCH|REFSEQ_OFFSET|SOURCE|SIFT|PolyPhen|HGVS_OFFSET|CLIN_SIG|SOMATIC|PHENO|PUBMED|CHECK_REF|MOTIF_NAME|MOTIF_POS|HIGH_INF_POS|MOTIF_SCORE_CHANGE|TRANSCRIPTION_FACTORS|SpliceAI_pred_DP_AG|SpliceAI_pred_DP_AL|SpliceAI_pred_DP_DG|SpliceAI_pred_DP_DL|SpliceAI_pred_DS_AG|SpliceAI_pred_DS_AL|SpliceAI_pred_DS_DG|SpliceAI_pred_DS_DL|SpliceAI_pred_SYMBOL|CAPICE_CL|CAPICE_SC|HPO|IncompletePenetrance|InheritanceModesGene|VKGL_CL|ASV_ACMG_class|ASV_AnnotSV_ranking_criteria|ASV_AnnotSV_ranking_score|gnomAD|gnomAD_AF|gnomAD_HN|VIPC|VIPP_renamed|VIPL_renamed">
13
13
  ##INFO=<ID=MATEID,Number=.,Type=String,Description="ID of mate breakend">
14
14
  ##INFO=<ID=MATE_BND_DEPTH,Number=1,Type=Integer,Description="Read depth at remote translocation mate breakend">
15
15
  ##INFO=<ID=SVLEN,Number=.,Type=Integer,Description="Difference in length between REF and ALT alleles">
@@ -120,7 +120,7 @@ export class MockApiClient implements Api {
120
120
  args: "-i testdata_b37_vip.vcf -t /Users/user/vip-report-template/dist/vip-report-template.html -f",
121
121
  },
122
122
  htsFile: {
123
- uri: "testdata_b37_vip.vcf",
123
+ uri: "/path/to/testdata_b37_vip.vcf",
124
124
  htsFormat: "VCF",
125
125
  genomeAssembly: "GRCh37",
126
126
  },
@@ -14,11 +14,18 @@ type AppStateVariants = {
14
14
  sort?: SortOrder | null; // null: do not sort. undefined: sort undefined
15
15
  };
16
16
 
17
+ type AppStateSamples = {
18
+ page?: number;
19
+ searchQuery?: string;
20
+ probandFilterValue?: boolean;
21
+ };
22
+
17
23
  export type AppState = {
18
24
  variants?: AppStateVariants;
19
- samples?: {
25
+ sampleVariants?: {
20
26
  [key: number]: { variants: AppStateVariants };
21
27
  };
28
+ samples?: AppStateSamples;
22
29
  };
23
30
 
24
31
  export type AppActions = {
@@ -26,22 +33,23 @@ export type AppActions = {
26
33
  setVariantsPage(page: number): void;
27
34
  setVariantsPageSize(pageSize: number): void;
28
35
  setVariantsSearchQuery(searchQuery: string): void;
29
- clearVariantsSearchQuery(): void;
30
36
  setVariantsFilterQuery(query: QueryClause): void;
31
37
  clearVariantsFilterQuery(selector: Selector): void;
32
38
  setVariantsSort(sort: SortOrder | null): void;
33
39
  setSampleVariantsPage(sample: Item<Sample>, page: number): void;
34
40
  setSampleVariantsPageSize(sample: Item<Sample>, pageSize: number): void;
35
41
  setSampleVariantsSearchQuery(sample: Item<Sample>, searchQuery: string): void;
36
- clearSampleVariantsSearchQuery(sample: Item<Sample>): void;
37
42
  setSampleVariantsFilterQuery(sample: Item<Sample>, query: QueryClause): void;
38
43
  clearSampleVariantsFilterQuery(sample: Item<Sample>, selector: Selector): void;
39
44
  setSampleVariantsSort(sample: Item<Sample>, sort: SortOrder | null): void;
45
+ setSamplePage(page: number): void;
46
+ setSampleSearchQuery(searchQuery: string): void;
47
+ setSampleProbandFilterValue(probandFilterValue: boolean): void;
40
48
  };
41
49
 
42
50
  export type AppStore = [state: AppState, actions: AppActions];
43
51
 
44
- const defaultState: AppState = { variants: {}, samples: {} };
52
+ const defaultState: AppState = { variants: {}, sampleVariants: {} };
45
53
 
46
54
  const StoreContext = createContext<AppStore>() as Context<AppStore>;
47
55
 
@@ -49,12 +57,12 @@ export const Provider: ParentComponent = (props) => {
49
57
  const [state, setState] = createStore(defaultState);
50
58
 
51
59
  function getVariants(sample: Item<Sample>) {
52
- return state.samples ? state.samples[sample.id]?.variants || {} : {};
60
+ return state.sampleVariants ? state.sampleVariants[sample.id]?.variants || {} : {};
53
61
  }
54
62
 
55
63
  const actions: AppActions = {
56
64
  reset() {
57
- setState({ variants: undefined, samples: undefined });
65
+ setState({ variants: undefined, sampleVariants: undefined, samples: undefined });
58
66
  },
59
67
  setVariantsPage(page: number) {
60
68
  setState({ variants: { ...(state.variants || {}), page } });
@@ -65,9 +73,6 @@ export const Provider: ParentComponent = (props) => {
65
73
  setVariantsSearchQuery(searchQuery: string) {
66
74
  setState({ variants: { ...(state.variants || {}), searchQuery } });
67
75
  },
68
- clearVariantsSearchQuery() {
69
- setState({ variants: { ...(state.variants || {}), searchQuery: undefined } });
70
- },
71
76
  setVariantsFilterQuery(query: QueryClause) {
72
77
  setState({
73
78
  variants: {
@@ -93,37 +98,34 @@ export const Provider: ParentComponent = (props) => {
93
98
  });
94
99
  },
95
100
  setSampleVariantsPage(sample: Item<Sample>, page: number) {
96
- setState({ samples: { ...(state.samples || {}), [sample.id]: { variants: { ...getVariants(sample), page } } } });
101
+ setState({
102
+ sampleVariants: {
103
+ ...(state.sampleVariants || {}),
104
+ [sample.id]: { variants: { ...getVariants(sample), page } },
105
+ },
106
+ });
97
107
  },
98
108
  setSampleVariantsPageSize(sample: Item<Sample>, pageSize: number) {
99
109
  setState({
100
- samples: {
101
- ...(state.samples || {}),
110
+ sampleVariants: {
111
+ ...(state.sampleVariants || {}),
102
112
  [sample.id]: { variants: { ...getVariants(sample), pageSize, page: undefined } },
103
113
  },
104
114
  });
105
115
  },
106
116
  setSampleVariantsSearchQuery(sample: Item<Sample>, searchQuery: string) {
107
117
  setState({
108
- samples: {
109
- ...(state.samples || {}),
118
+ sampleVariants: {
119
+ ...(state.sampleVariants || {}),
110
120
  [sample.id]: { variants: { ...getVariants(sample), searchQuery, page: undefined } },
111
121
  },
112
122
  });
113
123
  },
114
- clearSampleVariantsSearchQuery(sample: Item<Sample>) {
115
- setState({
116
- samples: {
117
- ...(state.samples || {}),
118
- [sample.id]: { variants: { ...getVariants(sample), searchQuery: undefined, page: undefined } },
119
- },
120
- });
121
- },
122
124
  setSampleVariantsFilterQuery(sample: Item<Sample>, query: QueryClause) {
123
125
  const variants = getVariants(sample);
124
126
  setState({
125
- samples: {
126
- ...(state.samples || {}),
127
+ sampleVariants: {
128
+ ...(state.sampleVariants || {}),
127
129
  [sample.id]: {
128
130
  variants: {
129
131
  ...variants,
@@ -137,8 +139,8 @@ export const Provider: ParentComponent = (props) => {
137
139
  clearSampleVariantsFilterQuery(sample: Item<Sample>, selector: Selector) {
138
140
  const variants = getVariants(sample);
139
141
  setState({
140
- samples: {
141
- ...(state.samples || {}),
142
+ sampleVariants: {
143
+ ...(state.sampleVariants || {}),
142
144
  [sample.id]: {
143
145
  variants: {
144
146
  ...getVariants(sample),
@@ -151,9 +153,21 @@ export const Provider: ParentComponent = (props) => {
151
153
  },
152
154
  setSampleVariantsSort(sample: Item<Sample>, sort: SortOrder | null) {
153
155
  setState({
154
- samples: { ...(state.samples || {}), [sample.id]: { variants: { ...getVariants(sample), sort } } },
156
+ sampleVariants: {
157
+ ...(state.sampleVariants || {}),
158
+ [sample.id]: { variants: { ...getVariants(sample), sort } },
159
+ },
155
160
  });
156
161
  },
162
+ setSamplePage(page: number) {
163
+ setState({ samples: { ...(state.samples || {}), page } });
164
+ },
165
+ setSampleSearchQuery(searchQuery: string) {
166
+ setState({ samples: { ...(state.samples || {}), searchQuery } });
167
+ },
168
+ setSampleProbandFilterValue(probandFilterValue: boolean) {
169
+ setState({ samples: { ...(state.samples || {}), probandFilterValue } });
170
+ },
157
171
  };
158
172
  const store: AppStore = [state, actions];
159
173
 
@@ -29,7 +29,6 @@ export function createSampleQuery(
29
29
  const searchFilterQuery = createQuery(search, filters, metadata);
30
30
  const query: Query =
31
31
  searchFilterQuery !== null ? { operator: "and", args: [sampleQuery, searchFilterQuery] } : sampleQuery;
32
- console.log(query);
33
32
  return query;
34
33
  }
35
34
 
@@ -63,6 +63,9 @@ export const SampleVariantConsequence: Component<{
63
63
  consequenceId: number;
64
64
  decisionTree: DecisionTree | null;
65
65
  }> = (props) => {
66
+ const hasDecisionTreePathMeta = () =>
67
+ (props.recordsMeta.info.CSQ?.nested?.items || []).findIndex((csq) => csq.id === "VIPP") !== -1;
68
+
66
69
  return (
67
70
  <>
68
71
  <div class="columns">
@@ -74,7 +77,7 @@ export const SampleVariantConsequence: Component<{
74
77
  record={props.variant}
75
78
  />
76
79
  </div>
77
- {props.decisionTree !== null && (
80
+ {props.decisionTree !== null && hasDecisionTreePathMeta() && (
78
81
  <div class="column">
79
82
  <h1 class="title is-5">Classification tree path</h1>
80
83
  <DecisionTreePath
@@ -66,7 +66,7 @@ export const SampleVariants: Component<{
66
66
  const [state, actions] = useStore();
67
67
 
68
68
  function getStateVariants() {
69
- return state.samples ? state.samples[props.sample.id]?.variants : undefined;
69
+ return state.sampleVariants ? state.sampleVariants[props.sample.id]?.variants : undefined;
70
70
  }
71
71
 
72
72
  // state initialization - start
@@ -1,57 +1,116 @@
1
- import { Component, createResource, createSignal } from "solid-js";
1
+ import { Component, createResource, Show } from "solid-js";
2
2
  import { SampleTable } from "../components/SampleTable";
3
3
  import { Pager } from "../components/record/Pager";
4
4
  import { SearchBox } from "../components/SearchBox";
5
5
  import { Checkbox, CheckboxEvent } from "../components/Checkbox";
6
6
  import { Breadcrumb } from "../components/Breadcrumb";
7
- import { EMPTY_PARAMS, EMPTY_PHENOTYPES, EMPTY_SAMPLES_PAGE, fetchPhenotypes, fetchSamples } from "../utils/ApiUtils";
7
+ import { EMPTY_PARAMS, EMPTY_PHENOTYPES, fetchPhenotypes, fetchSamples } from "../utils/ApiUtils";
8
+ import { useStore } from "../store";
9
+ import { Params, Query, QueryClause } from "@molgenis/vip-report-api/src/Api";
10
+ import { Loader } from "../components/Loader";
8
11
 
9
12
  export const Samples: Component = () => {
10
- const [params, setParams] = createSignal(EMPTY_PARAMS);
11
- const [samples] = createResource(params, fetchSamples, { initialValue: EMPTY_SAMPLES_PAGE });
13
+ const [state, actions] = useStore();
12
14
  const [phenotypes] = createResource(EMPTY_PARAMS, fetchPhenotypes, { initialValue: EMPTY_PHENOTYPES });
13
15
 
14
- const onPageChange = (page: number) => setParams({ page });
15
- const onSearchChange = (search: string) =>
16
- setParams({
17
- page: 0,
18
- query: search !== "" ? { selector: ["person", "individualId"], operator: "~=", args: search } : undefined,
19
- });
16
+ function getStateSamples() {
17
+ return state.samples ? state.samples : undefined;
18
+ }
19
+
20
+ if (getStateSamples()?.page === undefined) {
21
+ actions.setSamplePage(0);
22
+ }
23
+
24
+ const onPageChange = (page: number) => actions.setSamplePage(page);
25
+ const onSearchChange = (search: string) => {
26
+ actions.setSampleSearchQuery(search);
27
+ actions.setSamplePage(0);
28
+ };
20
29
  const onProbandFilterChange = (event: CheckboxEvent) => {
21
- setParams({
22
- page: 0,
23
- query: event.checked ? { selector: ["proband"], operator: "==", args: event.checked } : undefined,
24
- });
30
+ actions.setSampleProbandFilterValue(event.checked);
31
+ actions.setSamplePage(0);
32
+ };
33
+
34
+ function createQuery(search: string | undefined, probandFilterValue: boolean | undefined): Query | null {
35
+ const searchQuery: QueryClause | undefined =
36
+ search !== undefined && search !== ""
37
+ ? { selector: ["person", "individualId"], operator: "~=", args: search }
38
+ : undefined;
39
+ const probandQuery: QueryClause | undefined =
40
+ probandFilterValue !== undefined && probandFilterValue
41
+ ? { selector: ["proband"], operator: "==", args: probandFilterValue }
42
+ : undefined;
43
+ if (searchQuery !== undefined || probandQuery != undefined) {
44
+ const args: QueryClause[] = [];
45
+ if (searchQuery !== undefined) {
46
+ args.push(searchQuery);
47
+ }
48
+ if (probandQuery !== undefined) {
49
+ args.push(probandQuery);
50
+ }
51
+ if (args.length > 0) {
52
+ const query: Query = {
53
+ operator: "and",
54
+ args: args,
55
+ };
56
+ return query;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+
62
+ const params = (): Params => {
63
+ return {
64
+ query: createQuery(searchQuery(), probandFilterValue()) || undefined,
65
+ page: page() || undefined,
66
+ };
25
67
  };
26
68
 
69
+ const page = () => getStateSamples()?.page;
70
+ const searchQuery = () => getStateSamples()?.searchQuery;
71
+ const probandFilterValue = () => getStateSamples()?.probandFilterValue;
72
+
73
+ const [samples] = createResource(params, fetchSamples);
74
+
27
75
  return (
28
76
  <>
29
77
  <Breadcrumb items={[{ text: "Samples" }]} />
30
- <div class="columns">
31
- <div class="column is-4 is-offset-3">
32
- {!samples.loading && <Pager page={samples().page} onPageChange={onPageChange} />}
33
- </div>
34
- <div class="column is-2 is-offset-1">
35
- {!samples.loading && <span class="is-pulled-right">{samples().page.totalElements} records</span>}
36
- </div>
37
- </div>
38
-
39
- <div class="columns">
40
- <div class="column is-1-fullhd is-2">
41
- <SearchBox onInput={onSearchChange} />
42
- <p class="has-text-weight-semibold">Proband</p>
43
- <div class="field">
44
- <div class="control">
45
- <Checkbox value={"proband"} label="" onChange={onProbandFilterChange} />
78
+ <Show when={samples()} fallback={<Loader />}>
79
+ {(samples) => (
80
+ <>
81
+ <div class="columns">
82
+ <div class="column is-4 is-offset-3">{<Pager page={samples.page} onPageChange={onPageChange} />}</div>
83
+ <div class="column is-2 is-offset-1">
84
+ {<span class="is-pulled-right">{samples.page.totalElements} records</span>}
85
+ </div>
86
+ </div>
87
+
88
+ <div class="columns">
89
+ <div class="column is-1-fullhd is-2">
90
+ <SearchBox onInput={onSearchChange} value={state.samples?.searchQuery} />
91
+ <p class="has-text-weight-semibold">Proband</p>
92
+ <div class="field">
93
+ <div class="control">
94
+ <Checkbox
95
+ value={"proband"}
96
+ label=""
97
+ onChange={onProbandFilterChange}
98
+ checked={state.samples?.probandFilterValue}
99
+ />
100
+ </div>
101
+ </div>
102
+ </div>
103
+ <div class="column">
104
+ <span class="is-italic">
105
+ Click on an individual id for detailed information for this sample. In this screen a link to the
106
+ variants for this sample is available.
107
+ </span>
108
+ {!phenotypes.loading && <SampleTable samples={samples.items} phenotypes={phenotypes().items} />}
109
+ </div>
46
110
  </div>
47
- </div>
48
- </div>
49
- <div class="column">
50
- {!samples.loading && !phenotypes.loading && (
51
- <SampleTable samples={samples().items} phenotypes={phenotypes().items} />
52
- )}
53
- </div>
54
- </div>
111
+ </>
112
+ )}
113
+ </Show>
55
114
  </>
56
115
  );
57
116
  };
@@ -28,6 +28,8 @@ export const VariantConsequence: Component = () => {
28
28
 
29
29
  const csqFields = (): FieldMetadata[] => recordsMetadata().info.CSQ?.nested?.items || [];
30
30
  const csqValues = (): ValueArray => getSpecificConsequence(variant().data.n.CSQ as ValueArray, consequenceId);
31
+
32
+ const hasDecisionTreePathMeta = () => csqFields().findIndex((csq) => csq.id === "VIPP") !== -1;
31
33
  return (
32
34
  <Show when={!variant.loading} fallback={<Loader />}>
33
35
  <Breadcrumb
@@ -42,17 +44,19 @@ export const VariantConsequence: Component = () => {
42
44
  <h1 class="title is-5">Consequence</h1>
43
45
  <ConsequenceTable csqMetadata={csqFields()} csqValues={csqValues()} record={variant()} />
44
46
  </div>
45
- <Show when={!recordsMetadata.loading && !decisionTree.loading && (decisionTree() as DecisionTree)}>
46
- {(decisionTree) => (
47
- <div class="column">
48
- <h1 class="title is-5">Classification tree path</h1>
49
- <DecisionTreePath
50
- decisionTree={decisionTree}
51
- path={getDecisionTreePath(recordsMetadata(), variant(), consequenceId)}
52
- />
53
- </div>
54
- )}
55
- </Show>
47
+ {hasDecisionTreePathMeta() && (
48
+ <Show when={!recordsMetadata.loading && !decisionTree.loading && (decisionTree() as DecisionTree)}>
49
+ {(decisionTree) => (
50
+ <div class="column">
51
+ <h1 class="title is-5">Classification tree path</h1>
52
+ <DecisionTreePath
53
+ decisionTree={decisionTree}
54
+ path={getDecisionTreePath(recordsMetadata(), variant(), consequenceId)}
55
+ />
56
+ </div>
57
+ )}
58
+ </Show>
59
+ )}
56
60
  </div>
57
61
  <div class="columns">
58
62
  <div class="column is-6">