From c4d66a1383af21c62096d421827497fa8361f4a1 Mon Sep 17 00:00:00 2001
From: Jordan Aasen <166539328+jaasen-livefront@users.noreply.github.com>
Date: Thu, 19 Sep 2024 11:53:25 -0700
Subject: [PATCH] [PM-11904] - send options form (#11142)
* send options form
* remove commented code
* fix margin. update i18 key
* remove unecessary input
* remove unnecessary typing. DRY up messages
---
apps/browser/src/_locales/en/messages.json | 27 ++++++
.../options/send-options.component.html | 31 ++++++
.../options/send-options.component.ts | 95 +++++++++++++++++++
.../base-send-details.component.ts | 18 ++--
.../send-details/send-details.component.html | 5 +-
.../send-details/send-details.component.ts | 2 +
.../send-file-details.component.ts | 29 +-----
.../send-text-details.component.html | 2 +-
.../send-text-details.component.ts | 33 ++-----
.../src/send-form/send-form-container.ts | 10 +-
10 files changed, 180 insertions(+), 72 deletions(-)
create mode 100644 libs/tools/send/send-ui/src/send-form/components/options/send-options.component.html
create mode 100644 libs/tools/send/send-ui/src/send-form/components/options/send-options.component.ts
diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 061929fc49..3c0d212bfc 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -531,6 +531,9 @@
"notes": {
"message": "Notes"
},
+ "privateNote": {
+ "message": "Private note"
+ },
"note": {
"message": "Note"
},
@@ -2267,6 +2270,23 @@
"excludedDomainsSavedSuccess": {
"message": "Excluded domain changes saved"
},
+ "limitSendViews": {
+ "message": "Limit views"
+ },
+ "limitSendViewsHint": {
+ "message": "No one can view this Send after the limit is reached.",
+ "description": "Displayed under the limit views field on Send"
+ },
+ "limitSendViewsCount": {
+ "message": "$ACCESSCOUNT$ views left",
+ "description": "Displayed under the limit views field on Send",
+ "placeholders": {
+ "accessCount": {
+ "content": "$1",
+ "example": "2"
+ }
+ }
+ },
"send": {
"message": "Send",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
@@ -2409,6 +2429,10 @@
"message": "Optionally require a password for users to access this Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
+ "sendPasswordDescV2": {
+ "message": "Require this password to view the Send.",
+ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
+ },
"sendNotesDesc": {
"message": "Private notes about this Send.",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
@@ -2514,6 +2538,9 @@
"hideEmail": {
"message": "Hide my email address from recipients."
},
+ "hideYourEmail": {
+ "message": "Hide your email address from viewers."
+ },
"sendOptionsPolicyInEffect": {
"message": "One or more organization policies are affecting your Send options."
},
diff --git a/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.html b/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.html
new file mode 100644
index 0000000000..e57b5af34c
--- /dev/null
+++ b/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.html
@@ -0,0 +1,31 @@
+
+
+ {{ "additionalOptions" | i18n }}
+
+
+
+ {{ "limitSendViews" | i18n }}
+
+ {{ "limitSendViewsHint" | i18n }}
+ {{ "limitSendViewsCount" | i18n: viewsLeft }}
+
+
+ {{ "password" | i18n }}
+ {{ "newPassword" | i18n }}
+
+
+
+ {{ "sendPasswordDescV2" | i18n }}
+
+
+
+ {{ "hideYourEmail" | i18n }}
+
+
+ {{ "privateNote" | i18n }}
+
+
+
+
diff --git a/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.ts b/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.ts
new file mode 100644
index 0000000000..46b0940c91
--- /dev/null
+++ b/libs/tools/send/send-ui/src/send-form/components/options/send-options.component.ts
@@ -0,0 +1,95 @@
+import { CommonModule } from "@angular/common";
+import { Component, Input, OnInit } from "@angular/core";
+import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
+import { FormBuilder, ReactiveFormsModule } from "@angular/forms";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
+import {
+ CardComponent,
+ CheckboxModule,
+ FormFieldModule,
+ IconButtonModule,
+ SectionComponent,
+ SectionHeaderComponent,
+ TypographyModule,
+} from "@bitwarden/components";
+
+import { SendFormConfig } from "../../abstractions/send-form-config.service";
+import { SendFormContainer } from "../../send-form-container";
+
+@Component({
+ selector: "tools-send-options",
+ templateUrl: "./send-options.component.html",
+ standalone: true,
+ imports: [
+ SectionComponent,
+ SectionHeaderComponent,
+ TypographyModule,
+ JslibModule,
+ CardComponent,
+ FormFieldModule,
+ ReactiveFormsModule,
+ IconButtonModule,
+ CheckboxModule,
+ CommonModule,
+ ],
+})
+export class SendOptionsComponent implements OnInit {
+ @Input({ required: true })
+ config: SendFormConfig;
+ @Input()
+ originalSendView: SendView;
+ sendOptionsForm = this.formBuilder.group({
+ maxAccessCount: [null as number],
+ accessCount: [null as number],
+ notes: [null as string],
+ password: [null as string],
+ hideEmail: [false as boolean],
+ });
+ get hasPassword(): boolean {
+ return (
+ this.sendOptionsForm.value.password !== null && this.sendOptionsForm.value.password !== ""
+ );
+ }
+
+ get shouldShowCount(): boolean {
+ return this.config.mode === "edit" && this.sendOptionsForm.value.maxAccessCount !== null;
+ }
+
+ get viewsLeft(): number {
+ return this.sendOptionsForm.value.maxAccessCount
+ ? this.sendOptionsForm.value.maxAccessCount - this.sendOptionsForm.value.accessCount
+ : 0;
+ }
+
+ constructor(
+ private sendFormContainer: SendFormContainer,
+ private formBuilder: FormBuilder,
+ ) {
+ this.sendFormContainer.registerChildForm("sendOptionsForm", this.sendOptionsForm);
+ this.sendOptionsForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
+ this.sendFormContainer.patchSend((send) => {
+ Object.assign(send, {
+ maxAccessCount: value.maxAccessCount,
+ accessCount: value.accessCount,
+ password: value.password,
+ hideEmail: value.hideEmail,
+ notes: value.notes,
+ });
+ return send;
+ });
+ });
+ }
+ ngOnInit() {
+ if (this.sendFormContainer.originalSendView) {
+ this.sendOptionsForm.patchValue({
+ maxAccessCount: this.sendFormContainer.originalSendView.maxAccessCount,
+ accessCount: this.sendFormContainer.originalSendView.accessCount,
+ password: this.sendFormContainer.originalSendView.password,
+ hideEmail: this.sendFormContainer.originalSendView.hideEmail,
+ notes: this.sendFormContainer.originalSendView.notes,
+ });
+ }
+ }
+}
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 f3e2229dd2..b5cf8ee0c7 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
@@ -1,7 +1,7 @@
import { DatePipe } from "@angular/common";
import { Component, Input, OnInit } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
-import { FormBuilder, FormGroup, FormControl, Validators } from "@angular/forms";
+import { FormBuilder, FormControl, Validators } from "@angular/forms";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
@@ -9,11 +9,6 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import { SendFormConfig } from "../../abstractions/send-form-config.service";
import { SendFormContainer } from "../../send-form-container";
-export type BaseSendDetailsForm = FormGroup<{
- name: FormControl;
- selectedDeletionDatePreset: FormControl;
-}>;
-
// Value = hours
export enum DatePreset {
OneHour = 1,
@@ -38,21 +33,20 @@ export class BaseSendDetailsComponent implements OnInit {
@Input() config: SendFormConfig;
@Input() originalSendView?: SendView;
- sendDetailsForm: BaseSendDetailsForm;
customDeletionDateOption: DatePresetSelectOption | null = null;
datePresetOptions: DatePresetSelectOption[] = [];
+ sendDetailsForm = this.formBuilder.group({
+ name: new FormControl("", Validators.required),
+ selectedDeletionDatePreset: new FormControl(DatePreset.SevenDays || "", Validators.required),
+ });
+
constructor(
protected sendFormContainer: SendFormContainer,
protected formBuilder: FormBuilder,
protected i18nService: I18nService,
protected datePipe: DatePipe,
) {
- this.sendDetailsForm = this.formBuilder.group({
- name: new FormControl("", Validators.required),
- selectedDeletionDatePreset: new FormControl(DatePreset.SevenDays || "", Validators.required),
- });
-
this.sendDetailsForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
this.sendFormContainer.patchSend((send) => {
return Object.assign(send, {
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 47e1fc6059..b10956daac 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
@@ -1,5 +1,5 @@
-
+
{{ "sendDetails" | i18n }}
@@ -13,14 +13,12 @@
*ngIf="config.sendType === TextSendType"
[config]="config"
[originalSendView]="originalSendView"
- [sendDetailsForm]="sendDetailsForm"
>
@@ -39,4 +37,5 @@
{{ "deletionDateDescV2" | i18n }}
+
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts
index aadfc590c2..2d00888b9b 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts
@@ -17,6 +17,7 @@ import {
} from "@bitwarden/components";
import { SendFormContainer } from "../../send-form-container";
+import { SendOptionsComponent } from "../options/send-options.component";
import { BaseSendDetailsComponent } from "./base-send-details.component";
import { SendFileDetailsComponent } from "./send-file-details.component";
@@ -36,6 +37,7 @@ import { SendTextDetailsComponent } from "./send-text-details.component";
ReactiveFormsModule,
SendTextDetailsComponent,
SendFileDetailsComponent,
+ SendOptionsComponent,
IconButtonModule,
CheckboxModule,
CommonModule,
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
index 86c9fa96f1..61391e2072 100644
--- 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
@@ -1,14 +1,7 @@
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 { FormBuilder, Validators, ReactiveFormsModule, FormsModule } from "@angular/forms";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
@@ -19,14 +12,6 @@ import { ButtonModule, FormFieldModule, SectionComponent } from "@bitwarden/comp
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",
@@ -44,10 +29,10 @@ export type SendFileDetailsForm = BaseSendFileDetailsForm & BaseSendDetailsForm;
export class SendFileDetailsComponent implements OnInit {
@Input() config: SendFormConfig;
@Input() originalSendView?: SendView;
- @Input() sendDetailsForm: BaseSendDetailsForm;
- baseSendFileDetailsForm: BaseSendFileDetailsForm;
- sendFileDetailsForm: SendFileDetailsForm;
+ sendFileDetailsForm = this.formBuilder.group({
+ file: this.formBuilder.control(null, Validators.required),
+ });
FileSendType = SendType.File;
fileName = "";
@@ -56,12 +41,6 @@ export class SendFileDetailsComponent implements OnInit {
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) => {
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.html b/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.html
index bddd8f226d..b7875d1d45 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.html
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.html
@@ -1,4 +1,4 @@
-
+
{{ "sendTypeTextToShare" | i18n }}
diff --git a/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.ts b/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.ts
index 970c74644d..85fc324f2f 100644
--- a/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.ts
+++ b/libs/tools/send/send-ui/src/send-form/components/send-details/send-text-details.component.ts
@@ -1,13 +1,7 @@
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,
-} from "@angular/forms";
+import { FormBuilder, FormControl, Validators, ReactiveFormsModule } from "@angular/forms";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
@@ -16,15 +10,6 @@ import { CheckboxModule, FormFieldModule, SectionComponent } from "@bitwarden/co
import { SendFormConfig } from "../../abstractions/send-form-config.service";
import { SendFormContainer } from "../../send-form-container";
-import { BaseSendDetailsForm } from "./base-send-details.component";
-
-type BaseSendTextDetailsForm = FormGroup<{
- text: FormControl;
- hidden: FormControl;
-}>;
-
-export type SendTextDetailsForm = BaseSendTextDetailsForm & BaseSendDetailsForm;
-
@Component({
selector: "tools-send-text-details",
templateUrl: "./send-text-details.component.html",
@@ -41,22 +26,16 @@ export type SendTextDetailsForm = BaseSendTextDetailsForm & BaseSendDetailsForm;
export class SendTextDetailsComponent implements OnInit {
@Input() config: SendFormConfig;
@Input() originalSendView?: SendView;
- @Input() sendDetailsForm: BaseSendDetailsForm;
- baseSendTextDetailsForm: BaseSendTextDetailsForm;
- sendTextDetailsForm: SendTextDetailsForm;
+ sendTextDetailsForm = this.formBuilder.group({
+ text: new FormControl("", Validators.required),
+ hidden: new FormControl(false),
+ });
constructor(
private formBuilder: FormBuilder,
protected sendFormContainer: SendFormContainer,
) {
- this.baseSendTextDetailsForm = this.formBuilder.group({
- text: new FormControl("", Validators.required),
- hidden: new FormControl(false),
- });
-
- this.sendTextDetailsForm = Object.assign(this.baseSendTextDetailsForm, this.sendDetailsForm);
-
this.sendFormContainer.registerChildForm("sendTextDetailsForm", this.sendTextDetailsForm);
this.sendTextDetailsForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((value) => {
@@ -73,7 +52,7 @@ export class SendTextDetailsComponent implements OnInit {
ngOnInit() {
if (this.originalSendView) {
- this.baseSendTextDetailsForm.patchValue({
+ this.sendTextDetailsForm.patchValue({
text: this.originalSendView.text?.text || "",
hidden: this.originalSendView.text?.hidden || false,
});
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 21508d9672..84e0913194 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
@@ -1,17 +1,19 @@
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import { SendFormConfig } from "./abstractions/send-form-config.service";
+import { SendOptionsComponent } from "./components/options/send-options.component";
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";
+import { SendFileDetailsComponent } from "./components/send-details/send-file-details.component";
+import { SendTextDetailsComponent } from "./components/send-details/send-text-details.component";
/**
* The complete form for a send. Includes all the sub-forms from their respective section components.
* TODO: Add additional form sections as they are implemented.
*/
export type SendForm = {
sendDetailsForm?: SendDetailsComponent["sendDetailsForm"];
- sendTextDetailsForm?: SendTextDetailsForm;
- sendFileDetailsForm?: SendFileDetailsForm;
+ sendTextDetailsForm?: SendTextDetailsComponent["sendTextDetailsForm"];
+ sendFileDetailsForm?: SendFileDetailsComponent["sendFileDetailsForm"];
+ sendOptionsForm?: SendOptionsComponent["sendOptionsForm"];
};
/**