mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
adding capture function for tacking events in posthog
This commit is contained in:
parent
df62c97579
commit
4303658ddb
@ -34,7 +34,6 @@ import {
|
||||
} from "constants/fetch-keys";
|
||||
// constants
|
||||
import { INBOX_ISSUE_SOURCE } from "constants/inbox";
|
||||
import { usePostHog } from "posthog-js/react";
|
||||
import { ISSUE_CREATE } from "constants/posthog-events";
|
||||
|
||||
export interface IssuesModalProps {
|
||||
@ -69,7 +68,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
fieldsToShow = ["all"],
|
||||
onSubmit,
|
||||
}) => {
|
||||
const posthog = usePostHog();
|
||||
// states
|
||||
const [createMore, setCreateMore] = useState(false);
|
||||
const [activeProject, setActiveProject] = useState<string | null>(null);
|
||||
@ -241,7 +239,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
|
||||
await issuesService
|
||||
.createIssues(workspaceSlug as string, activeProject ?? "", payload, user)
|
||||
.then(async (res) => {
|
||||
posthog?.capture(ISSUE_CREATE);
|
||||
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
|
||||
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
||||
if (payload.module && payload.module !== "")
|
||||
|
@ -26,110 +26,121 @@ type Props = {
|
||||
|
||||
export type TPeekOverviewModes = "side" | "modal" | "full";
|
||||
|
||||
export const IssuePeekOverview: React.FC<Props> = observer(
|
||||
({ handleMutation, projectId, readOnly, workspaceSlug }) => {
|
||||
const [isSidePeekOpen, setIsSidePeekOpen] = useState(false);
|
||||
const [isModalPeekOpen, setIsModalPeekOpen] = useState(false);
|
||||
const [peekOverviewMode, setPeekOverviewMode] = useState<TPeekOverviewModes>("side");
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
export const IssuePeekOverview: React.FC<Props> = observer((props) => {
|
||||
const { handleMutation, projectId, readOnly, workspaceSlug } = props;
|
||||
// states
|
||||
const [isSidePeekOpen, setIsSidePeekOpen] = useState(false);
|
||||
const [isModalPeekOpen, setIsModalPeekOpen] = useState(false);
|
||||
const [peekOverviewMode, setPeekOverviewMode] = useState<TPeekOverviewModes>("side");
|
||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
const { peekIssue } = router.query;
|
||||
const router = useRouter();
|
||||
const { peekIssue } = router.query;
|
||||
|
||||
const { issues: issuesStore } = useMobxStore();
|
||||
const { deleteIssue, getIssueById, issues, updateIssue } = issuesStore;
|
||||
const { issues: issuesStore } = useMobxStore();
|
||||
const { deleteIssue, getIssueById, issues, updateIssue } = issuesStore;
|
||||
|
||||
const issue = issues[peekIssue?.toString() ?? ""];
|
||||
const issue = issues[peekIssue?.toString() ?? ""];
|
||||
|
||||
const { user } = useUser();
|
||||
const { user } = useUser();
|
||||
|
||||
const handleClose = () => {
|
||||
const { query } = router;
|
||||
delete query.peekIssue;
|
||||
const handleClose = () => {
|
||||
const { query } = router;
|
||||
delete query.peekIssue;
|
||||
|
||||
router.push({
|
||||
pathname: router.pathname,
|
||||
query: { ...query },
|
||||
});
|
||||
};
|
||||
router.push({
|
||||
pathname: router.pathname,
|
||||
query: { ...query },
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdateIssue = async (formData: Partial<IIssue>) => {
|
||||
if (!issue || !user) return;
|
||||
const handleUpdateIssue = async (formData: Partial<IIssue>) => {
|
||||
if (!issue || !user) return;
|
||||
|
||||
await updateIssue(workspaceSlug, projectId, issue.id, formData, user);
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
|
||||
handleMutation();
|
||||
};
|
||||
await updateIssue(workspaceSlug, projectId, issue.id, formData, user);
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
|
||||
handleMutation();
|
||||
};
|
||||
|
||||
const handleDeleteIssue = async () => {
|
||||
if (!issue || !user) return;
|
||||
const handleDeleteIssue = async () => {
|
||||
if (!issue || !user) return;
|
||||
await deleteIssue(workspaceSlug, projectId, issue.id, user);
|
||||
handleMutation();
|
||||
handleClose();
|
||||
};
|
||||
|
||||
await deleteIssue(workspaceSlug, projectId, issue.id, user);
|
||||
handleMutation();
|
||||
useEffect(() => {
|
||||
if (!peekIssue) return;
|
||||
|
||||
handleClose();
|
||||
};
|
||||
getIssueById(workspaceSlug, projectId, peekIssue.toString());
|
||||
}, [getIssueById, peekIssue, projectId, workspaceSlug]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!peekIssue) return;
|
||||
|
||||
getIssueById(workspaceSlug, projectId, peekIssue.toString());
|
||||
}, [getIssueById, peekIssue, projectId, workspaceSlug]);
|
||||
|
||||
useEffect(() => {
|
||||
if (peekIssue) {
|
||||
if (peekOverviewMode === "side") {
|
||||
setIsSidePeekOpen(true);
|
||||
setIsModalPeekOpen(false);
|
||||
} else {
|
||||
setIsModalPeekOpen(true);
|
||||
setIsSidePeekOpen(false);
|
||||
}
|
||||
} else {
|
||||
setIsSidePeekOpen(false);
|
||||
useEffect(() => {
|
||||
if (peekIssue) {
|
||||
if (peekOverviewMode === "side") {
|
||||
setIsSidePeekOpen(true);
|
||||
setIsModalPeekOpen(false);
|
||||
} else {
|
||||
setIsModalPeekOpen(true);
|
||||
setIsSidePeekOpen(false);
|
||||
}
|
||||
}, [peekIssue, peekOverviewMode]);
|
||||
} else {
|
||||
setIsSidePeekOpen(false);
|
||||
setIsModalPeekOpen(false);
|
||||
}
|
||||
}, [peekIssue, peekOverviewMode]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DeleteIssueModal
|
||||
isOpen={deleteIssueModal}
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
data={issue ? { ...issue } : null}
|
||||
onSubmit={handleDeleteIssue}
|
||||
user={user}
|
||||
/>
|
||||
<Transition.Root appear show={isSidePeekOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="transition-transform duration-300"
|
||||
enterFrom="translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transition-transform duration-200"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="fixed z-20 bg-custom-background-100 top-0 right-0 h-full w-1/2 shadow-custom-shadow-md">
|
||||
<SidePeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
<Transition.Root appear show={isModalPeekOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
return (
|
||||
<>
|
||||
<DeleteIssueModal
|
||||
isOpen={deleteIssueModal}
|
||||
handleClose={() => setDeleteIssueModal(false)}
|
||||
data={issue ? { ...issue } : null}
|
||||
onSubmit={handleDeleteIssue}
|
||||
user={user}
|
||||
/>
|
||||
<Transition.Root appear show={isSidePeekOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="transition-transform duration-300"
|
||||
enterFrom="translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transition-transform duration-200"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="fixed z-20 bg-custom-background-100 top-0 right-0 h-full w-1/2 shadow-custom-shadow-md">
|
||||
<SidePeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
<Transition.Root appear show={isModalPeekOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
|
||||
</Transition.Child>
|
||||
<div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-out duration-300"
|
||||
@ -139,55 +150,42 @@ export const IssuePeekOverview: React.FC<Props> = observer(
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
|
||||
<Dialog.Panel>
|
||||
<div
|
||||
className={`fixed z-20 bg-custom-background-100 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg shadow-custom-shadow-xl transition-all duration-300 ${
|
||||
peekOverviewMode === "modal" ? "h-[70%] w-3/5" : "h-[95%] w-[95%]"
|
||||
}`}
|
||||
>
|
||||
{peekOverviewMode === "modal" && (
|
||||
<SidePeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
)}
|
||||
{peekOverviewMode === "full" && (
|
||||
<FullScreenPeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
<div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Dialog.Panel>
|
||||
<div
|
||||
className={`fixed z-20 bg-custom-background-100 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg shadow-custom-shadow-xl transition-all duration-300 ${
|
||||
peekOverviewMode === "modal" ? "h-[70%] w-3/5" : "h-[95%] w-[95%]"
|
||||
}`}
|
||||
>
|
||||
{peekOverviewMode === "modal" && (
|
||||
<SidePeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
)}
|
||||
{peekOverviewMode === "full" && (
|
||||
<FullScreenPeekView
|
||||
handleClose={handleClose}
|
||||
handleDeleteIssue={() => setDeleteIssueModal(true)}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
issue={issue}
|
||||
mode={peekOverviewMode}
|
||||
readOnly={readOnly}
|
||||
setMode={(mode) => setPeekOverviewMode(mode)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { usePostHog } from "posthog-js/react";
|
||||
import useSWR from "swr";
|
||||
// services
|
||||
import userService from "services/user.service";
|
||||
@ -11,7 +10,6 @@ import type { ICurrentUserResponse } from "types";
|
||||
|
||||
export default function useUser({ redirectTo = "", redirectIfFound = false, options = {} } = {}) {
|
||||
const router = useRouter();
|
||||
const posthog = usePostHog();
|
||||
// API to fetch user information
|
||||
const { data, isLoading, error, mutate } = useSWR<ICurrentUserResponse>(
|
||||
CURRENT_USER,
|
||||
|
@ -11,6 +11,10 @@ import type {
|
||||
ISubIssueResponse,
|
||||
} from "types";
|
||||
import { API_BASE_URL } from "helpers/common.helper";
|
||||
import PosthogService from "./posthog.service";
|
||||
import { ISSUE_CREATE } from "constants/posthog-events";
|
||||
|
||||
const posthogService = new PosthogService();
|
||||
|
||||
class ProjectIssuesServices extends APIService {
|
||||
constructor() {
|
||||
@ -26,6 +30,7 @@ class ProjectIssuesServices extends APIService {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
||||
.then((response) => {
|
||||
trackEventServices.trackIssueEvent(response.data, "ISSUE_CREATE", user);
|
||||
posthogService.capture(ISSUE_CREATE, response.data, user);
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
|
27
web/services/posthog.service.ts
Normal file
27
web/services/posthog.service.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import APIService from "./api.service";
|
||||
|
||||
class PosthogService extends APIService {
|
||||
constructor() {
|
||||
super("");
|
||||
}
|
||||
capture(event: string, data: any = {}, user: any = {}) {
|
||||
this.request({
|
||||
method: "post",
|
||||
url: `${process.env.NEXT_PUBLIC_POSTHOG_HOST || ""}/capture/`,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: {
|
||||
api_key: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
||||
properties: {
|
||||
user,
|
||||
...data,
|
||||
},
|
||||
distinct_id: user?.email,
|
||||
event,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default PosthogService;
|
@ -1,7 +1,4 @@
|
||||
// mobx
|
||||
import { ISSUE_CREATE } from "constants/posthog-events";
|
||||
import { action, observable, runInAction, makeAutoObservable } from "mobx";
|
||||
import { usePostHog } from "posthog-js/react";
|
||||
// services
|
||||
import issueService from "services/issues.service";
|
||||
// types
|
||||
|
Loading…
Reference in New Issue
Block a user