Skip to content

Commit

Permalink
feat(web): Add workspace function (#1229)
Browse files Browse the repository at this point in the history
Co-authored-by: tcsola <[email protected]>
  • Loading branch information
ZTongci and tcsola authored Nov 7, 2024
1 parent 8a6cf01 commit cf1bd0e
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 35 deletions.
117 changes: 117 additions & 0 deletions web/src/beta/features/CreateWorkspaceModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import {
Button,
Icon,
Modal,
ModalPanel,
TextInput,
Typography
} from "@reearth/beta/lib/reearth-ui";
import { useWorkspaceFetcher } from "@reearth/services/api";
import { useT } from "@reearth/services/i18n";
import { useAddWorkspaceModal } from "@reearth/services/state";
import { styled, useTheme } from "@reearth/services/theme";
import { FC, useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

const AddWorkspaceModal: FC = () => {
const t = useT();
const theme = useTheme();

const navigate = useNavigate();
const [addWorkspaceModal, setAddWorkspaceModal] = useAddWorkspaceModal();
const { useCreateWorkspace: addWorkspace, useWorkspacesQuery } =
useWorkspaceFetcher();

const [workspaceNameConfirm, setWorkspaceNameConfirm] = useState<string>("");

const handleCloseAddworkspaceModal = useCallback(() => {
setAddWorkspaceModal(false);
}, [setAddWorkspaceModal]);

const handleAddWorkspace = useCallback(async () => {
const { data } = await addWorkspace({
name: workspaceNameConfirm
});
setAddWorkspaceModal(false);
navigate(`/dashboard/${data?.id}`);
}, [addWorkspace, workspaceNameConfirm, setAddWorkspaceModal, navigate]);

const { workspaces } = useWorkspacesQuery();
const isDuplicatedName: boolean | undefined = useMemo(() => {
const name = workspaceNameConfirm.trim();
if (!name) return false;
const allWorkspaceNames = workspaces?.map((workspace) => workspace.name);
return allWorkspaceNames?.includes(name);
}, [workspaceNameConfirm, workspaces]);

useEffect(() => {
if (!addWorkspaceModal) {
setWorkspaceNameConfirm("");
}
}, [addWorkspaceModal]);

return (
<Modal visible={addWorkspaceModal} size="small">
<ModalPanel
title={t("Create new workspace")}
layout="common"
onCancel={handleCloseAddworkspaceModal}
actions={[
<Button
key="cancel"
title={t("Cancel")}
appearance="secondary"
onClick={handleCloseAddworkspaceModal}
/>,
<Button
key="create"
title={t("create")}
appearance="primary"
disabled={isDuplicatedName}
onClick={handleAddWorkspace}
/>
]}
>
<ModalContentWrapper>
<Typography size="body">{t("Your workspace Name *")}</Typography>
<TextInput
placeholder="your workspace name"
onChange={setWorkspaceNameConfirm}
/>

{isDuplicatedName && (
<WarningContentWrapper>
<Icon icon="lightBulb" color={theme.warning.main} size="normal" />
<WarningTextMessage size="body" color={theme.warning.main}>
{t(
"The name is already in use by another workspace. Please choose a different name."
)}
</WarningTextMessage>
</WarningContentWrapper>
)}
</ModalContentWrapper>
</ModalPanel>
</Modal>
);
};

export default AddWorkspaceModal;

const ModalContentWrapper = styled("div")(({ theme }) => ({
display: "flex",
flexDirection: "column",
justifyContent: "start",
gap: theme.spacing.normal
}));

const WarningContentWrapper = styled("div")(({ theme }) => ({
display: "flex",
alignItems: "center",
gap: theme.spacing.small,
maxWidth: "100%",
marginTop: theme.spacing.small
}));

const WarningTextMessage = styled(Typography)(() => ({
maxWidth: "calc(100% - 24px)"
}));
38 changes: 21 additions & 17 deletions web/src/beta/features/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";
import { FC, useMemo } from "react";

import AddWorkspaceModal from "../CreateWorkspaceModal";
import CursorStatus from "../CursorStatus";

import ContentsContainer from "./ContentsContainer";
Expand Down Expand Up @@ -68,26 +69,29 @@ const Dashboard: FC<DashboardProps> = ({ workspaceId }) => {
} = useHooks({ workspaceId, topTabItems, bottomTabsItems });

return (
<Wrapper>
<LeftSideWrapper>
<LeftSidePanel
<>
<Wrapper>
<LeftSideWrapper>
<LeftSidePanel
tab={currentTab}
isPersonal={isPersonal}
currentWorkspace={currentWorkspace}
workspaces={workspaces}
topTabs={topTabs}
bottomTabs={bottomTabs}
onSignOut={onSignOut}
onWorkspaceChange={handleWorkspaceChange}
/>
</LeftSideWrapper>
<ContentsContainer
tab={currentTab}
isPersonal={isPersonal}
workspaceId={workspaceId}
currentWorkspace={currentWorkspace}
workspaces={workspaces}
topTabs={topTabs}
bottomTabs={bottomTabs}
onSignOut={onSignOut}
onWorkspaceChange={handleWorkspaceChange}
/>
</LeftSideWrapper>
<ContentsContainer
tab={currentTab}
workspaceId={workspaceId}
currentWorkspace={currentWorkspace}
/>
<CursorStatus />
</Wrapper>
<CursorStatus />
</Wrapper>
<AddWorkspaceModal />
</>
);
};

Expand Down
29 changes: 17 additions & 12 deletions web/src/beta/features/Navbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { styled } from "@reearth/services/theme";

import AddWorkspaceModal from "../CreateWorkspaceModal";

import useHook from "./hooks";
import LeftSection from "./LeftSection";
import useRightSide from "./useRightSection";
Expand Down Expand Up @@ -47,18 +49,21 @@ const Navbar: React.FC<Props> = ({
});

return (
<Wrapper>
<LeftSection
currentProject={currentProject}
currentWorkspace={currentWorkspace}
workspaces={workspaces}
sceneId={sceneId}
page={page}
onWorkspaceChange={handleWorkspaceChange}
onSignOut={handleLogout}
/>
{rightSide}
</Wrapper>
<>
<Wrapper>
<LeftSection
currentProject={currentProject}
currentWorkspace={currentWorkspace}
workspaces={workspaces}
sceneId={sceneId}
page={page}
onWorkspaceChange={handleWorkspaceChange}
onSignOut={handleLogout}
/>
{rightSide}
</Wrapper>
<AddWorkspaceModal />
</>
);
};

Expand Down
14 changes: 12 additions & 2 deletions web/src/beta/hooks/useWorkspaceManagementMenu.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { config } from "@reearth/services/config";
import { useT } from "@reearth/services/i18n";
import { useAddWorkspaceModal } from "@reearth/services/state";
import { useMemo } from "react";
import { useNavigate } from "react-router-dom";

Expand All @@ -8,6 +9,7 @@ import { PopupMenuItem } from "../lib/reearth-ui";
export default ({ workspaceId }: { workspaceId?: string }) => {
const navigate = useNavigate();
const t = useT();
const [_, setAddWorkspaceModal] = useAddWorkspaceModal();

const workspaceManagementMenu: PopupMenuItem[] = useMemo(
() =>
Expand All @@ -17,9 +19,17 @@ export default ({ workspaceId }: { workspaceId?: string }) => {
id: "workspaceSettings",
title: t("Workspace Settings"),
icon: "setting",
hasBorderBottom: true,
onClick: () => navigate(`/settings/workspaces/${workspaceId}`)
},
{
id: "addWorkspace",
title: t("New Workspace"),
icon: "newWorkspace",
hasBorderBottom: true,
onClick: () => {
setAddWorkspaceModal(true);
}
},
{
id: "accountSettings",
title: t("Account Settings"),
Expand All @@ -28,7 +38,7 @@ export default ({ workspaceId }: { workspaceId?: string }) => {
}
]
: [],
[workspaceId, navigate, t]
[workspaceId, t, navigate, setAddWorkspaceModal]
);

return {
Expand Down
10 changes: 10 additions & 0 deletions web/src/beta/lib/reearth-ui/components/Icon/Icons/NewWorkspace.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions web/src/beta/lib/reearth-ui/components/Icon/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ import MemberAdd from "./Icons/MemberAdd.svg?react";
import Minus from "./Icons/Minus.svg?react";
import More from "./Icons/More.svg?react";
import NavigatorAngle from "./Icons/NavigatorAngle.svg?react";
import NewWorkspace from "./Icons/NewWorkspace.svg?react";
import Notebook from "./Icons/Notebook.svg?react";
import Padding from "./Icons/Padding.svg?react";
import Page from "./Icons/Page.svg?react";
Expand Down Expand Up @@ -251,6 +252,7 @@ export default {
minus: Minus,
more: More,
navigatorAngle: NavigatorAngle,
newWorkspace: NewWorkspace,
notebook: Notebook,
padding: Padding,
page: Page,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ const ActionWrapper = styled("div")<{ showBorder: boolean }>(
);

const CommonLayout = styled("div")(({ theme }) => ({
width: "100%",
display: "flex",
flexDirection: "column",
gap: theme.spacing.large,
Expand Down
7 changes: 6 additions & 1 deletion web/src/services/i18n/translations/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ Size: ''
Path: ''
No Asset has been uploaded yet: ''
Asset URL copied to clipboard: ''
Create new workspace: ''
Cancel: ''
create: ''
Your workspace Name *: ''
The name is already in use by another workspace. Please choose a different name.: ''
Use Name or Email: ''
Find Member: ''
No Member match your search.: ''
Expand All @@ -51,7 +56,6 @@ Project Setting: ''
Export (Experimental): ''
Move to Recycle Bin: ''
Create new project: ''
Cancel: ''
Apply: ''
Project Name *: ''
Text: ''
Expand Down Expand Up @@ -323,6 +327,7 @@ Workspace: ''
Workspace Name: ''
This process will delete this workspace: ''
Workspace Settings: ''
New Workspace: ''
Account Settings: ''
Write your story :): ''
Normal: ''
Expand Down
9 changes: 7 additions & 2 deletions web/src/services/i18n/translations/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,14 @@ Size: サイズ
Path: パス
No Asset has been uploaded yet: まだアセットがアップロードされていません
Asset URL copied to clipboard: アセットURLがクリップボードにコピーされました
Create new workspace: ワークスペースを作る
Cancel: キャンセル
create: 作成する
Your workspace Name *: あなたのワークスペースの名前
The name is already in use by another workspace. Please choose a different name.: このワークスペース名はすでに使用されています。別の名前を指定してください。
Use Name or Email: 名前またはメールアドレスを使用
Find Member: メンバーを検索
No Member match your search.: 一致するメンバーが見つかりません
No Member match your search.: 一致するメンバーが見つかりません'
Last Created: 最終作成日
First Created: 最初の作成日
Last Updated: 最終更新日
Expand All @@ -51,7 +56,6 @@ Project Setting: プロジェクト設定
Export (Experimental): エクスポート(実験的)
Move to Recycle Bin: ゴミ箱に移動
Create new project: 新しいプロジェクトを作成
Cancel: キャンセル
Apply: 適用
Project Name *: プロジェクト名 *
Text: テキスト
Expand Down Expand Up @@ -323,6 +327,7 @@ Workspace: ワークスペース
Workspace Name: ワークスペース名
This process will delete this workspace: この操作により、このワークスペースが削除されます
Workspace Settings: ワークスペース設定
New Workspace: 新しいワークスペース
Account Settings: アカウント設定
Write your story :): ストーリーを書く :)
Normal: 通常
Expand Down
3 changes: 3 additions & 0 deletions web/src/services/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ export const useCurrentTheme = () => useAtom(currentTheme);
const workspace = atom<Workspace | undefined>(undefined);
export const useWorkspace = () => useAtom(workspace);

const addWorkspaceModal = atom<boolean>(false);
export const useAddWorkspaceModal = () => useAtom(addWorkspaceModal);

const userId = atomWithStorage<string | undefined>("userId", undefined);
export const useUserId = () => useAtom(userId);

Expand Down

0 comments on commit cf1bd0e

Please sign in to comment.