From 5d1a08c92bf7e7991727acbaf4e983f6a8514ba6 Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Mon, 18 Dec 2023 13:51:21 -0800 Subject: [PATCH 1/7] WIP header complete organization view --- .../src/pages/Dashboard/Statistics/index.tsx | 138 +++++++++++------- frontend/src/pages/Dashboard/index.tsx | 87 ++++++++++- frontend/src/pages/DocumentView/index.tsx | 6 +- .../src/pages/WorkspaceDashboard/index.tsx | 6 +- 4 files changed, 179 insertions(+), 58 deletions(-) diff --git a/frontend/src/pages/Dashboard/Statistics/index.tsx b/frontend/src/pages/Dashboard/Statistics/index.tsx index f3be2f7..68337ff 100644 --- a/frontend/src/pages/Dashboard/Statistics/index.tsx +++ b/frontend/src/pages/Dashboard/Statistics/index.tsx @@ -37,60 +37,96 @@ const Statistics = ({ organization }: { organization: any }) => { }, [organization?.slug]); return ( -
-
-
- {documents.status === 'loading' ? ( - - ) : ( -
-

- {nFormatter(documents.value)} -

-

- {pluralize('Document', documents.value)} -

-
- )} -
+ //
+ //
+ //
+ // {documents.status === 'loading' ? ( + // + // ) : ( + //
+ //

+ // {nFormatter(documents.value)} + //

+ //

+ // {pluralize('Document', documents.value)} + //

+ //
+ // )} + //
-
- {vectors.status === 'loading' ? ( - - ) : ( -
-

- {nFormatter(vectors.value)} -

-

- {pluralize('Vector', vectors.value)} -

-
- )} -
+ //
+ // {vectors.status === 'loading' ? ( + // + // ) : ( + //
+ //

+ // {nFormatter(vectors.value)} + //

+ //

+ // {pluralize('Vector', vectors.value)} + //

+ //
+ // )} + //
-
- {cache.status === 'loading' ? ( - - ) : ( -
-

- {humanFileSize(cache.value)} -

-

Vector Cache (MB)

-
- )} -
+ //
+ // {cache.status === 'loading' ? ( + // + // ) : ( + //
+ //

+ // {humanFileSize(cache.value)} + //

+ //

Vector Cache (MB)

+ //
+ // )} + //
-
-
-

- {organization?.lastUpdated - ? moment(organization.lastUpdated).fromNow() - : moment(organization.createdAt).fromNow()} -

-

Last Modified

-
+ //
+ //
+ //

+ // {organization?.lastUpdated + // ? moment(organization.lastUpdated).fromNow() + // : moment(organization.createdAt).fromNow()} + //

+ //

Last Modified

+ //
+ //
+ //
+ //
+ +
+
+
+ + Documents + + + {' '} + + + ({nFormatter(documents.value)}) + +
+
+ +
+
+ + {pluralize('Vector', vectors.value)}:{' '} + + {nFormatter(vectors.value)} + + + + Vector Cache:{' '} + + {humanFileSize(cache.value)} + + + + Dimensions: {10} +
diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index d3134b7..ccf7a18 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -12,6 +12,13 @@ import DocumentsList from './DocumentsList'; import Organization from '../../models/organization'; import ApiKeyCard from './ApiKey'; import ConnectorCard from './Connector'; +import truncate from 'truncate'; + +import ChromaLogo from '../../images/vectordbs/chroma.png'; +import PineconeLogo from '../../images/vectordbs/pinecone-inverted.png'; +import qDrantLogo from '../../images/vectordbs/qdrant.png'; +import WeaviateLogo from '../../images/vectordbs/weaviate.png'; +import { GearSix } from '@phosphor-icons/react'; export default function Dashboard() { const { slug } = useParams(); @@ -97,18 +104,25 @@ export default function Dashboard() { workspaces={workspaces} hasMoreWorkspaces={hasMoreWorkspaces} loadMoreWorkspaces={fetchWorkspaces} + headerExtendedItems={ + {}} + /> + } > {!!organization && (
- - + */}
)} -
@@ -128,3 +142,70 @@ export default function Dashboard() { ); } + +function OrganizationHeader({ + organization, + workspace, + connector, + deleteWorkspace, +}: any) { + let logo; + switch (connector?.type) { + case 'chroma': + logo = ChromaLogo; + break; + case 'qdrant': + logo = qDrantLogo; + break; + case 'weaviate': + logo = WeaviateLogo; + break; + default: + logo = PineconeLogo; + } + + return ( + <> +
+
+ + {truncate(organization?.name, 20)} + +
+
+
+ + + + +
+ + ); +} diff --git a/frontend/src/pages/DocumentView/index.tsx b/frontend/src/pages/DocumentView/index.tsx index 474aef0..51ff6c4 100644 --- a/frontend/src/pages/DocumentView/index.tsx +++ b/frontend/src/pages/DocumentView/index.tsx @@ -169,7 +169,7 @@ function DocumentViewHeader({ organization, workspace, document }: any) { return ( <>
diff --git a/frontend/src/pages/WorkspaceDashboard/index.tsx b/frontend/src/pages/WorkspaceDashboard/index.tsx index ccbec2c..28101bd 100644 --- a/frontend/src/pages/WorkspaceDashboard/index.tsx +++ b/frontend/src/pages/WorkspaceDashboard/index.tsx @@ -801,7 +801,7 @@ function WorkspaceViewHeader({ return ( <>
From 5dd88adb77dd6d5b048044b314a5ba83311f2787 Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Mon, 18 Dec 2023 15:02:15 -0800 Subject: [PATCH 2/7] implement header update connector and sync buttons/image glitch fixes --- frontend/src/pages/Dashboard/index.tsx | 542 +++++++++++++++++- .../src/pages/WorkspaceDashboard/index.tsx | 5 +- 2 files changed, 538 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index ccf7a18..2b7a087 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -15,10 +15,12 @@ import ConnectorCard from './Connector'; import truncate from 'truncate'; import ChromaLogo from '../../images/vectordbs/chroma.png'; -import PineconeLogo from '../../images/vectordbs/pinecone-inverted.png'; +import PineconeLogoInverted from '../../images/vectordbs/pinecone-inverted.png'; +import PineconeLogo from '../../images/vectordbs/pinecone.png'; import qDrantLogo from '../../images/vectordbs/qdrant.png'; import WeaviateLogo from '../../images/vectordbs/weaviate.png'; import { GearSix } from '@phosphor-icons/react'; +import { titleCase } from 'title-case'; export default function Dashboard() { const { slug } = useParams(); @@ -115,12 +117,21 @@ export default function Dashboard() { > {!!organization && (
+ setConnector(newConnector)} + /> + {/* - */} + /> */} + {/* */}
)} @@ -161,7 +172,7 @@ function OrganizationHeader({ logo = WeaviateLogo; break; default: - logo = PineconeLogo; + logo = PineconeLogoInverted; } return ( @@ -198,9 +209,7 @@ function OrganizationHeader({
+
+ + )} +
+ + ); +}; + +const SyncConnectorModal = ({ + organization, + connector, +}: { + organization: any; + connector: any; +}) => { + const [synced, setSynced] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const sync = async () => { + setError(null); + setLoading(true); + const { job, error } = await Organization.syncConnector( + organization.slug, + connector.id + ); + + if (!job) { + setError(error); + setLoading(false); + setSynced(false); + return; + } + + setLoading(false); + setSynced(true); + }; + + return ( + + event.target == event.currentTarget && event.currentTarget?.close() + } + > +
+ +
+ {error && ( +

+ {error} +

+ )} + {synced ? ( + + ) : ( + + )} +
+
+ + ); +}; diff --git a/frontend/src/pages/WorkspaceDashboard/index.tsx b/frontend/src/pages/WorkspaceDashboard/index.tsx index 28101bd..843d3ba 100644 --- a/frontend/src/pages/WorkspaceDashboard/index.tsx +++ b/frontend/src/pages/WorkspaceDashboard/index.tsx @@ -17,7 +17,8 @@ import { CaretDown } from '@phosphor-icons/react'; import truncate from 'truncate'; import ChromaLogo from '../../images/vectordbs/chroma.png'; -import PineconeLogo from '../../images/vectordbs/pinecone-inverted.png'; +import PineconeLogoInverted from '../../images/vectordbs/pinecone-inverted.png'; +import PineconeLogo from '../../images/vectordbs/pinecone.png'; import qDrantLogo from '../../images/vectordbs/qdrant.png'; import WeaviateLogo from '../../images/vectordbs/weaviate.png'; @@ -795,7 +796,7 @@ function WorkspaceViewHeader({ logo = WeaviateLogo; break; default: - logo = PineconeLogo; + logo = PineconeLogoInverted; } return ( From db50cb436f47b823534de277de20581d95aa367b Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Mon, 18 Dec 2023 17:39:13 -0800 Subject: [PATCH 3/7] working organization dashboard table, WIP quick actions & workspaces sidebar --- .../pages/Dashboard/DocumentsList/index.tsx | 281 ++++++++++++++++-- .../pages/Dashboard/WorkspacesList/index.tsx | 2 +- frontend/src/pages/Dashboard/index.tsx | 8 +- 3 files changed, 256 insertions(+), 35 deletions(-) diff --git a/frontend/src/pages/Dashboard/DocumentsList/index.tsx b/frontend/src/pages/Dashboard/DocumentsList/index.tsx index 69e9fe0..234797c 100644 --- a/frontend/src/pages/Dashboard/DocumentsList/index.tsx +++ b/frontend/src/pages/Dashboard/DocumentsList/index.tsx @@ -11,6 +11,8 @@ import UploadDocumentModal from './UploadModal'; import UploadModalNoKey from './UploadModal/UploadModalNoKey'; import DocumentListPagination from '../../../components/DocumentPaginator'; import useQuery from '../../../hooks/useQuery'; +import Document from '../../../models/document'; +import { File, Trash } from '@phosphor-icons/react'; export default function DocumentsList({ organization, @@ -41,6 +43,18 @@ export default function DocumentsList({ setCurrentPage(setTo); } + const deleteDocument = async (documentId: number) => { + if ( + !confirm( + 'Are you sure you want to delete this document? This will remove the document from your vector database and remove it from the cache. This process cannot be undone.' + ) + ) + return false; + const success = await Document.delete(documentId); + if (!success) return false; + document.getElementById(`document-row-${documentId}`)?.remove(); + }; + useEffect(() => { async function getDocs(slug?: string) { if (!slug) return false; @@ -59,30 +73,17 @@ export default function DocumentsList({ if (loading) { return ( -
-
-
-

- Documents {totalDocuments! > 0 ? `(${totalDocuments})` : ''} -

-
-
-
-
-
-
+
); } return ( <> -
+ {/*
-
-

- Documents {totalDocuments! > 0 ? `(${totalDocuments})` : ''} -

-
{workspaces.length > 0 ? ( <> {!!knownConnector ? ( @@ -128,16 +129,41 @@ export default function DocumentsList({ Workspace
- Created + Date
- Status + Vectors
+ + {documents?.length === 0 && ( +
+
+
+ 0 Documents +
+
+ Upload documents to your workspace +
+ +
+
+ )} <> {documents.map((document) => { return ( @@ -216,17 +242,212 @@ export default function DocumentsList({
)} +
*/} +
+
+ + + + + + + + + + + + {documents?.length > 0 && ( + + {documents.map((document, index) => ( + + ))} + + )} +
+ Name + + Workspace + + Date + + Vectors + + {' '} +
+ + {workspaces?.length === 0 && ( +
+
+
+ Create a workspace to get started +
+
+ Workspaces are used to organize your documents +
+ +
+
+ )} + + {documents?.length === 0 && workspaces?.length > 0 && ( +
+
+
+ 0 Documents +
+
+ Upload documents to your workspace +
+ +
+
+ )} +
+ +
+ +
+ {canUpload ? ( + + ) : ( + + )}
- - {canUpload ? ( - - ) : ( - - )} ); } + +const Fragment = ({ + document, + index, + deleteDocument, + organization, +}: { + document: any; + index: number; + deleteDocument: any; + organization: any; +}) => { + return ( + <> + + + +

{truncate(document?.name, 35)}

+ + + + + {truncate(document.workspace.name, 20) || ''} + + + + {moment(document?.createdAt).format('lll')} + Cached + + + Details + + + +
+
+ +
+
+ + + + ); +}; diff --git a/frontend/src/pages/Dashboard/WorkspacesList/index.tsx b/frontend/src/pages/Dashboard/WorkspacesList/index.tsx index 7ba65a9..a35bc64 100644 --- a/frontend/src/pages/Dashboard/WorkspacesList/index.tsx +++ b/frontend/src/pages/Dashboard/WorkspacesList/index.tsx @@ -20,7 +20,7 @@ export default function WorkspacesList({ totalWorkspaces?: number; }) { return ( -
+

diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 2b7a087..e1090d7 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -135,8 +135,8 @@ export default function Dashboard() {

)} -
-
+
+
void; }) => { const [loading, setLoading] = useState(false); - const [type, setType] = useState(connector.type); + const [type, setType] = useState(connector?.type); const [error, setError] = useState(null); const [success, setSuccess] = useState(false); - const settings = JSON.parse(connector.settings); + const settings = JSON.parse(connector?.settings); const handleSubmit = async (e: any) => { e.preventDefault(); From d12e548ac89b46d31eb32481d22af31f12d817e8 Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Tue, 19 Dec 2023 17:06:48 -0800 Subject: [PATCH 4/7] organization page complete with quick actions sidebar --- frontend/src/components/Header/index.tsx | 34 +-- frontend/src/layout/AppLayout.tsx | 3 + .../Dashboard/QuickActionSidebar/index.tsx | 262 ++++++++++++++++++ .../src/pages/Dashboard/Statistics/index.tsx | 85 ++---- frontend/src/pages/Dashboard/index.tsx | 18 +- 5 files changed, 311 insertions(+), 91 deletions(-) create mode 100644 frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx diff --git a/frontend/src/components/Header/index.tsx b/frontend/src/components/Header/index.tsx index 9c11d3c..a99e794 100644 --- a/frontend/src/components/Header/index.tsx +++ b/frontend/src/components/Header/index.tsx @@ -14,10 +14,17 @@ export default function Header(props: { sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void; extendedItems?: any; + quickActions: boolean; }) { const [copied, setCopied] = useState(false); if (!props.entity) return null; - const { entity, property, nameProp, extendedItems = <> } = props; + const { + entity, + property, + nameProp, + extendedItems = <>, + quickActions = false, + } = props; const handleCopy = () => { window.navigator.clipboard.writeText(entity[property]); @@ -124,25 +131,12 @@ export default function Header(props: { //
//
// -
-
- {/*
- Organization {'>'} Workspace 1 {'>'} Document 1 -
-
- - -
*/} - {extendedItems} -
+
+
{extendedItems}
); } diff --git a/frontend/src/layout/AppLayout.tsx b/frontend/src/layout/AppLayout.tsx index 25d236c..2a29122 100644 --- a/frontend/src/layout/AppLayout.tsx +++ b/frontend/src/layout/AppLayout.tsx @@ -13,6 +13,7 @@ interface DefaultLayoutProps { children: ReactNode; hasMoreWorkspaces?: boolean; loadMoreWorkspaces?: VoidFunction; + hasQuickActions?: boolean; } const AppLayout = ({ @@ -26,6 +27,7 @@ const AppLayout = ({ children, hasMoreWorkspaces, loadMoreWorkspaces, + hasQuickActions = false, }: DefaultLayoutProps) => { const [sidebarOpen, setSidebarOpen] = useState(false); @@ -52,6 +54,7 @@ const AppLayout = ({ sidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} extendedItems={headerExtendedItems} + quickActions={hasQuickActions} />
)} diff --git a/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx new file mode 100644 index 0000000..2024417 --- /dev/null +++ b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx @@ -0,0 +1,262 @@ +import { + CaretDown, + Key, + MagnifyingGlass, + Plus, + SpinnerGap, + Toolbox, + User, +} from '@phosphor-icons/react'; +import CreateWorkspaceModal from '../WorkspacesList/CreateWorkspaceModal'; +import { useEffect, useState } from 'react'; +import { NavLink, useParams } from 'react-router-dom'; +import paths from '../../../utils/paths'; +import truncate from 'truncate'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import { debounce } from 'lodash'; +import Organization from '../../../models/organization'; + +const debouncedSearch = debounce( + async (searchTerm, setResults, setIsSearching, slug) => { + if (!slug) return; + setIsSearching(true); + + const { workspacesResults = [] } = await Organization.searchWorkspaces( + slug, + 1, // Page 1 + 30, // 30 results per page + searchTerm + ); + + setResults(workspacesResults); + setIsSearching(false); + }, + 500 +); + +export default function QuickActionsSidebar({ + knownConnector, + organization, + workspaces, + totalWorkspaces = 0, + loadMoreWorkspaces, + hasMoreWorkspaces, +}: { + knownConnector: any; + organization: any; + workspaces: any[]; + totalWorkspaces?: number; + loadMoreWorkspaces?: VoidFunction; + hasMoreWorkspaces: boolean; +}) { + const { slug } = useParams(); + const [quickActionsOpen, setQuickActionsOpen] = useState(true); + const [searchTerm, setSearchTerm] = useState(''); + const [searchResults, setSearchResults] = useState([]); + const [isSearching, setIsSearching] = useState(false); + + const renderWorkspaceItem = (workspace: any) => ( + + ); + + const loadMoreWorkspacesAndScrollToBottom = async () => { + loadMoreWorkspaces?.(); + const organizationList = document.getElementById('organization-list'); + if (organizationList) { + organizationList.scrollTop = organizationList.scrollHeight; + } + }; + + useEffect(() => { + if (searchTerm !== '') { + setIsSearching(true); + debouncedSearch(searchTerm, setSearchResults, setIsSearching, slug); + } else { + setSearchResults(workspaces); + setIsSearching(false); + } + }, [searchTerm, slug]); + + return ( +
+ + +
+ +
+ +
Tools
+
+
+ + +
+ +
Add User
+
+
+ + +
+ +
OpenAI Key
+
+
+ + +
+ +
Background Jobs
+
+
+
+ +
+
+
+ + + +
+ Workspaces +
+
+ +
+
+ + setSearchTerm(e.target.value)} + className="border-none bg-transparent text-sm text-white/60 placeholder-white/60 focus:outline-none" + /> +
+ + {isSearching ? ( + + ) : searchTerm !== '' && searchResults.length > 0 ? ( +
+ {searchResults.map((workspace, idx) => ( + + ))} +
+ ) : searchTerm !== '' && searchResults.length === 0 ? ( +
+
+

No results found.

+
+
+ ) : workspaces.length > 0 ? ( +
+ 5 ? 180 : workspaces.length * 50} + next={loadMoreWorkspacesAndScrollToBottom} + hasMore={hasMoreWorkspaces} + loader={} + > + {workspaces.map(renderWorkspaceItem)} + +
+ ) : ( +
+
+

+ No workspaces,{' '} + + . +

+
+
+ )} + +
+
+ ); +} + +function WorkspaceItem({ workspace, slug }: any) { + return ( +
+ +
+ {truncate(workspace.name, 15)} +
+
+
+ ); +} + +function LoadingWorkspaceItem() { + return ( +
+
+

Loading...

+
+
+ ); +} diff --git a/frontend/src/pages/Dashboard/Statistics/index.tsx b/frontend/src/pages/Dashboard/Statistics/index.tsx index 68337ff..e0c2577 100644 --- a/frontend/src/pages/Dashboard/Statistics/index.tsx +++ b/frontend/src/pages/Dashboard/Statistics/index.tsx @@ -1,11 +1,16 @@ import { memo, useState, useEffect } from 'react'; -import PreLoader from '../../../components/Preloader'; import { humanFileSize, nFormatter } from '../../../utils/numbers'; -import moment from 'moment'; import Organization from '../../../models/organization'; import pluralize from 'pluralize'; +import Workspace from '../../../models/workspace'; -const Statistics = ({ organization }: { organization: any }) => { +const Statistics = ({ + organization, + workspaces, +}: { + organization: any; + workspaces: any; +}) => { const [documents, setDocuments] = useState({ status: 'loading', value: 0, @@ -18,6 +23,10 @@ const Statistics = ({ organization }: { organization: any }) => { status: 'loading', value: 0, }); + const [dimensions, setDimensions] = useState({ + status: 'loading', + value: '-', + }); useEffect(() => { async function collectStats() { @@ -32,70 +41,17 @@ const Statistics = ({ organization }: { organization: any }) => { Organization.stats(organization.slug, 'cache-size').then((json) => { setCache({ status: 'complete', value: json.value }); }); + Workspace.stats(organization.slug, workspaces[0].slug, 'dimensions').then( + (json) => { + setDimensions({ status: 'complete', value: json.value }); + } + ); } collectStats(); - }, [organization?.slug]); + }, [organization?.slug, workspaces[0]?.slug]); return ( - //
- //
- //
- // {documents.status === 'loading' ? ( - // - // ) : ( - //
- //

- // {nFormatter(documents.value)} - //

- //

- // {pluralize('Document', documents.value)} - //

- //
- // )} - //
- - //
- // {vectors.status === 'loading' ? ( - // - // ) : ( - //
- //

- // {nFormatter(vectors.value)} - //

- //

- // {pluralize('Vector', vectors.value)} - //

- //
- // )} - //
- - //
- // {cache.status === 'loading' ? ( - // - // ) : ( - //
- //

- // {humanFileSize(cache.value)} - //

- //

Vector Cache (MB)

- //
- // )} - //
- - //
- //
- //

- // {organization?.lastUpdated - // ? moment(organization.lastUpdated).fromNow() - // : moment(organization.createdAt).fromNow()} - //

- //

Last Modified

- //
- //
- //
- //
- -
+
@@ -125,7 +81,8 @@ const Statistics = ({ organization }: { organization: any }) => { - Dimensions: {10} + Dimensions:{' '} + {dimensions.value}
diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index e1090d7..7dd4a33 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -5,9 +5,8 @@ import DefaultLayout from '../../layout/DefaultLayout'; import User from '../../models/user'; import paths from '../../utils/paths'; import AppLayout from '../../layout/AppLayout'; -import { useParams } from 'react-router-dom'; +import { NavLink, useParams } from 'react-router-dom'; import Statistics from './Statistics'; -import WorkspacesList from './WorkspacesList'; import DocumentsList from './DocumentsList'; import Organization from '../../models/organization'; import ApiKeyCard from './ApiKey'; @@ -21,6 +20,8 @@ import qDrantLogo from '../../images/vectordbs/qdrant.png'; import WeaviateLogo from '../../images/vectordbs/weaviate.png'; import { GearSix } from '@phosphor-icons/react'; import { titleCase } from 'title-case'; +import CreateWorkspaceModal from './WorkspacesList/CreateWorkspaceModal'; +import QuickActionsSidebar from './QuickActionSidebar'; export default function Dashboard() { const { slug } = useParams(); @@ -114,6 +115,7 @@ export default function Dashboard() { deleteWorkspace={() => {}} /> } + hasQuickActions={true} > {!!organization && (
@@ -134,7 +136,7 @@ export default function Dashboard() { {/* */}
)} - +
-
@@ -208,12 +211,13 @@ function OrganizationHeader({ Sync
- +
); From 3f2acca224f203080b3e507692ea0579f403b405 Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Tue, 19 Dec 2023 17:10:01 -0800 Subject: [PATCH 5/7] limit some quick actions to admin only --- .../Dashboard/QuickActionSidebar/index.tsx | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx index 2024417..ea69976 100644 --- a/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx +++ b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx @@ -15,6 +15,7 @@ import truncate from 'truncate'; import InfiniteScroll from 'react-infinite-scroll-component'; import { debounce } from 'lodash'; import Organization from '../../../models/organization'; +import useUser from '../../../hooks/useUser'; const debouncedSearch = debounce( async (searchTerm, setResults, setIsSearching, slug) => { @@ -50,6 +51,7 @@ export default function QuickActionsSidebar({ hasMoreWorkspaces: boolean; }) { const { slug } = useParams(); + const { user } = useUser(); const [quickActionsOpen, setQuickActionsOpen] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [searchResults, setSearchResults] = useState([]); @@ -107,27 +109,30 @@ export default function QuickActionsSidebar({ animationDuration: '0.15s', }} > - -
- -
Tools
-
-
+ {user?.role === 'admin' && ( + <> + +
+ +
Tools
+
+
- -
- -
Add User
-
-
- - -
- -
OpenAI Key
-
-
+ +
+ +
Add User
+
+
+ +
+ +
OpenAI Key
+
+
+ + )}
From d0ae466f435c132ca74d370f51abe587468f41df Mon Sep 17 00:00:00 2001 From: shatfield4 Date: Tue, 19 Dec 2023 17:43:54 -0800 Subject: [PATCH 6/7] fix no connector bug on new organization connection --- .../pages/Dashboard/DocumentsList/index.tsx | 28 +- frontend/src/pages/Dashboard/index.tsx | 460 +++++++++++++++++- 2 files changed, 471 insertions(+), 17 deletions(-) diff --git a/frontend/src/pages/Dashboard/DocumentsList/index.tsx b/frontend/src/pages/Dashboard/DocumentsList/index.tsx index 234797c..7e4f940 100644 --- a/frontend/src/pages/Dashboard/DocumentsList/index.tsx +++ b/frontend/src/pages/Dashboard/DocumentsList/index.tsx @@ -2,7 +2,6 @@ import { Link } from 'react-router-dom'; import paths from '../../../utils/paths'; import moment from 'moment'; import { AlertOctagon, FileText } from 'react-feather'; -// import { CodeBlock, vs2015 } from 'react-code-blocks'; import { useEffect, useState } from 'react'; import Organization from '../../../models/organization'; import truncate from 'truncate'; @@ -316,7 +315,32 @@ export default function DocumentsList({ )} - {workspaces?.length === 0 && ( + {!!!knownConnector && ( +
+
+
+ Connect a Vector Database to get started +
+
+ Begin by connecting a Vector Database to your organization +
+ +
+
+ )} + + {!!knownConnector && workspaces?.length === 0 && (
diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 7dd4a33..875622f 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -1,4 +1,4 @@ -import { FullScreenLoader } from '../../components/Preloader'; +import PreLoader, { FullScreenLoader } from '../../components/Preloader'; import useUser from '../../hooks/useUser'; import { useState, useEffect } from 'react'; import DefaultLayout from '../../layout/DefaultLayout'; @@ -18,10 +18,11 @@ import PineconeLogoInverted from '../../images/vectordbs/pinecone-inverted.png'; import PineconeLogo from '../../images/vectordbs/pinecone.png'; import qDrantLogo from '../../images/vectordbs/qdrant.png'; import WeaviateLogo from '../../images/vectordbs/weaviate.png'; -import { GearSix } from '@phosphor-icons/react'; +import { GearSix, Prohibit } from '@phosphor-icons/react'; import { titleCase } from 'title-case'; import CreateWorkspaceModal from './WorkspacesList/CreateWorkspaceModal'; import QuickActionsSidebar from './QuickActionSidebar'; +import { APP_NAME } from '../../utils/constants'; export default function Dashboard() { const { slug } = useParams(); @@ -117,7 +118,7 @@ export default function Dashboard() { } hasQuickActions={true} > - {!!organization && ( + {!!organization && !!connector && (
- Connector logo + {!!connector?.type ? ( + Connector logo + ) : ( + <> + window.location.reload()} + /> +
+ +
+ + )} +
+ +
+ + ); +}; + const UpdateConnectorModal = ({ organization, connector, From 9b6c5e49b0775f18405970ead706b9a4cba7dade Mon Sep 17 00:00:00 2001 From: timothycarambat Date: Thu, 21 Dec 2023 11:46:46 -0800 Subject: [PATCH 7/7] pr review --- .../pages/Dashboard/DocumentsList/index.tsx | 165 +--------------- .../Dashboard/QuickActionSidebar/index.tsx | 187 +----------------- frontend/src/pages/Dashboard/index.tsx | 28 +-- .../src/pages/WorkspaceDashboard/index.tsx | 1 - 4 files changed, 6 insertions(+), 375 deletions(-) diff --git a/frontend/src/pages/Dashboard/DocumentsList/index.tsx b/frontend/src/pages/Dashboard/DocumentsList/index.tsx index 7e4f940..cf15e94 100644 --- a/frontend/src/pages/Dashboard/DocumentsList/index.tsx +++ b/frontend/src/pages/Dashboard/DocumentsList/index.tsx @@ -1,7 +1,5 @@ -import { Link } from 'react-router-dom'; import paths from '../../../utils/paths'; import moment from 'moment'; -import { AlertOctagon, FileText } from 'react-feather'; import { useEffect, useState } from 'react'; import Organization from '../../../models/organization'; import truncate from 'truncate'; @@ -81,167 +79,6 @@ export default function DocumentsList({ return ( <> - {/*
-
- {workspaces.length > 0 ? ( - <> - {!!knownConnector ? ( - - ) : ( - - )} - - ) : ( - - )} -
- {documents.length > 0 ? ( -
-
-
-
- Document Name -
-
- Workspace -
-
- Date -
-
- Vectors -
-
- -
-
-
- - {documents?.length === 0 && ( -
-
-
- 0 Documents -
-
- Upload documents to your workspace -
- -
-
- )} - <> - {documents.map((document) => { - return ( -
-
-
-
- - - {truncate(document.name, 20)} - -
-
- -
- - {moment(document.createdAt).format('lll')} - -
-
- - Cached - -
- - -
-
- ); - })} - -
- ) : ( -
-
-
-

You have no documents in any workspaces!

-

- Get started managing documents by adding them to workspaces - via the UI or code. -

- -
-
-
- )} -
*/}
-
+
UPLOAD
diff --git a/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx index ea69976..eb6350f 100644 --- a/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx +++ b/frontend/src/pages/Dashboard/QuickActionSidebar/index.tsx @@ -1,83 +1,22 @@ import { CaretDown, Key, - MagnifyingGlass, - Plus, SpinnerGap, Toolbox, User, } from '@phosphor-icons/react'; -import CreateWorkspaceModal from '../WorkspacesList/CreateWorkspaceModal'; -import { useEffect, useState } from 'react'; -import { NavLink, useParams } from 'react-router-dom'; +import { useState } from 'react'; +import { NavLink } from 'react-router-dom'; import paths from '../../../utils/paths'; -import truncate from 'truncate'; -import InfiniteScroll from 'react-infinite-scroll-component'; -import { debounce } from 'lodash'; -import Organization from '../../../models/organization'; import useUser from '../../../hooks/useUser'; -const debouncedSearch = debounce( - async (searchTerm, setResults, setIsSearching, slug) => { - if (!slug) return; - setIsSearching(true); - - const { workspacesResults = [] } = await Organization.searchWorkspaces( - slug, - 1, // Page 1 - 30, // 30 results per page - searchTerm - ); - - setResults(workspacesResults); - setIsSearching(false); - }, - 500 -); - export default function QuickActionsSidebar({ - knownConnector, organization, - workspaces, - totalWorkspaces = 0, - loadMoreWorkspaces, - hasMoreWorkspaces, }: { - knownConnector: any; organization: any; - workspaces: any[]; - totalWorkspaces?: number; - loadMoreWorkspaces?: VoidFunction; - hasMoreWorkspaces: boolean; }) { - const { slug } = useParams(); const { user } = useUser(); const [quickActionsOpen, setQuickActionsOpen] = useState(true); - const [searchTerm, setSearchTerm] = useState(''); - const [searchResults, setSearchResults] = useState([]); - const [isSearching, setIsSearching] = useState(false); - - const renderWorkspaceItem = (workspace: any) => ( - - ); - - const loadMoreWorkspacesAndScrollToBottom = async () => { - loadMoreWorkspaces?.(); - const organizationList = document.getElementById('organization-list'); - if (organizationList) { - organizationList.scrollTop = organizationList.scrollHeight; - } - }; - - useEffect(() => { - if (searchTerm !== '') { - setIsSearching(true); - debouncedSearch(searchTerm, setSearchResults, setIsSearching, slug); - } else { - setSearchResults(workspaces); - setIsSearching(false); - } - }, [searchTerm, slug]); return (
@@ -140,128 +79,6 @@ export default function QuickActionsSidebar({
- -
-
-
- - - -
- Workspaces -
-
- -
-
- - setSearchTerm(e.target.value)} - className="border-none bg-transparent text-sm text-white/60 placeholder-white/60 focus:outline-none" - /> -
- - {isSearching ? ( - - ) : searchTerm !== '' && searchResults.length > 0 ? ( -
- {searchResults.map((workspace, idx) => ( - - ))} -
- ) : searchTerm !== '' && searchResults.length === 0 ? ( -
-
-

No results found.

-
-
- ) : workspaces.length > 0 ? ( -
- 5 ? 180 : workspaces.length * 50} - next={loadMoreWorkspacesAndScrollToBottom} - hasMore={hasMoreWorkspaces} - loader={} - > - {workspaces.map(renderWorkspaceItem)} - -
- ) : ( -
-
-

- No workspaces,{' '} - - . -

-
-
- )} - -
-
- ); -} - -function WorkspaceItem({ workspace, slug }: any) { - return ( -
- -
- {truncate(workspace.name, 15)} -
-
-
- ); -} - -function LoadingWorkspaceItem() { - return ( -
-
-

Loading...

-
); } diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 875622f..e01ae59 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -9,8 +9,6 @@ import { NavLink, useParams } from 'react-router-dom'; import Statistics from './Statistics'; import DocumentsList from './DocumentsList'; import Organization from '../../models/organization'; -import ApiKeyCard from './ApiKey'; -import ConnectorCard from './Connector'; import truncate from 'truncate'; import ChromaLogo from '../../images/vectordbs/chroma.png'; @@ -20,7 +18,6 @@ import qDrantLogo from '../../images/vectordbs/qdrant.png'; import WeaviateLogo from '../../images/vectordbs/weaviate.png'; import { GearSix, Prohibit } from '@phosphor-icons/react'; import { titleCase } from 'title-case'; -import CreateWorkspaceModal from './WorkspacesList/CreateWorkspaceModal'; import QuickActionsSidebar from './QuickActionSidebar'; import { APP_NAME } from '../../utils/constants'; @@ -36,7 +33,6 @@ export default function Dashboard() { const [workspaces, setWorkspaces] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [hasMoreWorkspaces, setHasMoreWorkspaces] = useState(true); - const [totalWorkspaces, setTotalWorkspaces] = useState(0); async function fetchWorkspaces(focusedOrg?: { slug: string }) { const org = focusedOrg || organization; @@ -55,11 +51,9 @@ export default function Dashboard() { setWorkspaces(uniques); setHasMoreWorkspaces(uniques.length < totalWorkspaces); - setTotalWorkspaces(totalWorkspaces); } else { setWorkspaces(_workspaces); setHasMoreWorkspaces(totalWorkspaces > Organization.workspacePageSize); - setTotalWorkspaces(totalWorkspaces); } setCurrentPage(currentPage + 1); return true; @@ -129,12 +123,6 @@ export default function Dashboard() { organization={organization} connector={connector} /> - {/* */} - {/* */}
)} @@ -146,13 +134,7 @@ export default function Dashboard() { workspaces={workspaces} />
- +
); @@ -192,11 +174,7 @@ function OrganizationHeader({ organization, connector }: any) { className="flex h-11 w-11 items-center justify-center rounded-lg border-2 border-white border-opacity-20 transition-all duration-300 hover:bg-opacity-5" > {!!connector?.type ? ( - Connector logo + Connector logo ) : ( <> -
+
Sync
diff --git a/frontend/src/pages/WorkspaceDashboard/index.tsx b/frontend/src/pages/WorkspaceDashboard/index.tsx index baff31a..014b1e6 100644 --- a/frontend/src/pages/WorkspaceDashboard/index.tsx +++ b/frontend/src/pages/WorkspaceDashboard/index.tsx @@ -7,7 +7,6 @@ import paths from '../../utils/paths'; import AppLayout from '../../layout/AppLayout'; import { useParams } from 'react-router-dom'; import Organization from '../../models/organization'; -import ApiKeyCard from './ApiKey'; import Statistics from './Statistics'; import DocumentsList from './DocumentsList'; import Workspace from '../../models/workspace';