Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #28 from AIerLab/study-abroad-planning
Browse files Browse the repository at this point in the history
Study abroad planning
  • Loading branch information
Weidows authored Dec 11, 2023
2 parents 538a900 + a3c461c commit dfe6307
Show file tree
Hide file tree
Showing 9 changed files with 462 additions and 189 deletions.
Binary file added react-app/src/api/db/prisma/dev.db-journal
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
Warnings:
- You are about to drop the column `filePath` on the `ReviewStorage` table. All the data in the column will be lost.
- You are about to drop the column `filename` on the `ReviewStorage` table. All the data in the column will be lost.
- You are about to drop the column `filesize` on the `ReviewStorage` table. All the data in the column will be lost.
- You are about to drop the column `filetype` on the `ReviewStorage` table. All the data in the column will be lost.
- You are about to drop the column `hash` on the `ReviewStorage` table. All the data in the column will be lost.
- Added the required column `fileStorageHash` to the `ReviewStorage` table without a default value. This is not possible if the table is not empty.
*/
-- CreateTable
CREATE TABLE "FileStorage" (
"hash" TEXT NOT NULL PRIMARY KEY,
"file" BLOB NOT NULL,
"filePath" TEXT,
"filename" TEXT,
"filesize" INTEGER,
"filetype" TEXT
);

-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_ReviewStorage" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"profile_id" TEXT NOT NULL DEFAULT '',
"RequestMessage" TEXT,
"RequestUser" TEXT NOT NULL,
"mentioned" TEXT NOT NULL DEFAULT '',
"deleted" BOOLEAN NOT NULL DEFAULT false,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"fileStorageHash" TEXT NOT NULL,
CONSTRAINT "ReviewStorage_fileStorageHash_fkey" FOREIGN KEY ("fileStorageHash") REFERENCES "FileStorage" ("hash") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_ReviewStorage" ("RequestMessage", "RequestUser", "createdAt", "deleted", "id", "mentioned", "profile_id", "updatedAt") SELECT "RequestMessage", "RequestUser", "createdAt", "deleted", "id", "mentioned", "profile_id", "updatedAt" FROM "ReviewStorage";
DROP TABLE "ReviewStorage";
ALTER TABLE "new_ReviewStorage" RENAME TO "ReviewStorage";
CREATE UNIQUE INDEX "ReviewStorage_id_key" ON "ReviewStorage"("id");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

-- CreateIndex
CREATE UNIQUE INDEX "FileStorage_hash_key" ON "FileStorage"("hash");
61 changes: 61 additions & 0 deletions react-app/src/api/db/review.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// import {
// ReviewStorage,
// createReviewStorage,
// getReviewStorage,
// updateReviewStorage,
// deleteReviewStorage,
// } from "./review";

// describe("Prisma CRUD", () => {
// let testReview: ReviewStorage = {
// id: 1,
// profile_id: "media",
// RequestUser: "18330785221",
// mentioned: "18330785221",
// filename: "Test Filename",
// filesize: 100,
// filetype: "Test Type",
// };

// it("creates a review", async () => {
// const review = await createReviewStorage(testReview);

// expect(review.id).toBeDefined();
// });

// it("gets the created review", async () => {
// const review = await getReviewStorage(testReview.id);

// if (review) {
// expect(review.profile_id).toBe("media");
// } else {
// fail("Review is null");
// }
// });

// it("updates the review", async () => {
// await updateReviewStorage(testReview.id, {
// ...testReview,
// profile_id: "",
// // 如果你更新了其他属性,也需要在这里添加
// });

// const review = await getReviewStorage(testReview.id);
// if (review) {
// expect(review.profile_id).toBe("Updated Profile");
// } else {
// fail("Review is null");
// }
// });

// it("deletes the review", async () => {
// await deleteReviewStorage(testReview.id);

// try {
// await getReviewStorage(testReview.id);
// fail("Review was not deleted");
// } catch (error) {
// // Review was deleted
// }
// });
// });
15 changes: 11 additions & 4 deletions react-app/src/api/db/review.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FileCardProps } from "@/components/FileCard";
import prisma from "../prisma";
import { FileLocalStorage } from "./file/storage";

interface ReviewStorage {
id?: number;
Expand All @@ -19,10 +21,15 @@ interface ReviewStorage {
updatedAt?: Date;
}

// ReviewStorage CRUD
async function createReviewStorage(data: ReviewStorage) {
async function createReviewStorage(
payload: FormData,
fileProps: FileCardProps
) {
FileLocalStorage(payload,fileProps);
return await prisma.reviewStorage.create({
data: data,
data: {
profile_id: "",
},
});
}

Expand Down Expand Up @@ -62,7 +69,7 @@ async function deleteReviewStorage(id: number) {

export {
ReviewStorage as ReviewStorage,
createReviewStorage,
// createReviewStorage,
getReviewStorages,
getReviewStoragesDesc,
getReviewStorage,
Expand Down
69 changes: 57 additions & 12 deletions react-app/src/api/review.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,70 @@
import axios, { AxiosProgressEvent, AxiosRequestConfig } from 'axios'
import axios, { AxiosProgressEvent, AxiosRequestConfig } from "axios";

const API_ENDPOINT = "http://aidvisor.valmech.net:5000";
// const API_ENDPOINT = "http://localhost:8000";
const API_ENDPOINT = "http://aidvisor.valmech.net";
const api = axios.create({
baseURL: API_ENDPOINT,
headers: {
'X-API-Key': 'secret_api_key',
}
})
"X-API-Key": "secret_api_key",
},
});

export const GetOpenAIConnectionTest = async () => {
return await api.post("/api/test/conn/");
};

export interface GetFileReviewResponse {
data: string
data: string;
}

export const GetFileReview = async (payload: FormData, onProgressUpdate: (p: AxiosProgressEvent) => void) => {
export const GetFileReview = async (
payload: FormData,
onProgressUpdate: (p: AxiosProgressEvent) => void
) => {
const config: AxiosRequestConfig = {
onUploadProgress: onProgressUpdate
}
onUploadProgress: onProgressUpdate,
};
// return await api.post('/api/file/review', payload, config)
return await api.post('/api/file/rating', payload, config)
return await api.post("/api/tabs/reports-review/", payload, config);
};

interface GetStudyAboardPlanningResponse {
data: {
冲刺院校1: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
冲刺院校2: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
适中院校1: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
适中院校2: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
保底院校1: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
保底院校2: {
学校名称: string;
推荐专业: string;
推荐原因: string;
};
};
}

export const GetOpenAIConnectionTest = async () => {
return await api.post("/api/conn/test");
export const GetStudyAboardPlanning = async (
payload: FormData
): Promise<GetStudyAboardPlanningResponse> => {
return await api.post("/api/tabs/study-aboard-planning/", payload);
};
87 changes: 62 additions & 25 deletions react-app/src/components/FileCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,32 @@ import styles from "./index.module.css";
import { humanizeFileSize } from "utils/humanize";

import Tooltip from "components/Tooltip/index";
import { TableCellsIcon } from "@heroicons/react/24/solid";

// TODO: how to download? by open a link in browser
// or as background job?

export type ValidFileType = ".txt" | ".pdf" | ".doc" | ".docx" | ".md";
export function GetValidFileTypeList() {
return [".txt", ".pdf", ".doc", ".docx", ".md"];
export enum ValidFileTypeEnum {
TXT = ".txt",
PDF = ".pdf",
DOC = ".doc",
DOCX = ".docx",
MD = ".md",
XLS = ".xls",
}
export function IsValidFileType(ext: string) {
if (!ext) return false;
ext = ext.toLowerCase();
return GetValidFileTypeList().includes(ext);
export type ValidFileType = keyof ValidFileTypeEnum;

export enum TabIDsEnum {
ReportsReview = "reports-review",
StudyAbroadPlanning = "study-abroad-planning",
}

export interface FileCardCommonProps {
type: "review";
tab: TabIDsEnum;

className?: string;

filetype: ValidFileType;
filetype: ValidFileTypeEnum;
filesize: number;
filename: string;
uploadProgress: number; // percentage, i.e. 0 - 1
Expand All @@ -51,8 +57,6 @@ export interface FileCardNotDoneProps {
}

export interface FileCardReviewProps {
type: "review";

done: true;
overview: string;
grade: number;
Expand All @@ -77,8 +81,7 @@ export function FileCard(props: FileCardProps) {
<div className={s("file-info-wrap")}>
<span className={s("file-name")}> {props.filename} </span>
<span className={s("file-size")}>
{" "}
{humanizeFileSize(props.filesize)}{" "}
{humanizeFileSize(props.filesize)}
</span>
</div>
</div>
Expand Down Expand Up @@ -145,13 +148,13 @@ export function FileCard(props: FileCardProps) {
</div>
{props.done && (
<div className={s("card vertical shadow")}>
{props.type === "review" && (
{props.tab && (
<div className="w-full">
<h2> 审核概述 </h2>
<h2> 处理结果 </h2>
<DashedSparator className={s("my-4")} />
<p className={s("overview")}>{props.overview}</p>
<DashedSparator className={s("my-4")} />
<div className={s("card horizontal bordered")}>
{/* <div className={s("card horizontal bordered")}>
<div className="flex flex-row space-x-4 items-center flex-1 w-0">
<DocumentIcon type={props.filetype} />
<div className={s("file-info-wrap")}>
Expand All @@ -160,12 +163,10 @@ export function FileCard(props: FileCardProps) {
"file-name text-indigo-500 dark:text-indigo-300"
)}
>
{" "}
{props.filename}{" "}
{props.filename}
</span>
<span className={s("file-size")}>
{" "}
{humanizeFileSize(props.filesize)}{" "}
{humanizeFileSize(props.filesize)}
</span>
</div>
</div>
Expand All @@ -177,10 +178,10 @@ export function FileCard(props: FileCardProps) {
mentioned={props.mentioned}
mentionables={props.mentionables}
onCopyOverview={handleOverviewCopy}
/>
/> */}
</div>
)}
{props.type === "review" && (
{props.tab === TabIDsEnum.ReportsReview && (
<div className="w-full">
<h2> 评分结果 </h2>
<span className={s("grade")}>{props.grade}</span>
Expand Down Expand Up @@ -286,15 +287,16 @@ export function DocumentIcon({
type,
classNames,
}: {
type: ValidFileType;
type: ValidFileTypeEnum;
classNames?: string;
}) {
const mappings: Record<ValidFileType, ReactElement> = {
const mappings: Record<ValidFileTypeEnum, ReactElement> = {
".txt": <TxtIcon className={classNames} />,
".pdf": <PdfIcon className={classNames} />,
".doc": <DocIcon className={classNames} />,
".docx": <DocIcon className={classNames} />,
".md": <DocIcon className={classNames} />,
".md": <TxtIcon className={classNames} />,
".xls": <ExcelIcon className={classNames} />,
};

return mappings[type];
Expand Down Expand Up @@ -386,3 +388,38 @@ const DocIcon = forwardRef<SVGSVGElement, React.HTMLProps<SVGSVGElement>>(
);
}
);

const ExcelIcon = forwardRef<SVGSVGElement, React.HTMLProps<SVGSVGElement>>(
(props, ref) => {
return (
<svg
ref={ref}
{...props}
width="40"
height="40"
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"

// stroke-width="1.5"
// stroke="currentColor"
// class="w-6 h-6"
>
{/* <path
d="M5 6C5 3.79086 6.79086 2 9 2H27C31.4183 2 35 5.58172 35 10V34C35 36.2091 33.2091 38 31 38H9C6.79086 38 5 36.2091 5 34V6Z"
fill="#9CCC65"
/>
<path
d="M26.5 3.5C30.366 3.5 33.5 6.63401 33.5 10.5H26.5V3.5Z"
fill="white"
/> */}
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3.375 19.5h17.25m-17.25 0a1.125 1.125 0 01-1.125-1.125M3.375 19.5h7.5c.621 0 1.125-.504 1.125-1.125m-9.75 0V5.625m0 12.75v-1.5c0-.621.504-1.125 1.125-1.125m18.375 2.625V5.625m0 12.75c0 .621-.504 1.125-1.125 1.125m1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125m0 3.75h-7.5A1.125 1.125 0 0112 18.375m9.75-12.75c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125m19.5 0v1.5c0 .621-.504 1.125-1.125 1.125M2.25 5.625v1.5c0 .621.504 1.125 1.125 1.125m0 0h17.25m-17.25 0h7.5c.621 0 1.125.504 1.125 1.125M3.375 8.25c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125m17.25-3.75h-7.5c-.621 0-1.125.504-1.125 1.125m8.625-1.125c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125M12 10.875v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 10.875c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125M13.125 12h7.5m-7.5 0c-.621 0-1.125.504-1.125 1.125M20.625 12c.621 0 1.125.504 1.125 1.125v1.5c0 .621-.504 1.125-1.125 1.125m-17.25 0h7.5M12 14.625v-1.5m0 1.5c0 .621-.504 1.125-1.125 1.125M12 14.625c0 .621.504 1.125 1.125 1.125m-2.25 0c.621 0 1.125.504 1.125 1.125m0 1.5v-1.5m0 0c0-.621.504-1.125 1.125-1.125m0 0h7.5"
fill="#9ECC65"
/>
</svg>
);
}
);
Loading

0 comments on commit dfe6307

Please sign in to comment.