From ffbf57292c98b561699bcf6505488b3e929ce5c8 Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Sun, 28 Jul 2024 19:44:41 +0530 Subject: [PATCH] Create synced files management modal on the settings page Use a Command Dialog to allow easier filtering of files to view without having to leave the settings page --- src/interface/web/app/settings/page.tsx | 173 +++++++++++++++++++++++- 1 file changed, 170 insertions(+), 3 deletions(-) diff --git a/src/interface/web/app/settings/page.tsx b/src/interface/web/app/settings/page.tsx index 917c6434..eb948355 100644 --- a/src/interface/web/app/settings/page.tsx +++ b/src/interface/web/app/settings/page.tsx @@ -31,6 +31,14 @@ import { TableCell, TableRow, } from "@/components/ui/table" +import { + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandDialog +} from "@/components/ui/command"; import { ArrowRight, @@ -58,6 +66,7 @@ import { ArrowCircleUp, ArrowCircleDown, ArrowsClockwise, + Check, } from "@phosphor-icons/react"; import NavMenu from "../components/navMenu/navMenu"; @@ -65,6 +74,160 @@ import SidePanel from "../components/sidePanel/chatHistorySidePanel"; import Loading from "../components/loading/loading"; +const ManageFilesModal: React.FC<{ onClose: () => void }> = ({ onClose }) => { + const [syncedFiles, setSyncedFiles] = useState([]); + const [selectedFiles, setSelectedFiles] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + + useEffect(() => { + const fetchFiles = async () => { + try { + const response = await fetch('/api/content/computer'); + if (!response.ok) throw new Error('Failed to fetch files'); + + // Extract resonse + const syncedFiles = await response.json(); + // Validate response + if (Array.isArray(syncedFiles)) { + // Set synced files state + setSyncedFiles(syncedFiles.toSorted()); + } else { + console.error('Unexpected data format from API'); + } + } catch (error) { + console.error('Error fetching files:', error); + } + }; + + fetchFiles(); + }, []); + + const filteredFiles = syncedFiles.filter(file => + file.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + const deleteSelected = async () => { + let filesToDelete = selectedFiles.length > 0 ? selectedFiles : filteredFiles; + console.log("Delete selected files", filesToDelete); + + if (filesToDelete.length === 0) { + console.log("No files to delete"); + return; + } + + try { + const response = await fetch('/api/content/files', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ files: filesToDelete }), + }); + + if (!response.ok) throw new Error('Failed to delete files'); + + // Update the syncedFiles state + setSyncedFiles(prevFiles => prevFiles.filter(file => !filesToDelete.includes(file))); + + // Reset selectedFiles + setSelectedFiles([]); + + console.log("Deleted files:", filesToDelete); + } catch (error) { + console.error('Error deleting files:', error); + } + }; + + const deleteFile = async (filename: string) => { + console.log("Delete selected file", filename); + try { + const response = await fetch(`/api/content/file?filename=${encodeURIComponent(filename)}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) throw new Error('Failed to delete file'); + + // Update the syncedFiles state + setSyncedFiles(prevFiles => prevFiles.filter(file => file !== filename)); + + // Remove the file from selectedFiles if it's there + setSelectedFiles(prevSelected => prevSelected.filter(file => file !== filename)); + + console.log("Deleted file:", filename); + } catch (error) { + console.error('Error deleting file:', error); + } + }; + + return ( + +
+
+ +
+ +
+ + No such files synced. + + {filteredFiles.map((filename: string) => ( + { + setSelectedFiles(prev => + prev.includes(value) + ? prev.filter(f => f !== value) + : [...prev, value] + ); + }} + > +
+
+ {selectedFiles.includes(filename) && } + {filename} +
+ +
+
+ ))} +
+
+
+ +
+
+ +
+
+
+
+ ); +} + + interface DropdownComponentProps { items: ModelOptions[]; selected: number; @@ -188,6 +351,7 @@ export default function SettingsView() { const [number, setNumber] = useState(undefined); const [otp, setOTP] = useState(""); const [numberValidationState, setNumberValidationState] = useState(PhoneNumberValidationState.Verified); + const [isManageFilesModalOpen, setIsManageFilesModalOpen] = useState(false); const { toast } = useToast(); const cardClassName = "w-full lg:w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg"; @@ -414,7 +578,9 @@ export default function SettingsView() { if (userConfig) { let newUserConfig = userConfig; newUserConfig.enabled_content_source.notion = false; + newUserConfig.notion_token = null; setUserConfig(newUserConfig); + setNotionToken(newUserConfig.notion_token); } // Notify user about disconnecting content source @@ -539,6 +705,7 @@ export default function SettingsView() { + {isManageFilesModalOpen && setIsManageFilesModalOpen(false)} />}
Content
@@ -548,10 +715,10 @@ export default function SettingsView() { Manage your synced files -