From cea39c758e8ce1b335fdd7eec7b377b9e071e07d Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Wed, 25 Oct 2023 15:48:57 +0530 Subject: [PATCH] chore: layout refactor (#2532) * chore: layout refactor * fix: profile auth issue * chore: project setting layout refactor * chore: workspace layout refactor * chore: profile layout refactor * chore: layout import refactor --- web/components/headers/index.ts | 1 + web/components/headers/user-profile.tsx | 25 + web/components/profile/navbar.tsx | 9 +- web/layouts/app-layout-legacy/app-header.tsx | 75 --- web/layouts/app-layout-legacy/app-sidebar.tsx | 43 -- web/layouts/app-layout-legacy/layout.tsx | 1 - web/layouts/auth-layout-legacy/index.ts | 3 - .../project-authorization-wrapper.tsx | 122 ----- .../user-authorization-wrapper.tsx | 42 -- .../workspace-authorization-wrapper.tsx | 123 ----- web/layouts/profile-layout.tsx | 49 -- web/layouts/profile-layout/index.ts | 1 + web/layouts/profile-layout/layout.tsx | 44 ++ web/layouts/setting-layout/index.ts | 2 + .../project-setting-layout/layout.tsx | 34 +- .../workspace-setting-layout/layout.tsx | 32 +- web/pages/[workspaceSlug]/me/my-issues.tsx | 123 ----- .../[workspaceSlug]/me/profile/activity.tsx | 289 +++++------ .../[workspaceSlug]/me/profile/index.tsx | 451 +++++++++--------- .../me/profile/preferences.tsx | 45 +- .../profile/[userId]/assigned.tsx | 8 +- .../profile/[userId]/created.tsx | 8 +- .../profile/[userId]/index.tsx | 24 +- .../profile/[userId]/subscribed.tsx | 8 +- .../[projectId]/settings/automations.tsx | 23 +- .../[projectId]/settings/estimates.tsx | 28 +- .../[projectId]/settings/features.tsx | 93 ++-- .../projects/[projectId]/settings/index.tsx | 53 +- .../[projectId]/settings/integrations.tsx | 71 +-- .../projects/[projectId]/settings/labels.tsx | 149 +++--- .../projects/[projectId]/settings/members.tsx | 444 ++++++++--------- .../projects/[projectId]/settings/states.tsx | 143 +++--- .../[workspaceSlug]/settings/billing.tsx | 37 +- .../[workspaceSlug]/settings/exports.tsx | 22 +- .../[workspaceSlug]/settings/imports.tsx | 21 +- web/pages/[workspaceSlug]/settings/index.tsx | 393 +++++++-------- .../[workspaceSlug]/settings/integrations.tsx | 39 +- .../[workspaceSlug]/settings/members.tsx | 409 ++++++++-------- .../workspace-views/issues.tsx | 39 -- 39 files changed, 1496 insertions(+), 2030 deletions(-) create mode 100644 web/components/headers/user-profile.tsx delete mode 100644 web/layouts/app-layout-legacy/app-header.tsx delete mode 100644 web/layouts/app-layout-legacy/app-sidebar.tsx delete mode 100644 web/layouts/app-layout-legacy/layout.tsx delete mode 100644 web/layouts/auth-layout-legacy/index.ts delete mode 100644 web/layouts/auth-layout-legacy/project-authorization-wrapper.tsx delete mode 100644 web/layouts/auth-layout-legacy/user-authorization-wrapper.tsx delete mode 100644 web/layouts/auth-layout-legacy/workspace-authorization-wrapper.tsx delete mode 100644 web/layouts/profile-layout.tsx create mode 100644 web/layouts/profile-layout/index.ts create mode 100644 web/layouts/profile-layout/layout.tsx create mode 100644 web/layouts/setting-layout/index.ts delete mode 100644 web/pages/[workspaceSlug]/me/my-issues.tsx delete mode 100644 web/pages/[workspaceSlug]/workspace-views/issues.tsx diff --git a/web/components/headers/index.ts b/web/components/headers/index.ts index 0657b5ae3..1a52dd4de 100644 --- a/web/components/headers/index.ts +++ b/web/components/headers/index.ts @@ -18,3 +18,4 @@ export * from "./project-draft-issues"; export * from "./project-archived-issue-details"; export * from "./project-archived-issues"; export * from "./project-issue-details"; +export * from "./user-profile"; diff --git a/web/components/headers/user-profile.tsx b/web/components/headers/user-profile.tsx new file mode 100644 index 000000000..870aa1b54 --- /dev/null +++ b/web/components/headers/user-profile.tsx @@ -0,0 +1,25 @@ +import { FC } from "react"; + +import { useRouter } from "next/router"; + +// ui +import { BreadcrumbItem, Breadcrumbs } from "@plane/ui"; +// hooks +import { observer } from "mobx-react-lite"; + +export const UserProfileHeader: FC = observer(() => { + const router = useRouter(); + return ( +
+
+
+ router.back()}> + + +
+
+
+ ); +}); diff --git a/web/components/profile/navbar.tsx b/web/components/profile/navbar.tsx index cd43cc974..433452536 100644 --- a/web/components/profile/navbar.tsx +++ b/web/components/profile/navbar.tsx @@ -5,11 +5,9 @@ import Link from "next/link"; // components import { ProfileIssuesFilter } from "components/profile"; -// types -import { UserAuth } from "types"; type Props = { - memberRole: UserAuth; + isAuthorized: boolean; }; const viewerTabs = [ @@ -38,12 +36,11 @@ const adminTabs = [ }, ]; -export const ProfileNavbar: React.FC = ({ memberRole }) => { +export const ProfileNavbar: React.FC = ({ isAuthorized }) => { const router = useRouter(); const { workspaceSlug, userId } = router.query; - const tabsList = - memberRole.isOwner || memberRole.isMember || memberRole.isViewer ? [...viewerTabs, ...adminTabs] : viewerTabs; + const tabsList = isAuthorized ? [...viewerTabs, ...adminTabs] : viewerTabs; return (
diff --git a/web/layouts/app-layout-legacy/app-header.tsx b/web/layouts/app-layout-legacy/app-header.tsx deleted file mode 100644 index f9ae83497..000000000 --- a/web/layouts/app-layout-legacy/app-header.tsx +++ /dev/null @@ -1,75 +0,0 @@ -// next imports -import { useRouter } from "next/router"; -import Link from "next/link"; -// icons -import { Menu } from "lucide-react"; -// ui components -import { Tooltip } from "@plane/ui"; -// hooks -import useProjectDetails from "hooks/use-project-details"; - -type Props = { - breadcrumbs?: JSX.Element; - left?: JSX.Element; - right?: JSX.Element; - setToggleSidebar: React.Dispatch>; - noHeader: boolean; -}; - -const { NEXT_PUBLIC_DEPLOY_URL } = process.env; -let plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL; - -if (typeof window !== "undefined" && !plane_deploy_url) { - plane_deploy_url = window.location.protocol + "//" + window.location.host + "/spaces"; -} - -const Header: React.FC = ({ breadcrumbs, left, right, setToggleSidebar, noHeader }) => { - const { projectDetails } = useProjectDetails(); - - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; - - return ( -
-
-
- -
-
{breadcrumbs}
- - {projectDetails && projectDetails?.is_deployed && ( - - - -
-
- radio_button_checked -
-
Public
-
- open_in_new -
-
-
-
- - )} - -
{left}
-
-
{right}
-
- ); -}; - -export default Header; diff --git a/web/layouts/app-layout-legacy/app-sidebar.tsx b/web/layouts/app-layout-legacy/app-sidebar.tsx deleted file mode 100644 index 1db9dc983..000000000 --- a/web/layouts/app-layout-legacy/app-sidebar.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import dynamic from "next/dynamic"; -// components -import { WorkspaceHelpSection, WorkspaceSidebarDropdown, WorkspaceSidebarMenu } from "components/workspace"; - -const WorkspaceSidebarQuickAction = dynamic<{}>( - () => import("components/workspace/sidebar-quick-action").then((mod) => mod.WorkspaceSidebarQuickAction), - { - ssr: false, - } -); - -import { ProjectSidebarList } from "components/project"; -// mobx store -import { useMobxStore } from "lib/mobx/store-provider"; -import { observer } from "mobx-react-lite"; - -export interface SidebarProps { - toggleSidebar: boolean; - setToggleSidebar: React.Dispatch>; -} - -const Sidebar: React.FC = observer(({ toggleSidebar, setToggleSidebar }) => { - const { theme: themeStore } = useMobxStore(); - - return ( -
-
- - - - - -
-
- ); -}); - -export default Sidebar; diff --git a/web/layouts/app-layout-legacy/layout.tsx b/web/layouts/app-layout-legacy/layout.tsx deleted file mode 100644 index 90eef899c..000000000 --- a/web/layouts/app-layout-legacy/layout.tsx +++ /dev/null @@ -1 +0,0 @@ -export const AppLayoutLegacy = () => <>; diff --git a/web/layouts/auth-layout-legacy/index.ts b/web/layouts/auth-layout-legacy/index.ts deleted file mode 100644 index 608e96606..000000000 --- a/web/layouts/auth-layout-legacy/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./project-authorization-wrapper"; -export * from "./workspace-authorization-wrapper"; -export * from "./user-authorization-wrapper"; diff --git a/web/layouts/auth-layout-legacy/project-authorization-wrapper.tsx b/web/layouts/auth-layout-legacy/project-authorization-wrapper.tsx deleted file mode 100644 index 69f33b509..000000000 --- a/web/layouts/auth-layout-legacy/project-authorization-wrapper.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { useState } from "react"; - -import Link from "next/link"; -import { useRouter } from "next/router"; - -// contexts -import { useProjectMyMembership, ProjectMemberProvider } from "contexts/project-member.context"; -// layouts -import AppHeader from "layouts/app-layout-legacy/app-header"; -import AppSidebar from "layouts/app-layout-legacy/app-sidebar"; -// components -import { NotAuthorizedView, JoinProject } from "components/auth-screens"; -import { CommandPalette } from "components/command-palette"; -// ui -import { Button, LayersIcon, Spinner } from "@plane/ui"; -import { EmptyState } from "components/common"; -// images -import emptyProject from "public/empty-state/project.svg"; - -type Props = { - children: React.ReactNode; - noHeader?: boolean; - bg?: "primary" | "secondary"; - breadcrumbs?: JSX.Element; - left?: JSX.Element; - right?: JSX.Element; -}; - -export const ProjectAuthorizationWrapper: React.FC = (props) => ( - - - -); - -const ProjectAuthorizationWrapped: React.FC = ({ - children, - noHeader = false, - bg = "primary", - breadcrumbs, - left, - right, -}) => { - const [toggleSidebar, setToggleSidebar] = useState(false); - - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; - - const { loading, error, memberRole: memberType } = useProjectMyMembership(); - - const settingsLayout = router.pathname.includes("/settings"); - - return ( - <> - -
- - - {loading ? ( -
-
-

Loading your project...

- -
-
- ) : error?.status === 401 || error?.status === 403 ? ( - - ) : error?.status === 404 ? ( -
- { - const e = new KeyboardEvent("keydown", { - key: "p", - }); - document.dispatchEvent(e); - }, - }} - /> -
- ) : settingsLayout && (memberType?.isGuest || memberType?.isViewer) ? ( - - - - - - } - type="project" - /> - ) : ( -
- -
-
{children}
-
-
- )} -
- - ); -}; diff --git a/web/layouts/auth-layout-legacy/user-authorization-wrapper.tsx b/web/layouts/auth-layout-legacy/user-authorization-wrapper.tsx deleted file mode 100644 index 33e414e28..000000000 --- a/web/layouts/auth-layout-legacy/user-authorization-wrapper.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// services -import { UserService } from "services/user.service"; -// ui -import { Spinner } from "@plane/ui"; -// fetch-keys -import { CURRENT_USER } from "constants/fetch-keys"; - -type Props = { - children: React.ReactNode; -}; - -// services -const userService = new UserService(); - -export const UserAuthorizationLayout: React.FC = ({ children }) => { - const router = useRouter(); - - const { data: currentUser, error } = useSWR(CURRENT_USER, () => userService.currentUser()); - - if (!currentUser && !error) { - return ( -
-
- -
-
- ); - } - - if (error) { - const redirectTo = router.asPath; - - router.push(`/?next=${redirectTo}`); - return null; - } - - return <>{children}; -}; diff --git a/web/layouts/auth-layout-legacy/workspace-authorization-wrapper.tsx b/web/layouts/auth-layout-legacy/workspace-authorization-wrapper.tsx deleted file mode 100644 index 0f8b7a3d4..000000000 --- a/web/layouts/auth-layout-legacy/workspace-authorization-wrapper.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { useState } from "react"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import useSWR from "swr"; -// services -import { WorkspaceService } from "services/workspace.service"; -// contexts -import { WorkspaceMemberProvider } from "contexts/workspace-member.context"; -// layouts -import AppSidebar from "layouts/app-layout-legacy/app-sidebar"; -import AppHeader from "layouts/app-layout-legacy/app-header"; -import { UserAuthorizationLayout } from "./user-authorization-wrapper"; -// components -import { Button, LayersIcon, Spinner } from "@plane/ui"; -import { NotAuthorizedView, NotAWorkspaceMember } from "components/auth-screens"; -import { CommandPalette } from "components/command-palette"; -// fetch-keys -import { WORKSPACE_MEMBERS_ME } from "constants/fetch-keys"; - -type Props = { - children: React.ReactNode; - noHeader?: boolean; - bg?: "primary" | "secondary"; - breadcrumbs?: JSX.Element; - left?: JSX.Element; - right?: JSX.Element; -}; - -const workspaceService = new WorkspaceService(); - -export const WorkspaceAuthorizationLayout: React.FC = ({ - children, - noHeader = false, - bg = "primary", - breadcrumbs, - left, - right, -}) => { - const [toggleSidebar, setToggleSidebar] = useState(false); - - const router = useRouter(); - const { workspaceSlug } = router.query; - - const { data: workspaceMemberMe, error } = useSWR( - workspaceSlug ? WORKSPACE_MEMBERS_ME(workspaceSlug as string) : null, - workspaceSlug ? () => workspaceService.workspaceMemberMe(workspaceSlug.toString()) : null - ); - - if (!workspaceMemberMe && !error) - return ( -
-
-

Loading your workspace...

- -
-
- ); - - if (error?.status === 401 || error?.status === 403) return ; - - // FIXME: show 404 for workspace not workspace member - if (error?.status === 404) { - return ( -
-

No such workspace exists. Create one?

-
- ); - } - - const settingsLayout = router.pathname.includes("/settings"); - const memberType = { - isOwner: workspaceMemberMe?.role === 20, - isMember: workspaceMemberMe?.role === 15, - isViewer: workspaceMemberMe?.role === 10, - isGuest: workspaceMemberMe?.role === 5, - }; - - return ( - - - -
- - {settingsLayout && (memberType?.isGuest || memberType?.isViewer) ? ( - - - - - - } - type="workspace" - /> - ) : ( -
- -
-
{children}
-
-
- )} -
-
-
- ); -}; diff --git a/web/layouts/profile-layout.tsx b/web/layouts/profile-layout.tsx deleted file mode 100644 index e7ee873a5..000000000 --- a/web/layouts/profile-layout.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useRouter } from "next/router"; -// hooks -import { useWorkspaceMyMembership } from "contexts/workspace-member.context"; -// layouts -import { WorkspaceAuthorizationLayout } from "layouts/auth-layout-legacy"; -// components -import { ProfileNavbar, ProfileSidebar } from "components/profile"; -// ui -import { Breadcrumbs, BreadcrumbItem } from "@plane/ui"; - -type Props = { - children: React.ReactNode; - className?: string; -}; - -export const ProfileAuthWrapper = (props: Props) => { - const router = useRouter(); - return ( - router.back()}> - - - } - > - - - ); -}; - -const ProfileLayout: React.FC = ({ children, className }) => { - const { memberRole } = useWorkspaceMyMembership(); - - return ( -
- -
- - {memberRole.isOwner || memberRole.isMember || memberRole.isViewer ? ( -
{children}
- ) : ( -
- You do not have the permission to access this page. -
- )} -
-
- ); -}; diff --git a/web/layouts/profile-layout/index.ts b/web/layouts/profile-layout/index.ts new file mode 100644 index 000000000..eec9d1e67 --- /dev/null +++ b/web/layouts/profile-layout/index.ts @@ -0,0 +1 @@ +export * from "./layout"; diff --git a/web/layouts/profile-layout/layout.tsx b/web/layouts/profile-layout/layout.tsx new file mode 100644 index 000000000..c7e379167 --- /dev/null +++ b/web/layouts/profile-layout/layout.tsx @@ -0,0 +1,44 @@ +import useSWR from "swr"; +import { useRouter } from "next/router"; +// services +import { WorkspaceService } from "services/workspace.service"; +// components +import { ProfileNavbar, ProfileSidebar } from "components/profile"; +// constants +import { WORKSPACE_MEMBERS_ME } from "constants/fetch-keys"; + +type Props = { + children: React.ReactNode; + className?: string; +}; + +// services +const workspaceService = new WorkspaceService(); + +export const ProfileAuthWrapper: React.FC = ({ children, className }) => { + const router = useRouter(); + const { workspaceSlug } = router.query; + + const { data: memberDetails } = useSWR( + workspaceSlug ? WORKSPACE_MEMBERS_ME(workspaceSlug.toString()) : null, + workspaceSlug ? () => workspaceService.workspaceMemberMe(workspaceSlug.toString()) : null + ); + + const isAuthorized = memberDetails?.role === 20 || memberDetails?.role === 15 || memberDetails?.role === 10; + + return ( +
+ +
+ + {isAuthorized ? ( +
{children}
+ ) : ( +
+ You do not have the permission to access this page. +
+ )} +
+
+ ); +}; diff --git a/web/layouts/setting-layout/index.ts b/web/layouts/setting-layout/index.ts new file mode 100644 index 000000000..32a12e160 --- /dev/null +++ b/web/layouts/setting-layout/index.ts @@ -0,0 +1,2 @@ +export * from "./project-setting-layout"; +export * from "./workspace-setting-layout"; diff --git a/web/layouts/setting-layout/project-setting-layout/layout.tsx b/web/layouts/setting-layout/project-setting-layout/layout.tsx index b34f599ae..7a0bee0eb 100644 --- a/web/layouts/setting-layout/project-setting-layout/layout.tsx +++ b/web/layouts/setting-layout/project-setting-layout/layout.tsx @@ -1,40 +1,20 @@ import { FC, ReactNode } from "react"; -// layouts -import { UserAuthWrapper, ProjectAuthWrapper, WorkspaceAuthWrapper } from "layouts/auth-layout"; // components -import { AppSidebar } from "layouts/app-layout"; import { ProjectSettingsSidebar } from "./sidebar"; export interface IProjectSettingLayout { children: ReactNode; - header: ReactNode; } export const ProjectSettingLayout: FC = (props) => { - const { children, header } = props; + const { children } = props; return ( - <> - - - -
- -
- {header} -
-
-
- -
- {children} -
-
-
-
-
-
-
- +
+
+ +
+ {children} +
); }; diff --git a/web/layouts/setting-layout/workspace-setting-layout/layout.tsx b/web/layouts/setting-layout/workspace-setting-layout/layout.tsx index 74c09b05f..a584c26c1 100644 --- a/web/layouts/setting-layout/workspace-setting-layout/layout.tsx +++ b/web/layouts/setting-layout/workspace-setting-layout/layout.tsx @@ -1,38 +1,20 @@ import { FC, ReactNode } from "react"; -// layouts -import { UserAuthWrapper, WorkspaceAuthWrapper } from "layouts/auth-layout"; // components -import { AppSidebar } from "layouts/app-layout"; import { WorkspaceSettingsSidebar } from "./sidebar"; export interface IWorkspaceSettingLayout { children: ReactNode; - header: ReactNode; } export const WorkspaceSettingLayout: FC = (props) => { - const { children, header } = props; + const { children } = props; return ( - <> - - -
- -
- {header} -
-
-
- -
- {children} -
-
-
-
-
-
- +
+
+ +
+ {children} +
); }; diff --git a/web/pages/[workspaceSlug]/me/my-issues.tsx b/web/pages/[workspaceSlug]/me/my-issues.tsx deleted file mode 100644 index 09036471f..000000000 --- a/web/pages/[workspaceSlug]/me/my-issues.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import React, { useEffect } from "react"; - -import { useRouter } from "next/router"; - -// icons -import { Plus } from "lucide-react"; -// layouts -import { WorkspaceAuthorizationLayout } from "layouts/auth-layout-legacy"; -// hooks -import useMyIssuesFilters from "hooks/my-issues/use-my-issues-filter"; -// components -import { MyIssuesView, MyIssuesViewOptions } from "components/issues"; -// ui -import { Breadcrumbs, BreadcrumbItem, Button } from "@plane/ui"; -// types -import type { NextPage } from "next"; -import useUser from "hooks/use-user"; - -const MyIssuesPage: NextPage = () => { - const router = useRouter(); - const { workspaceSlug } = router.query; - - const { user } = useUser(); - - const { filters, setFilters } = useMyIssuesFilters(workspaceSlug?.toString()); - - const tabsList = [ - { - key: "assigned", - label: "Assigned", - selected: (filters?.assignees ?? []).length > 0, - onClick: () => { - setFilters({ - assignees: [user?.id ?? ""], - created_by: null, - subscriber: null, - }); - }, - }, - { - key: "created", - label: "Created", - selected: (filters?.created_by ?? []).length > 0, - onClick: () => { - setFilters({ - assignees: null, - created_by: [user?.id ?? ""], - subscriber: null, - }); - }, - }, - { - key: "subscribed", - label: "Subscribed", - selected: (filters?.subscriber ?? []).length > 0, - onClick: () => { - setFilters({ - assignees: null, - created_by: null, - subscriber: [user?.id ?? ""], - }); - }, - }, - ]; - - useEffect(() => { - if (!filters || !user) return; - - if (!filters.assignees && !filters.created_by && !filters.subscriber) { - setFilters({ - assignees: [user.id], - }); - return; - } - }, [filters, setFilters, user]); - - return ( - router.back()}> - - - } - right={ -
- - -
- } - > -
-
-
- {tabsList.map((tab) => ( - - ))} -
-
- -
-
- ); -}; - -export default MyIssuesPage; diff --git a/web/pages/[workspaceSlug]/me/profile/activity.tsx b/web/pages/[workspaceSlug]/me/profile/activity.tsx index 5298da83f..85117d975 100644 --- a/web/pages/[workspaceSlug]/me/profile/activity.tsx +++ b/web/pages/[workspaceSlug]/me/profile/activity.tsx @@ -4,7 +4,8 @@ import Link from "next/link"; // services import { UserService } from "services/user.service"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; +import { AppLayout } from "layouts/app-layout"; // components import { ActivityIcon, ActivityMessage } from "components/core"; import { RichReadOnlyEditor } from "@plane/rich-text-editor"; @@ -30,160 +31,164 @@ const ProfileActivity = () => { ); return ( - }> - {userActivity ? ( -
-
-

Activity

-
-
-
    - {userActivity.results.map((activityItem: any) => { - if (activityItem.field === "comment") { - return ( -
    -
    -
    - {activityItem.field ? ( - activityItem.new_value === "restore" && ( - - ) - ) : activityItem.actor_detail.avatar && activityItem.actor_detail.avatar !== "" ? ( - {activityItem.actor_detail.display_name} - ) : ( -
    - {activityItem.actor_detail.display_name?.charAt(0)} -
    - )} + }> + + {userActivity ? ( +
    +
    +

    Activity

    +
    +
    +
      + {userActivity.results.map((activityItem: any) => { + if (activityItem.field === "comment") { + return ( +
      +
      +
      + {activityItem.field ? ( + activityItem.new_value === "restore" && ( + + ) + ) : activityItem.actor_detail.avatar && activityItem.actor_detail.avatar !== "" ? ( + {activityItem.actor_detail.display_name} + ) : ( +
      + {activityItem.actor_detail.display_name?.charAt(0)} +
      + )} - - -
      -
      -
      -
      - {activityItem.actor_detail.is_bot - ? activityItem.actor_detail.first_name + " Bot" - : activityItem.actor_detail.display_name} -
      -

      - Commented {timeAgo(activityItem.created_at)} -

      + +
      -
      - +
      +
      +
      + {activityItem.actor_detail.is_bot + ? activityItem.actor_detail.first_name + " Bot" + : activityItem.actor_detail.display_name} +
      +

      + Commented {timeAgo(activityItem.created_at)} +

      +
      +
      + +
      -
      - ); - } + ); + } - const message = - activityItem.verb === "created" && - activityItem.field !== "cycles" && - activityItem.field !== "modules" && - activityItem.field !== "attachment" && - activityItem.field !== "link" && - activityItem.field !== "estimate" ? ( - - created{" "} - - - this issue. - - - - ) : activityItem.field ? ( - - ) : ( - "created the issue." - ); + const message = + activityItem.verb === "created" && + activityItem.field !== "cycles" && + activityItem.field !== "modules" && + activityItem.field !== "attachment" && + activityItem.field !== "link" && + activityItem.field !== "estimate" ? ( + + created{" "} + + + this issue. + + + + ) : activityItem.field ? ( + + ) : ( + "created the issue." + ); - if ("field" in activityItem && activityItem.field !== "updated_by") { - return ( -
    • -
      -
      - <> -
      -
      -
      -
      - {activityItem.field ? ( - activityItem.new_value === "restore" ? ( - + if ("field" in activityItem && activityItem.field !== "updated_by") { + return ( +
    • +
      +
      + <> +
      +
      +
      +
      + {activityItem.field ? ( + activityItem.new_value === "restore" ? ( + + ) : ( + + ) + ) : activityItem.actor_detail.avatar && + activityItem.actor_detail.avatar !== "" ? ( + {activityItem.actor_detail.display_name} ) : ( - - ) - ) : activityItem.actor_detail.avatar && activityItem.actor_detail.avatar !== "" ? ( - {activityItem.actor_detail.display_name} - ) : ( -
      - {activityItem.actor_detail.display_name?.charAt(0)} -
      - )} +
      + {activityItem.actor_detail.display_name?.charAt(0)} +
      + )} +
      -
      -
      -
      - {activityItem.field === "archived_at" && activityItem.new_value !== "restore" ? ( - Plane - ) : activityItem.actor_detail.is_bot ? ( - - {activityItem.actor_detail.first_name} Bot - - ) : ( - - {activityItem.actor_detail.display_name} - - )}{" "} - {message} {timeAgo(activityItem.created_at)} +
      +
      + {activityItem.field === "archived_at" && activityItem.new_value !== "restore" ? ( + Plane + ) : activityItem.actor_detail.is_bot ? ( + + {activityItem.actor_detail.first_name} Bot + + ) : ( + + {activityItem.actor_detail.display_name} + + )}{" "} + {message}{" "} + {timeAgo(activityItem.created_at)} +
      -
      - + +
      -
    • - - ); - } - })} -
    -
    -
    - ) : ( - - - - - - - )} -
    + + ); + } + })} +
+
+
+ ) : ( + + + + + + + )} +
+ ); }; diff --git a/web/pages/[workspaceSlug]/me/profile/index.tsx b/web/pages/[workspaceSlug]/me/profile/index.tsx index 9e2e16570..ffcfdcdee 100644 --- a/web/pages/[workspaceSlug]/me/profile/index.tsx +++ b/web/pages/[workspaceSlug]/me/profile/index.tsx @@ -9,7 +9,8 @@ import { UserService } from "services/user.service"; import useUserAuth from "hooks/use-user-auth"; import useToast from "hooks/use-toast"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components import { ImagePickerPopover, ImageUploadModal } from "components/core"; import { WorkspaceSettingHeader } from "components/headers"; @@ -143,252 +144,254 @@ const Profile: NextPage = () => { })); return ( - }> - setIsImageUploadModalOpen(false)} - isRemoving={isRemoving} - handleDelete={() => handleDelete(myProfile?.avatar, true)} - onSuccess={(url) => { - setValue("avatar", url); - handleSubmit(onSubmit)(); - setIsImageUploadModalOpen(false); - }} - value={watch("avatar") !== "" ? watch("avatar") : undefined} - userImage - /> - {myProfile ? ( -
-
-
- {myProfile?.first_name -
-
-
- + }> + + setIsImageUploadModalOpen(false)} + isRemoving={isRemoving} + handleDelete={() => handleDelete(myProfile?.avatar, true)} + onSuccess={(url) => { + setValue("avatar", url); + handleSubmit(onSubmit)(); + setIsImageUploadModalOpen(false); + }} + value={watch("avatar") !== "" ? watch("avatar") : undefined} + userImage + /> + {myProfile ? ( + +
+
+ {myProfile?.first_name +
+
+
+ +
-
-
- ( - { - setValue("cover_image", imageUrl); - }} - control={control} - value={watch("cover_image") ?? "https://images.unsplash.com/photo-1506383796573-caf02b4a79ab"} - /> - )} - /> -
-
- -
-
-
- {`${watch("first_name")} ${watch("last_name")}`} +
+ ( + { + setValue("cover_image", imageUrl); + }} + control={control} + value={watch("cover_image") ?? "https://images.unsplash.com/photo-1506383796573-caf02b4a79ab"} + /> + )} + />
- {watch("email")}
- - - - - - View Profile - - -
+
+
+
+ {`${watch("first_name")} ${watch("last_name")}`} +
+ {watch("email")} +
-
-
-

First Name

- ( - - )} - /> + + + + + + View Profile + +
-
-

Last Name

+
+
+

First Name

+ ( + + )} + /> +
- ( - - )} - /> -
+
+

Last Name

-
-

Email

- ( - - )} - /> -
+ ( + + )} + /> +
-
-

Role

- ( - - {USER_ROLES.map((item) => ( - - {item.label} - - ))} - - )} - /> - {errors.role && Please select a role} -
+
+

Email

+ ( + + )} + /> +
-
-

Display name

- { - if (value.trim().length < 1) return "Display name can't be empty."; +
+

Role

+ ( + + {USER_ROLES.map((item) => ( + + {item.label} + + ))} + + )} + /> + {errors.role && Please select a role} +
- if (value.split(" ").length > 1) return "Display name can't have two consecutive spaces."; +
+

Display name

+ { + if (value.trim().length < 1) return "Display name can't be empty."; - if (value.replace(/\s/g, "").length < 1) - return "Display name must be at least 1 characters long."; + if (value.split(" ").length > 1) return "Display name can't have two consecutive spaces."; - if (value.replace(/\s/g, "").length > 20) - return "Display name must be less than 20 characters long."; + if (value.replace(/\s/g, "").length < 1) + return "Display name must be at least 1 characters long."; - return true; - }, - }} - render={({ field: { value, onChange, ref } }) => ( - - )} - /> -
+ if (value.replace(/\s/g, "").length > 20) + return "Display name must be less than 20 characters long."; -
-

Timezone

+ return true; + }, + }} + render={({ field: { value, onChange, ref } }) => ( + + )} + /> +
- ( - t.value === value)?.label ?? value : "Select a timezone"} - options={timeZoneOptions} - onChange={onChange} - optionsClassName="w-full" - input - /> - )} - /> - {errors.role && Please select a role} -
+
+

Timezone

-
- + ( + t.value === value)?.label ?? value : "Select a timezone"} + options={timeZoneOptions} + onChange={onChange} + optionsClassName="w-full" + input + /> + )} + /> + {errors.role && Please select a role} +
+ +
+ +
+ + ) : ( +
+
- - ) : ( -
- -
- )} - + )} + + ); }; diff --git a/web/pages/[workspaceSlug]/me/profile/preferences.tsx b/web/pages/[workspaceSlug]/me/profile/preferences.tsx index beae8a341..11a19d186 100644 --- a/web/pages/[workspaceSlug]/me/profile/preferences.tsx +++ b/web/pages/[workspaceSlug]/me/profile/preferences.tsx @@ -5,7 +5,8 @@ import { useTheme } from "next-themes"; import { useMobxStore } from "lib/mobx/store-provider"; import useToast from "hooks/use-toast"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components import { CustomThemeSelector, ThemeSwitch } from "components/core"; import { WorkspaceSettingHeader } from "components/headers"; @@ -44,29 +45,31 @@ const ProfilePreferencesPage = observer(() => { }; return ( - }> - {userStore.currentUser ? ( -
-
-

Preferences

-
-
-
-

Theme

-

Select or customize your interface color scheme.

+ }> + + {userStore.currentUser ? ( +
+
+

Preferences

-
- +
+
+

Theme

+

Select or customize your interface color scheme.

+
+
+ +
+ {userTheme?.theme === "custom" && }
- {userTheme?.theme === "custom" && } -
- ) : ( -
- -
- )} -
+ ) : ( +
+ +
+ )} + +
); }); diff --git a/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx b/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx index 267679a89..cce7a2b56 100644 --- a/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx +++ b/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx @@ -3,11 +3,11 @@ import type { NextPage } from "next"; import { useRouter } from "next/router"; import useSWR from "swr"; import { observer } from "mobx-react-lite"; -// contexts -import { ProfileIssuesContextProvider } from "contexts/profile-issues-context"; // layouts +import { AppLayout } from "layouts/app-layout"; import { ProfileAuthWrapper } from "layouts/profile-layout"; // components +import { UserProfileHeader } from "components/headers"; import { ProfileIssuesListLayout } from "components/issues/issue-layouts/list/profile-issues-root"; import { ProfileIssuesKanBanLayout } from "components/issues/issue-layouts/kanban/profile-issues-root"; // hooks @@ -45,7 +45,7 @@ const ProfileAssignedIssues: NextPage = observer(() => { const activeLayout = profileIssueFiltersStore.userDisplayFilters.layout; return ( - + }> {profileIssuesStore.loader ? (
Loading...
@@ -59,7 +59,7 @@ const ProfileAssignedIssues: NextPage = observer(() => {
)} - + ); }); diff --git a/web/pages/[workspaceSlug]/profile/[userId]/created.tsx b/web/pages/[workspaceSlug]/profile/[userId]/created.tsx index 1cac31e62..ad6e89dea 100644 --- a/web/pages/[workspaceSlug]/profile/[userId]/created.tsx +++ b/web/pages/[workspaceSlug]/profile/[userId]/created.tsx @@ -1,20 +1,20 @@ import React from "react"; -// contexts -import { ProfileIssuesContextProvider } from "contexts/profile-issues-context"; // layouts +import { AppLayout } from "layouts/app-layout"; import { ProfileAuthWrapper } from "layouts/profile-layout"; // components +import { UserProfileHeader } from "components/headers"; import { ProfileIssuesView } from "components/profile"; // types import type { NextPage } from "next"; const ProfileCreatedIssues: NextPage = () => ( - + }> - + ); export default ProfileCreatedIssues; diff --git a/web/pages/[workspaceSlug]/profile/[userId]/index.tsx b/web/pages/[workspaceSlug]/profile/[userId]/index.tsx index c674dcf33..eb175b631 100644 --- a/web/pages/[workspaceSlug]/profile/[userId]/index.tsx +++ b/web/pages/[workspaceSlug]/profile/[userId]/index.tsx @@ -7,8 +7,10 @@ import useSWR from "swr"; // services import { UserService } from "services/user.service"; // layouts +import { AppLayout } from "layouts/app-layout"; import { ProfileAuthWrapper } from "layouts/profile-layout"; // components +import { UserProfileHeader } from "components/headers"; import { ProfileActivity, ProfilePriorityDistribution, @@ -43,17 +45,19 @@ const ProfileOverview: NextPage = () => { }); return ( - -
- - -
- - + }> + +
+ + +
+ + +
+
- -
- + + ); }; diff --git a/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx b/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx index 3a1ca01ee..3d3400a80 100644 --- a/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx +++ b/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx @@ -1,20 +1,20 @@ import React from "react"; -// contexts -import { ProfileIssuesContextProvider } from "contexts/profile-issues-context"; // layouts +import { AppLayout } from "layouts/app-layout"; import { ProfileAuthWrapper } from "layouts/profile-layout"; // components +import { UserProfileHeader } from "components/headers"; import { ProfileIssuesView } from "components/profile"; // types import type { NextPage } from "next"; const ProfileSubscribedIssues: NextPage = () => ( - + }> - + ); export default ProfileSubscribedIssues; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx index cc709d598..99a7f01ef 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/automations.tsx @@ -7,7 +7,8 @@ import useSWR, { mutate } from "swr"; // services import { ProjectService } from "services/project"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // hooks import useUserAuth from "hooks/use-user-auth"; import useProjectDetails from "hooks/use-project-details"; @@ -70,15 +71,17 @@ const AutomationsSettings: NextPage = () => { const isAdmin = memberDetails?.role === 20; return ( - }> -
-
-

Automations

-
- - -
-
+ } withProjectWrapper> + +
+
+

Automations

+
+ + +
+
+
); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx index 125142cf2..0bfbd04b0 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/estimates.tsx @@ -7,7 +7,8 @@ import { ProjectService, ProjectEstimateService } from "services/project"; // hooks import useProjectDetails from "hooks/use-project-details"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // components import { CreateUpdateEstimateModal, SingleEstimate } from "components/estimates"; import { ProjectSettingHeader } from "components/headers"; @@ -98,18 +99,17 @@ const EstimatesSettings: NextPage = () => { }; return ( - <> - { - setEstimateFormOpen(false); - setEstimateToUpdate(undefined); - }} - user={user} - /> - - }> + } withProjectWrapper> + + { + setEstimateFormOpen(false); + setEstimateToUpdate(undefined); + }} + user={user} + />

Estimates

@@ -172,7 +172,7 @@ const EstimatesSettings: NextPage = () => { )}
- +
); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx index 2e232e1b0..41878525c 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx @@ -6,7 +6,8 @@ import useSWR, { mutate } from "swr"; import { ProjectService } from "services/project"; import { TrackEventService, MiscellaneousEventType } from "services/track_event.service"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // hooks import useToast from "hooks/use-toast"; import useUserAuth from "hooks/use-user-auth"; @@ -136,52 +137,54 @@ const FeaturesSettings: NextPage = () => { const isAdmin = memberDetails?.role === 20; return ( - }> -
-
-

Features

-
-
- {featuresList.map((feature) => ( -
-
-
- {feature.icon} -
-
-

{feature.title}

-

{feature.description}

+ } withProjectWrapper> + +
+
+

Features

+
+
+ {featuresList.map((feature) => ( +
+
+
+ {feature.icon} +
+
+

{feature.title}

+

{feature.description}

+
+ { + trackEventService.trackMiscellaneousEvent( + { + workspaceId: (projectDetails?.workspace as any)?.id, + workspaceSlug, + projectId, + projectIdentifier: projectDetails?.identifier, + projectName: projectDetails?.name, + }, + getEventType(feature.title, !projectDetails?.[feature.property as keyof IProject]), + user as IUser + ); + handleSubmit({ + [feature.property]: !projectDetails?.[feature.property as keyof IProject], + }); + }} + disabled={!isAdmin} + size="sm" + />
- { - trackEventService.trackMiscellaneousEvent( - { - workspaceId: (projectDetails?.workspace as any)?.id, - workspaceSlug, - projectId, - projectIdentifier: projectDetails?.identifier, - projectName: projectDetails?.name, - }, - getEventType(feature.title, !projectDetails?.[feature.property as keyof IProject]), - user as IUser - ); - handleSubmit({ - [feature.property]: !projectDetails?.[feature.property as keyof IProject], - }); - }} - disabled={!isAdmin} - size="sm" - /> -
- ))} -
-
-
+ ))} +
+ + + ); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx index 26b3ae90c..b78d44970 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx @@ -3,7 +3,8 @@ import { useRouter } from "next/router"; import useSWR from "swr"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // components import { ProjectSettingHeader } from "components/headers"; import { @@ -18,9 +19,6 @@ import type { NextPage } from "next"; import { useMobxStore } from "lib/mobx/store-provider"; import { observer } from "mobx-react-lite"; -// services -// const projectService = new ProjectService(); - const GeneralSettings: NextPage = observer(() => { const { project: projectStore } = useMobxStore(); // states @@ -42,33 +40,34 @@ const GeneralSettings: NextPage = observer(() => { // const selectedNetwork = NETWORK_CHOICES.find((n) => n.key === watch("network")); const isAdmin = projectDetails?.member_role === 20; - console.log("isAdmin", isAdmin); return ( - }> - {projectDetails && ( - setSelectedProject(null)} - /> - )} - -
- {projectDetails && workspaceSlug ? ( - - ) : ( - - )} - - {isAdmin && ( - setSelectedProject(projectDetails.id ?? null)} + } withProjectWrapper> + + {projectDetails && ( + setSelectedProject(null)} /> )} -
-
+ +
+ {projectDetails && workspaceSlug ? ( + + ) : ( + + )} + + {isAdmin && ( + setSelectedProject(projectDetails.id ?? null)} + /> + )} +
+ + ); }); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx index 7daa2cec1..0011ceff8 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx @@ -5,7 +5,8 @@ import { useRouter } from "next/router"; import useSWR from "swr"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // services import { IntegrationService } from "services/integrations"; import { ProjectService } from "services/project"; @@ -50,40 +51,42 @@ const ProjectIntegrations: NextPage = () => { const isAdmin = projectDetails?.member_role === 20; return ( - }> -
-
-

Integrations

-
- {workspaceIntegrations ? ( - workspaceIntegrations.length > 0 ? ( -
- {workspaceIntegrations.map((integration) => ( - - ))} -
+ }> + +
+
+

Integrations

+
+ {workspaceIntegrations ? ( + workspaceIntegrations.length > 0 ? ( +
+ {workspaceIntegrations.map((integration) => ( + + ))} +
+ ) : ( + router.push(`/${workspaceSlug}/settings/integrations`), + }} + disabled={!isAdmin} + /> + ) ) : ( - router.push(`/${workspaceSlug}/settings/integrations`), - }} - disabled={!isAdmin} - /> - ) - ) : ( - - - - - - - )} -
-
+ + + + + + + )} +
+
+ ); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx index 222cbc90a..6b0ff25e1 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/labels.tsx @@ -9,7 +9,8 @@ import useUserAuth from "hooks/use-user-auth"; // services import { IssueLabelService } from "services/issue"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // components import { CreateUpdateLabelInline, @@ -92,43 +93,60 @@ const LabelsSettings: NextPage = () => { onClose={() => setSelectDeleteLabel(null)} user={user} /> - }> -
-
-

Labels

+ }> + +
+
+

Labels

- -
-
- {labelForm && ( - { - setLabelForm(false); - setIsUpdating(false); - setLabelToUpdate(null); - }} - ref={scrollToRef} - /> - )} - <> - {issueLabels ? ( - issueLabels.length > 0 ? ( - issueLabels.map((label) => { - const children = issueLabels?.filter((l) => l.parent === label.id); + +
+
+ {labelForm && ( + { + setLabelForm(false); + setIsUpdating(false); + setLabelToUpdate(null); + }} + ref={scrollToRef} + /> + )} + <> + {issueLabels ? ( + issueLabels.length > 0 ? ( + issueLabels.map((label) => { + const children = issueLabels?.filter((l) => l.parent === label.id); - if (children && children.length === 0) { - if (!label.parent) + if (children && children.length === 0) { + if (!label.parent) + return ( + addLabelToGroup(label)} + editLabel={(label) => { + editLabel(label); + scrollToRef.current?.scrollIntoView({ + behavior: "smooth", + }); + }} + handleLabelDelete={() => setSelectDeleteLabel(label)} + /> + ); + } else return ( - addLabelToGroup(label)} + labelChildren={children} + addLabelToGroup={addLabelToGroup} editLabel={(label) => { editLabel(label); scrollToRef.current?.scrollIntoView({ @@ -136,49 +154,34 @@ const LabelsSettings: NextPage = () => { }); }} handleLabelDelete={() => setSelectDeleteLabel(label)} + user={user} /> ); - } else - return ( - { - editLabel(label); - scrollToRef.current?.scrollIntoView({ - behavior: "smooth", - }); - }} - handleLabelDelete={() => setSelectDeleteLabel(label)} - user={user} - /> - ); - }) + }) + ) : ( + newLabel(), + }} + /> + ) ) : ( - newLabel(), - }} - /> - ) - ) : ( - - - - - - - )} - -
-
-
+ + + + + + + )} + +
+
+
+ ); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx index a23ac5f5f..7a0b34197 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/members.tsx @@ -12,7 +12,8 @@ import useProjectMembers from "hooks/use-project-members"; import useProjectDetails from "hooks/use-project-details"; import { Controller, useForm } from "react-hook-form"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // components import ConfirmProjectMemberRemove from "components/project/confirm-project-member-remove"; import SendProjectInvitationModal from "components/project/send-project-invitation-modal"; @@ -196,234 +197,239 @@ const MembersSettings: NextPage = () => { const isAdmin = memberDetails?.role === 20; return ( - }> - { - setSelectedRemoveMember(null); - setSelectedInviteRemoveMember(null); - }} - data={members.find((item) => item.id === selectedRemoveMember || item.id === selectedInviteRemoveMember)} - handleDelete={async () => { - if (!activeWorkspace || !projectDetails) return; - if (selectedRemoveMember) { - await projectService.deleteProjectMember(activeWorkspace.slug, projectDetails.id, selectedRemoveMember); - mutateMembers((prevData: any) => prevData?.filter((item: any) => item.id !== selectedRemoveMember), false); - } - if (selectedInviteRemoveMember) { - await projectInvitationService.deleteProjectInvitation( - activeWorkspace.slug, - projectDetails.id, - selectedInviteRemoveMember - ); - mutateInvitations( - (prevData: any) => prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember), - false - ); - } - setToastAlert({ - type: "success", - message: "Member removed successfully", - title: "Success", - }); - }} - /> - mutateMembers()} - /> -
-
-

Defaults

-
-
-
-
-

Project Lead

-
- {projectDetails ? ( - ( - { - submitChanges({ project_lead: val }); - }} - isDisabled={!isAdmin} - /> - )} - /> - ) : ( - - - - )} + }> + + { + setSelectedRemoveMember(null); + setSelectedInviteRemoveMember(null); + }} + data={members.find((item) => item.id === selectedRemoveMember || item.id === selectedInviteRemoveMember)} + handleDelete={async () => { + if (!activeWorkspace || !projectDetails) return; + if (selectedRemoveMember) { + await projectService.deleteProjectMember(activeWorkspace.slug, projectDetails.id, selectedRemoveMember); + mutateMembers( + (prevData: any) => prevData?.filter((item: any) => item.id !== selectedRemoveMember), + false + ); + } + if (selectedInviteRemoveMember) { + await projectInvitationService.deleteProjectInvitation( + activeWorkspace.slug, + projectDetails.id, + selectedInviteRemoveMember + ); + mutateInvitations( + (prevData: any) => prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember), + false + ); + } + setToastAlert({ + type: "success", + message: "Member removed successfully", + title: "Success", + }); + }} + /> + mutateMembers()} + /> +
+
+

Defaults

+
+
+
+
+

Project Lead

+
+ {projectDetails ? ( + ( + { + submitChanges({ project_lead: val }); + }} + isDisabled={!isAdmin} + /> + )} + /> + ) : ( + + + + )} +
-
-
-

Default Assignee

-
- {projectDetails ? ( - ( - { - submitChanges({ default_assignee: val }); - }} - isDisabled={!isAdmin} - /> - )} - /> - ) : ( - - - - )} +
+

Default Assignee

+
+ {projectDetails ? ( + ( + { + submitChanges({ default_assignee: val }); + }} + isDisabled={!isAdmin} + /> + )} + /> + ) : ( + + + + )} +
-
-
-

Members

- -
- {!projectMembers || !projectInvitations ? ( - - - - - - - ) : ( -
- {members.length > 0 - ? members.map((member) => ( -
-
- {member.avatar && member.avatar !== "" ? ( -
- {member.display_name} -
- ) : member.display_name || member.email ? ( -
- {(member.display_name || member.email)?.charAt(0)} -
- ) : ( -
- ? -
- )} -
- {member.member ? ( - - - - {member.first_name} {member.last_name} - - ({member.display_name}) - - +
+

Members

+ +
+ {!projectMembers || !projectInvitations ? ( + + + + + + + ) : ( +
+ {members.length > 0 + ? members.map((member) => ( +
+
+ {member.avatar && member.avatar !== "" ? ( +
+ {member.display_name} +
+ ) : member.display_name || member.email ? ( +
+ {(member.display_name || member.email)?.charAt(0)} +
) : ( -

{member.display_name || member.email}

+
+ ? +
)} - {isOwner &&

{member.email}

} +
+ {member.member ? ( + + + + {member.first_name} {member.last_name} + + ({member.display_name}) + + + ) : ( +

{member.display_name || member.email}

+ )} + {isOwner &&

{member.email}

} +
+
+
+ {!member.member && ( +
+ Pending +
+ )} + + + {ROLE[member.role as keyof typeof ROLE]} + + {member.memberId !== user?.id && } +
+ } + value={member.role} + onChange={(value: 5 | 10 | 15 | 20 | undefined) => { + if (!activeWorkspace || !projectDetails) return; + + mutateMembers( + (prevData: any) => + prevData.map((m: any) => (m.id === member.id ? { ...m, role: value } : m)), + false + ); + + projectService + .updateProjectMember(activeWorkspace.slug, projectDetails.id, member.id, { + role: value, + }) + .catch(() => { + setToastAlert({ + type: "error", + title: "Error!", + message: "An error occurred while updating member role. Please try again.", + }); + }); + }} + disabled={ + member.memberId === user?.id || + !member.member || + (currentUser && currentUser.role !== 20 && currentUser.role < member.role) + } + > + {Object.keys(ROLE).map((key) => { + if (currentUser && currentUser.role !== 20 && currentUser.role < parseInt(key)) return null; + + return ( + + <>{ROLE[parseInt(key) as keyof typeof ROLE]} + + ); + })} + + + { + if (member.member) setSelectedRemoveMember(member.id); + else setSelectedInviteRemoveMember(member.id); + }} + > + + + + {member.memberId !== user?.id ? "Remove member" : "Leave project"} + + +
-
- {!member.member && ( -
- Pending -
- )} - - - {ROLE[member.role as keyof typeof ROLE]} - - {member.memberId !== user?.id && } -
- } - value={member.role} - onChange={(value: 5 | 10 | 15 | 20 | undefined) => { - if (!activeWorkspace || !projectDetails) return; - - mutateMembers( - (prevData: any) => - prevData.map((m: any) => (m.id === member.id ? { ...m, role: value } : m)), - false - ); - - projectService - .updateProjectMember(activeWorkspace.slug, projectDetails.id, member.id, { - role: value, - }) - .catch(() => { - setToastAlert({ - type: "error", - title: "Error!", - message: "An error occurred while updating member role. Please try again.", - }); - }); - }} - disabled={ - member.memberId === user?.id || - !member.member || - (currentUser && currentUser.role !== 20 && currentUser.role < member.role) - } - > - {Object.keys(ROLE).map((key) => { - if (currentUser && currentUser.role !== 20 && currentUser.role < parseInt(key)) return null; - - return ( - - <>{ROLE[parseInt(key) as keyof typeof ROLE]} - - ); - })} - - - { - if (member.member) setSelectedRemoveMember(member.id); - else setSelectedInviteRemoveMember(member.id); - }} - > - - - - {member.memberId !== user?.id ? "Remove member" : "Leave project"} - - - -
-
- )) - : null} -
- )} -
-
+ )) + : null} +
+ )} +
+
+ ); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx index af233d013..d27fe1dcc 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx @@ -10,7 +10,8 @@ import { ProjectStateService } from "services/project"; import useProjectDetails from "hooks/use-project-details"; import useUserAuth from "hooks/use-user-auth"; // layouts -import { ProjectSettingLayout } from "layouts/setting-layout/project-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { ProjectSettingLayout } from "layouts/setting-layout"; // components import { CreateUpdateStateInline, DeleteStateModal, SingleState, StateGroup } from "components/states"; import { ProjectSettingHeader } from "components/headers"; @@ -57,81 +58,83 @@ const StatesSettings: NextPage = () => { onClose={() => setSelectDeleteState(null)} user={user} /> - }> -
-
-

States

-
-
- {states && projectDetails && orderedStateGroups ? ( - Object.keys(orderedStateGroups).map((key) => { - if (orderedStateGroups[key].length !== 0) - return ( -
-
-

{key}

- -
-
- {key === activeGroup && ( - { - setActiveGroup(null); - setSelectedState(null); - }} - data={null} - selectedGroup={key as keyof StateGroup} - user={user} - /> - )} - {orderedStateGroups[key].map((state, index) => - state.id !== selectedState ? ( - setSelectedState(state.id)} - handleDeleteState={() => setSelectDeleteState(state.id)} + }> + +
+
+

States

+
+
+ {states && projectDetails && orderedStateGroups ? ( + Object.keys(orderedStateGroups).map((key) => { + if (orderedStateGroups[key].length !== 0) + return ( +
+
+

{key}

+ +
+
+ {key === activeGroup && ( + { + setActiveGroup(null); + setSelectedState(null); + }} + data={null} + selectedGroup={key as keyof StateGroup} user={user} /> - ) : ( -
- { - setActiveGroup(null); - setSelectedState(null); - }} - groupLength={orderedStateGroups[key].length} - data={statesList?.find((state) => state.id === selectedState) ?? null} - selectedGroup={key as keyof StateGroup} + )} + {orderedStateGroups[key].map((state, index) => + state.id !== selectedState ? ( + setSelectedState(state.id)} + handleDeleteState={() => setSelectDeleteState(state.id)} user={user} /> -
- ) - )} + ) : ( +
+ { + setActiveGroup(null); + setSelectedState(null); + }} + groupLength={orderedStateGroups[key].length} + data={statesList?.find((state) => state.id === selectedState) ?? null} + selectedGroup={key as keyof StateGroup} + user={user} + /> +
+ ) + )} +
-
- ); - }) - ) : ( - - - - - - - )} + ); + }) + ) : ( + + + + + + + )} +
-
- + + ); }; diff --git a/web/pages/[workspaceSlug]/settings/billing.tsx b/web/pages/[workspaceSlug]/settings/billing.tsx index 65a645217..8178d000b 100644 --- a/web/pages/[workspaceSlug]/settings/billing.tsx +++ b/web/pages/[workspaceSlug]/settings/billing.tsx @@ -1,6 +1,7 @@ import React from "react"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // component import { WorkspaceSettingHeader } from "components/headers"; // ui @@ -9,24 +10,26 @@ import { Button } from "@plane/ui"; import type { NextPage } from "next"; const BillingSettings: NextPage = () => ( - }> -
-
-
-

Billing & Plans

-
-
-
+ }> + +
-

Current plan

-

You are currently using the free plan

- - - +
+

Billing & Plans

+
-
-
-
+
+
+

Current plan

+

You are currently using the free plan

+ + + +
+
+ + + ); export default BillingSettings; diff --git a/web/pages/[workspaceSlug]/settings/exports.tsx b/web/pages/[workspaceSlug]/settings/exports.tsx index 97e599094..58380df8e 100644 --- a/web/pages/[workspaceSlug]/settings/exports.tsx +++ b/web/pages/[workspaceSlug]/settings/exports.tsx @@ -1,20 +1,24 @@ +// layout +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components +import { WorkspaceSettingHeader } from "components/headers"; import ExportGuide from "components/exporter/guide"; // types import type { NextPage } from "next"; // helper -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; -import { WorkspaceSettingHeader } from "components/headers"; const ImportExport: NextPage = () => ( - }> -
-
-

Exports

+ }> + +
+
+

Exports

+
+
- -
- + + ); export default ImportExport; diff --git a/web/pages/[workspaceSlug]/settings/imports.tsx b/web/pages/[workspaceSlug]/settings/imports.tsx index 5263a97b7..033a85848 100644 --- a/web/pages/[workspaceSlug]/settings/imports.tsx +++ b/web/pages/[workspaceSlug]/settings/imports.tsx @@ -1,20 +1,23 @@ // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components +import { AppLayout } from "layouts/app-layout"; import IntegrationGuide from "components/integration/guide"; import { WorkspaceSettingHeader } from "components/headers"; // types import type { NextPage } from "next"; const ImportExport: NextPage = () => ( - }> -
-
-

Imports

-
- -
-
+ }> + +
+
+

Imports

+
+ +
+
+
); export default ImportExport; diff --git a/web/pages/[workspaceSlug]/settings/index.tsx b/web/pages/[workspaceSlug]/settings/index.tsx index 35fb220e8..5ccd4ed9e 100644 --- a/web/pages/[workspaceSlug]/settings/index.tsx +++ b/web/pages/[workspaceSlug]/settings/index.tsx @@ -13,7 +13,8 @@ import { FileService } from "services/file.service"; import useToast from "hooks/use-toast"; import useUserAuth from "hooks/use-user-auth"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components import { ImageUploadModal } from "components/core"; import { DeleteWorkspaceModal } from "components/workspace"; @@ -152,207 +153,209 @@ const WorkspaceSettings: NextPage = () => { const isAdmin = memberDetails?.role === 20; return ( - }> - setIsImageUploadModalOpen(false)} - isRemoving={isImageRemoving} - handleDelete={() => handleDelete(activeWorkspace?.logo)} - onSuccess={(imageUrl) => { - setIsImageUploading(true); - setValue("logo", imageUrl); - setIsImageUploadModalOpen(false); - handleSubmit(onSubmit)().then(() => setIsImageUploading(false)); - }} - value={watch("logo")} - /> - { - setIsOpen(false); - }} - data={activeWorkspace ?? null} - user={user} - /> - {activeWorkspace ? ( -
-
-
- -
-
-

{watch("name")}

- {`${ - typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "") - }/${activeWorkspace.slug}`} -
-
-
-
- -
-
-
-

Workspace Name

- ( - - )} - /> -
- -
-

Company Size

- ( - c === value) ?? "Select organization size"} - width="w-full" - input - disabled={!isAdmin} - > - {ORGANIZATION_SIZE?.map((item) => ( - - {item} - - ))} - - )} - /> -
- -
-

Workspace URL

- ( - - )} - /> -
-
- -
- -
-
- {isAdmin && ( - - {({ open }) => ( -
- +

{watch("name")}

+ {`${ + typeof window !== "undefined" && window.location.origin.replace("http://", "").replace("https://", "") + }/${activeWorkspace.slug}`} +
+ -
-
- - + {watch("logo") && watch("logo") !== null && watch("logo") !== "" ? ( + <> + + Edit logo + + ) : ( + "Upload logo" + )} +
- )} - - )} -
- ) : ( -
- -
- )} -
+
+
+ +
+
+
+

Workspace Name

+ ( + + )} + /> +
+ +
+

Company Size

+ ( + c === value) ?? "Select organization size"} + width="w-full" + input + disabled={!isAdmin} + > + {ORGANIZATION_SIZE?.map((item) => ( + + {item} + + ))} + + )} + /> +
+ +
+

Workspace URL

+ ( + + )} + /> +
+
+ +
+ +
+
+ {isAdmin && ( + + {({ open }) => ( +
+ + Delete Workspace + {/* */} + {open ? : } + + + + +
+ + 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. + +
+ +
+
+
+
+
+ )} +
+ )} +
+ ) : ( +
+ +
+ )} + + ); }; diff --git a/web/pages/[workspaceSlug]/settings/integrations.tsx b/web/pages/[workspaceSlug]/settings/integrations.tsx index 1ec29736e..434925c82 100644 --- a/web/pages/[workspaceSlug]/settings/integrations.tsx +++ b/web/pages/[workspaceSlug]/settings/integrations.tsx @@ -7,7 +7,8 @@ import useSWR from "swr"; // services import { IntegrationService } from "services/integrations"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components import { SingleIntegrationCard } from "components/integration"; import { WorkspaceSettingHeader } from "components/headers"; @@ -32,23 +33,25 @@ const WorkspaceIntegrations: NextPage = () => { ); return ( - }> -
- -
- {appIntegrations ? ( - appIntegrations.map((integration) => ( - - )) - ) : ( - - - - - )} -
-
-
+ }> + +
+ +
+ {appIntegrations ? ( + appIntegrations.map((integration) => ( + + )) + ) : ( + + + + + )} +
+
+
+
); }; diff --git a/web/pages/[workspaceSlug]/settings/members.tsx b/web/pages/[workspaceSlug]/settings/members.tsx index 0a2cc7cc9..4c055b687 100644 --- a/web/pages/[workspaceSlug]/settings/members.tsx +++ b/web/pages/[workspaceSlug]/settings/members.tsx @@ -12,7 +12,8 @@ import useToast from "hooks/use-toast"; import useUser from "hooks/use-user"; import useWorkspaceMembers from "hooks/use-workspace-members"; // layouts -import { WorkspaceSettingLayout } from "layouts/setting-layout/workspace-setting-layout"; +import { AppLayout } from "layouts/app-layout"; +import { WorkspaceSettingLayout } from "layouts/setting-layout"; // components import ConfirmWorkspaceMemberRemove from "components/workspace/confirm-workspace-member-remove"; import SendWorkspaceInvitationModal from "components/workspace/send-workspace-invitation-modal"; @@ -92,218 +93,220 @@ const MembersSettings: NextPage = () => { }; return ( - }> - { - setSelectedRemoveMember(null); - setSelectedInviteRemoveMember(null); - }} - data={ - selectedRemoveMember - ? members.find((item) => item.id === selectedRemoveMember) - : selectedInviteRemoveMember - ? members.find((item) => item.id === selectedInviteRemoveMember) - : null - } - handleDelete={async () => { - if (!workspaceSlug) return; - if (selectedRemoveMember) { - workspaceService - .deleteWorkspaceMember(workspaceSlug as string, selectedRemoveMember) - .catch((err) => { - const error = err?.error; - setToastAlert({ - type: "error", - title: "Error", - message: error || "Something went wrong", - }); - }) - .finally(() => { - mutateMembers((prevData: any) => prevData?.filter((item: any) => item.id !== selectedRemoveMember)); - }); + }> + + { + setSelectedRemoveMember(null); + setSelectedInviteRemoveMember(null); + }} + data={ + selectedRemoveMember + ? members.find((item) => item.id === selectedRemoveMember) + : selectedInviteRemoveMember + ? members.find((item) => item.id === selectedInviteRemoveMember) + : null } - if (selectedInviteRemoveMember) { - mutateInvitations( - (prevData: any) => prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember), - false - ); - workspaceService - .deleteWorkspaceInvitations(workspaceSlug as string, selectedInviteRemoveMember) - .then(() => { - setToastAlert({ - type: "success", - title: "Success", - message: "Member removed successfully", + handleDelete={async () => { + if (!workspaceSlug) return; + if (selectedRemoveMember) { + workspaceService + .deleteWorkspaceMember(workspaceSlug as string, selectedRemoveMember) + .catch((err) => { + const error = err?.error; + setToastAlert({ + type: "error", + title: "Error", + message: error || "Something went wrong", + }); + }) + .finally(() => { + mutateMembers((prevData: any) => prevData?.filter((item: any) => item.id !== selectedRemoveMember)); }); - }) - .catch((err) => { - const error = err?.error; - setToastAlert({ - type: "error", - title: "Error", - message: error || "Something went wrong", + } + if (selectedInviteRemoveMember) { + mutateInvitations( + (prevData: any) => prevData?.filter((item: any) => item.id !== selectedInviteRemoveMember), + false + ); + workspaceService + .deleteWorkspaceInvitations(workspaceSlug as string, selectedInviteRemoveMember) + .then(() => { + setToastAlert({ + type: "success", + title: "Success", + message: "Member removed successfully", + }); + }) + .catch((err) => { + const error = err?.error; + setToastAlert({ + type: "error", + title: "Error", + message: error || "Something went wrong", + }); + }) + .finally(() => { + mutateInvitations(); }); - }) - .finally(() => { - mutateInvitations(); - }); - } - setSelectedRemoveMember(null); - setSelectedInviteRemoveMember(null); - }} - /> - -
-
-

Members

- -
- {!workspaceMembers || !workspaceInvitations ? ( - - - - - - - ) : ( -
- {members.length > 0 - ? members.map((member) => ( -
-
- {member.avatar && member.avatar !== "" ? ( - - - {member.display_name - - - ) : member.display_name || member.email ? ( - - - {(member.display_name || member.email)?.charAt(0)} - - - ) : ( -
- ? -
- )} -
- {member.member ? ( + } + setSelectedRemoveMember(null); + setSelectedInviteRemoveMember(null); + }} + /> + +
+
+

Members

+ +
+ {!workspaceMembers || !workspaceInvitations ? ( + + + + + + + ) : ( +
+ {members.length > 0 + ? members.map((member) => ( +
+
+ {member.avatar && member.avatar !== "" ? ( - - - {member.first_name} {member.last_name} - - ({member.display_name}) + + {member.display_name + + + ) : member.display_name || member.email ? ( + + + {(member.display_name || member.email)?.charAt(0)} ) : ( -

{member.display_name || member.email}

+
+ ? +
)} - {isOwner &&

{member.email}

} +
+ {member.member ? ( + + + + {member.first_name} {member.last_name} + + ({member.display_name}) + + + ) : ( +

{member.display_name || member.email}

+ )} + {isOwner &&

{member.email}

} +
+
+
+ {!member?.status && ( +
+

Pending

+
+ )} + {member?.status && !member?.accountCreated && ( +
+

Account not created

+
+ )} + + + {ROLE[member.role as keyof typeof ROLE]} + + {member.memberId !== user?.id && } +
+ } + value={member.role} + onChange={(value: 5 | 10 | 15 | 20 | undefined) => { + if (!workspaceSlug) return; + + mutateMembers( + (prevData: any) => + prevData?.map((m: any) => (m.id === member.id ? { ...m, role: value } : m)), + false + ); + + workspaceService + .updateWorkspaceMember(workspaceSlug?.toString(), member.id, { + role: value, + }) + .catch(() => { + setToastAlert({ + type: "error", + title: "Error!", + message: "An error occurred while updating member role. Please try again.", + }); + }); + }} + disabled={ + member.memberId === currentUser?.member.id || + !member.status || + (currentUser && currentUser.role !== 20 && currentUser.role < member.role) + } + > + {Object.keys(ROLE).map((key) => { + if (currentUser && currentUser.role !== 20 && currentUser.role < parseInt(key)) return null; + + return ( + + <>{ROLE[parseInt(key) as keyof typeof ROLE]} + + ); + })} + + + { + if (member.member) { + setSelectedRemoveMember(member.id); + } else { + setSelectedInviteRemoveMember(member.id); + } + }} + > + + + + {user?.id === member.memberId ? "Leave" : "Remove member"} + + +
-
- {!member?.status && ( -
-

Pending

-
- )} - {member?.status && !member?.accountCreated && ( -
-

Account not created

-
- )} - - - {ROLE[member.role as keyof typeof ROLE]} - - {member.memberId !== user?.id && } -
- } - value={member.role} - onChange={(value: 5 | 10 | 15 | 20 | undefined) => { - if (!workspaceSlug) return; - - mutateMembers( - (prevData: any) => - prevData?.map((m: any) => (m.id === member.id ? { ...m, role: value } : m)), - false - ); - - workspaceService - .updateWorkspaceMember(workspaceSlug?.toString(), member.id, { - role: value, - }) - .catch(() => { - setToastAlert({ - type: "error", - title: "Error!", - message: "An error occurred while updating member role. Please try again.", - }); - }); - }} - disabled={ - member.memberId === currentUser?.member.id || - !member.status || - (currentUser && currentUser.role !== 20 && currentUser.role < member.role) - } - > - {Object.keys(ROLE).map((key) => { - if (currentUser && currentUser.role !== 20 && currentUser.role < parseInt(key)) return null; - - return ( - - <>{ROLE[parseInt(key) as keyof typeof ROLE]} - - ); - })} - - - { - if (member.member) { - setSelectedRemoveMember(member.id); - } else { - setSelectedInviteRemoveMember(member.id); - } - }} - > - - - - {user?.id === member.memberId ? "Leave" : "Remove member"} - - - -
-
- )) - : null} -
- )} -
-
+ )) + : null} +
+ )} + +
+ ); }; diff --git a/web/pages/[workspaceSlug]/workspace-views/issues.tsx b/web/pages/[workspaceSlug]/workspace-views/issues.tsx deleted file mode 100644 index ef81e86a9..000000000 --- a/web/pages/[workspaceSlug]/workspace-views/issues.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// layouts -import { WorkspaceAuthorizationLayout } from "layouts/auth-layout-legacy"; -// components -// import { WorkspaceIssuesViewOptions } from "components/issues/workspace-views/workspace-issue-view-option"; -// import { WorkspaceViewIssues } from "components/issues/workspace-views/workpace-view-issues"; -// ui -import { PrimaryButton } from "components/ui"; -// icons -import { CheckCircle, Plus } from "lucide-react"; - -const WorkspaceView = () => ( - - - Workspace issues -
- } - right={ -
- {/* */} - { - const e = new KeyboardEvent("keydown", { key: "c" }); - document.dispatchEvent(e); - }} - > - - Add Issue - -
- } - > - {/* */} - -); - -export default WorkspaceView;