Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/constants/src/event-tracker/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const getProjectEventPayload = (payload: any) => ({
element: payload.element,
});


export const getPageEventPayload = (payload: any) => ({
workspace_id: payload.workspace_id,
project_id: payload.project,
Expand Down Expand Up @@ -196,6 +195,17 @@ export const MEMBER_TRACKER_EVENTS = {
},
};

export const MEMBER_TRACKER_ELEMENTS = {
HEADER_ADD_BUTTON: "header_add_member_button",
ACCEPT_INVITATION_BUTTON: "accept_invitation_button",
ONBOARDING_JOIN_WORKSPACE: "workspace_join_continue_to_workspace_button",
ONBOARDING_INVITE_MEMBER: "invite_member_continue_button",
SIDEBAR_PROJECT_QUICK_ACTIONS: "sidebar_project_quick_actions",
PROJECT_MEMBER_TABLE_CONTEXT_MENU: "project_member_table_context_menu",
WORKSPACE_MEMBER_TABLE_CONTEXT_MENU: "workspace_member_table_context_menu",
WORKSPACE_INVITATIONS_LIST_CONTEXT_MENU: "workspace_invitations_list_context_menu",
} as const;

export const AUTH_TRACKER_EVENTS = {
navigate: {
sign_up: "navigate_to_sign_up_page",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { Search } from "lucide-react";
// types
import { EUserPermissions, EUserPermissionsLevel, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import {
EUserPermissions,
EUserPermissionsLevel,
MEMBER_TRACKER_ELEMENTS,
MEMBER_TRACKER_EVENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IWorkspaceBulkInviteFormData } from "@plane/types";
// ui
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
import { cn, getUserRole } from "@plane/utils";
import { cn } from "@plane/utils";
// components
import { NotAuthorizedView } from "@/components/auth-screens";
import { CountChip } from "@/components/common";
Expand All @@ -19,7 +24,8 @@ import { SettingsContentWrapper } from "@/components/settings";
import { WorkspaceMembersList } from "@/components/workspace";
// helpers
// hooks
import { useEventTracker, useMember, useUserPermissions, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useMember, useUserPermissions, useWorkspace } from "@/hooks/store";
// plane web components
import { BillingActionsButton } from "@/plane-web/components/workspace/billing";
import { SendWorkspaceInvitationModal } from "@/plane-web/components/workspace/members";
Expand All @@ -32,7 +38,6 @@ const WorkspaceMembersSettingsPage = observer(() => {
const { workspaceSlug } = useParams();
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { captureEvent } = useEventTracker();
const {
workspace: { workspaceMemberIds, inviteMembersToWorkspace },
} = useMember();
Expand All @@ -52,16 +57,11 @@ const WorkspaceMembersSettingsPage = observer(() => {
return inviteMembersToWorkspace(workspaceSlug.toString(), data)
.then(() => {
setInviteModal(false);
captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [
...data.emails.map((email) => ({
email: email.email,
role: getUserRole(email.role as unknown as EUserPermissions),
})),
],
project_id: undefined,
state: "SUCCESS",
element: "Workspace settings member page",
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.invite,
payload: {
emails: [...data.emails.map((email) => email.email)],
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
Expand All @@ -70,16 +70,12 @@ const WorkspaceMembersSettingsPage = observer(() => {
});
})
.catch((err) => {
captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [
...data.emails.map((email) => ({
email: email.email,
role: getUserRole(email.role as unknown as EUserPermissions),
})),
],
project_id: undefined,
state: "FAILED",
element: "Workspace settings member page",
captureError({
eventName: MEMBER_TRACKER_EVENTS.invite,
payload: {
emails: [...data.emails.map((email) => email.email)],
},
error: err,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand Down Expand Up @@ -129,7 +125,12 @@ const WorkspaceMembersSettingsPage = observer(() => {
/>
</div>
{canPerformWorkspaceAdminActions && (
<Button variant="primary" size="sm" onClick={() => setInviteModal(true)}>
<Button
variant="primary"
size="sm"
onClick={() => setInviteModal(true)}
data-ph-element={MEMBER_TRACKER_ELEMENTS.HEADER_ADD_BUTTON}
>
{t("workspace_settings.settings.members.add_member")}
</Button>
)}
Expand Down
34 changes: 17 additions & 17 deletions web/app/(all)/invitations/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ import { useTheme } from "next-themes";
import useSWR, { mutate } from "swr";
import { CheckCircle2 } from "lucide-react";
// plane imports
import { ROLE, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { ROLE, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// types
import type { IWorkspaceMemberInvitation } from "@plane/types";
// ui
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
import { truncateText, getUserRole } from "@plane/utils";
import { truncateText } from "@plane/utils";
// components
import { EmptyState } from "@/components/common";
import { WorkspaceLogo } from "@/components/workspace/logo";
import { USER_WORKSPACES_LIST } from "@/constants/fetch-keys";
// helpers
// hooks
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useEventTracker, useUser, useUserProfile, useWorkspace } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
// services
Expand All @@ -43,7 +44,7 @@ const UserInvitationsPage = observer(() => {
const router = useAppRouter();
// store hooks
const { t } = useTranslation();
const { captureEvent, joinWorkspaceMetricGroup } = useEventTracker();
const { joinWorkspaceMetricGroup } = useEventTracker();
const { data: currentUser } = useUser();
const { updateUserProfile } = useUserProfile();

Expand Down Expand Up @@ -86,14 +87,11 @@ const UserInvitationsPage = observer(() => {
const invitation = invitations?.find((i) => i.id === firstInviteId);
const redirectWorkspace = invitations?.find((i) => i.id === firstInviteId)?.workspace;
joinWorkspaceMetricGroup(redirectWorkspace?.id);
captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id,
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
role: getUserRole((invitation?.role as unknown as EUserPermissions)!),
project_id: undefined,
accepted_from: "App",
state: "SUCCESS",
element: "Workspace invitations page",
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.accept,
payload: {
member_id: invitation?.id,
},
});
updateUserProfile({ last_workspace_id: redirectWorkspace?.id })
.then(() => {
Expand All @@ -111,12 +109,13 @@ const UserInvitationsPage = observer(() => {
setIsJoiningWorkspaces(false);
});
})
.catch(() => {
captureEvent(MEMBER_TRACKER_EVENTS.accept, {
project_id: undefined,
accepted_from: "App",
state: "FAILED",
element: "Workspace invitations page",
.catch((err) => {
captureError({
eventName: MEMBER_TRACKER_EVENTS.accept,
payload: {
member_id: invitationsRespond?.[0],
},
error: err,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand Down Expand Up @@ -194,6 +193,7 @@ const UserInvitationsPage = observer(() => {
onClick={submitInvitations}
disabled={isJoiningWorkspaces || invitationsRespond.length === 0}
loading={isJoiningWorkspaces}
data-ph-element={MEMBER_TRACKER_ELEMENTS.ACCEPT_INVITATION_BUTTON}
>
{t("accept_and_join")}
</Button>
Expand Down
36 changes: 17 additions & 19 deletions web/core/components/onboarding/invitations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

import React, { useState } from "react";
// plane imports
import { ROLE, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { ROLE, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
// types
import { IWorkspaceMemberInvitation } from "@plane/types";
// ui
import { Button, Checkbox, Spinner } from "@plane/ui";
import { truncateText, getUserRole } from "@plane/utils";
import { truncateText } from "@plane/utils";
// constants
// helpers
import { WorkspaceLogo } from "@/components/workspace/logo";
// hooks
import { useEventTracker, useUserSettings, useWorkspace } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useUserSettings, useWorkspace } from "@/hooks/store";
// services
import { WorkspaceService } from "@/plane-web/services";

Expand All @@ -29,7 +30,6 @@ export const Invitations: React.FC<Props> = (props) => {
const [isJoiningWorkspaces, setIsJoiningWorkspaces] = useState(false);
const [invitationsRespond, setInvitationsRespond] = useState<string[]>([]);
// store hooks
const { captureEvent } = useEventTracker();
const { fetchWorkspaces } = useWorkspace();
const { fetchCurrentUserSettings } = useUserSettings();

Expand All @@ -50,26 +50,23 @@ export const Invitations: React.FC<Props> = (props) => {

try {
await workspaceService.joinWorkspaces({ invitations: invitationsRespond });
captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id,
role: getUserRole(invitation?.role as any),
project_id: undefined,
accepted_from: "App",
state: "SUCCESS",
element: "Workspace invitations page",
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.accept,
payload: {
member_id: invitation?.id,
},
});
await fetchWorkspaces();
await fetchCurrentUserSettings();
await handleNextStep();
} catch (error) {
} catch (error: any) {
console.error(error);
captureEvent(MEMBER_TRACKER_EVENTS.accept, {
member_id: invitation?.id,
role: getUserRole(invitation?.role as any),
project_id: undefined,
accepted_from: "App",
state: "FAILED",
element: "Workspace invitations page",
captureError({
eventName: MEMBER_TRACKER_EVENTS.accept,
payload: {
member_id: invitation?.id,
},
error: error,
});
setIsJoiningWorkspaces(false);
}
Expand Down Expand Up @@ -117,6 +114,7 @@ export const Invitations: React.FC<Props> = (props) => {
className="w-full"
onClick={submitInvitations}
disabled={isJoiningWorkspaces || !invitationsRespond.length}
data-ph-element={MEMBER_TRACKER_ELEMENTS.ONBOARDING_JOIN_WORKSPACE}
>
{isJoiningWorkspaces ? <Spinner height="20px" width="20px" /> : "Continue to workspace"}
</Button>
Expand Down
33 changes: 14 additions & 19 deletions web/core/components/onboarding/invite-members.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@ import { usePopper } from "react-popper";
import { Check, ChevronDown, Plus, XCircle } from "lucide-react";
import { Listbox } from "@headlessui/react";
// plane imports
import { ROLE, ROLE_DETAILS, EUserPermissions, MEMBER_TRACKER_EVENTS } from "@plane/constants";
import { ROLE, ROLE_DETAILS, EUserPermissions, MEMBER_TRACKER_EVENTS, MEMBER_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
// types
import { IUser, IWorkspace } from "@plane/types";
// ui
import { Button, Input, Spinner, TOAST_TYPE, setToast } from "@plane/ui";
// constants
// helpers
import { getUserRole } from "@plane/utils";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
// services
import { WorkspaceService } from "@/plane-web/services";
// assets
Expand Down Expand Up @@ -276,8 +275,6 @@ export const InviteMembers: React.FC<Props> = (props) => {
const [isInvitationDisabled, setIsInvitationDisabled] = useState(true);

const { resolvedTheme } = useTheme();
// store hooks
const { captureEvent } = useEventTracker();

const {
control,
Expand Down Expand Up @@ -311,16 +308,11 @@ export const InviteMembers: React.FC<Props> = (props) => {
})),
})
.then(async () => {
captureEvent(MEMBER_TRACKER_EVENTS.invite, {
emails: [
...payload.emails.map((email) => ({
email: email.email,
role: getUserRole(email.role),
})),
],
project_id: undefined,
state: "SUCCESS",
element: "Onboarding",
captureSuccess({
eventName: MEMBER_TRACKER_EVENTS.invite,
payload: {
workspace: workspace.slug,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
Expand All @@ -331,10 +323,12 @@ export const InviteMembers: React.FC<Props> = (props) => {
await nextStep();
})
.catch((err) => {
captureEvent(MEMBER_TRACKER_EVENTS.invite, {
project_id: undefined,
state: "FAILED",
element: "Onboarding",
captureError({
eventName: MEMBER_TRACKER_EVENTS.invite,
payload: {
workspace: workspace.slug,
},
error: err,
});
setToast({
type: TOAST_TYPE.ERROR,
Expand Down Expand Up @@ -426,6 +420,7 @@ export const InviteMembers: React.FC<Props> = (props) => {
size="lg"
className="w-full"
disabled={isInvitationDisabled || !isValid || isSubmitting}
data-ph-element={MEMBER_TRACKER_ELEMENTS.ONBOARDING_INVITE_MEMBER}
>
{isSubmitting ? <Spinner height="20px" width="20px" /> : "Continue"}
</Button>
Expand Down
Loading