From 00f2317a8210f9ac86d7fd0739bd549055265de8 Mon Sep 17 00:00:00 2001 From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:36:53 -0700 Subject: [PATCH] [PM-11903] - add file send component (#11132) * wip - send file details * wip - file send * send file details * fix click on send list container * remove popup code * remove popup code * finalize send file details * address PR feedback. add base form to send form * revert changes to send list items container * revert changes to send list items container --------- Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> --- apps/browser/src/_locales/en/messages.json | 3 + .../add-edit/send-add-edit.component.ts | 19 ++-- .../base-send-details.component.ts | 2 + .../send-details/send-details.component.html | 7 ++ .../send-details/send-details.component.ts | 2 + .../send-file-details.component.html | 30 ++++++ .../send-file-details.component.ts | 92 +++++++++++++++++++ .../components/send-form.component.ts | 8 +- .../src/send-form/send-form-container.ts | 4 + 9 files changed, 152 insertions(+), 15 deletions(-) create mode 100644 libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.html create mode 100644 libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index a57b65f6982..061929fc49c 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -1136,6 +1136,9 @@ "file": { "message": "File" }, + "fileToShare": { + "message": "File to share" + }, "selectFile": { "message": "Select a file" }, diff --git a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts index 48e6cbb8a31..49526bb032b 100644 --- a/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts +++ b/apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts @@ -117,25 +117,18 @@ export class SendAddEditComponent { ) .subscribe((config) => { this.config = config; - this.headerText = this.getHeaderText(config.mode, config.sendType); + this.headerText = this.getHeaderText(config.mode); }); } /** - * Gets the header text based on the mode and type. + * Gets the header text based on the mode. * @param mode The mode of the send form. - * @param type The type of the send form. * @returns The header text. */ - private getHeaderText(mode: SendFormMode, type: SendType) { - const headerKey = - mode === "edit" || mode === "partial-edit" ? "editItemHeader" : "newItemHeader"; - - switch (type) { - case SendType.Text: - return this.i18nService.t(headerKey, this.i18nService.t("sendTypeText")); - case SendType.File: - return this.i18nService.t(headerKey, this.i18nService.t("sendTypeFile")); - } + private getHeaderText(mode: SendFormMode) { + return this.i18nService.t( + mode === "edit" || mode === "partial-edit" ? "editSend" : "createSend", + ); } } diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts index 282f6caffab..f3e2229dd2b 100644 --- a/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts +++ b/libs/tools/send/send-ui/src/send-form/components/send-details/base-send-details.component.ts @@ -62,6 +62,8 @@ export class BaseSendDetailsComponent implements OnInit { } as SendView); }); }); + + this.sendFormContainer.registerChildForm("sendDetailsForm", this.sendDetailsForm); } async ngOnInit() { diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html index e1f3f4f0d9f..47e1fc6059a 100644 --- a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html +++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.html @@ -16,6 +16,13 @@

{{ "sendDetails" | i18n }}

[sendDetailsForm]="sendDetailsForm" > + + {{ "deletionDate" | i18n }} +
+
{{ "file" | i18n }}
+
{{ originalSendView.file.fileName }}
+
{{ originalSendView.file.sizeName }}
+
+ + {{ "fileToShare" | i18n }} + + + {{ fileName || ("noFileChosen" | i18n) }} + + + {{ "maxFileSize" | i18n }} + + + diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts new file mode 100644 index 00000000000..86c9fa96f1a --- /dev/null +++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-file-details.component.ts @@ -0,0 +1,92 @@ +import { CommonModule } from "@angular/common"; +import { Component, Input, OnInit } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, + ReactiveFormsModule, + FormsModule, +} from "@angular/forms"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { SendType } from "@bitwarden/common/tools/send/enums/send-type"; +import { SendFileView } from "@bitwarden/common/tools/send/models/view/send-file.view"; +import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; +import { ButtonModule, FormFieldModule, SectionComponent } from "@bitwarden/components"; + +import { SendFormConfig } from "../../abstractions/send-form-config.service"; +import { SendFormContainer } from "../../send-form-container"; + +import { BaseSendDetailsForm } from "./base-send-details.component"; + +type BaseSendFileDetailsForm = FormGroup<{ + file: FormControl; +}>; + +export type SendFileDetailsForm = BaseSendFileDetailsForm & BaseSendDetailsForm; + +@Component({ + selector: "tools-send-file-details", + templateUrl: "./send-file-details.component.html", + standalone: true, + imports: [ + ButtonModule, + CommonModule, + JslibModule, + ReactiveFormsModule, + FormFieldModule, + SectionComponent, + FormsModule, + ], +}) +export class SendFileDetailsComponent implements OnInit { + @Input() config: SendFormConfig; + @Input() originalSendView?: SendView; + @Input() sendDetailsForm: BaseSendDetailsForm; + + baseSendFileDetailsForm: BaseSendFileDetailsForm; + sendFileDetailsForm: SendFileDetailsForm; + + FileSendType = SendType.File; + fileName = ""; + + constructor( + private formBuilder: FormBuilder, + protected sendFormContainer: SendFormContainer, + ) { + this.baseSendFileDetailsForm = this.formBuilder.group({ + file: this.formBuilder.control(null, Validators.required), + }); + + this.sendFileDetailsForm = Object.assign(this.baseSendFileDetailsForm, this.sendDetailsForm); + + this.sendFormContainer.registerChildForm("sendFileDetailsForm", this.sendFileDetailsForm); + + this.sendFileDetailsForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => { + this.sendFormContainer.patchSend((send) => { + return Object.assign(send, { + file: value.file, + }); + }); + }); + } + + onFileSelected = (event: Event): void => { + const file = (event.target as HTMLInputElement).files?.[0]; + if (!file) { + return; + } + this.fileName = file.name; + this.sendFormContainer.onFileSelected(file); + }; + + ngOnInit() { + if (this.originalSendView) { + this.sendFileDetailsForm.patchValue({ + file: this.originalSendView.file, + }); + } + } +} diff --git a/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts index 2cb1907d921..b265b644df4 100644 --- a/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts +++ b/libs/tools/send/send-ui/src/send-form/components/send-form.component.ts @@ -65,6 +65,7 @@ export class SendFormComponent implements AfterViewInit, OnInit, OnChanges, Send private bitSubmit: BitSubmitDirective; private destroyRef = inject(DestroyRef); private _firstInitialized = false; + private file: File | null = null; /** * The form ID to use for the form. Used to connect it to a submit button. @@ -188,14 +189,17 @@ export class SendFormComponent implements AfterViewInit, OnInit, OnChanges, Send private i18nService: I18nService, ) {} + onFileSelected(file: File): void { + this.file = file; + } + submit = async () => { if (this.sendForm.invalid) { this.sendForm.markAllAsTouched(); return; } - // TODO: Add file handling - await this.addEditFormService.saveSend(this.updatedSendView, null, this.config); + await this.addEditFormService.saveSend(this.updatedSendView, this.file, this.config); this.toastService.showToast({ variant: "success", diff --git a/libs/tools/send/send-ui/src/send-form/send-form-container.ts b/libs/tools/send/send-ui/src/send-form/send-form-container.ts index f3af1ecd816..21508d96727 100644 --- a/libs/tools/send/send-ui/src/send-form/send-form-container.ts +++ b/libs/tools/send/send-ui/src/send-form/send-form-container.ts @@ -2,6 +2,7 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view"; import { SendFormConfig } from "./abstractions/send-form-config.service"; import { SendDetailsComponent } from "./components/send-details/send-details.component"; +import { SendFileDetailsForm } from "./components/send-details/send-file-details.component"; import { SendTextDetailsForm } from "./components/send-details/send-text-details.component"; /** * The complete form for a send. Includes all the sub-forms from their respective section components. @@ -10,6 +11,7 @@ import { SendTextDetailsForm } from "./components/send-details/send-text-details export type SendForm = { sendDetailsForm?: SendDetailsComponent["sendDetailsForm"]; sendTextDetailsForm?: SendTextDetailsForm; + sendFileDetailsForm?: SendFileDetailsForm; }; /** @@ -37,5 +39,7 @@ export abstract class SendFormContainer { group: Exclude, ): void; + abstract onFileSelected(file: File): void; + abstract patchSend(updateFn: (current: SendView) => SendView): void; }