improvement: enhance activity components and types modularity (#6262)

This commit is contained in:
Prateek Shourya 2024-12-23 20:03:42 +05:30 committed by GitHub
parent ac47cc62ee
commit 6070ed4d36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 77 additions and 47 deletions

36
packages/types/src/activity.d.ts vendored Normal file
View file

@ -0,0 +1,36 @@
export type TBaseActivity<
TFieldKey extends string = string,
TVerbKey extends string = string,
> = {
id: string;
field: TFieldKey | undefined;
epoch: number;
verb: TVerbKey;
comment: string | undefined;
// updates
old_value: string | undefined;
new_value: string | undefined;
old_identifier: string | undefined;
new_identifier: string | undefined;
// actor detail
actor: string;
// timestamp
created_at: string;
updated_at: string;
};
export type TWorkspaceBaseActivity<
K extends string = string,
V extends string = string,
> = TBaseActivity<K, V> & {
workspace: string;
};
export type TProjectBaseActivity<
K extends string = string,
V extends string = string,
> = TWorkspaceBaseActivity<K, V> & {
project: string;
};
export type TBaseActivityVerbs = "created" | "updated" | "deleted";

View file

@ -4,10 +4,7 @@ export enum EUserPermissions {
GUEST = 5,
}
export type TUserPermissions =
| EUserPermissions.ADMIN
| EUserPermissions.MEMBER
| EUserPermissions.GUEST;
export type TUserPermissions = EUserPermissions.ADMIN | EUserPermissions.MEMBER | EUserPermissions.GUEST;
// project pages
export enum EPageAccess {
@ -62,4 +59,5 @@ export enum EFileAssetType {
TEAM_SPACE_DESCRIPTION = "TEAM_SPACE_DESCRIPTION",
INITIATIVE_DESCRIPTION = "INITIATIVE_DESCRIPTION",
PROJECT_DESCRIPTION = "PROJECT_DESCRIPTION",
TEAM_SPACE_COMMENT_DESCRIPTION = "TEAM_SPACE_COMMENT_DESCRIPTION",
}

View file

@ -35,3 +35,4 @@ export * from "./file";
export * from "./workspace-draft-issues/base";
export * from "./command-palette";
export * from "./timezone";
export * from "./activity";

View file

@ -1,25 +1,3 @@
export interface TProjectActivity {
id: string;
content: string;
createdAt: string;
updatedAt: string;
userId: string;
projectId: string;
created_at: string;
field: string;
verb: string;
actor_detail: {
display_name: string;
id: string;
};
workspace_detail: {
slug: string;
};
project_detail: {
name: string;
};
new_value: string;
old_value: string;
project: string;
new_identifier?: string;
}
import { TProjectBaseActivity } from "@plane/types";
export type TProjectActivity = TProjectBaseActivity;

View file

@ -2,16 +2,20 @@
import { FC, ReactNode } from "react";
import { Network } from "lucide-react";
// hooks
// types
import { TWorkspaceBaseActivity } from "@plane/types";
// ui
import { Tooltip } from "@plane/ui";
// helpers
import { renderFormattedTime, renderFormattedDate, calculateTimeAgo } from "@/helpers/date-time.helper";
// hooks
import { usePlatformOS } from "@/hooks/use-platform-os";
import { TProjectActivity } from "@/plane-web/types";
// local components
import { User } from "./user";
type TActivityBlockComponent = {
icon?: ReactNode;
activity: TProjectActivity;
activity: TWorkspaceBaseActivity;
ends: "top" | "bottom" | undefined;
children: ReactNode;
customUserName?: string;
@ -25,12 +29,11 @@ export const ActivityBlockComponent: FC<TActivityBlockComponent> = (props) => {
if (!activity) return <></>;
return (
<div
className={`relative flex items-center gap-3 text-xs ${
ends === "top" ? `pb-2` : ends === "bottom" ? `pt-2` : `py-2`
className={`relative flex items-center gap-2 text-xs ${
ends === "top" ? `pb-3` : ends === "bottom" ? `pt-3` : `py-3`
}`}
>
<div className="absolute left-[13px] top-0 bottom-0 w-0.5 bg-custom-background-80" aria-hidden />
<div className="flex-shrink-0 ring-6 w-7 h-7 rounded-full overflow-hidden flex justify-center items-center z-[4] bg-custom-background-80 text-custom-text-200">
<div className="flex-shrink-0 ring-6 w-7 h-7 rounded-full overflow-hidden flex justify-center items-start mt-0.5 z-[4] text-custom-text-200">
{icon ? icon : <Network className="w-3.5 h-3.5" />}
</div>
<div className="w-full truncate text-custom-text-200">
@ -40,7 +43,7 @@ export const ActivityBlockComponent: FC<TActivityBlockComponent> = (props) => {
isMobile={isMobile}
tooltipContent={`${renderFormattedDate(activity.created_at)}, ${renderFormattedTime(activity.created_at)}`}
>
<span className="whitespace-nowrap text-custom-text-350 font-medium">
<span className="whitespace-nowrap text-custom-text-350 font-medium cursor-help">
{calculateTimeAgo(activity.created_at)}
</span>
</Tooltip>

View file

@ -19,6 +19,8 @@ export const ActivityItem: FC<TActivityItem> = observer((props) => {
if (!activity) return null;
const activityType = activity.field;
if (!activityType) return null;
const { message, customUserName } = messages(activity);
const icon = iconsMap[activityType] || iconsMap.default;

View file

@ -26,6 +26,7 @@ import {
// components
import { ArchiveIcon, DoubleCircleIcon, ContrastIcon, DiceIcon, Intake } from "@plane/ui";
import { store } from "@/lib/store-context";
import { TProjectActivity } from "@/plane-web/types";
type ActivityIconMap = {
@ -70,8 +71,9 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
const newValue = activity.new_value;
const oldValue = activity.old_value;
const verb = activity.verb;
const workspaceDetail = store.workspaceRoot.getWorkspaceById(activity.workspace);
const getBooleanActionText = (value: string) => {
const getBooleanActionText = (value: string | undefined) => {
if (value === "true") return "enabled";
if (value === "false") return "disabled";
return verb;
@ -170,7 +172,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
</span>
{verb !== "removed" ? (
<a
href={`/${activity.workspace_detail?.slug}/projects/${activity.project}/cycles/${activity.new_identifier}`}
href={`/${workspaceDetail?.slug}/projects/${activity.project}/cycles/${activity.new_identifier}`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex font-medium text-custom-text-100"
@ -273,7 +275,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
};
default:
return {
message: `${verb} ${activityType.replace(/_/g, " ")} `,
message: `${verb} ${activityType?.replace(/_/g, " ")} `,
};
}
};

View file

@ -1,27 +1,37 @@
import { FC } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { TProjectActivity } from "@/plane-web/types";
// types
import { TWorkspaceBaseActivity } from "@plane/types";
// store hooks
import { useMember, useWorkspace } from "@/hooks/store";
type TUser = {
activity: TProjectActivity;
activity: TWorkspaceBaseActivity;
customUserName?: string;
};
export const User: FC<TUser> = (props) => {
export const User: FC<TUser> = observer((props) => {
const { activity, customUserName } = props;
// store hooks
const { getUserDetails } = useMember();
const { getWorkspaceById } = useWorkspace();
// derived values
const actorDetail = getUserDetails(activity.actor);
const workspaceDetail = getWorkspaceById(activity.workspace);
return (
<>
{customUserName || activity.actor_detail?.display_name.includes("-intake") ? (
{customUserName || actorDetail?.display_name.includes("-intake") ? (
<span className="text-custom-text-100 font-medium">{customUserName || "Plane"}</span>
) : (
<Link
href={`/${activity?.workspace_detail?.slug}/profile/${activity?.actor_detail?.id}`}
href={`/${workspaceDetail?.slug}/profile/${actorDetail?.id}`}
className="hover:underline text-custom-text-100 font-medium"
>
{activity.actor_detail?.display_name}
{actorDetail?.display_name}
</Link>
)}
</>
);
};
});