working organization dashboard table, WIP quick actions & workspaces sidebar

This commit is contained in:
shatfield4
2023-12-18 17:39:13 -08:00
parent 5dd88adb77
commit db50cb436f
3 changed files with 256 additions and 35 deletions
@@ -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 (
<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-grow overflow-y-auto rounded-xl border-2 border-white/20 bg-main">
<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 ? (
@@ -128,16 +129,41 @@ export default function DocumentsList({
<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>
<span className="font-medium">Date</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>
<span className="font-medium">Vectors</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?.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>
)}
<>
{documents.map((document) => {
return (
@@ -216,17 +242,212 @@ export default function DocumentsList({
</div>
</div>
)}
</div> */}
<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>
{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
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"
>
<div className="text-center text-sm font-bold leading-tight text-zinc-900">
Create Workspace
</div>
</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>
<div className="pt-20">
<DocumentListPagination
pageCount={Math.ceil(
totalDocuments! / Organization.documentPageSize
)}
currentPage={currentPage}
gotoPage={updatePage}
/>
</div>
{canUpload ? (
<UploadDocumentModal workspaces={workspaces} />
) : (
<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>
</>
);
};
@@ -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">
+4 -4
View File
@@ -135,8 +135,8 @@ export default function Dashboard() {
</div>
)}
<Statistics organization={organization} />
<div className="mt-4 grid grid-cols-12 gap-4 md:mt-6 md:gap-6 2xl:mt-7.5 2xl:gap-7.5">
<div className="col-span-12 xl:col-span-8">
<div className="mt-4 flex w-full">
<div className="mr-6.5 w-full">
<DocumentsList
knownConnector={connector}
organization={organization}
@@ -229,10 +229,10 @@ const UpdateConnectorModal = ({
onUpdate: (newConnector: any) => void;
}) => {
const [loading, setLoading] = useState(false);
const [type, setType] = useState(connector.type);
const [type, setType] = useState(connector?.type);
const [error, setError] = useState<null | string>(null);
const [success, setSuccess] = useState<null | boolean>(false);
const settings = JSON.parse(connector.settings);
const settings = JSON.parse(connector?.settings);
const handleSubmit = async (e: any) => {
e.preventDefault();