Merge pull request #366 from makeplane/style/project_settings

style: project settings pages
This commit is contained in:
Aaryan Khandelwal 2023-03-03 14:04:04 +05:30 committed by GitHub
commit 03a8ad336e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 657 additions and 712 deletions

View File

@ -109,7 +109,7 @@ export const CreateUpdateLabelInline: React.FC<Props> = ({
return ( return (
<div <div
className={`flex items-center gap-2 rounded-md border p-3 md:w-2/3 ${ className={`flex items-center gap-2 rounded-[10px] border bg-white p-5 ${
labelForm ? "" : "hidden" labelForm ? "" : "hidden"
}`} }`}
> >

View File

@ -18,16 +18,16 @@ export const SingleLabel: React.FC<Props> = ({
editLabel, editLabel,
handleLabelDelete, handleLabelDelete,
}) => ( }) => (
<div className="gap-2 space-y-3 divide-y rounded-md border p-3 md:w-2/3"> <div className="gap-2 space-y-3 divide-y rounded-[10px] border bg-white p-5">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-3">
<span <span
className="h-3 w-3 flex-shrink-0 rounded-full" className="h-3.5 w-3.5 flex-shrink-0 rounded-full"
style={{ style={{
backgroundColor: label.color && label.color !== "" ? label.color : "#000", backgroundColor: label.color && label.color !== "" ? label.color : "#000",
}} }}
/> />
<h6 className="text-sm">{label.name}</h6> <h6 className="font-medium text-gray-600">{label.name}</h6>
</div> </div>
<CustomMenu ellipsis> <CustomMenu ellipsis>
<CustomMenu.MenuItem onClick={() => addLabelToGroup(label)}> <CustomMenu.MenuItem onClick={() => addLabelToGroup(label)}>

View File

@ -199,7 +199,7 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
className={({ active, selected }) => className={({ active, selected }) =>
`${active ? "bg-indigo-50" : ""} ${ `${active ? "bg-indigo-50" : ""} ${
selected ? "bg-indigo-50 font-medium" : "" selected ? "bg-indigo-50 font-medium" : ""
} text-gray-900 cursor-default select-none p-2` } cursor-default select-none p-2 text-gray-900`
} }
value={{ value={{
id: person.member.id, id: person.member.id,
@ -258,7 +258,7 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
</div> </div>
</div> </div>
</div> </div>
<div className="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3"> <div className="mt-5 flex justify-end gap-2">
<Button theme="secondary" onClick={handleClose}> <Button theme="secondary" onClick={handleClose}>
Cancel Cancel
</Button> </Button>

View File

@ -10,7 +10,7 @@ import useToast from "hooks/use-toast";
// ui // ui
import { CustomSelect } from "components/ui"; import { CustomSelect } from "components/ui";
// icons // icons
import GithubLogo from "public/logos/github-black.png"; import GithubLogo from "public/logos/github-square.png";
// types // types
import { IWorkspaceIntegrations } from "types"; import { IWorkspaceIntegrations } from "types";
// fetch-keys // fetch-keys
@ -85,16 +85,16 @@ export const SingleIntegration: React.FC<Props> = ({ integration }) => {
return ( return (
<> <>
{integration && ( {integration && (
<div className="flex items-center justify-between gap-2 border p-4 rounded-xl"> <div className="flex items-center justify-between gap-2 rounded-[10px] border bg-white p-5">
<div className="flex items-start gap-4"> <div className="flex items-start gap-4">
<div className="h-12 w-12"> <div className="h-12 w-12">
<Image src={GithubLogo} alt="GithubLogo" /> <Image src={GithubLogo} alt="GithubLogo" />
</div> </div>
<div> <div>
<h3 className="flex items-center gap-4 font-semibold text-xl"> <h3 className="flex items-center gap-4 text-xl font-semibold">
{integration.integration_detail.title} {integration.integration_detail.title}
</h3> </h3>
<p className="text-gray-400 text-sm">Select GitHub repository to enable sync.</p> <p className="text-sm text-gray-400">Select GitHub repository to enable sync.</p>
</div> </div>
</div> </div>
<CustomSelect <CustomSelect
@ -127,10 +127,10 @@ export const SingleIntegration: React.FC<Props> = ({ integration }) => {
</CustomSelect.Option> </CustomSelect.Option>
)) ))
) : ( ) : (
<p className="text-gray-400 text-center text-xs">No repositories found</p> <p className="p-2 text-center text-xs text-gray-400">No repositories found</p>
) )
) : ( ) : (
<p className="text-gray-400 text-center text-xs">Loading repositories</p> <p className="p-2 text-center text-xs text-gray-400">Loading repositories...</p>
)} )}
</CustomSelect> </CustomSelect>
</div> </div>

View File

@ -127,7 +127,10 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
}; };
return ( return (
<form onSubmit={handleSubmit(onSubmit)} className="flex items-center gap-x-2 bg-gray-50 p-2"> <form
onSubmit={handleSubmit(onSubmit)}
className="flex items-center gap-x-2 rounded-[10px] bg-white p-5"
>
<div className="h-8 w-8 flex-shrink-0"> <div className="h-8 w-8 flex-shrink-0">
<Popover className="relative flex h-full w-full items-center justify-center rounded-xl bg-gray-200"> <Popover className="relative flex h-full w-full items-center justify-center rounded-xl bg-gray-200">
{({ open }) => ( {({ open }) => (
@ -175,7 +178,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
name="name" name="name"
register={register} register={register}
autoFocus autoFocus
placeholder="Enter state name" placeholder="Name"
validations={{ validations={{
required: true, required: true,
}} }}
@ -210,7 +213,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
id="description" id="description"
name="description" name="description"
register={register} register={register}
placeholder="Enter state description" placeholder="Description"
error={errors.description} error={errors.description}
autoComplete="off" autoComplete="off"
/> />

View File

@ -24,12 +24,12 @@ import { IState } from "types";
import { StateGroup } from "components/states"; import { StateGroup } from "components/states";
// fetch-keys // fetch-keys
import { STATE_LIST } from "constants/fetch-keys"; import { STATE_LIST } from "constants/fetch-keys";
import { getStateGroupIcon } from "components/icons";
type Props = { type Props = {
index: number; index: number;
state: IState; state: IState;
statesList: IState[]; statesList: IState[];
activeGroup: StateGroup;
handleEditState: () => void; handleEditState: () => void;
handleDeleteState: () => void; handleDeleteState: () => void;
}; };
@ -38,7 +38,6 @@ export const SingleState: React.FC<Props> = ({
index, index,
state, state,
statesList, statesList,
activeGroup,
handleEditState, handleEditState,
handleDeleteState, handleDeleteState,
}) => { }) => {
@ -136,16 +135,11 @@ export const SingleState: React.FC<Props> = ({
}; };
return ( return (
<div className="group flex items-center justify-between gap-2 bg-gray-50 p-3"> <div className={`group flex items-center justify-between gap-2 rounded-[10px] bg-white p-5`}>
<div className="flex items-center gap-2"> <div className="flex items-center gap-3">
<span {getStateGroupIcon(state.group, "20", "20", state.color)}
className="h-3 w-3 flex-shrink-0 rounded-full"
style={{
backgroundColor: state.color,
}}
/>
<div> <div>
<h6 className="text-sm">{addSpaceIfCamelCase(state.name)}</h6> <h6 className="font-medium text-gray-600">{addSpaceIfCamelCase(state.name)}</h6>
<p className="text-xs text-gray-400">{state.description}</p> <p className="text-xs text-gray-400">{state.description}</p>
</div> </div>
</div> </div>
@ -153,7 +147,7 @@ export const SingleState: React.FC<Props> = ({
{index !== 0 && ( {index !== 0 && (
<button <button
type="button" type="button"
className="hidden group-hover:inline-block text-gray-400 hover:text-gray-900" className="hidden text-gray-400 hover:text-gray-900 group-hover:inline-block"
onClick={() => handleMove(state, "up")} onClick={() => handleMove(state, "up")}
> >
<ArrowUpIcon className="h-4 w-4" /> <ArrowUpIcon className="h-4 w-4" />
@ -162,7 +156,7 @@ export const SingleState: React.FC<Props> = ({
{!(index === groupLength - 1) && ( {!(index === groupLength - 1) && (
<button <button
type="button" type="button"
className="hidden group-hover:inline-block text-gray-400 hover:text-gray-900" className="hidden text-gray-400 hover:text-gray-900 group-hover:inline-block"
onClick={() => handleMove(state, "down")} onClick={() => handleMove(state, "down")}
> >
<ArrowDownIcon className="h-4 w-4" /> <ArrowDownIcon className="h-4 w-4" />
@ -173,7 +167,7 @@ export const SingleState: React.FC<Props> = ({
) : ( ) : (
<button <button
type="button" type="button"
className="hidden group-hover:inline-block text-xs text-gray-400 hover:text-gray-900" className="hidden text-xs text-gray-400 hover:text-gray-900 group-hover:inline-block"
onClick={handleMakeDefault} onClick={handleMakeDefault}
disabled={isSubmitting} disabled={isSubmitting}
> >

View File

@ -20,7 +20,7 @@ const Sidebar: React.FC<SidebarProps> = ({ toggleSidebar, setToggleSidebar }) =>
return ( return (
<nav className="relative z-20 h-screen"> <nav className="relative z-20 h-screen">
<div <div
className={`${sidebarCollapse ? "" : "w-auto md:w-80"} fixed inset-y-0 top-0 ${ className={`${sidebarCollapse ? "" : "w-auto md:w-72"} fixed inset-y-0 top-0 ${
toggleSidebar ? "left-0" : "-left-60 md:left-0" toggleSidebar ? "left-0" : "-left-60 md:left-0"
} flex h-full flex-col bg-white duration-300 md:relative`} } flex h-full flex-col bg-white duration-300 md:relative`}
> >

View File

@ -19,11 +19,11 @@ import { JoinProject } from "components/project";
import Container from "layouts/container"; import Container from "layouts/container";
import AppSidebar from "layouts/app-layout/app-sidebar"; import AppSidebar from "layouts/app-layout/app-sidebar";
import AppHeader from "layouts/app-layout/app-header"; import AppHeader from "layouts/app-layout/app-header";
import SettingsSidebar from "layouts/settings-layout/settings-sidebar";
// types // types
import { UserAuth } from "types"; import { UserAuth } from "types";
// fetch-keys // fetch-keys
import { PROJECT_MEMBERS } from "constants/fetch-keys"; import { PROJECT_MEMBERS } from "constants/fetch-keys";
import SettingsNavbar from "layouts/settings-navbar";
type Meta = { type Meta = {
title?: string | null; title?: string | null;
@ -41,69 +41,10 @@ type AppLayoutProps = {
breadcrumbs?: JSX.Element; breadcrumbs?: JSX.Element;
left?: JSX.Element; left?: JSX.Element;
right?: JSX.Element; right?: JSX.Element;
settingsLayout?: "project" | "workspace"; settingsLayout?: boolean;
memberType?: UserAuth; memberType?: UserAuth;
}; };
const workspaceLinks: (wSlug: string) => Array<{
label: string;
href: string;
}> = (workspaceSlug) => [
{
label: "General",
href: `/${workspaceSlug}/settings`,
},
{
label: "Members",
href: `/${workspaceSlug}/settings/members`,
},
{
label: "Billing & Plans",
href: `/${workspaceSlug}/settings/billing`,
},
{
label: "Integrations",
href: `/${workspaceSlug}/settings/integrations`,
},
];
const sidebarLinks: (
wSlug?: string,
pId?: string
) => Array<{
label: string;
href: string;
}> = (workspaceSlug, projectId) => [
{
label: "General",
href: `/${workspaceSlug}/projects/${projectId}/settings`,
},
{
label: "Control",
href: `/${workspaceSlug}/projects/${projectId}/settings/control`,
},
{
label: "Members",
href: `/${workspaceSlug}/projects/${projectId}/settings/members`,
},
{
label: "Features",
href: `/${workspaceSlug}/projects/${projectId}/settings/features`,
},
{
label: "States",
href: `/${workspaceSlug}/projects/${projectId}/settings/states`,
},
{
label: "Labels",
href: `/${workspaceSlug}/projects/${projectId}/settings/labels`,
},
{
label: "Integrations",
href: `/${workspaceSlug}/projects/${projectId}/settings/integrations`,
},
];
const AppLayout: FC<AppLayoutProps> = ({ const AppLayout: FC<AppLayoutProps> = ({
meta, meta,
children, children,
@ -113,7 +54,7 @@ const AppLayout: FC<AppLayoutProps> = ({
breadcrumbs, breadcrumbs,
left, left,
right, right,
settingsLayout, settingsLayout = false,
memberType, memberType,
}) => { }) => {
// states // states
@ -179,16 +120,6 @@ const AppLayout: FC<AppLayoutProps> = ({
} }
/> />
) : ( ) : (
<>
{settingsLayout && (
<SettingsSidebar
links={
settingsLayout === "workspace"
? workspaceLinks(workspaceSlug as string)
: sidebarLinks(workspaceSlug as string, projectId as string)
}
/>
)}
<main className="flex h-screen w-full min-w-0 flex-col overflow-y-auto"> <main className="flex h-screen w-full min-w-0 flex-col overflow-y-auto">
{!noHeader && ( {!noHeader && (
<AppHeader <AppHeader
@ -205,7 +136,7 @@ const AppLayout: FC<AppLayoutProps> = ({
) : isMember ? ( ) : isMember ? (
<div <div
className={`w-full flex-grow ${ className={`w-full flex-grow ${
noPadding ? "" : settingsLayout ? "p-9 lg:px-16 lg:pt-10" : "p-9" noPadding ? "" : settingsLayout ? "p-9 lg:px-32 lg:pt-9" : "p-9"
} ${ } ${
bg === "primary" bg === "primary"
? "bg-primary" ? "bg-primary"
@ -214,13 +145,25 @@ const AppLayout: FC<AppLayoutProps> = ({
: "bg-primary" : "bg-primary"
}`} }`}
> >
{settingsLayout && (
<div className="mb-12 space-y-6">
<div>
<h3 className="text-3xl font-semibold">
{projectId ? "Project" : "Workspace"} Settings
</h3>
<p className="mt-1 text-gray-600">
This information will be displayed to every member of the project.
</p>
</div>
<SettingsNavbar />
</div>
)}
{children} {children}
</div> </div>
) : ( ) : (
<JoinProject isJoiningProject={isJoiningProject} handleJoin={handleJoin} /> <JoinProject isJoiningProject={isJoiningProject} handleJoin={handleJoin} />
)} )}
</main> </main>
</>
)} )}
</div> </div>
</Container> </Container>

View File

@ -1,41 +0,0 @@
// next
import Link from "next/link";
import { useRouter } from "next/router";
type Props = {
links: {
label: string;
href: string;
}[];
};
const SettingsSidebar: React.FC<Props> = ({ links }) => {
const router = useRouter();
return (
<nav className="h-screen w-72 border-r border-gray-200">
<div className="mt-16 p-2 pl-6">
<h2 className="flex items-center gap-2 text-lg font-medium leading-5">Settings</h2>
<div className="mt-6 space-y-1">
{links.map((link, index) => (
<h4 key={index}>
<Link href={link.href}>
<a
className={`${
link.href === router.asPath
? "bg-gray-200 text-gray-900"
: "hover:bg-gray-100 focus:bg-gray-100"
} flex items-center gap-3 rounded-md p-2 text-xs font-medium outline-none`}
>
{link.label}
</a>
</Link>
</h4>
))}
</div>
</div>
</nav>
);
};
export default SettingsSidebar;

View File

@ -0,0 +1,85 @@
import Link from "next/link";
import { useRouter } from "next/router";
const SettingsNavbar: React.FC = () => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const workspaceLinks: Array<{
label: string;
href: string;
}> = [
{
label: "General",
href: `/${workspaceSlug}/settings`,
},
{
label: "Members",
href: `/${workspaceSlug}/settings/members`,
},
{
label: "Billing & Plans",
href: `/${workspaceSlug}/settings/billing`,
},
{
label: "Integrations",
href: `/${workspaceSlug}/settings/integrations`,
},
];
const projectLinks: Array<{
label: string;
href: string;
}> = [
{
label: "General",
href: `/${workspaceSlug}/projects/${projectId}/settings`,
},
{
label: "Control",
href: `/${workspaceSlug}/projects/${projectId}/settings/control`,
},
{
label: "Members",
href: `/${workspaceSlug}/projects/${projectId}/settings/members`,
},
{
label: "Features",
href: `/${workspaceSlug}/projects/${projectId}/settings/features`,
},
{
label: "States",
href: `/${workspaceSlug}/projects/${projectId}/settings/states`,
},
{
label: "Labels",
href: `/${workspaceSlug}/projects/${projectId}/settings/labels`,
},
{
label: "Integrations",
href: `/${workspaceSlug}/projects/${projectId}/settings/integrations`,
},
];
return (
<div className="flex flex-wrap gap-4">
{(projectId ? projectLinks : workspaceLinks).map((link) => (
<Link href={link.href}>
<a>
<div
className={`rounded-3xl border px-5 py-1.5 text-sm sm:px-7 sm:py-2 sm:text-base ${
router.asPath === link.href
? "border-theme bg-theme text-white"
: "border-gray-300 bg-white hover:bg-hover-gray"
}`}
>
{link.label}
</div>
</a>
</Link>
))}
</div>
);
};
export default SettingsNavbar;

View File

@ -104,7 +104,6 @@ const ControlSettings: NextPage<TControlSettingsProps> = (props) => {
return ( return (
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -115,18 +114,16 @@ const ControlSettings: NextPage<TControlSettingsProps> = (props) => {
<BreadcrumbItem title="Control Settings" /> <BreadcrumbItem title="Control Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-8"> <div className="space-y-8 sm:space-y-12">
<div> <div className="grid grid-cols-12 items-start gap-4 sm:gap-16">
<h3 className="text-3xl font-bold leading-6 text-gray-900">Control</h3> <div className="col-span-12 sm:col-span-6">
<p className="mt-4 text-sm text-gray-500">Set the control for the project.</p> <h4 className="text-xl font-semibold">Project Lead</h4>
<p className="text-gray-500">Select the project leader.</p>
</div> </div>
<div className="grid grid-cols-12 gap-16"> <div className="col-span-12 sm:col-span-6">
<div className="col-span-5 space-y-16">
<div>
<h4 className="text-md mb-1 leading-6 text-gray-900">Project Lead</h4>
<p className="mb-3 text-sm text-gray-500">Select the project leader.</p>
{projectDetails ? ( {projectDetails ? (
<Controller <Controller
name="project_lead" name="project_lead"
@ -180,12 +177,12 @@ const ControlSettings: NextPage<TControlSettingsProps> = (props) => {
)} )}
</div> </div>
</div> </div>
<div className="col-span-5 space-y-16"> <div className="grid grid-cols-12 items-start gap-4 sm:gap-16">
<div> <div className="col-span-12 sm:col-span-6">
<h4 className="text-md mb-1 leading-6 text-gray-900">Default Assignee</h4> <h4 className="text-xl font-semibold">Default Assignee</h4>
<p className="mb-3 text-sm text-gray-500"> <p className="text-gray-500">Select the default assignee for the project.</p>
Select the default assignee for the project. </div>
</p> <div className="col-span-12 sm:col-span-6">
{projectDetails ? ( {projectDetails ? (
<Controller <Controller
name="default_assignee" name="default_assignee"
@ -239,8 +236,7 @@ const ControlSettings: NextPage<TControlSettingsProps> = (props) => {
)} )}
</div> </div>
</div> </div>
</div> <div className="sm:text-right">
<div>
<Button type="submit" disabled={isSubmitting}> <Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Updating Project..." : "Update Project"} {isSubmitting ? "Updating Project..." : "Update Project"}
</Button> </Button>

View File

@ -20,6 +20,7 @@ import { IProject, UserAuth } from "types";
import type { NextPage, GetServerSidePropsContext } from "next"; import type { NextPage, GetServerSidePropsContext } from "next";
// fetch-keys // fetch-keys
import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys";
import { ContrastIcon, GridViewIcon } from "components/icons";
const FeaturesSettings: NextPage<UserAuth> = (props) => { const FeaturesSettings: NextPage<UserAuth> = (props) => {
const router = useRouter(); const router = useRouter();
@ -77,7 +78,6 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
return ( return (
<AppLayout <AppLayout
settingsLayout="project"
memberType={props} memberType={props}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -88,25 +88,26 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="Features Settings" /> <BreadcrumbItem title="Features Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="space-y-8">
<h3 className="text-2xl font-semibold">Features</h3>
<div className="space-y-5">
<div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-gray-200 bg-white p-6">
<div className="flex items-start gap-3">
<ContrastIcon color="#3f76ff" width={28} height={28} className="flex-shrink-0" />
<div> <div>
<h3 className="text-3xl font-bold leading-6 text-gray-900">Project Features</h3> <h4 className="text-xl font-semibold">Cycles</h4>
</div> <p className="text-gray-500">
<div className="space-y-8 md:w-2/3"> Cycles are enabled for all the projects in this workspace. Access them from the
<div className="flex items-center justify-between gap-x-10 gap-y-2">
<div>
<h4 className="text-md mb-1 leading-6 text-gray-900">Use cycles</h4>
<p className="mb-3 text-sm text-gray-500">
Cycles are enabled for all the projects in this workspace. Access it from the
navigation bar. navigation bar.
</p> </p>
</div> </div>
<div> </div>
<button <button
type="button" type="button"
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${ className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
projectDetails?.cycle_view ? "bg-indigo-500" : "bg-gray-200" projectDetails?.cycle_view ? "bg-green-500" : "bg-gray-200"
}`} }`}
role="switch" role="switch"
aria-checked={projectDetails?.cycle_view} aria-checked={projectDetails?.cycle_view}
@ -121,20 +122,21 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
/> />
</button> </button>
</div> </div>
</div> <div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-gray-200 bg-white p-6">
<div className="flex items-center justify-between gap-x-10 gap-y-2"> <div className="flex items-start gap-3">
<GridViewIcon color="#ff6b00" width={28} height={28} className="flex-shrink-0" />
<div> <div>
<h4 className="text-md mb-1 leading-6 text-gray-900">Use modules</h4> <h4 className="-mt-1.5 text-xl font-semibold">Modules</h4>
<p className="mb-3 text-sm text-gray-500"> <p className="text-gray-500">
Modules are enabled for all the projects in this workspace. Access it from the Modules are enabled for all the projects in this workspace. Access it from the
navigation bar. navigation bar.
</p> </p>
</div> </div>
<div> </div>
<button <button
type="button" type="button"
className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${ className={`relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
projectDetails?.module_view ? "bg-indigo-500" : "bg-gray-200" projectDetails?.module_view ? "bg-green-500" : "bg-gray-200"
}`} }`}
role="switch" role="switch"
aria-checked={projectDetails?.module_view} aria-checked={projectDetails?.module_view}
@ -162,7 +164,6 @@ const FeaturesSettings: NextPage<UserAuth> = (props) => {
</Button> </Button>
</a> </a>
</div> </div>
</div>
</section> </section>
</AppLayout> </AppLayout>
); );

View File

@ -30,6 +30,7 @@ import type { NextPage, GetServerSidePropsContext } from "next";
import { PROJECTS_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys"; import { PROJECTS_LIST, PROJECT_DETAILS, WORKSPACE_DETAILS } from "constants/fetch-keys";
// constants // constants
import { NETWORK_CHOICES } from "constants/project"; import { NETWORK_CHOICES } from "constants/project";
import SettingsNavbar from "layouts/settings-navbar";
const defaultValues: Partial<IProject> = { const defaultValues: Partial<IProject> = {
name: "", name: "",
@ -125,7 +126,6 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
return ( return (
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -136,6 +136,7 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="General Settings" /> <BreadcrumbItem title="General Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<ConfirmProjectDeletion <ConfirmProjectDeletion
data={projectDetails ?? null} data={projectDetails ?? null}
@ -146,21 +147,13 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
}} }}
/> />
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-8"> <div className="space-y-8 sm:space-y-12">
<div> <div className="grid grid-cols-12 items-start gap-4 sm:gap-16">
<h3 className="text-3xl font-bold leading-6 text-gray-900">General</h3> <div className="col-span-12 sm:col-span-6">
<p className="mt-4 text-sm text-gray-500"> <h4 className="text-xl font-semibold">Icon & Name</h4>
This information will be displayed to every member of the project. <p className="text-gray-500">Select an icon and a name for your project.</p>
</p>
</div> </div>
<div className="grid grid-cols-12 gap-16"> <div className="col-span-12 flex gap-2 sm:col-span-6">
<div className="col-span-5 space-y-16">
<div>
<h4 className="text-md mb-1 leading-6 text-gray-900">Icon & Name</h4>
<p className="mb-3 text-sm text-gray-500">
Select an icon and a name for the project.
</p>
<div className="flex gap-2">
{projectDetails ? ( {projectDetails ? (
<Controller <Controller
control={control} control={control}
@ -185,7 +178,6 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
error={errors.name} error={errors.name}
register={register} register={register}
placeholder="Project Name" placeholder="Project Name"
className="w-auto"
validations={{ validations={{
required: "Name is required", required: "Name is required",
}} }}
@ -197,11 +189,12 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
)} )}
</div> </div>
</div> </div>
<div className="grid grid-cols-12 gap-4 sm:gap-16">
<div className="col-span-12 sm:col-span-6">
<h4 className="text-xl font-semibold">Description</h4>
<p className="text-gray-500">Give a description to your project.</p>
</div> </div>
<div className="col-span-5 space-y-16"> <div className="col-span-12 sm:col-span-6">
<div>
<h4 className="text-md mb-1 leading-6 text-gray-900">Description</h4>
<p className="mb-3 text-sm text-gray-500">Give a description to the project.</p>
{projectDetails ? ( {projectDetails ? (
<TextArea <TextArea
id="description" id="description"
@ -219,12 +212,14 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
)} )}
</div> </div>
</div> </div>
<div className="col-span-5 space-y-16"> <div className="grid grid-cols-12 gap-4 sm:gap-16">
<div> <div className="col-span-12 sm:col-span-6">
<h4 className="text-md mb-1 leading-6 text-gray-900">Identifier</h4> <h4 className="text-xl font-semibold">Identifier</h4>
<p className="mb-3 text-sm text-gray-500"> <p className="text-gray-500">
Create a 1-6 characters{"'"} identifier for the project. Create a 1-6 characters{"'"} identifier for the project.
</p> </p>
</div>
<div className="col-span-12 sm:col-span-6">
{projectDetails ? ( {projectDetails ? (
<Input <Input
id="identifier" id="identifier"
@ -232,7 +227,6 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
error={errors.identifier} error={errors.identifier}
register={register} register={register}
placeholder="Enter identifier" placeholder="Enter identifier"
className="w-40"
onChange={(e: any) => { onChange={(e: any) => {
if (!activeWorkspace || !e.target.value) return; if (!activeWorkspace || !e.target.value) return;
checkIdentifierAvailability(activeWorkspace.slug, e.target.value); checkIdentifierAvailability(activeWorkspace.slug, e.target.value);
@ -256,10 +250,12 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
)} )}
</div> </div>
</div> </div>
<div className="col-span-5 space-y-16"> <div className="grid grid-cols-12 gap-4 sm:gap-16">
<div> <div className="col-span-12 sm:col-span-6">
<h4 className="text-md mb-1 leading-6 text-gray-900">Network</h4> <h4 className="text-xl font-semibold">Network</h4>
<p className="mb-3 text-sm text-gray-500">Select privacy type for the project.</p> <p className="text-gray-500">Select privacy type for the project.</p>
</div>
<div className="col-span-12 sm:col-span-6">
{projectDetails ? ( {projectDetails ? (
<Controller <Controller
name="network" name="network"
@ -290,8 +286,7 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
)} )}
</div> </div>
</div> </div>
</div> <div className="sm:text-right">
<div>
{projectDetails ? ( {projectDetails ? (
<Button type="submit" disabled={isSubmitting}> <Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Updating Project..." : "Update Project"} {isSubmitting ? "Updating Project..." : "Update Project"}
@ -302,22 +297,16 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
</Loader> </Loader>
)} )}
</div> </div>
<div className="col-span-12"> <div className="grid grid-cols-12 gap-4 sm:gap-16">
{projectDetails ? ( <div className="col-span-12 sm:col-span-6">
<div> <h4 className="text-xl font-semibold">Danger Zone</h4>
<h4 className="text-md mb-1 leading-6 text-gray-900">Danger Zone</h4> <p className="text-gray-500">
<p className="mb-3 text-sm text-gray-500"> The danger zone of the project delete page is a critical area that requires careful
The danger zone of the project delete page is a critical area that requires consideration and attention. When deleting a project, all of the data and resources
careful consideration and attention. When deleting a project, all of the data and within that project will be permanently removed and cannot be recovered.
resources within that project will be permanently removed and cannot be recovered.
</p> </p>
</div> </div>
) : ( <div className="col-span-12 sm:col-span-6">
<Loader className="w-full space-y-2">
<Loader.Item height="22px" width="250px" light />
<Loader.Item height="46px" width="100%" light />
</Loader>
)}
{projectDetails ? ( {projectDetails ? (
<div> <div>
<OutlineButton <OutlineButton
@ -334,6 +323,7 @@ const GeneralSettings: NextPage<UserAuth> = (props) => {
)} )}
</div> </div>
</div> </div>
</div>
</form> </form>
</AppLayout> </AppLayout>
); );

View File

@ -44,7 +44,6 @@ const ProjectIntegrations: NextPage<UserAuth> = (props) => {
return ( return (
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -55,20 +54,20 @@ const ProjectIntegrations: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="Integrations" /> <BreadcrumbItem title="Integrations" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
{workspaceIntegrations ? ( {workspaceIntegrations ? (
workspaceIntegrations.length > 0 ? ( workspaceIntegrations.length > 0 ? (
<section className="space-y-8"> <section className="space-y-8">
<div> <h3 className="text-2xl font-semibold">Integrations</h3>
<h3 className="text-3xl font-bold leading-6 text-gray-900">Integrations</h3> <div className="space-y-5">
<p className="mt-4 text-sm text-gray-500">Manage the project integrations.</p>
</div>
{workspaceIntegrations.map((integration) => ( {workspaceIntegrations.map((integration) => (
<SingleIntegration <SingleIntegration
key={integration.integration_detail.id} key={integration.integration_detail.id}
integration={integration} integration={integration}
/> />
))} ))}
</div>
</section> </section>
) : ( ) : (
<div className="grid h-full w-full place-items-center px-4 sm:px-0"> <div className="grid h-full w-full place-items-center px-4 sm:px-0">

View File

@ -19,7 +19,7 @@ import {
SingleLabelGroup, SingleLabelGroup,
} from "components/labels"; } from "components/labels";
// ui // ui
import { Button, Loader } from "components/ui"; import { Loader } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// icons // icons
import { PlusIcon } from "@heroicons/react/24/outline"; import { PlusIcon } from "@heroicons/react/24/outline";
@ -28,6 +28,7 @@ import { IIssueLabels, UserAuth } from "types";
import type { GetServerSidePropsContext, NextPage } from "next"; import type { GetServerSidePropsContext, NextPage } from "next";
// fetch-keys // fetch-keys
import { PROJECT_DETAILS, PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; import { PROJECT_DETAILS, PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
import { PrimaryButton } from "components/ui/button/primary-button";
const LabelsSettings: NextPage<UserAuth> = (props) => { const LabelsSettings: NextPage<UserAuth> = (props) => {
const { isMember, isOwner, isViewer, isGuest } = props; const { isMember, isOwner, isViewer, isGuest } = props;
@ -98,7 +99,6 @@ const LabelsSettings: NextPage<UserAuth> = (props) => {
parent={parentLabel} parent={parentLabel}
/> />
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -109,26 +109,28 @@ const LabelsSettings: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="Labels Settings" /> <BreadcrumbItem title="Labels Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="grid grid-cols-12 gap-10">
<div> <div className="col-span-12 sm:col-span-5">
<h3 className="text-3xl font-bold leading-6 text-gray-900">Labels</h3> <h3 className="text-2xl font-semibold">Labels</h3>
<p className="mt-4 text-sm text-gray-500">Manage the labels of this project.</p> <p className="text-gray-500">Manage the labels of this project.</p>
</div> <PrimaryButton onClick={newLabel} size="sm" className="mt-4">
<div className="flex items-center justify-between gap-2 md:w-2/3"> <span className="flex items-center gap-2">
<h4 className="text-md mb-1 leading-6 text-gray-900">Manage labels</h4>
<Button theme="secondary" className="flex items-center gap-x-1" onClick={newLabel}>
<PlusIcon className="h-4 w-4" /> <PlusIcon className="h-4 w-4" />
New label New label
</Button> </span>
</PrimaryButton>
</div> </div>
<div className="space-y-5"> <div className="col-span-12 space-y-5 sm:col-span-7">
{labelForm && (
<CreateUpdateLabelInline <CreateUpdateLabelInline
labelForm={labelForm} labelForm={labelForm}
setLabelForm={setLabelForm} setLabelForm={setLabelForm}
isUpdating={isUpdating} isUpdating={isUpdating}
labelToUpdate={labelToUpdate} labelToUpdate={labelToUpdate}
/> />
)}
<> <>
{issueLabels ? ( {issueLabels ? (
issueLabels.map((label) => { issueLabels.map((label) => {
@ -158,7 +160,7 @@ const LabelsSettings: NextPage<UserAuth> = (props) => {
); );
}) })
) : ( ) : (
<Loader className="space-y-5 md:w-2/3"> <Loader className="space-y-5">
<Loader.Item height="40px" /> <Loader.Item height="40px" />
<Loader.Item height="40px" /> <Loader.Item height="40px" />
<Loader.Item height="40px" /> <Loader.Item height="40px" />

View File

@ -18,7 +18,7 @@ import AppLayout from "layouts/app-layout";
import ConfirmProjectMemberRemove from "components/project/confirm-project-member-remove"; import ConfirmProjectMemberRemove from "components/project/confirm-project-member-remove";
import SendProjectInvitationModal from "components/project/send-project-invitation-modal"; import SendProjectInvitationModal from "components/project/send-project-invitation-modal";
// ui // ui
import { Button, CustomListbox, CustomMenu, Loader } from "components/ui"; import { Button, CustomMenu, CustomSelect, Loader } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// icons // icons
import { PlusIcon } from "@heroicons/react/24/outline"; import { PlusIcon } from "@heroicons/react/24/outline";
@ -158,7 +158,6 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
members={members} members={members}
/> />
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -169,45 +168,41 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
<BreadcrumbItem title="Members Settings" /> <BreadcrumbItem title="Members Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="space-y-8">
<div> <div className="flex items-end justify-between gap-4">
<h3 className="text-3xl font-bold leading-6 text-gray-900">Members</h3> <h3 className="text-2xl font-semibold">Members</h3>
<p className="mt-4 text-sm text-gray-500">Manage all the members of the project.</p> <button
type="button"
className="flex items-center gap-2 text-theme outline-none"
onClick={() => setInviteModal(true)}
>
<PlusIcon className="h-4 w-4" />
Add Member
</button>
</div> </div>
{!projectMembers || !projectInvitations ? ( {!projectMembers || !projectInvitations ? (
<Loader className="space-y-5 md:w-2/3"> <Loader className="space-y-5">
<Loader.Item height="40px" /> <Loader.Item height="40px" />
<Loader.Item height="40px" /> <Loader.Item height="40px" />
<Loader.Item height="40px" /> <Loader.Item height="40px" />
<Loader.Item height="40px" /> <Loader.Item height="40px" />
</Loader> </Loader>
) : ( ) : (
<div className="md:w-2/3"> <div className="divide-y rounded-[10px] border border-gray-200 bg-white px-6">
<div className="flex items-center justify-between gap-2">
<h4 className="text-md mb-1 leading-6 text-gray-900">Manage members</h4>
<Button
theme="secondary"
className="flex items-center gap-x-1"
onClick={() => setInviteModal(true)}
>
<PlusIcon className="h-4 w-4" />
Add Member
</Button>
</div>
<div className="mt-6 space-y-6">
{members.length > 0 {members.length > 0
? members.map((member) => ( ? members.map((member) => (
<div key={member.id} className="flex items-center justify-between"> <div key={member.id} className="flex items-center justify-between py-6">
<div className="flex items-center gap-x-8 gap-y-2"> <div className="flex items-center gap-x-8 gap-y-2">
<div className="relative flex h-10 w-10 items-center justify-center rounded bg-gray-700 p-4 capitalize text-white"> <div className="relative flex h-10 w-10 items-center justify-center rounded-lg bg-gray-700 p-4 capitalize text-white">
{member.avatar && member.avatar !== "" ? ( {member.avatar && member.avatar !== "" ? (
<Image <Image
src={member.avatar} src={member.avatar}
alt={member.first_name} alt={member.first_name}
layout="fill" layout="fill"
objectFit="cover" objectFit="cover"
className="rounded" className="rounded-lg"
/> />
) : member.first_name !== "" ? ( ) : member.first_name !== "" ? (
member.first_name.charAt(0) member.first_name.charAt(0)
@ -217,9 +212,9 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
</div> </div>
<div> <div>
<h4 className="text-sm"> <h4 className="text-sm">
{member.first_name} {member.last_name}{" "} {member.first_name} {member.last_name}
</h4> </h4>
<p className="text-xs text-gray-500">{member.email}</p> <p className="mt-0.5 text-xs text-gray-500">{member.email}</p>
</div> </div>
</div> </div>
{!member.member && ( {!member.member && (
@ -228,16 +223,12 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
</span> </span>
)} )}
<div className="flex items-center gap-2 text-xs"> <div className="flex items-center gap-2 text-xs">
{selectedMember === member.id ? ( <CustomSelect
<CustomListbox label={ROLE[member.role as keyof typeof ROLE]}
options={Object.keys(ROLE).map((key) => ({
value: key,
display: ROLE[parseInt(key) as keyof typeof ROLE],
}))}
title={ROLE[member.role as keyof typeof ROLE] ?? "Select Role"}
value={member.role} value={member.role}
onChange={(value) => { onChange={(value: 5 | 10 | 15 | 20 | undefined) => {
if (!activeWorkspace || !projectDetails) return; if (!activeWorkspace || !projectDetails) return;
projectService projectService
.updateProjectMember( .updateProjectMember(
activeWorkspace.slug, activeWorkspace.slug,
@ -256,9 +247,7 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
mutateMembers( mutateMembers(
(prevData: any) => (prevData: any) =>
prevData.map((m: any) => prevData.map((m: any) =>
m.id === selectedMember m.id === member.id ? { ...m, ...res, role: value } : m
? { ...m, ...res, role: value }
: m
), ),
false false
); );
@ -268,36 +257,21 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
console.log(err); console.log(err);
}); });
}} }}
/> >
) : ( {Object.keys(ROLE).map((key) => (
<p>{ROLE[member.role as keyof typeof ROLE] ?? "None"}</p> <CustomSelect.Option value={key}>
)} <>{ROLE[parseInt(key) as keyof typeof ROLE]}</>
</CustomSelect.Option>
))}
</CustomSelect>
<CustomMenu ellipsis> <CustomMenu ellipsis>
<CustomMenu.MenuItem <CustomMenu.MenuItem
onClick={() => { onClick={() => {
if (!member.member) { if (member.member) setSelectedRemoveMember(member.id);
setToastAlert({ else setSelectedInviteRemoveMember(member.id);
type: "error",
message: "You can't edit a pending invitation.",
title: "Error",
});
} else {
setSelectedMember(member.id);
}
}} }}
> >
Edit Remove member
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => {
if (member.member) {
setSelectedRemoveMember(member.id);
} else {
setSelectedInviteRemoveMember(member.id);
}
}}
>
Remove
</CustomMenu.MenuItem> </CustomMenu.MenuItem>
</CustomMenu> </CustomMenu>
</div> </div>
@ -305,7 +279,6 @@ const MembersSettings: NextPage<TMemberSettingsProps> = (props) => {
)) ))
: null} : null}
</div> </div>
</div>
)} )}
</section> </section>
</AppLayout> </AppLayout>

View File

@ -65,7 +65,6 @@ const StatesSettings: NextPage<UserAuth> = (props) => {
onClose={() => setSelectDeleteState(null)} onClose={() => setSelectDeleteState(null)}
/> />
<AppLayout <AppLayout
settingsLayout="project"
memberType={{ isMember, isOwner, isViewer, isGuest }} memberType={{ isMember, isOwner, isViewer, isGuest }}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -76,30 +75,31 @@ const StatesSettings: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="States Settings" /> <BreadcrumbItem title="States Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<div className="space-y-8"> <div className="grid grid-cols-12 gap-10">
<div> <div className="col-span-12 sm:col-span-5">
<h3 className="text-3xl font-bold leading-6 text-gray-900">States</h3> <h3 className="text-2xl font-semibold">States</h3>
<p className="mt-4 text-sm text-gray-500">Manage the states of this project.</p> <p className="text-gray-500">Manage the states of this project.</p>
</div> </div>
<div className="flex flex-col justify-between gap-4"> <div className="col-span-12 space-y-8 sm:col-span-7">
{states && projectDetails ? ( {states && projectDetails ? (
Object.keys(orderedStateGroups).map((key) => { Object.keys(orderedStateGroups).map((key) => {
if (orderedStateGroups[key].length !== 0) if (orderedStateGroups[key].length !== 0)
return ( return (
<div key={key}> <div key={key}>
<div className="mb-2 flex w-full justify-between md:w-2/3"> <div className="mb-2 flex w-full justify-between">
<p className="text-md capitalize leading-6 text-gray-900">{key} states</p> <h4 className="font-medium capitalize">{key}</h4>
<button <button
type="button" type="button"
className="flex items-center gap-2 text-theme outline-none"
onClick={() => setActiveGroup(key as keyof StateGroup)} onClick={() => setActiveGroup(key as keyof StateGroup)}
className="flex items-center gap-2 text-xs text-theme"
> >
<PlusIcon className="h-3 w-3 text-theme" /> <PlusIcon className="h-4 w-4" />
Add Add
</button> </button>
</div> </div>
<div className="space-y-1 rounded-xl border divide-y p-1 md:w-2/3"> <div className="divide-y rounded-[10px] border border-gray-200">
{key === activeGroup && ( {key === activeGroup && (
<CreateUpdateStateInline <CreateUpdateStateInline
onClose={() => { onClose={() => {
@ -117,7 +117,6 @@ const StatesSettings: NextPage<UserAuth> = (props) => {
index={index} index={index}
state={state} state={state}
statesList={statesList} statesList={statesList}
activeGroup={activeGroup}
handleEditState={() => setSelectedState(state.id)} handleEditState={() => setSelectedState(state.id)}
handleDeleteState={() => setSelectDeleteState(state.id)} handleDeleteState={() => setSelectDeleteState(state.id)}
/> />

View File

@ -38,7 +38,6 @@ const BillingSettings: NextPage<TBillingSettingsProps> = (props) => {
return ( return (
<> <>
<AppLayout <AppLayout
settingsLayout="workspace"
memberType={props} memberType={props}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -49,6 +48,7 @@ const BillingSettings: NextPage<TBillingSettingsProps> = (props) => {
<BreadcrumbItem title="Members Settings" /> <BreadcrumbItem title="Members Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="space-y-8">
<div> <div>

View File

@ -105,7 +105,6 @@ const WorkspaceSettings: NextPage<TWorkspaceSettingsProps> = (props) => {
return ( return (
<AppLayout <AppLayout
settingsLayout="workspace"
memberType={props} memberType={props}
meta={{ meta={{
title: "Plane - Workspace Settings", title: "Plane - Workspace Settings",
@ -115,6 +114,7 @@ const WorkspaceSettings: NextPage<TWorkspaceSettingsProps> = (props) => {
<BreadcrumbItem title={`${activeWorkspace?.name ?? "Workspace"} Settings`} /> <BreadcrumbItem title={`${activeWorkspace?.name ?? "Workspace"} Settings`} />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<ImageUploadModal <ImageUploadModal
isOpen={isImageUploadModalOpen} isOpen={isImageUploadModalOpen}

View File

@ -37,7 +37,6 @@ const WorkspaceIntegrations: NextPage<UserAuth> = (props) => {
return ( return (
<> <>
<AppLayout <AppLayout
settingsLayout="workspace"
memberType={props} memberType={props}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -48,6 +47,7 @@ const WorkspaceIntegrations: NextPage<UserAuth> = (props) => {
<BreadcrumbItem title="Integrations" /> <BreadcrumbItem title="Integrations" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="space-y-8">
<div> <div>

View File

@ -138,7 +138,6 @@ const MembersSettings: NextPage<TMembersSettingsProps> = (props) => {
members={members} members={members}
/> />
<AppLayout <AppLayout
settingsLayout="workspace"
memberType={props} memberType={props}
breadcrumbs={ breadcrumbs={
<Breadcrumbs> <Breadcrumbs>
@ -149,6 +148,7 @@ const MembersSettings: NextPage<TMembersSettingsProps> = (props) => {
<BreadcrumbItem title="Members Settings" /> <BreadcrumbItem title="Members Settings" />
</Breadcrumbs> </Breadcrumbs>
} }
settingsLayout
> >
<section className="space-y-8"> <section className="space-y-8">
<div> <div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -4,6 +4,7 @@ module.exports = {
extend: { extend: {
colors: { colors: {
theme: "#3f76ff", theme: "#3f76ff",
"hover-gray": "#f5f5f5",
primary: "#f9fafb", // gray-50 primary: "#f9fafb", // gray-50
secondary: "white", secondary: "white",
}, },

View File

@ -74,7 +74,7 @@ export interface IWorkspaceIntegrations {
id: string; id: string;
integration: string; integration: string;
integration_detail: IIntegrations; integration_detail: IIntegrations;
metadata: anyl; metadata: any;
updated_at: string; updated_at: string;
updated_by: string; updated_by: string;
workspace: string; workspace: string;