added new profile colum onboarding_free_state to keep track of onboarding state for free users, migration included, app updated to use new profile field
This commit is contained in:
Родитель
386f570eb5
Коммит
8d065b4682
|
@ -51,3 +51,4 @@ SUBSCRIPTIONS_WITH_UNLIMITED="monitor-unlimited,mozilla-one,guardian_vpn,premium
|
|||
SUBSCRIPTIONS_WITH_PHONE="relay-phones,"
|
||||
SUBSCRIPTIONS_WITH_VPN="guardian_vpn_1,guardian_vpn"
|
||||
MAX_ONBOARDING_AVAILABLE=3
|
||||
MAX_ONBOARDING_FREE_AVAILABLE=3
|
||||
|
|
|
@ -158,6 +158,7 @@ class ProfileSerializer(StrictReadOnlyFieldsMixin, serializers.ModelSerializer):
|
|||
"has_phone",
|
||||
"has_vpn",
|
||||
"onboarding_state",
|
||||
"onboarding_free_state",
|
||||
"date_subscribed",
|
||||
"avatar",
|
||||
"next_email_try",
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 3.2.19 on 2023-10-19 23:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("emails", "0057_profile_sent_welcome_email"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="profile",
|
||||
name="onboarding_free_state",
|
||||
field=models.PositiveIntegerField(default=0),
|
||||
),
|
||||
]
|
|
@ -125,6 +125,7 @@ class Profile(models.Model):
|
|||
# TODO: Schema migration to remove null=True
|
||||
remove_level_one_email_trackers = models.BooleanField(null=True, default=False)
|
||||
onboarding_state = models.PositiveIntegerField(default=0)
|
||||
onboarding_free_state = models.PositiveIntegerField(default=0)
|
||||
auto_block_spam = models.BooleanField(default=False)
|
||||
forwarded_first_reply = models.BooleanField(default=False)
|
||||
# Empty string means the profile was created through relying party flow
|
||||
|
|
|
@ -14,6 +14,7 @@ const runtimeConfigs = {
|
|||
mozmailDomain: "mozmail.com",
|
||||
googleAnalyticsId: "UA-77033033-33",
|
||||
maxOnboardingAvailable: 3,
|
||||
maxOnboardingFreeAvailable: 3,
|
||||
featureFlags: {
|
||||
// Also add keys here to RuntimeConfig in src/config.ts
|
||||
tips: true,
|
||||
|
|
|
@ -106,6 +106,7 @@ export const mockedProfiles: Record<(typeof mockIds)[number], ProfileData> = {
|
|||
id: 4,
|
||||
next_email_try: "2020-04-09T00:00:00.000Z",
|
||||
onboarding_state: 3,
|
||||
onboarding_free_state: 3,
|
||||
forwarded_first_reply: true,
|
||||
server_storage: true,
|
||||
store_phone_log: true,
|
||||
|
@ -127,6 +128,7 @@ export const mockedProfiles: Record<(typeof mockIds)[number], ProfileData> = {
|
|||
id: 0,
|
||||
next_email_try: "2020-04-09T00:00:00.000Z",
|
||||
onboarding_state: 0,
|
||||
onboarding_free_state: 0,
|
||||
forwarded_first_reply: false,
|
||||
server_storage: true,
|
||||
store_phone_log: true,
|
||||
|
@ -148,6 +150,7 @@ export const mockedProfiles: Record<(typeof mockIds)[number], ProfileData> = {
|
|||
id: 1,
|
||||
next_email_try: "2020-04-09T00:00:00.000Z",
|
||||
onboarding_state: 0,
|
||||
onboarding_free_state: 0,
|
||||
forwarded_first_reply: false,
|
||||
server_storage: true,
|
||||
subdomain: null,
|
||||
|
@ -169,6 +172,7 @@ export const mockedProfiles: Record<(typeof mockIds)[number], ProfileData> = {
|
|||
id: 2,
|
||||
next_email_try: "2020-04-09T00:00:00.000Z",
|
||||
onboarding_state: 3,
|
||||
onboarding_free_state: 3,
|
||||
forwarded_first_reply: true,
|
||||
server_storage: true,
|
||||
subdomain: null,
|
||||
|
@ -190,6 +194,7 @@ export const mockedProfiles: Record<(typeof mockIds)[number], ProfileData> = {
|
|||
id: 3,
|
||||
next_email_try: "2020-04-09T00:00:00.000Z",
|
||||
onboarding_state: 3,
|
||||
onboarding_free_state: 3,
|
||||
forwarded_first_reply: true,
|
||||
server_storage: true,
|
||||
subdomain: "mydomain",
|
||||
|
|
|
@ -75,7 +75,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
value: 1,
|
||||
});
|
||||
|
||||
if (props.profile.onboarding_state === 0) {
|
||||
if (props.profile.onboarding_free_state === 0) {
|
||||
const skipMaskCreation = () => {
|
||||
props.onNextStep(3);
|
||||
gaEvent({
|
||||
|
@ -117,7 +117,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
);
|
||||
}
|
||||
|
||||
if (props.profile.onboarding_state === 1) {
|
||||
if (props.profile.onboarding_free_state === 1) {
|
||||
const skipMaskTesting = () => {
|
||||
props.onNextStep(3);
|
||||
gaEvent({
|
||||
|
@ -197,7 +197,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
);
|
||||
}
|
||||
|
||||
if (props.profile.onboarding_state === 2) {
|
||||
if (props.profile.onboarding_free_state === 2) {
|
||||
const linkForBrowser = supportsChromeExtension()
|
||||
? "https://chrome.google.com/webstore/detail/firefox-relay/lknpoadjjkjcmjhbjpcljdednccbldeb?utm_source=fx-relay&utm_medium=onboarding&utm_campaign=install-addon"
|
||||
: "https://addons.mozilla.org/firefox/addon/private-relay/";
|
||||
|
@ -273,10 +273,10 @@ export const FreeOnboarding = (props: Props) => {
|
|||
<VisuallyHidden>
|
||||
<progress
|
||||
max={getRuntimeConfig().maxOnboardingAvailable}
|
||||
value={props.profile.onboarding_state + 1}
|
||||
value={props.profile.onboarding_free_state + 1}
|
||||
>
|
||||
{l10n.getString("multi-part-onboarding-step-counter", {
|
||||
step: props.profile.onboarding_state,
|
||||
step: props.profile.onboarding_free_state,
|
||||
max: getRuntimeConfig().maxOnboardingAvailable,
|
||||
})}
|
||||
</progress>
|
||||
|
@ -285,7 +285,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
<ol className={styles["styled-progress-bar"]} aria-hidden={true}>
|
||||
<li
|
||||
className={
|
||||
props.profile.onboarding_state >= 0
|
||||
props.profile.onboarding_free_state >= 0
|
||||
? styles["is-completed"]
|
||||
: undefined
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
</li>
|
||||
<li
|
||||
className={
|
||||
props.profile.onboarding_state >= 1
|
||||
props.profile.onboarding_free_state >= 1
|
||||
? styles["is-completed"]
|
||||
: undefined
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ export const FreeOnboarding = (props: Props) => {
|
|||
</li>
|
||||
<li
|
||||
className={
|
||||
props.profile.onboarding_state >= 2
|
||||
props.profile.onboarding_free_state >= 2
|
||||
? styles["is-completed"]
|
||||
: undefined
|
||||
}
|
||||
|
|
|
@ -18,4 +18,5 @@ export type RuntimeConfig = {
|
|||
mozmailDomain: "mozmail.com";
|
||||
googleAnalyticsId: `UA-${number}-${number}`;
|
||||
maxOnboardingAvailable: number;
|
||||
maxOnboardingFreeAvailable: number;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ export type ProfileData = {
|
|||
has_vpn: boolean;
|
||||
subdomain: string | null;
|
||||
onboarding_state: number;
|
||||
onboarding_free_state: number;
|
||||
forwarded_first_reply: boolean;
|
||||
avatar: string;
|
||||
date_subscribed: null | DateString;
|
||||
|
|
|
@ -71,7 +71,8 @@ const Profile: NextPage = () => {
|
|||
const addonData = useAddonData();
|
||||
const l10n = useL10n();
|
||||
const freeOnboardingCelebrationStep =
|
||||
getRuntimeConfig().maxOnboardingAvailable + 1;
|
||||
// +1 because we want to show the celebration confetti after the last step
|
||||
getRuntimeConfig().maxOnboardingFreeAvailable + 1;
|
||||
const bottomBannerSubscriptionLinkRef = useGaViewPing({
|
||||
category: "Purchase Button",
|
||||
label: "profile-bottom-promo",
|
||||
|
@ -232,11 +233,12 @@ const Profile: NextPage = () => {
|
|||
if (
|
||||
isFlagActive(runtimeData.data, "free_user_onboarding") &&
|
||||
!profile.has_premium &&
|
||||
profile.onboarding_state < getRuntimeConfig().maxOnboardingAvailable
|
||||
profile.onboarding_free_state <
|
||||
getRuntimeConfig().maxOnboardingFreeAvailable
|
||||
) {
|
||||
const onNextStep = (step: number) => {
|
||||
profileData.update(profile.id, {
|
||||
onboarding_state: step,
|
||||
onboarding_free_state: step,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -565,8 +567,10 @@ const Profile: NextPage = () => {
|
|||
totalForwardedEmails={profile.emails_forwarded}
|
||||
totalEmailTrackersRemoved={profile.level_one_trackers_blocked}
|
||||
/>
|
||||
{/* confetti animation should be shown if user has sent first forwarded email, is a free user, and has not reached the max onboarding step */}
|
||||
{isFlagActive(runtimeData.data, "free_user_onboarding") &&
|
||||
!profile.has_premium &&
|
||||
profile.forwarded_first_reply &&
|
||||
profile.onboarding_state < freeOnboardingCelebrationStep && (
|
||||
<Confetti
|
||||
tweenDuration={5000}
|
||||
|
|
|
@ -379,6 +379,7 @@ SUBSCRIPTIONS_WITH_PHONE = config("SUBSCRIPTIONS_WITH_PHONE", default="", cast=C
|
|||
SUBSCRIPTIONS_WITH_VPN = config("SUBSCRIPTIONS_WITH_VPN", default="", cast=Csv())
|
||||
|
||||
MAX_ONBOARDING_AVAILABLE = config("MAX_ONBOARDING_AVAILABLE", 0, cast=int)
|
||||
MAX_ONBOARDING_FREE_AVAILABLE = config("MAX_ONBOARDING_AVAILABLE", 0, cast=int)
|
||||
|
||||
MAX_ADDRESS_CREATION_PER_DAY = config("MAX_ADDRESS_CREATION_PER_DAY", 100, cast=int)
|
||||
MAX_REPLIES_PER_DAY = config("MAX_REPLIES_PER_DAY", 100, cast=int)
|
||||
|
|
Загрузка…
Ссылка в новой задаче