mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: added project-views related events
This commit is contained in:
parent
64fe785722
commit
c237effa75
@ -2,7 +2,7 @@ import { useRouter } from "next/router";
|
|||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useApplication, useProject, useUser } from "hooks/store";
|
import { useApplication, useEventTracker, useProject, useUser } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
|
import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
|
||||||
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
|
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
|
||||||
@ -24,6 +24,7 @@ export const ProjectViewsHeader: React.FC = observer(() => {
|
|||||||
membership: { currentProjectRole },
|
membership: { currentProjectRole },
|
||||||
} = useUser();
|
} = useUser();
|
||||||
const { currentProjectDetails } = useProject();
|
const { currentProjectDetails } = useProject();
|
||||||
|
const { setTrackElement } = useEventTracker();
|
||||||
|
|
||||||
const canUserCreateIssue =
|
const canUserCreateIssue =
|
||||||
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
currentProjectRole && [EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER].includes(currentProjectRole);
|
||||||
@ -75,7 +76,10 @@ export const ProjectViewsHeader: React.FC = observer(() => {
|
|||||||
variant="primary"
|
variant="primary"
|
||||||
size="sm"
|
size="sm"
|
||||||
prependIcon={<Plus className="h-3.5 w-3.5 stroke-2" />}
|
prependIcon={<Plus className="h-3.5 w-3.5 stroke-2" />}
|
||||||
onClick={() => toggleCreateViewModal(true)}
|
onClick={() => {
|
||||||
|
setTrackElement("Views page");
|
||||||
|
toggleCreateViewModal(true);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Create View
|
Create View
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -2,14 +2,16 @@ import { useRouter } from "next/router";
|
|||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
// hooks
|
// hooks
|
||||||
import { useIssues, useLabel, useProjectState, useProjectView } from "hooks/store";
|
import { useEventTracker, useIssues, useLabel, useProjectState, useProjectView } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
import { AppliedFiltersList } from "components/issues";
|
import { AppliedFiltersList } from "components/issues";
|
||||||
// ui
|
// ui
|
||||||
import { Button } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import { IIssueFilterOptions } from "@plane/types";
|
import { IIssueFilterOptions } from "@plane/types";
|
||||||
|
// constants
|
||||||
import { EIssueFilterType, EIssuesStoreType } from "constants/issue";
|
import { EIssueFilterType, EIssuesStoreType } from "constants/issue";
|
||||||
|
import { VIEW_UPDATED } from "constants/event-tracker";
|
||||||
|
|
||||||
export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
||||||
// router
|
// router
|
||||||
@ -26,6 +28,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||||||
const { projectLabels } = useLabel();
|
const { projectLabels } = useLabel();
|
||||||
const { projectStates } = useProjectState();
|
const { projectStates } = useProjectState();
|
||||||
const { viewMap, updateView } = useProjectView();
|
const { viewMap, updateView } = useProjectView();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
// derived values
|
// derived values
|
||||||
const viewDetails = viewId ? viewMap[viewId.toString()] : null;
|
const viewDetails = viewId ? viewMap[viewId.toString()] : null;
|
||||||
const userFilters = issueFilters?.filters;
|
const userFilters = issueFilters?.filters;
|
||||||
@ -87,6 +90,13 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||||||
filters: {
|
filters: {
|
||||||
...(appliedFilters ?? {}),
|
...(appliedFilters ?? {}),
|
||||||
},
|
},
|
||||||
|
}).then((res) => {
|
||||||
|
captureEvent(VIEW_UPDATED, {
|
||||||
|
view_id: res.id,
|
||||||
|
filters: res.filters,
|
||||||
|
element: "View Navbar",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,12 +4,13 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import { AlertTriangle } from "lucide-react";
|
import { AlertTriangle } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectView } from "hooks/store";
|
import { useProjectView, useEventTracker } from "hooks/store";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// ui
|
// ui
|
||||||
import { Button } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import { IProjectView } from "@plane/types";
|
import { IProjectView } from "@plane/types";
|
||||||
|
import { VIEW_DELETED } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: IProjectView;
|
data: IProjectView;
|
||||||
@ -26,6 +27,7 @@ export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
|
|||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { deleteView } = useProjectView();
|
const { deleteView } = useProjectView();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
// toast alert
|
// toast alert
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
@ -42,20 +44,29 @@ export const DeleteProjectViewModal: React.FC<Props> = observer((props) => {
|
|||||||
await deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
|
await deleteView(workspaceSlug.toString(), projectId.toString(), data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
handleClose();
|
handleClose();
|
||||||
|
captureEvent(VIEW_DELETED, {
|
||||||
|
view_id: data.id,
|
||||||
|
element: "Views page",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "View deleted successfully.",
|
message: "View deleted successfully.",
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() => {
|
||||||
|
captureEvent(VIEW_DELETED, {
|
||||||
|
view_id: data.id,
|
||||||
|
element: "Views page",
|
||||||
|
state: "FAILED",
|
||||||
|
});
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: "View could not be deleted. Please try again.",
|
message: "View could not be deleted. Please try again.",
|
||||||
})
|
});
|
||||||
)
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setIsDeleteLoading(false);
|
setIsDeleteLoading(false);
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import { FC, Fragment } from "react";
|
import { FC, Fragment } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectView } from "hooks/store";
|
import { useEventTracker, useProjectView } from "hooks/store";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// components
|
// components
|
||||||
import { ProjectViewForm } from "components/views";
|
import { ProjectViewForm } from "components/views";
|
||||||
// types
|
// types
|
||||||
import { IProjectView } from "@plane/types";
|
import { IProjectView } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { VIEW_CREATED, VIEW_UPDATED } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data?: IProjectView | null;
|
data?: IProjectView | null;
|
||||||
@ -20,8 +23,12 @@ type Props = {
|
|||||||
|
|
||||||
export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
||||||
const { data, isOpen, onClose, preLoadedData, workspaceSlug, projectId } = props;
|
const { data, isOpen, onClose, preLoadedData, workspaceSlug, projectId } = props;
|
||||||
|
// router
|
||||||
|
const router = useRouter();
|
||||||
|
const { cycleId, moduleId, viewId } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { createView, updateView } = useProjectView();
|
const { createView, updateView } = useProjectView();
|
||||||
|
const { captureEvent, trackElement } = useEventTracker();
|
||||||
// toast alert
|
// toast alert
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
@ -31,33 +38,64 @@ export const CreateUpdateProjectViewModal: FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const handleCreateView = async (payload: IProjectView) => {
|
const handleCreateView = async (payload: IProjectView) => {
|
||||||
await createView(workspaceSlug, projectId, payload)
|
await createView(workspaceSlug, projectId, payload)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
|
captureEvent(VIEW_CREATED, {
|
||||||
|
view_id: res.id,
|
||||||
|
filters: res.filters,
|
||||||
|
element_id: cycleId ?? moduleId ?? viewId ?? projectId,
|
||||||
|
element: trackElement
|
||||||
|
? trackElement
|
||||||
|
: cycleId
|
||||||
|
? "Cycle issues page"
|
||||||
|
: moduleId
|
||||||
|
? "Module issues page"
|
||||||
|
: viewId
|
||||||
|
? "View issues page"
|
||||||
|
: "Project issues page",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "View created successfully.",
|
message: "View created successfully.",
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() => {
|
||||||
|
captureEvent(VIEW_CREATED, {
|
||||||
|
state: "FAILED",
|
||||||
|
});
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: "Something went wrong. Please try again.",
|
message: "Something went wrong. Please try again.",
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateView = async (payload: IProjectView) => {
|
const handleUpdateView = async (payload: IProjectView) => {
|
||||||
await updateView(workspaceSlug, projectId, data?.id as string, payload)
|
await updateView(workspaceSlug, projectId, data?.id as string, payload)
|
||||||
.then(() => handleClose())
|
.then((res) => {
|
||||||
.catch((err) =>
|
captureEvent(VIEW_UPDATED, {
|
||||||
|
view_id: res.id,
|
||||||
|
filters: res.filters,
|
||||||
|
element: "Views page",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
|
handleClose();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
captureEvent(VIEW_UPDATED, {
|
||||||
|
view_id: data?.id,
|
||||||
|
element: "Views page",
|
||||||
|
state: "FAILED",
|
||||||
|
});
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: err.detail ?? "Something went wrong. Please try again.",
|
message: err.detail ?? "Something went wrong. Please try again.",
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFormSubmit = async (formData: IProjectView) => {
|
const handleFormSubmit = async (formData: IProjectView) => {
|
||||||
|
@ -4,7 +4,7 @@ import { useRouter } from "next/router";
|
|||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react";
|
import { LinkIcon, PencilIcon, StarIcon, TrashIcon } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectView, useUser } from "hooks/store";
|
import { useEventTracker, useProjectView, useUser } from "hooks/store";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// components
|
// components
|
||||||
import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "components/views";
|
import { CreateUpdateProjectViewModal, DeleteProjectViewModal } from "components/views";
|
||||||
@ -17,6 +17,7 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
|||||||
import { IProjectView } from "@plane/types";
|
import { IProjectView } from "@plane/types";
|
||||||
// constants
|
// constants
|
||||||
import { EUserProjectRoles } from "constants/project";
|
import { EUserProjectRoles } from "constants/project";
|
||||||
|
import { VIEW_FAVORITED, VIEW_UNFAVORITED } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
view: IProjectView;
|
view: IProjectView;
|
||||||
@ -37,17 +38,30 @@ export const ProjectViewListItem: React.FC<Props> = observer((props) => {
|
|||||||
membership: { currentProjectRole },
|
membership: { currentProjectRole },
|
||||||
} = useUser();
|
} = useUser();
|
||||||
const { addViewToFavorites, removeViewFromFavorites } = useProjectView();
|
const { addViewToFavorites, removeViewFromFavorites } = useProjectView();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleAddToFavorites = () => {
|
const handleAddToFavorites = () => {
|
||||||
if (!workspaceSlug || !projectId) return;
|
if (!workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
|
addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id).then(() => {
|
||||||
|
captureEvent(VIEW_FAVORITED, {
|
||||||
|
view_id: view.id,
|
||||||
|
element: "Views page",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveFromFavorites = () => {
|
const handleRemoveFromFavorites = () => {
|
||||||
if (!workspaceSlug || !projectId) return;
|
if (!workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
removeViewFromFavorites(workspaceSlug.toString(), projectId.toString(), view.id);
|
removeViewFromFavorites(workspaceSlug.toString(), projectId.toString(), view.id).then(() => {
|
||||||
|
captureEvent(VIEW_UNFAVORITED, {
|
||||||
|
view_id: view.id,
|
||||||
|
element: "Views page",
|
||||||
|
state: "SUCCESS",
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => {
|
const handleCopyText = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
@ -3,7 +3,7 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { Search } from "lucide-react";
|
import { Search } from "lucide-react";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
// hooks
|
// hooks
|
||||||
import { useApplication, useProjectView, useUser } from "hooks/store";
|
import { useApplication, useEventTracker, useProjectView, useUser } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
import { ProjectViewListItem } from "components/views";
|
import { ProjectViewListItem } from "components/views";
|
||||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||||
@ -28,6 +28,7 @@ export const ProjectViewsList = observer(() => {
|
|||||||
currentUser,
|
currentUser,
|
||||||
} = useUser();
|
} = useUser();
|
||||||
const { projectViewIds, getViewById, loader } = useProjectView();
|
const { projectViewIds, getViewById, loader } = useProjectView();
|
||||||
|
const { setTrackElement } = useEventTracker();
|
||||||
|
|
||||||
if (loader || !projectViewIds) return <ViewListLoader />;
|
if (loader || !projectViewIds) return <ViewListLoader />;
|
||||||
|
|
||||||
@ -73,7 +74,10 @@ export const ProjectViewsList = observer(() => {
|
|||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: VIEW_EMPTY_STATE_DETAILS["project-views"].primaryButton.text,
|
text: VIEW_EMPTY_STATE_DETAILS["project-views"].primaryButton.text,
|
||||||
onClick: () => toggleCreateViewModal(true),
|
onClick: () => {
|
||||||
|
setTrackElement("Views empty state");
|
||||||
|
toggleCreateViewModal(true);
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
size="lg"
|
size="lg"
|
||||||
disabled={!isEditingAllowed}
|
disabled={!isEditingAllowed}
|
||||||
|
@ -165,6 +165,12 @@ export const MODULE_UNFAVORITED = "Module unfavorited";
|
|||||||
export const MODULE_LINK_CREATED = "Module link created";
|
export const MODULE_LINK_CREATED = "Module link created";
|
||||||
export const MODULE_LINK_UPDATED = "Module link updated";
|
export const MODULE_LINK_UPDATED = "Module link updated";
|
||||||
export const MODULE_LINK_DELETED = "Module link deleted";
|
export const MODULE_LINK_DELETED = "Module link deleted";
|
||||||
|
// Project View Events
|
||||||
|
export const VIEW_CREATED = "View created";
|
||||||
|
export const VIEW_UPDATED = "View updated";
|
||||||
|
export const VIEW_DELETED = "View deleted";
|
||||||
|
export const VIEW_FAVORITED = "View favorited";
|
||||||
|
export const VIEW_UNFAVORITED = "View unfavorited";
|
||||||
// Issue Events
|
// Issue Events
|
||||||
export const ISSUE_CREATED = "Issue created";
|
export const ISSUE_CREATED = "Issue created";
|
||||||
export const ISSUE_UPDATED = "Issue updated";
|
export const ISSUE_UPDATED = "Issue updated";
|
||||||
|
Loading…
Reference in New Issue
Block a user