From 1d8b4296fbb1dc0b9a25ca8492349ebd6119a91f Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Fri, 3 Mar 2023 14:30:21 +0530 Subject: [PATCH] style: workspace settings pages --- apps/app/components/popup/index.tsx | 25 +- .../project/single-integration-card.tsx | 2 +- apps/app/layouts/settings-navbar.tsx | 2 +- .../projects/[projectId]/settings/members.tsx | 18 +- .../pages/[workspaceSlug]/settings/index.tsx | 145 ++++++------ .../[workspaceSlug]/settings/integrations.tsx | 7 +- .../[workspaceSlug]/settings/members.tsx | 222 ++++++++---------- 7 files changed, 182 insertions(+), 239 deletions(-) diff --git a/apps/app/components/popup/index.tsx b/apps/app/components/popup/index.tsx index 9c18eb916..48a4348c6 100644 --- a/apps/app/components/popup/index.tsx +++ b/apps/app/components/popup/index.tsx @@ -3,6 +3,8 @@ import React, { useRef, useState } from "react"; import Image from "next/image"; import { useRouter } from "next/router"; +import useSWR, { mutate } from "swr"; + // services import workspaceService from "services/workspace.service"; // hooks @@ -10,10 +12,11 @@ import useToast from "hooks/use-toast"; // ui import { Button, Loader } from "components/ui"; // icons -import GithubLogo from "public/logos/github-black.png"; -import useSWR, { mutate } from "swr"; -import { APP_INTEGRATIONS, WORKSPACE_INTEGRATIONS } from "constants/fetch-keys"; +import GithubLogo from "public/logos/github-square.png"; +// types import { IWorkspaceIntegrations } from "types"; +// fetch-keys +import { WORKSPACE_INTEGRATIONS } from "constants/fetch-keys"; const OAuthPopUp = ({ integration }: any) => { const [deletingIntegration, setDeletingIntegration] = useState(false); @@ -97,28 +100,28 @@ const OAuthPopUp = ({ integration }: any) => { ); return ( -
+
-
+
GithubLogo
-

+

{integration.title} {workspaceIntegrations ? ( isInstalled ? ( - - Installed + + Installed ) : ( - - Not + + Not Installed ) ) : null}

-

+

{workspaceIntegrations ? isInstalled ? "Activate GitHub integrations on individual projects to sync with specific repositories." diff --git a/apps/app/components/project/single-integration-card.tsx b/apps/app/components/project/single-integration-card.tsx index 6113b402f..42220647b 100644 --- a/apps/app/components/project/single-integration-card.tsx +++ b/apps/app/components/project/single-integration-card.tsx @@ -87,7 +87,7 @@ export const SingleIntegration: React.FC = ({ integration }) => { {integration && (

-
+
GithubLogo
diff --git a/apps/app/layouts/settings-navbar.tsx b/apps/app/layouts/settings-navbar.tsx index 205e0f00e..8ad1cc5c4 100644 --- a/apps/app/layouts/settings-navbar.tsx +++ b/apps/app/layouts/settings-navbar.tsx @@ -64,7 +64,7 @@ const SettingsNavbar: React.FC = () => { return (
{(projectId ? projectLinks : workspaceLinks).map((link) => ( - +
= (props) => { - const { isMember, isOwner, isViewer, isGuest } = props; - +const MembersSettings: NextPage = ({ isMember, isOwner, isViewer, isGuest }) => { const [inviteModal, setInviteModal] = useState(false); - const [selectedMember, setSelectedMember] = useState(null); const [selectedRemoveMember, setSelectedRemoveMember] = useState(null); const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState(null); @@ -251,7 +242,6 @@ const MembersSettings: NextPage = (props) => { ), false ); - setSelectedMember(null); }) .catch((err) => { console.log(err); @@ -259,7 +249,7 @@ const MembersSettings: NextPage = (props) => { }} > {Object.keys(ROLE).map((key) => ( - + <>{ROLE[parseInt(key) as keyof typeof ROLE]} ))} diff --git a/apps/app/pages/[workspaceSlug]/settings/index.tsx b/apps/app/pages/[workspaceSlug]/settings/index.tsx index e1c242f03..ac38dd0ca 100644 --- a/apps/app/pages/[workspaceSlug]/settings/index.tsx +++ b/apps/app/pages/[workspaceSlug]/settings/index.tsx @@ -27,7 +27,7 @@ import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types -import type { IWorkspace } from "types"; +import type { IWorkspace, UserAuth } from "types"; import type { GetServerSideProps, NextPage } from "next"; // fetch-keys import { WORKSPACE_DETAILS, USER_WORKSPACES } from "constants/fetch-keys"; @@ -41,14 +41,7 @@ const defaultValues: Partial = { logo: null, }; -type TWorkspaceSettingsProps = { - isOwner: boolean; - isMember: boolean; - isViewer: boolean; - isGuest: boolean; -}; - -const WorkspaceSettings: NextPage = (props) => { +const WorkspaceSettings: NextPage = (props) => { const [isOpen, setIsOpen] = useState(false); const [isImageUploading, setIsImageUploading] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); @@ -135,17 +128,16 @@ const WorkspaceSettings: NextPage = (props) => { data={activeWorkspace ?? null} /> {activeWorkspace ? ( -
-
-

General

-

- This information will be displayed to every member of the workspace. -

-
-
-
-

Logo

-
+
+
+
+

Logo

+

+ Max file size is 5MB. Supported file types are .jpg and .png. +

+
+
+
-

- Max file size is 5MB. Supported file types are .jpg and .png. -

-
-
-
-

URL

-

Give a name to your workspace.

-
- -
+
+
+
+

URL

+

Your workspace URL.

+
+
= (props) => { value={`app.plane.so/${activeWorkspace.slug}`} disabled /> +
-
-

Name

-

Give a name to your workspace.

+
+
+
+

Name

+

Give a name to your workspace.

+
+
= (props) => { validations={{ required: "Name is required", }} - className="w-full" />
-
-

Company Size

-

How big is your company?

+
+
+
+

Company Size

+

How big is your company?

+
+
= (props) => { )} />
-
- +
+
+ +
+
+
+

Danger Zone

+

+ The danger zone of the workspace delete page is a critical area that requires + careful consideration and attention. When deleting a workspace, all of the data and + resources within that workspace will be permanently removed and cannot be recovered. +

-
-
-

Danger Zone

-

- The danger zone of the workspace delete page is a critical area that requires - careful consideration and attention. When deleting a workspace, all of the data - and resources within that workspace will be permanently removed and cannot be - recovered. -

-
-
- setIsOpen(true)}> - Delete the workspace - -
+
+ setIsOpen(true)}> + Delete the workspace +
diff --git a/apps/app/pages/[workspaceSlug]/settings/integrations.tsx b/apps/app/pages/[workspaceSlug]/settings/integrations.tsx index 5b9f2bd5e..f55eb22b3 100644 --- a/apps/app/pages/[workspaceSlug]/settings/integrations.tsx +++ b/apps/app/pages/[workspaceSlug]/settings/integrations.tsx @@ -50,11 +50,8 @@ const WorkspaceIntegrations: NextPage = (props) => { settingsLayout >
-
-

Integrations

-

Manage the workspace integrations.

-
-
+

Integrations

+
{integrations ? ( integrations.map((integration) => ( = (props) => { - const [selectedMember, setSelectedMember] = useState(null); +const MembersSettings: NextPage = (props) => { const [selectedRemoveMember, setSelectedRemoveMember] = useState(null); const [selectedInviteRemoveMember, setSelectedInviteRemoveMember] = useState(null); const [inviteModal, setInviteModal] = useState(false); - const { - query: { workspaceSlug }, - } = useRouter(); + const router = useRouter(); + const { workspaceSlug } = router.query; const { setToastAlert } = useToast(); @@ -151,135 +143,107 @@ const MembersSettings: NextPage = (props) => { settingsLayout >
-
-

Members

-

Manage all the members of the workspace.

+
+

Members

+
{!workspaceMembers || !workspaceInvitations ? ( - + ) : ( -
-
-

Manage members

- -
-
- {members.length > 0 - ? members.map((member) => ( -
-
-
- {member.avatar && member.avatar !== "" ? ( - {member.first_name} - ) : member.first_name !== "" ? ( - member.first_name.charAt(0) - ) : ( - member.email.charAt(0) - )} -
-
-

- {member.first_name} {member.last_name} -

-

{member.email}

-
-
-
- {selectedMember === member.id ? ( - ({ - display: ROLE[parseInt(key) as keyof typeof ROLE], - value: key, - }))} - title={ROLE[member.role as keyof typeof ROLE] ?? "None"} - value={member.role} - onChange={(value) => { - workspaceService - .updateWorkspaceMember( - activeWorkspace?.slug as string, - member.id, - { - role: value, - } - ) - .then(() => { - mutateMembers( - (prevData) => - prevData?.map((m) => - m.id === selectedMember ? { ...m, role: value } : m - ), - false - ); - setToastAlert({ - title: "Success", - type: "success", - message: "Member role updated successfully.", - }); - setSelectedMember(null); - }) - .catch(() => { - setToastAlert({ - title: "Error", - type: "error", - message: "An error occurred while updating member role.", - }); - }); - }} +
+ {members.length > 0 + ? members.map((member) => ( +
+
+
+ {member.avatar && member.avatar !== "" ? ( + {member.first_name} + ) : member.first_name !== "" ? ( + member.first_name.charAt(0) ) : ( - ROLE[member.role as keyof typeof ROLE] ?? "None" + member.email.charAt(0) )} - - { - if (!member.member) { - setToastAlert({ - type: "error", - message: "You can't edit a pending invitation.", - title: "Error", - }); - } else { - setSelectedMember(member.id); - } - }} - > - Edit - - { - if (member.member) { - setSelectedRemoveMember(member.id); - } else { - setSelectedInviteRemoveMember(member.id); - } - }} - > - Remove - - +
+
+

+ {member.first_name} {member.last_name} +

+

{member.email}

- )) - : null} -
+
+ { + workspaceService + .updateWorkspaceMember(activeWorkspace?.slug as string, member.id, { + role: value, + }) + .then(() => { + mutateMembers( + (prevData) => + prevData?.map((m) => + m.id === member.id ? { ...m, role: value } : m + ), + false + ); + setToastAlert({ + title: "Success", + type: "success", + message: "Member role updated successfully.", + }); + }) + .catch(() => { + setToastAlert({ + title: "Error", + type: "error", + message: "An error occurred while updating member role.", + }); + }); + }} + > + {Object.keys(ROLE).map((key) => ( + + <>{ROLE[parseInt(key) as keyof typeof ROLE]} + + ))} + + + { + if (member.member) { + setSelectedRemoveMember(member.id); + } else { + setSelectedInviteRemoveMember(member.id); + } + }} + > + Remove member + + +
+
+ )) + : null}
)}