Skip to content

Commit

Permalink
🐞 fix(chat):Fix uploadthing api callback
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackishGreen33 committed Dec 9, 2024
1 parent 678418f commit a2c9501
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const DashboardClient: React.FC = () => {
});

const { mutate: deleteFile, isPending: isDeletingFile } =
useDeleteWorkspaceFile();
useDeleteWorkspaceFile({ setCurrentlyDeletingFile });

const [DeleteDialog, confirmDelete] = useConfirm(
'删除文档',
Expand Down
55 changes: 25 additions & 30 deletions src/app/api/uploadthing/core.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// import { PDFLoader } from 'langchain/document_loaders/fs/pdf'
// import { OpenAIEmbeddings } from 'langchain/embeddings/openai'
// import { PineconeStore } from 'langchain/vectorstores/pinecone'
import { ID, Query } from 'node-appwrite';
import { createUploadthing, type FileRouter } from 'uploadthing/next';

import { DATABASE_ID, FILES_ID } from '@/common/configs';
import { getCurrent } from '@/common/libs/actions/auth.actions';
import { createSessionClient } from '@/common/libs/appwrite';
import { type File } from '@/common/types/files';
import { getWorkspaces } from '@/common/libs/actions/workspaces.action';
import client from '@/common/libs/rpc';
// import { PLANS } from '@/config/stripe'
// import { getPineconeClient } from '@/common/libs/pinecone';
// import { getUserSubscriptionPlan } from '@/common/libs/stripe'
Expand All @@ -19,10 +17,12 @@ const middleware = async () => {

if (!user) throw new Error('Unauthorized');

const workspaces = await getWorkspaces();

// const subscriptionPlan = await getUserSubscriptionPlan();

// return { subscriptionPlan, userId: user.$id };
return { userId: user.$id };
return { userId: user.$id, workspaceId: workspaces.documents[0].$id };
};

const onUploadComplete = async ({
Expand All @@ -39,36 +39,29 @@ const onUploadComplete = async ({
console.log('Upload complete for userId:', metadata.userId);
console.log('file url', file.url);

console.log('debug start');

const { databases } = await createSessionClient();

console.log('databases', databases);

const fileList = await databases.listDocuments<File>(DATABASE_ID, FILES_ID, [
Query.equal('key', file.key),
]);

console.log('fileList', fileList);

const isFileExist = fileList.documents[0];
const isFileExist = await client.api.files[':key'].$get({
param: { key: file.key },
});

console.log('isFileExist', isFileExist);

if (isFileExist) return;

const createdFile = await databases.createDocument(
DATABASE_ID,
FILES_ID,
ID.unique(),
{
const res = await client.api.files['$post']({
form: {
key: file.key,
name: file.name,
userId: metadata.userId,
workspaceId: metadata.workspaceId,
url: file.url,
uploadStatus: 'PROCESSING',
}
);
},
});

if (!res.ok) {
throw new Error('Failed to create file');
}

const createdFile = await res.json();

console.log('createdFile', createdFile);

Expand Down Expand Up @@ -109,12 +102,14 @@ const onUploadComplete = async ({
// namespace: createdFile?.id,
// });

await databases.updateDocument(DATABASE_ID, FILES_ID, createdFile.id, {
uploadStatus: 'SUCCESS',
await client.api.files[':fileId']['$patch']({
form: { uploadStatus: 'SUCCESS' },
param: { fileId: createdFile.data.$id },
});
} catch (err) {
await databases.updateDocument(DATABASE_ID, FILES_ID, createdFile.id, {
uploadStatus: 'FAILED',
await client.api.files[':fileId']['$patch']({
form: { uploadStatus: 'FAILED' },
param: { fileId: createdFile.data.$id },
});
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/common/api/files/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as useDeleteWorkspaceFile } from './useDeleteWorkspaceFile';
export { default as useGetUploadStatus } from './useGetUploadStatus';
export { default as useGetWorkspaceFile } from './useGetWorkspaceFile';
export { default as useGetWorkspaceFiles } from './useGetWorkspaceFiles';
export { default as useGetWorkspaceFileWithKey } from './useGetWorkspaceFileWithKey';
10 changes: 9 additions & 1 deletion src/common/api/files/useDeleteWorkspaceFile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { InferRequestType, InferResponseType } from 'hono';
import { Dispatch, SetStateAction } from 'react';
import { toast } from 'sonner';

import client from '@/common/libs/rpc';
Expand All @@ -12,7 +13,11 @@ type RequestType = InferRequestType<
(typeof client.api.files)[':fileId']['$delete']
>;

const useDeleteWorkspaceFile = () => {
const useDeleteWorkspaceFile = ({
setCurrentlyDeletingFile,
}: {
setCurrentlyDeletingFile: Dispatch<SetStateAction<string | null>>;
}) => {
const queryClient = useQueryClient();

const mutation = useMutation<ResponseType, Error, RequestType>({
Expand All @@ -33,6 +38,9 @@ const useDeleteWorkspaceFile = () => {
queryClient.invalidateQueries({ queryKey: ['files'] });
queryClient.invalidateQueries({ queryKey: ['file', data.$id] });
},
onMutate({ param }) {
setCurrentlyDeletingFile(param.fileId);
},
onError: () => {
toast.error('文档删除失败');
},
Expand Down
34 changes: 34 additions & 0 deletions src/common/api/files/useGetUploadStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useQuery } from '@tanstack/react-query';

import client from '@/common/libs/rpc';

interface UseGetUploadStatusProps {
fileId: string;
}

const useGetUploadStatus = ({ fileId }: UseGetUploadStatusProps) => {
const query = useQuery({
queryKey: ['uploadStatus', fileId],
queryFn: async () => {
const response = await client.api.files.uploadStatus[':fileId'].$get({
param: { fileId },
});

if (!response.ok) {
throw new Error('Failed to fetch file');
}

const { data } = await response.json();

return data;
},
refetchInterval: (data) =>
data.state.status === 'success' || data.state.status === 'error'
? false
: 500,
});

return query;
};

export default useGetUploadStatus;
32 changes: 0 additions & 32 deletions src/common/api/files/useGetWorkspaceFileWithKey.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/common/components/chat/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ const ChatInput: React.FC<ChatInputProps> = ({ isDisabled }) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();

// addMessage();

textareaRef.current?.focus();
}
}}
Expand All @@ -45,7 +43,6 @@ const ChatInput: React.FC<ChatInputProps> = ({ isDisabled }) => {
className="absolute bottom-1.5 right-[8px]"
aria-label="send message"
onClick={() => {
// addMessage();
textareaRef.current?.focus();
}}
>
Expand Down
141 changes: 69 additions & 72 deletions src/common/components/chat/ChatWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
'use client';

import { ChevronLeft, Loader2, XCircle } from 'lucide-react';
import Link from 'next/link';

import { useGetUploadStatus } from '@/common/api/files';

import ChatInput from './ChatInput';
import { buttonVariants } from '../ui/button';

// import { PLANS } from '@/config/stripe'
// import { ChatContextProvider } from './ChatContext'
// import Messages from './Messages'
Expand All @@ -10,88 +18,77 @@ interface ChatWrapperProps {
}

const ChatWrapper: React.FC<ChatWrapperProps> = ({ fileId }) => {
// const { data, isLoading } = trpc.getFileUploadStatus.useQuery(
// {
// fileId,
// },
// {
// refetchInterval: (data) =>
// data?.status === 'SUCCESS' || data?.status === 'FAILED' ? false : 500,
// }
// );

// if (isLoading)
// return (
// <div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
// <div className="mb-28 flex flex-1 flex-col items-center justify-center">
// <div className="flex flex-col items-center gap-2">
// <Loader2 className="h-8 w-8 animate-spin text-blue-500" />
// <h3 className="text-xl font-semibold">载入中...</h3>
// <p className="text-sm text-zinc-500">
// 我们正在准备您的文档
// </p>
// </div>
// </div>
// <ChatInput isDisabled />
// </div>
// );
const { data: status, isLoading } = useGetUploadStatus({ fileId });

// if (data?.status === 'PROCESSING')
// return (
// <div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
// <div className="mb-28 flex flex-1 flex-col items-center justify-center">
// <div className="flex flex-col items-center gap-2">
// <Loader2 className="h-8 w-8 animate-spin text-blue-500" />
// <h3 className="text-xl font-semibold">处里 PDF...</h3>
// <p className="text-sm text-zinc-500">这不会花很长时间。</p>
// </div>
// </div>
// <ChatInput isDisabled />
// </div>
// );
if (isLoading)
return (
<div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
<div className="mb-28 flex flex-1 flex-col items-center justify-center">
<div className="flex flex-col items-center gap-2">
<Loader2 className="h-8 w-8 animate-spin text-blue-500" />
<h3 className="text-xl font-semibold">载入中...</h3>
<p className="text-sm text-zinc-500">我们正在准备您的文档</p>
</div>
</div>
<ChatInput isDisabled />
</div>
);

// if (data?.status === 'FAILED')
// return (
// <div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
// <div className="mb-28 flex flex-1 flex-col items-center justify-center">
// <div className="flex flex-col items-center gap-2">
// <XCircle className="h-8 w-8 text-red-500" />
// <h3 className="text-xl font-semibold">Too many pages in PDF</h3>
// <p className="text-sm text-zinc-500">
// Your{' '}
// <span className="font-medium">
// {isSubscribed ? 'Pro' : 'Free'}
// </span>{' '}
// plan supports up to{' '}
// {isSubscribed
// ? PLANS.find((p) => p.name === 'Pro')?.pagesPerPdf
// : PLANS.find((p) => p.name === 'Free')?.pagesPerPdf}{' '}
// pages per PDF.
// </p>
// <Link
// href="/dashboard"
// className={buttonVariants({
// variant: 'secondary',
// className: 'mt-4',
// })}
// >
// <ChevronLeft className="mr-1.5 h-3 w-3" />
// 返回
// </Link>
// </div>
// </div>
if (status === 'PROCESSING')
return (
<div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
<div className="mb-28 flex flex-1 flex-col items-center justify-center">
<div className="flex flex-col items-center gap-2">
<Loader2 className="h-8 w-8 animate-spin text-blue-500" />
<h3 className="text-xl font-semibold">处里 PDF...</h3>
<p className="text-sm text-zinc-500">这不会花很长时间。</p>
</div>
</div>
<ChatInput isDisabled />
</div>
);

// <ChatInput isDisabled />
// </div>
// );
if (status === 'FAILED')
return (
<div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
<div className="mb-28 flex flex-1 flex-col items-center justify-center">
<div className="flex flex-col items-center gap-2">
<XCircle className="h-8 w-8 text-red-500" />
<h3 className="text-xl font-semibold">Too many pages in PDF</h3>
<p className="text-sm text-zinc-500">
Your{' '}
<span className="font-medium">
{/* {isSubscribed ? 'Pro' : 'Free'} */}
</span>{' '}
plan supports up to{' '}
{/* {isSubscribed
? PLANS.find((p) => p.name === 'Pro')?.pagesPerPdf
: PLANS.find((p) => p.name === 'Free')?.pagesPerPdf}{' '} */}
pages per PDF.
</p>
<Link
href="/dashboard"
className={buttonVariants({
variant: 'secondary',
className: 'mt-4',
})}
>
<ChevronLeft className="mr-1.5 h-3 w-3" />
返回
</Link>
</div>
</div>
<ChatInput isDisabled />
</div>
);

return (
// <ChatContextProvider fileId={fileId}>
<div className="relative flex min-h-full flex-col justify-between gap-2 divide-y divide-zinc-200 bg-zinc-50">
<div className="mb-28 flex flex-1 flex-col justify-between">
{/* <Messages fileId={fileId} /> */}
</div>
{/* <ChatInput /> */}
<ChatInput />
</div>
// </ChatContextProvider>
);
Expand Down
Loading

0 comments on commit a2c9501

Please sign in to comment.