@plutonhq/core-frontend 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/@types/backups.d.ts +1 -1
- package/dist-lib/@types/backups.d.ts.map +1 -1
- package/dist-lib/components/Plan/BackupEvents/BackupEvents.d.ts.map +1 -1
- package/dist-lib/components/Plan/BackupEvents/BackupEvents.js +27 -27
- package/dist-lib/components/Plan/BackupEvents/BackupEvents.js.map +1 -1
- package/dist-lib/components/Plan/Backups/Backups.d.ts.map +1 -1
- package/dist-lib/components/Plan/Backups/Backups.js +189 -159
- package/dist-lib/components/Plan/Backups/Backups.js.map +1 -1
- package/dist-lib/components/Plan/PlanPruneModal/PlanPruneModal.d.ts.map +1 -1
- package/dist-lib/components/Plan/PlanPruneModal/PlanPruneModal.js +62 -26
- package/dist-lib/components/Plan/PlanPruneModal/PlanPruneModal.js.map +1 -1
- package/dist-lib/components/Plan/PlanSettings/PlanPruneSettings.d.ts.map +1 -1
- package/dist-lib/components/Plan/PlanSettings/PlanPruneSettings.js +138 -62
- package/dist-lib/components/Plan/PlanSettings/PlanPruneSettings.js.map +1 -1
- package/dist-lib/components/Plan/PlanSettings/PlanSettings.module.scss.js +42 -42
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.d.ts +32 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.d.ts.map +1 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.js +252 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewer.js.map +1 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.d.ts +23 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.d.ts.map +1 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.js +72 -0
- package/dist-lib/components/Plan/SnapshotViewer/SnapshotViewerFile.js.map +1 -0
- package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.d.ts.map +1 -1
- package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.js +188 -198
- package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.js.map +1 -1
- package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.module.scss.js +20 -64
- package/dist-lib/components/Restore/RestoreFileSelector/RestoreFileSelector.module.scss.js.map +1 -1
- package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.d.ts.map +1 -1
- package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.js +125 -159
- package/dist-lib/components/Restore/RestoredFileBrowser/RestoredFileBrowser.js.map +1 -1
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowser.module.scss.js +74 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowser.module.scss.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.d.ts +17 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.js +57 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserDirectories.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.d.ts +18 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.js +24 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileList.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.d.ts +18 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.js +37 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserFileRow.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.d.ts +9 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.js +15 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.d.ts +11 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.js +18 -0
- package/dist-lib/components/common/SnapshotBrowser/SnapshotBrowserToolbar.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.d.ts +12 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.js +70 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.d.ts +22 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.js +79 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.d.ts +6 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.d.ts.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.js +18 -0
- package/dist-lib/components/common/SnapshotBrowser/hooks/useSnapshotSort.js.map +1 -0
- package/dist-lib/components/common/SnapshotBrowser/index.d.ts +11 -0
- package/dist-lib/components/common/SnapshotBrowser/index.d.ts.map +1 -0
- package/dist-lib/components/common/StatusLabel/StatusLabel.d.ts +1 -1
- package/dist-lib/components/common/StatusLabel/StatusLabel.d.ts.map +1 -1
- package/dist-lib/components/common/StatusLabel/StatusLabel.js +17 -12
- package/dist-lib/components/common/StatusLabel/StatusLabel.js.map +1 -1
- package/dist-lib/components/common/form/NumberInput/NumberInput.module.scss.js +4 -4
- package/dist-lib/components/index.d.ts +10 -0
- package/dist-lib/components/index.d.ts.map +1 -1
- package/dist-lib/components.js +152 -132
- package/dist-lib/components.js.map +1 -1
- package/dist-lib/hooks/usePlanSingleActions.d.ts.map +1 -1
- package/dist-lib/hooks/usePlanSingleActions.js +21 -21
- package/dist-lib/hooks/usePlanSingleActions.js.map +1 -1
- package/dist-lib/services/backups.d.ts +4 -0
- package/dist-lib/services/backups.d.ts.map +1 -1
- package/dist-lib/services/backups.js +34 -25
- package/dist-lib/services/backups.js.map +1 -1
- package/dist-lib/services.js +113 -112
- package/dist-lib/styles/core-frontend.css +1 -1
- package/dist-lib/utils/index.d.ts +1 -0
- package/dist-lib/utils/index.d.ts.map +1 -1
- package/dist-lib/utils/snapshotDatabase.d.ts +16 -0
- package/dist-lib/utils/snapshotDatabase.d.ts.map +1 -0
- package/dist-lib/utils/snapshotDatabase.js +105 -0
- package/dist-lib/utils/snapshotDatabase.js.map +1 -0
- package/dist-lib/utils.js +24 -22
- package/dist-lib/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/@types/backups.ts +1 -1
- package/src/components/Plan/BackupEvents/BackupEvents.tsx +5 -3
- package/src/components/Plan/Backups/Backups.tsx +40 -1
- package/src/components/Plan/PlanPruneModal/PlanPruneModal.tsx +54 -11
- package/src/components/Plan/PlanSettings/PlanPruneSettings.tsx +145 -61
- package/src/components/Plan/PlanSettings/PlanSettings.module.scss +5 -0
- package/src/components/Plan/SnapshotViewer/SnapshotViewer.tsx +344 -0
- package/src/components/Plan/SnapshotViewer/SnapshotViewerFile.tsx +89 -0
- package/src/components/Restore/RestoreFileSelector/RestoreFileSelector.tsx +82 -145
- package/src/components/Restore/RestoredFileBrowser/RestoredFileBrowser.tsx +71 -156
- package/src/components/common/SnapshotBrowser/SnapshotBrowser.module.scss +376 -0
- package/src/components/common/SnapshotBrowser/SnapshotBrowserDirectories.tsx +84 -0
- package/src/components/common/SnapshotBrowser/SnapshotBrowserFileList.tsx +52 -0
- package/src/components/common/SnapshotBrowser/SnapshotBrowserFileRow.tsx +44 -0
- package/src/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.tsx +22 -0
- package/src/components/common/SnapshotBrowser/SnapshotBrowserToolbar.tsx +29 -0
- package/src/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.ts +130 -0
- package/src/components/common/SnapshotBrowser/hooks/useSnapshotNavigation.ts +154 -0
- package/src/components/common/SnapshotBrowser/hooks/useSnapshotSort.ts +24 -0
- package/src/components/common/SnapshotBrowser/index.ts +13 -0
- package/src/components/common/StatusLabel/StatusLabel.tsx +7 -1
- package/src/components/common/form/NumberInput/NumberInput.module.scss +1 -0
- package/src/components/index.ts +13 -0
- package/src/hooks/usePlanSingleActions.tsx +5 -3
- package/src/services/backups.ts +12 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/snapshotDatabase.ts +201 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RestoredFileBrowser.js","sources":["../../../../src/components/Restore/RestoredFileBrowser/RestoredFileBrowser.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\r\nimport { FixedSizeList as List } from 'react-window';\r\nimport Icon from '../../common/Icon/Icon';\r\nimport classes from './RestoredFileBrowser.module.scss';\r\nimport { RestoredFileItem, RestoredItemsStats } from '../../../@types/restores';\r\nimport { formatBytes, formatNumberToK, isMobile } from '../../../utils/helpers';\r\nimport { getParentPath, getPathSeparator, normalizePath, splitPath } from '../../../utils/restore';\r\nimport FileIcon from '../../common/FileIcon/FileIcon';\r\n\r\ninterface RestoredFileBrowserProps {\r\n files: RestoredFileItem[];\r\n stats?: RestoredItemsStats;\r\n isPreview?: boolean;\r\n}\r\n\r\nconst isMobileDevice = isMobile();\r\nconst ITEM_HEIGHT = isMobileDevice ? 65 : 45;\r\n\r\nconst RestoredFileBrowser = ({ files, stats, isPreview = false }: RestoredFileBrowserProps) => {\r\n const [selectedFolder, setSelectedFolder] = useState<string>('');\r\n const [search, setSearch] = useState('');\r\n const [filters, setFilters] = useState({\r\n unchanged: true,\r\n restored: true,\r\n updated: true,\r\n });\r\n\r\n const [expandedFolders, setExpandedFolders] = useState<Set<string>>(() => {\r\n const allPaths = new Set<string>();\r\n files.forEach((file) => {\r\n const separator = getPathSeparator(file.path);\r\n const parts = splitPath(file.path);\r\n let currentPath = '';\r\n\r\n parts.forEach((part, index) => {\r\n currentPath = currentPath ? `${currentPath}${separator}${part}` : part;\r\n // Only expand folders up to 5 levels deep (index < 5)\r\n if (index < 3) {\r\n allPaths.add(currentPath);\r\n }\r\n });\r\n });\r\n return allPaths;\r\n });\r\n\r\n const fileSystem = useMemo(() => {\r\n const system: { [key: string]: RestoredFileItem[] } = {};\r\n\r\n files\r\n .filter((file) => {\r\n const matchesSearch = file.path.toLowerCase().includes(search.toLowerCase());\r\n const matchesFilter = filters[file.action];\r\n return matchesSearch && matchesFilter;\r\n })\r\n .forEach((file) => {\r\n const dirPath = getParentPath(file.path);\r\n // Use the normalized path as key\r\n const normalizedDirPath = normalizePath(dirPath);\r\n\r\n if (normalizedDirPath) {\r\n if (!system[normalizedDirPath]) {\r\n system[normalizedDirPath] = [];\r\n }\r\n system[normalizedDirPath].push(file);\r\n }\r\n });\r\n\r\n return system;\r\n }, [files, search, filters]);\r\n\r\n const directories = useMemo(() => {\r\n const dirs = new Set<string>();\r\n // Derive directories from all files, not filtered fileSystem, to keep tree stable during search\r\n files.forEach((file) => {\r\n const dirPath = getParentPath(file.path);\r\n const separator = getPathSeparator(dirPath);\r\n const parts = splitPath(dirPath);\r\n let currentPath = '';\r\n\r\n parts.forEach((part) => {\r\n currentPath = currentPath ? `${currentPath}${separator}${part}` : part;\r\n if (currentPath) {\r\n dirs.add(currentPath);\r\n }\r\n });\r\n });\r\n return Array.from(dirs);\r\n }, [files]);\r\n\r\n // Set initial selected folder when directories change\r\n useEffect(() => {\r\n if (directories.length > 0 && selectedFolder === '') {\r\n setSelectedFolder(directories[0]);\r\n }\r\n }, [directories, selectedFolder]);\r\n\r\n const hasSubdirectories = (dir: string) => {\r\n const separator = getPathSeparator(dir);\r\n return directories.some((d) => d !== dir && d.startsWith(dir + separator));\r\n };\r\n\r\n const hasUpdatedContent = (dir: string) => {\r\n return Object.entries(fileSystem).some(([path, files]) => {\r\n return path.startsWith(dir) && files.some((f) => f.action === 'restored' || f.action === 'updated');\r\n });\r\n };\r\n\r\n const expandParentDirectories = (dir: string) => {\r\n const newExpanded = new Set(expandedFolders);\r\n const separator = getPathSeparator(dir);\r\n const parts = splitPath(dir);\r\n let currentPath = '';\r\n\r\n // Expand all parent directories\r\n parts.forEach((part, index) => {\r\n currentPath = currentPath ? `${currentPath}${separator}${part}` : part;\r\n if (index < parts.length - 1) {\r\n // Don't expand the target directory itself\r\n newExpanded.add(currentPath);\r\n }\r\n });\r\n\r\n setExpandedFolders(newExpanded);\r\n };\r\n\r\n const toggleFolder = (dir: string) => {\r\n const newExpanded = new Set(expandedFolders);\r\n if (expandedFolders.has(dir)) {\r\n newExpanded.delete(dir);\r\n } else {\r\n newExpanded.add(dir);\r\n }\r\n setExpandedFolders(newExpanded);\r\n };\r\n\r\n const isVisible = (dir: string) => {\r\n const separator = getPathSeparator(dir);\r\n const parts = splitPath(dir);\r\n const parentParts = parts.slice(0, -1);\r\n let parentPath = '';\r\n\r\n // Check if all parent folders are expanded\r\n return parentParts.every((part) => {\r\n parentPath = parentPath ? `${parentPath}${separator}${part}` : part;\r\n return expandedFolders.has(parentPath);\r\n });\r\n };\r\n\r\n const sortedFiles = useMemo(() => {\r\n if (!selectedFolder || !fileSystem[selectedFolder]) return [];\r\n\r\n return fileSystem[selectedFolder].sort((a, b) => {\r\n const normalizedPathA = normalizePath(a.path);\r\n const normalizedPathB = normalizePath(b.path);\r\n const isDirectoryA = directories.includes(normalizedPathA);\r\n const isDirectoryB = directories.includes(normalizedPathB);\r\n\r\n // First sort by type: directories first, then files\r\n if (isDirectoryA && !isDirectoryB) return -1;\r\n if (!isDirectoryA && isDirectoryB) return 1;\r\n\r\n // If both are same type, sort by status priority\r\n const priority = { restored: 0, updated: 1, unchanged: 2 };\r\n return priority[a.action] - priority[b.action];\r\n });\r\n }, [selectedFolder, fileSystem, directories]);\r\n\r\n const showGoUpButton = selectedFolder && getParentPath(selectedFolder) !== selectedFolder && selectedFolder !== '' && selectedFolder !== '/';\r\n const totalItems = sortedFiles.length + (showGoUpButton ? 1 : 0);\r\n\r\n const FileRow = ({ index, style }: { index: number; style: React.CSSProperties }) => {\r\n // If showing go up button and this is the first item\r\n if (showGoUpButton && index === 0) {\r\n return (\r\n <div\r\n style={style}\r\n className={`${classes.file} ${classes.fileIsDir} ${classes.goUpButton}`}\r\n onClick={() => {\r\n const parentPath = getParentPath(selectedFolder);\r\n const normalizedParentPath = normalizePath(parentPath);\r\n console.log('normalizedParentPath :', normalizedParentPath);\r\n if (!normalizedParentPath || normalizedParentPath === '') return;\r\n expandParentDirectories(normalizedParentPath);\r\n setSelectedFolder(normalizedParentPath);\r\n }}\r\n >\r\n <div className={classes.fileName}>...</div>\r\n <div className={classes.status}></div>\r\n <div></div>\r\n </div>\r\n );\r\n }\r\n\r\n const fileIndex = showGoUpButton ? index - 1 : index;\r\n const file = sortedFiles[fileIndex];\r\n\r\n if (!file) return null;\r\n\r\n const parts = splitPath(file.path);\r\n const fileName = parts[parts.length - 1];\r\n const normalizedPath = normalizePath(file.path);\r\n const isDirectory = directories.includes(normalizedPath);\r\n const hasUpdates = hasUpdatedContent(normalizedPath);\r\n const fileAction = file.action;\r\n const isRestored = file.action === 'restored' ? true : false;\r\n const fileActionLabel = isRestored ? 'New' : file.action;\r\n\r\n return (\r\n <div\r\n style={style}\r\n className={`${classes.file} ${isDirectory ? classes.fileIsDir : ''}`}\r\n onClick={() => {\r\n if (isDirectory) {\r\n setSelectedFolder(normalizedPath);\r\n expandParentDirectories(normalizedPath);\r\n }\r\n }}\r\n >\r\n <div className={classes.fileName}>\r\n {isDirectory ? <Icon type={isDirectory ? 'fm-directory' : 'fm-file'} size={16} /> : <FileIcon filename={fileName || ''} />}{' '}\r\n {isRestored && <span className={classes.newFileIndicator} />} {fileName}\r\n {hasUpdates && <i />}\r\n </div>\r\n <div className={`${classes.status} ${classes[fileAction]}`}>\r\n <i>{fileActionLabel}</i>\r\n </div>\r\n <div className={classes.fileSize}>{isDirectory ? '-' : formatBytes(file.size)}</div>\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className={classes.restoredFileBrowser}>\r\n <div className={classes.toolbar}>\r\n <div className={classes.toolbarLeft}>\r\n {stats && (\r\n <div className={classes.stats}>\r\n <strong>Summary: </strong> {formatNumberToK(stats.total_files)} Items {' • '}\r\n {formatBytes(stats.bytes_restored)}/{formatBytes(stats.total_bytes)}\r\n </div>\r\n )}\r\n </div>\r\n <div className={classes.toolbarRight}>\r\n <div className={classes.filters}>\r\n {(Object.keys(filters) as Array<keyof typeof filters>).map((action) => (\r\n <label key={action}>\r\n <input type=\"checkbox\" checked={filters[action]} onChange={(e) => setFilters({ ...filters, [action]: e.target.checked })} />\r\n {action === 'restored' ? 'New' : action}\r\n </label>\r\n ))}\r\n </div>\r\n <div className={classes.search}>\r\n <Icon type=\"search\" size={16} />\r\n <input type=\"text\" placeholder=\"Search in current Directory...\" value={search} onChange={(e) => setSearch(e.target.value)} />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className={classes.browserContent}>\r\n <div className={`${classes.sidebar} styled__scrollbar`}>\r\n <div className={classes.sidebarHeader}>Directories</div>\r\n {directories.map((dir) => {\r\n const parts = splitPath(dir);\r\n const dirName = parts[parts.length - 1];\r\n const depth = parts.length - 1;\r\n const isExpanded = expandedFolders.has(dir);\r\n const hasUpdates = hasUpdatedContent(dir);\r\n const hasChildren = hasSubdirectories(dir);\r\n\r\n // Only render if parent folders are expanded or if it's a root folder\r\n if (depth === 0 || isVisible(dir)) {\r\n return (\r\n <div\r\n key={dir}\r\n className={`${classes.directory} ${selectedFolder === dir ? classes.selected : ''} ${hasChildren ? '' : classes.directoryEmpty}`}\r\n style={{ paddingLeft: `${depth * 20}px` }}\r\n onClick={() => {\r\n setSelectedFolder(dir);\r\n expandParentDirectories(dir);\r\n }}\r\n >\r\n {hasChildren ? (\r\n <button\r\n className={classes.toggleButton}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n toggleFolder(dir);\r\n }}\r\n >\r\n {isExpanded ? '-' : '+'}\r\n </button>\r\n ) : (\r\n <span className={`${classes.togglePlaceholder}`} />\r\n )}\r\n <span className={classes.dirName}>\r\n <Icon type={'fm-directory'} size={14} /> {dirName}\r\n {hasUpdates && <span className={classes.notification} />}\r\n </span>\r\n </div>\r\n );\r\n }\r\n return null;\r\n })}\r\n </div>\r\n\r\n <div className={classes.content}>\r\n <div className={classes.fileList}>\r\n <div className={classes.header}>\r\n <div>Name</div>\r\n <div>Status</div>\r\n <div>Size</div>\r\n </div>\r\n {selectedFolder && totalItems > 0 ? (\r\n <List\r\n height={window.innerHeight - (isPreview ? 370 : 250)}\r\n itemCount={totalItems}\r\n itemSize={ITEM_HEIGHT}\r\n width=\"100%\"\r\n className={`${classes.fileListVirtualized} styled__scrollbar`}\r\n >\r\n {FileRow}\r\n </List>\r\n ) : (\r\n <div className={classes.fileListEmpty}>Select a folder from the left to browse its content</div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default RestoredFileBrowser;\r\n"],"names":["isMobileDevice","isMobile","ITEM_HEIGHT","RestoredFileBrowser","files","stats","isPreview","selectedFolder","setSelectedFolder","useState","search","setSearch","filters","setFilters","expandedFolders","setExpandedFolders","allPaths","file","separator","getPathSeparator","parts","splitPath","currentPath","part","index","fileSystem","useMemo","system","matchesSearch","matchesFilter","dirPath","getParentPath","normalizedDirPath","normalizePath","directories","dirs","useEffect","hasSubdirectories","dir","d","hasUpdatedContent","path","f","expandParentDirectories","newExpanded","toggleFolder","isVisible","parentParts","parentPath","sortedFiles","a","b","normalizedPathA","normalizedPathB","isDirectoryA","isDirectoryB","priority","showGoUpButton","totalItems","FileRow","style","jsxs","classes","normalizedParentPath","jsx","fileIndex","fileName","normalizedPath","isDirectory","hasUpdates","fileAction","isRestored","fileActionLabel","Icon","FileIcon","formatBytes","formatNumberToK","action","e","dirName","depth","isExpanded","hasChildren","List"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RestoredFileBrowser.js","sources":["../../../../src/components/Restore/RestoredFileBrowser/RestoredFileBrowser.tsx"],"sourcesContent":["import { useState, useMemo, useEffect } from 'react';\r\nimport Icon from '../../common/Icon/Icon';\r\nimport FileIcon from '../../common/FileIcon/FileIcon';\r\nimport classes from './RestoredFileBrowser.module.scss';\r\nimport { RestoredFileItem, RestoredItemsStats } from '../../../@types/restores';\r\nimport { formatBytes, formatNumberToK, isMobile } from '../../../utils/helpers';\r\nimport { getParentPath, getPathSeparator, normalizePath, splitPath } from '../../../utils/restore';\r\nimport { SnapshotBrowserToolbar, SnapshotBrowserDirectories, SnapshotBrowserFileList, SnapshotBrowserGoUpRow } from '../../common/SnapshotBrowser';\r\nimport { useSnapshotNavigation } from '../../common/SnapshotBrowser/hooks/useSnapshotNavigation';\r\nimport sbClasses from '../../common/SnapshotBrowser/SnapshotBrowser.module.scss';\r\n\r\ninterface RestoredFileBrowserProps {\r\n files: RestoredFileItem[];\r\n stats?: RestoredItemsStats;\r\n isPreview?: boolean;\r\n}\r\n\r\nconst isMobileDevice = isMobile();\r\nconst ITEM_HEIGHT = isMobileDevice ? 65 : 45;\r\nconst GRID_COLUMNS = '1fr 100px minmax(80px, auto)';\r\n\r\nconst RestoredFileBrowser = ({ files, stats, isPreview = false }: RestoredFileBrowserProps) => {\r\n const [search, setSearch] = useState('');\r\n const [filters, setFilters] = useState({\r\n unchanged: true,\r\n restored: true,\r\n updated: true,\r\n });\r\n\r\n const [expandedFolders, setExpandedFolders] = useState<Set<string>>(() => {\r\n const allPaths = new Set<string>();\r\n files.forEach((file) => {\r\n const separator = getPathSeparator(file.path);\r\n const parts = splitPath(file.path);\r\n let currentPath = '';\r\n\r\n parts.forEach((part, index) => {\r\n currentPath = currentPath ? `${currentPath}${separator}${part}` : part;\r\n if (index < 3) {\r\n allPaths.add(currentPath);\r\n }\r\n });\r\n });\r\n return allPaths;\r\n });\r\n\r\n const fileSystem = useMemo(() => {\r\n const system: { [key: string]: RestoredFileItem[] } = {};\r\n\r\n files\r\n .filter((file) => {\r\n const matchesSearch = file.path.toLowerCase().includes(search.toLowerCase());\r\n const matchesFilter = filters[file.action];\r\n return matchesSearch && matchesFilter;\r\n })\r\n .forEach((file) => {\r\n const dirPath = getParentPath(file.path);\r\n const normalizedDirPath = normalizePath(dirPath);\r\n\r\n if (normalizedDirPath) {\r\n if (!system[normalizedDirPath]) {\r\n system[normalizedDirPath] = [];\r\n }\r\n system[normalizedDirPath].push(file);\r\n }\r\n });\r\n\r\n return system;\r\n }, [files, search, filters]);\r\n\r\n const directories = useMemo(() => {\r\n const dirs = new Set<string>();\r\n files.forEach((file) => {\r\n const dirPath = getParentPath(file.path);\r\n const separator = getPathSeparator(dirPath);\r\n const parts = splitPath(dirPath);\r\n let currentPath = '';\r\n\r\n parts.forEach((part) => {\r\n currentPath = currentPath ? `${currentPath}${separator}${part}` : part;\r\n if (currentPath) {\r\n dirs.add(currentPath);\r\n }\r\n });\r\n });\r\n return Array.from(dirs);\r\n }, [files]);\r\n\r\n const { selectedFolder, setSelectedFolder, hasSubdirectories, isVisible, expandParentFolders, toggleFolder } = useSnapshotNavigation(\r\n directories,\r\n expandedFolders,\r\n setExpandedFolders,\r\n { splitPath, getPathSeparator, hasLeadingSeparator: false },\r\n );\r\n\r\n useEffect(() => {\r\n if (directories.length > 0 && selectedFolder === '') {\r\n setSelectedFolder(directories[0]);\r\n }\r\n }, [directories, selectedFolder, setSelectedFolder]);\r\n\r\n const hasUpdatedContent = (dir: string) => {\r\n return Object.entries(fileSystem).some(([path, dirFiles]) => {\r\n return path.startsWith(dir) && dirFiles.some((f) => f.action === 'restored' || f.action === 'updated');\r\n });\r\n };\r\n\r\n const sortedFiles = useMemo(() => {\r\n if (!selectedFolder || !fileSystem[selectedFolder]) return [];\r\n\r\n return fileSystem[selectedFolder].sort((a, b) => {\r\n const normalizedPathA = normalizePath(a.path);\r\n const normalizedPathB = normalizePath(b.path);\r\n const isDirectoryA = directories.includes(normalizedPathA);\r\n const isDirectoryB = directories.includes(normalizedPathB);\r\n\r\n if (isDirectoryA && !isDirectoryB) return -1;\r\n if (!isDirectoryA && isDirectoryB) return 1;\r\n\r\n const priority = { restored: 0, updated: 1, unchanged: 2 };\r\n return priority[a.action] - priority[b.action];\r\n });\r\n }, [selectedFolder, fileSystem, directories]);\r\n\r\n const showGoUpButton = selectedFolder && getParentPath(selectedFolder) !== selectedFolder && selectedFolder !== '' && selectedFolder !== '/';\r\n const totalItems = sortedFiles.length + (showGoUpButton ? 1 : 0);\r\n\r\n const FileRow = ({ index, style }: { index: number; style: React.CSSProperties }) => {\r\n if (showGoUpButton && index === 0) {\r\n return (\r\n <SnapshotBrowserGoUpRow\r\n style={style}\r\n onGoUp={() => {\r\n const parentPath = getParentPath(selectedFolder);\r\n const normalizedParentPath = normalizePath(parentPath);\r\n if (!normalizedParentPath || normalizedParentPath === '') return;\r\n expandParentFolders(normalizedParentPath);\r\n setSelectedFolder(normalizedParentPath);\r\n }}\r\n gridTemplateColumns={GRID_COLUMNS}\r\n />\r\n );\r\n }\r\n\r\n const fileIndex = showGoUpButton ? index - 1 : index;\r\n const file = sortedFiles[fileIndex];\r\n\r\n if (!file) return null;\r\n\r\n const parts = splitPath(file.path);\r\n const fileName = parts[parts.length - 1];\r\n const normalizedPath = normalizePath(file.path);\r\n const isDirectory = directories.includes(normalizedPath);\r\n const hasUpdates = hasUpdatedContent(normalizedPath);\r\n const fileAction = file.action;\r\n const isRestored = file.action === 'restored';\r\n const fileActionLabel = isRestored ? 'New' : file.action;\r\n\r\n return (\r\n <div\r\n style={{ ...style, gridTemplateColumns: GRID_COLUMNS }}\r\n className={`${sbClasses.snapshotFile} ${isDirectory ? sbClasses.fileIsDir : ''}`}\r\n onClick={() => {\r\n if (isDirectory) {\r\n setSelectedFolder(normalizedPath);\r\n expandParentFolders(normalizedPath);\r\n }\r\n }}\r\n >\r\n <div className={sbClasses.fileName}>\r\n {isDirectory ? <Icon type={'fm-directory'} size={16} /> : <FileIcon filename={fileName || ''} />}{' '}\r\n {isRestored && <span className={classes.newFileIndicator} />} {fileName}\r\n {hasUpdates && <i />}\r\n </div>\r\n <div className={`${classes.status} ${classes[fileAction]}`}>\r\n <i>{fileActionLabel}</i>\r\n </div>\r\n <div className={classes.fileSize}>{isDirectory ? '-' : formatBytes(file.size)}</div>\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className={sbClasses.snapshotBrowser}>\r\n <SnapshotBrowserToolbar\r\n search={search}\r\n onSearchChange={setSearch}\r\n leftContent={\r\n stats && (\r\n <div className={sbClasses.stats}>\r\n <strong>Summary: </strong> {formatNumberToK(stats.total_files)} Items {' • '}\r\n {formatBytes(stats.bytes_restored)}/{formatBytes(stats.total_bytes)}\r\n </div>\r\n )\r\n }\r\n rightContent={\r\n <div className={classes.filters}>\r\n {(Object.keys(filters) as Array<keyof typeof filters>).map((action) => (\r\n <label key={action}>\r\n <input type=\"checkbox\" checked={filters[action]} onChange={(e) => setFilters({ ...filters, [action]: e.target.checked })} />\r\n {action === 'restored' ? 'New' : action}\r\n </label>\r\n ))}\r\n </div>\r\n }\r\n />\r\n\r\n <div className={sbClasses.browserContent}>\r\n <SnapshotBrowserDirectories\r\n directories={directories}\r\n selectedFolder={selectedFolder}\r\n expandedFolders={expandedFolders}\r\n onDirectoryClick={(dir) => {\r\n setSelectedFolder(dir);\r\n expandParentFolders(dir);\r\n }}\r\n onToggleFolder={toggleFolder}\r\n isVisible={isVisible}\r\n hasSubdirectories={hasSubdirectories}\r\n renderDirectoryExtra={(dir) => {\r\n const hasUpdates = hasUpdatedContent(dir);\r\n return hasUpdates ? <span className={classes.notification} /> : null;\r\n }}\r\n />\r\n\r\n <div className={sbClasses.content}>\r\n <SnapshotBrowserFileList\r\n files={Array(totalItems)}\r\n height={window.innerHeight - (isPreview ? 370 : 250)}\r\n itemSize={ITEM_HEIGHT}\r\n headerContent={\r\n <>\r\n <div>Name</div>\r\n <div>Status</div>\r\n <div>Size</div>\r\n </>\r\n }\r\n renderRow={FileRow}\r\n selectedFolder={selectedFolder || null}\r\n gridTemplateColumns={GRID_COLUMNS}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default RestoredFileBrowser;\r\n"],"names":["isMobileDevice","isMobile","ITEM_HEIGHT","GRID_COLUMNS","RestoredFileBrowser","files","stats","isPreview","search","setSearch","useState","filters","setFilters","expandedFolders","setExpandedFolders","allPaths","file","separator","getPathSeparator","parts","splitPath","currentPath","part","index","fileSystem","useMemo","system","matchesSearch","matchesFilter","dirPath","getParentPath","normalizedDirPath","normalizePath","directories","dirs","selectedFolder","setSelectedFolder","hasSubdirectories","isVisible","expandParentFolders","toggleFolder","useSnapshotNavigation","useEffect","hasUpdatedContent","dir","path","dirFiles","f","sortedFiles","a","b","normalizedPathA","normalizedPathB","isDirectoryA","isDirectoryB","priority","showGoUpButton","totalItems","FileRow","style","jsx","SnapshotBrowserGoUpRow","parentPath","normalizedParentPath","fileIndex","fileName","normalizedPath","isDirectory","hasUpdates","fileAction","isRestored","fileActionLabel","jsxs","sbClasses","Icon","FileIcon","classes","formatBytes","SnapshotBrowserToolbar","formatNumberToK","action","e","SnapshotBrowserDirectories","SnapshotBrowserFileList","Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const t = "_snapshotBrowser_wLZ6H", e = "_storageSelect_x5Y34", o = "_toolbar_8CUgH", s = "_toolbarRight_d5DNW", r = "_search_uTjHh", i = "_toolbarLeft_lzMER", a = "_stats_uNive", n = "_browserContent_7EKnV", l = "_loadingState_UrPuT", c = "_sidebar_Dwr4Y", _ = "_sidebarHeader_HSjGb", d = "_noDirectories_xpBll", f = "_directory_j1rhT", g = "_toggleButton_1D4RS", h = "_togglePlaceholder_z6AXP", b = "_dirName_jZCs4", p = "_directoryEmpty_SgiKx", S = "_selected_r7Mw7", u = "_content_wUpVw", y = "_fileList_xL0re", L = "_header_I04uE", m = "_activeSort_Yp9aa", w = "_headerActions_uZpzN", A = "_fileListEmpty_GKzxO", E = "_virtualFileList_xTzAQ", F = "_snapshotFile_TRFxD", N = "_fileIsDir_p0G1c", x = "_fileName_Neb7E", B = "_fileModifiedAt_S6CoI", D = "_fileSize_x6NTv", v = "_fileActions_tyxE6", z = "_goUpButton_gK1aV", M = "_errorState_u2XFr", C = "_restoreModalFile_tuyR4", H = {
|
|
2
|
+
snapshotBrowser: t,
|
|
3
|
+
storageSelect: e,
|
|
4
|
+
toolbar: o,
|
|
5
|
+
toolbarRight: s,
|
|
6
|
+
search: r,
|
|
7
|
+
toolbarLeft: i,
|
|
8
|
+
stats: a,
|
|
9
|
+
browserContent: n,
|
|
10
|
+
loadingState: l,
|
|
11
|
+
sidebar: c,
|
|
12
|
+
sidebarHeader: _,
|
|
13
|
+
noDirectories: d,
|
|
14
|
+
directory: f,
|
|
15
|
+
toggleButton: g,
|
|
16
|
+
togglePlaceholder: h,
|
|
17
|
+
dirName: b,
|
|
18
|
+
directoryEmpty: p,
|
|
19
|
+
selected: S,
|
|
20
|
+
content: u,
|
|
21
|
+
fileList: y,
|
|
22
|
+
header: L,
|
|
23
|
+
activeSort: m,
|
|
24
|
+
headerActions: w,
|
|
25
|
+
fileListEmpty: A,
|
|
26
|
+
virtualFileList: E,
|
|
27
|
+
snapshotFile: F,
|
|
28
|
+
fileIsDir: N,
|
|
29
|
+
fileName: x,
|
|
30
|
+
fileModifiedAt: B,
|
|
31
|
+
fileSize: D,
|
|
32
|
+
fileActions: v,
|
|
33
|
+
goUpButton: z,
|
|
34
|
+
errorState: M,
|
|
35
|
+
restoreModalFile: C
|
|
36
|
+
};
|
|
37
|
+
export {
|
|
38
|
+
m as activeSort,
|
|
39
|
+
n as browserContent,
|
|
40
|
+
u as content,
|
|
41
|
+
H as default,
|
|
42
|
+
b as dirName,
|
|
43
|
+
f as directory,
|
|
44
|
+
p as directoryEmpty,
|
|
45
|
+
M as errorState,
|
|
46
|
+
v as fileActions,
|
|
47
|
+
N as fileIsDir,
|
|
48
|
+
y as fileList,
|
|
49
|
+
A as fileListEmpty,
|
|
50
|
+
B as fileModifiedAt,
|
|
51
|
+
x as fileName,
|
|
52
|
+
D as fileSize,
|
|
53
|
+
z as goUpButton,
|
|
54
|
+
L as header,
|
|
55
|
+
w as headerActions,
|
|
56
|
+
l as loadingState,
|
|
57
|
+
d as noDirectories,
|
|
58
|
+
C as restoreModalFile,
|
|
59
|
+
r as search,
|
|
60
|
+
S as selected,
|
|
61
|
+
c as sidebar,
|
|
62
|
+
_ as sidebarHeader,
|
|
63
|
+
t as snapshotBrowser,
|
|
64
|
+
F as snapshotFile,
|
|
65
|
+
a as stats,
|
|
66
|
+
e as storageSelect,
|
|
67
|
+
g as toggleButton,
|
|
68
|
+
h as togglePlaceholder,
|
|
69
|
+
o as toolbar,
|
|
70
|
+
i as toolbarLeft,
|
|
71
|
+
s as toolbarRight,
|
|
72
|
+
E as virtualFileList
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=SnapshotBrowser.module.scss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowser.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface SnapshotBrowserDirectoriesProps {
|
|
3
|
+
directories: string[];
|
|
4
|
+
selectedFolder: string;
|
|
5
|
+
expandedFolders: Set<string>;
|
|
6
|
+
useProgressiveLoading?: boolean;
|
|
7
|
+
onDirectoryClick: (path: string) => void;
|
|
8
|
+
onToggleFolder: (dir: string) => void;
|
|
9
|
+
isVisible: (dir: string) => boolean;
|
|
10
|
+
hasSubdirectories: (dir: string) => boolean;
|
|
11
|
+
renderDirectoryExtra?: (dir: string) => ReactNode;
|
|
12
|
+
/** Custom function to split a path into parts. Defaults to splitting by / and \ */
|
|
13
|
+
splitPath?: (path: string) => string[];
|
|
14
|
+
}
|
|
15
|
+
declare const SnapshotBrowserDirectories: ({ directories, selectedFolder, expandedFolders, useProgressiveLoading, onDirectoryClick, onToggleFolder, isVisible, hasSubdirectories, renderDirectoryExtra, splitPath: splitPathFn, }: SnapshotBrowserDirectoriesProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export default SnapshotBrowserDirectories;
|
|
17
|
+
//# sourceMappingURL=SnapshotBrowserDirectories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserDirectories.d.ts","sourceRoot":"","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserDirectories.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlC,UAAU,+BAA+B;IACtC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACpC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IAClD,mFAAmF;IACnF,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CACzC;AAID,QAAA,MAAM,0BAA0B,GAAI,wLAWjC,+BAA+B,4CAkDjC,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsxs as a, jsx as l } from "react/jsx-runtime";
|
|
2
|
+
import C from "../Icon/Icon.js";
|
|
3
|
+
import e from "./SnapshotBrowser.module.scss.js";
|
|
4
|
+
const v = (t) => t.split(/[/\\]/).filter(Boolean), j = ({
|
|
5
|
+
directories: t,
|
|
6
|
+
selectedFolder: h,
|
|
7
|
+
expandedFolders: p,
|
|
8
|
+
useProgressiveLoading: c,
|
|
9
|
+
onDirectoryClick: d,
|
|
10
|
+
onToggleFolder: m,
|
|
11
|
+
isVisible: r,
|
|
12
|
+
hasSubdirectories: f,
|
|
13
|
+
renderDirectoryExtra: o,
|
|
14
|
+
splitPath: N = v
|
|
15
|
+
}) => /* @__PURE__ */ a("div", { className: `${e.sidebar} styled__scrollbar`, children: [
|
|
16
|
+
/* @__PURE__ */ l("div", { className: e.sidebarHeader, children: /* @__PURE__ */ a("h4", { children: [
|
|
17
|
+
"Directories (",
|
|
18
|
+
t.length,
|
|
19
|
+
c && "+",
|
|
20
|
+
")"
|
|
21
|
+
] }) }),
|
|
22
|
+
t.length === 0 && /* @__PURE__ */ l("div", { className: e.noDirectories, children: c ? "Loading directories..." : "No directories found" }),
|
|
23
|
+
t.map((s) => {
|
|
24
|
+
const n = N(s), g = n[n.length - 1] || s, u = n.length - 1, b = p.has(s), i = f(s);
|
|
25
|
+
return r(s) ? /* @__PURE__ */ a(
|
|
26
|
+
"div",
|
|
27
|
+
{
|
|
28
|
+
className: `${e.directory} ${h === s ? e.selected : ""} ${i ? "" : e.directoryEmpty}`,
|
|
29
|
+
style: { paddingLeft: `${u * 20}px` },
|
|
30
|
+
onClick: () => d(s),
|
|
31
|
+
children: [
|
|
32
|
+
i ? /* @__PURE__ */ l(
|
|
33
|
+
"button",
|
|
34
|
+
{
|
|
35
|
+
className: e.toggleButton,
|
|
36
|
+
onClick: ($) => {
|
|
37
|
+
$.stopPropagation(), m(s);
|
|
38
|
+
},
|
|
39
|
+
children: b ? "-" : "+"
|
|
40
|
+
}
|
|
41
|
+
) : /* @__PURE__ */ l("span", { className: e.togglePlaceholder }),
|
|
42
|
+
/* @__PURE__ */ a("span", { className: e.dirName, children: [
|
|
43
|
+
/* @__PURE__ */ l(C, { type: "fm-directory", size: 14 }),
|
|
44
|
+
" ",
|
|
45
|
+
g
|
|
46
|
+
] }),
|
|
47
|
+
o == null ? void 0 : o(s)
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
s
|
|
51
|
+
) : null;
|
|
52
|
+
})
|
|
53
|
+
] });
|
|
54
|
+
export {
|
|
55
|
+
j as default
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=SnapshotBrowserDirectories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserDirectories.js","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserDirectories.tsx"],"sourcesContent":["import { ReactNode } from 'react';\r\nimport Icon from '../Icon/Icon';\r\nimport classes from './SnapshotBrowser.module.scss';\r\n\r\ninterface SnapshotBrowserDirectoriesProps {\r\n directories: string[];\r\n selectedFolder: string;\r\n expandedFolders: Set<string>;\r\n useProgressiveLoading?: boolean;\r\n onDirectoryClick: (path: string) => void;\r\n onToggleFolder: (dir: string) => void;\r\n isVisible: (dir: string) => boolean;\r\n hasSubdirectories: (dir: string) => boolean;\r\n renderDirectoryExtra?: (dir: string) => ReactNode;\r\n /** Custom function to split a path into parts. Defaults to splitting by / and \\ */\r\n splitPath?: (path: string) => string[];\r\n}\r\n\r\nconst defaultSplitPath = (path: string) => path.split(/[/\\\\]/).filter(Boolean);\r\n\r\nconst SnapshotBrowserDirectories = ({\r\n directories,\r\n selectedFolder,\r\n expandedFolders,\r\n useProgressiveLoading,\r\n onDirectoryClick,\r\n onToggleFolder,\r\n isVisible,\r\n hasSubdirectories,\r\n renderDirectoryExtra,\r\n splitPath: splitPathFn = defaultSplitPath,\r\n}: SnapshotBrowserDirectoriesProps) => {\r\n return (\r\n <div className={`${classes.sidebar} styled__scrollbar`}>\r\n <div className={classes.sidebarHeader}>\r\n <h4>\r\n Directories ({directories.length}\r\n {useProgressiveLoading && '+'})\r\n </h4>\r\n </div>\r\n {directories.length === 0 && (\r\n <div className={classes.noDirectories}>{useProgressiveLoading ? 'Loading directories...' : 'No directories found'}</div>\r\n )}\r\n {directories.map((dir) => {\r\n const parts = splitPathFn(dir);\r\n const dirName = parts[parts.length - 1] || dir;\r\n const depth = parts.length - 1;\r\n const isExpanded = expandedFolders.has(dir);\r\n const hasChildren = hasSubdirectories(dir);\r\n\r\n if (!isVisible(dir)) return null;\r\n\r\n return (\r\n <div\r\n key={dir}\r\n className={`${classes.directory} ${selectedFolder === dir ? classes.selected : ''} ${hasChildren ? '' : classes.directoryEmpty}`}\r\n style={{ paddingLeft: `${depth * 20}px` }}\r\n onClick={() => onDirectoryClick(dir)}\r\n >\r\n {hasChildren ? (\r\n <button\r\n className={classes.toggleButton}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onToggleFolder(dir);\r\n }}\r\n >\r\n {isExpanded ? '-' : '+'}\r\n </button>\r\n ) : (\r\n <span className={classes.togglePlaceholder} />\r\n )}\r\n <span className={classes.dirName}>\r\n <Icon type={'fm-directory'} size={14} /> {dirName}\r\n </span>\r\n {renderDirectoryExtra?.(dir)}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n\r\nexport default SnapshotBrowserDirectories;\r\n"],"names":["defaultSplitPath","path","SnapshotBrowserDirectories","directories","selectedFolder","expandedFolders","useProgressiveLoading","onDirectoryClick","onToggleFolder","isVisible","hasSubdirectories","renderDirectoryExtra","splitPathFn","classes","jsx","dir","parts","dirName","depth","isExpanded","hasChildren","jsxs","e","Icon"],"mappings":";;;AAkBA,MAAMA,IAAmB,CAACC,MAAiBA,EAAK,MAAM,OAAO,EAAE,OAAO,OAAO,GAEvEC,IAA6B,CAAC;AAAA,EACjC,aAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,uBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,WAAWC,IAAcZ;AAC5B,wBAEO,OAAA,EAAI,WAAW,GAAGa,EAAQ,OAAO,sBAC/B,UAAA;AAAA,EAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWD,EAAQ,eACrB,4BAAC,MAAA,EAAG,UAAA;AAAA,IAAA;AAAA,IACaV,EAAY;AAAA,IACzBG,KAAyB;AAAA,IAAI;AAAA,EAAA,EAAA,CACjC,EAAA,CACH;AAAA,EACCH,EAAY,WAAW,KACrB,gBAAAW,EAAC,OAAA,EAAI,WAAWD,EAAQ,eAAgB,UAAAP,IAAwB,2BAA2B,uBAAA,CAAuB;AAAA,EAEpHH,EAAY,IAAI,CAACY,MAAQ;AACvB,UAAMC,IAAQJ,EAAYG,CAAG,GACvBE,IAAUD,EAAMA,EAAM,SAAS,CAAC,KAAKD,GACrCG,IAAQF,EAAM,SAAS,GACvBG,IAAad,EAAgB,IAAIU,CAAG,GACpCK,IAAcV,EAAkBK,CAAG;AAEzC,WAAKN,EAAUM,CAAG,IAGf,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QAEE,WAAW,GAAGR,EAAQ,SAAS,IAAIT,MAAmBW,IAAMF,EAAQ,WAAW,EAAE,IAAIO,IAAc,KAAKP,EAAQ,cAAc;AAAA,QAC9H,OAAO,EAAE,aAAa,GAAGK,IAAQ,EAAE,KAAA;AAAA,QACnC,SAAS,MAAMX,EAAiBQ,CAAG;AAAA,QAElC,UAAA;AAAA,UAAAK,IACE,gBAAAN;AAAA,YAAC;AAAA,YAAA;AAAA,cACE,WAAWD,EAAQ;AAAA,cACnB,SAAS,CAACS,MAAM;AACb,gBAAAA,EAAE,gBAAA,GACFd,EAAeO,CAAG;AAAA,cACrB;AAAA,cAEC,cAAa,MAAM;AAAA,YAAA;AAAA,UAAA,IAGvB,gBAAAD,EAAC,QAAA,EAAK,WAAWD,EAAQ,kBAAA,CAAmB;AAAA,UAE/C,gBAAAQ,EAAC,QAAA,EAAK,WAAWR,EAAQ,SACtB,UAAA;AAAA,YAAA,gBAAAC,EAACS,GAAA,EAAK,MAAM,gBAAgB,MAAM,IAAI;AAAA,YAAE;AAAA,YAAEN;AAAA,UAAA,GAC7C;AAAA,UACCN,KAAA,gBAAAA,EAAuBI;AAAA,QAAG;AAAA,MAAA;AAAA,MArBtBA;AAAA,IAAA,IAJiB;AAAA,EA4B/B,CAAC;AAAA,GACJ;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
interface SnapshotBrowserFileListProps {
|
|
3
|
+
files: any[];
|
|
4
|
+
height: number;
|
|
5
|
+
itemSize?: number;
|
|
6
|
+
headerContent: ReactNode;
|
|
7
|
+
renderRow: (props: {
|
|
8
|
+
index: number;
|
|
9
|
+
style: React.CSSProperties;
|
|
10
|
+
}) => React.ReactElement | null;
|
|
11
|
+
selectedFolder: string | null;
|
|
12
|
+
emptyMessage?: string;
|
|
13
|
+
isLoading?: boolean;
|
|
14
|
+
gridTemplateColumns?: string;
|
|
15
|
+
}
|
|
16
|
+
declare const SnapshotBrowserFileList: ({ files, height, itemSize, headerContent, renderRow, selectedFolder, emptyMessage, isLoading, gridTemplateColumns, }: SnapshotBrowserFileListProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default SnapshotBrowserFileList;
|
|
18
|
+
//# sourceMappingURL=SnapshotBrowserFileList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserFileList.d.ts","sourceRoot":"","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserFileList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQzC,UAAU,4BAA4B;IACnC,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,SAAS,CAAC;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAA;KAAE,KAAK,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC/F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,QAAA,MAAM,uBAAuB,GAAI,sHAU9B,4BAA4B,4CAmB9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsxs as h, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { FixedSizeList as d } from "react-window";
|
|
3
|
+
import t from "./SnapshotBrowser.module.scss.js";
|
|
4
|
+
import { isMobile as f } from "../../../utils/helpers.js";
|
|
5
|
+
const v = f(), p = v ? 65 : 46, b = ({
|
|
6
|
+
files: e,
|
|
7
|
+
height: o,
|
|
8
|
+
itemSize: r = p,
|
|
9
|
+
headerContent: n,
|
|
10
|
+
renderRow: a,
|
|
11
|
+
selectedFolder: s,
|
|
12
|
+
emptyMessage: c = "Select a folder from the left to browse its content",
|
|
13
|
+
isLoading: m,
|
|
14
|
+
gridTemplateColumns: l
|
|
15
|
+
}) => /* @__PURE__ */ h("div", { className: t.fileList, children: [
|
|
16
|
+
/* @__PURE__ */ i("div", { className: t.header, style: l ? { gridTemplateColumns: l } : void 0, children: n }),
|
|
17
|
+
s !== null && e.length > 0 && /* @__PURE__ */ i("div", { className: t.virtualFileList, children: /* @__PURE__ */ i(d, { height: o, itemCount: e.length, itemSize: r, width: "100%", overscanCount: 5, children: a }) }),
|
|
18
|
+
s === null && /* @__PURE__ */ i("div", { className: t.fileListEmpty, children: c }),
|
|
19
|
+
s !== null && !m && e.length === 0 && /* @__PURE__ */ i("div", { className: t.fileListEmpty, children: "This folder is empty" })
|
|
20
|
+
] });
|
|
21
|
+
export {
|
|
22
|
+
b as default
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=SnapshotBrowserFileList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserFileList.js","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserFileList.tsx"],"sourcesContent":["import React, { ReactNode } from 'react';\r\nimport { FixedSizeList as List } from 'react-window';\r\nimport classes from './SnapshotBrowser.module.scss';\r\nimport { isMobile } from '../../../utils';\r\n\r\nconst isMobileDevice = isMobile();\r\nconst DEFAULT_ITEM_HEIGHT = isMobileDevice ? 65 : 46;\r\n\r\ninterface SnapshotBrowserFileListProps {\r\n files: any[];\r\n height: number;\r\n itemSize?: number;\r\n headerContent: ReactNode;\r\n renderRow: (props: { index: number; style: React.CSSProperties }) => React.ReactElement | null;\r\n selectedFolder: string | null;\r\n emptyMessage?: string;\r\n isLoading?: boolean;\r\n gridTemplateColumns?: string;\r\n}\r\n\r\nconst SnapshotBrowserFileList = ({\r\n files,\r\n height,\r\n itemSize = DEFAULT_ITEM_HEIGHT,\r\n headerContent,\r\n renderRow,\r\n selectedFolder,\r\n emptyMessage = 'Select a folder from the left to browse its content',\r\n isLoading,\r\n gridTemplateColumns,\r\n}: SnapshotBrowserFileListProps) => {\r\n return (\r\n <div className={classes.fileList}>\r\n <div className={classes.header} style={gridTemplateColumns ? { gridTemplateColumns } : undefined}>\r\n {headerContent}\r\n </div>\r\n\r\n {selectedFolder !== null && files.length > 0 && (\r\n <div className={classes.virtualFileList}>\r\n <List height={height} itemCount={files.length} itemSize={itemSize} width=\"100%\" overscanCount={5}>\r\n {renderRow}\r\n </List>\r\n </div>\r\n )}\r\n\r\n {selectedFolder === null && <div className={classes.fileListEmpty}>{emptyMessage}</div>}\r\n {selectedFolder !== null && !isLoading && files.length === 0 && <div className={classes.fileListEmpty}>This folder is empty</div>}\r\n </div>\r\n );\r\n};\r\n\r\nexport default SnapshotBrowserFileList;\r\n"],"names":["isMobileDevice","isMobile","DEFAULT_ITEM_HEIGHT","SnapshotBrowserFileList","files","height","itemSize","headerContent","renderRow","selectedFolder","emptyMessage","isLoading","gridTemplateColumns","jsxs","classes","jsx","List"],"mappings":";;;;AAKA,MAAMA,IAAiBC,EAAA,GACjBC,IAAsBF,IAAiB,KAAK,IAc5CG,IAA0B,CAAC;AAAA,EAC9B,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC,IAAWJ;AAAA,EACX,eAAAK;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,WAAAC;AAAA,EACA,qBAAAC;AACH,MAEM,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAQ,UACrB,UAAA;AAAA,EAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWD,EAAQ,QAAQ,OAAOF,IAAsB,EAAE,qBAAAA,EAAA,IAAwB,QACnF,UAAAL,EAAA,CACJ;AAAA,EAECE,MAAmB,QAAQL,EAAM,SAAS,KACxC,gBAAAW,EAAC,OAAA,EAAI,WAAWD,EAAQ,iBACrB,UAAA,gBAAAC,EAACC,KAAK,QAAAX,GAAgB,WAAWD,EAAM,QAAQ,UAAAE,GAAoB,OAAM,QAAO,eAAe,GAC3F,UAAAE,EAAA,CACJ,EAAA,CACH;AAAA,EAGFC,MAAmB,QAAQ,gBAAAM,EAAC,SAAI,WAAWD,EAAQ,eAAgB,UAAAJ,GAAa;AAAA,EAChFD,MAAmB,QAAQ,CAACE,KAAaP,EAAM,WAAW,KAAK,gBAAAW,EAAC,OAAA,EAAI,WAAWD,EAAQ,eAAe,UAAA,uBAAA,CAAoB;AAAA,GAC9H;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
interface SnapshotBrowserFileRowProps {
|
|
3
|
+
style: React.CSSProperties;
|
|
4
|
+
file: {
|
|
5
|
+
path: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
isDirectory?: boolean;
|
|
8
|
+
};
|
|
9
|
+
isDirectory: boolean;
|
|
10
|
+
onClick?: () => void;
|
|
11
|
+
namePrefix?: ReactNode;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
gridTemplateColumns?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
declare const SnapshotBrowserFileRow: ({ style, file, isDirectory, onClick, namePrefix, children, gridTemplateColumns, className, }: SnapshotBrowserFileRowProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default SnapshotBrowserFileRow;
|
|
18
|
+
//# sourceMappingURL=SnapshotBrowserFileRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserFileRow.d.ts","sourceRoot":"","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserFileRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKzC,UAAU,2BAA2B;IAClC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC;IAC3B,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7D,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,QAAA,MAAM,sBAAsB,GAAI,8FAS7B,2BAA2B,4CAgB7B,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsxs as t, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import c from "../Icon/Icon.js";
|
|
3
|
+
import d from "../FileIcon/FileIcon.js";
|
|
4
|
+
import e from "./SnapshotBrowser.module.scss.js";
|
|
5
|
+
const I = ({
|
|
6
|
+
style: m,
|
|
7
|
+
file: s,
|
|
8
|
+
isDirectory: o,
|
|
9
|
+
onClick: l,
|
|
10
|
+
namePrefix: p,
|
|
11
|
+
children: n,
|
|
12
|
+
gridTemplateColumns: i,
|
|
13
|
+
className: f
|
|
14
|
+
}) => {
|
|
15
|
+
const r = s.name || s.path.split("/").pop() || "";
|
|
16
|
+
return /* @__PURE__ */ t(
|
|
17
|
+
"div",
|
|
18
|
+
{
|
|
19
|
+
style: { ...m, ...i ? { gridTemplateColumns: i } : {} },
|
|
20
|
+
className: `${e.snapshotFile} ${o ? e.fileIsDir : ""} ${f || ""}`,
|
|
21
|
+
onClick: l,
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ t("div", { className: e.fileName, children: [
|
|
24
|
+
p,
|
|
25
|
+
o ? /* @__PURE__ */ a(c, { type: "fm-directory", size: 16 }) : /* @__PURE__ */ a(d, { filename: r }),
|
|
26
|
+
" ",
|
|
27
|
+
r
|
|
28
|
+
] }),
|
|
29
|
+
n
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
I as default
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=SnapshotBrowserFileRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserFileRow.js","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserFileRow.tsx"],"sourcesContent":["import React, { ReactNode } from 'react';\r\nimport Icon from '../Icon/Icon';\r\nimport FileIcon from '../FileIcon/FileIcon';\r\nimport classes from './SnapshotBrowser.module.scss';\r\n\r\ninterface SnapshotBrowserFileRowProps {\r\n style: React.CSSProperties;\r\n file: { path: string; name?: string; isDirectory?: boolean };\r\n isDirectory: boolean;\r\n onClick?: () => void;\r\n namePrefix?: ReactNode;\r\n children?: ReactNode;\r\n gridTemplateColumns?: string;\r\n className?: string;\r\n}\r\n\r\nconst SnapshotBrowserFileRow = ({\r\n style,\r\n file,\r\n isDirectory,\r\n onClick,\r\n namePrefix,\r\n children,\r\n gridTemplateColumns,\r\n className,\r\n}: SnapshotBrowserFileRowProps) => {\r\n const fileName = file.name || file.path.split('/').pop() || '';\r\n\r\n return (\r\n <div\r\n style={{ ...style, ...(gridTemplateColumns ? { gridTemplateColumns } : {}) }}\r\n className={`${classes.snapshotFile} ${isDirectory ? classes.fileIsDir : ''} ${className || ''}`}\r\n onClick={onClick}\r\n >\r\n <div className={classes.fileName}>\r\n {namePrefix}\r\n {isDirectory ? <Icon type={'fm-directory'} size={16} /> : <FileIcon filename={fileName} />} {fileName}\r\n </div>\r\n {children}\r\n </div>\r\n );\r\n};\r\n\r\nexport default SnapshotBrowserFileRow;\r\n"],"names":["SnapshotBrowserFileRow","style","file","isDirectory","onClick","namePrefix","children","gridTemplateColumns","className","fileName","jsxs","classes","jsx","Icon","FileIcon"],"mappings":";;;;AAgBA,MAAMA,IAAyB,CAAC;AAAA,EAC7B,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,aAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,UAAAC;AAAA,EACA,qBAAAC;AAAA,EACA,WAAAC;AACH,MAAmC;AAChC,QAAMC,IAAWP,EAAK,QAAQA,EAAK,KAAK,MAAM,GAAG,EAAE,IAAA,KAAS;AAE5D,SACG,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,OAAO,EAAE,GAAGT,GAAO,GAAIM,IAAsB,EAAE,qBAAAA,EAAA,IAAwB,GAAC;AAAA,MACxE,WAAW,GAAGI,EAAQ,YAAY,IAAIR,IAAcQ,EAAQ,YAAY,EAAE,IAAIH,KAAa,EAAE;AAAA,MAC7F,SAAAJ;AAAA,MAEA,UAAA;AAAA,QAAA,gBAAAM,EAAC,OAAA,EAAI,WAAWC,EAAQ,UACpB,UAAA;AAAA,UAAAN;AAAA,UACAF,IAAc,gBAAAS,EAACC,GAAA,EAAK,MAAM,gBAAgB,MAAM,GAAA,CAAI,IAAK,gBAAAD,EAACE,GAAA,EAAS,UAAUL,EAAA,CAAU;AAAA,UAAG;AAAA,UAAEA;AAAA,QAAA,GAChG;AAAA,QACCH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface SnapshotBrowserGoUpRowProps {
|
|
3
|
+
style: React.CSSProperties;
|
|
4
|
+
onGoUp: () => void;
|
|
5
|
+
gridTemplateColumns?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const SnapshotBrowserGoUpRow: ({ style, onGoUp, gridTemplateColumns }: SnapshotBrowserGoUpRowProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default SnapshotBrowserGoUpRow;
|
|
9
|
+
//# sourceMappingURL=SnapshotBrowserGoUpRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserGoUpRow.d.ts","sourceRoot":"","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,2BAA2B;IAClC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,QAAA,MAAM,sBAAsB,GAAI,wCAAwC,2BAA2B,4CAUlG,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import s from "./SnapshotBrowser.module.scss.js";
|
|
3
|
+
const l = ({ style: r, onGoUp: i, gridTemplateColumns: o }) => /* @__PURE__ */ e(
|
|
4
|
+
"div",
|
|
5
|
+
{
|
|
6
|
+
style: { ...r, ...o ? { gridTemplateColumns: o } : {} },
|
|
7
|
+
className: `${s.snapshotFile} ${s.fileIsDir} ${s.goUpButton}`,
|
|
8
|
+
onClick: i,
|
|
9
|
+
children: /* @__PURE__ */ e("div", { className: s.fileName, children: "..." })
|
|
10
|
+
}
|
|
11
|
+
);
|
|
12
|
+
export {
|
|
13
|
+
l as default
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=SnapshotBrowserGoUpRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserGoUpRow.js","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserGoUpRow.tsx"],"sourcesContent":["import React from 'react';\r\nimport classes from './SnapshotBrowser.module.scss';\r\n\r\ninterface SnapshotBrowserGoUpRowProps {\r\n style: React.CSSProperties;\r\n onGoUp: () => void;\r\n gridTemplateColumns?: string;\r\n}\r\n\r\nconst SnapshotBrowserGoUpRow = ({ style, onGoUp, gridTemplateColumns }: SnapshotBrowserGoUpRowProps) => {\r\n return (\r\n <div\r\n style={{ ...style, ...(gridTemplateColumns ? { gridTemplateColumns } : {}) }}\r\n className={`${classes.snapshotFile} ${classes.fileIsDir} ${classes.goUpButton}`}\r\n onClick={onGoUp}\r\n >\r\n <div className={classes.fileName}>...</div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default SnapshotBrowserGoUpRow;\r\n"],"names":["SnapshotBrowserGoUpRow","style","onGoUp","gridTemplateColumns","jsx","classes"],"mappings":";;AASA,MAAMA,IAAyB,CAAC,EAAE,OAAAC,GAAO,QAAAC,GAAQ,qBAAAC,QAE3C,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACE,OAAO,EAAE,GAAGH,GAAO,GAAIE,IAAsB,EAAE,qBAAAA,EAAA,IAAwB,GAAC;AAAA,IACxE,WAAW,GAAGE,EAAQ,YAAY,IAAIA,EAAQ,SAAS,IAAIA,EAAQ,UAAU;AAAA,IAC7E,SAASH;AAAA,IAET,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAQ,UAAU,UAAA,MAAA,CAAG;AAAA,EAAA;AAAA;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface SnapshotBrowserToolbarProps {
|
|
3
|
+
search: string;
|
|
4
|
+
onSearchChange: (value: string) => void;
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
leftContent?: ReactNode;
|
|
7
|
+
rightContent?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare const SnapshotBrowserToolbar: ({ search, onSearchChange, isLoading, leftContent, rightContent }: SnapshotBrowserToolbarProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export default SnapshotBrowserToolbar;
|
|
11
|
+
//# sourceMappingURL=SnapshotBrowserToolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserToolbar.d.ts","sourceRoot":"","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlC,UAAU,2BAA2B;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,YAAY,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,QAAA,MAAM,sBAAsB,GAAI,kEAAkE,2BAA2B,4CAc5H,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsxs as a, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import o from "../Icon/Icon.js";
|
|
3
|
+
import r from "./SnapshotBrowser.module.scss.js";
|
|
4
|
+
const p = ({ search: s, onSearchChange: t, isLoading: l, leftContent: i, rightContent: c }) => /* @__PURE__ */ a("div", { className: r.toolbar, children: [
|
|
5
|
+
/* @__PURE__ */ e("div", { className: r.toolbarLeft, children: i }),
|
|
6
|
+
/* @__PURE__ */ a("div", { className: r.toolbarRight, children: [
|
|
7
|
+
c,
|
|
8
|
+
/* @__PURE__ */ a("div", { className: r.search, children: [
|
|
9
|
+
/* @__PURE__ */ e(o, { type: "search", size: 16 }),
|
|
10
|
+
/* @__PURE__ */ e("input", { type: "text", placeholder: "Search in current Directory...", value: s, onChange: (n) => t(n.target.value) }),
|
|
11
|
+
l && /* @__PURE__ */ e(o, { type: "loading", size: 12 })
|
|
12
|
+
] })
|
|
13
|
+
] })
|
|
14
|
+
] });
|
|
15
|
+
export {
|
|
16
|
+
p as default
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=SnapshotBrowserToolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnapshotBrowserToolbar.js","sources":["../../../../src/components/common/SnapshotBrowser/SnapshotBrowserToolbar.tsx"],"sourcesContent":["import { ReactNode } from 'react';\r\nimport Icon from '../Icon/Icon';\r\nimport classes from './SnapshotBrowser.module.scss';\r\n\r\ninterface SnapshotBrowserToolbarProps {\r\n search: string;\r\n onSearchChange: (value: string) => void;\r\n isLoading?: boolean;\r\n leftContent?: ReactNode;\r\n rightContent?: ReactNode;\r\n}\r\n\r\nconst SnapshotBrowserToolbar = ({ search, onSearchChange, isLoading, leftContent, rightContent }: SnapshotBrowserToolbarProps) => {\r\n return (\r\n <div className={classes.toolbar}>\r\n <div className={classes.toolbarLeft}>{leftContent}</div>\r\n <div className={classes.toolbarRight}>\r\n {rightContent}\r\n <div className={classes.search}>\r\n <Icon type=\"search\" size={16} />\r\n <input type=\"text\" placeholder=\"Search in current Directory...\" value={search} onChange={(e) => onSearchChange(e.target.value)} />\r\n {isLoading && <Icon type=\"loading\" size={12} />}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default SnapshotBrowserToolbar;\r\n"],"names":["SnapshotBrowserToolbar","search","onSearchChange","isLoading","leftContent","rightContent","jsxs","classes","jsx","Icon","e"],"mappings":";;;AAYA,MAAMA,IAAyB,CAAC,EAAE,QAAAC,GAAQ,gBAAAC,GAAgB,WAAAC,GAAW,aAAAC,GAAa,cAAAC,QAE5E,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAQ,SACrB,UAAA;AAAA,EAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWD,EAAQ,aAAc,UAAAH,GAAY;AAAA,EAClD,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAQ,cACpB,UAAA;AAAA,IAAAF;AAAA,IACD,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAQ,QACrB,UAAA;AAAA,MAAA,gBAAAC,EAACC,GAAA,EAAK,MAAK,UAAS,MAAM,IAAI;AAAA,MAC9B,gBAAAD,EAAC,SAAA,EAAM,MAAK,QAAO,aAAY,kCAAiC,OAAOP,GAAQ,UAAU,CAACS,MAAMR,EAAeQ,EAAE,OAAO,KAAK,GAAG;AAAA,MAC/HP,KAAa,gBAAAK,EAACC,GAAA,EAAK,MAAK,WAAU,MAAM,GAAA,CAAI;AAAA,IAAA,EAAA,CAChD;AAAA,EAAA,EAAA,CACH;AAAA,GACH;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SnapshotDatabase } from '../../../../utils';
|
|
2
|
+
import { FileItem } from '../../../../@types';
|
|
3
|
+
export declare const useSnapshotDatabase: (files: FileItem[], backupId: string, useProgressiveLoading: boolean) => {
|
|
4
|
+
db: SnapshotDatabase | null;
|
|
5
|
+
initError: string | null;
|
|
6
|
+
discoveredDirectories: string[];
|
|
7
|
+
expandedFolders: Set<string>;
|
|
8
|
+
setExpandedFolders: import("react").Dispatch<import("react").SetStateAction<Set<string>>>;
|
|
9
|
+
setDiscoveredDirectories: import("react").Dispatch<import("react").SetStateAction<string[]>>;
|
|
10
|
+
addDirectoriesSorted: (newDirs: string[]) => void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=useSnapshotDatabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSnapshotDatabase.d.ts","sourceRoot":"","sources":["../../../../../src/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,eAAO,MAAM,mBAAmB,GAAI,OAAO,QAAQ,EAAE,EAAE,UAAU,MAAM,EAAE,uBAAuB,OAAO;;;;;;;oCA6DvF,MAAM,EAAE;CAgEvB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useState as p, useCallback as E, useEffect as z } from "react";
|
|
2
|
+
import A from "../../../../utils/snapshotDatabase.js";
|
|
3
|
+
const L = (d, D, m) => {
|
|
4
|
+
const [u, b] = p(null), [g, w] = p(null), [S, l] = p([]), [x, h] = p(/* @__PURE__ */ new Set()), c = E((a) => {
|
|
5
|
+
const t = {}, n = [];
|
|
6
|
+
a.forEach((e) => {
|
|
7
|
+
const s = e.substring(0, e.lastIndexOf("/")) || "";
|
|
8
|
+
t[s] || (t[s] = []), t[s].push(e);
|
|
9
|
+
}), a.forEach((e) => {
|
|
10
|
+
const s = e.substring(0, e.lastIndexOf("/")) || "";
|
|
11
|
+
(s === "" || !a.includes(s)) && n.push(e);
|
|
12
|
+
});
|
|
13
|
+
const o = [], r = (e) => {
|
|
14
|
+
const s = t[e] || [];
|
|
15
|
+
s.sort((i, f) => {
|
|
16
|
+
const v = i.split("/").pop() || "", F = f.split("/").pop() || "";
|
|
17
|
+
return v.localeCompare(F);
|
|
18
|
+
}), s.forEach((i) => {
|
|
19
|
+
o.push(i), r(i);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
return n.sort((e, s) => {
|
|
23
|
+
const i = e.split("/").pop() || "", f = s.split("/").pop() || "";
|
|
24
|
+
return i.localeCompare(f);
|
|
25
|
+
}), n.forEach((e) => {
|
|
26
|
+
o.push(e), r(e);
|
|
27
|
+
}), o;
|
|
28
|
+
}, []), y = E(
|
|
29
|
+
(a) => {
|
|
30
|
+
l((t) => {
|
|
31
|
+
const n = [...t, ...a], o = Array.from(new Set(n));
|
|
32
|
+
return c(o);
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
[c]
|
|
36
|
+
);
|
|
37
|
+
return z(() => ((async () => {
|
|
38
|
+
try {
|
|
39
|
+
console.log("Initializing database for", d.length, "files");
|
|
40
|
+
const t = new A(D);
|
|
41
|
+
if (await t.initializeFromFiles(d), b(t), console.log("Database initialized successfully"), m) {
|
|
42
|
+
const n = await t.getTopLevelDirectories(3), o = c(n);
|
|
43
|
+
l(o), console.log("Loaded top-level directories:", o.length);
|
|
44
|
+
const r = /* @__PURE__ */ new Set();
|
|
45
|
+
o.slice(0, 2).forEach((e) => r.add(e)), h(r);
|
|
46
|
+
} else {
|
|
47
|
+
const n = await t.getTopLevelDirectories(999), o = c(n);
|
|
48
|
+
l(o);
|
|
49
|
+
const r = /* @__PURE__ */ new Set();
|
|
50
|
+
o.slice(0, 3).forEach((e) => r.add(e)), h(r);
|
|
51
|
+
}
|
|
52
|
+
} catch (t) {
|
|
53
|
+
console.error("Failed to initialize database:", t), w(t instanceof Error ? t.message : "Unknown error");
|
|
54
|
+
}
|
|
55
|
+
})(), () => {
|
|
56
|
+
u && u.cleanup().catch(console.error);
|
|
57
|
+
}), [d, D, m, c]), {
|
|
58
|
+
db: u,
|
|
59
|
+
initError: g,
|
|
60
|
+
discoveredDirectories: S,
|
|
61
|
+
expandedFolders: x,
|
|
62
|
+
setExpandedFolders: h,
|
|
63
|
+
setDiscoveredDirectories: l,
|
|
64
|
+
addDirectoriesSorted: y
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export {
|
|
68
|
+
L as useSnapshotDatabase
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=useSnapshotDatabase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSnapshotDatabase.js","sources":["../../../../../src/components/common/SnapshotBrowser/hooks/useSnapshotDatabase.ts"],"sourcesContent":["import { useState, useEffect, useCallback } from 'react';\r\nimport { SnapshotDatabase } from '../../../../utils';\r\nimport { FileItem } from '../../../../@types';\r\n\r\nexport const useSnapshotDatabase = (files: FileItem[], backupId: string, useProgressiveLoading: boolean) => {\r\n const [db, setDb] = useState<SnapshotDatabase | null>(null);\r\n const [initError, setInitError] = useState<string | null>(null);\r\n const [discoveredDirectories, setDiscoveredDirectories] = useState<string[]>([]);\r\n const [expandedFolders, setExpandedFolders] = useState<Set<string>>(new Set());\r\n\r\n // Helper function to sort directories in true hierarchical order\r\n const sortDirectoriesHierarchically = useCallback((dirs: string[]): string[] => {\r\n const tree: { [key: string]: string[] } = {};\r\n const roots: string[] = [];\r\n\r\n // Build parent-child relationships\r\n dirs.forEach((dir) => {\r\n const parentPath = dir.substring(0, dir.lastIndexOf('/')) || '';\r\n if (!tree[parentPath]) {\r\n tree[parentPath] = [];\r\n }\r\n tree[parentPath].push(dir);\r\n });\r\n\r\n // Find root directories (those whose parent is not in the list)\r\n dirs.forEach((dir) => {\r\n const parentPath = dir.substring(0, dir.lastIndexOf('/')) || '';\r\n if (parentPath === '' || !dirs.includes(parentPath)) {\r\n roots.push(dir);\r\n }\r\n });\r\n\r\n // Recursively build sorted list\r\n const sortedList: string[] = [];\r\n\r\n const addChildrenRecursively = (parent: string) => {\r\n const children = tree[parent] || [];\r\n children.sort((a, b) => {\r\n const nameA = a.split('/').pop() || '';\r\n const nameB = b.split('/').pop() || '';\r\n return nameA.localeCompare(nameB);\r\n });\r\n\r\n children.forEach((child) => {\r\n sortedList.push(child);\r\n addChildrenRecursively(child);\r\n });\r\n };\r\n\r\n roots.sort((a, b) => {\r\n const nameA = a.split('/').pop() || '';\r\n const nameB = b.split('/').pop() || '';\r\n return nameA.localeCompare(nameB);\r\n });\r\n\r\n roots.forEach((root) => {\r\n sortedList.push(root);\r\n addChildrenRecursively(root);\r\n });\r\n\r\n return sortedList;\r\n }, []);\r\n\r\n // Helper function to add new directories while maintaining sorted order\r\n const addDirectoriesSorted = useCallback(\r\n (newDirs: string[]) => {\r\n setDiscoveredDirectories((prev) => {\r\n const allDirs = [...prev, ...newDirs];\r\n const uniqueDirs = Array.from(new Set(allDirs));\r\n return sortDirectoriesHierarchically(uniqueDirs);\r\n });\r\n },\r\n [sortDirectoriesHierarchically],\r\n );\r\n\r\n // Initialize database\r\n useEffect(() => {\r\n const initDb = async () => {\r\n try {\r\n console.log('Initializing database for', files.length, 'files');\r\n const database = new SnapshotDatabase(backupId);\r\n await database.initializeFromFiles(files);\r\n setDb(database);\r\n console.log('Database initialized successfully');\r\n\r\n if (useProgressiveLoading) {\r\n // Load only top-level directories initially\r\n const topDirs = await database.getTopLevelDirectories(3);\r\n const sortedTopDirs = sortDirectoriesHierarchically(topDirs);\r\n setDiscoveredDirectories(sortedTopDirs);\r\n console.log('Loaded top-level directories:', sortedTopDirs.length);\r\n\r\n const initialExpanded = new Set<string>();\r\n sortedTopDirs.slice(0, 2).forEach((dir) => initialExpanded.add(dir));\r\n setExpandedFolders(initialExpanded);\r\n } else {\r\n // For smaller datasets, load all directories\r\n const allDirs = await database.getTopLevelDirectories(999);\r\n const sortedAllDirs = sortDirectoriesHierarchically(allDirs);\r\n setDiscoveredDirectories(sortedAllDirs);\r\n\r\n const initialExpanded = new Set<string>();\r\n sortedAllDirs.slice(0, 3).forEach((dir) => initialExpanded.add(dir));\r\n setExpandedFolders(initialExpanded);\r\n }\r\n } catch (error) {\r\n console.error('Failed to initialize database:', error);\r\n setInitError(error instanceof Error ? error.message : 'Unknown error');\r\n }\r\n };\r\n\r\n initDb();\r\n\r\n return () => {\r\n if (db) {\r\n db.cleanup().catch(console.error);\r\n }\r\n };\r\n }, [files, backupId, useProgressiveLoading, sortDirectoriesHierarchically]);\r\n\r\n return {\r\n db,\r\n initError,\r\n discoveredDirectories,\r\n expandedFolders,\r\n setExpandedFolders,\r\n setDiscoveredDirectories,\r\n addDirectoriesSorted,\r\n };\r\n};\r\n"],"names":["useSnapshotDatabase","files","backupId","useProgressiveLoading","db","setDb","useState","initError","setInitError","discoveredDirectories","setDiscoveredDirectories","expandedFolders","setExpandedFolders","sortDirectoriesHierarchically","useCallback","dirs","tree","roots","dir","parentPath","sortedList","addChildrenRecursively","parent","children","a","b","nameA","nameB","child","root","addDirectoriesSorted","newDirs","prev","allDirs","uniqueDirs","useEffect","database","SnapshotDatabase","topDirs","sortedTopDirs","initialExpanded","sortedAllDirs","error"],"mappings":"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"}
|