Jake Vanderwerf
2025-09-30 2cb91676044ecd0abd9c45b4835abb8b0d042312
1
(()=>{class e{constructor(){this.queue=window.jvbQueue,this.loading=window.jvbLoading,this.cache=window.jvbCache,this.a11y=window.jvbA11y,this.error=window.jvbError,this.activeTab="artist",this.reset=!1,this.observer=null,this.form={},this.isSaving=!1,this.hasChanges=!1,this.trackedChanges=new Map,this.items=new Map,this.isLoading=!1,this.tabNav="vertical"===localStorage.getItem("jvbTabNav"),this.template=new Map,this.endpoints="myster",this.resetFilters(),this.hasMore=!0,this.maxPages=1,this.totalItems=0,this.initElements(),this.initEvents(),this.firstLoad=!1,this.firstLoad||(this.resetTable(),this.firstLoad=!0);let e=document.querySelectorAll("button.tab"),t={};this.modals={},e.forEach((e=>{let i=e.dataset.tab;t[i]=()=>{e.classList.contains("active")&&(this.activeTab=i),this.loading.setContent([this.activeTab]),this.resetTable(),this.resetFilters(),this.filters.content=i,localStorage.setItem("jvbAdminTab",i),this.loadItems(!0).then((()=>{}))},this.modals[i]=new window.jvbModal(document.querySelector(`dialog.edit-modal.${i}`,{open:!1,onSave:()=>this.saveEditModal.bind(this)})),this.items.set(i,new Map)})),this.tabs=new window.jvbTabs(document.querySelector(".replace"),t),this.loading.setContent([this.activeTab]),this.tabs.switchTab(this.activeTab),this.loadItems(),this.saveTimeout=null,this.SAVE_DELAY=5e3,this.debouncedSave=this.debouncedSave.bind(this)}resetFilters(){this.filters={page:1,order:"DESC",orderby:"name",content:this.activeTab}}resetTable(){removeChildren(this.grid);let e=window.getTemplate(`${this.activeTab}Table`).cloneNode(!0);this.row=`${this.activeTab}Row`;let t=e.querySelector("thead").cloneNode(!0),i=e.querySelector("tfoot");Array.from(t.children).forEach((e=>{i.appendChild(e.cloneNode(!0))})),this.grid.append(e),this.body=this.grid.querySelector("tbody"),this.grid.removeEventListener("change",this.boundChanges),this.boundChanges=this.trackChanges.bind(this),this.grid.addEventListener("change",this.boundChanges)}initElements(){this.container=document.querySelector(".replace"),this.grid=this.container.querySelector(".items-container"),this.tabToggle=this.container.querySelector("input#vertical"),this.tabToggle.checked=this.tabNav}trackChanges(e){this.hasChanges=!0;let t=e.target.closest("tr").id;this.trackedChanges.has(t)||this.trackedChanges.set(t,new Map);let i=e.target.name,a=e.target.value;this.trackedChanges.get(t).set(i,a),this.debouncedSave()}debouncedSave(){this.saveTimeout&&clearTimeout(this.saveTimeout),this.saveTimeout=setTimeout((()=>{this.processChanges()}),this.SAVE_DELAY)}async processChanges(){if(0!==this.trackedChanges.size)try{this.loading.showLoading();let e=t(this.trackedChanges);console.log("Saving changes:",e);const i=await fetch(`${jvbSettings.api}${this.endpoints}`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce,action_nonce:jvbAdmin.nonce},body:JSON.stringify({user:jvbSettings.currentUser,data:e,content:this.activeTab})});if(!i.ok)throw new Error(`Server returned ${i.status}`);const a=await i.json();if(!a.success)throw new Error(a.message||"Unknown error");this.reset=!0,this.trackedChanges=new Map,this.hasChanges=!1,this.loadItems(),this.a11y.announce("Changes saved successfully")}catch(e){this.handleError(e,"saving changes")}finally{this.loading.hideLoading()}}initEvents(){this.tabToggle.addEventListener("change",(e=>{this.tabNav=e.target.checked;let t=e.target.checked?"vertical":"horizontal";localStorage.setItem("jvbTabNav",t),window.jvbA11y.announce(this.tabNav?"Changed to vertical navigation":"Changed to horizontal navigation")})),this.grid.addEventListener("keydown",(e=>{if("Tab"===e.key&&this.tabNav){let t=e.target.closest("td").dataset.id,i=e.target.closest("tr"),a=Array.from(this.body.querySelectorAll("tr")),s=a.indexOf(i),n=a.length;if(-1!==s&&s<n){e.preventDefault();let i=e.shiftKey?s-1:s+1;a[i].scrollIntoView({behavior:"smooth",block:"center",inline:"center"}),a[i].querySelector(`[data-id="${t}"] input`).focus()}s===n-5&&this.hasMore&&this.loadItems(!1)}})),this.clickListener=this.handleClick.bind(this),this.container.addEventListener("click",this.clickListener)}handleClick(e){if("button"!==e.target&&!e.target.closest('button[data-action="edit"]'))return;let t="button"===e.target?e.target.dataset.id:e.target.closest("button").dataset.id,i=this.items.get(this.activeTab).get(parseInt(t)),a=this.container.querySelector(`dialog.edit-modal.${this.activeTab}`);for(let[e,t]of Object.entries(i)){let i=a.querySelector(`[name="${e}"]`);i&&(i.value=t)}this.form.instance&&(this.form.instance=null),this.form.instance=this.handleForm(a.querySelector("form"),t),this.modals[this.activeTab].modal.dataset.id=i.id,this.modals[this.activeTab].handleOpen()}handleForm(e,t){return window.jvbForm.addForm(e,{onSave:this.saveEditModal.bind(this),itemID:t})}async saveEditModal(){if(this.isSaving)return;this.isSaving=!0;let e=this.modals[this.activeTab],t=e.modal.querySelector("form"),i=e.modal.dataset.id,a=(this.items.get(this.activeTab).get(parseInt(i)),new FormData(t));console.log(a);let s={};for(const[e,t]of a.entries())if(e.includes(":")){let i=e.split(":");s[i[0]]||(s[i[0]]={}),s[i[0]][i[1]]=t}else s[e]=t;console.log(s),a={},a[i]=s;try{await fetch(`${jvbSettings.api}${this.endpoints}`,{method:"POST",headers:{"Content-Type":"application/json","X-WP-Nonce":jvbSettings.nonce,action_nonce:jvbAdmin.nonce},body:JSON.stringify({user:jvbSettings.currentUser,data:a,content:this.activeTab})})}catch(e){}finally{this.modals[this.activeTab].handleClose(),this.isSaving=!1}t.reset()}setupInfiniteScroll(){this.observer&&this.observer.disconnect();const e=this.body.lastElementChild;e&&(this.observer=new IntersectionObserver((e=>{e.forEach((e=>{e.isIntersecting&&this.hasMore&&!this.isLoading&&(console.log("Last row visible, loading more items"),this.loadItems(!1))}))}),{rootMargin:"200px 0px",threshold:.1}),this.observer.observe(e),console.log("Observing last row:",e))}async loadItems(e=!0){if(!this.isLoading&&this.hasMore)try{this.isLoading=!0,this.loading.showLoading(),e&&(this.filters.page=1,this.grid.classList.remove("empty"));const t=this.buildFilters();console.log(this.filters),console.log("Reset? ",this.reset);const i=await this.cache.fetchWithCache(`${jvbSettings.api}${this.endpoints}?${t.toString()}`,{method:"GET",headers:{"X-WP-Nonce":jvbSettings.nonce,action_nonce:jvbAdmin.nonce}},{context:"admin",forceRefresh:!0});return console.log(i,"Fetched Data:"),this.renderItems(i.items||[],this.filters.page>1),[this.hasMore,this.totalItems,this.maxPages]=[i.has_more,i.total_items,i.total_pages],this.hasMore&&this.filters.page++,this.setupInfiniteScroll(),i}catch(e){throw this.handleError(e,"loading news"),e}finally{this.isLoading=!1,this.loading.hideLoading()}}buildFilters(){const e=JSON.parse(JSON.stringify(this.filters));let t={};for(var[i,a]of Object.entries(e))!1!==a&&null!==a&&(t[i]=a);return new URLSearchParams(t)}renderItems(e,t=!1){const i=document.createDocumentFragment(),a=s=>{const n=Math.min(s+10,e.length);for(let t=s;t<n;t++){const a=e[t],s=this.createItemElement(a);this.items.get(this.activeTab).set(a.id,a),i.appendChild(s)}n<e.length?requestAnimationFrame((()=>{a(n)})):(this.body.appendChild(i),this.a11y.makeNavigable(this.grid.querySelectorAll(".item:not([data-keyboard-nav])")),this.a11y.announceItems(e.length,t,this.hasMore),this.setupInfiniteScroll())};e.length>0?a(0):this.a11y.announceItems(0,t)}createItemElement(e){let t=window.getTemplate(this.row);t.id=e.id,t.querySelectorAll("td").forEach((t=>{let i=t.dataset.id,a=t.querySelector('input[type="text"]');a&&(a.value=e[i],t.querySelector("label").remove(),t.querySelector(".description").remove())}));let[i,a,s]=[t.querySelector('[data-id="actions"] input'),t.querySelector('[data-id="actions"] label'),t.querySelector('[data-id="actions"] button')];return[i.checked,i.id,a.htmlFor,s.dataset.id]=[e.public,`public-${e.id}`,`public-${e.id}`,e.id],t}createShopElement(e){let t=window.getTemplate(this.row);t.id=e.id;let[i,a,s,n,o,r,l,d,c,h,u,g,v,m,b,p,y,S,w,f]=[t.querySelector('[data-id="actions"] input'),t.querySelector('[data-id="actions"] label'),t.querySelector('[data-id="actions"] button'),t.querySelector('[data-id="term_name"] input'),t.querySelector('[data-id="owner"] input'),t.querySelector('[data-id="managers"] input'),t.querySelector('[data-id="city"] input'),t.querySelector('[data-id="location"] input'),t.querySelector('[data-id="established"] input'),t.querySelector('[data-id="phone"] input'),t.querySelector('[data-id="email"] input'),t.querySelector('[data-id="admin_contact"] input'),t.querySelector('[data-id="public_contact"] input'),t.querySelector('[data-id="links"] input'),t.querySelector('[data-id="rate"] input'),t.querySelector('[data-id="languages"] input'),t.querySelector('[data-id="keywords"] input'),t.querySelector('[data-id="slogan"] input'),t.querySelector('[data-id="insta_handle"] input'),t.querySelector('[data-id="followers"] input')];if([i.checked,i.id,a.htmlFor,s.dataset.id,n.value,o.value,r.value,l.value,d.value,c.value,h.value,u.value,g.value,v.value,b.value,S.value,w.value]=[e.public,`public-${e.id}`,`public-${e.id}`,e.id,e.term_name,e.owner,e.managers,e.city,e.location.address,e.established,e.phone,e.email,e.admin_contact,e.public_contact,e.rate,e.slogan,e.insta_handle],e.links.length>0){let t="";e.links.forEach((e=>{t+=`[${e.url}, ${e.title}, ${e.tracker}]`})),m.value=t.trim()}if(e.followers.length>0){let t="";e.followers.forEach((e=>{t+=`[${e.count}, ${e.source}, ${formatDate(e.checked)}]`})),f.value=t}if(e.keywords.length>0){let t=[];e.keywords.forEach((e=>{t.push(e.keyword)})),y.value=t.join(", ")}if(e.languages.length>0){let t=[];e.languages.forEach((e=>{t.push(e.language)})),p.value=t.join(", ")}return t}createPartnerElement(e){let t=window.getTemplate(this.row);t.id=e.id;let[i,a,s]=[t.querySelector('[data-id="actions"] input'),t.querySelector('[data-id="actions"] label'),t.querySelector('[data-id="actions"] button')];return[i.checked,i.id,a.htmlFor,s.dataset.id]=[e.public,`public-${e.id}`,`public-${e.id}`,e.id],t}createStyleElement(e){let t=window.getTemplate(this.row);t.id=e.id,t.querySelectorAll("td").forEach((t=>{let i=t.dataset.id,a=t.querySelector('input[type="text"]');a&&(a.value=e[i])}));let[i,a,s]=[t.querySelector('[data-id="actions"] input'),t.querySelector('[data-id="actions"] label'),t.querySelector('[data-id="actions"] button')];return[i.checked,i.id,a.htmlFor,s.dataset.id]=[e.public,`public-${e.id}`,`public-${e.id}`,e.id],t}createArtistElement(e){let t=window.getTemplate(this.row);t.id=e.id;let[i,a,s,n,o,r,l,d,c,h,u,g,v,m,b,p,y,S,w]=[t.querySelector('[data-id="actions"] input'),t.querySelector('[data-id="actions"] label'),t.querySelector('[data-id="actions"] button'),t.querySelector('[data-id="display_name"] input'),t.querySelector('[data-id="first_name"] input'),t.querySelector('[data-id="phone"] input'),t.querySelector('[data-id="email"] input'),t.querySelector('[data-id="links"] input'),t.querySelector('[data-id="admin_contact"] input'),t.querySelector('[data-id="public_contact"] input'),t.querySelector('[data-id="followers"] input'),t.querySelector('[data-id="insta_handle"] input'),t.querySelector('[data-id="type"] input'),t.querySelector('[data-id="city"] input'),t.querySelector('[data-id="shop"] input'),t.querySelector('[data-id="rate"] input'),t.querySelector('[data-id="languages"] input'),t.querySelector('[data-id="keywords"] input'),t.querySelector('[data-id="credentials"] input')];if([i.checked,i.id,a.htmlFor,s.dataset.id,n.value,o.value,r.value,l.value,c.value,h.value,v.value,m.value,b.value,g.value,p.value]=[e.public,`public-${e.id}`,`public-${e.id}`,e.id,e.display_name,e.first_name,e.phone,e.email,e.admin_contact,e.public_contact,e.type,e.city,e.shop,e.insta_handle,e.rate],e.links.length>0){let t="";e.links.forEach((e=>{t+=`[${e.url}, ${e.title}, ${e.tracker}]`})),d.value=t.trim()}if(e.followers.length>0){let t="";e.followers.forEach((e=>{t+=`[${e.count}, ${e.source}, ${formatDate(e.checked)}]`})),u.value=t}if(e.keywords.length>0){let t=[];e.keywords.forEach((e=>{t.push(e.keyword)})),S.value=t.join(", ")}if(e.languages.length>0){let t=[];e.languages.forEach((e=>{t.push(e.language)})),y.value=t.join(", ")}return t}handleError(e,t){console.error(`News error (${t}):`,e),window.jvbError&&window.jvbError.log(e,{component:"Admin",action:t}),window.jvbA11y&&window.jvbA11y.announce(`Error ${t}. ${e.message||"Please try again."}`)}}function t(e){return Array.from(e).reduce(((e,[i,a])=>(a instanceof Map&&(a=t(a)),e[i]=a,e)),{})}document.addEventListener("DOMContentLoaded",(()=>{new e}))})();