1<divdata-querystatsclass="relative group/querystats"style="display: none;"> 2 {% if "querystats" in request.session %}
3<buttondata-toolbar-tab="querystats"class="inline-flex items-center cursor-pointer text-xs rounded-full px-2 py-px bg-white/20 text-white/80 whitespace-nowrap"> 4<spanclass="relative inline-flex size-2 mr-2"> 5<spanclass="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75"></span> 6<spanclass="relative inline-flex size-2 rounded-full bg-green-500"></span> 7</span> 8<spandata-querystats-summary></span> 9</button>10 {% else %}
11<formaction="{{ url('admin:querystats:querystats') }}"method="post">12 {{ csrf_input }}
13<inputtype="hidden"name="redirect_url"value="{{ request.get_full_path() }}">14<inputtype="hidden"name="querystats_action"value="enable">15<buttontype="submit"class="cursor-pointer text-xs rounded-full px-2 py-px bg-white/20 text-white/80 whitespace-nowrap">16<spanclass="rounded-full bg-zinc-500 w-2 h-2 inline-block mr-1"></span>17<spandata-querystats-summary></span>18</button>19</form>20 {% endif %}
2122<divdata-querystats-liststyle="display: none;"class="absolute z-50 hidden -translate-y-full right-0 -top-1 group-hover/querystats:block">23<divclass="p-2 text-xs border rounded shadow-md bg-zinc-900 border-zinc-700"><table><tbody></tbody></table></div>24</div>25<scriptasyncdefer>26// Catch errors since some browsers throw when using the new `type` option.27// https://bugs.webkit.org/show_bug.cgi?id=20921628varquerystatsTimings=[];29functionrenderQuerystats(){30// Render the original timing call31letsummary=querystatsTimings[0].description;32if(querystatsTimings.length>1){33summary+=` *`;34}35document.querySelector('[data-querystats-summary]').innerText=summary;3637// Make sure the elements are visible38document.querySelector('[data-querystats]').style.display='inline';3940// Render the table rows for all timings41constlist=document.querySelector('[data-querystats-list]');42if(querystatsTimings.length>1){43consttableRows=querystatsTimings.map(timing=>{44leturl=timing.url;45if(url.startsWith(window.location.origin)){46// Make the url relative if possible (usually is)47url=url.slice(window.location.origin.length);48}49return`<tr>50 <td class="pr-2 font-medium whitespace-nowrap">${url}</td>51 <td class="whitespace-nowrap">${timing.description}</td>52 </tr>`;53}).join('');54list.querySelector("tbody").innerHTML=tableRows;55list.style.display='';56}else{57list.style.display='none';58}59}60try{61constpo=newPerformanceObserver((list)=>{62for(constentryoflist.getEntries()){63if(!entry.serverTiming){64console.warn("Server timing not available for querystats.")65return;66}67for(consttimingofentry.serverTiming){68if(timing.name==="querystats"){69console.log("Querystats timing",entry)70timing.url=entry.name;// Store this for reference later71for(constexistingTimingofquerystatsTimings){72if(existingTiming==timing){73// Skip duplicate timings (happens on initial load...)74return;75}76}77querystatsTimings.push(timing);78renderQuerystats();79}80}81}82});83po.observe({type:'navigation',buffered:true});// Catch the regular page loads84po.observe({type:'resource',buffered:true});// Catch future ajax requests85}catch(e){86// Do nothing if the browser doesn't support this API.87}88</script>89</div>