mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
* move `add-edit-folder` component to `angular/vault/components` so it can be consumed by other platforms * add edit/add folder copy to web app copy * add extension refresh folder dialog to individual vault * adding folder delete message to the web * add deletion result for add/edit folder dialog * allow editing folder from web * fix strict types for changed files * update tests * remove border class so hover state shows * revert changes to new-item-dropdown-v2 * migrate `AddEditFolderDialogComponent` to `libs/vault` package * add Created enum type * add static open method for folder dialog * add fullName to `FolderFilter` type * save the full name of a folder before splitting it into parts * use the full name of the folder filter when available * use a shallow copy to edit the folder's full name --------- Co-authored-by: SmithThe4th <gsmith@bitwarden.com>
176 lines
5.2 KiB
TypeScript
176 lines
5.2 KiB
TypeScript
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
|
|
import { CommonModule } from "@angular/common";
|
|
import {
|
|
AfterViewInit,
|
|
Component,
|
|
DestroyRef,
|
|
inject,
|
|
Inject,
|
|
OnInit,
|
|
ViewChild,
|
|
} from "@angular/core";
|
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
|
import { firstValueFrom, map } from "rxjs";
|
|
|
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
|
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
|
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
|
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
|
import {
|
|
AsyncActionsModule,
|
|
BitSubmitDirective,
|
|
ButtonComponent,
|
|
ButtonModule,
|
|
DialogModule,
|
|
DialogService,
|
|
FormFieldModule,
|
|
IconButtonModule,
|
|
ToastService,
|
|
} from "@bitwarden/components";
|
|
import { KeyService } from "@bitwarden/key-management";
|
|
|
|
export enum AddEditFolderDialogResult {
|
|
Created = "created",
|
|
Deleted = "deleted",
|
|
}
|
|
|
|
export type AddEditFolderDialogData = {
|
|
/** When provided, dialog will display edit folder variant */
|
|
editFolderConfig?: { folder: FolderView };
|
|
};
|
|
|
|
@Component({
|
|
standalone: true,
|
|
selector: "vault-add-edit-folder-dialog",
|
|
templateUrl: "./add-edit-folder-dialog.component.html",
|
|
imports: [
|
|
CommonModule,
|
|
JslibModule,
|
|
DialogModule,
|
|
ButtonModule,
|
|
FormFieldModule,
|
|
ReactiveFormsModule,
|
|
IconButtonModule,
|
|
AsyncActionsModule,
|
|
],
|
|
})
|
|
export class AddEditFolderDialogComponent implements AfterViewInit, OnInit {
|
|
@ViewChild(BitSubmitDirective) private bitSubmit?: BitSubmitDirective;
|
|
@ViewChild("submitBtn") private submitBtn?: ButtonComponent;
|
|
|
|
folder: FolderView = new FolderView();
|
|
|
|
variant: "add" | "edit" = "add";
|
|
|
|
folderForm = this.formBuilder.group({
|
|
name: ["", Validators.required],
|
|
});
|
|
|
|
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
|
private destroyRef = inject(DestroyRef);
|
|
|
|
constructor(
|
|
private formBuilder: FormBuilder,
|
|
private folderService: FolderService,
|
|
private folderApiService: FolderApiServiceAbstraction,
|
|
private accountService: AccountService,
|
|
private keyService: KeyService,
|
|
private toastService: ToastService,
|
|
private i18nService: I18nService,
|
|
private logService: LogService,
|
|
private dialogService: DialogService,
|
|
private dialogRef: DialogRef<AddEditFolderDialogResult>,
|
|
@Inject(DIALOG_DATA) private data?: AddEditFolderDialogData,
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
if (this.data?.editFolderConfig) {
|
|
this.variant = "edit";
|
|
this.folderForm.controls.name.setValue(this.data.editFolderConfig.folder.name);
|
|
this.folder = this.data.editFolderConfig.folder;
|
|
} else {
|
|
// Create a new folder view
|
|
this.folder = new FolderView();
|
|
}
|
|
}
|
|
|
|
ngAfterViewInit(): void {
|
|
this.bitSubmit?.loading$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((loading) => {
|
|
if (!this.submitBtn) {
|
|
return;
|
|
}
|
|
|
|
this.submitBtn.loading = loading;
|
|
});
|
|
}
|
|
|
|
/** Submit the new folder */
|
|
submit = async () => {
|
|
if (this.folderForm.invalid) {
|
|
return;
|
|
}
|
|
|
|
this.folder.name = this.folderForm.controls.name.value ?? "";
|
|
|
|
try {
|
|
const activeUserId = await firstValueFrom(this.activeUserId$);
|
|
const userKey = await this.keyService.getUserKeyWithLegacySupport(activeUserId!);
|
|
const folder = await this.folderService.encrypt(this.folder, userKey);
|
|
await this.folderApiService.save(folder, activeUserId!);
|
|
|
|
this.toastService.showToast({
|
|
variant: "success",
|
|
title: "",
|
|
message: this.i18nService.t("editedFolder"),
|
|
});
|
|
|
|
this.close(AddEditFolderDialogResult.Created);
|
|
} catch (e) {
|
|
this.logService.error(e);
|
|
}
|
|
};
|
|
|
|
/** Delete the folder with when the user provides a confirmation */
|
|
deleteFolder = async () => {
|
|
const confirmed = await this.dialogService.openSimpleDialog({
|
|
title: { key: "deleteFolder" },
|
|
content: { key: "deleteFolderPermanently" },
|
|
type: "warning",
|
|
});
|
|
|
|
if (!confirmed) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const activeUserId = await firstValueFrom(this.activeUserId$);
|
|
await this.folderApiService.delete(this.folder.id, activeUserId!);
|
|
this.toastService.showToast({
|
|
variant: "success",
|
|
title: "",
|
|
message: this.i18nService.t("deletedFolder"),
|
|
});
|
|
} catch (e) {
|
|
this.logService.error(e);
|
|
}
|
|
|
|
this.close(AddEditFolderDialogResult.Deleted);
|
|
};
|
|
|
|
/** Close the dialog */
|
|
private close(result: AddEditFolderDialogResult) {
|
|
this.dialogRef.close(result);
|
|
}
|
|
|
|
static open(dialogService: DialogService, data?: AddEditFolderDialogData) {
|
|
return dialogService.open<AddEditFolderDialogResult, AddEditFolderDialogData>(
|
|
AddEditFolderDialogComponent,
|
|
{ data },
|
|
);
|
|
}
|
|
}
|