@jbrowse/plugin-menus 2.7.2 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SessionManager/components/AutosavedSessionsList.d.ts +6 -0
- package/dist/SessionManager/components/AutosavedSessionsList.js +23 -0
- package/dist/SessionManager/components/{DeleteDialog.d.ts → DeleteSavedSessionDialog.d.ts} +1 -1
- package/dist/SessionManager/components/{DeleteDialog.js → DeleteSavedSessionDialog.js} +4 -4
- package/dist/SessionManager/components/RegularSavedSessionsList.d.ts +6 -0
- package/dist/SessionManager/components/RegularSavedSessionsList.js +63 -0
- package/dist/SessionManager/components/SessionListItem.d.ts +10 -0
- package/dist/SessionManager/components/SessionListItem.js +25 -0
- package/dist/SessionManager/components/SessionManager.d.ts +2 -16
- package/dist/SessionManager/components/SessionManager.js +6 -92
- package/dist/SessionManager/components/util.d.ts +15 -0
- package/dist/SessionManager/components/util.js +2 -0
- package/esm/SessionManager/components/AutosavedSessionsList.d.ts +6 -0
- package/esm/SessionManager/components/AutosavedSessionsList.js +18 -0
- package/esm/SessionManager/components/{DeleteDialog.d.ts → DeleteSavedSessionDialog.d.ts} +1 -1
- package/esm/SessionManager/components/{DeleteDialog.js → DeleteSavedSessionDialog.js} +3 -3
- package/esm/SessionManager/components/RegularSavedSessionsList.d.ts +6 -0
- package/esm/SessionManager/components/RegularSavedSessionsList.js +35 -0
- package/esm/SessionManager/components/SessionListItem.d.ts +10 -0
- package/esm/SessionManager/components/SessionListItem.js +20 -0
- package/esm/SessionManager/components/SessionManager.d.ts +2 -16
- package/esm/SessionManager/components/SessionManager.js +6 -69
- package/esm/SessionManager/components/util.d.ts +15 -0
- package/esm/SessionManager/components/util.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const material_1 = require("@mui/material");
|
|
8
|
+
const mui_1 = require("tss-react/mui");
|
|
9
|
+
const mobx_react_1 = require("mobx-react");
|
|
10
|
+
const SessionListItem_1 = __importDefault(require("./SessionListItem"));
|
|
11
|
+
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
12
|
+
root: {
|
|
13
|
+
margin: theme.spacing(1),
|
|
14
|
+
},
|
|
15
|
+
}));
|
|
16
|
+
const AutosaveSessionsList = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
17
|
+
const { classes } = useStyles();
|
|
18
|
+
const autosavedSession = JSON.parse(localStorage.getItem(session.previousAutosaveId) || '{}').session;
|
|
19
|
+
return autosavedSession ? (react_1.default.createElement(material_1.Paper, { className: classes.root },
|
|
20
|
+
react_1.default.createElement(material_1.List, { subheader: react_1.default.createElement(material_1.ListSubheader, null, "Previous autosaved entry") },
|
|
21
|
+
react_1.default.createElement(SessionListItem_1.default, { session: session, sessionSnapshot: autosavedSession, onClick: () => session.loadAutosaveSession() })))) : null;
|
|
22
|
+
});
|
|
23
|
+
exports.default = AutosaveSessionsList;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export default function
|
|
2
|
+
export default function DeleteSavedSessionDialog({ open, sessionNameToDelete, handleClose, }: {
|
|
3
3
|
sessionNameToDelete: string;
|
|
4
4
|
open: boolean;
|
|
5
5
|
handleClose: (arg?: boolean) => void;
|
|
@@ -6,12 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
const material_1 = require("@mui/material");
|
|
8
8
|
const ui_1 = require("@jbrowse/core/ui");
|
|
9
|
-
function
|
|
10
|
-
return (react_1.default.createElement(ui_1.Dialog, { open: open,
|
|
9
|
+
function DeleteSavedSessionDialog({ open, sessionNameToDelete, handleClose, }) {
|
|
10
|
+
return (react_1.default.createElement(ui_1.Dialog, { open: open, title: `Delete session "${sessionNameToDelete}"?` },
|
|
11
11
|
react_1.default.createElement(material_1.DialogContent, null,
|
|
12
|
-
react_1.default.createElement(material_1.DialogContentText,
|
|
12
|
+
react_1.default.createElement(material_1.DialogContentText, null, "This action cannot be undone")),
|
|
13
13
|
react_1.default.createElement(material_1.DialogActions, null,
|
|
14
14
|
react_1.default.createElement(material_1.Button, { onClick: () => handleClose(), color: "primary" }, "Cancel"),
|
|
15
15
|
react_1.default.createElement(material_1.Button, { onClick: () => handleClose(true), color: "primary", autoFocus: true }, "Delete"))));
|
|
16
16
|
}
|
|
17
|
-
exports.default =
|
|
17
|
+
exports.default = DeleteSavedSessionDialog;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const react_1 = __importStar(require("react"));
|
|
30
|
+
const material_1 = require("@mui/material");
|
|
31
|
+
const mui_1 = require("tss-react/mui");
|
|
32
|
+
const mobx_react_1 = require("mobx-react");
|
|
33
|
+
// icons
|
|
34
|
+
const Delete_1 = __importDefault(require("@mui/icons-material/Delete"));
|
|
35
|
+
const DeleteSavedSessionDialog_1 = __importDefault(require("./DeleteSavedSessionDialog"));
|
|
36
|
+
const SessionListItem_1 = __importDefault(require("./SessionListItem"));
|
|
37
|
+
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
38
|
+
root: {
|
|
39
|
+
margin: theme.spacing(1),
|
|
40
|
+
},
|
|
41
|
+
message: {
|
|
42
|
+
padding: theme.spacing(3),
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
const RegularSavedSessionsList = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
46
|
+
const { classes } = useStyles();
|
|
47
|
+
const [sessionIndexToDelete, setSessionIndexToDelete] = (0, react_1.useState)();
|
|
48
|
+
function handleDialogClose(deleteSession = false) {
|
|
49
|
+
if (deleteSession && sessionIndexToDelete !== undefined) {
|
|
50
|
+
session.removeSavedSession(session.savedSessions[sessionIndexToDelete]);
|
|
51
|
+
}
|
|
52
|
+
setSessionIndexToDelete(undefined);
|
|
53
|
+
}
|
|
54
|
+
const sessionNameToDelete = sessionIndexToDelete !== undefined
|
|
55
|
+
? session.savedSessions[sessionIndexToDelete].name
|
|
56
|
+
: '';
|
|
57
|
+
return (react_1.default.createElement(material_1.Paper, { className: classes.root },
|
|
58
|
+
react_1.default.createElement(material_1.List, { subheader: react_1.default.createElement(material_1.ListSubheader, null, "Saved sessions") }, session.savedSessions.length ? (session.savedSessions.map((sessionSnapshot, idx) => (react_1.default.createElement(SessionListItem_1.default, { onClick: () => session.activateSession(sessionSnapshot.name), sessionSnapshot: sessionSnapshot, session: session, key: sessionSnapshot.name, secondaryAction: react_1.default.createElement(material_1.IconButton, { edge: "end", disabled: session.name === sessionSnapshot.name, onClick: () => setSessionIndexToDelete(idx) },
|
|
59
|
+
react_1.default.createElement(Delete_1.default, null)) })))) : (react_1.default.createElement(material_1.Typography, { className: classes.message }, "No saved sessions found"))),
|
|
60
|
+
sessionNameToDelete ? (react_1.default.createElement(react_1.default.Suspense, { fallback: null },
|
|
61
|
+
react_1.default.createElement(DeleteSavedSessionDialog_1.default, { open: true, sessionNameToDelete: sessionNameToDelete, handleClose: handleDialogClose }))) : null));
|
|
62
|
+
});
|
|
63
|
+
exports.default = RegularSavedSessionsList;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AbstractSessionModel } from '@jbrowse/core/util';
|
|
3
|
+
import { SessionSnap } from './util';
|
|
4
|
+
declare const SessionListItem: ({ session, sessionSnapshot, onClick, secondaryAction, }: {
|
|
5
|
+
sessionSnapshot: SessionSnap;
|
|
6
|
+
session: AbstractSessionModel;
|
|
7
|
+
onClick: () => void;
|
|
8
|
+
secondaryAction?: React.ReactNode;
|
|
9
|
+
}) => React.JSX.Element;
|
|
10
|
+
export default SessionListItem;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const material_1 = require("@mui/material");
|
|
8
|
+
const mobx_react_1 = require("mobx-react");
|
|
9
|
+
const pluralize_1 = __importDefault(require("pluralize"));
|
|
10
|
+
// icons
|
|
11
|
+
const ViewList_1 = __importDefault(require("@mui/icons-material/ViewList"));
|
|
12
|
+
const util_1 = require("@jbrowse/core/util");
|
|
13
|
+
const SessionListItem = (0, mobx_react_1.observer)(function ({ session, sessionSnapshot, onClick, secondaryAction, }) {
|
|
14
|
+
const { views = [] } = sessionSnapshot || {};
|
|
15
|
+
const totalTracks = (0, util_1.sum)(views.map(view => { var _a, _b; return (_b = (_a = view.tracks) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }));
|
|
16
|
+
const n = views.length;
|
|
17
|
+
return (react_1.default.createElement(material_1.ListItem, { secondaryAction: secondaryAction },
|
|
18
|
+
react_1.default.createElement(material_1.ListItemButton, { onClick: onClick },
|
|
19
|
+
react_1.default.createElement(material_1.ListItemIcon, null,
|
|
20
|
+
react_1.default.createElement(ViewList_1.default, null)),
|
|
21
|
+
react_1.default.createElement(material_1.ListItemText, { primary: sessionSnapshot.name, secondary: session.name === sessionSnapshot.name
|
|
22
|
+
? 'Currently open'
|
|
23
|
+
: `${n} ${(0, pluralize_1.default)('view', n)}; ${totalTracks} open ${(0, pluralize_1.default)('track', totalTracks)}` }))));
|
|
24
|
+
});
|
|
25
|
+
exports.default = SessionListItem;
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
name: string;
|
|
5
|
-
views?: {
|
|
6
|
-
tracks: unknown[];
|
|
7
|
-
}[];
|
|
8
|
-
[key: string]: unknown;
|
|
9
|
-
}
|
|
10
|
-
interface SessionModel extends AbstractSessionModel {
|
|
11
|
-
savedSessions: SessionSnap[];
|
|
12
|
-
removeSavedSession: (arg: SessionSnap) => void;
|
|
13
|
-
activateSession: (arg: string) => void;
|
|
14
|
-
loadAutosaveSession: () => void;
|
|
15
|
-
previousAutosaveId: string;
|
|
16
|
-
}
|
|
17
|
-
declare const SessionManager: ({ session }: {
|
|
2
|
+
import { SessionModel } from './util';
|
|
3
|
+
declare const SessionManager: ({ session, }: {
|
|
18
4
|
session: SessionModel;
|
|
19
5
|
}) => React.JSX.Element;
|
|
20
6
|
export default SessionManager;
|
|
@@ -1,101 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
28
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
const react_1 =
|
|
30
|
-
const material_1 = require("@mui/material");
|
|
31
|
-
const mui_1 = require("tss-react/mui");
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
32
7
|
const mobx_react_1 = require("mobx-react");
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
const ViewList_1 = __importDefault(require("@mui/icons-material/ViewList"));
|
|
37
|
-
const DeleteDialog_1 = __importDefault(require("./DeleteDialog"));
|
|
38
|
-
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
39
|
-
root: {
|
|
40
|
-
margin: theme.spacing(1),
|
|
41
|
-
},
|
|
42
|
-
message: {
|
|
43
|
-
padding: theme.spacing(3),
|
|
44
|
-
},
|
|
45
|
-
}));
|
|
46
|
-
const AutosaveEntry = (0, mobx_react_1.observer)(({ session }) => {
|
|
47
|
-
const { classes } = useStyles();
|
|
48
|
-
const autosavedSession = JSON.parse(localStorage.getItem(session.previousAutosaveId) || '{}').session;
|
|
49
|
-
const { views = [] } = autosavedSession || {};
|
|
50
|
-
const totalTracks = views
|
|
51
|
-
.map(view => view.tracks.length)
|
|
52
|
-
.reduce((a, b) => a + b, 0);
|
|
53
|
-
return autosavedSession ? (react_1.default.createElement(material_1.Paper, { className: classes.root },
|
|
54
|
-
react_1.default.createElement(material_1.List, { subheader: react_1.default.createElement(material_1.ListSubheader, null, "Previous autosaved entry") },
|
|
55
|
-
react_1.default.createElement(material_1.ListItem, { button: true, onClick: () => session.loadAutosaveSession() },
|
|
56
|
-
react_1.default.createElement(material_1.ListItemIcon, null,
|
|
57
|
-
react_1.default.createElement(ViewList_1.default, null)),
|
|
58
|
-
react_1.default.createElement(material_1.ListItemText, { primary: autosavedSession.name, secondary: session.name === autosavedSession.name
|
|
59
|
-
? 'Currently open'
|
|
60
|
-
: `${views.length} ${(0, pluralize_1.default)('view', views.length)}; ${totalTracks}
|
|
61
|
-
open ${(0, pluralize_1.default)('track', totalTracks)}` }))))) : null;
|
|
62
|
-
});
|
|
63
|
-
const SessionManager = (0, mobx_react_1.observer)(({ session }) => {
|
|
64
|
-
const { classes } = useStyles();
|
|
65
|
-
const [sessionIndexToDelete, setSessionIndexToDelete] = (0, react_1.useState)();
|
|
66
|
-
const [open, setOpen] = (0, react_1.useState)(false);
|
|
67
|
-
function handleDialogClose(deleteSession = false) {
|
|
68
|
-
if (deleteSession && sessionIndexToDelete !== undefined) {
|
|
69
|
-
session.removeSavedSession(session.savedSessions[sessionIndexToDelete]);
|
|
70
|
-
}
|
|
71
|
-
setSessionIndexToDelete(undefined);
|
|
72
|
-
setOpen(false);
|
|
73
|
-
}
|
|
74
|
-
const sessionNameToDelete = sessionIndexToDelete !== undefined
|
|
75
|
-
? session.savedSessions[sessionIndexToDelete].name
|
|
76
|
-
: '';
|
|
8
|
+
const AutosavedSessionsList_1 = __importDefault(require("./AutosavedSessionsList"));
|
|
9
|
+
const RegularSavedSessionsList_1 = __importDefault(require("./RegularSavedSessionsList"));
|
|
10
|
+
const SessionManager = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
77
11
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
78
|
-
react_1.default.createElement(
|
|
79
|
-
react_1.default.createElement(
|
|
80
|
-
react_1.default.createElement(material_1.List, { subheader: react_1.default.createElement(material_1.ListSubheader, null, "Saved sessions") }, session.savedSessions.length ? (session.savedSessions.map((sessionSnapshot, idx) => {
|
|
81
|
-
const { views = [] } = sessionSnapshot;
|
|
82
|
-
const totalTracks = views
|
|
83
|
-
.map(view => view.tracks.length)
|
|
84
|
-
.reduce((a, b) => a + b, 0);
|
|
85
|
-
return (react_1.default.createElement(material_1.ListItem, { button: true, disabled: session.name === sessionSnapshot.name, onClick: () => session.activateSession(sessionSnapshot.name), key: sessionSnapshot.name },
|
|
86
|
-
react_1.default.createElement(material_1.ListItemIcon, null,
|
|
87
|
-
react_1.default.createElement(ViewList_1.default, null)),
|
|
88
|
-
react_1.default.createElement(material_1.ListItemText, { primary: sessionSnapshot.name, secondary: session.name === sessionSnapshot.name
|
|
89
|
-
? 'Currently open'
|
|
90
|
-
: `${views.length} ${(0, pluralize_1.default)('view', views.length)}; ${totalTracks}
|
|
91
|
-
open ${(0, pluralize_1.default)('track', totalTracks)}` }),
|
|
92
|
-
react_1.default.createElement(material_1.ListItemSecondaryAction, null,
|
|
93
|
-
react_1.default.createElement(material_1.IconButton, { edge: "end", disabled: session.name === sessionSnapshot.name, "aria-label": "Delete", onClick: () => {
|
|
94
|
-
setSessionIndexToDelete(idx);
|
|
95
|
-
setOpen(true);
|
|
96
|
-
} },
|
|
97
|
-
react_1.default.createElement(Delete_1.default, null)))));
|
|
98
|
-
})) : (react_1.default.createElement(material_1.Typography, { className: classes.message }, "No saved sessions found")))),
|
|
99
|
-
react_1.default.createElement(DeleteDialog_1.default, { open: open, sessionNameToDelete: sessionNameToDelete, handleClose: handleDialogClose })));
|
|
12
|
+
react_1.default.createElement(AutosavedSessionsList_1.default, { session: session }),
|
|
13
|
+
react_1.default.createElement(RegularSavedSessionsList_1.default, { session: session })));
|
|
100
14
|
});
|
|
101
15
|
exports.default = SessionManager;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AbstractSessionModel } from '@jbrowse/core/util';
|
|
2
|
+
export interface SessionSnap {
|
|
3
|
+
name: string;
|
|
4
|
+
views?: {
|
|
5
|
+
tracks?: unknown[];
|
|
6
|
+
}[];
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface SessionModel extends AbstractSessionModel {
|
|
10
|
+
savedSessions: SessionSnap[];
|
|
11
|
+
removeSavedSession: (arg: SessionSnap) => void;
|
|
12
|
+
activateSession: (arg: string) => void;
|
|
13
|
+
loadAutosaveSession: () => void;
|
|
14
|
+
previousAutosaveId: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { List, ListSubheader, Paper } from '@mui/material';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
|
+
import SessionListItem from './SessionListItem';
|
|
6
|
+
const useStyles = makeStyles()(theme => ({
|
|
7
|
+
root: {
|
|
8
|
+
margin: theme.spacing(1),
|
|
9
|
+
},
|
|
10
|
+
}));
|
|
11
|
+
const AutosaveSessionsList = observer(function ({ session, }) {
|
|
12
|
+
const { classes } = useStyles();
|
|
13
|
+
const autosavedSession = JSON.parse(localStorage.getItem(session.previousAutosaveId) || '{}').session;
|
|
14
|
+
return autosavedSession ? (React.createElement(Paper, { className: classes.root },
|
|
15
|
+
React.createElement(List, { subheader: React.createElement(ListSubheader, null, "Previous autosaved entry") },
|
|
16
|
+
React.createElement(SessionListItem, { session: session, sessionSnapshot: autosavedSession, onClick: () => session.loadAutosaveSession() })))) : null;
|
|
17
|
+
});
|
|
18
|
+
export default AutosaveSessionsList;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export default function
|
|
2
|
+
export default function DeleteSavedSessionDialog({ open, sessionNameToDelete, handleClose, }: {
|
|
3
3
|
sessionNameToDelete: string;
|
|
4
4
|
open: boolean;
|
|
5
5
|
handleClose: (arg?: boolean) => void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Button, DialogActions, DialogContent, DialogContentText, } from '@mui/material';
|
|
3
3
|
import { Dialog } from '@jbrowse/core/ui';
|
|
4
|
-
export default function
|
|
5
|
-
return (React.createElement(Dialog, { open: open,
|
|
4
|
+
export default function DeleteSavedSessionDialog({ open, sessionNameToDelete, handleClose, }) {
|
|
5
|
+
return (React.createElement(Dialog, { open: open, title: `Delete session "${sessionNameToDelete}"?` },
|
|
6
6
|
React.createElement(DialogContent, null,
|
|
7
|
-
React.createElement(DialogContentText,
|
|
7
|
+
React.createElement(DialogContentText, null, "This action cannot be undone")),
|
|
8
8
|
React.createElement(DialogActions, null,
|
|
9
9
|
React.createElement(Button, { onClick: () => handleClose(), color: "primary" }, "Cancel"),
|
|
10
10
|
React.createElement(Button, { onClick: () => handleClose(true), color: "primary", autoFocus: true }, "Delete"))));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { IconButton, List, ListSubheader, Paper, Typography, } from '@mui/material';
|
|
3
|
+
import { makeStyles } from 'tss-react/mui';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
|
+
// icons
|
|
6
|
+
import DeleteIcon from '@mui/icons-material/Delete';
|
|
7
|
+
import DeleteSavedSessionDialog from './DeleteSavedSessionDialog';
|
|
8
|
+
import SessionListItem from './SessionListItem';
|
|
9
|
+
const useStyles = makeStyles()(theme => ({
|
|
10
|
+
root: {
|
|
11
|
+
margin: theme.spacing(1),
|
|
12
|
+
},
|
|
13
|
+
message: {
|
|
14
|
+
padding: theme.spacing(3),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
const RegularSavedSessionsList = observer(function ({ session, }) {
|
|
18
|
+
const { classes } = useStyles();
|
|
19
|
+
const [sessionIndexToDelete, setSessionIndexToDelete] = useState();
|
|
20
|
+
function handleDialogClose(deleteSession = false) {
|
|
21
|
+
if (deleteSession && sessionIndexToDelete !== undefined) {
|
|
22
|
+
session.removeSavedSession(session.savedSessions[sessionIndexToDelete]);
|
|
23
|
+
}
|
|
24
|
+
setSessionIndexToDelete(undefined);
|
|
25
|
+
}
|
|
26
|
+
const sessionNameToDelete = sessionIndexToDelete !== undefined
|
|
27
|
+
? session.savedSessions[sessionIndexToDelete].name
|
|
28
|
+
: '';
|
|
29
|
+
return (React.createElement(Paper, { className: classes.root },
|
|
30
|
+
React.createElement(List, { subheader: React.createElement(ListSubheader, null, "Saved sessions") }, session.savedSessions.length ? (session.savedSessions.map((sessionSnapshot, idx) => (React.createElement(SessionListItem, { onClick: () => session.activateSession(sessionSnapshot.name), sessionSnapshot: sessionSnapshot, session: session, key: sessionSnapshot.name, secondaryAction: React.createElement(IconButton, { edge: "end", disabled: session.name === sessionSnapshot.name, onClick: () => setSessionIndexToDelete(idx) },
|
|
31
|
+
React.createElement(DeleteIcon, null)) })))) : (React.createElement(Typography, { className: classes.message }, "No saved sessions found"))),
|
|
32
|
+
sessionNameToDelete ? (React.createElement(React.Suspense, { fallback: null },
|
|
33
|
+
React.createElement(DeleteSavedSessionDialog, { open: true, sessionNameToDelete: sessionNameToDelete, handleClose: handleDialogClose }))) : null));
|
|
34
|
+
});
|
|
35
|
+
export default RegularSavedSessionsList;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AbstractSessionModel } from '@jbrowse/core/util';
|
|
3
|
+
import { SessionSnap } from './util';
|
|
4
|
+
declare const SessionListItem: ({ session, sessionSnapshot, onClick, secondaryAction, }: {
|
|
5
|
+
sessionSnapshot: SessionSnap;
|
|
6
|
+
session: AbstractSessionModel;
|
|
7
|
+
onClick: () => void;
|
|
8
|
+
secondaryAction?: React.ReactNode;
|
|
9
|
+
}) => React.JSX.Element;
|
|
10
|
+
export default SessionListItem;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ListItem, ListItemButton, ListItemIcon, ListItemText, } from '@mui/material';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import pluralize from 'pluralize';
|
|
5
|
+
// icons
|
|
6
|
+
import ViewListIcon from '@mui/icons-material/ViewList';
|
|
7
|
+
import { sum } from '@jbrowse/core/util';
|
|
8
|
+
const SessionListItem = observer(function ({ session, sessionSnapshot, onClick, secondaryAction, }) {
|
|
9
|
+
const { views = [] } = sessionSnapshot || {};
|
|
10
|
+
const totalTracks = sum(views.map(view => { var _a, _b; return (_b = (_a = view.tracks) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }));
|
|
11
|
+
const n = views.length;
|
|
12
|
+
return (React.createElement(ListItem, { secondaryAction: secondaryAction },
|
|
13
|
+
React.createElement(ListItemButton, { onClick: onClick },
|
|
14
|
+
React.createElement(ListItemIcon, null,
|
|
15
|
+
React.createElement(ViewListIcon, null)),
|
|
16
|
+
React.createElement(ListItemText, { primary: sessionSnapshot.name, secondary: session.name === sessionSnapshot.name
|
|
17
|
+
? 'Currently open'
|
|
18
|
+
: `${n} ${pluralize('view', n)}; ${totalTracks} open ${pluralize('track', totalTracks)}` }))));
|
|
19
|
+
});
|
|
20
|
+
export default SessionListItem;
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
name: string;
|
|
5
|
-
views?: {
|
|
6
|
-
tracks: unknown[];
|
|
7
|
-
}[];
|
|
8
|
-
[key: string]: unknown;
|
|
9
|
-
}
|
|
10
|
-
interface SessionModel extends AbstractSessionModel {
|
|
11
|
-
savedSessions: SessionSnap[];
|
|
12
|
-
removeSavedSession: (arg: SessionSnap) => void;
|
|
13
|
-
activateSession: (arg: string) => void;
|
|
14
|
-
loadAutosaveSession: () => void;
|
|
15
|
-
previousAutosaveId: string;
|
|
16
|
-
}
|
|
17
|
-
declare const SessionManager: ({ session }: {
|
|
2
|
+
import { SessionModel } from './util';
|
|
3
|
+
declare const SessionManager: ({ session, }: {
|
|
18
4
|
session: SessionModel;
|
|
19
5
|
}) => React.JSX.Element;
|
|
20
6
|
export default SessionManager;
|
|
@@ -1,73 +1,10 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { IconButton, List, ListItem, ListItemIcon, ListItemSecondaryAction, ListItemText, ListSubheader, Paper, Typography, } from '@mui/material';
|
|
3
|
-
import { makeStyles } from 'tss-react/mui';
|
|
1
|
+
import React from 'react';
|
|
4
2
|
import { observer } from 'mobx-react';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import ViewListIcon from '@mui/icons-material/ViewList';
|
|
9
|
-
import DeleteDialog from './DeleteDialog';
|
|
10
|
-
const useStyles = makeStyles()(theme => ({
|
|
11
|
-
root: {
|
|
12
|
-
margin: theme.spacing(1),
|
|
13
|
-
},
|
|
14
|
-
message: {
|
|
15
|
-
padding: theme.spacing(3),
|
|
16
|
-
},
|
|
17
|
-
}));
|
|
18
|
-
const AutosaveEntry = observer(({ session }) => {
|
|
19
|
-
const { classes } = useStyles();
|
|
20
|
-
const autosavedSession = JSON.parse(localStorage.getItem(session.previousAutosaveId) || '{}').session;
|
|
21
|
-
const { views = [] } = autosavedSession || {};
|
|
22
|
-
const totalTracks = views
|
|
23
|
-
.map(view => view.tracks.length)
|
|
24
|
-
.reduce((a, b) => a + b, 0);
|
|
25
|
-
return autosavedSession ? (React.createElement(Paper, { className: classes.root },
|
|
26
|
-
React.createElement(List, { subheader: React.createElement(ListSubheader, null, "Previous autosaved entry") },
|
|
27
|
-
React.createElement(ListItem, { button: true, onClick: () => session.loadAutosaveSession() },
|
|
28
|
-
React.createElement(ListItemIcon, null,
|
|
29
|
-
React.createElement(ViewListIcon, null)),
|
|
30
|
-
React.createElement(ListItemText, { primary: autosavedSession.name, secondary: session.name === autosavedSession.name
|
|
31
|
-
? 'Currently open'
|
|
32
|
-
: `${views.length} ${pluralize('view', views.length)}; ${totalTracks}
|
|
33
|
-
open ${pluralize('track', totalTracks)}` }))))) : null;
|
|
34
|
-
});
|
|
35
|
-
const SessionManager = observer(({ session }) => {
|
|
36
|
-
const { classes } = useStyles();
|
|
37
|
-
const [sessionIndexToDelete, setSessionIndexToDelete] = useState();
|
|
38
|
-
const [open, setOpen] = useState(false);
|
|
39
|
-
function handleDialogClose(deleteSession = false) {
|
|
40
|
-
if (deleteSession && sessionIndexToDelete !== undefined) {
|
|
41
|
-
session.removeSavedSession(session.savedSessions[sessionIndexToDelete]);
|
|
42
|
-
}
|
|
43
|
-
setSessionIndexToDelete(undefined);
|
|
44
|
-
setOpen(false);
|
|
45
|
-
}
|
|
46
|
-
const sessionNameToDelete = sessionIndexToDelete !== undefined
|
|
47
|
-
? session.savedSessions[sessionIndexToDelete].name
|
|
48
|
-
: '';
|
|
3
|
+
import AutosaveSessionsList from './AutosavedSessionsList';
|
|
4
|
+
import RegularSavedSessionsList from './RegularSavedSessionsList';
|
|
5
|
+
const SessionManager = observer(function ({ session, }) {
|
|
49
6
|
return (React.createElement(React.Fragment, null,
|
|
50
|
-
React.createElement(
|
|
51
|
-
React.createElement(
|
|
52
|
-
React.createElement(List, { subheader: React.createElement(ListSubheader, null, "Saved sessions") }, session.savedSessions.length ? (session.savedSessions.map((sessionSnapshot, idx) => {
|
|
53
|
-
const { views = [] } = sessionSnapshot;
|
|
54
|
-
const totalTracks = views
|
|
55
|
-
.map(view => view.tracks.length)
|
|
56
|
-
.reduce((a, b) => a + b, 0);
|
|
57
|
-
return (React.createElement(ListItem, { button: true, disabled: session.name === sessionSnapshot.name, onClick: () => session.activateSession(sessionSnapshot.name), key: sessionSnapshot.name },
|
|
58
|
-
React.createElement(ListItemIcon, null,
|
|
59
|
-
React.createElement(ViewListIcon, null)),
|
|
60
|
-
React.createElement(ListItemText, { primary: sessionSnapshot.name, secondary: session.name === sessionSnapshot.name
|
|
61
|
-
? 'Currently open'
|
|
62
|
-
: `${views.length} ${pluralize('view', views.length)}; ${totalTracks}
|
|
63
|
-
open ${pluralize('track', totalTracks)}` }),
|
|
64
|
-
React.createElement(ListItemSecondaryAction, null,
|
|
65
|
-
React.createElement(IconButton, { edge: "end", disabled: session.name === sessionSnapshot.name, "aria-label": "Delete", onClick: () => {
|
|
66
|
-
setSessionIndexToDelete(idx);
|
|
67
|
-
setOpen(true);
|
|
68
|
-
} },
|
|
69
|
-
React.createElement(DeleteIcon, null)))));
|
|
70
|
-
})) : (React.createElement(Typography, { className: classes.message }, "No saved sessions found")))),
|
|
71
|
-
React.createElement(DeleteDialog, { open: open, sessionNameToDelete: sessionNameToDelete, handleClose: handleDialogClose })));
|
|
7
|
+
React.createElement(AutosaveSessionsList, { session: session }),
|
|
8
|
+
React.createElement(RegularSavedSessionsList, { session: session })));
|
|
72
9
|
});
|
|
73
10
|
export default SessionManager;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AbstractSessionModel } from '@jbrowse/core/util';
|
|
2
|
+
export interface SessionSnap {
|
|
3
|
+
name: string;
|
|
4
|
+
views?: {
|
|
5
|
+
tracks?: unknown[];
|
|
6
|
+
}[];
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface SessionModel extends AbstractSessionModel {
|
|
10
|
+
savedSessions: SessionSnap[];
|
|
11
|
+
removeSavedSession: (arg: SessionSnap) => void;
|
|
12
|
+
activateSession: (arg: string) => void;
|
|
13
|
+
loadAutosaveSession: () => void;
|
|
14
|
+
previousAutosaveId: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-menus",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "JBrowse 2 basic menus",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "ee8c2bdc8bd4f1a70b1eefda984f04a2830d9ca0"
|
|
60
60
|
}
|