[SG-483] Trial Initiation Cleanup (#4064)
* Remove 'showTrial' feature flag * Replace Register component with trial and redirect trial routes to register * Shore up fallback logic for bad params * Remove register component that is no longer used * Adjust register form margin top * Update unit tests for new param handling * Use enums for org names and add missing org routing * Add new tests and fix existing flaky ones * Use an enum for layouts
This commit is contained in:
parent
9c0aa9e8d4
commit
40cade39bb
|
@ -16,7 +16,6 @@
|
|||
"proxyEvents": "https://events.bitwarden.com"
|
||||
},
|
||||
"flags": {
|
||||
"showTrial": true,
|
||||
"showPasswordless": true
|
||||
"showPasswordless": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
"proxyNotifications": "http://localhost:61840"
|
||||
},
|
||||
"flags": {
|
||||
"showTrial": true,
|
||||
"secretsManager": true,
|
||||
"showPasswordless": true
|
||||
}
|
||||
|
|
|
@ -6,7 +6,5 @@
|
|||
"proxyNotifications": "http://localhost:61841",
|
||||
"port": 8081
|
||||
},
|
||||
"flags": {
|
||||
"showTrial": false
|
||||
}
|
||||
"flags": {}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
"proxyEvents": "https://events.qa.bitwarden.pw"
|
||||
},
|
||||
"flags": {
|
||||
"showTrial": true,
|
||||
"secretsManager": false,
|
||||
"showPasswordless": true
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
"port": 8081
|
||||
},
|
||||
"flags": {
|
||||
"showTrial": false,
|
||||
"showPasswordless": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,210 +0,0 @@
|
|||
<div class="layout" [ngClass]="['layout', layout]">
|
||||
<!-- TEAMS 1 Header -->
|
||||
<header
|
||||
class="header"
|
||||
*ngIf="
|
||||
layout === 'default' ||
|
||||
layout === 'teams' ||
|
||||
layout === 'teams1' ||
|
||||
layout === 'teams2' ||
|
||||
layout === 'enterprise' ||
|
||||
layout === 'enterprise1' ||
|
||||
layout === 'enterprise2' ||
|
||||
layout === 'cnetcmpgnent' ||
|
||||
layout === 'cnetcmpgnteams' ||
|
||||
layout === 'cnetcmpgnind'
|
||||
"
|
||||
>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-7">
|
||||
<img
|
||||
alt="Bitwarden"
|
||||
class="logo mb-2"
|
||||
src="../../images/register-layout/logo-horizontal-white.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-7" *ngIf="layout">
|
||||
<div class="mt-5">
|
||||
<!-- Default Body -->
|
||||
<div
|
||||
*ngIf="
|
||||
layout === 'teams' ||
|
||||
layout === 'enterprise' ||
|
||||
layout === 'enterprise1' ||
|
||||
layout === 'default'
|
||||
"
|
||||
>
|
||||
<h1>The Bitwarden Password Manager</h1>
|
||||
<h2>
|
||||
Trusted by millions of individuals, teams, and organizations worldwide for secure
|
||||
password storage and sharing.
|
||||
</h2>
|
||||
<p>Store logins, secure notes, and more</p>
|
||||
<p>Collaborate and share securely</p>
|
||||
<p>Access anywhere on any device</p>
|
||||
<p>Create your account to get started</p>
|
||||
</div>
|
||||
|
||||
<!-- Teams & Enterprise Body -->
|
||||
<div *ngIf="layout === 'teams1' || layout === 'teams2' || layout === 'enterprise2'">
|
||||
<h1>
|
||||
Start Your <span *ngIf="layout === 'teams1'">Teams<br /></span
|
||||
><span *ngIf="layout === 'enterprise2'">Enterprise</span> Free Trial Now
|
||||
</h1>
|
||||
<h2>
|
||||
Millions of individuals, teams, and organizations worldwide trust Bitwarden for secure
|
||||
password storage and sharing.
|
||||
</h2>
|
||||
<p>Collaborate and share securely</p>
|
||||
<p>Deploy and manage quickly and easily</p>
|
||||
<p>Access anywhere on any device</p>
|
||||
<p>Create your account to get started</p>
|
||||
</div>
|
||||
|
||||
<!-- CNET Campaign Teams & Enterprise Body -->
|
||||
<div *ngIf="layout === 'cnetcmpgnteams' || layout === 'cnetcmpgnent'">
|
||||
<h1>
|
||||
Start Your <span *ngIf="layout === 'cnetcmpgnteams'">Teams<br /></span
|
||||
><span *ngIf="layout === 'cnetcmpgnent'">Enterprise</span> Free Trial Now
|
||||
</h1>
|
||||
<h2>
|
||||
Millions of individuals, teams, and organizations worldwide trust Bitwarden for secure
|
||||
password storage and sharing.
|
||||
</h2>
|
||||
<p>Collaborate and share securely</p>
|
||||
<p>Deploy and manage quickly and easily</p>
|
||||
<p>Access anywhere on any device</p>
|
||||
<p>Create your account to get started</p>
|
||||
</div>
|
||||
|
||||
<!-- CNET Campaign Premium Body -->
|
||||
<div *ngIf="layout === 'cnetcmpgnind'">
|
||||
<h1>Start Your Premium Account Now</h1>
|
||||
<h2>
|
||||
Millions of individuals, teams, and organizations worldwide trust Bitwarden for secure
|
||||
password storage and sharing.
|
||||
</h2>
|
||||
<p>Store logins, secure notes, and more</p>
|
||||
<p>Secure your account with advanced two-step login</p>
|
||||
<p>Access anywhere on any device</p>
|
||||
<p>Create your account to get started</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div [ngClass]="{ 'col-5': layout, 'col-12': !layout }">
|
||||
<div class="row justify-content-md-center mt-5">
|
||||
<div [ngClass]="{ 'col-5': !layout, 'col-12': layout }">
|
||||
<h1 class="lead text-center mb-4" *ngIf="!layout">{{ "createAccount" | i18n }}</h1>
|
||||
<div class="card d-block">
|
||||
<div class="card-body">
|
||||
<app-callout
|
||||
title="{{ 'createOrganizationStep1' | i18n }}"
|
||||
type="info"
|
||||
icon="bwi bwi-thumb-tack"
|
||||
*ngIf="showCreateOrgMessage"
|
||||
>
|
||||
{{ "createOrganizationCreatePersonalAccount" | i18n }}
|
||||
</app-callout>
|
||||
<app-register-form
|
||||
[queryParamEmail]="email"
|
||||
[enforcedPolicyOptions]="enforcedPolicyOptions"
|
||||
[referenceDataValue]="referenceData"
|
||||
></app-register-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-7 d-flex align-items-center">
|
||||
<div
|
||||
*ngIf="
|
||||
layout === 'cnetcmpgnent' || layout === 'cnetcmpgnteams' || layout === 'cnetcmpgnind'
|
||||
"
|
||||
>
|
||||
<figure>
|
||||
<figcaption>
|
||||
<cite>
|
||||
<img
|
||||
src="../../images/register-layout/cnet-logo.svg"
|
||||
class="w-25 d-block mx-auto"
|
||||
alt="cnet logo"
|
||||
/>
|
||||
</cite>
|
||||
</figcaption>
|
||||
<blockquote class="mx-auto text-center px-4">
|
||||
"No more excuses; start using Bitwarden today. The identity you save could be your
|
||||
own. The money definitely will be."
|
||||
</blockquote>
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div
|
||||
*ngIf="
|
||||
layout === 'teams' ||
|
||||
layout === 'teams1' ||
|
||||
layout === 'teams2' ||
|
||||
layout === 'enterprise' ||
|
||||
layout === 'enterprise1' ||
|
||||
layout === 'enterprise2' ||
|
||||
layout === 'default'
|
||||
"
|
||||
>
|
||||
<figure>
|
||||
<figcaption>
|
||||
<cite>
|
||||
<img
|
||||
src="../../images/register-layout/forbes-logo.svg"
|
||||
class="w-25 d-block mx-auto"
|
||||
alt="Forbes Logo"
|
||||
/>
|
||||
</cite>
|
||||
</figcaption>
|
||||
<blockquote class="mx-auto text-center px-4">
|
||||
“Bitwarden boasts the backing of some of the world's best security experts and an
|
||||
attractive, easy-to-use interface”
|
||||
</blockquote>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="
|
||||
layout === 'cnetcmpgnent' || layout === 'cnetcmpgnteams' || layout === 'cnetcmpgnind'
|
||||
"
|
||||
class="col-5 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img
|
||||
src="../../images/register-layout/usnews-360-badge.svg"
|
||||
class="w-50 d-block"
|
||||
alt="US News 360 Reviews Best Password Manager"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="
|
||||
layout === 'teams' ||
|
||||
layout === 'teams1' ||
|
||||
layout === 'teams2' ||
|
||||
layout === 'enterprise' ||
|
||||
layout === 'enterprise1' ||
|
||||
layout === 'enterprise2' ||
|
||||
layout === 'default'
|
||||
"
|
||||
class="col-5 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img
|
||||
src="../../images/register-layout/usnews-360-badge.svg"
|
||||
class="w-50 d-block"
|
||||
alt="US News 360 Reviews Best Password Manager"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,149 +0,0 @@
|
|||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { UntypedFormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuthService } from "@bitwarden/common/abstractions/auth.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||
import { FormValidationErrorsService } from "@bitwarden/common/abstractions/formValidationErrors.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/abstractions/policy/policy-api.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy/policy.service.abstraction";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { PolicyData } from "@bitwarden/common/models/data/policy.data";
|
||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/models/domain/master-password-policy-options";
|
||||
import { Policy } from "@bitwarden/common/models/domain/policy";
|
||||
import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request";
|
||||
|
||||
import { RouterService } from "../core";
|
||||
|
||||
@Component({
|
||||
selector: "app-register",
|
||||
templateUrl: "register.component.html",
|
||||
})
|
||||
export class RegisterComponent extends BaseRegisterComponent implements OnInit, OnDestroy {
|
||||
email = "";
|
||||
showCreateOrgMessage = false;
|
||||
layout = "";
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
|
||||
private policies: Policy[];
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
formValidationErrorService: FormValidationErrorsService,
|
||||
formBuilder: UntypedFormBuilder,
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
apiService: ApiService,
|
||||
private route: ActivatedRoute,
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
private policyApiService: PolicyApiServiceAbstraction,
|
||||
private policyService: PolicyService,
|
||||
environmentService: EnvironmentService,
|
||||
logService: LogService,
|
||||
private routerService: RouterService
|
||||
) {
|
||||
super(
|
||||
formValidationErrorService,
|
||||
formBuilder,
|
||||
authService,
|
||||
router,
|
||||
i18nService,
|
||||
cryptoService,
|
||||
apiService,
|
||||
stateService,
|
||||
platformUtilsService,
|
||||
passwordGenerationService,
|
||||
environmentService,
|
||||
logService
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
this.route.queryParams.pipe(first()).subscribe((qParams) => {
|
||||
this.referenceData = new ReferenceEventRequest();
|
||||
if (qParams.email != null && qParams.email.indexOf("@") > -1) {
|
||||
this.email = qParams.email;
|
||||
}
|
||||
if (qParams.premium != null) {
|
||||
this.routerService.setPreviousUrl("/settings/premium");
|
||||
} else if (qParams.org != null) {
|
||||
this.showCreateOrgMessage = true;
|
||||
this.referenceData.flow = qParams.org;
|
||||
const route = this.router.createUrlTree(["create-organization"], {
|
||||
queryParams: { plan: qParams.org },
|
||||
});
|
||||
this.routerService.setPreviousUrl(route.toString());
|
||||
}
|
||||
if (qParams.layout != null) {
|
||||
this.layout = this.referenceData.layout = qParams.layout;
|
||||
}
|
||||
if (qParams.reference != null) {
|
||||
this.referenceData.id = qParams.reference;
|
||||
} else {
|
||||
this.referenceData.id = ("; " + document.cookie)
|
||||
.split("; reference=")
|
||||
.pop()
|
||||
.split(";")
|
||||
.shift();
|
||||
}
|
||||
// Are they coming from an email for sponsoring a families organization
|
||||
if (qParams.sponsorshipToken != null) {
|
||||
// After logging in redirect them to setup the families sponsorship
|
||||
const route = this.router.createUrlTree(["setup/families-for-enterprise"], {
|
||||
queryParams: { plan: qParams.sponsorshipToken },
|
||||
});
|
||||
this.routerService.setPreviousUrl(route.toString());
|
||||
}
|
||||
if (this.referenceData.id === "") {
|
||||
this.referenceData.id = null;
|
||||
}
|
||||
});
|
||||
const invite = await this.stateService.getOrganizationInvitation();
|
||||
if (invite != null) {
|
||||
try {
|
||||
const policies = await this.policyApiService.getPoliciesByToken(
|
||||
invite.organizationId,
|
||||
invite.token,
|
||||
invite.email,
|
||||
invite.organizationUserId
|
||||
);
|
||||
if (policies.data != null) {
|
||||
const policiesData = policies.data.map((p) => new PolicyData(p));
|
||||
this.policies = policiesData.map((p) => new Policy(p));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.policies != null) {
|
||||
this.policyService
|
||||
.masterPasswordPolicyOptions$(this.policies)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((enforcedPasswordPolicyOptions) => {
|
||||
this.enforcedPolicyOptions = enforcedPasswordPolicyOptions;
|
||||
});
|
||||
}
|
||||
|
||||
await super.ngOnInit();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
|
@ -23,26 +23,39 @@
|
|||
|
||||
<div class="tw-pt-12">
|
||||
<!-- Layout params are used by marketing to determine left-hand content -->
|
||||
<app-default-content *ngIf="layout === 'default'"></app-default-content>
|
||||
<app-teams-content *ngIf="layout === 'teams'"></app-teams-content>
|
||||
<app-teams1-content *ngIf="layout === 'teams1'"></app-teams1-content>
|
||||
<app-teams2-content *ngIf="layout === 'teams2'"></app-teams2-content>
|
||||
<app-enterprise-content *ngIf="layout === 'enterprise'"></app-enterprise-content>
|
||||
<app-enterprise1-content *ngIf="layout === 'enterprise1'"></app-enterprise1-content>
|
||||
<app-enterprise2-content *ngIf="layout === 'enterprise2'"></app-enterprise2-content>
|
||||
<app-default-content *ngIf="layout === layouts.default"></app-default-content>
|
||||
<app-teams-content *ngIf="layout === layouts.teams"></app-teams-content>
|
||||
<app-teams1-content *ngIf="layout === layouts.teams1"></app-teams1-content>
|
||||
<app-teams2-content *ngIf="layout === layouts.teams2"></app-teams2-content>
|
||||
<app-enterprise-content *ngIf="layout === layouts.enterprise"></app-enterprise-content>
|
||||
<app-enterprise1-content *ngIf="layout === layouts.enterprise1"></app-enterprise1-content>
|
||||
<app-enterprise2-content *ngIf="layout === layouts.enterprise2"></app-enterprise2-content>
|
||||
<app-cnet-enterprise-content
|
||||
*ngIf="layout === 'cnetcmpgnent'"
|
||||
*ngIf="layout === layouts.cnetcmpgnent"
|
||||
></app-cnet-enterprise-content>
|
||||
<app-cnet-individual-content
|
||||
*ngIf="layout === 'cnetcmpgnind'"
|
||||
*ngIf="layout === layouts.cnetcmpgnind"
|
||||
></app-cnet-individual-content>
|
||||
<app-cnet-teams-content *ngIf="layout === 'cnetcmpgnteams'"></app-cnet-teams-content>
|
||||
<app-abm-enterprise-content *ngIf="layout === 'abmenterprise'"></app-abm-enterprise-content>
|
||||
<app-abm-teams-content *ngIf="layout === 'abmteams'"></app-abm-teams-content>
|
||||
<app-cnet-teams-content *ngIf="layout === layouts.cnetcmpgnteams"></app-cnet-teams-content>
|
||||
<app-abm-enterprise-content
|
||||
*ngIf="layout === layouts.abmenterprise"
|
||||
></app-abm-enterprise-content>
|
||||
<app-abm-teams-content *ngIf="layout === layouts.abmteams"></app-abm-teams-content>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-w-1/2">
|
||||
<div class="tw-pt-56">
|
||||
<div *ngIf="!useTrialStepper">
|
||||
<div
|
||||
class="tw-min-w-xl tw-m-auto tw-mt-28 tw-max-w-xl tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-8"
|
||||
>
|
||||
<app-register-form
|
||||
[queryParamEmail]="email"
|
||||
[enforcedPolicyOptions]="enforcedPolicyOptions"
|
||||
[referenceDataValue]="referenceData"
|
||||
></app-register-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-pt-44" *ngIf="useTrialStepper">
|
||||
<div class="tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background">
|
||||
<div class="tw-flex tw-h-12 tw-w-full tw-items-center tw-rounded-t tw-bg-secondary-100">
|
||||
<h2 class="tw-mb-0 tw-pl-4 tw-text-base tw-font-bold tw-uppercase">
|
||||
|
|
|
@ -168,8 +168,9 @@ describe("TrialInitiationComponent", () => {
|
|||
it("should set org variable to be enterprise and plan to EnterpriseAnnually if org param is enterprise", fakeAsync(() => {
|
||||
mockQueryParams.next({ org: "enterprise" });
|
||||
tick(); // wait for resolution
|
||||
fixture = TestBed.createComponent(TrialInitiationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
component.ngOnInit();
|
||||
expect(component.org).toBe("enterprise");
|
||||
expect(component.plan).toBe(PlanType.EnterpriseAnnually);
|
||||
}));
|
||||
|
@ -182,13 +183,33 @@ describe("TrialInitiationComponent", () => {
|
|||
expect(component.org).toBe("");
|
||||
expect(component.accountCreateOnly).toBe(true);
|
||||
}));
|
||||
it("should set the org to be families and plan to FamiliesAnnually if org param is invalid ", fakeAsync(async () => {
|
||||
it("should not set the org if org param is invalid ", fakeAsync(async () => {
|
||||
mockQueryParams.next({ org: "hahahaha" });
|
||||
tick(); // wait for resolution
|
||||
fixture = TestBed.createComponent(TrialInitiationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
expect(component.org).toBe("");
|
||||
expect(component.accountCreateOnly).toBe(true);
|
||||
}));
|
||||
it("should set the layout variable if layout param is valid ", fakeAsync(async () => {
|
||||
mockQueryParams.next({ layout: "teams1" });
|
||||
tick(); // wait for resolution
|
||||
fixture = TestBed.createComponent(TrialInitiationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
expect(component.layout).toBe("teams1");
|
||||
expect(component.accountCreateOnly).toBe(false);
|
||||
}));
|
||||
it("should not set the layout variable and leave as 'default' if layout param is invalid ", fakeAsync(async () => {
|
||||
mockQueryParams.next({ layout: "asdfasdf" });
|
||||
tick(); // wait for resolution
|
||||
fixture = TestBed.createComponent(TrialInitiationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
component.ngOnInit();
|
||||
expect(component.org).toBe("families");
|
||||
expect(component.plan).toBe(PlanType.FamiliesAnnually);
|
||||
expect(component.layout).toBe("default");
|
||||
expect(component.accountCreateOnly).toBe(true);
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
|
@ -20,6 +20,30 @@ import { ReferenceEventRequest } from "@bitwarden/common/models/request/referenc
|
|||
import { RouterService } from "./../../core/router.service";
|
||||
import { VerticalStepperComponent } from "./vertical-stepper/vertical-stepper.component";
|
||||
|
||||
enum ValidOrgParams {
|
||||
families = "families",
|
||||
enterprise = "enterprise",
|
||||
teams = "teams",
|
||||
individual = "individual",
|
||||
premium = "premium",
|
||||
free = "free",
|
||||
}
|
||||
|
||||
enum ValidLayoutParams {
|
||||
default = "default",
|
||||
teams = "teams",
|
||||
teams1 = "teams1",
|
||||
teams2 = "teams2",
|
||||
enterprise = "enterprise",
|
||||
enterprise1 = "enterprise1",
|
||||
enterprise2 = "enterprise2",
|
||||
cnetcmpgnent = "cnetcmpgnent",
|
||||
cnetcmpgnind = "cnetcmpgnind",
|
||||
cnetcmpgnteams = "cnetcmpgnteams",
|
||||
abmenterprise = "abmenterprise",
|
||||
abmteams = "abmteams",
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "app-trial",
|
||||
templateUrl: "trial-initiation.component.html",
|
||||
|
@ -35,9 +59,20 @@ export class TrialInitiationComponent implements OnInit, OnDestroy {
|
|||
plan: PlanType;
|
||||
product: ProductType;
|
||||
accountCreateOnly = true;
|
||||
useTrialStepper = false;
|
||||
policies: Policy[];
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
validOrgs: string[] = ["teams", "enterprise", "families"];
|
||||
trialFlowOrgs: string[] = [
|
||||
ValidOrgParams.teams,
|
||||
ValidOrgParams.enterprise,
|
||||
ValidOrgParams.families,
|
||||
];
|
||||
routeFlowOrgs: string[] = [
|
||||
ValidOrgParams.free,
|
||||
ValidOrgParams.premium,
|
||||
ValidOrgParams.individual,
|
||||
];
|
||||
layouts = ValidLayoutParams;
|
||||
referenceData: ReferenceEventRequest;
|
||||
@ViewChild("stepper", { static: false }) verticalStepper: VerticalStepperComponent;
|
||||
|
||||
|
@ -87,39 +122,38 @@ export class TrialInitiationComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.referenceDataId = qParams.reference;
|
||||
|
||||
if (!qParams.org) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (qParams.layout) {
|
||||
if (Object.values(ValidLayoutParams).includes(qParams.layout)) {
|
||||
this.layout = qParams.layout;
|
||||
this.accountCreateOnly = false;
|
||||
}
|
||||
|
||||
if (this.validOrgs.includes(qParams.org)) {
|
||||
if (this.trialFlowOrgs.includes(qParams.org)) {
|
||||
this.org = qParams.org;
|
||||
} else {
|
||||
this.org = "families";
|
||||
}
|
||||
this.orgLabel = this.titleCasePipe.transform(this.org);
|
||||
this.useTrialStepper = true;
|
||||
this.referenceData.flow = qParams.org;
|
||||
|
||||
this.referenceData.flow = qParams.org;
|
||||
if (this.org === ValidOrgParams.families) {
|
||||
this.plan = PlanType.FamiliesAnnually;
|
||||
this.product = ProductType.Families;
|
||||
} else if (this.org === ValidOrgParams.teams) {
|
||||
this.plan = PlanType.TeamsAnnually;
|
||||
this.product = ProductType.Teams;
|
||||
} else if (this.org === ValidOrgParams.enterprise) {
|
||||
this.plan = PlanType.EnterpriseAnnually;
|
||||
this.product = ProductType.Enterprise;
|
||||
}
|
||||
} else if (this.routeFlowOrgs.includes(qParams.org)) {
|
||||
this.referenceData.flow = qParams.org;
|
||||
const route = this.router.createUrlTree(["create-organization"], {
|
||||
queryParams: { plan: qParams.org },
|
||||
});
|
||||
this.routerService.setPreviousUrl(route.toString());
|
||||
}
|
||||
|
||||
// Are they coming from an email for sponsoring a families organization
|
||||
// After logging in redirect them to setup the families sponsorship
|
||||
this.setupFamilySponsorship(qParams.sponsorshipToken);
|
||||
|
||||
this.orgLabel = this.titleCasePipe.transform(this.org);
|
||||
this.accountCreateOnly = false;
|
||||
|
||||
if (this.org === "families") {
|
||||
this.plan = PlanType.FamiliesAnnually;
|
||||
this.product = ProductType.Families;
|
||||
} else if (this.org === "teams") {
|
||||
this.plan = PlanType.TeamsAnnually;
|
||||
this.product = ProductType.Teams;
|
||||
} else if (this.org === "enterprise") {
|
||||
this.plan = PlanType.EnterpriseAnnually;
|
||||
this.product = ProductType.Enterprise;
|
||||
}
|
||||
});
|
||||
|
||||
const invite = await this.stateService.getOrganizationInvitation();
|
||||
|
|
|
@ -15,7 +15,6 @@ import { LoginWithDeviceComponent } from "./accounts/login/login-with-device.com
|
|||
import { LoginComponent } from "./accounts/login/login.component";
|
||||
import { RecoverDeleteComponent } from "./accounts/recover-delete.component";
|
||||
import { RecoverTwoFactorComponent } from "./accounts/recover-two-factor.component";
|
||||
import { RegisterComponent } from "./accounts/register.component";
|
||||
import { RemovePasswordComponent } from "./accounts/remove-password.component";
|
||||
import { SetPasswordComponent } from "./accounts/set-password.component";
|
||||
import { SsoComponent } from "./accounts/sso.component";
|
||||
|
@ -69,16 +68,15 @@ const routes: Routes = [
|
|||
{ path: "2fa", component: TwoFactorComponent, canActivate: [UnauthGuard] },
|
||||
{
|
||||
path: "register",
|
||||
component: RegisterComponent,
|
||||
component: TrialInitiationComponent,
|
||||
canActivate: [UnauthGuard],
|
||||
data: { titleId: "createAccount" },
|
||||
},
|
||||
buildFlaggedRoute("showTrial", {
|
||||
{
|
||||
path: "trial",
|
||||
component: TrialInitiationComponent,
|
||||
canActivate: [UnauthGuard],
|
||||
data: { titleId: "startTrial" },
|
||||
}),
|
||||
redirectTo: "register",
|
||||
pathMatch: "full",
|
||||
},
|
||||
{
|
||||
path: "sso",
|
||||
component: SsoComponent,
|
||||
|
|
|
@ -7,7 +7,6 @@ import { LockComponent } from "../accounts/lock.component";
|
|||
import { RecoverDeleteComponent } from "../accounts/recover-delete.component";
|
||||
import { RecoverTwoFactorComponent } from "../accounts/recover-two-factor.component";
|
||||
import { RegisterFormModule } from "../accounts/register-form/register-form.module";
|
||||
import { RegisterComponent } from "../accounts/register.component";
|
||||
import { RemovePasswordComponent } from "../accounts/remove-password.component";
|
||||
import { SetPasswordComponent } from "../accounts/set-password.component";
|
||||
import { SsoComponent } from "../accounts/sso.component";
|
||||
|
@ -218,7 +217,6 @@ import { SharedModule } from ".";
|
|||
PurgeVaultComponent,
|
||||
RecoverDeleteComponent,
|
||||
RecoverTwoFactorComponent,
|
||||
RegisterComponent,
|
||||
RemovePasswordComponent,
|
||||
SecurityComponent,
|
||||
SecurityKeysComponent,
|
||||
|
@ -341,7 +339,6 @@ import { SharedModule } from ".";
|
|||
PurgeVaultComponent,
|
||||
RecoverDeleteComponent,
|
||||
RecoverTwoFactorComponent,
|
||||
RegisterComponent,
|
||||
RemovePasswordComponent,
|
||||
SecurityComponent,
|
||||
SecurityKeysComponent,
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
// required to avoid linting errors when there are no flags
|
||||
/* eslint-disable-next-line @typescript-eslint/ban-types */
|
||||
export type Flags = {
|
||||
showTrial?: boolean;
|
||||
secretsManager?: boolean;
|
||||
showPasswordless?: boolean;
|
||||
} & SharedFlags;
|
||||
|
|
Loading…
Reference in New Issue