-
{{ "collectionsDesc" | i18n }}
-
-
{{ "collections" | i18n }}
-
-
-
-
+
+
+
+
+
+
+ {{ c.name }}
+ |
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web/src/app/vault/individual-vault/collections.component.ts b/apps/web/src/app/vault/individual-vault/collections.component.ts
index 6cf0901f33..6add775b4a 100644
--- a/apps/web/src/app/vault/individual-vault/collections.component.ts
+++ b/apps/web/src/app/vault/individual-vault/collections.component.ts
@@ -1,4 +1,5 @@
-import { Component, OnDestroy } from "@angular/core";
+import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
+import { Component, OnDestroy, Inject } from "@angular/core";
import { CollectionsComponent as BaseCollectionsComponent } from "@bitwarden/angular/admin-console/components/collections.component";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
@@ -8,6 +9,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
+import { DialogService } from "@bitwarden/components";
@Component({
selector: "app-vault-collections",
@@ -21,6 +23,8 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
cipherService: CipherService,
organizationSerivce: OrganizationService,
logService: LogService,
+ protected dialogRef: DialogRef,
+ @Inject(DIALOG_DATA) params: CollectionsDialogParams,
) {
super(
collectionService,
@@ -30,10 +34,16 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
organizationSerivce,
logService,
);
+ this.cipherId = params?.cipherId;
}
- ngOnDestroy() {
- this.selectAll(false);
+ override async submit(): Promise
{
+ const success = await super.submit();
+ if (success) {
+ this.dialogRef.close(CollectionsDialogResult.Saved);
+ return true;
+ }
+ return false;
}
check(c: CollectionView, select?: boolean) {
@@ -46,4 +56,31 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
selectAll(select: boolean) {
this.collections.forEach((c) => this.check(c, select));
}
+
+ ngOnDestroy() {
+ this.selectAll(false);
+ }
+}
+
+export interface CollectionsDialogParams {
+ cipherId: string;
+}
+
+export enum CollectionsDialogResult {
+ Saved = "saved",
+}
+
+/**
+ * Strongly typed helper to open a Collections dialog
+ * @param dialogService Instance of the dialog service that will be used to open the dialog
+ * @param config Optional configuration for the dialog
+ */
+export function openIndividualVaultCollectionsDialog(
+ dialogService: DialogService,
+ config?: DialogConfig,
+) {
+ return dialogService.open(
+ CollectionsComponent,
+ config,
+ );
}
diff --git a/apps/web/src/app/vault/individual-vault/vault.component.ts b/apps/web/src/app/vault/individual-vault/vault.component.ts
index 6fe31f29f4..a25ba6edbc 100644
--- a/apps/web/src/app/vault/individual-vault/vault.component.ts
+++ b/apps/web/src/app/vault/individual-vault/vault.component.ts
@@ -86,7 +86,7 @@ import {
BulkShareDialogResult,
openBulkShareDialog,
} from "./bulk-action-dialogs/bulk-share-dialog/bulk-share-dialog.component";
-import { CollectionsComponent } from "./collections.component";
+import { openIndividualVaultCollectionsDialog } from "./collections.component";
import { FolderAddEditDialogResult, openFolderAddEditDialog } from "./folder-add-edit.component";
import { ShareComponent } from "./share.component";
import { VaultFilterComponent } from "./vault-filter/components/vault-filter.component";
@@ -568,17 +568,7 @@ export class VaultComponent implements OnInit, OnDestroy {
}
async editCipherCollections(cipher: CipherView) {
- const [modal] = await this.modalService.openViewRef(
- CollectionsComponent,
- this.collectionsModalRef,
- (comp) => {
- comp.cipherId = cipher.id;
- comp.onSavedCollections.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
- },
- );
+ openIndividualVaultCollectionsDialog(this.dialogService, { data: { cipherId: cipher.id } });
}
async addCipher() {
diff --git a/apps/web/src/app/vault/org-vault/collections.component.ts b/apps/web/src/app/vault/org-vault/collections.component.ts
index 020d3fbe95..67eac2098f 100644
--- a/apps/web/src/app/vault/org-vault/collections.component.ts
+++ b/apps/web/src/app/vault/org-vault/collections.component.ts
@@ -1,4 +1,5 @@
-import { Component } from "@angular/core";
+import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
@@ -11,8 +12,13 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
import { CipherCollectionsRequest } from "@bitwarden/common/vault/models/request/cipher-collections.request";
+import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
+import { DialogService } from "@bitwarden/components";
-import { CollectionsComponent as BaseCollectionsComponent } from "../individual-vault/collections.component";
+import {
+ CollectionsComponent as BaseCollectionsComponent,
+ CollectionsDialogResult,
+} from "../individual-vault/collections.component";
@Component({
selector: "app-org-vault-collections",
@@ -29,6 +35,8 @@ export class CollectionsComponent extends BaseCollectionsComponent {
organizationService: OrganizationService,
private apiService: ApiService,
logService: LogService,
+ protected dialogRef: DialogRef,
+ @Inject(DIALOG_DATA) params: OrgVaultCollectionsDialogParams,
) {
super(
collectionService,
@@ -37,8 +45,14 @@ export class CollectionsComponent extends BaseCollectionsComponent {
cipherService,
organizationService,
logService,
+ dialogRef,
+ params,
);
this.allowSelectNone = true;
+ this.collectionIds = params?.collectionIds;
+ this.collections = params?.collections;
+ this.organization = params?.organization;
+ this.cipherId = params?.cipherId;
}
protected async loadCipher() {
@@ -79,3 +93,25 @@ export class CollectionsComponent extends BaseCollectionsComponent {
}
}
}
+
+export interface OrgVaultCollectionsDialogParams {
+ collectionIds: string[];
+ collections: CollectionView[];
+ organization: Organization;
+ cipherId: string;
+}
+
+/**
+ * Strongly typed helper to open a Collections dialog
+ * @param dialogService Instance of the dialog service that will be used to open the dialog
+ * @param config Optional configuration for the dialog
+ */
+export function openOrgVaultCollectionsDialog(
+ dialogService: DialogService,
+ config?: DialogConfig,
+) {
+ return dialogService.open(
+ CollectionsComponent,
+ config,
+ );
+}
diff --git a/apps/web/src/app/vault/org-vault/vault.component.ts b/apps/web/src/app/vault/org-vault/vault.component.ts
index 50d3216150..587758dda1 100644
--- a/apps/web/src/app/vault/org-vault/vault.component.ts
+++ b/apps/web/src/app/vault/org-vault/vault.component.ts
@@ -75,6 +75,7 @@ import {
BulkDeleteDialogResult,
openBulkDeleteDialog,
} from "../individual-vault/bulk-action-dialogs/bulk-delete-dialog/bulk-delete-dialog.component";
+import { CollectionsDialogResult } from "../individual-vault/collections.component";
import { RoutedVaultFilterBridgeService } from "../individual-vault/vault-filter/services/routed-vault-filter-bridge.service";
import { RoutedVaultFilterService } from "../individual-vault/vault-filter/services/routed-vault-filter.service";
import { createFilterFunction } from "../individual-vault/vault-filter/shared/models/filter-function";
@@ -95,7 +96,7 @@ import {
BulkCollectionsDialogComponent,
BulkCollectionsDialogResult,
} from "./bulk-collections-dialog";
-import { CollectionsComponent } from "./collections.component";
+import { openOrgVaultCollectionsDialog } from "./collections.component";
import { VaultFilterComponent } from "./vault-filter/vault-filter.component";
const BroadcasterSubscriptionId = "OrgVaultComponent";
@@ -711,21 +712,37 @@ export class VaultComponent implements OnInit, OnDestroy {
} else {
collections = await firstValueFrom(this.allCollectionsWithoutUnassigned$);
}
- const [modal] = await this.modalService.openViewRef(
- CollectionsComponent,
- this.collectionsModalRef,
- (comp) => {
- comp.flexibleCollectionsV1Enabled = this.flexibleCollectionsV1Enabled;
- comp.collectionIds = cipher.collectionIds;
- comp.collections = collections;
- comp.organization = this.organization;
- comp.cipherId = cipher.id;
- comp.onSavedCollections.pipe(takeUntil(this.destroy$)).subscribe(() => {
- modal.close();
- this.refresh();
- });
+ const dialog = openOrgVaultCollectionsDialog(this.dialogService, {
+ data: {
+ collectionIds: cipher.collectionIds,
+ collections: collections.filter((c) => !c.readOnly && c.id != Unassigned),
+ organization: this.organization,
+ cipherId: cipher.id,
},
- );
+ });
+ /**
+
+ const [modal] = await this.modalService.openViewRef(
+ CollectionsComponent,
+ this.collectionsModalRef,
+ (comp) => {
+ comp.flexibleCollectionsV1Enabled = this.flexibleCollectionsV1Enabled;
+ comp.collectionIds = cipher.collectionIds;
+ comp.collections = collections;
+ comp.organization = this.organization;
+ comp.cipherId = cipher.id;
+ comp.onSavedCollections.pipe(takeUntil(this.destroy$)).subscribe(() => {
+ modal.close();
+ this.refresh();
+ });
+ },
+ );
+
+ */
+
+ if ((await lastValueFrom(dialog.closed)) == CollectionsDialogResult.Saved) {
+ await this.refresh();
+ }
}
async addCipher() {
diff --git a/libs/angular/src/admin-console/components/collections.component.ts b/libs/angular/src/admin-console/components/collections.component.ts
index 167fe0a97f..5f8c4145cb 100644
--- a/libs/angular/src/admin-console/components/collections.component.ts
+++ b/libs/angular/src/admin-console/components/collections.component.ts
@@ -59,7 +59,7 @@ export class CollectionsComponent implements OnInit {
}
}
- async submit() {
+ async submit(): Promise {
const selectedCollectionIds = this.collections
.filter((c) => {
if (this.organization.canEditAllCiphers(this.flexibleCollectionsV1Enabled)) {
@@ -75,7 +75,7 @@ export class CollectionsComponent implements OnInit {
this.i18nService.t("errorOccurred"),
this.i18nService.t("selectOneCollection"),
);
- return;
+ return false;
}
this.cipherDomain.collectionIds = selectedCollectionIds;
try {
@@ -83,8 +83,10 @@ export class CollectionsComponent implements OnInit {
await this.formPromise;
this.onSavedCollections.emit();
this.platformUtilsService.showToast("success", null, this.i18nService.t("editedItem"));
+ return true;
} catch (e) {
this.logService.error(e);
+ return false;
}
}