mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: added workspace settings events
This commit is contained in:
parent
35a9527325
commit
2b8569a0c9
@ -2,6 +2,8 @@ import { useState, Fragment, FC } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
// hooks
|
||||||
|
import { useEventTracker } from "hooks/store";
|
||||||
// services
|
// services
|
||||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
import { API_TOKENS_LIST } from "constants/fetch-keys";
|
import { API_TOKENS_LIST } from "constants/fetch-keys";
|
||||||
@ -9,6 +11,8 @@ import { APITokenService } from "services/api_token.service";
|
|||||||
// ui
|
// ui
|
||||||
// types
|
// types
|
||||||
import { IApiToken } from "@plane/types";
|
import { IApiToken } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { API_TOKEN_DELETED } from "constants/event-tracker";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -26,6 +30,8 @@ export const DeleteApiTokenModal: FC<Props> = (props) => {
|
|||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
// store hooks
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClose();
|
onClose();
|
||||||
@ -45,6 +51,9 @@ export const DeleteApiTokenModal: FC<Props> = (props) => {
|
|||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "Token deleted successfully.",
|
message: "Token deleted successfully.",
|
||||||
});
|
});
|
||||||
|
captureEvent(API_TOKEN_DELETED, {
|
||||||
|
token_id: tokenId,
|
||||||
|
});
|
||||||
|
|
||||||
mutate<IApiToken[]>(
|
mutate<IApiToken[]>(
|
||||||
API_TOKENS_LIST(workspaceSlug.toString()),
|
API_TOKENS_LIST(workspaceSlug.toString()),
|
||||||
|
@ -2,6 +2,8 @@ import React, { useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
// hooks
|
||||||
|
import { useEventTracker } from "hooks/store";
|
||||||
// services
|
// services
|
||||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ import { APITokenService } from "services/api_token.service";
|
|||||||
// helpers
|
// helpers
|
||||||
// types
|
// types
|
||||||
import { IApiToken } from "@plane/types";
|
import { IApiToken } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { API_TOKEN_CREATED } from "constants/event-tracker";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -33,6 +37,8 @@ export const CreateApiTokenModal: React.FC<Props> = (props) => {
|
|||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
// store hooks
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClose();
|
onClose();
|
||||||
@ -73,6 +79,11 @@ export const CreateApiTokenModal: React.FC<Props> = (props) => {
|
|||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
captureEvent(API_TOKEN_CREATED, {
|
||||||
|
token_id: res.id,
|
||||||
|
expiry_date: data.expired_at ?? undefined,
|
||||||
|
never_exprires: res.expired_at ? false : true,
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
setToast({
|
setToast({
|
||||||
|
@ -5,12 +5,14 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||||||
// hooks
|
// hooks
|
||||||
import { Button, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button, CustomSearchSelect, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
|
|
||||||
import { useProject } from "hooks/store";
|
import { useEventTracker, useProject } from "hooks/store";
|
||||||
// services
|
// services
|
||||||
import { ProjectExportService } from "services/project";
|
import { ProjectExportService } from "services/project";
|
||||||
// ui
|
// ui
|
||||||
// types
|
// types
|
||||||
import { IUser, IImporterService } from "@plane/types";
|
import { IUser, IImporterService } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { ISSUES_EXPORTED } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -33,6 +35,7 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
|||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { workspaceProjectIds, getProjectById } = useProject();
|
const { workspaceProjectIds, getProjectById } = useProject();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const options = workspaceProjectIds?.map((projectId) => {
|
const options = workspaceProjectIds?.map((projectId) => {
|
||||||
const projectDetails = getProjectById(projectId);
|
const projectDetails = getProjectById(projectId);
|
||||||
@ -68,6 +71,11 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
|||||||
mutateServices();
|
mutateServices();
|
||||||
router.push(`/${workspaceSlug}/settings/exports`);
|
router.push(`/${workspaceSlug}/settings/exports`);
|
||||||
setExportLoading(false);
|
setExportLoading(false);
|
||||||
|
captureEvent(ISSUES_EXPORTED, {
|
||||||
|
format: provider,
|
||||||
|
project_ids: value,
|
||||||
|
export_seperate: multiple,
|
||||||
|
});
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Export Successful",
|
title: "Export Successful",
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
import GithubLogo from "public/services/github.png";
|
import GithubLogo from "public/services/github.png";
|
||||||
import { IntegrationService, GithubIntegrationService } from "services/integrations";
|
import { IntegrationService, GithubIntegrationService } from "services/integrations";
|
||||||
// hooks
|
// hooks
|
||||||
|
import { useEventTracker } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
// icons
|
// icons
|
||||||
// images
|
// images
|
||||||
@ -31,6 +32,8 @@ import { IntegrationService, GithubIntegrationService } from "services/integrati
|
|||||||
import { IGithubRepoCollaborator, IGithubServiceImportFormData } from "@plane/types";
|
import { IGithubRepoCollaborator, IGithubServiceImportFormData } from "@plane/types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { APP_INTEGRATIONS, IMPORTER_SERVICES_LIST, WORKSPACE_INTEGRATIONS } from "constants/fetch-keys";
|
import { APP_INTEGRATIONS, IMPORTER_SERVICES_LIST, WORKSPACE_INTEGRATIONS } from "constants/fetch-keys";
|
||||||
|
// constants
|
||||||
|
import { GITHUB_ISSUES_IMPORTED } from "constants/event-tracker";
|
||||||
|
|
||||||
export type TIntegrationSteps = "import-configure" | "import-data" | "repo-details" | "import-users" | "import-confirm";
|
export type TIntegrationSteps = "import-configure" | "import-data" | "repo-details" | "import-users" | "import-confirm";
|
||||||
export interface IIntegrationData {
|
export interface IIntegrationData {
|
||||||
@ -90,9 +93,11 @@ export const GithubImporterRoot: React.FC = () => {
|
|||||||
state: "import-configure",
|
state: "import-configure",
|
||||||
});
|
});
|
||||||
const [users, setUsers] = useState<IUserDetails[]>([]);
|
const [users, setUsers] = useState<IUserDetails[]>([]);
|
||||||
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, provider } = router.query;
|
const { workspaceSlug, provider } = router.query;
|
||||||
|
// store hooks
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const { handleSubmit, control, setValue, watch } = useForm<TFormValues>({
|
const { handleSubmit, control, setValue, watch } = useForm<TFormValues>({
|
||||||
defaultValues: defaultFormValues,
|
defaultValues: defaultFormValues,
|
||||||
@ -147,6 +152,7 @@ export const GithubImporterRoot: React.FC = () => {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
router.push(`/${workspaceSlug}/settings/imports`);
|
router.push(`/${workspaceSlug}/settings/imports`);
|
||||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
||||||
|
captureEvent(GITHUB_ISSUES_IMPORTED);
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
setToast({
|
setToast({
|
||||||
|
@ -4,6 +4,8 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { FormProvider, useForm } from "react-hook-form";
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
// hooks
|
||||||
|
import { useEventTracker } from "hooks/store";
|
||||||
// icons
|
// icons
|
||||||
import { ArrowLeft, Check, List, Settings } from "lucide-react";
|
import { ArrowLeft, Check, List, Settings } from "lucide-react";
|
||||||
// services
|
// services
|
||||||
@ -25,6 +27,8 @@ import {
|
|||||||
TJiraIntegrationSteps,
|
TJiraIntegrationSteps,
|
||||||
IJiraIntegrationData,
|
IJiraIntegrationData,
|
||||||
} from ".";
|
} from ".";
|
||||||
|
// constants
|
||||||
|
import { JIRA_ISSUES_IMPORTED } from "constants/event-tracker";
|
||||||
|
|
||||||
const integrationWorkflowData: Array<{
|
const integrationWorkflowData: Array<{
|
||||||
title: string;
|
title: string;
|
||||||
@ -61,9 +65,11 @@ export const JiraImporterRoot: React.FC = () => {
|
|||||||
state: "import-configure",
|
state: "import-configure",
|
||||||
});
|
});
|
||||||
const [disableTopBarAfter, setDisableTopBarAfter] = useState<TJiraIntegrationSteps | null>(null);
|
const [disableTopBarAfter, setDisableTopBarAfter] = useState<TJiraIntegrationSteps | null>(null);
|
||||||
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
// store hooks
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const methods = useForm<IJiraImporterForm>({
|
const methods = useForm<IJiraImporterForm>({
|
||||||
defaultValues: jiraFormDefaultValues,
|
defaultValues: jiraFormDefaultValues,
|
||||||
@ -81,6 +87,7 @@ export const JiraImporterRoot: React.FC = () => {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
|
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
|
||||||
router.push(`/${workspaceSlug}/settings/imports`);
|
router.push(`/${workspaceSlug}/settings/imports`);
|
||||||
|
captureEvent(JIRA_ISSUES_IMPORTED);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -9,7 +9,7 @@ import { AlertTriangleIcon } from "lucide-react";
|
|||||||
// ui
|
// ui
|
||||||
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button, Input, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
// constants
|
// constants
|
||||||
import { PROJECT_MEMBER_LEAVE } from "constants/event-tracker";
|
import { PROJECT_MEMBER_LEFT } from "constants/event-tracker";
|
||||||
// hooks
|
// hooks
|
||||||
import { useEventTracker, useUser } from "hooks/store";
|
import { useEventTracker, useUser } from "hooks/store";
|
||||||
// types
|
// types
|
||||||
@ -64,7 +64,7 @@ export const LeaveProjectModal: FC<ILeaveProjectModal> = observer((props) => {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
handleClose();
|
handleClose();
|
||||||
router.push(`/${workspaceSlug}/projects`);
|
router.push(`/${workspaceSlug}/projects`);
|
||||||
captureEvent(PROJECT_MEMBER_LEAVE, {
|
captureEvent(PROJECT_MEMBER_LEFT, {
|
||||||
state: "SUCCESS",
|
state: "SUCCESS",
|
||||||
element: "Project settings members page",
|
element: "Project settings members page",
|
||||||
});
|
});
|
||||||
@ -75,7 +75,7 @@ export const LeaveProjectModal: FC<ILeaveProjectModal> = observer((props) => {
|
|||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: "Something went wrong please try again later.",
|
message: "Something went wrong please try again later.",
|
||||||
});
|
});
|
||||||
captureEvent(PROJECT_MEMBER_LEAVE, {
|
captureEvent(PROJECT_MEMBER_LEFT, {
|
||||||
state: "FAILED",
|
state: "FAILED",
|
||||||
element: "Project settings members page",
|
element: "Project settings members page",
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ import { CustomSelect, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
|||||||
// components
|
// components
|
||||||
import { ConfirmProjectMemberRemove } from "components/project";
|
import { ConfirmProjectMemberRemove } from "components/project";
|
||||||
// constants
|
// constants
|
||||||
import { PM_ROLE_CHANGED, PROJECT_MEMBER_LEAVE, PROJECT_MEMBER_REMOVED } from "constants/event-tracker";
|
import { PM_ROLE_CHANGED, PROJECT_MEMBER_LEFT, PROJECT_MEMBER_REMOVED } from "constants/event-tracker";
|
||||||
import { EUserProjectRoles } from "constants/project";
|
import { EUserProjectRoles } from "constants/project";
|
||||||
import { ROLE } from "constants/workspace";
|
import { ROLE } from "constants/workspace";
|
||||||
// hooks
|
// hooks
|
||||||
@ -49,7 +49,7 @@ export const ProjectMemberListItem: React.FC<Props> = observer((props) => {
|
|||||||
if (userDetails.member?.id === currentUser?.id) {
|
if (userDetails.member?.id === currentUser?.id) {
|
||||||
await leaveProject(workspaceSlug.toString(), projectId.toString())
|
await leaveProject(workspaceSlug.toString(), projectId.toString())
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
captureEvent(PROJECT_MEMBER_LEAVE, {
|
captureEvent(PROJECT_MEMBER_LEFT, {
|
||||||
state: "SUCCESS",
|
state: "SUCCESS",
|
||||||
element: "Project settings members page",
|
element: "Project settings members page",
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,8 @@ import { useRouter } from "next/router";
|
|||||||
// ui
|
// ui
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import { TOAST_TYPE, setToast } from "@plane/ui";
|
import { TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
|
// hooks
|
||||||
|
import { useEventTracker } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
// helpers
|
// helpers
|
||||||
import { csvDownload } from "helpers/download.helper";
|
import { csvDownload } from "helpers/download.helper";
|
||||||
@ -12,6 +14,8 @@ import { WebhookForm } from "./form";
|
|||||||
import { GeneratedHookDetails } from "./generated-hook-details";
|
import { GeneratedHookDetails } from "./generated-hook-details";
|
||||||
// utils
|
// utils
|
||||||
import { getCurrentHookAsCSV } from "./utils";
|
import { getCurrentHookAsCSV } from "./utils";
|
||||||
|
// constants
|
||||||
|
import { WEBHOOK_CREATED } from "constants/event-tracker";
|
||||||
// ui
|
// ui
|
||||||
|
|
||||||
interface ICreateWebhookModal {
|
interface ICreateWebhookModal {
|
||||||
@ -35,6 +39,8 @@ export const CreateWebhookModal: React.FC<ICreateWebhookModal> = (props) => {
|
|||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
// store hooks
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleCreateWebhook = async (formData: IWebhook, webhookEventType: TWebhookEventTypes) => {
|
const handleCreateWebhook = async (formData: IWebhook, webhookEventType: TWebhookEventTypes) => {
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
@ -64,6 +70,14 @@ export const CreateWebhookModal: React.FC<ICreateWebhookModal> = (props) => {
|
|||||||
|
|
||||||
await createWebhook(workspaceSlug.toString(), payload)
|
await createWebhook(workspaceSlug.toString(), payload)
|
||||||
.then(({ webHook, secretKey }) => {
|
.then(({ webHook, secretKey }) => {
|
||||||
|
captureEvent(WEBHOOK_CREATED, {
|
||||||
|
webhook_id: webHook.id,
|
||||||
|
event_type: webhookEventType,
|
||||||
|
events:
|
||||||
|
webhookEventType === "individual"
|
||||||
|
? Object.keys(payload).filter((key) => key !== "url" && payload[key as keyof IWebhook] === true)
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
|
@ -5,7 +5,9 @@ import { AlertTriangle } from "lucide-react";
|
|||||||
// ui
|
// ui
|
||||||
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
import { useWebhook } from "hooks/store";
|
import { useEventTracker, useWebhook } from "hooks/store";
|
||||||
|
// constants
|
||||||
|
import { WEBHOOK_DELETED } from "constants/event-tracker";
|
||||||
|
|
||||||
interface IDeleteWebhook {
|
interface IDeleteWebhook {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -20,6 +22,7 @@ export const DeleteWebhookModal: FC<IDeleteWebhook> = (props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { removeWebhook } = useWebhook();
|
const { removeWebhook } = useWebhook();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const { workspaceSlug, webhookId } = router.query;
|
const { workspaceSlug, webhookId } = router.query;
|
||||||
|
|
||||||
@ -34,6 +37,9 @@ export const DeleteWebhookModal: FC<IDeleteWebhook> = (props) => {
|
|||||||
|
|
||||||
removeWebhook(workspaceSlug.toString(), webhookId.toString())
|
removeWebhook(workspaceSlug.toString(), webhookId.toString())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
captureEvent(WEBHOOK_DELETED, {
|
||||||
|
webhook_id: webhookId.toString(),
|
||||||
|
});
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.SUCCESS,
|
type: TOAST_TYPE.SUCCESS,
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
|
@ -10,11 +10,13 @@ import {
|
|||||||
WebhookSecretKey,
|
WebhookSecretKey,
|
||||||
WebhookToggle,
|
WebhookToggle,
|
||||||
} from "components/web-hooks";
|
} from "components/web-hooks";
|
||||||
import { useWebhook } from "hooks/store";
|
import { useEventTracker, useWebhook } from "hooks/store";
|
||||||
// components
|
// components
|
||||||
// ui
|
// ui
|
||||||
// types
|
// types
|
||||||
import { IWebhook, TWebhookEventTypes } from "@plane/types";
|
import { IWebhook, TWebhookEventTypes } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { WEBHOOK_UPDATED } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data?: Partial<IWebhook>;
|
data?: Partial<IWebhook>;
|
||||||
@ -37,17 +39,25 @@ export const WebhookForm: FC<Props> = observer((props) => {
|
|||||||
const [webhookEventType, setWebhookEventType] = useState<TWebhookEventTypes>("all");
|
const [webhookEventType, setWebhookEventType] = useState<TWebhookEventTypes>("all");
|
||||||
// store hooks
|
// store hooks
|
||||||
const { webhookSecretKey } = useWebhook();
|
const { webhookSecretKey } = useWebhook();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
// use form
|
// use form
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
control,
|
control,
|
||||||
formState: { isSubmitting, errors },
|
formState: { isSubmitting, errors, dirtyFields },
|
||||||
} = useForm<IWebhook>({
|
} = useForm<IWebhook>({
|
||||||
defaultValues: { ...initialWebhookPayload, ...data },
|
defaultValues: { ...initialWebhookPayload, ...data },
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFormSubmit = async (formData: IWebhook) => {
|
const handleFormSubmit = async (formData: IWebhook) => {
|
||||||
await onSubmit(formData, webhookEventType);
|
await onSubmit(formData, webhookEventType).then(() => {
|
||||||
|
if (!data) return;
|
||||||
|
captureEvent(WEBHOOK_UPDATED, {
|
||||||
|
webhook_id: data.id,
|
||||||
|
change_details: Object.keys(dirtyFields),
|
||||||
|
enabled: formData.is_active,
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -9,11 +9,13 @@ import { Button, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
|||||||
import { csvDownload } from "helpers/download.helper";
|
import { csvDownload } from "helpers/download.helper";
|
||||||
import { copyTextToClipboard } from "helpers/string.helper";
|
import { copyTextToClipboard } from "helpers/string.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useWebhook, useWorkspace } from "hooks/store";
|
import { useEventTracker, useWebhook, useWorkspace } from "hooks/store";
|
||||||
// types
|
// types
|
||||||
import { IWebhook } from "@plane/types";
|
import { IWebhook } from "@plane/types";
|
||||||
// utils
|
// utils
|
||||||
import { getCurrentHookAsCSV } from "../utils";
|
import { getCurrentHookAsCSV } from "../utils";
|
||||||
|
// constants
|
||||||
|
import { WEBHOOK_KEY_REGEN } from "constants/event-tracker";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: Partial<IWebhook>;
|
data: Partial<IWebhook>;
|
||||||
@ -30,6 +32,7 @@ export const WebhookSecretKey: FC<Props> = observer((props) => {
|
|||||||
// store hooks
|
// store hooks
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { currentWebhook, regenerateSecretKey, webhookSecretKey } = useWebhook();
|
const { currentWebhook, regenerateSecretKey, webhookSecretKey } = useWebhook();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleCopySecretKey = () => {
|
const handleCopySecretKey = () => {
|
||||||
if (!webhookSecretKey) return;
|
if (!webhookSecretKey) return;
|
||||||
@ -63,6 +66,9 @@ export const WebhookSecretKey: FC<Props> = observer((props) => {
|
|||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "New key regenerated successfully.",
|
message: "New key regenerated successfully.",
|
||||||
});
|
});
|
||||||
|
captureEvent(WEBHOOK_KEY_REGEN, {
|
||||||
|
webhook_id: data.id,
|
||||||
|
});
|
||||||
|
|
||||||
if (currentWebhook && webhookSecretKey) {
|
if (currentWebhook && webhookSecretKey) {
|
||||||
const csvData = getCurrentHookAsCSV(currentWorkspace, currentWebhook, webhookSecretKey);
|
const csvData = getCurrentHookAsCSV(currentWorkspace, currentWebhook, webhookSecretKey);
|
||||||
|
@ -3,10 +3,12 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// hooks
|
// hooks
|
||||||
import { ToggleSwitch } from "@plane/ui";
|
import { ToggleSwitch } from "@plane/ui";
|
||||||
import { useWebhook } from "hooks/store";
|
import { useEventTracker, useWebhook } from "hooks/store";
|
||||||
// ui
|
// ui
|
||||||
// types
|
// types
|
||||||
import { IWebhook } from "@plane/types";
|
import { IWebhook } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { WEBHOOK_DISABLED, WEBHOOK_ENABLED } from "constants/event-tracker";
|
||||||
|
|
||||||
interface IWebhookListItem {
|
interface IWebhookListItem {
|
||||||
webhook: IWebhook;
|
webhook: IWebhook;
|
||||||
@ -19,11 +21,16 @@ export const WebhooksListItem: FC<IWebhookListItem> = (props) => {
|
|||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { updateWebhook } = useWebhook();
|
const { updateWebhook } = useWebhook();
|
||||||
|
const { captureEvent } = useEventTracker();
|
||||||
|
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
if (!workspaceSlug || !webhook.id) return;
|
if (!workspaceSlug || !webhook.id) return;
|
||||||
|
|
||||||
updateWebhook(workspaceSlug.toString(), webhook.id, { is_active: !webhook.is_active });
|
updateWebhook(workspaceSlug.toString(), webhook.id, { is_active: !webhook.is_active }).then(() =>
|
||||||
|
captureEvent(!webhook.is_active ? WEBHOOK_ENABLED : WEBHOOK_DISABLED, {
|
||||||
|
webhook_id: webhook.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -8,8 +8,10 @@ import { ChevronDown, Dot, XCircle } from "lucide-react";
|
|||||||
import { CustomSelect, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
import { CustomSelect, Tooltip, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { ConfirmWorkspaceMemberRemove } from "components/workspace";
|
import { ConfirmWorkspaceMemberRemove } from "components/workspace";
|
||||||
|
// helpers
|
||||||
|
import { getUserRole } from "helpers/user.helper";
|
||||||
// constants
|
// constants
|
||||||
import { WORKSPACE_MEMBER_lEAVE } from "constants/event-tracker";
|
import { WM_ROLE_CHANGED, WORKSPACE_MEMBER_REMOVED, WORKSPACE_MEMBER_LEFT } from "constants/event-tracker";
|
||||||
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
|
import { EUserWorkspaceRoles, ROLE } from "constants/workspace";
|
||||||
// hooks
|
// hooks
|
||||||
import { useEventTracker, useMember, useUser } from "hooks/store";
|
import { useEventTracker, useMember, useUser } from "hooks/store";
|
||||||
@ -43,7 +45,9 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
await leaveWorkspace(workspaceSlug.toString())
|
await leaveWorkspace(workspaceSlug.toString())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
captureEvent(WORKSPACE_MEMBER_lEAVE, {
|
captureEvent(WORKSPACE_MEMBER_LEFT, {
|
||||||
|
member_id: currentUser?.id,
|
||||||
|
role: currentWorkspaceRole ? getUserRole(currentWorkspaceRole as number) : undefined,
|
||||||
state: "SUCCESS",
|
state: "SUCCESS",
|
||||||
element: "Workspace settings members page",
|
element: "Workspace settings members page",
|
||||||
});
|
});
|
||||||
@ -61,13 +65,23 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
|
|||||||
const handleRemoveMember = async () => {
|
const handleRemoveMember = async () => {
|
||||||
if (!workspaceSlug || !memberDetails) return;
|
if (!workspaceSlug || !memberDetails) return;
|
||||||
|
|
||||||
await removeMemberFromWorkspace(workspaceSlug.toString(), memberDetails.member.id).catch((err) =>
|
await removeMemberFromWorkspace(workspaceSlug.toString(), memberDetails.member.id)
|
||||||
setToast({
|
.then(() =>
|
||||||
type: TOAST_TYPE.ERROR,
|
captureEvent(WORKSPACE_MEMBER_REMOVED, {
|
||||||
title: "Error",
|
member_id: memberDetails.member.id,
|
||||||
message: err?.error || "Something went wrong. Please try again.",
|
removed_by_role: currentWorkspaceRole ? getUserRole(currentWorkspaceRole as number) : undefined,
|
||||||
})
|
role: memberDetails.role ? getUserRole(memberDetails.role as number) : undefined,
|
||||||
);
|
state: "SUCCESS",
|
||||||
|
element: "Workspace settings members page",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch((err) =>
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error",
|
||||||
|
message: err?.error || "Something went wrong. Please try again.",
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemove = async () => {
|
const handleRemove = async () => {
|
||||||
@ -162,13 +176,22 @@ export const WorkspaceMembersListItem: FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
updateMember(workspaceSlug.toString(), memberDetails.member.id, {
|
updateMember(workspaceSlug.toString(), memberDetails.member.id, {
|
||||||
role: value,
|
role: value,
|
||||||
}).catch(() => {
|
})
|
||||||
setToast({
|
.then(() =>
|
||||||
type: TOAST_TYPE.ERROR,
|
captureEvent(WM_ROLE_CHANGED, {
|
||||||
title: "Error!",
|
member_id: memberDetails.member.id,
|
||||||
message: "An error occurred while updating member role. Please try again.",
|
changed_role: value ? getUserRole(value as number) : undefined,
|
||||||
|
state: "SUCCESS",
|
||||||
|
element: "Workspace settings members page",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(() => {
|
||||||
|
setToast({
|
||||||
|
type: TOAST_TYPE.ERROR,
|
||||||
|
title: "Error!",
|
||||||
|
message: "An error occurred while updating member role. Please try again.",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
disabled={!hasRoleChangeAccess}
|
disabled={!hasRoleChangeAccess}
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
|
@ -48,7 +48,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||||||
control,
|
control,
|
||||||
reset,
|
reset,
|
||||||
watch,
|
watch,
|
||||||
formState: { errors },
|
formState: { errors, dirtyFields },
|
||||||
} = useForm<IWorkspace>({
|
} = useForm<IWorkspace>({
|
||||||
defaultValues: { ...defaultValues, ...currentWorkspace },
|
defaultValues: { ...defaultValues, ...currentWorkspace },
|
||||||
});
|
});
|
||||||
@ -70,6 +70,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||||||
eventName: WORKSPACE_UPDATED,
|
eventName: WORKSPACE_UPDATED,
|
||||||
payload: {
|
payload: {
|
||||||
...res,
|
...res,
|
||||||
|
change_details: Object.keys(dirtyFields),
|
||||||
state: "SUCCESS",
|
state: "SUCCESS",
|
||||||
element: "Workspace general settings page",
|
element: "Workspace general settings page",
|
||||||
},
|
},
|
||||||
|
@ -19,6 +19,7 @@ export const getWorkspaceEventPayload = (payload: any) => ({
|
|||||||
organization_size: payload.organization_size,
|
organization_size: payload.organization_size,
|
||||||
first_time: payload.first_time,
|
first_time: payload.first_time,
|
||||||
state: payload.state,
|
state: payload.state,
|
||||||
|
change_details: payload.change_details,
|
||||||
element: payload.element,
|
element: payload.element,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -172,7 +173,9 @@ export const elementFromPath = (routePath?: string) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
element: element,
|
element: element,
|
||||||
element_id: ["Project", "Draft", "Archive"].includes(element) ? routePath.split("/")?.at(-2) : routePath.split("/")?.at(-1),
|
element_id: ["Project", "Draft", "Archive"].includes(element)
|
||||||
|
? routePath.split("/")?.at(-2)
|
||||||
|
: routePath.split("/")?.at(-1),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -265,14 +268,34 @@ export const PAGE_RESTORED = "Page restored";
|
|||||||
export const AI_TRIGGERED = "AI triggered";
|
export const AI_TRIGGERED = "AI triggered";
|
||||||
export const AI_RES_USED = "AI response used";
|
export const AI_RES_USED = "AI response used";
|
||||||
export const AI_RES_REGENERATED = "AI response regenerated";
|
export const AI_RES_REGENERATED = "AI response regenerated";
|
||||||
// Member Events
|
// Project Member Events
|
||||||
export const MEMBER_INVITED = "Member invited";
|
|
||||||
export const MEMBER_ACCEPTED = "Member accepted";
|
|
||||||
export const PROJECT_MEMBER_ADDED = "Project member added";
|
export const PROJECT_MEMBER_ADDED = "Project member added";
|
||||||
export const PROJECT_MEMBER_LEAVE = "Project member leave";
|
export const PROJECT_MEMBER_LEFT = "Project member left";
|
||||||
export const PROJECT_MEMBER_REMOVED = "Project member removed";
|
export const PROJECT_MEMBER_REMOVED = "Project member removed";
|
||||||
export const PM_ROLE_CHANGED = "Project member role changed";
|
export const PM_ROLE_CHANGED = "Project member role changed";
|
||||||
export const WORKSPACE_MEMBER_lEAVE = "Workspace member leave";
|
// Workspace Member Events
|
||||||
|
export const MEMBER_INVITED = "Member invited";
|
||||||
|
export const MEMBER_ACCEPTED = "Member accepted";
|
||||||
|
export const WORKSPACE_MEMBER_REMOVED = "Workspace member removed";
|
||||||
|
export const WORKSPACE_MEMBER_LEFT = "Workspace member left";
|
||||||
|
export const WM_ROLE_CHANGED = "Workspace member role changed";
|
||||||
|
// Issues Export Events
|
||||||
|
export const ISSUES_EXPORTED = "Issues exported";
|
||||||
|
// Issues Import Events
|
||||||
|
export const GITHUB_ISSUES_IMPORTED = "Github issues imported";
|
||||||
|
export const JIRA_ISSUES_IMPORTED = "Jira issues imported";
|
||||||
|
// Webhook Events
|
||||||
|
export const WEBHOOK_CREATED = "Webhook created";
|
||||||
|
export const WEBHOOK_UPDATED = "Webhook updated";
|
||||||
|
export const WEBHOOK_DELETED = "Webhook deleted";
|
||||||
|
export const WEBHOOK_ENABLED = "Webhook enabled";
|
||||||
|
export const WEBHOOK_DISABLED = "Webhook diabled";
|
||||||
|
export const WEBHOOK_KEY_REGEN = "Webhook secret key regenerated";
|
||||||
|
// API Token Events
|
||||||
|
export const API_TOKEN_CREATED = "API token created";
|
||||||
|
export const API_TOKEN_UPDATED = "API token updated";
|
||||||
|
export const API_TOKEN_DELETED = "API token deleted";
|
||||||
|
export const API_TOKEN_REGEN = "API token regenerated";
|
||||||
// Sign-in & Sign-up Events
|
// Sign-in & Sign-up Events
|
||||||
export const NAVIGATE_TO_SIGNUP = "Navigate to sign-up page";
|
export const NAVIGATE_TO_SIGNUP = "Navigate to sign-up page";
|
||||||
export const NAVIGATE_TO_SIGNIN = "Navigate to sign-in page";
|
export const NAVIGATE_TO_SIGNIN = "Navigate to sign-in page";
|
||||||
|
@ -26,7 +26,7 @@ const PostHogProvider: FC<IPosthogWrapper> = (props) => {
|
|||||||
currentWorkspaceId,
|
currentWorkspaceId,
|
||||||
posthogAPIKey,
|
posthogAPIKey,
|
||||||
posthogHost,
|
posthogHost,
|
||||||
isCloud = false,
|
isCloud = true,
|
||||||
telemetryEnabled = false,
|
telemetryEnabled = false,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
|
Loading…
Reference in New Issue
Block a user