Skip to content

Commit

Permalink
feat(web): Export & Import Project (#1154)
Browse files Browse the repository at this point in the history
Co-authored-by: lby <[email protected]>
  • Loading branch information
m-abe-dev and airslice authored Oct 1, 2024
1 parent b00aca9 commit 25f35c5
Show file tree
Hide file tree
Showing 14 changed files with 429 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const ProjectGridViewItem: FC<ProjectProps> = ({
handleProjectHover,
handleProjectNameDoubleClick,
handleProjectStarClick
// exportModalVisible,
// closeExportModal,
// handleExportProject
} = useHooks({
project,
selectedProjectId,
Expand All @@ -34,55 +37,68 @@ const ProjectGridViewItem: FC<ProjectProps> = ({
});

return (
<Card>
<CardImage
backgroundImage={project.imageUrl}
onDoubleClick={onProjectOpen}
onClick={(e) => onProjectSelect?.(e, project.id)}
isHovered={isHovered ?? false}
onMouseEnter={() => handleProjectHover?.(true)}
onMouseLeave={() => handleProjectHover?.(false)}
isSelected={selectedProjectId === project.id}
>
<StarButtonWrapper
isStarred={isStarred ?? false}
<>
<Card>
<CardImage
backgroundImage={project.imageUrl}
onDoubleClick={onProjectOpen}
onClick={(e) => onProjectSelect?.(e, project.id)}
isHovered={isHovered ?? false}
onMouseEnter={() => handleProjectHover?.(true)}
onMouseLeave={() => handleProjectHover?.(false)}
isSelected={selectedProjectId === project.id}
>
<Button
iconButton
icon={isStarred ? "starFilled" : "star"}
onClick={(e) => handleProjectStarClick?.(e)}
iconColor={isStarred ? theme.warning.main : theme.content.main}
appearance="simple"
/>
</StarButtonWrapper>
</CardImage>
<CardFooter>
{hasMapOrStoryPublished && <PublishStatus />}
<CardTitleWrapper>
{!isEditing ? (
<CardTitle onDoubleClick={handleProjectNameDoubleClick}>
{projectName}
</CardTitle>
) : (
<TextInput
onChange={handleProjectNameChange}
onBlur={handleProjectNameBlur}
value={projectName}
autoFocus={isEditing}
appearance="present"
<StarButtonWrapper
isStarred={isStarred ?? false}
isHovered={isHovered ?? false}
isSelected={selectedProjectId === project.id}
>
<Button
iconButton
icon={isStarred ? "starFilled" : "star"}
onClick={(e) => handleProjectStarClick?.(e)}
iconColor={isStarred ? theme.warning.main : theme.content.main}
appearance="simple"
/>
)}
</CardTitleWrapper>
<PopupMenu
menu={popupMenu}
label={
<Button icon="dotsThreeVertical" iconButton appearance="simple" />
}
/>
</CardFooter>
</Card>
</StarButtonWrapper>
</CardImage>
<CardFooter>
{hasMapOrStoryPublished && <PublishStatus />}
<CardTitleWrapper>
{!isEditing ? (
<CardTitle onDoubleClick={handleProjectNameDoubleClick}>
{projectName}
</CardTitle>
) : (
<TextInput
onChange={handleProjectNameChange}
onBlur={handleProjectNameBlur}
value={projectName}
autoFocus={isEditing}
appearance="present"
/>
)}
</CardTitleWrapper>
<PopupMenu
menu={popupMenu}
label={
<Button icon="dotsThreeVertical" iconButton appearance="simple" />
}
/>
</CardFooter>
</Card>
{/* MEMO: this modal will be used in the future */}
{/* <Modal visible={exportModalVisible} size="small">
<ModalPanel
title={t("Export Project")}
actions={actions}
onCancel={closeExportModal}
appearance="normal"
>
<ModalContent />
</ModalPanel>
</Modal> */}
</>
);
};

Expand Down Expand Up @@ -155,3 +171,8 @@ const CardTitle = styled("div")(({ theme }) => ({
textOverflow: "ellipsis",
cursor: "pointer"
}));

// const ModalContent = styled("div")(() => ({
// width: "100%",
// height: "272px"
// }));
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ const ProjectListViewItem: FC<ProjectProps> = ({
handleProjectHover,
handleProjectNameDoubleClick,
handleProjectStarClick
// exportModalVisible,
// closeExportModal,
// handleExportProject
} = useHooks({
project,
selectedProjectId,
Expand All @@ -51,67 +54,80 @@ const ProjectListViewItem: FC<ProjectProps> = ({
});

return (
<ListWrapper
onClick={(e) => onProjectSelect?.(e, project.id)}
isHovered={isHovered ?? false}
onDoubleClick={onProjectOpen}
onMouseEnter={() => handleProjectHover?.(true)}
onMouseLeave={() => handleProjectHover?.(false)}
isSelected={selectedProjectId === project.id}
>
<ThumbnailCol>
<ActionWrapper>
<StarButtonWrapper
isStarred={isStarred ?? false}
isHovered={isHovered ?? false}
isSelected={selectedProjectId === project.id}
>
<Button
iconButton
icon={isStarred ? "starFilled" : "star"}
onClick={(e) => handleProjectStarClick?.(e)}
iconColor={isStarred ? theme.warning.main : theme.content.main}
appearance="simple"
<>
<ListWrapper
onClick={(e) => onProjectSelect?.(e, project.id)}
isHovered={isHovered ?? false}
onDoubleClick={onProjectOpen}
onMouseEnter={() => handleProjectHover?.(true)}
onMouseLeave={() => handleProjectHover?.(false)}
isSelected={selectedProjectId === project.id}
>
<ThumbnailCol>
<ActionWrapper>
<StarButtonWrapper
isStarred={isStarred ?? false}
isHovered={isHovered ?? false}
isSelected={selectedProjectId === project.id}
>
<Button
iconButton
icon={isStarred ? "starFilled" : "star"}
onClick={(e) => handleProjectStarClick?.(e)}
iconColor={isStarred ? theme.warning.main : theme.content.main}
appearance="simple"
/>
</StarButtonWrapper>
<ProjectImage backgroundImage={project.imageUrl} />
</ActionWrapper>
</ThumbnailCol>
<ProjectNameCol>
<PublishStatus status={hasMapOrStoryPublished} />
{!isEditing ? (
<TitleWrapper onDoubleClick={handleProjectNameDoubleClick}>
{projectName}
</TitleWrapper>
) : (
<TextInput
onChange={handleProjectNameChange}
onBlur={handleProjectNameBlur}
value={projectName}
autoFocus={isEditing}
appearance="present"
/>
</StarButtonWrapper>
<ProjectImage backgroundImage={project.imageUrl} />
</ActionWrapper>
</ThumbnailCol>
<ProjectNameCol>
<PublishStatus status={hasMapOrStoryPublished} />
{!isEditing ? (
<TitleWrapper onDoubleClick={handleProjectNameDoubleClick}>
{projectName}
</TitleWrapper>
) : (
<TextInput
onChange={handleProjectNameChange}
onBlur={handleProjectNameBlur}
value={projectName}
autoFocus={isEditing}
appearance="present"
)}
</ProjectNameCol>
<TimeCol>
<Typography size="body">{UpdatedAt}</Typography>
</TimeCol>
<TimeCol>
<Typography size="body">{createAt}</Typography>
</TimeCol>
<ActionCol
onClick={(e: MouseEvent) => {
e.stopPropagation();
}}
>
<PopupMenu
menu={popupMenu}
label={
<Button icon="dotsThreeVertical" iconButton appearance="simple" />
}
/>
)}
</ProjectNameCol>
<TimeCol>
<Typography size="body">{UpdatedAt}</Typography>
</TimeCol>
<TimeCol>
<Typography size="body">{createAt}</Typography>
</TimeCol>
<ActionCol
onClick={(e: MouseEvent) => {
e.stopPropagation();
}}
>
<PopupMenu
menu={popupMenu}
label={
<Button icon="dotsThreeVertical" iconButton appearance="simple" />
}
/>
</ActionCol>
</ListWrapper>
</ActionCol>
</ListWrapper>
{/* MEMO: this modal will be used in the future */}
{/* <Modal visible={exportModalVisible} size="small">
<ModalPanel
title={t("Export Project")}
actions={actions}
onCancel={closeExportModal}
appearance="normal"
>
<ModalContent />
</ModalPanel>
</Modal> */}
</>
);
};

Expand Down Expand Up @@ -200,3 +216,8 @@ const TitleWrapper = styled("div")(({ theme }) => ({
overflow: "hidden",
textOverflow: "ellipsis"
}));

// const ModalContent = styled("div")(() => ({
// width: "100%",
// height: "272px"
// }));
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,12 +25,15 @@ export default ({
}: Props) => {
const t = useT();
const { useStoriesQuery } = useStorytellingFetcher();
const { useExportProject } = useProjectFetcher();
const { stories } = useStoriesQuery({ sceneId: project?.sceneId });

const [isEditing, setIsEditing] = useState(false);
const [projectName, setProjectName] = useState(project.name);
const [isHovered, setIsHovered] = useState(false);
const [isStarred, setIsStarred] = useState(project.starred);
// MEMO: this modal state and function will be used in the future
// const [exportModalVisible, setExportModalVisible] = useState(false);

const handleProjectNameChange = useCallback((newValue: string) => {
setProjectName(newValue);
Expand All @@ -49,6 +55,26 @@ export default ({
onProjectSelect?.(undefined);
}, [onProjectSelect, project.id, selectedProjectId]);

// const openExportModal = useCallback(() => {
// setExportModalVisible(true);
// }, []);

// const closeExportModal = useCallback(() => {
// setExportModalVisible(false);
// }, []);

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 @@ -65,6 +91,12 @@ export default ({
title: t("Project Setting"),
path: `/settings/project/${project.id}`,
icon: "setting"
},
{
id: "export",
title: t("Export"),
icon: "downloadSimple",
onClick: () => handleExportProject()
}
];

Expand Down Expand Up @@ -122,6 +154,7 @@ export default ({
handleProjectNameBlur,
handleProjectHover,
handleProjectNameDoubleClick,
handleProjectStarClick
handleProjectStarClick,
handleExportProject
};
};
Loading

0 comments on commit 25f35c5

Please sign in to comment.