| | |
| | | window.jvbTaxCreator=class{constructor(e){this.selector=e,this.taxonomy=e.currentConfig?.taxonomy,this.taxonomy?(this.createNew=e.modal.querySelector(".create-new-term"),this.toggle=e.modal.querySelector(".new-term-toggle"),this.form=this.createNew.querySelector(".create-new-term-section"),this.initListeners(),this.initTermCreation()):console.error("TaxonomyCreator: No active field or taxonomy found")}initListeners(){this.clickHandler=this.handleClick.bind(this),document.addEventListener("click",this.clickHandler)}handleClick(e){window.targetCheck(e,".create-new-term summary")&&(this.createNew.open&&this.createNew.querySelector('input[name="term_name"]').focus(),this.resetParentOptions()),window.targetCheck(e,".submit-term")&&this.handleTermCreation(e),window.targetCheck(e,".create-term")&&this.handleAutocompleteCreate(e)}async handleTermCreation(e){const t=this.form.querySelector('input[name="term_name"]').value.trim(),r=parseInt(this.form.querySelector("input#select_parent")?.value)||0;if(t)try{this.form.querySelector("button").disabled=!0;const e=await this.createTerm(t,r);if(e.success&&e.term){let t=e.term;this.createNew.open=!1,await this.selector.store.invalidate({taxonomy:this.taxonomy}),this.selector.addSelectedTermToModal(t.id,t.name,t.path||t.name),(this.selector.store.filters.parent||0)===r&&await this.selector.store.setFilters({taxonomy:this.taxonomy,parent:r,page:1,search:""}),this.form.querySelector('input[name="term_name"]').value="";const n=this.createNew.querySelector(".term-suggestions");n&&(n.hidden=!0)}}catch(e){console.error("Error creating term:",e),this.selector.error?.log(e,{component:"TaxonomyCreator",action:"handleTermCreation"})||console.error("Failed to create term")}finally{this.form.querySelector("button").disabled=!1}}async handleAutocompleteCreate(e){const t=e.target,r=this.selector.getFieldId(t),n=this.selector.fields.get(r);if(!n)return;const o=n.container.querySelector("input[data-autocomplete]"),a=o?.value.trim()||t.dataset.query;if(a)try{t.disabled=!0;const e=t.innerHTML;t.textContent="Creating...";const r=await this.createTerm(a,0);if(r.success&&r.term){const e=r.term;n.selectedTerms.add(parseInt(e.id)),this.selector.addTermToDisplay(n.id,e.id,e.name,e.path||e.name),n.input.value=Array.from(n.selectedTerms).join(","),n.input.dispatchEvent(new Event("change",{bubbles:!0})),n.autocompleteDropdown.hidden=!0,o&&(o.value=""),await this.selector.store.setFilter("taxonomy",n.taxonomy)}else t.innerHTML=e}catch(e){console.error("Error creating term:",e),t.textContent="Failed - Try again",setTimeout((()=>{t.innerHTML=`<strong>Create:</strong> "${a}"`,t.disabled=!1}),2e3)}}initTermCreation(){this.form&&this.form.addEventListener("change",(e=>{e.preventDefault(),e.stopPropagation()}))}resetParentOptions(){let e=this.createNew.querySelector("#select_parent");if(!e)return;let t=e.querySelector("option");if(!t)return;window.removeChildren(e),e.append(t.cloneNode(!0));const r=this.selector.store.filters.parent||0;if(0!==r){const n=this.selector.store.data.get(r);if(n){let r=t.cloneNode(!0);r.value=n.id,r.textContent=n.name,e.append(r)}}const n=[];this.selector.store.data.forEach((e=>{e.taxonomy===this.taxonomy&&e.parent===r&&n.push(e)})),n.sort(((e,t)=>e.name.localeCompare(t.name))),n.forEach((r=>{let n=t.cloneNode(!0);n.id=`select-parent-${r.id}`,n.value=r.id,n.textContent=" — "+r.name,e.append(n)}))}async createTerm(e,t=0){let r=this.createNew.querySelector(".loading-message.create-term"),n=r?.querySelector("span");try{r&&(r.hidden=!1),n&&window.typeText?window.typeText(n,"Checking term..."):n&&(n.textContent="Checking term...");const o=await this.searchExistingTerms(e),a=o.filter((t=>t.name.toLowerCase()===e.toLowerCase()));if(a.length>0)return this.showTermSuggestions(a,!0),{success:!1,reason:"exists"};if(o.length>0)return this.showTermSuggestions(o,!1),{success:!1,reason:"similar"};n&&(n.textContent="Creating term...");const s=await fetch(`${jvbSettings.api}terms`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce},body:JSON.stringify({taxonomy:this.taxonomy,name:e,parent:t})});if(!s.ok)throw new Error(`Server error: ${s.status}`);return await s.json()}catch(e){throw console.error("Error creating term:",e),e}finally{this.form.querySelector("button").disabled=!1,r&&(r.hidden=!0)}}async searchExistingTerms(e){return new Promise((t=>{const r=(e,n)=>{"data-loaded"===e&&(this.selector.store.unsubscribe(r),t(n.data?.items||[]))};this.selector.store.subscribe(r),this.selector.store.setFilters({taxonomy:this.taxonomy,search:e,page:1,parent:0})}))}showTermSuggestions(e,t=!1){const r=this.createNew.querySelector(".term-suggestions")||this.createSuggestionContainer();window.removeChildren(r);const n=document.createElement("h4");n.textContent=t?"This term already exists:":"Similar terms already exist:",r.appendChild(n);const o=document.createElement("ul");o.className="term-suggestion-list",e.forEach((e=>{const t=document.createElement("li"),n=document.createElement("button");n.type="button",n.className="use-existing-term",n.setAttribute("data-id",e.id),n.textContent=e.path||e.name,n.addEventListener("click",(()=>{this.selector.addSelectedTermToModal(e.id,e.name,e.path||e.name),this.createNew.open=!1,r.hidden=!0,this.form.querySelector('input[name="term_name"]').value=""})),t.appendChild(n),o.appendChild(t)})),r.appendChild(o),r.hidden=!1}createSuggestionContainer(){const e=document.createElement("div");return e.className="term-suggestions",e.hidden=!0,this.createNew.querySelector("form").after(e),e}createAutocompleteOption(e,t){const r=document.createElement("button");return r.type="button",r.className="autocomplete-item create-term",r.innerHTML=`<span>Create "${e}"</span>`,r.dataset.query=e,r.dataset.fieldId=t.id,r.addEventListener("click",(async()=>{await this.handleAutocompleteCreate(r,e,t)})),r}async handleAutocompleteCreate(e,t,r){if(!r)return;const n=e.innerHTML;try{e.disabled=!0,e.innerHTML="<span>Creating...</span>";const n=0,o=await this.createTerm(t,n);if(o.success&&o.term){const e=o.term;r.selectedTerms.add(parseInt(e.id)),this.selector.addTermToDisplay(r.id,e.id,e.name,e.path||e.name),r.input.value=Array.from(r.selectedTerms).join(","),r.input.dispatchEvent(new Event("change",{bubbles:!0})),await this.selector.store.invalidate({taxonomy:r.taxonomy}),r.autocompleteDropdown.hidden=!0;const t=r.container.querySelector("input[data-autocomplete]");t&&(t.value="")}}catch(t){console.error("Error creating term:",t),e.innerHTML=n,e.disabled=!1,this.selector.error?.log(t,{component:"TaxonomyCreator",action:"handleAutocompleteCreate"})}}destroy(){this.clickHandler&&document.removeEventListener("click",this.clickHandler);const e=this.createNew?.querySelector(".loading-message.create-term");e&&(e.hidden=!0);const t=this.createNew?.querySelector(".term-suggestions");t&&(t.hidden=!0)}}; |
| | | window.jvbTaxCreator=class{constructor(e){this.selector=e,this.queue=window.jvbQueue,this.initElements(),this.initListeners()}initElements(){this.selectors={details:"details.create-term",parent:"#select_parent",summary:".create-term summary",suggestion:".term-suggestions",name:"#term_name",button:".submit-term",form:"form.create-term",label:{name:'[for="term_name"]',parent:'[for="select_parent"]'},loading:".loading-message.create-term"},this.ui=window.uiFromSelectors(this.selectors,this.selector.container)}handleOpen(e){this.field=e,this.ui.details&&(this.ui.details.hidden=!e.canCreate,this.ui.summary&&(this.ui.summary.textContent=`Add new ${e.singular}`),this.ui.label.name&&(this.ui.label.name.textContent=`Name this ${e.singular}`),this.ui.label.parent&&(this.ui.label.parent.textContent="Nest it under"))}initListeners(){this.clickHandler=this.handleClick.bind(this),document.addEventListener("click",this.clickHandler),this.ui.form&&this.ui.form.addEventListener("change",e=>{e.preventDefault(),e.stopPropagation()})}handleClick(e){if(window.targetCheck(e,this.selectors.summary))return this.ui.details.open&&this.ui.name?.focus(),void this.resetParentOptions()}async handleTermCreation(e){if(!e.name||e.name.length<2)return!1;try{const t=await this.createTerm(e);let i=this.selector.currentField();return t.success?t.term?.pending?(this.selector.setMessage(i,!0,`"${e.name}" submitted for approval`,!1),!1):(t.success&&t.term&&(await this.handleSuccessfulCreation(t.term,e),this.clearForm()),t.term):t.term&&t.term.id?(this.selector.setMessage(i,!0,`Using existing "${t.term.name}"`),t.term):(this.selector.setMessage(i,!0,t.message||"Creation failed",!1),!1)}catch(e){return console.error("Error creating term:",e),!1}}async handleSuccessfulCreation(e,t){const i={id:e.id,name:e.name,path:e.path||e.name,slug:e.slug||e.name.toLowerCase().replace(/\s+/g,"-"),parent:t.parent||0,taxonomy:t.taxonomy,count:0,hasChildren:!1};this.selector.store.data.set(e.id,i),this.ui.details&&(this.ui.details.open=!1),this.selector.store.clearCache(),this.selector.store.fetch().catch(e=>{console.warn("Background fetch after term creation failed:",e)})}resetParentOptions(){const e=this.selector.currentField();if(!e)return;const t=e.taxonomy;if(!t)return;if(!this.ui.parent)return;let i=this.ui.parent.querySelector("option");if(!i)return;window.removeChildren(this.ui.parent),this.ui.parent.append(i.cloneNode(!0));const r=this.selector.store.filters.parent||0;if(0!==r){const e=this.selector.store.get(r);if(e){let t=i.cloneNode(!0);t.value=e.id,t.textContent=e.name,this.ui.parent.append(t)}}const s=[];this.selector.store.getFiltered().forEach(e=>{e.taxonomy===t&&e.parent===r&&s.push(e)}),s.sort((e,t)=>e.name.localeCompare(t.name)),s.forEach(e=>{let t=i.cloneNode(!0);t.id=`select-parent-${e.id}`,t.value=e.id,t.textContent=" — "+e.name,this.ui.parent.append(t)})}async createTerm(e){if(e.name&&void 0!==e.parent&&e.taxonomy)try{const t=await fetch(`${jvbSettings.api}terms`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":window.auth.getNonce()},body:JSON.stringify(e)});if(!t.ok)throw new Error(`Server error: ${t.status}`);return await t.json()}catch(e){throw console.error("Error creating term:",e),e}}clearForm(){this.ui.name&&(this.ui.name.value=""),this.selector.ui.search.input&&(this.selector.ui.search.input.value="")}destroy(){this.clickHandler&&document.removeEventListener("click",this.clickHandler),this.ui.loading&&(this.ui.loading.hidden=!0)}}; |