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
16 changes: 10 additions & 6 deletions packages/constants/src/event-tracker/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ export const MEMBER_TRACKER_EVENTS = {
leave: "workspace_member_left",
},
};

export const MEMBER_TRACKER_ELEMENTS = {
HEADER_ADD_BUTTON: "header_add_member_button",
ACCEPT_INVITATION_BUTTON: "accept_invitation_button",
Expand All @@ -207,15 +206,20 @@ export const MEMBER_TRACKER_ELEMENTS = {
} as const;

export const AUTH_TRACKER_EVENTS = {
navigate: {
sign_up: "navigate_to_sign_up_page",
sign_in: "navigate_to_sign_in_page",
},
code_verify: "code_verified",
sign_up_with_password: "sign_up_with_password",
sign_in_with_password: "sign_in_with_password",
sign_in_with_code: "sign_in_with_magic_link",
forgot_password: "forgot_password_clicked",
new_code_requested: "new_code_requested",
};
export const AUTH_TRACKER_ELEMENTS = {
NAVIGATE_TO_SIGN_UP: "navigate_to_sign_up",
FORGOT_PASSWORD_FROM_SIGNIN: "forgot_password_from_signin",
SIGNUP_FROM_FORGOT_PASSWORD: "signup_from_forgot_password",
SIGN_IN_FROM_SIGNUP: "sign_in_from_signup",
SIGN_IN_WITH_UNIQUE_CODE: "sign_in_with_unique_code",
REQUEST_NEW_CODE: "request_new_code",
VERIFY_CODE: "verify_code",
};

export const GLOBAL_VIEW_TRACKER_EVENTS = {
Expand Down
23 changes: 14 additions & 9 deletions web/app/(all)/accounts/forgot-password/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import { Controller, useForm } from "react-hook-form";
// icons
import { CircleCheck } from "lucide-react";
// plane imports
import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { AUTH_TRACKER_ELEMENTS, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button, Input, TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui";
import { cn, checkEmailValidity } from "@plane/utils";
// helpers
import { EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker, useInstance } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useInstance } from "@/hooks/store";
import useTimer from "@/hooks/use-timer";
// wrappers
import { AuthenticationWrapper } from "@/lib/wrappers";
Expand Down Expand Up @@ -45,8 +46,6 @@ const ForgotPasswordPage = observer(() => {
const email = searchParams.get("email");
// plane hooks
const { t } = useTranslation();
// store hooks
const { captureEvent } = useEventTracker();
const { config } = useInstance();
// hooks
const { resolvedTheme } = useTheme();
Expand All @@ -71,8 +70,11 @@ const ForgotPasswordPage = observer(() => {
email: formData.email,
})
.then(() => {
captureEvent(AUTH_TRACKER_EVENTS.forgot_password, {
state: "SUCCESS",
captureSuccess({
eventName: AUTH_TRACKER_EVENTS.forgot_password,
payload: {
email: formData.email,
},
});
setToast({
type: TOAST_TYPE.SUCCESS,
Expand All @@ -82,8 +84,11 @@ const ForgotPasswordPage = observer(() => {
setResendCodeTimer(30);
})
.catch((err) => {
captureEvent(AUTH_TRACKER_EVENTS.forgot_password, {
state: "FAILED",
captureError({
eventName: AUTH_TRACKER_EVENTS.forgot_password,
payload: {
email: formData.email,
},
});
setToast({
type: TOAST_TYPE.ERROR,
Expand Down Expand Up @@ -120,7 +125,7 @@ const ForgotPasswordPage = observer(() => {
{t("auth.common.new_to_plane")}
<Link
href="/"
onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})}
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGNUP_FROM_FORGOT_PASSWORD}
className="font-semibold text-custom-primary-100 hover:underline"
>
{t("auth.common.create_account")}
Expand Down
8 changes: 2 additions & 6 deletions web/app/(all)/sign-up/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import Link from "next/link";
// ui
import { useTheme } from "next-themes";
// components
import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { AUTH_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { AuthRoot } from "@/components/account";
// constants
// helpers
import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker } from "@/hooks/store";
// assets
import { AuthenticationWrapper } from "@/lib/wrappers";
import PlaneBackgroundPatternDark from "@/public/auth/background-pattern-dark.svg";
Expand All @@ -26,8 +24,6 @@ export type AuthType = "sign-in" | "sign-up";
const SignInPage = observer(() => {
// plane hooks
const { t } = useTranslation();
// store hooks
const { captureEvent } = useEventTracker();
// hooks
const { resolvedTheme } = useTheme();

Expand All @@ -54,7 +50,7 @@ const SignInPage = observer(() => {
{t("auth.common.already_have_an_account")}
<Link
href="/"
onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_in, {})}
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_FROM_SIGNUP}
className="font-semibold text-custom-primary-100 hover:underline"
>
{t("auth.common.login")}
Expand Down
8 changes: 3 additions & 5 deletions web/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import Link from "next/link";
// ui
import { useTheme } from "next-themes";
// components
import { AUTH_TRACKER_EVENTS } from "@plane/constants";
import { AUTH_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { AuthRoot } from "@/components/account";
import { PageHead } from "@/components/core";
// constants
// helpers
import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker, useInstance } from "@/hooks/store";
import { useInstance } from "@/hooks/store";
// layouts
import DefaultLayout from "@/layouts/default-layout";
// wrappers
Expand All @@ -29,8 +29,6 @@ const HomePage = observer(() => {
const { resolvedTheme } = useTheme();
// plane hooks
const { t } = useTranslation();
// hooks
const { captureEvent } = useEventTracker();
// store
const { config } = useInstance();
// derived values
Expand Down Expand Up @@ -63,7 +61,7 @@ const HomePage = observer(() => {
{t("auth.common.new_to_plane")}
<Link
href="/sign-up"
onClick={() => captureEvent(AUTH_TRACKER_EVENTS.navigate.sign_up, {})}
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
className="font-semibold text-custom-primary-100 hover:underline"
>
{t("auth.common.create_account")}
Expand Down
37 changes: 25 additions & 12 deletions web/core/components/account/auth-forms/password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Link from "next/link";
// icons
import { Eye, EyeOff, Info, X, XCircle } from "lucide-react";
// plane imports
import { API_BASE_URL, E_PASSWORD_STRENGTH, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { API_BASE_URL, E_PASSWORD_STRENGTH, AUTH_TRACKER_EVENTS, AUTH_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button, Input, Spinner } from "@plane/ui";
import { getPasswordStrength } from "@plane/utils";
Expand All @@ -16,7 +16,7 @@ import { ForgotPasswordPopover, PasswordStrengthMeter } from "@/components/accou
// helpers
import { EAuthModes, EAuthSteps } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
// services
import { AuthService } from "@/services/auth.service";

Expand Down Expand Up @@ -46,8 +46,6 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
const { email, isSMTPConfigured, handleAuthStep, handleEmailClear, mode, nextPath } = props;
// plane imports
const { t } = useTranslation();
// hooks
const { captureEvent } = useEventTracker();
// ref
const formRef = useRef<HTMLFormElement>(null);
// states
Expand Down Expand Up @@ -77,15 +75,14 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {

const redirectToUniqueCodeSignIn = async () => {
handleAuthStep(EAuthSteps.UNIQUE_CODE);
captureEvent(AUTH_TRACKER_EVENTS.sign_in_with_code);
};

const passwordSupport =
mode === EAuthModes.SIGN_IN ? (
<div className="w-full">
{isSMTPConfigured ? (
<Link
onClick={() => captureEvent(AUTH_TRACKER_EVENTS.forgot_password)}
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
className="text-xs font-medium text-custom-primary-100"
>
Expand Down Expand Up @@ -154,17 +151,32 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
: true;
if (isPasswordValid) {
setIsSubmitting(true);
captureEvent(
mode === EAuthModes.SIGN_IN
? AUTH_TRACKER_EVENTS.sign_in_with_password
: AUTH_TRACKER_EVENTS.sign_up_with_password
);
captureSuccess({
eventName:
mode === EAuthModes.SIGN_IN
? AUTH_TRACKER_EVENTS.sign_in_with_password
: AUTH_TRACKER_EVENTS.sign_up_with_password,
payload: {
email: passwordFormData.email,
},
});
if (formRef.current) formRef.current.submit(); // Manually submit the form if the condition is met
} else {
setBannerMessage(true);
}
}}
onError={() => setIsSubmitting(false)}
onError={() => {
setIsSubmitting(false);
captureError({
eventName:
mode === EAuthModes.SIGN_IN
? AUTH_TRACKER_EVENTS.sign_in_with_password
: AUTH_TRACKER_EVENTS.sign_up_with_password,
payload: {
email: passwordFormData.email,
},
});
}}
>
<input type="hidden" name="csrfmiddlewaretoken" />
<input type="hidden" value={passwordFormData.email} name="email" />
Expand Down Expand Up @@ -292,6 +304,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
{isSMTPConfigured && (
<Button
type="button"
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
onClick={redirectToUniqueCodeSignIn}
variant="outline-primary"
className="w-full"
Expand Down
47 changes: 38 additions & 9 deletions web/core/components/account/auth-forms/unique-code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import React, { useEffect, useState } from "react";
import { CircleCheck, XCircle } from "lucide-react";
import { API_BASE_URL, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { API_BASE_URL, AUTH_TRACKER_ELEMENTS, AUTH_TRACKER_EVENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button, Input, Spinner } from "@plane/ui";
// constants
// helpers
import { EAuthModes } from "@/helpers/authentication.helper";
// hooks
import { useEventTracker } from "@/hooks/store";
import { captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import useTimer from "@/hooks/use-timer";
// services
import { AuthService } from "@/services/auth.service";
Expand Down Expand Up @@ -38,8 +38,6 @@ const defaultValues: TUniqueCodeFormValues = {

export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
const { mode, email, handleEmailClear, generateEmailUniqueCode, isExistingEmail, nextPath } = props;
// hooks
const { captureEvent } = useEventTracker();
// derived values
const defaultResetTimerValue = 5;
// states
Expand All @@ -62,10 +60,22 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
setResendCodeTimer(defaultResetTimerValue);
handleFormChange("code", uniqueCode?.code || "");
setIsRequestingNewCode(false);
captureSuccess({
eventName: AUTH_TRACKER_EVENTS.new_code_requested,
payload: {
email: email,
},
});
} catch {
setResendCodeTimer(0);
console.error("Error while requesting new code");
setIsRequestingNewCode(false);
captureError({
eventName: AUTH_TRACKER_EVENTS.new_code_requested,
payload: {
email: email,
},
});
}
};

Expand All @@ -84,12 +94,23 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
action={`${API_BASE_URL}/auth/${mode === EAuthModes.SIGN_IN ? "magic-sign-in" : "magic-sign-up"}/`}
onSubmit={() => {
setIsSubmitting(true);
captureEvent(AUTH_TRACKER_EVENTS.code_verify, {
state: "SUCCESS",
first_time: !isExistingEmail,
captureSuccess({
eventName: AUTH_TRACKER_EVENTS.code_verify,
payload: {
state: "SUCCESS",
first_time: !isExistingEmail,
},
});
}}
onError={() => {
setIsSubmitting(false);
captureError({
eventName: AUTH_TRACKER_EVENTS.code_verify,
payload: {
state: "FAILED",
},
});
}}
onError={() => setIsSubmitting(false)}
>
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
<input type="hidden" value={uniqueCodeFormData.email} name="email" />
Expand Down Expand Up @@ -145,6 +166,7 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
</p>
<button
type="button"
data-ph-element={AUTH_TRACKER_ELEMENTS.REQUEST_NEW_CODE}
onClick={() => generateNewCode(uniqueCodeFormData.email)}
className={
isRequestNewCodeDisabled
Expand All @@ -163,7 +185,14 @@ export const AuthUniqueCodeForm: React.FC<TAuthUniqueCodeForm> = (props) => {
</div>

<div className="space-y-2.5">
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
<Button
type="submit"
variant="primary"
className="w-full"
size="lg"
disabled={isButtonDisabled}
data-ph-element={AUTH_TRACKER_ELEMENTS.VERIFY_CODE}
>
{isRequestingNewCode ? (
t("auth.common.unique_code.sending_code")
) : isSubmitting ? (
Expand Down