Skip to content

Commit

Permalink
Revert "Remove panes (#107)"
Browse files Browse the repository at this point in the history
This reverts commit 7975c06.
  • Loading branch information
zkdan authored Mar 8, 2024
1 parent 7975c06 commit ffc4c1c
Show file tree
Hide file tree
Showing 14 changed files with 501 additions and 254 deletions.
84 changes: 84 additions & 0 deletions Eplant/DirectPane.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useEffect } from 'react'
import { useSearchParams } from 'react-router-dom'

import { CallReceived } from '@mui/icons-material'
import { Box, CircularProgress, IconButton } from '@mui/material'
import { useTheme } from '@mui/material/styles'

import { useConfig } from './config'
import { useActiveId, useModel, usePageLoad, usePanes } from './state'
import { updateColors } from './updateColors'
import ViewTab from './ViewTab'
/**
* Directly render a pane based on its id
*/
function DirectPane() {
const [panes, panesDispatch] = usePanes()
const params = useSearchParams()[0]
const id = params.get('id') as string
const theme = useTheme()
const [activeId] = useActiveId()
const [model] = useModel()
const { tabHeight, views } = useConfig()
const [globalProgress, loaded] = usePageLoad()
useEffect(() => {
updateColors(theme)
}, [theme, loaded])

useEffect(() => {
if (loaded && panes[id] && model.getNodeById(id)) window.close()
}, [panes, loaded, model])

return loaded ? (
<div
className='flexlayout__layout'
style={{
display: 'flex',
flexDirection: 'column',
overflow: 'auto',
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
width: '100%',
bgcolor: 'background.main',
height: `${tabHeight}px`,
}}
className={id == activeId ? 'flexlayout__tabset-selected' : ''}
>
<div className='flexlayout__tab_button flexlayout__tab_button_top flexlayout__tab_button--selected'>
<div className='flexlayout__tab-content'>
{panes[id]?.activeGene ? panes[id]?.activeGene + ' - ' : ''}
{views.find((v) => v.id == panes[id]?.view)?.name}
</div>
</div>
<div style={{ flexGrow: 1 }}></div>
<IconButton
onClick={() => {
panesDispatch({ type: 'close-popout', id })
}}
>
<CallReceived />
</IconButton>
</Box>
<Box flexGrow={1}>
<ViewTab id={id} />
</Box>
</div>
) : (
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<CircularProgress />
</div>
)
}
export default DirectPane
2 changes: 2 additions & 0 deletions Eplant/Eplant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CssBaseline, ThemeProvider } from '@mui/material'
import { dark, light } from './css/theme'
import Sidebar from './UI/Sidebar'
import { useConfig } from './config'
import DirectPane from './DirectPane'
import EplantLayout from './EplantLayout'
import { useDarkMode } from './state'
export type EplantProps = Record<string, never>
Expand All @@ -19,6 +20,7 @@ export default function Eplant() {
<Routes>
<Route path={rootPath}>
<Route index element={<MainEplant />} />
<Route path='pane' element={<DirectPane />} />
</Route>
</Routes>
</ThemeProvider>
Expand Down
219 changes: 189 additions & 30 deletions Eplant/EplantLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,71 @@
import { useEffect} from 'react'
import { useEffect, useRef } from 'react'
import * as FlexLayout from 'flexlayout-react'
import {
Actions,
BorderNode,
ITabSetRenderValues,
Layout,
TabSetNode,
} from 'flexlayout-react'

import { Add, CallMade, Close } from '@mui/icons-material'
import { Box, CircularProgress, IconButton } from '@mui/material'
import { useTheme } from '@mui/material/styles'

import { ViewContainer } from './UI/Layout/ViewContainer'
import TabsetPlaceholder from './UI/Layout/TabsetPlaceholder'
import { sidebarWidth } from './UI/Sidebar'
import FallbackView from './views/FallbackView'
import { useConfig } from './config'
import GeneticElement, { Species } from './GeneticElement'
import {
pageLoad,
useActiveGeneId,
useActiveViewId,
useGeneticElements,
getPaneName,
storage,
useActiveId,
useModel,
usePageLoad,
useSpecies} from './state'
usePanes,
} from './state'
import { updateColors } from './updateColors'
import ViewTab from './ViewTab'

const EplantLayout = () => {
const [activeGeneId, setActiveGeneId] = useActiveGeneId()
const [activeViewId, setActiveViewId] = useActiveViewId()

const [genes] = useGeneticElements()
const [panes, panesDispatch] = usePanes()
const layout = useRef<Layout>(null)
const [activeId, setActiveId] = useActiveId()
const { tabHeight } = useConfig()
const [model, setModel] = useModel()
const theme = useTheme()
const [globalProgress, loaded] = usePageLoad()
const config = useConfig()

useEffect(() => {
if (loaded) {
updateColors(theme)
}
}, [theme, loaded])

// Update the model when the activeId changes
useEffect(() => {
if (model.getNodeById(activeId)) model.doAction(Actions.selectTab(activeId))
// TODO: Need to add back if using flex-layout from Alex's fork
// else model.doAction(Actions.deselectTabset())
}, [activeId, model])

// Add a new tab when there is a non-popout pane
useEffect(() => {
if (loaded) {
for (const id in panes) {
if (panes[id].popout) continue
if (!model.getNodeById(id)) addTab({ tabId: id })
}
}
}, [panes, model, loaded])

useEffect(() => {
if (!loaded) return
const json = model.toJson()
if (!json.global) json.global = {}
json.global.tabSetTabStripHeight = tabHeight
setModel(FlexLayout.Model.fromJson(json))
}, [tabHeight, loaded])

return (
<Box
sx={(theme) => ({
Expand All @@ -48,26 +82,52 @@ const EplantLayout = () => {
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'stretch',
justifyContent: 'stretch',
alignItems: 'center',
justifyContent: 'center',
}}
>
{loaded ? (
<ViewContainer
gene={genes.find((gene) => gene.id === activeGeneId) ?? null}
view={
config.views.find(
(view) => view.id === (activeViewId ?? config.defaultView)
) ?? FallbackView
}
setView={(view) => {
setActiveViewId(view.id)
<FlexLayout.Layout
ref={layout}
model={model}
factory={(node) => factory(node, model)}
onTabSetPlaceHolder={() => (
<TabsetPlaceholder addTab={() => addTab({})} />
)}
onModelChange={(newModel) => {
// Update the selected tab
const newId = newModel
.getActiveTabset()
?.getSelectedNode?.()
?.getId?.()
if (newId) setActiveId(newId)
storage.set('flexlayout-model', JSON.stringify(model.toJson()))
}}
sx={{
width: '100%',
height: '100%',
onRenderTabSet={onRenderTabSet}
onRenderTab={(node, renderValues) => {
renderValues.buttons = [
<IconButton
key='close'
// Why is this necessary?
// Idk, but flexlayout-react uses it for their close buttons
// And they don't work without it
onMouseDown={(e) => {
e.stopPropagation()
}}
onTouchStart={(e) => {
e.stopPropagation()
}}
onMouseUp={(e) => {
panesDispatch({ type: 'close', id: node.getId() })
model.doAction(Actions.deleteTab(node.getId()))
}}
size='small'
>
<Close />
</IconButton>,
]
}}
/>
></FlexLayout.Layout>
) : (
<div>
<CircularProgress
Expand All @@ -79,5 +139,104 @@ const EplantLayout = () => {
</Box>
</Box>
)
function addTab({ tabsetId, tabId }: { tabsetId?: string; tabId?: string }) {
if (!layout.current) return

const id = tabId ?? (Math.random().toString(16).split('.')[1] as string)
const activeTab = model.getActiveTabset()?.getSelectedNode?.()?.getId?.()
const activeGene = activeTab ? panes[activeTab]?.activeGene ?? null : null
// Make a pane if a new id needs to be generated
// If the id is provided then assume that there already is a pane
if (!tabId) {
panesDispatch({
type: 'new',
id,
activeGene,
})
}

const name = panes[id] ? getPaneName(panes[id]) : 'Get started'

layout.current.addTabToTabSet(
tabsetId ??
model.getActiveTabset()?.getId?.() ??
model.getRoot().getChildren()[0]?.getId() ??
'',
{
name: name,
component: 'view',
id,
type: 'tab',
}
)
}

function makePopout(id: string) {
panesDispatch({
type: 'make-popout',
id,
})
const url =
(window.location.pathname + '/pane').replace('//', '/') + '?id=' + id
const pane = window.open(url, id, 'popup,width=800,height=600')
if (pane) {
model.doAction(Actions.deleteTab(id))
}
}

function onRenderTabSet(
node: TabSetNode | BorderNode,
renderValues: ITabSetRenderValues
) {
if (node.getChildren().length == 0) return
renderValues.stickyButtons.push(
<IconButton
onClick={() => addTab({ tabsetId: node.getId() })}
size='small'
key='add-tab'
>
<Add />
</IconButton>
)
renderValues.buttons.push(
<IconButton
onClick={() => {
const id = node.getSelectedNode()?.getId()
if (id) makePopout(id)
}}
size='small'
key='make-popout'
>
<CallMade />
</IconButton>
)
}
}
export default EplantLayout

/**
* The flexlayout factory is a function that takes a layout node and returns the React component that should be rendered there.
* @param node The node to render
* @param model The flexlayout model
* @returns The React component to render
*/
const factory: (
node: FlexLayout.TabNode,
model: FlexLayout.Model
) => JSX.Element | undefined = (node, model) => {
const id = node.getId() as string
return (
<div
style={{
height: '100%',
width: '100%',
display: 'flex',
justifyContent: 'center',
boxSizing: 'border-box',
alignItems: 'center',
}}
>
<ViewTab layout={{ model, node }} id={id} />
</div>
)
}
export default EplantLayout
9 changes: 5 additions & 4 deletions Eplant/UI/Layout/ViewContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react'

import { useConfig } from '@eplant/config'
import GeneticElement from '@eplant/GeneticElement'
import { usePrinting } from '@eplant/state'
import { usePrinting, useViewID } from '@eplant/state'
import Modal from '@eplant/UI/Modal'
import downloadFile from '@eplant/util/downloadFile'
import ErrorBoundary from '@eplant/util/ErrorBoundary'
Expand Down Expand Up @@ -54,14 +54,15 @@ export function ViewContainer<T, S, A>({

const [viewingCitations, setViewingCitations] = React.useState(false)

const viewId = useViewID()

const { userViews, views, genericViews } = useConfig()

React.useEffect(() => {
if (printing) {
if (printing == viewId) {
setTimeout(() => {
window.print()
setPrinting(false)
setPrinting(null)
}, 100)
}
}, [printing])
Expand Down Expand Up @@ -266,7 +267,7 @@ export function ViewContainer<T, S, A>({
borderWidth: '0px 0px 0px 1px',
borderColor: theme.palette.background.edgeLight,
flexDirection: 'column',
...(printing
...(printing == viewId
? {
display: 'block !important',
padding: 0,
Expand Down
Loading

0 comments on commit ffc4c1c

Please sign in to comment.