Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): Export & Import Project #1154

Merged
merged 12 commits into from
Oct 1, 2024
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
Loading