diff --git a/apps/central/src/components/SchemaCreateModal.vue b/apps/central/src/components/SchemaCreateModal.vue index ca02704cb3..2d485c5d13 100644 --- a/apps/central/src/components/SchemaCreateModal.vue +++ b/apps/central/src/components/SchemaCreateModal.vue @@ -152,6 +152,7 @@ export default { "FAIR_DATA_POINT", "BEACON_V2", "ERN_DASHBOARD", + "UI_DASHBOARD", "BIOBANK_DIRECTORY", "BIOBANK_DIRECTORY_STAGING", "SHARED_STAGING", diff --git a/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/DataModels.java b/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/DataModels.java index d974360f86..4c09d8f595 100644 --- a/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/DataModels.java +++ b/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/DataModels.java @@ -50,6 +50,7 @@ public Task getImportTask(Schema schema, boolean includeDemoData) { public enum Regular { DIRECTORY(DirectoryLoader::new), ERN_DASHBOARD(DashboardLoader::new), + UI_DASHBOARD(UiDashboardLoader::new), PROJECTMANAGER(ProjectManagerLoader::new), BIOBANK_DIRECTORY(BiobankDirectoryLoader::new), RD3_V2(RD3v2Loader::new), diff --git a/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/UiDashboardLoader.java b/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/UiDashboardLoader.java new file mode 100644 index 0000000000..3127168cd4 --- /dev/null +++ b/backend/molgenis-emx2-datamodels/src/main/java/org/molgenis/emx2/datamodels/UiDashboardLoader.java @@ -0,0 +1,33 @@ +package org.molgenis.emx2.datamodels; + +import org.molgenis.emx2.MolgenisException; +import org.molgenis.emx2.Privileges; +import org.molgenis.emx2.Schema; +import org.molgenis.emx2.io.ImportDataModelTask; +import org.molgenis.emx2.io.MolgenisIO; +import org.molgenis.emx2.sql.SqlDatabase; + +public class UiDashboardLoader extends ImportDataModelTask { + + public UiDashboardLoader(Schema schema, Boolean includeDemoData) { + super(schema, includeDemoData); + } + + @Override + public void run() { + this.start(); + try { + createSchema(getSchema(), "ui_dashboards/molgenis.csv"); + getSchema().addMember(SqlDatabase.ANONYMOUS, Privileges.VIEWER.toString()); + MolgenisIO.fromClasspathDirectory("ui_dashboards/ontologies", getSchema(), false); + + if (isIncludeDemoData()) { + MolgenisIO.fromClasspathDirectory("ui_dashboards/demodata", getSchema(), false); + } + this.complete(); + } catch (Exception e) { + this.completeWithError(e.getMessage()); + throw new MolgenisException("Failed to create schema", e); + } + } +} diff --git a/backend/molgenis-emx2-datamodels/src/test/java/org/molgenis/emx2/datamodels/TestLoaders.java b/backend/molgenis-emx2-datamodels/src/test/java/org/molgenis/emx2/datamodels/TestLoaders.java index 9d9c6da180..1c361c1bbf 100644 --- a/backend/molgenis-emx2-datamodels/src/test/java/org/molgenis/emx2/datamodels/TestLoaders.java +++ b/backend/molgenis-emx2-datamodels/src/test/java/org/molgenis/emx2/datamodels/TestLoaders.java @@ -31,6 +31,7 @@ public class TestLoaders { public static final String PROJECT_MANAGER = "ProjectManager"; public static final String CATALOGUE_ONTOLOGIES = "CatalogueOntologies"; public static final String DIRECTORY_ONTOLOGIES = "DirectoryOntologies"; + public static final String DASHBOARD_TEST = "UiDashboardTest"; static Database database; @BeforeAll @@ -57,6 +58,7 @@ public static void setup() { database.dropSchemaIfExists(FAIR_DATA_POINT); database.dropSchemaIfExists(FAIR_DATA_HUB_TEST); database.dropSchemaIfExists(PROJECT_MANAGER); + database.dropSchemaIfExists(DASHBOARD_TEST); // delete ontologies last database.dropSchemaIfExists(CATALOGUE_ONTOLOGIES); } @@ -163,4 +165,11 @@ void test18PortalLoader() throws URISyntaxException, IOException { DataModels.Regular.RD3_V2.getImportTask(schema, false).run(); assertEquals(94, schema.getTableNames().size()); } + + @Test + public void dashboardTestLoader() { + Schema schema = database.dropCreateSchema(DASHBOARD_TEST); + DataModels.Regular.UI_DASHBOARD.getImportTask(schema, true).run(); + assertEquals(6, schema.getTableNames().size()); + } } diff --git a/data/ui_dashboards/demodata/Chart data.csv b/data/ui_dashboards/demodata/Chart data.csv new file mode 100644 index 0000000000..1b8b4b28be --- /dev/null +++ b/data/ui_dashboards/demodata/Chart data.csv @@ -0,0 +1,13 @@ +id,name,value,value label,series,primary category,secondary category,primary category label,secondary category label,time value,time unit,color,description,sort order,included in chart +recruitment-count-control,Healthy Controls,30,,,,,,,,,,Number of Healthy Controls patients recruited,2,recruitment-count +recruitment-count-intervention,Intervention,30,,,,,,,,,,Number of Intervention patients recruited,0,recruitment-count +recruitment-count-placebo,Placebo,30,,,,,,,,,,Number of Placebo patients recruited,1,recruitment-count +recruitment-count-by-site-site-001-healthy controls,Healthy Controls,10,,,site_001,,University Hospital of AAA,,,,,Number of Healthy Controls patients recruited at University Hospital of AAA,0,recruitment-count-by-site +recruitment-count-by-site-site-001-intervention,Intervention,10,,,site_001,,University Hospital of AAA,,,,,Number of Intervention patients recruited at University Hospital of AAA,3,recruitment-count-by-site +recruitment-count-by-site-site-001-placebo,Placebo,15,,,site_001,,University Hospital of AAA,,,,,Number of Placebo patients recruited at University Hospital of AAA,6,recruitment-count-by-site +recruitment-count-by-site-site-002-healthy controls,Healthy Controls,10,,,site_002,,National insitute of BBB,,,,,Number of Healthy Controls patients recruited at National insitute of BBB,1,recruitment-count-by-site +recruitment-count-by-site-site-002-intervention,Intervention,5,,,site_002,,National insitute of BBB,,,,,Number of Intervention patients recruited at National insitute of BBB,4,recruitment-count-by-site +recruitment-count-by-site-site-002-placebo,Placebo,10,,,site_002,,National insitute of BBB,,,,,Number of Placebo patients recruited at National insitute of BBB,7,recruitment-count-by-site +recruitment-count-by-site-site-003-healthy controls,Healthy Controls,10,,,site_003,,University of CCC,,,,,Number of Healthy Controls patients recruited at University of CCC,2,recruitment-count-by-site +recruitment-count-by-site-site-003-intervention,Intervention,15,,,site_003,,University of CCC,,,,,Number of Intervention patients recruited at University of CCC,5,recruitment-count-by-site +recruitment-count-by-site-site-003-placebo,Placebo,5,,,site_003,,University of CCC,,,,,Number of Placebo patients recruited at University of CCC,8,recruitment-count-by-site \ No newline at end of file diff --git a/data/ui_dashboards/demodata/Charts.csv b/data/ui_dashboards/demodata/Charts.csv new file mode 100644 index 0000000000..1f40a2afe9 --- /dev/null +++ b/data/ui_dashboards/demodata/Charts.csv @@ -0,0 +1,3 @@ +chart id,chart type,chart title,chart subtitle,x axis label,x axis min value,x axis max value,x axis ticks,y axis label,y axis min value,y axis max value,y axis ticks,top margin,right margin,bottom margin,left margin,legend position,data points,dashboard page +recruitment-count,vertical bar chart,Patients recruited by group,Count of patients by study allocation since the start of the project (Jan 2025),Group,,,,Count,0,,,15,10,80,30,top,,Home +recruitment-count-by-site,vertical bar chart,Patient recruitment by site and group,Further breakdown of recruitment data by study site and group assignment,Site,,,,Count,0,,,15,10,80,30,top,,Home \ No newline at end of file diff --git a/data/ui_dashboards/demodata/Dashboard pages.csv b/data/ui_dashboards/demodata/Dashboard pages.csv new file mode 100644 index 0000000000..bc4f9e329d --- /dev/null +++ b/data/ui_dashboards/demodata/Dashboard pages.csv @@ -0,0 +1,2 @@ +name,description +Home,The default page that is displayed when the dashboard is loaded \ No newline at end of file diff --git a/data/ui_dashboards/molgenis.csv b/data/ui_dashboards/molgenis.csv new file mode 100644 index 0000000000..6df778aa98 --- /dev/null +++ b/data/ui_dashboards/molgenis.csv @@ -0,0 +1,69 @@ +tableName,tableExtends,tableType,columnName,columnType,key,required,refTable,refBack,defaultValue,validation,semantics,description +Dashboard pages,,,,,,,,,,,http://semanticscience.org/resource/SIO_000302,The user interfaces in the vue application and the charts are displayed in each view +Dashboard pages,,,name,string,1,TRUE,,,,,http://schema.org/name,Name of the page +Dashboard pages,,,description,text,,,,,,,http://schema.org/description,Text that describes the aim of the page +Dashboard pages,,,charts,refback,,,Charts,chart id,,,http://edamontology.org/topic_0092,One or more charts displayed on a page +Charts,,,,,,,,,,,http://semanticscience.org/resource/SIO_000904,Visualisations that are displayed on page +Charts,,,chart id,string,1,TRUE,,,,,http://semanticscience.org/resource/SIO_000115,"A unique value that identifies a visualisation, the associated settings and data points." +Charts,,,chart type,ontology,,,Chart types,,,,http://semanticscience.org/resource/SIO_000904,"The chart type (e.g., pie chart, table, bar, etc.)" +Charts,,,chart title,string,,,,,,,http://semanticscience.org/resource/SIO_000473,A title to be displayed above a chart +Charts,,,chart subtitle,string,,,,,,,http://semanticscience.org/resource/SIO_000474,A subtitle to be displayed below the title. This text provides additional context for the data points displayed in the chart. +Charts,,,x axis label,string,,,,,,,"http://semanticscience.org/resource/SIO_000452,http://semanticscience.org/resource/SIO_000179,http://semanticscience.org/resource/SIO_001316",Text to be displayed along the x-axis (horizontal axis) +Charts,,,x axis min value,int,,,,,,,"http://semanticscience.org/resource/SIO_000452,http://semanticscience.org/resource/SIO_001113",A value that indicates the minimum threshold to display on the x-axis (applies only to continuous variables) +Charts,,,x axis max value,int,,,,,,,"http://semanticscience.org/resource/SIO_000452,http://semanticscience.org/resource/SIO_001114",A value that indicates the minimum threshold to display on the x-axis (applies only to continuous variables) +Charts,,,x axis ticks,int_array,,,,,,,"http://semanticscience.org/resource/SIO_000452,http://semanticscience.org/resource/SIO_000915",An array of numbers that indicate the breakpoints on the x-axis +Charts,,,y axis label,string,,,,,,,"http://semanticscience.org/resource/SIO_000453,http://semanticscience.org/resource/SIO_000179",Text to be displayed along the y-axis (vertical axis) +Charts,,,y axis min value,int,,,,,,,"http://semanticscience.org/resource/SIO_000453,http://semanticscience.org/resource/SIO_001113",A value that indicates the minimum threshold to display on the y-axis (applies only to continuous variables) +Charts,,,y axis max value,int,,,,,,,"http://semanticscience.org/resource/SIO_000453,http://semanticscience.org/resource/SIO_001114",A value that indicates the minimum threshold to display on the y-axis (applies only to continuous variables) +Charts,,,y axis ticks,int_array,,,,,,,"http://semanticscience.org/resource/SIO_000453,http://semanticscience.org/resource/SIO_000915,http://semanticscience.org/resource/SIO_001316",An array of numbers that indicate the breakpoints on the y-axis +Charts,,,top margin,int,,,,,15,"(function () { + if (topMargin !== null && topMargin < 0) { + return ""The top margin cannot be less than 0"" + } + if (topMargin !== null && topMargin > 250) { + return ""The top margin cannot be more than 250"" + } +})();",http://purl.obolibrary.org/obo/NCIT_C69210,A number that indicates the amount of white space to add to the top of the chart +Charts,,,right margin,int,,,,,15,"(function () { + if (rightMargin !== null && rightMargin < 0) { + return ""The right margin cannot be less than 0"" + } + if (rightMargin !== null && rightMargin > 250) { + return ""The right margin cannot be more than 250"" + } +})();",http://purl.obolibrary.org/obo/NCIT_C69201,A number that indicates the amount of white space to add to the right of the chart +Charts,,,bottom margin,int,,,,,60,"(function () { + if (bottomMargin !== null && bottomMargin < 0) { + return ""The bottom margin cannot be less than 0"" + } + if (bottomMargin !== null && bottomMargin > 250) { + return ""The bottom margin cannot be more than 250"" + } +})();",http://purl.obolibrary.org/obo/NCIT_C69210,A number that indicates the amount of white space to add to the bottom of the chart +Charts,,,left margin,int,,,,,80,"(function () { + if (leftMargin !== null && leftMargin < 0) { + return ""The left margin cannot be less than 0"" + } + if (leftMargin !== null && leftMargin > 250) { + return ""The left margin cannot be more than 250"" + } +})();",http://purl.obolibrary.org/obo/NCIT_C69201,A number that indicates the amount of white space to add to the left of the chart +Charts,,,legend position,ontology,,,Legend positions,,top,,"http://semanticscience.org/resource/SIO_000468,http://semanticscience.org/resource/SIO_000056",The position of the legend around the chart. +Charts,,,data points,refback,,,Chart data,included in chart,,,http://semanticscience.org/resource/SIO_000546,Data that is prepared to be used in a chart +Charts,,,dashboard page,ref,,,Dashboard pages,,,,http://semanticscience.org/resource/SIO_000302, +Chart data,,,,,,,,,,,http://semanticscience.org/resource/SIO_000089,Data used in a visualisation +Chart data,,,id,string,1,TRUE,,,,,"http://semanticscience.org/resource/SIO_000115",A value that identifies this data point in a chart +Chart data,,,name,string,,,,,,,"http://semanticscience.org/resource/SIO_000116","A label to be displayed in the chart that visually identifies the data point. By default, data points must have a name and value defined. If you would like to create a chart that displays number of participants by disease and research institution, then you would put the diseases in the ""name"" column and the institutions in the ""primary category"" column." +Chart data,,,value,decimal,,,,,,,http://semanticscience.org/resource/SIO_000465,"The calculated value of the data point. A value that is described by the ""name"" and can be further grouped by the primary and secondary categories." +Chart data,,,value label,string,,,,,,,"http://semanticscience.org/resource/SIO_000179","An alternative label that will be displayed in the chart in place of the actual value. This is useful if you would like to format the values in the specific format (e.g., ""10.05% increase"" instead of ""10.05""). If you use the ""value label"" column, the ""value"" column must be populated." +Chart data,,,series,string,,,,,,,"http://semanticscience.org/resource/SIO_000464",A data series is a data set composed of related values displayed in a statistical graph. It is intended to use this column for line charts. This column is useful to link data points of a group in addition to the primary and secondary category columns. +Chart data,,,primary category,string,,,,,,,"http://semanticscience.org/resource/SIO_000455,http://semanticscience.org/resource/SIO_000456","A primary category axis is a category axis that either defines the sole value range or holds the larger set of categorical values specified by the secondary category axis. For example, if you need to group the categories listed in the ""name"" column, then define the grouping levels here." +Chart data,,,secondary category,string,,,,,,,"http://semanticscience.org/resource/SIO_000455,http://semanticscience.org/resource/SIO_000457",A secondary category axis is a category axis that defines a finer granular part (or subset) of the value range of the primary category axis. +Chart data,,,primary category label,string,,,,,,,http://semanticscience.org/resource/SIO_000179,"An alternative label that will be displayed instead of the value in ""primary category"" column" +Chart data,,,secondary category label,string,,,,,,,http://semanticscience.org/resource/SIO_000179,"An alternative label that will be displayed instead of the value in ""secondary category"" column" +Chart data,,,time value,string,,,,,,,"http://semanticscience.org/resource/SIO_000391"," time measurement is a measurement value of the duration of some interval of time or a particular instant of time (against some frame of reference). This column should be populated if you are visualising data by time. It is intended to place the value in this column (e.g., ""2020,2021,2022,..."" or ""12, 13,14""; years, months, etc.) and set the unit in the ""time unit"" column." +Chart data,,,time unit,ontology,,,Time intervals,,,,"http://semanticscience.org/resource/SIO_000074","A unit that provides context to the value in the column ""time interval"". E.g., ""months"", ""years"", etc." +Chart data,,,color,string,,,,,,,"http://schema.org/color","A colour value (RGB, HEX, HSL, etc.) used to style the data point" +Chart data,,,description,text,,,,,,,"http://semanticscience.org/resource/SIO_000136",A description is language entity in which elements of a language (formal or natural) are used to characterize an entity. This is useful if you are using tooltips in charts. Information placed in this column could be displayed in the charts. +Chart data,,,sort order,int,,,,,,,"http://semanticscience.org/resource/SIO_001316",A numerical value indicating the sorting method for data points +Chart data,,,included in chart,ref,,,Charts,,,,"http://edamontology.org/topic_0092",A value that links one or more data points to a visualisation \ No newline at end of file diff --git a/data/ui_dashboards/ontologies/Chart types.csv b/data/ui_dashboards/ontologies/Chart types.csv new file mode 100644 index 0000000000..697d4a7809 --- /dev/null +++ b/data/ui_dashboards/ontologies/Chart types.csv @@ -0,0 +1,10 @@ +order,name,label,tags,parent,codesystem,code,ontologyTermURI,definition +,data highlight,,,,,,, +,horizontal bar chart,,,,SIO,SIO:000444,http://semanticscience.org/resource/SIO_000444, +,line graph,,,,SIO,SIO:000442,http://semanticscience.org/resource/SIO_000442, +,map,,,,SIO,SIO:000906,http://semanticscience.org/resource/SIO_000906, +,pie chart,,,,SIO,SIO:000929,http://semanticscience.org/resource/SIO_000929, +,progress meter,,,,,,, +,scatterplot,,,,SIO,SIO:000423,http://semanticscience.org/resource/SIO_000423, +,table,,,,SIO,SIO:000419,http://semanticscience.org/resource/SIO_000419, +,vertical bar chart,,,,SIO,SIO:000445,http://semanticscience.org/resource/SIO_000445, \ No newline at end of file diff --git a/data/ui_dashboards/ontologies/Legend positions.csv b/data/ui_dashboards/ontologies/Legend positions.csv new file mode 100644 index 0000000000..493f24e482 --- /dev/null +++ b/data/ui_dashboards/ontologies/Legend positions.csv @@ -0,0 +1,5 @@ +name,definition +top,"A vertical position that indicates a chart legend should be placed before (i.e., above) a chart." +right,A horizontal position that indicates a chart legend should be placed on the righthand side of a chart. +bottom,"A vertical position that indicates a chart legend should be placed after (i.e., below) a chart." +left,A horizontal position that indicates a chart legend should be placed on the lefthand side of a chart. \ No newline at end of file diff --git a/data/ui_dashboards/ontologies/Time intervals.csv b/data/ui_dashboards/ontologies/Time intervals.csv new file mode 100644 index 0000000000..4ddce7a3a6 --- /dev/null +++ b/data/ui_dashboards/ontologies/Time intervals.csv @@ -0,0 +1,14 @@ +name,parent,codesystem,code,ontologyTermURI,definition +second,,sio,SIO_000435,http://semanticscience.org/resource/SIO_000435,"A second (symbol: s) is the base unit of time in the International System of Units (SI) and is the second division of the hour by sixty, the first division by 60 being the minute." +microsecond,second,uo,UO_0000029,http://purl.obolibrary.org/obo/UO_0000029,"""A time unit which is equal to one millionth of a second or 10^[-6] s."" [NIST:NIST]" +millisecond,second,uo,UO_0000028,http://purl.obolibrary.org/obo/UO_0000028,"""A time unit which is equal to one thousandth of a second or 10^[-3] s."" [NIST:NIST]" +nanosecond,second,uo,UO_0000150,http://purl.obolibrary.org/obo/UO_0000150,"""A time unit which is equal to one thousandth of one millionth of a second or 10^[-9] s."" [NIST:NIST]" +picosecond,second,uo,UO_0000030,http://purl.obolibrary.org/obo/UO_0000030,"""A time unit which is equal to 10^[-12] s."" [NIST:NIST]" +minute,,sio,SIO_000434,http://semanticscience.org/resource/SIO_000434,A minute is a period of 60 seconds. +hour,,sio,SIO_000433,http://semanticscience.org/resource/SIO_000433,An hour is a period of 60 minutes. +day,,sio,SIO_000430,http://semanticscience.org/resource/SIO_000430,A day is a period of 24 hours. +week,,sio,SIO_001354,http://semanticscience.org/resource/SIO_001354,A week is a period of 7 consecutive days. +month,,sio,SIO_000429,http://semanticscience.org/resource/SIO_000429,A month is a period of time that divides the year. +year,,sio,SIO_000428,http://semanticscience.org/resource/SIO_000428,A year is a period of time taken by a planet to make one revolution around the sun. +century,,sio,SIO_000431,http://semanticscience.org/resource/SIO_000431,A century is a period of one hundred years. +millennium,,sio,SIO_000432,http://semanticscience.org/resource/SIO_000432,A millenium is a period of 1000 years