mirror of
https://github.com/Mintplex-Labs/vector-admin.git
synced 2026-07-19 21:23:38 -04:00
Merge pull request #95 from Mintplex-Labs/v2-organization
v2 Organization page
This commit is contained in:
@@ -7,6 +7,7 @@ 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;
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
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';
|
||||
@@ -11,6 +8,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 +40,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,174 +70,245 @@ export default function DocumentsList({
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="col-span-12 flex-1 rounded-sm border border-stroke bg-main py-6 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4">
|
||||
<div className="flex items-start justify-between px-4">
|
||||
<div>
|
||||
<h4 className="mb-6 px-4 text-xl font-semibold text-black dark:text-white">
|
||||
Documents {totalDocuments! > 0 ? `(${totalDocuments})` : ''}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex h-60 w-full items-center justify-center px-7.5">
|
||||
<div className="h-full w-full animate-pulse rounded-lg bg-slate-100" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="mb-9 flex h-screen flex-col overflow-hidden bg-main py-6 transition-all duration-300"
|
||||
style={{ height: `calc(100vh - 210px` }}
|
||||
></div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="col-span-12 flex-1 rounded-sm border border-stroke bg-white py-6 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4">
|
||||
<div className="flex items-start justify-between px-4">
|
||||
<div>
|
||||
<h4 className="mb-6 px-4 text-xl font-semibold text-black dark:text-white">
|
||||
Documents {totalDocuments! > 0 ? `(${totalDocuments})` : ''}
|
||||
</h4>
|
||||
</div>
|
||||
{workspaces.length > 0 ? (
|
||||
<>
|
||||
{!!knownConnector ? (
|
||||
<div
|
||||
className="mb-9 flex h-screen flex-col overflow-hidden bg-main transition-all duration-300"
|
||||
style={{ height: `calc(100vh - 160px)` }}
|
||||
>
|
||||
<div className="flex-grow overflow-y-auto rounded-xl border-2 border-white/20 bg-main">
|
||||
<table className="w-full rounded-xl text-left text-xs font-medium text-white text-opacity-80">
|
||||
<thead className="sticky top-0 w-full border-b-2 border-white/20 bg-main ">
|
||||
<tr className="mt-10">
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 pb-2 pt-6 text-xs font-light text-white text-opacity-80"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 pb-2 pt-6 text-xs font-light text-white text-opacity-80"
|
||||
>
|
||||
Workspace
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 pb-2 pt-6 text-xs font-light text-white text-opacity-80"
|
||||
>
|
||||
Date
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 pb-2 pt-6 text-xs font-light text-white text-opacity-80"
|
||||
>
|
||||
Vectors
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="px-6 pb-2 pt-6 text-xs font-light text-white text-opacity-80"
|
||||
>
|
||||
{' '}
|
||||
</th>
|
||||
<th
|
||||
hidden={workspaces.length === 0}
|
||||
scope="col"
|
||||
className="relative px-6 pb-2 pt-6"
|
||||
>
|
||||
<button
|
||||
onClick={() => {
|
||||
document
|
||||
.getElementById('upload-document-modal')
|
||||
?.showModal();
|
||||
}}
|
||||
className="inline-flex h-[26px] w-[98px] items-center justify-center gap-2.5 rounded-[100px] bg-white bg-opacity-10 px-2.5 py-1"
|
||||
>
|
||||
<div className="font-satoshi text-xs font-black tracking-tight text-sky-400">
|
||||
UPLOAD
|
||||
</div>
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{documents?.length > 0 && (
|
||||
<tbody className="bg-main">
|
||||
{documents.map((document, index) => (
|
||||
<Fragment
|
||||
key={document?.id}
|
||||
document={document}
|
||||
index={index}
|
||||
deleteDocument={deleteDocument}
|
||||
organization={organization}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
)}
|
||||
</table>
|
||||
|
||||
{!!!knownConnector && (
|
||||
<div className="-mt-10 flex h-full w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center justify-center gap-y-4 text-center">
|
||||
<div className="text-center font-medium text-white text-opacity-40">
|
||||
Connect a Vector Database to get started
|
||||
</div>
|
||||
<div className="text-center text-sm font-light text-white text-opacity-80">
|
||||
Begin by connecting a Vector Database to your organization
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
document
|
||||
.getElementById('upload-document-modal')
|
||||
window.document
|
||||
?.getElementById('new-connector-modal')
|
||||
?.showModal();
|
||||
}}
|
||||
className="rounded-lg px-2 py-1 text-sm text-slate-800 hover:bg-slate-200"
|
||||
className="mt-4 inline-flex items-center justify-center gap-2.5 rounded-lg bg-white p-2.5 px-36 shadow"
|
||||
>
|
||||
Add Document
|
||||
<div className="text-center text-sm font-bold leading-tight text-zinc-900">
|
||||
Connect Vector Database
|
||||
</div>
|
||||
</button>
|
||||
) : (
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!knownConnector && workspaces?.length === 0 && (
|
||||
<div className="-mt-10 flex h-full w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center justify-center gap-y-4 text-center">
|
||||
<div className="text-center font-medium text-white text-opacity-40">
|
||||
Create a workspace to get started
|
||||
</div>
|
||||
<div className="text-center text-sm font-light text-white text-opacity-80">
|
||||
Workspaces are used to organize your documents
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
disabled={true}
|
||||
className="flex items-center gap-x-1 rounded-lg bg-red-50 px-2 py-1 text-sm text-red-800"
|
||||
onClick={() => {
|
||||
window.document
|
||||
?.getElementById('workspace-creation-modal')
|
||||
?.showModal();
|
||||
}}
|
||||
className="mt-4 inline-flex items-center justify-center gap-2.5 rounded-lg bg-white p-2.5 px-36 shadow"
|
||||
>
|
||||
<AlertOctagon className="h4- w-4" /> Requires Vector Database
|
||||
Connection
|
||||
<div className="text-center text-sm font-bold leading-tight text-zinc-900">
|
||||
Create Workspace
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={true}
|
||||
className="flex items-center gap-x-1 rounded-lg bg-red-50 px-2 py-1 text-sm text-red-800"
|
||||
>
|
||||
<AlertOctagon className="h4- w-4" /> Requires Workspace
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{documents?.length === 0 && workspaces?.length > 0 && (
|
||||
<div className="-mt-10 flex h-full w-full items-center justify-center">
|
||||
<div className="flex flex-col items-center justify-center gap-y-4 text-center">
|
||||
<div className="text-center font-medium text-white text-opacity-40">
|
||||
0 Documents
|
||||
</div>
|
||||
<div className="text-center text-sm font-light text-white text-opacity-80">
|
||||
Upload documents to your workspace
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
window.document
|
||||
?.getElementById('upload-document-modal')
|
||||
?.showModal();
|
||||
}}
|
||||
className="mt-4 inline-flex items-center justify-center gap-2.5 rounded-lg bg-white p-2.5 px-36 shadow"
|
||||
>
|
||||
<div className="text-center text-sm font-bold leading-tight text-zinc-900">
|
||||
Upload Documents
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{documents.length > 0 ? (
|
||||
<div>
|
||||
<div className="border-b border-stroke px-4 pb-5 dark:border-strokedark md:px-6 xl:px-7.5">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-2/12 xl:w-3/12">
|
||||
<span className="font-medium">Document Name</span>
|
||||
</div>
|
||||
<div className="w-6/12 2xsm:w-5/12 md:w-3/12">
|
||||
<span className="font-medium">Workspace</span>
|
||||
</div>
|
||||
<div className="hidden w-4/12 md:block xl:w-3/12">
|
||||
<span className="font-medium">Created</span>
|
||||
</div>
|
||||
<div className="w-5/12 2xsm:w-4/12 md:w-3/12 xl:w-2/12">
|
||||
<span className="font-medium">Status</span>
|
||||
</div>
|
||||
<div className="hidden w-2/12 text-center 2xsm:block md:w-1/12">
|
||||
<span className="font-medium"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<>
|
||||
{documents.map((document) => {
|
||||
return (
|
||||
<div
|
||||
id={`document-row-${document.id}`}
|
||||
key={document.id}
|
||||
className="flex w-full items-center gap-5 px-7.5 py-3 text-gray-600 hover:bg-gray-3 dark:hover:bg-meta-4"
|
||||
>
|
||||
<div className="flex w-full items-center gap-3">
|
||||
<div className="w-2/12 xl:w-3/12">
|
||||
<div className="flex items-center gap-x-1">
|
||||
<FileText className="h-4 w-4" />
|
||||
<span className="hidden font-medium xl:block">
|
||||
{truncate(document.name, 20)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-6/12 2xsm:w-5/12 md:w-3/12">
|
||||
<a
|
||||
href={paths.workspace(
|
||||
organization.slug,
|
||||
document.workspace.slug
|
||||
)}
|
||||
className="hover:text-blue-500 hover:underline"
|
||||
>
|
||||
<span className="font-medium">
|
||||
{truncate(document.workspace.name, 20) || ''}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div className="hidden w-3/12 overflow-x-scroll md:block xl:w-3/12">
|
||||
<span className="font-medium">
|
||||
{moment(document.createdAt).format('lll')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-5/12 2xsm:w-4/12 md:w-3/12 xl:w-2/12">
|
||||
<span className="inline-block rounded bg-green-500 bg-opacity-25 px-2.5 py-0.5 text-sm font-medium text-green-500">
|
||||
Cached
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className=" flex items-center gap-x-2">
|
||||
<a
|
||||
href={paths.document(
|
||||
organization.slug,
|
||||
document.workspace.slug,
|
||||
document.id
|
||||
)}
|
||||
className="rounded-lg px-2 py-1 text-blue-400 transition-all duration-300 hover:bg-blue-50 hover:text-blue-600"
|
||||
>
|
||||
Details
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
</div>
|
||||
<div className="pt-20">
|
||||
<DocumentListPagination
|
||||
pageCount={Math.ceil(
|
||||
totalDocuments! / Organization.documentPageSize
|
||||
)}
|
||||
currentPage={currentPage}
|
||||
gotoPage={updatePage}
|
||||
/>
|
||||
</div>
|
||||
{canUpload ? (
|
||||
<UploadDocumentModal workspaces={workspaces} />
|
||||
) : (
|
||||
<div>
|
||||
<div className="flex min-h-[40vh] w-full px-8">
|
||||
<div className="flex flex h-auto w-full flex-col items-center justify-center gap-y-2 rounded-lg bg-slate-50">
|
||||
<p>You have no documents in any workspaces!</p>
|
||||
<p>
|
||||
Get started managing documents by adding them to workspaces
|
||||
via the UI or code.
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
className="text-xl text-blue-500 underline"
|
||||
>
|
||||
Show code example (coming soon)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<UploadModalNoKey />
|
||||
)}
|
||||
</div>
|
||||
<DocumentListPagination
|
||||
pageCount={Math.ceil(totalDocuments! / Organization.documentPageSize)}
|
||||
currentPage={currentPage}
|
||||
gotoPage={updatePage}
|
||||
/>
|
||||
{canUpload ? (
|
||||
<UploadDocumentModal workspaces={workspaces} />
|
||||
) : (
|
||||
<UploadModalNoKey />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const Fragment = ({
|
||||
document,
|
||||
index,
|
||||
deleteDocument,
|
||||
organization,
|
||||
}: {
|
||||
document: any;
|
||||
index: number;
|
||||
deleteDocument: any;
|
||||
organization: any;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<tr
|
||||
key={document?.id}
|
||||
id={`document-row-${document?.id}`}
|
||||
className={`h-9 hover:bg-white/10 ${
|
||||
index % 2 === 0 ? 'bg-main-2' : 'bg-main'
|
||||
}`}
|
||||
>
|
||||
<td className="flex items-center gap-x-1 px-6 py-2 text-sm font-light text-white">
|
||||
<File className="flex-shrink-0" size={16} weight="fill" />
|
||||
<p>{truncate(document?.name, 35)}</p>
|
||||
</td>
|
||||
<td className="px-6 ">
|
||||
<a
|
||||
href={paths.workspace(organization.slug, document.workspace.slug)}
|
||||
className="hover:text-sky-400 hover:underline"
|
||||
>
|
||||
<span className="font-medium">
|
||||
{truncate(document.workspace.name, 20) || ''}
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
<td className="px-6 ">{moment(document?.createdAt).format('lll')}</td>
|
||||
<td className="px-6 ">Cached</td>
|
||||
<td className="px-6 ">
|
||||
<a
|
||||
href={paths.document(
|
||||
organization.slug,
|
||||
document.workspace.slug,
|
||||
document.id
|
||||
)}
|
||||
className="rounded-lg px-2 py-1 text-sky-400 transition-all duration-300 hover:bg-blue-50"
|
||||
>
|
||||
Details
|
||||
</a>
|
||||
</td>
|
||||
<td className="px-6">
|
||||
<div className="flex items-center gap-x-4">
|
||||
<div className=" flex items-center gap-x-6">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => deleteDocument(document?.id)}
|
||||
className="rounded-lg px-2 py-1 text-white transition-all duration-300 hover:bg-red-50 hover:text-red-600"
|
||||
>
|
||||
<Trash size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import {
|
||||
CaretDown,
|
||||
Key,
|
||||
SpinnerGap,
|
||||
Toolbox,
|
||||
User,
|
||||
} from '@phosphor-icons/react';
|
||||
import { useState } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import paths from '../../../utils/paths';
|
||||
import useUser from '../../../hooks/useUser';
|
||||
|
||||
export default function QuickActionsSidebar({
|
||||
organization,
|
||||
}: {
|
||||
organization: any;
|
||||
}) {
|
||||
const { user } = useUser();
|
||||
const [quickActionsOpen, setQuickActionsOpen] = useState(true);
|
||||
|
||||
return (
|
||||
<div className="-mt-14 w-[217px]">
|
||||
<button
|
||||
onClick={() => setQuickActionsOpen(!quickActionsOpen)}
|
||||
className="w-full text-white/80"
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="font-['Plus Jakarta Sans'] whitespace-nowrap text-xs font-semibold uppercase leading-tight tracking-wide text-white text-opacity-80">
|
||||
quick actions
|
||||
</div>
|
||||
<div
|
||||
className={`${
|
||||
quickActionsOpen ? '' : 'rotate-180'
|
||||
} transition-all duration-300`}
|
||||
>
|
||||
<CaretDown size={18} weight="bold" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
className={`${
|
||||
quickActionsOpen
|
||||
? 'slide-down mb-4 mt-4 transition-all duration-300'
|
||||
: 'slide-up'
|
||||
}`}
|
||||
style={{
|
||||
animationDuration: '0.15s',
|
||||
}}
|
||||
>
|
||||
{user?.role === 'admin' && (
|
||||
<>
|
||||
<NavLink to={paths.toolsHome(organization)}>
|
||||
<div className="mt-5 flex items-center gap-x-2 text-white hover:cursor-pointer hover:text-sky-400 hover:underline">
|
||||
<Toolbox size={18} weight="bold" />
|
||||
<div className="text-sm font-medium">Tools</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
<NavLink to={paths.users()}>
|
||||
<div className="mt-5 flex items-center gap-x-2 text-white hover:cursor-pointer hover:text-sky-400 hover:underline">
|
||||
<User size={18} weight="bold" />
|
||||
<div className="text-sm font-medium">Add User</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
|
||||
<NavLink to={paths.settings()}>
|
||||
<div className="mt-5 flex items-center gap-x-2 text-white hover:cursor-pointer hover:text-sky-400 hover:underline">
|
||||
<Key size={18} weight="bold" />
|
||||
<div className="text-sm font-medium">OpenAI Key</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
</>
|
||||
)}
|
||||
<NavLink to={paths.jobs(organization)}>
|
||||
<div className="mt-5 flex items-center gap-x-2 text-white hover:cursor-pointer hover:text-sky-400 hover:underline">
|
||||
<SpinnerGap size={18} weight="bold" />
|
||||
<div className="text-sm font-medium">Background Jobs</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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,65 +41,49 @@ 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 (
|
||||
<div className="col-span-12 rounded-md border border-stroke bg-white p-7.5 shadow-default dark:border-strokedark dark:bg-boxdark">
|
||||
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 xl:grid-cols-4 xl:gap-0">
|
||||
<div className="flex items-center justify-center gap-2 border-b border-stroke pb-5 dark:border-strokedark xl:border-b-0 xl:border-r xl:pb-0">
|
||||
{documents.status === 'loading' ? (
|
||||
<PreLoader />
|
||||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<h4 className="mb-0.5 text-xl font-bold text-black dark:text-white md:text-title-lg">
|
||||
{nFormatter(documents.value)}
|
||||
</h4>
|
||||
<p className="text-sm font-medium">
|
||||
{pluralize('Document', documents.value)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="-mt-6 flex w-full items-center pr-7">
|
||||
<div className=" ml-4 flex items-center gap-x-6">
|
||||
<div className="flex items-center gap-x-1">
|
||||
<span className="font-['Plus Jakarta Sans'] text-sm font-bold uppercase leading-[18px] tracking-wide text-white">
|
||||
Documents
|
||||
</span>
|
||||
<span className="font-['JetBrains Mono'] text-sm font-bold uppercase leading-[18px] tracking-wide text-white">
|
||||
{' '}
|
||||
</span>
|
||||
<span className="font-['JetBrains Mono'] text-sm font-extrabold uppercase leading-[18px] tracking-wide text-white">
|
||||
({nFormatter(documents.value)})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center gap-2 border-b border-stroke pb-5 dark:border-strokedark xl:border-b-0 xl:border-r xl:pb-0">
|
||||
{vectors.status === 'loading' ? (
|
||||
<PreLoader />
|
||||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<h4 className="mb-0.5 text-xl font-bold text-black dark:text-white md:text-title-lg">
|
||||
{nFormatter(vectors.value)}
|
||||
</h4>
|
||||
<p className="text-sm font-medium">
|
||||
{pluralize('Vector', vectors.value)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center gap-2 border-b border-stroke pb-5 dark:border-strokedark sm:border-b-0 sm:pb-0 xl:border-r">
|
||||
{cache.status === 'loading' ? (
|
||||
<PreLoader />
|
||||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<h4 className="mb-0.5 text-xl font-bold text-black dark:text-white md:text-title-lg">
|
||||
{humanFileSize(cache.value)}
|
||||
</h4>
|
||||
<p className="text-sm font-medium">Vector Cache (MB)</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="flex flex-col items-center">
|
||||
<h4 className="mb-0.5 text-xl font-bold text-black dark:text-white md:text-title-lg">
|
||||
{organization?.lastUpdated
|
||||
? moment(organization.lastUpdated).fromNow()
|
||||
: moment(organization.createdAt).fromNow()}
|
||||
</h4>
|
||||
<p className="text-sm font-medium">Last Modified</p>
|
||||
</div>
|
||||
<div className="ml-4 mr-48 w-full rounded-xl border-2 border-white/20 px-5 py-2 text-sky-400">
|
||||
<div className="flex items-center justify-between whitespace-nowrap">
|
||||
<span className="font-jetbrains uppercase text-white">
|
||||
{pluralize('Vector', vectors.value)}:{' '}
|
||||
<span className=" font-jetbrainsbold">
|
||||
{nFormatter(vectors.value)}
|
||||
</span>
|
||||
</span>
|
||||
<span className="font-jetbrains uppercase text-white">
|
||||
Vector Cache:{' '}
|
||||
<span className=" font-jetbrainsbold">
|
||||
{humanFileSize(cache.value)}
|
||||
</span>
|
||||
</span>
|
||||
<span className="font-jetbrains uppercase text-white">
|
||||
Dimensions:{' '}
|
||||
<span className=" font-jetbrainsbold">{dimensions.value}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function WorkspacesList({
|
||||
totalWorkspaces?: number;
|
||||
}) {
|
||||
return (
|
||||
<div className="col-span-12 flex-1 rounded-sm border border-stroke bg-white py-6 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4">
|
||||
<div className="col-span-12 max-w-[217px] flex-1 rounded-sm border border-stroke bg-white py-6 shadow-default dark:border-strokedark dark:bg-boxdark xl:col-span-4">
|
||||
<div className=" top-0 z-10 bg-white">
|
||||
<div className="mb-6 flex w-full items-center justify-between px-7.5">
|
||||
<h4 className="text-xl font-semibold text-black dark:text-white">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -169,7 +169,7 @@ function DocumentViewHeader({ organization, workspace, document }: any) {
|
||||
return (
|
||||
<>
|
||||
<div className=" mr-10 w-full rounded-xl border-2 border-white/20 px-5 py-2 text-sky-400">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<div className="flex items-center gap-x-2 text-lg">
|
||||
<a
|
||||
href={paths.organization(organization)}
|
||||
className="text-sky-400 hover:cursor-pointer hover:underline"
|
||||
@@ -188,7 +188,9 @@ function DocumentViewHeader({ organization, workspace, document }: any) {
|
||||
<div className="text-sky-400" style={{ transform: 'rotate(270deg)' }}>
|
||||
<CaretDown weight="bold" />
|
||||
</div>
|
||||
<span className="text-white">{truncate(document?.name, 30)}</span>
|
||||
<span className="text-lg font-medium text-white">
|
||||
{truncate(document?.name, 30)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-x-3">
|
||||
|
||||
@@ -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';
|
||||
@@ -17,7 +16,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,13 +795,13 @@ function WorkspaceViewHeader({
|
||||
logo = WeaviateLogo;
|
||||
break;
|
||||
default:
|
||||
logo = PineconeLogo;
|
||||
logo = PineconeLogoInverted;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" mr-10 w-full rounded-xl border-2 border-white/20 px-5 py-2 text-sky-400">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<div className="flex items-center gap-x-2 text-lg">
|
||||
<a
|
||||
href={paths.organization(organization)}
|
||||
className="text-sky-400 hover:cursor-pointer hover:underline"
|
||||
@@ -811,7 +811,9 @@ function WorkspaceViewHeader({
|
||||
<div className="text-sky-400" style={{ transform: 'rotate(270deg)' }}>
|
||||
<CaretDown weight="bold" />
|
||||
</div>
|
||||
<span className="text-white">{truncate(workspace?.name, 20)}</span>
|
||||
<span className="text-lg font-medium text-white">
|
||||
{truncate(workspace?.name, 20)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-x-3">
|
||||
|
||||
Reference in New Issue
Block a user