Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bulk delete of sessions on jbrowse-desktop #2387

Merged
merged 3 commits into from
Oct 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@material-ui/core'
import ExpandMore from '@material-ui/icons/ExpandMore'
import { makeStyles } from '@material-ui/core/styles'
import { DataGrid } from '@material-ui/data-grid'
import { DataGrid } from '@mui/x-data-grid'
import { observer } from 'mobx-react'
import clsx from 'clsx'
import isObject from 'is-object'
Expand Down
2 changes: 1 addition & 1 deletion packages/core/ReExports/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default [
'@material-ui/core/SvgIcon',
'@material-ui/core/utils',
'@material-ui/lab',
'@material-ui/data-grid',
'@mui/x-data-grid',

'@jbrowse/core/Plugin',
'@jbrowse/core/pluggableElementTypes/ViewType',
Expand Down
3 changes: 2 additions & 1 deletion packages/core/ReExports/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as MUICore from '@material-ui/core'
import * as MUIUtils from '@material-ui/core/utils'
import MUISvgIcon from '@material-ui/core/SvgIcon'
import * as MUILab from '@material-ui/lab'
import * as MUIDataGrid from '@material-ui/data-grid'
import * as MUIDataGrid from '@mui/x-data-grid'
import MUIBox from '@material-ui/core/Box'
import MUIButton from '@material-ui/core/Button'
import MUIButtonGroup from '@material-ui/core/ButtonGroup'
Expand Down Expand Up @@ -95,6 +95,7 @@ const libs = {
'@material-ui/core/utils': MUIUtils,
// end special case
'@material-ui/lab': MUILab,
'@mui/x-data-grid': MUIDataGrid,
'@material-ui/data-grid': MUIDataGrid,

// material-ui subcomponents, should get rid of these
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"dependencies": {
"@babel/runtime": "^7.15.3",
"@material-ui/icons": "^4.0.0",
"@material-ui/icons": "^4.0.1",
"abortable-promise-cache": "^1.1.3",
"base64-js": "^1.3.0",
"canvas": "^2.8.0",
Expand Down Expand Up @@ -64,7 +64,7 @@
},
"peerDependencies": {
"@material-ui/core": "^4.12.2",
"@material-ui/data-grid": "^4.0.0-alpha.37",
"@mui/x-data-grid": "^4.0.0",
"@material-ui/lab": "^4.0.0-alpha.45",
"mobx": "^5.0.0",
"mobx-react": "^6.0.0",
Expand Down
2 changes: 1 addition & 1 deletion plugins/grid-bookmark/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@jbrowse/plugin-config": "^1.0.0",
"@jbrowse/plugin-linear-genome-view": "^1.4.4",
"@material-ui/core": "^4.9.13",
"@material-ui/data-grid": "^4.0.0-alpha.37",
"@mui/x-data-grid": "^4.0.1",
"@material-ui/lab": "^4.0.0-alpha.45",
"mobx-react": "^6.0.0",
"mobx-state-tree": "3.14.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import GridBookmarkWidget from './GridBookmarkWidget'

// need to mock out data grid and force all columns to render
// https://github.com/mui-org/material-ui-x/issues/1151
jest.mock('@material-ui/data-grid', () => {
const { DataGrid } = jest.requireActual('@material-ui/data-grid')
jest.mock('@mui/x-data-grid', () => {
const { DataGrid } = jest.requireActual('@mui/x-data-grid')
return {
...jest.requireActual('@material-ui/data-grid'),
...jest.requireActual('@mui/x-data-grid'),
DataGrid: props => {
return <DataGrid {...props} columnBuffer={6} />
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Button,
makeStyles,
} from '@material-ui/core'
import { DataGrid, GridCellParams } from '@material-ui/data-grid'
import { DataGrid, GridCellParams } from '@mui/x-data-grid'
import { getSession, assembleLocString, measureText } from '@jbrowse/core/util'
import DeleteIcon from '@material-ui/icons/Delete'
import ViewCompactIcon from '@material-ui/icons/ViewCompact'
Expand Down
2 changes: 1 addition & 1 deletion plugins/variants/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@gmod/bgzf-filehandle": "^1.3.4",
"@gmod/tabix": "^1.5.0",
"@gmod/vcf": "^5.0.0",
"@material-ui/data-grid": "^4.0.0-alpha.37",
"@mui/x-data-grid": "^4.0.1",
"@material-ui/icons": "^4.11.2",
"generic-filehandle": "^2.2.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import SimpleFeature, {
SimpleFeatureSerialized,
} from '@jbrowse/core/util/simpleFeature'
import { DataGrid } from '@material-ui/data-grid'
import { DataGrid } from '@mui/x-data-grid'
import { observer } from 'mobx-react'
import { getSession } from '@jbrowse/core/util'
import { getEnv } from 'mobx-state-tree'
Expand Down
2 changes: 1 addition & 1 deletion products/jbrowse-desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"@jbrowse/plugin-variants": "^1.4.4",
"@jbrowse/plugin-wiggle": "^1.4.4",
"@material-ui/core": "^4.12.2",
"@material-ui/data-grid": "^4.0.0-alpha.37",
"@mui/x-data-grid": "^4.0.1",
"@material-ui/icons": "^4.0.0",
"@material-ui/lab": "^4.0.0-alpha.45",
"clsx": "^1.0.4",
Expand Down
150 changes: 108 additions & 42 deletions products/jbrowse-desktop/src/StartScreen/RecentSessionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import React, { useState, useEffect, useMemo } from 'react'
import fs from 'fs'
import {
CircularProgress,
FormControl,
Grid,
IconButton,
Expand All @@ -9,7 +10,7 @@ import {
Typography,
makeStyles,
} from '@material-ui/core'
import { DataGrid, GridCellParams } from '@material-ui/data-grid'
import { DataGrid, GridCellParams } from '@mui/x-data-grid'
import {
ToggleButtonGroup,
ToggleButton,
Expand All @@ -25,7 +26,9 @@ import EditIcon from '@material-ui/icons/Edit'
import ViewComfyIcon from '@material-ui/icons/ViewComfy'
import ListIcon from '@material-ui/icons/List'

// local
// locals
import RenameSessionDialog from './dialogs/RenameSessionDialog'
import DeleteSessionDialog from './dialogs/DeleteSessionDialog'
import { useLocalStorage, createPluginManager } from './util'
import SessionCard from './SessionCard'

Expand All @@ -42,39 +45,28 @@ const useStyles = makeStyles(theme => ({
},
}))

interface SessionStats {
screenshot: string
stats: fs.Stats
}

type Session = [string, SessionStats]

function RecentSessionsList({
setError,
sortedSessions,
setSessionToDelete,
setSelectedSessions,
setSessionToRename,
setPluginManager,
}: {
setError: (e: unknown) => void
setSessionToDelete: (e: string) => void
setSessionToRename: (e: string) => void
setPluginManager: (pm: PluginManager) => void
sortedSessions: [string, { stats: fs.Stats }][]
setSelectedSessions: (arg: string[]) => void
sortedSessions: Session[]
}) {
const classes = useStyles()
const columns = [
{
field: 'delete',
minWidth: 40,
width: 40,
sortable: false,
filterable: false,
headerName: ' ',
renderCell: (params: GridCellParams) => {
const { value } = params
return (
<IconButton onClick={() => setSessionToDelete(value as string)}>
<Tooltip title="Delete session">
<DeleteIcon />
</Tooltip>
</IconButton>
)
},
},
{
field: 'rename',
minWidth: 40,
Expand Down Expand Up @@ -145,12 +137,15 @@ function RecentSessionsList({
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
rows={sortedSessions.map(([sessionName, { stats }]) => ({
checkboxSelection
disableSelectionOnClick
onSelectionModelChange={args => setSelectedSessions(args as string[])}
rows={sortedSessions.map(([sessionName, session]) => ({
id: sessionName,
name: sessionName,
rename: sessionName,
delete: sessionName,
lastModified: stats?.mtime,
lastModified: session.stats?.mtime,
}))}
rowHeight={25}
headerHeight={33}
Expand All @@ -160,17 +155,15 @@ function RecentSessionsList({
)
}

type Session = [string, { screenshot: string; stats: fs.Stats }]

function RecentSessionsCards({
sortedSessions,
setError,
setSessionToDelete,
setSessionsToDelete,
setSessionToRename,
setPluginManager,
}: {
setError: (e: unknown) => void
setSessionToDelete: (e: string) => void
setSessionsToDelete: (e: string[]) => void
setSessionToRename: (e: string) => void
setPluginManager: (pm: PluginManager) => void
sortedSessions: Session[]
Expand All @@ -193,7 +186,7 @@ function RecentSessionsCards({
setError(e)
}
}}
onDelete={setSessionToDelete}
onDelete={(del: string) => setSessionsToDelete([del])}
onRename={setSessionToRename}
/>
</Grid>
Expand All @@ -202,32 +195,92 @@ function RecentSessionsCards({
)
}

// note: span helps with https://stackoverflow.com/a/66713470/2129219
function ToggleButtonWithTooltip(props: ToggleButtonProps) {
const { title, children, ...other } = props
const { title = '', children, ...other } = props
return (
<Tooltip title={title || ''}>
<ToggleButton {...other}>{children}</ToggleButton>
<Tooltip title={title}>
<span>
<ToggleButton {...other}>{children}</ToggleButton>
</span>
</Tooltip>
)
}

const getTime = (a: Session) => {
return +a[1].stats?.mtime
}

export default function RecentSessionPanel({
setError,
sortedSessions,
setSessionToRename,
setSessionToDelete,
setPluginManager,
}: {
setError: (e: unknown) => void
sortedSessions: Session[]
setSessionToRename: (e: string) => void
setSessionToDelete: (e: string) => void
setPluginManager: (pm: PluginManager) => void
}) {
const classes = useStyles()
const [displayMode, setDisplayMode] = useLocalStorage('displayMode', 'list')
const [sessions, setSessions] = useState<Map<string, SessionStats>>(new Map())
const [sessionsToDelete, setSessionsToDelete] = useState<string[]>()
const [sessionToRename, setSessionToRename] = useState<string>()
const [updateSessionsList, setUpdateSessionsList] = useState(0)
const [selectedSessions, setSelectedSessions] = useState<string[]>()

const sessionNames = useMemo(() => Object.keys(sessions || {}), [sessions])

const sortedSessions = useMemo(() => {
return sessions
? [...sessions.entries()].sort((a, b) => getTime(b) - getTime(a))
: []
}, [sessions])

useEffect(() => {
;(async () => {
try {
const sessions = await ipcRenderer.invoke('listSessions')
setSessions(sessions)
} catch (e) {
console.error(e)
setError(e)
}
})()
}, [setError, updateSessionsList])

if (!sessions) {
return (
<CircularProgress
style={{
position: 'fixed',
top: '50%',
left: '50%',
marginTop: -25,
marginLeft: -25,
}}
size={50}
/>
)
}

return (
<div>
<RenameSessionDialog
sessionToRename={sessionToRename}
sessionNames={sessionNames}
onClose={() => {
setSessionToRename(undefined)
setUpdateSessionsList(s => s + 1)
}}
/>
{sessionsToDelete ? (
<DeleteSessionDialog
setError={setError}
sessionsToDelete={sessionsToDelete}
onClose={() => {
setSessionsToDelete(undefined)
setUpdateSessionsList(s => s + 1)
}}
/>
) : null}
<FormControl className={classes.formControl}>
<ToggleButtonGroup
exclusive
Expand All @@ -243,21 +296,34 @@ export default function RecentSessionPanel({
</ToggleButtonGroup>
</FormControl>

<FormControl className={classes.formControl}>
<ToggleButtonGroup>
<ToggleButtonWithTooltip
value="delete"
title="Delete sessions"
disabled={!selectedSessions?.length}
onClick={() => setSessionsToDelete(selectedSessions)}
>
<DeleteIcon />
</ToggleButtonWithTooltip>
</ToggleButtonGroup>
</FormControl>

{sortedSessions.length ? (
displayMode === 'grid' ? (
<RecentSessionsCards
setPluginManager={setPluginManager}
sortedSessions={sortedSessions}
setError={setError}
setSessionToDelete={setSessionToDelete}
setSessionsToDelete={setSessionsToDelete}
setSessionToRename={setSessionToRename}
/>
) : (
<RecentSessionsList
setPluginManager={setPluginManager}
sortedSessions={sortedSessions}
setError={setError}
setSessionToDelete={setSessionToDelete}
setSelectedSessions={setSelectedSessions}
setSessionToRename={setSessionToRename}
/>
)
Expand Down
Loading