From fbd3a5af2ae1b536a15a011e388601f20818a698 Mon Sep 17 00:00:00 2001 From: ervinpiol Date: Fri, 11 Oct 2024 13:10:31 +0800 Subject: [PATCH] feat: add delete and add data source --- web/src/app/ee/admin/teams/Main.tsx | 8 +- .../app/ee/admin/teams/TeamspaceAssistant.tsx | 35 ++- .../ee/admin/teams/TeamspaceDataSource.tsx | 276 +++++++++--------- .../ee/admin/teams/TeamspaceDocumentSet.tsx | 35 ++- .../app/ee/admin/teams/TeamspaceSidebar.tsx | 2 +- .../admin/teams/TeamspaceSidebarContent.tsx | 2 +- web/src/app/ee/admin/teams/TeamspacesCard.tsx | 5 +- web/src/components/Loading.tsx | 2 +- 8 files changed, 184 insertions(+), 181 deletions(-) diff --git a/web/src/app/ee/admin/teams/Main.tsx b/web/src/app/ee/admin/teams/Main.tsx index bf1bb6a3c67..025e8f335a1 100644 --- a/web/src/app/ee/admin/teams/Main.tsx +++ b/web/src/app/ee/admin/teams/Main.tsx @@ -45,6 +45,10 @@ export const Main = ({ assistants }: { assistants: Assistant[] }) => { error: documentSetsError, } = useDocumentSets(); + if (isLoading || isDocumentSetsLoading || userIsLoading || isCCPairsLoading) { + return ; + } + if (error || !data) { return
Error loading teams
; } @@ -53,10 +57,6 @@ export const Main = ({ assistants }: { assistants: Assistant[] }) => { return
Error loading teams
; } - if (isLoading || isDocumentSetsLoading || userIsLoading || isCCPairsLoading) { - return ; - } - if (ccPairsError || !ccPairs) { return
Error loading connectors
; } diff --git a/web/src/app/ee/admin/teams/TeamspaceAssistant.tsx b/web/src/app/ee/admin/teams/TeamspaceAssistant.tsx index a8b0f586c2d..d2095903691 100644 --- a/web/src/app/ee/admin/teams/TeamspaceAssistant.tsx +++ b/web/src/app/ee/admin/teams/TeamspaceAssistant.tsx @@ -218,21 +218,26 @@ export const TeamspaceAssistant = ({ -
- {currentAssistants.slice(0, 8).map((assistant) => ( -
- {assistant.name!.charAt(0)} -
- ))} - {currentAssistants.length > 8 && ( -
- +{currentAssistants.length - 8} -
- )} -
+ + {teamspace.assistants.length > 0 ? ( +
+ {currentAssistants.slice(0, 8).map((assistant) => ( +
+ {assistant.name!.charAt(0)} +
+ ))} + {currentAssistants.length > 8 && ( +
+ +{currentAssistants.length - 8} +
+ )} +
+ ) : ( +

There are no assistant.

+ )} } title="Assistants" diff --git a/web/src/app/ee/admin/teams/TeamspaceDataSource.tsx b/web/src/app/ee/admin/teams/TeamspaceDataSource.tsx index e9126dfb321..8af3f4818fd 100644 --- a/web/src/app/ee/admin/teams/TeamspaceDataSource.tsx +++ b/web/src/app/ee/admin/teams/TeamspaceDataSource.tsx @@ -1,101 +1,70 @@ "use client"; +import { useEffect, useState } from "react"; import { CustomModal } from "@/components/CustomModal"; import { SearchInput } from "@/components/SearchInput"; import { Button } from "@/components/ui/button"; -import { - CCPairDescriptor, - ConnectorIndexingStatus, - Teamspace, -} from "@/lib/types"; import { Globe, Pencil } from "lucide-react"; -import { useEffect, useState } from "react"; import { useToast } from "@/hooks/use-toast"; +import { ConnectorIndexingStatus, Teamspace } from "@/lib/types"; + +interface SimplifiedDataSource { + id: number; + name: string | null; +} interface TeamspaceDataSourceProps { teamspace: Teamspace & { gradient: string }; - ccPairs: ConnectorIndexingStatus[] | undefined; + ccPairs: ConnectorIndexingStatus[]; refreshTeamspaces: () => void; } -interface DataSourceContentProps { - searchTerm: string; - setSearchTerm: (term: string) => void; - filteredCurrentDataSources?: CCPairDescriptor[]; - filteredGlobalDataSources?: ConnectorIndexingStatus[] | undefined; - isGlobal?: boolean; - onSelect?: (cc_pair: ConnectorIndexingStatus) => void; - selectedDataSources?: ConnectorIndexingStatus[] | undefined; -} - -function isConnectorIndexingStatus( - dataSource: ConnectorIndexingStatus | CCPairDescriptor -): dataSource is ConnectorIndexingStatus { - return ( - (dataSource as ConnectorIndexingStatus).cc_pair_id !== undefined - ); -} - const DataSourceContent = ({ searchTerm, setSearchTerm, - filteredCurrentDataSources, - filteredGlobalDataSources, + filteredDataSources, isGlobal, onSelect, - selectedDataSources, -}: DataSourceContentProps) => { - const dataSources = isGlobal - ? filteredGlobalDataSources - : filteredCurrentDataSources; - - const getDataSourceId = ( - dataSource: ConnectorIndexingStatus | CCPairDescriptor - ) => { - if (isConnectorIndexingStatus(dataSource)) { - return dataSource.cc_pair_id; - } else { - return dataSource.id; - } - }; - + hasDataSource, +}: { + searchTerm: string; + setSearchTerm: (term: string) => void; + filteredDataSources?: SimplifiedDataSource[]; + isGlobal?: boolean; + onSelect?: (dataSource: SimplifiedDataSource) => void; + hasDataSource?: boolean; +}) => { return (

- {isGlobal ? "Available" : "Current"} Document Sets + {isGlobal ? "Available" : "Current"} Data Source

-
- {dataSources?.map((dataSource) => ( -
- getDataSourceId(selected) === getDataSourceId(dataSource) - ) - ? "bg-primary-300 border-input-colored" - : "" - }`} - onClick={() => - onSelect && - isConnectorIndexingStatus(dataSource) && - onSelect(dataSource) - } - > - -

{dataSource.name}

-
- ))} -
+ + {hasDataSource ? ( +
+ {filteredDataSources?.map((dataSource) => ( +
onSelect && onSelect(dataSource)} + > + +

{dataSource.name}

+
+ ))} +
+ ) : ( +

There are no {isGlobal ? "Available" : "Current"} Data Sources.

+ )}
); }; @@ -107,47 +76,64 @@ export const TeamspaceDataSource = ({ }: TeamspaceDataSourceProps) => { const { toast } = useToast(); const [isDataSourceModalOpen, setIsDataSourceModalOpen] = useState(false); - const [selectedDataSources, setSelectedDataSources] = useState< - ConnectorIndexingStatus[] - >([]); const [searchTermCurrent, setSearchTermCurrent] = useState(""); const [searchTermGlobal, setSearchTermGlobal] = useState(""); + const [currentDataSources, setCurrentDataSources] = useState< + SimplifiedDataSource[] + >(teamspace.cc_pairs); - const filterDataSources = ( - ccPairs: ConnectorIndexingStatus[] | undefined, - searchTerm: string - ) => - ccPairs?.filter( - (ccPair) => - ccPair.public_doc && - !teamspace.cc_pairs.some( - (currentCCPair) => currentCCPair.id === ccPair.cc_pair_id - ) && - ccPair.name?.toLowerCase().includes(searchTerm.toLowerCase()) - ); + useEffect(() => { + setCurrentDataSources(teamspace.cc_pairs); + }, [teamspace]); - const filteredCurrentDataSources = teamspace.cc_pairs.filter((ccPair) => - ccPair.name?.toLowerCase().includes(searchTermCurrent.toLowerCase()) + const [globalDataSources, setGlobalDataSources] = useState< + SimplifiedDataSource[] + >(() => + ccPairs + .filter( + (ccPair) => + ccPair.public_doc && + !teamspace.cc_pairs.some( + (currentCCPair) => currentCCPair.id === ccPair.cc_pair_id + ) + ) + .map((ccPair) => ({ id: ccPair.cc_pair_id, name: ccPair.name })) ); - const [filteredGlobalDataSources, setFilteredGlobalDataSources] = useState( - () => filterDataSources(ccPairs, searchTermGlobal) - ); + const [tempCurrentDataSources, setTempCurrentDataSources] = + useState(currentDataSources); + const [tempGlobalDataSources, setTempGlobalDataSources] = + useState(globalDataSources); useEffect(() => { - setFilteredGlobalDataSources(filterDataSources(ccPairs, searchTermGlobal)); - }, [ccPairs, teamspace.cc_pairs, searchTermGlobal]); - - const handleSelectDataSource = ( - ccPair: ConnectorIndexingStatus - ) => { - setSelectedDataSources((prevSelected) => - prevSelected.some((selected) => selected.cc_pair_id === ccPair.cc_pair_id) - ? prevSelected.filter( - (selected) => selected.cc_pair_id !== ccPair.cc_pair_id + setTempCurrentDataSources(currentDataSources); + const updatedGlobalDataSources = ccPairs + .filter( + (ccPair) => + ccPair.public_doc && + !currentDataSources.some( + (dataSource) => dataSource.id === ccPair.cc_pair_id ) - : [...prevSelected, ccPair] - ); + ) + .map((ccPair) => ({ id: ccPair.cc_pair_id, name: ccPair.name })); + setGlobalDataSources(updatedGlobalDataSources); + setTempGlobalDataSources(updatedGlobalDataSources); + }, [currentDataSources, ccPairs]); + + const handleSelectDataSource = (ccPair: SimplifiedDataSource) => { + if ( + tempCurrentDataSources.some((dataSource) => dataSource.id === ccPair.id) + ) { + setTempCurrentDataSources((prev) => + prev.filter((dataSource) => dataSource.id !== ccPair.id) + ); + setTempGlobalDataSources((prev) => [...prev, ccPair]); + } else { + setTempCurrentDataSources((prev) => [...prev, ccPair]); + setTempGlobalDataSources((prev) => + prev.filter((dataSource) => dataSource.id !== ccPair.id) + ); + } }; const handleSaveChanges = async () => { @@ -162,8 +148,12 @@ export const TeamspaceDataSource = ({ assistant_ids: teamspace.assistants.map( (assistant) => assistant.id ), - document_set_ids: teamspace.cc_pairs.map((ccPair) => ccPair.id), - cc_pair_ids: selectedDataSources.map((ccPair) => ccPair.cc_pair_id), + document_set_ids: teamspace.document_sets.map( + (docSet) => docSet.id + ), + cc_pair_ids: tempCurrentDataSources.map( + (dataSource) => dataSource.id + ), }), } ); @@ -173,29 +163,36 @@ export const TeamspaceDataSource = ({ if (!response.ok) { toast({ title: "Update Failed", - description: `Unable to update document sets: ${responseJson.detail || "Unknown error."}`, + description: `Unable to update data source: ${responseJson.detail || "Unknown error."}`, variant: "destructive", }); return; - } else { - toast({ - title: "Data Source Updated", - description: - "Data Source have been successfully updated in the teamspace.", - variant: "success", - }); - refreshTeamspaces(); - setFilteredGlobalDataSources( - filterDataSources(ccPairs, searchTermGlobal) - ); } + + setCurrentDataSources(tempCurrentDataSources); + setGlobalDataSources(tempGlobalDataSources); + toast({ + title: "Data Source Updated", + description: + "Data Source have been successfully updated in the teamspace.", + variant: "success", + }); + refreshTeamspaces(); } catch (error) { toast({ title: "Update Failed", - description: "An error occurred while updating document sets.", + description: "An error occurred while updating data source.", variant: "destructive", }); } + + handleCloseModal(); + }; + + const handleCloseModal = () => { + setIsDataSourceModalOpen(false); + setTempCurrentDataSources(currentDataSources); + setTempGlobalDataSources(globalDataSources); }; return ( @@ -219,7 +216,7 @@ export const TeamspaceDataSource = ({ {teamspace.cc_pairs.slice(0, 8).map((teamspaceDataSource) => (
{teamspaceDataSource.name!.charAt(0)}
@@ -231,44 +228,43 @@ export const TeamspaceDataSource = ({ )} ) : ( -

There are no document sets.

+

There are no data sourceg.

)} } title="Data Source" open={isDataSourceModalOpen} - onClose={() => { - setIsDataSourceModalOpen(false); - setSelectedDataSources([]); - }} + onClose={handleCloseModal} >
- {teamspace.cc_pairs.length > 0 ? ( - - ) : ( -

There are no current document sets.

- )} + + dataSource.name + ?.toLowerCase() + .includes(searchTermCurrent.toLowerCase()) + )} + isGlobal={false} + onSelect={handleSelectDataSource} + hasDataSource={tempCurrentDataSources.length > 0} + /> + dataSource.name + ?.toLowerCase() + .includes(searchTermGlobal.toLowerCase()) + )} + isGlobal={true} onSelect={handleSelectDataSource} - selectedDataSources={selectedDataSources} + hasDataSource={tempGlobalDataSources.length > 0} />
-
- +
+
); diff --git a/web/src/app/ee/admin/teams/TeamspaceDocumentSet.tsx b/web/src/app/ee/admin/teams/TeamspaceDocumentSet.tsx index 609ccf93857..5f9a6af3181 100644 --- a/web/src/app/ee/admin/teams/TeamspaceDocumentSet.tsx +++ b/web/src/app/ee/admin/teams/TeamspaceDocumentSet.tsx @@ -207,21 +207,26 @@ export const TeamspaceDocumentSet = ({
-
- {currentDocumentSets.slice(0, 8).map((documentSet) => ( -
- {documentSet.name!.charAt(0)} -
- ))} - {currentDocumentSets.length > 8 && ( -
- +{currentDocumentSets.length - 8} -
- )} -
+ + {teamspace.document_sets.length > 0 ? ( +
+ {currentDocumentSets.slice(0, 8).map((documentSet) => ( +
+ {documentSet.name!.charAt(0)} +
+ ))} + {currentDocumentSets.length > 8 && ( +
+ +{currentDocumentSets.length - 8} +
+ )} +
+ ) : ( +

There are no document set.

+ )} } title="Document Sets" diff --git a/web/src/app/ee/admin/teams/TeamspaceSidebar.tsx b/web/src/app/ee/admin/teams/TeamspaceSidebar.tsx index 086bf51054b..571bc09839c 100644 --- a/web/src/app/ee/admin/teams/TeamspaceSidebar.tsx +++ b/web/src/app/ee/admin/teams/TeamspaceSidebar.tsx @@ -12,7 +12,7 @@ interface TeamspaceSidebarProps { onClose: () => void; isExpanded: boolean; assistants: Assistant[]; - ccPairs: ConnectorIndexingStatus[] | undefined; + ccPairs: ConnectorIndexingStatus[]; documentSets: DocumentSet[]; refreshTeamspaces: () => void; } diff --git a/web/src/app/ee/admin/teams/TeamspaceSidebarContent.tsx b/web/src/app/ee/admin/teams/TeamspaceSidebarContent.tsx index 03922441c28..b00690541fa 100644 --- a/web/src/app/ee/admin/teams/TeamspaceSidebarContent.tsx +++ b/web/src/app/ee/admin/teams/TeamspaceSidebarContent.tsx @@ -12,7 +12,7 @@ interface TeamspaceSidebarContentProps { teamspace: Teamspace & { gradient: string }; selectedTeamspaceId?: number; assistants: Assistant[]; - ccPairs: ConnectorIndexingStatus[] | undefined; + ccPairs: ConnectorIndexingStatus[]; documentSets: DocumentSet[]; refreshTeamspaces: () => void; } diff --git a/web/src/app/ee/admin/teams/TeamspacesCard.tsx b/web/src/app/ee/admin/teams/TeamspacesCard.tsx index 0565f6543ef..1506f214e12 100644 --- a/web/src/app/ee/admin/teams/TeamspacesCard.tsx +++ b/web/src/app/ee/admin/teams/TeamspacesCard.tsx @@ -208,10 +208,7 @@ export const TeamspacesCard = ({
- {" "} - {tokenRate - ? `${tokenRate.token_budget} Token Rate` - : "No Token Rate"} + {teamspace.cc_pairs.length} Data Source
diff --git a/web/src/components/Loading.tsx b/web/src/components/Loading.tsx index 7cdcb5a9887..e3b449fe270 100644 --- a/web/src/components/Loading.tsx +++ b/web/src/components/Loading.tsx @@ -44,7 +44,7 @@ export const LoadingAnimation: React.FC = ({ export const ThreeDotsLoader = () => { return ( -
+