1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-22 19:23:52 +00:00

[AC-1607] Add offboarding survey to subscription pages (#7809)

* Add offboarding survey to subscription pages

* Cleaning up unused code

* Removing unused eslint suppression

* Product updates

* Jared's feedback
This commit is contained in:
Alex Morask
2024-02-09 12:08:46 -05:00
committed by GitHub
parent 64381cbae0
commit b239e3736f
12 changed files with 358 additions and 43 deletions

View File

@@ -1,8 +1,11 @@
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { lastValueFrom, Observable } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SubscriptionResponse } from "@bitwarden/common/billing/models/response/subscription.response";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction as ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -11,6 +14,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DialogService } from "@bitwarden/components";
import {
OffboardingSurveyDialogResultType,
openOffboardingSurvey,
} from "../shared/offboarding-survey.component";
@Component({
templateUrl: "user-subscription.component.html",
})
@@ -26,6 +34,7 @@ export class UserSubscriptionComponent implements OnInit {
cancelPromise: Promise<any>;
reinstatePromise: Promise<any>;
presentUserWithOffboardingSurvey$: Observable<boolean>;
constructor(
private stateService: StateService,
@@ -37,12 +46,16 @@ export class UserSubscriptionComponent implements OnInit {
private fileDownloadService: FileDownloadService,
private dialogService: DialogService,
private environmentService: EnvironmentService,
private configService: ConfigService,
) {
this.selfHosted = platformUtilsService.isSelfHost();
this.cloudWebVaultUrl = this.environmentService.getCloudWebVaultUrl();
}
async ngOnInit() {
this.presentUserWithOffboardingSurvey$ = this.configService.getFeatureFlag$<boolean>(
FeatureFlag.AC1607_PresentUserOffboardingSurvey,
);
await this.load();
this.firstLoaded = true;
}
@@ -93,36 +106,17 @@ export class UserSubscriptionComponent implements OnInit {
}
}
async cancel() {
if (this.loading) {
return;
}
cancel = async () => {
const presentUserWithOffboardingSurvey = await this.configService.getFeatureFlag<boolean>(
FeatureFlag.AC1607_PresentUserOffboardingSurvey,
);
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "cancelSubscription" },
content: { key: "cancelConfirmation" },
type: "warning",
});
if (!confirmed) {
return;
if (presentUserWithOffboardingSurvey) {
await this.cancelWithOffboardingSurvey();
} else {
await this.cancelWithWarning();
}
try {
this.cancelPromise = this.apiService.postCancelPremium();
await this.cancelPromise;
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("canceledSubscription"),
);
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.load();
} catch (e) {
this.logService.error(e);
}
}
};
downloadLicense() {
if (this.loading) {
@@ -166,6 +160,55 @@ export class UserSubscriptionComponent implements OnInit {
}
}
private cancelWithOffboardingSurvey = async () => {
const reference = openOffboardingSurvey(this.dialogService, {
data: {
type: "User",
},
});
this.cancelPromise = lastValueFrom(reference.closed);
const result = await this.cancelPromise;
if (result === OffboardingSurveyDialogResultType.Closed) {
return;
}
await this.load();
};
private async cancelWithWarning() {
if (this.loading) {
return;
}
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "cancelSubscription" },
content: { key: "cancelConfirmation" },
type: "warning",
});
if (!confirmed) {
return;
}
try {
this.cancelPromise = this.apiService.postCancelPremium();
await this.cancelPromise;
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("canceledSubscription"),
);
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.load();
} catch (e) {
this.logService.error(e);
}
}
get subscriptionMarkedForCancel() {
return (
this.subscription != null && !this.subscription.cancelled && this.subscription.cancelAtEndDate