style: project settings theming (#936)

* style: project and workspace members theming

* style: project features theming

* style: project settings states theming

* style: project settings labels theming

* style: project settings integrations theming
This commit is contained in:
Aaryan Khandelwal 2023-04-22 23:46:19 +05:30 committed by GitHub
parent c80094581e
commit 169a60723b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 211 additions and 294 deletions

View File

@ -108,28 +108,26 @@ export const CreateUpdateLabelInline = forwardRef<Ref, Props>(function CreateUpd
return ( return (
<div <div
className={`flex items-center gap-2 scroll-m-8 rounded-[10px] border border-brand-base bg-brand-surface-2 p-5 ${ className={`flex scroll-m-8 items-center gap-2 rounded-[10px] border border-brand-base bg-brand-base p-5 ${
labelForm ? "" : "hidden" labelForm ? "" : "hidden"
}`} }`}
ref={ref} ref={ref}
> >
<div className="h-8 w-8 flex-shrink-0"> <div className="h-8 w-8 flex-shrink-0">
<Popover className="relative z-10 flex h-full w-full items-center justify-center rounded-xl bg-brand-surface-2"> <Popover className="relative z-10 flex h-full w-full items-center justify-center">
{({ open }) => ( {({ open }) => (
<> <>
<Popover.Button <Popover.Button
className={`group inline-flex items-center text-base font-medium focus:outline-none focus:ring-2 focus:ring-brand-accent focus:ring-offset-2 ${ className={`group inline-flex items-center text-base font-medium focus:outline-none ${
open ? "text-brand-base" : "text-brand-secondary" open ? "text-brand-base" : "text-brand-secondary"
}`} }`}
> >
{watch("color") && watch("color") !== "" && (
<span <span
className="h-4 w-4 rounded" className="h-5 w-5 rounded"
style={{ style={{
backgroundColor: watch("color") ?? "#000", backgroundColor: watch("color"),
}} }}
/> />
)}
</Popover.Button> </Popover.Button>
<Transition <Transition

View File

@ -66,7 +66,11 @@ export const SingleLabelGroup: React.FC<Props> = ({
}; };
return ( return (
<Disclosure as="div" className="rounded-[10px] border border-brand-base bg-brand-surface-1 p-5 text-brand-base" defaultOpen> <Disclosure
as="div"
className="rounded-[10px] border border-brand-base bg-brand-base p-5 text-brand-base"
defaultOpen
>
{({ open }) => ( {({ open }) => (
<> <>
<div className="flex cursor-pointer items-center justify-between gap-2"> <div className="flex cursor-pointer items-center justify-between gap-2">
@ -74,7 +78,7 @@ export const SingleLabelGroup: React.FC<Props> = ({
<span> <span>
<RectangleGroupIcon className="h-4 w-4" /> <RectangleGroupIcon className="h-4 w-4" />
</span> </span>
<h6 className="font-medium text-brand-base">{label.name}</h6> <h6>{label.name}</h6>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<CustomMenu ellipsis> <CustomMenu ellipsis>
@ -122,7 +126,7 @@ export const SingleLabelGroup: React.FC<Props> = ({
key={child.id} key={child.id}
className="group flex items-center justify-between rounded-md border border-brand-base p-2 text-sm" className="group flex items-center justify-between rounded-md border border-brand-base p-2 text-sm"
> >
<h5 className="flex items-center gap-3 text-brand-base"> <h5 className="flex items-center gap-3">
<span <span
className="h-2.5 w-2.5 flex-shrink-0 rounded-full" className="h-2.5 w-2.5 flex-shrink-0 rounded-full"
style={{ style={{

View File

@ -5,7 +5,7 @@ import { CustomMenu } from "components/ui";
// types // types
import { IIssueLabels } from "types"; import { IIssueLabels } from "types";
//icons //icons
import { RectangleGroupIcon, LinkIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline"; import { RectangleGroupIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
type Props = { type Props = {
label: IIssueLabels; label: IIssueLabels;
@ -20,7 +20,7 @@ export const SingleLabel: React.FC<Props> = ({
editLabel, editLabel,
handleLabelDelete, handleLabelDelete,
}) => ( }) => (
<div className="gap-2 space-y-3 divide-y divide-brand-base rounded-[10px] border border-brand-base bg-brand-surface-1 p-5"> <div className="gap-2 space-y-3 divide-y divide-brand-base rounded-[10px] border border-brand-base bg-brand-base p-5">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span <span
@ -29,7 +29,7 @@ export const SingleLabel: React.FC<Props> = ({
backgroundColor: label.color && label.color !== "" ? label.color : "#000", backgroundColor: label.color && label.color !== "" ? label.color : "#000",
}} }}
/> />
<h6 className="font-medium text-brand-base">{label.name}</h6> <h6 className="text-sm">{label.name}</h6>
</div> </div>
<CustomMenu ellipsis> <CustomMenu ellipsis>
<CustomMenu.MenuItem onClick={() => addLabelToGroup(label)}> <CustomMenu.MenuItem onClick={() => addLabelToGroup(label)}>

View File

@ -18,7 +18,6 @@ import SlackLogo from "public/services/slack.png";
import { IWorkspaceIntegration } from "types"; import { IWorkspaceIntegration } from "types";
// fetch-keys // fetch-keys
import { PROJECT_GITHUB_REPOSITORY } from "constants/fetch-keys"; import { PROJECT_GITHUB_REPOSITORY } from "constants/fetch-keys";
import { comboMatches } from "@blueprintjs/core";
type Props = { type Props = {
integration: IWorkspaceIntegration; integration: IWorkspaceIntegration;
@ -27,14 +26,12 @@ type Props = {
const integrationDetails: { [key: string]: any } = { const integrationDetails: { [key: string]: any } = {
github: { github: {
logo: GithubLogo, logo: GithubLogo,
installed: description: "Select GitHub repository to enable sync.",
"Activate GitHub integrations on individual projects to sync with specific repositories.",
notInstalled: "Connect with GitHub with your Plane workspace to sync project issues.",
}, },
slack: { slack: {
logo: SlackLogo, logo: SlackLogo,
installed: "Activate Slack integrations on individual projects to sync with specific cahnnels.", description:
notInstalled: "Connect with Slack with your Plane workspace to sync project issues.", "Connect your slack channel to this project to get regular updates. Control which notification you want to receive.",
}, },
}; };
@ -67,19 +64,19 @@ export const SingleIntegration: React.FC<Props> = ({ integration }) => {
} = repo; } = repo;
projectService projectService
.syncGiuthubRepository(workspaceSlug as string, projectId as string, integration.id, { .syncGithubRepository(workspaceSlug as string, projectId as string, integration.id, {
name, name,
owner: login, owner: login,
repository_id: id, repository_id: id,
url: html_url, url: html_url,
}) })
.then((res) => { .then(() => {
mutate(PROJECT_GITHUB_REPOSITORY(projectId as string)); mutate(PROJECT_GITHUB_REPOSITORY(projectId as string));
setToastAlert({ setToastAlert({
type: "success", type: "success",
title: "Success!", title: "Success!",
message: `${login}/${name} respository synced with the project successfully.`, message: `${login}/${name} repository synced with the project successfully.`,
}); });
}) })
.catch((err) => { .catch((err) => {
@ -88,7 +85,7 @@ export const SingleIntegration: React.FC<Props> = ({ integration }) => {
setToastAlert({ setToastAlert({
type: "error", type: "error",
title: "Error!", title: "Error!",
message: "Respository could not be synced with the project. Please try again.", message: "Repository could not be synced with the project. Please try again.",
}); });
}); });
}; };
@ -96,24 +93,20 @@ export const SingleIntegration: React.FC<Props> = ({ integration }) => {
return ( return (
<> <>
{integration && ( {integration && (
<div className="flex items-center justify-between gap-2 rounded-[10px] border border-brand-base bg-brand-surface-1 p-5"> <div className="flex items-center justify-between gap-2 rounded-[10px] border border-brand-base bg-brand-base p-5">
<div className="flex items-start gap-4"> <div className="flex items-start gap-4">
<div className="h-12 w-12 flex-shrink-0"> <div className="h-12 w-12 flex-shrink-0">
<Image <Image
src={integrationDetails[integration.integration_detail.provider].logo} src={integrationDetails[integration.integration_detail.provider].logo}
alt="GithubLogo" alt={`${integration.integration_detail.title} Logo`}
/> />
</div> </div>
<div> <div>
<h3 className="flex items-center gap-4 text-xl font-semibold"> <h3 className="flex items-center gap-4 text-xl font-semibold">
{integration.integration_detail.title} {integration.integration_detail.title}
</h3> </h3>
<p className="text-sm text-gray-400"> <p className="text-sm text-brand-secondary">
{integration.integration_detail.provider === "github" {integrationDetails[integration.integration_detail.provider].description}
? "Select GitHub repository to enable sync."
: integration.integration_detail.provider === "slack"
? "Connect your slack channel to this project to get regular updates. Control which notification you want to receive"
: null}
</p> </p>
</div> </div>
</div> </div>

View File

@ -155,7 +155,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
return ( return (
<form <form
onSubmit={handleSubmit(onSubmit)} onSubmit={handleSubmit(onSubmit)}
className="flex items-center gap-x-2 rounded-[10px] bg-brand-surface-1 p-5" className="flex items-center gap-x-2 rounded-[10px] bg-brand-base p-5"
> >
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<Popover className="relative flex h-full w-full items-center justify-center"> <Popover className="relative flex h-full w-full items-center justify-center">
@ -163,7 +163,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({ data, onClose, select
<> <>
<Popover.Button <Popover.Button
className={`group inline-flex items-center text-base font-medium focus:outline-none ${ className={`group inline-flex items-center text-base font-medium focus:outline-none ${
open ? "text-gray-900" : "text-gray-500" open ? "text-brand-base" : "text-brand-secondary"
}`} }`}
> >
{watch("color") && watch("color") !== "" && ( {watch("color") && watch("color") !== "" && (

View File

@ -134,21 +134,19 @@ export const SingleState: React.FC<Props> = ({
}; };
return ( return (
<div <div className="group flex items-center justify-between gap-2 border-brand-base bg-brand-base p-5 first:rounded-t-[10px] last:rounded-b-[10px]">
className={`group flex items-center justify-between gap-2 border-brand-base bg-brand-surface-1 p-5 first:rounded-t-[10px] last:rounded-b-[10px]`}
>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
{getStateGroupIcon(state.group, "20", "20", state.color)} {getStateGroupIcon(state.group, "20", "20", state.color)}
<div> <div>
<h6 className="text-brand-muted-1 font-medium">{addSpaceIfCamelCase(state.name)}</h6> <h6 className="text-sm">{addSpaceIfCamelCase(state.name)}</h6>
<p className="text-xs text-gray-400">{state.description}</p> <p className="text-xs text-brand-secondary">{state.description}</p>
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{index !== 0 && ( {index !== 0 && (
<button <button
type="button" type="button"
className="hidden text-gray-400 hover:text-brand-base group-hover:inline-block" className="hidden text-brand-secondary group-hover:inline-block"
onClick={() => handleMove(state, "up")} onClick={() => handleMove(state, "up")}
> >
<ArrowUpIcon className="h-4 w-4" /> <ArrowUpIcon className="h-4 w-4" />
@ -157,18 +155,18 @@ export const SingleState: React.FC<Props> = ({
{!(index === groupLength - 1) && ( {!(index === groupLength - 1) && (
<button <button
type="button" type="button"
className="hidden text-gray-400 hover:text-brand-base group-hover:inline-block" className="hidden text-brand-secondary group-hover:inline-block"
onClick={() => handleMove(state, "down")} onClick={() => handleMove(state, "down")}
> >
<ArrowDownIcon className="h-4 w-4" /> <ArrowDownIcon className="h-4 w-4" />
</button> </button>
)} )}
{state.default ? ( {state.default ? (
<span className="text-xs text-gray-400">Default</span> <span className="text-xs text-brand-secondary">Default</span>
) : ( ) : (
<button <button
type="button" type="button"
className="hidden text-xs text-gray-400 hover:text-brand-base group-hover:inline-block" className="hidden text-xs text-brand-secondary group-hover:inline-block"
onClick={handleMakeDefault} onClick={handleMakeDefault}
disabled={isSubmitting} disabled={isSubmitting}
> >
@ -177,7 +175,7 @@ export const SingleState: React.FC<Props> = ({
)} )}
<button type="button" className="grid place-items-center" onClick={handleEditState}> <button type="button" className="grid place-items-center" onClick={handleEditState}>
<PencilSquareIcon className="h-4 w-4 text-gray-400" /> <PencilSquareIcon className="h-4 w-4 text-brand-secondary" />
</button> </button>
<button <button
type="button" type="button"
@ -189,14 +187,14 @@ export const SingleState: React.FC<Props> = ({
> >
{state.default ? ( {state.default ? (
<Tooltip tooltipContent="Cannot delete the default state."> <Tooltip tooltipContent="Cannot delete the default state.">
<TrashIcon className="h-4 w-4 text-red-400" /> <TrashIcon className="h-4 w-4 text-red-500" />
</Tooltip> </Tooltip>
) : groupLength === 1 ? ( ) : groupLength === 1 ? (
<Tooltip tooltipContent="Cannot have an empty group."> <Tooltip tooltipContent="Cannot have an empty group.">
<TrashIcon className="h-4 w-4 text-red-400" /> <TrashIcon className="h-4 w-4 text-red-500" />
</Tooltip> </Tooltip>
) : ( ) : (
<TrashIcon className="h-4 w-4 text-red-400" /> <TrashIcon className="h-4 w-4 text-red-500" />
)} )}
</button> </button>
</div> </div>

View File

@ -6,7 +6,7 @@ import useSWR, { mutate } from "swr";
// services // services
import projectService from "services/project.service"; import projectService from "services/project.service";
import trackEventServices from "services/track-event.service"; import trackEventServices, { MiscellaneousEventType } from "services/track-event.service";
// layouts // layouts
import { ProjectAuthorizationWrapper } from "layouts/auth-layout"; import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
// hooks // hooks
@ -23,6 +23,52 @@ import type { NextPage } from "next";
// fetch-keys // fetch-keys
import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys";
const featuresList = [
{
title: "Cycles",
description:
"Cycles are enabled for all the projects in this workspace. Access them from the sidebar.",
icon: <ContrastIcon color="#3f76ff" width={28} height={28} className="flex-shrink-0" />,
property: "cycle_view",
},
{
title: "Modules",
description:
"Modules are enabled for all the projects in this workspace. Access it from the sidebar.",
icon: <PeopleGroupIcon color="#ff6b00" width={28} height={28} className="flex-shrink-0" />,
property: "module_view",
},
{
title: "Views",
description:
"Views are enabled for all the projects in this workspace. Access it from the sidebar.",
icon: <ViewListIcon color="#05c3ff" width={28} height={28} className="flex-shrink-0" />,
property: "issue_views_view",
},
{
title: "Pages",
description:
"Pages are enabled for all the projects in this workspace. Access it from the sidebar.",
icon: <DocumentTextIcon color="#fcbe1d" width={28} height={28} className="flex-shrink-0" />,
property: "page_view",
},
];
const getEventType = (feature: string, toggle: boolean): MiscellaneousEventType => {
switch (feature) {
case "Cycles":
return toggle ? "TOGGLE_CYCLE_ON" : "TOGGLE_CYCLE_OFF";
case "Modules":
return toggle ? "TOGGLE_MODULE_ON" : "TOGGLE_MODULE_OFF";
case "Views":
return toggle ? "TOGGLE_VIEW_ON" : "TOGGLE_VIEW_OFF";
case "Pages":
return toggle ? "TOGGLE_PAGES_ON" : "TOGGLE_PAGES_OFF";
default:
return toggle ? "TOGGLE_PAGES_ON" : "TOGGLE_PAGES_OFF";
}
};
const FeaturesSettings: NextPage = () => { const FeaturesSettings: NextPage = () => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
@ -91,24 +137,27 @@ const FeaturesSettings: NextPage = () => {
<section className="space-y-8"> <section className="space-y-8">
<h3 className="text-2xl font-semibold">Features</h3> <h3 className="text-2xl font-semibold">Features</h3>
<div className="space-y-5"> <div className="space-y-5">
<div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-brand-base bg-brand-surface-1 p-5"> {featuresList.map((feature) => (
<div
key={feature.property}
className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-brand-base bg-brand-base p-5"
>
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<ContrastIcon color="#3F76FF" width={28} height={28} className="flex-shrink-0" /> {feature.icon}
<div> <div>
<h4 className="text-xl font-semibold">Cycles</h4> <h4 className="text-lg font-semibold">{feature.title}</h4>
<p className="text-brand-secondary"> <p className="text-sm text-brand-secondary">{feature.description}</p>
Cycles are enabled for all the projects in this workspace. Access them from the
navigation bar.
</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-green-500" : "bg-brand-surface-2" projectDetails?.[feature.property as keyof IProject]
? "bg-green-500"
: "bg-brand-surface-2"
}`} }`}
role="switch" role="switch"
aria-checked={projectDetails?.cycle_view} aria-checked={projectDetails?.[feature.property as keyof IProject]}
onClick={() => { onClick={() => {
trackEventServices.trackMiscellaneousEvent( trackEventServices.trackMiscellaneousEvent(
{ {
@ -118,143 +167,27 @@ const FeaturesSettings: NextPage = () => {
projectIdentifier: projectDetails?.identifier, projectIdentifier: projectDetails?.identifier,
projectName: projectDetails?.name, projectName: projectDetails?.name,
}, },
!projectDetails?.cycle_view ? "TOGGLE_CYCLE_ON" : "TOGGLE_CYCLE_OFF" !projectDetails?.[feature.property as keyof IProject]
? getEventType(feature.title, true)
: getEventType(feature.title, false)
); );
handleSubmit({ cycle_view: !projectDetails?.cycle_view }); handleSubmit({
[feature.property]: !projectDetails?.[feature.property as keyof IProject],
});
}} }}
> >
<span className="sr-only">Use cycles</span> <span className="sr-only">Use {feature.title}</span>
<span <span
aria-hidden="true" aria-hidden="true"
className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${ className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${
projectDetails?.cycle_view ? "translate-x-5" : "translate-x-0" projectDetails?.[feature.property as keyof IProject]
}`} ? "translate-x-5"
/> : "translate-x-0"
</button>
</div>
<div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-brand-base bg-brand-surface-1 p-5">
<div className="flex items-start gap-3">
<PeopleGroupIcon color="#FF6B00" width={28} height={28} className="flex-shrink-0" />
<div>
<h4 className="-mt-1.5 text-xl font-semibold">Modules</h4>
<p className="text-brand-secondary">
Modules are enabled for all the projects in this workspace. Access it from the
navigation bar.
</p>
</div>
</div>
<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 ${
projectDetails?.module_view ? "bg-green-500" : "bg-brand-surface-2"
}`}
role="switch"
aria-checked={projectDetails?.module_view}
onClick={() => {
trackEventServices.trackMiscellaneousEvent(
{
workspaceId: (projectDetails?.workspace as any)?.id,
workspaceSlug,
projectId,
projectIdentifier: projectDetails?.identifier,
projectName: projectDetails?.name,
},
!projectDetails?.module_view ? "TOGGLE_MODULE_ON" : "TOGGLE_MODULE_OFF"
);
handleSubmit({ module_view: !projectDetails?.module_view });
}}
>
<span className="sr-only">Use cycles</span>
<span
aria-hidden="true"
className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${
projectDetails?.module_view ? "translate-x-5" : "translate-x-0"
}`}
/>
</button>
</div>
<div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-brand-base bg-brand-surface-1 p-5">
<div className="flex items-start gap-3">
<ViewListIcon color="#05C3FF" width={28} height={28} className="flex-shrink-0" />
<div>
<h4 className="-mt-1.5 text-xl font-semibold">Views</h4>
<p className="text-brand-secondary">
Views are enabled for all the projects in this workspace. Access it from the
navigation bar.
</p>
</div>
</div>
<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 ${
projectDetails?.issue_views_view ? "bg-green-500" : "bg-brand-surface-2"
}`}
role="switch"
aria-checked={projectDetails?.issue_views_view}
onClick={() => {
trackEventServices.trackMiscellaneousEvent(
{
workspaceId: (projectDetails?.workspace as any)?.id,
workspaceSlug,
projectId,
projectIdentifier: projectDetails?.identifier,
projectName: projectDetails?.name,
},
!projectDetails?.issue_views_view ? "TOGGLE_VIEW_ON" : "TOGGLE_VIEW_OFF"
);
handleSubmit({ issue_views_view: !projectDetails?.issue_views_view });
}}
>
<span className="sr-only">Use views</span>
<span
aria-hidden="true"
className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${
projectDetails?.issue_views_view ? "translate-x-5" : "translate-x-0"
}`}
/>
</button>
</div>
<div className="flex items-center justify-between gap-x-8 gap-y-2 rounded-[10px] border border-brand-base bg-brand-surface-1 p-5">
<div className="flex items-start gap-3">
<DocumentTextIcon color="#FCBE1D" width={28} height={28} className="flex-shrink-0" />
<div>
<h4 className="text-xl font-semibold">Pages</h4>
<p className="text-brand-secondary">
Pages are enabled for all the projects in this workspace. Access them from the
navigation bar.
</p>
</div>
</div>
<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 ${
projectDetails?.page_view ? "bg-green-500" : "bg-brand-surface-2"
}`}
role="switch"
aria-checked={projectDetails?.page_view}
onClick={() => {
trackEventServices.trackMiscellaneousEvent(
{
workspaceId: (projectDetails?.workspace as any)?.id,
workspaceSlug,
projectId,
projectIdentifier: projectDetails?.identifier,
projectName: projectDetails?.name,
},
!projectDetails?.page_view ? "TOGGLE_PAGES_ON" : "TOGGLE_PAGES_OFF"
);
handleSubmit({ page_view: !projectDetails?.page_view });
}}
>
<span className="sr-only">Use cycles</span>
<span
aria-hidden="true"
className={`inline-block h-5 w-5 transform rounded-full bg-brand-surface-1 shadow ring-0 transition duration-200 ease-in-out ${
projectDetails?.page_view ? "translate-x-5" : "translate-x-0"
}`} }`}
/> />
</button> </button>
</div> </div>
))}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<a href="https://plane.so/" target="_blank" rel="noreferrer"> <a href="https://plane.so/" target="_blank" rel="noreferrer">

View File

@ -10,6 +10,7 @@ import projectService from "services/project.service";
import workspaceService from "services/workspace.service"; import workspaceService from "services/workspace.service";
// hooks // hooks
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
import useProjectDetails from "hooks/use-project-details";
// layouts // layouts
import { ProjectAuthorizationWrapper } from "layouts/auth-layout"; import { ProjectAuthorizationWrapper } from "layouts/auth-layout";
// components // components
@ -23,12 +24,7 @@ import { PlusIcon, XMarkIcon } from "@heroicons/react/24/outline";
// types // types
import type { NextPage } from "next"; import type { NextPage } from "next";
// fetch-keys // fetch-keys
import { import { PROJECT_INVITATIONS, PROJECT_MEMBERS, WORKSPACE_DETAILS } from "constants/fetch-keys";
PROJECT_DETAILS,
PROJECT_INVITATIONS,
PROJECT_MEMBERS,
WORKSPACE_DETAILS,
} from "constants/fetch-keys";
// constants // constants
import { ROLE } from "constants/workspace"; import { ROLE } from "constants/workspace";
@ -48,24 +44,13 @@ const MembersSettings: NextPage = () => {
() => (workspaceSlug ? workspaceService.getWorkspace(workspaceSlug as string) : null) () => (workspaceSlug ? workspaceService.getWorkspace(workspaceSlug as string) : null)
); );
const { data: projectDetails } = useSWR( const { projectDetails } = useProjectDetails();
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
workspaceSlug && projectId
? () => projectService.getProject(workspaceSlug as string, projectId as string)
: null
);
const { data: projectMembers, mutate: mutateMembers } = useSWR( const { data: projectMembers, mutate: mutateMembers } = useSWR(
workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null, workspaceSlug && projectId ? PROJECT_MEMBERS(projectId as string) : null,
workspaceSlug && projectId workspaceSlug && projectId
? () => projectService.projectMembers(workspaceSlug as string, projectId as string) ? () => projectService.projectMembers(workspaceSlug as string, projectId as string)
: null, : null
{
onErrorRetry(err, _, __, revalidate, revalidateOpts) {
if (err?.status === 403) return;
setTimeout(() => revalidate(revalidateOpts), 5000);
},
}
); );
const { data: projectInvitations, mutate: mutateInvitations } = useSWR( const { data: projectInvitations, mutate: mutateInvitations } = useSWR(
@ -176,11 +161,11 @@ const MembersSettings: NextPage = () => {
<Loader.Item height="40px" /> <Loader.Item height="40px" />
</Loader> </Loader>
) : ( ) : (
<div className="divide-y divide-brand-base rounded-[10px] border border-brand-base bg-brand-surface-1 px-6"> <div className="divide-y divide-brand-base rounded-[10px] border border-brand-base bg-brand-base px-6">
{members.length > 0 {members.length > 0
? members.map((member) => ( ? members.map((member) => (
<div key={member.id} className="flex items-center justify-between py-6"> <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-6 gap-y-2">
<div className="relative flex h-10 w-10 items-center justify-center rounded-lg 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
@ -203,12 +188,12 @@ const MembersSettings: NextPage = () => {
<p className="mt-0.5 text-xs text-brand-secondary">{member.email}</p> <p className="mt-0.5 text-xs text-brand-secondary">{member.email}</p>
</div> </div>
</div> </div>
{!member.member && (
<span className="inline-flex items-center rounded-full bg-yellow-100 px-2.5 py-0.5 text-xs font-medium text-yellow-800">
Request Pending
</span>
)}
<div className="flex items-center gap-2 text-xs"> <div className="flex items-center gap-2 text-xs">
{!member.member && (
<div className="mr-2 flex items-center justify-center rounded-full bg-yellow-500/20 px-2 py-1 text-center text-xs text-yellow-500">
Pending
</div>
)}
<CustomSelect <CustomSelect
label={ROLE[member.role as keyof typeof ROLE]} label={ROLE[member.role as keyof typeof ROLE]}
value={member.role} value={member.role}
@ -242,6 +227,7 @@ const MembersSettings: NextPage = () => {
console.log(err); console.log(err);
}); });
}} }}
position="right"
> >
{Object.keys(ROLE).map((key) => ( {Object.keys(ROLE).map((key) => (
<CustomSelect.Option key={key} value={key}> <CustomSelect.Option key={key} value={key}>

View File

@ -110,7 +110,10 @@ const StatesSettings: NextPage = () => {
handleDeleteState={() => setSelectDeleteState(state.id)} handleDeleteState={() => setSelectDeleteState(state.id)}
/> />
) : ( ) : (
<div className="border-b last:border-b-0" key={state.id}> <div
className="border-b border-brand-base last:border-b-0"
key={state.id}
>
<CreateUpdateStateInline <CreateUpdateStateInline
onClose={() => { onClose={() => {
setActiveGroup(null); setActiveGroup(null);

View File

@ -157,7 +157,7 @@ const MembersSettings: NextPage = () => {
<Loader.Item height="40px" /> <Loader.Item height="40px" />
</Loader> </Loader>
) : ( ) : (
<div className="divide-y rounded-[10px] divide-brand-base border border-brand-base bg-brand-surface-1 px-6"> <div className="divide-y divide-brand-base rounded-[10px] border border-brand-base bg-brand-base px-6">
{members.length > 0 {members.length > 0
? members.map((member) => ( ? members.map((member) => (
<div key={member.id} className="flex items-center justify-between py-6"> <div key={member.id} className="flex items-center justify-between py-6">
@ -184,13 +184,12 @@ const MembersSettings: NextPage = () => {
<p className="text-xs text-brand-secondary">{member.email}</p> <p className="text-xs text-brand-secondary">{member.email}</p>
</div> </div>
</div> </div>
<div className="flex items-center"> <div className="flex items-center gap-2 text-xs">
{!member?.status && ( {!member?.status && (
<div className="flex mr-2 px-2 py-1 bg-yellow-200 text-yellow-700 text-center rounded-full text-xs items-center justify-center"> <div className="mr-2 flex items-center justify-center rounded-full bg-yellow-500/20 px-2 py-1 text-center text-xs text-yellow-500">
<p>Pending</p> <p>Pending</p>
</div> </div>
)} )}
<div className="flex items-center gap-2 text-xs">
<CustomSelect <CustomSelect
label={ROLE[member.role as keyof typeof ROLE]} label={ROLE[member.role as keyof typeof ROLE]}
value={member.role} value={member.role}
@ -221,6 +220,7 @@ const MembersSettings: NextPage = () => {
}); });
}); });
}} }}
position="right"
> >
{Object.keys(ROLE).map((key) => ( {Object.keys(ROLE).map((key) => (
<CustomSelect.Option key={key} value={key}> <CustomSelect.Option key={key} value={key}>
@ -243,7 +243,6 @@ const MembersSettings: NextPage = () => {
</CustomMenu> </CustomMenu>
</div> </div>
</div> </div>
</div>
)) ))
: null} : null}
</div> </div>

View File

@ -244,7 +244,7 @@ class ProjectServices extends APIService {
}); });
} }
async syncGiuthubRepository( async syncGithubRepository(
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,
workspaceIntegrationId: string, workspaceIntegrationId: string,

View File

@ -47,7 +47,7 @@ type ViewEventType = "VIEW_CREATE" | "VIEW_UPDATE" | "VIEW_DELETE";
type IssueCommentType = "ISSUE_COMMENT_CREATE" | "ISSUE_COMMENT_UPDATE" | "ISSUE_COMMENT_DELETE"; type IssueCommentType = "ISSUE_COMMENT_CREATE" | "ISSUE_COMMENT_UPDATE" | "ISSUE_COMMENT_DELETE";
type MiscellaneousEventType = export type MiscellaneousEventType =
| "TOGGLE_CYCLE_ON" | "TOGGLE_CYCLE_ON"
| "TOGGLE_CYCLE_OFF" | "TOGGLE_CYCLE_OFF"
| "TOGGLE_MODULE_ON" | "TOGGLE_MODULE_ON"

View File

@ -96,8 +96,11 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
/* scrollbar style */ body {
color: rgba(var(--color-text-base));
}
/* scrollbar style */
::-webkit-scrollbar { ::-webkit-scrollbar {
display: none; display: none;
} }
@ -206,7 +209,7 @@
); );
} }
.progress-bar{ .progress-bar {
fill: currentColor; fill: currentColor;
color: rgba(var(--color-bg-sidebar)); color: rgba(var(--color-bg-sidebar));
} }