From 7378d1405e72ca88a4fcf4c38a0a4d544bd6eaa4 Mon Sep 17 00:00:00 2001 From: Yukthi Date: Wed, 30 Oct 2024 20:20:48 -0400 Subject: [PATCH] Added plant, cell, and tissue efps with routing --- Eplant/Eplant.tsx | 64 +- Eplant/UI/Layout/ViewContainer/index.tsx | 110 +++- Eplant/config.tsx | 4 +- Eplant/main.tsx | 18 +- Eplant/util/stateUtils/ActionsPanel.tsx | 50 ++ Eplant/util/stateUtils/index.ts | 14 +- Eplant/views/CellEFP/CellEFP.tsx | 18 +- Eplant/views/CellEFP/actions.tsx | 10 +- Eplant/views/ExperimentEFP/ExperimentEFP.tsx | 88 +++ Eplant/views/ExperimentEFP/efps.tsx | 254 ++++++++ Eplant/views/PlantEFP/PlantEFP.tsx | 88 +++ Eplant/views/PlantEFP/efps.tsx | 22 + Eplant/views/PlantEFP/index.tsx | 3 +- Eplant/views/eFP/Viewer/EFPList.tsx | 85 +++ Eplant/views/eFP/Viewer/EFPViewer.tsx | 351 +++++++++++ Eplant/views/eFP/Viewer/MaskModal.tsx | 5 +- Eplant/views/eFP/Viewer/actions.tsx | 60 ++ Eplant/views/eFP/Viewer/index.tsx | 586 ++++++++----------- Eplant/views/eFP/Viewer/types.tsx | 16 +- Eplant/views/eFP/index.tsx | 8 +- index.html | 6 +- vite.config.ts | 6 +- 22 files changed, 1394 insertions(+), 472 deletions(-) create mode 100644 Eplant/util/stateUtils/ActionsPanel.tsx create mode 100644 Eplant/views/ExperimentEFP/ExperimentEFP.tsx create mode 100644 Eplant/views/ExperimentEFP/efps.tsx create mode 100644 Eplant/views/PlantEFP/PlantEFP.tsx create mode 100644 Eplant/views/PlantEFP/efps.tsx create mode 100644 Eplant/views/eFP/Viewer/EFPList.tsx create mode 100644 Eplant/views/eFP/Viewer/EFPViewer.tsx create mode 100644 Eplant/views/eFP/Viewer/actions.tsx diff --git a/Eplant/Eplant.tsx b/Eplant/Eplant.tsx index 62f62b77..6cbfb4a9 100644 --- a/Eplant/Eplant.tsx +++ b/Eplant/Eplant.tsx @@ -30,70 +30,18 @@ export type EplantProps = Record */ const Eplant = () => { const [darkMode] = useDarkMode() - const [activeGeneId, setActiveGeneId] = useActiveGeneId() - const [activeViewId, setActiveViewId] = useState('') const [isCollapse, setIsCollapse] = useSidebarState() + const [activeGeneId, setActiveGeneId] = useActiveGeneId() const [genes, setGenes] = useGeneticElements() const theme = useTheme() const [globalProgress, loaded] = usePageLoad() const config = useConfig() - const navigate = useNavigate() - const location = useLocation() - const params = useParams() - const [speciesList] = useSpecies() + useEffect(() => { if (loaded) { updateColors(theme) } }, [theme, loaded]) - // On app url change, make sure loaded gene and view aligns with URL - useEffect(() => { - const loadGene = async (geneid: string) => { - // TODO: This is super jank, should probably write some better utilities for loading genes - const species = speciesList.find( - (species) => species.name === 'Arabidopsis' - ) - const gene = await species?.api.searchGene(geneid) - if (gene) { - setGenes([...genes, gene]) - } - } - if (params.geneid) { - if (params.geneid !== activeGeneId) { - if (!genes.find((gene) => gene.id === params.geneid)) { - loadGene(params.geneid) - } - setActiveGeneId(params.geneid) - } - } else { - // Set active gene to first available if one is already loaded - if (genes.length > 0) { - setActiveGeneId(genes[0].id) - } else { - setActiveGeneId('') - } - } - setActiveViewId(location.pathname.split('/')[1]) - }, [location.pathname]) - - // On active gene change update the gene path segment - useEffect(() => { - if (location.pathname !== import.meta.env.BASE_URL) { - // Only run this after initial redirect - const pathSegments = location.pathname.split('/') - const geneid = activeGeneId ? activeGeneId : '' - if (pathSegments.length == 3) { - pathSegments[pathSegments.length - 1] = geneid - } else if (pathSegments.length == 2) { - pathSegments.push(geneid) - } - - const newPath = pathSegments.join('/') + location.search - if (newPath !== location.pathname + location.search) { - navigate(newPath) - } - } - }, [activeGeneId, location.pathname]) return ( @@ -124,14 +72,6 @@ const Eplant = () => { {loaded ? ( gene.id === activeGeneId) ?? null} - view={ - config.views.find( - (view) => view.id === (activeViewId ?? config.defaultView) - ) ?? FallbackView - } - setView={(viewid) => { - setActiveViewId(viewid) - }} sx={{ width: '100%', height: '100%', diff --git a/Eplant/UI/Layout/ViewContainer/index.tsx b/Eplant/UI/Layout/ViewContainer/index.tsx index 9a1a6506..988f3206 100644 --- a/Eplant/UI/Layout/ViewContainer/index.tsx +++ b/Eplant/UI/Layout/ViewContainer/index.tsx @@ -1,13 +1,20 @@ import { useEffect, useId, useMemo, useState } from 'react' -import { Outlet, useLocation, useNavigate } from 'react-router-dom' +import { Outlet, useLocation, useNavigate, useParams } from 'react-router-dom' import { useConfig } from '@eplant/config' import GeneticElement from '@eplant/GeneticElement' -import { usePrinting } from '@eplant/state' +import { + useActiveGeneId, + useGeneticElements, + usePrinting, + useSpecies, +} from '@eplant/state' import Modal from '@eplant/UI/Modal' import downloadFile from '@eplant/util/downloadFile' import ErrorBoundary from '@eplant/util/ErrorBoundary' import { useViewData } from '@eplant/View/viewData' +import CellEFP from '@eplant/views/CellEFP' +import FallbackView from '@eplant/views/FallbackView' import { AppBar, Box, @@ -40,13 +47,9 @@ import ViewOptions from './ViewOptions' * @returns */ export function ViewContainer({ - view, - setView, gene, ...props }: { - view: View - setView: (viewid: string) => void gene: GeneticElement | null } & BoxProps) { // const { activeData, error, dispatch, state } = useViewData(view, gene) @@ -57,10 +60,16 @@ export function ViewContainer({ const [printing, setPrinting] = usePrinting() const [viewingCitations, setViewingCitations] = useState(false) - const navigate = useNavigate() - const location = useLocation() const { userViews, views, genericViews } = useConfig() + const navigate = useNavigate() + const location = useLocation() + const params = useParams() + const [speciesList] = useSpecies() + const [genes, setGenes] = useGeneticElements() + const [activeGeneId, setActiveGeneId] = useActiveGeneId() + const [activeViewId, setActiveViewId] = useState('') + const activeView = views.find((view) => view.id === activeViewId) ?? CellEFP useEffect(() => { if (printing) { @@ -70,8 +79,61 @@ export function ViewContainer({ }, 100) } }, [printing]) - const topBar = useMemo( - () => ( + + // On app url change, make sure loaded gene and view aligns with URL + useEffect(() => { + const loadGene = async (geneid: string) => { + // TODO: This is super jank, should probably write some better utilities for loading genes + const species = speciesList.find( + (species) => species.name === 'Arabidopsis' + ) + const gene = await species?.api.searchGene(geneid) + if (gene) { + setGenes([...genes, gene]) + } + } + if (params.geneid) { + if (params.geneid !== activeGeneId) { + if (!genes.find((gene) => gene.id === params.geneid)) { + loadGene(params.geneid) + } + setActiveGeneId(params.geneid) + } + } else { + // Set active gene to first available if one is already loaded + if (genes.length > 0) { + setActiveGeneId(genes[0].id) + } else { + setActiveGeneId('') + } + } + setActiveViewId(location.pathname.split('/')[1]) + }, [location.pathname]) + + // On active gene change update the gene path segment + useEffect(() => { + if (location.pathname !== import.meta.env.BASE_URL) { + // Only run this after initial redirect + const pathSegments = location.pathname + .split('/') + .filter((segment) => segment !== '') + if (pathSegments.length == 2 && activeGeneId) { + pathSegments[pathSegments.length - 1] = activeGeneId + } else if (pathSegments.length == 1 && activeGeneId) { + pathSegments.push(activeGeneId) + // Will never get here as of now, but if we decide to persist activeGene need + // to do this. + } + + const newPath = '/' + pathSegments.join('/') + '/' + location.search + if (newPath !== location.pathname + '/' + location.search) { + navigate(newPath) + } + } + }, [activeGeneId]) + + const topBar = useMemo(() => { + return ( ({ @@ -102,9 +164,9 @@ export function ViewContainer({ {/* View selector dropdown */}