improvement: enhance activity components and types modularity (#6262)
This commit is contained in:
parent
ac47cc62ee
commit
6070ed4d36
8 changed files with 77 additions and 47 deletions
36
packages/types/src/activity.d.ts
vendored
Normal file
36
packages/types/src/activity.d.ts
vendored
Normal 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";
|
||||
|
|
@ -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",
|
||||
}
|
||||
|
|
|
|||
1
packages/types/src/index.d.ts
vendored
1
packages/types/src/index.d.ts
vendored
|
|
@ -35,3 +35,4 @@ export * from "./file";
|
|||
export * from "./workspace-draft-issues/base";
|
||||
export * from "./command-palette";
|
||||
export * from "./timezone";
|
||||
export * from "./activity";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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, " ")} `,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue