From 6d98360b04d036104f299804ae1d0cd727ff7696 Mon Sep 17 00:00:00 2001
From: Nick Krantz <125900171+nick-livefront@users.noreply.github.com>
Date: Mon, 6 Oct 2025 11:42:21 -0500
Subject: [PATCH] remove unused view component (#16582)
---
.../organizations/collections/vault.module.ts | 2 -
.../vault/individual-vault/vault.module.ts | 2 -
.../individual-vault/view.component.html | 31 ---
.../individual-vault/view.component.spec.ts | 148 ------------
.../vault/individual-vault/view.component.ts | 218 ------------------
5 files changed, 401 deletions(-)
delete mode 100644 apps/web/src/app/vault/individual-vault/view.component.html
delete mode 100644 apps/web/src/app/vault/individual-vault/view.component.spec.ts
delete mode 100644 apps/web/src/app/vault/individual-vault/view.component.ts
diff --git a/apps/web/src/app/admin-console/organizations/collections/vault.module.ts b/apps/web/src/app/admin-console/organizations/collections/vault.module.ts
index 1a093ff835..d7c6a468eb 100644
--- a/apps/web/src/app/admin-console/organizations/collections/vault.module.ts
+++ b/apps/web/src/app/admin-console/organizations/collections/vault.module.ts
@@ -2,7 +2,6 @@ import { NgModule } from "@angular/core";
import { SharedModule } from "../../../shared/shared.module";
import { OrganizationBadgeModule } from "../../../vault/individual-vault/organization-badge/organization-badge.module";
-import { ViewComponent } from "../../../vault/individual-vault/view.component";
import { CollectionDialogComponent } from "../shared/components/collection-dialog";
import { CollectionNameBadgeComponent } from "./collection-badge";
@@ -19,7 +18,6 @@ import { VaultComponent } from "./vault.component";
OrganizationBadgeModule,
CollectionDialogComponent,
VaultComponent,
- ViewComponent,
],
})
export class VaultModule {}
diff --git a/apps/web/src/app/vault/individual-vault/vault.module.ts b/apps/web/src/app/vault/individual-vault/vault.module.ts
index 573eceef64..156e73b439 100644
--- a/apps/web/src/app/vault/individual-vault/vault.module.ts
+++ b/apps/web/src/app/vault/individual-vault/vault.module.ts
@@ -10,7 +10,6 @@ import { OrganizationBadgeModule } from "./organization-badge/organization-badge
import { PipesModule } from "./pipes/pipes.module";
import { VaultRoutingModule } from "./vault-routing.module";
import { VaultComponent } from "./vault.component";
-import { ViewComponent } from "./view.component";
@NgModule({
imports: [
@@ -23,7 +22,6 @@ import { ViewComponent } from "./view.component";
BulkDialogsModule,
CollectionDialogComponent,
VaultComponent,
- ViewComponent,
],
})
export class VaultModule {}
diff --git a/apps/web/src/app/vault/individual-vault/view.component.html b/apps/web/src/app/vault/individual-vault/view.component.html
deleted file mode 100644
index ac6db21236..0000000000
--- a/apps/web/src/app/vault/individual-vault/view.component.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- {{ cipherTypeString }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/web/src/app/vault/individual-vault/view.component.spec.ts b/apps/web/src/app/vault/individual-vault/view.component.spec.ts
deleted file mode 100644
index d60a6313c6..0000000000
--- a/apps/web/src/app/vault/individual-vault/view.component.spec.ts
+++ /dev/null
@@ -1,148 +0,0 @@
-import { ComponentFixture, TestBed } from "@angular/core/testing";
-import { mock } from "jest-mock-extended";
-import { of } from "rxjs";
-
-import { CollectionService } from "@bitwarden/admin-console/common";
-import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
-import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
-import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
-import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
-import { Utils } from "@bitwarden/common/platform/misc/utils";
-import { FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec";
-import { UserId } from "@bitwarden/common/types/guid";
-import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
-import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
-import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
-import { CipherAuthorizationService } from "@bitwarden/common/vault/services/cipher-authorization.service";
-import { TaskService } from "@bitwarden/common/vault/tasks";
-import { DIALOG_DATA, DialogRef, DialogService, ToastService } from "@bitwarden/components";
-import { KeyService } from "@bitwarden/key-management";
-import { ChangeLoginPasswordService } from "@bitwarden/vault";
-
-import { ViewCipherDialogParams, ViewCipherDialogResult, ViewComponent } from "./view.component";
-
-describe("ViewComponent", () => {
- let component: ViewComponent;
- let fixture: ComponentFixture;
-
- const mockCipher: CipherView = {
- id: "cipher-id",
- type: 1,
- organizationId: "org-id",
- isDeleted: false,
- } as CipherView;
-
- const mockOrganization: Organization = {
- id: "org-id",
- name: "Test Organization",
- } as Organization;
-
- const mockParams: ViewCipherDialogParams = {
- cipher: mockCipher,
- };
- const userId = Utils.newGuid() as UserId;
- const accountService: FakeAccountService = mockAccountServiceWith(userId);
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- imports: [ViewComponent],
- providers: [
- { provide: DIALOG_DATA, useValue: mockParams },
- { provide: DialogRef, useValue: mock() },
- { provide: I18nService, useValue: { t: jest.fn().mockReturnValue("login") } },
- { provide: DialogService, useValue: mock() },
- { provide: CipherService, useValue: mock() },
- { provide: ToastService, useValue: mock() },
- { provide: MessagingService, useValue: mock() },
- {
- provide: AccountService,
- useValue: accountService,
- },
- { provide: LogService, useValue: mock() },
- {
- provide: OrganizationService,
- useValue: { organizations$: jest.fn().mockReturnValue(of([mockOrganization])) },
- },
- { provide: CollectionService, useValue: mock() },
- { provide: FolderService, useValue: mock() },
- { provide: KeyService, useValue: mock() },
- {
- provide: BillingAccountProfileStateService,
- useValue: mock(),
- },
- { provide: ConfigService, useValue: mock() },
- { provide: AccountService, useValue: mockAccountServiceWith("UserId" as UserId) },
- {
- provide: CipherAuthorizationService,
- useValue: {
- canDeleteCipher$: jest.fn().mockReturnValue(true),
- },
- },
- { provide: TaskService, useValue: mock() },
- ],
- })
- .overrideComponent(ViewComponent, {
- remove: {
- providers: [
- { provide: PlatformUtilsService, useValue: PlatformUtilsService },
- {
- provide: ChangeLoginPasswordService,
- useValue: ChangeLoginPasswordService,
- },
- ],
- },
- add: {
- providers: [
- { provide: PlatformUtilsService, useValue: mock() },
- {
- provide: ChangeLoginPasswordService,
- useValue: mock(),
- },
- ],
- },
- })
- .compileComponents();
-
- fixture = TestBed.createComponent(ViewComponent);
- component = fixture.componentInstance;
- component.params = mockParams;
- component.cipher = mockCipher;
- });
-
- describe("ngOnInit", () => {
- it("initializes the component with cipher and organization", async () => {
- await component.ngOnInit();
-
- expect(component.cipher).toEqual(mockCipher);
- expect(component.organization).toEqual(mockOrganization);
- });
- });
-
- describe("edit", () => {
- it("closes the dialog with the proper arguments", async () => {
- const dialogRefCloseSpy = jest.spyOn(component["dialogRef"], "close");
-
- await component.edit();
-
- expect(dialogRefCloseSpy).toHaveBeenCalledWith({ action: ViewCipherDialogResult.Edited });
- });
- });
-
- describe("delete", () => {
- it("calls the delete method on delete and closes the dialog with the proper arguments", async () => {
- const deleteSpy = jest.spyOn(component, "delete");
- const dialogRefCloseSpy = jest.spyOn(component["dialogRef"], "close");
- jest.spyOn(component["dialogService"], "openSimpleDialog").mockResolvedValue(true);
-
- await component.delete();
-
- expect(deleteSpy).toHaveBeenCalled();
- expect(dialogRefCloseSpy).toHaveBeenCalledWith({ action: ViewCipherDialogResult.Deleted });
- });
- });
-});
diff --git a/apps/web/src/app/vault/individual-vault/view.component.ts b/apps/web/src/app/vault/individual-vault/view.component.ts
deleted file mode 100644
index 6de29f8e32..0000000000
--- a/apps/web/src/app/vault/individual-vault/view.component.ts
+++ /dev/null
@@ -1,218 +0,0 @@
-// FIXME: Update this file to be type safe and remove this and next line
-// @ts-strict-ignore
-import { CommonModule } from "@angular/common";
-import { Component, EventEmitter, Inject, OnInit } from "@angular/core";
-import { firstValueFrom, map, Observable } from "rxjs";
-
-import { CollectionView } from "@bitwarden/admin-console/common";
-import { VaultViewPasswordHistoryService } from "@bitwarden/angular/services/view-password-history.service";
-import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
-import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
-import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
-import { getUserId } from "@bitwarden/common/auth/services/account.service";
-import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
-import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
-import { CollectionId } from "@bitwarden/common/types/guid";
-import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
-import { ViewPasswordHistoryService } from "@bitwarden/common/vault/abstractions/view-password-history.service";
-import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
-import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
-import { CipherAuthorizationService } from "@bitwarden/common/vault/services/cipher-authorization.service";
-import { UnionOfValues } from "@bitwarden/common/vault/types/union-of-values";
-import {
- DIALOG_DATA,
- DialogRef,
- DialogConfig,
- AsyncActionsModule,
- DialogModule,
- DialogService,
- ToastService,
-} from "@bitwarden/components";
-import { CipherViewComponent } from "@bitwarden/vault";
-
-import { SharedModule } from "../../shared/shared.module";
-
-export interface ViewCipherDialogParams {
- cipher: CipherView;
-
- /**
- * Optional list of collections the cipher is assigned to. If none are provided, they will be loaded using the
- * `CipherService` and the `collectionIds` property of the cipher.
- */
- collections?: CollectionView[];
-
- /**
- * Optional collection ID used to know the collection filter selected.
- */
- activeCollectionId?: CollectionId;
-
- /**
- * If true, the edit button will be disabled in the dialog.
- */
- disableEdit?: boolean;
-}
-
-export const ViewCipherDialogResult = {
- Edited: "edited",
- Deleted: "deleted",
- PremiumUpgrade: "premiumUpgrade",
-} as const;
-
-type ViewCipherDialogResult = UnionOfValues;
-
-export interface ViewCipherDialogCloseResult {
- action: ViewCipherDialogResult;
-}
-
-/**
- * Component for viewing a cipher, presented in a dialog.
- * @deprecated Use the VaultItemDialogComponent instead.
- */
-@Component({
- selector: "app-vault-view",
- templateUrl: "view.component.html",
- imports: [CipherViewComponent, CommonModule, AsyncActionsModule, DialogModule, SharedModule],
- providers: [{ provide: ViewPasswordHistoryService, useClass: VaultViewPasswordHistoryService }],
-})
-export class ViewComponent implements OnInit {
- cipher: CipherView;
- collections?: CollectionView[];
- onDeletedCipher = new EventEmitter();
- cipherTypeString: string;
- organization: Organization;
-
- canDeleteCipher$: Observable;
-
- constructor(
- @Inject(DIALOG_DATA) public params: ViewCipherDialogParams,
- private dialogRef: DialogRef,
- private i18nService: I18nService,
- private dialogService: DialogService,
- private messagingService: MessagingService,
- private logService: LogService,
- private cipherService: CipherService,
- private toastService: ToastService,
- private organizationService: OrganizationService,
- private cipherAuthorizationService: CipherAuthorizationService,
- private accountService: AccountService,
- ) {}
-
- /**
- * Lifecycle hook for component initialization.
- */
- async ngOnInit() {
- this.cipher = this.params.cipher;
- this.collections = this.params.collections;
- this.cipherTypeString = this.getCipherViewTypeString();
-
- const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
-
- if (this.cipher.organizationId) {
- this.organization = await firstValueFrom(
- this.organizationService
- .organizations$(userId)
- .pipe(
- map((organizations) => organizations.find((o) => o.id === this.cipher.organizationId)),
- ),
- );
- }
-
- this.canDeleteCipher$ = this.cipherAuthorizationService.canDeleteCipher$(this.cipher);
- }
-
- /**
- * Method to handle cipher deletion. Called when a user clicks the delete button.
- */
- delete = async () => {
- const confirmed = await this.dialogService.openSimpleDialog({
- title: { key: "deleteItem" },
- content: {
- key: this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation",
- },
- type: "warning",
- });
-
- if (!confirmed) {
- return;
- }
-
- try {
- await this.deleteCipher();
- this.toastService.showToast({
- variant: "success",
- title: this.i18nService.t("success"),
- message: this.i18nService.t(
- this.cipher.isDeleted ? "permanentlyDeletedItem" : "deletedItem",
- ),
- });
- this.onDeletedCipher.emit(this.cipher);
- this.messagingService.send(
- this.cipher.isDeleted ? "permanentlyDeletedCipher" : "deletedCipher",
- );
- } catch (e) {
- this.logService.error(e);
- }
-
- this.dialogRef.close({ action: ViewCipherDialogResult.Deleted });
- };
-
- /**
- * Helper method to delete cipher.
- */
- protected async deleteCipher(): Promise {
- const asAdmin = this.organization?.canEditAllCiphers;
- const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
- if (this.cipher.isDeleted) {
- await this.cipherService.deleteWithServer(this.cipher.id, userId, asAdmin);
- } else {
- await this.cipherService.softDeleteWithServer(this.cipher.id, userId, asAdmin);
- }
- }
-
- /**
- * Method to handle cipher editing. Called when a user clicks the edit button.
- */
- async edit(): Promise {
- this.dialogRef.close({ action: ViewCipherDialogResult.Edited });
- }
-
- /**
- * Method to get cipher view type string, used for the dialog title.
- * E.g. "View login" or "View note".
- * @returns The localized string for the cipher type
- */
- getCipherViewTypeString(): string {
- if (!this.cipher) {
- return null;
- }
-
- switch (this.cipher.type) {
- case CipherType.Login:
- return this.i18nService.t("viewItemHeaderLogin");
- case CipherType.SecureNote:
- return this.i18nService.t("viewItemHeaderCard");
- case CipherType.Card:
- return this.i18nService.t("viewItemHeaderIdentity");
- case CipherType.Identity:
- return this.i18nService.t("viewItemHeaderNote");
- case CipherType.SshKey:
- return this.i18nService.t("viewItemHeaderSshKey");
- default:
- return null;
- }
- }
-}
-
-/**
- * Strongly typed helper to open a cipher view dialog
- * @param dialogService Instance of the dialog service that will be used to open the dialog
- * @param config Configuration for the dialog
- * @returns A reference to the opened dialog
- */
-export function openViewCipherDialog(
- dialogService: DialogService,
- config: DialogConfig,
-): DialogRef {
- return dialogService.open(ViewComponent, config);
-}