Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dashboards): connect CRANIO dashboard to the database #4516

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
6398ed8
fix: enabled ts
davidruvolo51 Nov 19, 2024
9c8d97a
feat: generated schema types
davidruvolo51 Nov 19, 2024
3b58687
fix: enabled typescript and fixed immediate ts issues
davidruvolo51 Nov 20, 2024
3c47f67
feat: refactored and typed primary data queries
davidruvolo51 Nov 20, 2024
ca12d3a
chore: added proxy for reports
davidruvolo51 Nov 22, 2024
bf8b15d
feat: added function for retrieven organisation metadata
davidruvolo51 Nov 22, 2024
76f98c2
added types for user interfaces
davidruvolo51 Nov 22, 2024
6bf0f62
fix: resolved module import ts error
davidruvolo51 Nov 22, 2024
a0face2
feat: refactored main router view; restructured global data objects
davidruvolo51 Nov 22, 2024
3f0364d
feat: added function for retrieving cranio schema names
davidruvolo51 Nov 22, 2024
c5a27d2
feat: added function for retrieving chart data
davidruvolo51 Nov 22, 2024
77d0bc3
feat: added function to auto generate axis ticks
davidruvolo51 Nov 22, 2024
6d7a4ff
feat: init general functions
davidruvolo51 Nov 22, 2024
1947796
feat: initial rewrite of center overview
davidruvolo51 Nov 22, 2024
5a0a5c0
feat: restructured update functions; initialized suture chart
davidruvolo51 Nov 25, 2024
fe70f06
fix: added fixed value if max is less than 10
davidruvolo51 Nov 25, 2024
e9b0ae8
fix: updated data type
davidruvolo51 Nov 25, 2024
9a0a979
feat: added color palette generator to charts
davidruvolo51 Nov 25, 2024
9fee919
fix: dropped warning message
davidruvolo51 Nov 25, 2024
0e31872
feat: added function for flattening datasets
davidruvolo51 Nov 25, 2024
729b63f
finished dashboard page
davidruvolo51 Nov 25, 2024
424200e
added graphql endpoint as a prop
davidruvolo51 Nov 25, 2024
3609e2d
feat: finished overview page
davidruvolo51 Nov 25, 2024
6e563ab
ran formatter
davidruvolo51 Nov 25, 2024
257f672
chore: renamed files
davidruvolo51 Nov 26, 2024
a22b86b
feat: simplifed data preparation steps
davidruvolo51 Nov 26, 2024
23afe1d
chore: dropped empty component files
davidruvolo51 Nov 26, 2024
bf5b01c
feat: connected CLP center overview to the database
davidruvolo51 Nov 26, 2024
cbf3d16
chore: ran formatter
davidruvolo51 Nov 27, 2024
c94d2ba
fix: restructured api urls
davidruvolo51 Nov 27, 2024
1a871fa
fix: changed import path
davidruvolo51 Nov 27, 2024
be65b08
feat: finished clp dashboard pages
davidruvolo51 Nov 27, 2024
fb87698
feat: init text loading element
davidruvolo51 Nov 28, 2024
794663c
fix: fixed text loading; adjusted busy message heights
davidruvolo51 Nov 28, 2024
b0e1c37
feat: initial connection of surgical view
davidruvolo51 Nov 28, 2024
aaf736f
fix: adjusted queries
davidruvolo51 Dec 2, 2024
d99863d
Merge branch 'master' into feat/cranio-charts
davidruvolo51 Dec 9, 2024
fef6151
Merge branch 'master' into feat/cranio-charts
davidruvolo51 Jan 6, 2025
7109ced
fix: connected age chart to filter; set color palettes
davidruvolo51 Jan 6, 2025
1cc8fca
feat: connected all center overview
davidruvolo51 Jan 6, 2025
e4f7064
fix: links are now expanded by default
davidruvolo51 Jan 6, 2025
3ff1f78
connected last page to tables; added error messages; minor revisions
davidruvolo51 Jan 7, 2025
bb78ee8
docs: updated readme
davidruvolo51 Jan 7, 2025
8717d5b
feat: add unittests for axis functions
davidruvolo51 Jan 8, 2025
dd801c8
data: diagnosis filter now shows term and code
davidruvolo51 Jan 10, 2025
bb77540
fix: integration of feedback; minor revisions and fixes
davidruvolo51 Jan 16, 2025
c9823cb
post-review revisions and fixes
davidruvolo51 Jan 17, 2025
5208a83
added more reusable functions
davidruvolo51 Jan 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions apps/cranio-provider/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ Changes can be made to the application by cloning the `molgenis/molgenis-emx2` r

### Setting up your development instance

Select an EMX2 instance to use as your development instance. Log in as admin and create two schemas:
Select an EMX2 instance to use as your development instance. Log in as admin and create three schemas:

1. Public Schema: used to display the `cranio-public` vue application. Use the template `ERN_DASHBOARDS`. Give it a name e.g., `ErnStats`
2. Provider Schema: An organisation-level schema to display the `cranio-provider` vue application. Use one of the organisations listed in the [Cranio Organisations.csv](https://github.com/molgenis/projects-rd-erns/blob/main/erns/cranio/imports/organisations.csv) file. The name of the schema is listed in the column `schemaName`. For example, use `DK1` to create a schema for `Aarhus University Hospital`.
3. All Providers schema: A schema used to store the all site (or ERN wide) aggregations

After creating both schemas, navigate to the settings table in the provider schema. Here we will create a reference to the public schema to link the provider with public schemas. This allows the vue applications to be independent and to avoid hardcoding any schema information. The key is hardcoded.

| Key | Value |
|-----|-------|
| CRANIO_PUBLIC_SCHEMA | `<public_schema_name>` |
| Key | Value |
|------------------------|--------------------------|
| CRANIO_PUBLIC_SCHEMA | `<public_schema_name>` |
| CRANIO_PROVIDER_SCHEMA | `<provider_schema_name>` |

Using the example schema name created in step one, we would use `ErnStats`.

Expand Down
2 changes: 1 addition & 1 deletion apps/cranio-provider/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
>
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
3 changes: 0 additions & 3 deletions apps/cranio-provider/jsconfig.json

This file was deleted.

5 changes: 3 additions & 2 deletions apps/cranio-provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"format": "prettier src --write --config ../.prettierrc.js",
"checkFormat": "prettier src --check --config ../.prettierrc.js"
"format": "prettier src tests --write --config ../.prettierrc.js",
"checkFormat": "prettier src --check --config ../.prettierrc.js",
"test": "vitest"
},
"dependencies": {
"@heroicons/vue": "^2.0.18",
Expand Down
153 changes: 45 additions & 108 deletions apps/cranio-provider/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,49 @@
<LoadingScreen v-if="loading && !error" />
<div class="message-box-container" v-else-if="!loading && error">
<MessageBox type="error">
<p><{{ error }}</p>
<p>{{ error }}</p>
</MessageBox>
</div>
<div v-else>
<PageHeader
title="ERN CRANIO Registry"
:subtitle="provider.name"
:subtitle="currentOrganisation?.name"
:imageSrc="
Object.hasOwn(provider.image, 'id')
? `${provider.image.url}`
currentOrganisation?.image
? `${currentOrganisation?.image?.url}`
davidruvolo51 marked this conversation as resolved.
Show resolved Hide resolved
: 'img/banner-diagnoses.jpg'
"
/>
<PageSection
class="bg-gray-050"
aria-labelledby="temp-message-title"
:verticalPadding="1"
>
<h2 id="temp-message-title" class="visually-hidden">
About the dashboards
</h2>
<MessageBox type="warning">
<p>
This dashboard is currently under development. All data shown in
the following visualisations have been randomly generated for
demonstration purposes.
</p>
</MessageBox>
</PageSection>
<Dashboard class="provider-dashboard-container" :horizontalPadding="5">
<ProviderSidebar />
<router-view
:providerId="provider.id"
:providerName="provider.name"
:organisation="currentOrganisation"
:schemaNames="cranioSchemas"
:api="{
graphql: {
current: `/${currentOrganisation?.schemaName}/api/graphql`,
public: `/${cranioSchemas?.CRANIO_PUBLIC_SCHEMA}/api/graphql`,
providers: `/${cranioSchemas?.CRANIO_PROVIDER_SCHEMA}/api/graphql`,
},
}"
></router-view>
</Dashboard>
</div>
</Page>
<AppFooter :publicSchema="cranioPublicSchema" />
<AppFooter :publicSchema="cranioSchemas?.CRANIO_PUBLIC_SCHEMA" />
</Molgenis>
</template>

<script setup lang="ts">
import { ref, onBeforeMount } from "vue";
import { getCranioSchemaNames } from "./utils/getCranioSchemaNames";
import { getSchemaName } from "./utils/getSchemaName";
import { getOrganisation } from "./utils/getOrganisation";

import type { IMgErrorResponse, ICranioSchemas } from "./types";
import type { IOrganisations } from "./types/schema";

// @ts-ignore
import { Molgenis } from "molgenis-components";
import {
Page,
Expand All @@ -56,101 +55,39 @@ import {
Dashboard,
MessageBox,
LoadingScreen,
// @ts-ignore
} from "molgenis-viz";

// @ts-ignore
import ProviderSidebar from "./components/ProviderSidebar.vue";
import AppFooter from "./components/AppFooter.vue";

import gql from "graphql-tag";
import { request } from "graphql-request";

const session = ref(null);
const page = ref(null);

let loading = ref<boolean>(true);
let error = ref<Error | null>(null);
let cranioPublicSchema = ref<string | null>(null);
let schema = ref<object | null>(null);
let provider = ref<object | null>(null);

async function getCranioPublicSchema() {
const query = gql`
{
_settings {
key
value
}
}
`;
const response = await request("../api/graphql", query);
const result = response._settings?.filter(
(row) => row.key === "CRANIO_PUBLIC_SCHEMA"
)[0];
const loading = ref<boolean>(true);
const error = ref<string>();
const cranioSchemas = ref<ICranioSchemas>();
const currentSchemaName = ref<string>();
const currentOrganisation = ref<IOrganisations>();

if (!result.value) {
throw new Error(
"Missing the name of the schema that controls the vue application cranio_public. In the current schema, navigate to the settings table. Add a new setting with the key 'CRANIO_PUBLIC_SCHEMA' and enter the name in the value column. Hit save and refresh the page."
onBeforeMount(async () => {
try {
cranioSchemas.value = await getCranioSchemaNames();
currentSchemaName.value = await getSchemaName();
currentOrganisation.value = await getOrganisation(
`/${cranioSchemas.value?.CRANIO_PUBLIC_SCHEMA}/api/graphql`,
currentSchemaName.value
);
} else {
cranioPublicSchema.value = result.value;
}
}

async function getSchemaMeta() {
const query = gql`
{
_schema {
name
}
} catch (err: unknown) {
if (Object.hasOwn(err as Error, "response")) {
const message = (err as IMgErrorResponse).response.errors[0].message;
error.value = message;
} else {
error.value = (err as Error).message;
}
`;
const result = await request("../api/graphql", query);
schema.value = result._schema.name;
}

async function getProviderMeta() {
const query = gql`{
Organisations (
filter: {
providerInformation: {
providerIdentifier: {
equals: "${schema.value}"
}
}
}
) {
name
image {
id
url
size
extension
}
providerInformation {
providerIdentifier
}
}
}`;

const result = await request(
`/${cranioPublicSchema.value}/api/graphql`,
query
);
const data = result.Organisations[0];
data.id = data.providerInformation[0].providerIdentifier;
delete data.providerInformation;
provider.value = data;
}

async function loadData() {
await getSchemaMeta();
await getProviderMeta();
}

onBeforeMount(async () => {
await getCranioPublicSchema().catch((err) => (error.value = err));
await loadData()
.catch((err) => (error.value = err))
.finally(() => (loading.value = false));
} finally {
loading.value = false;
}
});
</script>
23 changes: 12 additions & 11 deletions apps/cranio-provider/src/components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@
<a :href="`/${publicSchema}/cranio-public/#/about`">About</a>
</li>
<li>
<a :href="`/${publicSchema}/cranio-public/#/dashboard`"
>Dashboard</a
>
<a :href="`/${publicSchema}/cranio-public/#/dashboard`">
Dashboard
</a>
</li>
</UnorderedList>
</div>
<div class="footer-column footer-links">
<p><strong>For Members</strong></p>
<UnorderedList listType="none">
<li>
<a :href="`/${publicSchema}/cranio-public/#/Providers`"
>Providers</a
>
<a :href="`/${publicSchema}/cranio-public/#/Providers`">
Providers
</a>
</li>
<li>
<a :href="`/${publicSchema}/cranio-public/#/Documents`"
>Documents</a
>
<a :href="`/${publicSchema}/cranio-public/#/Documents`">
Documents
</a>
</li>
</UnorderedList>
</div>
Expand Down Expand Up @@ -65,10 +65,11 @@
</template>

<script setup lang="ts">
// @ts-ignore
import { PageFooter, UnorderedList } from "molgenis-viz";

const props = defineProps<{
publicSchema: string | null;
defineProps<{
publicSchema?: string;
}>();
</script>

Expand Down
27 changes: 10 additions & 17 deletions apps/cranio-provider/src/components/DashboardChartLayout.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
<template>
<div :class="classNames">
<div class="dashboard-chart-layout" :class="`columns-${columns}`">
<slot></slot>
</div>
</template>

<script setup>
import { computed } from "vue";

const props = defineProps({
columns: {
type: Number,
default: 2,
validator: (value) => {
return value >= 1 && value <= 4;
},
},
});

const classNames = computed(() => {
return `dashboard-chart-layout columns-${props.columns}`;
});
<script setup lang="ts">
withDefaults(
defineProps<{
columns: 1 | 2 | 3 | 4;
}>(),
{
columns: 2,
}
);
</script>

<style lang="scss">
Expand Down
Loading