Jake Vanderwerf
10 days ago de317675a8069b747cb253ba3e2b5dc394ca36ef
assets/js/concise/FormController.js
@@ -482,13 +482,14 @@
         } else {
            this.notify('form-submit', {
               config: form,
               data: this.changes.get(form.id)?.changes??{},
               data: this.changes.get(form.id)?.changes ?? {},
            });
         }
         if (form.options.endpoint && !form.options.handled) {
            console.log('Submitting form...');
            await this.handleServerSave(form, this.collectFormData(form.form));
         }
      }
      if (form.options.endpoint && !form.options.handled) {
         e.preventDefault();
         console.log('Submitting form...', this.changes.get(form.id)?.changes ?? {});
         await this.handleServerSave(form, this.changes.get(form.id)?.changes ?? {});
      }
@@ -526,7 +527,6 @@
      }
      if (form.tabs) {
         console.log('Updating step progress on change');
         this.updateStepProgress(form);
      }
@@ -668,18 +668,70 @@
   async handleServerSave(form, changes) {
      this.cancelServerSave(form.id);
      if (window.jvbQueue) {
         changes.user = window.auth.getUser();
      if (form.useQueue && window.jvbQueue) {
         // changes.user = window.auth.getUser();
         window.jvbQueue.addToQueue({
            endpoint: form.options.endpoint,
            data: changes,
            headers: form.options.headers??{},
         });
      } else {
         await window.auth.fetch(jvbBase.api+form.options.endpoint, {
            body: changes,
            headers: form.options.headers??{},
         });
         try {
            let response = await window.auth.fetch(jvbSettings.api+form.options.endpoint, {
               body: changes,
               headers: form.options.headers??{},
               method: 'POST',
            });
            if (!response.ok) {
               let errorDetails;
               try {
                  // Attempt to parse the server's error payload as JSON
                  errorDetails = await response.json();
               } catch {
                  // Fallback if the error response isn't JSON (e.g., HTML error page)
                  errorDetails = { message: response.statusText || 'Unknown HTTP error' };
               }
               this.notify('form-error', {
                  config: form,
                  data: errorDetails
               });
               return;
            }
            let result = await response.json();
            this.notify('form-success', {
               config: form,
               result: result
            });
         } catch (error) {
            if (error.status) {
               this.notify('form-error', {
                  config: form,
                  data: error
               });
               // This is an HTTP error thrown manually (e.g., 404, 500)
            } else if (error instanceof SyntaxError) {
               this.notify('form-error', {
                  config: form,
                  data: {
                     status: 'error',
                     success: false,
                     message: 'Something went wrong'
                  }
               });
               // This happens if response.json() fails on a successful 200 OK response
               console.error('Data Error: Server returned invalid JSON format.');
            } else {
               this.notify('form-error', {
                  config: form,
                  data: {
                     status: 'network_error',
                     message: 'Network error: could not connect to the server'
                  }
               });
            }
         }
      }
   }
@@ -694,6 +746,7 @@
         autoUpload: false,
         imageMeta: true,
         delay: 1500,
         useQueue: true,
         endpoint: Object.hasOwn(form.dataset, 'save') ? form.dataset.save: '',
         showStatus: true,
         showSummary: false,
@@ -709,6 +762,9 @@
      if (!Object.hasOwn(form.dataset, 'formId')) {
         form.dataset.formId = window.generateID('form_');
      }
      if (Object.hasOwn(form.dataset, 'action')) {
         options.headers = window.auth.getHeader(form.dataset.action);
      }
      const formId = form.dataset.formId;
      this.addFormListeners(form);
@@ -844,7 +900,7 @@
               p: 'p',
            },
            setup({ el, refs, manyRefs, data }) {
               const skipFields = ['sendAll', ...data.config.options.ignore??[]];
               const skipFields = ['sendAll', ...data?.config?.options?.ignore??[]];
               for (let [key, value] of Object.entries(data.changes)) {
                  if (skipFields.includes(key) || form.isEmptyValue(value)) continue;
@@ -898,8 +954,6 @@
               }
               refs.result?.remove();
               data.config.element.after(el);
               window.fade(data.config.element, false);
            }
         }
      );
@@ -1610,6 +1664,12 @@
      field.classList.remove('has-success');
      field.classList.add('has-error');
      field.scrollIntoView({
         behavior: "smooth",
         block: "center",
         inline: "nearest"
      });
      field.querySelector(this.inputSelectors)?.focus();
      if (item.ui.message) {
         item.ui.message.hidden = false;
@@ -2300,6 +2360,9 @@
   window.auth.subscribe(event => {
      if (event === 'auth-loaded') {
         window.jvbForm = new FormController();
         document.querySelectorAll('form[data-auto]').forEach(form => {
            window.jvbForm.registerForm(form, {});
         });
      }
   });
});