Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 01e1cff

Browse files
authored
refactor(web): apply new project import API & update UI/UX [VIZ-2267] (#1813)
1 parent 84db2e6 commit 01e1cff

File tree

13 files changed

+584
-277
lines changed

13 files changed

+584
-277
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {
2+
Button,
3+
Modal,
4+
ModalPanel,
5+
Typography
6+
} from "@reearth/app/lib/reearth-ui";
7+
import { useT } from "@reearth/services/i18n";
8+
import { styled } from "@reearth/services/theme";
9+
import { FC } from "react";
10+
11+
type Props = {
12+
onClose?: () => void;
13+
onProjectImportErrorLogDownload?: () => void;
14+
};
15+
const ProjectImportErrorModal: FC<Props> = ({
16+
onClose,
17+
onProjectImportErrorLogDownload
18+
}) => {
19+
const t = useT();
20+
21+
return (
22+
<Modal size="small" visible data-testid="project-import-failed-modal">
23+
<ModalPanel
24+
actions={
25+
<>
26+
<Button
27+
size="normal"
28+
title={t("Download Error Log")}
29+
onClick={onProjectImportErrorLogDownload}
30+
/>
31+
<Button
32+
size="normal"
33+
title={t("Ok")}
34+
appearance="primary"
35+
onClick={onClose}
36+
/>
37+
</>
38+
}
39+
title={t("Import Failed")}
40+
>
41+
<Wrapper>
42+
<Typography size="body">
43+
{t("We were unable to import the project.")}
44+
</Typography>
45+
<Typography size="body">
46+
{t(
47+
"Since this file was exported from the system, the structure should be valid. The issue may be caused by:"
48+
)}
49+
<CausesList>
50+
<li>{t("File corruption or incomplete upload")}</li>
51+
<li>{t("Version incompatibility")}</li>
52+
<li>{t("Permission restrictions")}</li>
53+
<li>{t("A temporary system error")}</li>
54+
</CausesList>
55+
{t(
56+
"Please check the issue and try importing again from the start."
57+
)}
58+
</Typography>
59+
</Wrapper>
60+
</ModalPanel>
61+
</Modal>
62+
);
63+
};
64+
65+
export default ProjectImportErrorModal;
66+
67+
const Wrapper = styled("div")(({ theme }) => ({
68+
display: "flex",
69+
flexDirection: "column",
70+
padding: theme.spacing.large,
71+
gap: theme.spacing.normal
72+
}));
73+
74+
const CausesList = styled("ul")(({ theme }) => ({
75+
marginTop: theme.spacing.small,
76+
marginBottom: theme.spacing.small,
77+
paddingLeft: theme.spacing.large,
78+
listStyleType: "disc",
79+
display: "flex",
80+
flexDirection: "column",
81+
gap: theme.spacing.smallest
82+
}));

web/src/app/features/Dashboard/ContentsContainer/Projects/hooks.ts

Lines changed: 16 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import { useApolloClient } from "@apollo/client";
22
import useLoadMore from "@reearth/app/hooks/useLoadMore";
33
import { ManagerLayout } from "@reearth/app/ui/components/ManagerBase";
44
import {
5-
useProject,
6-
useProjectImportExportMutations,
75
useProjectMutations,
86
useProjects,
97
useStarredProjects
@@ -15,20 +13,19 @@ import {
1513
SortDirection,
1614
Visualizer
1715
} from "@reearth/services/gql";
18-
import { useT } from "@reearth/services/i18n";
19-
import { useNotification } from "@reearth/services/state";
2016
import {
2117
useCallback,
2218
useMemo,
2319
useState,
2420
MouseEvent,
2521
useEffect,
26-
useRef,
27-
ChangeEvent
22+
useRef
2823
} from "react";
2924
import { useNavigate } from "react-router-dom";
3025

31-
import { getImportStatus, ImportStatus, Project } from "../../type";
26+
import { Project } from "../../type";
27+
28+
import useProjectImport from "./useProjectImport";
3229

3330
const PROJECTS_VIEW_STATE_STORAGE_KEY_PREFIX = `reearth-visualizer-dashboard-project-view-state`;
3431

@@ -49,8 +46,6 @@ export default (workspaceId?: string) => {
4946
publishProject
5047
} = useProjectMutations();
5148

52-
const { importProject } = useProjectImportExportMutations();
53-
5449
const navigate = useNavigate();
5550
const client = useApolloClient();
5651
const { projectVisibility } = appFeature();
@@ -77,9 +72,6 @@ export default (workspaceId?: string) => {
7772
keyword: searchTerm
7873
});
7974

80-
const t = useT();
81-
const [, setNotification] = useNotification();
82-
8375
const filtedProjects = useMemo(() => {
8476
return (projects ?? [])
8577
.map<Project | undefined>((project) =>
@@ -266,63 +258,15 @@ export default (workspaceId?: string) => {
266258
};
267259
}, [wrapperRef, contentRef]);
268260

269-
//import project
270-
const [importedProjectId, setImportedProjectId] = useState<
271-
string | undefined
272-
>();
273-
const [importStatus, setImportStatus] = useState<ImportStatus>();
274-
275-
const { refetch: refetchProject } = useProject(importedProjectId);
276-
277-
const handleProjectImport = useCallback(
278-
async (event: ChangeEvent<HTMLInputElement>) => {
279-
const file = event.target.files?.[0];
280-
if (file && workspaceId) {
281-
setImportStatus("processing");
282-
const result = await importProject(file, workspaceId);
283-
if (
284-
"project_id" in result &&
285-
typeof result.project_id === "string" &&
286-
result.project_id
287-
) {
288-
setImportedProjectId(result.project_id);
289-
}
290-
}
291-
},
292-
[workspaceId, importProject]
293-
);
294-
295-
useEffect(() => {
296-
if (!importedProjectId) return;
297-
298-
let retries = 0;
299-
const MAX_RETRIES = 100;
300-
301-
const interval = setInterval(() => {
302-
if (++retries > MAX_RETRIES) {
303-
clearInterval(interval);
304-
return;
305-
}
306-
refetchProject().then((result) => {
307-
const status =
308-
result.data?.node?.__typename === "Project"
309-
? getImportStatus(result.data.node.metadata?.importStatus)
310-
: undefined;
311-
312-
setImportStatus(status);
313-
if (status === "success") {
314-
setNotification({
315-
type: "success",
316-
text: t("Successfully imported project!")
317-
});
318-
refetch();
319-
}
320-
if (status !== "processing") clearInterval(interval);
321-
});
322-
}, 3000);
323-
324-
return () => clearInterval(interval);
325-
}, [importedProjectId, refetch, refetchProject, setNotification, t]);
261+
const {
262+
importStatus,
263+
handleProjectImport,
264+
handleProjectImportErrorDownload,
265+
handleProjectImportErrorClose
266+
} = useProjectImport({
267+
workspaceId,
268+
refetchProjectList: refetch
269+
});
326270

327271
// project remove
328272
const handleProjectRemove = useCallback(
@@ -374,7 +318,9 @@ export default (workspaceId?: string) => {
374318
handleProjectSortChange,
375319
handleSearch,
376320
handleProjectImport,
377-
handleProjectRemove
321+
handleProjectRemove,
322+
handleProjectImportErrorDownload,
323+
handleProjectImportErrorClose
378324
};
379325
};
380326

web/src/app/features/Dashboard/ContentsContainer/Projects/index.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ManagerWrapper
99
} from "@reearth/app/ui/components/ManagerBase";
1010
import ManagerEmptyContent from "@reearth/app/ui/components/ManagerBase/ManagerEmptyContent";
11+
import { ProjectImportStatus } from "@reearth/services/gql";
1112
import { useT } from "@reearth/services/i18n";
1213
import { styled, useTheme } from "@reearth/services/theme";
1314
import { FC, useMemo, useRef, Fragment } from "react";
@@ -16,6 +17,7 @@ import useHooks from "./hooks";
1617
import ProjectGridViewItem from "./Project/ProjectGridViewItem";
1718
import ProjectListViewItem from "./Project/ProjectListViewItem";
1819
import ProjectCreatorModal from "./ProjectCreatorModal";
20+
import ProjectImportErrorModal from "./ProjectImportErrorModal";
1921

2022
const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
2123
const {
@@ -41,7 +43,9 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
4143
handleProjectSortChange,
4244
handleSearch,
4345
handleProjectImport,
44-
handleProjectRemove
46+
handleProjectRemove,
47+
handleProjectImportErrorDownload,
48+
handleProjectImportErrorClose
4549
} = useHooks(workspaceId);
4650

4751
const theme = useTheme();
@@ -183,7 +187,8 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
183187
layout={layout}
184188
data-testid={`projects-group-${layout}`}
185189
>
186-
{importStatus === "processing" &&
190+
{(importStatus === ProjectImportStatus.Processing ||
191+
importStatus === ProjectImportStatus.Uploading) &&
187192
(layout === "grid" ? (
188193
<ImportingCardContainer>
189194
<ImportCardPlaceholder />
@@ -247,6 +252,13 @@ const Projects: FC<{ workspaceId?: string }> = ({ workspaceId }) => {
247252
data-testid="project-creator-modal"
248253
/>
249254
)}
255+
256+
{importStatus === ProjectImportStatus.Failed && (
257+
<ProjectImportErrorModal
258+
onClose={handleProjectImportErrorClose}
259+
onProjectImportErrorLogDownload={handleProjectImportErrorDownload}
260+
/>
261+
)}
250262
</ManagerWrapper>
251263
);
252264
};

0 commit comments

Comments
 (0)