Skip to content

Commit

Permalink
✨🚧Supported deleteProject
Browse files Browse the repository at this point in the history
  • Loading branch information
carefree0910 committed Apr 29, 2023
1 parent d9ae4f4 commit 56edbe5
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 10 deletions.
4 changes: 4 additions & 0 deletions cfdraw/.web/src/actions/manageProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,7 @@ export function getAutoSaveProject(): Promise<IProject> {
return saveProject(autoSaveProject, async () => void 0, true).then(() => autoSaveProject);
});
}

export function deleteProject(uid: string): Promise<void> {
return Requests.delete("_python", `/projects/?userId=${userStore.userId}&uid=${uid}`);
}
7 changes: 7 additions & 0 deletions cfdraw/.web/src/assets/icons/delete.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions cfdraw/.web/src/lang/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ export enum Toast_Words {
"loading-project-message" = "loading-project-message",
"load-project-success-message" = "load-project-success-message",
"please-select-project-message" = "please-select-project-message",
"please-select-project-to-delete-message" = "please-select-project-to-delete-message",
"already-selected-project-message" = "already-selected-project-message",
"cannot-delete-auto-save-project-message" = "cannot-delete-auto-save-project-message",
"downloading-project-message" = "downloading-project-message",
"importing-local-project-message" = "importing-local-project-message",
"import-local-project-success-message" = "import-local-project-success-message",
"import-local-project-error-message" = "import-local-project-error-message",
"delete-project-success-message" = "delete-project-success-message",
"add-text-success-message" = "add-text-success-message",
"add-text-error-message" = "add-text-error-message",
"auto-arrange-no-need-message" = "auto-arrange-no-need-message",
Expand Down Expand Up @@ -53,11 +56,14 @@ export const toastLangRecords: Record<Lang, Record<Toast_Words, string>> = {
[Toast_Words["loading-project-message"]]: "加载项目中,请稍候",
[Toast_Words["load-project-success-message"]]: "加载项目成功",
[Toast_Words["please-select-project-message"]]: "请先选择想要加载的项目",
[Toast_Words["please-select-project-to-delete-message"]]: "请先选择想要删除的项目",
[Toast_Words["already-selected-project-message"]]: "要加载的项目是当前的项目,无需重复加载",
[Toast_Words["cannot-delete-auto-save-project-message"]]: "不能删除「自动保存」项目",
[Toast_Words["downloading-project-message"]]: "下载项目中",
[Toast_Words["importing-local-project-message"]]: "导入中",
[Toast_Words["import-local-project-success-message"]]: "导入成功",
[Toast_Words["import-local-project-error-message"]]: "导入失败",
[Toast_Words["delete-project-success-message"]]: "删除项目成功",
[Toast_Words["add-text-success-message"]]: "添加文字成功",
[Toast_Words["add-text-error-message"]]: "添加文字时出了些问题",
[Toast_Words["auto-arrange-no-need-message"]]: "当前节点无需整理",
Expand Down Expand Up @@ -87,12 +93,15 @@ export const toastLangRecords: Record<Lang, Record<Toast_Words, string>> = {
[Toast_Words["loading-project-message"]]: "Loading",
[Toast_Words["load-project-success-message"]]: "Project loaded successfully!",
[Toast_Words["please-select-project-message"]]: "Please select a project first",
[Toast_Words["please-select-project-to-delete-message"]]: "Please select a project to delete",
[Toast_Words["already-selected-project-message"]]:
"The project you want to load is the current project, no need to load again",
[Toast_Words["cannot-delete-auto-save-project-message"]]: "Cannot delete 'Auto Save' project",
[Toast_Words["downloading-project-message"]]: "Downloading",
[Toast_Words["importing-local-project-message"]]: "Importing",
[Toast_Words["import-local-project-success-message"]]: "Imported successfully!",
[Toast_Words["import-local-project-error-message"]]: "Import failed",
[Toast_Words["delete-project-success-message"]]: "Project deleted successfully!",
[Toast_Words["add-text-success-message"]]: "Text added successfully",
[Toast_Words["add-text-error-message"]]: "Something is wrong when adding Text Node",
[Toast_Words["auto-arrange-no-need-message"]]: "There is no need to arrange the Nodes",
Expand Down
42 changes: 34 additions & 8 deletions cfdraw/.web/src/plugins/_react/ProjectPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { v4 as uuidv4 } from "uuid";
import Upload from "rc-upload";
import { observer } from "mobx-react-lite";
import { useMemo, useState, useEffect, useCallback } from "react";
import { Flex } from "@chakra-ui/react";
import { Box, Flex, Image } from "@chakra-ui/react";

import { Dictionary, Graph, INodePack, getRandomHash, shallowCopy } from "@carefree0910/core";
import { langStore, translate, useSafeExecute } from "@carefree0910/business";

import type { IPlugin } from "@/schema/plugins";
import DeleteIcon from "@/assets/icons/delete.svg";
import { toastWord } from "@/utils/toast";
import { Toast_Words } from "@/lang/toast";
import { Projects_Words } from "@/lang/projects";
Expand All @@ -22,6 +23,7 @@ import {
import {
AUTO_SAVE_PREFIX,
IProject,
deleteProject,
fetchAllProjectItems,
getProject,
loadProject,
Expand Down Expand Up @@ -51,8 +53,12 @@ const ProjectPlugin = ({ pluginInfo, ...props }: IPlugin) => {
const [userInputName, setUserInputName] = useState(name);
const [allUid2Name, setAllUid2Name] = useState<Dictionary<string> | undefined>();
const allProjectUids = useMemo(() => Object.keys(allUid2Name ?? {}), [allUid2Name]);
const isSelectingAutoSave = useMemo(
() => selectedUid.startsWith(AUTO_SAVE_PREFIX),
[selectedUid],
);
const getLoadUid = useCallback(() => {
if (!selectedUid.startsWith(AUTO_SAVE_PREFIX)) return Promise.resolve(selectedUid);
if (!isSelectingAutoSave) return Promise.resolve(selectedUid);
// should create a new project when loading auto save project
return getProject(selectedUid).then((autoSaveProject) => {
const newProject = shallowCopy(autoSaveProject);
Expand Down Expand Up @@ -154,6 +160,20 @@ const ProjectPlugin = ({ pluginInfo, ...props }: IPlugin) => {
failed: async () => toastWord("error", Toast_Words["import-local-project-error-message"]),
})({ json });
}
function onDeleteProject() {
if (!selectedUid) {
toastWord("warning", Toast_Words["please-select-project-to-delete-message"]);
return;
}
if (isSelectingAutoSave) {
toastWord("warning", Toast_Words["cannot-delete-auto-save-project-message"]);
return;
}
deleteProject(selectedUid).then(() => {
toastWord("success", Toast_Words["delete-project-success-message"]);
updateUids();
});
}

return (
<Render id={id} {...props}>
Expand All @@ -167,12 +187,18 @@ const ProjectPlugin = ({ pluginInfo, ...props }: IPlugin) => {
<CFDivider />
{allUid2Name ? (
allProjectUids.length > 0 ? (
<CFSrollableSelect
value={selectedUid}
options={allProjectUids}
onOptionClick={(uid) => setSelectedUid(uid)}
optionConverter={(uid) => allUid2Name[uid]}
/>
<Flex w="100%">
<CFSrollableSelect
flex={1}
value={selectedUid}
options={allProjectUids}
onOptionClick={(uid) => setSelectedUid(uid)}
optionConverter={(uid) => allUid2Name[uid]}
/>
<Box as="button" w="32px" h="100%" p="4px" mx="4px" onClick={onDeleteProject}>
<Image src={DeleteIcon} />
</Box>
</Flex>
) : (
<CFText>{translate(Projects_Words["no-projects-available"], lang)}</CFText>
)
Expand Down
4 changes: 4 additions & 0 deletions cfdraw/.web/src/requests/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ export class Requests {
.postForm(endpoint, formData)
.then((res) => res.data);
}

static delete<T extends APISources = APISources>(source: T, endpoint: string): Promise<void> {
return useAPI(source).delete(endpoint);
}
}
25 changes: 23 additions & 2 deletions cfdraw/app/endpoints/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def save_project(data: ProjectModel) -> SaveProjectResponse:
return SaveProjectResponse(success=False, message=err_msg)
return SaveProjectResponse(success=True, message="")

@app.api.get(f"/get_project/", responses=get_responses(ProjectModel))
@app.api.get("/get_project/", responses=get_responses(ProjectModel))
async def fetch_project(userId: str, uid: str) -> ProjectModel: # type: ignore
try:
upload_project_folder = app.config.upload_project_folder / userId
Expand All @@ -137,7 +137,7 @@ async def fetch_project(userId: str, uid: str) -> ProjectModel: # type: ignore
except Exception as err:
raise_err(err)

@app.api.get(f"/all_projects/")
@app.api.get("/all_projects/")
async def fetch_all_projects(userId: str) -> List[ProjectMeta]:
upload_project_folder = app.config.upload_project_folder / userId
if not upload_project_folder.exists():
Expand All @@ -150,6 +150,27 @@ async def fetch_all_projects(userId: str) -> List[ProjectMeta]:
s = sorted([(v["updateTime"], k) for k, v in meta.items()], reverse=True)
return [ProjectMeta(**meta[k]) for _, k in s]

@app.api.delete("/projects/")
async def delete_project(userId: str, uid: str) -> None:
upload_project_folder = app.config.upload_project_folder / userId
if not upload_project_folder.exists():
return
file = f"{uid}{suffix}"
path = upload_project_folder / file
if path.is_file():
path.unlink()
# maintain meta
meta_path = upload_project_folder / constants.PROJECT_META_FILE
if not meta_path.is_file():
maintain_meta(app, userId)
else:
with open(meta_path, "r") as f:
meta = json.load(f)
if uid in meta:
meta.pop(uid)
with open(meta_path, "w") as f:
json.dump(meta, f)


class ProjectEndpoint(IEndpoint):
def register(self) -> None:
Expand Down

0 comments on commit 56edbe5

Please sign in to comment.