From cae4f0e8a92aac03e3756c8d434b291331a74ecd Mon Sep 17 00:00:00 2001 From: Colin Date: Mon, 6 Nov 2023 08:45:22 -0500 Subject: [PATCH] Volatile-ize spreadsheet view Remove [skip ci] Volatile [skip ci] Parse out INFO field [skip ci] Misc Misc Restyling Refactoring More misc Misc Misc Misc Misc New Refname renaming fix for breakpoint split view Breakpoint split view Misc [skip ci] Refactors --- package.json | 2 +- packages/core/ReExports/modules.tsx | 6 +- packages/core/package.json | 2 +- packages/core/ui/ResizeBar.tsx | 6 +- packages/core/ui/ResizeHandle.tsx | 7 +- packages/core/ui/index.ts | 1 + .../bed/src/BigBedAdapter/BigBedAdapter.ts | 5 +- .../BreakpointSplitView.ts | 15 +- .../components/AlignmentConnections.tsx | 13 +- .../components/Breakends.tsx | 23 +- .../components/Translocations.tsx | 13 +- .../src/BreakpointSplitView/util.ts | 15 +- plugins/data-management/package.json | 2 +- .../facetedModel.ts | 6 +- plugins/dotplot-view/package.json | 2 +- plugins/grid-bookmark/package.json | 2 +- .../SpreadsheetView/components/CellData.tsx | 35 - .../components/ColumnFilterControls.tsx | 84 -- .../SpreadsheetView/components/ColumnMenu.tsx | 169 --- .../SpreadsheetView/components/DataRow.tsx | 126 --- .../SpreadsheetView/components/DataTable.tsx | 91 -- .../components/DataTableHeader.tsx | 122 -- .../components/GlobalFilterControls.tsx | 70 -- .../components/ImportWizard.tsx | 79 +- .../components/NumberEditor.tsx | 52 - .../components/RowCountMessage.tsx | 44 - .../SpreadsheetView/components/RowMenu.tsx | 65 -- .../components/SortIndicator.tsx | 36 - .../components/Spreadsheet.test.ts | 17 - .../components/Spreadsheet.tsx | 75 +- .../components/SpreadsheetView.tsx | 119 +- .../SpreadsheetView/components/StatusBar.tsx | 75 -- .../src/SpreadsheetView/components/util.ts | 35 +- .../importAdapters/BedImport.test.ts | 14 - .../importAdapters/BedImport.ts | 225 ++-- .../importAdapters/BedpeImport.ts | 97 ++ .../importAdapters/ImportUtils.test.ts | 25 - .../importAdapters/ImportUtils.ts | 152 --- .../importAdapters/STARFusionImport.test.ts | 27 - .../importAdapters/STARFusionImport.ts | 85 +- .../importAdapters/VcfImport.test.ts | 42 - .../importAdapters/VcfImport.ts | 211 ++-- .../importAdapters/components/LocString.tsx | 49 + .../SpreadsheetView/importAdapters/util.ts | 135 +++ .../src/SpreadsheetView/index.ts | 3 +- .../models/ColumnDataTypes/LocEnd.ts | 21 - .../models/ColumnDataTypes/LocRef.ts | 21 - .../models/ColumnDataTypes/LocStart.ts | 21 - .../models/ColumnDataTypes/LocString.tsx | 328 ------ .../MakeSpreadsheetColumnType.tsx | 38 - .../models/ColumnDataTypes/Number.tsx | 177 --- .../models/ColumnDataTypes/Text.tsx | 173 --- .../models/ColumnDataTypes/index.ts | 34 - .../SpreadsheetView/models/FilterControls.ts | 95 -- .../SpreadsheetView/models/ImportWizard.ts | 338 +++--- .../src/SpreadsheetView/models/Row.ts | 46 - .../src/SpreadsheetView/models/Spreadsheet.ts | 208 ---- .../SpreadsheetView/models/Spreadsheet.tsx | 138 +++ .../models/SpreadsheetView.test.ts | 2 +- .../SpreadsheetView/models/SpreadsheetView.ts | 346 ++---- .../SpreadsheetView/models/StaticRowSet.ts | 65 -- .../components/SvInspectorView.tsx | 61 +- .../sv-inspector/src/SvInspectorView/index.ts | 9 +- .../SvInspectorView/models/SvInspectorView.ts | 294 ++--- .../models/adhocFeatureUtils.js | 152 --- .../models/breakpointSplitViewFromTableRow.js | 84 -- .../models/breakpointSplitViewFromTableRow.ts | 88 ++ plugins/variants/package.json | 2 +- .../src/LinearVariantDisplay/configSchema.ts | 9 +- .../src/LinearVariantDisplay/model.ts | 3 +- .../VariantSampleGrid.tsx | 6 +- plugins/wiggle/package.json | 2 +- products/jbrowse-desktop/package.json | 2 +- products/jbrowse-react-app/package.json | 2 +- products/jbrowse-web/package.json | 2 +- yarn.lock | 1003 +++++++++-------- 76 files changed, 1866 insertions(+), 4383 deletions(-) delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/CellData.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnFilterControls.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnMenu.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/DataRow.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/DataTable.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/DataTableHeader.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/GlobalFilterControls.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/NumberEditor.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/RowCountMessage.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/RowMenu.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/SortIndicator.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.test.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/components/StatusBar.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.test.ts create mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedpeImport.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.test.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.test.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.test.ts create mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/components/LocString.tsx create mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/util.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocEnd.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocRef.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocStart.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocString.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/MakeSpreadsheetColumnType.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Number.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Text.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/index.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/FilterControls.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/Row.ts delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.ts create mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.tsx delete mode 100644 plugins/spreadsheet-view/src/SpreadsheetView/models/StaticRowSet.ts delete mode 100644 plugins/sv-inspector/src/SvInspectorView/models/adhocFeatureUtils.js delete mode 100644 plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.js create mode 100644 plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.ts diff --git a/package.json b/package.json index d7233c9727..834af1f866 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@emotion/styled": "^11.8.1", "@mui/material": "^5.10.17", "@mui/system": "^5.14.4", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "@node-oauth/express-oauth-server": "^4.0.0", "@oclif/test": "^3.2.1", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", diff --git a/packages/core/ReExports/modules.tsx b/packages/core/ReExports/modules.tsx index 9702590372..404627418e 100644 --- a/packages/core/ReExports/modules.tsx +++ b/packages/core/ReExports/modules.tsx @@ -364,11 +364,7 @@ const DataGridEntries: Record> = { default: module.GridPanelWrapper, })), ), - GridPreferencesPanel: lazy(() => - import('@mui/x-data-grid').then(module => ({ - default: module.GridPreferencesPanel, - })), - ), + GridRemoveIcon: lazy(() => import('@mui/x-data-grid').then(module => ({ default: module.GridRemoveIcon, diff --git a/packages/core/package.json b/packages/core/package.json index 9e9e594e6f..6ecaf4f879 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -58,7 +58,7 @@ }, "peerDependencies": { "@mui/material": "^5.0.0", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "mobx": "^6.0.0", "mobx-react": "^9.0.0", "mobx-state-tree": "^5.0.0", diff --git a/packages/core/ui/ResizeBar.tsx b/packages/core/ui/ResizeBar.tsx index b128d691f6..a978b41a6f 100644 --- a/packages/core/ui/ResizeBar.tsx +++ b/packages/core/ui/ResizeBar.tsx @@ -89,10 +89,8 @@ export default function ResizeBar({
{offsets.map((left, i) => ( { - setInitial([...widths]) - }} + key={`${left}-${i}`} + onMouseDown={() => setInitial([...widths])} left={i === offsets.length - 1 ? left - 3 : left} onDrag={(_: number, totalDistance: number, idx: number) => { const newWidths = [...widths] diff --git a/packages/core/ui/ResizeHandle.tsx b/packages/core/ui/ResizeHandle.tsx index 3584800e13..40e66cf4a6 100644 --- a/packages/core/ui/ResizeHandle.tsx +++ b/packages/core/ui/ResizeHandle.tsx @@ -12,11 +12,14 @@ const useStyles = makeStyles()({ }, flexbox_verticalHandle: { cursor: 'col-resize', - alignSelf: 'stretch', // the height: 100% is actually unable to function inside flexbox + alignSelf: 'stretch', + // uses alignSelf:stretch with flexbox as the height: 100% is actually + // unable to function inside flexbox }, flexbox_horizontalHandle: { cursor: 'row-resize', - alignSelf: 'stretch', // similar to above + alignSelf: 'stretch', + // similar to above }, }) diff --git a/packages/core/ui/index.ts b/packages/core/ui/index.ts index 88bb6ba9b4..2c8a3da44e 100644 --- a/packages/core/ui/index.ts +++ b/packages/core/ui/index.ts @@ -14,5 +14,6 @@ export { default as PrerenderedCanvas } from './PrerenderedCanvas' export { default as Tooltip } from './Tooltip' export { default as ReturnToImportFormDialog } from './ReturnToImportFormDialog' export { default as ResizeHandle } from './ResizeHandle' +export { default as ResizeBar } from './ResizeBar' export { default as SanitizedHTML } from './SanitizedHTML' export * from './Menu' diff --git a/plugins/bed/src/BigBedAdapter/BigBedAdapter.ts b/plugins/bed/src/BigBedAdapter/BigBedAdapter.ts index 4441d3be3a..88679d4ff5 100644 --- a/plugins/bed/src/BigBedAdapter/BigBedAdapter.ts +++ b/plugins/bed/src/BigBedAdapter/BigBedAdapter.ts @@ -5,11 +5,12 @@ import { BaseFeatureDataAdapter, BaseOptions, } from '@jbrowse/core/data_adapters/BaseAdapter' -import { Region } from '@jbrowse/core/util/types' import { openLocation } from '@jbrowse/core/util/io' import { ObservableCreate } from '@jbrowse/core/util/rxjs' -import SimpleFeature, { Feature } from '@jbrowse/core/util/simpleFeature' +import { SimpleFeature, Feature, Region } from '@jbrowse/core/util' import { map, mergeAll } from 'rxjs/operators' + +// locals import { ucscProcessedTranscript } from '../util' function isUCSC(f: Feature) { diff --git a/plugins/breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView.ts b/plugins/breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView.ts index 0988e3f57e..97425bbe1e 100644 --- a/plugins/breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView.ts +++ b/plugins/breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView.ts @@ -1,23 +1,20 @@ -import { getSession, Feature, Region } from '@jbrowse/core/util' +import { Feature, AbstractSessionModel } from '@jbrowse/core/util' import ViewType from '@jbrowse/core/pluggableElementTypes/ViewType' import { parseBreakend } from '@gmod/vcf' -import { IStateTreeNode } from 'mobx-state-tree' export default class BreakpointSplitViewType extends ViewType { - snapshotFromBreakendFeature( + async snapshotFromBreakendFeature( feature: Feature, - view: { displayedRegions: Region[] } & IStateTreeNode, + assemblyName: string, + session: AbstractSessionModel, ) { const alt = feature.get('ALT')?.[0] const bnd = alt ? parseBreakend(alt) : undefined const startPos = feature.get('start') let endPos const bpPerPx = 10 - - // TODO: Figure this out for multiple assembly names - const { assemblyName } = view.displayedRegions[0] - const { assemblyManager } = getSession(view) - const assembly = assemblyManager.get(assemblyName) + const { assemblyManager } = session + const assembly = await assemblyManager.waitForAssembly(assemblyName) if (!assembly) { throw new Error(`assembly ${assemblyName} not found`) diff --git a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/AlignmentConnections.tsx b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/AlignmentConnections.tsx index 787316acab..9997aa3c2e 100644 --- a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/AlignmentConnections.tsx +++ b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/AlignmentConnections.tsx @@ -81,20 +81,15 @@ const AlignmentConnections = observer(function ({ if (!showIntraviewLinks && level1 === level2) { return null } - const f1ref = assembly.getCanonicalRefName(f1.get('refName')) - const f2ref = assembly.getCanonicalRefName(f2.get('refName')) - - if (!f1ref || !f2ref) { - throw new Error(`unable to find ref for ${f1ref || f2ref}`) - } - + const f1ref = f1.get('refName') + const f2ref = f2.get('refName') const s1 = f1.get('strand') const s2 = f2.get('strand') const p1 = c1[s1 === -1 ? LEFT : RIGHT] const sn1 = s2 === -1 const p2 = hasPaired ? c2[sn1 ? LEFT : RIGHT] : c2[sn1 ? RIGHT : LEFT] - const x1 = getPxFromCoordinate(views[level1], f1ref, p1) - const x2 = getPxFromCoordinate(views[level2], f2ref, p2) + const x1 = getPxFromCoordinate(views[level1], f1ref, p1, assembly) + const x2 = getPxFromCoordinate(views[level2], f2ref, p2, assembly) const reversed1 = views[level1].pxToBp(x1).reversed const reversed2 = views[level2].pxToBp(x2).reversed const tracks = views.map(v => v.getTrack(trackId)) diff --git a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Breakends.tsx b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Breakends.tsx index 59096317cf..84ec3ba7d3 100644 --- a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Breakends.tsx +++ b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Breakends.tsx @@ -37,11 +37,7 @@ const Breakends = observer(function ({ const [mouseoverElt, setMouseoverElt] = useState() const snap = getSnapshot(model) useNextFrame(snap) - const assembly = assemblyManager.get(views[0].assemblyNames[0]) - - if (!assembly) { - return null - } + const asm = assemblyManager.get(views[0].assemblyNames[0]) let yoff = 0 if (ref.current) { @@ -49,7 +45,7 @@ const Breakends = observer(function ({ yoff = rect.top } - return ( + return asm ? ( - ) + ) : null }) export default Breakends diff --git a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Translocations.tsx b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Translocations.tsx index 0b6e46ec17..2c47f8b5ec 100644 --- a/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Translocations.tsx +++ b/plugins/breakpoint-split-view/src/BreakpointSplitView/components/Translocations.tsx @@ -50,10 +50,6 @@ const Translocations = observer(function ({ useNextFrame(snap) const assembly = assemblyManager.get(views[0].assemblyNames[0]) - if (!assembly) { - return null - } - let yOffset = 0 if (ref.current) { const rect = ref.current.getBoundingClientRect() @@ -64,10 +60,8 @@ const Translocations = observer(function ({ // just return null here note: would need to do processing of the INFO // CHR2/END and see which view could contain those coordinates to really do // it properly - if (views.length < 2) { - return null - } - return ( + + return !assembly || views.length < 2 ? null : ( ) { self.widths = args }, + })) + .actions(self => ({ afterAttach() { addDisposer( self, autorun(() => { - this.setVisible(Object.fromEntries(self.fields.map(c => [c, true]))) + self.setVisible(Object.fromEntries(self.fields.map(c => [c, true]))) }), ) addDisposer( self, autorun(() => { - this.setWidths({ + self.setWidths({ name: measureGridWidth( self.rows.map(r => r.name), diff --git a/plugins/dotplot-view/package.json b/plugins/dotplot-view/package.json index 58f6ca38ab..ad792fd619 100644 --- a/plugins/dotplot-view/package.json +++ b/plugins/dotplot-view/package.json @@ -38,7 +38,7 @@ "dependencies": { "@floating-ui/react": "^0.26.3", "@mui/icons-material": "^5.0.1", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "@types/file-saver": "^2.0.1", "@types/normalize-wheel": "^1.0.0", "clone": "^2.1.2", diff --git a/plugins/grid-bookmark/package.json b/plugins/grid-bookmark/package.json index 25a87afd58..182fc60f7d 100644 --- a/plugins/grid-bookmark/package.json +++ b/plugins/grid-bookmark/package.json @@ -46,7 +46,7 @@ "@jbrowse/plugin-config": "^2.0.0", "@jbrowse/plugin-linear-genome-view": "^2.0.0", "@mui/material": "^5.0.0", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "mobx": "^6.0.0", "mobx-react": "^9.0.0", "mobx-state-tree": "^5.0.0", diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/CellData.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/CellData.tsx deleted file mode 100644 index ae2b765989..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/CellData.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react' -import { observer } from 'mobx-react' -import { Instance } from 'mobx-state-tree' - -// locals -import SpreadsheetStateModel from '../models/Spreadsheet' - -type SpreadsheetModel = Instance - -const CellData = observer(function ({ - cell, - spreadsheetModel, - columnNumber, -}: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - cell: any - spreadsheetModel: SpreadsheetModel - columnNumber: number -}) { - const ret = spreadsheetModel.columns[columnNumber] - if (ret && 'dataType' in ret && ret.dataType.DataCellReactComponent) { - return ( - - ) - } - - return cell.text -}) - -export default CellData diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnFilterControls.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnFilterControls.tsx deleted file mode 100644 index e903bf7c94..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnFilterControls.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import React from 'react' -import { Grid, IconButton, Typography } from '@mui/material' -import { observer } from 'mobx-react' -import { getParent } from 'mobx-state-tree' -import { makeStyles } from 'tss-react/mui' - -// icons -import FilterIcon from '@mui/icons-material/FilterList' -import CloseIcon from '@mui/icons-material/Close' - -const useStyles = makeStyles()(theme => ({ - columnName: { - verticalAlign: 'middle', - paddingRight: '0.3em', - }, - columnFilter: { - overflow: 'hidden', - whiteSpace: 'nowrap', - boxSizing: 'border-box', - width: '100%', - position: 'relative', - }, - filterIcon: { - position: 'relative', - top: '12px', - }, - filterIconBg: { - background: theme.palette.tertiary.main, - color: 'white', - padding: theme.spacing(1.5), - }, -})) - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function FilterOperations({ filterModel }: { filterModel: any }) { - if (filterModel) { - return - } - return null -} - -const ColumnFilterControls = observer(function ({ - viewModel, - filterModel, - columnNumber, - height, -}: // eslint-disable-next-line @typescript-eslint/no-explicit-any -any) { - const { classes } = useStyles() - - const columnDefinition = viewModel.spreadsheet.columns[columnNumber] - if (!columnDefinition) { - throw new Error('no column definition! filters are probably out of date') - } - return ( - - - - - - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getParent(filterModel, 2).removeColumnFilter(filterModel) - } - title="remove filter" - > - - - - {columnDefinition.name} - {' '} - - - - ) -}) - -export default ColumnFilterControls diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnMenu.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnMenu.tsx deleted file mode 100644 index 5b4bd51b59..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/ColumnMenu.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import React from 'react' -import { observer } from 'mobx-react' -import { iterMap } from '@jbrowse/core/util' -import { Menu } from '@jbrowse/core/ui' -import { MenuItem } from '@jbrowse/core/ui/Menu' -import { SpreadsheetModel } from '../models/Spreadsheet' -import { SpreadsheetViewModel } from '../models/SpreadsheetView' - -// icons -import CheckIcon from '@mui/icons-material/Check' -import FilterListIcon from '@mui/icons-material/FilterList' -import PermDataSettingIcon from '@mui/icons-material/PermDataSetting' -import SortIcon from '@mui/icons-material/Sort' - -const ColumnMenu = observer(function ({ - viewModel, - spreadsheetModel, - currentColumnMenu, - setColumnMenu, -}: { - spreadsheetModel: SpreadsheetModel - viewModel: SpreadsheetViewModel - currentColumnMenu?: { colNumber: number; anchorEl: HTMLElement } - setColumnMenu: (arg?: { anchorEl: HTMLElement; colNumber: number }) => void -}) { - const columnMenuClose = () => setColumnMenu(undefined) - const columnNumber = currentColumnMenu?.colNumber || 0 - const sortMenuClick = (descending: boolean) => { - spreadsheetModel.setSortColumns([ - { - columnNumber, - descending, - }, - ]) - } - - const { dataTypeChoices } = spreadsheetModel - - // make a Map of categoryName => [entry...] - type Record = (typeof dataTypeChoices)[0] - interface RecordGroup { - isCategory: boolean - subMenuItems: Record[] - } - const dataTypeTopLevelMenu = new Map() - dataTypeChoices.forEach(dataTypeRecord => { - const { displayName, categoryName } = dataTypeRecord - if (categoryName) { - let entry = dataTypeTopLevelMenu.get(categoryName) as RecordGroup - if (!entry) { - entry = { - isCategory: true, - subMenuItems: [], - } - dataTypeTopLevelMenu.set(categoryName, entry) - } - entry.subMenuItems.push(dataTypeRecord) - } else { - dataTypeTopLevelMenu.set(displayName, dataTypeRecord) - } - }) - - const { columns, sortColumns } = spreadsheetModel - const dataType = currentColumnMenu && columns[columnNumber].dataType - const dataTypeName = dataType?.type || '' - const dataTypeDisplayName = - (currentColumnMenu && columns[columnNumber].dataType.displayName) || '' - - const isSortingAscending = - !!currentColumnMenu && - sortColumns.some( - c => c.columnNumber === currentColumnMenu.colNumber && !c.descending, - ) - const isSortingDescending = - !!currentColumnMenu && - sortColumns.some( - c => c.columnNumber === currentColumnMenu.colNumber && c.descending, - ) - - const menuItems = [ - // top-level column menu - { - label: 'Sort ascending', - icon: SortIcon, - type: 'radio', - checked: isSortingAscending, - onClick: () => sortMenuClick(false), - }, - { - label: 'Sort descending', - icon: SortIcon, - type: 'radio', - checked: isSortingDescending, - onClick: () => sortMenuClick(true), - }, - { - label: 'No sort', - icon: SortIcon, - type: 'radio', - checked: !isSortingDescending && !isSortingAscending, - onClick: () => spreadsheetModel.setSortColumns([]), - }, - // data type menu - { - label: `Type: ${dataTypeDisplayName}`, - icon: PermDataSettingIcon, - subMenu: iterMap( - dataTypeTopLevelMenu.entries(), - ([displayName, record]) => { - if ('typeName' in record && record.typeName) { - const { typeName } = record - return { - label: displayName || typeName, - icon: dataTypeName === typeName ? CheckIcon : undefined, - onClick: () => - spreadsheetModel.setColumnType(columnNumber, typeName), - } - } else if ('subMenuItems' in record && record.subMenuItems) { - const { subMenuItems } = record - return { - label: displayName, - icon: subMenuItems.some(i => i.typeName === dataTypeName) - ? CheckIcon - : undefined, - subMenu: subMenuItems.map(({ typeName, displayName }) => ({ - label: displayName, - icon: typeName === dataTypeName ? CheckIcon : undefined, - onClick: () => - spreadsheetModel.setColumnType(columnNumber, typeName), - })), - } - } else { - return null - } - }, - ).filter(Boolean), - }, - ] as MenuItem[] - - // don't display the filter item if this data type doesn't have filtering - // implemented - if (dataType?.hasFilter) { - menuItems.push({ - label: 'Create filter', - icon: FilterListIcon, - onClick: () => - viewModel.filterControls.addBlankColumnFilter(columnNumber), - }) - } - - return ( - { - callback() - columnMenuClose() - }} - onClose={columnMenuClose} - menuItems={menuItems} - anchorOrigin={{ - vertical: 'bottom', - horizontal: 'right', - }} - /> - ) -}) - -export default ColumnMenu diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataRow.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/DataRow.tsx deleted file mode 100644 index 5ea3c1703b..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataRow.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React from 'react' -import { Checkbox, IconButton, FormControlLabel } from '@mui/material' -import { observer } from 'mobx-react' -import { Instance } from 'mobx-state-tree' -import { indigo } from '@mui/material/colors' -import { makeStyles } from 'tss-react/mui' - -// icons -import ArrowDropDown from '@mui/icons-material/ArrowDropDown' - -// locals -import SpreadsheetStateModel from '../models/Spreadsheet' -import RowStateModel from '../models/Row' -import CellData from './CellData' - -type SpreadsheetModel = Instance -type RowModel = Instance - -const useStyles = makeStyles()(theme => ({ - rowNumCell: { - textAlign: 'left', - border: `1px solid ${theme.palette.action.disabledBackground}`, - position: 'relative', - padding: '0 2px 0 0', - whiteSpace: 'nowrap', - userSelect: 'none', - }, - rowNumber: { - fontWeight: 'normal', - display: 'inline-block', - flex: 'none', - paddingRight: '20px', - margin: 0, - whiteSpace: 'nowrap', - }, - rowMenuButton: { - padding: 0, - margin: 0, - position: 'absolute', - right: 0, - display: 'inline-block', - whiteSpace: 'nowrap', - flex: 'none', - }, - rowMenuButtonIcon: {}, - rowSelector: { - position: 'relative', - top: '-2px', - margin: 0, - padding: '0 0.2rem', - }, - - dataRowSelected: { - background: indigo[100], - '& th': { - background: indigo[100], - }, - }, -})) - -const DataRow = observer(function ({ - rowModel, - rowNumber, - spreadsheetModel, -}: { - rowModel: RowModel - rowNumber: string - spreadsheetModel: SpreadsheetModel -}) { - const { classes } = useStyles() - const { hideRowSelection, columnDisplayOrder } = spreadsheetModel - let rowClass = '' - if (rowModel.isSelected) { - rowClass += `${classes.dataRowSelected}` - } - - function labelClick(evt: React.MouseEvent) { - rowModel.toggleSelect() - evt.stopPropagation() - evt.preventDefault() - } - - return ( - - - {hideRowSelection ? ( - - } - label={rowModel.id} - /> - ) : null} - { - spreadsheetModel.setRowMenuPosition({ - anchorEl: event.currentTarget, - rowNumber, - }) - event.preventDefault() - event.stopPropagation() - }} - > - - - - {columnDisplayOrder.map(colNumber => ( - - - - ))} - - ) -}) - -export default DataRow diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTable.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTable.tsx deleted file mode 100644 index 34c083cbce..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTable.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react' -import { observer } from 'mobx-react' -import { getParent, Instance } from 'mobx-state-tree' -import { makeStyles } from 'tss-react/mui' - -// locals -import SpreadsheetStateModel from '../models/Spreadsheet' -import RowStateModel from '../models/Row' -import RowMenu from './RowMenu' -import DataRow from './DataRow' -import DataTableHeader from './DataTableHeader' - -type SpreadsheetModel = Instance -type RowModel = Instance - -const useStyles = makeStyles()(theme => ({ - dataTable: { - borderCollapse: 'collapse', - '& td': { - border: `1px solid ${theme.palette.action.disabledBackground}`, - padding: '0.2rem', - maxWidth: '50em', - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - }, - - emptyMessage: { - captionSide: 'bottom', - }, -})) - -const DataTableBody = observer(function ({ - rows, - spreadsheetModel, - page, - rowsPerPage, -}: { - rows: RowModel[] - spreadsheetModel: SpreadsheetModel - page: number - rowsPerPage: number -}) { - return ( - - {rows.slice(rowsPerPage * page, rowsPerPage * (page + 1)).map(row => ( - - ))} - - ) -}) - -const DataTable = observer(function ({ - model, - page, - rowsPerPage, -}: { - model: SpreadsheetModel - page: number - rowsPerPage: number -}) { - const { rowSet } = model - const { classes } = useStyles() - const rows = rowSet.sortedFilteredRows - return ( - <> - - - - - {!rows.length ? ( - - ) : null} -
- {rowSet.count ? 'no rows match criteria' : 'no rows present'} -
- - ) -}) - -export default DataTable diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTableHeader.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTableHeader.tsx deleted file mode 100644 index a0aca2f6e1..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/DataTableHeader.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useState } from 'react' -import { IconButton, Tooltip } from '@mui/material' -import { observer } from 'mobx-react' -import { getParent } from 'mobx-state-tree' -import { makeStyles } from 'tss-react/mui' - -// icons -import CropFreeIcon from '@mui/icons-material/CropFree' -import ArrowDropDown from '@mui/icons-material/ArrowDropDown' - -// locals -import { SpreadsheetModel } from '../models/Spreadsheet' -import ColumnMenu from './ColumnMenu' -import SortIndicator from './SortIndicator' -import { numToColName } from './util' - -interface ColMenu { - colNumber: number - anchorEl: HTMLElement -} - -const useStyles = makeStyles()(theme => ({ - columnHead: { - fontWeight: 'normal', - background: theme.palette.mode === 'dark' ? '#333' : '#eee', - position: 'sticky', - top: 0, - zIndex: 2, - whiteSpace: 'nowrap', - }, - - columnButtonContainer: { - display: 'none', - position: 'absolute', - right: 0, - top: 0, - background: theme.palette.background.paper, - height: '100%', - }, - - topLeftCorner: { - background: theme.palette.mode === 'dark' ? '#333' : '#eee', - zIndex: 2, - position: 'sticky', - top: 0, - minWidth: theme.spacing(2), - textAlign: 'left', - }, -})) - -const DataTableHeader = observer(function ({ - model, -}: { - model: SpreadsheetModel -}) { - const { classes } = useStyles() - const { columnDisplayOrder, columns, hasColumnNames, rowSet } = model - const [currentColumnMenu, setColumnMenu] = useState() - const [currentHoveredColumn, setHoveredColumn] = useState() - - return ( - <> - - - - - - model.unselectAll()} - disabled={!rowSet.selectedCount} - > - - - - - - {columnDisplayOrder.map(colNumber => ( - setHoveredColumn(colNumber)} - onMouseOut={() => setHoveredColumn(undefined)} - > - - {(hasColumnNames && columns[colNumber]?.name) || - numToColName(colNumber)} -
- { - setColumnMenu({ - colNumber, - anchorEl: evt.currentTarget, - }) - }} - > - - -
- - ))} - - - - - ) -}) - -export default DataTableHeader diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/GlobalFilterControls.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/GlobalFilterControls.tsx deleted file mode 100644 index 1dc44e13fa..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/GlobalFilterControls.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { useState, useEffect } from 'react' - -import { IconButton, InputAdornment, TextField } from '@mui/material' -import ClearIcon from '@mui/icons-material/Clear' -import FilterIcon from '@mui/icons-material/FilterList' - -import { observer } from 'mobx-react' -import { makeStyles } from 'tss-react/mui' -import { useDebounce } from '@jbrowse/core/util' - -const useStyles = makeStyles()({ - textFilterControlEndAdornment: { - marginRight: '-18px', - }, -}) - -const TextFilter = observer(function ({ - textFilter, -}: { - textFilter: { stringToFind: string; setString: (arg: string) => void } -}) { - const { classes } = useStyles() - // this paragraph is silliness to debounce the text filter input - const [textFilterValue, setTextFilterValue] = useState( - textFilter.stringToFind, - ) - const debouncedTextFilter = useDebounce(textFilterValue, 500) - useEffect(() => { - textFilter.setString(debouncedTextFilter) - }, [debouncedTextFilter, textFilter]) - - return ( -
- setTextFilterValue(evt.target.value)} - variant="outlined" - InputProps={{ - startAdornment: ( - - - - ), - endAdornment: ( - - setTextFilterValue('')} - > - - - - ), - }} - /> -
- ) -}) - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const GlobalFilterControls = observer(({ model }: { model: any }) => { - const textFilter = model.filterControls.rowFullText - return -}) - -export default GlobalFilterControls diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/ImportWizard.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/ImportWizard.tsx index e53d8a230d..dd050440b6 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/ImportWizard.tsx +++ b/plugins/spreadsheet-view/src/SpreadsheetView/components/ImportWizard.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react' import { Button, - Checkbox, FormControl, FormGroup, FormLabel, @@ -11,13 +10,17 @@ import { } from '@mui/material' import { observer } from 'mobx-react' import { getRoot } from 'mobx-state-tree' +import { makeStyles } from 'tss-react/mui' import { AbstractRootModel, getSession } from '@jbrowse/core/util' -import { FileSelector, ErrorMessage, AssemblySelector } from '@jbrowse/core/ui' +import { + FileSelector, + ErrorMessage, + AssemblySelector, + LoadingEllipses, +} from '@jbrowse/core/ui' // locals import { ImportWizardModel } from '../models/ImportWizard' -import NumberEditor from './NumberEditor' -import { makeStyles } from 'tss-react/mui' const useStyles = makeStyles()({ container: { @@ -31,23 +34,16 @@ const ImportWizard = observer(({ model }: { model: ImportWizardModel }) => { const session = getSession(model) const { classes } = useStyles() const { assemblyNames, assemblyManager } = session - const { - fileType, - canCancel, - fileSource, - isReadyToOpen, - fileTypes, - hasColumnNameLine, - error, - } = model + const { fileType, fileSource, fileTypes, error, loading } = model const [selected, setSelected] = useState(assemblyNames[0]) const err = assemblyManager.get(selected)?.error || error const showRowControls = fileType === 'CSV' || fileType === 'TSV' - const rootModel = getRoot(model) + const rootModel = getRoot(model) return (
{err ? : null} + {loading ? : null}
Tabular file @@ -55,7 +51,7 @@ const ImportWizard = observer(({ model }: { model: ImportWizardModel }) => { model.setFileSource(arg)} - rootModel={rootModel as AbstractRootModel} + rootModel={rootModel} /> @@ -81,23 +77,6 @@ const ImportWizard = observer(({ model }: { model: ImportWizardModel }) => {
Column Names - model.toggleHasColumnNameLine()} - /> - } - /> -
) : null} @@ -108,30 +87,18 @@ const ImportWizard = observer(({ model }: { model: ImportWizardModel }) => { onChange={val => setSelected(val)} />
-
- {canCancel ? ( - - ) : null}{' '} - -
+
) }) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/NumberEditor.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/NumberEditor.tsx deleted file mode 100644 index 73cab60dbf..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/NumberEditor.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { TextField } from '@mui/material' -import { makeStyles } from 'tss-react/mui' -import { observer } from 'mobx-react' - -// locals -import { ImportWizardModel } from '../models/ImportWizard' - -const useStyles = makeStyles()({ - textField: { - width: '2rem', - verticalAlign: 'baseline', - }, -}) - -const NumberEditor = observer(function ({ - model, - disabled, - modelPropName, - modelSetterName, -}: { - model: ImportWizardModel - disabled: boolean - modelPropName: string - modelSetterName: string -}) { - // @ts-expect-error - const [val, setVal] = useState(model[modelPropName]) - const { classes } = useStyles() - useEffect(() => { - const num = Number.parseInt(val, 10) - if (!Number.isNaN(num)) { - if (num > 0) { - // @ts-expect-error - model[modelSetterName](num) - } else { - setVal(1) - } - } - }, [model, modelSetterName, val]) - return ( - setVal(evt.target.value)} - className={classes.textField} - /> - ) -}) - -export default NumberEditor diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/RowCountMessage.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/RowCountMessage.tsx deleted file mode 100644 index 30b33e013c..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/RowCountMessage.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react' -import { observer } from 'mobx-react' -import { Instance } from 'mobx-state-tree' - -// locals -import SpreadsheetStateModel from '../models/Spreadsheet' - -type SpreadsheetModel = Instance - -const RowCountMessage = observer(function ({ - spreadsheet, -}: { - spreadsheet: SpreadsheetModel -}) { - if (spreadsheet.rowSet.isLoaded) { - const { - passingFiltersCount, - count, - selectedCount, - selectedAndPassingFiltersCount, - } = spreadsheet.rowSet - - let rowMessage - if (passingFiltersCount !== count) { - rowMessage = `${spreadsheet.rowSet.passingFiltersCount} rows of ${spreadsheet.rowSet.count} total` - if (selectedCount) { - rowMessage += `, ${selectedAndPassingFiltersCount} selected` - const selectedAndNotPassingFiltersCount = - selectedCount - selectedAndPassingFiltersCount - if (selectedAndNotPassingFiltersCount) { - rowMessage += ` (${selectedAndNotPassingFiltersCount} selected rows do not pass filters)` - } - } - } else { - rowMessage = `${spreadsheet.rowSet.count} rows` - if (selectedCount) { - rowMessage += `, ${selectedCount} selected` - } - } - return <>{rowMessage} - } - return null -}) -export default RowCountMessage diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/RowMenu.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/RowMenu.tsx deleted file mode 100644 index 928605b455..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/RowMenu.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react' -import { observer } from 'mobx-react' -import { Menu, MenuItem } from '@jbrowse/core/ui' -import { Instance } from 'mobx-state-tree' - -// locals -import SpreadsheetModel from '../models/Spreadsheet' -import ViewModel from '../models/SpreadsheetView' - -const RowMenu = observer(function ({ - viewModel, - spreadsheetModel, -}: { - viewModel: Instance - spreadsheetModel: Instance -}) { - const currentRowMenu = spreadsheetModel.rowMenuPosition - const { setRowMenuPosition } = spreadsheetModel - - const rowMenuClose = () => { - setRowMenuPosition(null) - } - - const rowNumber = spreadsheetModel.rowMenuPosition?.rowNumber - if (rowNumber === undefined) { - return null - } - - const row = spreadsheetModel.rowSet.rows[+rowNumber - 1] - - function handleMenuItemClick(_event: unknown, callback: Function) { - callback(viewModel, spreadsheetModel, rowNumber, row) - rowMenuClose() - } - - // got through and evaluate all the `disabled` callbacks of the menu items - const menuItems: MenuItem[] = viewModel.rowMenuItems.map(item => { - if (typeof item.disabled === 'function') { - const disabled = item.disabled( - viewModel, - spreadsheetModel, - +rowNumber, - row, - ) - return { ...item, disabled } - } - return item - }) - - return ( - - ) -}) - -export default RowMenu diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/SortIndicator.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/SortIndicator.tsx deleted file mode 100644 index 95259aca1b..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/SortIndicator.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react' -import { makeStyles } from 'tss-react/mui' - -// icons -import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp' -import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown' -import { SpreadsheetModel } from '../models/Spreadsheet' - -const useStyles = makeStyles()({ - sortIndicator: { - position: 'relative', - top: '0.2rem', - fontSize: '1rem', - }, -}) - -export default function SortIndicator({ - model, - columnNumber, -}: { - model: SpreadsheetModel - columnNumber: number -}) { - const { classes } = useStyles() - const sortSpec = model.sortColumns.find(c => c.columnNumber === columnNumber) - - if (sortSpec) { - const { descending } = sortSpec - return descending ? ( - - ) : ( - - ) - } - return null -} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.test.ts deleted file mode 100644 index 567f09aa73..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { numToColName } from './util' - -describe('num to col name', () => { - const cases = [ - [10, 'K'], - [26, 'AA'], - [0, 'A'], - [25, 'Z'], - [27 * 26 - 1, 'ZZ'], - ] as const - - cases.forEach(([input, output]) => { - test(`${input} -> ${output}`, () => { - expect(numToColName(input)).toBe(output) - }) - }) -}) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.tsx index 97eb2490d3..33e612cc4c 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.tsx +++ b/plugins/spreadsheet-view/src/SpreadsheetView/components/Spreadsheet.tsx @@ -1,14 +1,12 @@ -import React from 'react' +import React, { useState } from 'react' import { observer } from 'mobx-react' -import { Instance } from 'mobx-state-tree' import { makeStyles } from 'tss-react/mui' +import { DataGrid, GridToolbar } from '@mui/x-data-grid' +import { ErrorMessage, LoadingEllipses, ResizeBar } from '@jbrowse/core/ui' +import { useResizeBar } from '@jbrowse/core/ui/useResizeBar' // locals -import SpreadsheetStateModel from '../models/Spreadsheet' -import { LoadingEllipses } from '@jbrowse/core/ui' -import DataTable from './DataTable' - -type SpreadsheetModel = Instance +import { SpreadsheetModel } from '../models/Spreadsheet' const useStyles = makeStyles()(theme => ({ root: { @@ -19,23 +17,56 @@ const useStyles = makeStyles()(theme => ({ }, })) -const Spreadsheet = observer(function ({ - model, - height, - page, - rowsPerPage, -}: { - model: SpreadsheetModel - height: number - page: number - rowsPerPage: number -}) { - const { classes } = useStyles() +const DataTable = observer(function ({ model }: { model: SpreadsheetModel }) { + const { ref, scrollLeft } = useResizeBar() + const { data, visible, columns, widths } = model + const { rows } = data! + const [error, setError] = useState() + + return ( +
+ {error ? ( + setError(undefined)} /> + ) : undefined} + f ?? 100)} + setWidths={newWidths => + model.setWidths( + Object.fromEntries( + Object.entries(widths).map((entry, idx) => [ + entry[0], + newWidths[idx], + ]), + ), + ) + } + scrollLeft={scrollLeft} + /> + model.setVisible(n)} + rowHeight={25} + hideFooter={rows.length < 100} + slots={{ toolbar: GridToolbar }} + slotProps={{ + toolbar: { + showQuickFilter: true, + }, + }} + rows={rows} + columns={columns!} + /> +
+ ) +}) +const Spreadsheet = observer(function ({ model }: { model: SpreadsheetModel }) { + const { classes } = useStyles() return ( -
- {model?.rowSet?.isLoaded && model.initialized ? ( - +
+ {model?.data ? ( + ) : ( )} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/SpreadsheetView.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/SpreadsheetView.tsx index 1a6c8f0b19..663818bb1e 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/SpreadsheetView.tsx +++ b/plugins/spreadsheet-view/src/SpreadsheetView/components/SpreadsheetView.tsx @@ -1,39 +1,22 @@ -import React, { useState } from 'react' -import { Grid } from '@mui/material' +import React, { Suspense, lazy, useState } from 'react' import { makeStyles } from 'tss-react/mui' import { observer } from 'mobx-react' import { ResizeHandle } from '@jbrowse/core/ui' // locals -import ImportWizard from './ImportWizard' import Spreadsheet from './Spreadsheet' -import GlobalFilterControls from './GlobalFilterControls' -import ColumnFilterControls from './ColumnFilterControls' import { SpreadsheetViewModel } from '../models/SpreadsheetView' -import StatusBar from './StatusBar' -const headerHeight = 52 -const colFilterHeight = 46 -const statusBarHeight = 40 +const ImportWizard = lazy(() => import('./ImportWizard')) const useStyles = makeStyles()(theme => ({ - header: { - overflow: 'hidden', - whiteSpace: 'nowrap', - boxSizing: 'border-box', - height: headerHeight, - paddingLeft: theme.spacing(1), - }, contentArea: { overflow: 'auto', }, resizeHandle: { - height: 3, - position: 'absolute', - bottom: 0, - left: 0, - background: theme.palette.action.disabled, + height: 5, boxSizing: 'border-box', + background: theme.palette.action.disabled, borderTop: '1px solid #fafafa', }, })) @@ -43,83 +26,37 @@ const SpreadsheetView = observer(function ({ }: { model: SpreadsheetViewModel }) { + const [initialHeight, setInitialHeight] = useState(0) const { classes } = useStyles() - const { - spreadsheet, - filterControls, - hideFilterControls, - hideVerticalResizeHandle, - mode, - height, - } = model - const [page, setPage] = useState(0) - const [rowsPerPage, setRowsPerPage] = useState(100) - + const { spreadsheet, hideVerticalResizeHandle, height } = model return ( -
- {mode !== 'display' || hideFilterControls ? null : ( - <> - - - - - - {filterControls.columnFilters.map((f, i) => ( - - ))} - - )} - - {mode === 'import' ? ( - - ) : ( -
-
- {spreadsheet ? ( - - ) : null} -
-
- )} - {spreadsheet ? ( - - ) : null} + <> +
+ +
{hideVerticalResizeHandle ? null : ( setInitialHeight(height)} + onDrag={(_, dist) => model.setHeight(initialHeight - dist)} className={classes.resizeHandle} /> )} -
+ + ) +}) + +const SpreadsheetContainer = observer(function ({ + model, +}: { + model: SpreadsheetViewModel +}) { + return !model.initialized ? ( + + + + ) : ( + ) }) -export default SpreadsheetView +export default SpreadsheetContainer diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/StatusBar.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/components/StatusBar.tsx deleted file mode 100644 index d24b5b1b4e..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/StatusBar.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -import { FormGroup, TablePagination } from '@mui/material' -import { makeStyles } from 'tss-react/mui' - -// locals -import RowCountMessage from './RowCountMessage' -import { SpreadsheetModel } from '../models/Spreadsheet' -import { observer } from 'mobx-react' - -const statusBarHeight = 40 - -const useStyles = makeStyles()(theme => ({ - statusBar: { - height: statusBarHeight, - boxSizing: 'border-box', - borderTop: '1px outset #b1b1b1', - paddingLeft: theme.spacing(1), - }, - verticallyCenter: { - display: 'flex', - justifyContent: 'center', - flexDirection: 'column', - }, - spacer: { - flexGrow: 1, - }, -})) - -const StatusBar = observer(function StatusBar({ - page, - rowsPerPage, - setPage, - setRowsPerPage, - spreadsheet, - mode, -}: { - page: number - mode: string - spreadsheet: SpreadsheetModel - rowsPerPage: number - setPage: (arg: number) => void - setRowsPerPage: (arg: number) => void -}) { - const { classes } = useStyles() - return ( -
- {spreadsheet ? ( - -
- -
-
- setPage(newPage)} - onRowsPerPageChange={event => { - setRowsPerPage(+event.target.value) - setPage(0) - }} - /> -
- - ) : null} -
- ) -}) - -export default StatusBar diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/components/util.ts b/plugins/spreadsheet-view/src/SpreadsheetView/components/util.ts index fc1bafa1a4..a79e0cb8b4 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/components/util.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/components/util.ts @@ -1,16 +1,25 @@ -function letterFor(n: number) { - return String.fromCharCode(n + 65) -} +import { getSession } from '@jbrowse/core/util' +import { getParent } from 'mobx-state-tree' +import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' -export function numToColName(num: number) { - if (num >= 0) { - if (num < 26) { - return letterFor(num) - } - if (num < 27 * 26) { - return letterFor(Math.floor(num / 26 - 1)) + letterFor(num % 26) - } - } +type LGV = LinearGenomeViewModel +type MaybeLGV = LinearGenomeViewModel | undefined + +// locals +import { SpreadsheetModel } from '../models/Spreadsheet' - throw new RangeError('column number out of range') +export function locationLinkClick( + spreadsheet: SpreadsheetModel, + locString: string, +) { + const session = getSession(spreadsheet) + const { assemblyName } = spreadsheet + const { id } = getParent<{ id: string }>(spreadsheet) + + const newViewId = `${id}_${assemblyName}` + let view = session.views.find(v => v.id === newViewId) as MaybeLGV + if (!view) { + view = session.addView('LinearGenomeView', { id: newViewId }) as LGV + } + return view.navToLocString(locString, assemblyName) } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.test.ts deleted file mode 100644 index f20f9126be..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { promises as fsPromises } from 'fs' -import path from 'path' - -import { removeBedHeaders } from './BedImport' - -test('bed header trimming', async () => { - const filepath = path.join(__dirname, '..', 'test_data', 'foo.bed') - const buf = await fsPromises.readFile(filepath) - expect(buf[0]).toEqual(98) - expect(buf[1]).toEqual(114) - const trimmedBuffer = removeBedHeaders(buf) - expect(trimmedBuffer[0]).toEqual(99) - expect(trimmedBuffer.length).toBe(275) -}) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.ts index 07c4a0a70a..2a7871dd15 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedImport.ts @@ -1,155 +1,94 @@ -import { ParseOptions, parseTsvBuffer } from './ImportUtils' +import { assembleLocString } from '@jbrowse/core/util' +import { parseStrand } from './util' +import LocString from './components/LocString' -const browserBytes = 'browser '.split('').map(c => c.charCodeAt(0)) -const trackBytes = 'track '.split('').map(c => c.charCodeAt(0)) -const commentBytes = '#'.split('').map(c => c.charCodeAt(0)) +const MAX_SET_SCAN = 100 +const MAX_BED_COL = 6 -function bytesAreFoundAt(position: number, buffer: Buffer, bytes: number[]) { +export async function parseBedBuffer(buffer: Buffer) { + const data = new TextDecoder('utf8', { fatal: true }).decode(buffer) + const lines = data.split(/\n|\r\n|\r/).filter(f => !!f) + const headerLines = [] let i = 0 - for (; i < bytes.length; i += 1) { - if (buffer[position + i] !== bytes[i]) { - return false - } + for ( + ; + i < lines.length && + (lines[i].startsWith('#') || + lines[i].startsWith('browser') || + lines[i].startsWith('track')); + i++ + ) { + headerLines.push(lines[i]) } - return true -} -export function removeBedHeaders(buffer: Buffer) { - // slice off the first lines of the buffer if it starts with one or more - // header lines - let i = 0 - for (; i < buffer.length; i += 1) { - if ( - bytesAreFoundAt(i, buffer, browserBytes) || - bytesAreFoundAt(i, buffer, trackBytes) || - bytesAreFoundAt(i, buffer, commentBytes) - ) { - // consume up to the next newline - do { - i += 1 - } while (buffer[i] !== 10) - } else { - // end of headers, return - break - } + const header = headerLines.join('\n') + const lastHeaderLine = headerLines.at(-1) + let names = [] as string[] + if (lastHeaderLine?.startsWith('#')) { + names = lastHeaderLine + .slice(1) + .split('\t') + .map(f => f.trim()) } - if (i) { - return buffer.slice(i) - } - return buffer -} -export async function parseBedBuffer(buffer: Buffer, options: ParseOptions) { - const b = removeBedHeaders(buffer) - const data = await parseTsvBuffer(b) - const bedColumns = [ - { name: 'chrom', dataType: { type: 'LocRef' } }, - { name: 'chromStart', dataType: { type: 'LocStart' } }, - { name: 'chromEnd', dataType: { type: 'LocEnd' } }, - { name: 'name', dataType: { type: 'Text' } }, - { name: 'score', dataType: { type: 'Number' } }, - { name: 'strand', dataType: { type: 'Text' } }, - ] - data.columns.forEach((col, colNumber) => { - const bedColumn = bedColumns[colNumber] - if (bedColumn) { - col.name = bedColumn.name - col.dataType = bedColumn.dataType - } - }) - data.hasColumnNames = true - data.assemblyName = options.selectedAssemblyName + const columns = new Set([ + 'refName', + 'start', + 'end', + 'mate.refName', + 'mate.start', + 'mate.end', + 'name', + 'score', + 'strand', + 'mate.strand', + ...names.slice(9), + ]) + const rows = [] + for (let j = 0; i < lines.length; i++, j++) { + const line = lines[i] + const l = line.split('\t') + const refName = l[0] + const start = +l[1] + const end = +l[2] + const name = l[3] + const score = +l[4] + const strand = parseStrand(l[5]) - data.columnDisplayOrder.push(data.columnDisplayOrder.length) - data.columns.unshift({ - name: 'Location', - dataType: { type: 'LocString' }, - isDerived: true, - derivationFunctionText: `jexl:{text:row.cells[0].text+':'+row.cells[1].text+'..'+row.cells[2].text,\n - extendedData: {refName: row.cells.ref.text, start: parseInt(row.cells.start.text,10), end: parseInt(row.cells.end.text,10)}}`, - }) - return data -} - -export async function parseBedPEBuffer(buffer: Buffer, options: ParseOptions) { - const b = removeBedHeaders(buffer) - const data = await parseTsvBuffer(b) - interface BedColumn { - name: string - dataType: { - type: string - } - featureField: string[] - } - const bedColumns: BedColumn[] = [ - { name: 'chrom1', dataType: { type: 'Text' }, featureField: ['refName'] }, - { name: 'start1', dataType: { type: 'Number' }, featureField: ['start'] }, - { name: 'end1', dataType: { type: 'Number' }, featureField: ['end'] }, - { - name: 'chrom2', - dataType: { type: 'Text' }, - featureField: ['mate', 'refName'], - }, - { - name: 'start2', - dataType: { type: 'Number' }, - featureField: ['mate', 'start'], - }, - { - name: 'end2', - dataType: { type: 'Number' }, - featureField: ['mate', 'end'], - }, - { name: 'name', dataType: { type: 'Text' }, featureField: ['name'] }, - { name: 'score', dataType: { type: 'Number' }, featureField: ['score'] }, - { name: 'strand1', dataType: { type: 'Text' }, featureField: ['strand'] }, - { - name: 'strand2', - dataType: { type: 'Text' }, - featureField: ['mate', 'strand'], - }, - ] - data.columns.forEach((col, colNumber) => { - const bedColumn = bedColumns[colNumber] - if (bedColumn) { - col.name = bedColumn.name - col.dataType = bedColumn.dataType - } - }) - data.hasColumnNames = true + const extra = l.slice(MAX_BED_COL) + const rest = Object.fromEntries( + extra.map((e, idx) => { + const key = names[idx + MAX_BED_COL] || `extra_${idx}` - // decorate each row with a feature object in its extendedData - data.rowSet.rows.forEach((row, rowNumber) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const featureData: Record = {} - row.cells.forEach(({ text }, columnNumber) => { - const bedColumn = bedColumns[columnNumber] - const val = - bedColumn && bedColumn.dataType.type === 'Number' && text - ? parseFloat(text) - : text - if (bedColumn) { - // a predefined column - if (bedColumn.featureField.length === 2) { - if (!featureData[bedColumn.featureField[0]]) { - featureData[bedColumn.featureField[0]] = {} - } - featureData[bedColumn.featureField[0]][bedColumn.featureField[1]] = - val - } else { - featureData[bedColumn.featureField[0]] = val + if (j < MAX_SET_SCAN) { + columns.add(key) } - } else { - // some other column - featureData[`column${columnNumber + 1}`] = val - } - }) - featureData.uniqueId = `bedpe-${rowNumber}` - row.extendedData = { - feature: featureData, - } - }) + return [key, e] + }), + ) - data.assemblyName = options.selectedAssemblyName + rows.push({ + ...rest, + loc: assembleLocString({ + refName, + start, + end, + }), + id: `row_${i}`, + start, + end, + refName, + strand, + name, + score, + }) + } - return data + return { + header, + rows, + columns: [...columns], + customComponents: { + loc: LocString, + }, + } } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedpeImport.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedpeImport.ts new file mode 100644 index 0000000000..5751953b6c --- /dev/null +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/BedpeImport.ts @@ -0,0 +1,97 @@ +import { parseStrand } from './util' + +const MAX_SET_SCAN = 100 +const MAX_BEDPE_COL = 10 + +export async function parseBedPEBuffer(buffer: Buffer) { + const data = new TextDecoder('utf8', { fatal: true }).decode(buffer) + const lines = data.split(/\n|\r\n|\r/).filter(f => !!f) + const headerLines = [] + let i = 0 + for ( + ; + i < lines.length && + (lines[i].startsWith('#') || + lines[i].startsWith('browser') || + lines[i].startsWith('track')); + i++ + ) { + headerLines.push(lines[i]) + } + const header = headerLines.join('\n') + const lastHeaderLine = headerLines.at(-1) + let names = [] as string[] + if (lastHeaderLine?.startsWith('#')) { + names = lastHeaderLine + .slice(1) + .split('\t') + .map(f => f.trim()) + } + + const columns = new Set([ + 'refName', + 'start', + 'end', + 'mate.refName', + 'mate.start', + 'mate.end', + 'name', + 'score', + 'strand', + 'mate.strand', + ...names.slice(9), + ]) + const rows = [] + for (let j = 0; i < lines.length; i++, j++) { + const line = lines[i] + const l = line.split('\t') + const ref1 = l[0] + const start1 = +l[1] + const end1 = +l[2] + const ref2 = l[3] + const start2 = +l[4] + const end2 = +l[5] + const name = l[6] + const score = +l[7] + const strand1 = parseStrand(l[8]) + const strand2 = parseStrand(l[9]) + + let extra = l.slice(MAX_BEDPE_COL) + let ALT + if (['DUP', 'TRA', 'INV', 'CNV', 'DEL'].includes(extra[0])) { + ALT = `<${extra[0]}>` + if (j < MAX_SET_SCAN) { + columns.add('ALT') + } + extra = extra.slice(1) + } + const rest = Object.fromEntries( + extra.map((e, idx) => { + const key = names[idx + MAX_BEDPE_COL] || `extra_${idx}` + + if (j < MAX_SET_SCAN) { + columns.add(key) + } + return [key, e] + }), + ) + + rows.push({ + ...rest, + id: `row_${i}`, + start: start1, + end: end1, + refName: ref1, + strand: strand1, + name, + ALT, + score, + 'mate.refName': ref2, + 'mate.start': start2, + 'mate.end': end2, + 'mate.strand': strand2, + }) + } + + return { header, rows, columns: [...columns] } +} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.test.ts deleted file mode 100644 index 3347ef3d77..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { promises as fsPromises } from 'fs' -import path from 'path' - -// locals -import { parseCsvBuffer } from './ImportUtils' -import SpreadsheetModel from '../models/Spreadsheet' - -test('csv to spreadsheet snapshot', async () => { - const filepath = path.join( - __dirname, - '..', - 'test_data', - 'breast_cancer.subset.csv', - ) - const buf = await fsPromises.readFile(filepath) - const spreadsheetSnap = await parseCsvBuffer(buf, { - hasColumnNameLine: true, - columnNameLineNumber: 1, - isValidRefName: () => true, - }) - expect(spreadsheetSnap).toMatchSnapshot() - // @ts-expect-error - const spreadsheet = SpreadsheetModel.create(spreadsheetSnap) - expect(spreadsheet.rowSet.rows.length).toBe(49) -}) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.ts deleted file mode 100644 index d0a1b16833..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/ImportUtils.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { parseLocString } from '@jbrowse/core/util' - -export function bufferToString(buffer: Buffer) { - return new TextDecoder('utf8', { fatal: true }).decode(buffer) -} - -async function parseWith(buffer: Buffer, options = {}) { - const csv = await import('csvtojson').then(module => module.default) - return csv({ noheader: true, output: 'csv', ...options }).fromString( - bufferToString(buffer), - ) -} - -export interface Row { - id: string - // eslint-disable-next-line @typescript-eslint/no-explicit-any - extendedData?: any - cells: { - text: string - // eslint-disable-next-line @typescript-eslint/no-explicit-any - extendedData?: any - }[] -} - -export interface RowSet { - isLoaded: boolean - rows: Row[] -} - -export interface ParseOptions { - hasColumnNameLine?: boolean - columnNameLineNumber?: number - selectedAssemblyName?: string - isValidRefName?: (refName: string, assemblyName?: string) => boolean -} - -export interface Column { - name: string - dataType: { type: string } - isDerived?: boolean - derivationFunctionText?: string -} - -function guessColumnType( - rowSet: RowSet, - columnNumber: number, - isValidRefName: (refName: string, assemblyName?: string) => boolean, -) { - const text = rowSet.rows[0].cells[columnNumber].text || '' - - let guessedType = 'Text' - - let parsedLoc - try { - parsedLoc = parseLocString(text, isValidRefName) - } catch (error) { - // - } - if (parsedLoc?.refName && typeof parsedLoc.start === 'number') { - guessedType = 'LocString' - } else if (/^\d+(\.\d+)?$/.test(text)) { - guessedType = 'Number' - } - - // MAYBE TODO: iterate over the rest of the rows to confirm - // the type for all the rows - - return guessedType -} - -function dataToSpreadsheetSnapshot( - rows: string[][], - options: ParseOptions = {}, -) { - const { - hasColumnNameLine = false, - columnNameLineNumber = 1, - isValidRefName = () => false, - selectedAssemblyName, - } = options - // rows is an array of row objects and columnNames - // is an array of column names (in import order) - let maxCols = 0 - const rowSet: RowSet = { - isLoaded: true, - rows: rows.map((row, rowNumber) => { - const id = rowNumber + (hasColumnNameLine ? 0 : 1) - if (row.length > maxCols) { - maxCols = row.length - } - return { - id: String(id), - cells: row.map((text, columnNumber) => { - return { columnNumber, text } - }), - } - }), - } - - // process the column names row if present - const columnNames: Record = {} - if (hasColumnNameLine && columnNameLineNumber !== undefined) { - const [colNamesRow] = rowSet.rows.splice(columnNameLineNumber - 1, 1) - - if (colNamesRow) { - colNamesRow.cells.forEach((cell, columnNumber) => { - columnNames[columnNumber] = cell.text || '' - }) - } - } - - // make our column definitions - const columns: Column[] = [] - const columnDisplayOrder = [] - for (let columnNumber = 0; columnNumber < maxCols; columnNumber += 1) { - columnDisplayOrder.push(columnNumber) - const guessedType = guessColumnType(rowSet, columnNumber, isValidRefName) - - // store extendeddata for LocString column - if (guessedType === 'LocString') { - for (const row of rowSet.rows) { - const cell = row.cells[columnNumber] - cell.extendedData = parseLocString(cell.text, isValidRefName) - } - } - - columns[columnNumber] = { - name: columnNames[columnNumber], - dataType: { - type: guessedType, - }, - } - } - - return { - rowSet, - columnDisplayOrder, - hasColumnNames: !!hasColumnNameLine, - columns, - assemblyName: selectedAssemblyName, - } -} - -export async function parseCsvBuffer(buffer: Buffer, options?: ParseOptions) { - const rows = await parseWith(buffer) - return dataToSpreadsheetSnapshot(rows, options) -} - -export async function parseTsvBuffer(buffer: Buffer, options?: ParseOptions) { - const rows = await parseWith(buffer, { delimiter: '\t' }) - return dataToSpreadsheetSnapshot(rows, options) -} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.test.ts deleted file mode 100644 index 22a31768be..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { promises as fsPromises } from 'fs' -import path from 'path' - -// locals -import { parseSTARFusionBuffer } from './STARFusionImport' -import SpreadsheetModel from '../models/Spreadsheet' - -test('starfusion import', async () => { - const filepath = path.join( - __dirname, - '..', - 'test_data', - 'starfusion_example.fusion_predictions.tsv', - ) - const buf = await fsPromises.readFile(filepath) - const spreadsheetSnap = await parseSTARFusionBuffer(buf, { - selectedAssemblyName: 'fogbat', - isValidRefName() { - return true - }, - }) - expect(spreadsheetSnap).toMatchSnapshot() - - // @ts-expect-error - const spreadsheet = SpreadsheetModel.create(spreadsheetSnap) - expect(spreadsheet.rowSet.rows.length).toBe(24) -}) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.ts index 4cfd7444ca..ca8c7f4583 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/STARFusionImport.ts @@ -1,74 +1,13 @@ -import { parseTsvBuffer, ParseOptions } from './ImportUtils' - -function parseSTARFusionBreakpointString(str: string) { - const fields = str.split(':') - const refName = fields[0] - const pos = Number.parseInt(fields[1], 10) - const strand = fields[2] === '-' ? -1 : 1 - return { refName, pos, strand } -} - -const numericColumns: Record = { - SpanningFragCount: true, - FFPM: true, - LeftBreakEntropy: true, - RightBreakEntropy: true, - JunctionReadCount: true, -} - -export async function parseSTARFusionBuffer( - buffer: Buffer, - options: ParseOptions, -) { - const data = await parseTsvBuffer(buffer, { - hasColumnNameLine: true, - columnNameLineNumber: 1, - selectedAssemblyName: options.selectedAssemblyName, - isValidRefName: () => false, - }) - - // remove the # in #FusionName - data.columns[0].name = data.columns[0].name.replace('#', '') - // set some columns to be numeric - data.columns.forEach(col => { - if (numericColumns[col.name]) { - col.dataType = { type: 'Number' } - } - }) - - // decorate each row with a feature object in its extendedData - data.rowSet.rows.forEach((row, rowNumber) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const featureData: Record = {} - row.cells.forEach(({ text }, columnNumber) => { - const column = data.columns[columnNumber] - if (column.name === 'LeftBreakpoint' && text) { - const { refName, pos, strand } = parseSTARFusionBreakpointString(text) - featureData.refName = refName - featureData.start = pos - featureData.end = pos - featureData.strand = strand - } else if (column.name === 'RightBreakpoint' && text) { - const { refName, pos, strand } = parseSTARFusionBreakpointString(text) - featureData.mate = { - refName, - start: pos, - end: pos, - strand, - } - } else if (text && numericColumns[column.name]) { - // some other column, numeric - featureData[column.name] = parseFloat(text) - } else { - // some other column, text - featureData[column.name] = text - } - }) - featureData.uniqueId = `sf-${rowNumber + 1}` - row.extendedData = { - feature: featureData, - } - }) - - return data +export function parseSTARFusionBuffer(buffer: Buffer) { + const str = new TextDecoder('utf8').decode(buffer) + const lines = str.split(/\n|\r\n/) + const header = lines[0].slice(1).split('\t') + return { + rows: lines + .slice(1) + .map(row => + Object.fromEntries(row.split('\t').map((c, i) => [header[i], c])), + ), + columns: header, + } } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.test.ts deleted file mode 100644 index eb5f934ed9..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { promises as fsPromises } from 'fs' -import path from 'path' -import { parseVcfBuffer, splitVcfFileHeaderAndBody } from './VcfImport' -import SpreadsheetModel from '../models/Spreadsheet' - -describe('vcf file splitter', () => { - const cases: [string, {}][] = [ - [ - '##fileformat=VCFv4.3\nfogbat\n', - { header: '##fileformat=VCFv4.3\n', body: 'fogbat\n' }, - ], - [ - '##fileformat=VCFv4.3\n##zonker\n##deek\n##donk\nfogbat\n', - { - header: '##fileformat=VCFv4.3\n##zonker\n##deek\n##donk\n', - body: 'fogbat\n', - }, - ], - ] - - cases.forEach(([input, output], caseNumber) => { - test(`case ${caseNumber}`, () => { - expect(splitVcfFileHeaderAndBody(input)).toEqual(output) - }) - }) -}) - -test('vcf file import', async () => { - const filepath = path.join( - __dirname, - '..', - 'test_data', - '1801160099-N32519_26611_S51_56704.hard-filtered.vcf', - ) - const buf = await fsPromises.readFile(filepath) - const spreadsheetSnap = parseVcfBuffer(buf) - expect(spreadsheetSnap).toMatchSnapshot() - - // @ts-expect-error - const spreadsheet = SpreadsheetModel.create(spreadsheetSnap) - expect(spreadsheet.rowSet.rows.length).toBe(101) -}) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.ts index 0e7abc2d6b..d46db1ab6a 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/VcfImport.ts @@ -1,118 +1,117 @@ import VCF from '@gmod/vcf' -import { VcfFeature } from '@jbrowse/plugin-variants' +import { assembleLocString } from '@jbrowse/core/util' + +// locals +import LocString from './components/LocString' import { - bufferToString, - Row, - RowSet, - Column, - ParseOptions, -} from './ImportUtils' + launchBreakpointSplitView, + launchLinearGenomeView, + launchLinearGenomeViewWithEndFocus, +} from './util' +import { SpreadsheetModel } from '../models/Spreadsheet' +import { VcfFeature } from '@jbrowse/plugin-variants' -const vcfCoreColumns: { name: string; type: string }[] = [ - { name: 'CHROM', type: 'Text' }, // 0 - { name: 'POS', type: 'Number' }, // 1 - { name: 'ID', type: 'Text' }, // 2 - { name: 'REF', type: 'Text' }, // 3 - { name: 'ALT', type: 'Text' }, // 4 - { name: 'QUAL', type: 'Number' }, // 5 - { name: 'FILTER', type: 'Text' }, // 6 - { name: 'INFO', type: 'Text' }, // 7 - { name: 'FORMAT', type: 'Text' }, // 8 -] +type Row = Record -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function vcfRecordToRow(vcfParser: any, line: string, lineNumber: number): Row { - const vcfVariant = vcfParser.parseLine(line) - const vcfFeature = new VcfFeature({ - variant: vcfVariant, - parser: vcfParser, - id: `vcf-${lineNumber}`, - }) - - const data = line.split('\t').map(d => (d === '.' ? '' : d)) - // no format column, add blank - if (data.length === 8) { - data.push('') - } - const row: Row = { - id: String(lineNumber + 1), - extendedData: { vcfFeature: vcfFeature.toJSON() }, - cells: data.map((text, columnNumber) => { - return { - columnNumber, - text, - } - }), +export function parseVcfBuffer(buffer: Buffer) { + const str = new TextDecoder('utf8').decode(buffer) + const lines = str + .split(/\n|\r\n/) + .map(f => f.trim()) + .filter(f => !!f) + const headerLines = [] + let i = 0 + for (; i < lines.length && lines[i].startsWith('#'); i++) { + headerLines.push(lines[i]) } - return row -} - -export function parseVcfBuffer(buffer: Buffer, options: ParseOptions = {}) { - const { selectedAssemblyName } = options - let { header, body } = splitVcfFileHeaderAndBody(bufferToString(buffer)) - const rows: Row[] = [] + const header = headerLines.join('\n') const vcfParser = new VCF({ header }) - header = '' // garbage collect - body.split(/\n|\r\n|\r/).forEach((line: string, lineNumber) => { - if (/\S/.test(line)) { - rows.push(vcfRecordToRow(vcfParser, line, lineNumber)) + const keys = new Set() + const rows = lines.slice(i).map((l, id) => { + const [CHROM, POS, ID, REF, ALT, QUAL, FILTER, INFO, FORMAT] = l.split('\t') + const ret = Object.fromEntries( + INFO?.split(';') + .map(f => f.trim()) + .map(e => { + const [key, val = 'true'] = e.split('=') + const k = `INFO.${key.trim()}` + keys.add(k) + return [k, val.trim()] + }) || [], + ) + const feature = new VcfFeature({ + parser: vcfParser, + variant: vcfParser.parseLine(l), + id: `${id}`, + }) + return { + loc: assembleLocString({ + refName: feature.get('refName'), + start: feature.get('start'), + end: feature.get('end'), + }), + CHROM, + POS, + ID, + REF, + ALT, + QUAL, + FILTER, + FORMAT, + id, + feature: new VcfFeature({ + parser: vcfParser, + variant: vcfParser.parseLine(l), + id: `${id}`, + }), + ___lineData: l, + ...ret, } }) - body = '' // garbage collect - - const rowSet: RowSet = { - isLoaded: true, - rows, - } - - const columnDisplayOrder: number[] = [] - const columns: Column[] = [] - for (let i = 0; i < vcfCoreColumns.length; i += 1) { - columnDisplayOrder.push(i) - columns[i] = { - name: vcfCoreColumns[i].name, - dataType: { type: vcfCoreColumns[i].type }, - } - } - for (let i = 0; i < vcfParser.samples.length; i += 1) { - const oi = vcfCoreColumns.length + i - columnDisplayOrder.push(oi) - columns[oi] = { name: vcfParser.samples[i], dataType: { type: 'Text' } } - } - - columnDisplayOrder.push(columnDisplayOrder.length) - columns.unshift({ - name: 'Location', - dataType: { type: 'LocString' }, - isDerived: true, - derivationFunctionText: `jexl:{text:row.extendedData.vcfFeature.refName+':'\n - +row.extendedData.vcfFeature.start+'..'+row.extendedData.vcfFeature.end, extendedData:\n - {refName:row.extendedData.vcfFeature.refName,start:row.extendedData.vcfFeature.start,end:row.extendedData.vcfFeature.end}}`, - }) - - return { - rowSet, - columnDisplayOrder, - hasColumnNames: true, - columns, - assemblyName: selectedAssemblyName, - } -} - -export function splitVcfFileHeaderAndBody(wholeFile: string) { - // split into header and the rest of the file - let headerEndIndex = 0 - let prevChar - for (; headerEndIndex < wholeFile.length; headerEndIndex += 1) { - const c = wholeFile[headerEndIndex] - if (prevChar === '\n' && c !== '#') { - break - } - prevChar = c - } return { - header: wholeFile.slice(0, Math.max(0, headerEndIndex)), - body: wholeFile.slice(headerEndIndex), + vcfParser, + rows, + columns: [ + 'loc', + 'CHROM', + 'POS', + 'ID', + 'REF', + 'ALT', + 'QUAL', + 'FILTER', + 'FORMAT', + ...keys, + ], + CustomComponents: { + loc: { + Component: LocString, + props: { + getMenuItems: ({ + model, + row, + }: { + model: SpreadsheetModel + row: Row + }) => [ + { + label: 'Open in linear genome view (whole feature)', + onClick: () => + launchLinearGenomeView({ model, value: row.loc as string }), + }, + { + label: 'Open in linear genome view (focused on ends of SV)', + onClick: () => launchLinearGenomeViewWithEndFocus({ model, row }), + }, + { + label: 'Open in breakpoint split view', + onClick: () => + launchBreakpointSplitView({ model, row, vcfParser }), + }, + ], + }, + }, + }, } } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/components/LocString.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/components/LocString.tsx new file mode 100644 index 0000000000..4042e9f3f9 --- /dev/null +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/components/LocString.tsx @@ -0,0 +1,49 @@ +import React from 'react' +import { Link } from '@mui/material' +import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton' +import { MenuItem } from '@jbrowse/core/ui' +import { getSession } from '@jbrowse/core/util' + +// icons +import MoreHoriz from '@mui/icons-material/MoreHoriz' + +// locals +import { locationLinkClick } from '../../components/util' +import { SpreadsheetModel } from '../../models/Spreadsheet' + +export default function LocString({ + value, + model, + row, + getMenuItems, +}: { + value: string + model: SpreadsheetModel + row: Record + getMenuItems: (arg: { + model: SpreadsheetModel + row: Record + }) => MenuItem[] +}) { + return ( + <> + { + try { + event.preventDefault() + await locationLinkClick(model, value) + } catch (e) { + console.error(e) + getSession(model).notify(`${e}`, 'error') + } + }} + > + {value} + + + + + + ) +} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/util.ts b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/util.ts new file mode 100644 index 0000000000..af2f9ee16b --- /dev/null +++ b/plugins/spreadsheet-view/src/SpreadsheetView/importAdapters/util.ts @@ -0,0 +1,135 @@ +import { + Feature, + assembleLocString, + getEnv, + getSession, +} from '@jbrowse/core/util' +import { getParent } from 'mobx-state-tree' +import { VcfFeature } from '@jbrowse/plugin-variants' +import VCF, { parseBreakend } from '@gmod/vcf' + +// locals +import { locationLinkClick } from '../components/util' +import { SpreadsheetModel } from '../models/Spreadsheet' + +export function parseStrand(strand: string) { + if (strand === '+') { + return 1 + } else if (strand === '-') { + return -1 + } else if (strand === '.') { + return 0 + } else { + return undefined + } +} + +export async function launchLinearGenomeView({ + model, + value, +}: { + model: SpreadsheetModel + value: string +}) { + try { + await locationLinkClick(model, value) + } catch (e) { + console.error(e) + getSession(model).notify(`${e}`, 'error') + } +} + +export async function launchBreakpointSplitView({ + model, + row, + vcfParser, +}: { + model: SpreadsheetModel + row: Record + vcfParser: VCF +}) { + try { + const session = getSession(model) + const { pluginManager } = getEnv(model) + const { assemblyName } = model + if (!assemblyName) { + throw new Error('assemblyName not set') + } + const viewType = pluginManager.getViewType('BreakpointSplitView') + const feat = new VcfFeature({ + id: row.id as string, + // eslint-disable-next-line no-underscore-dangle + variant: vcfParser.parseLine(row.___lineData as string), + parser: vcfParser, + }) + // @ts-expect-error + const snap = await viewType.snapshotFromBreakendFeature( + feat, + assemblyName, + session, + ) + const v = getParent<{ width: number }>(model) + snap.views[0].offsetPx -= v.width / 2 + 100 + snap.views[1].offsetPx -= v.width / 2 + 100 + + session.addView('BreakpointSplitView', snap) + } catch (e) { + console.error(e) + getSession(model).notify(`${e}`, 'error') + } +} + +function getBreakpoints(feature: Feature) { + const alt = feature.get('ALT')?.[0] + + const bnd = alt ? parseBreakend(alt) : undefined + let endPos + let mateRefName: string | undefined + + // a VCF breakend feature + if (alt === '') { + const INFO = feature.get('INFO') + endPos = INFO.END[0] - 1 + mateRefName = INFO.CHR2[0] + } else if (bnd?.MatePosition) { + const matePosition = bnd.MatePosition.split(':') + endPos = +matePosition[1] - 1 + mateRefName = matePosition[0] + } else if (feature.get('mate')) { + const mate = feature.get('mate') + mateRefName = mate.refName + endPos = mate.start + } + + return [ + { + refName: feature.get('refName'), + start: feature.get('start') - 1000, + end: feature.get('end') + 1000, + }, + { + refName: mateRefName!, + start: endPos - 1000, + end: endPos + 1000, + }, + ] as const +} +export async function launchLinearGenomeViewWithEndFocus({ + model, + row, +}: { + model: SpreadsheetModel + row: Record +}) { + try { + const { feature } = row + const [s1, s2] = getBreakpoints(feature as Feature) + await locationLinkClick( + model, + `${assembleLocString(s1)} ${assembleLocString(s2)}`, + ) + } catch (e) { + console.error(e) + getSession(model).notify(`${e}`, 'error') + } +} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/index.ts b/plugins/spreadsheet-view/src/SpreadsheetView/index.ts index 91b6a6ea5e..62c3f560ce 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/index.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/index.ts @@ -1,10 +1,11 @@ import { lazy } from 'react' import { ViewType } from '@jbrowse/core/pluggableElementTypes' import PluginManager from '@jbrowse/core/PluginManager' -import stateModel from './models/SpreadsheetView' +import stateModelFactory from './models/SpreadsheetView' export default (pluginManager: PluginManager) => { pluginManager.addViewType(() => { + const stateModel = stateModelFactory() return new ViewType({ name: 'SpreadsheetView', displayName: 'Spreadsheet view', diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocEnd.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocEnd.ts deleted file mode 100644 index c2ee0bbe40..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocEnd.ts +++ /dev/null @@ -1,21 +0,0 @@ -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' -import { FilterModelType as NumberFilterModel } from './Number' -import { types } from 'mobx-state-tree' - -const FilterModelType = types.compose( - NumberFilterModel, - types.model({ - type: types.literal('LocEnd'), - }), -) - -const LocEnd = MakeSpreadsheetColumnType('LocEnd', { - categoryName: 'Location', - displayName: 'End', - compare(cellA: { text: string }, cellB: { text: string }) { - return parseFloat(cellA.text) - parseFloat(cellB.text) - }, - FilterModelType, -}) - -export default LocEnd diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocRef.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocRef.ts deleted file mode 100644 index a9e57037e5..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocRef.ts +++ /dev/null @@ -1,21 +0,0 @@ -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' -import { FilterModelType as NumberFilterModel } from './Text' -import { types } from 'mobx-state-tree' - -const FilterModelType = types.compose( - NumberFilterModel, - types.model({ - type: types.literal('LocRef'), - }), -) - -const LocRef = MakeSpreadsheetColumnType('LocRef', { - categoryName: 'Location', - displayName: 'Reference seq', - compare(cellA: { text: string }, cellB: { text: string }) { - return cellA.text.localeCompare(cellB.text) - }, - FilterModelType, -}) - -export default LocRef diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocStart.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocStart.ts deleted file mode 100644 index ae204f57a7..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocStart.ts +++ /dev/null @@ -1,21 +0,0 @@ -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' -import { types } from 'mobx-state-tree' -import { FilterModelType as NumberFilterModel } from './Number' - -const FilterModelType = types.compose( - NumberFilterModel, - types.model({ - type: types.literal('LocStart'), - }), -) - -const LocStart = MakeSpreadsheetColumnType('LocStart', { - categoryName: 'Location', - displayName: 'Start', - compare(cellA: { text: string }, cellB: { text: string }) { - return parseFloat(cellA.text) - parseFloat(cellB.text) - }, - FilterModelType, -}) - -export default LocStart diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocString.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocString.tsx deleted file mode 100644 index 77d4783ee3..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/LocString.tsx +++ /dev/null @@ -1,328 +0,0 @@ -import React from 'react' -import { - IconButton, - TextField, - MenuItem, - InputAdornment, - Select, -} from '@mui/material' -import { makeStyles } from 'tss-react/mui' -import { observer } from 'mobx-react' -import { types, getParent, getPropertyMembers } from 'mobx-state-tree' - -// jbrowse imports -import { - getPropertyType, - getEnumerationValues, - getSubType, -} from '@jbrowse/core/util/mst-reflection' -import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' -import { - doesIntersect2, - isContainedWithin, - compareLocs, - getSession, - parseLocString, -} from '@jbrowse/core/util' - -// icons -import ClearIcon from '@mui/icons-material/Clear' - -// locals -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' - -type LGV = LinearGenomeViewModel - -const useStyles = makeStyles()({ - textFilterControlAdornment: { marginRight: '-18px' }, - textFilterControl: { - '& .MuiInput-formControl': { - marginTop: 8, - }, - '& .MuiInputLabel-formControl': { - top: '-7px', - '&.MuiInputLabel-shrink': { - top: '-3px', - }, - }, - }, -}) - -// React component for the column filter control -const FilterReactComponent = observer(function ({ - filterModel, -}: { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - filterModel: any -}) { - const { classes } = useStyles() - const operationChoices = getEnumerationValues( - getSubType(getPropertyType(getPropertyMembers(filterModel), 'operation')), - ) - return ( - <> - {' '} - filterModel.setLocString(evt.target.value)} - className={classes.textFilterControl} - InputProps={{ - endAdornment: ( - - filterModel.setLocString('')} - > - - - - ), - }} - /> - - ) -}) - -const OPERATIONS = [ - 'overlaps with', - 'contained within', - 'fully contains', - 'does not overlap', - 'not contained within', - 'does not contain', -] - -interface Loc { - start: number - end: number - refName: string -} - -// NOTE: assembly names, if present, are ignored in all of these predicates -const OPERATION_PREDICATES = { - 'overlaps with': (cellLocation, specifiedLocation) => { - return ( - cellLocation.refName === specifiedLocation.refName && - doesIntersect2( - cellLocation.start, - cellLocation.end, - specifiedLocation.start, - specifiedLocation.end, - ) - ) - }, - 'contained within': (cellLocation, specifiedLocation) => { - return ( - cellLocation.refName === specifiedLocation.refName && - isContainedWithin( - cellLocation.start, - cellLocation.end, - specifiedLocation.start, - specifiedLocation.end, - ) - ) - }, - 'fully contains': (cellLocation, specifiedLocation) => { - return ( - cellLocation.refName === specifiedLocation.refName && - isContainedWithin( - specifiedLocation.start, - specifiedLocation.end, - cellLocation.start, - cellLocation.end, - ) - ) - }, -} as Record boolean> - -OPERATION_PREDICATES['does not overlap'] = ( - cellLocation, - specifiedLocation, -) => { - return !OPERATION_PREDICATES['overlaps with'](cellLocation, specifiedLocation) -} -OPERATION_PREDICATES['not contained within'] = ( - cellLocation, - specifiedLocation, -) => { - return !OPERATION_PREDICATES['contained within']( - cellLocation, - specifiedLocation, - ) -} -OPERATION_PREDICATES['does not contain'] = ( - cellLocation, - specifiedLocation, -) => { - return !OPERATION_PREDICATES['fully contains']( - cellLocation, - specifiedLocation, - ) -} - -// MST model for the column filter control -const FilterModelType = types - .model('ColumnLocStringFilter', { - type: types.literal('LocString'), - columnNumber: types.integer, - locString: '', - operation: types.optional(types.enumeration(OPERATIONS), OPERATIONS[0]), - }) - .views(self => ({ - get locStringIsInvalid() { - if (self.locString) { - const parsed = this.parsedLocString - return ( - !parsed || - parsed.refName === '' || - typeof parsed.start !== 'number' || - typeof parsed.end !== 'number' || - parsed.start > parsed.end - ) - } - return false - }, - get parsedLocString() { - const session = getSession(self) - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const model = getParent(self, 3).spreadsheet - const { assemblyName } = model - try { - return parseLocString(self.locString, refName => - session.assemblyManager.isValidRefName(refName, assemblyName), - ) - } catch (e) { - return undefined - } - }, - })) - .views(self => ({ - // returns a function that tests the given row - get predicate() { - const { - locString, - locStringIsInvalid, - parsedLocString, - operation, - columnNumber, - } = self // avoid closing over self - if (!locString || locStringIsInvalid || !parsedLocString) { - return function alwaysTrue() { - return true - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return function stringPredicate(_sheet: any, row: any) { - const { cellsWithDerived: cells } = row - const cell = cells[columnNumber] - - if (!cell?.text || !cell.extendedData) { - return false - } - const parsedCellText = cell.extendedData - if (!parsedCellText.refName) { - return false - } - - const predicate = OPERATION_PREDICATES[operation] - if (!predicate) { - throw new Error(`"${operation}" not implemented in location filter`) - } - - return predicate(parsedCellText, parsedLocString as Loc) - } - }, - })) - .actions(self => ({ - setLocString(s: string) { - self.locString = s - }, - setOperation(op: string) { - self.operation = op - }, - })) - .volatile(() => ({ ReactComponent: FilterReactComponent })) - -// opens a new LGV at the location described in the locString in the cell text - -async function locationLinkClick( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - spreadsheet: any, - _columnNumber: number, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - cell: any, -) { - const session = getSession(spreadsheet) - const { assemblyName } = spreadsheet - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { id } = getParent(spreadsheet) - - const newViewId = `${id}_${assemblyName}` - let view = session.views.find(v => v.id === newViewId) as LGV - if (!view) { - view = session.addView('LinearGenomeView', { - id: newViewId, - }) as LGV - } - await view.navToLocString(cell.text, assemblyName) -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type DataCell = any - -const DataCellReactComponent = observer(function ({ - cell, - columnNumber, - spreadsheet, -}: DataCell) { - return ( - { - evt.preventDefault() - const session = getSession(spreadsheet) - try { - await locationLinkClick(spreadsheet, columnNumber, cell) - } catch (e) { - console.error(e) - session.notifyError(`${e}`, e) - } - }} - title="open a new linear genome view here" - href="#link" - > - {cell.text} - - ) -}) - -const LocStringColumnType = MakeSpreadsheetColumnType('LocString', { - categoryName: 'Location', - displayName: 'Full location', - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - compare(cellA: { extendedData: any }, cellB: { extendedData: any }) { - return compareLocs(cellA.extendedData, cellB.extendedData) - }, - FilterModelType, - DataCellReactComponent, -}) - -export default LocStringColumnType diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/MakeSpreadsheetColumnType.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/MakeSpreadsheetColumnType.tsx deleted file mode 100644 index 6a50f04914..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/MakeSpreadsheetColumnType.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import React from 'react' -import { types } from 'mobx-state-tree' - -/** utility function for assembling the MST model of a column data type */ -export default function MakeSpreadsheetColumnType( - name: string, - { - DataCellReactComponent = null, - FilterModelType = null, - compare, - displayName = undefined, - categoryName = undefined, - }: { - compare?: any - DataCellReactComponent?: React.FC | null - FilterModelType?: any - displayName?: string - categoryName?: string - }, -) { - return types - .model(`ColumnDataType${name}`, { - type: types.literal(name), - }) - .volatile(() => ({ - DataCellReactComponent, - FilterModelType: FilterModelType, - displayName: displayName || name, - categoryName, - })) - .views(() => ({ - compare, - get hasFilter() { - return !!FilterModelType - }, - })) -} diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Number.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Number.tsx deleted file mode 100644 index b4a8c44c29..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Number.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import React from 'react' -import { types } from 'mobx-state-tree' -import { observer } from 'mobx-react' -import { MenuItem, Select, TextField } from '@mui/material' -import { makeStyles } from 'tss-react/mui' -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' - -const OPERATIONS = [ - 'equals', - 'greater than', - 'less than', - 'between', - 'not between', -] - -// NOTE: assembly names, if present, are ignored in all of these predicates -const OPERATION_PREDICATES = { - equals: (numberInCell, firstNumber) => { - return numberInCell === firstNumber - }, - 'greater than': (numberInCell, firstNumber) => { - return numberInCell > firstNumber - }, - 'less than': (numberInCell, firstNumber) => { - return numberInCell < firstNumber - }, - between: (numberInCell, firstNumber, secondNumber) => { - return ( - numberInCell > firstNumber && - secondNumber !== undefined && - numberInCell < secondNumber - ) - }, -} as Record boolean> - -OPERATION_PREDICATES['not between'] = ( - numberInCell, - firstNumber, - secondNumber, -) => { - return !OPERATION_PREDICATES.between(numberInCell, firstNumber, secondNumber) -} - -const useStyles = makeStyles()({ - textFilterControlAdornment: { marginRight: '-18px' }, - textFilterControl: { - '& .MuiInput-formControl': { - marginTop: 8, - }, - '& .MuiInputLabel-formControl': { - top: '-7px', - '&.MuiInputLabel-shrink': { - top: '-3px', - }, - }, - }, -}) - -// React component for the column filter control -const FilterReactComponent = observer( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ({ filterModel }: { filterModel: any }) => { - const { classes } = useStyles() - - const operationChoices = OPERATIONS - - return ( - <> - {' '} - { - filterModel.setFirstNumber(parseFloat(evt.target.value)) - }} - className={classes.textFilterControl} - /> - {filterModel.operation !== 'between' && - filterModel.operation !== 'not between' ? null : ( - <> - {' and '} - - filterModel.setSecondNumber(parseFloat(evt.target.value)) - } - className={classes.textFilterControl} - /> - - )} - - ) - }, -) - -// MST model for the column filter control -const FilterModelType = types - .model('ColumnNumberFilter', { - type: types.literal('Number'), - columnNumber: types.integer, - firstNumber: types.maybe(types.number), - secondNumber: types.maybe(types.number), - operation: types.optional(types.enumeration(OPERATIONS), OPERATIONS[0]), - }) - .views(self => ({ - // returns a function that tests the given row - get predicate() { - if (typeof self.firstNumber !== 'number') { - return function alwaysTrue() { - return true - } - } - - const { firstNumber, secondNumber, operation, columnNumber } = self // avoid closing over self - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return function stringPredicate(_sheet: any, row: any) { - const { cellsWithDerived } = row - const cell = cellsWithDerived[columnNumber] - - if (!cell?.text) { - return false - } - - const parsedCellText = parseFloat(cell.text) - if (typeof parsedCellText !== 'number') { - return false - } - - const predicate = OPERATION_PREDICATES[operation] - if (!predicate) { - throw new Error(`"${operation}" not implemented in location filter`) - } - - return predicate(parsedCellText, firstNumber, secondNumber) - } - }, - })) - .actions(self => ({ - setFirstNumber(n: number) { - self.firstNumber = - Number.isNaN(n) || typeof n !== 'number' ? undefined : n - }, - setSecondNumber(n: number) { - self.secondNumber = - Number.isNaN(n) || typeof n !== 'number' ? undefined : n - }, - setOperation(op: string) { - self.operation = op - }, - })) - .volatile(() => ({ ReactComponent: FilterReactComponent })) - -const NumberColumn = MakeSpreadsheetColumnType('Number', { - compare(cellA: { text: string }, cellB: { text: string }) { - return parseFloat(cellA.text) - parseFloat(cellB.text) - }, - FilterModelType, -}) - -export { NumberColumn, FilterModelType } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Text.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Text.tsx deleted file mode 100644 index 4c704ca138..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/Text.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import React from 'react' -import { - IconButton, - TextField, - MenuItem, - InputAdornment, - Select, -} from '@mui/material' -import { makeStyles } from 'tss-react/mui' -import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' -import { types, getPropertyMembers } from 'mobx-state-tree' -import { observer } from 'mobx-react' -import { - getPropertyType, - getEnumerationValues, - getSubType, -} from '@jbrowse/core/util/mst-reflection' - -// icons -import ClearIcon from '@mui/icons-material/Clear' - -const OPERATIONS = [ - 'equals', - 'contains', - 'does not contain', - 'does not equal', - 'starts with', - 'ends with', -] - -// NOTE: assembly names, if present, are ignored in all of these predicates -const OPERATION_PREDICATES = { - contains: (textInCell, stringToFind) => { - return textInCell.toLowerCase().includes(stringToFind) - }, - equals: (textInCell, stringToFind) => { - return textInCell.toLowerCase() === stringToFind - }, - 'starts with': (textInCell, stringToFind) => { - return textInCell.toLowerCase().startsWith(stringToFind) - }, - 'ends with': (textInCell, stringToFind) => { - const index = textInCell.toLowerCase().indexOf(stringToFind) - if (index === -1) { - return false - } - return index === textInCell.length - stringToFind.length - }, -} as Record boolean> - -OPERATION_PREDICATES['does not contain'] = (textInCell, stringToFind) => { - return !OPERATION_PREDICATES.contains(textInCell, stringToFind) -} -OPERATION_PREDICATES['does not equal'] = (textInCell, stringToFind) => { - return !OPERATION_PREDICATES.equals(textInCell, stringToFind) -} - -const useStyles = makeStyles()({ - textFilterControlAdornment: { marginRight: '-18px' }, - textFilterControl: { - margin: 0, - '& .MuiInput-formControl': { - marginTop: 8, - }, - '& .MuiInputLabel-formControl': { - top: '-7px', - '&.MuiInputLabel-shrink': { - top: '-3px', - }, - }, - }, -}) - -// React component for the column filter control -const FilterReactComponent = observer( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ({ filterModel }: { filterModel: any }) => { - const { classes } = useStyles() - const operationChoices = getEnumerationValues( - getSubType(getPropertyType(getPropertyMembers(filterModel), 'operation')), - ) - return ( - <> - {' '} - filterModel.setString(evt.target.value)} - className={classes.textFilterControl} - InputProps={{ - endAdornment: ( - - filterModel.setString('')} - > - - - - ), - }} - /> - - ) - }, -) - -// MST model for the column filter control -const ColumnTextFilter = types - .model('ColumnTextFilter', { - type: types.literal('Text'), - columnNumber: types.integer, - stringToFind: '', - operation: types.optional(types.enumeration(OPERATIONS), OPERATIONS[0]), - }) - .views(self => ({ - // returns a function that tests the given row - get predicate() { - const { stringToFind, columnNumber, operation } = self // avoid closing over self - if (!stringToFind) { - return function alwaysTrue() { - return true - } - } - const s = stringToFind.toLowerCase() // case insensitive match - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return function stringPredicate(_sheet: any, row: any) { - const { cellsWithDerived } = row - const cell = cellsWithDerived[columnNumber] - if (!cell?.text) { - return false - } - const predicate = OPERATION_PREDICATES[operation] - if (!predicate) { - throw new Error(`"${operation}" not implemented in location filter`) - } - return predicate(cell.text, s) - } - }, - })) - .actions(self => ({ - setString(s: string) { - self.stringToFind = s - }, - setOperation(op: string) { - self.operation = op - }, - })) - .volatile(() => ({ ReactComponent: FilterReactComponent })) - -const TextColumnType = MakeSpreadsheetColumnType('Text', { - compare(cellA: { text: string }, cellB: { text: string }) { - return cellA.text.localeCompare(cellB.text) - }, - FilterModelType: ColumnTextFilter, -}) - -export { TextColumnType as TextColumn, ColumnTextFilter as FilterModelType } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/index.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/index.ts deleted file mode 100644 index 02eb921348..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ColumnDataTypes/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import LocString from './LocString' -import LocRef from './LocRef' -import LocStart from './LocStart' -import LocEnd from './LocEnd' -import { NumberColumn as Number } from './Number' -import { TextColumn as Text } from './Text' -import { types, IAnyModelType } from 'mobx-state-tree' - -const ColumnTypes = { - Number, - Text, - LocString, - LocRef, - LocStart, - LocEnd, -} - -const allColumnTypes = Object.values(ColumnTypes) -const AnyColumnType = types.union(...allColumnTypes) -const AnyFilterModelType = types.union( - ...allColumnTypes - .map(columnType => { - // just instantiate the blank types to get their filter model types - const { FilterModelType } = columnType.create({ - // @ts-expect-error - type: columnType.properties.type.value, - }) - return FilterModelType as unknown as IAnyModelType - }) - // some column types might not have filter machinery, filter those out - .filter(t => !!t), -) - -export { ColumnTypes, AnyColumnType, AnyFilterModelType } diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/FilterControls.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/FilterControls.ts deleted file mode 100644 index afa9c17f0a..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/FilterControls.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { types, getParent, SnapshotIn } from 'mobx-state-tree' -import { AnyFilterModelType as AnyColumnFilter } from './ColumnDataTypes' - -// filter that finds a simple string in any of the cells of a row -const RowFullTextFilter = types - .model('RowFullTextFilter', { - type: types.literal('RowFullText'), - stringToFind: '', - }) - .views(self => ({ - // returns a function that tests the given row - get predicate() { - let s = self.stringToFind // avoid closing over self - if (!s) { - return function alwaysTrue() { - return true - } - } - s = s.toLowerCase() - return function stringPredicate( - _sheet: unknown, - row: { cellsWithDerived: { text: string }[] }, - ) { - const { cellsWithDerived } = row - for (const cell of cellsWithDerived) { - // note: case insensitive - if (cell.text && cell.text.toLowerCase().includes(s)) { - return true - } - } - return false - } - }, - })) - .actions(self => ({ - setString(s: string) { - self.stringToFind = s - }, - clear() { - self.stringToFind = '' - }, - })) - -const model = types - .model('SpreadsheetFilterControls', { - rowFullText: types.optional( - RowFullTextFilter, - () => - ({ - type: 'RowFullText', - stringToFind: '', - }) as SnapshotIn, - ), - columnFilters: types.array(AnyColumnFilter), - }) - .views(self => ({ - get filters() { - return [self.rowFullText, ...self.columnFilters].filter(f => !!f) - }, - setRowFullTextFilter(stringToFind: string) { - // @ts-expect-error - self.rowFullText = { - type: 'RowFullText', - stringToFind, - } - }, - rowPassesFilters(sheet: unknown, row: unknown) { - for (const filter of this.filters) { - if (!filter.predicate(sheet, row)) { - return false - } - } - return true - }, - })) - .actions(self => ({ - addBlankColumnFilter(columnNumber: number) { - const { dataType } = - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getParent(self).spreadsheet.columns[columnNumber] - self.columnFilters.push({ - type: dataType.type, - columnNumber, - }) - }, - removeColumnFilter(filter: typeof AnyColumnFilter) { - return self.columnFilters.remove(filter) - }, - clearAllFilters() { - self.columnFilters.clear() - self.rowFullText.clear() - }, - })) - -export default model diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/ImportWizard.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/ImportWizard.ts index a055935e93..9f0c5c33d7 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/ImportWizard.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/models/ImportWizard.ts @@ -1,20 +1,16 @@ import { types, getParent, Instance } from 'mobx-state-tree' import { openLocation } from '@jbrowse/core/util/io' import { getSession, getEnv } from '@jbrowse/core/util' +import { SpreadsheetViewStateModel } from './SpreadsheetView' -// 30MB -const IMPORT_SIZE_LIMIT = 30_000_000 +const IMPORT_SIZE_LIMIT = 40_000_000 -const fileTypes = ['CSV', 'TSV', 'VCF', 'BED', 'BEDPE', 'STAR-Fusion'] +const fileTypes = ['VCF', 'BED', 'BEDPE', 'STAR-Fusion'] const fileTypeParsers = { - CSV: () => - import('../importAdapters/ImportUtils').then(r => r.parseCsvBuffer), - TSV: () => - import('../importAdapters/ImportUtils').then(r => r.parseTsvBuffer), VCF: () => import('../importAdapters/VcfImport').then(r => r.parseVcfBuffer), BED: () => import('../importAdapters/BedImport').then(r => r.parseBedBuffer), BEDPE: () => - import('../importAdapters/BedImport').then(r => r.parseBedPEBuffer), + import('../importAdapters/BedpeImport').then(r => r.parseBedPEBuffer), 'STAR-Fusion': () => import('../importAdapters/STARFusionImport').then( r => r.parseSTARFusionBuffer, @@ -29,175 +25,181 @@ const fileTypesRegexp = new RegExp(`\\.(${fileTypes.join('|')})(\\.gz)?$`, 'i') */ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars -const ImportWizard = types - .model('SpreadsheetImportWizard', { - /** - * #property - */ - fileType: types.optional(types.enumeration(fileTypes), 'CSV'), - /** - * #property - */ - hasColumnNameLine: true, - /** - * #property - */ - columnNameLineNumber: 1, - /** - * #property - */ - selectedAssemblyName: types.maybe(types.string), - }) - .volatile(() => ({ - fileTypes, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - fileSource: undefined as any, - error: undefined as unknown, - loading: false, - })) - .views(self => ({ - get isReadyToOpen() { - return ( - !self.error && - self.fileSource && - (self.fileSource.blobId || - self.fileSource.localPath || - self.fileSource.uri) - ) - }, - get canCancel() { +function stateModelFactory() { + return types + .model('SpreadsheetImportWizard', { + /** + * #property + */ + fileType: types.optional(types.enumeration(fileTypes), 'VCF'), + /** + * #property + */ + hasColumnNameLine: true, + /** + * #property + */ + columnNameLineNumber: 1, + /** + * #property + */ + selectedAssemblyName: types.maybe(types.string), + }) + .volatile(() => ({ + fileTypes, // eslint-disable-next-line @typescript-eslint/no-explicit-any - return getParent(self).readyToDisplay - }, - - get fileName() { - return ( - self.fileSource.uri || - self.fileSource.localPath || - (self.fileSource.blobId && self.fileSource.name) - ) - }, - - get requiresUnzip() { - return this.fileName.endsWith('gz') - }, - - isValidRefName(refName: string, assemblyName?: string) { - const { assemblyManager } = getSession(self) - if (!assemblyName) { - return false - } - return assemblyManager.isValidRefName(refName, assemblyName) - }, - })) - .actions(self => ({ - setSelectedAssemblyName(s: string) { - self.selectedAssemblyName = s - }, - setFileSource(newSource: unknown) { - self.fileSource = newSource - self.error = undefined - - if (self.fileSource) { - // try to autodetect the file type, ignore errors - const name = self.fileName - - if (name) { - const firstMatch = fileTypesRegexp.exec(name)?.[1] - if (firstMatch) { - self.fileType = - firstMatch === 'tsv' && name.includes('star-fusion') - ? 'STAR-Fusion' - : firstMatch.toUpperCase() + fileSource: undefined as any, + error: undefined as unknown, + loading: false, + })) + .views(self => ({ + /** + * #getter + */ + get isReadyToOpen() { + const { error, fileSource } = self + return ( + !error && + (fileSource?.blobId || fileSource?.localPath || fileSource?.uri) + ) + }, + + /** + * #getter + */ + get fileName() { + const { fileSource } = self + return fileSource + ? fileSource.uri || + fileSource.localPath || + (fileSource.blobId && fileSource.name) + : undefined + }, + /** + * #getter + */ + get requiresUnzip() { + return this.fileName.endsWith('gz') + }, + /** + * #method + */ + isValidRefName(refName: string, assemblyName?: string) { + const { assemblyManager } = getSession(self) + if (!assemblyName) { + return false + } + return assemblyManager.isValidRefName(refName, assemblyName) + }, + })) + .actions(self => ({ + /** + * #action + */ + setSelectedAssemblyName(s: string) { + self.selectedAssemblyName = s + }, + /** + * #action + */ + setFileSource(newSource: unknown) { + self.fileSource = newSource + self.error = undefined + + if (self.fileSource) { + // try to autodetect the file type, ignore errors + const name = self.fileName + + if (name) { + const firstMatch = fileTypesRegexp.exec(name)?.[1] + if (firstMatch) { + self.fileType = + firstMatch === 'tsv' && name.includes('star-fusion') + ? 'STAR-Fusion' + : firstMatch.toUpperCase() + } } } - } - }, - - toggleHasColumnNameLine() { - self.hasColumnNameLine = !self.hasColumnNameLine - }, - - setColumnNameLineNumber(newnumber: number) { - if (newnumber > 0) { - self.columnNameLineNumber = newnumber - } - }, - - setFileType(typeName: string) { - self.fileType = typeName - }, - - setError(error: unknown) { - console.error(error) - self.loading = false - self.error = error - }, - - setLoaded() { - self.loading = false - self.error = undefined - }, - - cancelButton() { - self.error = undefined - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getParent(self).setDisplayMode() - }, + }, + /** + * #action + */ + setFileType(typeName: string) { + self.fileType = typeName + }, + /** + * #action + */ + setError(error: unknown) { + console.error(error) + self.loading = false + self.error = error + }, + /** + * #action + */ + setLoaded() { + self.loading = false + self.error = undefined + }, + /** + * #action + * fetch and parse the file, make a new Spreadsheet model for it, + * then set the parent to display it + */ + async import(assemblyName: string) { + if (!self.fileSource) { + return + } - // fetch and parse the file, make a new Spreadsheet model for it, - // then set the parent to display it - async import(assemblyName: string) { - if (!self.fileSource) { - return - } + if (self.loading) { + throw new Error('Cannot import, load already in progress') + } - if (self.loading) { - throw new Error('Cannot import, load already in progress') - } + self.selectedAssemblyName = assemblyName + self.loading = true + const type = self.fileType as keyof typeof fileTypeParsers + const typeParser = await fileTypeParsers[type]() + if (!typeParser) { + throw new Error(`cannot open files of type '${self.fileType}'`) + } - self.selectedAssemblyName = assemblyName - self.loading = true - const type = self.fileType as keyof typeof fileTypeParsers - const typeParser = await fileTypeParsers[type]() - if (!typeParser) { - throw new Error(`cannot open files of type '${self.fileType}'`) - } + const { unzip } = await import('@gmod/bgzf-filehandle') + const { pluginManager } = getEnv(self) + const filehandle = openLocation(self.fileSource, pluginManager) + let stat + try { + stat = await filehandle.stat() + } catch (e) { + // not required for stat to succeed to proceed, but it is helpful + console.warn(e) + } - const { unzip } = await import('@gmod/bgzf-filehandle') - const { pluginManager } = getEnv(self) - const filehandle = openLocation(self.fileSource, pluginManager) - try { - const stat = await filehandle.stat() - if (stat.size > IMPORT_SIZE_LIMIT) { - throw new Error( - `File is too big. Tabular files are limited to at most ${( - IMPORT_SIZE_LIMIT / 1000 - ).toLocaleString()}kb.`, + try { + if (stat && stat.size > IMPORT_SIZE_LIMIT) { + throw new Error( + `File is too big. Tabular files are limited to at most ${( + IMPORT_SIZE_LIMIT / 1_000_000 + ).toLocaleString()}Mb.`, + ) + } + const buffer = await filehandle.readFile() + const buf2 = self.requiresUnzip ? await unzip(buffer) : buffer + const spreadsheet = await typeParser(buf2) + this.setLoaded() + getParent(self).displaySpreadsheet( + spreadsheet, + assemblyName, ) + } catch (e) { + console.error(e) + this.setError(e) } - } catch (e) { - // not required for stat to succeed to proceed, but it is helpful - console.warn(e) - } - - try { - await filehandle - .readFile() - .then(buffer => (self.requiresUnzip ? unzip(buffer) : buffer)) - .then(buffer => typeParser(buffer, self)) - .then(spreadsheet => { - this.setLoaded() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getParent(self).displaySpreadsheet(spreadsheet) - }) - } catch (e) { - this.setError(e) - } - }, - })) + }, + })) +} -export type ImportWizardStateModel = typeof ImportWizard +export type ImportWizardStateModel = ReturnType export type ImportWizardModel = Instance -export default ImportWizard +export default stateModelFactory diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/Row.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/Row.ts deleted file mode 100644 index 45445bb0e7..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/Row.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { types, getParent } from 'mobx-state-tree' - -const CellModel = types.model('SpreadsheetCell', { - text: types.string, - extendedData: types.maybe(types.frozen()), -}) - -const RowModel = types - .model('SpreadsheetRow', { - id: types.identifier, - cells: types.array(CellModel), - extendedData: types.maybe(types.frozen()), - isSelected: false, - }) - .actions(self => ({ - toggleSelect() { - self.isSelected = !self.isSelected - }, - unSelect() { - self.isSelected = false - }, - select() { - self.isSelected = true - }, - setExtendedData(data: unknown) { - self.extendedData = data - }, - })) - .views(self => ({ - get cellsWithDerived() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { columns } = getParent(self, 3) - let i = 0 - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return columns.map((column: { isDerived: boolean; expr: any }) => { - if (column.isDerived) { - return column.expr.evalSync({ - row: self, - }) - } - return self.cells[i++] - }) - }, - })) - -export default RowModel diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.ts deleted file mode 100644 index 40a88a9dd9..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { stringToJexlExpression } from '@jbrowse/core/util/jexlStrings' -import { getSession, getEnv } from '@jbrowse/core/util' -import { autorun } from 'mobx' -import { - addDisposer, - types, - getParent, - SnapshotIn, - Instance, -} from 'mobx-state-tree' - -// locals -import { ColumnTypes, AnyColumnType } from './ColumnDataTypes' -import StaticRowSetModel from './StaticRowSet' -import RowModel from './Row' - -type Row = Instance - -const ColumnDefinition = types - .model('ColumnDefinition', { - name: types.maybe(types.string), - dataType: types.optional(AnyColumnType, () => ({ - type: 'Text', - })), - // set to true if column is derived from other columns - // if the column is derived, each cell will have a - // `derivationFunction` that is called to get its value - isDerived: false, - // if this cell is derived from other cells, execute this function to get - // the value - derivationFunctionText: types.maybe(types.string), - }) - .views(self => ({ - get expr() { - if (self.isDerived) { - // compile this as a jexl expression - return stringToJexlExpression( - String(self.derivationFunctionText), - getEnv(self).pluginManager.jexl, - ) - } - return undefined - }, - })) - -type RowMenuPosition = { anchorEl: Element; rowNumber: string } | null - -/** - * #stateModel SpreadsheetViewSpreadsheet - * #category view - */ -function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars - -const Spreadsheet = types - .model('Spreadsheet', { - /** - * #property - */ - rowSet: types.optional(StaticRowSetModel, () => StaticRowSetModel.create()), - /** - * #property - */ - columns: types.array(ColumnDefinition), - /** - * #property - */ - columnDisplayOrder: types.array(types.number), - /** - * #property - */ - hasColumnNames: false, - /** - * #property - */ - sortColumns: types.array( - types - .model('SortColumns', { - columnNumber: types.number, - descending: false, - }) - .actions(self => ({ - switchDirection() { - self.descending = !self.descending - }, - })), - ), - - assemblyName: types.maybe(types.string), - }) - .volatile(() => ({ - defaultDataType: ColumnTypes.Text, - rowMenuPosition: null as RowMenuPosition, - isLoaded: false, - })) - .views(self => ({ - /** - * #getter - */ - get initialized() { - const session = getSession(self) - const name = self.assemblyName - return name ? session.assemblyManager.get(name)?.initialized : false - }, - /** - * #getter - */ - get hideRowSelection() { - // just delegates to parent - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return getParent(self).hideRowSelection - }, - - /** - * #getter - * list of data type names to be made available in the column - * dropdown menu - */ - get dataTypeChoices() { - const typeNames = Object.keys(ColumnTypes) as (keyof typeof ColumnTypes)[] - return typeNames.map(typeName => { - const dataType = ColumnTypes[typeName].create({ type: typeName }) - const { displayName, categoryName } = dataType - return { typeName, displayName, categoryName } - }) - }, - - /** - * #method - */ - rowSortingComparisonFunction(rowA: Row, rowB: Row) { - for (const { columnNumber, descending } of self.sortColumns) { - const { dataType } = self.columns[columnNumber] - const result = dataType.compare( - rowA.cellsWithDerived[columnNumber], - rowB.cellsWithDerived[columnNumber], - ) - if (result) { - return descending ? -result : result - } - } - return 0 - }, - })) - .actions(self => ({ - afterAttach() { - addDisposer( - self, - autorun(async () => { - const session = getSession(self) - const { assemblyManager } = session - try { - if (self.assemblyName) { - await assemblyManager.waitForAssembly(self.assemblyName) - this.setLoaded(true) - } - } catch (error) { - session.notify( - `failed to load assembly ${self.assemblyName} ${error}`, - 'error', - ) - } - }), - ) - }, - - /** - * #action - */ - setLoaded(flag: boolean) { - self.isLoaded = flag - }, - - /** - * #action - */ - setRowMenuPosition(newPosition: RowMenuPosition) { - self.rowMenuPosition = newPosition - }, - - /** - * #action - */ - setSortColumns(newSort: NonNullable>) { - if (newSort) { - // @ts-expect-error - self.sortColumns = newSort - } - }, - - /** - * #action - */ - setColumnType(columnNumber: number, newTypeName: string) { - self.columns[columnNumber].dataType = { type: newTypeName } - }, - - /** - * #action - */ - unselectAll() { - return self.rowSet.unselectAll() - }, - })) - -export type SpreadsheetStateModel = typeof Spreadsheet -export type SpreadsheetModel = Instance - -export default Spreadsheet diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.tsx b/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.tsx new file mode 100644 index 0000000000..bf0e0ef8f8 --- /dev/null +++ b/plugins/spreadsheet-view/src/SpreadsheetView/models/Spreadsheet.tsx @@ -0,0 +1,138 @@ +import React from 'react' +import { getSession, measureGridWidth } from '@jbrowse/core/util' +import { autorun } from 'mobx' +import { addDisposer, types, Instance } from 'mobx-state-tree' + +/** + * #stateModel SpreadsheetViewSpreadsheet + * #category view + */ +function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars + +export interface SpreadsheetData { + rows: Record[] + columns: string[] + CustomComponents?: Record< + string, + { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Component: React.FC + props: Record + } + > +} + +function stateModelFactory() { + return types + .model('Spreadsheet', { + /** + * #property + */ + assemblyName: types.maybe(types.string), + }) + .volatile(() => ({ + data: undefined as SpreadsheetData | undefined, + visible: {} as Record, + widths: {} as Record, + })) + .views(self => ({ + /** + * #getter + */ + get initialized() { + return !!self.data + }, + })) + .actions(self => ({ + /** + * #action + */ + setVisible(args: Record) { + self.visible = args + }, + /** + * #action + */ + setData(data?: SpreadsheetData, assemblyName?: string) { + self.data = data + self.assemblyName = assemblyName + }, + /** + * #action + */ + setWidths(w: Record) { + self.widths = w + }, + })) + .views(self => ({ + /** + * #getter + */ + get columns() { + const { data, widths } = self + return data?.columns.map(m => { + const res = data.CustomComponents?.[m] + return { + field: m, + width: widths[m], + renderCell: res + ? ({ + value, + row, + }: { + value?: string + row: Record + }) => ( + + ) + : undefined, + } + }) + }, + /** + * #getter + */ + get widthList() { + return Object.values(self.widths).map(f => f ?? 100) + }, + })) + + .actions(self => ({ + afterAttach() { + addDisposer( + self, + autorun(() => { + if (self.data) { + self.setVisible( + Object.fromEntries(self.data.columns.map(c => [c, true])), + ) + } + }), + ) + addDisposer( + self, + autorun(() => { + if (self.data) { + const { rows, columns } = self.data + const widths = Object.fromEntries( + columns + .filter(f => self.visible[f]) + .map(e => [e, measureGridWidth(rows.map(r => r[e]))]), + ) + self.setWidths(widths) + } + }), + ) + }, + })) +} + +export type SpreadsheetStateModel = ReturnType +export type SpreadsheetModel = Instance + +export default stateModelFactory diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.test.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.test.ts index 6b5b4b395a..562babc6d8 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.test.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.test.ts @@ -2,7 +2,7 @@ import SpreadsheetView from './SpreadsheetView' describe('Spreadsheet View mst model', () => { it('can instantiate with empty args', () => { - const view = SpreadsheetView.create({ type: 'SpreadsheetView' }) + const view = SpreadsheetView().create({ type: 'SpreadsheetView' }) expect(view).toBeTruthy() }) }) diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.ts index 510272c4b0..14f85a5746 100644 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.ts +++ b/plugins/spreadsheet-view/src/SpreadsheetView/models/SpreadsheetView.ts @@ -1,243 +1,143 @@ -import { - types, - getParent, - getEnv, - cast, - SnapshotIn, - Instance, -} from 'mobx-state-tree' +import { types, getParent, Instance } from 'mobx-state-tree' import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models' -import { readConfObject } from '@jbrowse/core/configuration' -import { MenuItem } from '@jbrowse/core/ui' import { getSession } from '@jbrowse/core/util' // icons -import DoneIcon from '@mui/icons-material/Done' import FolderOpenIcon from '@mui/icons-material/FolderOpen' -import SpreadsheetModel from './Spreadsheet' -import ImportWizardModel from './ImportWizard' -import FilterControlsModel from './FilterControls' +// locals +import spreadsheetModelFactory, { SpreadsheetData } from './Spreadsheet' +import importWizardFactory from './ImportWizard' -type Spreadsheet = Instance - -export type MenuItemWithDisabledCallback = MenuItem & { - disabled?: - | boolean - | (( - viewModel: unknown, - spreadsheetModel: Spreadsheet, - rowNumber: number, - row: Spreadsheet['rowSet']['rows'][0], - ) => boolean) -} - -const defaultRowMenuItems: MenuItemWithDisabledCallback[] = [ - { - label: 'Toggle select', - icon: DoneIcon, - onClick(_view: unknown, spreadsheet: Spreadsheet) { - const rowNumber = spreadsheet.rowMenuPosition?.rowNumber - if (rowNumber !== undefined) { - spreadsheet.rowSet.rows[+rowNumber - 1].toggleSelect() - } - }, - }, -] - -const minHeight = 40 const defaultHeight = 440 /** * #stateModel SpreadsheetView * #category view + * + * extends + * - [BaseViewModel](../baseviewmodel) */ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars -const model = types - .model('SpreadsheetView', { - /** - * #property - */ - type: types.literal('SpreadsheetView'), - /** - * #property - */ - offsetPx: 0, - /** - * #property - */ - height: types.optional( - types.refinement( - 'SpreadsheetViewHeight', - types.number, - n => n >= minHeight, - ), - defaultHeight, - ), - /** - * #property - */ - hideVerticalResizeHandle: false, - /** - * #property - */ - hideFilterControls: false, - /** - * #property - */ - filterControls: types.optional(FilterControlsModel, () => - FilterControlsModel.create({}), - ), - /** - * #property - * switch specifying whether we are showing the import wizard or the - * spreadsheet in our viewing area - */ - mode: types.optional( - types.enumeration('SpreadsheetViewMode', ['import', 'display']), - 'import', - ), - /** - * #property - */ - importWizard: types.optional(ImportWizardModel, () => - ImportWizardModel.create(), - ), - /** - * #property - */ - spreadsheet: types.maybe(SpreadsheetModel), - }) - .volatile(() => ({ - width: 400, - rowMenuItems: defaultRowMenuItems, - })) - .views(self => ({ - /** - * #getter - */ - get readyToDisplay() { - return !!self.spreadsheet && self.spreadsheet.isLoaded - }, - /** - * #getter - */ - get hideRowSelection() { - return !!getEnv(self).hideRowSelection - }, - /** - * #getter - */ - get outputRows() { - if (self.spreadsheet && self.spreadsheet.rowSet.isLoaded) { - const selected = self.spreadsheet.rowSet.selectedFilteredRows - if (selected.length) { - return selected - } - return self.spreadsheet.rowSet.sortedFilteredRows - } - return undefined - }, - /** - * #getter - */ - get assembly() { - const name = self.spreadsheet?.assemblyName - if (name) { - const assemblies = getSession(self).assemblies - return assemblies?.find(asm => readConfObject(asm, 'name') === name) - } - return undefined - }, - })) - .actions(self => ({ - /** - * #action - */ - setRowMenuItems(newItems: MenuItem[]) { - self.rowMenuItems = newItems - }, - /** - * #action - */ - setWidth(newWidth: number) { - self.width = newWidth - return self.width - }, - /** - * #action - */ - setHeight(newHeight: number) { - self.height = newHeight > minHeight ? newHeight : minHeight - return self.height - }, - /** - * #action - */ - resizeHeight(distance: number) { - const oldHeight = self.height - const newHeight = this.setHeight(self.height + distance) - return newHeight - oldHeight - }, - /** - * #action - */ - resizeWidth(distance: number) { - const oldWidth = self.width - const newWidth = this.setWidth(self.width + distance) - return newWidth - oldWidth - }, +function stateModelFactory() { + const ImportWizard = importWizardFactory() + const SpreadsheetModelType = spreadsheetModelFactory() + return types + .compose( + BaseViewModel, + types.model('SpreadsheetView', { + /** + * #property + */ + type: types.literal('SpreadsheetView'), + /** + * #property + */ + height: types.optional(types.number, defaultHeight), + /** + * #property + */ + hideVerticalResizeHandle: false, + /** + * #property + */ + importWizard: types.optional(ImportWizard, {}), + /** + * #property + */ + spreadsheet: types.optional(SpreadsheetModelType, {}), + }), + ) + .volatile(() => ({ + width: 400, + })) + .views(self => ({ + /** + * #getter + */ + get assemblyName() { + return self.spreadsheet.assemblyName + }, + /** + * #getter + */ + get initialized() { + return self.spreadsheet.initialized + }, + /** + * #getter + */ + get assembly() { + const name = self.spreadsheet.assemblyName + return name ? getSession(self).assemblyManager.get(name) : undefined + }, + })) + .actions(self => ({ + /** + * #action + */ + setWidth(newWidth: number) { + self.width = newWidth + return self.width + }, + /** + * #action + */ + setHeight(newHeight: number) { + self.height = newHeight + return self.height + }, + /** + * #action + */ + resizeHeight(distance: number) { + const oldHeight = self.height + const newHeight = this.setHeight(self.height + distance) + return newHeight - oldHeight + }, + /** + * #action + */ + resizeWidth(distance: number) { + const oldWidth = self.width + const newWidth = this.setWidth(self.width + distance) + return newWidth - oldWidth + }, - /** - * #action - * load a new spreadsheet and set our mode to display it - */ - displaySpreadsheet(spreadsheet: SnapshotIn) { - self.filterControls.clearAllFilters() - self.spreadsheet = cast(spreadsheet) - self.mode = 'display' - }, - /** - * #action - */ - setImportMode() { - self.mode = 'import' - }, - /** - * #action - */ - setDisplayMode() { - if (self.readyToDisplay) { - self.mode = 'display' - } - }, - /** - * #action - */ - closeView() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - getParent(self, 2).removeView(self) - }, - })) - .views(self => ({ - /** - * #method - */ - menuItems() { - return [ - { - label: 'Return to import form', - onClick: () => self.setImportMode(), - icon: FolderOpenIcon, - }, - ] - }, - })) + /** + * #action + * load a new spreadsheet and set our mode to display it + */ + displaySpreadsheet(spreadsheet?: SpreadsheetData, assemblyName?: string) { + self.spreadsheet.setData(spreadsheet, assemblyName) + }, -const SpreadsheetView = types.compose(BaseViewModel, model) + /** + * #action + */ + closeView() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + getParent(self, 2).removeView(self) + }, + })) + .views(self => ({ + /** + * #method + */ + menuItems() { + return [ + { + label: 'Return to import form', + onClick: () => self.displaySpreadsheet(), + icon: FolderOpenIcon, + }, + ] + }, + })) +} -export type SpreadsheetViewStateModel = typeof SpreadsheetView +export type SpreadsheetViewStateModel = ReturnType export type SpreadsheetViewModel = Instance -export default SpreadsheetView +export default stateModelFactory diff --git a/plugins/spreadsheet-view/src/SpreadsheetView/models/StaticRowSet.ts b/plugins/spreadsheet-view/src/SpreadsheetView/models/StaticRowSet.ts deleted file mode 100644 index 0ad5ff77e7..0000000000 --- a/plugins/spreadsheet-view/src/SpreadsheetView/models/StaticRowSet.ts +++ /dev/null @@ -1,65 +0,0 @@ -import RowModel from './Row' -import { types, getParent } from 'mobx-state-tree' - -const StaticRowModel = types - .model('StaticRowSet', { - isLoaded: types.literal(true), - rows: types.array(RowModel), - }) - .views(self => ({ - get count() { - return self.rows.length - }, - - get passingFiltersCount() { - return this.sortedFilteredRows.length - }, - - get selectedCount() { - return this.selectedRows.length - }, - - get selectedAndPassingFiltersCount() { - return this.selectedFilteredRows.length - }, - - get sortedRows() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const parent = getParent(self) - return [...self.rows].sort(parent.rowSortingComparisonFunction) - }, - - get selectedRows() { - return self.rows.filter(r => r.isSelected) - }, - - get selectedFilteredRows() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const sheet = getParent(self) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const view = getParent(sheet) - const { filterControls } = view - return this.selectedRows.filter(row => - filterControls.rowPassesFilters(sheet, row), - ) - }, - - // the set of all rows that pass the filters, sorted - get sortedFilteredRows() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const sheet = getParent(self) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const view = getParent(sheet) - const { filterControls } = view - return self.rows - .filter(row => filterControls.rowPassesFilters(sheet, row)) - .sort(sheet.rowSortingComparisonFunction) - }, - })) - .actions(self => ({ - unselectAll() { - self.rows.forEach(row => row.unSelect()) - }, - })) - -export default StaticRowModel diff --git a/plugins/sv-inspector/src/SvInspectorView/components/SvInspectorView.tsx b/plugins/sv-inspector/src/SvInspectorView/components/SvInspectorView.tsx index 63c1f75bff..f31e0339dd 100644 --- a/plugins/sv-inspector/src/SvInspectorView/components/SvInspectorView.tsx +++ b/plugins/sv-inspector/src/SvInspectorView/components/SvInspectorView.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { observer } from 'mobx-react' import { makeStyles } from 'tss-react/mui' import { ResizeHandle } from '@jbrowse/core/ui' @@ -41,36 +41,39 @@ const SvInspectorView = observer(function ({ const { SpreadsheetViewReactComponent, CircularViewReactComponent, - showCircularView, + spreadsheetView, + circularView, } = model + const [initialCircWidth, setInitialCircWidth] = useState(0) + const [initialSpreadsheetWidth, setInitialSpreadsheetWidth] = useState(0) return (
- +
- {showCircularView ? ( - <> - { - const ret1 = model.circularView.resizeWidth(-distance) - return model.spreadsheetView.resizeWidth(-ret1) - }} - vertical - flexbox - className={classes.resizeHandleVert} - /> -
- - -
- - ) : null} + { + circularView.setWidth(initialCircWidth + total) + spreadsheetView.setWidth(initialSpreadsheetWidth - total) + }} + onMouseDown={() => { + setInitialSpreadsheetWidth(spreadsheetView.width) + setInitialCircWidth(circularView.width) + }} + vertical + flexbox + className={classes.resizeHandleVert} + /> +
+ + +
+ ) : ( + + ) +}) + +export default SvInspectorViewContainer diff --git a/plugins/sv-inspector/src/SvInspectorView/index.ts b/plugins/sv-inspector/src/SvInspectorView/index.ts index 6815b69f72..181614d34d 100644 --- a/plugins/sv-inspector/src/SvInspectorView/index.ts +++ b/plugins/sv-inspector/src/SvInspectorView/index.ts @@ -8,7 +8,7 @@ import { IAnyStateTreeNode } from 'mobx-state-tree' import BreakpointSplitViewType from '@jbrowse/plugin-breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView' import { CircularViewModel } from '@jbrowse/plugin-circular-view' -function defaultOnChordClick( +async function defaultOnChordClick( feature: Feature, chordTrack: IAnyStateTreeNode, pluginManager: PluginManager, @@ -19,7 +19,12 @@ function defaultOnChordClick( const viewType = pluginManager.getViewType( 'BreakpointSplitView', ) as BreakpointSplitViewType - const viewSnapshot = viewType.snapshotFromBreakendFeature(feature, view) + const [assemblyName] = view.assemblyNames + const viewSnapshot = await viewType.snapshotFromBreakendFeature( + feature, + assemblyName, + session, + ) // try to center the offsetPx viewSnapshot.views[0].offsetPx -= view.width / 2 + 100 diff --git a/plugins/sv-inspector/src/SvInspectorView/models/SvInspectorView.ts b/plugins/sv-inspector/src/SvInspectorView/models/SvInspectorView.ts index 7f557ff2c7..8cf72a1c4d 100644 --- a/plugins/sv-inspector/src/SvInspectorView/models/SvInspectorView.ts +++ b/plugins/sv-inspector/src/SvInspectorView/models/SvInspectorView.ts @@ -4,22 +4,22 @@ import { types, getParent, addDisposer, Instance } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' import { getSession, Region } from '@jbrowse/core/util' -import { readConfObject } from '@jbrowse/core/configuration' +import { getConf } from '@jbrowse/core/configuration' import { ElementId } from '@jbrowse/core/util/types/mst' import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models' import { SpreadsheetViewStateModel } from '@jbrowse/plugin-spreadsheet-view' import { CircularViewStateModel } from '@jbrowse/plugin-circular-view' // icons -import OpenInNewIcon from '@mui/icons-material/OpenInNew' +// import OpenInNewIcon from '@mui/icons-material/OpenInNew' import FolderOpenIcon from '@mui/icons-material/FolderOpen' // locals -import { - canOpenBreakpointSplitViewFromTableRow, - openBreakpointSplitViewFromTableRow, - getFeatureForRow, -} from './breakpointSplitViewFromTableRow' +// import { +// canOpenBreakpointSplitViewFromTableRow, +// openBreakpointSplitViewFromTableRow, +// getFeatureForRow, +// } from './breakpointSplitViewFromTableRow' /** * #stateModel SvInspectorView @@ -41,7 +41,6 @@ function SvInspectorViewF(pluginManager: PluginManager) { const minHeight = 400 const defaultHeight = 550 - const headerHeight = 52 const circularViewOptionsBarHeight = 52 return types .compose( @@ -60,53 +59,40 @@ function SvInspectorViewF(pluginManager: PluginManager) { /** * #property */ - height: types.optional( - types.refinement( - 'SvInspectorViewHeight', - types.number, - n => n >= minHeight, - ), - defaultHeight, - ), + height: types.optional(types.number, defaultHeight), /** * #property */ onlyDisplayRelevantRegionsInCircularView: false, + /** * #property - * switch specifying whether we are showing the import wizard or the - * spreadsheet in our viewing area */ - mode: types.optional( - types.enumeration('SvInspectorViewMode', ['import', 'display']), - 'import', - ), + spreadsheetView: types.optional(SpreadsheetModel, { + hideVerticalResizeHandle: true, + type: 'SpreadsheetView', + }), /** * #property */ - spreadsheetView: types.optional(SpreadsheetModel, () => - SpreadsheetModel.create({ - type: 'SpreadsheetView', - hideVerticalResizeHandle: true, - }), - ), - /** - * #property - */ - circularView: types.optional(CircularModel, () => - CircularModel.create({ - type: 'CircularView', - hideVerticalResizeHandle: true, - hideTrackSelectorButton: true, - disableImportForm: true, - }), - ), + circularView: types.optional(CircularModel, { + type: 'CircularView', + hideVerticalResizeHandle: true, + hideTrackSelectorButton: true, + disableImportForm: true, + }), }), ) .volatile(() => ({ width: 800, })) .views(self => ({ + /** + * #getter + */ + get initialized() { + return self.spreadsheetView.initialized + }, /** * #getter */ @@ -118,26 +104,21 @@ function SvInspectorViewF(pluginManager: PluginManager) { * #getter */ get assemblyName() { - const { assembly } = self.spreadsheetView - return assembly ? readConfObject(assembly, 'name') : undefined + return self.spreadsheetView.assemblyName }, /** * #getter */ get showCircularView() { - return self.spreadsheetView.mode === 'display' + return self.spreadsheetView.initialized }, /** * #getter */ get features() { - const session = getSession(self) - const { spreadsheetView } = self - const { outputRows = [] } = spreadsheetView - return outputRows - .map((r, i) => getFeatureForRow(session, spreadsheetView, r, i)) - .filter(f => !!f) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return [] as any[] }, /** * #getter @@ -196,18 +177,6 @@ function SvInspectorViewF(pluginManager: PluginManager) { self.height = newHeight > minHeight ? newHeight : minHeight return self.height }, - /** - * #action - */ - setImportMode() { - self.spreadsheetView.setImportMode() - }, - /** - * #action - */ - setDisplayMode() { - self.spreadsheetView.setDisplayMode() - }, /** * #action */ @@ -225,7 +194,7 @@ function SvInspectorViewF(pluginManager: PluginManager) { * #action */ setOnlyDisplayRelevantRegionsInCircularView(val: boolean) { - self.onlyDisplayRelevantRegionsInCircularView = Boolean(val) + self.onlyDisplayRelevantRegionsInCircularView = val }, })) .views(self => ({ @@ -236,7 +205,9 @@ function SvInspectorViewF(pluginManager: PluginManager) { return [ { label: 'Return to import form', - onClick: () => self.setImportMode(), + onClick: () => { + self.spreadsheetView.speadsheet.setData(undefined) + }, icon: FolderOpenIcon, }, ] @@ -255,151 +226,122 @@ function SvInspectorViewF(pluginManager: PluginManager) { // synchronize subview widths addDisposer( self, - autorun( - () => { - const borderWidth = 1 - if (self.showCircularView) { - const spreadsheetWidth = Math.round(self.width * 0.66) - const circularViewWidth = self.width - spreadsheetWidth - self.spreadsheetView.setWidth(spreadsheetWidth - borderWidth) - self.circularView.setWidth(circularViewWidth) - } else { - self.spreadsheetView.setWidth(self.width) - } - }, - { name: 'SvInspectorView width binding' }, - ), + autorun(() => { + const borderWidth = 1 + if (self.showCircularView) { + const spreadsheetWidth = Math.round(self.width * 0.66) + const circularViewWidth = self.width - spreadsheetWidth + self.spreadsheetView.setWidth(spreadsheetWidth - borderWidth) + self.circularView.setWidth(circularViewWidth) + } else { + self.spreadsheetView.setWidth(self.width) + } + }), ) // synchronize subview heights addDisposer( self, - autorun( - () => { - self.spreadsheetView.setHeight(self.height - headerHeight) - self.circularView.setHeight( - self.height - headerHeight - circularViewOptionsBarHeight, - ) - }, - { name: 'SvInspectorView height binding' }, - ), + autorun(() => { + const { height } = self + self.spreadsheetView.setHeight(height) + self.circularView.setHeight(height - circularViewOptionsBarHeight) + }), ) - // bind circularview displayedRegions to spreadsheet assembly, mediated // by the onlyRelevantRegions toggle addDisposer( self, - autorun( - async () => { - const { - assemblyName, - onlyDisplayRelevantRegionsInCircularView, - circularView, - featureRefNames, - } = self + autorun(async () => { + const { + assemblyName, + onlyDisplayRelevantRegionsInCircularView, + circularView, + featureRefNames, + } = self + try { + if (!circularView.initialized) { + return + } const { tracks } = circularView const { assemblyManager } = getSession(self) if (!assemblyName) { return } - const asm = await assemblyManager.waitForAssembly(assemblyName) + const asm = assemblyManager.get(assemblyName) if (!asm) { return } - - const { getCanonicalRefName, regions = [] } = asm + const { regions = [] } = asm if (onlyDisplayRelevantRegionsInCircularView) { if (tracks.length === 1) { - try { - // canonicalize the store's ref names if necessary - const refSet = new Set( - featureRefNames.map(r => getCanonicalRefName(r) || r), - ) - - circularView.setDisplayedRegions( - clone(regions.filter(r => refSet.has(r.refName))), - ) - } catch (e) { - circularView.setError(e) - } + // canonicalize the store's ref names if necessary + const refSet = new Set( + featureRefNames.map(r => asm.getCanonicalRefName(r) || r), + ) + circularView.setDisplayedRegions( + clone(regions.filter(r => refSet.has(r.refName))), + ) } } else { circularView.setDisplayedRegions(regions) } - }, - { name: 'SvInspectorView displayed regions bind' }, - ), + } catch (e) { + console.error(e) + circularView.setError(e) + } + }), ) - // bind circularview tracks to our track snapshot view addDisposer( self, - reaction( - () => ({ - generatedTrackConf: self?.featuresCircularTrackConfiguration, - assemblyName: self?.assemblyName, - }), - data => { - if (!data) { - return - } - const { assemblyName, generatedTrackConf } = data - const { circularView } = self - // hide any visible tracks - circularView.tracks.forEach(t => - circularView.hideTrack(t.configuration.trackId), - ) - - // put our track in as the only track - if (assemblyName && generatedTrackConf) { - // @ts-expect-error - circularView.addTrackConf(generatedTrackConf, { - assemblyName, - }) - } - }, - { - name: 'SvInspectorView track configuration binding', - fireImmediately: true, - }, - ), + autorun(() => { + const { assemblyName, featuresCircularTrackConfiguration } = self + const { circularView } = self + // hide any visible tracks + circularView.tracks.forEach(t => + circularView.hideTrack(t.configuration.trackId), + ) + // put our track in as the only track + if (assemblyName && featuresCircularTrackConfiguration) { + circularView.addTrackConf(featuresCircularTrackConfiguration) + } + }), ) - - // bind spreadsheetView row menu actions to us + // // bind spreadsheetView row menu actions to us addDisposer( self, autorun(() => { - self.spreadsheetView.setRowMenuItems( - // these are the MenuItem entries for the row menu actions in the - // spreadsheet view. these are installed into the child - // SpreadsheetView using an autorun below - [ - { - label: 'Open split detail view', - icon: OpenInNewIcon, - // @ts-expect-error - disabled(spreadsheetView, spreadsheet, rowNumber, row) { - return !canOpenBreakpointSplitViewFromTableRow( - self, - spreadsheetView, - spreadsheet, - row, - rowNumber, - ) - }, - - // @ts-expect-error - onClick(spreadsheetView, spreadsheet, rowNumber, row) { - openBreakpointSplitViewFromTableRow( - self, - spreadsheetView, - spreadsheet, - row, - rowNumber, - ) - }, - }, - ], - ) + // self.spreadsheetView.setRowMenuItems( + // // these are the MenuItem entries for the row menu actions in the + // // spreadsheet view. these are installed into the child + // // SpreadsheetView using an autorun below + // [ + // { + // label: 'Open split detail view', + // icon: OpenInNewIcon, + // // @ts-expect-error + // disabled(spreadsheetView, spreadsheet, rowNumber, row) { + // return !canOpenBreakpointSplitViewFromTableRow( + // self, + // spreadsheetView, + // spreadsheet, + // row, + // rowNumber, + // ) + // }, + // // @ts-expect-error + // onClick(spreadsheetView, spreadsheet, rowNumber, row) { + // openBreakpointSplitViewFromTableRow( + // self, + // spreadsheetView, + // spreadsheet, + // row, + // rowNumber, + // ) + // }, + // }, + // ], + // ) }), ) }, diff --git a/plugins/sv-inspector/src/SvInspectorView/models/adhocFeatureUtils.js b/plugins/sv-inspector/src/SvInspectorView/models/adhocFeatureUtils.js deleted file mode 100644 index 8a7baf1420..0000000000 --- a/plugins/sv-inspector/src/SvInspectorView/models/adhocFeatureUtils.js +++ /dev/null @@ -1,152 +0,0 @@ -// this file contains the rather verbose functions for -// creating features from CSV/TSV lines -import { parseLocString } from '@jbrowse/core/util' - -export function makeAdHocFeature( - columns, - columnsAlreadyUsedInLocations, - row, - loc1, - loc2, - rowNumber, -) { - // load all the other data in the row into an `otherData` object - const otherData = {} - columns.forEach((column, columnNumber) => { - if (columnsAlreadyUsedInLocations.includes(columnNumber)) { - return - } - let { text } = row.cells[columnNumber] - if (column.dataType.type === 'Number') { - text = parseFloat(text) - } - otherData[column.name] = text - }) - - // make the final feature data out of otherData + the parsed locations - return { - ...otherData, - uniqueId: `sv-inspector-adhoc-${rowNumber}`, - refName: loc1.refName, - start: loc1.start, - end: loc1.end, - mate: { - refName: loc2.refName, - start: loc2.start, - end: loc2.end, - }, - } -} - -export function makeAdHocSvFeatureFromTwoLocations( - columns, - locationColumnNumbers, - row, - rowNumber, - isValidRefName, -) { - // use the first two locations we found (first according to *displayed* order) - const loc1 = parseLocString( - row.cells[locationColumnNumbers[0]].text, - isValidRefName, - ) - const loc2 = parseLocString( - row.cells[locationColumnNumbers[1]].text, - isValidRefName, - ) - - const columnsAlreadyUsedInLocations = [ - locationColumnNumbers[0], - locationColumnNumbers[1], - ] - - return makeAdHocFeature( - columns, - columnsAlreadyUsedInLocations, - row, - loc1, - loc2, - rowNumber, - ) -} - -export function makeAdHocSvFeatureFromTwoRefStartEndSets( - columns, - locRefColumnNumbers, - locStartColumnNumbers, - locEndColumnNumbers, - row, - rowNumber, -) { - const textOf = colno => row.cells[colno].text - const loc1 = { - refName: textOf(locRefColumnNumbers[0]), - start: parseInt(textOf(locStartColumnNumbers[0]), 10) - 1, - end: parseInt(textOf(locEndColumnNumbers[0]), 10), - } - const loc2 = { - refName: textOf(locRefColumnNumbers[1]), - start: parseInt(textOf(locStartColumnNumbers[1]), 10) - 1, - end: parseInt(textOf(locEndColumnNumbers[1]), 10), - } - const columnsAlreadyUsedInLocations = [ - locRefColumnNumbers[0], - locStartColumnNumbers[0], - locEndColumnNumbers[0], - locRefColumnNumbers[1], - locStartColumnNumbers[1], - locEndColumnNumbers[1], - ] - return makeAdHocFeature( - columns, - columnsAlreadyUsedInLocations, - row, - loc1, - loc2, - rowNumber, - ) -} - -// makes a feature data object (passed as `data` to a SimpleFeature constructor) -// out of table row if the row has 2 location columns. undefined if not -export function makeAdHocSvFeature(sheet, rowNumber, row, isValidRefName) { - const { columns, columnDisplayOrder } = sheet - const columnTypes = {} - columnDisplayOrder.forEach(columnNumber => { - const columnDefinition = columns[columnNumber] - if (!columnTypes[columnDefinition.dataType.type]) { - columnTypes[columnDefinition.dataType.type] = [] - } - columnTypes[columnDefinition.dataType.type].push(columnNumber) - }) - const locationColumnNumbers = columnTypes.LocString || [] - const locStartColumnNumbers = columnTypes.LocStart || [] - const locEndColumnNumbers = columnTypes.LocEnd || [] - const locRefColumnNumbers = columnTypes.LocRef || [] - - // if we have 2 or more columns of type location, make a feature from them - if (locationColumnNumbers.length >= 2) { - return makeAdHocSvFeatureFromTwoLocations( - columns, - locationColumnNumbers, - row, - rowNumber, - isValidRefName, - ) - } - if ( - locRefColumnNumbers.length >= 2 && - locStartColumnNumbers.length >= 2 && - locEndColumnNumbers.length >= 2 - ) { - return makeAdHocSvFeatureFromTwoRefStartEndSets( - columns, - locRefColumnNumbers, - locStartColumnNumbers, - locEndColumnNumbers, - row, - rowNumber, - ) - } - return undefined -} diff --git a/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.js b/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.js deleted file mode 100644 index 0b0eb8d429..0000000000 --- a/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.js +++ /dev/null @@ -1,84 +0,0 @@ -import { SimpleFeature, getEnv, getSession } from '@jbrowse/core/util' -import { makeAdHocSvFeature } from './adhocFeatureUtils' - -export function getFeatureForRow(session, spreadsheetView, row, rowNumber) { - return ( - row.extendedData?.vcfFeature || - row.extendedData?.feature || - makeAdHocSvFeature( - spreadsheetView.spreadsheet, - rowNumber, - row, - session.assemblyManager.isValidRefName, - ) - ) -} - -export function breakpointSplitViewSnapshotFromTableRow( - svInspectorView, - spreadsheetView, - spreadsheet, - row, - rowNumber, -) { - const { pluginManager } = getEnv(svInspectorView) - const session = getSession(spreadsheetView) - const featureData = getFeatureForRow(session, spreadsheet, row, rowNumber) - - if (featureData) { - const feature = new SimpleFeature(featureData) - session.setSelection(feature) - return pluginManager - .getViewType('BreakpointSplitView') - .snapshotFromBreakendFeature(feature, svInspectorView.circularView) - } - return undefined -} - -export function openBreakpointSplitViewFromTableRow( - svInspectorView, - spreadsheetView, - spreadsheet, - row, - rowNumber, -) { - const viewSnapshot = breakpointSplitViewSnapshotFromTableRow( - svInspectorView, - spreadsheetView, - spreadsheet, - row, - rowNumber, - ) - if (viewSnapshot) { - // try to center the offsetPx - const { circularView } = svInspectorView - viewSnapshot.views[0].offsetPx -= circularView.width / 2 + 100 - viewSnapshot.views[1].offsetPx -= circularView.width / 2 + 100 - - const session = getSession(spreadsheetView) - session.addView('BreakpointSplitView', viewSnapshot) - } -} - -export function canOpenBreakpointSplitViewFromTableRow( - svInspectorView, - spreadsheetView, - spreadsheet, - row, - rowNumber, -) { - try { - return Boolean( - breakpointSplitViewSnapshotFromTableRow( - svInspectorView, - spreadsheetView, - spreadsheet, - row, - rowNumber, - ), - ) - } catch (e) { - console.error('Unable to open breakpoint split view from table row', e) - return false - } -} diff --git a/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.ts b/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.ts new file mode 100644 index 0000000000..f5eaba0a1b --- /dev/null +++ b/plugins/sv-inspector/src/SvInspectorView/models/breakpointSplitViewFromTableRow.ts @@ -0,0 +1,88 @@ +// import { SimpleFeature, getEnv, getSession } from '@jbrowse/core/util' +// import { makeAdHocSvFeature } from './adhocFeatureUtils' +// import BreakpointSplitViewType from '@jbrowse/plugin-breakpoint-split-view/src/BreakpointSplitView/BreakpointSplitView' + +// export function getFeatureForRow(session, spreadsheetView, row, rowNumber) { +// return ( +// row.extendedData?.vcfFeature || +// row.extendedData?.feature || +// makeAdHocSvFeature( +// spreadsheetView.spreadsheet, +// rowNumber, +// row, +// session.assemblyManager.isValidRefName, +// ) +// ) +// } + +// export async function breakpointSplitViewSnapshotFromTableRow( +// svInspectorView, +// spreadsheetView, +// spreadsheet, +// row, +// rowNumber, +// ) { +// const { pluginManager } = getEnv(svInspectorView) +// const session = getSession(spreadsheetView) +// const featureData = getFeatureForRow(session, spreadsheet, row, rowNumber) + +// if (featureData) { +// const feature = new SimpleFeature(featureData) +// session.setSelection(feature) +// const { assemblyName } = spreadsheetView +// const viewType = pluginManager.getViewType( +// 'BreakpointSplitView', +// ) as BreakpointSplitViewType + +// return viewType.snapshotFromBreakendFeature(feature, assemblyName, session) +// } +// return undefined +// } + +// export function openBreakpointSplitViewFromTableRow( +// svInspectorView, +// spreadsheetView, +// spreadsheet, +// row, +// rowNumber, +// ) { +// const viewSnapshot = breakpointSplitViewSnapshotFromTableRow( +// svInspectorView, +// spreadsheetView, +// spreadsheet, +// row, +// rowNumber, +// ) +// if (viewSnapshot) { +// // try to center the offsetPx +// const { circularView } = svInspectorView +// viewSnapshot.views[0].offsetPx -= circularView.width / 2 + 100 +// viewSnapshot.views[1].offsetPx -= circularView.width / 2 + 100 + +// const session = getSession(spreadsheetView) +// session.addView('BreakpointSplitView', viewSnapshot) +// } +// } + +// export function canOpenBreakpointSplitViewFromTableRow( +// svInspectorView, +// spreadsheetView, +// spreadsheet, +// row, +// rowNumber, +// ) { +// try { +// return Boolean( +// breakpointSplitViewSnapshotFromTableRow( +// svInspectorView, +// spreadsheetView, +// spreadsheet, +// row, +// rowNumber, +// ), +// ) +// } catch (e) { +// console.error('Unable to open breakpoint split view from table row', e) +// return false +// } +// } diff --git a/plugins/variants/package.json b/plugins/variants/package.json index 7b310e0b07..a182d94945 100644 --- a/plugins/variants/package.json +++ b/plugins/variants/package.json @@ -41,7 +41,7 @@ "@gmod/tabix": "^1.5.6", "@gmod/vcf": "^5.0.9", "@mui/icons-material": "^5.0.2", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "generic-filehandle": "^3.0.0" }, "peerDependencies": { diff --git a/plugins/variants/src/LinearVariantDisplay/configSchema.ts b/plugins/variants/src/LinearVariantDisplay/configSchema.ts index 2a80ada3a0..ade30430e1 100644 --- a/plugins/variants/src/LinearVariantDisplay/configSchema.ts +++ b/plugins/variants/src/LinearVariantDisplay/configSchema.ts @@ -5,9 +5,12 @@ import { linearBasicDisplayConfigSchemaFactory } from '@jbrowse/plugin-linear-ge /** * #config LinearVariantDisplay - * mostly empty, this display type is very much - * like a `FeatureTrack` with a `LinearBasicDisplay` except it has a custom - * feature details widget + * + * mostly empty, this display type is very much like a `FeatureTrack` with a + * `LinearBasicDisplay` except it has a custom feature details widget + * + * extends + * - [LinearBasicDisplay](../linearbasicdisplay) */ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/plugins/variants/src/LinearVariantDisplay/model.ts b/plugins/variants/src/LinearVariantDisplay/model.ts index fc1ea0aab7..f55121a911 100644 --- a/plugins/variants/src/LinearVariantDisplay/model.ts +++ b/plugins/variants/src/LinearVariantDisplay/model.ts @@ -14,9 +14,8 @@ import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration' /** * #stateModel LinearVariantDisplay - * similar to basic display, but provides custom widget on feature click - * extends * + * extends * - [LinearBasicDisplay](../linearbasicdisplay) */ export default function stateModelFactory( diff --git a/plugins/variants/src/VariantFeatureWidget/VariantSampleGrid.tsx b/plugins/variants/src/VariantFeatureWidget/VariantSampleGrid.tsx index 331c172468..f7fcf956dd 100644 --- a/plugins/variants/src/VariantFeatureWidget/VariantSampleGrid.tsx +++ b/plugins/variants/src/VariantFeatureWidget/VariantSampleGrid.tsx @@ -143,7 +143,11 @@ export default function VariantSamples(props: { disableColumnMenu slots={{ toolbar: checked ? GridToolbar : null }} slotProps={{ - toolbar: { printOptions: { disableToolbarButton: true } }, + toolbar: { + printOptions: { + disableToolbarButton: true, + }, + }, }} />
diff --git a/plugins/wiggle/package.json b/plugins/wiggle/package.json index b5a2f1a498..d1bfb729a3 100644 --- a/plugins/wiggle/package.json +++ b/plugins/wiggle/package.json @@ -52,7 +52,7 @@ "@jbrowse/plugin-data-management": "^2.0.0", "@jbrowse/plugin-linear-genome-view": "^2.0.0", "@mui/material": "^5.0.0", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "mobx": "^6.0.0", "mobx-react": "^9.0.0", "mobx-state-tree": "^5.0.0", diff --git a/products/jbrowse-desktop/package.json b/products/jbrowse-desktop/package.json index 4c368bcc1b..f301100771 100644 --- a/products/jbrowse-desktop/package.json +++ b/products/jbrowse-desktop/package.json @@ -78,7 +78,7 @@ "@jbrowse/text-indexing": "^2.10.3", "@mui/icons-material": "^5.0.0", "@mui/material": "^5.10.17", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "clone": "^2.1.2", "deepmerge": "^4.2.2", "electron-debug": "^3.0.1", diff --git a/products/jbrowse-react-app/package.json b/products/jbrowse-react-app/package.json index 26be9be814..26f7d0b028 100644 --- a/products/jbrowse-react-app/package.json +++ b/products/jbrowse-react-app/package.json @@ -82,7 +82,7 @@ "@jbrowse/web-core": "^2.10.3", "@mui/icons-material": "^5.0.0", "@mui/material": "^5.10.17", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "base64-js": "^1.0.0", "clone": "^2.1.2", "copy-to-clipboard": "^3.3.1", diff --git a/products/jbrowse-web/package.json b/products/jbrowse-web/package.json index 42717514f5..4b350adb96 100644 --- a/products/jbrowse-web/package.json +++ b/products/jbrowse-web/package.json @@ -49,7 +49,7 @@ "@jbrowse/web-core": "^2.10.3", "@mui/icons-material": "^5.0.0", "@mui/material": "^5.10.17", - "@mui/x-data-grid": "^6.0.1", + "@mui/x-data-grid": "next", "base64-js": "^1.3.0", "clone": "^2.1.2", "copy-to-clipboard": "^3.3.1", diff --git a/yarn.lock b/yarn.lock index 6e676d024f..661d717cd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -110,523 +110,523 @@ tslib "^1.11.1" "@aws-sdk/client-cloudfront@^3.525.0": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudfront/-/client-cloudfront-3.529.1.tgz#3c5de61900f174a66321b2678c9101c7b993ec4f" - integrity sha512-bZMOxDimIelC0On0H37LUhFzlSxLtox/gQJmlXS/53mTZW/NYGacRmvW/IskHTtOH+Le4ggh+cDZfH0hgonPQg== + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudfront/-/client-cloudfront-3.533.0.tgz#f23476ce05aa698b4ea5cdb9e86550933049e31c" + integrity sha512-Ze9hoHyUrdwDaxgb5RRjelLiAe/46o9i9634mSk+7J8jguyAUYrUdMwBFuyiaBTsqb6qfCt3fKZ+WYV2a4j2Rw== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.529.1" - "@aws-sdk/core" "3.529.1" - "@aws-sdk/credential-provider-node" "3.529.1" - "@aws-sdk/middleware-host-header" "3.523.0" - "@aws-sdk/middleware-logger" "3.523.0" - "@aws-sdk/middleware-recursion-detection" "3.523.0" - "@aws-sdk/middleware-user-agent" "3.525.0" - "@aws-sdk/region-config-resolver" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@aws-sdk/util-user-agent-browser" "3.523.0" - "@aws-sdk/util-user-agent-node" "3.525.0" - "@aws-sdk/xml-builder" "3.523.0" - "@smithy/config-resolver" "^2.1.4" - "@smithy/core" "^1.3.5" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/hash-node" "^2.1.3" - "@smithy/invalid-dependency" "^2.1.3" - "@smithy/middleware-content-length" "^2.1.3" - "@smithy/middleware-endpoint" "^2.4.4" - "@smithy/middleware-retry" "^2.1.4" - "@smithy/middleware-serde" "^2.1.3" - "@smithy/middleware-stack" "^2.1.3" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/url-parser" "^2.1.3" - "@smithy/util-base64" "^2.1.1" + "@aws-sdk/client-sts" "3.533.0" + "@aws-sdk/core" "3.533.0" + "@aws-sdk/credential-provider-node" "3.533.0" + "@aws-sdk/middleware-host-header" "3.533.0" + "@aws-sdk/middleware-logger" "3.533.0" + "@aws-sdk/middleware-recursion-detection" "3.533.0" + "@aws-sdk/middleware-user-agent" "3.533.0" + "@aws-sdk/region-config-resolver" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@aws-sdk/util-user-agent-browser" "3.533.0" + "@aws-sdk/util-user-agent-node" "3.533.0" + "@aws-sdk/xml-builder" "3.533.0" + "@smithy/config-resolver" "^2.1.5" + "@smithy/core" "^1.3.8" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/hash-node" "^2.1.4" + "@smithy/invalid-dependency" "^2.1.4" + "@smithy/middleware-content-length" "^2.1.4" + "@smithy/middleware-endpoint" "^2.4.6" + "@smithy/middleware-retry" "^2.1.7" + "@smithy/middleware-serde" "^2.2.1" + "@smithy/middleware-stack" "^2.1.4" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/url-parser" "^2.1.4" + "@smithy/util-base64" "^2.2.1" "@smithy/util-body-length-browser" "^2.1.1" - "@smithy/util-body-length-node" "^2.2.1" - "@smithy/util-defaults-mode-browser" "^2.1.4" - "@smithy/util-defaults-mode-node" "^2.2.3" - "@smithy/util-endpoints" "^1.1.4" - "@smithy/util-middleware" "^2.1.3" - "@smithy/util-retry" "^2.1.3" - "@smithy/util-stream" "^2.1.3" - "@smithy/util-utf8" "^2.1.1" - "@smithy/util-waiter" "^2.1.3" + "@smithy/util-body-length-node" "^2.2.2" + "@smithy/util-defaults-mode-browser" "^2.1.7" + "@smithy/util-defaults-mode-node" "^2.2.7" + "@smithy/util-endpoints" "^1.1.5" + "@smithy/util-middleware" "^2.1.4" + "@smithy/util-retry" "^2.1.4" + "@smithy/util-stream" "^2.1.5" + "@smithy/util-utf8" "^2.2.0" + "@smithy/util-waiter" "^2.1.4" tslib "^2.5.0" "@aws-sdk/client-s3@^3.515.0": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.529.1.tgz#12be8ac86cd4676790957745b20bef9eb2c14247" - integrity sha512-ZpvyO4w3XWo/OjXLd3fm7CLcKUUYcyady9qzTnKKSnp8a2NqO7UvU/1zhYdm+yyy8TR/9t7sDy+q6AYd4Nsr8g== + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.533.0.tgz#37962aa66666a1884ec57fa8eea6ce14d716a3e0" + integrity sha512-KkzRS3Dt+dmNBe0a627RGr5aFqI+xw5UhqB+8Gr4r6Xy1/8sMGE+AXKVl/sYVbRQo/9aSCBak71baGE3XCm/pQ== dependencies: "@aws-crypto/sha1-browser" "3.0.0" "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.529.1" - "@aws-sdk/core" "3.529.1" - "@aws-sdk/credential-provider-node" "3.529.1" - "@aws-sdk/middleware-bucket-endpoint" "3.525.0" - "@aws-sdk/middleware-expect-continue" "3.523.0" - "@aws-sdk/middleware-flexible-checksums" "3.523.0" - "@aws-sdk/middleware-host-header" "3.523.0" - "@aws-sdk/middleware-location-constraint" "3.523.0" - "@aws-sdk/middleware-logger" "3.523.0" - "@aws-sdk/middleware-recursion-detection" "3.523.0" - "@aws-sdk/middleware-sdk-s3" "3.525.0" - "@aws-sdk/middleware-signing" "3.523.0" - "@aws-sdk/middleware-ssec" "3.523.0" - "@aws-sdk/middleware-user-agent" "3.525.0" - "@aws-sdk/region-config-resolver" "3.525.0" - "@aws-sdk/signature-v4-multi-region" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@aws-sdk/util-user-agent-browser" "3.523.0" - "@aws-sdk/util-user-agent-node" "3.525.0" - "@aws-sdk/xml-builder" "3.523.0" - "@smithy/config-resolver" "^2.1.4" - "@smithy/core" "^1.3.5" - "@smithy/eventstream-serde-browser" "^2.1.3" - "@smithy/eventstream-serde-config-resolver" "^2.1.3" - "@smithy/eventstream-serde-node" "^2.1.3" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/hash-blob-browser" "^2.1.3" - "@smithy/hash-node" "^2.1.3" - "@smithy/hash-stream-node" "^2.1.3" - "@smithy/invalid-dependency" "^2.1.3" - "@smithy/md5-js" "^2.1.3" - "@smithy/middleware-content-length" "^2.1.3" - "@smithy/middleware-endpoint" "^2.4.4" - "@smithy/middleware-retry" "^2.1.4" - "@smithy/middleware-serde" "^2.1.3" - "@smithy/middleware-stack" "^2.1.3" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/url-parser" "^2.1.3" - "@smithy/util-base64" "^2.1.1" + "@aws-sdk/client-sts" "3.533.0" + "@aws-sdk/core" "3.533.0" + "@aws-sdk/credential-provider-node" "3.533.0" + "@aws-sdk/middleware-bucket-endpoint" "3.533.0" + "@aws-sdk/middleware-expect-continue" "3.533.0" + "@aws-sdk/middleware-flexible-checksums" "3.533.0" + "@aws-sdk/middleware-host-header" "3.533.0" + "@aws-sdk/middleware-location-constraint" "3.533.0" + "@aws-sdk/middleware-logger" "3.533.0" + "@aws-sdk/middleware-recursion-detection" "3.533.0" + "@aws-sdk/middleware-sdk-s3" "3.533.0" + "@aws-sdk/middleware-signing" "3.533.0" + "@aws-sdk/middleware-ssec" "3.533.0" + "@aws-sdk/middleware-user-agent" "3.533.0" + "@aws-sdk/region-config-resolver" "3.533.0" + "@aws-sdk/signature-v4-multi-region" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@aws-sdk/util-user-agent-browser" "3.533.0" + "@aws-sdk/util-user-agent-node" "3.533.0" + "@aws-sdk/xml-builder" "3.533.0" + "@smithy/config-resolver" "^2.1.5" + "@smithy/core" "^1.3.8" + "@smithy/eventstream-serde-browser" "^2.1.4" + "@smithy/eventstream-serde-config-resolver" "^2.1.4" + "@smithy/eventstream-serde-node" "^2.1.4" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/hash-blob-browser" "^2.1.5" + "@smithy/hash-node" "^2.1.4" + "@smithy/hash-stream-node" "^2.1.4" + "@smithy/invalid-dependency" "^2.1.4" + "@smithy/md5-js" "^2.1.4" + "@smithy/middleware-content-length" "^2.1.4" + "@smithy/middleware-endpoint" "^2.4.6" + "@smithy/middleware-retry" "^2.1.7" + "@smithy/middleware-serde" "^2.2.1" + "@smithy/middleware-stack" "^2.1.4" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/url-parser" "^2.1.4" + "@smithy/util-base64" "^2.2.1" "@smithy/util-body-length-browser" "^2.1.1" - "@smithy/util-body-length-node" "^2.2.1" - "@smithy/util-defaults-mode-browser" "^2.1.4" - "@smithy/util-defaults-mode-node" "^2.2.3" - "@smithy/util-endpoints" "^1.1.4" - "@smithy/util-retry" "^2.1.3" - "@smithy/util-stream" "^2.1.3" - "@smithy/util-utf8" "^2.1.1" - "@smithy/util-waiter" "^2.1.3" + "@smithy/util-body-length-node" "^2.2.2" + "@smithy/util-defaults-mode-browser" "^2.1.7" + "@smithy/util-defaults-mode-node" "^2.2.7" + "@smithy/util-endpoints" "^1.1.5" + "@smithy/util-retry" "^2.1.4" + "@smithy/util-stream" "^2.1.5" + "@smithy/util-utf8" "^2.2.0" + "@smithy/util-waiter" "^2.1.4" tslib "^2.5.0" -"@aws-sdk/client-sso-oidc@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.529.1.tgz#40440af993f0d2c1d7fdc3ef5840867a223e773b" - integrity sha512-bimxCWAvRnVcluWEQeadXvHyzWlBWsuGVligsaVZaGF0TLSn0eLpzpN9B1EhHzTf7m0Kh/wGtPSH1JxO6PpB+A== +"@aws-sdk/client-sso-oidc@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.533.0.tgz#a4a3ad2c50a8852119c28b7dc5aa43b6aac9570f" + integrity sha512-jxG+L81bcuH6JJkls+VSRsOTpixvNEQ8clpUglal/XC+qiV09yZUnOi+Fxf2q7OAB7bfM9DB3Wy8YwbhaR2wYg== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.529.1" - "@aws-sdk/core" "3.529.1" - "@aws-sdk/middleware-host-header" "3.523.0" - "@aws-sdk/middleware-logger" "3.523.0" - "@aws-sdk/middleware-recursion-detection" "3.523.0" - "@aws-sdk/middleware-user-agent" "3.525.0" - "@aws-sdk/region-config-resolver" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@aws-sdk/util-user-agent-browser" "3.523.0" - "@aws-sdk/util-user-agent-node" "3.525.0" - "@smithy/config-resolver" "^2.1.4" - "@smithy/core" "^1.3.5" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/hash-node" "^2.1.3" - "@smithy/invalid-dependency" "^2.1.3" - "@smithy/middleware-content-length" "^2.1.3" - "@smithy/middleware-endpoint" "^2.4.4" - "@smithy/middleware-retry" "^2.1.4" - "@smithy/middleware-serde" "^2.1.3" - "@smithy/middleware-stack" "^2.1.3" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/url-parser" "^2.1.3" - "@smithy/util-base64" "^2.1.1" + "@aws-sdk/client-sts" "3.533.0" + "@aws-sdk/core" "3.533.0" + "@aws-sdk/middleware-host-header" "3.533.0" + "@aws-sdk/middleware-logger" "3.533.0" + "@aws-sdk/middleware-recursion-detection" "3.533.0" + "@aws-sdk/middleware-user-agent" "3.533.0" + "@aws-sdk/region-config-resolver" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@aws-sdk/util-user-agent-browser" "3.533.0" + "@aws-sdk/util-user-agent-node" "3.533.0" + "@smithy/config-resolver" "^2.1.5" + "@smithy/core" "^1.3.8" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/hash-node" "^2.1.4" + "@smithy/invalid-dependency" "^2.1.4" + "@smithy/middleware-content-length" "^2.1.4" + "@smithy/middleware-endpoint" "^2.4.6" + "@smithy/middleware-retry" "^2.1.7" + "@smithy/middleware-serde" "^2.2.1" + "@smithy/middleware-stack" "^2.1.4" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/url-parser" "^2.1.4" + "@smithy/util-base64" "^2.2.1" "@smithy/util-body-length-browser" "^2.1.1" - "@smithy/util-body-length-node" "^2.2.1" - "@smithy/util-defaults-mode-browser" "^2.1.4" - "@smithy/util-defaults-mode-node" "^2.2.3" - "@smithy/util-endpoints" "^1.1.4" - "@smithy/util-middleware" "^2.1.3" - "@smithy/util-retry" "^2.1.3" - "@smithy/util-utf8" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.2" + "@smithy/util-defaults-mode-browser" "^2.1.7" + "@smithy/util-defaults-mode-node" "^2.2.7" + "@smithy/util-endpoints" "^1.1.5" + "@smithy/util-middleware" "^2.1.4" + "@smithy/util-retry" "^2.1.4" + "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@aws-sdk/client-sso@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.529.1.tgz#012a4c1861d586c2a96bef5e442bd505bdf3ca5f" - integrity sha512-KT1U/ZNjDhVv2ZgjzaeAn9VM7l667yeSguMrRYC8qk5h91/61MbjZypi6eOuKuVM+0fsQvzKScTQz0Lio0eYag== +"@aws-sdk/client-sso@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.533.0.tgz#ff0fd1631ed26d577e4ba28601699131d3c285e0" + integrity sha512-qO+PCEM3fGS/3uBJQjQ01oAI+ashN0CHTJF8X0h3ycVsv3VAAYrpZigpylOOgv7c253s7VrSwjvdKIE8yTbelw== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/core" "3.529.1" - "@aws-sdk/middleware-host-header" "3.523.0" - "@aws-sdk/middleware-logger" "3.523.0" - "@aws-sdk/middleware-recursion-detection" "3.523.0" - "@aws-sdk/middleware-user-agent" "3.525.0" - "@aws-sdk/region-config-resolver" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@aws-sdk/util-user-agent-browser" "3.523.0" - "@aws-sdk/util-user-agent-node" "3.525.0" - "@smithy/config-resolver" "^2.1.4" - "@smithy/core" "^1.3.5" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/hash-node" "^2.1.3" - "@smithy/invalid-dependency" "^2.1.3" - "@smithy/middleware-content-length" "^2.1.3" - "@smithy/middleware-endpoint" "^2.4.4" - "@smithy/middleware-retry" "^2.1.4" - "@smithy/middleware-serde" "^2.1.3" - "@smithy/middleware-stack" "^2.1.3" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/url-parser" "^2.1.3" - "@smithy/util-base64" "^2.1.1" + "@aws-sdk/core" "3.533.0" + "@aws-sdk/middleware-host-header" "3.533.0" + "@aws-sdk/middleware-logger" "3.533.0" + "@aws-sdk/middleware-recursion-detection" "3.533.0" + "@aws-sdk/middleware-user-agent" "3.533.0" + "@aws-sdk/region-config-resolver" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@aws-sdk/util-user-agent-browser" "3.533.0" + "@aws-sdk/util-user-agent-node" "3.533.0" + "@smithy/config-resolver" "^2.1.5" + "@smithy/core" "^1.3.8" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/hash-node" "^2.1.4" + "@smithy/invalid-dependency" "^2.1.4" + "@smithy/middleware-content-length" "^2.1.4" + "@smithy/middleware-endpoint" "^2.4.6" + "@smithy/middleware-retry" "^2.1.7" + "@smithy/middleware-serde" "^2.2.1" + "@smithy/middleware-stack" "^2.1.4" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/url-parser" "^2.1.4" + "@smithy/util-base64" "^2.2.1" "@smithy/util-body-length-browser" "^2.1.1" - "@smithy/util-body-length-node" "^2.2.1" - "@smithy/util-defaults-mode-browser" "^2.1.4" - "@smithy/util-defaults-mode-node" "^2.2.3" - "@smithy/util-endpoints" "^1.1.4" - "@smithy/util-middleware" "^2.1.3" - "@smithy/util-retry" "^2.1.3" - "@smithy/util-utf8" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.2" + "@smithy/util-defaults-mode-browser" "^2.1.7" + "@smithy/util-defaults-mode-node" "^2.2.7" + "@smithy/util-endpoints" "^1.1.5" + "@smithy/util-middleware" "^2.1.4" + "@smithy/util-retry" "^2.1.4" + "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@aws-sdk/client-sts@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.529.1.tgz#ad57e10868f5a89557dada02d2f951989e277ec6" - integrity sha512-Rvk2Sr3MACQTOtngUU+omlf4E17k47dRVXR7OFRD6Ow5iGgC9tkN2q/ExDPW/ktPOmM0lSgzWyQ6/PC/Zq3HUg== +"@aws-sdk/client-sts@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.533.0.tgz#a792fc321509dee0b104a3470653663315068bce" + integrity sha512-Z/z76T/pEq0DsBpoyWSMQdS7R6IRpq2ZV6dfZwr+HZ2vho2Icd70nIxwiNzZxaV16aVIhu5/l/5v5Ns9ZCfyOA== dependencies: "@aws-crypto/sha256-browser" "3.0.0" "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/core" "3.529.1" - "@aws-sdk/middleware-host-header" "3.523.0" - "@aws-sdk/middleware-logger" "3.523.0" - "@aws-sdk/middleware-recursion-detection" "3.523.0" - "@aws-sdk/middleware-user-agent" "3.525.0" - "@aws-sdk/region-config-resolver" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@aws-sdk/util-user-agent-browser" "3.523.0" - "@aws-sdk/util-user-agent-node" "3.525.0" - "@smithy/config-resolver" "^2.1.4" - "@smithy/core" "^1.3.5" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/hash-node" "^2.1.3" - "@smithy/invalid-dependency" "^2.1.3" - "@smithy/middleware-content-length" "^2.1.3" - "@smithy/middleware-endpoint" "^2.4.4" - "@smithy/middleware-retry" "^2.1.4" - "@smithy/middleware-serde" "^2.1.3" - "@smithy/middleware-stack" "^2.1.3" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/url-parser" "^2.1.3" - "@smithy/util-base64" "^2.1.1" + "@aws-sdk/core" "3.533.0" + "@aws-sdk/middleware-host-header" "3.533.0" + "@aws-sdk/middleware-logger" "3.533.0" + "@aws-sdk/middleware-recursion-detection" "3.533.0" + "@aws-sdk/middleware-user-agent" "3.533.0" + "@aws-sdk/region-config-resolver" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@aws-sdk/util-user-agent-browser" "3.533.0" + "@aws-sdk/util-user-agent-node" "3.533.0" + "@smithy/config-resolver" "^2.1.5" + "@smithy/core" "^1.3.8" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/hash-node" "^2.1.4" + "@smithy/invalid-dependency" "^2.1.4" + "@smithy/middleware-content-length" "^2.1.4" + "@smithy/middleware-endpoint" "^2.4.6" + "@smithy/middleware-retry" "^2.1.7" + "@smithy/middleware-serde" "^2.2.1" + "@smithy/middleware-stack" "^2.1.4" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/url-parser" "^2.1.4" + "@smithy/util-base64" "^2.2.1" "@smithy/util-body-length-browser" "^2.1.1" - "@smithy/util-body-length-node" "^2.2.1" - "@smithy/util-defaults-mode-browser" "^2.1.4" - "@smithy/util-defaults-mode-node" "^2.2.3" - "@smithy/util-endpoints" "^1.1.4" - "@smithy/util-middleware" "^2.1.3" - "@smithy/util-retry" "^2.1.3" - "@smithy/util-utf8" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.2" + "@smithy/util-defaults-mode-browser" "^2.1.7" + "@smithy/util-defaults-mode-node" "^2.2.7" + "@smithy/util-endpoints" "^1.1.5" + "@smithy/util-middleware" "^2.1.4" + "@smithy/util-retry" "^2.1.4" + "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@aws-sdk/core@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.529.1.tgz#378bf215f3bf407158b4743e4d94bed4fa2e2594" - integrity sha512-Sj42sYPfaL9PHvvciMICxhyrDZjqnnvFbPKDmQL5aFKyXy122qx7RdVqUOQERDmMQfvJh6+0W1zQlLnre89q4Q== +"@aws-sdk/core@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.533.0.tgz#222dd8eed4fe93904462dc094d35bc67f5eaaac7" + integrity sha512-m3jq9WJbIvlDOnN5KG5U/org1MwOwXzfyU2Rr/48rRey6/+kNSm5QzYZMT0Htsk8V5Ukp325dzs/XR8DyO9uMQ== dependencies: - "@smithy/core" "^1.3.5" - "@smithy/protocol-http" "^3.2.1" - "@smithy/signature-v4" "^2.1.3" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" + "@smithy/core" "^1.3.8" + "@smithy/protocol-http" "^3.2.2" + "@smithy/signature-v4" "^2.1.4" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" fast-xml-parser "4.2.5" tslib "^2.5.0" -"@aws-sdk/credential-provider-env@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.523.0.tgz#4bc04b32c15ff7237ba1de866b96ccea24e433c7" - integrity sha512-Y6DWdH6/OuMDoNKVzZlNeBc6f1Yjk1lYMjANKpIhMbkRCvLJw/PYZKOZa8WpXbTYdgg9XLjKybnLIb3ww3uuzA== +"@aws-sdk/credential-provider-env@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.533.0.tgz#d246b17f1206cf77d4d55651116b3b0d637a45e9" + integrity sha512-opj7hfcCeNosSmxfJkJr0Af0aSxlqwkdCPlLEvOTwbHmdkovD+SyEpaI4/0ild0syZDMifuJAU6I6K0ukbcm3g== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-http@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.525.0.tgz#3a785ea8724200596ad1a48cf8485658401eb589" - integrity sha512-RNWQGuSBQZhl3iqklOslUEfQ4br1V3DCPboMpeqFtddUWJV3m2u2extFur9/4Uy+1EHVF120IwZUKtd8dF+ibw== - dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/fetch-http-handler" "^2.4.3" - "@smithy/node-http-handler" "^2.4.1" - "@smithy/property-provider" "^2.1.3" - "@smithy/protocol-http" "^3.2.1" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" - "@smithy/util-stream" "^2.1.3" +"@aws-sdk/credential-provider-http@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.533.0.tgz#bf403804e956d32ea405f7dd3f2cbf9c9a089fe8" + integrity sha512-m5z3V9MRO77t1CF312QKaQSfYG2MM/USqZ1Jj6srb+kJBX+GuVXbkc0+NwrpG5+j8Iukgxy1tms+0p3Wjatu6A== + dependencies: + "@aws-sdk/types" "3.533.0" + "@smithy/fetch-http-handler" "^2.4.5" + "@smithy/node-http-handler" "^2.4.3" + "@smithy/property-provider" "^2.1.4" + "@smithy/protocol-http" "^3.2.2" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" + "@smithy/util-stream" "^2.1.5" tslib "^2.5.0" -"@aws-sdk/credential-provider-ini@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.529.1.tgz#b2ca21746585079ab9cc0e7d212417ee92cc83e2" - integrity sha512-RjHsuTvHIwXG7a/3ERexemiD3c9riKMCZQzY2/b0Gg0ButEVbBcMfERtUzWmQ0V4ufe/PEZjP68MH1gupcoF9A== - dependencies: - "@aws-sdk/client-sts" "3.529.1" - "@aws-sdk/credential-provider-env" "3.523.0" - "@aws-sdk/credential-provider-process" "3.523.0" - "@aws-sdk/credential-provider-sso" "3.529.1" - "@aws-sdk/credential-provider-web-identity" "3.529.1" - "@aws-sdk/types" "3.523.0" - "@smithy/credential-provider-imds" "^2.2.3" - "@smithy/property-provider" "^2.1.3" - "@smithy/shared-ini-file-loader" "^2.3.3" - "@smithy/types" "^2.10.1" +"@aws-sdk/credential-provider-ini@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.533.0.tgz#3018cf2d26b0153a3599a375037220254ca0506c" + integrity sha512-xQ7TMY+j99zxOph+LJJhGPIav6RpydESZgIp5cp/pFY4Liwe5e84M7SaCgkFLck2HE9s7MhP42c8xmC6u9PIuw== + dependencies: + "@aws-sdk/client-sts" "3.533.0" + "@aws-sdk/credential-provider-env" "3.533.0" + "@aws-sdk/credential-provider-process" "3.533.0" + "@aws-sdk/credential-provider-sso" "3.533.0" + "@aws-sdk/credential-provider-web-identity" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/credential-provider-imds" "^2.2.6" + "@smithy/property-provider" "^2.1.4" + "@smithy/shared-ini-file-loader" "^2.3.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-node@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.529.1.tgz#4c53c47320cf440be55786287a7d33b7364d2316" - integrity sha512-mvY7F3dMmk/0dZOCfl5sUI1bG0osureBjxhELGCF0KkJqhWI0hIzh8UnPkYytSg3vdc97CMv7pTcozxrdA3b0g== - dependencies: - "@aws-sdk/credential-provider-env" "3.523.0" - "@aws-sdk/credential-provider-http" "3.525.0" - "@aws-sdk/credential-provider-ini" "3.529.1" - "@aws-sdk/credential-provider-process" "3.523.0" - "@aws-sdk/credential-provider-sso" "3.529.1" - "@aws-sdk/credential-provider-web-identity" "3.529.1" - "@aws-sdk/types" "3.523.0" - "@smithy/credential-provider-imds" "^2.2.3" - "@smithy/property-provider" "^2.1.3" - "@smithy/shared-ini-file-loader" "^2.3.3" - "@smithy/types" "^2.10.1" +"@aws-sdk/credential-provider-node@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.533.0.tgz#96d6fcbef83520bd270a5797d9ca8ba7517e05d0" + integrity sha512-Tn2grwFfFDLV5Hr8sZvZY5pjEmDUOm/e+ipnyxxCBB/K7t2ru2R4jG/RUa6+dZXSH/pi+TNte9cYq/Lx2Szjlw== + dependencies: + "@aws-sdk/credential-provider-env" "3.533.0" + "@aws-sdk/credential-provider-http" "3.533.0" + "@aws-sdk/credential-provider-ini" "3.533.0" + "@aws-sdk/credential-provider-process" "3.533.0" + "@aws-sdk/credential-provider-sso" "3.533.0" + "@aws-sdk/credential-provider-web-identity" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/credential-provider-imds" "^2.2.6" + "@smithy/property-provider" "^2.1.4" + "@smithy/shared-ini-file-loader" "^2.3.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-process@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.523.0.tgz#8cf85637f5075065a164d008f392d3ae3539ea23" - integrity sha512-f0LP9KlFmMvPWdKeUKYlZ6FkQAECUeZMmISsv6NKtvPCI9e4O4cLTeR09telwDK8P0HrgcRuZfXM7E30m8re0Q== +"@aws-sdk/credential-provider-process@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.533.0.tgz#e7fa3e721fb7e82fd9c1c33dd9b224b16e5cf8b9" + integrity sha512-9Iuhp8dhMqEv7kPsZlc9KFhC5XvuB/jFv3IZoTtRgbACW4cdxng7OwJEWdeZGrcjy9x40Tc2DT9KcmCE895KpQ== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/shared-ini-file-loader" "^2.3.3" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/shared-ini-file-loader" "^2.3.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-sso@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.529.1.tgz#ee685cfbb87d2aa138d46d6c115adac850e78ba7" - integrity sha512-KFMKkaoTGDgSJG+o9Ii7AglWG5JQeF6IFw9cXLMwDdIrp3KUmRcUIqe0cjOoCqeQEDGy0VHsimHmKKJ3894i/A== - dependencies: - "@aws-sdk/client-sso" "3.529.1" - "@aws-sdk/token-providers" "3.529.1" - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/shared-ini-file-loader" "^2.3.3" - "@smithy/types" "^2.10.1" +"@aws-sdk/credential-provider-sso@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.533.0.tgz#ede23bde4e871ad1c3a234c7b364ed3c010d851a" + integrity sha512-1zPZQnFUoZ0fWuLPW2X2L3jPKyd+qW8VzFO1k26oX1KJuiEZJzoYbfap08soy6vhFI+n4NfsAgvoA1IMsqG0Pg== + dependencies: + "@aws-sdk/client-sso" "3.533.0" + "@aws-sdk/token-providers" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/shared-ini-file-loader" "^2.3.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/credential-provider-web-identity@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.529.1.tgz#84fe00b22b4a4377a637c5ee2c628ba3a696152a" - integrity sha512-AGuZDOKN+AttjwTjrF47WLqzeEut2YynyxjkXZhxZF/xn8i5Y51kUAUdXsXw1bgR25pAeXQIdhsrQlRa1Pm5kw== +"@aws-sdk/credential-provider-web-identity@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.533.0.tgz#f7c8c27e07d881ac9b702f14bad0849ba9f9e184" + integrity sha512-utemXrFmvFxBvX+WCznlh5wGdXRIfwEyeNIDFs+WLRn8NIR/6gqCipi7rlC9ZbFFkBhkCTssa6+ruXG+kUQcMg== dependencies: - "@aws-sdk/client-sts" "3.529.1" - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/types" "^2.10.1" + "@aws-sdk/client-sts" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-bucket-endpoint@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.525.0.tgz#f354fbc0b4a55b0b13ab704672382c5aeafae0b3" - integrity sha512-nYfQ2Xspfef7j8mZO7varUWLPH6HQlXateH7tBVtBNUAazyQE4UJEvC0fbQ+Y01e+FKlirim/m2umkdMXqAlTg== +"@aws-sdk/middleware-bucket-endpoint@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.533.0.tgz#1f67477a84192ad88df0885531528c1f753d3eb8" + integrity sha512-k1KJe8SEDfgXpEBlMmlCBHhUFJekL5pEEfwbcS/cfjfcZIWrLlfTqjnA0+TKrB6EO/8ZZiKaxHrTjhft5AMcqA== dependencies: - "@aws-sdk/types" "3.523.0" + "@aws-sdk/types" "3.533.0" "@aws-sdk/util-arn-parser" "3.495.0" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" "@smithy/util-config-provider" "^2.2.1" tslib "^2.5.0" -"@aws-sdk/middleware-expect-continue@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.523.0.tgz#9db5a9dd54a41fb71d40e744ff800a697a82e969" - integrity sha512-E5DyRAHU39VHaAlQLqXYS/IKpgk3vsryuU6kkOcIIK8Dgw0a2tjoh5AOCaNa8pD+KgAGrFp35JIMSX1zui5diA== +"@aws-sdk/middleware-expect-continue@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.533.0.tgz#59ab0d537f366a62ec5854e06ee70eac216ccb2d" + integrity sha512-a9NXE+4DwFQgv9cS+YYg7b8ugBatATkCe/cunFRrTpqMXmIpHE8i4zDEoCZVCi4YMkLaphC/WBAhXNl4T6w8pg== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-flexible-checksums@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.523.0.tgz#7f0e4a98aac00f08b154cb283d33a36993dd730d" - integrity sha512-lIa1TdWY9q4zsDFarfSnYcdrwPR+nypaU4n6hb95i620/1F5M5s6H8P0hYtwTNNvx+slrR8F3VBML9pjBtzAHw== +"@aws-sdk/middleware-flexible-checksums@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.533.0.tgz#106c981f503accad443f2896793cea066f2b4dc6" + integrity sha512-vvD2XPXbR4PKf3/VSx6dzB+1iWzpyy8uGlt1p1y5uvQRetbmCAnzchUd5xn18MUr85MlOKKBfykYzA7gTiVgSA== dependencies: "@aws-crypto/crc32" "3.0.0" "@aws-crypto/crc32c" "3.0.0" - "@aws-sdk/types" "3.523.0" + "@aws-sdk/types" "3.533.0" "@smithy/is-array-buffer" "^2.1.1" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" - "@smithy/util-utf8" "^2.1.1" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" + "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@aws-sdk/middleware-host-header@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.523.0.tgz#9aaa29edd668905eed8ee8af482b96162dafdeb1" - integrity sha512-4g3q7Ta9sdD9TMUuohBAkbx/e3I/juTqfKi7TPgP+8jxcYX72MOsgemAMHuP6CX27eyj4dpvjH+w4SIVDiDSmg== +"@aws-sdk/middleware-host-header@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.533.0.tgz#227b785e632a92ec9e6a261a523c9e7d215af9fd" + integrity sha512-y9JaPjvz3pk4DZcFB6Nud//Hc6y4BkkSwiGXfthwFv5kxfaaksHKd8smDjL3RUPqDKl8AI9vxHzTz1UrQQkpQw== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-location-constraint@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.523.0.tgz#c5b2395119ece973773f80f67eef43603d159c12" - integrity sha512-1QAUXX3U0jkARnU0yyjk81EO4Uw5dCeQOtvUY5s3bUOHatR3ThosQeIr6y9BCsbXHzNnDe1ytCjqAPyo8r/bYw== +"@aws-sdk/middleware-location-constraint@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.533.0.tgz#6a925ebc9a7a5e7f164c4c2cb12969cdea3eed19" + integrity sha512-cZPH7L+aw9uGSIbwWmemIHHUPZ43FYwSx/hnWC8asLs3zLMD26V9TyQFAASlUk9jrzxqJg/SBaxfPHjBT3kg9w== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-logger@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.523.0.tgz#ad61bfdd73b5983ab8a8926b9c01825bc048babf" - integrity sha512-PeDNJNhfiaZx54LBaLTXzUaJ9LXFwDFFIksipjqjvxMafnoVcQwKbkoPUWLe5ytT4nnL1LogD3s55mERFUsnwg== +"@aws-sdk/middleware-logger@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.533.0.tgz#259915eceaf158f00b9a4f925c442bde3d6462af" + integrity sha512-W+ou4YgqnHn/xVNcBgfwAUCtXTHGJjjsFffdt69s1Tb7rP5U4gXnl8wHHADajy9tXiKK48fRc2SGF42EthjQIA== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-recursion-detection@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.523.0.tgz#21d9ec52700545d7935d6c943cb40bffa69ab4b4" - integrity sha512-nZ3Vt7ehfSDYnrcg/aAfjjvpdE+61B3Zk68i6/hSUIegT3IH9H1vSW67NDKVp+50hcEfzWwM2HMPXxlzuyFyrw== +"@aws-sdk/middleware-recursion-detection@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.533.0.tgz#ac48fdce1e3f7c3e106c41d16a784596695418eb" + integrity sha512-dobVdJ4g1avrVG6QTRHndfvdTxUeloDCn32WLwyOV11XF/2x5p8QJ1VZS+K24xsl29DoJ8bXibZf9xZ7MPwRLg== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-sdk-s3@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.525.0.tgz#c3ce03940240fa7a42bfa3f1916d2ce9fa0fafbf" - integrity sha512-ewFyyFM6wdFTOqCiId5GQNi7owDdLEonQhB4h8tF6r3HV52bRlDvZA4aDos+ft6N/XY2J6L0qlFTFq+/oiurXw== +"@aws-sdk/middleware-sdk-s3@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.533.0.tgz#05e89dbe14bf5c52a78cb9593a5c7d9f00ce102f" + integrity sha512-9bd1+u5bFEQnh/2X9mybdQ4kVWhe6/XeCHC1KrER846Ntd3QYdX61KwJktg0URdqw5QFdqD+rmn0nQ3Ku8AmxA== dependencies: - "@aws-sdk/types" "3.523.0" + "@aws-sdk/types" "3.533.0" "@aws-sdk/util-arn-parser" "3.495.0" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/protocol-http" "^3.2.1" - "@smithy/signature-v4" "^2.1.3" - "@smithy/smithy-client" "^2.4.2" - "@smithy/types" "^2.10.1" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/protocol-http" "^3.2.2" + "@smithy/signature-v4" "^2.1.4" + "@smithy/smithy-client" "^2.4.5" + "@smithy/types" "^2.11.0" "@smithy/util-config-provider" "^2.2.1" tslib "^2.5.0" -"@aws-sdk/middleware-signing@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.523.0.tgz#1b2c458eb6a00da45b0800916ee463ff727c0717" - integrity sha512-pFXV4don6qcmew/OvEjLUr2foVjzoJ8o5k57Oz9yAHz8INx3RHK8MP/K4mVhHo6n0SquRcWrm4kY/Tw+89gkEA== - dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/protocol-http" "^3.2.1" - "@smithy/signature-v4" "^2.1.3" - "@smithy/types" "^2.10.1" - "@smithy/util-middleware" "^2.1.3" +"@aws-sdk/middleware-signing@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.533.0.tgz#4da88e63aa21b2835dd654708dcbe1fcd353a1a8" + integrity sha512-qJZBoNKoSacIkHZfHcQfxmrogQcb0OPEaeEwwH563f8D5qYjQ3yuSaq7X9BKL7W8f9GjUYUJYZJwK3tbDh1ccg== + dependencies: + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/protocol-http" "^3.2.2" + "@smithy/signature-v4" "^2.1.4" + "@smithy/types" "^2.11.0" + "@smithy/util-middleware" "^2.1.4" tslib "^2.5.0" -"@aws-sdk/middleware-ssec@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.523.0.tgz#1bc0b57859a3e90af7e6103341903896f601e622" - integrity sha512-FaqAZQeF5cQzZLOIboIJRaWVOQ2F2pJZAXGF5D7nJsxYNFChotA0O0iWimBRxU35RNn7yirVxz35zQzs20ddIw== +"@aws-sdk/middleware-ssec@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.533.0.tgz#5901bb3c5765cc84c9fd8f86c5b569fc44f88cc3" + integrity sha512-UQn/d5x+lWBnsZDwkqm+x9qM9jAwPW2VDXoTrN2UMgMqao+iDki9FxvvHqYYYv4zDS4TYGXI6O9Zhmf5wwqygA== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/middleware-user-agent@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.525.0.tgz#3ac154829460271c53ad49d8301d4c849e9afb9f" - integrity sha512-4al/6uO+t/QIYXK2OgqzDKQzzLAYJza1vWFS+S0lJ3jLNGyLB5BMU5KqWjDzevYZ4eCnz2Nn7z0FveUTNz8YdQ== +"@aws-sdk/middleware-user-agent@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.533.0.tgz#0cad8c5a4220170d3368708a589ded997a12256d" + integrity sha512-H5vbkgwFVgp9egQ/CR+gLRXhVJ/jHqq+J9TTug/To4ev183fcNc2OE15ojiNek8phuSsBZITLaQB+DWBTydsAA== dependencies: - "@aws-sdk/types" "3.523.0" - "@aws-sdk/util-endpoints" "3.525.0" - "@smithy/protocol-http" "^3.2.1" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@aws-sdk/util-endpoints" "3.533.0" + "@smithy/protocol-http" "^3.2.2" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/region-config-resolver@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.525.0.tgz#ebd7edd0059857f59ed605c37cf5752542cf8914" - integrity sha512-8kFqXk6UyKgTMi7N7QlhA6qM4pGPWbiUXqEY2RgUWngtxqNFGeM9JTexZeuavQI+qLLe09VPShPNX71fEDcM6w== +"@aws-sdk/region-config-resolver@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.533.0.tgz#86f922a7888eff36411ab5507b7a1fd39c08696d" + integrity sha512-1FLLcohz23aVV+lK3iCUJpjKO/4adXjre0KMg9tvHWwCkOD/sZgLjzlv+BW5Fx2vH3Dgo0kDQ04+XEsbuVC2xA== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/types" "^2.11.0" "@smithy/util-config-provider" "^2.2.1" - "@smithy/util-middleware" "^2.1.3" + "@smithy/util-middleware" "^2.1.4" tslib "^2.5.0" -"@aws-sdk/signature-v4-multi-region@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.525.0.tgz#b9b7e1079b0a8a1df4bb282216aa20b56d139ba5" - integrity sha512-j8gkdfiokaherRgokfZBl2azYBMHlegT7pOnR/3Y79TSz6G+bJeIkuNk8aUbJArr6R8nvAM1j4dt1rBM+efolQ== +"@aws-sdk/signature-v4-multi-region@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.533.0.tgz#eb62e95bf10df37dd1fefaf08c038f3bd300f97c" + integrity sha512-0S552/0UfESFF0f3+wAzbV5F9vSIsGAaYTEW3wMgD1DAeZGDq37xUZjYFZ+XjKqQ/ZnR+pQf3QVW5geFmbKkgQ== dependencies: - "@aws-sdk/middleware-sdk-s3" "3.525.0" - "@aws-sdk/types" "3.523.0" - "@smithy/protocol-http" "^3.2.1" - "@smithy/signature-v4" "^2.1.3" - "@smithy/types" "^2.10.1" + "@aws-sdk/middleware-sdk-s3" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/protocol-http" "^3.2.2" + "@smithy/signature-v4" "^2.1.4" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/token-providers@3.529.1": - version "3.529.1" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.529.1.tgz#0d86e0edb50cfff51ac063410fde60edf3ae4b2d" - integrity sha512-NpgMjsfpqiugbxrYGXtta914N43Mx/H0niidqv8wKMTgWQEtsJvYtOni+kuLXB+LmpjaMFNlpadooFU/bK4buA== +"@aws-sdk/token-providers@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.533.0.tgz#7cfca598d77931bb3cbdaefca72c24d2133c10ec" + integrity sha512-mHaZUeJ6zfbkW0E64dUmzDwReO1LoDYRful+FT1dbKqQr0p+9Q8o4n6fAswwAVfCYHaAeIt68vE0zVkAlbGCqA== dependencies: - "@aws-sdk/client-sso-oidc" "3.529.1" - "@aws-sdk/types" "3.523.0" - "@smithy/property-provider" "^2.1.3" - "@smithy/shared-ini-file-loader" "^2.3.3" - "@smithy/types" "^2.10.1" + "@aws-sdk/client-sso-oidc" "3.533.0" + "@aws-sdk/types" "3.533.0" + "@smithy/property-provider" "^2.1.4" + "@smithy/shared-ini-file-loader" "^2.3.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@aws-sdk/types@3.523.0", "@aws-sdk/types@^3.222.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.523.0.tgz#2bb11390023949f31d9211212f41e245a7f03489" - integrity sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A== +"@aws-sdk/types@3.533.0", "@aws-sdk/types@^3.222.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.533.0.tgz#4c4ade8f41f153295c69f1dea812dcd6154613e3" + integrity sha512-mFb0701oLRcJ7Y2unlrszzk9rr2P6nt2A4Bdz4K5WOsY4f4hsdbcYkrzA1NPmIUTEttU9JT0YG+8z0XxLEX4Aw== dependencies: - "@smithy/types" "^2.10.1" + "@smithy/types" "^2.11.0" tslib "^2.5.0" "@aws-sdk/util-arn-parser@3.495.0": @@ -636,14 +636,14 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-endpoints@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.525.0.tgz#d9f53b60e69dbe4623a4200d10be1be2ac73438f" - integrity sha512-DIW7WWU5tIGkeeKX6NJUyrEIdWMiqjLQG3XBzaUj+ufIENwNjdAHhlD8l2vX7Yr3JZRT6yN/84wBCj7Tw1xd1g== +"@aws-sdk/util-endpoints@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.533.0.tgz#b9751fef5436caabdf0f168534b84c4a61df4d7d" + integrity sha512-pmjRqWqno6X61RaJ/iEbSSql79Jyaq9d9SvTkyvo8Ce8Kb+49cflzUY1PP0s40Caj4H+bUkpksVHwO7t2qIakw== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/types" "^2.10.1" - "@smithy/util-endpoints" "^1.1.4" + "@aws-sdk/types" "3.533.0" + "@smithy/types" "^2.11.0" + "@smithy/util-endpoints" "^1.1.5" tslib "^2.5.0" "@aws-sdk/util-locate-window@^3.0.0": @@ -653,24 +653,24 @@ dependencies: tslib "^2.5.0" -"@aws-sdk/util-user-agent-browser@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.523.0.tgz#77188e83f9d470ddf140fe8c5d4d51049c9d5898" - integrity sha512-6ZRNdGHX6+HQFqTbIA5+i8RWzxFyxsZv8D3soRfpdyWIKkzhSz8IyRKXRciwKBJDaC7OX2jzGE90wxRQft27nA== +"@aws-sdk/util-user-agent-browser@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.533.0.tgz#323da7e2cae11528adcdab98573f1e4196e97cb6" + integrity sha512-wyzDxH89yQ89+Q/9rWZeYBeegaXkB4nhb9Bd+xG4J3KgaNVuVvaYT6Nbzjg4oPtuC+pPeQp1iSXKs/2QTlsqPA== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/types" "^2.11.0" bowser "^2.11.0" tslib "^2.5.0" -"@aws-sdk/util-user-agent-node@3.525.0": - version "3.525.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.525.0.tgz#aa96c28bad8360d2a350c30c3c209c35f99ac5ee" - integrity sha512-88Wjt4efyUSBGcyIuh1dvoMqY1k15jpJc5A/3yi67clBQEFsu9QCodQCQPqmRjV3VRcMtBOk+jeCTiUzTY5dRQ== +"@aws-sdk/util-user-agent-node@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.533.0.tgz#14e65837096544f7504953831a7a45a6a29525b2" + integrity sha512-Tu79n4+q1MAPPFEtu7xTgiTQGzOAPe4c2p8vSyrIJEBHclf7cyvZxgziQAyM9Yy4DoRdtnnAeeybao3U4d+CzA== dependencies: - "@aws-sdk/types" "3.523.0" - "@smithy/node-config-provider" "^2.2.4" - "@smithy/types" "^2.10.1" + "@aws-sdk/types" "3.533.0" + "@smithy/node-config-provider" "^2.2.5" + "@smithy/types" "^2.11.0" tslib "^2.5.0" "@aws-sdk/util-utf8-browser@^3.0.0": @@ -680,12 +680,12 @@ dependencies: tslib "^2.3.1" -"@aws-sdk/xml-builder@3.523.0": - version "3.523.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.523.0.tgz#6abdaf5716f6c7153c328bbbd499345fae755dce" - integrity sha512-wfvyVymj2TUw7SuDor9IuFcAzJZvWRBZotvY/wQJOlYa3UP3Oezzecy64N4FWfBJEsZdrTN+HOZFl+IzTWWnUA== +"@aws-sdk/xml-builder@3.533.0": + version "3.533.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.533.0.tgz#7809aaab095c6325e21eab40d4be6a4e5f57adef" + integrity sha512-wkqoK76SWokrNhcFbcNxGpDAS2S7VL03u7GcTYwezaA7L20VH4r2sT2u6VUFQ5v+aPZ973BesNTIF4sAItvCaw== dependencies: - "@smithy/types" "^2.10.1" + "@smithy/types" "^2.11.0" tslib "^2.5.0" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.8.3": @@ -1712,7 +1712,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.17.9", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.17.9", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e" integrity sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw== @@ -2793,7 +2793,7 @@ csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^5.14.4", "@mui/system@^5.15.13": +"@mui/system@^5.14.4", "@mui/system@^5.15.13", "@mui/system@^5.15.9": version "5.15.13" resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.13.tgz#dd86dbbebf92e4afdf0fa01afdae28598745ba4c" integrity sha512-eHaX3sniZXNWkxX0lmcLxROhQ5La0HkOuF7zxbSdAoHUOk07gboQYmF6hSJ/VBFx/GLanIw67FMTn88vc8niLg== @@ -2812,7 +2812,7 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.13.tgz#d1584912942f9dc042441ecc2d1452be39c666b8" integrity sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g== -"@mui/utils@^5.14.16", "@mui/utils@^5.15.13": +"@mui/utils@^5.15.13", "@mui/utils@^5.15.9": version "5.15.13" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.13.tgz#4adfed6c585a6787f1f0d7d1fadb9ff0f7ddb2bd" integrity sha512-qNlR9FLEhORC4zVZ3fzF48213EhP/92N71AcFbhHN73lPJjAbq9lUv+71P7uEdRHdrrOlm8+1zE8/OBy6MUqdg== @@ -2822,14 +2822,15 @@ prop-types "^15.8.1" react-is "^18.2.0" -"@mui/x-data-grid@^6.0.1": - version "6.19.6" - resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-6.19.6.tgz#6334bb70a7a2685fc1cf3ed902172661c3206f3f" - integrity sha512-jpZkX1Gnlo87gKcD10mKMY8YoAzUD8Cv3/IvedH3FINDKO3hnraMeOciKDeUk0tYSj8RUDB02kpTHCM8ojLVBA== +"@mui/x-data-grid@next": + version "7.0.0-beta.7" + resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-7.0.0-beta.7.tgz#aae5c43fb71543377382080ddf19767635bd2f52" + integrity sha512-rZ7lvibUDbGqEABBGlNvfQ5SdIa+8ve3/d8YjdZ2DUOeJwR+K7X4MnVItIrZuKPRYoSy1kWDRsjr8u0sEIIEoA== dependencies: - "@babel/runtime" "^7.23.2" - "@mui/utils" "^5.14.16" - clsx "^2.0.0" + "@babel/runtime" "^7.24.0" + "@mui/system" "^5.15.9" + "@mui/utils" "^5.15.9" + clsx "^2.1.0" prop-types "^15.8.1" reselect "^4.1.8" @@ -3715,7 +3716,7 @@ dependencies: tslib "^2.5.0" -"@smithy/config-resolver@^2.1.4", "@smithy/config-resolver@^2.1.5": +"@smithy/config-resolver@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.1.5.tgz#51d047d2ff7b69cbb8d8b1a197f0edc2a17fbc1b" integrity sha512-LcBB5JQC3Tx2ZExIJzfvWaajhFIwHrUNQeqxhred2r5nnqrdly9uoCrvM1sxOOdghYuWWm2Kr8tBCDOmxsgeTA== @@ -3726,7 +3727,7 @@ "@smithy/util-middleware" "^2.1.4" tslib "^2.5.0" -"@smithy/core@^1.3.5": +"@smithy/core@^1.3.8": version "1.3.8" resolved "https://registry.yarnpkg.com/@smithy/core/-/core-1.3.8.tgz#91e432bf78fe79ef80b0314e4dec12de92b7b561" integrity sha512-6cFhQ9ChU7MxvOXJn6nuUSONacpNsGHWhfueROQuM/0vibDdZA9FWEdNbVkuVuc+BFI5BnaX3ltERUlpUirpIA== @@ -3740,7 +3741,7 @@ "@smithy/util-middleware" "^2.1.4" tslib "^2.5.0" -"@smithy/credential-provider-imds@^2.2.3", "@smithy/credential-provider-imds@^2.2.6": +"@smithy/credential-provider-imds@^2.2.6": version "2.2.6" resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.6.tgz#a518575d5b830370fa76a270c376ce9f208d4c74" integrity sha512-+xQe4Pite0kdk9qn0Vyw5BRVh0iSlj+T4TEKRXr4E1wZKtVgIzGlkCrfICSjiPVFkPxk4jMpVboMYdEiiA88/w== @@ -3761,7 +3762,7 @@ "@smithy/util-hex-encoding" "^2.1.1" tslib "^2.5.0" -"@smithy/eventstream-serde-browser@^2.1.3": +"@smithy/eventstream-serde-browser@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.4.tgz#e3b4873969740cbcf67ac4bfcddb36ed31c0097d" integrity sha512-K0SyvrUu/vARKzNW+Wp9HImiC/cJ6K88/n7FTH1slY+MErdKoiSbRLaXbJ9qD6x1Hu28cplHMlhADwZelUx/Ww== @@ -3770,7 +3771,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/eventstream-serde-config-resolver@^2.1.3": +"@smithy/eventstream-serde-config-resolver@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.4.tgz#7fa9a57f1911ce163a4959ee04006ad4eaa3eba3" integrity sha512-FH+2AwOwZ0kHPB9sciWJtUqx81V4vizfT3P6T9eslmIC2hi8ch/KFvQlF7jDmwR1aLlPlq6qqLKLqzK/71Ki4A== @@ -3778,7 +3779,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/eventstream-serde-node@^2.1.3": +"@smithy/eventstream-serde-node@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.4.tgz#1a1ab2b5d1d70b7d686ab4c77b0540c422f9aaac" integrity sha512-gsc5ZTvVcB9sleLQzsK/rOhgn52+AAsmhEr41WDwAcctccBjh429+b8gT9t+SU8QyajypfsLOZfJQu0+zE515Q== @@ -3796,7 +3797,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/fetch-http-handler@^2.4.3", "@smithy/fetch-http-handler@^2.4.5": +"@smithy/fetch-http-handler@^2.4.5": version "2.4.5" resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.5.tgz#e036f6653259e742841d10280fc049c337e739e8" integrity sha512-FR1IMGdo0yRFs1tk71zRGSa1MznVLQOVNaPjyNtx6dOcy/u0ovEnXN5NVz6slw5KujFlg3N1w4+UbO8F3WyYUg== @@ -3807,7 +3808,7 @@ "@smithy/util-base64" "^2.2.1" tslib "^2.5.0" -"@smithy/hash-blob-browser@^2.1.3": +"@smithy/hash-blob-browser@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.5.tgz#962aac56c8a839171a69035cb148c2828af8f79c" integrity sha512-6HxT9Q25YxkyBLHiFEjNullTo2/w2hWo1IMnUZDn0Sun5D+BWEZiExJ83gKLVlkHvuAZX/bA5A8yxFLQ5FpGuQ== @@ -3817,7 +3818,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/hash-node@^2.1.3": +"@smithy/hash-node@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.1.4.tgz#a2cc973ca9a074085d3b70969b5be186a0d5ee94" integrity sha512-uvCcpDLXaTTL0X/9ezF8T8sS77UglTfZVQaUOBiCvR0QydeSyio3t0Hj3QooVdyFsKTubR8gCk/ubLk3vAyDng== @@ -3827,7 +3828,7 @@ "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@smithy/hash-stream-node@^2.1.3": +"@smithy/hash-stream-node@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-2.1.4.tgz#51d5a214e018bc5431538ca663aee822afa66008" integrity sha512-HcDQRs/Fcx7lwAd+/vSW/e7ltdh148D2Pq7XI61CEWcOoQdQ0W8aYBHDRC4zjtXv6hySdmWE+vo3dvdTt7aj8A== @@ -3836,7 +3837,7 @@ "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@smithy/invalid-dependency@^2.1.3": +"@smithy/invalid-dependency@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.1.4.tgz#aa58540c21b39fbedf58192fb34e6fb49cc736ca" integrity sha512-QzlNBl6jt3nb9jNnE51wTegReVvUdozyMMrFEyb/rc6AzPID1O+qMJYjAAoNw098y0CZVfCpEnoK2+mfBOd8XA== @@ -3851,7 +3852,7 @@ dependencies: tslib "^2.5.0" -"@smithy/md5-js@^2.1.3": +"@smithy/md5-js@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-2.1.4.tgz#607c54622d020625056deffc18644864ff307621" integrity sha512-WHTnnYJPKE7Sy49DogLuox42TnlwD3cQ6TObPD6WFWjKocWIdpEpIvdJHwWUfSFf0JIi8ON8z6ZEhsnyKVCcLQ== @@ -3860,7 +3861,7 @@ "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@smithy/middleware-content-length@^2.1.3": +"@smithy/middleware-content-length@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.1.4.tgz#0939d7b36f029f075a118ac1673db2655f51ff81" integrity sha512-C6VRwfcr0w9qRFhDGCpWMVhlEIBFlmlPRP1aX9Cv9xDj9SUwlDrNvoV1oP1vjRYuLxCDgovBBynCwwcluS2wLw== @@ -3869,7 +3870,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/middleware-endpoint@^2.4.4", "@smithy/middleware-endpoint@^2.4.6": +"@smithy/middleware-endpoint@^2.4.6": version "2.4.6" resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.6.tgz#18fbae774b722d47d4d40dad73466893a035a072" integrity sha512-AsXtUXHPOAS0EGZUSFOsVJvc7p0KL29PGkLxLfycPOcFVLru/oinYB6yvyL73ZZPX2OB8sMYUMrj7eH2kI7V/w== @@ -3882,7 +3883,7 @@ "@smithy/util-middleware" "^2.1.4" tslib "^2.5.0" -"@smithy/middleware-retry@^2.1.4", "@smithy/middleware-retry@^2.1.7": +"@smithy/middleware-retry@^2.1.7": version "2.1.7" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.1.7.tgz#ad49013c40f0b3593ad8140dd7b50368a1e2ce42" integrity sha512-8fOP/cJN4oMv+5SRffZC8RkqfWxHqGgn/86JPINY/1DnTRegzf+G5GT9lmIdG1YasuSbU7LISfW9PXil3isPVw== @@ -3897,7 +3898,7 @@ tslib "^2.5.0" uuid "^8.3.2" -"@smithy/middleware-serde@^2.1.3", "@smithy/middleware-serde@^2.2.1": +"@smithy/middleware-serde@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.2.1.tgz#b4a6a757e3f6f62e432f53020a06d27eabe8f424" integrity sha512-VAWRWqnNjgccebndpyK94om4ZTYzXLQxUmNCXYzM/3O9MTfQjTNBgtFtQwyIIez6z7LWcCsXmnKVIOE9mLqAHQ== @@ -3905,7 +3906,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/middleware-stack@^2.1.3", "@smithy/middleware-stack@^2.1.4": +"@smithy/middleware-stack@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.1.4.tgz#eb475eb31ad6fed0aa21ee0896c3c80114b73507" integrity sha512-Qqs2ba8Ax1rGKOSGJS2JN23fhhox2WMdRuzx0NYHtXzhxbJOIMmz9uQY6Hf4PY8FPteBPp1+h0j5Fmr+oW12sg== @@ -3913,7 +3914,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/node-config-provider@^2.2.4", "@smithy/node-config-provider@^2.2.5": +"@smithy/node-config-provider@^2.2.5": version "2.2.5" resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.2.5.tgz#39c7a06e798f763722d12fccab6160896b2ee08b" integrity sha512-CxPf2CXhjO79IypHJLBATB66Dw6suvr1Yc2ccY39hpR6wdse3pZ3E8RF83SODiNH0Wjmkd0ze4OF8exugEixgA== @@ -3923,7 +3924,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/node-http-handler@^2.4.1", "@smithy/node-http-handler@^2.4.3": +"@smithy/node-http-handler@^2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.4.3.tgz#f9cc5a2197098a78be5a31776829b82a01b34276" integrity sha512-bD5zRdEl1u/4vAAMeQnGEUNbH1seISV2Z0Wnn7ltPRl/6B2zND1R9XzTfsOnH1R5jqghpochF/mma8u7uXz0qQ== @@ -3934,7 +3935,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/property-provider@^2.1.3", "@smithy/property-provider@^2.1.4": +"@smithy/property-provider@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.1.4.tgz#0f127125c4b6f3ae0ddb4777946926f0bd8f0ca1" integrity sha512-nWaY/MImj1BiXZ9WY65h45dcxOx8pl06KYoHxwojDxDL+Q9yLU1YnZpgv8zsHhEftlj9KhePENjQTlNowWVyug== @@ -3942,7 +3943,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/protocol-http@^3.2.1", "@smithy/protocol-http@^3.2.2": +"@smithy/protocol-http@^3.2.2": version "3.2.2" resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-3.2.2.tgz#af001dcc61e6ce6374315c907ad5bbd09bd3c810" integrity sha512-xYBlllOQcOuLoxzhF2u8kRHhIFGQpDeTQj/dBSnw4kfI29WMKL5RnW1m9YjnJAJ49miuIvrkJR+gW5bCQ+Mchw== @@ -3974,7 +3975,7 @@ dependencies: "@smithy/types" "^2.11.0" -"@smithy/shared-ini-file-loader@^2.3.3", "@smithy/shared-ini-file-loader@^2.3.5": +"@smithy/shared-ini-file-loader@^2.3.5": version "2.3.5" resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.5.tgz#3e2f6f5fcfb1edf934f531dbf17429e2631e3a21" integrity sha512-oI99+hOvsM8oAJtxAGmoL/YCcGXtbP0fjPseYGaNmJ4X5xOFTer0KPk7AIH3AL6c5AlYErivEi1X/X78HgTVIw== @@ -3982,7 +3983,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/signature-v4@^2.1.3": +"@smithy/signature-v4@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.1.4.tgz#e83b426ab4138cbb06c755c14a152ed514e1d052" integrity sha512-gnu9gCn0qQ8IdhNjs6o3QVCXzUs33znSDYwVMWo3nX4dM6j7z9u6FC302ShYyVWfO4MkVMuGCCJ6nl3PcH7V1Q== @@ -3996,7 +3997,7 @@ "@smithy/util-utf8" "^2.2.0" tslib "^2.5.0" -"@smithy/smithy-client@^2.4.2", "@smithy/smithy-client@^2.4.5": +"@smithy/smithy-client@^2.4.5": version "2.4.5" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.4.5.tgz#63cf9e12c94c113de200cc99f2cecca8a0cda822" integrity sha512-igXOM4kPXPo6b5LZXTUqTnrGk20uVd8OXoybC3f89gczzGfziLK4yUNOmiHSdxY9OOMOnnhVe5MpTm01MpFqvA== @@ -4008,14 +4009,14 @@ "@smithy/util-stream" "^2.1.5" tslib "^2.5.0" -"@smithy/types@^2.10.1", "@smithy/types@^2.11.0": +"@smithy/types@^2.11.0": version "2.11.0" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.11.0.tgz#d40c27302151be243d3a7319a154b7d7d5775021" integrity sha512-AR0SXO7FuAskfNhyGfSTThpLRntDI5bOrU0xrpVYU0rZyjl3LBXInZFMTP/NNSd7IS6Ksdtar0QvnrPRIhVrLQ== dependencies: tslib "^2.5.0" -"@smithy/url-parser@^2.1.3", "@smithy/url-parser@^2.1.4": +"@smithy/url-parser@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.1.4.tgz#b24c13d80677b1cbcf61172f1c3dd49402ff6a07" integrity sha512-1hTy6UYRYqOZlHKH2/2NzdNQ4NNmW2Lp0sYYvztKy+dEQuLvZL9w88zCzFQqqFer3DMcscYOshImxkJTGdV+rg== @@ -4024,7 +4025,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/util-base64@^2.1.1", "@smithy/util-base64@^2.2.1": +"@smithy/util-base64@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.2.1.tgz#215634c4ab9dd48abf4dad6bb328fadc14c488c3" integrity sha512-troGfokrpoqv8TGgsb8p4vvM71vqor314514jyQ0i9Zae3qs0jUVbSMCIBB1tseVynXFRcZJAZ9hPQYlifLD5A== @@ -4040,7 +4041,7 @@ dependencies: tslib "^2.5.0" -"@smithy/util-body-length-node@^2.2.1": +"@smithy/util-body-length-node@^2.2.2": version "2.2.2" resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.2.2.tgz#33924882adcc8f4e083cc4ec789210b033d4cca1" integrity sha512-U7DooaT1SfW7XHrOcxthYJnQ+WMaefRrFPxW5Qmypw38Ivv+TKvfVuVHA9V162h8BeW9rzOJwOunjgXd0DdB4w== @@ -4062,7 +4063,7 @@ dependencies: tslib "^2.5.0" -"@smithy/util-defaults-mode-browser@^2.1.4": +"@smithy/util-defaults-mode-browser@^2.1.7": version "2.1.7" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.7.tgz#a14cb2d585bcb01a9b36b93819fe042460cfc612" integrity sha512-vvIpWsysEdY77R0Qzr6+LRW50ye7eii7AyHM0OJnTi0isHYiXo5M/7o4k8gjK/b1upQJdfjzSBoJVa2SWrI+2g== @@ -4073,7 +4074,7 @@ bowser "^2.11.0" tslib "^2.5.0" -"@smithy/util-defaults-mode-node@^2.2.3": +"@smithy/util-defaults-mode-node@^2.2.7": version "2.2.7" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.2.7.tgz#f92aa2de80a5bb469cc3fdbc4ff000bbccead0bc" integrity sha512-qzXkSDyU6Th+rNNcNkG4a7Ix7m5HlMOtSCPxTVKlkz7eVsqbSSPggegbFeQJ2MVELBB4wnzNPsVPJIrpIaJpXA== @@ -4086,7 +4087,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/util-endpoints@^1.1.4": +"@smithy/util-endpoints@^1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-1.1.5.tgz#2f07510013353299b95f483842c59115c0a01e00" integrity sha512-tgDpaUNsUtRvNiBulKU1VnpoXU1GINMfZZXunRhUXOTBEAufG1Wp79uDXLau2gg1RZ4dpAR6lXCkrmddihCGUg== @@ -4102,7 +4103,7 @@ dependencies: tslib "^2.5.0" -"@smithy/util-middleware@^2.1.3", "@smithy/util-middleware@^2.1.4": +"@smithy/util-middleware@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.1.4.tgz#eb5f8d3f3639c1c2ff6fae574353249c174f1c03" integrity sha512-5yYNOgCN0DL0OplME0pthoUR/sCfipnROkbTO7m872o0GHCVNJj5xOFJ143rvHNA54+pIPMLum4z2DhPC2pVGA== @@ -4110,7 +4111,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/util-retry@^2.1.3", "@smithy/util-retry@^2.1.4": +"@smithy/util-retry@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.1.4.tgz#cfbe7aa7609f92eecdce562be5308599a2f6537b" integrity sha512-JRZwhA3fhkdenSEYIWatC8oLwt4Bdf2LhHbNQApqb7yFoIGMl4twcYI3BcJZ7YIBZrACA9jGveW6tuCd836XzQ== @@ -4119,7 +4120,7 @@ "@smithy/types" "^2.11.0" tslib "^2.5.0" -"@smithy/util-stream@^2.1.3", "@smithy/util-stream@^2.1.5": +"@smithy/util-stream@^2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.1.5.tgz#8fa752e55b30209de47d00aed40f93b9b781fae1" integrity sha512-FqvBFeTgx+QC4+i8USHqU8Ifs9nYRpW/OBfksojtgkxPIQ2H7ypXDEbnQRAV7PwoNHWcSwPomLYi0svmQQG5ow== @@ -4140,7 +4141,7 @@ dependencies: tslib "^2.5.0" -"@smithy/util-utf8@^2.1.1", "@smithy/util-utf8@^2.2.0": +"@smithy/util-utf8@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.2.0.tgz#e352a81adc0491fbdc0086a00950d7e8333e211f" integrity sha512-hBsKr5BqrDrKS8qy+YcV7/htmMGxriA1PREOf/8AGBhHIZnfilVv1Waf1OyKhSbFW15U/8+gcMUQ9/Kk5qwpHQ== @@ -4148,7 +4149,7 @@ "@smithy/util-buffer-from" "^2.1.1" tslib "^2.5.0" -"@smithy/util-waiter@^2.1.3": +"@smithy/util-waiter@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-2.1.4.tgz#675798056b120a51ca4220d3dac5703ca6a7bba5" integrity sha512-AK17WaC0hx1wR9juAOsQkJ6DjDxBGEf5TrKhpXtNFEn+cVto9Li3MVsdpAO97AF7bhFXSyC8tJA3F4ThhqwCdg== @@ -5462,9 +5463,9 @@ "@types/react" "*" "@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.0.26": - version "18.2.65" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.65.tgz#54eb311fa9aba173c9e163d42ec188d5a42878b8" - integrity sha512-98TsY0aW4jqx/3RqsUXwMDZSWR1Z4CUlJNue8ueS2/wcxZOsz4xmW1X8ieaWVRHcmmQM3R8xVA4XWB3dJnWwDQ== + version "18.2.66" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.66.tgz#d2eafc8c4e70939c5432221adb23d32d76bfe451" + integrity sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -7543,7 +7544,7 @@ clsx@^1.1.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -clsx@^2.0.0, clsx@^2.1.0: +clsx@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb" integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg== @@ -9053,9 +9054,9 @@ electron-publish@24.13.1: mime "^2.5.2" electron-to-chromium@^1.4.668: - version "1.4.703" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.703.tgz#786ab0c8cfe548b9da03890f923e69b1ae522741" - integrity sha512-094ZZC4nHXPKl/OwPinSMtLN9+hoFkdfQGKnvXbY+3WEAYtVDpz9UhJIViiY6Zb8agvqxiaJzNG9M+pRZWvSZw== + version "1.4.705" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.705.tgz#ef4f912620bd7c9555a20554ffc568184c0ddceb" + integrity sha512-LKqhpwJCLhYId2VVwEzFXWrqQI5n5zBppz1W9ehhTlfYU8CUUW6kClbN8LHF/v7flMgRdETS772nqywJ+ckVAw== electron-updater@^6.1.1: version "6.1.8" @@ -10093,14 +10094,14 @@ flatted@^3.2.9: integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== flow-parser@0.*: - version "0.230.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.230.0.tgz#f0e54bdac58a20553bb81ef26bdc8a616360f1cd" - integrity sha512-ZAfKaarESYYcP/RoLdM91vX0u/1RR7jI5TJaFLnxwRlC2mp0o+Rw7ipIY7J6qpIpQYtAobWb/J6S0XPeu0gO8g== + version "0.231.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.231.0.tgz#13daa172b3c06ffacbb31025592dc0db41fe28f3" + integrity sha512-WVzuqwq7ZnvBceCG0DGeTQebZE+iIU0mlk5PmJgYj9DDrt+0isGC2m1ezW9vxL4V+HERJJo9ExppOnwKH2op6Q== follow-redirects@^1.0.0, follow-redirects@^1.15.4: - version "1.15.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" - integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== for-each@^0.3.3: version "0.3.3" @@ -17455,9 +17456,9 @@ terser-webpack-plugin@^5.2.5, terser-webpack-plugin@^5.3.1, terser-webpack-plugi terser "^5.26.0" terser@^5.10.0, terser@^5.26.0: - version "5.29.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.1.tgz#44e58045b70c09792ba14bfb7b4e14ca8755b9fa" - integrity sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ== + version "5.29.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35" + integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2"