chore: added workspace settings events

This commit is contained in:
LAKHAN BAHETI 2024-03-11 17:25:19 +05:30
parent 35a9527325
commit 2b8569a0c9
16 changed files with 169 additions and 38 deletions

View File

@ -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()),

View File

@ -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({

View File

@ -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",

View File

@ -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({

View File

@ -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);

View File

@ -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",
}); });

View File

@ -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",
}); });

View File

@ -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!",

View File

@ -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!",

View File

@ -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(() => {

View File

@ -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);

View File

@ -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 (

View File

@ -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"

View File

@ -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",
}, },

View File

@ -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";

View File

@ -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