From ace0a6693b591cff9f2cd8dc601969f725e7b0fb Mon Sep 17 00:00:00 2001 From: Daisie Huang Date: Mon, 24 Jul 2023 11:07:21 -0700 Subject: [PATCH 01/51] Update stable_pr_template.md --- PULL_REQUEST_TEMPLATE/stable_pr_template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PULL_REQUEST_TEMPLATE/stable_pr_template.md b/PULL_REQUEST_TEMPLATE/stable_pr_template.md index 80357313..3e0b320e 100644 --- a/PULL_REQUEST_TEMPLATE/stable_pr_template.md +++ b/PULL_REQUEST_TEMPLATE/stable_pr_template.md @@ -1,6 +1,6 @@ ## vX.X.X: Description Add a summary description of the main user-facing changes made in this release, relative to the last stable release. -- [] Tagged as a release in this repo -- [] Passes integration tests on a development instance -- [] Images pushed to Dockerhub +- [ ] Tagged as a release in this repo +- [ ] Passes integration tests on a development instance +- [ ] Images pushed to Dockerhub From c84596416a636d4e7029e1081a87e3ccd265ef79 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 25 Jul 2023 09:53:42 -0400 Subject: [PATCH 02/51] CanDIG PR dispatch (test branch) --- .github/workflows/candig-dispatch.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/candig-dispatch.yml diff --git a/.github/workflows/candig-dispatch.yml b/.github/workflows/candig-dispatch.yml new file mode 100644 index 00000000..86a38be1 --- /dev/null +++ b/.github/workflows/candig-dispatch.yml @@ -0,0 +1,27 @@ +name: Dispatch +on: + push: + branches: [add-dispatch] +jobs: + CanDIG-dispatch: + runs-on: ubuntu-latest + env: + PARENT_REPOSITORY: 'CanDIG/CanDIGv2' + CHECKOUT_BRANCH: 'develop' + PR_AGAINST_BRANCH: 'develop' + OWNER: 'CanDIG' + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Create PR in CanDIGv2 + id: make_pr + uses: jman005/github-action-pr-expanded@v0 + with: + github_token: ${{ secrets.SUBMODULE_PR }} + parent_repository: ${{ env.PARENT_REPOSITORY }} + checkout_branch: ${{ env.CHECKOUT_BRANCH}} + pr_against_branch: ${{ env.PR_AGAINST_BRANCH }} + pr_description: "PR triggered by update to stable branch on ${{ github.repository }}. Commit hash: ${{ github.sha }} Commit message: ${{ github.event.head_commit.message }}" + owner: ${{ env.OWNER }} + submodule_path: lib/candig-data-portal/candig-data-portal + label: Submodule update From 62d822a46c0bd01962623054674e2a32a77b73b6 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 25 Jul 2023 09:55:53 -0400 Subject: [PATCH 03/51] Stable branch for dispatch --- .github/workflows/candig-dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/candig-dispatch.yml b/.github/workflows/candig-dispatch.yml index 86a38be1..f991cc8d 100644 --- a/.github/workflows/candig-dispatch.yml +++ b/.github/workflows/candig-dispatch.yml @@ -1,7 +1,7 @@ name: Dispatch on: push: - branches: [add-dispatch] + branches: [stable] jobs: CanDIG-dispatch: runs-on: ubuntu-latest From 91555047e81c38265a2d9c640cb4a4ce831230b8 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 25 Jul 2023 10:11:44 -0400 Subject: [PATCH 04/51] Develop branch for PR dispatch --- .github/workflows/candig-dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/candig-dispatch.yml b/.github/workflows/candig-dispatch.yml index f991cc8d..30c67aa7 100644 --- a/.github/workflows/candig-dispatch.yml +++ b/.github/workflows/candig-dispatch.yml @@ -1,7 +1,7 @@ name: Dispatch on: push: - branches: [stable] + branches: [develop] jobs: CanDIG-dispatch: runs-on: ubuntu-latest From 27be8df6263c729c6f7c0dfed06c19d0b74c5bc6 Mon Sep 17 00:00:00 2001 From: Courtney <37649170+CourtneyGosselin@users.noreply.github.com> Date: Thu, 27 Jul 2023 12:29:30 -0700 Subject: [PATCH 05/51] Change from cookies to localstorage (#91) * Change from cookies to localstorage * Change cookie function name to local storage Signed-off-by: Courtney Gosselin --- package.json | 1 - .../widgets/dataVisualization.js | 39 ++++++++++--------- src/views/summary/CustomOfflineChart.js | 33 ++++++++-------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index df271a86..978d67f2 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "highcharts": "^10.0.0", "highcharts-react-official": "^3.1.0", "history": "^5.0.0", - "js-cookie": "^3.0.5", "material-ui-popup-state": "^1.8.0", "npm": "^8.6.0", "papaparse": "^5.3.2", diff --git a/src/views/clinicalGenomic/widgets/dataVisualization.js b/src/views/clinicalGenomic/widgets/dataVisualization.js index b1bd6cea..953c4843 100644 --- a/src/views/clinicalGenomic/widgets/dataVisualization.js +++ b/src/views/clinicalGenomic/widgets/dataVisualization.js @@ -11,7 +11,6 @@ import DialogActions from '@mui/material/DialogActions'; import Button from '@mui/material/Button'; // Third-party libraries -import Cookies from 'js-cookie'; import { IconEdit, IconX, IconPlus } from '@tabler/icons'; // Custom Components and context @@ -69,26 +68,30 @@ function DataVisualization(props) { // Top 4 keys from dataVis const topKeys = Object.keys(dataVis).slice(0, 4); - // Cookies + // LocalStorage const [dataValue, setDataValue] = useState( - Cookies.get('dataVisData') ? JSON.parse(Cookies.get('dataVisData'))[0] : 'patients_per_cohort' + localStorage.getItem('dataVisData') ? JSON.parse(localStorage.getItem('dataVisData'))[0] : 'patients_per_cohort' + ); + const [chartType, setChartType] = useState( + localStorage.getItem('dataVisChartType') ? JSON.parse(localStorage.getItem('dataVisChartType'))[0] : 'bar' + ); + const [dataVisData, setdataVisData] = useState( + localStorage.getItem('dataVisData') ? JSON.parse(localStorage.getItem('dataVisData')) : topKeys ); - const [chartType, setChartType] = useState(Cookies.get('dataVisChartType') ? JSON.parse(Cookies.get('dataVisChartType'))[0] : 'bar'); - const [dataVisData, setdataVisData] = useState(Cookies.get('dataVisData') ? JSON.parse(Cookies.get('dataVisData')) : topKeys); const [dataVisChartType, setDataVisChartType] = useState( - Cookies.get('dataVisChartType') ? JSON.parse(Cookies.get('dataVisChartType')) : ['bar', 'line', 'column', 'bar'] + localStorage.getItem('dataVisChartType') ? JSON.parse(localStorage.getItem('dataVisChartType')) : ['bar', 'line', 'column', 'bar'] ); const [dataVisTrim, setDataVisTrim] = useState( - Cookies.get('dataVisTrim') ? JSON.parse(Cookies.get('dataVisTrim')) : [false, false, false, false] + localStorage.getItem('dataVisTrim') ? JSON.parse(localStorage.getItem('dataVisTrim')) : [false, false, false, false] ); - // Intial cookie setting if there are none + // Intial localStorage setting if there are none useEffect(() => { - if (!Cookies.get('dataVisData') && !Cookies.get('dataVisChartType')) { + if (!localStorage.getItem('dataVisData') && !localStorage.getItem('dataVisChartType')) { const charts = topKeys.map(() => 'bar'); - Cookies.set('dataVisChartType', JSON.stringify(charts), { expires: 365 }); - Cookies.set('dataVisData', JSON.stringify(topKeys), { expires: 365 }); - Cookies.set('dataVisTrim', JSON.stringify([false, false, false, false]), { expires: 365 }); + localStorage.setItem('dataVisChartType', JSON.stringify(charts), { expires: 365 }); + localStorage.setItem('dataVisData', JSON.stringify(topKeys), { expires: 365 }); + localStorage.setItem('dataVisTrim', JSON.stringify([false, false, false, false]), { expires: 365 }); } }, []); @@ -103,9 +106,9 @@ function DataVisualization(props) { setDataVisChartType(newDataVisChartType); setdataVisData(newdataVisData); setDataVisTrim(newDataVisTrim); - Cookies.set('dataVisData', JSON.stringify(newdataVisData), { expires: 365 }); - Cookies.set('dataVisChartType', JSON.stringify(newDataVisChartType), { expires: 365 }); - Cookies.set('dataVisTrim', JSON.stringify(newDataVisTrim), { expires: 365 }); + localStorage.setItem('dataVisData', JSON.stringify(newdataVisData), { expires: 365 }); + localStorage.setItem('dataVisChartType', JSON.stringify(newDataVisChartType), { expires: 365 }); + localStorage.setItem('dataVisTrim', JSON.stringify(newDataVisTrim), { expires: 365 }); } function AddChart(data, chartType) { @@ -116,9 +119,9 @@ function DataVisualization(props) { setDataVisChartType(newDataVisChartType); setdataVisData(newdataVisData); setDataVisTrim(newDataVisTrim); - Cookies.set('dataVisData', JSON.stringify(newdataVisData), { expires: 365 }); - Cookies.set('dataVisChartType', JSON.stringify(newDataVisChartType), { expires: 365 }); - Cookies.set('dataVisTrim', JSON.stringify(newDataVisTrim), { expires: 365 }); + localStorage.setItem('dataVisChartType', JSON.stringify(newDataVisChartType), { expires: 365 }); + localStorage.setItem('dataVisTrim', JSON.stringify(newDataVisTrim), { expires: 365 }); + localStorage.setItem('dataVisData', JSON.stringify(newdataVisData), { expires: 365 }); } /* eslint-disable jsx-a11y/no-onchange */ function returnChartDialog() { diff --git a/src/views/summary/CustomOfflineChart.js b/src/views/summary/CustomOfflineChart.js index 85262bef..b9e436bb 100644 --- a/src/views/summary/CustomOfflineChart.js +++ b/src/views/summary/CustomOfflineChart.js @@ -9,7 +9,6 @@ import { Box, IconButton } from '@mui/material'; import { useSelector } from 'react-redux'; // Third-party libraries -import Cookies from 'js-cookie'; import Highcharts, { map } from 'highcharts'; import HighchartsReact from 'highcharts-react-official'; import NoDataToDisplay from 'highcharts/modules/no-data-to-display'; @@ -257,25 +256,25 @@ function CustomOfflineChart(props) { createChart(); }, [dataVis, chart, chartData, JSON.stringify(dataObject), trim]); - function setCookieDataVisChart(event) { - // Set cookie for Data Visualization Chart Type - const dataVisChart = JSON.parse(Cookies.get('dataVisChartType')); + function setLocalStorageDataVisChart(event) { + // Set LocalStorage for Data Visualization Chart Type + const dataVisChart = JSON.parse(localStorage.getItem('dataVisChartType')); dataVisChart[index] = event.target.value; - Cookies.set('dataVisChartType', JSON.stringify(dataVisChart), { expires: 365 }); + localStorage.setItem('dataVisChartType', JSON.stringify(dataVisChart), { expires: 365 }); } - function setCookieDataVisData(event) { - // Set Cookie for Data Visualization Data - const dataVisData = JSON.parse(Cookies.get('dataVisData')); + function setLocalStorageDataVisData(event) { + // Set LocalStorage for Data Visualization Data + const dataVisData = JSON.parse(localStorage.getItem('dataVisData')); dataVisData[index] = event.target.value; - Cookies.set('dataVisData', JSON.stringify(dataVisData), { expires: 365 }); + localStorage.setItem('dataVisData', JSON.stringify(dataVisData), { expires: 365 }); } - function setCookieDataVisTrim(value) { - // Set Cookie for Data Visualization Trim status - const dataVisTrim = JSON.parse(Cookies.get('dataVisTrim')); + function setLocalStorageDataVisTrim(value) { + // Set LocalStorage for Data Visualization Trim status + const dataVisTrim = JSON.parse(localStorage.getItem('dataVisTrim')); dataVisTrim[index] = value; - Cookies.set('dataVisTrim', JSON.stringify(dataVisTrim), { expires: 365 }); + localStorage.setItem('dataVisTrim', JSON.stringify(dataVisTrim), { expires: 365 }); } /* eslint-disable jsx-a11y/no-onchange */ @@ -329,7 +328,7 @@ function CustomOfflineChart(props) { id="types" onChange={(event) => { setChartData(event.target.value); - setCookieDataVisData(event); + setLocalStorageDataVisData(event); }} > {Object.keys(dataVis).map((key) => ( @@ -350,7 +349,7 @@ function CustomOfflineChart(props) { id="types" onChange={(event) => { setChart(event.target.value); - setCookieDataVisChart(event); + setLocalStorageDataVisChart(event); }} > @@ -365,7 +364,7 @@ function CustomOfflineChart(props) { id="types" onChange={(event) => { setChart(event.target.value); - setCookieDataVisChart(event); + setLocalStorageDataVisChart(event); }} > @@ -382,7 +381,7 @@ function CustomOfflineChart(props) { type="checkbox" id="trim" onChange={() => { - setCookieDataVisTrim(!trim); + setLocalStorageDataVisTrim(!trim); setTrim((old) => !old); }} checked={trim} From 6149ff915d188e306bbad9af437afa8f755675b5 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Thu, 27 Jul 2023 15:27:37 -0400 Subject: [PATCH 06/51] Fix a bug where consuming all data from an endpoint would fail if one server had a lot more data than the other --- src/views/clinicalGenomic/search/SearchHandler.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/clinicalGenomic/search/SearchHandler.js b/src/views/clinicalGenomic/search/SearchHandler.js index b120fb25..c9eb103a 100644 --- a/src/views/clinicalGenomic/search/SearchHandler.js +++ b/src/views/clinicalGenomic/search/SearchHandler.js @@ -18,11 +18,11 @@ function ConsumeAllPages(url, resultConsumer, service = 'katsu') { parsedData[loc.location.name] = []; } - if (loc.results.next) { + if (loc.results?.next) { nextQuery = `${url}${url.includes('?') ? '&' : '?'}page=${idx + 1}`; } - if (loc.results.results) { + if (loc.results?.results) { parsedData[loc.location.name] = parsedData[loc.location.name].concat(loc.results.results.map(resultConsumer)); } }); @@ -102,7 +102,7 @@ function SearchHandler() { } searchParams.append('page_size', 100); - const url = `v2/authorized/donors?${searchParams}`; + const url = `v2/authorized/donors/?${searchParams}`; const donorQueryPromise = () => trackPromise( From 91f8167d00d16bf1b9e3ba08f17fd281882e4b69 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Thu, 3 Aug 2023 14:05:58 -0400 Subject: [PATCH 07/51] Fix a bug where clinical results wouldn't properly filter down genomic results --- src/views/clinicalGenomic/search/SearchHandler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/clinicalGenomic/search/SearchHandler.js b/src/views/clinicalGenomic/search/SearchHandler.js index c9eb103a..22dcfc56 100644 --- a/src/views/clinicalGenomic/search/SearchHandler.js +++ b/src/views/clinicalGenomic/search/SearchHandler.js @@ -316,7 +316,7 @@ function SearchHandler() { return caseData; }) .filter((caseData) => { - if (reader.query && Object.keys(reader.query).length > 0 && caseData.donorID) { + if (reader.donorLists && Object.keys(reader.donorLists).length > 0 && caseData.donorID) { return finalList.includes(caseData.donorID); } return true; From abc6f368ca912b683563472d5a5ca7345236c716 Mon Sep 17 00:00:00 2001 From: Justin Date: Tue, 15 Aug 2023 14:29:17 -0400 Subject: [PATCH 08/51] Remove commit description from dispach --- .github/workflows/candig-dispatch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/candig-dispatch.yml b/.github/workflows/candig-dispatch.yml index 30c67aa7..82467322 100644 --- a/.github/workflows/candig-dispatch.yml +++ b/.github/workflows/candig-dispatch.yml @@ -21,7 +21,7 @@ jobs: parent_repository: ${{ env.PARENT_REPOSITORY }} checkout_branch: ${{ env.CHECKOUT_BRANCH}} pr_against_branch: ${{ env.PR_AGAINST_BRANCH }} - pr_description: "PR triggered by update to stable branch on ${{ github.repository }}. Commit hash: ${{ github.sha }} Commit message: ${{ github.event.head_commit.message }}" + pr_description: "PR triggered by update to develop branch on ${{ github.repository }}. Commit hash: ${{ github.sha }}" owner: ${{ env.OWNER }} submodule_path: lib/candig-data-portal/candig-data-portal label: Submodule update From 7a1ec14a0247876031f9fa45dada06970597b5e6 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Mon, 18 Sep 2023 13:49:38 -0400 Subject: [PATCH 09/51] Add linter --- .github/workflows/lint.yml | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..0a4a842a --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,40 @@ +name: Lint + +on: + # Trigger the workflow on push or pull request, + # but only for the main branch + push: + branches: + - main + pull_request: + branches: + - main + +# Down scope as necessary via https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token +permissions: + checks: write + contents: write + +jobs: + run-linters: + name: Run linters + runs-on: ubuntu-latest + + steps: + - name: Check out Git repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v1 + with: + node-version: 12 + + + - name: Install Node.js dependencies + run: npm ci + + - name: Run linters + uses: wearerequired/lint-action@v2 + with: + eslint: true + prettier: true From cfbdd9ba4b86a2955a153f16810ba829a533437d Mon Sep 17 00:00:00 2001 From: fnguyen Date: Mon, 18 Sep 2023 13:51:28 -0400 Subject: [PATCH 10/51] The PR should be to develop, not main --- .github/workflows/lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0a4a842a..b466e241 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,10 +5,10 @@ on: # but only for the main branch push: branches: - - main + - develop pull_request: branches: - - main + - develop # Down scope as necessary via https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token permissions: From 6427493d07a423689604e6758aacd5c3d8a4d7a2 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 11:38:49 -0400 Subject: [PATCH 11/51] Linter fixes --- .eslintrc | 3 + package-lock.json | 16 ++-- package.json | 1 - .../NotificationSection/NotificationList.js | 2 - .../Header/ProfileSection/UpgradePlanCard.js | 2 - .../MainLayout/Header/SearchSection/index.js | 2 +- .../MainLayout/Sidebar/SidebarContext.js | 7 ++ src/layout/NavMotion.js | 1 - src/ui-component/cards/CardSecondaryAction.js | 1 - .../cards/Skeleton/ImagePlaceholder.js | 2 - .../cards/Skeleton/PopularCard.js | 1 - .../cards/Skeleton/TotalGrowthBarChart.js | 2 - src/ui-component/extended/Avatar.js | 1 - src/views/clinical/mcode.js | 3 + .../clinicalGenomic/clinicalGenomicSearch.js | 9 +- .../clinicalGenomic/search/SearchHandler.js | 11 ++- .../clinicalGenomic/widgets/clinicalData.js | 34 +------- .../widgets/dataVisualization.js | 4 +- .../clinicalGenomic/widgets/genomicData.js | 34 +------- .../widgets/patientCountSingle.js | 8 +- .../clinicalGenomic/widgets/patientCounts.js | 2 +- .../clinicalGenomic/widgets/patientView.js | 85 ++++++++++--------- src/views/clinicalGenomic/widgets/sidebar.js | 35 ++++++-- .../dashboard/Default/TotalIncomeDarkCard.js | 1 - .../dashboard/Default/datasetIdSelect.js | 12 +-- src/views/dashboard/Default/index.js | 2 +- src/views/genomicsData/HtsgetBrowser.js | 6 +- src/views/genomicsData/IGViewer.js | 34 +++++--- src/views/genomicsData/VariantsSearch.js | 16 ++-- src/views/summary/CustomOfflineChart.js | 38 +++++++-- src/views/summary/TreatingCentreMap.js | 3 - src/views/summary/summary.js | 2 +- src/views/utilities/Color.js | 1 - src/views/utilities/MaterialIcons.js | 2 - src/views/utilities/Shadow.js | 1 - src/views/utilities/TablerIcons.js | 2 - src/views/utilities/Typography.js | 1 - 37 files changed, 202 insertions(+), 185 deletions(-) diff --git a/.eslintrc b/.eslintrc index 46f55f4c..a294a621 100644 --- a/.eslintrc +++ b/.eslintrc @@ -44,6 +44,9 @@ "no-unused-vars": [ 1, { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_", "ignoreRestSiblings": false } ], diff --git a/package-lock.json b/package-lock.json index 1fa64919..22b5f7fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6663,9 +6663,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001343", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001343.tgz", - "integrity": "sha512-8KeCrAtPMabo/XW14B+R9sZYoClx1n0b+WYgwDKZPtWR3TcdvWzdSy7mPyFEmR5WU1St9v1PW6sdO5dkFOEzfA==", + "version": "1.0.30001535", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001535.tgz", + "integrity": "sha512-48jLyUkiWFfhm/afF7cQPqPjaUmSraEhK4j+FCTJpgnGGEZHqyLe3hmWH7lIooZdSzXL0ReMvHz0vKDoTBsrwg==", "funding": [ { "type": "opencollective", @@ -6674,6 +6674,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -27891,9 +27895,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001343", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001343.tgz", - "integrity": "sha512-8KeCrAtPMabo/XW14B+R9sZYoClx1n0b+WYgwDKZPtWR3TcdvWzdSy7mPyFEmR5WU1St9v1PW6sdO5dkFOEzfA==" + "version": "1.0.30001535", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001535.tgz", + "integrity": "sha512-48jLyUkiWFfhm/afF7cQPqPjaUmSraEhK4j+FCTJpgnGGEZHqyLe3hmWH7lIooZdSzXL0ReMvHz0vKDoTBsrwg==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", diff --git a/package.json b/package.json index 978d67f2..c2a43107 100644 --- a/package.json +++ b/package.json @@ -96,4 +96,3 @@ "webpack-cli": "^4.9.2" } } - diff --git a/src/layout/MainLayout/Header/NotificationSection/NotificationList.js b/src/layout/MainLayout/Header/NotificationSection/NotificationList.js index de2983fe..25a29b56 100644 --- a/src/layout/MainLayout/Header/NotificationSection/NotificationList.js +++ b/src/layout/MainLayout/Header/NotificationSection/NotificationList.js @@ -1,5 +1,3 @@ -import React from 'react'; - import { makeStyles } from '@mui/styles'; import { Avatar, diff --git a/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.js b/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.js index 1dee2001..9484637d 100644 --- a/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.js +++ b/src/layout/MainLayout/Header/ProfileSection/UpgradePlanCard.js @@ -1,5 +1,3 @@ -import React from 'react'; - import { makeStyles } from '@mui/styles'; import { Button, Card, CardContent, Grid, Stack, Typography } from '@mui/material'; diff --git a/src/layout/MainLayout/Header/SearchSection/index.js b/src/layout/MainLayout/Header/SearchSection/index.js index e8de0428..2f9eb180 100644 --- a/src/layout/MainLayout/Header/SearchSection/index.js +++ b/src/layout/MainLayout/Header/SearchSection/index.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; // material-ui import { makeStyles } from '@mui/styles'; diff --git a/src/layout/MainLayout/Sidebar/SidebarContext.js b/src/layout/MainLayout/Sidebar/SidebarContext.js index 557b4aca..d87e6d66 100644 --- a/src/layout/MainLayout/Sidebar/SidebarContext.js +++ b/src/layout/MainLayout/Sidebar/SidebarContext.js @@ -1,5 +1,7 @@ import React from 'react'; +import PropTypes from 'prop-types'; + const DEFAULT_STATE = false; const SidebarReaderContext = React.createContext(DEFAULT_STATE); @@ -20,6 +22,11 @@ export function SidebarProvider(props) { ); } +SidebarProvider.propTypes = { + data: PropTypes.object, + setData: PropTypes.func +}; + /** * Obtain the context reader of the federation sites query. * @returns {Object} a React context of the sidebar DOM component diff --git a/src/layout/NavMotion.js b/src/layout/NavMotion.js index 0daa894c..f513d5f1 100644 --- a/src/layout/NavMotion.js +++ b/src/layout/NavMotion.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // third-party import { motion } from 'framer-motion'; diff --git a/src/ui-component/cards/CardSecondaryAction.js b/src/ui-component/cards/CardSecondaryAction.js index 4f0aa9f2..ed5166f0 100644 --- a/src/ui-component/cards/CardSecondaryAction.js +++ b/src/ui-component/cards/CardSecondaryAction.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // mui import { useTheme } from '@mui/styles'; diff --git a/src/ui-component/cards/Skeleton/ImagePlaceholder.js b/src/ui-component/cards/Skeleton/ImagePlaceholder.js index 94aef7ee..40f2e50f 100644 --- a/src/ui-component/cards/Skeleton/ImagePlaceholder.js +++ b/src/ui-component/cards/Skeleton/ImagePlaceholder.js @@ -1,5 +1,3 @@ -import React from 'react'; - // mui import Skeleton from '@mui/material/Skeleton'; diff --git a/src/ui-component/cards/Skeleton/PopularCard.js b/src/ui-component/cards/Skeleton/PopularCard.js index d0965147..19ca6f3f 100644 --- a/src/ui-component/cards/Skeleton/PopularCard.js +++ b/src/ui-component/cards/Skeleton/PopularCard.js @@ -1,4 +1,3 @@ -import React from 'react'; // mui import { makeStyles } from '@mui/styles'; import { Card, CardContent, Grid, Skeleton } from '@mui/material'; diff --git a/src/ui-component/cards/Skeleton/TotalGrowthBarChart.js b/src/ui-component/cards/Skeleton/TotalGrowthBarChart.js index a0ea7b92..ab758bb0 100644 --- a/src/ui-component/cards/Skeleton/TotalGrowthBarChart.js +++ b/src/ui-component/cards/Skeleton/TotalGrowthBarChart.js @@ -1,5 +1,3 @@ -import React from 'react'; - // mui import { Card, CardContent, Grid } from '@mui/material'; import Skeleton from '@mui/material/Skeleton'; diff --git a/src/ui-component/extended/Avatar.js b/src/ui-component/extended/Avatar.js index 2e89a895..96891ee9 100644 --- a/src/ui-component/extended/Avatar.js +++ b/src/ui-component/extended/Avatar.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // mui import { makeStyles } from '@mui/styles'; diff --git a/src/views/clinical/mcode.js b/src/views/clinical/mcode.js index b6dd9569..b4b74d64 100644 --- a/src/views/clinical/mcode.js +++ b/src/views/clinical/mcode.js @@ -66,6 +66,8 @@ const useStyles = makeStyles({ } }); +// NB: This function isn't really used anywhere and it's messing with the linter +/* eslint-disable react-hooks/exhaustive-deps */ function MCodeView() { const theme = useTheme(); const classes = useStyles(); @@ -635,5 +637,6 @@ function MCodeView() { ); } +/* eslint-enable react-hooks/exhaustive-deps */ export default MCodeView; diff --git a/src/views/clinicalGenomic/clinicalGenomicSearch.js b/src/views/clinicalGenomic/clinicalGenomicSearch.js index bda5ddb0..37b67827 100644 --- a/src/views/clinicalGenomic/clinicalGenomicSearch.js +++ b/src/views/clinicalGenomic/clinicalGenomicSearch.js @@ -1,9 +1,9 @@ import { useEffect } from 'react'; import { useSelector } from 'react-redux'; -import { AppBar, Button, Divider, Toolbar, Typography } from '@mui/material'; +import { AppBar, Button, Toolbar, Typography } from '@mui/material'; -import { makeStyles, useTheme } from '@mui/styles'; +import { makeStyles } from '@mui/styles'; import MainCard from 'ui-component/cards/MainCard'; import VariantsSearch from '../genomicsData/VariantsSearch'; import PatientCounts from './widgets/patientCounts'; @@ -16,7 +16,7 @@ import { COHORTS } from 'store/constant'; import SearchHandler from './search/SearchHandler'; import GenomicData from './widgets/genomicData'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_) => ({ stickytop: { position: 'fixed', backgroundColor: 'white', @@ -81,12 +81,11 @@ function ClinicalGenomicSearch() { const classes = useStyles(); const sidebarWriter = useSidebarWriterContext(); const sidebarOpened = useSelector((state) => state.customization.opened); - const theme = useTheme(); // When we load, set the sidebar component useEffect(() => { sidebarWriter(); - }, []); + }, [sidebarWriter]); return ( <> diff --git a/src/views/clinicalGenomic/search/SearchHandler.js b/src/views/clinicalGenomic/search/SearchHandler.js index 22dcfc56..6c521bf1 100644 --- a/src/views/clinicalGenomic/search/SearchHandler.js +++ b/src/views/clinicalGenomic/search/SearchHandler.js @@ -37,6 +37,10 @@ function ConsumeAllPages(url, resultConsumer, service = 'katsu') { return fetchFederation(url, service).then((data) => RecursiveQuery(data, 1)); } +// NB: I assign to lastPromise a bunch to keep track of whether or not we need to chain promises together +// However, the linter really dislikes this, and assumes I want to put everything inside one useEffect? +/* eslint-disable react-hooks/exhaustive-deps */ + // This handles transforming queries in the SearchResultsContext to actual search queries function SearchHandler() { const reader = useSearchQueryReaderContext(); @@ -316,7 +320,11 @@ function SearchHandler() { return caseData; }) .filter((caseData) => { - if (reader.donorLists && Object.keys(reader.donorLists).length > 0 && caseData.donorID) { + if ( + reader.donorLists && + Object.keys(reader.donorLists).length > 0 && + caseData.donorID + ) { return finalList.includes(caseData.donorID); } return true; @@ -357,5 +365,6 @@ function SearchHandler() { // NB: This might be a good reason to have this be a function call instead of what it currently is. return <>; } +/* eslint-enable react-hooks/exhaustive-deps */ export default SearchHandler; diff --git a/src/views/clinicalGenomic/widgets/clinicalData.js b/src/views/clinicalGenomic/widgets/clinicalData.js index 71cf02d9..1862c40c 100644 --- a/src/views/clinicalGenomic/widgets/clinicalData.js +++ b/src/views/clinicalGenomic/widgets/clinicalData.js @@ -1,7 +1,7 @@ import * as React from 'react'; // mui -import { useTheme, makeStyles } from '@mui/styles'; +import { useTheme } from '@mui/styles'; import { DataGrid } from '@mui/x-data-grid'; import { Box, Typography } from '@mui/material'; @@ -10,38 +10,6 @@ import { Box, Typography } from '@mui/material'; // project imports import { useSearchQueryWriterContext, useSearchResultsReaderContext } from '../SearchResultsContext'; -// Styles -const useStyles = makeStyles({ - dropdownItem: { - background: 'white', - paddingRight: '1.25em', - paddingLeft: '1.25em', - border: 'none', - width: 'fit-content(5em)', - '&:hover': { - background: '#2196f3', - color: 'white' - } - }, - mobileRow: { - width: '800px' - }, - scrollbar: { - scrollbarWidth: 'thin', - '&::-webkit-scrollbar': { - height: '0.4em', - width: '0.4em' - }, - '&::-webkit-scrollbar-track': { - boxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)', - webkitBoxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)' - }, - '&::-webkit-scrollbar-thumb': { - backgroundColor: 'rgba(0,0,0,.1)' - } - } -}); - function ClinicalView() { const theme = useTheme(); diff --git a/src/views/clinicalGenomic/widgets/dataVisualization.js b/src/views/clinicalGenomic/widgets/dataVisualization.js index 953c4843..c04e7d4a 100644 --- a/src/views/clinicalGenomic/widgets/dataVisualization.js +++ b/src/views/clinicalGenomic/widgets/dataVisualization.js @@ -20,7 +20,7 @@ import { useSearchResultsReaderContext } from '../SearchResultsContext'; // Constants import { validStackedCharts, DataVisualizationChartInfo } from 'store/constant'; -function DataVisualization(props) { +function DataVisualization() { // Hooks const resultsContext = useSearchResultsReaderContext().counts; // Plan for context below see current dataVis for expected shape @@ -93,7 +93,7 @@ function DataVisualization(props) { localStorage.setItem('dataVisData', JSON.stringify(topKeys), { expires: 365 }); localStorage.setItem('dataVisTrim', JSON.stringify([false, false, false, false]), { expires: 365 }); } - }, []); + }, []); // eslint-disable-line react-hooks/exhaustive-deps const handleToggleDialog = () => { setOpen((prevOpen) => !prevOpen); diff --git a/src/views/clinicalGenomic/widgets/genomicData.js b/src/views/clinicalGenomic/widgets/genomicData.js index d0ad1310..3658cdcc 100644 --- a/src/views/clinicalGenomic/widgets/genomicData.js +++ b/src/views/clinicalGenomic/widgets/genomicData.js @@ -1,7 +1,7 @@ import * as React from 'react'; // mui -import { useTheme, makeStyles } from '@mui/styles'; +import { useTheme } from '@mui/styles'; import { DataGrid } from '@mui/x-data-grid'; import { Box, Typography } from '@mui/material'; @@ -10,38 +10,6 @@ import { Box, Typography } from '@mui/material'; // project imports import { useSearchQueryReaderContext, useSearchResultsReaderContext } from '../SearchResultsContext'; -// Styles -const useStyles = makeStyles({ - dropdownItem: { - background: 'white', - paddingRight: '1.25em', - paddingLeft: '1.25em', - border: 'none', - width: 'fit-content(5em)', - '&:hover': { - background: '#2196f3', - color: 'white' - } - }, - mobileRow: { - width: '800px' - }, - scrollbar: { - scrollbarWidth: 'thin', - '&::-webkit-scrollbar': { - height: '0.4em', - width: '0.4em' - }, - '&::-webkit-scrollbar-track': { - boxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)', - webkitBoxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)' - }, - '&::-webkit-scrollbar-thumb': { - backgroundColor: 'rgba(0,0,0,.1)' - } - } -}); - function GenomicData() { const theme = useTheme(); diff --git a/src/views/clinicalGenomic/widgets/patientCountSingle.js b/src/views/clinicalGenomic/widgets/patientCountSingle.js index b5a420ce..ecb2e4ba 100644 --- a/src/views/clinicalGenomic/widgets/patientCountSingle.js +++ b/src/views/clinicalGenomic/widgets/patientCountSingle.js @@ -1,9 +1,10 @@ -import { Fragment, useEffect, useState } from 'react'; +import { useState } from 'react'; import { Avatar, Box, Button, CardHeader, Divider, Grid, Typography } from '@mui/material'; import { useTheme, makeStyles } from '@mui/styles'; import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore'; import UnfoldLessIcon from '@mui/icons-material/UnfoldLess'; +import PropTypes from 'prop-types'; const useStyles = makeStyles((theme) => ({ patientEntry: { @@ -138,4 +139,9 @@ function PatientCountSingle(props) { ); } +PatientCountSingle.propTypes = { + site: PropTypes.string, + counts: PropTypes.object +}; + export default PatientCountSingle; diff --git a/src/views/clinicalGenomic/widgets/patientCounts.js b/src/views/clinicalGenomic/widgets/patientCounts.js index 2f2481d9..4af074a8 100644 --- a/src/views/clinicalGenomic/widgets/patientCounts.js +++ b/src/views/clinicalGenomic/widgets/patientCounts.js @@ -14,7 +14,7 @@ const useStyles = makeStyles((theme) => ({ } })); -function PatientCounts(props) { +function PatientCounts() { const classes = useStyles(); const context = useSearchResultsReaderContext(); const sites = context?.federation; diff --git a/src/views/clinicalGenomic/widgets/patientView.js b/src/views/clinicalGenomic/widgets/patientView.js index 6cdb7d91..91b8f950 100644 --- a/src/views/clinicalGenomic/widgets/patientView.js +++ b/src/views/clinicalGenomic/widgets/patientView.js @@ -5,10 +5,11 @@ import { makeStyles, useTheme } from '@mui/styles'; import { TreeView, TreeItem } from '@mui/lab'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import PropTypes from 'prop-types'; import { useSearchResultsReaderContext } from '../SearchResultsContext'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_theme) => ({ label: { textTransform: 'capitalize', display: 'inline-flex' @@ -96,7 +97,49 @@ const JSONTree = (props) => { ); }; -function PatientView(props) { +JSONTree.propTypes = { + id: PropTypes.string, + label: PropTypes.string, + json: PropTypes.object, + searchExp: PropTypes.string +}; + +// Prune the patient entry according to search +const recursivePrune = (json, searchTerm) => { + if (Array.isArray(json)) { + // Create a new array with pruned children + const retVal = json.map((child) => recursivePrune(child, searchTerm)).filter((child) => child !== undefined); + return retVal.length <= 0 ? undefined : retVal; + } + + if (isObject(json)) { + // Find any key that matches the search + const retVal = {}; + Object.keys(json).forEach((key) => { + if (key.toLowerCase().indexOf(searchTerm) >= 0) { + // include all children of a matching parent + retVal[key] = json[key]; + return; + } + + // For all non-valid keys, there might be a valid child -- recurse downwards and prune + const childObj = recursivePrune(json[key], searchTerm); + if (childObj !== undefined) { + retVal[key] = childObj; + } + }); + return Object.keys(retVal).length > 0 ? retVal : undefined; + } + + if (typeof json === 'string' && json.toLowerCase().indexOf(searchTerm) >= 0) { + // Check if we're a match of the search + return json; + } + + return undefined; +}; + +function PatientView() { const resultsContext = useSearchResultsReaderContext(); const patient = resultsContext.donor?.map((loc) => loc?.results?.results?.[0])?.filter((donor) => donor)?.[0]; const [expanded, setExpanded] = useState(['.']); @@ -116,41 +159,6 @@ function PatientView(props) { return includeValues ? [`${prefix}:${typeof json === 'string' ? json.toLowerCase() : json}`] : []; }; - // Prune the patient entry according to search - const recursivePrune = (json, searchTerm) => { - if (Array.isArray(json)) { - // Create a new array with pruned children - const retVal = json.map((child) => recursivePrune(child, searchTerm)).filter((child) => child !== undefined); - return retVal.length <= 0 ? undefined : retVal; - } - - if (isObject(json)) { - // Find any key that matches the search - const retVal = {}; - Object.keys(json).forEach((key) => { - if (key.toLowerCase().indexOf(searchTerm) >= 0) { - // include all children of a matching parent - retVal[key] = json[key]; - return; - } - - // For all non-valid keys, there might be a valid child -- recurse downwards and prune - const childObj = recursivePrune(json[key], searchTerm); - if (childObj !== undefined) { - retVal[key] = childObj; - } - }); - return Object.keys(retVal).length > 0 ? retVal : undefined; - } - - if (typeof json === 'string' && json.toLowerCase().indexOf(searchTerm) >= 0) { - // Check if we're a match of the search - return json; - } - - return undefined; - }; - const handleExpandAll = () => { setExpanded((old) => (old.length <= 1 ? getAllChildIDs(prunedPatient, '.', false) : ['.'])); }; @@ -199,6 +207,7 @@ function PatientView(props) { }; // When the patient changes, we need to update the pruned view according to search + const patientString = JSON.stringify(patient); useEffect(() => { if (search !== '') { setPrunedPatient(recursivePrune(patient, search)); @@ -206,7 +215,7 @@ function PatientView(props) { // Otherwise, just reset the prunedPatient view to the patient view setPrunedPatient(patient); } - }, [JSON.stringify(patient)]); + }, [patientString]); // eslint-disable-line react-hooks/exhaustive-deps const noResultsMessage = !patient ? ( 'Please select a patient from the above table' diff --git a/src/views/clinicalGenomic/widgets/sidebar.js b/src/views/clinicalGenomic/widgets/sidebar.js index 2f5544fd..4d13a202 100644 --- a/src/views/clinicalGenomic/widgets/sidebar.js +++ b/src/views/clinicalGenomic/widgets/sidebar.js @@ -15,11 +15,12 @@ import { import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; import CheckBoxIcon from '@mui/icons-material/CheckBox'; import { makeStyles, useTheme } from '@mui/styles'; +import PropTypes from 'prop-types'; import { useSearchQueryWriterContext, useSearchResultsReaderContext } from '../SearchResultsContext'; import { fetchFederation } from '../../../store/api'; -const useStyles = makeStyles((theme) => ({ +const useStyles = makeStyles((_) => ({ tab: { minWidth: 40 }, @@ -73,6 +74,12 @@ function SidebarGroup(props) { ); } +SidebarGroup.propTypes = { + name: PropTypes.string, + children: PropTypes.node, + hide: PropTypes.bool +}; + function StyledCheckboxList(props) { const { groupName, isDonorList, isFilterList, remap, onWrite, options, useAutoComplete, hide } = props; const [checked, setChecked] = useState({}); @@ -205,15 +212,26 @@ function StyledCheckboxList(props) { )) ); } + +StyledCheckboxList.propTypes = { + groupName: PropTypes.string, + hide: PropTypes.bool, + isDonorList: PropTypes.bool, + isFilterList: PropTypes.bool, + remap: PropTypes.func, + onWrite: PropTypes.func, + options: PropTypes.array, + useAutoComplete: PropTypes.bool +}; + // A group of genomics data // Keeping this separate from the rest as it's all somewhat self-contained // NB: Should maybe go into a separate .js file function GenomicsGroup(props) { const { chromosomes, genes, onWrite, hide } = props; - const classes = useStyles(); // Genomic data - const referenceGenomes = ['hg38']; - const [selectedGenome, setSelectedGenome] = useState('hg38'); + // const referenceGenomes = ['hg38']; + const [selectedGenome, _setSelectedGenome] = useState('hg38'); const [selectedChromosomes, setSelectedChromosomes] = useState(''); const [selectedGenes, setSelectedGenes] = useState(''); const [startPos, setStartPos] = useState(0); @@ -300,7 +318,14 @@ function GenomicsGroup(props) { ); } -function Sidebar(props) { +GenomicsGroup.propTypes = { + chromosomes: PropTypes.array, + genes: PropTypes.array, + hide: PropTypes.bool, + onWrite: PropTypes.func +}; + +function Sidebar() { const [selectedtab, setSelectedTab] = useState('All'); const readerContext = useSearchResultsReaderContext(); const writerContext = useSearchQueryWriterContext(); diff --git a/src/views/dashboard/Default/TotalIncomeDarkCard.js b/src/views/dashboard/Default/TotalIncomeDarkCard.js index c8a6abf4..62e0a2a4 100644 --- a/src/views/dashboard/Default/TotalIncomeDarkCard.js +++ b/src/views/dashboard/Default/TotalIncomeDarkCard.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // mui import { makeStyles } from '@mui/styles'; diff --git a/src/views/dashboard/Default/datasetIdSelect.js b/src/views/dashboard/Default/datasetIdSelect.js index fac49806..f8cbec01 100644 --- a/src/views/dashboard/Default/datasetIdSelect.js +++ b/src/views/dashboard/Default/datasetIdSelect.js @@ -1,9 +1,9 @@ -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import Box from '@mui/material/Box'; import MenuItem from '@mui/material/MenuItem'; import FormControl from '@mui/material/FormControl'; import Select from '@mui/material/Select'; -import { fetchDatasets } from '../../../store/api'; +// import { fetchDatasets } from '../../../store/api'; import AlertComponent from 'ui-component/AlertComponent'; // REDUX @@ -15,15 +15,16 @@ export default function DatasetIdSelect() { // STATES const [selectedDataset, setSelectedDataset] = useState(events.customization.selectedDataset); - const [datasets, setDatasets] = useState(events.customization.datasets); + const [datasets, _setDatasets] = useState(events.customization.datasets); const [open, setOpen] = useState(false); - const [alertMessage, setAlertMessage] = useState(''); - const [alertSeverity, setAlertSeverity] = useState(''); + const [alertMessage, _setAlertMessage] = useState(''); + const [alertSeverity, _setAlertSeverity] = useState(''); function updateParentState(datasetName, datasetId) { dispatch({ type: 'SET_UPDATE_STATE', payload: { datasetName, datasetId } }); } + /* function setFirstDataset(datasetsList) { const firstDataset = datasetsList[Object.keys(datasetsList)[0]]; setSelectedDataset(firstDataset.name); @@ -57,6 +58,7 @@ export default function DatasetIdSelect() { }); } }); + */ const handleChange = (id, name) => { setSelectedDataset(name); diff --git a/src/views/dashboard/Default/index.js b/src/views/dashboard/Default/index.js index c40d70f2..56e12752 100644 --- a/src/views/dashboard/Default/index.js +++ b/src/views/dashboard/Default/index.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; // mui import { Grid } from '@mui/material'; diff --git a/src/views/genomicsData/HtsgetBrowser.js b/src/views/genomicsData/HtsgetBrowser.js index 703f9fd6..2728ab63 100644 --- a/src/views/genomicsData/HtsgetBrowser.js +++ b/src/views/genomicsData/HtsgetBrowser.js @@ -28,8 +28,8 @@ function HtsgetBrowser() { const [open, setOpen] = useState(false); const [selectedBamIds, setSelectedBamIds] = useState([]); const [selectedVcfIds, setSelectedVcfIds] = useState([]); - const [alertMessage, setAlertMessage] = useState(''); - const [alertSeverity, setAlertSeverity] = useState(''); + const [alertMessage, _setAlertMessage] = useState(''); + const [alertSeverity, _setAlertSeverity] = useState(''); useEffect(() => { setSelected([]); @@ -41,7 +41,7 @@ function HtsgetBrowser() { // Get a list of genomics files available trackPromise( fetchKatsu('/api/genomicsreports') - .then((data) => { + .then((_data) => { // TODO: get a list of ids of genomics files from API above // Or any other APIs that can provide a list of IDs // Note: if only VCF files are served, then the following TODOs concerning BAM files diff --git a/src/views/genomicsData/IGViewer.js b/src/views/genomicsData/IGViewer.js index 08b7a287..ecfa29f2 100644 --- a/src/views/genomicsData/IGViewer.js +++ b/src/views/genomicsData/IGViewer.js @@ -1,24 +1,36 @@ +import { useState } from 'react'; + +import { Alert, Snackbar } from '@mui/material'; + import NewWindow from 'react-new-window'; import CramVcfInstance from 'ui-component/IGV/CramVcfInstance'; import PropTypes from 'prop-types'; const IGViewer = ({ closeWindow, options }) => { + const [open, setOpen] = useState(false); const onClosed = () => { closeWindow(); }; return ( - alert('Please allow popups for this website')} - features={{ - outerHeight: '100%', - outerWidth: '100%' - }} - > - - + <> + setOpen(false)}> + setOpen(false)} severity="error" sx={{ width: '100%' }}> + Please allow popups for this website + + + setOpen(true)} + features={{ + outerHeight: '100%', + outerWidth: '100%' + }} + > + + + ); }; diff --git a/src/views/genomicsData/VariantsSearch.js b/src/views/genomicsData/VariantsSearch.js index fb037e46..aa5cac0f 100644 --- a/src/views/genomicsData/VariantsSearch.js +++ b/src/views/genomicsData/VariantsSearch.js @@ -7,11 +7,11 @@ import VariantsTable from 'ui-component/Tables/VariantsTable'; import { SearchIndicator } from 'ui-component/LoadingIndicator/SearchIndicator'; import AlertComponent from 'ui-component/AlertComponent'; import { ListOfReferenceNames } from 'store/constant'; -import { trackPromise, usePromiseTracker } from 'ui-component/LoadingIndicator/LoadingIndicator'; +import { trackPromise } from 'ui-component/LoadingIndicator/LoadingIndicator'; import 'assets/css/VariantsSearch.css'; import { searchVariant, fetchFederationClinicalData, htsget } from 'store/api'; import IGViewer from './IGViewer'; -import DropDown from '../../ui-component/DropDown'; +// import DropDown from '../../ui-component/DropDown'; import { processMCodeMainData, processMedicationListData, @@ -26,6 +26,10 @@ import { useTheme } from '@mui/styles'; import Stack from '@mui/material/Stack'; import Divider from '@mui/material/Divider'; +// NB: This VariantsSearch is currently unused, but is throwing linter errors +// Disabling it for now +/* eslint-disable no-unused-vars */ +/* eslint-disable react-hooks/exhaustive-deps */ function VariantsSearch() { const [isLoading, setLoading] = useState(true); const theme = useTheme(); @@ -34,12 +38,12 @@ function VariantsSearch() { const [rowData, setRowData] = useState([]); const [displayVariantsTable, setDisplayVariantsTable] = useState(false); - const { promiseInProgress } = usePromiseTracker(); + // const { promiseInProgress } = usePromiseTracker(); const [open, setOpen] = useState(false); const [alertMessage, setAlertMessage] = useState(''); const [alertSeverity, setAlertSeverity] = useState('warning'); const [isIGVWindowOpen, setIsIGVWindowOpen] = useState(false); - const [showIGVButton, setShowIGVButton] = useState(false); + const [_showIGVButton, setShowIGVButton] = useState(false); const [IGVOptions, setIGVOptions] = useState({}); const [variantSearchOptions, setVariantSearchOptions] = useState({}); const [patientList, setPatientList] = useState([]); @@ -48,7 +52,7 @@ function VariantsSearch() { // Clinical Search Filter const clinicalSearchPatients = useSelector((state) => state.customization.clinicalSearchResultPatients); const clinicalSearch = useSelector((state) => state.customization.clinicalSearch); - const [cancerType, setCancerType] = React.useState([]); + const [cancerType, _setCancerType] = React.useState([]); // Dropdown patient table open/closed const [isListOpenMedications, setListOpenMedications] = React.useState(false); @@ -567,5 +571,7 @@ function VariantsSearch() { ); } +/* eslint-enable no-unused-vars */ +/* eslint-enable react-hooks/exhaustive-deps */ export default VariantsSearch; diff --git a/src/views/summary/CustomOfflineChart.js b/src/views/summary/CustomOfflineChart.js index b9e436bb..f1aeaa2c 100644 --- a/src/views/summary/CustomOfflineChart.js +++ b/src/views/summary/CustomOfflineChart.js @@ -1,4 +1,4 @@ -import { createRef, useCallback, useState, useEffect } from 'react'; +import { createRef, useState, useEffect } from 'react'; // MUI import PropTypes from 'prop-types'; @@ -9,7 +9,7 @@ import { Box, IconButton } from '@mui/material'; import { useSelector } from 'react-redux'; // Third-party libraries -import Highcharts, { map } from 'highcharts'; +import Highcharts from 'highcharts'; import HighchartsReact from 'highcharts-react-official'; import NoDataToDisplay from 'highcharts/modules/no-data-to-display'; import { IconTrash } from '@tabler/icons'; @@ -197,7 +197,7 @@ function CustomOfflineChart(props) { series: [{ data, colorByPoint: true, showInLegend: false }], tooltip: { useHTML: true, - formatter: function () { + formatter: () => { let dataSum = 0; this.series.points.forEach((point) => { dataSum += point.y; @@ -254,7 +254,22 @@ function CustomOfflineChart(props) { } createChart(); - }, [dataVis, chart, chartData, JSON.stringify(dataObject), trim]); + }, [ + dataVis, + chart, + chartData, + trim, + cutoff, + dataObject, + grayscale, + height, + orderAlphabetically, + orderByFrequency, + theme.palette.grey, + theme.palette.primary, + theme.palette.secondary, + theme.palette.tertiary + ]); function setLocalStorageDataVisChart(event) { // Set LocalStorage for Data Visualization Chart Type @@ -288,7 +303,7 @@ function CustomOfflineChart(props) { } else { chartObj?.hideLoading(); } - }, [loading]); + }, [chartRef, loading]); const showTrim = (dataObject || dataVis[chartData]) && Object.entries(dataObject === '' ? dataVis[chartData] : dataObject).length > 15; @@ -397,15 +412,20 @@ function CustomOfflineChart(props) { } CustomOfflineChart.propTypes = { + chartType: PropTypes.string, + cutoff: PropTypes.number, + data: PropTypes.string, + dataObject: PropTypes.any, + dataVis: PropTypes.any, dropDown: PropTypes.bool, + edit: PropTypes.bool, + grayscale: PropTypes.bool, height: PropTypes.string, - dataVis: PropTypes.any, - dataObject: PropTypes.any, + index: PropTypes.number, + loading: PropTypes.bool, onRemoveChart: PropTypes.func, - grayscale: PropTypes.bool, orderByFrequency: PropTypes.bool, orderAlphabetically: PropTypes.bool, - cutoff: PropTypes.number, trimByDefault: PropTypes.bool }; diff --git a/src/views/summary/TreatingCentreMap.js b/src/views/summary/TreatingCentreMap.js index 70607cb7..c8ccb716 100644 --- a/src/views/summary/TreatingCentreMap.js +++ b/src/views/summary/TreatingCentreMap.js @@ -5,9 +5,6 @@ import HighchartsMap from 'highcharts/modules/map'; import mapDataCanada from '@highcharts/map-collection/countries/ca/ca-all.geo.json'; import PropTypes from 'prop-types'; -// mui -import { useTheme } from '@mui/styles'; - import { LoadingIndicator, usePromiseTracker, trackPromise } from 'ui-component/LoadingIndicator/LoadingIndicator'; import MainCard from 'ui-component/cards/MainCard'; diff --git a/src/views/summary/summary.js b/src/views/summary/summary.js index ea60bb7d..af33c0eb 100644 --- a/src/views/summary/summary.js +++ b/src/views/summary/summary.js @@ -44,7 +44,7 @@ function Summary() { const sidebarWriter = useSidebarWriterContext(); useEffect(() => { sidebarWriter(null); - }, []); + }, [sidebarWriter]); /* Aggregated count of federated data */ function federationStatCount(data, endpoint) { diff --git a/src/views/utilities/Color.js b/src/views/utilities/Color.js index d92b9206..d41e88b3 100644 --- a/src/views/utilities/Color.js +++ b/src/views/utilities/Color.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // mui import { useTheme } from '@mui/styles'; diff --git a/src/views/utilities/MaterialIcons.js b/src/views/utilities/MaterialIcons.js index b4674af1..538369d8 100644 --- a/src/views/utilities/MaterialIcons.js +++ b/src/views/utilities/MaterialIcons.js @@ -1,5 +1,3 @@ -import React from 'react'; - // mui import { makeStyles } from '@mui/styles'; import { Card } from '@mui/material'; diff --git a/src/views/utilities/Shadow.js b/src/views/utilities/Shadow.js index 442e9d61..3603760c 100644 --- a/src/views/utilities/Shadow.js +++ b/src/views/utilities/Shadow.js @@ -1,5 +1,4 @@ import PropTypes from 'prop-types'; -import React from 'react'; // mui import { useTheme } from '@mui/styles'; diff --git a/src/views/utilities/TablerIcons.js b/src/views/utilities/TablerIcons.js index 61b3bff0..3b9a965a 100644 --- a/src/views/utilities/TablerIcons.js +++ b/src/views/utilities/TablerIcons.js @@ -1,5 +1,3 @@ -import React from 'react'; - // mui import { makeStyles } from '@mui/styles'; import { Card } from '@mui/material'; diff --git a/src/views/utilities/Typography.js b/src/views/utilities/Typography.js index 56fa8bf3..54cd234b 100644 --- a/src/views/utilities/Typography.js +++ b/src/views/utilities/Typography.js @@ -1,4 +1,3 @@ -import React from 'react'; // mui import { Grid, Link } from '@mui/material'; import MuiTypography from '@mui/material/Typography'; From 070076bd26b4d68c12afedd1149c4b00432b18a6 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 11:43:29 -0400 Subject: [PATCH 12/51] Prettier fixes --- .github/workflows/candig-dispatch.yml | 18 +++--- .github/workflows/lint.yml | 63 ++++++++++----------- .prettierrc | 3 +- PULL_REQUEST_TEMPLATE/stable_pr_template.md | 7 ++- 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/.github/workflows/candig-dispatch.yml b/.github/workflows/candig-dispatch.yml index 82467322..a5df4832 100644 --- a/.github/workflows/candig-dispatch.yml +++ b/.github/workflows/candig-dispatch.yml @@ -3,14 +3,14 @@ on: push: branches: [develop] jobs: - CanDIG-dispatch: - runs-on: ubuntu-latest - env: - PARENT_REPOSITORY: 'CanDIG/CanDIGv2' - CHECKOUT_BRANCH: 'develop' - PR_AGAINST_BRANCH: 'develop' - OWNER: 'CanDIG' - steps: + CanDIG-dispatch: + runs-on: ubuntu-latest + env: + PARENT_REPOSITORY: 'CanDIG/CanDIGv2' + CHECKOUT_BRANCH: 'develop' + PR_AGAINST_BRANCH: 'develop' + OWNER: 'CanDIG' + steps: - name: Check out repository code uses: actions/checkout@v3 - name: Create PR in CanDIGv2 @@ -21,7 +21,7 @@ jobs: parent_repository: ${{ env.PARENT_REPOSITORY }} checkout_branch: ${{ env.CHECKOUT_BRANCH}} pr_against_branch: ${{ env.PR_AGAINST_BRANCH }} - pr_description: "PR triggered by update to develop branch on ${{ github.repository }}. Commit hash: ${{ github.sha }}" + pr_description: 'PR triggered by update to develop branch on ${{ github.repository }}. Commit hash: ${{ github.sha }}' owner: ${{ env.OWNER }} submodule_path: lib/candig-data-portal/candig-data-portal label: Submodule update diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b466e241..c392bca7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,40 +1,39 @@ name: Lint on: - # Trigger the workflow on push or pull request, - # but only for the main branch - push: - branches: - - develop - pull_request: - branches: - - develop + # Trigger the workflow on push or pull request, + # but only for the main branch + push: + branches: + - develop + pull_request: + branches: + - develop # Down scope as necessary via https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token permissions: - checks: write - contents: write + checks: write + contents: write jobs: - run-linters: - name: Run linters - runs-on: ubuntu-latest - - steps: - - name: Check out Git repository - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v1 - with: - node-version: 12 - - - - name: Install Node.js dependencies - run: npm ci - - - name: Run linters - uses: wearerequired/lint-action@v2 - with: - eslint: true - prettier: true + run-linters: + name: Run linters + runs-on: ubuntu-latest + + steps: + - name: Check out Git repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Install Node.js dependencies + run: npm ci + + - name: Run linters + uses: wearerequired/lint-action@v2 + with: + eslint: true + prettier: true diff --git a/.prettierrc b/.prettierrc index 2eeeb745..c6905b15 100644 --- a/.prettierrc +++ b/.prettierrc @@ -5,6 +5,5 @@ "trailingComma": "none", "tabWidth": 4, "useTabs": false, - "endOfLine": "auto", - "camelcase": "off" + "endOfLine": "auto" } diff --git a/PULL_REQUEST_TEMPLATE/stable_pr_template.md b/PULL_REQUEST_TEMPLATE/stable_pr_template.md index 3e0b320e..1fdb79fe 100644 --- a/PULL_REQUEST_TEMPLATE/stable_pr_template.md +++ b/PULL_REQUEST_TEMPLATE/stable_pr_template.md @@ -1,6 +1,7 @@ ## vX.X.X: Description + Add a summary description of the main user-facing changes made in this release, relative to the last stable release. -- [ ] Tagged as a release in this repo -- [ ] Passes integration tests on a development instance -- [ ] Images pushed to Dockerhub +- [ ] Tagged as a release in this repo +- [ ] Passes integration tests on a development instance +- [ ] Images pushed to Dockerhub From 19c714930bbcddfff1ad87dd656f37f4bd4bf64e Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 11:45:31 -0400 Subject: [PATCH 13/51] Missed a prettier fix --- .github/pull_request_template.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f44ce857..45d1647f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,33 +1,33 @@ ## Ticket(s) - ## Description - ## Expected Behaviour - ## Related Issues (if appropriate) - ## Screenshots (if appropriate) + ### Before PR ### After PR ## To do/Tickets to be made before merging branch -- + +- ## Types of Change(s) -- [ ] 🪲 Bug fix (non-breaking change that fixes an issue) -- [ ] ✨ New feature (non-breaking change that adds functionality) -- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change) + +- [ ] 🪲 Bug fix (non-breaking change that fixes an issue) +- [ ] ✨ New feature (non-breaking change that adds functionality) +- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change) ## Has it been tested for: -- [ ] My change requires a change to the documentation -- [ ] I have updated the documentation accordingly -- [ ] Prettier linter doesn't return errors -- [ ] Production branch PR browser testing: Chrome, Firefox, Edge, etc. -- [ ] Locally tested -- [ ] Dev server tested -- [ ] Production tested when merging into stable/production branch \ No newline at end of file + +- [ ] My change requires a change to the documentation +- [ ] I have updated the documentation accordingly +- [ ] Prettier linter doesn't return errors +- [ ] Production branch PR browser testing: Chrome, Firefox, Edge, etc. +- [ ] Locally tested +- [ ] Dev server tested +- [ ] Production tested when merging into stable/production branch From b17045bc1779a72c3ab9dd367d3450b621dd2bf1 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 11:46:52 -0400 Subject: [PATCH 14/51] Prettier was overzealous with the overwriting --- .github/pull_request_template.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 45d1647f..3f5680fa 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,19 @@ ## Ticket(s) +- + ## Description +- + ## Expected Behaviour +- + ## Related Issues (if appropriate) +- + ## Screenshots (if appropriate) ### Before PR From 230364d211882ef49c88961b9dd9d8305692c389 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 13:09:19 -0400 Subject: [PATCH 15/51] Apply suggestions by @CourtneyGosselin --- .github/workflows/lint.yml | 2 +- .../dashboard/Default/datasetIdSelect.js | 114 ---- src/views/genomicsData/VariantsSearch.js | 577 ------------------ 3 files changed, 1 insertion(+), 692 deletions(-) delete mode 100644 src/views/dashboard/Default/datasetIdSelect.js delete mode 100644 src/views/genomicsData/VariantsSearch.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c392bca7..c2e26e23 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,7 +2,7 @@ name: Lint on: # Trigger the workflow on push or pull request, - # but only for the main branch + # but only for the develop branch push: branches: - develop diff --git a/src/views/dashboard/Default/datasetIdSelect.js b/src/views/dashboard/Default/datasetIdSelect.js deleted file mode 100644 index f8cbec01..00000000 --- a/src/views/dashboard/Default/datasetIdSelect.js +++ /dev/null @@ -1,114 +0,0 @@ -import { useState } from 'react'; -import Box from '@mui/material/Box'; -import MenuItem from '@mui/material/MenuItem'; -import FormControl from '@mui/material/FormControl'; -import Select from '@mui/material/Select'; -// import { fetchDatasets } from '../../../store/api'; -import AlertComponent from 'ui-component/AlertComponent'; - -// REDUX -import { useSelector, useDispatch } from 'react-redux'; - -export default function DatasetIdSelect() { - const events = useSelector((state) => state); - const dispatch = useDispatch(); - - // STATES - const [selectedDataset, setSelectedDataset] = useState(events.customization.selectedDataset); - const [datasets, _setDatasets] = useState(events.customization.datasets); - const [open, setOpen] = useState(false); - const [alertMessage, _setAlertMessage] = useState(''); - const [alertSeverity, _setAlertSeverity] = useState(''); - - function updateParentState(datasetName, datasetId) { - dispatch({ type: 'SET_UPDATE_STATE', payload: { datasetName, datasetId } }); - } - - /* - function setFirstDataset(datasetsList) { - const firstDataset = datasetsList[Object.keys(datasetsList)[0]]; - setSelectedDataset(firstDataset.name); - updateParentState(firstDataset.name, firstDataset.id); - dispatch({ type: 'SET_SELECTED_DATASET', payload: firstDataset.name }); - } - - function processDatasetJson(datasetJson) { - const datasetsList = {}; - datasetJson.forEach((dataset) => { - datasetsList[dataset.id] = dataset; - }); - return datasetsList; - } - - useEffect(() => { - if (!selectedDataset) { - fetchDatasets() - .then((data) => { - if (data.results) { - const datasetsList = processDatasetJson(data.results.datasets); - setDatasets(datasetsList); - setFirstDataset(datasetsList); - dispatch({ type: 'SET_DATASETS', payload: datasetsList }); - } - }) - .catch(() => { - setOpen(true); - setAlertMessage('No datasets are currently available. If this issue persists, contact your sysadmin for assistance'); - setAlertSeverity('error'); - }); - } - }); - */ - - const handleChange = (id, name) => { - setSelectedDataset(name); - updateParentState(name, id); // Suppose tp be id - dispatch({ type: 'SET_SELECTED_DATASET', payload: name }); - }; - - const datasetList = Object.keys(datasets).map((key) => ( - handleChange(datasets[key].id, datasets[key].name)}> - {datasets[key].name} - - )); - - return ( - - - {selectedDataset && ( - - {/* Dataset ID */} - - - )} - - - - ); -} diff --git a/src/views/genomicsData/VariantsSearch.js b/src/views/genomicsData/VariantsSearch.js deleted file mode 100644 index aa5cac0f..00000000 --- a/src/views/genomicsData/VariantsSearch.js +++ /dev/null @@ -1,577 +0,0 @@ -import * as React from 'react'; - -import { useState, useEffect } from 'react'; -import { Grid, Button, FormControl, InputLabel, Input, NativeSelect, Box } from '@mui/material'; -import { useSelector, useDispatch } from 'react-redux'; -import VariantsTable from 'ui-component/Tables/VariantsTable'; -import { SearchIndicator } from 'ui-component/LoadingIndicator/SearchIndicator'; -import AlertComponent from 'ui-component/AlertComponent'; -import { ListOfReferenceNames } from 'store/constant'; -import { trackPromise } from 'ui-component/LoadingIndicator/LoadingIndicator'; -import 'assets/css/VariantsSearch.css'; -import { searchVariant, fetchFederationClinicalData, htsget } from 'store/api'; -import IGViewer from './IGViewer'; -// import DropDown from '../../ui-component/DropDown'; -import { - processMCodeMainData, - processMedicationListData, - processCondtionsListData, - processSexListData, - processCancerTypeListData, - processHistologicalTypeListData -} from 'store/mcode'; - -// mui -import { useTheme } from '@mui/styles'; -import Stack from '@mui/material/Stack'; -import Divider from '@mui/material/Divider'; - -// NB: This VariantsSearch is currently unused, but is throwing linter errors -// Disabling it for now -/* eslint-disable no-unused-vars */ -/* eslint-disable react-hooks/exhaustive-deps */ -function VariantsSearch() { - const [isLoading, setLoading] = useState(true); - const theme = useTheme(); - const dispatch = useDispatch(); - const events = useSelector((state) => state); - - const [rowData, setRowData] = useState([]); - const [displayVariantsTable, setDisplayVariantsTable] = useState(false); - // const { promiseInProgress } = usePromiseTracker(); - const [open, setOpen] = useState(false); - const [alertMessage, setAlertMessage] = useState(''); - const [alertSeverity, setAlertSeverity] = useState('warning'); - const [isIGVWindowOpen, setIsIGVWindowOpen] = useState(false); - const [_showIGVButton, setShowIGVButton] = useState(false); - const [IGVOptions, setIGVOptions] = useState({}); - const [variantSearchOptions, setVariantSearchOptions] = useState({}); - const [patientList, setPatientList] = useState([]); - const [IGVBaseUrl, setIGVBaseUrl] = useState(`${htsget}/htsget/v1/variants/`); - - // Clinical Search Filter - const clinicalSearchPatients = useSelector((state) => state.customization.clinicalSearchResultPatients); - const clinicalSearch = useSelector((state) => state.customization.clinicalSearch); - const [cancerType, _setCancerType] = React.useState([]); - - // Dropdown patient table open/closed - const [isListOpenMedications, setListOpenMedications] = React.useState(false); - const [isListOpenConditions, setListOpenConditions] = React.useState(false); - const [isListOpenSex, setListOpenSex] = React.useState(false); - const [isListOpenCancerType, setListOpenCancerType] = React.useState(false); - const [isListOpenHistological, setListOpenHistological] = React.useState(false); - - // Dropdown patient table filtering current selection in dropdown - const [selectedMedications, setSelectedMedications] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedMedications); - const [selectedConditions, setSelectedConditions] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedConditions); - const [selectedSex, setSelectedSex] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedSex); - const [selectedCancerType, setSelectedCancerType] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedCancerType); - const [selectedHistologicalType, setSelectedHistologicalType] = React.useState( - clinicalSearch.clinicalSearchDropDowns.selectedHistologicalType - ); - - // Dropdown patient table list for filtering - const [medicationList, setMedicationList] = React.useState(clinicalSearch.clinicalSearchDropDowns.medicationList); - const [conditionList, setConditionList] = React.useState(clinicalSearch.clinicalSearchDropDowns.conditionList); - const [sexList, setSexList] = React.useState(clinicalSearch.clinicalSearchDropDowns.sexList); - const [cancerTypeList, setCancerTypeList] = React.useState(clinicalSearch.clinicalSearchDropDowns.cancerTypeList); - const [HistologicalList, setHistologicalList] = React.useState(clinicalSearch.clinicalSearchDropDowns.HistologicalList); - - /* - Build the dropdown for chromosome - * @param {None} - * Return a list of options with chromosome - */ - function chrSelectBuilder() { - const refNameList = []; - ListOfReferenceNames.forEach((refName) => { - refNameList.push( - - ); - }); - return refNameList; - } - - function setClincalSearchPatients(data) { - dispatch({ - type: 'SET_CLINICAL_SEARCH_PATIENTS', - payload: { - data - } - }); - } - - function setRedux(rows) { - const tempClinicalSearchResults = []; - rows.forEach((patient) => { - tempClinicalSearchResults.push({ id: patient.id, genomicId: patient.genomic_id }); - }); - dispatch({ - type: 'SET_SELECTED_CLINICAL_SEARCH_RESULTS', - payload: { - selectedClinicalSearchResults: tempClinicalSearchResults, - clinicalSearchDropDowns: { - medicationList, - selectedMedications, - conditionList, - selectedConditions, - sexList, - selectedSex, - cancerTypeList, - selectedCancerType, - HistologicalList, - selectedHistologicalType - } - } - }); - } - - const dropDownSelection = (dropDownGroup, selected) => { - if (dropDownGroup === 'CONDITIONS') { - setSelectedConditions(selected); - setListOpenConditions(false); - } else if (dropDownGroup === 'MEDICATIONS') { - setSelectedMedications(selected); - setListOpenMedications(false); - } else if (dropDownGroup === 'SEX') { - setSelectedSex(selected); - setListOpenSex(false); - } else if (dropDownGroup === 'CANCER TYPE') { - setSelectedCancerType(selected); - setListOpenCancerType(false); - } else if (dropDownGroup === 'HISTOLOGICAL') { - setSelectedHistologicalType(selected); - setListOpenHistological(false); - } - }; - - // Filtering on cache - useEffect(() => { - if (Object.keys(clinicalSearchPatients.data).length !== 0) { - const tempRows = []; - const response = clinicalSearchPatients.data; - - for (let j = 0; j < response.results.length; j += 1) { - for (let i = 0; i < response.results[j].count; i += 1) { - // Patient table filtering - if ( - selectedConditions === 'All' && - selectedMedications === 'All' && - selectedSex === 'All' && - selectedCancerType === 'All' && - selectedHistologicalType === 'All' - ) { - // All patients - if (processMCodeMainData(response.results[j].results[i], response.results[j].location[0]).id !== null) { - tempRows.push(processMCodeMainData(response.results[j].results[i], response.results[j].location[0])); - } - } else { - // Filtered patients - let patientCondition = false; - response?.results[j]?.results[i]?.cancer_condition?.body_site?.every((bodySite) => { - if (selectedConditions === 'All' || selectedConditions === bodySite.label) { - patientCondition = true; - return false; - } - return true; - }); - let patientMedication = false; - response?.results[j]?.results[i]?.medication_statement.every((medication) => { - if (selectedMedications === 'All' || selectedMedications === medication?.medication_code.label) { - patientMedication = true; - return false; - } - return true; - }); - let patientSex = false; - if (selectedSex === 'All' || selectedSex === response?.results[j]?.results[i]?.subject.sex) { - patientSex = true; - } - let patientCancerType = false; - if (selectedCancerType === 'All') { - patientCancerType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - response?.results[j]?.results[i]?.cancer_condition?.code?.id !== undefined && - response?.results[j]?.results[i]?.cancer_condition?.code?.id === cancerType[k]['Cancer type code'] - ) { - if ( - selectedCancerType === - `${cancerType[k]['Cancer type label']} ${cancerType[k]['Cancer type code']}` || - selectedCancerType === 'NA' - ) { - patientCancerType = true; - } - } - } - } - let patientHistologicalType = false; - if (selectedHistologicalType === 'All') { - patientHistologicalType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - response?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id !== undefined && - response?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id === - cancerType[k]['Tumour histological type code'] - ) { - if ( - selectedHistologicalType === - `${cancerType[k]['Tumour histological type label']} ${cancerType[k]['Tumour histological type code']}` || - selectedHistologicalType === 'NA' - ) { - patientHistologicalType = true; - } - } - } - } - if ( - patientCondition && - patientMedication && - patientSex && - patientCancerType && - patientHistologicalType && - processMCodeMainData(response.results[j].results[i]).id !== null - ) { - tempRows.push(processMCodeMainData(response.results[j].results[i], response.results[j].location[0])); - } - } - } - } - const tempClinicalSearchResults = []; - tempRows.forEach((patient) => { - tempClinicalSearchResults.push({ id: patient.id, genomicId: patient.genomic_id }); - }); - - setPatientList(tempClinicalSearchResults); - // Dropdown patient table list for filtering - setMedicationList(processMedicationListData(response.results)); - setConditionList(processCondtionsListData(response.results)); - setSexList(processSexListData(response.results)); - setCancerTypeList(processCancerTypeListData(response.results)); - setHistologicalList(processHistologicalTypeListData(response.results)); - setLoading(false); - - setRedux(tempRows); - } - }, [selectedSex, selectedConditions, selectedMedications, selectedCancerType, selectedHistologicalType]); - - useEffect(() => { - setLoading(true); - setDisplayVariantsTable(false); - // get patient data from redux store or fetch it - if (Object.keys(clinicalSearch.selectedClinicalSearchResults).length !== 0) { - setPatientList(clinicalSearch.selectedClinicalSearchResults); - } - trackPromise( - fetchFederationClinicalData('/api/mcodepackets').then((response) => { - const patientData = []; - setClincalSearchPatients(response); - response.results.forEach((result) => { - result.results.forEach((patient) => { - patientData.push({ - id: patient.id, - genomicId: patient.genomics_report?.extra_properties?.genomic_id ?? 'NA' - }); - }); - }); - - const tempRows = []; - for (let j = 0; j < response.results.length; j += 1) { - for (let i = 0; i < response.results[j].count; i += 1) { - // Patient table filtering - if ( - selectedConditions === 'All' && - selectedMedications === 'All' && - selectedSex === 'All' && - selectedCancerType === 'All' && - selectedHistologicalType === 'All' - ) { - // All patients - if (processMCodeMainData(response.results[j].results[i], response.results[j].location[0]).id !== null) { - tempRows.push(processMCodeMainData(response.results[j].results[i], response.results[j].location[0])); - } - } else { - // Filtered patients - let patientCondition = false; - response?.results[j]?.results[i]?.cancer_condition?.body_site?.every((bodySite) => { - if (selectedConditions === 'All' || selectedConditions === bodySite.label) { - patientCondition = true; - return false; - } - return true; - }); - let patientMedication = false; - response?.results[j]?.results[i]?.medication_statement.every((medication) => { - if (selectedMedications === 'All' || selectedMedications === medication?.medication_code.label) { - patientMedication = true; - return false; - } - return true; - }); - let patientSex = false; - if (selectedSex === 'All' || selectedSex === response?.results[j]?.results[i]?.subject.sex) { - patientSex = true; - } - let patientCancerType = false; - if (selectedCancerType === 'All') { - patientCancerType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - response?.results[j]?.results[i]?.cancer_condition?.code?.id !== undefined && - response?.results[j]?.results[i]?.cancer_condition?.code?.id === cancerType[k]['Cancer type code'] - ) { - if ( - selectedCancerType === - `${cancerType[k]['Cancer type label']} ${cancerType[k]['Cancer type code']}` || - selectedCancerType === 'NA' - ) { - patientCancerType = true; - } - } - } - } - let patientHistologicalType = false; - if (selectedHistologicalType === 'All') { - patientHistologicalType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - response?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id !== - undefined && - response?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id === - cancerType[k]['Tumour histological type code'] - ) { - if ( - selectedHistologicalType === - `${cancerType[k]['Tumour histological type label']} ${cancerType[k]['Tumour histological type code']}` || - selectedHistologicalType === 'NA' - ) { - patientHistologicalType = true; - } - } - } - } - if ( - patientCondition && - patientMedication && - patientSex && - patientCancerType && - patientHistologicalType && - processMCodeMainData(response.results[j].results[i]).id !== null - ) { - tempRows.push(processMCodeMainData(response.results[j].results[i], response.results[j].location[0])); - } - } - } - } - const tempClinicalSearchResults = []; - tempRows.forEach((patient) => { - tempClinicalSearchResults.push({ id: patient.id, genomicId: patient.genomic_id }); - }); - - setPatientList(tempClinicalSearchResults ?? patientData); - // Dropdown patient table list for filtering - setMedicationList(processMedicationListData(response.results)); - setConditionList(processCondtionsListData(response.results)); - setSexList(processSexListData(response.results)); - setCancerTypeList(processCancerTypeListData(response.results)); - setHistologicalList(processHistologicalTypeListData(response.results)); - setLoading(false); - - setRedux(tempRows); - }), - 'patientBox' - ); - }, []); - - /** - * This function handles the Search button - * It calls the searchVariant function from api.js according to the chromosome and position - * then compares the result with the patientList genomicID to find the matching patient - */ - const formHandler = (e) => { - e.preventDefault(); // Prevent form submission - setDisplayVariantsTable(false); - const referenceName = e.target.genome.value; - const chromosome = e.target.chromosome.value; - const start = e.target.start.value; - const end = e.target.end.value; - setVariantSearchOptions({ referenceName, chromosome, start, end }); - trackPromise( - searchVariant(chromosome, start, end) - .then((response) => { - const locationObjs = response.results; - if (Object.keys(locationObjs).length === 0) { - setAlertMessage('No variants found'); - setAlertSeverity('warning'); - setOpen(true); - } else { - const variantList = []; - locationObjs.forEach((location) => { - location.results.forEach((item) => - variantList.push({ - id: item.id, - genomicId: item.genomic_id, - locationName: location.location[0], - referenceName: item.reference_genome, - variantCount: item.variantcount, - samples: item.samples, - url: item.urls[0] // only one url unless the requirement changes - }) - ); - }); - // Build display table - const displayData = []; - for (let i = 0; i < variantList.length; i += 1) { - for (let j = 0; j < patientList.length; j += 1) { - if (variantList[i].genomicId === patientList[j].genomicId) { - displayData.push({ - patientId: patientList[j].id, - locationName: variantList[i].locationName, - genomicSampleId: variantList[i].genomicId, - variantCount: variantList[i].variantCount, - samples: variantList[i].samples, - VCFFile: variantList[i].id - }); - // get the url part before the file name for IGV - const url = variantList[i].url; - const urlParts = url.substring(0, url.lastIndexOf('/') + 1); - setIGVBaseUrl(urlParts); - break; // should have only 1 match, so we can break here - } - } - } - setRowData(displayData); - setDisplayVariantsTable(true); - } - }) - .catch((error) => { - setAlertMessage(error.message); - setAlertSeverity('error'); - setOpen(true); - }), - 'table' - ); - }; - - const toggleIGVWindow = () => { - setIsIGVWindowOpen(!isIGVWindowOpen); - }; - - /** - * This function keeps track of the selected row in the table - * then it creates the IGV options to send to the IGV window - */ - const onCheckboxSelectionChanged = (value) => { - if (value.length === 0) { - setShowIGVButton(false); - } else { - setShowIGVButton(true); - } - const trackList = []; - for (let i = 0; i < value.length; i += 1) { - trackList.push({ - name: value[i]['Patient ID'], - type: 'variant', - format: 'vcf', - sourceType: 'htsget', - url: `${IGVBaseUrl}${value[i]['VCF File']}` - }); - } - const options = { - genome: 'hg38', - locus: `${variantSearchOptions.chromosome}:${variantSearchOptions.start}-${variantSearchOptions.end}`, - tracks: trackList - }; - setIGVOptions(options); - }; - - return ( - <> - - {!isLoading ? ( - - } spacing={2}> - - - Total Patients - -
- {patientList.length} -
-
- } spacing={2}> - - - Reference Genome - - - - - - - - - Chromosome - - {chrSelectBuilder()} - - - - - - Start - - - - - - End - - - - - - - - - -
-
-
- ) : ( - - )} - - {displayVariantsTable ? ( - - ) : ( - - )} - - {isIGVWindowOpen && } - - ); -} -/* eslint-enable no-unused-vars */ -/* eslint-enable react-hooks/exhaustive-deps */ - -export default VariantsSearch; From 7ec3814fe54ec483c4e4b56c8d89171ef449c5d0 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 13:09:47 -0400 Subject: [PATCH 16/51] Remove extra code --- src/views/clinical/mcode.js | 642 ------------------------------------ 1 file changed, 642 deletions(-) delete mode 100644 src/views/clinical/mcode.js diff --git a/src/views/clinical/mcode.js b/src/views/clinical/mcode.js deleted file mode 100644 index b4b74d64..00000000 --- a/src/views/clinical/mcode.js +++ /dev/null @@ -1,642 +0,0 @@ -import * as React from 'react'; - -// npm installs -import ReactJson from 'react-json-view'; -import cancerTypeCSV from '../../assets/data_files/cancer_histological_codes_labels.csv'; -import papa from 'papaparse'; - -// mui -import { useTheme, makeStyles } from '@mui/styles'; -import { DataGrid, GridToolbar } from '@mui/x-data-grid'; -import { Grid, Box } from '@mui/material'; - -// REDUX -import { useSelector, useDispatch } from 'react-redux'; - -// project imports -import MainCard from 'ui-component/cards/MainCard'; -import { fetchFederationClinicalData } from 'store/api'; -import { - subjectColumns, - processMCodeMainData, - processMedicationListData, - processCondtionsListData, - processSexListData, - processCancerTypeListData, - processHistologicalTypeListData -} from 'store/mcode'; -import SingleRowTable from 'ui-component/SingleRowTable'; -import { trackPromise } from 'react-promise-tracker'; -import Stack from '@mui/material/Stack'; -import Divider from '@mui/material/Divider'; -import TableContainer from '@mui/material/TableContainer'; -import Table from '@mui/material/Table'; -import DropDown from '../../ui-component/DropDown'; -import { SearchIndicator } from 'ui-component/LoadingIndicator/SearchIndicator'; - -// Styles -const useStyles = makeStyles({ - dropdownItem: { - background: 'white', - paddingRight: '1.25em', - paddingLeft: '1.25em', - border: 'none', - width: 'fit-content(5em)', - '&:hover': { - background: '#2196f3', - color: 'white' - } - }, - mobileRow: { - width: '800px' - }, - scrollbar: { - scrollbarWidth: 'thin', - '&::-webkit-scrollbar': { - height: '0.4em', - width: '0.4em' - }, - '&::-webkit-scrollbar-track': { - boxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)', - webkitBoxShadow: 'inset 0 0 4px rgba(0,0,0,0.00)' - }, - '&::-webkit-scrollbar-thumb': { - backgroundColor: 'rgba(0,0,0,.1)' - } - } -}); - -// NB: This function isn't really used anywhere and it's messing with the linter -/* eslint-disable react-hooks/exhaustive-deps */ -function MCodeView() { - const theme = useTheme(); - const classes = useStyles(); - const events = useSelector((state) => state); - const dispatch = useDispatch(); - const clinicalSearch = useSelector((state) => state.customization.clinicalSearch); - const clinicalSearchPatients = useSelector((state) => state.customization.clinicalSearchResultPatients); - - const [isLoading, setIsLoading] = React.useState(true); - const [mcodeData, setMcodeData] = React.useState([]); - const [rows, setRows] = React.useState([]); - const [selectedPatient, setSelectedPatient] = React.useState(''); - const [selectedPatientMobileInfo, setSelectedPatientMobileInfo] = React.useState({}); - const [cancerType, setCancerType] = React.useState([]); - - // Mobile - const [desktopResolution, setdesktopResolution] = React.useState(window.innerWidth > 1200); - const [isListOpen, setListOpen] = React.useState(false); - - // Dropdown patient table open/closed - const [isListOpenMedications, setListOpenMedications] = React.useState(false); - const [isListOpenConditions, setListOpenConditions] = React.useState(false); - const [isListOpenSex, setListOpenSex] = React.useState(false); - const [isListOpenCancerType, setListOpenCancerType] = React.useState(false); - const [isListOpenHistological, setListOpenHistological] = React.useState(false); - - // Dropdown patient table filtering current selection in dropdown - const [selectedMedications, setSelectedMedications] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedMedications); - const [selectedConditions, setSelectedConditions] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedConditions); - const [selectedSex, setSelectedSex] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedSex); - const [selectedCancerType, setSelectedCancerType] = React.useState(clinicalSearch.clinicalSearchDropDowns.selectedCancerType); - const [selectedHistologicalType, setSelectedHistologicalType] = React.useState( - clinicalSearch.clinicalSearchDropDowns.selectedHistologicalType - ); - const [patientJSON, setPatientJSON] = React.useState([]); - - // Dropdown patient table list for filtering - const [medicationList, setMedicationList] = React.useState(clinicalSearch.clinicalSearchDropDowns.medicationList); - const [conditionList, setConditionList] = React.useState(clinicalSearch.clinicalSearchDropDowns.conditionList); - const [sexList, setSexList] = React.useState(clinicalSearch.clinicalSearchDropDowns.sexList); - const [cancerTypeList, setCancerTypeList] = React.useState(clinicalSearch.clinicalSearchDropDowns.cancerTypeList); - const [HistologicalList, setHistologicalList] = React.useState(clinicalSearch.clinicalSearchDropDowns.HistologicalList); - - const jsonTheme = { - base00: 'white', - base01: '#ddd', - base02: '#ddd', - base03: 'black', - base04: '#0E3E17', - base05: 'black', - base06: 'black', - base07: '#252525', - base08: '#252525', - base09: '#00418A', - base0A: '#00418A', - base0B: '#00418A', - base0C: '#00418A', - base0D: '#00418A', - base0E: '#00418A', - base0F: '#00418A' - }; - - function setClincalSearchPatients(data) { - dispatch({ - type: 'SET_CLINICAL_SEARCH_PATIENTS', - payload: { - data - } - }); - } - - function setRedux(rows) { - const tempClinicalSearchResults = []; - rows.forEach((patient) => { - tempClinicalSearchResults.push({ id: patient.id, genomicId: patient.genomic_id }); - }); - dispatch({ - type: 'SET_SELECTED_CLINICAL_SEARCH_RESULTS', - payload: { - selectedClinicalSearchResults: tempClinicalSearchResults, - clinicalSearchDropDowns: { - medicationList, - selectedMedications, - conditionList, - selectedConditions, - sexList, - selectedSex, - cancerTypeList, - selectedCancerType, - HistologicalList, - selectedHistologicalType - } - } - }); - } - // Parsing CancerType CSV into Dictionary - React.useEffect( - () => - papa.parse(cancerTypeCSV, { - header: true, - download: true, - skipEmptyLines: true, - // eslint-disable-next-line - complete: function (results) { - setCancerType(results.data); - } - }), - [] - ); - // Subtable selection of patient - const handleRowClick = (row) => { - let index; - mcodeData.results.forEach((federatedResults) => { - index = federatedResults.results.findIndex((item) => item.id === row.id); - if (index !== -1) { - setSelectedPatient(federatedResults.results[index].id); - setSelectedPatientMobileInfo({ - Ethnicity: federatedResults?.results[index]?.subject?.ethnicity - ? federatedResults?.results[index]?.subject?.ethnicity - : 'NA', - Sex: (federatedResults?.results[index]?.subject?.sex).toLowerCase() - ? (federatedResults?.results[index]?.subject?.sex).toLowerCase() - : 'NA', - Deceased: federatedResults?.results[index]?.subject?.deceased - ? federatedResults?.results[index]?.subject?.deceased - : 'NA', - Birthday: federatedResults?.results[index]?.subject?.date_of_birth - ? federatedResults?.results[index]?.subject?.date_of_birth - : 'NA', - DeathDate: federatedResults?.results[index]?.date_of_death ? federatedResults?.results[index]?.date_of_death : 'NA' - }); - - // Set patient JSON - setPatientJSON(federatedResults?.results[index], selectedPatient); - } - }); - - setListOpen(false); - }; - - const dropDownSelection = (dropDownGroup, selected) => { - if (dropDownGroup === 'CONDITIONS') { - setSelectedConditions(selected); - setListOpenConditions(false); - } else if (dropDownGroup === 'MEDICATIONS') { - setSelectedMedications(selected); - setListOpenMedications(false); - } else if (dropDownGroup === 'SEX') { - setSelectedSex(selected); - setListOpenSex(false); - } else if (dropDownGroup === 'CANCER TYPE') { - setSelectedCancerType(selected); - setListOpenCancerType(false); - } else if (dropDownGroup === 'HISTOLOGICAL') { - setSelectedHistologicalType(selected); - setListOpenHistological(false); - } - }; - - // Filtering Data - React.useEffect(() => { - if (Object.keys(clinicalSearchPatients.data).length !== 0) { - const tempRows = []; - const data = clinicalSearchPatients.data; - for (let j = 0; j < data.results.length; j += 1) { - for (let i = 0; i < data.results[j].count; i += 1) { - // Patient table filtering - if ( - selectedConditions === 'All' && - selectedMedications === 'All' && - selectedSex === 'All' && - selectedCancerType === 'All' && - selectedHistologicalType === 'All' - ) { - // All patients - if (processMCodeMainData(data.results[j].results[i], data.results[j].location[0]).id !== null) { - tempRows.push(processMCodeMainData(data.results[j].results[i], data.results[j].location[0])); - } - } else { - // Filtered patients - let patientCondition = false; - data?.results[j]?.results[i]?.cancer_condition?.body_site?.every((bodySite) => { - if (selectedConditions === 'All' || selectedConditions === bodySite.label) { - patientCondition = true; - return false; - } - return true; - }); - let patientMedication = false; - data?.results[j]?.results[i]?.medication_statement.every((medication) => { - if (selectedMedications === 'All' || selectedMedications === medication?.medication_code.label) { - patientMedication = true; - return false; - } - return true; - }); - let patientSex = false; - if (selectedSex === 'All' || selectedSex === (data?.results[j]?.results[i]?.subject.sex).toLowerCase()) { - patientSex = true; - } - let patientCancerType = false; - if (selectedCancerType === 'All') { - patientCancerType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - data?.results[j]?.results[i]?.cancer_condition?.code?.id !== undefined && - data?.results[j]?.results[i]?.cancer_condition?.code?.id === cancerType[k]['Cancer type code'] - ) { - if ( - selectedCancerType === - `${cancerType[k]['Cancer type label']} ${cancerType[k]['Cancer type code']}` || - selectedCancerType === 'NA' - ) { - patientCancerType = true; - } - } - } - } - let patientHistologicalType = false; - if (selectedHistologicalType === 'All') { - patientHistologicalType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - data?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id !== undefined && - data?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id === - cancerType[k]['Tumour histological type code'] - ) { - if ( - selectedHistologicalType === - `${cancerType[k]['Tumour histological type label']} ${cancerType[k]['Tumour histological type code']}` || - selectedHistologicalType === 'NA' - ) { - patientHistologicalType = true; - } - } - } - } - if ( - patientCondition && - patientMedication && - patientSex && - patientCancerType && - patientHistologicalType && - processMCodeMainData(data.results[j].results[i]).id !== null - ) { - tempRows.push(processMCodeMainData(data.results[j].results[i], data.results[j].location[0])); - } - } - } - } - setRows(tempRows); - // Subtables - if (tempRows.length !== 0) { - let index; - data.results.forEach((federatedResults) => { - index = federatedResults.results.findIndex((item) => item.id === tempRows[0].id); - if (index !== -1) { - setSelectedPatient(federatedResults.results[index].id); - setPatientJSON(federatedResults.results[index], selectedPatient); - if (tempRows[0].id !== null) { - setSelectedPatientMobileInfo({ - Ethnicity: tempRows[0]?.ethnicity ? tempRows[0]?.ethnicity : 'NA', - Sex: tempRows[0]?.sex ? tempRows[0]?.sex : 'NA', - Deceased: tempRows[0]?.deceased ? tempRows[0]?.deceased : 'NA', - Birthday: tempRows[0]?.date_of_birth ? tempRows[0]?.date_of_birth : 'NA', - DeathDate: tempRows[0]?.date_of_death ? tempRows[0]?.date_of_death : 'NA' - }); - } - } - }); - } else { - setSelectedPatient('None'); - setPatientJSON({}); - } - - setListOpen(false); - // Dropdown patient table list for filtering - setMedicationList(processMedicationListData(data.results)); - setConditionList(processCondtionsListData(data.results)); - setSexList(processSexListData(data.results)); - setCancerTypeList(processCancerTypeListData(data.results)); - setHistologicalList(processHistologicalTypeListData(data.results)); - setIsLoading(false); - - setRedux(tempRows); - } - }, [selectedSex, selectedConditions, selectedMedications, selectedCancerType, selectedHistologicalType]); - - // Tracks Screensize - React.useEffect(() => { - window.addEventListener('resize', () => setdesktopResolution(window.innerWidth > 1200)); - }, [desktopResolution, setdesktopResolution]); - - React.useEffect(() => { - setIsLoading(true); - const tempRows = []; - trackPromise( - fetchFederationClinicalData().then((data) => { - setMcodeData(data); - setClincalSearchPatients(data); - for (let j = 0; j < data.results.length; j += 1) { - for (let i = 0; i < data.results[j].count; i += 1) { - // Patient table filtering - if ( - selectedConditions === 'All' && - selectedMedications === 'All' && - selectedSex === 'All' && - selectedCancerType === 'All' && - selectedHistologicalType === 'All' - ) { - // All patients - if (processMCodeMainData(data.results[j].results[i], data.results[j].location[0]).id !== null) { - tempRows.push(processMCodeMainData(data.results[j].results[i], data.results[j].location[0])); - } - } else { - // Filtered patients - let patientCondition = false; - data?.results[j]?.results[i]?.cancer_condition?.body_site?.every((bodySite) => { - if (selectedConditions === 'All' || selectedConditions === bodySite.label) { - patientCondition = true; - return false; - } - return true; - }); - let patientMedication = false; - data?.results[j]?.results[i]?.medication_statement.every((medication) => { - if (selectedMedications === 'All' || selectedMedications === medication?.medication_code.label) { - patientMedication = true; - return false; - } - return true; - }); - let patientSex = false; - if (selectedSex === 'All' || selectedSex === (data?.results[j]?.results[i]?.subject.sex).toLowerCase()) { - patientSex = true; - } - let patientCancerType = false; - if (selectedCancerType === 'All') { - patientCancerType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - data?.results[j]?.results[i]?.cancer_condition?.code?.id !== undefined && - data?.results[j]?.results[i]?.cancer_condition?.code?.id === cancerType[k]['Cancer type code'] - ) { - if ( - selectedCancerType === - `${cancerType[k]['Cancer type label']} ${cancerType[k]['Cancer type code']}` || - selectedCancerType === 'NA' - ) { - patientCancerType = true; - } - } - } - } - let patientHistologicalType = false; - if (selectedHistologicalType === 'All') { - patientHistologicalType = true; - } else { - for (let k = 0; k < cancerType.length; k += 1) { - if ( - data?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id !== undefined && - data?.results[j]?.results[i]?.cancer_condition?.histology_morphology_behavior?.id === - cancerType[k]['Tumour histological type code'] - ) { - if ( - selectedHistologicalType === - `${cancerType[k]['Tumour histological type label']} ${cancerType[k]['Tumour histological type code']}` || - selectedHistologicalType === 'NA' - ) { - patientHistologicalType = true; - } - } - } - } - if ( - patientCondition && - patientMedication && - patientSex && - patientCancerType && - patientHistologicalType && - processMCodeMainData(data.results[j].results[i]).id !== null - ) { - tempRows.push(processMCodeMainData(data.results[j].results[i], data.results[j].location[0])); - } - } - } - } - setRows(tempRows); - // Subtables - if (tempRows.length !== 0) { - let index; - data.results.forEach((federatedResults) => { - index = federatedResults.results.findIndex((item) => item.id === tempRows[0].id); - if (index !== -1) { - setSelectedPatient(federatedResults.results[index].id); - setPatientJSON(federatedResults.results[index], selectedPatient); - if (tempRows[0].id !== null) { - setSelectedPatientMobileInfo({ - Ethnicity: tempRows[0]?.ethnicity ? tempRows[0]?.ethnicity : 'NA', - Sex: tempRows[0]?.sex ? tempRows[0]?.sex : 'NA', - Deceased: tempRows[0]?.deceased ? tempRows[0]?.deceased : 'NA', - Birthday: tempRows[0]?.date_of_birth ? tempRows[0]?.date_of_birth : 'NA', - DeathDate: tempRows[0]?.date_of_death ? tempRows[0]?.date_of_death : 'NA' - }); - } - } - }); - } else { - setSelectedPatient('None'); - setPatientJSON({}); - } - - setListOpen(false); - // Dropdown patient table list for filtering - setMedicationList(processMedicationListData(data.results)); - setConditionList(processCondtionsListData(data.results)); - setSexList(processSexListData(data.results)); - setCancerTypeList(processCancerTypeListData(data.results)); - setHistologicalList(processHistologicalTypeListData(data.results)); - setIsLoading(false); - - setRedux(tempRows); - }), - 'table' - ); - }, []); - - // JSON on bottom now const screenWidth = desktopResolution ? '48%' : '100%'; - const headerLabels = { - Ethnicity: 'Ethnicity', - Sex: 'Sex', - Deceased: 'Deceased', - Birthday: 'Date of Birth', - DeathDate: 'Date of Death' - }; - const headerWidths = { - Ethnicity: '85px', - Sex: '85px', - Deceased: '85px', - Birthday: '100px', - DeathDate: '110px' - }; - - return ( - - - {selectedPatient && desktopResolution && ( - - - }> - - - - - - -
-
- )} - {!desktopResolution && selectedPatient && ( - - )} - - {!isLoading ? ( - - {desktopResolution && ( - - handleRowClick(rowData.row)} - className={classes.scrollbar} - disableSelectionOnClick - /> - - )} - - - - Patient Id - -
- {selectedPatient} -
- - - -
-
- ) : ( - - )} -
-
- ); -} -/* eslint-enable react-hooks/exhaustive-deps */ - -export default MCodeView; From 78c118a8568e752ad3228ecfe4c7b123f8c4be35 Mon Sep 17 00:00:00 2001 From: fnguyen Date: Tue, 19 Sep 2023 14:04:30 -0400 Subject: [PATCH 17/51] Remove unneeded dependency --- src/views/clinicalGenomic/clinicalGenomicSearch.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/views/clinicalGenomic/clinicalGenomicSearch.js b/src/views/clinicalGenomic/clinicalGenomicSearch.js index 37b67827..49334472 100644 --- a/src/views/clinicalGenomic/clinicalGenomicSearch.js +++ b/src/views/clinicalGenomic/clinicalGenomicSearch.js @@ -5,7 +5,6 @@ import { AppBar, Button, Toolbar, Typography } from '@mui/material'; import { makeStyles } from '@mui/styles'; import MainCard from 'ui-component/cards/MainCard'; -import VariantsSearch from '../genomicsData/VariantsSearch'; import PatientCounts from './widgets/patientCounts'; import DataVisualization from './widgets/dataVisualization'; import ClinicalData from './widgets/clinicalData'; @@ -120,11 +119,6 @@ function ClinicalGenomicSearch() { - {sections.map((section) => (