@molgenis/vip-report-template 6.2.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/.nvmrc +1 -1
  2. package/.travis.yml +8 -8
  3. package/README.md +411 -1
  4. package/eslint.config.mjs +11 -0
  5. package/package.json +40 -35
  6. package/scripts/deploy_npm_registry.sh +5 -0
  7. package/src/App.tsx +30 -24
  8. package/src/assets/sass/main.scss +12 -4
  9. package/src/components/Allele.tsx +95 -0
  10. package/src/components/Anchor.tsx +1 -1
  11. package/src/components/Breadcrumb.tsx +6 -4
  12. package/src/components/DatasetDropdown.tsx +12 -25
  13. package/src/components/ErrorNotification.tsx +9 -0
  14. package/src/components/GenomeBrowser.tsx +40 -23
  15. package/src/components/HpoTerm.tsx +1 -1
  16. package/src/components/{record/Pager.tsx → Pager.tsx} +21 -14
  17. package/src/components/RecordsPerPage.tsx +9 -7
  18. package/src/components/RecordsTable.tsx +130 -0
  19. package/src/components/SampleTable.tsx +70 -98
  20. package/src/components/SearchBox.tsx +8 -2
  21. package/src/components/Sort.tsx +28 -25
  22. package/src/components/Table.tsx +16 -0
  23. package/src/components/Tooltip.tsx +20 -0
  24. package/src/components/VariantBreadcrumb.tsx +54 -0
  25. package/src/components/VariantConsequenceContainer.tsx +100 -0
  26. package/src/components/VariantConsequenceTable.tsx +58 -0
  27. package/src/components/VariantContainer.tsx +71 -0
  28. package/src/components/VariantFilters.tsx +27 -0
  29. package/src/components/VariantGenotypeTable.tsx +44 -0
  30. package/src/components/VariantInfoTable.tsx +24 -33
  31. package/src/components/VariantResults.tsx +103 -0
  32. package/src/components/VariantTable.tsx +62 -66
  33. package/src/components/VariantTypeSelect.tsx +34 -0
  34. package/src/components/VariantsContainer.tsx +150 -0
  35. package/src/components/VariantsContainerHeader.tsx +70 -0
  36. package/src/components/field/Field.tsx +80 -0
  37. package/src/components/field/FieldAlt.tsx +19 -0
  38. package/src/components/field/FieldChrom.tsx +6 -0
  39. package/src/components/{record/Id.tsx → field/FieldFilter.tsx} +2 -1
  40. package/src/components/field/FieldFormat.tsx +10 -0
  41. package/src/components/{record/Filter.tsx → field/FieldId.tsx} +1 -1
  42. package/src/components/field/FieldPos.tsx +6 -0
  43. package/src/components/field/FieldQual.tsx +6 -0
  44. package/src/components/field/FieldRef.tsx +8 -0
  45. package/src/components/field/composed/FieldClinVar.tsx +72 -0
  46. package/src/components/field/composed/FieldComposed.tsx +68 -0
  47. package/src/components/field/composed/FieldGene.tsx +39 -0
  48. package/src/components/field/composed/FieldGenotype.tsx +35 -0
  49. package/src/components/{record/format/GenotypeField.tsx → field/composed/FieldGenotypeSnvSv.tsx} +20 -16
  50. package/src/components/field/composed/FieldGenotypeStr.tsx +31 -0
  51. package/src/components/field/composed/FieldGnomAd.tsx +58 -0
  52. package/src/components/field/composed/FieldHpo.tsx +50 -0
  53. package/src/components/field/composed/FieldInheritanceModes.tsx +32 -0
  54. package/src/components/field/composed/FieldLocus.tsx +18 -0
  55. package/src/components/field/composed/FieldVipC.tsx +25 -0
  56. package/src/components/field/composed/FieldVipCS.tsx +15 -0
  57. package/src/components/field/composed/FieldVkgl.tsx +37 -0
  58. package/src/components/field/genotype/FieldGenotype.tsx +19 -0
  59. package/src/components/field/genotype/FieldGenotypeType.tsx +9 -0
  60. package/src/components/field/info/FieldConsequence.tsx +15 -0
  61. package/src/components/{record/info/Hgvs.tsx → field/info/FieldHgvs.tsx} +4 -6
  62. package/src/components/field/info/FieldInfo.tsx +27 -0
  63. package/src/components/{record/info/PubMed.tsx → field/info/FieldPubMed.tsx} +4 -7
  64. package/src/components/field/typed/FieldCategorical.tsx +17 -0
  65. package/src/components/{record/field/FieldValueCharacter.tsx → field/typed/FieldCharacter.tsx} +3 -2
  66. package/src/components/{record/field/FieldValueFlag.tsx → field/typed/FieldFlag.tsx} +3 -2
  67. package/src/components/{record/field/FieldValueFloat.tsx → field/typed/FieldFloat.tsx} +3 -2
  68. package/src/components/{record/field/FieldValueInteger.tsx → field/typed/FieldInteger.tsx} +3 -2
  69. package/src/components/{record/field/FieldValueString.tsx → field/typed/FieldString.tsx} +3 -2
  70. package/src/components/field/typed/FieldTyped.tsx +20 -0
  71. package/src/components/field/typed/FieldTypedItem.tsx +49 -0
  72. package/src/components/field/typed/FieldTypedMultiple.tsx +21 -0
  73. package/src/components/filter/Filter.tsx +56 -48
  74. package/src/components/filter/FilterWrapper.scss +23 -0
  75. package/src/components/filter/FilterWrapper.tsx +63 -0
  76. package/src/components/filter/composed/FilterAllelicImbalance.tsx +26 -0
  77. package/src/components/filter/composed/FilterComposed.tsx +92 -0
  78. package/src/components/filter/composed/FilterDeNovo.tsx +35 -0
  79. package/src/components/filter/composed/FilterHpo.tsx +16 -0
  80. package/src/components/filter/composed/FilterInheritance.tsx +42 -0
  81. package/src/components/filter/composed/FilterLocus.tsx +75 -0
  82. package/src/components/filter/composed/FilterVipC.tsx +16 -0
  83. package/src/components/filter/composed/FilterVipCS.tsx +16 -0
  84. package/src/components/filter/fixed/FilterAlt.tsx +20 -0
  85. package/src/components/filter/fixed/FilterChrom.tsx +22 -0
  86. package/src/components/filter/fixed/FilterFilter.tsx +20 -0
  87. package/src/components/filter/fixed/FilterFixed.tsx +96 -0
  88. package/src/components/filter/fixed/FilterId.tsx +20 -0
  89. package/src/components/filter/fixed/FilterPos.tsx +22 -0
  90. package/src/components/filter/fixed/FilterQual.tsx +21 -0
  91. package/src/components/filter/fixed/FilterRef.tsx +22 -0
  92. package/src/components/filter/typed/FilterCategorical.tsx +119 -0
  93. package/src/components/filter/typed/FilterFlag.tsx +23 -0
  94. package/src/components/filter/typed/FilterInterval.tsx +72 -0
  95. package/src/components/filter/typed/FilterString.tsx +43 -0
  96. package/src/components/filter/typed/FilterTyped.tsx +56 -0
  97. package/src/components/form/ButtonApply.tsx +11 -0
  98. package/src/components/form/ButtonDownload.tsx +11 -0
  99. package/src/components/form/ButtonReset.tsx +9 -0
  100. package/src/components/{Checkbox.tsx → form/Checkbox.tsx} +4 -9
  101. package/src/components/form/Input.tsx +19 -0
  102. package/src/components/form/Select.scss +7 -0
  103. package/src/components/form/Select.tsx +34 -0
  104. package/src/components/tree/DecisionTreeBoolMultiQuery.tsx +1 -1
  105. package/src/components/tree/DecisionTreeBoolQuery.tsx +1 -1
  106. package/src/components/tree/DecisionTreeNode.tsx +41 -39
  107. package/src/components/tree/DecisionTreeNodeBool.tsx +1 -1
  108. package/src/components/tree/DecisionTreeNodeBoolMulti.tsx +1 -1
  109. package/src/components/tree/DecisionTreeNodeCategorical.tsx +1 -1
  110. package/src/components/tree/DecisionTreeNodeExists.tsx +1 -1
  111. package/src/components/tree/DecisionTreeNodeLeaf.tsx +1 -1
  112. package/src/components/tree/DecisionTreeOutcomeNode.tsx +1 -1
  113. package/src/components/tree/DecisionTreePath.tsx +1 -1
  114. package/src/igv.d.ts +2 -1
  115. package/src/index.tsx +48 -19
  116. package/src/mocks/GRCh37/decisionTree.json +23 -22
  117. package/src/mocks/GRCh37/field_metadata.json +435 -95
  118. package/src/mocks/GRCh37/sampleTree.json +21 -1
  119. package/src/mocks/GRCh37/static.ts +62 -134
  120. package/src/mocks/GRCh37/vcf/family.vcf.blob +9 -3
  121. package/src/mocks/GRCh38/decisionTree.json +52 -33
  122. package/src/mocks/GRCh38/decisionTreeStr.json +572 -0
  123. package/src/mocks/GRCh38/fasta/chr1_149380406-149403321.fasta.gz.blob +0 -0
  124. package/src/mocks/GRCh38/field_metadata.json +435 -95
  125. package/src/mocks/GRCh38/sampleTree.json +175 -0
  126. package/src/mocks/GRCh38/static.ts +101 -42
  127. package/src/mocks/GRCh38/str.cram.blob +0 -0
  128. package/src/mocks/GRCh38/str.cram.crai.blob +0 -0
  129. package/src/mocks/GRCh38/vcf/family.vcf.blob +25 -24
  130. package/src/mocks/GRCh38/vcf/no_vep.vcf.blob +29 -28
  131. package/src/mocks/GRCh38/vcf/samples_0.vcf.blob +28 -27
  132. package/src/mocks/GRCh38/vcf/samples_1.vcf.blob +29 -28
  133. package/src/mocks/GRCh38/vcf/samples_100.vcf.blob +28 -27
  134. package/src/mocks/GRCh38/vcf/str.vcf.blob +321 -0
  135. package/src/mocks/MockApiClient.ts +339 -332
  136. package/src/mocks/config_cram.json +701 -0
  137. package/src/mocks/config_vcf.json +699 -0
  138. package/src/store/app.ts +30 -0
  139. package/src/store/index.tsx +3 -168
  140. package/src/store/variants.ts +182 -0
  141. package/src/types/config.d.ts +190 -0
  142. package/src/types/configCellComposed.d.ts +86 -0
  143. package/src/types/configCells.d.ts +129 -0
  144. package/src/types/configFilter.d.ts +80 -0
  145. package/src/types/configFilterComposed.d.ts +60 -0
  146. package/src/types/configSort.d.ts +13 -0
  147. package/src/types/filter.d.ts +17 -0
  148. package/src/types/store.d.ts +34 -0
  149. package/src/utils/api.ts +281 -0
  150. package/src/utils/config/config.ts +182 -0
  151. package/src/utils/config/configCells.ts +74 -0
  152. package/src/utils/config/configCellsComposed.ts +508 -0
  153. package/src/utils/config/configCellsField.ts +61 -0
  154. package/src/utils/config/configCellsFixed.ts +126 -0
  155. package/src/utils/config/configFilters.ts +46 -0
  156. package/src/utils/config/configFiltersComposed.ts +208 -0
  157. package/src/utils/config/configFiltersField.ts +49 -0
  158. package/src/utils/config/configFiltersFixed.ts +106 -0
  159. package/src/utils/config/configSorts.ts +44 -0
  160. package/src/utils/config/configValidator.ts +380 -0
  161. package/src/utils/config/configVip.ts +25 -0
  162. package/src/utils/csq.ts +115 -0
  163. package/src/utils/decisionTree.ts +45 -0
  164. package/src/utils/download.ts +30 -0
  165. package/src/utils/error.ts +69 -0
  166. package/src/utils/query/query.ts +55 -0
  167. package/src/utils/query/queryFilter.ts +132 -0
  168. package/src/utils/query/queryFilterComposed.ts +247 -0
  169. package/src/utils/query/queryFilterField.ts +75 -0
  170. package/src/utils/query/queryFilterFixed.ts +44 -0
  171. package/src/utils/query/querySample.ts +18 -0
  172. package/src/utils/query/queryVariantType.ts +76 -0
  173. package/src/utils/query/selector.ts +41 -0
  174. package/src/utils/{sortUtils.ts → query/sort.ts} +32 -11
  175. package/src/utils/sample.ts +19 -35
  176. package/src/utils/utils.ts +66 -2
  177. package/src/utils/variantType.ts +43 -0
  178. package/src/utils/vcf.ts +352 -0
  179. package/src/views/Help.tsx +109 -114
  180. package/src/views/Home.tsx +3 -2
  181. package/src/views/Sample.tsx +12 -7
  182. package/src/views/SampleVariant.tsx +23 -112
  183. package/src/views/SampleVariantConsequence.tsx +54 -144
  184. package/src/views/SampleVariants.tsx +33 -445
  185. package/src/views/SampleVariantsRedirect.tsx +20 -0
  186. package/src/views/Samples.tsx +7 -10
  187. package/src/views/Variant.tsx +31 -61
  188. package/src/views/VariantConsequence.tsx +42 -72
  189. package/src/views/Variants.tsx +29 -138
  190. package/src/views/VariantsRedirect.tsx +25 -0
  191. package/src/views/data/data.tsx +32 -6
  192. package/tests/store/variants.test.ts +122 -0
  193. package/tests/utils/config/config.test.ts +167 -0
  194. package/tests/utils/config/configCells.test.ts +86 -0
  195. package/tests/utils/config/configCellsComposed.test.ts +1163 -0
  196. package/tests/utils/config/configCellsField.test.ts +164 -0
  197. package/tests/utils/config/configCellsFixed.test.ts +99 -0
  198. package/tests/utils/config/configFilters.test.ts +80 -0
  199. package/tests/utils/config/configFiltersComposed.test.ts +504 -0
  200. package/tests/utils/config/configFiltersField.test.ts +140 -0
  201. package/tests/utils/config/configFiltersFixed.test.ts +81 -0
  202. package/tests/utils/config/configSorts.test.ts +55 -0
  203. package/tests/utils/config/configValidator.test.ts +56 -0
  204. package/tests/utils/config/configVip.test.ts +53 -0
  205. package/tests/utils/decisionTree.test.ts +71 -0
  206. package/tests/utils/download.test.ts +20 -0
  207. package/tests/utils/query/query.test.ts +84 -0
  208. package/tests/utils/query/queryFilter.test.ts +243 -0
  209. package/tests/utils/query/queryFilterComposed.test.ts +301 -0
  210. package/tests/utils/query/queryFilterField.test.ts +75 -0
  211. package/tests/utils/query/queryFilterFixed.test.ts +86 -0
  212. package/tests/utils/query/querySample.test.ts +45 -0
  213. package/tests/utils/query/queryVariantType.test.ts +56 -0
  214. package/{src/__tests__/sortUtils.test.ts → tests/utils/query/sort.test.ts} +3 -4
  215. package/tests/utils/sample.test.ts +259 -0
  216. package/tests/utils/utils.test.ts +120 -0
  217. package/tests/utils/variantType.test.ts +48 -0
  218. package/tests/utils/vcf.test.ts +649 -0
  219. package/tsconfig.json +6 -2
  220. package/vite.config.mts +20 -3
  221. package/.eslintignore +0 -4
  222. package/.eslintrc.js +0 -23
  223. package/src/Api.ts +0 -12
  224. package/src/__tests__/decisionTreeUtils.test.ts +0 -75
  225. package/src/__tests__/field.test.ts +0 -107
  226. package/src/__tests__/query.test.ts +0 -188
  227. package/src/__tests__/sample.test.ts +0 -184
  228. package/src/__tests__/utils.test.ts +0 -24
  229. package/src/__tests__/viewUtils.test.ts +0 -125
  230. package/src/components/ConsequenceTable.tsx +0 -45
  231. package/src/components/Error.tsx +0 -9
  232. package/src/components/FieldHeader.tsx +0 -26
  233. package/src/components/InfoCollapsablePane.tsx +0 -90
  234. package/src/components/VariantInfoNestedTable.tsx +0 -127
  235. package/src/components/VariantSampleTable.tsx +0 -58
  236. package/src/components/VariantsSampleTable.tsx +0 -184
  237. package/src/components/VariantsTable.tsx +0 -125
  238. package/src/components/filter/FilterAllelicBalance.tsx +0 -81
  239. package/src/components/filter/FilterCategorical.tsx +0 -81
  240. package/src/components/filter/FilterClinVar.tsx +0 -21
  241. package/src/components/filter/FilterGene.tsx +0 -34
  242. package/src/components/filter/FilterHpo.tsx +0 -161
  243. package/src/components/filter/FilterInheritance.tsx +0 -162
  244. package/src/components/filter/FilterIntegerGq.tsx +0 -47
  245. package/src/components/filter/FilterVI.tsx +0 -68
  246. package/src/components/filter/FilterVariantType.tsx +0 -146
  247. package/src/components/filter/Filters.tsx +0 -29
  248. package/src/components/filter/InfoFilter.tsx +0 -39
  249. package/src/components/filter/InfoFilters.tsx +0 -35
  250. package/src/components/filter/SampleFilters.tsx +0 -93
  251. package/src/components/filter/SamplesFilters.tsx +0 -33
  252. package/src/components/record/Allele.tsx +0 -38
  253. package/src/components/record/AlleleBreakend.tsx +0 -5
  254. package/src/components/record/AlleleMissing.tsx +0 -5
  255. package/src/components/record/AlleleNucs.tsx +0 -49
  256. package/src/components/record/AlleleSymbolic.tsx +0 -5
  257. package/src/components/record/Alt.tsx +0 -17
  258. package/src/components/record/Chrom.tsx +0 -5
  259. package/src/components/record/Format.tsx +0 -40
  260. package/src/components/record/Info.tsx +0 -55
  261. package/src/components/record/Pos.tsx +0 -5
  262. package/src/components/record/Qual.tsx +0 -5
  263. package/src/components/record/RecordDownload.tsx +0 -66
  264. package/src/components/record/Ref.tsx +0 -6
  265. package/src/components/record/field/Field.tsx +0 -36
  266. package/src/components/record/field/FieldMultipleValue.tsx +0 -22
  267. package/src/components/record/field/FieldSingleValue.tsx +0 -35
  268. package/src/components/record/info/ClinVar.tsx +0 -81
  269. package/src/components/record/info/Consequence.tsx +0 -18
  270. package/src/components/record/info/Gene.tsx +0 -56
  271. package/src/components/record/info/GnomAD.tsx +0 -54
  272. package/src/components/record/info/Hpo.tsx +0 -52
  273. package/src/components/record/info/InheritanceModes.tsx +0 -22
  274. package/src/components/record/info/VipC.tsx +0 -23
  275. package/src/components/record/info/Vkgl.tsx +0 -42
  276. package/src/mocks/GRCh37/vcf/no_vep.vcf.blob +0 -61
  277. package/src/mocks/GRCh37/vcf/samples_0.vcf.blob +0 -93
  278. package/src/mocks/GRCh37/vcf/samples_1.vcf.blob +0 -93
  279. package/src/mocks/GRCh37/vcf/samples_100.vcf.blob +0 -93
  280. package/src/utils/ApiUtils.ts +0 -263
  281. package/src/utils/csqUtils.ts +0 -27
  282. package/src/utils/decisionTreeUtils.ts +0 -31
  283. package/src/utils/field.ts +0 -49
  284. package/src/utils/query.ts +0 -154
  285. package/src/utils/viewUtils.ts +0 -32
@@ -0,0 +1,56 @@
1
+ import { Component, Match, Switch } from "solid-js";
2
+ import { FilterCategorical } from "./FilterCategorical";
3
+ import { FilterString } from "./FilterString";
4
+ import { FilterInterval } from "./FilterInterval";
5
+ import {
6
+ ConfigFilterField,
7
+ FilterValueCategorical,
8
+ FilterValueField,
9
+ FilterValueFlag,
10
+ FilterValueInterval,
11
+ FilterValueString,
12
+ } from "../../../types/configFilter";
13
+ import { ErrorNotification } from "../../ErrorNotification";
14
+ import { FilterFlag } from "./FilterFlag";
15
+ import { FilterProps } from "../Filter.tsx";
16
+
17
+ export const FilterTyped: Component<FilterProps<ConfigFilterField, FilterValueField>> = (props) => {
18
+ const type = () => props.config.field.type;
19
+
20
+ return (
21
+ <Switch fallback={<ErrorNotification error={`unexpected field type ${type()}`} />}>
22
+ <Match when={type() === "CATEGORICAL"}>
23
+ <FilterCategorical
24
+ config={props.config}
25
+ value={props.value as FilterValueCategorical}
26
+ onValueChange={props.onValueChange}
27
+ onValueClear={props.onValueClear}
28
+ />
29
+ </Match>
30
+ <Match when={type() === "CHARACTER" || type() === "STRING"}>
31
+ <FilterString
32
+ config={props.config}
33
+ value={props.value as FilterValueString}
34
+ onValueChange={props.onValueChange}
35
+ onValueClear={props.onValueClear}
36
+ />
37
+ </Match>
38
+ <Match when={type() === "INTEGER" || type() === "FLOAT"}>
39
+ <FilterInterval
40
+ config={props.config}
41
+ value={props.value as FilterValueInterval}
42
+ onValueChange={props.onValueChange}
43
+ onValueClear={props.onValueClear}
44
+ />
45
+ </Match>
46
+ <Match when={type() === "FLAG"}>
47
+ <FilterFlag
48
+ config={props.config}
49
+ value={props.value as FilterValueFlag}
50
+ onValueChange={props.onValueChange}
51
+ onValueClear={props.onValueClear}
52
+ />
53
+ </Match>
54
+ </Switch>
55
+ );
56
+ };
@@ -0,0 +1,11 @@
1
+ import { Component } from "solid-js";
2
+
3
+ export const ButtonApply: Component<{ onClick: () => void }> = (props) => {
4
+ return (
5
+ <button class="button is-small is-info" onClick={() => props.onClick()}>
6
+ <span class="icon">
7
+ <i class="fas fa-angle-right" />
8
+ </span>
9
+ </button>
10
+ );
11
+ };
@@ -0,0 +1,11 @@
1
+ import { Component } from "solid-js";
2
+
3
+ export const ButtonDownload: Component<{ title: string; onClick: () => void }> = (props) => {
4
+ return (
5
+ <button class="button is-info" onClick={() => props.onClick()} title={props.title}>
6
+ <span class="icon is-small">
7
+ <i class="fas fa-download" />
8
+ </span>
9
+ </button>
10
+ );
11
+ };
@@ -0,0 +1,9 @@
1
+ import { Component } from "solid-js";
2
+
3
+ export const ButtonReset: Component<{ onClick: () => void }> = (props) => {
4
+ return (
5
+ <button class="button is-small is-ghost" onClick={() => props.onClick()}>
6
+ Reset
7
+ </button>
8
+ );
9
+ };
@@ -1,15 +1,12 @@
1
- import { Component, Show } from "solid-js";
2
- import { Abbr } from "./Abbr";
1
+ import { ParentComponent } from "solid-js";
3
2
 
4
3
  export type CheckboxEvent = {
5
4
  value: string;
6
5
  checked: boolean;
7
6
  };
8
7
 
9
- export const Checkbox: Component<{
10
- value?: string;
11
- label: string;
12
- desc?: string;
8
+ export const Checkbox: ParentComponent<{
9
+ value: string;
13
10
  checked?: boolean;
14
11
  onChange: (event: CheckboxEvent) => void;
15
12
  }> = (props) => {
@@ -24,9 +21,7 @@ export const Checkbox: Component<{
24
21
  return (
25
22
  <label class="checkbox">
26
23
  <input class="mr-1" type="checkbox" value={props.value} checked={props.checked} onChange={onChange} />
27
- <Show when={props.desc !== undefined} fallback={<span>{props.label}</span>}>
28
- <Abbr title={props.desc as string} value={props.label} />
29
- </Show>
24
+ {props.children}
30
25
  </label>
31
26
  );
32
27
  };
@@ -0,0 +1,19 @@
1
+ import { Component } from "solid-js";
2
+
3
+ export type InputValue = string;
4
+ export type InputChangeEvent = { value: InputValue };
5
+ export type InputChangeCallback = (event: InputChangeEvent) => void;
6
+ export type InputProps = { placeholder?: string; value?: InputValue; onValueChange: InputChangeCallback };
7
+
8
+ export const Input: Component<InputProps> = (props) => {
9
+ // do not use 'value={props.value}' because 'value=undefined' will display the value 'undefined' in the input
10
+ return (
11
+ <input
12
+ class="input is-small"
13
+ type="text"
14
+ {...(props.value ? { value: props.value } : {})}
15
+ placeholder={props.placeholder}
16
+ onInput={(event) => props.onValueChange({ value: (event.target as HTMLInputElement).value })}
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,7 @@
1
+ /* from https://stackoverflow.com/a/29806043 */
2
+ select:required:invalid {
3
+ color: var(--bulma-input-placeholder-color)
4
+ }
5
+ option {
6
+ color: black;
7
+ }
@@ -0,0 +1,34 @@
1
+ import "./Select.scss";
2
+ import { Component, For, Show } from "solid-js";
3
+
4
+ export type SelectOption = { id: string; label: string };
5
+ export type SelectValue = string;
6
+ export type SelectChangeEvent = { value: SelectValue };
7
+ export type SelectChangeCallback = (event: SelectChangeEvent) => void;
8
+ export type SelectProps = {
9
+ placeholder?: string;
10
+ options: SelectOption[];
11
+ value?: SelectValue;
12
+ onValueChange: SelectChangeCallback;
13
+ };
14
+
15
+ export const Select: Component<SelectProps> = (props) => {
16
+ return (
17
+ <div class="select is-small is-fullwidth">
18
+ <select required onChange={(e) => props.onValueChange({ value: (e.target as HTMLSelectElement).value })}>
19
+ <Show when={props.placeholder}>
20
+ <option value="" selected={props.value === undefined}>
21
+ {props.placeholder}
22
+ </option>
23
+ </Show>
24
+ <For each={props.options}>
25
+ {(option) => (
26
+ <option value={option.id} selected={option.id === props.value}>
27
+ {option.label}
28
+ </option>
29
+ )}
30
+ </For>
31
+ </select>
32
+ </div>
33
+ );
34
+ };
@@ -1,5 +1,5 @@
1
1
  import { Component, For } from "solid-js";
2
- import { BoolMultiQuery } from "@molgenis/vip-report-api/src/Api";
2
+ import { BoolMultiQuery } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeBoolQuery } from "./DecisionTreeBoolQuery";
4
4
  import { DecisionTreeOutcomeNode } from "./DecisionTreeOutcomeNode";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Component, createMemo } from "solid-js";
2
- import { BoolQuery } from "@molgenis/vip-report-api/src/Api";
2
+ import { BoolQuery } from "@molgenis/vip-report-api";
3
3
  import { Abbr } from "../Abbr";
4
4
 
5
5
  export const DecisionTreeBoolQuery: Component<{ query: BoolQuery }> = (props) => {
@@ -1,13 +1,13 @@
1
1
  import { Component, createSignal, Match, Show, Signal, Switch } from "solid-js";
2
- import { BoolMultiNode, BoolNode, CategoricalNode, ExistsNode, LeafNode, Node } from "@molgenis/vip-report-api/src/Api";
3
- import { Error } from "../Error";
2
+ import { BoolMultiNode, BoolNode, CategoricalNode, ExistsNode, LeafNode, Node } from "@molgenis/vip-report-api";
3
+ import { ErrorNotification } from "../ErrorNotification";
4
4
  import { DecisionTreeNodeBool } from "./DecisionTreeNodeBool";
5
5
  import { DecisionTreeNodeBoolMulti } from "./DecisionTreeNodeBoolMulti";
6
6
  import { DecisionTreeNodeCategorical } from "./DecisionTreeNodeCategorical";
7
7
  import { DecisionTreeNodeExists } from "./DecisionTreeNodeExists";
8
8
  import { DecisionTreeNodeLeaf } from "./DecisionTreeNodeLeaf";
9
9
 
10
- export const DecisionTreeNode: Component<{ nodeId: string; node: Node }> = (props) => {
10
+ export const DecisionTreeNode: Component<{ nodeId: string; node: Node | undefined }> = (props) => {
11
11
  const [collapsed, setCollapsed]: Signal<boolean> = createSignal(true);
12
12
 
13
13
  function toggleCollapse() {
@@ -16,49 +16,51 @@ export const DecisionTreeNode: Component<{ nodeId: string; node: Node }> = (prop
16
16
 
17
17
  return (
18
18
  <Show
19
- when={props.node !== undefined}
19
+ when={props.node}
20
20
  fallback={
21
21
  <div class="notification is-danger is-light">
22
22
  Error: Unknown node "{props.nodeId}". (Possible mismatch between VCF file and provided decision tree.)
23
23
  </div>
24
24
  }
25
25
  >
26
- <div classList={{ card: true, "has-background-success": props.node.type === "LEAF" }}>
27
- <header class="card-header">
28
- <p class="card-header-title">
29
- <span>{props.nodeId}</span>
30
- {props.node.description && <span class="ml-1">({props.node.description})</span>}
31
- </p>
32
- <button class="card-header-icon" aria-label="more options" onClick={toggleCollapse}>
33
- <span class="icon">
34
- <i classList={{ fas: true, "fa-angle-down": collapsed(), "fa-angle-up": !collapsed() }} />
35
- </span>
36
- </button>
37
- </header>
38
- {!collapsed() && (
39
- <div class="card-content">
40
- <div class="content">
41
- <Switch fallback={<Error error={`invalid node type ${props.node.type}`} />}>
42
- <Match when={props.node.type === "BOOL"}>
43
- <DecisionTreeNodeBool node={props.node as BoolNode} />
44
- </Match>
45
- <Match when={props.node.type === "BOOL_MULTI"}>
46
- <DecisionTreeNodeBoolMulti node={props.node as BoolMultiNode} />
47
- </Match>
48
- <Match when={props.node.type === "CATEGORICAL"}>
49
- <DecisionTreeNodeCategorical node={props.node as CategoricalNode} />
50
- </Match>
51
- <Match when={props.node.type === "EXISTS"}>
52
- <DecisionTreeNodeExists node={props.node as ExistsNode} />
53
- </Match>
54
- <Match when={props.node.type === "LEAF"}>
55
- <DecisionTreeNodeLeaf node={props.node as LeafNode} />
56
- </Match>
57
- </Switch>
26
+ {(node) => (
27
+ <div classList={{ card: true, "has-background-success": node().type === "LEAF" }}>
28
+ <header class="card-header">
29
+ <p class="card-header-title">
30
+ <span>{node().label}</span>
31
+ {node().description && <span class="ml-1">({node().description})</span>}
32
+ </p>
33
+ <button class="card-header-icon" aria-label="more options" onClick={toggleCollapse}>
34
+ <span class="icon">
35
+ <i classList={{ fas: true, "fa-angle-down": collapsed(), "fa-angle-up": !collapsed() }} />
36
+ </span>
37
+ </button>
38
+ </header>
39
+ {!collapsed() && (
40
+ <div class="card-content">
41
+ <div class="content">
42
+ <Switch fallback={<ErrorNotification error={`invalid node type ${node().type}`} />}>
43
+ <Match when={node().type === "BOOL"}>
44
+ <DecisionTreeNodeBool node={node() as BoolNode} />
45
+ </Match>
46
+ <Match when={node().type === "BOOL_MULTI"}>
47
+ <DecisionTreeNodeBoolMulti node={node() as BoolMultiNode} />
48
+ </Match>
49
+ <Match when={node().type === "CATEGORICAL"}>
50
+ <DecisionTreeNodeCategorical node={node() as CategoricalNode} />
51
+ </Match>
52
+ <Match when={node().type === "EXISTS"}>
53
+ <DecisionTreeNodeExists node={node() as ExistsNode} />
54
+ </Match>
55
+ <Match when={node().type === "LEAF"}>
56
+ <DecisionTreeNodeLeaf node={node() as LeafNode} />
57
+ </Match>
58
+ </Switch>
59
+ </div>
58
60
  </div>
59
- </div>
60
- )}
61
- </div>
61
+ )}
62
+ </div>
63
+ )}
62
64
  </Show>
63
65
  );
64
66
  };
@@ -1,5 +1,5 @@
1
1
  import { Component } from "solid-js";
2
- import { BoolNode } from "@molgenis/vip-report-api/src/Api";
2
+ import { BoolNode } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeOutcomeNode } from "./DecisionTreeOutcomeNode";
4
4
  import { DecisionTreeBoolQuery } from "./DecisionTreeBoolQuery";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Component, For } from "solid-js";
2
- import { BoolMultiNode } from "@molgenis/vip-report-api/src/Api";
2
+ import { BoolMultiNode } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeBoolMultiQuery } from "./DecisionTreeBoolMultiQuery";
4
4
  import { DecisionTreeOutcomeNode } from "./DecisionTreeOutcomeNode";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Component, For } from "solid-js";
2
- import { CategoricalNode } from "@molgenis/vip-report-api/src/Api";
2
+ import { CategoricalNode } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeOutcomeNode } from "./DecisionTreeOutcomeNode";
4
4
 
5
5
  export const DecisionTreeNodeCategorical: Component<{ node: CategoricalNode }> = (props) => {
@@ -1,5 +1,5 @@
1
1
  import { Component } from "solid-js";
2
- import { ExistsNode } from "@molgenis/vip-report-api/src/Api";
2
+ import { ExistsNode } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeOutcomeNode } from "./DecisionTreeOutcomeNode";
4
4
 
5
5
  export const DecisionTreeNodeExists: Component<{ node: ExistsNode }> = (props) => {
@@ -1,5 +1,5 @@
1
1
  import { Component } from "solid-js";
2
- import { LeafNode } from "@molgenis/vip-report-api/src/Api";
2
+ import { LeafNode } from "@molgenis/vip-report-api";
3
3
 
4
4
  export const DecisionTreeNodeLeaf: Component<{ node: LeafNode }> = (props) => {
5
5
  return <span>classification: {props.node.class}</span>;
@@ -1,5 +1,5 @@
1
1
  import { Component } from "solid-js";
2
- import { NodeOutcome } from "@molgenis/vip-report-api/src/Api";
2
+ import { NodeOutcome } from "@molgenis/vip-report-api";
3
3
 
4
4
  export const DecisionTreeOutcomeNode: Component<{ node: NodeOutcome }> = (props) => {
5
5
  return (
@@ -1,5 +1,5 @@
1
1
  import { Component, For } from "solid-js";
2
- import { DecisionTree } from "@molgenis/vip-report-api/src/Api";
2
+ import { DecisionTree } from "@molgenis/vip-report-api";
3
3
  import { DecisionTreeNode } from "./DecisionTreeNode";
4
4
 
5
5
  export type DecisionTreePath = string[];
package/src/igv.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  declare module "igv" {
2
2
  export class Browser {
3
3
  loadTrack(config: unknown): Promise<unknown>;
4
+ removeAllTracks(): void;
5
+ root: HTMLDivElement;
4
6
  }
5
7
 
6
8
  export function createBrowser(div: HTMLDivElement, config: unknown): Promise<Browser>;
7
- export function removeBrowser(browser: Browser): void;
8
9
  }
package/src/index.tsx CHANGED
@@ -7,33 +7,38 @@ import App from "./App";
7
7
  import { dom, library } from "@fortawesome/fontawesome-svg-core";
8
8
  import {
9
9
  faAngleDown,
10
+ faAngleRight,
10
11
  faAngleUp,
11
12
  faCircleExclamation,
12
- faCircleXmark,
13
13
  faCircleInfo,
14
14
  faCircleQuestion,
15
+ faCircleXmark,
15
16
  faDownload,
16
17
  faExternalLink,
17
18
  faHome,
19
+ faInfo,
18
20
  faSearch,
19
21
  } from "@fortawesome/free-solid-svg-icons";
20
22
  import { Provider } from "./store";
21
- import { ErrorBoundary } from "solid-js";
22
- import { Error } from "./components/Error";
23
+ import { createSignal, ErrorBoundary, Show } from "solid-js";
23
24
  import { HashRouter, Route } from "@solidjs/router";
24
25
  import { Home } from "./views/Home";
25
26
  import { Samples } from "./views/Samples";
26
27
  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";
28
+ import { SampleVariant } from "./views/SampleVariant";
29
+ import { SampleVariantConsequence } from "./views/SampleVariantConsequence";
30
+ import { VariantsRedirect } from "./views/VariantsRedirect.tsx";
31
31
  import { Variant } from "./views/Variant";
32
32
  import { VariantConsequence } from "./views/VariantConsequence";
33
33
  import { Help } from "./views/Help";
34
+ import { SampleVariants } from "./views/SampleVariants.tsx";
35
+ import { SampleVariantsRedirect } from "./views/SampleVariantsRedirect.tsx";
36
+ import { Variants } from "./views/Variants.tsx";
37
+ import { ErrorNotification } from "./components/ErrorNotification.tsx";
34
38
 
35
39
  library.add(
36
40
  faAngleDown,
41
+ faAngleRight,
37
42
  faAngleUp,
38
43
  faCircleExclamation,
39
44
  faCircleXmark,
@@ -42,6 +47,7 @@ library.add(
42
47
  faDownload,
43
48
  faExternalLink,
44
49
  faHome,
50
+ faInfo,
45
51
  faSearch,
46
52
  );
47
53
 
@@ -50,16 +56,29 @@ function processIcons() {
50
56
  dom.watch();
51
57
  }
52
58
 
53
- if (document.readyState === "complete") {
59
+ // process icons if document state is "complete" or "interactive", list for event if "loading"
60
+ if (document.readyState !== "loading") {
54
61
  processIcons();
55
62
  } else {
56
63
  window.addEventListener("DOMContentLoaded", processIcons);
57
64
  }
58
65
 
66
+ const [error, setError] = createSignal<unknown>();
67
+ window.addEventListener("error", function () {
68
+ setError({ message: "An unexpected error occurred" });
69
+ });
70
+
71
+ window.addEventListener("unhandledrejection", function () {
72
+ setError({ message: "An unexpected error occurred" });
73
+ });
74
+
59
75
  render(
60
76
  () => (
61
77
  <Provider>
62
- <ErrorBoundary fallback={(err) => <Error error={err as unknown} />}>
78
+ <Show when={error() !== undefined}>
79
+ <ErrorNotification error={error()} />
80
+ </Show>
81
+ <ErrorBoundary fallback={(err) => <ErrorNotification error={err} />}>
63
82
  <HashRouter root={App}>
64
83
  <Route path="/" component={Home} />
65
84
  <Route path="/samples">
@@ -67,22 +86,32 @@ render(
67
86
  <Route path="/:sampleId">
68
87
  <Route path="/" component={Sample} />
69
88
  <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} />
89
+ <Route path="/" component={SampleVariantsRedirect} />
90
+ <Route path="/:variantType">
91
+ <Route path="/" component={SampleVariants} />
92
+ <Route path="/variant">
93
+ <Route path="/:variantId">
94
+ <Route path="/" component={SampleVariant} />
95
+ <Route path="/consequences">
96
+ <Route path="/:consequenceId" component={SampleVariantConsequence} />
97
+ </Route>
98
+ </Route>
75
99
  </Route>
76
100
  </Route>
77
101
  </Route>
78
102
  </Route>
79
103
  </Route>
80
104
  <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} />
105
+ <Route path="/" component={VariantsRedirect} />
106
+ <Route path="/:variantType">
107
+ <Route path="/" component={Variants} />
108
+ <Route path="/variant">
109
+ <Route path="/:variantId">
110
+ <Route path="/" component={Variant} />
111
+ <Route path="/consequences">
112
+ <Route path="/:consequenceId" component={VariantConsequence} />
113
+ </Route>
114
+ </Route>
86
115
  </Route>
87
116
  </Route>
88
117
  </Route>