mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-22312] Resolve TS 5.8 errors (#16108)
* refactor: remove ts-strict-ignore and update * refactor: remove ts-strict-ignore and update * refactor: simplify if statement * refactor: remove ts-strict-ignore and update * refactor: add nullable union for interfaces
This commit is contained in:
@@ -42,7 +42,7 @@ export type TrialOrganizationType = Exclude<ProductTierType, ProductTierType.Fre
|
||||
export interface OrganizationInfo {
|
||||
name: string;
|
||||
email: string;
|
||||
type: TrialOrganizationType;
|
||||
type: TrialOrganizationType | null;
|
||||
}
|
||||
|
||||
export interface OrganizationCreatedEvent {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[showClose]="false"
|
||||
*ngIf="freeTrialData?.shownBanner"
|
||||
>
|
||||
{{ freeTrialData.message }}
|
||||
{{ freeTrialData?.message }}
|
||||
<a
|
||||
bitLink
|
||||
linkType="secondary"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Location } from "@angular/common";
|
||||
import { Component, OnDestroy } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
@@ -47,21 +45,21 @@ import { FreeTrial } from "../../types/free-trial";
|
||||
standalone: false,
|
||||
})
|
||||
export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
organizationId: string;
|
||||
organizationId!: string;
|
||||
isUnpaid = false;
|
||||
accountCredit: number;
|
||||
accountCredit?: number;
|
||||
paymentSource?: PaymentSourceResponse;
|
||||
subscriptionStatus?: string;
|
||||
protected freeTrialData: FreeTrial;
|
||||
organization: Organization;
|
||||
organizationSubscriptionResponse: OrganizationSubscriptionResponse;
|
||||
protected freeTrialData?: FreeTrial;
|
||||
organization?: Organization;
|
||||
organizationSubscriptionResponse?: OrganizationSubscriptionResponse;
|
||||
|
||||
loading = true;
|
||||
|
||||
protected readonly Math = Math;
|
||||
launchPaymentModalAutomatically = false;
|
||||
|
||||
protected taxInformation: TaxInformation;
|
||||
protected taxInformation?: TaxInformation;
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
@@ -104,7 +102,7 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
.subscribe();
|
||||
|
||||
const state = this.router.getCurrentNavigation()?.extras?.state;
|
||||
// incase the above state is undefined or null we use redundantState
|
||||
// In case the above state is undefined or null, we use redundantState
|
||||
const redundantState: any = location.getState();
|
||||
const queryParam = this.activatedRoute.snapshot.queryParamMap.get(
|
||||
"launchPaymentModalAutomatically",
|
||||
@@ -116,10 +114,8 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
Object.prototype.hasOwnProperty.call(redundantState, "launchPaymentModalAutomatically")
|
||||
) {
|
||||
this.launchPaymentModalAutomatically = redundantState.launchPaymentModalAutomatically;
|
||||
} else if (queryParam === "true") {
|
||||
this.launchPaymentModalAutomatically = true;
|
||||
} else {
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
this.launchPaymentModalAutomatically = queryParam === "true";
|
||||
}
|
||||
}
|
||||
ngOnDestroy(): void {
|
||||
@@ -155,14 +151,21 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
this.paymentSource = paymentSource;
|
||||
this.subscriptionStatus = subscriptionStatus;
|
||||
this.taxInformation = taxInformation;
|
||||
this.isUnpaid = this.subscriptionStatus === "unpaid";
|
||||
|
||||
if (this.organizationId) {
|
||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||
this.organizationId,
|
||||
);
|
||||
|
||||
const userId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("User ID is not found");
|
||||
}
|
||||
|
||||
const organizationPromise = await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
@@ -173,15 +176,20 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
organizationSubscriptionPromise,
|
||||
organizationPromise,
|
||||
]);
|
||||
|
||||
if (!this.organization) {
|
||||
throw new Error("Organization is not found");
|
||||
}
|
||||
if (!this.paymentSource) {
|
||||
throw new Error("Payment source is not found");
|
||||
}
|
||||
|
||||
this.freeTrialData = this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
||||
this.organization,
|
||||
this.organizationSubscriptionResponse,
|
||||
paymentSource,
|
||||
this.paymentSource,
|
||||
);
|
||||
}
|
||||
// TODO: Eslint upgrade. Please resolve this since the ?? does nothing
|
||||
// eslint-disable-next-line no-constant-binary-expression
|
||||
this.isUnpaid = this.subscriptionStatus === "unpaid" ?? false;
|
||||
// If the flag `launchPaymentModalAutomatically` is set to true,
|
||||
// we schedule a timeout (delay of 800ms) to automatically launch the payment modal.
|
||||
// This delay ensures that any prior UI/rendering operations complete before triggering the modal.
|
||||
@@ -219,14 +227,14 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
const dialogRef = TrialPaymentDialogComponent.open(this.dialogService, {
|
||||
data: {
|
||||
organizationId: this.organizationId,
|
||||
subscription: this.organizationSubscriptionResponse,
|
||||
productTierType: this.organization?.productTierType,
|
||||
subscription: this.organizationSubscriptionResponse!,
|
||||
productTierType: this.organization!.productTierType,
|
||||
},
|
||||
});
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
if (result === TRIAL_PAYMENT_METHOD_DIALOG_RESULT_TYPE.SUBMITTED) {
|
||||
this.location.replaceState(this.location.path(), "", {});
|
||||
if (this.launchPaymentModalAutomatically && !this.organization.enabled) {
|
||||
if (this.launchPaymentModalAutomatically && !this.organization?.enabled) {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
@@ -238,13 +246,14 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
await this.billingApiService.verifyOrganizationBankAccount(this.organizationId, request);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
title: "",
|
||||
message: this.i18nService.t("verifiedBankAccount"),
|
||||
});
|
||||
};
|
||||
|
||||
protected get accountCreditHeaderText(): string {
|
||||
const key = this.accountCredit <= 0 ? "accountBalance" : "accountCredit";
|
||||
const hasAccountCredit = this.accountCredit && this.accountCredit > 0;
|
||||
const key = hasAccountCredit ? "accountCredit" : "accountBalance";
|
||||
return this.i18nService.t(key);
|
||||
}
|
||||
|
||||
@@ -279,7 +288,7 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
|
||||
if (!hasBillingAddress) {
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
title: "",
|
||||
message: this.i18nService.t("billingAddressRequiredToAddCredit"),
|
||||
});
|
||||
return false;
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
import { PaymentComponent } from "../payment/payment.component";
|
||||
|
||||
export interface AdjustPaymentDialogParams {
|
||||
initialPaymentMethod?: PaymentMethodType;
|
||||
initialPaymentMethod?: PaymentMethodType | null;
|
||||
organizationId?: string;
|
||||
productTier?: ProductTierType;
|
||||
providerId?: string;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Location } from "@angular/common";
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||
@@ -42,21 +40,21 @@ import {
|
||||
export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
loading = false;
|
||||
firstLoaded = false;
|
||||
billing: BillingPaymentResponse;
|
||||
org: OrganizationSubscriptionResponse;
|
||||
sub: SubscriptionResponse;
|
||||
billing?: BillingPaymentResponse;
|
||||
org?: OrganizationSubscriptionResponse;
|
||||
sub?: SubscriptionResponse;
|
||||
paymentMethodType = PaymentMethodType;
|
||||
organizationId: string;
|
||||
organizationId?: string;
|
||||
isUnpaid = false;
|
||||
organization: Organization;
|
||||
organization?: Organization;
|
||||
|
||||
verifyBankForm = this.formBuilder.group({
|
||||
amount1: new FormControl<number>(null, [
|
||||
amount1: new FormControl<number>(0, [
|
||||
Validators.required,
|
||||
Validators.max(99),
|
||||
Validators.min(0),
|
||||
]),
|
||||
amount2: new FormControl<number>(null, [
|
||||
amount2: new FormControl<number>(0, [
|
||||
Validators.required,
|
||||
Validators.max(99),
|
||||
Validators.min(0),
|
||||
@@ -64,7 +62,7 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
launchPaymentModalAutomatically = false;
|
||||
protected freeTrialData: FreeTrial;
|
||||
protected freeTrialData?: FreeTrial;
|
||||
|
||||
constructor(
|
||||
protected apiService: ApiService,
|
||||
@@ -84,7 +82,7 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
const state = this.router.getCurrentNavigation()?.extras?.state;
|
||||
// incase the above state is undefined or null we use redundantState
|
||||
// In case the above state is undefined or null, we use redundantState
|
||||
const redundantState: any = location.getState();
|
||||
if (state && Object.prototype.hasOwnProperty.call(state, "launchPaymentModalAutomatically")) {
|
||||
this.launchPaymentModalAutomatically = state.launchPaymentModalAutomatically;
|
||||
@@ -129,17 +127,23 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.loading = true;
|
||||
if (this.forOrganization) {
|
||||
const billingPromise = this.organizationApiService.getBilling(this.organizationId);
|
||||
const billingPromise = this.organizationApiService.getBilling(this.organizationId!);
|
||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||
this.organizationId,
|
||||
this.organizationId!,
|
||||
);
|
||||
|
||||
const userId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
if (!userId) {
|
||||
throw new Error("User ID is not found");
|
||||
}
|
||||
|
||||
const organizationPromise = await firstValueFrom(
|
||||
this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(this.organizationId)),
|
||||
.pipe(getOrganizationById(this.organizationId!)),
|
||||
);
|
||||
|
||||
[this.billing, this.org, this.organization] = await Promise.all([
|
||||
@@ -171,14 +175,16 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
};
|
||||
|
||||
addCredit = async () => {
|
||||
const dialogRef = openAddCreditDialog(this.dialogService, {
|
||||
data: {
|
||||
organizationId: this.organizationId,
|
||||
},
|
||||
});
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
if (result === AddCreditDialogResult.Added) {
|
||||
await this.load();
|
||||
if (this.forOrganization) {
|
||||
const dialogRef = openAddCreditDialog(this.dialogService, {
|
||||
data: {
|
||||
organizationId: this.organizationId!,
|
||||
},
|
||||
});
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
if (result === AddCreditDialogResult.Added) {
|
||||
await this.load();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,7 +200,7 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (result === AdjustPaymentDialogResultType.Submitted) {
|
||||
this.location.replaceState(this.location.path(), "", {});
|
||||
if (this.launchPaymentModalAutomatically && !this.organization.enabled) {
|
||||
if (this.launchPaymentModalAutomatically && !this.organization?.enabled) {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
@@ -208,18 +214,22 @@ export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
const request = new VerifyBankRequest();
|
||||
request.amount1 = this.verifyBankForm.value.amount1;
|
||||
request.amount2 = this.verifyBankForm.value.amount2;
|
||||
await this.organizationApiService.verifyBank(this.organizationId, request);
|
||||
request.amount1 = this.verifyBankForm.value.amount1!;
|
||||
request.amount2 = this.verifyBankForm.value.amount2!;
|
||||
await this.organizationApiService.verifyBank(this.organizationId!, request);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
title: "",
|
||||
message: this.i18nService.t("verifiedBankAccount"),
|
||||
});
|
||||
await this.load();
|
||||
};
|
||||
|
||||
determineOrgsWithUpcomingPaymentIssues() {
|
||||
if (!this.organization || !this.org || !this.billing) {
|
||||
throw new Error("Organization, organization subscription, or billing is not defined");
|
||||
}
|
||||
|
||||
this.freeTrialData = this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
||||
this.organization,
|
||||
this.org,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
bitButton
|
||||
buttonType="primary"
|
||||
[disabled]="orgInfoFormGroup.controls.name.invalid"
|
||||
[loading]="loading && (trialPaymentOptional$ | async)"
|
||||
[loading]="loading && (trialPaymentOptional$ | async)!"
|
||||
(click)="orgNameEntrySubmit()"
|
||||
>
|
||||
{{
|
||||
@@ -55,8 +55,8 @@
|
||||
<app-trial-billing-step
|
||||
*ngIf="stepper.selectedIndex === 2"
|
||||
[organizationInfo]="{
|
||||
name: orgInfoFormGroup.value.name,
|
||||
email: orgInfoFormGroup.value.billingEmail,
|
||||
name: orgInfoFormGroup.value.name!,
|
||||
email: orgInfoFormGroup.value.billingEmail!,
|
||||
type: trialOrganizationType,
|
||||
}"
|
||||
[subscriptionProduct]="
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { StepperSelectionEvent } from "@angular/cdk/stepper";
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
@@ -50,15 +48,15 @@ export type InitiationPath =
|
||||
standalone: false,
|
||||
})
|
||||
export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
@ViewChild("stepper", { static: false }) verticalStepper: VerticalStepperComponent;
|
||||
@ViewChild("stepper", { static: false }) verticalStepper!: VerticalStepperComponent;
|
||||
|
||||
inputPasswordFlow = InputPasswordFlow.SetInitialPasswordAccountRegistration;
|
||||
initializing = true;
|
||||
|
||||
/** Password Manager or Secrets Manager */
|
||||
product: ProductType;
|
||||
product?: ProductType;
|
||||
/** The tier of product being subscribed to */
|
||||
productTier: ProductTierType;
|
||||
productTier!: ProductTierType;
|
||||
/** Product types that display steppers for Password Manager */
|
||||
stepperProductTypes: ProductTierType[] = [
|
||||
ProductTierType.Teams,
|
||||
@@ -79,16 +77,16 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
orgId = "";
|
||||
orgLabel = "";
|
||||
billingSubLabel = "";
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
enforcedPolicyOptions?: MasterPasswordPolicyOptions;
|
||||
|
||||
/** User's email address associated with the trial */
|
||||
email = "";
|
||||
/** Token from the backend associated with the email verification */
|
||||
emailVerificationToken: string;
|
||||
emailVerificationToken?: string;
|
||||
loading = false;
|
||||
productTierValue: number;
|
||||
productTierValue?: ProductTierType;
|
||||
|
||||
trialLength: number;
|
||||
trialLength!: number;
|
||||
|
||||
orgInfoFormGroup = this.formBuilder.group({
|
||||
name: ["", { validators: [Validators.required, Validators.maxLength(50)], updateOn: "change" }],
|
||||
@@ -132,7 +130,7 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
// Show email validation toast when coming from email
|
||||
if (qParams.fromEmail && qParams.fromEmail === "true") {
|
||||
this.toastService.showToast({
|
||||
title: null,
|
||||
title: "",
|
||||
message: this.i18nService.t("emailVerifiedV2"),
|
||||
variant: "success",
|
||||
});
|
||||
@@ -172,9 +170,15 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
const invite = await this.organizationInviteService.getOrganizationInvite();
|
||||
let policies: Policy[] | null = null;
|
||||
let policies: Policy[] | undefined | null = null;
|
||||
|
||||
if (invite != null) {
|
||||
if (
|
||||
invite != null &&
|
||||
invite.organizationId &&
|
||||
invite.token &&
|
||||
invite.email &&
|
||||
invite.organizationUserId
|
||||
) {
|
||||
try {
|
||||
policies = await this.policyApiService.getPoliciesByToken(
|
||||
invite.organizationId,
|
||||
@@ -218,7 +222,7 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
if (event.selectedIndex === 1 && this.orgInfoFormGroup.controls.name.value === "") {
|
||||
this.orgInfoSubLabel = this.planInfoLabel;
|
||||
} else if (event.previouslySelectedIndex === 1) {
|
||||
this.orgInfoSubLabel = this.orgInfoFormGroup.controls.name.value;
|
||||
this.orgInfoSubLabel = this.orgInfoFormGroup.controls.name.value!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,8 +264,11 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
const organization: OrganizationInformation = {
|
||||
name: this.orgInfoFormGroup.value.name,
|
||||
billingEmail: this.orgInfoFormGroup.value.billingEmail,
|
||||
name: this.orgInfoFormGroup.value.name == null ? "" : this.orgInfoFormGroup.value.name,
|
||||
billingEmail:
|
||||
this.orgInfoFormGroup.value.billingEmail == null
|
||||
? ""
|
||||
: this.orgInfoFormGroup.value.billingEmail,
|
||||
initiationPath: trialInitiationPath,
|
||||
};
|
||||
|
||||
@@ -326,7 +333,7 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
get trialOrganizationType(): TrialOrganizationType {
|
||||
get trialOrganizationType(): TrialOrganizationType | null {
|
||||
if (this.productTier === ProductTierType.Free) {
|
||||
return null;
|
||||
}
|
||||
@@ -352,8 +359,12 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
|
||||
const response = await this.organizationBillingService.startFree({
|
||||
organization: {
|
||||
name: this.orgInfoFormGroup.value.name,
|
||||
billingEmail: this.orgInfoFormGroup.value.billingEmail,
|
||||
name: this.orgInfoFormGroup.value.name == null ? "" : this.orgInfoFormGroup.value.name,
|
||||
billingEmail:
|
||||
this.orgInfoFormGroup.value.billingEmail == null
|
||||
? ""
|
||||
: this.orgInfoFormGroup.value.billingEmail,
|
||||
initiationPath: "Password Manager trial from marketing website",
|
||||
},
|
||||
plan: {
|
||||
type: 0,
|
||||
@@ -405,11 +416,11 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy {
|
||||
await this.loginStrategyService.logIn(credentials);
|
||||
}
|
||||
|
||||
finishRegistration(passwordInputResult: PasswordInputResult) {
|
||||
async finishRegistration(passwordInputResult: PasswordInputResult) {
|
||||
this.submitting = true;
|
||||
return this.registrationFinishService
|
||||
.finishRegistration(this.email, passwordInputResult, this.emailVerificationToken)
|
||||
.catch((e) => {
|
||||
.catch((e: unknown): null => {
|
||||
this.validationService.showError(e);
|
||||
this.submitting = false;
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user