mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
issue open events added for project, cycle, module, archives, notification
This commit is contained in:
parent
46182584c9
commit
45abefcd00
@ -21,17 +21,22 @@ import {
|
||||
} from "lucide-react";
|
||||
import { IIssueActivity } from "@plane/types";
|
||||
import { Tooltip, BlockedIcon, BlockerIcon, RelatedIcon, LayersIcon, DiceIcon } from "@plane/ui";
|
||||
// constants
|
||||
import { ISSUE_OPENED } from "constants/event-tracker";
|
||||
// helpers
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
import { getElementFromPath } from "@/helpers/event-tracker.helper";
|
||||
import { capitalizeFirstLetter } from "@/helpers/string.helper";
|
||||
import { useEstimate, useLabel } from "@/hooks/store";
|
||||
import { useEstimate, useLabel, useEventTracker } from "@/hooks/store";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// types
|
||||
|
||||
export const IssueLink = ({ activity }: { activity: IIssueActivity }) => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// hooks
|
||||
const { isMobile } = usePlatformOS();
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@ -47,6 +52,13 @@ export const IssueLink = ({ activity }: { activity: IIssueActivity }) => {
|
||||
target={activity.issue === null ? "_self" : "_blank"}
|
||||
rel={activity.issue === null ? "" : "noopener noreferrer"}
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
onClick={() =>
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
element: getElementFromPath(router.asPath),
|
||||
element_id: "activity",
|
||||
mode: "detail",
|
||||
})
|
||||
}
|
||||
>
|
||||
<span className="whitespace-nowrap">{`${activity.project_detail.identifier}-${activity.issue_detail.sequence_id}`}</span>{" "}
|
||||
<span className="font-normal break-all">{activity.issue_detail?.name}</span>
|
||||
|
@ -15,13 +15,14 @@ import { StateDropdown } from "@/components/dropdowns";
|
||||
import { EmptyState } from "@/components/empty-state";
|
||||
// constants
|
||||
import { EmptyStateType } from "@/constants/empty-state";
|
||||
import { ISSUE_OPENED, E_ACYCLE } from "@/constants/event-tracker";
|
||||
import { CYCLE_ISSUES_WITH_PARAMS } from "@/constants/fetch-keys";
|
||||
import { EIssuesStoreType } from "@/constants/issue";
|
||||
// helper
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { renderFormattedDate, renderFormattedDateWithoutYear } from "@/helpers/date-time.helper";
|
||||
// hooks
|
||||
import { useIssues, useProject } from "@/hooks/store";
|
||||
import { useIssues, useProject, useEventTracker } from "@/hooks/store";
|
||||
import useLocalStorage from "@/hooks/use-local-storage";
|
||||
|
||||
export type ActiveCycleStatsProps = {
|
||||
@ -50,6 +51,7 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
|
||||
const {
|
||||
issues: { fetchActiveCycleIssues },
|
||||
} = useIssues(EIssuesStoreType.CYCLE);
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
const { currentProjectDetails } = useProject();
|
||||
|
||||
@ -140,6 +142,13 @@ export const ActiveCycleStats: FC<ActiveCycleStatsProps> = observer((props) => {
|
||||
key={issue.id}
|
||||
href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`}
|
||||
className="group flex cursor-pointer items-center justify-between gap-2 rounded-md hover:bg-custom-background-90 p-1"
|
||||
onClick={() =>
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
element: E_ACYCLE,
|
||||
element_id: tab?.toLowerCase(),
|
||||
mode: "detail",
|
||||
})
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-1.5 flex-grow w-full min-w-24 truncate">
|
||||
<PriorityIcon priority={issue.priority} withContainer size={12} />
|
||||
|
@ -14,11 +14,12 @@ import {
|
||||
CreatedUpcomingIssueListItem,
|
||||
IssueListItemProps,
|
||||
} from "@/components/dashboard/widgets";
|
||||
// ui
|
||||
// constants
|
||||
import { E_DASHBOARD, ISSUE_OPENED } from "constants/event-tracker";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { getRedirectionFilters } from "@/helpers/dashboard.helper";
|
||||
import { useIssueDetail } from "@/hooks/store";
|
||||
import { useIssueDetail, useEventTracker } from "@/hooks/store";
|
||||
// types
|
||||
|
||||
export type WidgetIssuesListProps = {
|
||||
@ -33,9 +34,19 @@ export const WidgetIssuesList: React.FC<WidgetIssuesListProps> = (props) => {
|
||||
const { isLoading, tab, type, widgetStats, workspaceSlug } = props;
|
||||
// store hooks
|
||||
const { setPeekIssue } = useIssueDetail();
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
const handleIssuePeekOverview = (issue: TIssue) =>
|
||||
const handleIssuePeekOverview = (issue: TIssue) => {
|
||||
setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id });
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
element: E_DASHBOARD,
|
||||
element_id: tab,
|
||||
mode: "peek",
|
||||
filters: {
|
||||
target_date: issue.target_date,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const filterParams = getRedirectionFilters(tab);
|
||||
|
||||
|
@ -188,7 +188,7 @@ export const AllIssueLayoutRoot: React.FC = observer(() => {
|
||||
isWorkspaceLevel
|
||||
/>
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issueFilters} />
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
@ -62,7 +62,7 @@ export const ArchivedIssueLayoutRoot: React.FC = observer(() => {
|
||||
<div className="relative h-full w-full overflow-auto">
|
||||
<ArchivedIssueListLayout />
|
||||
</div>
|
||||
<IssuePeekOverview is_archived />
|
||||
<IssuePeekOverview is_archived issuesFilter={issuesFilter.issueFilters} />
|
||||
</Fragment>
|
||||
)}
|
||||
</>
|
||||
|
@ -133,7 +133,7 @@ export const CycleLayoutRoot: React.FC = observer(() => {
|
||||
) : null}
|
||||
</div>
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issuesFilter.issueFilters} />
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
@ -68,7 +68,7 @@ export const DraftIssueLayoutRoot: React.FC = observer(() => {
|
||||
<DraftKanBanLayout />
|
||||
) : null}
|
||||
{/* issue peek overview */}
|
||||
<IssuePeekOverview is_draft />
|
||||
<IssuePeekOverview is_draft issuesFilter={issuesFilter.issueFilters}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -118,7 +118,7 @@ export const ModuleLayoutRoot: React.FC = observer(() => {
|
||||
) : null}
|
||||
</div>
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issuesFilter.issueFilters}/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
@ -86,7 +86,7 @@ export const ProjectLayoutRoot: FC = observer(() => {
|
||||
</div>
|
||||
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issuesFilter.issueFilters} />
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
@ -83,7 +83,7 @@ export const ProjectViewLayoutRoot: React.FC = observer(() => {
|
||||
</div>
|
||||
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issuesFilter.issueFilters}/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { ArchiveRestoreIcon, Link2, MoveDiagonal, MoveRight, Trash2 } from "lucide-react";
|
||||
// ui
|
||||
import {
|
||||
@ -16,11 +17,14 @@ import {
|
||||
// components
|
||||
import { IssueSubscription, IssueUpdateStatus } from "@/components/issues";
|
||||
import { STATE_GROUPS } from "@/constants/state";
|
||||
// constants
|
||||
import { ISSUE_OPENED } from "constants/event-tracker";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { getElementIdFromPath } from "@/helpers/event-tracker.helper";
|
||||
import { copyUrlToClipboard } from "@/helpers/string.helper";
|
||||
// store hooks
|
||||
import { useIssueDetail, useProjectState, useUser } from "@/hooks/store";
|
||||
import { useIssueDetail, useProjectState, useUser, useEventTracker } from "@/hooks/store";
|
||||
// hooks
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
export type TPeekModes = "side-peek" | "modal" | "full-screen";
|
||||
@ -73,6 +77,8 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
|
||||
handleRestoreIssue,
|
||||
isSubmitting,
|
||||
} = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
// store hooks
|
||||
const { data: currentUser } = useUser();
|
||||
const {
|
||||
@ -80,6 +86,7 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
|
||||
} = useIssueDetail();
|
||||
const { getStateById } = useProjectState();
|
||||
const { isMobile } = usePlatformOS();
|
||||
const { captureEvent } = useEventTracker();
|
||||
// derived values
|
||||
const issueDetails = getIssueById(issueId);
|
||||
const stateDetails = issueDetails ? getStateById(issueDetails?.state_id) : undefined;
|
||||
@ -118,7 +125,17 @@ export const IssuePeekOverviewHeader: FC<PeekOverviewHeaderProps> = observer((pr
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip tooltipContent="Open issue in full screen" isMobile={isMobile}>
|
||||
<Link href={`/${issueLink}`} onClick={() => removeRoutePeekId()}>
|
||||
<Link
|
||||
href={`/${issueLink}`}
|
||||
onClick={() => {
|
||||
removeRoutePeekId();
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
element: "peek",
|
||||
elementId: getElementIdFromPath(router.asPath),
|
||||
mode: "detail",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<MoveDiagonal className="h-4 w-4 text-custom-text-300 hover:text-custom-text-200" />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
|
@ -2,21 +2,24 @@ import { FC, useEffect, useState, useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useRouter } from "next/router";
|
||||
// types
|
||||
import { TIssue } from "@plane/types";
|
||||
import { IIssueFilters, TIssue } from "@plane/types";
|
||||
// ui
|
||||
import { TOAST_TYPE, setPromiseToast, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { IssueView } from "@/components/issues";
|
||||
// constants
|
||||
import { ISSUE_UPDATED, ISSUE_DELETED, ISSUE_ARCHIVED, ISSUE_RESTORED } from "@/constants/event-tracker";
|
||||
import { ISSUE_UPDATED, ISSUE_DELETED, ISSUE_ARCHIVED, ISSUE_RESTORED, ISSUE_OPENED } from "@/constants/event-tracker";
|
||||
import { EIssuesStoreType } from "@/constants/issue";
|
||||
import { EUserProjectRoles } from "@/constants/project";
|
||||
// helpers
|
||||
import { getElementFromPath, getElementIdFromPath } from "@/helpers/event-tracker.helper";
|
||||
// hooks
|
||||
import { useEventTracker, useIssueDetail, useIssues, useUser } from "@/hooks/store";
|
||||
|
||||
interface IIssuePeekOverview {
|
||||
is_archived?: boolean;
|
||||
is_draft?: boolean;
|
||||
issuesFilter?: IIssueFilters;
|
||||
}
|
||||
|
||||
export type TIssuePeekOperations = {
|
||||
@ -43,9 +46,10 @@ export type TIssuePeekOperations = {
|
||||
};
|
||||
|
||||
export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
const { is_archived = false, is_draft = false } = props;
|
||||
const { is_archived = false, is_draft = false, issuesFilter } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { userId } = router.query;
|
||||
const {
|
||||
membership: { currentWorkspaceAllProjectsRole },
|
||||
} = useUser();
|
||||
@ -67,7 +71,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
removeIssueFromModule,
|
||||
removeModulesFromIssue,
|
||||
} = useIssueDetail();
|
||||
const { captureIssueEvent } = useEventTracker();
|
||||
const { captureIssueEvent, captureEvent } = useEventTracker();
|
||||
// state
|
||||
const [loader, setLoader] = useState(false);
|
||||
|
||||
@ -387,6 +391,20 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
}
|
||||
}, [peekIssue, issueOperations]);
|
||||
|
||||
useEffect(() => {
|
||||
if (peekIssue && issuesFilter) {
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
layout: issuesFilter?.displayFilters?.layout,
|
||||
display_properties: issuesFilter?.displayFilters,
|
||||
filters: issuesFilter?.filters,
|
||||
mode: "peek",
|
||||
profile_id: userId,
|
||||
element: getElementFromPath(router.asPath),
|
||||
elementId: getElementIdFromPath(router.asPath),
|
||||
});
|
||||
}
|
||||
}, [peekIssue, userId, captureEvent, router.asPath]);
|
||||
|
||||
if (!peekIssue?.workspaceSlug || !peekIssue?.projectId || !peekIssue?.issueId) return <></>;
|
||||
|
||||
const issue = getIssueById(peekIssue.issueId) || undefined;
|
||||
|
@ -10,6 +10,7 @@ import type { IUserNotification, NotificationType } from "@plane/types";
|
||||
import { ArchiveIcon, CustomMenu, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// constants
|
||||
import {
|
||||
E_NOTIFICATION,
|
||||
ISSUE_OPENED,
|
||||
NOTIFICATIONS_READ,
|
||||
NOTIFICATION_ARCHIVED,
|
||||
@ -27,6 +28,8 @@ type NotificationCardProps = {
|
||||
selectedTab: NotificationType;
|
||||
notification: IUserNotification;
|
||||
isSnoozedTabOpen: boolean;
|
||||
isArchivedTabOpen: boolean;
|
||||
isUnreadTabOpen: boolean;
|
||||
closePopover: () => void;
|
||||
markNotificationReadStatus: (notificationId: string) => Promise<void>;
|
||||
markNotificationReadStatusToggle: (notificationId: string) => Promise<void>;
|
||||
@ -40,6 +43,8 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
|
||||
selectedTab,
|
||||
notification,
|
||||
isSnoozedTabOpen,
|
||||
isArchivedTabOpen,
|
||||
isUnreadTabOpen,
|
||||
closePopover,
|
||||
markNotificationReadStatus,
|
||||
markNotificationReadStatusToggle,
|
||||
@ -131,7 +136,14 @@ export const NotificationCard: React.FC<NotificationCardProps> = (props) => {
|
||||
markNotificationReadStatus(notification.id);
|
||||
captureEvent(ISSUE_OPENED, {
|
||||
issue_id: notification.data.issue.id,
|
||||
element: "notification",
|
||||
element: E_NOTIFICATION,
|
||||
element_id: isArchivedTabOpen
|
||||
? "archived"
|
||||
: isSnoozedTabOpen
|
||||
? "snoozed"
|
||||
: isUnreadTabOpen
|
||||
? "unread"
|
||||
: selectedTab,
|
||||
});
|
||||
closePopover();
|
||||
}}
|
||||
|
@ -63,12 +63,12 @@ export const NotificationPopover = observer(() => {
|
||||
const currentTabEmptyState = snoozed
|
||||
? EmptyStateType.NOTIFICATION_SNOOZED_EMPTY_STATE
|
||||
: archived
|
||||
? EmptyStateType.NOTIFICATION_ARCHIVED_EMPTY_STATE
|
||||
: selectedTab === "created"
|
||||
? EmptyStateType.NOTIFICATION_CREATED_EMPTY_STATE
|
||||
: selectedTab === "watching"
|
||||
? EmptyStateType.NOTIFICATION_SUBSCRIBED_EMPTY_STATE
|
||||
: EmptyStateType.NOTIFICATION_MY_ISSUE_EMPTY_STATE;
|
||||
? EmptyStateType.NOTIFICATION_ARCHIVED_EMPTY_STATE
|
||||
: selectedTab === "created"
|
||||
? EmptyStateType.NOTIFICATION_CREATED_EMPTY_STATE
|
||||
: selectedTab === "watching"
|
||||
? EmptyStateType.NOTIFICATION_SUBSCRIBED_EMPTY_STATE
|
||||
: EmptyStateType.NOTIFICATION_MY_ISSUE_EMPTY_STATE;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -154,6 +154,8 @@ export const NotificationPopover = observer(() => {
|
||||
selectedTab={selectedTab}
|
||||
key={notification.id}
|
||||
isSnoozedTabOpen={snoozed}
|
||||
isArchivedTabOpen={archived}
|
||||
isUnreadTabOpen={readNotification}
|
||||
closePopover={() => setIsActive(false)}
|
||||
notification={notification}
|
||||
markNotificationArchivedStatus={markNotificationArchivedStatus}
|
||||
|
@ -69,7 +69,7 @@ export const ProfileIssuesPage = observer((props: IProfileIssuesPage) => {
|
||||
) : null}
|
||||
</div>
|
||||
{/* peek overview */}
|
||||
<IssuePeekOverview />
|
||||
<IssuePeekOverview issuesFilter={issueFilters} />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -18,145 +18,6 @@ export type EventProps = {
|
||||
payload: any;
|
||||
};
|
||||
|
||||
export const getWorkspaceEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
organization_size: payload.organization_size,
|
||||
first_time: payload.first_time,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getProjectEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.id,
|
||||
identifier: payload.identifier,
|
||||
project_visibility: payload.network == 2 ? "Public" : "Private",
|
||||
changed_properties: payload.changed_properties,
|
||||
lead_id: payload.project_lead,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getCycleEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
cycle_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
start_date: payload.start_date,
|
||||
target_date: payload.target_date,
|
||||
cycle_status: payload.status,
|
||||
changed_properties: payload.changed_properties,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getModuleEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
module_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
start_date: payload.start_date,
|
||||
target_date: payload.target_date,
|
||||
module_status: payload.status,
|
||||
lead_id: payload.lead,
|
||||
changed_properties: payload.changed_properties,
|
||||
member_ids: payload.members,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getPageEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
access: payload.access === 0 ? "Public" : "Private",
|
||||
is_locked: payload.is_locked,
|
||||
archived_at: payload.archived_at,
|
||||
created_by: payload.created_by,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getIssueEventPayload = (props: IssueEventProps) => {
|
||||
const { eventName, payload, updates, routePath } = props;
|
||||
let eventPayload: any = {
|
||||
issue_id: payload.id,
|
||||
estimate_point: payload.estimate_point,
|
||||
link_count: payload.link_count,
|
||||
target_date: payload.target_date,
|
||||
is_draft: payload.is_draft,
|
||||
label_ids: payload.label_ids,
|
||||
assignee_ids: payload.assignee_ids,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
sequence_id: payload.sequence_id,
|
||||
module_ids: payload.module_ids,
|
||||
sub_issues_count: payload.sub_issues_count,
|
||||
parent_id: payload.parent_id,
|
||||
project_id: payload.project_id,
|
||||
workspace_id: payload.workspace_id,
|
||||
priority: payload.priority,
|
||||
state_id: payload.state_id,
|
||||
start_date: payload.start_date,
|
||||
attachment_count: payload.attachment_count,
|
||||
cycle_id: payload.cycle_id,
|
||||
module_id: payload.module_id,
|
||||
archived_at: payload.archived_at,
|
||||
state: payload.state,
|
||||
view_id: routePath?.includes("workspace-views") || routePath?.includes("views") ? routePath.split("/").pop() : "",
|
||||
};
|
||||
|
||||
if (eventName === ISSUE_UPDATED) {
|
||||
eventPayload = {
|
||||
...eventPayload,
|
||||
...updates,
|
||||
updated_from: elementFromPath(routePath),
|
||||
};
|
||||
}
|
||||
return eventPayload;
|
||||
};
|
||||
|
||||
export const getProjectStateEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.id,
|
||||
state_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
group: payload.group,
|
||||
color: payload.color,
|
||||
default: payload.default,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getIssuesListOpenedPayload = (payload: any) => ({
|
||||
type: payload.project_id ? "Project" : "Workspace",
|
||||
layout: payload?.filters?.displayFilters?.layout,
|
||||
filters: payload?.filters?.filters,
|
||||
display_properties: payload?.filters?.displayProperties,
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project_id,
|
||||
});
|
||||
|
||||
// Returns the element based on the path
|
||||
const elementFromPath = (routePath?: string) => {
|
||||
if (routePath?.includes("workspace-views")) return E_WORKSPACE_VIEW;
|
||||
if (routePath?.includes("cycles")) return E_CYCLE;
|
||||
if (routePath?.includes("modules")) return E_MODULE;
|
||||
if (routePath?.includes("views")) return E_PROJECT_VIEW;
|
||||
if (routePath?.includes("inbox")) return E_INBOX;
|
||||
if (routePath?.includes("draft")) return E_DRAFT;
|
||||
if (routePath?.includes("archived")) return E_ARCHIVE;
|
||||
return "";
|
||||
};
|
||||
|
||||
// Workspace crud Events
|
||||
export const WORKSPACE_CREATED = "Workspace created";
|
||||
export const WORKSPACE_UPDATED = "Workspace updated";
|
||||
@ -189,6 +50,8 @@ export const ISSUE_RESTORED = "Issue restored";
|
||||
// Issue Checkout Events
|
||||
export const ISSUES_LIST_OPENED = "Issues list opened";
|
||||
export const ISSUE_OPENED = "Issue opened";
|
||||
// Layout & Filter Events
|
||||
export const LAYOUT_CHANGED = "Layout changed";
|
||||
// Project State Events
|
||||
export const STATE_CREATED = "State created";
|
||||
export const STATE_UPDATED = "State updated";
|
||||
@ -244,9 +107,13 @@ export const GROUP_WORKSPACE = "Workspace_metrics";
|
||||
// Elements
|
||||
export const E_PROJECT = "Project";
|
||||
export const E_CYCLE = "Cycle";
|
||||
export const E_ACYCLE = "Active cycle";
|
||||
export const E_MODULE = "Module";
|
||||
export const E_PROJECT_VIEW = "Project view";
|
||||
export const E_WORKSPACE_VIEW = "Workspace view";
|
||||
export const E_DRAFT = "Draft";
|
||||
export const E_ARCHIVE = "Archives";
|
||||
export const E_INBOX = "Inbox";
|
||||
export const E_NOTIFICATION = "Notification";
|
||||
export const E_DASHBOARD= "Dashboard";
|
||||
export const E_PROFILE = "Profile";
|
||||
|
168
web/helpers/event-tracker.helper.ts
Normal file
168
web/helpers/event-tracker.helper.ts
Normal file
@ -0,0 +1,168 @@
|
||||
import {
|
||||
// elements
|
||||
E_ARCHIVE,
|
||||
E_CYCLE,
|
||||
E_DASHBOARD,
|
||||
E_DRAFT,
|
||||
E_INBOX,
|
||||
E_MODULE,
|
||||
E_PROFILE,
|
||||
E_PROJECT,
|
||||
E_PROJECT_VIEW,
|
||||
E_WORKSPACE_VIEW,
|
||||
// events
|
||||
ISSUE_UPDATED,
|
||||
// types
|
||||
IssueEventProps,
|
||||
} from "@/constants/event-tracker";
|
||||
|
||||
export const getWorkspaceEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
organization_size: payload.organization_size,
|
||||
first_time: payload.first_time,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getProjectEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.id,
|
||||
identifier: payload.identifier,
|
||||
project_visibility: payload.network == 2 ? "Public" : "Private",
|
||||
changed_properties: payload.changed_properties,
|
||||
lead_id: payload.project_lead,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getCycleEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
cycle_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
start_date: payload.start_date,
|
||||
target_date: payload.target_date,
|
||||
cycle_status: payload.status,
|
||||
changed_properties: payload.changed_properties,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getModuleEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
module_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
start_date: payload.start_date,
|
||||
target_date: payload.target_date,
|
||||
module_status: payload.status,
|
||||
lead_id: payload.lead,
|
||||
changed_properties: payload.changed_properties,
|
||||
member_ids: payload.members,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getPageEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
access: payload.access === 0 ? "Public" : "Private",
|
||||
is_locked: payload.is_locked,
|
||||
archived_at: payload.archived_at,
|
||||
created_by: payload.created_by,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getIssueEventPayload = (props: IssueEventProps) => {
|
||||
const { eventName, payload, updates, routePath } = props;
|
||||
let eventPayload: any = {
|
||||
issue_id: payload.id,
|
||||
estimate_point: payload.estimate_point,
|
||||
link_count: payload.link_count,
|
||||
target_date: payload.target_date,
|
||||
is_draft: payload.is_draft,
|
||||
label_ids: payload.label_ids,
|
||||
assignee_ids: payload.assignee_ids,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
sequence_id: payload.sequence_id,
|
||||
module_ids: payload.module_ids,
|
||||
sub_issues_count: payload.sub_issues_count,
|
||||
parent_id: payload.parent_id,
|
||||
project_id: payload.project_id,
|
||||
workspace_id: payload.workspace_id,
|
||||
priority: payload.priority,
|
||||
state_id: payload.state_id,
|
||||
start_date: payload.start_date,
|
||||
attachment_count: payload.attachment_count,
|
||||
cycle_id: payload.cycle_id,
|
||||
module_id: payload.module_id,
|
||||
archived_at: payload.archived_at,
|
||||
state: payload.state,
|
||||
view_id: routePath?.includes("workspace-views") || routePath?.includes("views") ? routePath.split("/").pop() : "",
|
||||
};
|
||||
|
||||
if (eventName === ISSUE_UPDATED) {
|
||||
eventPayload = {
|
||||
...eventPayload,
|
||||
...updates,
|
||||
updated_from: getElementFromPath(routePath),
|
||||
};
|
||||
}
|
||||
return eventPayload;
|
||||
};
|
||||
|
||||
export const getProjectStateEventPayload = (payload: any) => ({
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.id,
|
||||
state_id: payload.id,
|
||||
created_at: payload.created_at,
|
||||
updated_at: payload.updated_at,
|
||||
group: payload.group,
|
||||
color: payload.color,
|
||||
default: payload.default,
|
||||
state: payload.state,
|
||||
element: payload.element,
|
||||
});
|
||||
|
||||
export const getIssuesListOpenedPayload = (payload: any) => ({
|
||||
type: payload.project_id ? "Project" : "Workspace",
|
||||
layout: payload?.filters?.displayFilters?.layout,
|
||||
filters: payload?.filters?.filters,
|
||||
display_properties: payload?.filters?.displayProperties,
|
||||
workspace_id: payload.workspace_id,
|
||||
project_id: payload.project_id,
|
||||
});
|
||||
|
||||
// Returns the element based on the path
|
||||
export const getElementFromPath = (routePath?: string) => {
|
||||
if (routePath?.includes("workspace-views")) return E_WORKSPACE_VIEW;
|
||||
if (routePath?.includes("profile")) return E_PROFILE;
|
||||
if (routePath?.includes("cycles")) return E_CYCLE;
|
||||
if (routePath?.includes("modules")) return E_MODULE;
|
||||
if (routePath?.includes("views")) return E_PROJECT_VIEW;
|
||||
if (routePath?.includes("inbox")) return E_INBOX;
|
||||
if (routePath?.includes("draft")) return E_DRAFT;
|
||||
if (routePath?.includes("archives")) return E_ARCHIVE;
|
||||
if (routePath?.includes("projects")) return E_PROJECT;
|
||||
if (routePath?.split("/").length === 2) return E_DASHBOARD;
|
||||
return "";
|
||||
};
|
||||
|
||||
export const getElementIdFromPath = (routePath?: string) => {
|
||||
const element = getElementFromPath(routePath);
|
||||
return [E_PROJECT, E_DRAFT].includes(element)
|
||||
? routePath?.split("/").at(-2)
|
||||
: element === E_ARCHIVE
|
||||
? routePath?.split("/").at(-3)
|
||||
: routePath?.split("/").at(-1);
|
||||
};
|
@ -2,10 +2,15 @@ import { action, computed, makeObservable, observable } from "mobx";
|
||||
import posthog from "posthog-js";
|
||||
// stores
|
||||
import {
|
||||
//types
|
||||
EventProps,
|
||||
IssueEventProps,
|
||||
// payload helpers
|
||||
IssuesListOpenedEventProps,
|
||||
ISSUES_LIST_OPENED,
|
||||
GROUP_WORKSPACE,
|
||||
WORKSPACE_CREATED,
|
||||
} from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import {
|
||||
getCycleEventPayload,
|
||||
getIssueEventPayload,
|
||||
getModuleEventPayload,
|
||||
@ -14,12 +19,7 @@ import {
|
||||
getWorkspaceEventPayload,
|
||||
getPageEventPayload,
|
||||
getIssuesListOpenedPayload,
|
||||
// event constants
|
||||
ISSUES_LIST_OPENED,
|
||||
GROUP_WORKSPACE,
|
||||
WORKSPACE_CREATED,
|
||||
IssuesListOpenedEventProps,
|
||||
} from "@/constants/event-tracker";
|
||||
} from "@/helpers/event-tracker.helper";
|
||||
import { RootStore } from "./root.store";
|
||||
|
||||
export interface IEventTrackerStore {
|
||||
|
Loading…
Reference in New Issue
Block a user