Jake Vanderwerf
2025-10-18 b0194e10a87e16797a568d8a30d53ebecd27d8a4
assets/js/concise/TaxonomySelector.js
@@ -8,9 +8,25 @@
      this.error = window.jvbError;
      this.index = -1;
      // DataStore instances per taxonomy
      this.stores = new Map();
      this.storeSubscriptions = new Map();
      this.store = new window.jvbStore({
         name: `taxonomies`,
         storeName: `terms`,
         keyPath: 'id',
         indexes: [
            {name: 'taxonomy', keyPath: 'taxonomy'},
            {name: 'parent', keyPath: 'parent'},
            {name: 'slug', keyPath: 'slug', unique: true},
            {name: 'count', keyPath: 'count'},
         ],
         endpoint: 'terms',
         TTL: 7200000, //2 hours
         filters: {
            taxonomy: '',
            page: 1,
            search: '',
            parent: 0
         }
      });
      // Central field management
      this.fields = new Map();
@@ -39,35 +55,8 @@
      this.initModal();
      this.scanExistingFields();
      this.initGlobalListeners();
   }
   /**
    * Get or create a DataStore for a taxonomy
    */
   getOrCreateStore(taxonomy) {
      if (!this.stores.has(taxonomy)) {
         const store = new window.jvbStore({
            name: `tax_${taxonomy}`,
            endpoint: 'terms',
            TTL: 3600000, // 1 hour cache
            filters: {
               taxonomy: taxonomy,
               page: 1,
               search: '',
               parent: 0
            }
         });
         // Subscribe to store events
         const unsubscribe = store.subscribe((event, data) => {
            this.handleStoreEvent(taxonomy, event, data);
         });
         this.stores.set(taxonomy, store);
         this.storeSubscriptions.set(taxonomy, unsubscribe);
      }
      return this.stores.get(taxonomy);
      this.store.subscribe(this.handleStoreEvent.bind(this));
   }
   /**
@@ -227,7 +216,7 @@
      this.fields.set(fieldId, config);
      // Ensure store exists for this taxonomy
      this.getOrCreateStore(config.taxonomy);
      this.store.setFilter('taxonomy', config.taxonomy);
      // Initialize display for any pre-selected values
      if (config.selectedTerms.size > 0) {
@@ -252,7 +241,6 @@
      const field = this.fields.get(fieldId);
      if (!field || field.selectedTerms.size === 0) return;
      const store = this.getOrCreateStore(field.taxonomy);
      const selectedIds = Array.from(field.selectedTerms);
      // Check store for cached terms first
@@ -260,7 +248,7 @@
      const needsFetch = [];
      selectedIds.forEach(termId => {
         const term = store.getItem(termId);
         const term = this.store.getItem(termId);
         if (term) {
            cachedTerms.push(term);
         } else {
@@ -276,7 +264,8 @@
      // Fetch missing terms if needed
      if (needsFetch.length > 0) {
         try {
            const response = await store.fetch('terms', {
            const response = await this.store.fetch({
               filters: {
                  taxonomy: field.taxonomy,
                  termIDs: needsFetch.join(',')
@@ -285,7 +274,7 @@
            if (response.terms) {
               response.terms.forEach(term => {
                  store.setItem(term.id, term);
                  this.store.setItem(term.id, term);
                  this.addTermToDisplay(fieldId, term.id, term.name, term.path);
               });
            }
@@ -483,15 +472,16 @@
      this.currentPlural = jvbSettings.labels[this.currentConfig.taxonomy].plural;
      // Get or create store for this taxonomy
      this.activeStore = this.getOrCreateStore(this.currentConfig.taxonomy);
      this.store.setFilter('taxonomy', this.currentConfig.taxonomy);
      // Clear modal selection state
      this.selectedTerms.clear();
      // Copy field's current selections to modal state
      if (this.currentConfig.selectedTerms) {
         let termsToFetch = [];
         this.currentConfig.selectedTerms.forEach(termId => {
            const term = this.activeStore.getItem(termId);
            const term = this.store.getItem(termId);
            if (term) {
               this.selectedTerms.set(termId, {
                  id: termId,
@@ -499,16 +489,25 @@
                  path: term.path
               });
            } else {
               // If not in store, create minimal entry
               this.selectedTerms.set(termId, {
                  id: termId,
                  name: `Term ${termId}`,
                  path: `Term ${termId}`
               });
               termsToFetch.push(termId);
            }
         });
         if (termsToFetch.length > 0) {
            let terms = this.fetchSpecificTerms(termsToFetch);
            terms.forEach(term => {
               this.selectedTerms.set(term.id, {
                  id: term.id,
                  name: term.name,
                  path: term.path
               });
            });
      }
   }
   }
   fetchSpecificTerms(terms) {
      return [];
   }
   /**
    * Handle clicks within modal
@@ -1183,16 +1182,11 @@
      // Clear intervals and cleanup
      this.observer?.disconnect();
      // Unsubscribe from all stores
      this.storeSubscriptions.forEach(unsubscribe => unsubscribe());
      // Destroy all stores
      this.stores.forEach(store => store.destroy());
      this.store.destroy();
      // Clear all maps
      this.fields.clear();
      this.stores.clear();
      this.storeSubscriptions.clear();
      this.selectedTerms.clear();
   }
}