From a2169a14573361bf1546feb8d53b007390b19b4f Mon Sep 17 00:00:00 2001 From: craigrbarnes Date: Tue, 10 Dec 2024 12:52:37 -0500 Subject: [PATCH] update to 0.10.61 --- .env.production | 4 - .nvmrc | 1 + Dockerfile | 75 +-- config/brh/dataLibrary.json | 32 ++ config/brh/discovery.json | 506 +++++++++--------- config/brh/footer.json | 47 +- config/brh/landingPage.json | 4 +- config/brh/login.json | 48 +- config/{ => brh}/modals.json | 1 - config/brh/navigation.json | 57 +- config/brh/profile.json | 1 + config/brh/query.json | 2 + config/{ => brh}/session.json | 4 +- config/brh/submission.json | 30 ++ config/{ => brh}/themeColors.json | 235 ++++---- config/brh/themeFonts.json | 5 + config/brh/workspace.json | 2 + config/icons/color.json | 28 + config/icons/color/analysis.svg | 1 + config/icons/color/discovery.svg | 1 + config/icons/color/explorer.svg | 1 + config/icons/color/profile.svg | 1 + config/icons/color/workspaces.svg | 1 + config/icons/dataDictionary.json | 58 ++ .../dictionary_icon_administrative.svg | 16 + .../dictionary_icon_analysis.svg | 13 + .../dictionary_icon_biospecimen.svg | 11 + .../dictionary_icon_clinical.svg | 13 + .../dictionary_icon_clinical_assessment.svg | 20 + .../dictionary_icon_data_file.svg | 15 + .../dictionary_icon_data_observations.svg | 14 + .../dictionary_icon_default.svg | 16 + .../dictionary_icon_experimental_methods.svg | 11 + .../dictionary_icon_imaging.svg | 11 + .../dictionary_icon_index_file.svg | 16 + .../dictionary_icon_medical_history.svg | 13 + .../dictionary_icon_metadata.svg | 16 + .../dictionary_icon_notation.svg | 12 + .../dictionary_icon_study_administration.svg | 16 + ...ictionary_icon_subject_characteristics.svg | 14 + config/icons/download.svg | 1 - config/icons/gen3.json | 113 +++- config/icons/{ => gen3}/aiSearch.svg | 0 config/icons/{ => gen3}/analysis.svg | 0 config/icons/{ => gen3}/bar-chart.svg | 0 config/icons/gen3/chevron-contract.svg | 1 + config/icons/{ => gen3}/chevron-down.svg | 0 config/icons/gen3/chevron-expand.svg | 1 + config/icons/gen3/comparison.svg | 1 + config/icons/{ => gen3}/datafile.svg | 0 config/icons/{ => gen3}/dictionary.svg | 0 config/icons/gen3/download.svg | 1 + config/icons/{ => gen3}/exploration.svg | 0 config/icons/{ => gen3}/gen3-dark.svg | 0 config/icons/{ => gen3}/gen3.svg | 0 config/icons/gen3/jupyter.svg | 90 ++++ config/icons/gen3/loginArrowCircle.svg | 1 + config/icons/{ => gen3}/loginCircle.svg | 0 config/icons/gen3/not-found.svg | 94 ++++ config/icons/gen3/notebook.svg | 92 ++++ config/icons/gen3/open_in_modal.svg | 3 + config/icons/{ => gen3}/profile.svg | 0 config/icons/{ => gen3}/query.svg | 0 config/icons/gen3/upload.svg | 1 + config/icons/{ => gen3}/user.svg | 0 config/icons/{ => gen3}/workspace.svg | 0 config/icons/upload.svg | 17 - config/icons/workspace.json | 24 + config/icons/workspace/galaxy.svg | 19 + config/icons/workspace/jupyter.svg | 90 ++++ config/icons/workspace/rlogo.svg | 17 + config/icons/workspace/rstudio.svg | 12 + config/siteConfig.json | 3 - config/themeFonts.json | 5 - package-lock.json | 35 +- package.json | 57 +- src/lib/CohortBuilder/CustomCellRenderers.tsx | 38 +- src/lib/CohortBuilder/FileDetailsPanel.tsx | 170 ++++++ src/lib/Discovery/CustomCellRenderers.tsx | 99 ++-- src/lib/Discovery/CustomRowRenderers.tsx | 140 +++-- src/lib/Discovery/Filemap.tsx | 183 +++++++ src/lib/Grafana/grafana.ts | 43 ++ src/lib/content/loadContent.ts | 40 ++ src/pages/AISearch.tsx | 46 +- src/pages/Analysis.tsx | 7 + src/pages/Crosswalk.tsx | 7 + src/pages/DataDictionary.tsx | 7 +- src/pages/DataLibrary.tsx | 8 + src/pages/Explorer.tsx | 4 +- src/pages/NotebookLite.tsx | 7 + src/pages/SamplePage.tsx | 33 +- src/pages/Submission.tsx | 7 + src/pages/Workspace.tsx | 7 + src/pages/_app.tsx | 153 ++++-- src/pages/_document.tsx | 11 +- src/pages/api/auth/sessionLogout.ts | 3 + src/pages/app/[appName].tsx | 78 +++ src/pages/index.tsx | 14 +- src/pages/no-workspace-access.tsx | 7 + src/styles/globals.css | 87 +-- start.sh | 5 - tailwind.config.js | 8 +- 102 files changed, 2372 insertions(+), 890 deletions(-) delete mode 100644 .env.production create mode 100644 .nvmrc create mode 100644 config/brh/dataLibrary.json rename config/{ => brh}/modals.json (98%) create mode 100644 config/brh/query.json rename config/{ => brh}/session.json (51%) create mode 100644 config/brh/submission.json rename config/{ => brh}/themeColors.json (80%) create mode 100644 config/brh/themeFonts.json create mode 100644 config/brh/workspace.json create mode 100644 config/icons/color.json create mode 100644 config/icons/color/analysis.svg create mode 100644 config/icons/color/discovery.svg create mode 100644 config/icons/color/explorer.svg create mode 100644 config/icons/color/profile.svg create mode 100644 config/icons/color/workspaces.svg create mode 100644 config/icons/dataDictionary.json create mode 100755 config/icons/dataDictionary/dictionary_icon_administrative.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_analysis.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_biospecimen.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_clinical.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_clinical_assessment.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_data_file.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_data_observations.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_default.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_experimental_methods.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_imaging.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_index_file.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_medical_history.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_metadata.svg create mode 100755 config/icons/dataDictionary/dictionary_icon_notation.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_study_administration.svg create mode 100644 config/icons/dataDictionary/dictionary_icon_subject_characteristics.svg delete mode 100644 config/icons/download.svg rename config/icons/{ => gen3}/aiSearch.svg (100%) rename config/icons/{ => gen3}/analysis.svg (100%) rename config/icons/{ => gen3}/bar-chart.svg (100%) create mode 100644 config/icons/gen3/chevron-contract.svg rename config/icons/{ => gen3}/chevron-down.svg (100%) create mode 100644 config/icons/gen3/chevron-expand.svg create mode 100644 config/icons/gen3/comparison.svg rename config/icons/{ => gen3}/datafile.svg (100%) rename config/icons/{ => gen3}/dictionary.svg (100%) create mode 100644 config/icons/gen3/download.svg rename config/icons/{ => gen3}/exploration.svg (100%) rename config/icons/{ => gen3}/gen3-dark.svg (100%) rename config/icons/{ => gen3}/gen3.svg (100%) create mode 100644 config/icons/gen3/jupyter.svg create mode 100644 config/icons/gen3/loginArrowCircle.svg rename config/icons/{ => gen3}/loginCircle.svg (100%) create mode 100644 config/icons/gen3/not-found.svg create mode 100644 config/icons/gen3/notebook.svg create mode 100644 config/icons/gen3/open_in_modal.svg rename config/icons/{ => gen3}/profile.svg (100%) rename config/icons/{ => gen3}/query.svg (100%) create mode 100755 config/icons/gen3/upload.svg rename config/icons/{ => gen3}/user.svg (100%) rename config/icons/{ => gen3}/workspace.svg (100%) delete mode 100755 config/icons/upload.svg create mode 100644 config/icons/workspace.json create mode 100644 config/icons/workspace/galaxy.svg create mode 100644 config/icons/workspace/jupyter.svg create mode 100644 config/icons/workspace/rlogo.svg create mode 100644 config/icons/workspace/rstudio.svg delete mode 100644 config/siteConfig.json delete mode 100644 config/themeFonts.json create mode 100644 src/lib/CohortBuilder/FileDetailsPanel.tsx create mode 100644 src/lib/Discovery/Filemap.tsx create mode 100644 src/lib/Grafana/grafana.ts create mode 100644 src/lib/content/loadContent.ts create mode 100644 src/pages/Analysis.tsx create mode 100644 src/pages/Crosswalk.tsx create mode 100644 src/pages/DataLibrary.tsx create mode 100644 src/pages/NotebookLite.tsx create mode 100644 src/pages/Submission.tsx create mode 100644 src/pages/Workspace.tsx create mode 100644 src/pages/api/auth/sessionLogout.ts create mode 100644 src/pages/app/[appName].tsx create mode 100644 src/pages/no-workspace-access.tsx delete mode 100755 start.sh diff --git a/.env.production b/.env.production deleted file mode 100644 index af0acff..0000000 --- a/.env.production +++ /dev/null @@ -1,4 +0,0 @@ -BASE_PATH=/ff -GEN3_COMMONS_NAME=brh -NEXT_PUBLIC_GEN3_API='https://brhstaging.data-commons.org' -NEXT_PUBLIC_GEN3_AI_SEARCH_API='https://brhstaging.data-commons.org/ai' diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..016e34b --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v20.17.0 diff --git a/Dockerfile b/Dockerfile index fa1eb29..a513973 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,61 +1,30 @@ -# docker build -t gen3ff . -# docker run -p 3000:3000 -it gen3ff -# for Macbook silicon M1/m2 uncomment the following lines and comment quay.io/cdis/ubuntu:20.04: -#FROM arm64v8/ubuntu:20.04 as build +# Build stage +FROM node:20-slim AS builder -FROM quay.io/cdis/ubuntu:20.04 as build - -ARG NODE_VERSION=20 +WORKDIR /gen3 -ENV DEBIAN_FRONTEND=noninteractive +COPY ./package.json ./package-lock.json ./next.config.js ./tsconfig.json ./.env.development ./tailwind.config.js ./postcss.config.js ./ +RUN npm ci +COPY ./src ./src +COPY ./public ./public +COPY ./config ./config +RUN npm install @swc/core @napi-rs/magic-string && \ + npm run build -ARG BASE_PATH -ARG NEXT_PUBLIC_PORTAL_BASENAME -ENV NPM_CONFIG_PREFIX=/home/node/.npm-global -ENV PATH=$PATH:/home/node/.npm-global/bin +# Production stage +FROM node:20-slim AS runner WORKDIR /gen3 +ENV PORT=3000 -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - libssl1.1 \ - libgnutls30 \ - ca-certificates \ - curl \ - git \ - gnupg \ - nginx \ - python3 \ - time \ - vim \ - && mkdir -p /etc/apt/keyrings \ - && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ - && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \ - && apt-get update \ - && apt-get install -y nodejs \ - && apt-get clean \ - && rm -rf /var/src/apt/lists/* \ - && ln -sf /dev/stdout /var/log/nginx/access.log \ - && ln -sf /dev/stderr /var/log/nginx/error.log \ - && npm install -g npm@10.2.4 +RUN addgroup --system --gid 1001 nextjs && \ + adduser --system --uid 1001 nextjs -RUN addgroup --system --gid 1001 nextjs && adduser --system --uid 1001 nextjs -COPY ./package.json ./package-lock.json ./ -COPY ./package-lock.json ./ -COPY ./src ./src -COPY ./public ./public -COPY ./config ./config -COPY ./next.config.js ./ -COPY ./tsconfig.json ./ -COPY ./.env.development ./ -COPY ./.env.production ./ -COPY ./tailwind.config.js ./ -COPY ./postcss.config.js ./ -COPY ./start.sh ./ -RUN npm ci -RUN npm install \ - "@swc/core" \ - "@napi-rs/magic-string" -RUN npm run build +COPY --from=builder /gen3/config ./config +COPY --from=builder /gen3/public ./public +COPY --from=builder /gen3/.next/standalone ./ +COPY --from=builder /gen3/.next/static ./.next/static + +USER nextjs ENV PORT=3000 -CMD bash ./start.sh +CMD ["node", "server.js"] diff --git a/config/brh/dataLibrary.json b/config/brh/dataLibrary.json new file mode 100644 index 0000000..bb55a81 --- /dev/null +++ b/config/brh/dataLibrary.json @@ -0,0 +1,32 @@ +{ + "useAPI": true, + "actions": [ + { + "id": "exportTerra", + "label": "Export to Terra", + "rules": [ + { + "field": "type", + "operator": "equals", + "value": "terraform" + }, + { + "field": "type", + "operator": "count", + "value": 1 + } + ] + }, + { + "id": "exportZip", + "label": "Export to ZIP", + "rules": [ + { + "field": "type", + "operator": "equals", + "value": "csv" + } + ] + } + ] +} diff --git a/config/brh/discovery.json b/config/brh/discovery.json index 74740a0..64a4845 100644 --- a/config/brh/discovery.json +++ b/config/brh/discovery.json @@ -1,284 +1,290 @@ { - "tableConfig": { - "selectableRows": true, - "expandableRows": true - }, - "features": { - "dataFetchFunction": "AggMDSAllLocal", - "aiSearch" : true, - "advSearchFilters": { - "enabled": false, - "field": "advSearchFilters", - "displayName": "Filters", - "filters": [ - { - "key": "Research Focus Area" + "metadataConfig": [ + { + "tableConfig": { + "selectableRows": true, + "expandableRows": true + }, + "features": { + "dataFetchFunction": "AggMDSAllLocal", + "aiSearch": true, + "advSearchFilters": { + "enabled": false, + "field": "advSearchFilters", + "displayName": "Filters", + "filters": [ + { + "key": "Research Focus Area" + }, + { + "key": "Administering IC(s)" + }, + { + "key": "Simulated vs. Real Data" + }, + { + "key": "Year Grant Awarded" + }, + { + "key": "Study Description" + } + ] }, - { - "key": "Administering IC(s)" + "pageTitle": { + "enabled": false, + "text": "Study Discovery" }, - { - "key": "Simulated vs. Real Data" + "tagsColumn": { + "enabled": false }, + "tagsInDescription": { + "enabled": true + }, + "search": { + "searchBar": { + "enabled": true, + "searchableTextFields": [ + "short_name", + "full_name", + "study_description", + "study_id" + ] + }, + "tagSearchDropdown": { + "enabled": true, + "collapsibleButtonText": "Data Commons" + }, + "exportToWorkspace": { + "enabled": true, + "manifestFieldName": "__manifest", + "enableDownloadManifest": true, + "downloadManifestButtonText": "Download", + "documentationLinks": { + "gen3Client": "https://gen3.org/resources/user/gen3-client/", + "gen3Workspaces": "https://gen3.org/resources/user/analyze-data/" + } + } + }, + "authorization": { + "enabled": true, + "columnTooltip": "Filter by data access. Accessible indicates you are authorized to access. Not accessible indicates you are not authorized to access.", + "supportedValues": { + "accessible": { + "enabled": true, + "menuText": "Available" + }, + "unaccessible": { + "enabled": false, + "menuText": "Not Accessible" + }, + "pending": { + "enabled": false, + "menuText": "Pending" + }, + "notAvailable": { + "enabled": false, + "menuText": "Not Available" + } + } + } + }, + "aggregations": [ { - "key": "Year Grant Awarded" + "name": "Studies", + "field": "_unique_id", + "type": "count" }, { - "key": "Study Description" + "name": "Total Subjects", + "field": "_subjects_count", + "type": "sum" } - ] - }, - "pageTitle": { - "enabled": false, - "text": "Study Discovery" - }, - "tagsColumn": { - "enabled": false - }, - "tagsInDescription": { - "enabled": true - }, - "search": { - "searchBar": { - "enabled": true, - "searchableTextFields": [ - "short_name", - "full_name", - "study_description", - "study_id" - ] + ], + "tagSelector": { + "title": "Tags by category" }, - "tagSearchDropdown": { - "enabled": true, - "collapsibleButtonText": "Data Commons" - }, - "exportToWorkspace": { - "enabled": true, - "manifestFieldName": "__manifest", - "enableDownloadManifest": true, - "downloadManifestButtonText": "Download", - "documentationLinks": { - "gen3Client": "https://gen3.org/resources/user/gen3-client/", - "gen3Workspaces": "https://gen3.org/resources/user/analyze-data/" - } - } - }, - "authorization": { - "enabled": true, - "columnTooltip": "Filter by data access. Accessible indicates you are authorized to access. Not accessible indicates you are not authorized to access.", - "supportedValues": { - "accessible": { - "enabled": true, - "menuText": "Available" + "studyColumns": [ + { + "name": "Study Name", + "field": "short_name", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a", + "width": "157px", + "contentType": "string" }, - "unaccessible": { - "enabled": false, - "menuText": "Not Accessible" + { + "name": "Full Name", + "field": "full_name", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a", + "width": "400px", + "contentType": "string" }, - "pending": { - "enabled": false, - "menuText": "Pending" + { + "name": "Number of Subjects", + "field": "_subjects_count", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a", + "contentType": "number", + "width": "98px" }, - "notAvailable": { - "enabled": false, - "menuText": "Not Available" + { + "name": "ID Number", + "field": "study_id", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a", + "width": "152px", + "contentType": "string" + }, + { + "name": "Data Commons", + "field": "commons", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a", + "contentType": "link", + "cellRenderFunction": "withURL", + "params": { + "hrefValueFromField": "commons_url" + } + }, + { + "name": "DATA ACCESS METHOD", + "field": "data_access_method", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "API", + "contentType": "string" } - } - } - }, - "aggregations": [ - { - "name": "Studies", - "field": "_unique_id", - "type": "count" - }, - { - "name": "Total Subjects", - "field": "_subjects_count", - "type": "sum" - } - ], - "tagSelector": { - "title": "Tags by category" - }, - "studyColumns": [ - { - "name": "Study Name", - "field": "short_name", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "n/a", - "width": "157px", - "contentType": "string" - }, - { - "name": "Full Name", - "field": "full_name", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "n/a", - "width": "400px", - "contentType": "string" - }, - { - "name": "Number of Subjects", - "field": "_subjects_count", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "n/a", - "contentType": "number", - "width": "98px" - }, - { - "name": "ID Number", - "field": "study_id", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "n/a", - "width": "152px", - "contentType": "string" - }, - { - "name": "Data Commons", - "field": "commons", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "n/a", - "contentType": "link", - "cellRenderFunction": "withURL", - "params": { - "hrefValueFromField": "commons_url" - } - }, - { - "name": "DATA ACCESS METHOD", - "field": "data_access_method", - "errorIfNotAvailable": false, - "valueIfNotAvailable": "API", - "contentType": "string" - } - ], - "studyPreviewField": { - "name": "Description", - "field": "study_description", - "contentType": "string", - "includeName": false, - "includeIfNotAvailable": true, - "valueIfNotAvailable": "No description has been provided for this study." - }, - "simpleDetailsView": { - "showAllAvailableFields": false, - "header": { - "field": "name" - }, - "fieldsToShow": [ - { - "groupName": "Study Identifiers", - "groupWidth": "half", + ], + "studyPreviewField": { + "name": "Description", + "field": "study_description", + "contentType": "string", "includeName": false, - "fields": [ + "includeIfNotAvailable": true, + "valueIfNotAvailable": "No description has been provided for this study." + }, + "simpleDetailsView": { + "showAllAvailableFields": false, + "header": { + "field": "name" + }, + "fieldsToShow": [ { - "name": "Number of Subjects", - "field": "_subjects_count", - "contentType": "number" + "groupName": "Study Identifiers", + "groupWidth": "half", + "includeName": false, + "fields": [ + { + "name": "Number of Subjects", + "field": "_subjects_count", + "contentType": "number" + }, + { + "name": "Full Name", + "field": "full_name", + "contentType": "string" + }, + { + "name": "Short Name", + "field": "short_name", + "contentType": "text", + "includeName": true, + "includeIfNotAvailable": true, + "valueIfNotAvailable": "N/A" + }, + { + "name": "dbGaP Accession Number", + "field": "dbgap_accession", + "contentType": "text", + "includeName": true, + "includeIfNotAvailable": false + }, + { + "name": "Project ID", + "field": "project_id", + "contentType": "text", + "includeIfNotAvailable": false + }, + { + "name": "Data Commons", + "field": "commons", + "contentType": "text", + "includeIfNotAvailable": false + }, + { + "name": "Tutorial Notebook", + "field": "tutorial_notebook", + "contentType": "text", + "includeIfNotAvailable": true, + "valueIfNotAvailable": "NO" + } + ] }, { - "name": "Full Name", - "field": "full_name", - "contentType": "string" + "groupWidth": "full", + "fields": [ + { + "name": "Description", + "field": "study_description", + "contentType": "paragraphs", + "includeName": true, + "includeIfNotAvailable": true, + "valueIfNotAvailable": "No description has been provided for this study." + } + ] + } + ] + }, + "minimalFieldMapping": { + "tagsListFieldName": "tags", + "authzField": "authz", + "uid": "_unique_id" + }, + "tags": { + "tagCategories": [ + { + "name": "Commons", + "displayName": "Data Commons", + "color": "rgba(129, 211, 248, 1)", + "display": true }, { - "name": "Short Name", - "field": "short_name", - "contentType": "text", - "includeName": true, - "includeIfNotAvailable": true, - "valueIfNotAvailable": "N/A" + "name": "Program", + "color": "rgba(129, 211, 248, 1)", + "display": false }, { - "name": "dbGaP Accession Number", - "field": "dbgap_accession", - "contentType": "text", - "includeName": true, - "includeIfNotAvailable": false + "name": "Study Registration", + "color": "rgba(236, 128, 141, 1)", + "display": false }, { - "name": "Project ID", - "field": "project_id", - "contentType": "text", - "includeIfNotAvailable": false + "name": "Data Type", + "color": "rgba(112, 182, 3, 1)", + "display": false }, { - "name": "Data Commons", - "field": "commons", - "contentType": "text", - "includeIfNotAvailable": false + "name": "primary_site", + "color": "rgba(112, 182, 3, 1)", + "display": false }, { - "name": "Tutorial Notebook", - "field": "tutorial_notebook", - "contentType": "text", - "includeIfNotAvailable": true, - "valueIfNotAvailable": "NO" - } - ] - }, - { - "groupWidth": "full", - "fields": [ + "name": "disease_type", + "color": "rgba(112, 182, 3, 1)", + "display": false + }, + { + "name": "data_type", + "color": "rgba(112, 182, 3, 1)", + "display": false + }, { - "name": "Description", - "field": "study_description", - "contentType": "paragraphs", - "includeName": true, - "includeIfNotAvailable": true, - "valueIfNotAvailable": "No description has been provided for this study." + "name": "clinical_study_type", + "color": "rgba(112, 182, 3, 1)", + "display": false } ] } - ] - }, - "minimalFieldMapping": { - "tagsListFieldName": "tags", - "authzField": "authz", - "uid": "_unique_id" - }, - "tagCategories": [ - { - "name": "Commons", - "displayName": "Data Commons", - "color": "rgba(129, 211, 248, 1)", - "display": true - }, - { - "name": "Program", - "color": "rgba(129, 211, 248, 1)", - "display": false - }, - { - "name": "Study Registration", - "color": "rgba(236, 128, 141, 1)", - "display": false - }, - { - "name": "Data Type", - "color": "rgba(112, 182, 3, 1)", - "display": false - }, - { - "name": "primary_site", - "color": "rgba(112, 182, 3, 1)", - "display": false - }, - { - "name": "disease_type", - "color": "rgba(112, 182, 3, 1)", - "display": false - }, - { - "name": "data_type", - "color": "rgba(112, 182, 3, 1)", - "display": false - }, - { - "name": "clinical_study_type", - "color": "rgba(112, 182, 3, 1)", - "display": false } ] } diff --git a/config/brh/footer.json b/config/brh/footer.json index 536db1a..6bbf956 100644 --- a/config/brh/footer.json +++ b/config/brh/footer.json @@ -1,21 +1,36 @@ { "classNames": { - "root": "bg-base-darkest" + "root": "bg-base-darker", + "layout": "flex items-center justify-end" }, - "footerRightLogos": [ - [ - { - "logo": "/ff/icons/gen3.png", - "width": 132, - "height": 60, - "description": "Gen3 Logo" - }, - { - "logo": "/ff/icons/createdby.png", - "width": 170, - "height": 60, - "description": "Created by CTDS" - } + "rightSection": + { + "columns": [ + { + "rows": [ + { + "Icon": { + "logo": "/icons/gen3.png", + "width": 132, + "height": 60, + "description": "Gen3 Logo" + } + } + ] + }, + { + "rows": [ + { + "Icon": { + "logo": "/icons/createdby.png", + "width": 170, + "height": 60, + "description": "Created by CTDS" + } + } + ] + } ] - ] + } + } diff --git a/config/brh/landingPage.json b/config/brh/landingPage.json index c57e614..306be39 100644 --- a/config/brh/landingPage.json +++ b/config/brh/landingPage.json @@ -15,14 +15,14 @@ { "link": { "href": "/Discovery", - "text": "Discover Data" + "text": "Discovery Data" } } ], "right": [ { "image": { - "src": "https://gen3.org/figs/kv.svg", + "src": "/images/kv.svg", "alt": "Gen3 Data Platform" } } diff --git a/config/brh/login.json b/config/brh/login.json index a076d62..f999560 100644 --- a/config/brh/login.json +++ b/config/brh/login.json @@ -1,25 +1,25 @@ { - "topContent": [ - { - "text": "Biomedical Research Hub", - "className": "text-center text-3xl font-bold" - }, - { - "text": "Discover, Analyze, and Share Data", - "className": "text-center text-xl font-medium" - }, - { - "text": "The Biomedical Research Hub (BRH) is a standard-based data ecosystem for securely managing, analyzing and sharing biomedical data to support research communities and collaborations.", - "className": "text-center text-sm" - } - ], - "bottomContent": [ - { - "text": "If you have any questions about access or the registration process, please contact ", - "className": "text-center text-sm" - } - ], - "image": "images/brh/gene_bgy.png", - "email": "brhsupport@datacommons.io", - "showCredentialsLogin" : false - } + "topContent": [ + { + "text": "Biomedical Research Hub", + "className": "text-center text-3xl font-bold" + }, + { + "text": "Discover, Analyze, and Share Data", + "className": "text-center text-xl font-medium" + }, + { + "text": "The Biomedical Research Hub (BRH) is a standard-based data ecosystem for securely managing, analyzing and sharing biomedical data to support research communities and collaborations.", + "className": "text-center text-sm" + } + ], + "bottomContent": [ + { + "text": "If you have any questions about access or the registration process, please contact ", + "className": "text-center text-sm" + } + ], + "image": "images/brh/gene_bgy.png", + "email": "brhsupport@datacommons.io", + "showCredentialsLogin" : true +} diff --git a/config/modals.json b/config/brh/modals.json similarity index 98% rename from config/modals.json rename to config/brh/modals.json index 3122ceb..8eb9663 100644 --- a/config/modals.json +++ b/config/brh/modals.json @@ -1,6 +1,5 @@ { "systemUseModal": { - "enabled": false, "title": "Data Use Agreement for Academic and Institutional Users", "content": { "text": [ diff --git a/config/brh/navigation.json b/config/brh/navigation.json index 5423098..a21d0d6 100644 --- a/config/brh/navigation.json +++ b/config/brh/navigation.json @@ -1,42 +1,38 @@ { "navigation": { + "classNames": { + "root": "pl-1 mr-6 bg-base-max text-primary opacity-100 hover:opacity-100", + "item": "py-2 px-4 hover:bg-base-lightest hover:text-base-contrast", + "navigationPanel": "bg-base-max text-primary" + }, "logo": { - "src": "/ff/images/brh/logo.png", + "src": "/images/brh/logo.png", "height": 256, - "href": "https://brhstaging.data-commons.org/" + "width": 320, + "href": "/Discovery" }, "items": [ { "icon": "gen3:query", - "href": "https://brhstaging.data-commons.org/discovery", + "href": "/Discovery", "name": "Discovery", - "classNames" : { - "root": "border-opacity-50 border-blue", - "button": "hover:border-white" - }, "tooltip": "Use free-text search and tags to rapidly find relevant studies, discover new datasets across multiple resources, and easily export selected data files to the analysis workspace." }, - { - "icon": "gen3:aisearch", - "href": "/AISearch", - "name": "AI Search - Beta", - "tooltip": "Use AI Based search to find relevant studies using a chat-like interface." - }, { "name": "Workspace", - "href": "https://brhstaging.data-commons.org/workspace", + "href": "/Workspace", "icon": "gen3:workspace", "tooltip": "Gen3 workspaces are secure data analysis environments in the cloud that can access data from one or more data resources." }, { - "name": "Example Analysis", - "href": "https://brhstaging.data-commons.org/resource-browser", - "icon": "gen3:bar-chart", - "tooltip": "Learn how to use Jupyter Notebooks to explore and visualize data discovered in the Biomedical Research Hub by running a static tutorial notebook, or use one of these examples as a launching point for your own custom analysis." + "name": "Notebooks", + "href": "/NotebookLite", + "icon": "gen3:notebook", + "tooltip": "Notebooks for basic analysis" }, { "icon": "gen3:profile", - "href": "https://brhstaging.data-commons.org/identity", + "href": "/Profile", "name": "Profile", "tooltip": "Create API keys for programmatic data access, and review your authorization privileges to datasets and services." } @@ -48,32 +44,35 @@ "link": "https://uc-cdis.github.io/BRH-documentation/", "name": "Documentation", "classNames": { - "root": "border-blue border-opacity-50", - "label": "text-white font-bold text-sm", - "button": "hover:border-white mx-4" + "root": "border-base-light", + "label": "text-white", + "button": "hover:border-white" } }, { "link": "brhsupport@datacommons.io", "name": "Email Support", "classNames": { - "root": "border-base-lighter ", - "label": "text-white font-bold text-sm", - "button": "hover:border-white mx-4" + "root": "border-base-light", + "label": "text-white", + "button": "hover:border-white" } }, { "link": "https://uc-cdis.github.io/platform-citation/brh-cite/", "name": "Cite BRH", "classNames": { - "label": "text-white font-bold text-sm", - "button": "hover:border-white mx-4 mr-[64px]" + "root": "border-base-light", + "label": "text-white", + "button": "hover:border-white" } } ], - "showLogin": false, + "loginButtonVisibility": "visible", "classNames": { - "root": "bg-primary" + "root": "border-base-light text-primary-contrast-dark", + "label": "text-primary-contrast", + "button": "hover:border-white" } } } diff --git a/config/brh/profile.json b/config/brh/profile.json index 1696966..9428194 100644 --- a/config/brh/profile.json +++ b/config/brh/profile.json @@ -1,4 +1,5 @@ { + "hasExternalLogins" : true, "resourceTable": { "serviceColors": { "guppy": { diff --git a/config/brh/query.json b/config/brh/query.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/config/brh/query.json @@ -0,0 +1,2 @@ +{ +} diff --git a/config/session.json b/config/brh/session.json similarity index 51% rename from config/session.json rename to config/brh/session.json index fd92023..fe88d99 100644 --- a/config/session.json +++ b/config/brh/session.json @@ -1,7 +1,5 @@ { - "sessionConfig" : { "updateSessionTime": 5, "inactiveTimeLimit": 20, - "logoutInactiveUsers": true - } + "logoutInactiveUsers": false } diff --git a/config/brh/submission.json b/config/brh/submission.json new file mode 100644 index 0000000..18f6c32 --- /dev/null +++ b/config/brh/submission.json @@ -0,0 +1,30 @@ +{ + "projectTable": { + "columns": [ + { + "name": "Subjects", + "field": "_subject_count", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a" + }, + { + "name": "Studies", + "field": "_study_count", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a" + }, + { + "name": "Aliquots", + "field": "_aliquot_count", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a" + }, + { + "name": "Files", + "field": "_genotyping_array_count", + "errorIfNotAvailable": false, + "valueIfNotAvailable": "n/a" + } + ] + } +} diff --git a/config/themeColors.json b/config/brh/themeColors.json similarity index 80% rename from config/themeColors.json rename to config/brh/themeColors.json index 12483f5..424cda9 100644 --- a/config/themeColors.json +++ b/config/brh/themeColors.json @@ -1,147 +1,147 @@ { "primary": { + "max": "#eaf3fa", + "lightest": "#bcd7ed", + "lighter": "#1f839b", + "light": "#609fd4", "DEFAULT": "#3283C8", "vivid": "#2584d4", - "min": "#050d14", - "darkest": "#102b41", - "darker": "#1c486e", "dark": "#27669b", - "light": "#609fd4", - "lighter": "#8ebbe1", - "lightest": "#bcd7ed", - "max": "#eaf3fa" + "darker": "#1c486e", + "darkest": "#102b41", + "min": "#050d14" }, "primary-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#111111", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "secondary": { + "max": "#eaf3fa", + "lightest": "#bcd7ed", + "lighter": "#0197e1", + "light": "#609fd4", "DEFAULT": "#3283C8", "vivid": "#2584d4", - "min": "#050d14", - "darkest": "#102b41", - "darker": "#1c486e", "dark": "#27669b", - "light": "#609fd4", - "lighter": "#8ebbe1", - "lightest": "#bcd7ed", - "max": "#eaf3fa" + "darker": "#1c486e", + "darkest": "#102b41", + "min": "#050d14" }, "secondary-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#111111", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "accent": { + "max": "#f8eee7", + "lightest": "#e8c6b2", + "lighter": "#d79f7d", + "light": "#c77848", "DEFAULT": "#b75113", "vivid": "#c14f09", - "min": "#120802", - "darkest": "#3b1a06", - "darker": "#652d0a", "dark": "#8e3f0f", - "light": "#c77848", - "lighter": "#d79f7d", - "lightest": "#e8c6b2", - "max": "#f8eee7" + "darker": "#652d0a", + "darkest": "#3b1a06", + "min": "#120802" }, "accent-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#fefefe", "vivid": "#fefefe", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "accent-warm": { + "max": "#e9f3f5", + "lightest": "#b8d8df", + "lighter": "#87bcc8", + "light": "#56a1b2", "DEFAULT": "#25869b", "vivid": "#1b8ca5", - "min": "#040d0f", - "darkest": "#0c2c32", - "darker": "#144a55", "dark": "#1d6878", - "light": "#56a1b2", - "lighter": "#87bcc8", - "lightest": "#b8d8df", - "max": "#e9f3f5" + "darker": "#144a55", + "darkest": "#0c2c32", + "min": "#040d0f" }, "accent-warm-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#000000", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "accent-cool": { + "max": "#e9f3f5", + "lightest": "#b6d7df", + "lighter": "#84bbc8", + "light": "#519fb2", "DEFAULT": "#1f839b", "vivid": "#1689a4", - "min": "#030d0f", - "darkest": "#0a2b32", - "darker": "#114855", "dark": "#186678", - "light": "#519fb2", - "lighter": "#84bbc8", - "lightest": "#b6d7df", - "max": "#e9f3f5" + "darker": "#114855", + "darkest": "#0a2b32", + "min": "#030d0f" }, "accent-cool-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#000000", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "base": { + "max": "#f9f9f9", + "lightest": "#ebebeb", + "lighter": "#dcdcdc", + "light": "#cecece", "DEFAULT": "#c0c0c0", "vivid": "#c6baba", - "min": "#131313", - "darkest": "#4A4A4A", - "darker": "#6a6a6a", "dark": "#959595", - "light": "#cecece", - "lighter": "#dcdcdc", - "lightest": "#ebebeb", - "max": "#f9f9f9" + "darker": "#6a6a6a", + "darkest": "#3e3e3e", + "min": "#131313" }, "base-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#111111", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#111111", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "utility": { "link": "#155276", @@ -168,51 +168,60 @@ "category4": "#1b1b1b" }, "chart": { + "max": "#e7f4f6", + "lightest": "#b0dde0", + "lighter": "#7ac5cb", + "light": "#43adb6", "DEFAULT": "#0d95A1", "vivid": "#049caa", - "min": "#010f10", - "darkest": "#043034", - "darker": "#075259", "dark": "#0a737d", - "light": "#43adb6", - "lighter": "#7ac5cb", - "lightest": "#b0dde0", - "max": "#e7f4f6" + "darker": "#075259", + "darkest": "#043034", + "min": "#010f10" }, "chart-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#111111", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#fefefe", - "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" }, "table": { + "max": "#f9f9f9", + "lightest": "#ebebeb", + "lighter": "#dcdcdc", + "light": "#cecece", "DEFAULT": "#c0c0c0", "vivid": "#c6baba", - "min": "#131313", - "darkest": "#3e3e3e", - "darker": "#6a6a6a", "dark": "#959595", - "light": "#cecece", - "lighter": "#dcdcdc", - "lightest": "#ebebeb", - "max": "#f9f9f9" + "darker": "#6a6a6a", + "darkest": "#3e3e3e", + "min": "#131313" }, - "tablePallet-contrast": { + "table-contrast": { + "max": "#111111", + "lightest": "#111111", + "lighter": "#111111", + "light": "#111111", "DEFAULT": "#111111", "vivid": "#111111", - "min": "#fefefe", - "darkest": "#fefefe", - "darker": "#fefefe", "dark": "#111111", + "darker": "#fefefe", + "darkest": "#fefefe", + "min": "#fefefe" + }, + "navigation": { + "footer": "#373A3C", + "topbar_hover": "#FFFFFF", "light": "#111111", - "lighter": "#111111", - "lightest": "#111111", - "max": "#111111" - } + "DEFAULT": "#111111", + "dark": "#111111", + "darker": "#111111", + "darkest": "#111111", + "min": "#111111"} } diff --git a/config/brh/themeFonts.json b/config/brh/themeFonts.json new file mode 100644 index 0000000..f40ccb8 --- /dev/null +++ b/config/brh/themeFonts.json @@ -0,0 +1,5 @@ +{ + "heading": ["Poppins", "sans-serif"], + "content": ["Poppins", "sans-serif"], + "fontFamily": "Poppins" +} diff --git a/config/brh/workspace.json b/config/brh/workspace.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/config/brh/workspace.json @@ -0,0 +1,2 @@ +{ +} diff --git a/config/icons/color.json b/config/icons/color.json new file mode 100644 index 0000000..852e13a --- /dev/null +++ b/config/icons/color.json @@ -0,0 +1,28 @@ +{ + "prefix": "color", + "lastModified": 1724107947, + "icons": { + "analysis": { + "body": "", + "width": 64, + "height": 64 + }, + "discovery": { + "body": "", + "top": -13 + }, + "explorer": { + "body": "", + "left": -30, + "width": 511 + }, + "profile": { + "body": "" + }, + "workspaces": { + "body": "" + } + }, + "width": 512, + "height": 512 +} diff --git a/config/icons/color/analysis.svg b/config/icons/color/analysis.svg new file mode 100644 index 0000000..877872c --- /dev/null +++ b/config/icons/color/analysis.svg @@ -0,0 +1 @@ + diff --git a/config/icons/color/discovery.svg b/config/icons/color/discovery.svg new file mode 100644 index 0000000..2fe223a --- /dev/null +++ b/config/icons/color/discovery.svg @@ -0,0 +1 @@ + diff --git a/config/icons/color/explorer.svg b/config/icons/color/explorer.svg new file mode 100644 index 0000000..7cfe2d0 --- /dev/null +++ b/config/icons/color/explorer.svg @@ -0,0 +1 @@ + diff --git a/config/icons/color/profile.svg b/config/icons/color/profile.svg new file mode 100644 index 0000000..0fb33c8 --- /dev/null +++ b/config/icons/color/profile.svg @@ -0,0 +1 @@ + diff --git a/config/icons/color/workspaces.svg b/config/icons/color/workspaces.svg new file mode 100644 index 0000000..d073469 --- /dev/null +++ b/config/icons/color/workspaces.svg @@ -0,0 +1 @@ + diff --git a/config/icons/dataDictionary.json b/config/icons/dataDictionary.json new file mode 100644 index 0000000..7bf0508 --- /dev/null +++ b/config/icons/dataDictionary.json @@ -0,0 +1,58 @@ +{ + "prefix": "dataDictionary", + "lastModified": 1724107947, + "icons": { + "dictionary-icon-administrative": { + "body": "" + }, + "dictionary-icon-analysis": { + "body": "", + "height": 21 + }, + "dictionary-icon-biospecimen": { + "body": "" + }, + "dictionary-icon-clinical": { + "body": "" + }, + "dictionary-icon-clinical-assessment": { + "body": "" + }, + "dictionary-icon-data-file": { + "body": "" + }, + "dictionary-icon-data-observations": { + "body": "" + }, + "dictionary-icon-default": { + "body": "", + "height": 21 + }, + "dictionary-icon-experimental-methods": { + "body": "" + }, + "dictionary-icon-imaging": { + "body": "" + }, + "dictionary-icon-index-file": { + "body": "" + }, + "dictionary-icon-medical-history": { + "body": "" + }, + "dictionary-icon-metadata": { + "body": "" + }, + "dictionary-icon-notation": { + "body": "" + }, + "dictionary-icon-study-administration": { + "body": "" + }, + "dictionary-icon-subject-characteristics": { + "body": "" + } + }, + "width": 20, + "height": 20 +} diff --git a/config/icons/dataDictionary/dictionary_icon_administrative.svg b/config/icons/dataDictionary/dictionary_icon_administrative.svg new file mode 100755 index 0000000..34b2184 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_administrative.svg @@ -0,0 +1,16 @@ + + + + icon-administrative + Created with Sketch. + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_analysis.svg b/config/icons/dataDictionary/dictionary_icon_analysis.svg new file mode 100755 index 0000000..df8b2ec --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_analysis.svg @@ -0,0 +1,13 @@ + + + + icon_analysis + Created with Sketch. + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_biospecimen.svg b/config/icons/dataDictionary/dictionary_icon_biospecimen.svg new file mode 100755 index 0000000..bdeea3b --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_biospecimen.svg @@ -0,0 +1,11 @@ + + + + icon_Biospecimen + Created with Sketch. + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_clinical.svg b/config/icons/dataDictionary/dictionary_icon_clinical.svg new file mode 100755 index 0000000..69d2882 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_clinical.svg @@ -0,0 +1,13 @@ + + + + hospital + Created with Sketch. + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_clinical_assessment.svg b/config/icons/dataDictionary/dictionary_icon_clinical_assessment.svg new file mode 100755 index 0000000..49756c8 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_clinical_assessment.svg @@ -0,0 +1,20 @@ + + + + icon_clinical_assessment + Created with Sketch. + + + + + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_data_file.svg b/config/icons/dataDictionary/dictionary_icon_data_file.svg new file mode 100755 index 0000000..0284e37 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_data_file.svg @@ -0,0 +1,15 @@ + + + + icon_data_file + Created with Sketch. + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_data_observations.svg b/config/icons/dataDictionary/dictionary_icon_data_observations.svg new file mode 100644 index 0000000..5b80e47 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_data_observations.svg @@ -0,0 +1,14 @@ + + + + Group 22 + Created with Sketch. + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_default.svg b/config/icons/dataDictionary/dictionary_icon_default.svg new file mode 100644 index 0000000..90f8248 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_default.svg @@ -0,0 +1,16 @@ + + + + Group 47 + Created with Sketch. + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_experimental_methods.svg b/config/icons/dataDictionary/dictionary_icon_experimental_methods.svg new file mode 100644 index 0000000..cc0b4fc --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_experimental_methods.svg @@ -0,0 +1,11 @@ + + + + Group 23 + Created with Sketch. + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_imaging.svg b/config/icons/dataDictionary/dictionary_icon_imaging.svg new file mode 100644 index 0000000..8a96d61 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_imaging.svg @@ -0,0 +1,11 @@ + + + + Group 19 + Created with Sketch. + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_index_file.svg b/config/icons/dataDictionary/dictionary_icon_index_file.svg new file mode 100644 index 0000000..dab9dd4 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_index_file.svg @@ -0,0 +1,16 @@ + + + + Group + Created with Sketch. + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_medical_history.svg b/config/icons/dataDictionary/dictionary_icon_medical_history.svg new file mode 100755 index 0000000..69d2882 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_medical_history.svg @@ -0,0 +1,13 @@ + + + + hospital + Created with Sketch. + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_metadata.svg b/config/icons/dataDictionary/dictionary_icon_metadata.svg new file mode 100755 index 0000000..5f40962 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_metadata.svg @@ -0,0 +1,16 @@ + + + + icon_metadata + Created with Sketch. + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_notation.svg b/config/icons/dataDictionary/dictionary_icon_notation.svg new file mode 100755 index 0000000..d546f7d --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_notation.svg @@ -0,0 +1,12 @@ + + + + icon_notation + Created with Sketch. + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_study_administration.svg b/config/icons/dataDictionary/dictionary_icon_study_administration.svg new file mode 100644 index 0000000..3fce02a --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_study_administration.svg @@ -0,0 +1,16 @@ + + + + Group 21 + Created with Sketch. + + + + + + + + + + + diff --git a/config/icons/dataDictionary/dictionary_icon_subject_characteristics.svg b/config/icons/dataDictionary/dictionary_icon_subject_characteristics.svg new file mode 100644 index 0000000..3da1d98 --- /dev/null +++ b/config/icons/dataDictionary/dictionary_icon_subject_characteristics.svg @@ -0,0 +1,14 @@ + + + + Group 20 + Created with Sketch. + + + + + + + + + diff --git a/config/icons/download.svg b/config/icons/download.svg deleted file mode 100644 index 22a2656..0000000 --- a/config/icons/download.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/config/icons/gen3.json b/config/icons/gen3.json index 7f6e875..26d4c6a 100644 --- a/config/icons/gen3.json +++ b/config/icons/gen3.json @@ -1,6 +1,6 @@ { "prefix": "gen3", - "lastModified": 1712686390, + "lastModified": 1730144270, "icons": { "aisearch": { "body": "", @@ -19,11 +19,26 @@ "width": 315.67, "height": 294.22 }, + "chevron-contract": { + "body": "", + "width": 16, + "height": 16 + }, "chevron-down": { "body": "", "width": 58.026, "height": 58.026 }, + "chevron-expand": { + "body": "", + "width": 512, + "height": 512 + }, + "comparison": { + "body": "", + "width": 512, + "height": 512 + }, "datafile": { "body": "", "width": 60, @@ -34,13 +49,70 @@ "width": 489.709, "height": 489.709 }, + "dictionary-icon-administrative": { + "body": "" + }, + "dictionary-icon-analysis": { + "body": "", + "height": 21 + }, + "dictionary-icon-biospecimen": { + "body": "" + }, + "dictionary-icon-clinical": { + "body": "" + }, + "dictionary-icon-clinical-assessment": { + "body": "" + }, + "dictionary-icon-data-file": { + "body": "" + }, + "dictionary-icon-data-observations": { + "body": "" + }, + "dictionary-icon-default": { + "body": "", + "height": 21 + }, + "dictionary-icon-experimental-methods": { + "body": "" + }, + "dictionary-icon-imaging": { + "body": "" + }, + "dictionary-icon-index-file": { + "body": "" + }, + "dictionary-icon-medical-history": { + "body": "" + }, + "dictionary-icon-metadata": { + "body": "" + }, + "dictionary-icon-notation": { + "body": "" + }, + "dictionary-icon-study-administration": { + "body": "" + }, + "dictionary-icon-subject-characteristics": { + "body": "" + }, + "dot": { + "body": "", + "width": 256, + "height": 256 + }, "download": { - "body": "", + "body": "", "width": 24, "height": 24 }, "exploration": { - "body": "" + "body": "", + "width": 512, + "height": 512 }, "gen3": { "body": "", @@ -52,11 +124,31 @@ "width": 195, "height": 89 }, + "jupyter": { + "body": "", + "width": 44, + "height": 51 + }, + "loginarrowcircle": { + "body": "", + "width": 30, + "height": 30 + }, "logincircle": { "body": "", "width": 24, "height": 24 }, + "open-in-modal": { + "body": "", + "width": 24, + "height": 24 + }, + "notebook": { + "body": "", + "width": 682.667, + "height": 682.667 + }, "profile": { "body": "", "width": 512.001, @@ -68,16 +160,21 @@ "height": 511.999 }, "upload": { - "body": "" + "body": "", + "width": 24, + "height": 24 }, "user": { "body": "", - "width": 448 + "width": 448, + "height": 512 }, "workspace": { - "body": "" + "body": "", + "width": 512, + "height": 512 } }, - "width": 512, - "height": 512 + "width": 20, + "height": 20 } diff --git a/config/icons/aiSearch.svg b/config/icons/gen3/aiSearch.svg similarity index 100% rename from config/icons/aiSearch.svg rename to config/icons/gen3/aiSearch.svg diff --git a/config/icons/analysis.svg b/config/icons/gen3/analysis.svg similarity index 100% rename from config/icons/analysis.svg rename to config/icons/gen3/analysis.svg diff --git a/config/icons/bar-chart.svg b/config/icons/gen3/bar-chart.svg similarity index 100% rename from config/icons/bar-chart.svg rename to config/icons/gen3/bar-chart.svg diff --git a/config/icons/gen3/chevron-contract.svg b/config/icons/gen3/chevron-contract.svg new file mode 100644 index 0000000..7b16d84 --- /dev/null +++ b/config/icons/gen3/chevron-contract.svg @@ -0,0 +1 @@ + diff --git a/config/icons/chevron-down.svg b/config/icons/gen3/chevron-down.svg similarity index 100% rename from config/icons/chevron-down.svg rename to config/icons/gen3/chevron-down.svg diff --git a/config/icons/gen3/chevron-expand.svg b/config/icons/gen3/chevron-expand.svg new file mode 100644 index 0000000..3a62aae --- /dev/null +++ b/config/icons/gen3/chevron-expand.svg @@ -0,0 +1 @@ + diff --git a/config/icons/gen3/comparison.svg b/config/icons/gen3/comparison.svg new file mode 100644 index 0000000..114deb8 --- /dev/null +++ b/config/icons/gen3/comparison.svg @@ -0,0 +1 @@ + diff --git a/config/icons/datafile.svg b/config/icons/gen3/datafile.svg similarity index 100% rename from config/icons/datafile.svg rename to config/icons/gen3/datafile.svg diff --git a/config/icons/dictionary.svg b/config/icons/gen3/dictionary.svg similarity index 100% rename from config/icons/dictionary.svg rename to config/icons/gen3/dictionary.svg diff --git a/config/icons/gen3/download.svg b/config/icons/gen3/download.svg new file mode 100644 index 0000000..cab0abb --- /dev/null +++ b/config/icons/gen3/download.svg @@ -0,0 +1 @@ + diff --git a/config/icons/exploration.svg b/config/icons/gen3/exploration.svg similarity index 100% rename from config/icons/exploration.svg rename to config/icons/gen3/exploration.svg diff --git a/config/icons/gen3-dark.svg b/config/icons/gen3/gen3-dark.svg similarity index 100% rename from config/icons/gen3-dark.svg rename to config/icons/gen3/gen3-dark.svg diff --git a/config/icons/gen3.svg b/config/icons/gen3/gen3.svg similarity index 100% rename from config/icons/gen3.svg rename to config/icons/gen3/gen3.svg diff --git a/config/icons/gen3/jupyter.svg b/config/icons/gen3/jupyter.svg new file mode 100644 index 0000000..d0fa7e4 --- /dev/null +++ b/config/icons/gen3/jupyter.svg @@ -0,0 +1,90 @@ + +Group.svg +Created using Figma 0.90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/icons/gen3/loginArrowCircle.svg b/config/icons/gen3/loginArrowCircle.svg new file mode 100644 index 0000000..1fed0b6 --- /dev/null +++ b/config/icons/gen3/loginArrowCircle.svg @@ -0,0 +1 @@ + diff --git a/config/icons/loginCircle.svg b/config/icons/gen3/loginCircle.svg similarity index 100% rename from config/icons/loginCircle.svg rename to config/icons/gen3/loginCircle.svg diff --git a/config/icons/gen3/not-found.svg b/config/icons/gen3/not-found.svg new file mode 100644 index 0000000..68b0144 --- /dev/null +++ b/config/icons/gen3/not-found.svg @@ -0,0 +1,94 @@ + + + + 404 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/icons/gen3/notebook.svg b/config/icons/gen3/notebook.svg new file mode 100644 index 0000000..db56476 --- /dev/null +++ b/config/icons/gen3/notebook.svg @@ -0,0 +1,92 @@ + + + + diff --git a/config/icons/gen3/open_in_modal.svg b/config/icons/gen3/open_in_modal.svg new file mode 100644 index 0000000..3462c34 --- /dev/null +++ b/config/icons/gen3/open_in_modal.svg @@ -0,0 +1,3 @@ + + + diff --git a/config/icons/profile.svg b/config/icons/gen3/profile.svg similarity index 100% rename from config/icons/profile.svg rename to config/icons/gen3/profile.svg diff --git a/config/icons/query.svg b/config/icons/gen3/query.svg similarity index 100% rename from config/icons/query.svg rename to config/icons/gen3/query.svg diff --git a/config/icons/gen3/upload.svg b/config/icons/gen3/upload.svg new file mode 100755 index 0000000..8859cfc --- /dev/null +++ b/config/icons/gen3/upload.svg @@ -0,0 +1 @@ + diff --git a/config/icons/user.svg b/config/icons/gen3/user.svg similarity index 100% rename from config/icons/user.svg rename to config/icons/gen3/user.svg diff --git a/config/icons/workspace.svg b/config/icons/gen3/workspace.svg similarity index 100% rename from config/icons/workspace.svg rename to config/icons/gen3/workspace.svg diff --git a/config/icons/upload.svg b/config/icons/upload.svg deleted file mode 100755 index c2e2c5f..0000000 --- a/config/icons/upload.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - diff --git a/config/icons/workspace.json b/config/icons/workspace.json new file mode 100644 index 0000000..8cd2718 --- /dev/null +++ b/config/icons/workspace.json @@ -0,0 +1,24 @@ +{ + "prefix": "workspace", + "lastModified": 1724107947, + "icons": { + "galaxy": { + "body": "", + "width": 66 + }, + "jupyter": { + "body": "", + "width": 44, + "height": 51 + }, + "rlogo": { + "body": "", + "width": 75 + }, + "rstudio": { + "body": "", + "width": 50 + } + }, + "height": 50 +} diff --git a/config/icons/workspace/galaxy.svg b/config/icons/workspace/galaxy.svg new file mode 100644 index 0000000..3f743b7 --- /dev/null +++ b/config/icons/workspace/galaxy.svg @@ -0,0 +1,19 @@ + + + + Group Copy + Created with Sketch. + + + + + + + + + + + + + + diff --git a/config/icons/workspace/jupyter.svg b/config/icons/workspace/jupyter.svg new file mode 100644 index 0000000..ce0006b --- /dev/null +++ b/config/icons/workspace/jupyter.svg @@ -0,0 +1,90 @@ + +Group.svg +Created using Figma 0.90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/icons/workspace/rlogo.svg b/config/icons/workspace/rlogo.svg new file mode 100644 index 0000000..712b113 --- /dev/null +++ b/config/icons/workspace/rlogo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/config/icons/workspace/rstudio.svg b/config/icons/workspace/rstudio.svg new file mode 100644 index 0000000..32930f9 --- /dev/null +++ b/config/icons/workspace/rstudio.svg @@ -0,0 +1,12 @@ + + + + RStudio-Logo-flat + Created with Sketch. + + + + + + + diff --git a/config/siteConfig.json b/config/siteConfig.json deleted file mode 100644 index 73ad7dc..0000000 --- a/config/siteConfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "commons": "brh" -} diff --git a/config/themeFonts.json b/config/themeFonts.json deleted file mode 100644 index 9582a67..0000000 --- a/config/themeFonts.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "heading": ["Source Sans Pro", "sans-serif"], - "content": ["Source Sans Pro", "sans-serif"], - "fontFamily": "Source Sans Pro" -} diff --git a/package-lock.json b/package-lock.json index d5c542a..b33d5e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "@gen3/brh-data-portal", "version": "0.1.0", "dependencies": { - "@gen3/frontend": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-frontend-0.10.21.tgz", + "@gen3/frontend": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-frontend-0.10.25.tgz", "@mantine/core": "^6.0.21", "@mdx-js/loader": "^3.0.0", "@mdx-js/react": "^3.0.0", @@ -19,7 +19,7 @@ "react-responsive-carousel": "^3.2.23" }, "devDependencies": { - "@gen3/toolsff": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-toolsff-0.10.21.tgz", + "@gen3/toolsff": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-toolsff-0.10.25.tgz", "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.2", @@ -43,7 +43,7 @@ "npm": ">=10.2.3" }, "peerDependencies": { - "@gen3/core": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-core-0.10.21.tgz", + "@gen3/core": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-core-0.10.25.tgz", "react": "^18.2.0", "react-dom": "^18.2.0" } @@ -1744,9 +1744,9 @@ "integrity": "sha512-f7iw44q1EjBv3MNcHCGAgrW/QVyweaEouFsJzykPhTOGnZFSwFJRISToXornOmuAy7xUUGiVdqOLiykgZoYB8A==" }, "node_modules/@gen3/core": { - "version": "0.10.21", - "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-core-0.10.21.tgz", - "integrity": "sha512-Mw1rK5NZWUAUjPfY0EtXDTx5BMVGzsoVxVW/PqGx/d1769q16CfDOQMAPbTtcVqt20ajfRppYhsw2YzXKYOofA==", + "version": "0.10.25", + "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-core-0.10.25.tgz", + "integrity": "sha512-fQUa6x3PeKFEKx/DZ5wGBPzJmqJzLFGror5QcOVSrQgRXh4SyQBDunpPiLgyOXo/4ZjlHnlkSphz/y+KPEZNDA==", "license": "Apache-2.0", "peer": true, "dependencies": { @@ -1768,9 +1768,9 @@ } }, "node_modules/@gen3/frontend": { - "version": "0.10.21", - "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-frontend-0.10.21.tgz", - "integrity": "sha512-7gWlHCU94T01yuqc6YGR9PL2Lstaa1PsQ1BfbqFIstsE/Vx2F1LMa8tVZJPrefNx8ItQniCd/hOPUSf+SHPKMw==", + "version": "0.10.25", + "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-frontend-0.10.25.tgz", + "integrity": "sha512-cl2BCA2X/2A3X0mhlK+QLCGfnep+M4rZ9z5D+DUAUhxI0psay9ltHwGSYO4XXBAS/AJ0I2FeUe0rliDF02Sjdw==", "license": "Apache-2.0", "dependencies": { "@fontsource/montserrat": "^4.5.12", @@ -1799,6 +1799,7 @@ "echarts": "^5.4.3", "fetch-retry": "^5.0.6", "file-saver": "^2.0.5", + "filesize": "^10.1.1", "graphiql": "^3.0.5", "graphql": "^16.8.0", "graphql-ws": "^5.14.0", @@ -1843,7 +1844,7 @@ "npm": ">=10.2.3" }, "peerDependencies": { - "@gen3/core": "^0.10.12", + "@gen3/core": "^0.10.21", "react": "^18.2.0", "react-dom": "^18.2.0", "typescript": "5.0.2" @@ -1914,9 +1915,9 @@ } }, "node_modules/@gen3/toolsff": { - "version": "0.10.21", - "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-toolsff-0.10.21.tgz", - "integrity": "sha512-Nh9Smyuyl4GFZcw2gjvZK4S8LCMAgfAHjgW1l6XQfXRX9Gm1GQOqFGwTrQ0R29x225MKB7NwYXD5aeFJ/J4AgA==", + "version": "0.10.25", + "resolved": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-toolsff-0.10.25.tgz", + "integrity": "sha512-vJpckFxcbk320KoGwH4clspxiXYrWRQEwVFWLbMf/N63nqEYhqVUP9gGiy91AZ5A3pOJANeilcgfUvWurGgZMw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9114,6 +9115,14 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, + "node_modules/filesize": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.1.tgz", + "integrity": "sha512-L0cdwZrKlwZQkMSFnCflJ6J2Y+5egO/p3vgRSDQGxQt++QbUZe5gMbRO6kg6gzwQDPvq2Fk9AmoxUNfZ5gdqaQ==", + "engines": { + "node": ">= 10.4.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", diff --git a/package.json b/package.json index 81af1b4..fab618a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gen3/brh-data-portal", - "version": "0.1.0", + "version": "0.1.1", "private": "true", "engines": { "npm": ">=10.2.3", @@ -18,18 +18,33 @@ "getDRSToHostname": "node ./node_modules/@gen3/toolsff/dist/getDRSToHostname.esm.js --out=config/" }, "dependencies": { - "@gen3/frontend": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-frontend-0.10.21.tgz", - "@mantine/core": "^6.0.21", + "@fontsource/montserrat": "^5.0.19", + "@fontsource/poppins": "^5.0.15", + "@fontsource/source-sans-pro": "^5.0.8", + "jsonpath-plus": "^10.2.0", + "@gen3/core": "^0.10.61", + "@gen3/frontend": "^0.10.61", + "@grafana/faro-react": "^1.9.1", + "@grafana/faro-web-sdk": "^1.9.1", + "@grafana/faro-web-tracing": "^1.9.1", + "idb": "^8.0.0", + "@mantine/core": "^7.13.3", + "@mantine/form": "^7.13.3", + "@mantine/hooks": "^7.13.3", + "@mantine/modals": "^7.13.3", + "@mantine/dates": "^7.13.3", + "@mantine/notifications": "^7.13.3", "@mdx-js/loader": "^3.0.0", "@mdx-js/react": "^3.0.0", - "@next/mdx": "^14.1.0", - "@types/mdx": "^2.0.11", + "@next/mdx": "^14.2.15", "cookies-next": "^4.1.1", - "jose": "^4.15.4", - "react-responsive-carousel": "^3.2.23" + "react": "^18.2.0", + "react-dom": "18.2.0", + "swr": "^2.2.5" }, "devDependencies": { - "@gen3/toolsff": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-toolsff-0.10.21.tgz", + "@axe-core/react": "^4.10.0", + "@gen3/toolsff": "^0.10.61", "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.2", @@ -37,20 +52,28 @@ "@types/lodash": "^4.14.202", "@types/react": "^18.2.21", "@types/react-dom": "^18.2.7", - "next": "^14.1.0", + "@types/mdx": "^2.0.11", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "eslint": "8.57.0", + "eslint-config-next": "14.2.3", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsx-a11y": "^6.6.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", + "next": "^14.2.15", "postcss": "^8.4.29", + "postcss-import": "^16.1.0", "postcss-loader": "^7.3.2", + "postcss-modules": "^6.0.0", "postcss-preset-env": "^8.4.2", + "postcss-preset-mantine": "^1.17.0", + "prettier": "^2.7.1", "react": "^18.2.0", "react-dom": "18.2.0", - "tailwindcss": "^3.3.7", - "ts-jest": "^29.0.3", + "tailwindcss": "^3.4.10", + "ts-jest": "^29.1.2", "ts-node": "^10.9.1", - "typescript": "5.0.2" - }, - "peerDependencies": { - "@gen3/core": "https://github.com/uc-cdis/gen3-frontend-framework/releases/download/v0.10.0-alpha/gen3-core-0.10.21.tgz", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "typescript": "^5.6.2" } } diff --git a/src/lib/CohortBuilder/CustomCellRenderers.tsx b/src/lib/CohortBuilder/CustomCellRenderers.tsx index 0d57ad0..0258645 100644 --- a/src/lib/CohortBuilder/CustomCellRenderers.tsx +++ b/src/lib/CohortBuilder/CustomCellRenderers.tsx @@ -1,28 +1,28 @@ import { - ExplorerTableCellRendererFactory, - type CellRendererFunctionProps, + ExplorerTableCellRendererFactory, + type CellRendererFunctionProps, } from '@gen3/frontend'; import { ActionIcon } from '@mantine/core'; -import React from 'react'; +import React from 'react'; import { FaExternalLinkAlt } from 'react-icons/fa'; - -const RenderDiacomLink = ({ cell }: CellRendererFunctionProps) => { - if (cell.getValue() === undefined || cell.getValue() === '') { - return ; - } else - return ( - - - - - - ); +const RenderDicomLink = ({ cell }: CellRendererFunctionProps) => { + if (!cell?.getValue() || cell?.getValue() === '') { + return ; + } else + return ( + + + + + + ); }; export const registerCohortTableCustomCellRenderers = () => { - ExplorerTableCellRendererFactory().registerRenderer( - 'link', 'DiacomLink' , - RenderDiacomLink, - ); + ExplorerTableCellRendererFactory().registerRenderer( + 'link', + 'DicomLink', + RenderDicomLink, + ); }; diff --git a/src/lib/CohortBuilder/FileDetailsPanel.tsx b/src/lib/CohortBuilder/FileDetailsPanel.tsx new file mode 100644 index 0000000..0721c01 --- /dev/null +++ b/src/lib/CohortBuilder/FileDetailsPanel.tsx @@ -0,0 +1,170 @@ +import { + Anchor, + Group, + LoadingOverlay, + Stack, + Table, + Text, + CopyButton, + ActionIcon, + Tooltip, + Button, +} from '@mantine/core'; +import { useGeneralGQLQuery, GEN3_FENCE_API } from '@gen3/core'; +import { + ErrorCard, + type TableDetailsPanelProps, + ExplorerTableDetailsPanelFactory, +} from '@gen3/frontend'; +import { + MdContentCopy as IconCopy, + MdCheck as IconCheck, +} from 'react-icons/md'; + +// a definition of the query response +interface QueryResponse { + data?: Record>; +} + +/** + * Checks if the given object is a QueryResponse. + * + * @param {any} obj - The object to be checked. + * @returns {boolean} Returns true if the object is a QueryResponse, false otherwise. + */ +const isQueryResponse = (obj: any): obj is QueryResponse => { + // Considering that the data property can be optional + return ( + typeof obj === 'object' && + (obj.data === undefined || typeof obj.data === 'object') + ); +}; + +/** + * Extracts data from a QueryResponse object based on an index. + * + * @param {QueryResponse} data - The QueryResponse object containing the data. + * @param {string} index - The index to extract the data from. + * @returns {Record} - The extracted data as a key-value pair object. + */ +const extractData = ( + data: QueryResponse, + index: string, +): Record => { + if (data === undefined || data === null) return {}; + if (data.data === undefined || data.data === null) return {}; + + return Array.isArray(data.data[index]) && data.data[index].length > 0 + ? data.data[index][0] + : {}; +}; + +export const FileDetailsPanel = ({ + id, + index, + tableConfig, + onClose, +}: TableDetailsPanelProps) => { + // get the idField from the configuration + const idField = tableConfig.detailsConfig?.idField; + // call the general Guppy GQL which takes an object { query: string, variables: object } + const { data, isLoading, isError } = useGeneralGQLQuery({ + query: `query ($filter: JSON) { + ${index} (filter: $filter, accessibility: all) { + ${tableConfig.fields} + } + }`, + variables: { + filter: { + AND: [ + { + IN: { + [idField ?? 0]: [id], + }, + }, + ], + }, + }, + }); + + // handle misconfiguration + if (!idField) { + return ( + + ); + } + // show data error if graphql fails + if (isError) { + return ; + } + + // process guppy response + const queryData = isQueryResponse(data) ? extractData(data, index) : {}; + + // create the rows for the table + const rows = Object.entries(queryData).map(([field, value]) => ( + + + {field} + + + {/* + if field is one that we want a link for make it an Anchor otherwise + render as text. + */} + {field === 'object_id' ? ( + + {value ? (value as string) : ''} + + ) : ( + {value ? (value as string) : ''} + )} + + + )); + return ( + + + Results for {id} + + + + + + + + {rows} +
FieldValue
+ + + {({ copied, copy }) => ( + + + {copied ? : } + + + )} + + + +
+ ); +}; + +export const registerCustomExplorerDetailsPanels = () => { + ExplorerTableDetailsPanelFactory().registerRendererCatalog({ + // NOTE: The catalog name must be tableDetails + tableDetails: { fileDetails: FileDetailsPanel }, // TODO: add simpler registration function that ensures the catalog name is tableDetails + }); +}; diff --git a/src/lib/Discovery/CustomCellRenderers.tsx b/src/lib/Discovery/CustomCellRenderers.tsx index adfa6b6..4a30224 100644 --- a/src/lib/Discovery/CustomCellRenderers.tsx +++ b/src/lib/Discovery/CustomCellRenderers.tsx @@ -1,66 +1,67 @@ import { - DiscoveryCellRendererFactory, - CellRenderFunctionProps, + DiscoveryCellRendererFactory, + CellRenderFunctionProps, } from '@gen3/frontend'; import { Badge, Text } from '@mantine/core'; import React from 'react'; import { - MdOutlineCheckCircle as CheckCircleOutlined, - MdOutlineRemoveCircleOutline as MinusCircleOutlined, + MdOutlineCheckCircle as CheckCircleOutlined, + MdOutlineRemoveCircleOutline as MinusCircleOutlined, } from 'react-icons/md'; import { isArray } from 'lodash'; import { JSONObject } from '@gen3/core'; import { toString } from 'lodash'; +import { FilemapPopup, FilemapInline } from '@/lib/Discovery/Filemap'; /** * Custom cell renderer for the linked study column for HEAL * @param cell */ export const LinkedStudyCell = ({ - value: cellValue, - }: CellRenderFunctionProps) => { - const value = cellValue as boolean; - return value ? ( - } - color="green" - > - Linked - - ) : ( - } color="primary"> - Not Linked - - ); + value: cellValue, +}: CellRenderFunctionProps) => { + const value = cellValue as boolean; + return value ? ( + } + color="green" + > + Linked + + ) : ( + } color="primary"> + Not Linked + + ); }; const WrappedStringCell = ( - { value }: CellRenderFunctionProps, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - params?: JSONObject, + { value }: CellRenderFunctionProps, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + params?: JSONObject, ) => { - if (value === undefined || value === null || toString(value) === '') { - return ( - - {`${ - params && params?.valueIfNotAvailable - ? params?.valueIfNotAvailable - : '' - }`}{' '} - - ); - } - - const content = value as string | string[]; + if (value === undefined || value === null || toString(value) === '') { return ( -
+ + {`${ + params && params?.valueIfNotAvailable + ? params?.valueIfNotAvailable + : '' + }`}{' '} + + ); + } + + const content = value as string | string[]; + return ( +
{isArray(content) ? content.join(', ') : content} -
- ); +
+ ); }; @@ -68,12 +69,16 @@ const WrappedStringCell = ( * Register custom cell renderers for DiscoveryTable */ export const registerDiscoveryCustomCellRenderers = () => { - DiscoveryCellRendererFactory.registerCellRendererCatalog({ - string: { - default: WrappedStringCell, - }, - boolean: { - LinkedStudyCell, - }, - }); + DiscoveryCellRendererFactory.registerCellRendererCatalog({ + string: { + default: WrappedStringCell, + }, + boolean: { + LinkedStudyCell, + }, + manifest: { + default: FilemapPopup, + inline: FilemapInline, + } + }); }; diff --git a/src/lib/Discovery/CustomRowRenderers.tsx b/src/lib/Discovery/CustomRowRenderers.tsx index 789ec5e..f785432 100644 --- a/src/lib/Discovery/CustomRowRenderers.tsx +++ b/src/lib/Discovery/CustomRowRenderers.tsx @@ -3,88 +3,80 @@ import React, { ReactElement } from 'react'; import { JSONPath } from 'jsonpath-plus'; import { Badge, Box, Text } from '@mantine/core'; import { - StudyDetailsField, - RowRenderFunctionParams, - DiscoveryRowRendererFactory, - useDiscoveryContext, - getTagColor, + StudyDetailsField, + RowRenderFunctionParams, + DiscoveryRowRendererFactory, + useDiscoveryContext, + getTagInfo, + TagData, } from '@gen3/frontend'; -// TODO: This is a hack to get around the fact that the data is not typed -interface TagData { - name: string; - category: string; -} +const DetailsWithTagsRowRenderer = ( + { row }: RowRenderFunctionParams, + studyPreviewConfig?: StudyDetailsField, +): ReactElement => { + const { discoveryConfig: config } = useDiscoveryContext(); -const DetailsWithTagsRowRenderer = - ( - { row } : RowRenderFunctionParams, - studyPreviewConfig?: StudyDetailsField, - ): ReactElement => { - const { discoveryConfig: config, setStudyDetails } = useDiscoveryContext(); + if (!studyPreviewConfig) { + return ; + } + const value = + JSONPath({ + json: row.original, + path: studyPreviewConfig.field, + }) ?? + config?.studyPreviewField?.valueIfNotAvailable ?? + ''; - if (!studyPreviewConfig) { - return ; - } - const value = - JSONPath({ - json: row.original, - path: studyPreviewConfig.field, - }) ?? - config?.studyPreviewField?.valueIfNotAvailable ?? - ''; + return ( + +
+ + {value} + - return ( - { - setStudyDetails(() => { - return { ...row.original }; - }); - }} - > -
- - {value} - +
+ {row.original?.tags.map((tagInfo: TagData) => { + const { color, display, label } = getTagInfo(tagInfo, config.tags); -
- {row.original?.tags.map(({ name, category }: TagData) => { - const color = getTagColor(category, config.tagCategories); - return ( - - {name} - - ); - })} -
-
- - ); - }; + if (tagInfo.name === '') return null; // no tag + if (!display) return null; + return ( + + {label} + + ); + })} +
+
+
+ ); +}; export default DetailsWithTagsRowRenderer; export const registerDiscoveryStudyPreviewRenderers = () => { - DiscoveryRowRendererFactory.registerRowRendererCatalog({ - string: { - default: DetailsWithTagsRowRenderer, - }, - }); + DiscoveryRowRendererFactory.registerRowRendererCatalog({ + string: { + default: DetailsWithTagsRowRenderer, + }, + }); }; diff --git a/src/lib/Discovery/Filemap.tsx b/src/lib/Discovery/Filemap.tsx new file mode 100644 index 0000000..a7fde6d --- /dev/null +++ b/src/lib/Discovery/Filemap.tsx @@ -0,0 +1,183 @@ +import { + CellRenderFunctionProps, + ReactECharts, + ReactEChartsProps, +} from '@gen3/frontend'; +import { Button, Popover, Text } from '@mantine/core'; +import { isArray } from 'lodash'; +import { useDeepCompareMemo } from 'use-deep-compare'; +import { useDisclosure } from '@mantine/hooks'; + +/** + * Represents a manifest item. + * @interface ManifestItem + */ +interface ManifestItem { + md5sum: string; + file_name: string; + file_size?: number; + object_id: string; + commons_name?: string; +} + +/** + * Interface representing the data structure for Bar Chart. + * + * @interface + * @name BarChartData + * @property {number} value - The numerical value associated with the bar. + * @property {string} name - The name or label associated with the bar. + */ +interface BarChartData { + value: number; + name: string; +} + +/** + * Counts the number of occurrences of file types in the given data array and returns an array of objects + * representing the file type and its percentage value within the total count. + * + * @param {Array} data - The array of data containing ManifestItem objects. + * @returns {Array} - The array of objects representing file types and their percentages. + */ +const countTypes = (data: Array): BarChartData[] => { + const counts: Record = {}; + data.forEach((item: ManifestItem) => { + const filetype = item.file_name.split('.').pop(); + if (!filetype) return; + counts[filetype] = counts[filetype] ? counts[filetype] + 1 : 1; + }); + const total = Object.values(counts).reduce((acc, val) => acc + val, 0); + return Object.entries(counts).map(([name, value]) => ({ + name, + value: Number(((value / total) * 100).toFixed(2)), + })); +}; + +/** + * Converts an array of manifest items into a chart definition for React ECharts. + * + * @param {Array} data - The array of manifest items to convert. + * @returns {ReactEChartsProps['option'] | undefined} - The chart definition or undefined if the data is invalid or empty. + */ +const useProcessManifestToChart = ( + values: Array, + showLabel = true, + showToolip = false, +): ReactEChartsProps['option'] | undefined => { + const chartDefinition = useDeepCompareMemo((): + | ReactEChartsProps['option'] + | undefined => { + if ( + values === undefined || + values === null || + !isArray(values) || + values.length === 0 + ) { + return undefined; + } + + const data = countTypes(values); + + return { + grid: { + left: 2, + top: 2, + right: 2, + bottom: 2, + }, + tooltip: { + trigger: 'item', + show: showToolip, + formatter: '{a} - {c}%', + position: 'right', + z: 100, + }, + xAxis: { + type: 'value', + show: false, + }, + yAxis: { + type: 'category', + data: data.map((d) => d.name), + show: false, + }, + series: data.map((d) => ({ + type: 'bar', + stack: 'total', + barWidth: 40, + name: d.name, + data: [d.value], + label: { + show: showLabel, + position: 'top', + minMargin: 8, + formatter: '{a} - {c}%', + }, + labelLine: { + show: true, + }, + labelLayout: () => { + return { + y: '35%', + moveOverlap: 'shiftX', + }; + }, + })), + }; + }, [values]); + + return chartDefinition; +}; + +/** + * Represents a Filemap popup component. + * + * @component + * @param {Object} value - An object containing the __manifest value to render. + * @returns {JSX.Element} - The rendered JSX element. + */ +export const FilemapPopup = ({ value }: CellRenderFunctionProps) => { + const [opened, { close, open }] = useDisclosure(false); + const chartDefinition = useProcessManifestToChart(value[0]); + + if (!chartDefinition) { + return n/a; + } + return ( + + + + + +
+ +
+
+
+ ); +}; + +/** + * Render a chart component based on the provided value. + * + * @param {object} value - An object or array containing the value for the chart component. + * @returns {JSX.Element} - The rendered chart component. + */ +export const FilemapInline = ({ value }: CellRenderFunctionProps) => { + const chartDefinition = useProcessManifestToChart(value[0], false, true); + + if (!chartDefinition) { + return n/a; + } + return ( +
+ +
+ ); +}; diff --git a/src/lib/Grafana/grafana.ts b/src/lib/Grafana/grafana.ts new file mode 100644 index 0000000..cc0aa51 --- /dev/null +++ b/src/lib/Grafana/grafana.ts @@ -0,0 +1,43 @@ +import { + getWebInstrumentations, + initializeFaro, + ReactIntegration, +} from '@grafana/faro-react'; +import { TracingInstrumentation } from '@grafana/faro-web-tracing'; + +// Get the current, runtime version of the App to surface to Faro +// import packageJson from "../../package.json"; + +export const initGrafanaFaro = () => { + return initializeFaro({ + url: 'https://faro.planx-pla.net/collect', + + app: { + // TODO: Populate with real values. + name: 'gen3-frontend-framework', + // version: packageJson.version, + version: '10.0.0', + environment: 'local', + }, + + instrumentations: [ + // load the mandatory web instrumentation + ...getWebInstrumentations({ + captureConsole: true, + }), + + // add tracing instrumentation which should include the React Profiler + new TracingInstrumentation(), + + new ReactIntegration({ + // In the future, we may choose to integrate with React router instrumentation to + // get deeper metrics on matched routes, navigation types, etc. + // Next/router doesn't seem to be supported which won't give us route metrics. + // + // Reference: https://github.com/grafana/faro-web-sdk/tree/main/packages/react + // + // router: {} + }), + ], + }); +}; diff --git a/src/lib/content/loadContent.ts b/src/lib/content/loadContent.ts new file mode 100644 index 0000000..d4c2c8d --- /dev/null +++ b/src/lib/content/loadContent.ts @@ -0,0 +1,40 @@ +import { + ContentSource, + Fonts, + RegisteredIcons, + TenStringArray, +} from '@gen3/frontend'; +import { GEN3_COMMONS_NAME } from '@gen3/core'; + +export const loadContent = async () => { + const modals = await ContentSource.get( + `config/${GEN3_COMMONS_NAME}/modals.json`, + ); + const session = await ContentSource.get( + `config/${GEN3_COMMONS_NAME}/session.json`, + ); + + const fonts = await ContentSource.get( + `config/${GEN3_COMMONS_NAME}/themeFonts.json`, + ); + + const themeColors = await ContentSource.get( + `config/${GEN3_COMMONS_NAME}/themeColors.json`, + ); + + const colors = Object.fromEntries( + Object.entries(themeColors).map(([key, values]) => [ + key, + Object.values(values) as TenStringArray, + ]), + ); + + const icons = await ContentSource.getAll(`config/icons/`, '\\.json'); + return { + modalsConfig: modals, + sessionConfig: session, + themeFonts: fonts as Fonts, + colors: colors, + icons: icons as RegisteredIcons[], + }; +}; diff --git a/src/pages/AISearch.tsx b/src/pages/AISearch.tsx index 3945a8b..5dacef7 100644 --- a/src/pages/AISearch.tsx +++ b/src/pages/AISearch.tsx @@ -1,49 +1,9 @@ import { - NavPageLayout, - NavPageLayoutProps, - Discovery, - DiscoveryPageGetServerSideProps as getServerSideProps, + AiSearchPage, + AISearchPageGetServerSideProps as getServerSideProps, } from '@gen3/frontend'; -import { Center, Text } from "@mantine/core"; -import { registerDiscoveryCustomCellRenderers } from '@/lib/Discovery/CustomCellRenderers'; -import { registerDiscoveryStudyPreviewRenderers } from '@/lib/Discovery/CustomRowRenderers'; - -registerDiscoveryCustomCellRenderers(); -registerDiscoveryStudyPreviewRenderers(); - -const DiscoveryPageCustom = ({ - headerProps, - footerProps, - discoveryConfig, - }: { - headerProps: any, - footerProps: any, - discoveryConfig:any, -}): JSX.Element => { - - if (discoveryConfig === undefined) { - return ( -
-
Discovery config is not defined. Page disabled
-
- ); - } - - return ( - -
-
- AI Search is a Beta Feature. Please note that this is still in testing and we appreciate your feedback. You must login to use it. -
- - -
-
- ); -}; - -export default DiscoveryPageCustom; +export default AiSearchPage; export { getServerSideProps }; diff --git a/src/pages/Analysis.tsx b/src/pages/Analysis.tsx new file mode 100644 index 0000000..21e809d --- /dev/null +++ b/src/pages/Analysis.tsx @@ -0,0 +1,7 @@ +import { + AnalysisPage, + AnalysisPageGetServerSideProps as getServerSideProps, + } from '@gen3/frontend'; + export default AnalysisPage; + + export { getServerSideProps }; diff --git a/src/pages/Crosswalk.tsx b/src/pages/Crosswalk.tsx new file mode 100644 index 0000000..6474055 --- /dev/null +++ b/src/pages/Crosswalk.tsx @@ -0,0 +1,7 @@ +import { + CrosswalkPage, + CrosswalkPageGetServerSideProps as getServerSideProps, +} from '@gen3/frontend'; +export default CrosswalkPage; + +export { getServerSideProps }; diff --git a/src/pages/DataDictionary.tsx b/src/pages/DataDictionary.tsx index 274b3b1..8f1a9ca 100644 --- a/src/pages/DataDictionary.tsx +++ b/src/pages/DataDictionary.tsx @@ -1,7 +1,8 @@ import { - DataDictionaryPage, - DataDictionaryPageGetServerSideProps as getServerSideProps, + DictionaryPage, + DictionaryPageGetServerSideProps as getServerSideProps, } from '@gen3/frontend'; -export default DataDictionaryPage; + +export default DictionaryPage; export { getServerSideProps }; diff --git a/src/pages/DataLibrary.tsx b/src/pages/DataLibrary.tsx new file mode 100644 index 0000000..23c665c --- /dev/null +++ b/src/pages/DataLibrary.tsx @@ -0,0 +1,8 @@ +import { + DataLibraryPage, + DataLibraryPageGetServerSideProps as getServerSideProps, +} from '@gen3/frontend'; + +export default DataLibraryPage; + +export { getServerSideProps }; diff --git a/src/pages/Explorer.tsx b/src/pages/Explorer.tsx index 8322e2c..631cff0 100644 --- a/src/pages/Explorer.tsx +++ b/src/pages/Explorer.tsx @@ -3,9 +3,11 @@ import { ExplorerPageGetServerSideProps as getServerSideProps, } from '@gen3/frontend'; -import { registerCohortTableCustomCellRenderers } from "@/lib/CohortBuilder/CustomCellRenderers"; +import { registerCohortTableCustomCellRenderers } from '@/lib/CohortBuilder/CustomCellRenderers'; +import { registerCustomExplorerDetailsPanels } from '@/lib/CohortBuilder/FileDetailsPanel'; registerCohortTableCustomCellRenderers(); +registerCustomExplorerDetailsPanels(); export default ExplorerPage; diff --git a/src/pages/NotebookLite.tsx b/src/pages/NotebookLite.tsx new file mode 100644 index 0000000..6c163d2 --- /dev/null +++ b/src/pages/NotebookLite.tsx @@ -0,0 +1,7 @@ +import { + NotebookLitePage, + NotebookLitePageGetStaticProps as getStaticProps, +} from '@gen3/frontend'; + +export default NotebookLitePage; +export { getStaticProps }; diff --git a/src/pages/SamplePage.tsx b/src/pages/SamplePage.tsx index 7fe48bb..9b652e1 100644 --- a/src/pages/SamplePage.tsx +++ b/src/pages/SamplePage.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Text, Paper } from '@mantine/core'; +import { Center, Text, Paper } from '@mantine/core'; import { NavPageLayout, NavPageLayoutProps, @@ -9,24 +9,33 @@ import { GetServerSideProps } from 'next'; const SamplePage = ({ headerProps, footerProps }: NavPageLayoutProps) => { return ( - -
- - This is a example custom page in Gen3 - - You can add your own content here, and add a link to this page in - the navigation bar by editing the config file in{' '} - COMMONSNAME/navigation.json - - + +
+
+ + This is a example custom page in Gen3 + + You can add your own content here, and add a link to this page in + the navigation bar by editing the config file in navigation.json + + +
); }; +// TODO: replace this with a custom getServerSideProps function export const getServerSideProps: GetServerSideProps< NavPageLayoutProps -> = async (_context) => { +> = async () => { return { props: { ...(await getNavPageLayoutPropsFromConfig()), diff --git a/src/pages/Submission.tsx b/src/pages/Submission.tsx new file mode 100644 index 0000000..f6e0969 --- /dev/null +++ b/src/pages/Submission.tsx @@ -0,0 +1,7 @@ +import { + SubmissionPage, + SubmissionPageGetServerSideProps as getServerSideProps, +} from '@gen3/frontend'; +export default SubmissionPage; + +export { getServerSideProps }; diff --git a/src/pages/Workspace.tsx b/src/pages/Workspace.tsx new file mode 100644 index 0000000..96f172e --- /dev/null +++ b/src/pages/Workspace.tsx @@ -0,0 +1,7 @@ +import { + WorkspacePage, + WorkspacePageGetServerSideProps as getServerSideProps, +} from '@gen3/frontend'; +export default WorkspacePage; + +export { getServerSideProps }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 2597606..9b45c99 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,42 +1,133 @@ -import type { AppProps } from 'next/app'; -import { useEffect } from 'react'; -import { Gen3Provider, TenStringArray, type ModalsConfig } from '@gen3/frontend'; -import themeColors from '../../config/themeColors.json'; -import themeFonts from '../../config/themeFonts.json'; -import icons from '../../config/icons/gen3.json'; -import '../styles/globals.css'; -import 'react-responsive-carousel/lib/styles/carousel.min.css'; -import 'graphiql/graphiql.css'; -import '@graphiql/react/dist/style.css'; -import { setDRSHostnames } from '@gen3/core'; +import App, { AppProps, AppContext, AppInitialProps } from 'next/app'; +import React, { useEffect, useRef } from 'react'; + +import { Faro, FaroErrorBoundary, withFaroProfiler } from '@grafana/faro-react'; + +import { initGrafanaFaro } from '../lib/Grafana/grafana'; + +import { + Gen3Provider, + TenStringArray, + type ModalsConfig, + RegisteredIcons, + Fonts, + SessionConfiguration, + // registerCohortDiscoveryApp, + registerCohortDiversityApp, + registerCohortBuilderDefaultPreviewRenderers, + registerExplorerDefaultCellRenderers, +} from '@gen3/frontend'; +import { registerCohortTableCustomCellRenderers } from '@/lib/CohortBuilder/CustomCellRenderers'; +import { registerCustomExplorerDetailsPanels } from '@/lib/CohortBuilder/FileDetailsPanel'; -// TODO: This can be done in a better way using newer NextJS features -import sessionConfig from '../../config/session.json'; -import modalsConfig from '../../config/modals.json'; +import '../styles/globals.css'; +import '@fontsource/montserrat'; +import '@fontsource/source-sans-pro'; +import '@fontsource/poppins'; + +import { setDRSHostnames } from '@gen3/core'; import drsHostnames from '../../config/drsHostnames.json'; +import { loadContent } from '../lib/content/loadContent'; + +if (typeof window !== 'undefined' && process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports + const ReactDOM = require('react-dom'); + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports + const axe = require('@axe-core/react'); + axe(React, ReactDOM, 1000); +} -const colors = Object.fromEntries( - Object.entries(themeColors).map(([key, values]) => [ - key, - Object.values(values) as TenStringArray, - ]), -); +interface Gen3AppProps { + colors: Record; + icons: Array; + themeFonts: Fonts; + modalsConfig: ModalsConfig; + sessionConfig: SessionConfiguration; +} -export default function App({ Component, pageProps }: AppProps) { +const Gen3App = ({ + Component, + pageProps, + colors, + icons, + themeFonts, + sessionConfig, + modalsConfig, + }: AppProps & Gen3AppProps) => { useEffect(() => { setDRSHostnames(drsHostnames); }, []); + const faroRef = useRef(null); + + useEffect(() => { + // one time init + // if ( + // process.env.NEXT_PUBLIC_FARO_COLLECTOR_URL && + // process.env.NEXT_PUBLIC_FARO_APP_ENVIRONMENT != "local" && + // !faroRef.current + // ) { + if (!faroRef.current) faroRef.current = initGrafanaFaro(); + // registerCohortDiscoveryApp(); + registerCohortDiversityApp(); + registerExplorerDefaultCellRenderers(); + registerCohortBuilderDefaultPreviewRenderers(); + registerCohortTableCustomCellRenderers(); + registerCustomExplorerDetailsPanels(); + // } + }, []); + return ( - - - + + + + + ); -} +}; + +// TODO: replace with page router +Gen3App.getInitialProps = async ( + context: AppContext, +): Promise => { + const ctx = await App.getInitialProps(context); + + try { + const res = await loadContent(); + return { + ...ctx, + ...res, + }; + } catch (error: any) { + console.error('Provider Wrapper error loading config', error.toString()); + } + // return default + return { + ...ctx, + colors: {}, + themeFonts: { + heading: ['Poppins', 'sans-serif'], + content: ['Poppins', 'sans-serif'], + fontFamily: 'Poppins', + }, + icons: [ + { + prefix: 'gen3', + lastModified: 0, + icons: {}, + width: 0, + height: 0, + }, + ], + modalsConfig: {}, + sessionConfig: {}, + }; +}; +export default withFaroProfiler(Gen3App); diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index e1e9cbb..53ff867 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -1,12 +1,15 @@ -import { Html, Head, Main, NextScript } from 'next/document'; +import { Head, Html, Main, NextScript } from 'next/document'; +import { ColorSchemeScript } from '@mantine/core'; export default function Document() { return ( - + + + -
- +
+ ); diff --git a/src/pages/api/auth/sessionLogout.ts b/src/pages/api/auth/sessionLogout.ts new file mode 100644 index 0000000..2441be7 --- /dev/null +++ b/src/pages/api/auth/sessionLogout.ts @@ -0,0 +1,3 @@ +import { sessionLogout } from '@gen3/frontend'; + +export default sessionLogout; diff --git a/src/pages/app/[appName].tsx b/src/pages/app/[appName].tsx new file mode 100644 index 0000000..6ac5ce6 --- /dev/null +++ b/src/pages/app/[appName].tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { + useCoreSelector, + selectGen3AppByName, + GEN3_COMMONS_NAME, +} from '@gen3/core'; +import { GetServerSideProps } from 'next'; +import { NextRouter, useRouter } from 'next/dist/client/router'; + +import { + NavPageLayout, + NavPageLayoutProps, + getNavPageLayoutPropsFromConfig, + ContentSource, +} from '@gen3/frontend'; + +interface AppConfig extends NavPageLayoutProps { + config?: object; +} + +const AppsPage = ({ headerProps, footerProps, config }: AppConfig) => { + const router = useRouter(); + const appName = getAppName(router); + + const GdcApp = useCoreSelector( + () => selectGen3AppByName(appName), // TODO update ById to ByName + ) as React.ElementType; + + return ( + + {GdcApp && } + + ); +}; + +const getAppName = (router: NextRouter): string => { + const { appName } = router.query; + if (typeof appName === 'string') return appName; + else if (typeof appName === 'object') return appName[0]; + + return 'UNKNOWN_APP_ID'; +}; + +export const getServerSideProps: GetServerSideProps< + NavPageLayoutProps +> = async (context) => { + const appName = context.query.appName as string; + + try { + const config: any = await ContentSource.get( + `config/${GEN3_COMMONS_NAME}/apps/${appName}.json`, + ); + + return { + props: { + ...(await getNavPageLayoutPropsFromConfig()), + config: config, + }, + }; + } catch (err) { + console.error(err); + return { + props: { + ...(await getNavPageLayoutPropsFromConfig()), + config: undefined, + }, + }; + } +}; + +export default AppsPage; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 178d3d4..b25b1e8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,13 +1,7 @@ import { - DiscoveryPage, - DiscoveryPageGetServerSideProps as getServerSideProps, + LandingPage, + LandingPageGetStaticProps as getStaticProps, } from '@gen3/frontend'; -import { registerDiscoveryCustomCellRenderers } from '@/lib/Discovery/CustomCellRenderers'; -import { registerDiscoveryStudyPreviewRenderers } from '@/lib/Discovery/CustomRowRenderers'; -registerDiscoveryCustomCellRenderers(); -registerDiscoveryStudyPreviewRenderers(); - -export default DiscoveryPage; - -export { getServerSideProps }; +export default LandingPage; +export { getStaticProps }; diff --git a/src/pages/no-workspace-access.tsx b/src/pages/no-workspace-access.tsx new file mode 100644 index 0000000..b9c9aa9 --- /dev/null +++ b/src/pages/no-workspace-access.tsx @@ -0,0 +1,7 @@ +import { + WorkspaceNoAccessPage, + WorkspaceNoAccessPageServerSideProps as getServerSideProps, +} from '@gen3/frontend'; +export default WorkspaceNoAccessPage; + +export { getServerSideProps }; diff --git a/src/styles/globals.css b/src/styles/globals.css index 4bc9d67..e941002 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,89 +1,20 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss/base"; +@import "tailwindcss/components"; -@import '~@fontsource/montserrat/700.css'; -@import '~@fontsource/montserrat/400-italic.css'; -@import '~@fontsource/montserrat/index.css'; -@import '~@fontsource/montserrat/600.css'; -@import '~@fontsource/montserrat/700-italic.css'; -@import '~@fontsource/source-sans-pro/index.css'; +@import '@mantine/core/styles.css'; +@import '@mantine/notifications/styles.css'; +@import 'mantine-react-table/styles.css'; -.tooltip { - position: relative; - display: inline-block; - font-size: 0.875rem; - font-weight: normal; - line-height: 1.6em; - letter-spacing: 0.02rem; -} - -.has-tooltip .tooltip { - visibility: hidden; - position: absolute; - z-index: 1000; - top: 90%; - vertical-align: middle; - transform: translateX(-75%); -} - -.has-tooltip .tooltip::before { - content: ''; - position: absolute; - bottom: 100%; - left: 50%; - margin-left: 35%; - border-width: 10px; - border-style: solid; - border-color: transparent transparent gray transparent; -} - -.has-tooltip .tooltip::after { - content: ''; - position: absolute; - bottom: 100%; - left: 50%; - margin-left: 35%; - transform: translateY(1px); - border-width: 10px; - border-style: solid; - border-color: transparent transparent white transparent; -} +@import "tailwindcss/utilities"; +@import '@gen3/frontend/dist/styles.css'; -.has-tooltip:hover .tooltip { - visibility: visible; -} +@import 'graphiql/graphiql.css'; +@import '@graphiql/react/dist/style.css'; -.h3-typo { - font-size: 1.125rem; - font-weight: 700; - letter-spacing: 0.02rem; -} - -.body-typo { - font-size: 0.875rem; - font-weight: normal; - line-height: 1.6em; - letter-spacing: 0.02rem; -} - -.navbutton-type { - font-size: 1.125rem; - font-weight: 700; - letter-spacing: 0.02rem; -} @layer base { html { @apply font-heading; } } -.mantine-TableBodyCell-DetailPanel { - border-color: aqua; - border-top: hidden; - padding: 16px; - margin: 16px 0; -} - -@tailwind utilities; @tailwind variants; diff --git a/start.sh b/start.sh deleted file mode 100755 index 5cf0f39..0000000 --- a/start.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -set -e -echo "starting server" -npm run start diff --git a/tailwind.config.js b/tailwind.config.js index f49e613..15fe3cd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,12 +2,12 @@ /* eslint-disable @typescript-eslint/no-var-requires */ const plugin = require('tailwindcss/plugin'); -const themeColors = require('./config/themeColors.json'); -const themeFonts = require('./config/themeFonts.json'); +/* eslint-disable @typescript-eslint/no-var-requires */ +const { GEN3_COMMONS_NAME } = require('@gen3/core'); +const themeColors = require(`./config/${GEN3_COMMONS_NAME}/themeColors.json`); +const themeFonts = require(`./config/${GEN3_COMMONS_NAME}/themeFonts.json`); module.exports = { - presets: [require('@gen3/frontend/tailwind')], - // important: '#__next', // Uncommenting this affects tailwind styling in Modals content: [ './src/pages/**/*.{js,ts,jsx,tsx}', './src/components/**/*.{js,ts,jsx,tsx}',