move premium banner to a standalone observable
This commit is contained in:
parent
5bc5649297
commit
93463d47e5
|
@ -74,7 +74,7 @@ describe("VaultBannersService", () => {
|
|||
|
||||
service = TestBed.inject(VaultBannersService);
|
||||
|
||||
expect(await service.shouldShowPremiumBanner()).toBe(true);
|
||||
expect(await firstValueFrom(service.shouldShowPremiumBanner())).toBe(true);
|
||||
});
|
||||
|
||||
describe("dismissing", () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Injectable } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { Observable, combineLatest, firstValueFrom, map } from "rxjs";
|
||||
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
|
@ -99,24 +99,25 @@ export class VaultBannersService {
|
|||
}
|
||||
|
||||
/** Returns true when the premium banner should be shown */
|
||||
async shouldShowPremiumBanner(): Promise<boolean> {
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
shouldShowPremiumBanner(): Observable<boolean> {
|
||||
return combineLatest([
|
||||
this.billingAccountProfileStateService.hasPremiumFromAnySource$,
|
||||
this.premiumBannerState.state$,
|
||||
]).pipe(
|
||||
map(([canAccessPremium, dismissedState]) => {
|
||||
const shouldShowPremiumBanner =
|
||||
!canAccessPremium && !this.platformUtilsService.isSelfHost();
|
||||
|
||||
// Check if nextPromptDate is in the past passed
|
||||
if (shouldShowPremiumBanner && dismissedState?.nextPromptDate) {
|
||||
const nextPromptDate = new Date(dismissedState.nextPromptDate);
|
||||
const now = new Date();
|
||||
return now >= nextPromptDate;
|
||||
}
|
||||
|
||||
return shouldShowPremiumBanner;
|
||||
}),
|
||||
);
|
||||
|
||||
const shouldShowPremiumBanner = !canAccessPremium && !this.platformUtilsService.isSelfHost();
|
||||
|
||||
const dismissedState = await firstValueFrom(this.premiumBannerState.state$);
|
||||
|
||||
// Check if nextPromptDate is in the past passed
|
||||
if (shouldShowPremiumBanner && dismissedState?.nextPromptDate) {
|
||||
const nextPromptDate = new Date(dismissedState.nextPromptDate);
|
||||
const now = new Date();
|
||||
|
||||
return now >= nextPromptDate;
|
||||
}
|
||||
|
||||
return shouldShowPremiumBanner;
|
||||
}
|
||||
|
||||
/** Dismiss the given banner and perform any respective side effects */
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<bit-banner
|
||||
class="-tw-m-6 tw-flex tw-flex-col tw-pb-6"
|
||||
bannerType="premium"
|
||||
*ngIf="visibleBanners.includes(VisibleVaultBanner.Premium)"
|
||||
*ngIf="premiumBannerVisible$ | async"
|
||||
(onClose)="dismissBanner(VisibleVaultBanner.Premium)"
|
||||
>
|
||||
{{ "premiumUpgradeUnlockFeatures" | i18n }}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { BannerModule } from "@bitwarden/components";
|
||||
import { BannerComponent, BannerModule } from "@bitwarden/components";
|
||||
|
||||
import { LooseComponentsModule } from "../../../shared";
|
||||
|
||||
|
@ -16,6 +18,7 @@ import { VaultBannersComponent } from "./vault-banners.component";
|
|||
describe("VaultBannersComponent", () => {
|
||||
let component: VaultBannersComponent;
|
||||
let fixture: ComponentFixture<VaultBannersComponent>;
|
||||
const premiumBanner$ = new BehaviorSubject<boolean>(false);
|
||||
|
||||
const bannerService = mock<VaultBannersService>({
|
||||
shouldShowPremiumBanner: jest.fn(),
|
||||
|
@ -26,7 +29,7 @@ describe("VaultBannersComponent", () => {
|
|||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
bannerService.shouldShowPremiumBanner.mockResolvedValue(false);
|
||||
bannerService.shouldShowPremiumBanner.mockReturnValue(premiumBanner$);
|
||||
bannerService.shouldShowUpdateBrowserBanner.mockResolvedValue(false);
|
||||
bannerService.shouldShowVerifyEmailBanner.mockResolvedValue(false);
|
||||
bannerService.shouldShowLowKDFBanner.mockResolvedValue(false);
|
||||
|
@ -66,13 +69,28 @@ describe("VaultBannersComponent", () => {
|
|||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
describe("premiumBannerVisible$", () => {
|
||||
it("shows premium banner", async () => {
|
||||
premiumBanner$.next(true);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const banner = fixture.debugElement.query(By.directive(BannerComponent));
|
||||
expect(banner.componentInstance.bannerType).toBe("premium");
|
||||
});
|
||||
|
||||
it("dismisses premium banner", async () => {
|
||||
premiumBanner$.next(false);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const banner = fixture.debugElement.query(By.directive(BannerComponent));
|
||||
expect(banner).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("determineVisibleBanner", () => {
|
||||
[
|
||||
{
|
||||
name: "Premium",
|
||||
method: bannerService.shouldShowPremiumBanner,
|
||||
banner: VisibleVaultBanner.Premium,
|
||||
},
|
||||
{
|
||||
name: "OutdatedBrowser",
|
||||
method: bannerService.shouldShowUpdateBrowserBanner,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Component, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { VaultBannersService, VisibleVaultBanner } from "./services/vault-banners.service";
|
||||
|
||||
|
@ -8,9 +9,12 @@ import { VaultBannersService, VisibleVaultBanner } from "./services/vault-banner
|
|||
})
|
||||
export class VaultBannersComponent implements OnInit {
|
||||
visibleBanners: VisibleVaultBanner[] = [];
|
||||
premiumBannerVisible$: Observable<boolean>;
|
||||
VisibleVaultBanner = VisibleVaultBanner;
|
||||
|
||||
constructor(private vaultBannerService: VaultBannersService) {}
|
||||
constructor(private vaultBannerService: VaultBannersService) {
|
||||
this.premiumBannerVisible$ = this.vaultBannerService.shouldShowPremiumBanner();
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.determineVisibleBanners();
|
||||
|
@ -27,13 +31,11 @@ export class VaultBannersComponent implements OnInit {
|
|||
const showBrowserOutdated = await this.vaultBannerService.shouldShowUpdateBrowserBanner();
|
||||
const showVerifyEmail = await this.vaultBannerService.shouldShowVerifyEmailBanner();
|
||||
const showLowKdf = await this.vaultBannerService.shouldShowLowKDFBanner();
|
||||
const showPremiumBanner = await this.vaultBannerService.shouldShowPremiumBanner();
|
||||
|
||||
this.visibleBanners = [
|
||||
showBrowserOutdated ? VisibleVaultBanner.OutdatedBrowser : null,
|
||||
showVerifyEmail ? VisibleVaultBanner.VerifyEmail : null,
|
||||
showLowKdf ? VisibleVaultBanner.KDFSettings : null,
|
||||
showPremiumBanner ? VisibleVaultBanner.Premium : null,
|
||||
].filter(Boolean); // remove all falsy values, i.e. null
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue