mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
added events for pages operations
This commit is contained in:
parent
83c8338c64
commit
4932de1ba3
@ -17,7 +17,9 @@ type Props = {
|
||||
isOpen: boolean;
|
||||
projectId: string;
|
||||
handleClose: () => void;
|
||||
onResponse: (response: any) => void;
|
||||
onResponse: (task: string, response: any) => void;
|
||||
onGenerateResponse?: (task: string, response: any) => void;
|
||||
onReGenerateResponse?: (task: string, response: any) => void;
|
||||
onError?: (error: any) => void;
|
||||
placement?: Placement;
|
||||
prompt?: string;
|
||||
@ -33,7 +35,19 @@ type FormData = {
|
||||
const aiService = new AIService();
|
||||
|
||||
export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
const { isOpen, projectId, handleClose, onResponse, onError, placement, prompt, button, className = "" } = props;
|
||||
const {
|
||||
isOpen,
|
||||
projectId,
|
||||
handleClose,
|
||||
onResponse,
|
||||
onGenerateResponse,
|
||||
onReGenerateResponse,
|
||||
onError,
|
||||
placement,
|
||||
prompt,
|
||||
button,
|
||||
className = "",
|
||||
} = props;
|
||||
// states
|
||||
const [response, setResponse] = useState("");
|
||||
const [invalidResponse, setInvalidResponse] = useState(false);
|
||||
@ -54,6 +68,7 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
control,
|
||||
reset,
|
||||
setFocus,
|
||||
getValues,
|
||||
formState: { isSubmitting },
|
||||
} = useForm<FormData>({
|
||||
defaultValues: {
|
||||
@ -118,6 +133,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
}
|
||||
|
||||
await callAIService(formData);
|
||||
if (response !== "" && onReGenerateResponse) onReGenerateResponse(formData.task, response);
|
||||
else if (response === "" && onGenerateResponse) onGenerateResponse(formData.task, response);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -162,7 +179,7 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
onResponse(response);
|
||||
onResponse(getValues("task"),response);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
@ -173,8 +190,8 @@ export const GptAssistantPopover: React.FC<Props> = (props) => {
|
||||
const generateResponseButtonText = isSubmitting
|
||||
? "Generating response..."
|
||||
: response === ""
|
||||
? "Generate response"
|
||||
: "Generate again";
|
||||
? "Generate response"
|
||||
: "Generate again";
|
||||
|
||||
return (
|
||||
<Popover as="div" className={`relative w-min text-left`}>
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { observer } from "mobx-react";
|
||||
import { useRouter } from "next/router";
|
||||
import { FileText } from "lucide-react";
|
||||
// hooks
|
||||
// ui
|
||||
import { Breadcrumbs, Button } from "@plane/ui";
|
||||
// helpers
|
||||
// components
|
||||
import { BreadcrumbLink } from "@/components/common";
|
||||
import { ProjectLogo } from "@/components/project";
|
||||
import { EUserProjectRoles } from "@/constants/project";
|
||||
// constants
|
||||
// components
|
||||
import { E_PAGES } from "@/constants/event-tracker";
|
||||
import { EUserProjectRoles } from "@/constants/project";
|
||||
// hooks
|
||||
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
|
||||
|
||||
export const PagesHeader = observer(() => {
|
||||
@ -61,7 +61,7 @@ export const PagesHeader = observer(() => {
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setTrackElement("Project pages page");
|
||||
setTrackElement(E_PAGES);
|
||||
toggleCreatePageModal(true);
|
||||
}}
|
||||
>
|
||||
|
@ -439,7 +439,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
|
||||
// this is done so that the title do not reset after gpt popover closed
|
||||
reset(getValues());
|
||||
}}
|
||||
onResponse={(response) => {
|
||||
onResponse={(_,response) => {
|
||||
handleAiAssistance(response);
|
||||
}}
|
||||
placement="top-end"
|
||||
|
@ -4,10 +4,12 @@ import { ArchiveRestoreIcon, ExternalLink, Link, Lock, Trash2, UsersRound } from
|
||||
import { ArchiveIcon, ContextMenu, CustomMenu, TContextMenuItem, TOAST_TYPE, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { DeletePageModal } from "@/components/pages";
|
||||
// constants
|
||||
import { E_PAGES, PAGE_ARCHIVED, PAGE_RESTORED, PAGE_UPDATED } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { copyUrlToClipboard } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { usePage } from "@/hooks/store";
|
||||
import { usePage, useEventTracker } from "@/hooks/store";
|
||||
|
||||
type Props = {
|
||||
pageId: string;
|
||||
@ -32,6 +34,7 @@ export const PageQuickActions: React.FC<Props> = observer((props) => {
|
||||
canCurrentUserChangeAccess,
|
||||
canCurrentUserDeletePage,
|
||||
} = usePage(pageId);
|
||||
const { setTrackElement, captureEvent } = useEventTracker();
|
||||
|
||||
const pageLink = `${workspaceSlug}/projects/${projectId}/pages/${pageId}`;
|
||||
const handleCopyText = () =>
|
||||
@ -48,7 +51,15 @@ export const PageQuickActions: React.FC<Props> = observer((props) => {
|
||||
const MENU_ITEMS: TContextMenuItem[] = [
|
||||
{
|
||||
key: "make-public-private",
|
||||
action: access === 0 ? makePrivate : makePublic,
|
||||
action: () => {
|
||||
access === 0 ? makePrivate() : makePublic();
|
||||
captureEvent(PAGE_UPDATED, {
|
||||
page_id: pageId,
|
||||
changed_property: "access",
|
||||
change_details: access === 0 ? "private" : "public",
|
||||
element: E_PAGES,
|
||||
});
|
||||
},
|
||||
title: access === 0 ? "Make private" : "Make public",
|
||||
icon: access === 0 ? Lock : UsersRound,
|
||||
shouldRender: canCurrentUserChangeAccess && !archived_at,
|
||||
@ -69,14 +80,23 @@ export const PageQuickActions: React.FC<Props> = observer((props) => {
|
||||
},
|
||||
{
|
||||
key: "archive-restore",
|
||||
action: archived_at ? restore : archive,
|
||||
action: () => {
|
||||
archived_at ? restore() : archive();
|
||||
captureEvent(archived_at ? PAGE_RESTORED : PAGE_ARCHIVED, {
|
||||
page_id: pageId,
|
||||
element: E_PAGES,
|
||||
});
|
||||
},
|
||||
title: archived_at ? "Restore" : "Archive",
|
||||
icon: archived_at ? ArchiveRestoreIcon : ArchiveIcon,
|
||||
shouldRender: canCurrentUserArchivePage,
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
action: () => setDeletePageModal(true),
|
||||
action: () => {
|
||||
setTrackElement(E_PAGES);
|
||||
setDeletePageModal(true);
|
||||
},
|
||||
title: "Delete",
|
||||
icon: Trash2,
|
||||
shouldRender: canCurrentUserDeletePage && !!archived_at,
|
||||
|
@ -8,10 +8,12 @@ import { ArchiveIcon } from "@plane/ui";
|
||||
// components
|
||||
import { GptAssistantPopover } from "@/components/core";
|
||||
import { PageInfoPopover, PageOptionsDropdown } from "@/components/pages";
|
||||
// constants
|
||||
import { AI_RES_REGENERATED, AI_RES_USED, AI_TRIGGERED, E_PAGES_DETAIL } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
// hooks
|
||||
import { useInstance } from "@/hooks/store";
|
||||
import { useInstance, useEventTracker } from "@/hooks/store";
|
||||
// store
|
||||
import { IPageStore } from "@/store/pages/page.store";
|
||||
|
||||
@ -29,12 +31,19 @@ export const PageExtraOptions: React.FC<Props> = observer((props) => {
|
||||
const [gptModalOpen, setGptModal] = useState(false);
|
||||
// store hooks
|
||||
const { config } = useInstance();
|
||||
const { captureEvent } = useEventTracker();
|
||||
// derived values
|
||||
const { archived_at, isContentEditable, is_locked } = page;
|
||||
const { archived_at, isContentEditable, is_locked, id } = page;
|
||||
|
||||
const handleAiAssistance = async (response: string) => {
|
||||
const handleAiAssistance = async (task: string, response: string) => {
|
||||
if (!editorRef) return;
|
||||
editorRef.current?.setEditorValueAtCursorPosition(response);
|
||||
captureEvent(AI_RES_USED, {
|
||||
page_id: id,
|
||||
element: E_PAGES_DETAIL,
|
||||
question: task,
|
||||
answer: response,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@ -61,6 +70,21 @@ export const PageExtraOptions: React.FC<Props> = observer((props) => {
|
||||
// reset(getValues());
|
||||
}}
|
||||
onResponse={handleAiAssistance}
|
||||
onGenerateResponse={(task) =>
|
||||
captureEvent(AI_TRIGGERED, {
|
||||
page_id: id,
|
||||
element: E_PAGES_DETAIL,
|
||||
question: task,
|
||||
})
|
||||
}
|
||||
onReGenerateResponse={(task, response) =>
|
||||
captureEvent(AI_RES_REGENERATED, {
|
||||
page_id: id,
|
||||
element: E_PAGES_DETAIL,
|
||||
question: task,
|
||||
prev_answer: response,
|
||||
})
|
||||
}
|
||||
placement="top-end"
|
||||
button={
|
||||
<button
|
||||
|
@ -7,11 +7,12 @@ import { ArchiveIcon, CustomMenu, TOAST_TYPE, ToggleSwitch, setToast } from "@pl
|
||||
// helpers
|
||||
import { copyTextToClipboard, copyUrlToClipboard } from "@/helpers/string.helper";
|
||||
// hooks
|
||||
import { useAppRouter } from "@/hooks/store";
|
||||
import { useAppRouter, useEventTracker } from "@/hooks/store";
|
||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||
|
||||
// store
|
||||
import { IPageStore } from "@/store/pages/page.store";
|
||||
import { E_PAGES_DETAIL, PAGE_ARCHIVED, PAGE_LOCKED, PAGE_RESTORED, PAGE_UNLOCKED } from "@/constants/event-tracker";
|
||||
|
||||
type Props = {
|
||||
editorRef: EditorRefApi | EditorReadOnlyRefApi | null;
|
||||
@ -33,46 +34,84 @@ export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
||||
canCurrentUserDuplicatePage,
|
||||
canCurrentUserLockPage,
|
||||
restore,
|
||||
access,
|
||||
} = page;
|
||||
// store hooks
|
||||
const { workspaceSlug, projectId } = useAppRouter();
|
||||
const { captureEvent } = useEventTracker();
|
||||
// page filters
|
||||
const { isFullWidth, handleFullWidth } = usePageFilters();
|
||||
const handleArchivePage = async () =>
|
||||
await archive().catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be archived. Please try again later.",
|
||||
})
|
||||
);
|
||||
await archive()
|
||||
.then(() =>
|
||||
captureEvent(PAGE_ARCHIVED, {
|
||||
page_id: id,
|
||||
access: access === 1 ? "private" : "public",
|
||||
element: E_PAGES_DETAIL,
|
||||
state: "SUCCESS",
|
||||
})
|
||||
)
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be archived. Please try again later.",
|
||||
})
|
||||
);
|
||||
|
||||
const handleRestorePage = async () =>
|
||||
await restore().catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be restored. Please try again later.",
|
||||
})
|
||||
);
|
||||
await restore()
|
||||
.then(() =>
|
||||
captureEvent(PAGE_RESTORED, {
|
||||
page_id: id,
|
||||
access: access === 1 ? "private" : "public",
|
||||
element: E_PAGES_DETAIL,
|
||||
state: "SUCCESS",
|
||||
})
|
||||
)
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be restored. Please try again later.",
|
||||
})
|
||||
);
|
||||
|
||||
const handleLockPage = async () =>
|
||||
await lock().catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be locked. Please try again later.",
|
||||
})
|
||||
);
|
||||
await lock()
|
||||
.then(() =>
|
||||
captureEvent(PAGE_LOCKED, {
|
||||
page_id: id,
|
||||
access: access === 1 ? "private" : "public",
|
||||
element: E_PAGES_DETAIL,
|
||||
state: "SUCCESS",
|
||||
})
|
||||
)
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be locked. Please try again later.",
|
||||
})
|
||||
);
|
||||
|
||||
const handleUnlockPage = async () =>
|
||||
await unlock().catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be unlocked. Please try again later.",
|
||||
})
|
||||
);
|
||||
await unlock()
|
||||
.then(() =>
|
||||
captureEvent(PAGE_UNLOCKED, {
|
||||
page_id: id,
|
||||
access: access === 1 ? "private" : "public",
|
||||
element: E_PAGES_DETAIL,
|
||||
state: "SUCCESS",
|
||||
})
|
||||
)
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Page could not be unlocked. Please try again later.",
|
||||
})
|
||||
);
|
||||
|
||||
// menu items list
|
||||
const MENU_ITEMS: {
|
||||
|
@ -11,10 +11,13 @@ import {
|
||||
PageSearchInput,
|
||||
PageTabNavigation,
|
||||
} from "@/components/pages";
|
||||
// constants
|
||||
import { PAGES_SORT_UPDATED } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { calculateTotalFilters } from "@/helpers/filter.helper";
|
||||
// hooks
|
||||
import { useMember, useProjectPages } from "@/hooks/store";
|
||||
import { useMember, useProjectPages, useEventTracker } from "@/hooks/store";
|
||||
import { filter } from "lodash";
|
||||
|
||||
type Props = {
|
||||
pageType: TPageNavigationTabs;
|
||||
@ -29,6 +32,7 @@ export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
|
||||
const {
|
||||
workspace: { workspaceMemberIds },
|
||||
} = useMember();
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
const handleRemoveFilter = useCallback(
|
||||
(key: keyof TPageFilterProps, value: string | null) => {
|
||||
@ -59,6 +63,14 @@ export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
|
||||
onChange={(val) => {
|
||||
if (val.key) updateFilters("sortKey", val.key);
|
||||
if (val.order) updateFilters("sortBy", val.order);
|
||||
captureEvent(PAGES_SORT_UPDATED, {
|
||||
changed_property: val.order ? "sort_by" : "order_by",
|
||||
change_details: val.order || val.key,
|
||||
current_sort: {
|
||||
order_by: filters.sortKey,
|
||||
sort_by: filters.sortBy,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<FiltersDropdown
|
||||
|
@ -6,10 +6,12 @@ import { Avatar, TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
|
||||
// components
|
||||
import { FavoriteStar } from "@/components/core";
|
||||
import { PageQuickActions } from "@/components/pages/dropdowns";
|
||||
// constants
|
||||
import { E_PAGES, PAGE_FAVORITED, PAGE_UNFAVORITED } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||
// hooks
|
||||
import { useMember, usePage } from "@/hooks/store";
|
||||
import { useMember, usePage, useEventTracker } from "@/hooks/store";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
@ -24,6 +26,7 @@ export const BlockItemAction: FC<Props> = observer((props) => {
|
||||
// store hooks
|
||||
const { access, created_at, is_favorite, owned_by, addToFavorites, removeFromFavorites } = usePage(pageId);
|
||||
const { getUserDetails } = useMember();
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
// derived values
|
||||
const ownerDetails = owned_by ? getUserDetails(owned_by) : undefined;
|
||||
@ -31,21 +34,31 @@ export const BlockItemAction: FC<Props> = observer((props) => {
|
||||
// handlers
|
||||
const handleFavorites = () => {
|
||||
if (is_favorite)
|
||||
removeFromFavorites().then(() =>
|
||||
removeFromFavorites().then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Page removed from favorites.",
|
||||
})
|
||||
);
|
||||
});
|
||||
captureEvent(PAGE_UNFAVORITED, {
|
||||
page_id: pageId,
|
||||
element: E_PAGES,
|
||||
state: "SUCCESS",
|
||||
});
|
||||
});
|
||||
else
|
||||
addToFavorites().then(() =>
|
||||
addToFavorites().then(() => {
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Page added to favorites.",
|
||||
})
|
||||
);
|
||||
});
|
||||
captureEvent(PAGE_FAVORITED, {
|
||||
page_id: pageId,
|
||||
element: E_PAGES,
|
||||
state: "SUCCESS",
|
||||
});
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
|
@ -5,6 +5,10 @@ import { TPageFilterProps, TPageFilters } from "@plane/types";
|
||||
// components
|
||||
import { FilterOption } from "@/components/issues";
|
||||
import { FilterCreatedBy, FilterCreatedDate } from "@/components/pages";
|
||||
// constants
|
||||
import { PAGES_FILTER_APPLIED, PAGES_FILTER_REMOVED } from "@/constants/event-tracker";
|
||||
// hooks
|
||||
import { useEventTracker } from "@/hooks/store";
|
||||
|
||||
type Props = {
|
||||
filters: TPageFilters;
|
||||
@ -16,11 +20,13 @@ export const PageFiltersSelection: React.FC<Props> = observer((props) => {
|
||||
const { filters, handleFiltersUpdate, memberIds } = props;
|
||||
// states
|
||||
const [filtersSearchQuery, setFiltersSearchQuery] = useState("");
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
const handleFilters = (key: keyof TPageFilterProps, value: boolean | string | string[]) => {
|
||||
const newValues = filters.filters?.[key] ?? [];
|
||||
if (typeof filters.filters?.[key] === "boolean" && typeof value === "boolean") return;
|
||||
|
||||
if (typeof newValues === "boolean" && typeof value === "boolean") return;
|
||||
const newValues = Array.from((filters.filters?.[key] ?? []) as string[]);
|
||||
|
||||
if (Array.isArray(newValues)) {
|
||||
if (Array.isArray(value))
|
||||
@ -32,6 +38,16 @@ export const PageFiltersSelection: React.FC<Props> = observer((props) => {
|
||||
if (newValues?.includes(value)) newValues.splice(newValues.indexOf(value), 1);
|
||||
else newValues.push(value);
|
||||
}
|
||||
captureEvent(
|
||||
((filters.filters?.[key] ?? []) as string[]).length > newValues.length
|
||||
? PAGES_FILTER_REMOVED
|
||||
: PAGES_FILTER_APPLIED,
|
||||
{
|
||||
filter_type: key,
|
||||
filter_property: value,
|
||||
current_filters: filters?.filters,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
handleFiltersUpdate("filters", {
|
||||
@ -64,12 +80,17 @@ export const PageFiltersSelection: React.FC<Props> = observer((props) => {
|
||||
<div className="py-2">
|
||||
<FilterOption
|
||||
isChecked={!!filters.filters?.favorites}
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
handleFiltersUpdate("filters", {
|
||||
...filters.filters,
|
||||
favorites: !filters.filters?.favorites,
|
||||
})
|
||||
}
|
||||
});
|
||||
captureEvent(!filters.filters?.favorites ? PAGES_FILTER_REMOVED : PAGES_FILTER_APPLIED, {
|
||||
filter_type: "favorites",
|
||||
filter_property: filters.filters?.favorites,
|
||||
current_filters: filters,
|
||||
});
|
||||
}}
|
||||
title="Favorites"
|
||||
/>
|
||||
</div>
|
||||
|
@ -2,8 +2,12 @@ import { FC } from "react";
|
||||
import Link from "next/link";
|
||||
// types
|
||||
import { TPageNavigationTabs } from "@plane/types";
|
||||
// constants
|
||||
import { PAGES_TAB_CHANGED, E_PAGES } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// hooks
|
||||
import { useEventTracker } from "@/hooks/store";
|
||||
|
||||
type TPageTabNavigation = {
|
||||
workspaceSlug: string;
|
||||
@ -29,9 +33,15 @@ const pageTabs: { key: TPageNavigationTabs; label: string }[] = [
|
||||
|
||||
export const PageTabNavigation: FC<TPageTabNavigation> = (props) => {
|
||||
const { workspaceSlug, projectId, pageType } = props;
|
||||
// store hooks
|
||||
const { captureEvent } = useEventTracker();
|
||||
|
||||
const handleTabClick = (e: React.MouseEvent<HTMLAnchorElement>, tabKey: TPageNavigationTabs) => {
|
||||
if (tabKey === pageType) e.preventDefault();
|
||||
captureEvent(PAGES_TAB_CHANGED, {
|
||||
tab: tabKey,
|
||||
element: E_PAGES,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -178,6 +178,21 @@ export const STATE_DELETED = "State deleted";
|
||||
export const PAGE_CREATED = "Page created";
|
||||
export const PAGE_UPDATED = "Page updated";
|
||||
export const PAGE_DELETED = "Page deleted";
|
||||
export const PAGE_FAVORITED = "Page favorited";
|
||||
export const PAGE_UNFAVORITED = "Page unfavorited";
|
||||
export const PAGE_ARCHIVED = "Page archived";
|
||||
export const PAGE_LOCKED = "Page locked";
|
||||
export const PAGE_UNLOCKED = "Page unlocked";
|
||||
export const PAGE_DUPLICATED = "Page duplicated";
|
||||
export const PAGE_RESTORED = "Page restored";
|
||||
export const PAGES_TAB_CHANGED = "Pages tab changed";
|
||||
export const PAGES_SORT_UPDATED = "Pages sort updated";
|
||||
export const PAGES_FILTER_APPLIED = "Pages filter applied";
|
||||
export const PAGES_FILTER_REMOVED = "Pages filter removed";
|
||||
// AI Assistant Events
|
||||
export const AI_TRIGGERED = "AI triggered";
|
||||
export const AI_RES_USED = "AI response used";
|
||||
export const AI_RES_REGENERATED = "AI response regenerated";
|
||||
// Member Events
|
||||
export const MEMBER_INVITED = "Member invited";
|
||||
export const MEMBER_ACCEPTED = "Member accepted";
|
||||
@ -222,3 +237,7 @@ export const SNOOZED_NOTIFICATIONS = "Snoozed notifications viewed";
|
||||
export const ARCHIVED_NOTIFICATIONS = "Archived notifications viewed";
|
||||
// Groups
|
||||
export const GROUP_WORKSPACE = "Workspace_metrics";
|
||||
|
||||
//Elements
|
||||
export const E_PAGES = "Pages page"
|
||||
export const E_PAGES_DETAIL = "Pages detail page"
|
@ -15,10 +15,12 @@ import { PageHead } from "@/components/core";
|
||||
import { PageDetailsHeader } from "@/components/headers";
|
||||
import { IssuePeekOverview } from "@/components/issues";
|
||||
import { PageEditorBody, PageEditorHeaderRoot } from "@/components/pages";
|
||||
// constants
|
||||
import { E_PAGES_DETAIL, PAGE_DUPLICATED } from "@/constants/event-tracker";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// hooks
|
||||
import { usePage, useProjectPages } from "@/hooks/store";
|
||||
import { usePage, useProjectPages, useEventTracker } from "@/hooks/store";
|
||||
// layouts
|
||||
import { AppLayout } from "@/layouts/app-layout";
|
||||
// lib
|
||||
@ -38,7 +40,8 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
// store hooks
|
||||
const { createPage, getPageById } = useProjectPages(projectId?.toString() ?? "");
|
||||
const page = usePage(pageId?.toString() ?? "");
|
||||
const { description_html, id, name } = page;
|
||||
const { captureEvent } = useEventTracker();
|
||||
const { description_html, id, name, access } = page;
|
||||
// editor markings hook
|
||||
const { markings, updateMarkings } = useEditorMarkings();
|
||||
// fetch page details
|
||||
@ -84,7 +87,15 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
};
|
||||
|
||||
await handleCreatePage(formData)
|
||||
.then((res) => router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res?.id}`))
|
||||
.then((res) => {
|
||||
router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res?.id}`);
|
||||
captureEvent(PAGE_DUPLICATED, {
|
||||
page_id: pageId,
|
||||
access: access == 1 ? "private" : "public",
|
||||
element: E_PAGES_DETAIL,
|
||||
state: "SUCCESS",
|
||||
});
|
||||
})
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
|
Loading…
Reference in New Issue
Block a user