Jake Vanderwerf
2025-12-23 25be5747a6e462a3d09fc6607b3639b79e4d9374
assets/js/concise/UploadManager.js
@@ -112,7 +112,7 @@
   }
   async init() {
      this.initializeFields();
      // this.initializeFields();
      this.initListeners();
      // Queue integration - handle completion/failure
@@ -165,21 +165,18 @@
   /*******************************************************************************
    * FIELD MANAGEMENT
    *******************************************************************************/
   initializeFields() {
      const fields = document.querySelectorAll(this.selectors.field.field);
      fields.forEach(uploader => this.registerUploader(uploader));
   }
   scanFields(container) {
   scanFields(container, autoUpload) {
      console.log(autoUpload, 'autoUpload');
      const fields = container.querySelectorAll(this.selectors.field.field);
      fields.forEach(uploader => this.registerUploader(uploader));
      fields.forEach(uploader => this.registerUploader(uploader, autoUpload));
   }
   registerUploader(uploader) {
   registerUploader(uploader, autoUpload) {
      const fieldId = this.determineFieldId(uploader);
      const config = this.extractFieldConfig(uploader);
      const config = this.extractFieldConfig(uploader, autoUpload);
      const ui = this.buildFieldUI(uploader);
      console.log(config, 'registering with config');
      // Store field data with Sets for runtime
      const fieldData = {
         id: fieldId,
@@ -206,8 +203,9 @@
      return fieldId;
   }
   extractFieldConfig(fieldElement) {
   extractFieldConfig(fieldElement, autoUpload) {
      return {
         autoUpload: autoUpload,
         destination: fieldElement.dataset.destination || 'meta',
         content: fieldElement.dataset.content || null,
         mode: fieldElement.dataset.mode || 'direct',
@@ -493,8 +491,6 @@
      const fieldWrapper = grid.closest('.field, .upload');
      if (!fieldWrapper) return;
      const movedItems = evt.items && evt.items.length > 0 ? evt.items : [evt.item];
      // Get current order from DOM
      let items = Array.from(grid.querySelectorAll('.item:not(.sortable-ghost):not(.sortable-clone)'))
         .map(upload => upload.dataset.uploadId)
@@ -640,6 +636,9 @@
      // Meta field changes
      if (fieldId) {
         const fieldData = this.getFieldData(fieldId);
         if (!fieldData.config.autoUpload) {
            return;
         }
         if (fieldData?.config.destination === 'post_group') {
            this.handleGroupMetaChange(e.target);
         } else {
@@ -760,7 +759,7 @@
      this.refreshSortable(fieldId);
      // Queue for upload if in direct mode
      if (fieldData.config.destination !== 'post_group') {
      if (fieldData.config.autoUpload && fieldData.config.destination !== 'post_group') {
         await this.queueUpload(fieldId);
         this.maybeLockUploads(fieldId);
      }
@@ -1554,7 +1553,8 @@
      this.refreshSortable(fieldKey);
      // Queue for upload if needed
      if (config.mode === 'direct' && config.destination !== 'post_group') {
      console.log(config);
      if (config.autoUpload && config.mode === 'direct' && config.destination !== 'post_group') {
         await this.queueUpload(fieldKey);
      }
   }
@@ -2488,16 +2488,6 @@
      // Can add custom logic here if needed
   }
   getCurrentSelection(fieldId) {
      let selected = [];
      for (let [key, handler] of this.selectionHandlers) {
         if ((fieldId === key || key.includes(fieldId)) && handler.selectedItems.size > 0) {
            selected = selected.concat([...handler.selectedItems]);
         }
      }
      return selected;
   }
   /*******************************************************************************
    * HELPER METHODS
    *******************************************************************************/
@@ -2632,27 +2622,6 @@
      return progress[status] || 0;
   }
   getModalType(fieldEl) {
      if (!fieldEl?.element) return null;
      if (fieldEl._cachedModalType !== undefined) {
         return fieldEl._cachedModalType;
      }
      const dialog = fieldEl.element.closest('dialog');
      if (!dialog) {
         fieldEl._cachedModalType = null;
         return null;
      }
      let modalType = null;
      if (dialog.classList.contains('edit')) modalType = 'edit';
      else if (dialog.classList.contains('create')) modalType = 'create';
      else if (dialog.classList.contains('bulkEdit')) modalType = 'bulkEdit';
      else modalType = dialog.className;
      fieldEl._cachedModalType = modalType;
      return modalType;
   }
   createUploadElement(upload, draggable = false) {
      let image = window.getTemplate('uploadItem');
@@ -2728,34 +2697,6 @@
    * PERSISTENCE
    *******************************************************************************/
   /**
    * Normalize field data loaded from IndexedDB
    * Converts Arrays back to Sets, handles missing properties
    */
   normalizeFieldData(fieldData) {
      if (!fieldData) return null;
      // Convert uploads array back to Set
      if (Array.isArray(fieldData.uploads)) {
         fieldData.uploads = new Set(fieldData.uploads);
      } else if (!fieldData.uploads) {
         fieldData.uploads = new Set();
      }
      // Convert groups array, ensure proper structure
      if (!Array.isArray(fieldData.groups)) {
         fieldData.groups = [];
      }
      // Ensure each group has uploads array
      fieldData.groups = fieldData.groups.map(group => ({
         ...group,
         uploads: Array.isArray(group.uploads) ? group.uploads : []
      }));
      return fieldData;
   }
   schedulePersistance(fieldId) {
      const key = `persist_${fieldId}`;
      window.debouncer.schedule(
@@ -2804,6 +2745,56 @@
   }
   /*******************************************************************************
    HELPER to GET UPLOADED FILES
   *******************************************************************************/
   /**
    * Get all files for a form (searches all upload fields within form)
    */
   async getFilesForForm(formElement) {
      const uploadFields = formElement.querySelectorAll('[data-upload-field]');
      const allFiles = [];
      for (const field of uploadFields) {
         const fieldId = this.determineFieldId(field);
         const files = await this.getFilesForField(fieldId);
         allFiles.push(...files);
      }
      return allFiles;
   }
   /**
    * Get all files for a specific field
    */
   async getFilesForField(fieldId) {
      const fieldData = this.getFieldData(fieldId);
      if (!fieldData?.uploads) return [];
      const files = [];
      const uploadsArray = fieldData.uploads instanceof Set
         ? Array.from(fieldData.uploads)
         : fieldData.uploads;
      for (const uploadId of uploadsArray) {
         const upload = this.uploadStore.get(uploadId);
         if (!upload) continue;
         // Get the actual File object from blob data
         const file = await this.getBlobData(uploadId);
         if (file) {
            files.push({
               file: file,
               uploadId: uploadId,
               fieldName: fieldData.config.name,
               meta: upload.meta || {}
            });
         }
      }
      return files;
   }
   /*******************************************************************************
    * RECOVERY & RESTORATION
    *******************************************************************************/
@@ -2856,7 +2847,7 @@
      });
      if (pendingFields.length === 0) return;
      this.showRecoveryNotification(pendingFields);
      await this.showRecoveryNotification(pendingFields);
   }
   async showRecoveryNotification(pendingFields) {