Jake Vanderwerf
2026-01-22 58e8ae0759ccfa97c478ccae4e0778bdce70966f
assets/js/concise/CRUD.js
@@ -362,7 +362,7 @@
                        this.forms.clearForm(formId);
                     }
                     this.ui.modals[name].form.reset();
                     this.resetForm(this.ui.modals[name].form);
                     if (name === 'date') {
                        this.handleCustomDateSelection()
@@ -626,7 +626,9 @@
      } else if (modal.classList.contains('create')) {
         title = `Creating your new ${this.singular}`;
      }
      this.savePosts(title,false);
      this.cancelBackup();
      this.handleBackup().then(()=>{});
      this.savePosts(title,false).then(()=>{});
   }
   handleChange(e) {
      // Early bailout - target must be in an item or be a filter
@@ -706,11 +708,8 @@
   handleBulkTaxonomy(result) {
      if (!result.termIds.length || !this.selected.size) return;
      const changes = {};
      const taxonomyField = `tax_${result.taxonomy}`;
      this.selected.forEach(itemID => {
         const item = this.store.get(parseInt(itemID));
         const item = this.store.get(itemID);
         if (!item) return;
         // Merge existing terms with new ones
@@ -718,18 +717,10 @@
         const existingIds = existingTerms.map(t => t.id);
         const newIds = [...new Set([...existingIds, ...result.termIds])];
         changes[itemID] = {
            [taxonomyField]: newIds.join(','),
            content: this.content
         };
         this.updateItem(itemID, result.taxonomy, newIds);
      });
      if (Object.keys(changes).length > 0) {
         this.savePosts(
            `Adding ${result.terms.length} ${result.taxonomy} to ${this.selected.size} ${this.plural}...`,
            false
         ).then(()=>{});
      }
      this.savePosts(`Adding ${result.terms.length} ${result.taxonomy} to ${this.selected.size} ${this.plural}...`,).then(()=> {});
      this.selectionHandler.clearSelection();
   }
@@ -759,13 +750,20 @@
         `changes-${this.content}`,
         async () => {
            if (this.changes.size > 0) {
               await this.changesStore.saveMany(this.changes);
               this.changes.clear();
               await this.handleBackup();
            }
         },
         2000
      );
   }
   cancelBackup() {
      window.debouncer.cancel(`changes-${this.content}`);
   }
   async handleBackup() {
      await this.changesStore.saveMany(this.changes);
      this.changes.clear();
   }
   handleFilterChange(target) {
      let filter = target.dataset.filter;
@@ -875,7 +873,6 @@
      }
   }
      openCreateModal(){
         this.ui.modals.create.form.reset();
         this.forms.registerForm(this.ui.modals.create.form,{
            cache: false,
         });
@@ -899,9 +896,18 @@
               }
               break;
            case 'trash':
               this.updateItem(itemID, 'post_status', 'trash');
               window.fade(button.closest('.item'), false);
               this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{});
               if (this.status === 'trash') {
                  if (confirm('Delete this item? This cannot be undone')) {
                     this.updateItem(itemID, 'post_status', 'delete');
                     window.fade(button.closest('.item'), false);
                     this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{});
                     this.store.delete(itemID);
                  }
               } else {
                  this.updateItem(itemID, 'post_status', 'trash');
                  window.fade(button.closest('.item'), false);
                  this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{});
               }
               break;
            case 'bulk-edit':
               if (this.selected.size > 0) {
@@ -921,7 +927,7 @@
         }
      }
      handleBulkDelete() {
         let isTrash = this.store.filters.status === 'trash';
         let isTrash = this.status === 'trash';
         if (this.selected.size > 0 && confirm(`${isTrash ? 'Permanently delete' : 'Send'} ${this.selected.size} ${this.selected.size === 1 ? this.singular : this.plural}${isTrash ? '' : 'to trash'}?`)) {
            this.selected.forEach(id => {
               this.store.delete(id);
@@ -1082,8 +1088,6 @@
      this.ui.modals.edit.h2.textContent = `Editing ${item.fields.post_title === '' ? this.singular : item.fields.post_title}`;
      this.ui.modals.edit.form.dataset.formId = `edit-${itemID}`;
      this.ui.modals.edit.form.reset();
      this.forms.registerForm(this.ui.modals.edit.form, {cache: false});
      this.isPopulating = true;
@@ -1118,9 +1122,9 @@
      this.forms.registerForm(this.ui.modals.bulkEdit.form, {cache:false});
      // this.isPopulating = true;
      // this.populate.populate(this.ui.modals.edit.form, item);
      // this.isPopulating = false;
      this.isPopulating = true;
      this.populate.populate(this.ui.modals.edit.form, item);
      this.isPopulating = false;
   }
   /*****************************************************************
@@ -1128,9 +1132,12 @@
   *****************************************************************/
   async savePosts(title = '', delay = false) {
      const memoryChanges = Array.from(this.changes.values());
      const storedChanges = await this.changesStore.getAll();
      const changes = window.deepMerge(storedChanges, memoryChanges);
      if (this.changes.size > 0) {
         this.cancelBackup();
         await this.handleBackup();
      }
      const changes = await this.changesStore.getAll();
      if (changes.length === 0) return;
      if (title === '') {
@@ -1221,11 +1228,13 @@
   updateUI() {
      if (this.ui.bulk.action) {
         let options = false;
         let hasEdit =this.ui.bulk.action.querySelector('[value="edit"]');
         if (this.status === 'trash' && hasEdit) {
         let hasEdit = this.ui.bulk.action.querySelector('[value="edit"]');
         let currentStatus = this.status;
         if (currentStatus === 'trash' && hasEdit) {
            window.removeChildren(this.ui.bulk.action);
            options = window.jvbTemplates.create('trashOptions');
         } else if (this.status !== 'trash' && !hasEdit) {
         } else if (currentStatus !== 'trash' && !hasEdit) {
            window.removeChildren(this.ui.bulk.action);
            options = window.jvbTemplates.create('notTrashOptions');
         }
@@ -1387,9 +1396,13 @@
   setFilter(name, value) {
      if (!this.allowedFilters.includes(name)) return;
      this.cache.set(name, value);
      if (name === 'status') this.status = value;
      if (name === 'orderby') this.orderby = value;
      if (name === 'order') this.order = value;
      let el = this.findFilterEl(name, value);
      this.setElValue(el, value);
      //TODO: If we set the element to checked, does that automatically call the change listener, which then also sets the store filter and cache?
      this.store.setFilter(name, value);
   }
@@ -1461,6 +1474,32 @@
   /***************************************************************
    CLEANUP
   ***************************************************************/
   resetForm(form) {
      // Clear text inputs, textareas
      form.querySelectorAll('input[type="hidden"], input[type="text"], input[type="number"], input[type="email"], input[type="url"], textarea').forEach(input => {
         input.value = '';
      });
      // Uncheck checkboxes and radios
      form.querySelectorAll('input[type="checkbox"], input[type="radio"]').forEach(input => {
         input.checked = false;
      });
      // Reset selects to first option
      form.querySelectorAll('select').forEach(select => {
         select.selectedIndex = 0;
      });
      // Clear any selected items displays
      form.querySelectorAll('.selected-items').forEach(container => {
         window.removeChildren(container);
      });
      // Clear upload previews
      form.querySelectorAll('.item-grid.preview').forEach(grid => {
         window.removeChildren(grid);
      });
   }
   destroy() {
      window.debouncer.cancel(`changes-${this.content}`);
      if (this.changes.size > 0) {