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

Merge Dashboard branch into Staging #36

Merged
merged 23 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d6ffaca
feat: ✨ redcap api link management done
greenstick Nov 2, 2023
3566c02
Merge branch 'staging' of https://github.com/AI-READI/fairhub.io into…
greenstick Nov 2, 2023
63d36e9
feat: ✨ first dashboard module complete
greenstick Nov 14, 2023
db73d87
Merge branch 'staging' of https://github.com/AI-READI/fairhub.io into…
greenstick Nov 14, 2023
6debdc0
merge: 🔀 dashboard cleanup
greenstick Nov 14, 2023
201ae22
chore: 🔨 yarn cleanup
greenstick Nov 14, 2023
45e5cd4
feat: ✨ more dashboard modules
greenstick Nov 15, 2023
533beee
fix: 🐛 EditDashboard loading prior state. WIP recruitment line chart
greenstick Dec 1, 2023
37d1df9
fix: 🐛 typescript cleanup
greenstick Dec 6, 2023
145884d
fix: 🐛 typescript fix
greenstick Dec 6, 2023
643ac8c
feat: ✨ dashboard module and report manifests
greenstick Dec 7, 2023
2d0ed24
feat: ✨ new chart types: groupedbar and groupedstackedbar
greenstick Dec 12, 2023
ec53272
feat: ✨ new recruitment visualization modules
greenstick Dec 12, 2023
bdeb1e4
style: 🎨 improvements to visualizations
greenstick Dec 13, 2023
c385ca1
fix: 🐛 minor fixes
greenstick Jan 23, 2024
454e9a2
Merge branch 'staging' of https://github.com/AI-READI/fairhub.io into…
greenstick Jan 23, 2024
67b9cfa
Merge branch 'staging' into dashboard
greenstick Jan 23, 2024
32e77cd
fix: 🐛 minor fixes
greenstick Jan 26, 2024
77ef9a6
feat: ✨ line chart done
greenstick Feb 4, 2024
42b1e74
chore: 🔨 lint, format, type-check
greenstick Feb 13, 2024
64b076b
feat: ✨ improved REDcap API structure (not yet merge ready)
greenstick Feb 20, 2024
1aebcd4
feat: ✨ improved REDcap & Dashboard API structure
greenstick Feb 20, 2024
39e35cb
Merge branch 'staging' into dashboard
greenstick Feb 20, 2024
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
3 changes: 3 additions & 0 deletions auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ declare global {
Component,
ComponentPublicInstance,
ComputedRef,
ExtractDefaultPropTypes,
ExtractPropTypes,
ExtractPublicPropTypes,
InjectionKey,
PropType,
Ref,
Expand Down
2 changes: 1 addition & 1 deletion mermaid/svg/dataset-metadata-er.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mermaid/svg/er.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion mermaid/svg/study-metadata-er.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions mermaid/svg/study-metadata.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"pinia": "^2.0.21",
"pinia-plugin-persistedstate": "^3.0.2",
"sanitize-html": "^2.11.0",
"source-map": "^0.7.4",
"storybook-tailwind-foundations": "^1.1.2",
"unimport": "^3.4.0",
"validator": "^13.9.0",
Expand Down Expand Up @@ -128,6 +129,7 @@
"unplugin-vue-components": "^0.25.1",
"vfonts": "^0.0.3",
"vite": "^3.0.9",
"vite-plugin-node-polyfills": "^0.16.0",
"vitest": "^0.23.0",
"vue-loader": "^16.8.3",
"vue-tsc": "^0.40.7"
Expand Down
234 changes: 234 additions & 0 deletions src/components/dashboard/DashboardModule.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
<script lang="ts">
import type { VisualizationRenderer } from "@/types/DashboardModule";

export default {
name: "DashboardModule",
props: ["vrenderers"],
setup(props: any) {
const visualizations: any[] = reactive([]);
// const vrenderers: VisualizationRenderer[] = [];
onMounted(() => {
const vrenderers = props.vrenderers as VisualizationRenderer[];
for (let i = 0; i < vrenderers.length; i++) {
let vrenderer = vrenderers[i];
let cls = vrenderer.class;
let cfg = vrenderer.config;
let instance = new cls(cfg).update();
visualizations.push(instance);
}
});
onUpdated(() => {
for (let i = 0; i < visualizations.length; i++) {
const visualization = toRaw(visualizations[i]) as any;
visualization.update();
}
});
return { visualizations: visualizations };
},
};
</script>

<template>
<div
v-for="(visualization, visualization_index) in visualizations"
:key="visualization_index"
class="visualization-container"
>
<svg
:id="`${visualization.setID}_visualization`"
class="visualization-element"
:viewBox="`0 0 ${visualization.width} ${visualization.height}`"
preserveAspectRatio="xMinYMid meet"
xmlns="http://www.w3.org/2000/svg"
/>

<n-grid
:cols="3"
:x-gap="20"
:y-gap="20"
:id="`${visualization.setID}_interface`"
class="interface"
>
<n-grid-item v-if="visualization.legend">
<n-card :id="`${visualization.setID}_legend`" :segmented="true" :bordered="false"></n-card>
</n-grid-item>

<n-grid-item v-if="visualization.tooltip">
<n-card :id="`${visualization.setID}_tooltip`" :segmented="true" :bordered="false"></n-card>
</n-grid-item>

<n-grid-item v-if="visualization.filters">
<n-dropdown
trigger="click"
:options="visualization.Filters.data"
@select="visualization.update($event, filter)"
placement="right-start"
:id="`${visualization.setID}_filters`"
>
<n-button>{{
`${visualization.accessors.filterby.name} > ${visualization.selectedFilter}`
}}</n-button>
</n-dropdown>
</n-grid-item>
</n-grid>
</div>
</template>

<style>
/*
Interaction Elements
*/

::marker {
display: none;
}

.interactable {
cursor: pointer;
}

/*
Visualization Background
*/

.visualization-background {
position: absolute;
}

/*
Visualization Elements
*/

.visualization-container {
max-height: 760px;
}
.visualization-container svg {
shape-rendering: geometricPrecision;
}
.visualization-container svg:path,
.visualization-container svg:rect,
.visualization-container svg:circle {
cursor: pointer !important;
}
.visualization-container text,
.visualization-container span {
text-transform: capitalize;
}
.visualization-container .visualization-element {
}
.visualization-container .visualization-element .data-elements {
}
.visualization-container .visualization-element .data-elements .data-element {
}
.visualization-container .visualization-element .x-axis {
}
.visualization-container .visualization-element .y-axis {
}
.visualization-container .visualization-element.unrotated .x-axis .label {
text-anchor: start;
vertical-align: middle;
line-height: 20px;
}
.visualization-container .visualization-element.unrotated .y-axis .label {
text-anchor: center;
}
.visualization-container .visualization-element.isrotated .x-axis .label {
text-anchor: center;
}
.visualization-container .visualization-element.isrotated .y-axis .label {
text-anchor: center;
vertical-align: middle;
line-height: 20px;
}

/*
Visualization Interface
*/

.visualization-container .interface {
display: flex;
flex-direction: row;
align-content: flex-start;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
width: 100%;
min-height: 80px;
margin-bottom: 12px;
}
.visualization-container .interface-element {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

/*
Visualization Interface – Tooltip
*/

.visualization-container .interface-element.tooltip {
}
.visualization-container .interface-element.tooltip .tooltip-items .tooltip-item {
line-height: 1.4em;
}
.visualization-container .interface-element.tooltip .tooltip-items .tooltip-label {
display: inline-flex;
flex-direction: row;
align-content: flex-start;
justify-content: flex-start;
align-items: flex-start;
font-weight: bold;
margin-right: 8px;
}
.visualization-container .interface-element.tooltip .tooltip-items .tooltip-value {
display: inline-flex;
flex-direction: row;
align-content: flex-start;
justify-content: flex-start;
align-items: flex-start;
}

/*
Visualization Interface – Legend
*/

.visualization-container .interface-element.legend {
list-style: none;
}
.visualization-container .interface-element.legend .legend-items {
padding-left: 0px;
}
.visualization-container .interface-element.legend .legend-items .legend-item {
padding-left: 0px;
line-height: 1.4em;
margin-right: 8px;
}
.visualization-container .interface-element.legend .legend-items .legend-item .legend-color {
display: inline-flex;
flex-direction: row;
align-content: flex-start;
justify-content: flex-start;
align-items: flex-start;
margin-right: 8px;
}
.visualization-container .interface-element.legend .legend-items .legend-item .legend-label {
padding-left: 8px;
text-anchor: left;
vertical-align: top;
font-weight: bold;
}

/*
Visualization Interface – Filters
*/

.visualization-container .interface-element.filters {
}
.visualization-container .interface-element.filters .filterbank .filter {
line-height: 1.4em;
}
.visualization-container .interface-element.filters .filterbank .filter .filter-value {
font-weight: bold;
vertical-align: middle;
}
</style>
12 changes: 8 additions & 4 deletions src/components/sidebar/AppSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,16 @@ const UpperMenuOptions = computed(() => [
label: "Files",
show: hideMenuOptions.value,
},
{
icon: renderIcon("material-symbols:api"),
key: "study:redcap:all-redcap-project-apis",
label: "REDCap",
show: hideMenuOptions.value,
},
{
icon: renderIcon("material-symbols:dashboard-rounded"),
key: "study:dashboard",
label: "Dashboard",
key: "study:dashboard:all-dashboards",
label: "Dashboards",
show: hideMenuOptions.value,
},
{
Expand Down Expand Up @@ -378,8 +384,6 @@ const defaultExpandedKeys = computed(() => {
if (currentRoute.name) {
const name = currentRoute.name as string;

console.log("appsidebar-name", name, name.startsWith("study:metadata"));

if (name.startsWith("study:metadata")) {
return ["study:metadata"];
}
Expand Down
69 changes: 69 additions & 0 deletions src/configs/dashboards/modules-manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import type { DashboardModuleConnector } from "@/types/DashboardModule";

const DashboardModulesManifest: DashboardModuleConnector[] = [
{
id: "instrument-completion-status-by-site",
name: "Instrument Completion Status by Site",
available: true,
report_key: "instrument-status",
selected: true,
},
{
id: "phenotype-race-by-sex",
name: "Phenotype & Race by Sex",
available: true,
report_key: "participant-value",
selected: false,
},
{
id: "phenotype-sex-by-site",
name: "Phenotype & Sex by Site",
available: true,
report_key: "participant-value",
selected: false,
},
{
id: "race-sex-by-site",
name: "Race & Sex by Site",
available: true,
report_key: "participant-value",
selected: true,
},
// {
// id: "completed-visits-by-site",
// name: "Completed Visits by Site",
// available: false,
// report_key: "participant-value",
// selected: false,
// },
// {
// id: "scheduled-visits-by-site",
// name: "Scheduled Visits by Site",
// available: false,
// report_key: "participant-value",
// selected: false,
// },
{
id: "phenotype-recruitment-by-site",
name: "Phenotype Recruitment Counts by Site",
available: true,
report_key: "participant-value",
selected: false,
},
{
id: "race-recruitment-by-site",
name: "Race Recruitment Counts by Site",
available: true,
report_key: "participant-value",
selected: false,
},
{
id: "current-medications-by-site",
name: "Current Medications By Site",
available: true,
report_key: "repeat-instrument",
selected: false,
},
];

export { DashboardModulesManifest };
Loading
Loading