Skip to content

Commit

Permalink
update: api and adding logics to ui
Browse files Browse the repository at this point in the history
  • Loading branch information
m-abe-dev committed Sep 25, 2024
1 parent 9ea2d09 commit 4a94b2a
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PopupMenuItem } from "@reearth/beta/lib/reearth-ui";
import useDoubleClick from "@reearth/beta/utils/use-double-click";
import { useStorytellingFetcher } from "@reearth/services/api";
import {
useStorytellingFetcher,
useProjectFetcher
} from "@reearth/services/api";
import { useT } from "@reearth/services/i18n";
import { MouseEvent, useCallback, useEffect, useMemo, useState } from "react";

Expand All @@ -22,6 +25,7 @@ export default ({
}: Props) => {
const t = useT();
const { useStoriesQuery } = useStorytellingFetcher();
const { useExportProject } = useProjectFetcher();
const { stories } = useStoriesQuery({ sceneId: project?.sceneId });

const [isEditing, setIsEditing] = useState(false);
Expand Down Expand Up @@ -49,6 +53,18 @@ export default ({
onProjectSelect?.(undefined);
}, [onProjectSelect, project.id, selectedProjectId]);

const handleExportProject = useCallback(async () => {
if (!project.id) return;

const result = await useExportProject(project.id);

if (result.status === "success") {
console.log("export success");
} else {
console.error("Failed to export project:", result.status);
}
}, [useExportProject, project.id]);

useEffect(() => {
setIsStarred(project.starred);
}, [project.starred]);
Expand All @@ -69,7 +85,8 @@ export default ({
{
id: "export",
title: t("Export"),
icon: "downloadSimple"
icon: "downloadSimple",
onClick: () => handleExportProject()
}
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export default (workspaceId?: string) => {
useProjectsQuery,
useUpdateProject,
useCreateProject,
useStarredProjectsQuery
useStarredProjectsQuery,
useImportProject
} = useProjectFetcher();
const navigate = useNavigate();

Expand Down Expand Up @@ -236,6 +237,21 @@ export default (workspaceId?: string) => {
};
}, []);

const handleImportProject = useCallback(
async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
const result = await useImportProject(file);
if (result.status === "success") {
console.log(result.data);
} else {
console.error("Failed to import project:", result.status);
}
}
},
[useImportProject]
);

return {
filtedProjects,
hasMoreProjects,
Expand All @@ -259,7 +275,8 @@ export default (workspaceId?: string) => {
handleScrollToBottom: onScrollToBottom,
handleLayoutChange,
handleProjectSortChange,
handleSearch
handleSearch,
handleImportProject
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import ManagerEmptyContent from "@reearth/beta/ui/components/ManagerBase/ManagerEmptyContent";
import { useT } from "@reearth/services/i18n";
import { styled, useTheme } from "@reearth/services/theme";
import { FC, useMemo } from "react";
import { FC, useMemo, useRef } from "react";

import useHooks from "./hooks";
import ProjectGridViewItem from "./Project/ProjectGridViewItem";
Expand Down Expand Up @@ -39,7 +39,8 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
handleScrollToBottom,
handleLayoutChange,
handleProjectSortChange,
handleSearch
handleSearch,
handleImportProject
} = useHooks(workspaceId);

const theme = useTheme();
Expand All @@ -55,6 +56,8 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
[t]
);

const fileInputRef = useRef<HTMLInputElement>(null);

return (
<ManagerWrapper onClick={() => handleProjectSelect(undefined)}>
<ManagerHeader
Expand All @@ -75,6 +78,13 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
managerSize="large"
icon="signIn"
appearance="secondary"
onClick={() => fileInputRef.current?.click()}
/>
<HiddenFileInput
type="file"
accept=".json"
ref={fileInputRef}
onChange={handleImportProject}
/>
</>
]}
Expand Down Expand Up @@ -296,3 +306,7 @@ const LoadingWrapper = styled("div")(() => ({
width: "100%",
height: 100
}));

const HiddenFileInput = styled("input")({
display: "none"
});
78 changes: 76 additions & 2 deletions web/src/services/api/projectApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import {
PUBLISH_PROJECT,
UPDATE_PROJECT,
UPDATE_PROJECT_ALIAS,
UPDATE_PROJECT_BASIC_AUTH
UPDATE_PROJECT_BASIC_AUTH,
EXPORT_PROJECT,
IMPORT_PROJECT
} from "@reearth/services/gql/queries/project";
import { CREATE_SCENE } from "@reearth/services/gql/queries/scene";
import { useT } from "@reearth/services/i18n";
Expand Down Expand Up @@ -387,6 +389,76 @@ export default () => {
[updateProjectAliasMutation, t, setNotification]
);

const [exportProjectMutation] = useMutation(EXPORT_PROJECT);
const useExportProject = useCallback(
async (projectId: string) => {
if (!projectId) return { status: "error" };

const { data, errors } = await exportProjectMutation({
variables: { projectId }
});

if (errors || !data?.exportProject) {
console.log("GraphQL: Failed to export project", errors);
setNotification({
type: "error",
text: t("Failed to export project.")
});

return { status: "error" };
}

const projectData = data.exportProject.projectData;

const blob = new Blob([JSON.stringify(projectData)], {
type: "application/json"
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${projectId}.json`;
link.click();
URL.revokeObjectURL(url);

setNotification({
type: "success",
text: t("Successfully exported project!")
});
return { data: projectData, status: "success" };
},
[exportProjectMutation, t, setNotification]
);

const [importProjectMutation] = useMutation(IMPORT_PROJECT);
const useImportProject = useCallback(
async (file: File) => {
if (!file) return { status: "error" };

const { data, errors } = await importProjectMutation({
variables: { file }
});

if (errors || !data?.importProject) {
console.log("GraphQL: Failed to import project", errors);
setNotification({
type: "error",
text: t("Failed to import project.")
});

return { status: "error" };
}

const projectData = data.importProject.projectData;

setNotification({
type: "success",
text: t("Successfully imported project!")
});
return { data: projectData, status: "success" };
},
[importProjectMutation, t, setNotification]
);

return {
publishProjectLoading,
useProjectQuery,
Expand All @@ -399,6 +471,8 @@ export default () => {
useDeleteProject,
useUpdateProjectBasicAuth,
useUpdateProjectAlias,
useStarredProjectsQuery
useStarredProjectsQuery,
useExportProject,
useImportProject
};
};
10 changes: 10 additions & 0 deletions web/src/services/gql/__gen__/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ const documents = {
"\n mutation ArchiveProject($projectId: ID!, $archived: Boolean!) {\n updateProject(input: { projectId: $projectId, archived: $archived }) {\n project {\n id\n isArchived\n }\n }\n }\n": types.ArchiveProjectDocument,
"\n mutation DeleteProject($projectId: ID!) {\n deleteProject(input: { projectId: $projectId }) {\n projectId\n }\n }\n": types.DeleteProjectDocument,
"\n query GetStarredProjects($teamId: ID!) {\n starredProjects(teamId: $teamId) {\n\t\t\t\tnodes {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tstarred\n scene {\n id\n }\n\t\t\t\t}\n\t\t\t\ttotalCount\n\t\t\t}\n }\n": types.GetStarredProjectsDocument,
"\n mutation ExportProject($projectId: ID!) {\n exportProject(input: { projectId: $projectId }) {\n projectData\n }\n }\n": types.ExportProjectDocument,
"\n mutation ImportProject($file: Upload!) {\n importProject(input: { file: $file }) {\n projectData\n }\n }\n": types.ImportProjectDocument,
"\n mutation UpdatePropertyValue(\n $propertyId: ID!\n $schemaGroupId: ID\n $itemId: ID\n $fieldId: ID!\n $value: Any\n $type: ValueType!\n $lang: Lang\n ) {\n updatePropertyValue(\n input: {\n propertyId: $propertyId\n schemaGroupId: $schemaGroupId\n itemId: $itemId\n fieldId: $fieldId\n value: $value\n type: $type\n }\n ) {\n property {\n id\n ...PropertyFragment\n layer {\n id\n ...Layer1Fragment\n }\n }\n }\n }\n": types.UpdatePropertyValueDocument,
"\n mutation AddPropertyItem(\n $propertyId: ID!\n $schemaGroupId: ID!\n $lang: Lang\n ) {\n addPropertyItem(\n input: {\n propertyId: $propertyId\n schemaGroupId: $schemaGroupId\n }\n ) {\n property {\n id\n ...PropertyFragment\n layer {\n id\n ...Layer1Fragment\n }\n }\n }\n }\n": types.AddPropertyItemDocument,
"\n mutation RemovePropertyItem($propertyId: ID!, $schemaGroupId: ID!, $itemId: ID!, $lang: Lang) {\n removePropertyItem(\n input: { propertyId: $propertyId, schemaGroupId: $schemaGroupId, itemId: $itemId }\n ) {\n property {\n id\n ...PropertyFragment\n layer {\n id\n ...Layer1Fragment\n }\n }\n }\n }\n": types.RemovePropertyItemDocument,
Expand Down Expand Up @@ -291,6 +293,14 @@ export function gql(source: "\n mutation DeleteProject($projectId: ID!) {\n
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n query GetStarredProjects($teamId: ID!) {\n starredProjects(teamId: $teamId) {\n\t\t\t\tnodes {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tstarred\n scene {\n id\n }\n\t\t\t\t}\n\t\t\t\ttotalCount\n\t\t\t}\n }\n"): (typeof documents)["\n query GetStarredProjects($teamId: ID!) {\n starredProjects(teamId: $teamId) {\n\t\t\t\tnodes {\n\t\t\t\t\tid\n\t\t\t\t\tname\n\t\t\t\t\tstarred\n scene {\n id\n }\n\t\t\t\t}\n\t\t\t\ttotalCount\n\t\t\t}\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation ExportProject($projectId: ID!) {\n exportProject(input: { projectId: $projectId }) {\n projectData\n }\n }\n"): (typeof documents)["\n mutation ExportProject($projectId: ID!) {\n exportProject(input: { projectId: $projectId }) {\n projectData\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function gql(source: "\n mutation ImportProject($file: Upload!) {\n importProject(input: { file: $file }) {\n projectData\n }\n }\n"): (typeof documents)["\n mutation ImportProject($file: Upload!) {\n importProject(input: { file: $file }) {\n projectData\n }\n }\n"];
/**
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
46 changes: 46 additions & 0 deletions web/src/services/gql/__gen__/graphql.ts

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions web/src/services/gql/queries/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,19 @@ export const GET_STARRED_PROJECTS = gql(`
}
}
`);

export const EXPORT_PROJECT = gql(`
mutation ExportProject($projectId: ID!) {
exportProject(input: { projectId: $projectId }) {
projectData
}
}
`);

export const IMPORT_PROJECT = gql(`
mutation ImportProject($file: Upload!) {
importProject(input: { file: $file }) {
projectData
}
}
`);
6 changes: 6 additions & 0 deletions web/src/services/i18n/translations/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Last Created: ''
First Created: ''
Last Updated: ''
New Project: ''
Import: ''
Export: ''
All projects: ''
Search Result for: ''
Project Name: ''
Expand Down Expand Up @@ -342,6 +344,10 @@ Successfully archive project!: ''
Successfully unarchived the project. You can now edit this project.: ''
Failed to delete project.: ''
Successfully delete project!: ''
Failed to export project.: ''
Successfully exported project!: ''
Failed to import project.: ''
Successfully imported project!: ''
Failed to update property.: ''
Successfully updated the property value!: ''
Failed to create story.: ''
Expand Down
4 changes: 4 additions & 0 deletions web/src/services/i18n/translations/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ Successfully archive project!: プロジェクトのアーカイブに成功し
Successfully unarchived the project. You can now edit this project.: プロジェクトの非編集化が解除されました。このプロジェクトは編集可能です。
Failed to delete project.: プロジェクトの削除に失敗しました。
Successfully delete project!: プロジェクトの削除に成功しました!
Failed to export project.: プロジェクトのエクスポートに失敗しました。
Successfully exported project!: プロジェクトのエクスポートに成功しました!
Failed to import project.: プロジェクトのインポートに失敗しました。
Successfully imported project!: プロジェクトのインポートに成功しました!
Failed to update property.: プロパティのアップデートに失敗しました。
Successfully updated the property value!: ''
Failed to create story.: ストーリーの作成に失敗しました。
Expand Down

0 comments on commit 4a94b2a

Please sign in to comment.