diff --git a/vite-app/dist/assets/index-CmEkuH8E.js b/vite-app/dist/assets/index-CmEkuH8E.js deleted file mode 100644 index 21d8b32b..00000000 --- a/vite-app/dist/assets/index-CmEkuH8E.js +++ /dev/null @@ -1,93 +0,0 @@ -(function(){const l=document.createElement("link").relList;if(l&&l.supports&&l.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))u(o);new MutationObserver(o=>{for(const f of o)if(f.type==="childList")for(const d of f.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&u(d)}).observe(document,{childList:!0,subtree:!0});function r(o){const f={};return o.integrity&&(f.integrity=o.integrity),o.referrerPolicy&&(f.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?f.credentials="include":o.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function u(o){if(o.ep)return;o.ep=!0;const f=r(o);fetch(o.href,f)}})();function cg(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var Fc={exports:{}},er={};/** - * @license React - * react-jsx-runtime.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Km;function y_(){if(Km)return er;Km=1;var n=Symbol.for("react.transitional.element"),l=Symbol.for("react.fragment");function r(u,o,f){var d=null;if(f!==void 0&&(d=""+f),o.key!==void 0&&(d=""+o.key),"key"in o){f={};for(var v in o)v!=="key"&&(f[v]=o[v])}else f=o;return o=f.ref,{$$typeof:n,type:u,key:d,ref:o!==void 0?o:null,props:f}}return er.Fragment=l,er.jsx=r,er.jsxs=r,er}var Qm;function b_(){return Qm||(Qm=1,Fc.exports=y_()),Fc.exports}var b=b_(),Wc={exports:{}},se={};/** - * @license React - * react.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Jm;function __(){if(Jm)return se;Jm=1;var n=Symbol.for("react.transitional.element"),l=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),u=Symbol.for("react.strict_mode"),o=Symbol.for("react.profiler"),f=Symbol.for("react.consumer"),d=Symbol.for("react.context"),v=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),S=Symbol.iterator;function O(x){return x===null||typeof x!="object"?null:(x=S&&x[S]||x["@@iterator"],typeof x=="function"?x:null)}var B={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},H=Object.assign,Z={};function V(x,$,P){this.props=x,this.context=$,this.refs=Z,this.updater=P||B}V.prototype.isReactComponent={},V.prototype.setState=function(x,$){if(typeof x!="object"&&typeof x!="function"&&x!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,x,$,"setState")},V.prototype.forceUpdate=function(x){this.updater.enqueueForceUpdate(this,x,"forceUpdate")};function j(){}j.prototype=V.prototype;function k(x,$,P){this.props=x,this.context=$,this.refs=Z,this.updater=P||B}var q=k.prototype=new j;q.constructor=k,H(q,V.prototype),q.isPureReactComponent=!0;var Y=Array.isArray,X={H:null,A:null,T:null,S:null,V:null},ue=Object.prototype.hasOwnProperty;function he(x,$,P,Q,te,ye){return P=ye.ref,{$$typeof:n,type:x,key:$,ref:P!==void 0?P:null,props:ye}}function Oe(x,$){return he(x.type,$,void 0,void 0,void 0,x.props)}function K(x){return typeof x=="object"&&x!==null&&x.$$typeof===n}function fe(x){var $={"=":"=0",":":"=2"};return"$"+x.replace(/[=:]/g,function(P){return $[P]})}var We=/\/+/g;function Je(x,$){return typeof x=="object"&&x!==null&&x.key!=null?fe(""+x.key):$.toString(36)}function Wt(){}function Jn(x){switch(x.status){case"fulfilled":return x.value;case"rejected":throw x.reason;default:switch(typeof x.status=="string"?x.then(Wt,Wt):(x.status="pending",x.then(function($){x.status==="pending"&&(x.status="fulfilled",x.value=$)},function($){x.status==="pending"&&(x.status="rejected",x.reason=$)})),x.status){case"fulfilled":return x.value;case"rejected":throw x.reason}}throw x}function rt(x,$,P,Q,te){var ye=typeof x;(ye==="undefined"||ye==="boolean")&&(x=null);var oe=!1;if(x===null)oe=!0;else switch(ye){case"bigint":case"string":case"number":oe=!0;break;case"object":switch(x.$$typeof){case n:case l:oe=!0;break;case y:return oe=x._init,rt(oe(x._payload),$,P,Q,te)}}if(oe)return te=te(x),oe=Q===""?"."+Je(x,0):Q,Y(te)?(P="",oe!=null&&(P=oe.replace(We,"$&/")+"/"),rt(te,$,P,"",function(Pn){return Pn})):te!=null&&(K(te)&&(te=Oe(te,P+(te.key==null||x&&x.key===te.key?"":(""+te.key).replace(We,"$&/")+"/")+oe)),$.push(te)),1;oe=0;var Et=Q===""?".":Q+":";if(Y(x))for(var Ze=0;Ze>>1,x=D[Ne];if(0>>1;Ne<$;){var P=2*(Ne+1)-1,Q=D[P],te=P+1,ye=D[te];if(0>o(Q,le))teo(ye,Q)?(D[Ne]=ye,D[te]=le,Ne=te):(D[Ne]=Q,D[P]=le,Ne=P);else if(teo(ye,le))D[Ne]=ye,D[te]=le,Ne=te;else break e}}return J}function o(D,J){var le=D.sortIndex-J.sortIndex;return le!==0?le:D.id-J.id}if(n.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var f=performance;n.unstable_now=function(){return f.now()}}else{var d=Date,v=d.now();n.unstable_now=function(){return d.now()-v}}var m=[],p=[],y=1,S=null,O=3,B=!1,H=!1,Z=!1,V=!1,j=typeof setTimeout=="function"?setTimeout:null,k=typeof clearTimeout=="function"?clearTimeout:null,q=typeof setImmediate<"u"?setImmediate:null;function Y(D){for(var J=r(p);J!==null;){if(J.callback===null)u(p);else if(J.startTime<=D)u(p),J.sortIndex=J.expirationTime,l(m,J);else break;J=r(p)}}function X(D){if(Z=!1,Y(D),!H)if(r(m)!==null)H=!0,ue||(ue=!0,Je());else{var J=r(p);J!==null&&rt(X,J.startTime-D)}}var ue=!1,he=-1,Oe=5,K=-1;function fe(){return V?!0:!(n.unstable_now()-KD&&fe());){var Ne=S.callback;if(typeof Ne=="function"){S.callback=null,O=S.priorityLevel;var x=Ne(S.expirationTime<=D);if(D=n.unstable_now(),typeof x=="function"){S.callback=x,Y(D),J=!0;break t}S===r(m)&&u(m),Y(D)}else u(m);S=r(m)}if(S!==null)J=!0;else{var $=r(p);$!==null&&rt(X,$.startTime-D),J=!1}}break e}finally{S=null,O=le,B=!1}J=void 0}}finally{J?Je():ue=!1}}}var Je;if(typeof q=="function")Je=function(){q(We)};else if(typeof MessageChannel<"u"){var Wt=new MessageChannel,Jn=Wt.port2;Wt.port1.onmessage=We,Je=function(){Jn.postMessage(null)}}else Je=function(){j(We,0)};function rt(D,J){he=j(function(){D(n.unstable_now())},J)}n.unstable_IdlePriority=5,n.unstable_ImmediatePriority=1,n.unstable_LowPriority=4,n.unstable_NormalPriority=3,n.unstable_Profiling=null,n.unstable_UserBlockingPriority=2,n.unstable_cancelCallback=function(D){D.callback=null},n.unstable_forceFrameRate=function(D){0>D||125Ne?(D.sortIndex=le,l(p,D),r(m)===null&&D===r(p)&&(Z?(k(he),he=-1):Z=!0,rt(X,le-Ne))):(D.sortIndex=x,l(m,D),H||B||(H=!0,ue||(ue=!0,Je()))),D},n.unstable_shouldYield=fe,n.unstable_wrapCallback=function(D){var J=O;return function(){var le=O;O=J;try{return D.apply(this,arguments)}finally{O=le}}}}(tf)),tf}var Wm;function x_(){return Wm||(Wm=1,ef.exports=S_()),ef.exports}var nf={exports:{}},ht={};/** - * @license React - * react-dom.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Im;function E_(){if(Im)return ht;Im=1;var n=go();function l(m){var p="https://react.dev/errors/"+m;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(l){console.error(l)}}return n(),nf.exports=E_(),nf.exports}/** - * @license React - * react-dom-client.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var tp;function O_(){if(tp)return tr;tp=1;var n=x_(),l=go(),r=fg();function u(e){var t="https://react.dev/errors/"+e;if(1x||(e.current=Ne[x],Ne[x]=null,x--)}function Q(e,t){x++,Ne[x]=e.current,e.current=t}var te=$(null),ye=$(null),oe=$(null),Et=$(null);function Ze(e,t){switch(Q(oe,t),Q(ye,e),Q(te,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Sm(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Sm(t),e=xm(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}P(te),Q(te,e)}function Pn(){P(te),P(ye),P(oe)}function Zo(e){e.memoizedState!==null&&Q(Et,e);var t=te.current,a=xm(t,e.type);t!==a&&(Q(ye,e),Q(te,a))}function Er(e){ye.current===e&&(P(te),P(ye)),Et.current===e&&(P(Et),Ji._currentValue=le)}var Bo=Object.prototype.hasOwnProperty,Lo=n.unstable_scheduleCallback,$o=n.unstable_cancelCallback,Py=n.unstable_shouldYield,Fy=n.unstable_requestPaint,cn=n.unstable_now,Wy=n.unstable_getCurrentPriorityLevel,td=n.unstable_ImmediatePriority,nd=n.unstable_UserBlockingPriority,Or=n.unstable_NormalPriority,Iy=n.unstable_LowPriority,ad=n.unstable_IdlePriority,e0=n.log,t0=n.unstable_setDisableYieldValue,ai=null,Ot=null;function Fn(e){if(typeof e0=="function"&&t0(e),Ot&&typeof Ot.setStrictMode=="function")try{Ot.setStrictMode(ai,e)}catch{}}var wt=Math.clz32?Math.clz32:l0,n0=Math.log,a0=Math.LN2;function l0(e){return e>>>=0,e===0?32:31-(n0(e)/a0|0)|0}var wr=256,Ar=4194304;function Aa(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Tr(e,t,a){var i=e.pendingLanes;if(i===0)return 0;var s=0,c=e.suspendedLanes,h=e.pingedLanes;e=e.warmLanes;var g=i&134217727;return g!==0?(i=g&~c,i!==0?s=Aa(i):(h&=g,h!==0?s=Aa(h):a||(a=g&~e,a!==0&&(s=Aa(a))))):(g=i&~c,g!==0?s=Aa(g):h!==0?s=Aa(h):a||(a=i&~e,a!==0&&(s=Aa(a)))),s===0?0:t!==0&&t!==s&&(t&c)===0&&(c=s&-s,a=t&-t,c>=a||c===32&&(a&4194048)!==0)?t:s}function li(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function i0(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ld(){var e=wr;return wr<<=1,(wr&4194048)===0&&(wr=256),e}function id(){var e=Ar;return Ar<<=1,(Ar&62914560)===0&&(Ar=4194304),e}function ko(e){for(var t=[],a=0;31>a;a++)t.push(e);return t}function ii(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function r0(e,t,a,i,s,c){var h=e.pendingLanes;e.pendingLanes=a,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=a,e.entangledLanes&=a,e.errorRecoveryDisabledLanes&=a,e.shellSuspendCounter=0;var g=e.entanglements,_=e.expirationTimes,T=e.hiddenUpdates;for(a=h&~a;0)":-1s||_[i]!==T[s]){var C=` -`+_[i].replace(" at new "," at ");return e.displayName&&C.includes("")&&(C=C.replace("",e.displayName)),C}while(1<=i&&0<=s);break}}}finally{Xo=!1,Error.prepareStackTrace=a}return(a=e?e.displayName||e.name:"")?sl(a):""}function d0(e){switch(e.tag){case 26:case 27:case 5:return sl(e.type);case 16:return sl("Lazy");case 13:return sl("Suspense");case 19:return sl("SuspenseList");case 0:case 15:return Ko(e.type,!1);case 11:return Ko(e.type.render,!1);case 1:return Ko(e.type,!0);case 31:return sl("Activity");default:return""}}function md(e){try{var t="";do t+=d0(e),e=e.return;while(e);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}function $t(e){switch(typeof e){case"bigint":case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function pd(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function h0(e){var t=pd(e)?"checked":"value",a=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),i=""+e[t];if(!e.hasOwnProperty(t)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var s=a.get,c=a.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return s.call(this)},set:function(h){i=""+h,c.call(this,h)}}),Object.defineProperty(e,t,{enumerable:a.enumerable}),{getValue:function(){return i},setValue:function(h){i=""+h},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Nr(e){e._valueTracker||(e._valueTracker=h0(e))}function gd(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var a=t.getValue(),i="";return e&&(i=pd(e)?e.checked?"true":"false":e.value),e=i,e!==a?(t.setValue(e),!0):!1}function jr(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var v0=/[\n"\\]/g;function kt(e){return e.replace(v0,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Qo(e,t,a,i,s,c,h,g){e.name="",h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"?e.type=h:e.removeAttribute("type"),t!=null?h==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+$t(t)):e.value!==""+$t(t)&&(e.value=""+$t(t)):h!=="submit"&&h!=="reset"||e.removeAttribute("value"),t!=null?Jo(e,h,$t(t)):a!=null?Jo(e,h,$t(a)):i!=null&&e.removeAttribute("value"),s==null&&c!=null&&(e.defaultChecked=!!c),s!=null&&(e.checked=s&&typeof s!="function"&&typeof s!="symbol"),g!=null&&typeof g!="function"&&typeof g!="symbol"&&typeof g!="boolean"?e.name=""+$t(g):e.removeAttribute("name")}function yd(e,t,a,i,s,c,h,g){if(c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.type=c),t!=null||a!=null){if(!(c!=="submit"&&c!=="reset"||t!=null))return;a=a!=null?""+$t(a):"",t=t!=null?""+$t(t):a,g||t===e.value||(e.value=t),e.defaultValue=t}i=i??s,i=typeof i!="function"&&typeof i!="symbol"&&!!i,e.checked=g?e.checked:!!i,e.defaultChecked=!!i,h!=null&&typeof h!="function"&&typeof h!="symbol"&&typeof h!="boolean"&&(e.name=h)}function Jo(e,t,a){t==="number"&&jr(e.ownerDocument)===e||e.defaultValue===""+a||(e.defaultValue=""+a)}function cl(e,t,a,i){if(e=e.options,t){t={};for(var s=0;s"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),es=!1;if(Tn)try{var si={};Object.defineProperty(si,"passive",{get:function(){es=!0}}),window.addEventListener("test",si,si),window.removeEventListener("test",si,si)}catch{es=!1}var In=null,ts=null,Cr=null;function wd(){if(Cr)return Cr;var e,t=ts,a=t.length,i,s="value"in In?In.value:In.textContent,c=s.length;for(e=0;e=di),jd=" ",Dd=!1;function Cd(e,t){switch(e){case"keyup":return q0.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Md(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var vl=!1;function G0(e,t){switch(e){case"compositionend":return Md(t);case"keypress":return t.which!==32?null:(Dd=!0,jd);case"textInput":return e=t.data,e===jd&&Dd?null:e;default:return null}}function Y0(e,t){if(vl)return e==="compositionend"||!rs&&Cd(e,t)?(e=wd(),Cr=ts=In=null,vl=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:a,offset:t-e};e=i}e:{for(;a;){if(a.nextSibling){a=a.nextSibling;break e}a=a.parentNode}a=void 0}a=qd(a)}}function Gd(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Gd(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Yd(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=jr(e.document);t instanceof e.HTMLIFrameElement;){try{var a=typeof t.contentWindow.location.href=="string"}catch{a=!1}if(a)e=t.contentWindow;else break;t=jr(e.document)}return t}function ss(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var I0=Tn&&"documentMode"in document&&11>=document.documentMode,ml=null,cs=null,pi=null,fs=!1;function Xd(e,t,a){var i=a.window===a?a.document:a.nodeType===9?a:a.ownerDocument;fs||ml==null||ml!==jr(i)||(i=ml,"selectionStart"in i&&ss(i)?i={start:i.selectionStart,end:i.selectionEnd}:(i=(i.ownerDocument&&i.ownerDocument.defaultView||window).getSelection(),i={anchorNode:i.anchorNode,anchorOffset:i.anchorOffset,focusNode:i.focusNode,focusOffset:i.focusOffset}),pi&&mi(pi,i)||(pi=i,i=Eu(cs,"onSelect"),0>=h,s-=h,zn=1<<32-wt(t)+s|a<c?c:8;var h=D.T,g={};D.T=g,Ps(e,!1,t,a);try{var _=s(),T=D.S;if(T!==null&&T(g,_),_!==null&&typeof _=="object"&&typeof _.then=="function"){var C=ob(_,i);ji(e,t,C,jt(e))}else ji(e,t,i,jt(e))}catch(L){ji(e,t,{then:function(){},status:"rejected",reason:L},jt())}finally{J.p=c,D.T=h}}function hb(){}function Qs(e,t,a,i){if(e.tag!==5)throw Error(u(476));var s=Kh(e).queue;Xh(e,s,t,le,a===null?hb:function(){return Qh(e),a(i)})}function Kh(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:le,baseState:le,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Cn,lastRenderedState:le},next:null};var a={};return t.next={memoizedState:a,baseState:a,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Cn,lastRenderedState:a},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Qh(e){var t=Kh(e).next.queue;ji(e,t,{},jt())}function Js(){return dt(Ji)}function Jh(){return Fe().memoizedState}function Ph(){return Fe().memoizedState}function vb(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var a=jt();e=na(a);var i=aa(t,e,a);i!==null&&(Dt(i,t,a),wi(i,t,a)),t={cache:ws()},e.payload=t;return}t=t.return}}function mb(e,t,a){var i=jt();a={lane:i,revertLane:0,action:a,hasEagerState:!1,eagerState:null,next:null},au(e)?Wh(t,a):(a=ms(e,t,a,i),a!==null&&(Dt(a,e,i),Ih(a,t,i)))}function Fh(e,t,a){var i=jt();ji(e,t,a,i)}function ji(e,t,a,i){var s={lane:i,revertLane:0,action:a,hasEagerState:!1,eagerState:null,next:null};if(au(e))Wh(t,s);else{var c=e.alternate;if(e.lanes===0&&(c===null||c.lanes===0)&&(c=t.lastRenderedReducer,c!==null))try{var h=t.lastRenderedState,g=c(h,a);if(s.hasEagerState=!0,s.eagerState=g,At(g,h))return kr(e,t,s,0),Ce===null&&$r(),!1}catch{}finally{}if(a=ms(e,t,s,i),a!==null)return Dt(a,e,i),Ih(a,t,i),!0}return!1}function Ps(e,t,a,i){if(i={lane:2,revertLane:Rc(),action:i,hasEagerState:!1,eagerState:null,next:null},au(e)){if(t)throw Error(u(479))}else t=ms(e,a,i,2),t!==null&&Dt(t,e,2)}function au(e){var t=e.alternate;return e===ce||t!==null&&t===ce}function Wh(e,t){wl=Fr=!0;var a=e.pending;a===null?t.next=t:(t.next=a.next,a.next=t),e.pending=t}function Ih(e,t,a){if((a&4194048)!==0){var i=t.lanes;i&=e.pendingLanes,a|=i,t.lanes=a,ud(e,a)}}var lu={readContext:dt,use:Ir,useCallback:Ke,useContext:Ke,useEffect:Ke,useImperativeHandle:Ke,useLayoutEffect:Ke,useInsertionEffect:Ke,useMemo:Ke,useReducer:Ke,useRef:Ke,useState:Ke,useDebugValue:Ke,useDeferredValue:Ke,useTransition:Ke,useSyncExternalStore:Ke,useId:Ke,useHostTransitionStatus:Ke,useFormState:Ke,useActionState:Ke,useOptimistic:Ke,useMemoCache:Ke,useCacheRefresh:Ke},ev={readContext:dt,use:Ir,useCallback:function(e,t){return yt().memoizedState=[e,t===void 0?null:t],e},useContext:dt,useEffect:Bh,useImperativeHandle:function(e,t,a){a=a!=null?a.concat([e]):null,nu(4194308,4,Hh.bind(null,t,e),a)},useLayoutEffect:function(e,t){return nu(4194308,4,e,t)},useInsertionEffect:function(e,t){nu(4,2,e,t)},useMemo:function(e,t){var a=yt();t=t===void 0?null:t;var i=e();if($a){Fn(!0);try{e()}finally{Fn(!1)}}return a.memoizedState=[i,t],i},useReducer:function(e,t,a){var i=yt();if(a!==void 0){var s=a(t);if($a){Fn(!0);try{a(t)}finally{Fn(!1)}}}else s=t;return i.memoizedState=i.baseState=s,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:s},i.queue=e,e=e.dispatch=mb.bind(null,ce,e),[i.memoizedState,e]},useRef:function(e){var t=yt();return e={current:e},t.memoizedState=e},useState:function(e){e=Gs(e);var t=e.queue,a=Fh.bind(null,ce,t);return t.dispatch=a,[e.memoizedState,a]},useDebugValue:Xs,useDeferredValue:function(e,t){var a=yt();return Ks(a,e,t)},useTransition:function(){var e=Gs(!1);return e=Xh.bind(null,ce,e.queue,!0,!1),yt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,a){var i=ce,s=yt();if(Se){if(a===void 0)throw Error(u(407));a=a()}else{if(a=t(),Ce===null)throw Error(u(349));(pe&124)!==0||Sh(i,t,a)}s.memoizedState=a;var c={value:a,getSnapshot:t};return s.queue=c,Bh(Eh.bind(null,i,c,e),[e]),i.flags|=2048,Tl(9,tu(),xh.bind(null,i,c,a,t),null),a},useId:function(){var e=yt(),t=Ce.identifierPrefix;if(Se){var a=Nn,i=zn;a=(i&~(1<<32-wt(i)-1)).toString(32)+a,t="«"+t+"R"+a,a=Wr++,0ae?(lt=ee,ee=null):lt=ee.sibling;var be=z(w,ee,A[ae],U);if(be===null){ee===null&&(ee=lt);break}e&&ee&&be.alternate===null&&t(w,ee),E=c(be,E,ae),de===null?F=be:de.sibling=be,de=be,ee=lt}if(ae===A.length)return a(w,ee),Se&&Ca(w,ae),F;if(ee===null){for(;aeae?(lt=ee,ee=null):lt=ee.sibling;var _a=z(w,ee,be.value,U);if(_a===null){ee===null&&(ee=lt);break}e&&ee&&_a.alternate===null&&t(w,ee),E=c(_a,E,ae),de===null?F=_a:de.sibling=_a,de=_a,ee=lt}if(be.done)return a(w,ee),Se&&Ca(w,ae),F;if(ee===null){for(;!be.done;ae++,be=A.next())be=L(w,be.value,U),be!==null&&(E=c(be,E,ae),de===null?F=be:de.sibling=be,de=be);return Se&&Ca(w,ae),F}for(ee=i(ee);!be.done;ae++,be=A.next())be=N(ee,w,ae,be.value,U),be!==null&&(e&&be.alternate!==null&&ee.delete(be.key===null?ae:be.key),E=c(be,E,ae),de===null?F=be:de.sibling=be,de=be);return e&&ee.forEach(function(g_){return t(w,g_)}),Se&&Ca(w,ae),F}function Te(w,E,A,U){if(typeof A=="object"&&A!==null&&A.type===H&&A.key===null&&(A=A.props.children),typeof A=="object"&&A!==null){switch(A.$$typeof){case O:e:{for(var F=A.key;E!==null;){if(E.key===F){if(F=A.type,F===H){if(E.tag===7){a(w,E.sibling),U=s(E,A.props.children),U.return=w,w=U;break e}}else if(E.elementType===F||typeof F=="object"&&F!==null&&F.$$typeof===Oe&&nv(F)===E.type){a(w,E.sibling),U=s(E,A.props),Ci(U,A),U.return=w,w=U;break e}a(w,E);break}else t(w,E);E=E.sibling}A.type===H?(U=ja(A.props.children,w.mode,U,A.key),U.return=w,w=U):(U=qr(A.type,A.key,A.props,null,w.mode,U),Ci(U,A),U.return=w,w=U)}return h(w);case B:e:{for(F=A.key;E!==null;){if(E.key===F)if(E.tag===4&&E.stateNode.containerInfo===A.containerInfo&&E.stateNode.implementation===A.implementation){a(w,E.sibling),U=s(E,A.children||[]),U.return=w,w=U;break e}else{a(w,E);break}else t(w,E);E=E.sibling}U=ys(A,w.mode,U),U.return=w,w=U}return h(w);case Oe:return F=A._init,A=F(A._payload),Te(w,E,A,U)}if(rt(A))return ie(w,E,A,U);if(Je(A)){if(F=Je(A),typeof F!="function")throw Error(u(150));return A=F.call(A),ne(w,E,A,U)}if(typeof A.then=="function")return Te(w,E,iu(A),U);if(A.$$typeof===q)return Te(w,E,Xr(w,A),U);ru(w,A)}return typeof A=="string"&&A!==""||typeof A=="number"||typeof A=="bigint"?(A=""+A,E!==null&&E.tag===6?(a(w,E.sibling),U=s(E,A),U.return=w,w=U):(a(w,E),U=gs(A,w.mode,U),U.return=w,w=U),h(w)):a(w,E)}return function(w,E,A,U){try{Di=0;var F=Te(w,E,A,U);return Rl=null,F}catch(ee){if(ee===Ei||ee===Qr)throw ee;var de=Tt(29,ee,null,w.mode);return de.lanes=U,de.return=w,de}finally{}}}var zl=av(!0),lv=av(!1),Yt=$(null),dn=null;function ia(e){var t=e.alternate;Q(et,et.current&1),Q(Yt,e),dn===null&&(t===null||Ol.current!==null||t.memoizedState!==null)&&(dn=e)}function iv(e){if(e.tag===22){if(Q(et,et.current),Q(Yt,e),dn===null){var t=e.alternate;t!==null&&t.memoizedState!==null&&(dn=e)}}else ra()}function ra(){Q(et,et.current),Q(Yt,Yt.current)}function Mn(e){P(Yt),dn===e&&(dn=null),P(et)}var et=$(0);function uu(e){for(var t=e;t!==null;){if(t.tag===13){var a=t.memoizedState;if(a!==null&&(a=a.dehydrated,a===null||a.data==="$?"||kc(a)))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if((t.flags&128)!==0)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}function Fs(e,t,a,i){t=e.memoizedState,a=a(i,t),a=a==null?t:y({},t,a),e.memoizedState=a,e.lanes===0&&(e.updateQueue.baseState=a)}var Ws={enqueueSetState:function(e,t,a){e=e._reactInternals;var i=jt(),s=na(i);s.payload=t,a!=null&&(s.callback=a),t=aa(e,s,i),t!==null&&(Dt(t,e,i),wi(t,e,i))},enqueueReplaceState:function(e,t,a){e=e._reactInternals;var i=jt(),s=na(i);s.tag=1,s.payload=t,a!=null&&(s.callback=a),t=aa(e,s,i),t!==null&&(Dt(t,e,i),wi(t,e,i))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var a=jt(),i=na(a);i.tag=2,t!=null&&(i.callback=t),t=aa(e,i,a),t!==null&&(Dt(t,e,a),wi(t,e,a))}};function rv(e,t,a,i,s,c,h){return e=e.stateNode,typeof e.shouldComponentUpdate=="function"?e.shouldComponentUpdate(i,c,h):t.prototype&&t.prototype.isPureReactComponent?!mi(a,i)||!mi(s,c):!0}function uv(e,t,a,i){e=t.state,typeof t.componentWillReceiveProps=="function"&&t.componentWillReceiveProps(a,i),typeof t.UNSAFE_componentWillReceiveProps=="function"&&t.UNSAFE_componentWillReceiveProps(a,i),t.state!==e&&Ws.enqueueReplaceState(t,t.state,null)}function ka(e,t){var a=t;if("ref"in t){a={};for(var i in t)i!=="ref"&&(a[i]=t[i])}if(e=e.defaultProps){a===t&&(a=y({},a));for(var s in e)a[s]===void 0&&(a[s]=e[s])}return a}var ou=typeof reportError=="function"?reportError:function(e){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var t=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof e=="object"&&e!==null&&typeof e.message=="string"?String(e.message):String(e),error:e});if(!window.dispatchEvent(t))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",e);return}console.error(e)};function ov(e){ou(e)}function sv(e){console.error(e)}function cv(e){ou(e)}function su(e,t){try{var a=e.onUncaughtError;a(t.value,{componentStack:t.stack})}catch(i){setTimeout(function(){throw i})}}function fv(e,t,a){try{var i=e.onCaughtError;i(a.value,{componentStack:a.stack,errorBoundary:t.tag===1?t.stateNode:null})}catch(s){setTimeout(function(){throw s})}}function Is(e,t,a){return a=na(a),a.tag=3,a.payload={element:null},a.callback=function(){su(e,t)},a}function dv(e){return e=na(e),e.tag=3,e}function hv(e,t,a,i){var s=a.type.getDerivedStateFromError;if(typeof s=="function"){var c=i.value;e.payload=function(){return s(c)},e.callback=function(){fv(t,a,i)}}var h=a.stateNode;h!==null&&typeof h.componentDidCatch=="function"&&(e.callback=function(){fv(t,a,i),typeof s!="function"&&(da===null?da=new Set([this]):da.add(this));var g=i.stack;this.componentDidCatch(i.value,{componentStack:g!==null?g:""})})}function gb(e,t,a,i,s){if(a.flags|=32768,i!==null&&typeof i=="object"&&typeof i.then=="function"){if(t=a.alternate,t!==null&&_i(t,a,s,!0),a=Yt.current,a!==null){switch(a.tag){case 13:return dn===null?Ec():a.alternate===null&&Ye===0&&(Ye=3),a.flags&=-257,a.flags|=65536,a.lanes=s,i===Rs?a.flags|=16384:(t=a.updateQueue,t===null?a.updateQueue=new Set([i]):t.add(i),wc(e,i,s)),!1;case 22:return a.flags|=65536,i===Rs?a.flags|=16384:(t=a.updateQueue,t===null?(t={transitions:null,markerInstances:null,retryQueue:new Set([i])},a.updateQueue=t):(a=t.retryQueue,a===null?t.retryQueue=new Set([i]):a.add(i)),wc(e,i,s)),!1}throw Error(u(435,a.tag))}return wc(e,i,s),Ec(),!1}if(Se)return t=Yt.current,t!==null?((t.flags&65536)===0&&(t.flags|=256),t.flags|=65536,t.lanes=s,i!==Ss&&(e=Error(u(422),{cause:i}),bi(Ht(e,a)))):(i!==Ss&&(t=Error(u(423),{cause:i}),bi(Ht(t,a))),e=e.current.alternate,e.flags|=65536,s&=-s,e.lanes|=s,i=Ht(i,a),s=Is(e.stateNode,i,s),js(e,s),Ye!==4&&(Ye=2)),!1;var c=Error(u(520),{cause:i});if(c=Ht(c,a),ki===null?ki=[c]:ki.push(c),Ye!==4&&(Ye=2),t===null)return!0;i=Ht(i,a),a=t;do{switch(a.tag){case 3:return a.flags|=65536,e=s&-s,a.lanes|=e,e=Is(a.stateNode,i,e),js(a,e),!1;case 1:if(t=a.type,c=a.stateNode,(a.flags&128)===0&&(typeof t.getDerivedStateFromError=="function"||c!==null&&typeof c.componentDidCatch=="function"&&(da===null||!da.has(c))))return a.flags|=65536,s&=-s,a.lanes|=s,s=dv(s),hv(s,e,a,i),js(a,s),!1}a=a.return}while(a!==null);return!1}var vv=Error(u(461)),nt=!1;function ut(e,t,a,i){t.child=e===null?lv(t,null,a,i):zl(t,e.child,a,i)}function mv(e,t,a,i,s){a=a.render;var c=t.ref;if("ref"in i){var h={};for(var g in i)g!=="ref"&&(h[g]=i[g])}else h=i;return Ba(t),i=Zs(e,t,a,h,c,s),g=Bs(),e!==null&&!nt?(Ls(e,t,s),Un(e,t,s)):(Se&&g&&bs(t),t.flags|=1,ut(e,t,i,s),t.child)}function pv(e,t,a,i,s){if(e===null){var c=a.type;return typeof c=="function"&&!ps(c)&&c.defaultProps===void 0&&a.compare===null?(t.tag=15,t.type=c,gv(e,t,c,i,s)):(e=qr(a.type,null,i,t,t.mode,s),e.ref=t.ref,e.return=t,t.child=e)}if(c=e.child,!uc(e,s)){var h=c.memoizedProps;if(a=a.compare,a=a!==null?a:mi,a(h,i)&&e.ref===t.ref)return Un(e,t,s)}return t.flags|=1,e=Rn(c,i),e.ref=t.ref,e.return=t,t.child=e}function gv(e,t,a,i,s){if(e!==null){var c=e.memoizedProps;if(mi(c,i)&&e.ref===t.ref)if(nt=!1,t.pendingProps=i=c,uc(e,s))(e.flags&131072)!==0&&(nt=!0);else return t.lanes=e.lanes,Un(e,t,s)}return ec(e,t,a,i,s)}function yv(e,t,a){var i=t.pendingProps,s=i.children,c=e!==null?e.memoizedState:null;if(i.mode==="hidden"){if((t.flags&128)!==0){if(i=c!==null?c.baseLanes|a:a,e!==null){for(s=t.child=e.child,c=0;s!==null;)c=c|s.lanes|s.childLanes,s=s.sibling;t.childLanes=c&~i}else t.childLanes=0,t.child=null;return bv(e,t,i,a)}if((a&536870912)!==0)t.memoizedState={baseLanes:0,cachePool:null},e!==null&&Kr(t,c!==null?c.cachePool:null),c!==null?gh(t,c):Cs(),iv(t);else return t.lanes=t.childLanes=536870912,bv(e,t,c!==null?c.baseLanes|a:a,a)}else c!==null?(Kr(t,c.cachePool),gh(t,c),ra(),t.memoizedState=null):(e!==null&&Kr(t,null),Cs(),ra());return ut(e,t,s,a),t.child}function bv(e,t,a,i){var s=Ts();return s=s===null?null:{parent:Ie._currentValue,pool:s},t.memoizedState={baseLanes:a,cachePool:s},e!==null&&Kr(t,null),Cs(),iv(t),e!==null&&_i(e,t,i,!0),null}function cu(e,t){var a=t.ref;if(a===null)e!==null&&e.ref!==null&&(t.flags|=4194816);else{if(typeof a!="function"&&typeof a!="object")throw Error(u(284));(e===null||e.ref!==a)&&(t.flags|=4194816)}}function ec(e,t,a,i,s){return Ba(t),a=Zs(e,t,a,i,void 0,s),i=Bs(),e!==null&&!nt?(Ls(e,t,s),Un(e,t,s)):(Se&&i&&bs(t),t.flags|=1,ut(e,t,a,s),t.child)}function _v(e,t,a,i,s,c){return Ba(t),t.updateQueue=null,a=bh(t,i,a,s),yh(e),i=Bs(),e!==null&&!nt?(Ls(e,t,c),Un(e,t,c)):(Se&&i&&bs(t),t.flags|=1,ut(e,t,a,c),t.child)}function Sv(e,t,a,i,s){if(Ba(t),t.stateNode===null){var c=bl,h=a.contextType;typeof h=="object"&&h!==null&&(c=dt(h)),c=new a(i,c),t.memoizedState=c.state!==null&&c.state!==void 0?c.state:null,c.updater=Ws,t.stateNode=c,c._reactInternals=t,c=t.stateNode,c.props=i,c.state=t.memoizedState,c.refs={},zs(t),h=a.contextType,c.context=typeof h=="object"&&h!==null?dt(h):bl,c.state=t.memoizedState,h=a.getDerivedStateFromProps,typeof h=="function"&&(Fs(t,a,h,i),c.state=t.memoizedState),typeof a.getDerivedStateFromProps=="function"||typeof c.getSnapshotBeforeUpdate=="function"||typeof c.UNSAFE_componentWillMount!="function"&&typeof c.componentWillMount!="function"||(h=c.state,typeof c.componentWillMount=="function"&&c.componentWillMount(),typeof c.UNSAFE_componentWillMount=="function"&&c.UNSAFE_componentWillMount(),h!==c.state&&Ws.enqueueReplaceState(c,c.state,null),Ti(t,i,c,s),Ai(),c.state=t.memoizedState),typeof c.componentDidMount=="function"&&(t.flags|=4194308),i=!0}else if(e===null){c=t.stateNode;var g=t.memoizedProps,_=ka(a,g);c.props=_;var T=c.context,C=a.contextType;h=bl,typeof C=="object"&&C!==null&&(h=dt(C));var L=a.getDerivedStateFromProps;C=typeof L=="function"||typeof c.getSnapshotBeforeUpdate=="function",g=t.pendingProps!==g,C||typeof c.UNSAFE_componentWillReceiveProps!="function"&&typeof c.componentWillReceiveProps!="function"||(g||T!==h)&&uv(t,c,i,h),ta=!1;var z=t.memoizedState;c.state=z,Ti(t,i,c,s),Ai(),T=t.memoizedState,g||z!==T||ta?(typeof L=="function"&&(Fs(t,a,L,i),T=t.memoizedState),(_=ta||rv(t,a,_,i,z,T,h))?(C||typeof c.UNSAFE_componentWillMount!="function"&&typeof c.componentWillMount!="function"||(typeof c.componentWillMount=="function"&&c.componentWillMount(),typeof c.UNSAFE_componentWillMount=="function"&&c.UNSAFE_componentWillMount()),typeof c.componentDidMount=="function"&&(t.flags|=4194308)):(typeof c.componentDidMount=="function"&&(t.flags|=4194308),t.memoizedProps=i,t.memoizedState=T),c.props=i,c.state=T,c.context=h,i=_):(typeof c.componentDidMount=="function"&&(t.flags|=4194308),i=!1)}else{c=t.stateNode,Ns(e,t),h=t.memoizedProps,C=ka(a,h),c.props=C,L=t.pendingProps,z=c.context,T=a.contextType,_=bl,typeof T=="object"&&T!==null&&(_=dt(T)),g=a.getDerivedStateFromProps,(T=typeof g=="function"||typeof c.getSnapshotBeforeUpdate=="function")||typeof c.UNSAFE_componentWillReceiveProps!="function"&&typeof c.componentWillReceiveProps!="function"||(h!==L||z!==_)&&uv(t,c,i,_),ta=!1,z=t.memoizedState,c.state=z,Ti(t,i,c,s),Ai();var N=t.memoizedState;h!==L||z!==N||ta||e!==null&&e.dependencies!==null&&Yr(e.dependencies)?(typeof g=="function"&&(Fs(t,a,g,i),N=t.memoizedState),(C=ta||rv(t,a,C,i,z,N,_)||e!==null&&e.dependencies!==null&&Yr(e.dependencies))?(T||typeof c.UNSAFE_componentWillUpdate!="function"&&typeof c.componentWillUpdate!="function"||(typeof c.componentWillUpdate=="function"&&c.componentWillUpdate(i,N,_),typeof c.UNSAFE_componentWillUpdate=="function"&&c.UNSAFE_componentWillUpdate(i,N,_)),typeof c.componentDidUpdate=="function"&&(t.flags|=4),typeof c.getSnapshotBeforeUpdate=="function"&&(t.flags|=1024)):(typeof c.componentDidUpdate!="function"||h===e.memoizedProps&&z===e.memoizedState||(t.flags|=4),typeof c.getSnapshotBeforeUpdate!="function"||h===e.memoizedProps&&z===e.memoizedState||(t.flags|=1024),t.memoizedProps=i,t.memoizedState=N),c.props=i,c.state=N,c.context=_,i=C):(typeof c.componentDidUpdate!="function"||h===e.memoizedProps&&z===e.memoizedState||(t.flags|=4),typeof c.getSnapshotBeforeUpdate!="function"||h===e.memoizedProps&&z===e.memoizedState||(t.flags|=1024),i=!1)}return c=i,cu(e,t),i=(t.flags&128)!==0,c||i?(c=t.stateNode,a=i&&typeof a.getDerivedStateFromError!="function"?null:c.render(),t.flags|=1,e!==null&&i?(t.child=zl(t,e.child,null,s),t.child=zl(t,null,a,s)):ut(e,t,a,s),t.memoizedState=c.state,e=t.child):e=Un(e,t,s),e}function xv(e,t,a,i){return yi(),t.flags|=256,ut(e,t,a,i),t.child}var tc={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function nc(e){return{baseLanes:e,cachePool:sh()}}function ac(e,t,a){return e=e!==null?e.childLanes&~a:0,t&&(e|=Xt),e}function Ev(e,t,a){var i=t.pendingProps,s=!1,c=(t.flags&128)!==0,h;if((h=c)||(h=e!==null&&e.memoizedState===null?!1:(et.current&2)!==0),h&&(s=!0,t.flags&=-129),h=(t.flags&32)!==0,t.flags&=-33,e===null){if(Se){if(s?ia(t):ra(),Se){var g=Ge,_;if(_=g){e:{for(_=g,g=fn;_.nodeType!==8;){if(!g){g=null;break e}if(_=tn(_.nextSibling),_===null){g=null;break e}}g=_}g!==null?(t.memoizedState={dehydrated:g,treeContext:Da!==null?{id:zn,overflow:Nn}:null,retryLane:536870912,hydrationErrors:null},_=Tt(18,null,null,0),_.stateNode=g,_.return=t,t.child=_,vt=t,Ge=null,_=!0):_=!1}_||Ua(t)}if(g=t.memoizedState,g!==null&&(g=g.dehydrated,g!==null))return kc(g)?t.lanes=32:t.lanes=536870912,null;Mn(t)}return g=i.children,i=i.fallback,s?(ra(),s=t.mode,g=fu({mode:"hidden",children:g},s),i=ja(i,s,a,null),g.return=t,i.return=t,g.sibling=i,t.child=g,s=t.child,s.memoizedState=nc(a),s.childLanes=ac(e,h,a),t.memoizedState=tc,i):(ia(t),lc(t,g))}if(_=e.memoizedState,_!==null&&(g=_.dehydrated,g!==null)){if(c)t.flags&256?(ia(t),t.flags&=-257,t=ic(e,t,a)):t.memoizedState!==null?(ra(),t.child=e.child,t.flags|=128,t=null):(ra(),s=i.fallback,g=t.mode,i=fu({mode:"visible",children:i.children},g),s=ja(s,g,a,null),s.flags|=2,i.return=t,s.return=t,i.sibling=s,t.child=i,zl(t,e.child,null,a),i=t.child,i.memoizedState=nc(a),i.childLanes=ac(e,h,a),t.memoizedState=tc,t=s);else if(ia(t),kc(g)){if(h=g.nextSibling&&g.nextSibling.dataset,h)var T=h.dgst;h=T,i=Error(u(419)),i.stack="",i.digest=h,bi({value:i,source:null,stack:null}),t=ic(e,t,a)}else if(nt||_i(e,t,a,!1),h=(a&e.childLanes)!==0,nt||h){if(h=Ce,h!==null&&(i=a&-a,i=(i&42)!==0?1:Ho(i),i=(i&(h.suspendedLanes|a))!==0?0:i,i!==0&&i!==_.retryLane))throw _.retryLane=i,yl(e,i),Dt(h,e,i),vv;g.data==="$?"||Ec(),t=ic(e,t,a)}else g.data==="$?"?(t.flags|=192,t.child=e.child,t=null):(e=_.treeContext,Ge=tn(g.nextSibling),vt=t,Se=!0,Ma=null,fn=!1,e!==null&&(Vt[Gt++]=zn,Vt[Gt++]=Nn,Vt[Gt++]=Da,zn=e.id,Nn=e.overflow,Da=t),t=lc(t,i.children),t.flags|=4096);return t}return s?(ra(),s=i.fallback,g=t.mode,_=e.child,T=_.sibling,i=Rn(_,{mode:"hidden",children:i.children}),i.subtreeFlags=_.subtreeFlags&65011712,T!==null?s=Rn(T,s):(s=ja(s,g,a,null),s.flags|=2),s.return=t,i.return=t,i.sibling=s,t.child=i,i=s,s=t.child,g=e.child.memoizedState,g===null?g=nc(a):(_=g.cachePool,_!==null?(T=Ie._currentValue,_=_.parent!==T?{parent:T,pool:T}:_):_=sh(),g={baseLanes:g.baseLanes|a,cachePool:_}),s.memoizedState=g,s.childLanes=ac(e,h,a),t.memoizedState=tc,i):(ia(t),a=e.child,e=a.sibling,a=Rn(a,{mode:"visible",children:i.children}),a.return=t,a.sibling=null,e!==null&&(h=t.deletions,h===null?(t.deletions=[e],t.flags|=16):h.push(e)),t.child=a,t.memoizedState=null,a)}function lc(e,t){return t=fu({mode:"visible",children:t},e.mode),t.return=e,e.child=t}function fu(e,t){return e=Tt(22,e,null,t),e.lanes=0,e.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},e}function ic(e,t,a){return zl(t,e.child,null,a),e=lc(t,t.pendingProps.children),e.flags|=2,t.memoizedState=null,e}function Ov(e,t,a){e.lanes|=t;var i=e.alternate;i!==null&&(i.lanes|=t),Es(e.return,t,a)}function rc(e,t,a,i,s){var c=e.memoizedState;c===null?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:i,tail:a,tailMode:s}:(c.isBackwards=t,c.rendering=null,c.renderingStartTime=0,c.last=i,c.tail=a,c.tailMode=s)}function wv(e,t,a){var i=t.pendingProps,s=i.revealOrder,c=i.tail;if(ut(e,t,i.children,a),i=et.current,(i&2)!==0)i=i&1|2,t.flags|=128;else{if(e!==null&&(e.flags&128)!==0)e:for(e=t.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&Ov(e,a,t);else if(e.tag===19)Ov(e,a,t);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;e.sibling===null;){if(e.return===null||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}i&=1}switch(Q(et,i),s){case"forwards":for(a=t.child,s=null;a!==null;)e=a.alternate,e!==null&&uu(e)===null&&(s=a),a=a.sibling;a=s,a===null?(s=t.child,t.child=null):(s=a.sibling,a.sibling=null),rc(t,!1,s,a,c);break;case"backwards":for(a=null,s=t.child,t.child=null;s!==null;){if(e=s.alternate,e!==null&&uu(e)===null){t.child=s;break}e=s.sibling,s.sibling=a,a=s,s=e}rc(t,!0,a,null,c);break;case"together":rc(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Un(e,t,a){if(e!==null&&(t.dependencies=e.dependencies),fa|=t.lanes,(a&t.childLanes)===0)if(e!==null){if(_i(e,t,a,!1),(a&t.childLanes)===0)return null}else return null;if(e!==null&&t.child!==e.child)throw Error(u(153));if(t.child!==null){for(e=t.child,a=Rn(e,e.pendingProps),t.child=a,a.return=t;e.sibling!==null;)e=e.sibling,a=a.sibling=Rn(e,e.pendingProps),a.return=t;a.sibling=null}return t.child}function uc(e,t){return(e.lanes&t)!==0?!0:(e=e.dependencies,!!(e!==null&&Yr(e)))}function yb(e,t,a){switch(t.tag){case 3:Ze(t,t.stateNode.containerInfo),ea(t,Ie,e.memoizedState.cache),yi();break;case 27:case 5:Zo(t);break;case 4:Ze(t,t.stateNode.containerInfo);break;case 10:ea(t,t.type,t.memoizedProps.value);break;case 13:var i=t.memoizedState;if(i!==null)return i.dehydrated!==null?(ia(t),t.flags|=128,null):(a&t.child.childLanes)!==0?Ev(e,t,a):(ia(t),e=Un(e,t,a),e!==null?e.sibling:null);ia(t);break;case 19:var s=(e.flags&128)!==0;if(i=(a&t.childLanes)!==0,i||(_i(e,t,a,!1),i=(a&t.childLanes)!==0),s){if(i)return wv(e,t,a);t.flags|=128}if(s=t.memoizedState,s!==null&&(s.rendering=null,s.tail=null,s.lastEffect=null),Q(et,et.current),i)break;return null;case 22:case 23:return t.lanes=0,yv(e,t,a);case 24:ea(t,Ie,e.memoizedState.cache)}return Un(e,t,a)}function Av(e,t,a){if(e!==null)if(e.memoizedProps!==t.pendingProps)nt=!0;else{if(!uc(e,a)&&(t.flags&128)===0)return nt=!1,yb(e,t,a);nt=(e.flags&131072)!==0}else nt=!1,Se&&(t.flags&1048576)!==0&&nh(t,Gr,t.index);switch(t.lanes=0,t.tag){case 16:e:{e=t.pendingProps;var i=t.elementType,s=i._init;if(i=s(i._payload),t.type=i,typeof i=="function")ps(i)?(e=ka(i,e),t.tag=1,t=Sv(null,t,i,e,a)):(t.tag=0,t=ec(null,t,i,e,a));else{if(i!=null){if(s=i.$$typeof,s===Y){t.tag=11,t=mv(null,t,i,e,a);break e}else if(s===he){t.tag=14,t=pv(null,t,i,e,a);break e}}throw t=Jn(i)||i,Error(u(306,t,""))}}return t;case 0:return ec(e,t,t.type,t.pendingProps,a);case 1:return i=t.type,s=ka(i,t.pendingProps),Sv(e,t,i,s,a);case 3:e:{if(Ze(t,t.stateNode.containerInfo),e===null)throw Error(u(387));i=t.pendingProps;var c=t.memoizedState;s=c.element,Ns(e,t),Ti(t,i,null,a);var h=t.memoizedState;if(i=h.cache,ea(t,Ie,i),i!==c.cache&&Os(t,[Ie],a,!0),Ai(),i=h.element,c.isDehydrated)if(c={element:i,isDehydrated:!1,cache:h.cache},t.updateQueue.baseState=c,t.memoizedState=c,t.flags&256){t=xv(e,t,i,a);break e}else if(i!==s){s=Ht(Error(u(424)),t),bi(s),t=xv(e,t,i,a);break e}else{switch(e=t.stateNode.containerInfo,e.nodeType){case 9:e=e.body;break;default:e=e.nodeName==="HTML"?e.ownerDocument.body:e}for(Ge=tn(e.firstChild),vt=t,Se=!0,Ma=null,fn=!0,a=lv(t,null,i,a),t.child=a;a;)a.flags=a.flags&-3|4096,a=a.sibling}else{if(yi(),i===s){t=Un(e,t,a);break e}ut(e,t,i,a)}t=t.child}return t;case 26:return cu(e,t),e===null?(a=Nm(t.type,null,t.pendingProps,null))?t.memoizedState=a:Se||(a=t.type,e=t.pendingProps,i=wu(oe.current).createElement(a),i[ft]=t,i[pt]=e,st(i,a,e),tt(i),t.stateNode=i):t.memoizedState=Nm(t.type,e.memoizedProps,t.pendingProps,e.memoizedState),null;case 27:return Zo(t),e===null&&Se&&(i=t.stateNode=Tm(t.type,t.pendingProps,oe.current),vt=t,fn=!0,s=Ge,ma(t.type)?(Hc=s,Ge=tn(i.firstChild)):Ge=s),ut(e,t,t.pendingProps.children,a),cu(e,t),e===null&&(t.flags|=4194304),t.child;case 5:return e===null&&Se&&((s=i=Ge)&&(i=Xb(i,t.type,t.pendingProps,fn),i!==null?(t.stateNode=i,vt=t,Ge=tn(i.firstChild),fn=!1,s=!0):s=!1),s||Ua(t)),Zo(t),s=t.type,c=t.pendingProps,h=e!==null?e.memoizedProps:null,i=c.children,Bc(s,c)?i=null:h!==null&&Bc(s,h)&&(t.flags|=32),t.memoizedState!==null&&(s=Zs(e,t,cb,null,null,a),Ji._currentValue=s),cu(e,t),ut(e,t,i,a),t.child;case 6:return e===null&&Se&&((e=a=Ge)&&(a=Kb(a,t.pendingProps,fn),a!==null?(t.stateNode=a,vt=t,Ge=null,e=!0):e=!1),e||Ua(t)),null;case 13:return Ev(e,t,a);case 4:return Ze(t,t.stateNode.containerInfo),i=t.pendingProps,e===null?t.child=zl(t,null,i,a):ut(e,t,i,a),t.child;case 11:return mv(e,t,t.type,t.pendingProps,a);case 7:return ut(e,t,t.pendingProps,a),t.child;case 8:return ut(e,t,t.pendingProps.children,a),t.child;case 12:return ut(e,t,t.pendingProps.children,a),t.child;case 10:return i=t.pendingProps,ea(t,t.type,i.value),ut(e,t,i.children,a),t.child;case 9:return s=t.type._context,i=t.pendingProps.children,Ba(t),s=dt(s),i=i(s),t.flags|=1,ut(e,t,i,a),t.child;case 14:return pv(e,t,t.type,t.pendingProps,a);case 15:return gv(e,t,t.type,t.pendingProps,a);case 19:return wv(e,t,a);case 31:return i=t.pendingProps,a=t.mode,i={mode:i.mode,children:i.children},e===null?(a=fu(i,a),a.ref=t.ref,t.child=a,a.return=t,t=a):(a=Rn(e.child,i),a.ref=t.ref,t.child=a,a.return=t,t=a),t;case 22:return yv(e,t,a);case 24:return Ba(t),i=dt(Ie),e===null?(s=Ts(),s===null&&(s=Ce,c=ws(),s.pooledCache=c,c.refCount++,c!==null&&(s.pooledCacheLanes|=a),s=c),t.memoizedState={parent:i,cache:s},zs(t),ea(t,Ie,s)):((e.lanes&a)!==0&&(Ns(e,t),Ti(t,null,null,a),Ai()),s=e.memoizedState,c=t.memoizedState,s.parent!==i?(s={parent:i,cache:i},t.memoizedState=s,t.lanes===0&&(t.memoizedState=t.updateQueue.baseState=s),ea(t,Ie,i)):(i=c.cache,ea(t,Ie,i),i!==s.cache&&Os(t,[Ie],a,!0))),ut(e,t,t.pendingProps.children,a),t.child;case 29:throw t.pendingProps}throw Error(u(156,t.tag))}function Zn(e){e.flags|=4}function Tv(e,t){if(t.type!=="stylesheet"||(t.state.loading&4)!==0)e.flags&=-16777217;else if(e.flags|=16777216,!Um(t)){if(t=Yt.current,t!==null&&((pe&4194048)===pe?dn!==null:(pe&62914560)!==pe&&(pe&536870912)===0||t!==dn))throw Oi=Rs,ch;e.flags|=8192}}function du(e,t){t!==null&&(e.flags|=4),e.flags&16384&&(t=e.tag!==22?id():536870912,e.lanes|=t,Cl|=t)}function Mi(e,t){if(!Se)switch(e.tailMode){case"hidden":t=e.tail;for(var a=null;t!==null;)t.alternate!==null&&(a=t),t=t.sibling;a===null?e.tail=null:a.sibling=null;break;case"collapsed":a=e.tail;for(var i=null;a!==null;)a.alternate!==null&&(i=a),a=a.sibling;i===null?t||e.tail===null?e.tail=null:e.tail.sibling=null:i.sibling=null}}function qe(e){var t=e.alternate!==null&&e.alternate.child===e.child,a=0,i=0;if(t)for(var s=e.child;s!==null;)a|=s.lanes|s.childLanes,i|=s.subtreeFlags&65011712,i|=s.flags&65011712,s.return=e,s=s.sibling;else for(s=e.child;s!==null;)a|=s.lanes|s.childLanes,i|=s.subtreeFlags,i|=s.flags,s.return=e,s=s.sibling;return e.subtreeFlags|=i,e.childLanes=a,t}function bb(e,t,a){var i=t.pendingProps;switch(_s(t),t.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return qe(t),null;case 1:return qe(t),null;case 3:return a=t.stateNode,i=null,e!==null&&(i=e.memoizedState.cache),t.memoizedState.cache!==i&&(t.flags|=2048),Dn(Ie),Pn(),a.pendingContext&&(a.context=a.pendingContext,a.pendingContext=null),(e===null||e.child===null)&&(gi(t)?Zn(t):e===null||e.memoizedState.isDehydrated&&(t.flags&256)===0||(t.flags|=1024,ih())),qe(t),null;case 26:return a=t.memoizedState,e===null?(Zn(t),a!==null?(qe(t),Tv(t,a)):(qe(t),t.flags&=-16777217)):a?a!==e.memoizedState?(Zn(t),qe(t),Tv(t,a)):(qe(t),t.flags&=-16777217):(e.memoizedProps!==i&&Zn(t),qe(t),t.flags&=-16777217),null;case 27:Er(t),a=oe.current;var s=t.type;if(e!==null&&t.stateNode!=null)e.memoizedProps!==i&&Zn(t);else{if(!i){if(t.stateNode===null)throw Error(u(166));return qe(t),null}e=te.current,gi(t)?ah(t):(e=Tm(s,i,a),t.stateNode=e,Zn(t))}return qe(t),null;case 5:if(Er(t),a=t.type,e!==null&&t.stateNode!=null)e.memoizedProps!==i&&Zn(t);else{if(!i){if(t.stateNode===null)throw Error(u(166));return qe(t),null}if(e=te.current,gi(t))ah(t);else{switch(s=wu(oe.current),e){case 1:e=s.createElementNS("http://www.w3.org/2000/svg",a);break;case 2:e=s.createElementNS("http://www.w3.org/1998/Math/MathML",a);break;default:switch(a){case"svg":e=s.createElementNS("http://www.w3.org/2000/svg",a);break;case"math":e=s.createElementNS("http://www.w3.org/1998/Math/MathML",a);break;case"script":e=s.createElement("div"),e.innerHTML=" - + +
diff --git a/vite-app/src/App.tsx b/vite-app/src/App.tsx index 9eeaae0f..bfdeb141 100644 --- a/vite-app/src/App.tsx +++ b/vite-app/src/App.tsx @@ -32,7 +32,8 @@ const App = observer(() => { ws.onopen = () => { console.log("Connected to file watcher"); - state.isConnected = true; + state.setConnected(true); + state.setLoading(true); // Set loading when connection opens reconnectAttemptsRef.current = 0; // Reset reconnect attempts on successful connection }; @@ -48,18 +49,21 @@ const App = observer(() => { console.log("initialize_logs", rows); state.upsertRows(rows); } else if (update.type === "log") { + state.setLoading(true); // Set loading for individual log updates const row: EvaluationRow = EvaluationRowSchema.parse(update.row); console.log("log", row); state.upsertRows([row]); } } catch (error) { console.error("Failed to parse WebSocket message:", error); + state.setLoading(false); // Clear loading state on error } }; ws.onclose = (event) => { console.log("Disconnected from file watcher", event.code, event.reason); - state.isConnected = false; + state.setConnected(false); + state.setLoading(false); // Clear loading state on disconnect // Attempt to reconnect if not a normal closure if ( @@ -72,7 +76,8 @@ const App = observer(() => { ws.onerror = (error) => { console.error("WebSocket error:", error); - state.isConnected = false; + state.setConnected(false); + state.setLoading(false); // Clear loading state on error }; }; @@ -99,6 +104,7 @@ const App = observer(() => { // Manual refresh handler const handleManualRefresh = () => { + state.setLoading(true); // Set loading when manually refreshing if (wsRef.current) { try { wsRef.current.onclose = null; // Prevent triggering reconnect logic diff --git a/vite-app/src/GlobalState.tsx b/vite-app/src/GlobalState.tsx index 14db70ae..4d7f6de1 100644 --- a/vite-app/src/GlobalState.tsx +++ b/vite-app/src/GlobalState.tsx @@ -1,7 +1,9 @@ -import { makeAutoObservable } from "mobx"; +import { makeAutoObservable, runInAction } from "mobx"; import type { EvaluationRow } from "./types/eval-protocol"; -import type { PivotConfig } from "./types/filters"; +import type { PivotConfig, FilterGroup } from "./types/filters"; import flattenJson from "./util/flatten-json"; +import type { FlatJson } from "./util/flatten-json"; +import { createFilterFunction } from "./util/filter-utils"; // Default pivot configuration const DEFAULT_PIVOT_CONFIG: PivotConfig = { @@ -12,6 +14,15 @@ const DEFAULT_PIVOT_CONFIG: PivotConfig = { filters: [], }; +// Default table filter configuration +const DEFAULT_TABLE_FILTER_CONFIG: FilterGroup[] = []; + +// Default pagination configuration +const DEFAULT_PAGINATION_CONFIG = { + currentPage: 1, + pageSize: 25, +}; + export class GlobalState { isConnected: boolean = false; // rollout_id -> EvaluationRow @@ -20,10 +31,41 @@ export class GlobalState { expandedRows: Record = {}; // Pivot configuration pivotConfig: PivotConfig; + // Table filter configuration + tableFilterConfig: FilterGroup[]; + // Debounced, actually applied table filter configuration (for performance while typing) + appliedTableFilterConfig: FilterGroup[]; + // Pagination configuration + currentPage: number; + pageSize: number; + // Loading state + isLoading: boolean = true; + + // Cached, denormalized data for performance + // rollout_id -> flattened row + private flattenedById: Record = {}; + // rollout_id -> created_at timestamp (ms) for cheap sort + private createdAtMsById: Record = {}; + + // Debounce timers for localStorage saves and filter application + private savePivotConfigTimer: ReturnType | null = null; + private saveTableFilterConfigTimer: ReturnType | null = + null; + private savePaginationConfigTimer: ReturnType | null = + null; + private applyTableFilterTimer: ReturnType | null = null; constructor() { // Load pivot config from localStorage or use defaults this.pivotConfig = this.loadPivotConfig(); + // Load table filter config from localStorage or use defaults + this.tableFilterConfig = this.loadTableFilterConfig(); + // Initialize applied filter config with current value + this.appliedTableFilterConfig = this.tableFilterConfig.slice(); + // Load pagination config from localStorage or use defaults + const paginationConfig = this.loadPaginationConfig(); + this.currentPage = paginationConfig.currentPage; + this.pageSize = paginationConfig.pageSize; makeAutoObservable(this); } @@ -42,13 +84,92 @@ export class GlobalState { return { ...DEFAULT_PIVOT_CONFIG }; } - // Save pivot configuration to localStorage - private savePivotConfig() { + // Load table filter configuration from localStorage + private loadTableFilterConfig(): FilterGroup[] { + try { + const stored = localStorage.getItem("tableFilterConfig"); + if (stored) { + const parsed = JSON.parse(stored); + return Array.isArray(parsed) ? parsed : DEFAULT_TABLE_FILTER_CONFIG; + } + } catch (error) { + console.warn( + "Failed to load table filter config from localStorage:", + error + ); + } + return DEFAULT_TABLE_FILTER_CONFIG; + } + + // Load pagination configuration from localStorage + private loadPaginationConfig() { try { - localStorage.setItem("pivotConfig", JSON.stringify(this.pivotConfig)); + const stored = localStorage.getItem("paginationConfig"); + if (stored) { + const parsed = JSON.parse(stored); + // Merge with defaults to handle any missing properties + return { ...DEFAULT_PAGINATION_CONFIG, ...parsed }; + } } catch (error) { - console.warn("Failed to save pivot config to localStorage:", error); + console.warn( + "Failed to load pagination config from localStorage:", + error + ); } + return { ...DEFAULT_PAGINATION_CONFIG }; + } + + // Save pivot configuration to localStorage + private savePivotConfig() { + if (this.savePivotConfigTimer) clearTimeout(this.savePivotConfigTimer); + this.savePivotConfigTimer = setTimeout(() => { + try { + localStorage.setItem("pivotConfig", JSON.stringify(this.pivotConfig)); + } catch (error) { + console.warn("Failed to save pivot config to localStorage:", error); + } + }, 200); + } + + // Save table filter configuration to localStorage + private saveTableFilterConfig() { + if (this.saveTableFilterConfigTimer) + clearTimeout(this.saveTableFilterConfigTimer); + this.saveTableFilterConfigTimer = setTimeout(() => { + try { + localStorage.setItem( + "tableFilterConfig", + JSON.stringify(this.tableFilterConfig) + ); + } catch (error) { + console.warn( + "Failed to save table filter config to localStorage:", + error + ); + } + }, 200); + } + + // Save pagination configuration to localStorage + private savePaginationConfig() { + if (this.savePaginationConfigTimer) + clearTimeout(this.savePaginationConfigTimer); + this.savePaginationConfigTimer = setTimeout(() => { + try { + localStorage.setItem( + "paginationConfig", + JSON.stringify({ + currentPage: this.currentPage, + pageSize: this.pageSize, + }) + ); + } catch (error) { + console.warn( + "Failed to save pagination config to localStorage:", + error + ); + } + }, 200); } // Update pivot configuration and save to localStorage @@ -57,6 +178,31 @@ export class GlobalState { this.savePivotConfig(); } + // Update table filter configuration and save to localStorage + updateTableFilterConfig(filters: FilterGroup[]) { + this.tableFilterConfig = filters; + this.saveTableFilterConfig(); + + // Debounce application of filters to avoid re-filtering on every keystroke + if (this.applyTableFilterTimer) clearTimeout(this.applyTableFilterTimer); + this.applyTableFilterTimer = setTimeout(() => { + this.appliedTableFilterConfig = this.tableFilterConfig.slice(); + }, 150); + } + + // Update pagination configuration and save to localStorage + updatePaginationConfig( + updates: Partial<{ currentPage: number; pageSize: number }> + ) { + if (updates.currentPage !== undefined) { + this.currentPage = updates.currentPage; + } + if (updates.pageSize !== undefined) { + this.pageSize = updates.pageSize; + } + this.savePaginationConfig(); + } + // Reset pivot configuration to defaults resetPivotConfig() { this.pivotConfig = { @@ -66,13 +212,67 @@ export class GlobalState { this.savePivotConfig(); } + // Reset table filter configuration to defaults + resetTableFilterConfig() { + this.tableFilterConfig = [...DEFAULT_TABLE_FILTER_CONFIG]; + this.appliedTableFilterConfig = [...DEFAULT_TABLE_FILTER_CONFIG]; + this.saveTableFilterConfig(); + } + + // Reset pagination configuration to defaults + resetPaginationConfig() { + this.currentPage = DEFAULT_PAGINATION_CONFIG.currentPage; + this.pageSize = DEFAULT_PAGINATION_CONFIG.pageSize; + this.savePaginationConfig(); + } + + // Set current page + setCurrentPage(page: number) { + this.currentPage = page; + this.savePaginationConfig(); + } + + // Set page size + setPageSize(size: number) { + this.pageSize = size; + this.currentPage = 1; // Reset to first page when changing page size + this.savePaginationConfig(); + } + + // Set loading state + setLoading(loading: boolean) { + this.isLoading = loading; + } + + // Set connection state + setConnected(connected: boolean) { + this.isConnected = connected; + } + upsertRows(dataset: EvaluationRow[]) { + runInAction(() => { + this.isLoading = true; + }); + dataset.forEach((row) => { if (!row.execution_metadata?.rollout_id) { return; } - this.dataset[row.execution_metadata.rollout_id] = row; + const rolloutId = row.execution_metadata.rollout_id; + this.dataset[rolloutId] = row; + // Cache created_at in ms for cheap sorts + const createdMs = new Date(row.created_at).getTime(); + this.createdAtMsById[rolloutId] = isNaN(createdMs) ? 0 : createdMs; + // Cache flattened row for filtering/pivot keys + this.flattenedById[rolloutId] = flattenJson(row); + }); + + runInAction(() => { + // Reset to first page when dataset changes + this.currentPage = 1; + this.isLoading = false; }); + this.savePaginationConfig(); } toggleRowExpansion(rolloutId?: string) { @@ -100,26 +300,65 @@ export class GlobalState { } // Computed values following MobX best practices - get sortedDataset() { - return Object.values(this.dataset).sort( - (a, b) => - new Date(b.created_at).getTime() - new Date(a.created_at).getTime() + get sortedIds() { + return Object.keys(this.dataset).sort( + (a, b) => (this.createdAtMsById[b] ?? 0) - (this.createdAtMsById[a] ?? 0) ); } + get sortedDataset() { + return this.sortedIds.map((id) => this.dataset[id]); + } + get flattenedDataset() { - return this.sortedDataset.map((row) => flattenJson(row)); + return this.sortedIds.map((id) => this.flattenedById[id]); + } + + get filteredFlattenedDataset() { + if (this.appliedTableFilterConfig.length === 0) { + return this.flattenedDataset; + } + + const filterFunction = createFilterFunction(this.appliedTableFilterConfig)!; + return this.flattenedDataset.filter(filterFunction); + } + + get filteredOriginalDataset() { + if (this.appliedTableFilterConfig.length === 0) { + return this.sortedDataset; + } + + const filterFunction = createFilterFunction(this.appliedTableFilterConfig)!; + return this.sortedIds + .filter((id) => filterFunction(this.flattenedById[id])) + .map((id) => this.dataset[id]); } get flattenedDatasetKeys() { const keySet = new Set(); - this.flattenedDataset.forEach((row) => { - Object.keys(row).forEach((key) => keySet.add(key)); + // Iterate over cached flattened rows to build a unique key list + this.sortedIds.forEach((id) => { + const flat = this.flattenedById[id]; + if (flat) { + Object.keys(flat).forEach((key) => keySet.add(key)); + } }); return Array.from(keySet); } get totalCount() { - return Object.keys(this.dataset).length; + return this.filteredFlattenedDataset.length; + } + + get totalPages() { + return Math.ceil(this.totalCount / this.pageSize); + } + + get startRow() { + return (this.currentPage - 1) * this.pageSize + 1; + } + + get endRow() { + return Math.min(this.currentPage * this.pageSize, this.totalCount); } } diff --git a/vite-app/src/components/Dashboard.tsx b/vite-app/src/components/Dashboard.tsx index 5911279c..7bedf67d 100644 --- a/vite-app/src/components/Dashboard.tsx +++ b/vite-app/src/components/Dashboard.tsx @@ -49,6 +49,24 @@ const EmptyState = ({ onRefresh }: { onRefresh: () => void }) => { ); }; +const LoadingState = () => { + return ( +
+
+
+
+
+

+ Loading evaluation data... +

+

+ Connecting to the server and loading data +

+
+
+ ); +}; + const Dashboard = observer(({ onRefresh }: DashboardProps) => { const expandAll = () => state.setAllRowsExpanded(true); const collapseAll = () => state.setAllRowsExpanded(false); @@ -81,7 +99,9 @@ const Dashboard = observer(({ onRefresh }: DashboardProps) => { {/* Content Area */} - {state.totalCount === 0 ? ( + {state.isLoading ? ( + + ) : state.sortedDataset.length === 0 ? ( ) : (
diff --git a/vite-app/src/components/EvaluationTable.tsx b/vite-app/src/components/EvaluationTable.tsx index fb470b9e..a2f84cc6 100644 --- a/vite-app/src/components/EvaluationTable.tsx +++ b/vite-app/src/components/EvaluationTable.tsx @@ -1,9 +1,9 @@ import { observer } from "mobx-react"; -import { useState, useEffect } from "react"; import { state } from "../App"; import { EvaluationRow } from "./EvaluationRow"; import Button from "./Button"; import Select from "./Select"; +import FilterSelector from "./FilterSelector"; import { TableHeader, TableHead, @@ -14,7 +14,9 @@ const TableBody = observer( ({ currentPage, pageSize }: { currentPage: number; pageSize: number }) => { const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; - const paginatedData = state.sortedDataset.slice(startIndex, endIndex); + // Use filtered original data for pagination + const filteredData = state.filteredOriginalDataset; + const paginatedData = filteredData.slice(startIndex, endIndex); return ( @@ -32,30 +34,54 @@ const TableBody = observer( // Dedicated component for rendering the list - following MobX best practices export const EvaluationTable = observer(() => { - const [currentPage, setCurrentPage] = useState(1); - const [pageSize, setPageSize] = useState(25); - - const totalRows = state.sortedDataset.length; - const totalPages = Math.ceil(totalRows / pageSize); - const startRow = (currentPage - 1) * pageSize + 1; - const endRow = Math.min(currentPage * pageSize, totalRows); + const totalRows = state.filteredOriginalDataset.length; + const totalPages = Math.ceil(totalRows / state.pageSize); + const startRow = (state.currentPage - 1) * state.pageSize + 1; + const endRow = Math.min(state.currentPage * state.pageSize, totalRows); const handlePageChange = (page: number) => { - setCurrentPage(Math.max(1, Math.min(page, totalPages))); + state.setCurrentPage(Math.max(1, Math.min(page, totalPages))); }; const handlePageSizeChange = (newPageSize: number) => { - setPageSize(newPageSize); - setCurrentPage(1); // Reset to first page when changing page size + state.setPageSize(newPageSize); }; - // Reset to first page when dataset changes - useEffect(() => { - setCurrentPage(1); - }, [totalRows]); + const handleFiltersChange = (filters: any[]) => { + state.updateTableFilterConfig(filters); + }; return (
+ {/* Filter Controls */} +
+
+
+

Table Filters

+
+ {state.tableFilterConfig.length > 0 ? ( + <> + Showing {totalRows} of {state.sortedDataset.length} rows + {totalRows !== state.sortedDataset.length && ( + (filtered) + )} + + ) : ( + `Showing all ${state.sortedDataset.length} rows` + )} +
+
+
+
+ +
+
+ {/* Pagination Controls - Fixed outside scrollable area */}
@@ -65,7 +91,7 @@ export const EvaluationTable = observer(() => {
onUpdate({ value: e.target.value })} + value={localValue} + onChange={onChange} + onKeyDown={onKeyDown} + onBlur={onBlur} placeholder="Value" className={`${commonStyles.input.base} ${commonStyles.input.size.sm} ${commonStyles.width.sm}`} style={{ boxShadow: commonStyles.input.shadow }} diff --git a/vite-app/src/components/FilterSelector.tsx b/vite-app/src/components/FilterSelector.tsx new file mode 100644 index 00000000..2800063d --- /dev/null +++ b/vite-app/src/components/FilterSelector.tsx @@ -0,0 +1,211 @@ +import React, { useCallback, useMemo } from "react"; +import type { FilterConfig, FilterGroup } from "../types/filters"; +import SearchableSelect from "./SearchableSelect"; +import FilterInput from "./FilterInput"; +import Button from "./Button"; +import { getFieldType, getOperatorsForField } from "../util/filter-utils"; + +interface FilterSelectorProps { + filters: FilterGroup[]; + onFiltersChange: (filters: FilterGroup[]) => void; + availableKeys: string[]; + title?: string; +} + +const FilterSelectorComponent = ({ + filters, + onFiltersChange, + availableKeys, + title = "Filters", +}: FilterSelectorProps) => { + const addFilterGroup = useCallback(() => { + onFiltersChange([...filters, { logic: "AND", filters: [] }]); + }, [filters, onFiltersChange]); + + const removeFilterGroup = useCallback( + (index: number) => { + onFiltersChange(filters.filter((_, i) => i !== index)); + }, + [filters, onFiltersChange] + ); + + const updateFilterGroupLogic = useCallback( + (index: number, logic: "AND" | "OR") => { + const newFilters = [...filters]; + newFilters[index] = { ...newFilters[index], logic }; + onFiltersChange(newFilters); + }, + [filters, onFiltersChange] + ); + + const addFilterToGroup = useCallback( + (groupIndex: number) => { + const newFilters = [...filters]; + newFilters[groupIndex].filters.push({ + field: "", + operator: "contains", + value: "", + type: "text", + }); + onFiltersChange(newFilters); + }, + [filters, onFiltersChange] + ); + + const removeFilterFromGroup = useCallback( + (groupIndex: number, filterIndex: number) => { + const newFilters = [...filters]; + newFilters[groupIndex].filters.splice(filterIndex, 1); + onFiltersChange(newFilters); + }, + [filters, onFiltersChange] + ); + + const updateFilterInGroup = useCallback( + ( + groupIndex: number, + filterIndex: number, + updates: Partial + ) => { + const newFilters = [...filters]; + newFilters[groupIndex].filters[filterIndex] = { + ...newFilters[groupIndex].filters[filterIndex], + ...updates, + }; + onFiltersChange(newFilters); + }, + [filters, onFiltersChange] + ); + + // Memoize options for available keys so we don't rebuild objects every render + const keyOptions = useMemo( + () => availableKeys.map((key) => ({ value: key, label: key })), + [availableKeys] + ); + + return ( +
+
+

{title}

+ {filters.length > 0 && ( + + )} +
+ +
+ {filters.map((group, groupIndex) => ( +
0 ? "border-t border-gray-200 mt-2" : "" + }`} + > +
+
+ + Group {groupIndex + 1} + + + updateFilterGroupLogic(groupIndex, value as "AND" | "OR") + } + options={[ + { value: "AND", label: "AND (all filters must match)" }, + { value: "OR", label: "OR (any filter can match)" }, + ]} + size="sm" + className="min-w-40" + /> +
+ +
+ +
+ {group.filters.map((filter, filterIndex) => { + const fieldType = filter.type || getFieldType(filter.field); + const operators = getOperatorsForField(fieldType); + + return ( +
+ { + const newType = getFieldType(value); + updateFilterInGroup(groupIndex, filterIndex, { + field: value, + type: newType, + operator: operators[0]?.value || "contains", + }); + }} + options={keyOptions} + placeholder="Select field..." + size="sm" + className="min-w-40" + /> + + updateFilterInGroup(groupIndex, filterIndex, { + operator: value, + }) + } + options={operators} + size="sm" + className="min-w-36" + /> + + updateFilterInGroup(groupIndex, filterIndex, updates) + } + /> + +
+ ); + })} + +
+ +
+
+
+ ))} + + {filters.length === 0 && ( +
+ +
+ )} +
+
+ ); +}; + +const FilterSelector = React.memo(FilterSelectorComponent); + +export default FilterSelector; diff --git a/vite-app/src/components/PivotTab.tsx b/vite-app/src/components/PivotTab.tsx index 4b870653..a381022c 100644 --- a/vite-app/src/components/PivotTab.tsx +++ b/vite-app/src/components/PivotTab.tsx @@ -2,14 +2,10 @@ import { observer } from "mobx-react"; import PivotTable from "./PivotTable"; import SearchableSelect from "./SearchableSelect"; import Button from "./Button"; -import FilterInput from "./FilterInput"; +import FilterSelector from "./FilterSelector"; import { state } from "../App"; -import { type FilterConfig, type FilterGroup } from "../types/filters"; -import { - getFieldType, - getOperatorsForField, - createFilterFunction, -} from "../util/filter-utils"; +import { type FilterGroup } from "../types/filters"; +import { createFilterFunction } from "../util/filter-utils"; interface FieldSelectorProps { title: string; @@ -128,177 +124,6 @@ const AggregatorSelector = ({
); -const FilterSelector = ({ - filters, - onFiltersChange, - availableKeys, -}: { - filters: FilterGroup[]; - onFiltersChange: (filters: FilterGroup[]) => void; - availableKeys: string[]; -}) => { - const addFilterGroup = () => { - onFiltersChange([...filters, { logic: "AND", filters: [] }]); - }; - - const removeFilterGroup = (index: number) => { - onFiltersChange(filters.filter((_, i) => i !== index)); - }; - - const updateFilterGroupLogic = (index: number, logic: "AND" | "OR") => { - const newFilters = [...filters]; - newFilters[index] = { ...newFilters[index], logic }; - onFiltersChange(newFilters); - }; - - const addFilterToGroup = (groupIndex: number) => { - const newFilters = [...filters]; - newFilters[groupIndex].filters.push({ - field: "", - operator: "contains", - value: "", - type: "text", - }); - onFiltersChange(newFilters); - }; - - const removeFilterFromGroup = (groupIndex: number, filterIndex: number) => { - const newFilters = [...filters]; - newFilters[groupIndex].filters.splice(filterIndex, 1); - onFiltersChange(newFilters); - }; - - const updateFilterInGroup = ( - groupIndex: number, - filterIndex: number, - updates: Partial - ) => { - const newFilters = [...filters]; - newFilters[groupIndex].filters[filterIndex] = { - ...newFilters[groupIndex].filters[filterIndex], - ...updates, - }; - onFiltersChange(newFilters); - }; - - return ( -
-
Filters:
-
- {filters.map((group, groupIndex) => ( -
-
-
- - Group {groupIndex + 1}: - - - updateFilterGroupLogic(groupIndex, value as "AND" | "OR") - } - options={[ - { value: "AND", label: "AND (all filters must match)" }, - { value: "OR", label: "OR (any filter can match)" }, - ]} - size="sm" - className="min-w-48" - /> -
- -
- -
- {group.filters.map((filter, filterIndex) => { - const fieldType = filter.type || getFieldType(filter.field); - const operators = getOperatorsForField(filter.field, fieldType); - - return ( -
- { - const newField = value; - const newType = getFieldType(newField); - updateFilterInGroup(groupIndex, filterIndex, { - field: newField, - type: newType, - }); - }} - options={[ - { value: "", label: "Select a field..." }, - ...(availableKeys?.map((key) => ({ - value: key, - label: key, - })) || []), - ]} - size="sm" - className="min-w-48" - /> - - updateFilterInGroup(groupIndex, filterIndex, { - operator: value, - }) - } - options={operators.map((op) => ({ - value: op.value, - label: op.label, - }))} - size="sm" - className="min-w-32" - /> - - updateFilterInGroup(groupIndex, filterIndex, updates) - } - /> - -
- ); - })} - - -
-
- ))} - - -
-
- ); -}; - const PivotTab = observer(() => { const { pivotConfig } = state; @@ -424,6 +249,7 @@ const PivotTab = observer(() => { filters={pivotConfig.filters} onFiltersChange={updateFilters} availableKeys={availableKeys} + title="Filters" /> {/* diff --git a/vite-app/src/components/SearchableSelect.tsx b/vite-app/src/components/SearchableSelect.tsx index 2fcca220..2fc19319 100644 --- a/vite-app/src/components/SearchableSelect.tsx +++ b/vite-app/src/components/SearchableSelect.tsx @@ -1,4 +1,10 @@ -import React, { useState, useRef, useEffect } from "react"; +import React, { + useState, + useRef, + useEffect, + useMemo, + useLayoutEffect, +} from "react"; import { commonStyles } from "../styles/common"; interface SearchableSelectProps { @@ -29,22 +35,29 @@ const SearchableSelect = React.forwardRef< ) => { const [isOpen, setIsOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(""); - const [filteredOptions, setFilteredOptions] = useState(options); + // Memoize filtering to avoid extra state updates and re-renders + const filteredOptions = useMemo(() => { + const lowered = searchTerm.toLowerCase(); + if (!lowered) return options; + return options.filter( + (option) => + option.label.toLowerCase().includes(lowered) || + option.value.toLowerCase().includes(lowered) + ); + }, [searchTerm, options]); const [dropdownPosition, setDropdownPosition] = useState<"left" | "right">( "left" ); + const [dropdownWidth, setDropdownWidth] = useState( + undefined + ); const [highlightedIndex, setHighlightedIndex] = useState(-1); const containerRef = useRef(null); const inputRef = useRef(null); + // Reset highlighted index when the search or options change useEffect(() => { - const filtered = options.filter( - (option) => - option.label.toLowerCase().includes(searchTerm.toLowerCase()) || - option.value.toLowerCase().includes(searchTerm.toLowerCase()) - ); - setFilteredOptions(filtered); - setHighlightedIndex(-1); // Reset highlighted index when options change + setHighlightedIndex(-1); }, [searchTerm, options]); useEffect(() => { @@ -100,24 +113,50 @@ const SearchableSelect = React.forwardRef< } }; - const calculateDropdownPosition = () => { - if (!containerRef.current) return "left"; + // Compute side and width so the dropdown can be wider than the trigger but still fit viewport + const computeDropdownLayout = (): { + side: "left" | "right"; + width: number; + } => { + if (!containerRef.current) return { side: "left", width: 240 }; const rect = containerRef.current.getBoundingClientRect(); const windowWidth = window.innerWidth; - const estimatedDropdownWidth = 300; // Approximate width for dropdown content + const VIEWPORT_MARGIN = 16; // px + const EXTRA_WIDTH = 240; // desired extra room beyond trigger + const MAX_WIDTH = 600; // hard cap + + const desired = Math.min(rect.width + EXTRA_WIDTH, MAX_WIDTH); - // If dropdown would overflow right edge, position it to the left - if (rect.left + estimatedDropdownWidth > windowWidth) { - return "right"; + const spaceRight = windowWidth - rect.left - VIEWPORT_MARGIN; // space if anchored left-0 + const spaceLeft = rect.right - VIEWPORT_MARGIN; // space if anchored right-0 + + const widthRight = Math.max(rect.width, Math.min(desired, spaceRight)); + const widthLeft = Math.max(rect.width, Math.min(desired, spaceLeft)); + + // Prefer the side that can accommodate closer to desired width + if (widthRight >= widthLeft && widthRight >= rect.width) { + return { side: "left", width: widthRight }; } - return "left"; + if (widthLeft > widthRight && widthLeft >= rect.width) { + return { side: "right", width: widthLeft }; + } + + // Fallback: clamp to viewport with preference to right anchoring if less overflow + const clamped = Math.max( + rect.width, + Math.min(desired, windowWidth - VIEWPORT_MARGIN * 2) + ); + const preferRight = rect.left < windowWidth - rect.right; + return { side: preferRight ? "left" : "right", width: clamped }; }; const handleToggle = () => { if (!disabled) { if (!isOpen) { - setDropdownPosition(calculateDropdownPosition()); + const layout = computeDropdownLayout(); + setDropdownPosition(layout.side); + setDropdownWidth(layout.width); } setIsOpen(!isOpen); if (!isOpen) { @@ -126,7 +165,62 @@ const SearchableSelect = React.forwardRef< } }; - const selectedOption = options.find((option) => option.value === value); + const selectedOption = useMemo( + () => options.find((option) => option.value === value), + [options, value] + ); + + // --- Simple list virtualization for large option sets --- + const listRef = useRef(null); + const [scrollTop, setScrollTop] = useState(0); + const [containerHeight, setContainerHeight] = useState(192); // Tailwind max-h-48 (~192px) + + const ITEM_HEIGHT = 32; // Approximate item height in px + const OVERSCAN = 5; + + const totalItems = filteredOptions.length; + const visibleCount = Math.max(1, Math.ceil(containerHeight / ITEM_HEIGHT)); + const startIndex = Math.max( + 0, + Math.floor(scrollTop / ITEM_HEIGHT) - OVERSCAN + ); + const endIndex = Math.min( + totalItems, + startIndex + visibleCount + OVERSCAN * 2 + ); + const topPaddingHeight = startIndex * ITEM_HEIGHT; + const bottomPaddingHeight = Math.max( + 0, + (totalItems - endIndex) * ITEM_HEIGHT + ); + + // Measure container height when open and on resize + useLayoutEffect(() => { + if (!isOpen) return; + const el = listRef.current; + if (!el) return; + + const measure = () => { + setContainerHeight(el.clientHeight || 192); + }; + measure(); + + const ro = new ResizeObserver(measure); + ro.observe(el); + return () => ro.disconnect(); + }, [isOpen]); + + // Reset scroll when opening or when search changes + useEffect(() => { + if (isOpen && listRef.current) { + listRef.current.scrollTop = 0; + setScrollTop(0); + } + }, [isOpen, searchTerm]); + + const handleScroll = (e: React.UIEvent) => { + setScrollTop((e.target as HTMLDivElement).scrollTop); + }; return (
@@ -151,7 +245,10 @@ const SearchableSelect = React.forwardRef< `} style={{ boxShadow: commonStyles.input.shadow }} > - + {selectedOption ? selectedOption.label : placeholder} setSearchTerm(e.target.value)} onKeyDown={handleKeyDown} placeholder="Search..." - className={`${commonStyles.input.base} ${commonStyles.input.size.sm} w-full min-w-48`} + className={`${commonStyles.input.base} ${commonStyles.input.size.sm} w-full`} style={{ boxShadow: commonStyles.input.shadow }} role="searchbox" aria-label="Search options" />
- {filteredOptions.length > 0 ? ( - filteredOptions.map((option, index) => ( -
handleSelect(option.value)} - onMouseEnter={() => setHighlightedIndex(index)} - className={`px-3 py-2 text-xs font-medium cursor-pointer hover:bg-gray-100 text-gray-700 border-b border-gray-100 last:border-b-0 ${ - highlightedIndex === index ? "bg-gray-100" : "" - }`} - role="option" - aria-selected={highlightedIndex === index} - tabIndex={-1} - > - {option.label} -
- )) + {totalItems > 0 ? ( + <> + {topPaddingHeight > 0 && ( +
+ )} + {filteredOptions + .slice(startIndex, endIndex) + .map((option, i) => { + const absoluteIndex = startIndex + i; + return ( +
handleSelect(option.value)} + onMouseEnter={() => + setHighlightedIndex(absoluteIndex) + } + className={`px-3 py-2 text-xs font-medium cursor-pointer hover:bg-gray-100 text-gray-700 border-b border-gray-100 last:border-b-0 ${ + highlightedIndex === absoluteIndex + ? "bg-gray-100" + : "" + }`} + role="option" + aria-selected={highlightedIndex === absoluteIndex} + aria-label={option.label} + tabIndex={-1} + style={{ height: ITEM_HEIGHT }} + title={option.label} + > +
+ {option.label} +
+
+ ); + })} + {bottomPaddingHeight > 0 && ( +
+ )} + ) : (
No options found diff --git a/vite-app/src/util/filter-utils.ts b/vite-app/src/util/filter-utils.ts index 1f097244..2f6c90c2 100644 --- a/vite-app/src/util/filter-utils.ts +++ b/vite-app/src/util/filter-utils.ts @@ -26,14 +26,14 @@ export const getOperatorsForField = (field: string, type?: string) => { } return [ + { value: "contains", label: "contains" }, + { value: "!contains", label: "not contains" }, { value: "==", label: "equals" }, { value: "!=", label: "not equals" }, { value: ">", label: "greater than" }, { value: "<", label: "less than" }, { value: ">=", label: "greater than or equal" }, { value: "<=", label: "less than or equal" }, - { value: "contains", label: "contains" }, - { value: "!contains", label: "not contains" }, ]; };