From d0e79454e550c91d58c69e0f8152f5a3bf66f65b Mon Sep 17 00:00:00 2001 From: "manthapavankumar11@gmail.com" Date: Mon, 31 Aug 2026 09:28:42 +0530 Subject: [PATCH] refactored the actions to make ui more intutive --- package-lock.json | 40 ++++---------- .../Collections/BulkActionsButton.jsx | 53 +++++++++++++++++++ src/pages/Collections.jsx | 47 ++++++++++++---- 3 files changed, 98 insertions(+), 42 deletions(-) create mode 100644 src/components/Collections/BulkActionsButton.jsx diff --git a/package-lock.json b/package-lock.json index 5c53bd1bc..942b740fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -121,7 +121,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", @@ -315,7 +314,6 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -422,7 +420,6 @@ "node_modules/@emotion/react": { "version": "11.14.0", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -460,7 +457,6 @@ "node_modules/@emotion/styled": { "version": "11.14.1", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1326,7 +1322,6 @@ "node_modules/@mui/icons-material": { "version": "7.2.0", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.6" }, @@ -1351,7 +1346,6 @@ "node_modules/@mui/material": { "version": "7.2.0", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.6", "@mui/core-downloads-tracker": "^7.2.0", @@ -1456,7 +1450,6 @@ "node_modules/@mui/system": { "version": "7.2.0", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.6", "@mui/private-theming": "^7.2.0", @@ -2994,7 +2987,8 @@ }, "node_modules/@types/aria-query": { "version": "5.0.4", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -3175,7 +3169,6 @@ "node_modules/@types/react": { "version": "18.3.23", "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3310,7 +3303,6 @@ "node_modules/@uppy/core": { "version": "4.4.7", "license": "MIT", - "peer": true, "dependencies": { "@transloadit/prettier-bytes": "^0.3.4", "@uppy/store-default": "^4.2.0", @@ -3325,7 +3317,6 @@ "node_modules/@uppy/dashboard": { "version": "4.3.4", "license": "MIT", - "peer": true, "dependencies": { "@transloadit/prettier-bytes": "^0.3.4", "@uppy/informer": "^4.2.1", @@ -3347,7 +3338,6 @@ "node_modules/@uppy/drag-drop": { "version": "4.1.3", "license": "MIT", - "peer": true, "dependencies": { "@uppy/utils": "^6.1.4", "preact": "^10.5.13" @@ -3370,7 +3360,6 @@ "node_modules/@uppy/progress-bar": { "version": "4.2.1", "license": "MIT", - "peer": true, "dependencies": { "@uppy/utils": "^6.1.1", "preact": "^10.5.13" @@ -3640,7 +3629,6 @@ "node_modules/acorn": { "version": "8.15.0", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3889,7 +3877,6 @@ "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.6", @@ -3987,7 +3974,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -4380,8 +4366,7 @@ }, "node_modules/csstype": { "version": "3.1.3", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/d3-array": { "version": "3.2.4", @@ -4499,7 +4484,6 @@ "node_modules/d3-selection": { "version": "3.0.0", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -5059,7 +5043,6 @@ "version": "8.57.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -6786,7 +6769,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -6798,7 +6780,6 @@ "version": "22.1.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "abab": "^2.0.6", "cssstyle": "^3.0.0", @@ -7244,7 +7225,6 @@ "node_modules/lucide-react": { "version": "0.545.0", "license": "ISC", - "peer": true, "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } @@ -7252,6 +7232,7 @@ "node_modules/lz-string": { "version": "1.5.0", "license": "MIT", + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -8145,8 +8126,7 @@ }, "node_modules/monaco-editor": { "version": "0.44.0", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/mri": { "version": "1.2.0", @@ -8803,6 +8783,7 @@ "node_modules/pretty-format": { "version": "27.5.1", "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -8815,6 +8796,7 @@ "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -8824,7 +8806,8 @@ }, "node_modules/pretty-format/node_modules/react-is": { "version": "17.0.2", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/prism-react-renderer": { "version": "2.4.1", @@ -8847,7 +8830,6 @@ "node_modules/prop-types": { "version": "15.8.1", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -8922,7 +8904,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -8992,7 +8973,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -9281,7 +9261,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -10498,7 +10477,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/src/components/Collections/BulkActionsButton.jsx b/src/components/Collections/BulkActionsButton.jsx new file mode 100644 index 000000000..0fad27ad9 --- /dev/null +++ b/src/components/Collections/BulkActionsButton.jsx @@ -0,0 +1,53 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { Button, Menu, MenuItem } from '@mui/material'; +import { ChevronDown } from 'lucide-react'; + +const BulkActionsButton = ({ count, onDelete, onDownloadSnapshot }) => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + + const handleClose = () => setAnchorEl(null); + + const handleSelect = (action) => { + handleClose(); + action?.(); + }; + + return ( + <> + + + handleSelect(onDownloadSnapshot)}>Download Snapshot + handleSelect(onDelete)} sx={{ color: 'error.main' }}> + Delete + + + + ); +}; + +BulkActionsButton.propTypes = { + count: PropTypes.number.isRequired, + onDelete: PropTypes.func.isRequired, + onDownloadSnapshot: PropTypes.func.isRequired, +}; + +export default BulkActionsButton; diff --git a/src/pages/Collections.jsx b/src/pages/Collections.jsx index b60b84ba5..f6009a305 100644 --- a/src/pages/Collections.jsx +++ b/src/pages/Collections.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { useClient } from '../context/client-context'; import SearchBar from '../components/Collections/SearchBar'; -import { Typography, Grid, Pagination, Box, Skeleton, IconButton, Tooltip, Button } from '@mui/material'; +import { Typography, Grid, Pagination, Box, Skeleton, IconButton, Tooltip } from '@mui/material'; import { keyframes } from '@mui/material/styles'; import { RefreshCw } from 'lucide-react'; import ErrorNotifier from '../components/ToastNotifications/ErrorNotifier'; @@ -14,10 +14,11 @@ import { debounce } from 'lodash'; import { useMaxCollections } from '../context/telemetry-context'; import CreateCollectionButton from '../components/Collections/CreateCollection/CreateCollectionButton'; import ConfirmationDialog from '../components/Common/ConfirmationDialog'; +import BulkActionsButton from '../components/Collections/BulkActionsButton'; const spin = keyframes` - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } `; function Collections() { @@ -33,6 +34,7 @@ function Collections() { const [selectedCollections, setSelectedCollections] = useState(new Set()); const [openBulkDeleteDialog, setOpenBulkDeleteDialog] = useState(false); const [bulkDeleteError, setBulkDeleteError] = useState(null); + const [bulkSnapshotError, setBulkSnapshotError] = useState(null); const { maxCollections } = useMaxCollections(); @@ -206,6 +208,31 @@ function Collections() { } }, [selectedCollections, qdrantClient, getCollectionsCall, currentPage]); + const handleBulkDownloadSnapshot = useCallback(async () => { + const names = Array.from(selectedCollections); + const errors = []; + for (const name of names) { + try { + const snapshot = await qdrantClient.createSnapshot(name); + const response = await qdrantClient.downloadSnapshot(name, snapshot.name); + const blob = await response.blob(); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = snapshot.name; + document.body.appendChild(a); + a.click(); + a.remove(); + window.URL.revokeObjectURL(url); + } catch (error) { + errors.push(`${name}: ${error.message}`); + } + } + if (errors.length > 0) { + setBulkSnapshotError(`Failed to download snapshot for: ${errors.join('; ')}`); + } + }, [selectedCollections, qdrantClient]); + const displayCollections = searchQuery ? filteredCollections : collections; return ( @@ -255,14 +282,11 @@ function Collections() { }} > {selectedCollections.size > 0 && ( - + setOpenBulkDeleteDialog(true)} + onDownloadSnapshot={handleBulkDownloadSnapshot} + /> )} getCollectionsCall(currentPage)} /> getCollectionsCall(currentPage)} key={'snapshots'} /> @@ -317,6 +341,7 @@ function Collections() { {bulkDeleteError && } + {bulkSnapshotError && } setOpenBulkDeleteDialog(false)}