From f5f3c4915f526074db6de2eb44e726187b2b3f0e Mon Sep 17 00:00:00 2001 From: guru_sainath Date: Mon, 15 Jul 2024 19:48:27 +0530 Subject: [PATCH] [WEB-1846] chore: integrated project other features enabled/disabled feature on project settings and updated the pro icon as a component (#5071) * chore: integrated time traking enabled/disabled feature on project settings and updated the pro icon as a component * chore: Showing the toggle and disabled to make any operations on project features * chore: default exports in constants * chore: seperated isEnabled and isPro * chore: updated time traking key * chore: updated UI in project feature settings --- packages/ui/src/button/toggle-switch.tsx | 4 +- .../[projectId]/settings/features/page.tsx | 5 +- .../workspace-active-cycles-upgrade.tsx | 6 +- .../estimates/estimate-list-item-buttons.tsx | 6 +- .../editor/embed/issue-embed-upgrade-card.tsx | 10 +- web/ce/constants/project/index.ts | 1 + .../constants/project/settings/features.tsx | 82 ++++++++++++ web/ce/constants/project/settings/index.ts | 1 + web/core/components/common/index.ts | 1 + web/core/components/common/pro-icon.tsx | 16 +++ .../components/estimates/create/stage-one.tsx | 5 +- .../project/settings/features-list.tsx | 126 +++++++++--------- web/ee/constants/project/index.ts | 1 + .../constants/project/settings/features.tsx | 1 + web/ee/constants/project/settings/index.ts | 1 + 15 files changed, 183 insertions(+), 83 deletions(-) create mode 100644 web/ce/constants/project/index.ts create mode 100644 web/ce/constants/project/settings/features.tsx create mode 100644 web/ce/constants/project/settings/index.ts create mode 100644 web/core/components/common/pro-icon.tsx create mode 100644 web/ee/constants/project/index.ts create mode 100644 web/ee/constants/project/settings/features.tsx create mode 100644 web/ee/constants/project/settings/index.ts diff --git a/packages/ui/src/button/toggle-switch.tsx b/packages/ui/src/button/toggle-switch.tsx index 6f76f2e7d..c779cb436 100644 --- a/packages/ui/src/button/toggle-switch.tsx +++ b/packages/ui/src/button/toggle-switch.tsx @@ -26,7 +26,7 @@ const ToggleSwitch: React.FC = (props) => { "h-4 w-6": size === "sm", "h-5 w-8": size === "md", "bg-custom-primary-100": value, - "cursor-not-allowed": disabled, + "cursor-not-allowed bg-custom-background-80": disabled, }, className )} @@ -43,7 +43,7 @@ const ToggleSwitch: React.FC = (props) => { "translate-x-3": value && size === "sm", "translate-x-4": value && size === "md", "translate-x-0.5 bg-custom-background-90": !value, - "cursor-not-allowed": disabled, + "cursor-not-allowed bg-custom-background-90": disabled, } )} /> diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/features/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/features/page.tsx index 9317003c7..f09ae985b 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/features/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/settings/features/page.tsx @@ -33,9 +33,6 @@ const FeaturesSettingsPage = observer(() => { <>
-
-

Features

-
{ ); }); -export default FeaturesSettingsPage; \ No newline at end of file +export default FeaturesSettingsPage; diff --git a/web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx b/web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx index 3049c013a..11d708be0 100644 --- a/web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx +++ b/web/ce/components/active-cycles/workspace-active-cycles-upgrade.tsx @@ -3,10 +3,10 @@ import React from "react"; import { observer } from "mobx-react"; import Image from "next/image"; -// icons -import { Crown } from "lucide-react"; // ui import { getButtonStyling } from "@plane/ui"; +// components +import { ProIcon } from "@/components/common"; // constants import { MARKETING_PRICING_PAGE_LINK } from "@/constants/common"; import { WORKSPACE_ACTIVE_CYCLES_DETAILS } from "@/constants/cycle"; @@ -45,7 +45,7 @@ export const WorkspaceActiveCyclesUpgrade = observer(() => { target="_blank" rel="noreferrer" > - + Upgrade diff --git a/web/ce/components/estimates/estimate-list-item-buttons.tsx b/web/ce/components/estimates/estimate-list-item-buttons.tsx index 6911754f8..72acb4dfc 100644 --- a/web/ce/components/estimates/estimate-list-item-buttons.tsx +++ b/web/ce/components/estimates/estimate-list-item-buttons.tsx @@ -1,7 +1,9 @@ import { FC } from "react"; import { observer } from "mobx-react"; -import { Crown, Pen, Trash } from "lucide-react"; +import { Pen, Trash } from "lucide-react"; import { Tooltip } from "@plane/ui"; +// components +import { ProIcon } from "@/components/common"; type TEstimateListItem = { estimateId: string; @@ -22,7 +24,7 @@ export const EstimateListItemButtons: FC = observer((props) = tooltipContent={
Upgrade
- +
} position="top" diff --git a/web/ce/components/pages/editor/embed/issue-embed-upgrade-card.tsx b/web/ce/components/pages/editor/embed/issue-embed-upgrade-card.tsx index 78aac5480..ce3db7389 100644 --- a/web/ce/components/pages/editor/embed/issue-embed-upgrade-card.tsx +++ b/web/ce/components/pages/editor/embed/issue-embed-upgrade-card.tsx @@ -1,11 +1,13 @@ -import { Crown } from "lucide-react"; // ui import { Button } from "@plane/ui"; +// components +import { ProIcon } from "@/components/common"; export const IssueEmbedUpgradeCard: React.FC = (props) => (
{props.node?.attrs?.project_identifier}-{props?.node?.attrs?.sequence_id} @@ -14,7 +16,7 @@ export const IssueEmbedUpgradeCard: React.FC = (props) => (
- +
Embed and access issues in pages seamlessly, upgrade to plane pro now. diff --git a/web/ce/constants/project/index.ts b/web/ce/constants/project/index.ts new file mode 100644 index 000000000..dcf101b0c --- /dev/null +++ b/web/ce/constants/project/index.ts @@ -0,0 +1 @@ +export * from "./settings"; diff --git a/web/ce/constants/project/settings/features.tsx b/web/ce/constants/project/settings/features.tsx new file mode 100644 index 000000000..609c0f02f --- /dev/null +++ b/web/ce/constants/project/settings/features.tsx @@ -0,0 +1,82 @@ +import { ReactNode } from "react"; +import { FileText, Inbox, Timer } from "lucide-react"; +import { ContrastIcon, DiceIcon, PhotoFilterIcon } from "@plane/ui"; + +export type TFeatureList = { + [key: string]: { + property: string; + title: string; + description: string; + icon: ReactNode; + isPro: boolean; + isEnabled: boolean; + }; +}; + +export type TProjectFeatures = { + [key: string]: { + title: string; + featureList: TFeatureList; + }; +}; + +export const PROJECT_FEATURES_LIST: TProjectFeatures = { + project_features: { + title: "Features", + featureList: { + cycles: { + property: "cycle_view", + title: "Cycles", + description: "Time-box issues and boost momentum, similar to sprints in scrum.", + icon: , + isPro: false, + isEnabled: true, + }, + modules: { + property: "module_view", + title: "Modules", + description: "Group multiple issues together and track the progress.", + icon: , + isPro: false, + isEnabled: true, + }, + views: { + property: "issue_views_view", + title: "Views", + description: "Apply filters to issues and save them to analyse and investigate work.", + icon: , + isPro: false, + isEnabled: true, + }, + pages: { + property: "page_view", + title: "Pages", + description: "Document ideas, feature requirements, discussions within your project.", + icon: , + isPro: false, + isEnabled: true, + }, + inbox: { + property: "inbox_view", + title: "Inbox", + description: "Capture external inputs, move valid issues to workflow.", + icon: , + isPro: false, + isEnabled: true, + }, + }, + }, + project_others: { + title: "Others", + featureList: { + is_time_tracking_enabled: { + property: "is_time_tracking_enabled", + title: "Time Tracking", + description: "Keep the work logs of the users in track ", + icon: , + isPro: true, + isEnabled: false, + }, + }, + }, +}; diff --git a/web/ce/constants/project/settings/index.ts b/web/ce/constants/project/settings/index.ts new file mode 100644 index 000000000..0e849261a --- /dev/null +++ b/web/ce/constants/project/settings/index.ts @@ -0,0 +1 @@ +export * from "./features"; diff --git a/web/core/components/common/index.ts b/web/core/components/common/index.ts index 12f4dd648..d6d348584 100644 --- a/web/core/components/common/index.ts +++ b/web/core/components/common/index.ts @@ -4,4 +4,5 @@ export * from "./latest-feature-block"; export * from "./breadcrumb-link"; export * from "./logo-spinner"; export * from "./logo"; +export * from "./pro-icon"; export * from "./count-chip"; diff --git a/web/core/components/common/pro-icon.tsx b/web/core/components/common/pro-icon.tsx new file mode 100644 index 000000000..39d4c2a90 --- /dev/null +++ b/web/core/components/common/pro-icon.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { FC } from "react"; +import { Crown } from "lucide-react"; +// helpers +import { cn } from "@/helpers/common.helper"; + +type TProIcon = { + className?: string; +}; + +export const ProIcon: FC = (props) => { + const { className } = props; + + return ; +}; diff --git a/web/core/components/estimates/create/stage-one.tsx b/web/core/components/estimates/create/stage-one.tsx index 26d9e0705..2f9bbd418 100644 --- a/web/core/components/estimates/create/stage-one.tsx +++ b/web/core/components/estimates/create/stage-one.tsx @@ -1,10 +1,11 @@ "use client"; import { FC } from "react"; -import { Crown, Info } from "lucide-react"; +import { Info } from "lucide-react"; import { TEstimateSystemKeys } from "@plane/types"; import { Tooltip } from "@plane/ui"; // components +import { ProIcon } from "@/components/common"; import { RadioInput } from "@/components/estimates"; // plane web constants import { ESTIMATE_SYSTEMS } from "@/plane-web/constants/estimates"; @@ -39,7 +40,7 @@ export const EstimateCreateStageOne: FC = (props) => {
{ESTIMATE_SYSTEMS[currentSystem]?.name} - +
) : ( diff --git a/web/core/components/project/settings/features-list.tsx b/web/core/components/project/settings/features-list.tsx index 9d8189793..7aaab91e3 100644 --- a/web/core/components/project/settings/features-list.tsx +++ b/web/core/components/project/settings/features-list.tsx @@ -2,13 +2,14 @@ import { FC } from "react"; import { observer } from "mobx-react"; -import { FileText, Inbox } from "lucide-react"; -// types import { IProject } from "@plane/types"; -// ui -import { ContrastIcon, DiceIcon, PhotoFilterIcon, ToggleSwitch, setPromiseToast } from "@plane/ui"; +import { ToggleSwitch, Tooltip, setPromiseToast } from "@plane/ui"; // hooks import { useEventTracker, useProject, useUser } from "@/hooks/store"; +// plane web components +import { UpgradeBadge } from "@/plane-web/components/workspace"; +// plane web constants +import { PROJECT_FEATURES_LIST } from "@/plane-web/constants/project/settings"; type Props = { workspaceSlug: string; @@ -16,39 +17,6 @@ type Props = { isAdmin: boolean; }; -const PROJECT_FEATURES_LIST = [ - { - title: "Cycles", - description: "Time-box issues and boost momentum, similar to sprints in scrum.", - icon: , - property: "cycle_view", - }, - { - title: "Modules", - description: "Group multiple issues together and track the progress.", - icon: , - property: "module_view", - }, - { - title: "Views", - description: "Apply filters to issues and save them to analyse and investigate work.", - icon: , - property: "issue_views_view", - }, - { - title: "Pages", - description: "Document ideas, feature requirements, discussions within your project.", - icon: , - property: "page_view", - }, - { - title: "Inbox", - description: "Capture external inputs, move valid issues to workflow.", - icon: , - property: "inbox_view", - }, -]; - export const ProjectFeaturesList: FC = observer((props) => { const { workspaceSlug, projectId, isAdmin } = props; // store hooks @@ -58,9 +26,20 @@ export const ProjectFeaturesList: FC = observer((props) => { // derived values const currentProjectDetails = getProjectById(projectId); - const handleSubmit = async (formData: Partial) => { + const handleSubmit = async (featureKey: string, featureProperty: string) => { if (!workspaceSlug || !projectId || !currentProjectDetails) return; - const updateProjectPromise = updateProject(workspaceSlug, projectId, formData); + + // capturing event + captureEvent(`Toggle ${featureKey}`, { + enabled: !currentProjectDetails?.[featureProperty as keyof IProject], + element: "Project settings feature page", + }); + + // making the request to update the project feature + const settingsPayload = { + [featureProperty]: !currentProjectDetails?.[featureProperty as keyof IProject], + }; + const updateProjectPromise = updateProject(workspaceSlug, projectId, settingsPayload); setPromiseToast(updateProjectPromise, { loading: "Updating project feature...", success: { @@ -77,35 +56,50 @@ export const ProjectFeaturesList: FC = observer((props) => { if (!currentUser) return <>; return ( -
- {PROJECT_FEATURES_LIST.map((feature) => ( -
-
-
{feature.icon}
-
-

{feature.title}

-

{feature.description}

+
+ {Object.keys(PROJECT_FEATURES_LIST).map((featureSectionKey) => { + const feature = PROJECT_FEATURES_LIST[featureSectionKey]; + return ( +
+
+

{feature.title}

+ {Object.keys(feature.featureList).map((featureItemKey) => { + const featureItem = feature.featureList[featureItemKey]; + return ( +
+
+
+ {featureItem.icon} +
+
+
+

{featureItem.title}

+ {featureItem.isPro && ( + + + + )} +
+

{featureItem.description}

+
+
+ + handleSubmit(featureItemKey, featureItem.property)} + disabled={!featureItem.isEnabled || !isAdmin} + size="sm" + /> +
+ ); + })}
- { - captureEvent(`Toggle ${feature.title.toLowerCase()}`, { - enabled: !currentProjectDetails?.[feature.property as keyof IProject], - element: "Project settings feature page", - }); - handleSubmit({ - [feature.property]: !currentProjectDetails?.[feature.property as keyof IProject], - }); - }} - disabled={!isAdmin} - size="sm" - /> -
- ))} + ); + })}
); }); diff --git a/web/ee/constants/project/index.ts b/web/ee/constants/project/index.ts new file mode 100644 index 000000000..dcf101b0c --- /dev/null +++ b/web/ee/constants/project/index.ts @@ -0,0 +1 @@ +export * from "./settings"; diff --git a/web/ee/constants/project/settings/features.tsx b/web/ee/constants/project/settings/features.tsx new file mode 100644 index 000000000..5a6c17aed --- /dev/null +++ b/web/ee/constants/project/settings/features.tsx @@ -0,0 +1 @@ +export * from "ce/constants/project/settings/features"; diff --git a/web/ee/constants/project/settings/index.ts b/web/ee/constants/project/settings/index.ts new file mode 100644 index 000000000..0e849261a --- /dev/null +++ b/web/ee/constants/project/settings/index.ts @@ -0,0 +1 @@ +export * from "./features";