From 93d545d368a1a5295f582d89e3a2e89fad9e1293 Mon Sep 17 00:00:00 2001 From: gakshita Date: Tue, 17 Dec 2024 14:24:51 +0530 Subject: [PATCH 1/3] chore: added common component for project activity --- .../common/activity/activity-block.tsx | 51 ++++ .../common/activity/activity-item.tsx | 30 ++ .../components/common/activity/helper.tsx | 279 ++++++++++++++++++ web/core/components/common/activity/index.ts | 1 + web/core/components/common/activity/user.tsx | 27 ++ web/core/components/common/index.ts | 1 + 6 files changed, 389 insertions(+) create mode 100644 web/core/components/common/activity/activity-block.tsx create mode 100644 web/core/components/common/activity/activity-item.tsx create mode 100644 web/core/components/common/activity/helper.tsx create mode 100644 web/core/components/common/activity/index.ts create mode 100644 web/core/components/common/activity/user.tsx diff --git a/web/core/components/common/activity/activity-block.tsx b/web/core/components/common/activity/activity-block.tsx new file mode 100644 index 00000000000..84f2dc9a479 --- /dev/null +++ b/web/core/components/common/activity/activity-block.tsx @@ -0,0 +1,51 @@ +"use client"; + +import { FC, ReactNode } from "react"; +import { Network } from "lucide-react"; +// hooks +import { Tooltip } from "@plane/ui"; +import { renderFormattedTime, renderFormattedDate, calculateTimeAgo } from "@/helpers/date-time.helper"; +import { usePlatformOS } from "@/hooks/use-platform-os"; +import { TProjectActivity } from "@/plane-web/types"; +import { User } from "./user"; + +type TActivityBlockComponent = { + icon?: ReactNode; + activity: TProjectActivity; + ends: "top" | "bottom" | undefined; + children: ReactNode; + customUserName?: string; +}; + +export const ActivityBlockComponent: FC = (props) => { + const { icon, activity, ends, children, customUserName } = props; + // hooks + const { isMobile } = usePlatformOS(); + + if (!activity) return <>; + return ( +
+
+
+ {icon ? icon : } +
+
+ {children} +
+ + + {calculateTimeAgo(activity.created_at)} + + +
+
+
+ ); +}; diff --git a/web/core/components/common/activity/activity-item.tsx b/web/core/components/common/activity/activity-item.tsx new file mode 100644 index 00000000000..2bf6ef5442b --- /dev/null +++ b/web/core/components/common/activity/activity-item.tsx @@ -0,0 +1,30 @@ +"use client"; + +import { FC } from "react"; +import { observer } from "mobx-react"; + +import { TProjectActivity } from "@/plane-web/types"; +import { ActivityBlockComponent } from "./activity-block"; +import { iconsMap, messages } from "./helper"; + +type TActivityItem = { + activity: TProjectActivity; + showProject?: boolean; + ends?: "top" | "bottom" | undefined; +}; + +export const ActivityItem: FC = observer((props) => { + const { activity, showProject = true, ends } = props; + + if (!activity) return null; + + const activityType = activity.field; + const { message, customUserName } = messages(activity); + const icon = iconsMap[activityType] || iconsMap.default; + + return ( + + <>{message} + + ); +}); diff --git a/web/core/components/common/activity/helper.tsx b/web/core/components/common/activity/helper.tsx new file mode 100644 index 00000000000..dda68477ddc --- /dev/null +++ b/web/core/components/common/activity/helper.tsx @@ -0,0 +1,279 @@ +import { ReactNode } from "react"; +import { + Signal, + RotateCcw, + Network, + Link as LinkIcon, + Calendar, + Tag, + Inbox, + AlignLeft, + Users, + Paperclip, + Type, + Triangle, + FileText, + Globe, + Hash, + Clock, + Bell, + LayoutGrid, + GitBranch, + Timer, + ListTodo, + Layers, +} from "lucide-react"; + +// components +import { ArchiveIcon, DoubleCircleIcon, ContrastIcon, DiceIcon, Intake } from "@plane/ui"; +import { TProjectActivity } from "@/plane-web/types"; + +type ActivityIconMap = { + [key: string]: ReactNode; +}; +export const iconsMap: ActivityIconMap = { + priority: , + archived_at: , + restored: , + link: , + start_date: , + target_date: , + label: , + inbox: , + description: , + assignee: , + attachment: , + name: , + state: , + estimate: , + cycle: , + module: , + page: , + network: , + identifier: , + timezone: , + is_project_updates_enabled: , + is_epic_enabled: , + is_workflow_enabled: , + is_time_tracking_enabled: , + is_issue_type_enabled: , + default: , + module_view: , + cycle_view: , + issue_views_view: , + page_view: , + intake_view: , +}; + +export const messages = (activity: TProjectActivity): { message: string | ReactNode; customUserName?: string } => { + const activityType = activity.field; + const newValue = activity.new_value; + const oldValue = activity.old_value; + const verb = activity.verb; + + const getBooleanActionText = (value: string) => { + if (value === "true") return "enabled"; + if (value === "false") return "disabled"; + return verb; + }; + + switch (activityType) { + case "priority": + return { + message: ( + <> + set the priority to {newValue || "none"} + + ), + }; + case "archived_at": + return { + message: newValue === "restore" ? "restored the project" : "archived the project", + customUserName: newValue === "archive" ? "Plane" : undefined, + }; + case "name": + return { + message: ( + <> + renamed the project to {newValue} + + ), + }; + case "description": + return { + message: newValue ? "updated the project description" : "removed the project description", + }; + case "start_date": + return { + message: ( + <> + {newValue ? ( + <> + set the start date to {newValue} + + ) : ( + "removed the start date" + )} + + ), + }; + case "target_date": + return { + message: ( + <> + {newValue ? ( + <> + set the target date to {newValue} + + ) : ( + "removed the target date" + )} + + ), + }; + case "state": + return { + message: ( + <> + set the state to {newValue || "none"} + + ), + }; + case "estimate": + return { + message: ( + <> + {newValue ? ( + <> + set the estimate point to {newValue} + + ) : ( + <> + removed the estimate point + {oldValue && ( + <> + {" "} + {oldValue} + + )} + + )} + + ), + }; + case "cycles": + return { + message: ( + <> + + {verb} this project {verb === "removed" ? "from" : "to"} the cycle{" "} + + {verb !== "removed" ? ( + + {activity.new_value} + + ) : ( + {activity.old_value || "Unknown cycle"} + )} + + ), + }; + case "modules": + return { + message: ( + <> + + {verb} this project {verb === "removed" ? "from" : "to"} the module{" "} + + + {verb === "removed" ? oldValue : newValue || "Unknown module"} + + + ), + }; + case "labels": + return { + message: ( + <> + {verb} the label{" "} + {newValue || oldValue || "Untitled label"} + + ), + }; + case "inbox": + return { + message: <>{newValue ? "enabled" : "disabled"} inbox, + }; + case "page": + return { + message: ( + <> + {newValue ? "created" : "removed"} the project page{" "} + {newValue || oldValue || "Untitled page"} + + ), + }; + case "network": + return { + message: <>{newValue ? "enabled" : "disabled"} network access, + }; + case "identifier": + return { + message: ( + <> + updated project identifier to {newValue || "none"} + + ), + }; + case "timezone": + return { + message: ( + <> + changed project timezone to{" "} + {newValue || "default"} + + ), + }; + case "module_view": + case "cycle_view": + case "issue_views_view": + case "page_view": + case "intake_view": + return { + message: ( + <> + {getBooleanActionText(newValue)} {activityType.replace(/_view$/, "").replace(/_/g, " ")} view + + ), + }; + case "is_project_updates_enabled": + return { + message: <>{getBooleanActionText(newValue)} project updates, + }; + case "is_epic_enabled": + return { + message: <>{getBooleanActionText(newValue)} epics, + }; + case "is_workflow_enabled": + return { + message: <>{getBooleanActionText(newValue)} custom workflow, + }; + case "is_time_tracking_enabled": + return { + message: <>{getBooleanActionText(newValue)} time tracking, + }; + case "is_issue_type_enabled": + return { + message: <>{getBooleanActionText(newValue)} issue types, + }; + default: + return { + message: `${verb} ${activityType.replace(/_/g, " ")} `, + }; + } +}; diff --git a/web/core/components/common/activity/index.ts b/web/core/components/common/activity/index.ts new file mode 100644 index 00000000000..8ab32d3d900 --- /dev/null +++ b/web/core/components/common/activity/index.ts @@ -0,0 +1 @@ +export * from "./activity-item"; diff --git a/web/core/components/common/activity/user.tsx b/web/core/components/common/activity/user.tsx new file mode 100644 index 00000000000..0229d80e859 --- /dev/null +++ b/web/core/components/common/activity/user.tsx @@ -0,0 +1,27 @@ +import { FC } from "react"; +import Link from "next/link"; +import { TProjectActivity } from "@/plane-web/types"; + +type TUser = { + activity: TProjectActivity; + customUserName?: string; +}; + +export const User: FC = (props) => { + const { activity, customUserName } = props; + + return ( + <> + {customUserName || activity.actor_detail?.display_name.includes("-intake") ? ( + {customUserName || "Plane"} + ) : ( + + {activity.actor_detail?.display_name} + + )} + + ); +}; diff --git a/web/core/components/common/index.ts b/web/core/components/common/index.ts index 28b73238862..1f9a4244051 100644 --- a/web/core/components/common/index.ts +++ b/web/core/components/common/index.ts @@ -5,3 +5,4 @@ export * from "./logo-spinner"; export * from "./logo"; export * from "./pro-icon"; export * from "./count-chip"; +export * from "./activity"; From f598653a6fc8c733ac1ed44b554cf3919b459688 Mon Sep 17 00:00:00 2001 From: gakshita Date: Tue, 17 Dec 2024 16:03:22 +0530 Subject: [PATCH 2/3] fix: added enum --- packages/types/src/enums.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index e37e2f4a5d5..2edc8df2519 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -60,4 +60,5 @@ export enum EFileAssetType { USER_COVER = "USER_COVER", WORKSPACE_LOGO = "WORKSPACE_LOGO", TEAM_SPACE_DESCRIPTION = "TEAM_SPACE_DESCRIPTION", + PROJECT_DESCRIPTION = "PROJECT_DESCRIPTION", } From 922793962c727c63ec93fc1b89d06709bdc85940 Mon Sep 17 00:00:00 2001 From: gakshita Date: Tue, 17 Dec 2024 16:04:24 +0530 Subject: [PATCH 3/3] fix: added enum for initiatives --- packages/types/src/enums.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/types/src/enums.ts b/packages/types/src/enums.ts index 2edc8df2519..92de9a7405c 100644 --- a/packages/types/src/enums.ts +++ b/packages/types/src/enums.ts @@ -60,5 +60,6 @@ export enum EFileAssetType { USER_COVER = "USER_COVER", WORKSPACE_LOGO = "WORKSPACE_LOGO", TEAM_SPACE_DESCRIPTION = "TEAM_SPACE_DESCRIPTION", + INITIATIVE_DESCRIPTION = "INITIATIVE_DESCRIPTION", PROJECT_DESCRIPTION = "PROJECT_DESCRIPTION", }