mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 08:43:33 +00:00
[PM-8161] Payment optional trial MVP (#10872)
* Initial comment * Add changes for the create org with payment method * Add the secrets manager trail flow * Add the banners * Add changes for the Disabled Org * Add banner to payment method page * Refactoring changes * Resolve the bug on tha payment method * Resolve lint error * Resolve Pr comments * resolve the lint issue * Resolve the lint wrong file issue * Rename object properly * Resolve pr comments from sm team * Resolve the pr comments from sm team * Fix the failing test * Resolve some issue with vault * Resolve the comments from sm team * Resolve some pr comments from vault team * Resolve pr comments from auth team * Exported ValidOrgParams enum * Removed unnecessary interpolation * Corrected bit-banner id for trial * Resolve pr comments from auth team * Resolve pr comments from auth team * Removed unnecessary method * Made OrganizationCreateRequest a subtype of OrganizationNoPaymentMethodCreateRequest * Resolve review changes from sm * Resolve review changes from dm * Resolve the pr comments from billing * move the free-trial to core * Move free-trial change to right file * Revert changes on the free trial page * Resolve the comment on protected trial page * Resolve the comment on protected trial page * Revert the next async change * resolve pr comment fro vault team * resolve the default message comments * remove unused method * resolve email sending issue * Fix the pop issue on payment method * Fix some console errors * Fix the pop refresh page * move the trial services to billing folder * resolve pr comments * Resolve the import issues * Move the observable up * Resolve blank payment method for trialing org * Changes to disable icon is removed onsubmit * Remove unused references * add a missing a period at the end of it * resolve the reload issue * Resolve the disable icon issue * Fix the admin access bug * Resolve the lint issue * Fix the message incorrect format * Formatting fixed * Resolve the access issue of other users role
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import { Component, OnInit, ViewChild } from "@angular/core";
|
||||
import { Location } from "@angular/common";
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { lastValueFrom } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { BillingPaymentResponse } from "@bitwarden/common/billing/models/response/billing-payment.response";
|
||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||
@@ -13,8 +16,12 @@ import { VerifyBankRequest } from "@bitwarden/common/models/request/verify-bank.
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { FreeTrial } from "../../core/types/free-trial";
|
||||
import { TrialFlowService } from "../services/trial-flow.service";
|
||||
|
||||
import { AddCreditDialogResult, openAddCreditDialog } from "./add-credit-dialog.component";
|
||||
import {
|
||||
AdjustPaymentDialogResult,
|
||||
@@ -26,7 +33,7 @@ import { TaxInfoComponent } from "./tax-info.component";
|
||||
templateUrl: "payment-method.component.html",
|
||||
})
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class PaymentMethodComponent implements OnInit {
|
||||
export class PaymentMethodComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(TaxInfoComponent) taxInfo: TaxInfoComponent;
|
||||
|
||||
loading = false;
|
||||
@@ -37,6 +44,7 @@ export class PaymentMethodComponent implements OnInit {
|
||||
paymentMethodType = PaymentMethodType;
|
||||
organizationId: string;
|
||||
isUnpaid = false;
|
||||
organization: Organization;
|
||||
|
||||
verifyBankForm = this.formBuilder.group({
|
||||
amount1: new FormControl<number>(null, [
|
||||
@@ -52,6 +60,8 @@ export class PaymentMethodComponent implements OnInit {
|
||||
});
|
||||
|
||||
taxForm = this.formBuilder.group({});
|
||||
launchPaymentModalAutomatically = false;
|
||||
protected freeTrialData: FreeTrial;
|
||||
|
||||
constructor(
|
||||
protected apiService: ApiService,
|
||||
@@ -59,12 +69,30 @@ export class PaymentMethodComponent implements OnInit {
|
||||
protected i18nService: I18nService,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
private router: Router,
|
||||
private location: Location,
|
||||
private logService: LogService,
|
||||
private route: ActivatedRoute,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
private trialFlowService: TrialFlowService,
|
||||
private organizationService: OrganizationService,
|
||||
protected syncService: SyncService,
|
||||
) {
|
||||
const state = this.router.getCurrentNavigation()?.extras?.state;
|
||||
// incase 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;
|
||||
} else if (
|
||||
redundantState &&
|
||||
Object.prototype.hasOwnProperty.call(redundantState, "launchPaymentModalAutomatically")
|
||||
) {
|
||||
this.launchPaymentModalAutomatically = redundantState.launchPaymentModalAutomatically;
|
||||
} else {
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
}
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
@@ -88,27 +116,37 @@ export class PaymentMethodComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
|
||||
if (this.forOrganization) {
|
||||
const billingPromise = this.organizationApiService.getBilling(this.organizationId);
|
||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||
this.organizationId,
|
||||
);
|
||||
const organizationPromise = this.organizationService.get(this.organizationId);
|
||||
|
||||
[this.billing, this.org] = await Promise.all([
|
||||
[this.billing, this.org, this.organization] = await Promise.all([
|
||||
billingPromise,
|
||||
organizationSubscriptionPromise,
|
||||
organizationPromise,
|
||||
]);
|
||||
this.determineOrgsWithUpcomingPaymentIssues();
|
||||
} else {
|
||||
const billingPromise = this.apiService.getUserBillingPayment();
|
||||
const subPromise = this.apiService.getUserSubscription();
|
||||
|
||||
[this.billing, this.sub] = await Promise.all([billingPromise, subPromise]);
|
||||
}
|
||||
|
||||
this.isUnpaid = this.subscription?.status === "unpaid" ?? false;
|
||||
|
||||
this.loading = 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.
|
||||
if (this.launchPaymentModalAutomatically) {
|
||||
window.setTimeout(async () => {
|
||||
await this.changePayment();
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
this.location.replaceState(this.location.path(), "", {});
|
||||
}, 800);
|
||||
}
|
||||
};
|
||||
|
||||
addCredit = async () => {
|
||||
@@ -132,6 +170,11 @@ export class PaymentMethodComponent implements OnInit {
|
||||
});
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
if (result === AdjustPaymentDialogResult.Adjusted) {
|
||||
this.location.replaceState(this.location.path(), "", {});
|
||||
if (this.launchPaymentModalAutomatically && !this.organization.enabled) {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
await this.load();
|
||||
}
|
||||
};
|
||||
@@ -162,6 +205,14 @@ export class PaymentMethodComponent implements OnInit {
|
||||
});
|
||||
};
|
||||
|
||||
determineOrgsWithUpcomingPaymentIssues() {
|
||||
this.freeTrialData = this.trialFlowService.checkForOrgsWithUpcomingPaymentIssues(
|
||||
this.organization,
|
||||
this.org,
|
||||
this.billing?.paymentSource,
|
||||
);
|
||||
}
|
||||
|
||||
get isCreditBalance() {
|
||||
return this.billing == null || this.billing.balance <= 0;
|
||||
}
|
||||
@@ -203,4 +254,8 @@ export class PaymentMethodComponent implements OnInit {
|
||||
get subscription() {
|
||||
return this.sub?.subscription ?? this.org?.subscription ?? null;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.launchPaymentModalAutomatically = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user