mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
[WEB-440] feat: create project feature selection modal. (#3909)
* [WEB-440] feat: create project feature selection modal. * [WEB-399] chore: explain project identifier. * chore: use `Link` component for redirection to project page.
This commit is contained in:
@@ -1,86 +1,91 @@
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRouter } from "next/router";
|
||||
import { ContrastIcon, FileText, Inbox, Layers } from "lucide-react";
|
||||
import { FileText, Inbox } from "lucide-react";
|
||||
// ui
|
||||
import { DiceIcon, ToggleSwitch, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
import { ContrastIcon, DiceIcon, PhotoFilterIcon, ToggleSwitch, setPromiseToast } from "@plane/ui";
|
||||
// hooks
|
||||
import { useEventTracker, useProject, useUser } from "hooks/store";
|
||||
// types
|
||||
import { IProject } from "@plane/types";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
isAdmin: boolean;
|
||||
};
|
||||
|
||||
const PROJECT_FEATURES_LIST = [
|
||||
{
|
||||
title: "Cycles",
|
||||
description: "Cycles are enabled for all the projects in this workspace. Access them from the sidebar.",
|
||||
description: "Time-box issues and boost momentum, similar to sprints in scrum.",
|
||||
icon: <ContrastIcon className="h-4 w-4 flex-shrink-0 rotate-180 text-purple-500" />,
|
||||
property: "cycle_view",
|
||||
},
|
||||
{
|
||||
title: "Modules",
|
||||
description: "Modules are enabled for all the projects in this workspace. Access it from the sidebar.",
|
||||
icon: <DiceIcon width={16} height={16} className="flex-shrink-0" />,
|
||||
description: "Group multiple issues together and track the progress.",
|
||||
icon: <DiceIcon width={16} height={16} className="flex-shrink-0 text-red-500" />,
|
||||
property: "module_view",
|
||||
},
|
||||
{
|
||||
title: "Views",
|
||||
description: "Views are enabled for all the projects in this workspace. Access it from the sidebar.",
|
||||
icon: <Layers className="h-4 w-4 flex-shrink-0 text-cyan-500" />,
|
||||
description: "Apply filters to issues and save them to analyse and investigate work.",
|
||||
icon: <PhotoFilterIcon className="h-4 w-4 flex-shrink-0 text-cyan-500" />,
|
||||
property: "issue_views_view",
|
||||
},
|
||||
{
|
||||
title: "Pages",
|
||||
description: "Pages are enabled for all the projects in this workspace. Access it from the sidebar.",
|
||||
description: "Document ideas, feature requirements, discussions within your project.",
|
||||
icon: <FileText className="h-4 w-4 flex-shrink-0 text-red-400" />,
|
||||
property: "page_view",
|
||||
},
|
||||
{
|
||||
title: "Inbox",
|
||||
description: "Inbox are enabled for all the projects in this workspace. Access it from the issues views page.",
|
||||
description: "Capture external inputs, move valid issues to workflow.",
|
||||
icon: <Inbox className="h-4 w-4 flex-shrink-0 text-fuchsia-500" />,
|
||||
property: "inbox_view",
|
||||
},
|
||||
];
|
||||
|
||||
export const ProjectFeaturesList: FC = observer(() => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
export const ProjectFeaturesList: FC<Props> = observer((props) => {
|
||||
const { workspaceSlug, projectId, isAdmin } = props;
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
const {
|
||||
currentUser,
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const { currentProjectDetails, updateProject } = useProject();
|
||||
const isAdmin = currentProjectRole === EUserProjectRoles.ADMIN;
|
||||
const { currentUser } = useUser();
|
||||
const { getProjectById, updateProject } = useProject();
|
||||
// derived values
|
||||
const currentProjectDetails = getProjectById(projectId);
|
||||
|
||||
const handleSubmit = async (formData: Partial<IProject>) => {
|
||||
if (!workspaceSlug || !projectId || !currentProjectDetails) return;
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Project feature updated successfully.",
|
||||
const updateProjectPromise = updateProject(workspaceSlug, projectId, formData);
|
||||
setPromiseToast(updateProjectPromise, {
|
||||
loading: "Updating project feature...",
|
||||
success: {
|
||||
title: "Success!",
|
||||
message: () => "Project feature updated successfully.",
|
||||
},
|
||||
error: {
|
||||
title: "Error!",
|
||||
message: () => "Something went wrong while updating project feature. Please try again.",
|
||||
},
|
||||
});
|
||||
updateProject(workspaceSlug.toString(), projectId.toString(), formData);
|
||||
};
|
||||
|
||||
if (!currentUser) return <></>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mx-4">
|
||||
{PROJECT_FEATURES_LIST.map((feature) => (
|
||||
<div
|
||||
key={feature.property}
|
||||
className="flex items-center justify-between gap-x-8 gap-y-2 border-b border-custom-border-100 bg-custom-background-100 p-4"
|
||||
className="flex items-center justify-between gap-x-8 gap-y-2 border-b border-custom-border-100 bg-custom-background-100 pt-4 pb-2 last:border-b-0"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">{feature.icon}</div>
|
||||
<div className="flex items-center justify-center rounded bg-custom-primary-50/10 p-3">{feature.icon}</div>
|
||||
<div className="">
|
||||
<h4 className="text-sm font-medium">{feature.title}</h4>
|
||||
<p className="text-sm tracking-tight text-custom-text-200">{feature.description}</p>
|
||||
<h4 className="text-sm font-medium leading-5">{feature.title}</h4>
|
||||
<p className="text-sm tracking-tight text-custom-text-300 leading-5">{feature.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
<ToggleSwitch
|
||||
|
||||
Reference in New Issue
Block a user