]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/ui/framework/forms.ts
Lexical: Media form improvements
[bookstack] / resources / js / wysiwyg / ui / framework / forms.ts
index a2db34dd7a12ade9f94b6a5a4deedbb68e41e7b4..b12d9f692fca9e1d4ca15070b160c5a1b21b50b9 100644 (file)
@@ -11,7 +11,7 @@ import {el} from "../../utils/dom";
 export interface EditorFormFieldDefinition {
     label: string;
     name: string;
-    type: 'text' | 'select' | 'textarea';
+    type: 'text' | 'select' | 'textarea' | 'checkbox' | 'hidden';
 }
 
 export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefinition {
@@ -19,15 +19,17 @@ export interface EditorSelectFormFieldDefinition extends EditorFormFieldDefiniti
     valuesByLabel: Record<string, string>
 }
 
+export type EditorFormFields = (EditorFormFieldDefinition|EditorUiBuilderDefinition)[];
+
 interface EditorFormTabDefinition {
     label: string;
-    contents: EditorFormFieldDefinition[];
+    contents: EditorFormFields;
 }
 
 export interface EditorFormDefinition {
     submitText: string;
     action: (formData: FormData, context: EditorUiContext) => Promise<boolean>;
-    fields: (EditorFormFieldDefinition|EditorUiBuilderDefinition)[];
+    fields: EditorFormFields;
 }
 
 export class EditorFormField extends EditorUiElement {
@@ -40,7 +42,12 @@ export class EditorFormField extends EditorUiElement {
 
     setValue(value: string) {
         const input = this.getDOMElement().querySelector('input,select,textarea') as HTMLInputElement;
-        input.value = value;
+        if (this.definition.type === 'checkbox') {
+            input.checked = Boolean(value);
+        } else {
+            input.value = value;
+        }
+        input.dispatchEvent(new Event('change'));
     }
 
     getName(): string {
@@ -54,10 +61,15 @@ export class EditorFormField extends EditorUiElement {
         if (this.definition.type === 'select') {
             const options = (this.definition as EditorSelectFormFieldDefinition).valuesByLabel
             const labels = Object.keys(options);
-            const optionElems = labels.map(label => el('option', {value: options[label]}, [label]));
+            const optionElems = labels.map(label => el('option', {value: options[label]}, [this.trans(label)]));
             input = el('select', {id, name: this.definition.name, class: 'editor-form-field-input'}, optionElems);
         } else if (this.definition.type === 'textarea') {
             input = el('textarea', {id, name: this.definition.name, class: 'editor-form-field-input'});
+        } else if (this.definition.type === 'checkbox') {
+            input = el('input', {id, name: this.definition.name, type: 'checkbox', class: 'editor-form-field-input-checkbox', value: 'true'});
+        } else if (this.definition.type === 'hidden') {
+            input = el('input', {id, name: this.definition.name, type: 'hidden'});
+            return el('div', {hidden: 'true'}, [input]);
         } else {
             input = el('input', {id, name: this.definition.name, class: 'editor-form-field-input'});
         }
@@ -72,6 +84,7 @@ export class EditorFormField extends EditorUiElement {
 export class EditorForm extends EditorContainerUiElement {
     protected definition: EditorFormDefinition;
     protected onCancel: null|(() => void) = null;
+    protected onSuccessfulSubmit: null|(() => void) = null;
 
     constructor(definition: EditorFormDefinition) {
         let children: (EditorFormField|EditorUiElement)[] = definition.fields.map(fieldDefinition => {
@@ -98,6 +111,10 @@ export class EditorForm extends EditorContainerUiElement {
         this.onCancel = callback;
     }
 
+    setOnSuccessfulSubmit(callback: () => void) {
+        this.onSuccessfulSubmit = callback;
+    }
+
     protected getFieldByName(name: string): EditorFormField|null {
 
         const search = (children: EditorUiElement[]): EditorFormField|null => {
@@ -128,10 +145,13 @@ export class EditorForm extends EditorContainerUiElement {
             ])
         ]);
 
-        form.addEventListener('submit', (event) => {
+        form.addEventListener('submit', async (event) => {
             event.preventDefault();
             const formData = new FormData(form as HTMLFormElement);
-            this.definition.action(formData, this.getContext());
+            const result = await this.definition.action(formData, this.getContext());
+            if (result && this.onSuccessfulSubmit) {
+                this.onSuccessfulSubmit();
+            }
         });
 
         cancelButton.addEventListener('click', (event) => {
@@ -147,11 +167,17 @@ export class EditorForm extends EditorContainerUiElement {
 export class EditorFormTab extends EditorContainerUiElement {
 
     protected definition: EditorFormTabDefinition;
-    protected fields: EditorFormField[];
+    protected fields: EditorUiElement[];
     protected id: string;
 
     constructor(definition: EditorFormTabDefinition) {
-        const fields = definition.contents.map(fieldDef => new EditorFormField(fieldDef));
+        const fields = definition.contents.map(fieldDef => {
+            if (isUiBuilderDefinition(fieldDef)) {
+                return fieldDef.build();
+            }
+            return new EditorFormField(fieldDef)
+        });
+
         super(fields);
 
         this.definition = definition;