diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..b762d8318 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "varfish/vueapp/ext/reev-frontend-lib"] + path = varfish/vueapp/ext/reev-frontend-lib + url = https://github.com/bihealth/reev-frontend-lib.git diff --git a/cases/templates/cases/entrypoint.html b/cases/templates/cases/entrypoint.html index 9449c2e14..06de5b276 100644 --- a/cases/templates/cases/entrypoint.html +++ b/cases/templates/cases/entrypoint.html @@ -12,6 +12,6 @@
- {% vite_scripts 'src/cases/main.js' %} - {% vite_styles 'src/cases/main.js' %} + {% vite_scripts 'src/cases/main.ts' %} + {% vite_styles 'src/cases/main.ts' %} {% endblock %} diff --git a/cases/vueapp/src/main.ts b/cases/vueapp/src/main.ts new file mode 100644 index 000000000..835f67695 --- /dev/null +++ b/cases/vueapp/src/main.ts @@ -0,0 +1,22 @@ +import App from '@cases/App.vue' +import { createApp, nextTick } from 'vue' +import { registerPlugins } from './plugins' + +declare global { + interface Window { + _paq: any[] + } +} + +async function bootstrap() { + const app = createApp(App) + + await registerPlugins(app) + + app.mount('#app') + + await nextTick() + window._paq?.push(['trackPageView']) +} + +bootstrap() diff --git a/cases/vueapp/src/plugins/index.ts b/cases/vueapp/src/plugins/index.ts new file mode 100644 index 000000000..f682b6b79 --- /dev/null +++ b/cases/vueapp/src/plugins/index.ts @@ -0,0 +1,11 @@ +import type { App } from 'vue' + +import { router } from '../router' +import { vuetify } from './vuetify' +import { pinia } from '../stores' +import { setupBackendUrls } from './reevFrontend' + +export async function registerPlugins(app: App) { + setupBackendUrls() + app.use(vuetify).use(router).use(pinia) +} diff --git a/cases/vueapp/src/plugins/reevFrontend.ts b/cases/vueapp/src/plugins/reevFrontend.ts new file mode 100644 index 000000000..59ac72abb --- /dev/null +++ b/cases/vueapp/src/plugins/reevFrontend.ts @@ -0,0 +1,14 @@ +import { urlConfig } from '@bihealth/reev-frontend-lib/lib/urlConfig' + +export function setupBackendUrls() { + urlConfig.baseUrlAnnonars = '/proxy/varfish/annonars' + urlConfig.baseUrlMehari = '/proxy/varfish/mehari' + urlConfig.baseUrlViguno = '/proxy/varfish/viguno' + urlConfig.baseUrlNginx = '/proxy/varfish/nginx' + urlConfig.baseUrlPubtator = '/proxy/remote/pubtator3-api' + + // urlConfig.baseUrlCadaPrio = '/internal/proxy/cada-prio' + // urlConfig.baseUrlDotty = '/internal/proxy/dotty' + // urlConfig.baseUrlVariantValidator = '/remote/variantvalidator' + // urlConfig.baseUrlPubtator = '/remote/pubtator3-api' +} diff --git a/cases/vueapp/src/plugins/vuetify.ts b/cases/vueapp/src/plugins/vuetify.ts new file mode 100644 index 000000000..8ea383055 --- /dev/null +++ b/cases/vueapp/src/plugins/vuetify.ts @@ -0,0 +1,61 @@ +/** + * plugins/vuetify.ts + * + * Framework documentation: https://vuetifyjs.com` + */ +// Styles +import '@mdi/font/css/materialdesignicons.css' +// Composables +import { type ThemeDefinition, createVuetify } from 'vuetify' +import { aliases, mdi } from 'vuetify/iconsets/mdi' +import { md3 } from 'vuetify/blueprints' +import * as components from 'vuetify/components' +import * as directives from 'vuetify/directives' +import '../styles/main.scss' + +const customLightTheme: ThemeDefinition = { + dark: false, + colors: { + primary: '#757ce8', + secondary: '#3f50b5', + tertiary: '#002884', + background: '#eeeeee', + success: '#4caf50', + warning: '#ff9800', + error: '#f44336', + info: '#f0f2f5', + }, +} + +// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides +export const vuetify = createVuetify({ + blueprint: md3, + components: { + ...components, + }, + icons: { + defaultSet: 'mdi', + aliases, + sets: { + mdi, + }, + }, + directives, + defaults: { + global: { + flat: true, + }, + VCard: { + rounded: 'lg', + }, + VSheet: { + rounded: 'lg', + }, + }, + theme: { + defaultTheme: 'customLightTheme', + themes: { + customLightTheme, + }, + }, +}) diff --git a/cases/vueapp/src/main.js b/cases/vueapp/src/router/index.ts similarity index 93% rename from cases/vueapp/src/main.js rename to cases/vueapp/src/router/index.ts index 96352d3b6..211dae3f8 100644 --- a/cases/vueapp/src/main.js +++ b/cases/vueapp/src/router/index.ts @@ -1,4 +1,3 @@ -import App from '@cases/App.vue' import CaseDetailApp from '@cases/components/CaseDetailApp.vue' import CaseListApp from '@cases/components/CaseListApp.vue' import SvDetails from '@svs/components/SvDetails.vue' @@ -6,8 +5,6 @@ import SvFilterApp from '@svs/components/SvFilterApp.vue' import { useHistoryStore } from '@varfish/stores/history' import FilterApp from '@variants/components/FilterApp.vue' import VariantDetails from '@variants/components/VariantDetails.vue' -import { createPinia } from 'pinia' -import { createApp } from 'vue' import { createRouter, createWebHashHistory } from 'vue-router' const routes = [ @@ -117,7 +114,7 @@ const routes = [ }, ] -const router = createRouter({ +export const router = createRouter({ history: createWebHashHistory(), routes, scrollBehavior(to, from, savedPosition) { @@ -134,12 +131,6 @@ const router = createRouter({ }, }) -const pinia = createPinia() -const app = createApp(App) -app.use(router) -app.use(pinia) -app.mount('#app') - router.beforeEach((_to, from) => { // Push history element, initial will be swallowed by store. const historyStore = useHistoryStore() diff --git a/cases/vueapp/src/stores/index.ts b/cases/vueapp/src/stores/index.ts new file mode 100644 index 000000000..72afdebc9 --- /dev/null +++ b/cases/vueapp/src/stores/index.ts @@ -0,0 +1,4 @@ +// Utilities +import { createPinia } from 'pinia' + +export const pinia = createPinia() diff --git a/cases/vueapp/src/styles/main.scss b/cases/vueapp/src/styles/main.scss new file mode 100644 index 000000000..8110ca3be --- /dev/null +++ b/cases/vueapp/src/styles/main.scss @@ -0,0 +1,22 @@ +@use 'vuetify' with ( + $utilities: ( + margin: false, + margin-x: false, + margin-y: false, + margin-top: false, + margin-bottom: false, + margin-left: false, + margin-right: false, + margin-start: false, + margin-end: false, + negative-margin: false, + negative-margin-x: false, + negative-margin-y: false, + negative-margin-top: false, + negative-margin-bottom: false, + negative-margin-left: false, + negative-margin-right: false, + negative-margin-start: false, + negative-margin-end: false, + ) +); diff --git a/config/urls.py b/config/urls.py index 89b5c96c2..6fe0711ec 100644 --- a/config/urls.py +++ b/config/urls.py @@ -121,6 +121,14 @@ def handler500(request, *args, **argv): ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), + # Augment url patterns with proxy for PubTator3 + url( + r"^proxy/remote/pubtator3-api/(?P.*)$", + HttpProxy.as_view( + base_url="https://www.ncbi.nlm.nih.gov/research/pubtator3-api/", + ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], + ), + ), url( r"^proxy/varfish/viguno/(?P.*)$", HttpProxy.as_view( diff --git a/materialdesignicons-webfont.woff2 b/materialdesignicons-webfont.woff2 new file mode 100644 index 000000000..8c69b85f6 Binary files /dev/null and b/materialdesignicons-webfont.woff2 differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..db171856f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./varfish/vueapp/tsconfig.json" +} diff --git a/varfish/vueapp/ext/reev-frontend-lib b/varfish/vueapp/ext/reev-frontend-lib new file mode 160000 index 000000000..0a9899742 --- /dev/null +++ b/varfish/vueapp/ext/reev-frontend-lib @@ -0,0 +1 @@ +Subproject commit 0a9899742e21cca45565107f3937593f34aaea92 diff --git a/varfish/vueapp/jsconfig.json b/varfish/vueapp/jsconfig.json index 4c0d8ff4a..c5d59ce29 100644 --- a/varfish/vueapp/jsconfig.json +++ b/varfish/vueapp/jsconfig.json @@ -10,7 +10,8 @@ "@svs/*": ["./src/svs/*"], "@cases/*": ["./src/cases/*"], "@cases_qc/*": ["./src/cases_qc/*"], - "@cohorts/*": ["./src/cohorts/*"] + "@cohorts/*": ["./src/cohorts/*"], + "@bihealth/reev-frontend-lib/*": ["./src/reev-frontend-lib/src/*"] } } } diff --git a/varfish/vueapp/package-lock.json b/varfish/vueapp/package-lock.json index 86ea16c46..168268b91 100644 --- a/varfish/vueapp/package-lock.json +++ b/varfish/vueapp/package-lock.json @@ -8,20 +8,26 @@ "name": "varfish-server", "version": "2.0.0", "dependencies": { + "@mdi/font": "^7.4.47", + "@protobuf-ts/runtime": "^2.9.3", "@reactgular/chunks": "^1.0.1", + "@types/luxon": "^3.4.2", "@vueform/multiselect": "^2.6.2", "@vuelidate/core": "^2.0.3", "@vuelidate/validators": "^2.0.4", "ag-grid-vue3": "^30.1.0", "camelcase": "^8.0.0", "core-js": "^3.32.2", + "fast-deep-equal": "^3.1.3", "igv": "^2.15.11", "javascript-time-ago": "^2.5.9", "lodash.debounce": "^4.0.8", "lodash.isequal": "^4.5.0", + "luxon": "^3.4.4", "pinia": "^2.1.6", "snakecase": "^1.0.0", "sort-by-typescript": "^1.2.5", + "title-case": "^4.3.1", "vega": "^5.25.0", "vega-embed": "^6.22.2", "vega-lite": "^5.15.0", @@ -29,6 +35,7 @@ "vue-draggable-next": "^2.2.1", "vue-router": "^4.2.5", "vue3-easy-data-table": "^1.5.47", + "vuetify": "^3.5.3", "yarn": "^1.22.19" }, "devDependencies": { @@ -81,8 +88,10 @@ "prettier": "3.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", + "sass": "^1.70.0", "storybook": "^7.6.10", "storybook-addon-fetch-mock": "^1.0.1", + "unplugin-fonts": "^1.1.1", "unplugin-icons": "^0.18.3", "unplugin-vue-components": "^0.26.0", "vite": "^4.5.2", @@ -3314,6 +3323,11 @@ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", "dev": true }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==" + }, "node_modules/@mdx-js/react": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", @@ -3748,6 +3762,11 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@protobuf-ts/runtime": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.9.3.tgz", + "integrity": "sha512-nivzCpg/qYD0RX2OmHOahJALb8ndjGmUhNBcTJ0BbXoqKwCSM6vYA+vegzS3rhuaPgbyC7Ec8idlnizzUfIRuw==" + }, "node_modules/@radix-ui/number": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", @@ -6906,6 +6925,11 @@ "integrity": "sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==", "dev": true }, + "node_modules/@types/luxon": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==" + }, "node_modules/@types/mdx": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.7.tgz", @@ -12056,8 +12080,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -13347,6 +13370,12 @@ "resolved": "https://registry.npmjs.org/igv/-/igv-2.15.11.tgz", "integrity": "sha512-oJs6z4ogv1GefIWaMdG5s4jFRuFQ/PjUgrGBMn12SbeeIC/VgHkHr56K5yIaC8ZSyameq/7IFDQaXu0qIu6cpA==" }, + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -15173,6 +15202,14 @@ "yallist": "^3.0.2" } }, + "node_modules/luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", + "engines": { + "node": ">=12" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", @@ -19254,6 +19291,23 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/sass": { + "version": "1.70.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", + "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -20610,6 +20664,11 @@ "node": ">=14.0.0" } }, + "node_modules/title-case": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/title-case/-/title-case-4.3.1.tgz", + "integrity": "sha512-VnPxQ+/j0X2FZ4ceGq1oLruTLjtN5Ul4sam5ypd4mDZLm1eHwkwip1gLxqhON/j4qyTlUlfPKslE/t4NPSlxhg==" + }, "node_modules/titleize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", @@ -21101,6 +21160,25 @@ "webpack-virtual-modules": "^0.6.1" } }, + "node_modules/unplugin-fonts": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unplugin-fonts/-/unplugin-fonts-1.1.1.tgz", + "integrity": "sha512-/Aw/rL9D2aslGGM0vi+2R2aG508RSwawLnnBuo+JDSqYc4cHJO1R1phllhN6GysEhBp/6a4B6+vSFPVapWyAAw==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.12", + "unplugin": "^1.3.1" + }, + "peerDependencies": { + "@nuxt/kit": "^3.0.0", + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, "node_modules/unplugin-icons": { "version": "0.18.3", "resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-0.18.3.tgz", @@ -21560,7 +21638,6 @@ } }, "node_modules/vega-embed/node_modules/yallist": { - "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "inBundle": true @@ -22411,6 +22488,39 @@ "vue": "^3.2.45" } }, + "node_modules/vuetify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.5.3.tgz", + "integrity": "sha512-z2H1HYEfFeqHTp47VbFOLAv6Nard/eP4+qIXY9c6Z/uUflLhq5K8cyXL6MKhfIzyUsto+KszjVTyX+bu7zT2QA==", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=1.0.0-alpha.12", + "vue": "^3.3.0", + "vue-i18n": "^9.0.0", + "webpack-plugin-vuetify": ">=2.0.0-alpha.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "vue-i18n": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", diff --git a/varfish/vueapp/package.json b/varfish/vueapp/package.json index d09f1a693..0bfc4b0c9 100644 --- a/varfish/vueapp/package.json +++ b/varfish/vueapp/package.json @@ -14,20 +14,26 @@ "build-storybook": "storybook build" }, "dependencies": { + "@mdi/font": "^7.4.47", + "@protobuf-ts/runtime": "^2.9.3", "@reactgular/chunks": "^1.0.1", + "@types/luxon": "^3.4.2", "@vueform/multiselect": "^2.6.2", "@vuelidate/core": "^2.0.3", "@vuelidate/validators": "^2.0.4", "ag-grid-vue3": "^30.1.0", "camelcase": "^8.0.0", "core-js": "^3.32.2", + "fast-deep-equal": "^3.1.3", "igv": "^2.15.11", "javascript-time-ago": "^2.5.9", "lodash.debounce": "^4.0.8", "lodash.isequal": "^4.5.0", + "luxon": "^3.4.4", "pinia": "^2.1.6", "snakecase": "^1.0.0", "sort-by-typescript": "^1.2.5", + "title-case": "^4.3.1", "vega": "^5.25.0", "vega-embed": "^6.22.2", "vega-lite": "^5.15.0", @@ -35,6 +41,7 @@ "vue-draggable-next": "^2.2.1", "vue-router": "^4.2.5", "vue3-easy-data-table": "^1.5.47", + "vuetify": "^3.5.3", "yarn": "^1.22.19" }, "devDependencies": { @@ -87,8 +94,10 @@ "prettier": "3.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", + "sass": "^1.70.0", "storybook": "^7.6.10", "storybook-addon-fetch-mock": "^1.0.1", + "unplugin-fonts": "^1.1.1", "unplugin-icons": "^0.18.3", "unplugin-vue-components": "^0.26.0", "vite": "^4.5.2", diff --git a/varfish/vueapp/tsconfig.json b/varfish/vueapp/tsconfig.json index 1fe264707..6c4df1792 100644 --- a/varfish/vueapp/tsconfig.json +++ b/varfish/vueapp/tsconfig.json @@ -11,7 +11,8 @@ "@svs/*": ["./src/svs/*"], "@cases/*": ["./src/cases/*"], "@cases_qc/*": ["./src/cases_qc/*"], - "@cohorts/*": ["./src/cohorts/*"] + "@cohorts/*": ["./src/cohorts/*"], + "@bihealth/reev-frontend-lib/*": ["./ext/reev-frontend-lib/src/*"] } } } diff --git a/varfish/vueapp/vite.config.js b/varfish/vueapp/vite.config.js index dcfbffa79..f85345e5e 100644 --- a/varfish/vueapp/vite.config.js +++ b/varfish/vueapp/vite.config.js @@ -2,6 +2,7 @@ const { resolve } = require('path') import Vue from '@vitejs/plugin-vue' import IconsResolver from 'unplugin-icons/resolver' import Icons from 'unplugin-icons/vite' +import Unfonts from 'unplugin-fonts/vite' import Components from 'unplugin-vue-components/vite' import { defineConfig } from 'vite' @@ -30,12 +31,23 @@ export default defineConfig({ plugins: [ Vue(), Components({ - resolvers: [IconsResolver()], + dts: true, + resolvers: [IconsResolver({ enabledCollections: ['mdi'],})], }), Icons({ - autoInstall: true, + // autoInstall: true, compiler: 'vue3', }), + Unfonts({ + google: { + families: [ + { + name: 'Roboto', + styles: 'wght@100;300;400;500;700;900' + } + ] + } + }) ], resolve: { alias: { @@ -47,9 +59,13 @@ export default defineConfig({ '@cases': resolve(__dirname, './src/cases'), '@cases_qc': resolve(__dirname, './src/cases_qc'), '@cohorts': resolve(__dirname, './src/cohorts'), + '@bihealth/reev-frontend-lib': resolve(__dirname, './ext/reev-frontend-lib/src'), }, preserveSymlinks: true, }, + server: { + origin: "http://127.0.0.1:3000" + }, test: { coverage: { all: true, diff --git a/variants/vueapp/src/components/VariantDetails.vue b/variants/vueapp/src/components/VariantDetails.vue index 2c672ac9b..5fc56149c 100644 --- a/variants/vueapp/src/components/VariantDetails.vue +++ b/variants/vueapp/src/components/VariantDetails.vue @@ -10,8 +10,12 @@ * See `SvDetails` for a peer app for structural variants */ -import { computed, onMounted } from 'vue' +import { computed, defineAsyncComponent, onMounted } from 'vue' import { useRouter } from 'vue-router' +import { StoreState } from '@bihealth/reev-frontend-lib/stores' +import { useGeneInfoStore } from '@bihealth/reev-frontend-lib/stores/geneInfo' +import { useSeqvarInfoStore } from '@bihealth/reev-frontend-lib/stores/seqvarInfo' +import { Seqvar, SeqvarImpl } from '@bihealth/reev-frontend-lib/lib/genomicVars' import { useCaseDetailsStore } from '@cases/stores/caseDetails' import { useVariantDetailsStore } from '@variants/stores/variantDetails' import { useVariantQueryStore } from '@variants/stores/variantQuery' @@ -41,6 +45,14 @@ import Overlay from '@varfish/components/Overlay.vue' import { allNavItems } from '@variants/components/VariantDetails.fields' import { watch } from 'vue' +const GeneOverviewCard = defineAsyncComponent( + () => + import( + '@bihealth/reev-frontend-lib/components/GeneOverviewCard/GeneOverviewCard.vue' + ), +) + +/** This component's props. */ const props = defineProps<{ /** UUID of the result row to display. */ resultRowUuid?: string @@ -60,6 +72,11 @@ const router = useRouter() // Store-related +/** Information about the sequence variant, used to fetch information on load. */ +const seqvarInfoStore = useSeqvarInfoStore() +/** Information about the affected gene, used to fetch information on load. */ +const geneInfoStore = useGeneInfoStore() + const historyStore = useHistoryStore() const caseDetailsStore = useCaseDetailsStore() @@ -125,6 +142,10 @@ const refreshStores = async () => { if (props.resultRowUuid && props.selectedSection) { await variantResultSetStore.initialize(appContext.csrf_token) await variantResultSetStore.fetchResultSetViaRow(props.resultRowUuid) + console.log( + 'variantResultSetStore.resultRow', + variantResultSetStore.resultRow, + ) await Promise.all([ variantFlagsStore.initialize( appContext.csrf_token, @@ -147,7 +168,29 @@ const refreshStores = async () => { variantResultSetStore.caseUuid, ), ]) - variantDetailsStore.fetchVariantDetails(variantResultSetStore.resultRow) + await variantDetailsStore.fetchVariantDetails( + variantResultSetStore.resultRow, + ) + + // TODO: properly use types + if (variantResultSetStore.resultRow !== undefined) { + const seqvar: Seqvar = new SeqvarImpl( + variantResultSetStore.resultRow.release === 'GRCh37' + ? 'grch37' + : 'grch38', + variantResultSetStore.resultRow.chromosome, + variantResultSetStore.resultRow.start, + variantResultSetStore.resultRow.reference, + variantResultSetStore.resultRow.alternative, + ) + await Promise.all([ + seqvarInfoStore.initialize(seqvar), + geneInfoStore.initialize( + variantResultSetStore.resultRow.payload!.hgnc_id, + seqvar.genomeBuild, + ), + ]) + } } document.querySelector(`#${props.selectedSection}`)?.scrollIntoView() @@ -170,6 +213,11 @@ onMounted(() => {