1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

initial integration of combined dialog

This commit is contained in:
Nick Krantz
2024-10-02 22:02:22 -05:00
parent 4c75c0723e
commit 50cf19efcd
3 changed files with 61 additions and 12 deletions

View File

@@ -1,6 +1,7 @@
import { TestBed } from "@angular/core/testing"; import { TestBed } from "@angular/core/testing";
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject } from "rxjs";
import { CollectionAdminService } from "@bitwarden/admin-console/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
@@ -9,7 +10,6 @@ import { CipherId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service"; import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
import { CollectionAdminService } from "../../core/collection-admin.service";
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service"; import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
import { AdminConsoleCipherFormConfigService } from "./admin-console-cipher-form-config.service"; import { AdminConsoleCipherFormConfigService } from "./admin-console-cipher-form-config.service";

View File

@@ -1,6 +1,7 @@
import { inject, Injectable } from "@angular/core"; import { inject, Injectable } from "@angular/core";
import { combineLatest, defer, filter, firstValueFrom, map, switchMap } from "rxjs"; import { combineLatest, defer, filter, firstValueFrom, map, switchMap } from "rxjs";
import { CollectionAdminService } from "@bitwarden/admin-console/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
@@ -18,7 +19,6 @@ import {
CipherFormConfigService, CipherFormConfigService,
CipherFormMode, CipherFormMode,
} from "../../../../../../../libs/vault/src/cipher-form/abstractions/cipher-form-config.service"; } from "../../../../../../../libs/vault/src/cipher-form/abstractions/cipher-form-config.service";
import { CollectionAdminService } from "../../core/collection-admin.service";
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service"; import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
/** Admin Console implementation of the `CipherFormConfigService`. */ /** Admin Console implementation of the `CipherFormConfigService`. */

View File

@@ -1,3 +1,4 @@
import { DialogRef } from "@angular/cdk/dialog";
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@@ -64,6 +65,7 @@ import { CollectionView } from "@bitwarden/common/vault/models/view/collection.v
import { ServiceUtils } from "@bitwarden/common/vault/service-utils"; import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
import { DialogService, Icons, NoItemsModule, ToastService } from "@bitwarden/components"; import { DialogService, Icons, NoItemsModule, ToastService } from "@bitwarden/components";
import { import {
CipherFormConfig,
CipherFormConfigService, CipherFormConfigService,
CollectionAssignmentResult, CollectionAssignmentResult,
PasswordRepromptService, PasswordRepromptService,
@@ -80,6 +82,11 @@ import {
CollectionDialogTabType, CollectionDialogTabType,
openCollectionDialog, openCollectionDialog,
} from "../components/collection-dialog"; } from "../components/collection-dialog";
import {
VaultItemDialogComponent,
VaultItemDialogMode,
VaultItemDialogResult,
} from "../components/vault-item-dialog/vault-item-dialog.component";
import { VaultItemEvent } from "../components/vault-items/vault-item-event"; import { VaultItemEvent } from "../components/vault-items/vault-item-event";
import { VaultItemsModule } from "../components/vault-items/vault-items.module"; import { VaultItemsModule } from "../components/vault-items/vault-items.module";
import { import {
@@ -184,6 +191,7 @@ export class VaultComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();
protected addAccessStatus$ = new BehaviorSubject<AddAccessStatusType>(0); protected addAccessStatus$ = new BehaviorSubject<AddAccessStatusType>(0);
private extensionRefreshEnabled: boolean; private extensionRefreshEnabled: boolean;
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
@@ -481,6 +489,8 @@ export class VaultComponent implements OnInit, OnDestroy {
firstSetup$ firstSetup$
.pipe( .pipe(
switchMap(() => this.route.queryParams), switchMap(() => this.route.queryParams),
// Only process the queryParams if the dialog is not open (only when extension refresh is enabled)
filter(() => this.vaultItemDialogRef == undefined || !this.extensionRefreshEnabled),
withLatestFrom(allCipherMap$, allCollections$, organization$), withLatestFrom(allCipherMap$, allCollections$, organization$),
switchMap(async ([qParams, allCiphersMap]) => { switchMap(async ([qParams, allCiphersMap]) => {
const cipherId = getCipherIdFromParams(qParams); const cipherId = getCipherIdFromParams(qParams);
@@ -490,10 +500,15 @@ export class VaultComponent implements OnInit, OnDestroy {
const cipher = allCiphersMap[cipherId]; const cipher = allCiphersMap[cipherId];
if (cipher) { if (cipher) {
if (qParams.action === "view") { let action = qParams.action;
// Only allow for edit in the admin console via query params, // Default to "view" if extension refresh is enabled
// This prevents multiple modals from stacking on top of each other between view & edit. if (action == null && this.extensionRefreshEnabled) {
// TODO: PM-12398 - combine view/edit actions into a single dialog action = "view";
}
if (action === "view") {
await this.viewCipherById(cipherId);
} else {
await this.editCipherId(cipherId, false); await this.editCipherId(cipherId, false);
} }
} else { } else {
@@ -877,18 +892,52 @@ export class VaultComponent implements OnInit, OnDestroy {
cipherId, cipherId,
); );
const dialogRef = openAddEditCipherDialog(this.dialogService, { await this.openVaultItemDialog("form", cipherFormConfig);
data: cipherFormConfig, }
/** Opens the view dialog for the given cipher unless password reprompt fails */
async viewCipherById(id: string) {
const cipher = await this.cipherService.get(id);
// If cipher exists (cipher is null when new) and MP reprompt
// is on for this cipher, then show password reprompt.
if (
cipher &&
cipher.reprompt !== 0 &&
!(await this.passwordRepromptService.showPasswordPrompt())
) {
// Didn't pass password prompt, so don't open add / edit modal.
await this.go({ cipherId: null, itemId: null, action: null });
return;
}
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
cipher?.edit ? "edit" : "partial-edit",
id as CipherId,
cipher?.type,
);
await this.openVaultItemDialog("view", cipherFormConfig);
}
/**
* Open the combined view / edit dialog for a cipher.
*/
async openVaultItemDialog(mode: VaultItemDialogMode, formConfig: CipherFormConfig) {
this.vaultItemDialogRef = VaultItemDialogComponent.open(this.dialogService, {
mode,
formConfig,
}); });
const result: AddEditCipherDialogCloseResult = await firstValueFrom(dialogRef.closed); const result = await lastValueFrom(this.vaultItemDialogRef.closed);
this.vaultItemDialogRef = undefined;
// When the cipher was edited, refresh the vault view // If the dialog was closed by deleting the cipher, refresh the vault.
if (result?.action === AddEditCipherDialogResult.Edited) { if (result === VaultItemDialogResult.Deleted || result === VaultItemDialogResult.Saved) {
this.refresh(); this.refresh();
} }
this.go({ cipherId: null, itemId: null, action: null }); // Clear the query params when the dialog closes
await this.go({ cipherId: null, itemId: null, action: null });
} }
async cloneCipher(cipher: CipherView) { async cloneCipher(cipher: CipherView) {