From f70af2c382104753358780f39128e786e3d21348 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Mon, 25 Sep 2023 22:54:32 -0400 Subject: [PATCH] Pass form values into the `SupportForm` component. --- .prettierignore | 2 +- package-lock.json | 16 ++-- package.json | 2 +- src/www/views/contact_view/index.ts | 60 +++++++-------- .../views/contact_view/support_form/index.ts | 76 +++++++++---------- .../contact_view/support_form/stories.ts | 37 ++++++++- 6 files changed, 111 insertions(+), 82 deletions(-) diff --git a/.prettierignore b/.prettierignore index face83d9a2e..15387e05076 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,4 +4,4 @@ docs/ resources/ third_party/ tools/ -node_modules/ +node_modules/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8b39f97f6d2..e31e4d122e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,7 +115,7 @@ "outline-i18n": "Jigsaw-Code/outline-i18n#v0.0.7", "postcss": "^7.0.39", "postcss-rtl": "^1.7.3", - "prettier": "^1.19.1", + "prettier": "2.8", "pretty-quick": "^2.0.1", "puppeteer": "^13.1.2", "replace-in-file": "^6.3.5", @@ -20592,14 +20592,18 @@ } }, "node_modules/prettier": { - "version": "1.19.1", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, - "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, "engines": { - "node": ">=4" + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-error": { @@ -41141,7 +41145,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "pretty-error": { diff --git a/package.json b/package.json index d64bf0fe3aa..8f8efe0ef8b 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "outline-i18n": "Jigsaw-Code/outline-i18n#v0.0.7", "postcss": "^7.0.39", "postcss-rtl": "^1.7.3", - "prettier": "^1.19.1", + "prettier": "^2.8.0", "pretty-quick": "^2.0.1", "puppeteer": "^13.1.2", "replace-in-file": "^6.3.5", diff --git a/src/www/views/contact_view/index.ts b/src/www/views/contact_view/index.ts index 39d6cd6e369..e5ecce05ad9 100644 --- a/src/www/views/contact_view/index.ts +++ b/src/www/views/contact_view/index.ts @@ -121,6 +121,7 @@ export class ContactView extends LitElement { ]; @state() private showIssueSelector = false; + private formValues: FormValues = {}; private readonly formRef: Ref = createRef(); @state() private isFormSubmitting = false; @@ -190,28 +191,27 @@ export class ContactView extends LitElement { private reset() { this.showIssueSelector = false; this.step = Step.ISSUE_WIZARD; - this.formRef.value.reset(); + this.formValues = {}; } - private submitForm(e: CustomEvent) { + private submitForm() { this.isFormSubmitting = true; - const formData: FormValues = e.detail; + if (!this.formRef.value.valid) { + throw Error('Cannot submit invalid form.'); + } + // TODO: Actually send the form data using the error reporter. - console.log('Submitting form data...', formData); + console.log('Submitting form data...', this.formValues); this.isFormSubmitting = false; - this.exitTemplate = html` - Thanks for helping us improve! We love hearing from you. - `; + this.exitTemplate = html` Thanks for helping us improve! We love hearing from you. `; this.step = Step.EXIT; } private get renderIntroTemplate(): TemplateResult { return html` -

- Tell us how we can help. Please do not enter personal information that is not requested below. -

+

Tell us how we can help. Please do not enter personal information that is not requested below.

`; } @@ -226,6 +226,7 @@ export class ContactView extends LitElement { ${ref(this.formRef)} .variant=${this.variant} .disabled=${this.isFormSubmitting} + .values=${this.formValues} @cancel=${this.reset} @submit=${this.submitForm} > @@ -235,17 +236,11 @@ export class ContactView extends LitElement { render() { switch (this.step) { case Step.FORM: { - return html` - ${this.renderIntroTemplate} ${this.renderForm} - `; + return html` ${this.renderIntroTemplate} ${this.renderForm} `; } case Step.EXIT: { - return html` - - ${this.exitTemplate} - - `; + return html` ${this.exitTemplate} `; } case Step.ISSUE_WIZARD: @@ -256,21 +251,20 @@ export class ContactView extends LitElement {
    ${this.openTicketSelectionOptions.map( - element => - html` -
  1. - - - - -
  2. - ` + element => html` +
  3. + + + + +
  4. + ` )}
diff --git a/src/www/views/contact_view/support_form/index.ts b/src/www/views/contact_view/support_form/index.ts index fa42f554a4a..a54e55da3a2 100644 --- a/src/www/views/contact_view/support_form/index.ts +++ b/src/www/views/contact_view/support_form/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {html, css, LitElement, TemplateResult, nothing} from 'lit'; +import {html, css, LitElement, TemplateResult, nothing, PropertyValues} from 'lit'; import {createRef, Ref, ref} from 'lit/directives/ref.js'; import {live} from 'lit/directives/live.js'; import {customElement, property, state} from 'lit/decorators.js'; @@ -78,21 +78,23 @@ export class SupportForm extends LitElement { @property({type: Boolean}) disabled = false; @property({type: String}) variant: AppType = AppType.CLIENT; + @property({type: Object}) values: FormValues = {}; private readonly formRef: Ref = createRef(); - @state() private formData: FormValues = {}; + @state() valid = false; - @state() private isFormValid = false; + override updated(changedProperties: PropertyValues) { + super.updated(changedProperties); + + if (changedProperties.has('values')) { + queueMicrotask(() => this.checkFormValidity()); + } + } /** Checks the entire form's validity state. */ private checkFormValidity() { const fieldNodes = this.formRef.value.querySelectorAll('*[name]'); - this.isFormValid = Array.from(fieldNodes).every(field => field.validity.valid); - } - - /** Resets the form. */ - reset() { - this.formData = {}; + this.valid = Array.from(fieldNodes).every(field => field.validity.valid); } /** Cancels the form. */ @@ -108,14 +110,17 @@ export class SupportForm extends LitElement { e.preventDefault(); e.stopPropagation(); - if (!this.isFormValid) { - throw Error('Cannot submit invalid form.'); - } - - const event = new CustomEvent('submit', {detail: this.formData}); + const event = new CustomEvent('submit', {detail: true}); this.dispatchEvent(event); } + private handleTextInput(e: Event) { + const key: keyof FormValues = (e.target as TextField).name as keyof FormValues; + const value = (e.target as TextField).value; + this.values[key] = value; + this.checkFormValidity(); + } + private get renderCloudProviderInputField(): TemplateResult | typeof nothing { if (this.variant !== AppType.MANAGER) return nothing; @@ -138,23 +143,18 @@ export class SupportForm extends LitElement { label="Cloud provider" helper="Which cloud provider does this relate to?" helperPersistent - .value=${live(this.formData.cloudProvider ?? '')} + .value=${live(this.values.cloudProvider ?? '')} + .disabled=${this.disabled} + required + outlined @selected=${(e: CustomEvent>) => { if (e.detail.index !== -1) { - this.formData.cloudProvider = providers[e.detail.index][0]; + this.values.cloudProvider = providers[e.detail.index][0]; } }} - .disabled=${this.disabled} - required - outlined @blur=${this.checkFormValidity} > - ${providers.map( - ([value, label]) => - html` - ${label} - ` - )} + ${providers.map(([value, label]) => html` ${label} `)} `; } @@ -165,15 +165,15 @@ export class SupportForm extends LitElement { return html` (this.formData.source = (e.target as TextField).value)} + .value=${live(this.values.source ?? '')} .maxLength=${SupportForm.DEFAULT_MAX_LENGTH_INPUT} .disabled=${this.disabled} required outlined + @input=${this.handleTextInput} @blur=${this.checkFormValidity} > `; @@ -184,47 +184,47 @@ export class SupportForm extends LitElement {
(this.formData.email = (e.target as TextField).value)} + .value=${live(this.values.email ?? '')} .maxLength=${SupportForm.DEFAULT_MAX_LENGTH_INPUT} autoValidate validationMessage="Please provide a correct email address." .disabled=${this.disabled} required outlined + @input=${this.handleTextInput} @blur=${this.checkFormValidity} > ${this.renderCloudProviderInputField} ${this.renderAccessKeySourceInputField} (this.formData.subject = (e.target as TextField).value)} + .value=${live(this.values.subject ?? '')} .maxLength=${SupportForm.DEFAULT_MAX_LENGTH_INPUT} .disabled=${this.disabled} required outlined + @input=${this.handleTextInput} @blur=${this.checkFormValidity} > (this.formData.description = (e.target as TextField).value)} + .value=${live(this.values.description ?? '')} rows="5" .maxLength=${SupportForm.MAX_LENGTH_DESCRIPTION} .disabled=${this.disabled} required outlined + @input=${this.handleTextInput} @blur=${this.checkFormValidity} > @@ -239,7 +239,7 @@ export class SupportForm extends LitElement { diff --git a/src/www/views/contact_view/support_form/stories.ts b/src/www/views/contact_view/support_form/stories.ts index 094b7b1a685..bf17f8e674a 100644 --- a/src/www/views/contact_view/support_form/stories.ts +++ b/src/www/views/contact_view/support_form/stories.ts @@ -20,6 +20,7 @@ import {html} from 'lit'; import './index'; import {AppType} from '../app_type'; +import {FormValues} from './index'; export default { title: 'Contact View/Support Form', @@ -44,7 +45,7 @@ export default { }, }; -export const Example = ({ +export const EmptyForm = ({ variant, disabled, onCancel, @@ -54,7 +55,35 @@ export const Example = ({ disabled: boolean; onCancel: Function; onSubmit: Function; -}) => - html` - +}) => html` + +`; + +export const CompleteForm = ({ + variant, + disabled, + onCancel, + onSubmit, +}: { + variant: AppType; + disabled: boolean; + onCancel: Function; + onSubmit: Function; +}) => { + const values: FormValues = { + email: 'foo@bar.com', + subject: 'My Test Subject', + description: 'My Test Description', + source: 'a friend', + cloudProvider: 'digitalocean', + }; + return html` + `; +};