mirror of
https://github.com/bitwarden/browser
synced 2025-12-13 06:43:35 +00:00
[AC-2520] Remove Unassigned Items Banner (#10042)
* chore: remove UnassignedItemsBanner feature flag, refs AC-2520 * chore: remove unassignedItemsBanner from web-header component, refs AC-2520 * chore: delete unassigned items banner service/api/spec, refs AC-2520 * chore: remove unassigned items banner messages (web), refs AC-2520 * chore: remove unassigned items banner messages (browser), refs AC-2520 * chore: remove unassigned items banner code from current tab (browser), refs AC-2520 * chore: remove state definition for unassigned items banner, refs AC-2520 * chore: revert state-definition removal, refs AC-2520
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
|
||||
@Injectable({ providedIn: "root" })
|
||||
export class UnassignedItemsBannerApiService {
|
||||
constructor(private apiService: ApiService) {}
|
||||
|
||||
async getShowUnassignedCiphersBanner(): Promise<boolean> {
|
||||
const r = await this.apiService.send(
|
||||
"GET",
|
||||
"/ciphers/has-unassigned-ciphers",
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { FakeStateProvider, mockAccountServiceWith } from "@bitwarden/common/spec";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { UnassignedItemsBannerApiService } from "./unassigned-items-banner.api.service";
|
||||
import { SHOW_BANNER_KEY, UnassignedItemsBannerService } from "./unassigned-items-banner.service";
|
||||
|
||||
describe("UnassignedItemsBanner", () => {
|
||||
let stateProvider: FakeStateProvider;
|
||||
let apiService: MockProxy<UnassignedItemsBannerApiService>;
|
||||
let environmentService: MockProxy<EnvironmentService>;
|
||||
let organizationService: MockProxy<OrganizationService>;
|
||||
|
||||
const sutFactory = () =>
|
||||
new UnassignedItemsBannerService(
|
||||
stateProvider,
|
||||
apiService,
|
||||
environmentService,
|
||||
organizationService,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
const fakeAccountService = mockAccountServiceWith("userId" as UserId);
|
||||
stateProvider = new FakeStateProvider(fakeAccountService);
|
||||
apiService = mock();
|
||||
environmentService = mock();
|
||||
environmentService.environment$ = of(null);
|
||||
organizationService = mock();
|
||||
organizationService.organizations$ = of([]);
|
||||
});
|
||||
|
||||
it("shows the banner if showBanner local state is true", async () => {
|
||||
const showBanner = stateProvider.activeUser.getFake(SHOW_BANNER_KEY);
|
||||
showBanner.nextState(true);
|
||||
|
||||
const sut = sutFactory();
|
||||
expect(await firstValueFrom(sut.showBanner$)).toBe(true);
|
||||
expect(apiService.getShowUnassignedCiphersBanner).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not show the banner if showBanner local state is false", async () => {
|
||||
const showBanner = stateProvider.activeUser.getFake(SHOW_BANNER_KEY);
|
||||
showBanner.nextState(false);
|
||||
|
||||
const sut = sutFactory();
|
||||
expect(await firstValueFrom(sut.showBanner$)).toBe(false);
|
||||
expect(apiService.getShowUnassignedCiphersBanner).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fetches from server if local state has not been set yet", async () => {
|
||||
apiService.getShowUnassignedCiphersBanner.mockResolvedValue(true);
|
||||
|
||||
const showBanner = stateProvider.activeUser.getFake(SHOW_BANNER_KEY);
|
||||
showBanner.nextState(undefined);
|
||||
|
||||
const sut = sutFactory();
|
||||
|
||||
expect(await firstValueFrom(sut.showBanner$)).toBe(true);
|
||||
expect(apiService.getShowUnassignedCiphersBanner).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -1,87 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { combineLatest, concatMap, map, startWith } from "rxjs";
|
||||
|
||||
import {
|
||||
OrganizationService,
|
||||
canAccessOrgAdmin,
|
||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
EnvironmentService,
|
||||
Region,
|
||||
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import {
|
||||
StateProvider,
|
||||
UNASSIGNED_ITEMS_BANNER_DISK,
|
||||
UserKeyDefinition,
|
||||
} from "@bitwarden/common/platform/state";
|
||||
|
||||
import { UnassignedItemsBannerApiService } from "./unassigned-items-banner.api.service";
|
||||
|
||||
export const SHOW_BANNER_KEY = new UserKeyDefinition<boolean>(
|
||||
UNASSIGNED_ITEMS_BANNER_DISK,
|
||||
"showBanner",
|
||||
{
|
||||
deserializer: (b) => b,
|
||||
clearOn: [],
|
||||
},
|
||||
);
|
||||
|
||||
/** Displays a banner that tells users how to move their unassigned items into a collection. */
|
||||
@Injectable({ providedIn: "root" })
|
||||
export class UnassignedItemsBannerService {
|
||||
private _showBanner = this.stateProvider.getActive(SHOW_BANNER_KEY);
|
||||
|
||||
showBanner$ = this._showBanner.state$.pipe(
|
||||
concatMap(async (showBannerState) => {
|
||||
// null indicates that the user has not seen or dismissed the banner yet - get the flag from server
|
||||
if (showBannerState == null) {
|
||||
const showBannerResponse = await this.apiService.getShowUnassignedCiphersBanner();
|
||||
await this._showBanner.update(() => showBannerResponse);
|
||||
return showBannerResponse;
|
||||
}
|
||||
|
||||
return showBannerState;
|
||||
}),
|
||||
);
|
||||
|
||||
private adminConsoleOrg$ = this.organizationService.organizations$.pipe(
|
||||
map((orgs) => orgs.find((o) => canAccessOrgAdmin(o))),
|
||||
);
|
||||
|
||||
adminConsoleUrl$ = combineLatest([
|
||||
this.adminConsoleOrg$,
|
||||
this.environmentService.environment$,
|
||||
]).pipe(
|
||||
map(([org, environment]) => {
|
||||
if (org == null || environment == null) {
|
||||
return "#";
|
||||
}
|
||||
|
||||
return environment.getWebVaultUrl() + "/#/organizations/" + org.id;
|
||||
}),
|
||||
);
|
||||
|
||||
bannerText$ = this.environmentService.environment$.pipe(
|
||||
map((e) =>
|
||||
e?.getRegion() == Region.SelfHosted
|
||||
? "unassignedItemsBannerSelfHostNotice"
|
||||
: "unassignedItemsBannerNotice",
|
||||
),
|
||||
);
|
||||
|
||||
loading$ = combineLatest([this.adminConsoleUrl$, this.bannerText$]).pipe(
|
||||
startWith(true),
|
||||
map(() => false),
|
||||
);
|
||||
|
||||
constructor(
|
||||
private stateProvider: StateProvider,
|
||||
private apiService: UnassignedItemsBannerApiService,
|
||||
private environmentService: EnvironmentService,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
async hideBanner() {
|
||||
await this._showBanner.update(() => false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user