Admin
This commit is contained in:
1 parent
b1061e67ac
commit
0fbbfdc997
30 files changed
+392
-60
No files matched your search
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
import{j as e,P as I,B as F,G as v,D as Ee,L as q,T as E,E as Mt,a as U,b as ot,c as k,C as K,S as ie,A as at,M as qe,d as W,e as it,f as ct,g as lt,u as ce,h as Z,i as X,k as $,l as ut,m as le,n as ue,o as Ut,p as Ve,I as re,q as Nt,r as se,s as oe,t as Ht,v as $t,w as dt,x as qt,y as ht,z as mt,F as Bt,H as zt,J as Wt,K as Gt,N as Qt,O as Kt,Q as Jt,R as Yt,U as Vt,V as Ae,W as Xt,X as Zt}from"./mui-BnAUJOoN.js";import{u as Be,a as de,b as en,L as Q,c as tn,O as nn,d as ee,e as J,f as te,g as rn,h as sn,q as ze,i as Pe,j as We,r as Le,k as on,R as an,Q as cn,l as ln}from"./tanstack-BqkrhB-y.js";import{d as un,r as w,g as Ge,b as fe}from"./react-C9_qfvjK.js";import{c as dn}from"./zustand-DKxXQGKw.js";import{i as pe,B as hn,a as mn,b as pn,u as M,t as S,T as fn}from"./i18n-Be01V9yD.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))o(r);new MutationObserver(r=>{for(const a of r)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&o(l)}).observe(document,{childList:!0,subtree:!0});function s(r){const a={};return r.integrity&&(a.integrity=r.integrity),r.referrerPolicy&&(a.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?a.credentials="include":r.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(r){if(r.ep)return;r.ep=!0;const a=s(r);fetch(r.href,a)}})();var _e={},Xe=un;_e.createRoot=Xe.createRoot,_e.hydrateRoot=Xe.hydrateRoot;const Fe=15,gn=3;var Te={BASE_URL:"/phpCourse/exam/dist",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const Me=new Map,je=n=>{const t=Me.get(n);return t?Object.fromEntries(Object.entries(t.stores).map(([s,o])=>[s,o.getState()])):{}},xn=(n,t,s)=>{if(n===void 0)return{type:"untracked",connection:t.connect(s)};const o=Me.get(s.name);if(o)return{type:"tracked",store:n,...o};const r={connection:t.connect(s),stores:{}};return Me.set(s.name,r),{type:"tracked",store:n,...r}},vn=(n,t={})=>(s,o,r)=>{const{enabled:a,anonymousActionType:l,store:d,...h}=t;let m;try{m=(a??(Te?"production":void 0)!=="production")&&window.__REDUX_DEVTOOLS_EXTENSION__}catch{}if(!m)return(Te?"production":void 0)!=="production"&&a&&console.warn("[zustand devtools middleware] Please install/enable Redux devtools extension"),n(s,o,r);const{connection:u,...i}=xn(d,m,h);let c=!0;r.setState=(g,x,j)=>{const y=s(g,x);if(!c)return y;const P=j===void 0?{type:l||"anonymous"}:typeof j=="string"?{type:j}:j;return d===void 0?(u==null||u.send(P,o()),y):(u==null||u.send({...P,type:`${d}/${P.type}`},{...je(h.name),[d]:r.getState()}),y)};const p=(...g)=>{const x=c;c=!1,s(...g),c=x},f=n(r.setState,o,r);if(i.type==="untracked"?u==null||u.init(f):(i.stores[i.store]=r,u==null||u.init(Object.fromEntries(Object.entries(i.stores).map(([g,x])=>[g,g===i.store?f:x.getState()])))),r.dispatchFromDevtools&&typeof r.dispatch=="function"){let g=!1;const x=r.dispatch;r.dispatch=(...j)=>{(Te?"production":void 0)!=="production"&&j[0].type==="__setState"&&!g&&(console.warn('[zustand devtools middleware] "__setState" action type is reserved to set state from the devtools. Avoid using it.'),g=!0),x(...j)}}return u.subscribe(g=>{var x;switch(g.type){case"ACTION":if(typeof g.payload!="string"){console.error("[zustand devtools middleware] Unsupported action format");return}return ke(g.payload,j=>{if(j.type==="__setState"){if(d===void 0){p(j.state);return}Object.keys(j.state).length!==1&&console.error(`
|
||||
[zustand devtools middleware] Unsupported __setState action format.
|
||||
When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),
|
||||
and value of this only key should be a state object. Example: { "type": "__setState", "state": { "abc123Store": { "foo": "bar" } } }
|
||||
`);const y=j.state[d];if(y==null)return;JSON.stringify(r.getState())!==JSON.stringify(y)&&p(y);return}r.dispatchFromDevtools&&typeof r.dispatch=="function"&&r.dispatch(j)});case"DISPATCH":switch(g.payload.type){case"RESET":return p(f),d===void 0?u==null?void 0:u.init(r.getState()):u==null?void 0:u.init(je(h.name));case"COMMIT":if(d===void 0){u==null||u.init(r.getState());return}return u==null?void 0:u.init(je(h.name));case"ROLLBACK":return ke(g.state,j=>{if(d===void 0){p(j),u==null||u.init(r.getState());return}p(j[d]),u==null||u.init(je(h.name))});case"JUMP_TO_STATE":case"JUMP_TO_ACTION":return ke(g.state,j=>{if(d===void 0){p(j);return}JSON.stringify(r.getState())!==JSON.stringify(j[d])&&p(j[d])});case"IMPORT_STATE":{const{nextLiftedState:j}=g.payload,y=(x=j.computedStates.slice(-1)[0])==null?void 0:x.state;if(!y)return;p(d===void 0?y:y[d]),u==null||u.send(null,j);return}case"PAUSE_RECORDING":return c=!c}return}}),f},yn=vn,ke=(n,t)=>{let s;try{s=JSON.parse(n)}catch(o){console.error("[zustand devtools middleware] Could not parse the received json",o)}s!==void 0&&t(s)};function jn(n,t){let s;try{s=n()}catch{return}return{getItem:r=>{var a;const l=h=>h===null?null:JSON.parse(h,void 0),d=(a=s.getItem(r))!=null?a:null;return d instanceof Promise?d.then(l):l(d)},setItem:(r,a)=>s.setItem(r,JSON.stringify(a,void 0)),removeItem:r=>s.removeItem(r)}}const ge=n=>t=>{try{const s=n(t);return s instanceof Promise?s:{then(o){return ge(o)(s)},catch(o){return this}}}catch(s){return{then(o){return this},catch(o){return ge(o)(s)}}}},Tn=(n,t)=>(s,o,r)=>{let a={getStorage:()=>localStorage,serialize:JSON.stringify,deserialize:JSON.parse,partialize:x=>x,version:0,merge:(x,j)=>({...j,...x}),...t},l=!1;const d=new Set,h=new Set;let m;try{m=a.getStorage()}catch{}if(!m)return n((...x)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),s(...x)},o,r);const u=ge(a.serialize),i=()=>{const x=a.partialize({...o()});let j;const y=u({state:x,version:a.version}).then(P=>m.setItem(a.name,P)).catch(P=>{j=P});if(j)throw j;return y},c=r.setState;r.setState=(x,j)=>{c(x,j),i()};const p=n((...x)=>{s(...x),i()},o,r);let f;const g=()=>{var x;if(!m)return;l=!1,d.forEach(y=>y(o()));const j=((x=a.onRehydrateStorage)==null?void 0:x.call(a,o()))||void 0;return ge(m.getItem.bind(m))(a.name).then(y=>{if(y)return a.deserialize(y)}).then(y=>{if(y)if(typeof y.version=="number"&&y.version!==a.version){if(a.migrate)return a.migrate(y.state,y.version);console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return y.state}).then(y=>{var P;return f=a.merge(y,(P=o())!=null?P:p),s(f,!0),i()}).then(()=>{j==null||j(f,void 0),l=!0,h.forEach(y=>y(f))}).catch(y=>{j==null||j(void 0,y)})};return r.persist={setOptions:x=>{a={...a,...x},x.getStorage&&(m=x.getStorage())},clearStorage:()=>{m==null||m.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>g(),hasHydrated:()=>l,onHydrate:x=>(d.add(x),()=>{d.delete(x)}),onFinishHydration:x=>(h.add(x),()=>{h.delete(x)})},g(),f||p},Cn=(n,t)=>(s,o,r)=>{let a={storage:jn(()=>localStorage),partialize:g=>g,version:0,merge:(g,x)=>({...x,...g}),...t},l=!1;const d=new Set,h=new Set;let m=a.storage;if(!m)return n((...g)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),s(...g)},o,r);const u=()=>{const g=a.partialize({...o()});return m.setItem(a.name,{state:g,version:a.version})},i=r.setState;r.setState=(g,x)=>{i(g,x),u()};const c=n((...g)=>{s(...g),u()},o,r);r.getInitialState=()=>c;let p;const f=()=>{var g,x;if(!m)return;l=!1,d.forEach(y=>{var P;return y((P=o())!=null?P:c)});const j=((x=a.onRehydrateStorage)==null?void 0:x.call(a,(g=o())!=null?g:c))||void 0;return ge(m.getItem.bind(m))(a.name).then(y=>{if(y)if(typeof y.version=="number"&&y.version!==a.version){if(a.migrate)return a.migrate(y.state,y.version);console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return y.state}).then(y=>{var P;return p=a.merge(y,(P=o())!=null?P:c),s(p,!0),u()}).then(()=>{j==null||j(p,void 0),p=o(),l=!0,h.forEach(y=>y(p))}).catch(y=>{j==null||j(void 0,y)})};return r.persist={setOptions:g=>{a={...a,...g},g.storage&&(m=g.storage)},clearStorage:()=>{m==null||m.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>f(),hasHydrated:()=>l,onHydrate:g=>(d.add(g),()=>{d.delete(g)}),onFinishHydration:g=>(h.add(g),()=>{h.delete(g)})},a.skipHydration||f(),p||c},Sn=(n,t)=>"getStorage"in t||"serialize"in t||"deserialize"in t?((Te?"production":void 0)!=="production"&&console.warn("[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead."),Tn(n,t)):Cn(n,t),wn=Sn,Oe=dn()(yn(wn(n=>({theme:void 0,currentSession:[void 0,void 0],setTheme:t=>n(()=>({theme:t})),setCurrentSession:t=>n(()=>({currentSession:t}))}),{name:"guestbook-storage"}))),G="https://khofmann.user
Line truncated
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/var et=Object.getOwnPropertySymbols,Nn=Object.prototype.hasOwnProperty,Hn=Object.prototype.propertyIsEnumerable;function $n(n){if(n==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(n)}function qn(){try{if(!Object.assign)return!1;var n=new String("abc");if(n[5]="de",Object.getOwnPropertyNames(n)[0]==="5")return!1;for(var t={},s=0;s<10;s++)t["_"+String.fromCharCode(s)]=s;var o=Object.getOwnPropertyNames(t).map(function(a){return t[a]});if(o.join("")!=="0123456789")return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(a){r[a]=a}),Object.keys(Object.assign({},r)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}var Bn=qn()?Object.assign:function(n,t){for(var s,o=$n(n),r,a=1;a<arguments.length;a++){s=Object(arguments[a]);for(var l in s)Nn.call(s,l)&&(o[l]=s[l]);if(et){r=et(s);for(var d=0;d<r.length;d++)Hn.call(s,r[d])&&(o[r[d]]=s[r[d]])}}return o};const zn=Ge(Bn);var V={BODY:"bodyAttributes",HTML:"htmlAttributes",TITLE:"titleAttributes"},C={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title"};Object.keys(C).map(function(n){return C[n]});var R={CHARSET:"charset",CSS_TEXT:"cssText",HREF:"href",HTTPEQUIV:"http-equiv",INNER_HTML:"innerHTML",ITEM_PROP:"itemprop",NAME:"name",PROPERTY:"property",REL:"rel",SRC:"src",TARGET:"target"},be={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},xe={DEFAULT_TITLE:"defaultTitle",DEFER:"defer",ENCODE_SPECIAL_CHARACTERS:"encodeSpecialCharacters",ON_CHANGE_CLIENT_STATE:"onChangeClientState",TITLE_TEMPLATE:"titleTemplate"},Wn=Object.keys(be).reduce(function(n,t){return n[be[t]]=t,n},{}),Gn=[C.NOSCRIPT,C.SCRIPT,C.STYLE],N="data-react-helmet",Qn=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(n){return typeof n}:function(n){return n&&typeof Symbol=="function"&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n},Kn=function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")},Jn=function(){function n(t,s){for(var o=0;o<s.length;o++){var r=s[o];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,s,o){return s&&n(t.prototype,s),o&&n(t,o),t}}(),L=Object.assign||function(n){for(var t=1;t<arguments.length;t++){var s=arguments[t];for(var o in s)Object.prototype.hasOwnProperty.call(s,o)&&(n[o]=s[o])}return n},Yn=function(n,t){if(typeof t!="function"&&t!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof t);n.prototype=Object.create(t&&t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(n,t):n.__proto__=t)},tt=function(n,t){var s={};for(var o in n)t.indexOf(o)>=0||Object.prototype.hasOwnProperty.call(n,o)&&(s[o]=n[o]);return s},Vn=function(n,t){if(!n)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t&&(typeof t=="object"||typeof t=="function")?t:n},Ue=function(t){var s=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return s===!1?String(t):String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},Xn=function(t){var s=ae(t,C.TITLE),o=ae(t,xe.TITLE_TEMPLATE);if(o&&s)return o.replace(/%s/g,function(){return Array.isArray(s)?s.join(""):s});var r=ae(t,xe.DEFAULT_TITLE);return s||r||void 0},Zn=function(t){return ae(t,xe.ON_CHANGE_CLIENT_STATE)||function(){}},De=function(t,s){return s.filter(function(o){return typeof o[t]<"u"}).map(function(o){return o[t]}).reduce(function(o,r){return L({},o,r)},{})},er=function(t,s){return s.filter(function(o){return typeof o[C.BASE]<"u"}).map(function(o){return o[C.BASE]}).reverse().reduce(function(o,r){if(!o.length)for(var a=Object.keys(r),l=0;l<a.length;l++){var d=a[l],h=d.toLowerCase();if(t.indexOf(h)!==-1&&r[h])return o.concat(r)}return o},[])},he=function(t,s,o){var r={};return o.filter(function(a){return Array.isArray(a[t])?!0:(typeof a[t]<"u"&&sr("Helmet: "+t+' should be of type "Array". Instead found type "'+Qn(a[t])+'"'),!1)}).map(function(a){return a[t]}).reverse().reduce(function(a,l){var d={};l.filter(function(c){for(var p=void 0,f=Object.keys(c),g=0;g<f.length;g++){var x=f[g],j=x.toLowerCase();s.indexOf(j)!==-1&&!(p===R.REL&&c[p].toLowerCase()==="canonical")&&!(j===R.REL&&c[j].toLowerCase()==="stylesheet")&&(p=j),s.indexOf(x)!==-1&&(x===R.INNER_HTML||x===R.CSS_TEXT||x===R.ITEM_PROP)&&(p=x)}if(!p||!c[p])return!1;var y=c[p].toLowerCase();return r[p]||(r[p]={}),d[p]||(d[p]={}),r[p][y]?!1:(d[p][y]=!0,!0)}).reverse().forEach(function(c){return a.push(c)});for(var h=Object.keys(d),m=0;m<h.length;m++){var u=h[m],i=zn({},r[u],d[u]);r[u]=i}return a},[]).reverse()},ae=function(t,s){for(var o=t.length-1;o>=0;o--){Line truncated
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import{j as e,P as I,B as D,G as j,D as me,L as q,T as A,E as Wt,a as N,b as dt,c as U,C as Z,S as z,A as Ge,M as Qe,d as G,e as ht,f as mt,g as pt,u as se,h as ee,i as X,k as $,l as ft,m as oe,n as ae,o as Gt,p as rt,I as de,q as Qt,r as te,s as ne,t as Kt,v as Jt,w as Ke,x as Yt,y as Je,z as Ye,F as gt,H as xt,J as yt,K as Vt,N as Xt,O as Zt,Q as en,R as tn,U as nn,V as Re,W as rn,X as sn}from"./mui-BnAUJOoN.js";import{u as Ve,a as ie,b as on,c as J,L as W,d as an,O as cn,e as Q,f as ce,g as ln,h as un,q as Ue,i as Ce,j as De,r as Oe,k as dn,R as hn,Q as mn,l as pn}from"./tanstack-DpDh5IPY.js";import{d as fn,r as w,g as Xe,b as ve}from"./react-C9_qfvjK.js";import{c as gn}from"./zustand-DKxXQGKw.js";import{i as ye,B as xn,a as yn,b as vn,u as L,t as S,T as jn}from"./i18n-Be01V9yD.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))o(r);new MutationObserver(r=>{for(const a of r)if(a.type==="childList")for(const u of a.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&o(u)}).observe(document,{childList:!0,subtree:!0});function s(r){const a={};return r.integrity&&(a.integrity=r.integrity),r.referrerPolicy&&(a.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?a.credentials="include":r.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function o(r){if(r.ep)return;r.ep=!0;const a=s(r);fetch(r.href,a)}})();var He={},st=fn;He.createRoot=st.createRoot,He.hydrateRoot=st.hydrateRoot;var k=(n=>(n.NOT_FOUND="NotFound",n.UNAUTHORIZED="Unauthorized",n.NOT_ALLOWED="NotAllowed",n.FAILED_UPDATE="FailedUpdate",n.MISSING_FIELD="MissingField",n.DUPLICATE="Duplicate",n))(k||{});const fe=15,Tn=3;var be={BASE_URL:"/phpCourse/exam/dist",MODE:"production",DEV:!1,PROD:!0,SSR:!1};const $e=new Map,we=n=>{const t=$e.get(n);return t?Object.fromEntries(Object.entries(t.stores).map(([s,o])=>[s,o.getState()])):{}},Cn=(n,t,s)=>{if(n===void 0)return{type:"untracked",connection:t.connect(s)};const o=$e.get(s.name);if(o)return{type:"tracked",store:n,...o};const r={connection:t.connect(s),stores:{}};return $e.set(s.name,r),{type:"tracked",store:n,...r}},Sn=(n,t={})=>(s,o,r)=>{const{enabled:a,anonymousActionType:u,store:d,...h}=t;let m;try{m=(a??(be?"production":void 0)!=="production")&&window.__REDUX_DEVTOOLS_EXTENSION__}catch{}if(!m)return(be?"production":void 0)!=="production"&&a&&console.warn("[zustand devtools middleware] Please install/enable Redux devtools extension"),n(s,o,r);const{connection:l,...i}=Cn(d,m,h);let c=!0;r.setState=(f,y,x)=>{const v=s(f,y);if(!c)return v;const P=x===void 0?{type:u||"anonymous"}:typeof x=="string"?{type:x}:x;return d===void 0?(l==null||l.send(P,o()),v):(l==null||l.send({...P,type:`${d}/${P.type}`},{...we(h.name),[d]:r.getState()}),v)};const p=(...f)=>{const y=c;c=!1,s(...f),c=y},g=n(r.setState,o,r);if(i.type==="untracked"?l==null||l.init(g):(i.stores[i.store]=r,l==null||l.init(Object.fromEntries(Object.entries(i.stores).map(([f,y])=>[f,f===i.store?g:y.getState()])))),r.dispatchFromDevtools&&typeof r.dispatch=="function"){let f=!1;const y=r.dispatch;r.dispatch=(...x)=>{(be?"production":void 0)!=="production"&&x[0].type==="__setState"&&!f&&(console.warn('[zustand devtools middleware] "__setState" action type is reserved to set state from the devtools. Avoid using it.'),f=!0),y(...x)}}return l.subscribe(f=>{var y;switch(f.type){case"ACTION":if(typeof f.payload!="string"){console.error("[zustand devtools middleware] Unsupported action format");return}return Me(f.payload,x=>{if(x.type==="__setState"){if(d===void 0){p(x.state);return}Object.keys(x.state).length!==1&&console.error(`
|
||||
[zustand devtools middleware] Unsupported __setState action format.
|
||||
When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),
|
||||
and value of this only key should be a state object. Example: { "type": "__setState", "state": { "abc123Store": { "foo": "bar" } } }
|
||||
`);const v=x.state[d];if(v==null)return;JSON.stringify(r.getState())!==JSON.stringify(v)&&p(v);return}r.dispatchFromDevtools&&typeof r.dispatch=="function"&&r.dispatch(x)});case"DISPATCH":switch(f.payload.type){case"RESET":return p(g),d===void 0?l==null?void 0:l.init(r.getState()):l==null?void 0:l.init(we(h.name));case"COMMIT":if(d===void 0){l==null||l.init(r.getState());return}return l==null?void 0:l.init(we(h.name));case"ROLLBACK":return Me(f.state,x=>{if(d===void 0){p(x),l==null||l.init(r.getState());return}p(x[d]),l==null||l.init(we(h.name))});case"JUMP_TO_STATE":case"JUMP_TO_ACTION":return Me(f.state,x=>{if(d===void 0){p(x);return}JSON.stringify(r.getState())!==JSON.stringify(x[d])&&p(x[d])});case"IMPORT_STATE":{const{nextLiftedState:x}=f.payload,v=(y=x.computedStates.slice(-1)[0])==null?void 0:y.state;if(!v)return;p(d===void 0?v:v[d]),l==null||l.send(null,x);return}case"PAUSE_RECORDING":return c=!c}return}}),g},wn=Sn,Me=(n,t)=>{let s;try{s=JSON.parse(n)}catch(o){console.error("[zustand devtools middleware] Could not parse the received json",o)}s!==void 0&&t(s)};function bn(n,t){let s;try{s=n()}catch{return}return{getItem:r=>{var a;const u=h=>h===null?null:JSON.parse(h,void 0),d=(a=s.getItem(r))!=null?a:null;return d instanceof Promise?d.then(u):u(d)},setItem:(r,a)=>s.setItem(r,JSON.stringify(a,void 0)),removeItem:r=>s.removeItem(r)}}const je=n=>t=>{try{const s=n(t);return s instanceof Promise?s:{then(o){return je(o)(s)},catch(o){return this}}}catch(s){return{then(o){return this},catch(o){return je(o)(s)}}}},En=(n,t)=>(s,o,r)=>{let a={getStorage:()=>localStorage,serialize:JSON.stringify,deserialize:JSON.parse,partialize:y=>y,version:0,merge:(y,x)=>({...x,...y}),...t},u=!1;const d=new Set,h=new Set;let m;try{m=a.getStorage()}catch{}if(!m)return n((...y)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),s(...y)},o,r);const l=je(a.serialize),i=()=>{const y=a.partialize({...o()});let x;const v=l({state:y,version:a.version}).then(P=>m.setItem(a.name,P)).catch(P=>{x=P});if(x)throw x;return v},c=r.setState;r.setState=(y,x)=>{c(y,x),i()};const p=n((...y)=>{s(...y),i()},o,r);let g;const f=()=>{var y;if(!m)return;u=!1,d.forEach(v=>v(o()));const x=((y=a.onRehydrateStorage)==null?void 0:y.call(a,o()))||void 0;return je(m.getItem.bind(m))(a.name).then(v=>{if(v)return a.deserialize(v)}).then(v=>{if(v)if(typeof v.version=="number"&&v.version!==a.version){if(a.migrate)return a.migrate(v.state,v.version);console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return v.state}).then(v=>{var P;return g=a.merge(v,(P=o())!=null?P:p),s(g,!0),i()}).then(()=>{x==null||x(g,void 0),u=!0,h.forEach(v=>v(g))}).catch(v=>{x==null||x(void 0,v)})};return r.persist={setOptions:y=>{a={...a,...y},y.getStorage&&(m=y.getStorage())},clearStorage:()=>{m==null||m.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>f(),hasHydrated:()=>u,onHydrate:y=>(d.add(y),()=>{d.delete(y)}),onFinishHydration:y=>(h.add(y),()=>{h.delete(y)})},f(),g||p},An=(n,t)=>(s,o,r)=>{let a={storage:bn(()=>localStorage),partialize:f=>f,version:0,merge:(f,y)=>({...y,...f}),...t},u=!1;const d=new Set,h=new Set;let m=a.storage;if(!m)return n((...f)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),s(...f)},o,r);const l=()=>{const f=a.partialize({...o()});return m.setItem(a.name,{state:f,version:a.version})},i=r.setState;r.setState=(f,y)=>{i(f,y),l()};const c=n((...f)=>{s(...f),l()},o,r);r.getInitialState=()=>c;let p;const g=()=>{var f,y;if(!m)return;u=!1,d.forEach(v=>{var P;return v((P=o())!=null?P:c)});const x=((y=a.onRehydrateStorage)==null?void 0:y.call(a,(f=o())!=null?f:c))||void 0;return je(m.getItem.bind(m))(a.name).then(v=>{if(v)if(typeof v.version=="number"&&v.version!==a.version){if(a.migrate)return a.migrate(v.state,v.version);console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return v.state}).then(v=>{var P;return p=a.merge(v,(P=o())!=null?P:c),s(p,!0),l()}).then(()=>{x==null||x(p,void 0),p=o(),u=!0,h.forEach(v=>v(p))}).catch(v=>{x==null||x(void 0,v)})};return r.persist={setOptions:f=>{a={...a,...f},f.storage&&(m=f.storage)},clearStorage:()=>{m==null||m.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>g(),hasHydrated:()=>u,onHydrate:f=>(d.add(f),()=>{d.delete(f)}),onFinishHydration:f=>(h.add(f),()=>{h.delete(f)})},a.skipHydration||g(),p||c},Pn=(n,t)=>"getStorage"in t||"serialize"in t||"deserialize"in t?((be?"production":void 0)!=="production"&&console.warn("[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead."),En(n,t)):An(n,t),On=Pn,ke=gn()(wn(On(n=>({theme:void 0,currentSession:[void 0,void 0],setTheme:t=>n(()=>({theme:t})),setCurrentSession:t=>n(()=>({currentSession:t}))}),{name:"guestbook-storage"}))),V="https://khofmann.user
Line truncated
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/var at=Object.getOwnPropertySymbols,zn=Object.prototype.hasOwnProperty,Wn=Object.prototype.propertyIsEnumerable;function Gn(n){if(n==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(n)}function Qn(){try{if(!Object.assign)return!1;var n=new String("abc");if(n[5]="de",Object.getOwnPropertyNames(n)[0]==="5")return!1;for(var t={},s=0;s<10;s++)t["_"+String.fromCharCode(s)]=s;var o=Object.getOwnPropertyNames(t).map(function(a){return t[a]});if(o.join("")!=="0123456789")return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach(function(a){r[a]=a}),Object.keys(Object.assign({},r)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}var Kn=Qn()?Object.assign:function(n,t){for(var s,o=Gn(n),r,a=1;a<arguments.length;a++){s=Object(arguments[a]);for(var u in s)zn.call(s,u)&&(o[u]=s[u]);if(at){r=at(s);for(var d=0;d<r.length;d++)Wn.call(s,r[d])&&(o[r[d]]=s[r[d]])}}return o};const Jn=Xe(Kn);var re={BODY:"bodyAttributes",HTML:"htmlAttributes",TITLE:"titleAttributes"},C={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title"};Object.keys(C).map(function(n){return C[n]});var R={CHARSET:"charset",CSS_TEXT:"cssText",HREF:"href",HTTPEQUIV:"http-equiv",INNER_HTML:"innerHTML",ITEM_PROP:"itemprop",NAME:"name",PROPERTY:"property",REL:"rel",SRC:"src",TARGET:"target"},Ie={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},Te={DEFAULT_TITLE:"defaultTitle",DEFER:"defer",ENCODE_SPECIAL_CHARACTERS:"encodeSpecialCharacters",ON_CHANGE_CLIENT_STATE:"onChangeClientState",TITLE_TEMPLATE:"titleTemplate"},Yn=Object.keys(Ie).reduce(function(n,t){return n[Ie[t]]=t,n},{}),Vn=[C.NOSCRIPT,C.SCRIPT,C.STYLE],B="data-react-helmet",Xn=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(n){return typeof n}:function(n){return n&&typeof Symbol=="function"&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n},Zn=function(n,t){if(!(n instanceof t))throw new TypeError("Cannot call a class as a function")},er=function(){function n(t,s){for(var o=0;o<s.length;o++){var r=s[o];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,s,o){return s&&n(t.prototype,s),o&&n(t,o),t}}(),M=Object.assign||function(n){for(var t=1;t<arguments.length;t++){var s=arguments[t];for(var o in s)Object.prototype.hasOwnProperty.call(s,o)&&(n[o]=s[o])}return n},tr=function(n,t){if(typeof t!="function"&&t!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof t);n.prototype=Object.create(t&&t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(n,t):n.__proto__=t)},it=function(n,t){var s={};for(var o in n)t.indexOf(o)>=0||Object.prototype.hasOwnProperty.call(n,o)&&(s[o]=n[o]);return s},nr=function(n,t){if(!n)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t&&(typeof t=="object"||typeof t=="function")?t:n},qe=function(t){var s=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return s===!1?String(t):String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")},rr=function(t){var s=he(t,C.TITLE),o=he(t,Te.TITLE_TEMPLATE);if(o&&s)return o.replace(/%s/g,function(){return Array.isArray(s)?s.join(""):s});var r=he(t,Te.DEFAULT_TITLE);return s||r||void 0},sr=function(t){return he(t,Te.ON_CHANGE_CLIENT_STATE)||function(){}},Ne=function(t,s){return s.filter(function(o){return typeof o[t]<"u"}).map(function(o){return o[t]}).reduce(function(o,r){return M({},o,r)},{})},or=function(t,s){return s.filter(function(o){return typeof o[C.BASE]<"u"}).map(function(o){return o[C.BASE]}).reverse().reduce(function(o,r){if(!o.length)for(var a=Object.keys(r),u=0;u<a.length;u++){var d=a[u],h=d.toLowerCase();if(t.indexOf(h)!==-1&&r[h])return o.concat(r)}return o},[])},ge=function(t,s,o){var r={};return o.filter(function(a){return Array.isArray(a[t])?!0:(typeof a[t]<"u"&&lr("Helmet: "+t+' should be of type "Array". Instead found type "'+Xn(a[t])+'"'),!1)}).map(function(a){return a[t]}).reverse().reduce(function(a,u){var d={};u.filter(function(c){for(var p=void 0,g=Object.keys(c),f=0;f<g.length;f++){var y=g[f],x=y.toLowerCase();s.indexOf(x)!==-1&&!(p===R.REL&&c[p].toLowerCase()==="canonical")&&!(x===R.REL&&c[x].toLowerCase()==="stylesheet")&&(p=x),s.indexOf(y)!==-1&&(y===R.INNER_HTML||y===R.CSS_TEXT||y===R.ITEM_PROP)&&(p=y)}if(!p||!c[p])return!1;var v=c[p].toLowerCase();return r[p]||(r[p]={}),d[p]||(d[p]={}),r[p][v]?!1:(d[p][v]=!0,!0)}).reverse().forEach(function(c){return a.push(c)});for(var h=Object.keys(d),m=0;m<h.length;m++){var l=h[m],i=Jn({},r[l],d[l]);r[l]=i}return a},[]).reverse()},he=function(t,s){for(var o=t.length-1;o>=0;o--)Line truncated
|
||||
+1
-1
@@ -14,4 +14,4 @@ var ws=e=>{throw TypeError(e)};var ze=(e,t,s)=>t.has(e)||ws("Cannot "+s);var l=(
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/var $e=C,Rr=Cr;function Er(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var xr=typeof Object.is=="function"?Object.is:Er,Or=Rr.useSyncExternalStore,Lr=$e.useRef,Ar=$e.useEffect,Tr=$e.useMemo,Ir=$e.useDebugValue;Si.useSyncExternalStoreWithSelector=function(e,t,s,i,r){var n=Lr(null);if(n.current===null){var o={hasValue:!1,value:null};n.current=o}else o=n.current;n=Tr(function(){function h(p){if(!u){if(u=!0,c=p,p=i(p),r!==void 0&&o.hasValue){var v=o.value;if(r(v,p))return d=v}return d=p}if(v=d,xr(c,p))return v;var m=i(p);return r!==void 0&&r(v,m)?v:(c=p,d=m)}var u=!1,c,d,f=s===void 0?null:s;return[function(){return h(t())},f===null?void 0:function(){return h(f())}]},[t,s,i,r]);var a=Or(e,n[0],n[1]);return Ar(function(){o.hasValue=!0,o.value=a},[a]),Ir(a),a};bi.exports=Si;var Vr=bi.exports;class bs{constructor(t,s){this.listeners=new Set,this._batching=!1,this._flushing=0,this.subscribe=i=>{var r,n;this.listeners.add(i);const o=(n=(r=this.options)==null?void 0:r.onSubscribe)==null?void 0:n.call(r,i,this);return()=>{this.listeners.delete(i),o==null||o()}},this.setState=i=>{var r,n,o;const a=this.state;this.state=(r=this.options)!=null&&r.updateFn?this.options.updateFn(a)(i):i(a),(o=(n=this.options)==null?void 0:n.onUpdate)==null||o.call(n),this._flush()},this._flush=()=>{if(this._batching)return;const i=++this._flushing;this.listeners.forEach(r=>{this._flushing===i&&r()})},this.batch=i=>{if(this._batching)return i();this._batching=!0,i(),this._batching=!1,this._flush()},this.state=t,this.options=s}}function Ve(e,t=s=>s){return Vr.useSyncExternalStoreWithSelector(e.subscribe,()=>e.state,()=>e.state,t,jr)}function jr(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;const s=Object.keys(e);if(s.length!==Object.keys(t).length)return!1;for(let i=0;i<s.length;i++)if(!Object.prototype.hasOwnProperty.call(t,s[i])||!Object.is(e[s[i]],t[s[i]]))return!1;return!0}const rt="__root__";function Dr(e,t){let s,i,r,n="";for(s in e)if((r=e[s])!==void 0)if(Array.isArray(r))for(i=0;i<r.length;i++)n&&(n+="&"),n+=encodeURIComponent(s)+"="+encodeURIComponent(r[i]);else n&&(n+="&"),n+=encodeURIComponent(s)+"="+encodeURIComponent(r);return""+n}function Ts(e){if(!e)return"";const t=decodeURIComponent(e);return t==="false"?!1:t==="true"?!0:+t*0===0&&+t+""===t?+t:t}function kr(e,t){let s,i;const r={},n=e.split("&");for(;s=n.shift();){const o=s.indexOf("=");if(o!==-1){i=s.slice(0,o);const a=s.slice(o+1);r[i]!==void 0?r[i]=[].concat(r[i],Ts(a)):r[i]=Ts(a)}else i=s,r[i]=""}return r}const Br=Ur(JSON.parse),$r=Qr(JSON.stringify,JSON.parse);function Ur(e){return t=>{t.substring(0,1)==="?"&&(t=t.substring(1));const s=kr(t);for(const i in s){const r=s[i];if(typeof r=="string")try{s[i]=e(r)}catch{}}return s}}function Qr(e,t){function s(i){if(typeof i=="object"&&i!==null)try{return e(i)}catch{}else if(typeof i=="string"&&typeof t=="function")try{return t(i),e(i)}catch{}return i}return i=>{i={...i},Object.keys(i).forEach(n=>{const o=i[n];typeof o>"u"||o===void 0?delete i[n]:i[n]=s(o)});const r=Dr(i).toString();return r?`?${r}`:""}}function je(e){return e[e.length-1]}function Kr(e){return typeof e=="function"}function Jt(e,t){return Kr(e)?e(t):e}function be(e,t){return t.reduce((s,i)=>(s[i]=e[i],s),{})}function pt(e,t){if(e===t)return e;const s=t,i=Vs(e)&&Vs(s);if(i||De(e)&&De(s)){const r=i?e:Object.keys(e),n=r.length,o=i?s:Object.keys(s),a=o.length,h=i?[]:{};let u=0;for(let c=0;c<a;c++){const d=i?c:o[c];(!i&&r.includes(d)||i)&&e[d]===void 0&&s[d]===void 0?(h[d]=void 0,u++):(h[d]=pt(e[d],s[d]),h[d]===e[d]&&e[d]!==void 0&&u++)}return n===a&&u===n?e:h}return s}function De(e){if(!Is(e))return!1;const t=e.constructor;if(typeof t>"u")return!0;const s=t.prototype;return!(!Is(s)||!s.hasOwnProperty("isPrototypeOf"))}function Is(e){return Object.prototype.toString.call(e)==="[object Object]"}function Vs(e){return Array.isArray(e)&&e.length===Object.keys(e).length}function Yt(e,t,s=!1){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(De(e)&&De(t)){const i=Object.keys(e).filter(n=>e[n]!==void 0),r=Object.keys(t).filter(n=>t[n]!==void 0);return!s&&i.length!==r.length?!1:!r.some(n=>!(n in e)||!Yt(e[n],t[n],s))}return Array.isArray(e)&&Array.isArray(t)?e.length!==t.length?!1:!e.some((i,r)=>!Yt(i,t[r],s)):!1}const Je=typeof window<"u"?C.useLayoutEffect:C.useEffect;function Gt(e){let t,s;const i=new Promise((r,n)=>{t=r,s=n});return i.status="pending",i.resolve=r=>{i.status="resolved",i.value=r,t(r),e==null||e(r)},i.reject=r=>{i.status="rejected",s(r)},i}function js(e){const t=C.useRef({value:e,prev:null}),s=t.current.value;return e!==s&&(t.current={value:e,prev:s}),t.current.prev}function Vt(e){return Ue(e.filter(Boolean).join("/"))}function Ue(e){return e.replace(/\/{2,}/g,"/")}function Ss(e){return e==="/"?e:e.replace(/^\/{1,}/,"")}function Bt(e){return e==="/"?e:e.replace(/\/{1,}$/,"")}function Nr(e){return Bt(Ss(e))}function ke(e,t){return e.endsWith("/")&&e!=="/"&&e!==`${t}/`?e.slice(0,-1):e}functLine truncated
|
||||
*/var $e=C,Rr=Cr;function Er(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var xr=typeof Object.is=="function"?Object.is:Er,Or=Rr.useSyncExternalStore,Lr=$e.useRef,Ar=$e.useEffect,Tr=$e.useMemo,Ir=$e.useDebugValue;Si.useSyncExternalStoreWithSelector=function(e,t,s,i,r){var n=Lr(null);if(n.current===null){var o={hasValue:!1,value:null};n.current=o}else o=n.current;n=Tr(function(){function h(p){if(!u){if(u=!0,c=p,p=i(p),r!==void 0&&o.hasValue){var v=o.value;if(r(v,p))return d=v}return d=p}if(v=d,xr(c,p))return v;var m=i(p);return r!==void 0&&r(v,m)?v:(c=p,d=m)}var u=!1,c,d,f=s===void 0?null:s;return[function(){return h(t())},f===null?void 0:function(){return h(f())}]},[t,s,i,r]);var a=Or(e,n[0],n[1]);return Ar(function(){o.hasValue=!0,o.value=a},[a]),Ir(a),a};bi.exports=Si;var Vr=bi.exports;class bs{constructor(t,s){this.listeners=new Set,this._batching=!1,this._flushing=0,this.subscribe=i=>{var r,n;this.listeners.add(i);const o=(n=(r=this.options)==null?void 0:r.onSubscribe)==null?void 0:n.call(r,i,this);return()=>{this.listeners.delete(i),o==null||o()}},this.setState=i=>{var r,n,o;const a=this.state;this.state=(r=this.options)!=null&&r.updateFn?this.options.updateFn(a)(i):i(a),(o=(n=this.options)==null?void 0:n.onUpdate)==null||o.call(n),this._flush()},this._flush=()=>{if(this._batching)return;const i=++this._flushing;this.listeners.forEach(r=>{this._flushing===i&&r()})},this.batch=i=>{if(this._batching)return i();this._batching=!0,i(),this._batching=!1,this._flush()},this.state=t,this.options=s}}function Ve(e,t=s=>s){return Vr.useSyncExternalStoreWithSelector(e.subscribe,()=>e.state,()=>e.state,t,jr)}function jr(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;const s=Object.keys(e);if(s.length!==Object.keys(t).length)return!1;for(let i=0;i<s.length;i++)if(!Object.prototype.hasOwnProperty.call(t,s[i])||!Object.is(e[s[i]],t[s[i]]))return!1;return!0}const rt="__root__";function Dr(e,t){let s,i,r,n="";for(s in e)if((r=e[s])!==void 0)if(Array.isArray(r))for(i=0;i<r.length;i++)n&&(n+="&"),n+=encodeURIComponent(s)+"="+encodeURIComponent(r[i]);else n&&(n+="&"),n+=encodeURIComponent(s)+"="+encodeURIComponent(r);return""+n}function Ts(e){if(!e)return"";const t=decodeURIComponent(e);return t==="false"?!1:t==="true"?!0:+t*0===0&&+t+""===t?+t:t}function kr(e,t){let s,i;const r={},n=e.split("&");for(;s=n.shift();){const o=s.indexOf("=");if(o!==-1){i=s.slice(0,o);const a=s.slice(o+1);r[i]!==void 0?r[i]=[].concat(r[i],Ts(a)):r[i]=Ts(a)}else i=s,r[i]=""}return r}const Br=Ur(JSON.parse),$r=Qr(JSON.stringify,JSON.parse);function Ur(e){return t=>{t.substring(0,1)==="?"&&(t=t.substring(1));const s=kr(t);for(const i in s){const r=s[i];if(typeof r=="string")try{s[i]=e(r)}catch{}}return s}}function Qr(e,t){function s(i){if(typeof i=="object"&&i!==null)try{return e(i)}catch{}else if(typeof i=="string"&&typeof t=="function")try{return t(i),e(i)}catch{}return i}return i=>{i={...i},Object.keys(i).forEach(n=>{const o=i[n];typeof o>"u"||o===void 0?delete i[n]:i[n]=s(o)});const r=Dr(i).toString();return r?`?${r}`:""}}function je(e){return e[e.length-1]}function Kr(e){return typeof e=="function"}function Jt(e,t){return Kr(e)?e(t):e}function be(e,t){return t.reduce((s,i)=>(s[i]=e[i],s),{})}function pt(e,t){if(e===t)return e;const s=t,i=Vs(e)&&Vs(s);if(i||De(e)&&De(s)){const r=i?e:Object.keys(e),n=r.length,o=i?s:Object.keys(s),a=o.length,h=i?[]:{};let u=0;for(let c=0;c<a;c++){const d=i?c:o[c];(!i&&r.includes(d)||i)&&e[d]===void 0&&s[d]===void 0?(h[d]=void 0,u++):(h[d]=pt(e[d],s[d]),h[d]===e[d]&&e[d]!==void 0&&u++)}return n===a&&u===n?e:h}return s}function De(e){if(!Is(e))return!1;const t=e.constructor;if(typeof t>"u")return!0;const s=t.prototype;return!(!Is(s)||!s.hasOwnProperty("isPrototypeOf"))}function Is(e){return Object.prototype.toString.call(e)==="[object Object]"}function Vs(e){return Array.isArray(e)&&e.length===Object.keys(e).length}function Yt(e,t,s=!1){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(De(e)&&De(t)){const i=Object.keys(e).filter(n=>e[n]!==void 0),r=Object.keys(t).filter(n=>t[n]!==void 0);return!s&&i.length!==r.length?!1:!r.some(n=>!(n in e)||!Yt(e[n],t[n],s))}return Array.isArray(e)&&Array.isArray(t)?e.length!==t.length?!1:!e.some((i,r)=>!Yt(i,t[r],s)):!1}const Je=typeof window<"u"?C.useLayoutEffect:C.useEffect;function Gt(e){let t,s;const i=new Promise((r,n)=>{t=r,s=n});return i.status="pending",i.resolve=r=>{i.status="resolved",i.value=r,t(r),e==null||e(r)},i.reject=r=>{i.status="rejected",s(r)},i}function js(e){const t=C.useRef({value:e,prev:null}),s=t.current.value;return e!==s&&(t.current={value:e,prev:s}),t.current.prev}function Vt(e){return Ue(e.filter(Boolean).join("/"))}function Ue(e){return e.replace(/\/{2,}/g,"/")}function Ss(e){return e==="/"?e:e.replace(/^\/{1,}/,"")}function Bt(e){return e==="/"?e:e.replace(/\/{1,}$/,"")}function Nr(e){return Bt(Ss(e))}function ke(e,t){return e.endsWith("/")&&e!=="/"&&e!==`${t}/`?e.slice(0,-1):e}functLine truncated
|
||||
Vendored
+2
-2
@@ -23,10 +23,10 @@
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>GuestBook</title>
|
||||
<script type="module" crossorigin src="/phpCourse/exam/dist/assets/index-Cag5GO1b.js"></script>
|
||||
<script type="module" crossorigin src="/phpCourse/exam/dist/assets/index-SI5snNZz.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/react-C9_qfvjK.js">
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/mui-BnAUJOoN.js">
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/tanstack-BqkrhB-y.js">
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/tanstack-DpDh5IPY.js">
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/zustand-DKxXQGKw.js">
|
||||
<link rel="modulepreload" crossorigin href="/phpCourse/exam/dist/assets/i18n-Be01V9yD.js">
|
||||
<link rel="stylesheet" crossorigin href="/phpCourse/exam/dist/assets/mui-CKDNpdid.css">
|
||||
|
||||
+12
-1
@@ -20,6 +20,9 @@
|
||||
"NotAllowed_postUpdate": "Keine Berechtigung",
|
||||
"NotFound_post:postUpdate": "Post nicht gefunden",
|
||||
|
||||
"NotAllowed_delete|PermissionsUser": "Keine Berechtigung",
|
||||
"NotFound_user:delete|PermissionsUser": "Benutzer nicht gefunden",
|
||||
|
||||
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
||||
|
||||
"username": "Benutzername",
|
||||
@@ -101,5 +104,13 @@
|
||||
|
||||
"Password confirm": "Passwort bestätigen",
|
||||
"Password match": "Passwörter stimmen nicht überein",
|
||||
"Change password": "Passwort ändern"
|
||||
"Change password": "Passwort ändern",
|
||||
|
||||
"Confirm user delete title": "Diesen User löschen?",
|
||||
"Confirm user delete body": "Möchtest du {{name}} wirklich Löschen?",
|
||||
|
||||
"Manage users": "Benutzer verwalten",
|
||||
"Admin": "Administration",
|
||||
"Make Admin": "Administratorrecht erteilen",
|
||||
"Demote Admin": "Administratorrecht entziehen"
|
||||
}
|
||||
+12
-1
@@ -20,6 +20,9 @@
|
||||
"NotAllowed_postUpdate": "Not allowed",
|
||||
"NotFound_post:postUpdate": "Post not found",
|
||||
|
||||
"NotAllowed_delete|PermissionsUser": "Not allowed",
|
||||
"NotFound_user:deleteUserdelete|PermissionsUser": "User not found",
|
||||
|
||||
"Duplicate_user:register": "A user with this username or email already exists",
|
||||
|
||||
"username": "username",
|
||||
@@ -102,5 +105,13 @@
|
||||
|
||||
"Password confirm": "Confirm password",
|
||||
"Password match": "Password do not match",
|
||||
"Change password": "Change password"
|
||||
"Change password": "Change password",
|
||||
|
||||
"Confirm user delete title": "Diesen User löschen?",
|
||||
"Confirm user delete body": "Möchtest du {{name}} wirklich Löschen?",
|
||||
|
||||
"Manage users": "Manage users",
|
||||
"Admin": "Administration",
|
||||
"Make Admin": "Make Admin",
|
||||
"Demote Admin": "Demote Admin"
|
||||
}
|
||||
Vendored
+1
-1
@@ -4822,7 +4822,7 @@ var drawChart = (function (exports) {
|
||||
</script>
|
||||
<script>
|
||||
/*<!--*/
|
||||
const data = {"version":2,"tree":{"name":"root","children":[{"name":"assets/zustand-DKxXQGKw.js","children":[{"name":"node_modules/.pnpm","children":[{"name":"zustand@4.5.4_@types+react@18.3.3_react@18.3.1/node_modules/zustand/esm","children":[{"uid":"610b02e0-1","name":"vanilla.mjs"},{"uid":"610b02e0-25","name":"index.mjs"}]},{"name":"use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store","children":[{"name":"cjs","children":[{"uid":"610b02e0-11","name":"use-sync-external-store-shim.production.min.js"},{"name":"use-sync-external-store-shim/with-selector.production.min.js","uid":"610b02e0-19"}]},{"name":"shim","children":[{"uid":"610b02e0-15","name":"index.js"},{"uid":"610b02e0-23","name":"with-selector.js"}]}]}]},{"name":"\u0000/node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store","children":[{"name":"shim","children":[{"uid":"610b02e0-3","name":"with-selector.js?commonjs-module"},{"uid":"610b02e0-7","name":"index.js?commonjs-module"},{"uid":"610b02e0-17","name":"index.js?commonjs-proxy"}]},{"name":"cjs","children":[{"name":"use-sync-external-store-shim","children":[{"uid":"610b02e0-5","name":"with-selector.production.min.js?commonjs-exports"},{"uid":"610b02e0-21","name":"with-selector.production.min.js?commonjs-proxy"}]},{"uid":"610b02e0-9","name":"use-sync-external-store-shim.production.min.js?commonjs-exports"},{"uid":"610b02e0-13","name":"use-sync-external-store-shim.production.min.js?commonjs-proxy"}]}]}]},{"name":"assets/i18n-Be01V9yD.js","children":[{"name":"node_modules/.pnpm","children":[{"name":"i18next@23.12.2/node_modules/i18next/dist/esm/i18next.js","uid":"610b02e0-27"},{"name":"void-elements@3.1.0/node_modules/void-elements/index.js","uid":"610b02e0-29"},{"name":"html-parse-stringify@3.0.1/node_modules/html-parse-stringify/dist/html-parse-stringify.module.js","uid":"610b02e0-31"},{"name":"react-i18next@15.0.0_i18next@23.12.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-i18next/dist/es","children":[{"uid":"610b02e0-33","name":"utils.js"},{"uid":"610b02e0-35","name":"unescape.js"},{"uid":"610b02e0-37","name":"defaults.js"},{"uid":"610b02e0-39","name":"i18nInstance.js"},{"uid":"610b02e0-41","name":"TransWithoutContext.js"},{"uid":"610b02e0-43","name":"initReactI18next.js"},{"uid":"610b02e0-45","name":"context.js"},{"uid":"610b02e0-47","name":"Trans.js"},{"uid":"610b02e0-49","name":"useTranslation.js"},{"uid":"610b02e0-51","name":"withTranslation.js"},{"uid":"610b02e0-53","name":"Translation.js"},{"uid":"610b02e0-55","name":"I18nextProvider.js"},{"uid":"610b02e0-57","name":"useSSR.js"},{"uid":"610b02e0-59","name":"withSSR.js"},{"uid":"610b02e0-61","name":"index.js"}]},{"name":"i18next-browser-languagedetector@8.0.0/node_modules/i18next-browser-languagedetector/dist/esm/i18nextBrowserLanguageDetector.js","uid":"610b02e0-63"},{"name":"i18next-http-backend@2.5.2/node_modules/i18next-http-backend/esm","children":[{"uid":"610b02e0-65","name":"utils.js"},{"uid":"610b02e0-75","name":"getFetch.cjs"},{"uid":"610b02e0-77","name":"request.js"},{"uid":"610b02e0-79","name":"index.js"}]},{"name":"cross-fetch@4.0.0/node_modules/cross-fetch/dist/browser-ponyfill.js","uid":"610b02e0-73"}]},{"uid":"610b02e0-67","name":"\u0000commonjs-dynamic-modules"},{"name":"\u0000/node_modules/.pnpm","children":[{"name":"i18next-http-backend@2.5.2/node_modules/i18next-http-backend/esm/getFetch.cjs?commonjs-module","uid":"610b02e0-69"},{"name":"cross-fetch@4.0.0/node_modules/cross-fetch/dist/browser-ponyfill.js?commonjs-module","uid":"610b02e0-71"}]}]},{"name":"assets/index-Cag5GO1b.js","children":[{"name":"\u0000vite/modulepreload-polyfill.js","uid":"610b02e0-81"},{"name":"\u0000/node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/client.js?commonjs-exports","uid":"610b02e0-83"},{"name":"node_modules/.pnpm","children":[{"name":"react-dom@18.3.1_react@18.3.1/node_modules/react-dom/client.js","uid":"610b02e0-85"},{"name":"zustand@4.5.4_@types+react@18.3.3_react@18.3.1/node_modules/zustand/esm/middleware.mjs","uid":"610b02e0-89"},{"name":"@fontsource+roboto@5.0.13/node_modules/@fontsource/roboto","children":[{"uid":"610b02e0-97","name":"300.css"},{"uid":"610b02e0-99","name":"400.css"},{"uid":"610b02e0-101","name":"500.css"},{"uid":"610b02e0-103","name":"700.css"}]},{"name":"react-side-effect@2.1.2_react@18.3.1/node_modules/react-side-effect/lib/index.js","uid":"610b02e0-105"},{"name":"react-fast-compare@3.2.2/node_modules/react-fast-compare/index.js","uid":"610b02e0-107"},{"name":"object-assign@4.1.1/node_modules/object-assign/index.js","uid":"610b02e0-109"},{"name":"react-helmet@6.1.0_react@18.3.1/node_modules/react-helmet/es/Helmet.js","uid":"610b02e0-111"}]},{"name":"src","children":[{"uid":"610b02e0-87","name":"constanst.ts"},{"name":"store/store.ts","uid":"610b02e0-91"},{"name":"api/Api.tsx","uid":"610b02e0-93"},{"uid":"610b02e0-95","name":"i18n.ts"},{"name":"components","children":[{"name":"Footer/Footer.tsx","Line truncated
|
||||
const data = {"version":2,"tree":{"name":"root","children":[{"name":"assets/zustand-DKxXQGKw.js","children":[{"name":"node_modules/.pnpm","children":[{"name":"zustand@4.5.4_@types+react@18.3.3_react@18.3.1/node_modules/zustand/esm","children":[{"uid":"33dc6614-1","name":"vanilla.mjs"},{"uid":"33dc6614-25","name":"index.mjs"}]},{"name":"use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store","children":[{"name":"cjs","children":[{"uid":"33dc6614-11","name":"use-sync-external-store-shim.production.min.js"},{"name":"use-sync-external-store-shim/with-selector.production.min.js","uid":"33dc6614-19"}]},{"name":"shim","children":[{"uid":"33dc6614-15","name":"index.js"},{"uid":"33dc6614-23","name":"with-selector.js"}]}]}]},{"name":"\u0000/node_modules/.pnpm/use-sync-external-store@1.2.0_react@18.3.1/node_modules/use-sync-external-store","children":[{"name":"shim","children":[{"uid":"33dc6614-3","name":"with-selector.js?commonjs-module"},{"uid":"33dc6614-7","name":"index.js?commonjs-module"},{"uid":"33dc6614-17","name":"index.js?commonjs-proxy"}]},{"name":"cjs","children":[{"name":"use-sync-external-store-shim","children":[{"uid":"33dc6614-5","name":"with-selector.production.min.js?commonjs-exports"},{"uid":"33dc6614-21","name":"with-selector.production.min.js?commonjs-proxy"}]},{"uid":"33dc6614-9","name":"use-sync-external-store-shim.production.min.js?commonjs-exports"},{"uid":"33dc6614-13","name":"use-sync-external-store-shim.production.min.js?commonjs-proxy"}]}]}]},{"name":"assets/i18n-Be01V9yD.js","children":[{"name":"node_modules/.pnpm","children":[{"name":"i18next@23.12.2/node_modules/i18next/dist/esm/i18next.js","uid":"33dc6614-27"},{"name":"void-elements@3.1.0/node_modules/void-elements/index.js","uid":"33dc6614-29"},{"name":"html-parse-stringify@3.0.1/node_modules/html-parse-stringify/dist/html-parse-stringify.module.js","uid":"33dc6614-31"},{"name":"react-i18next@15.0.0_i18next@23.12.2_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/react-i18next/dist/es","children":[{"uid":"33dc6614-33","name":"utils.js"},{"uid":"33dc6614-35","name":"unescape.js"},{"uid":"33dc6614-37","name":"defaults.js"},{"uid":"33dc6614-39","name":"i18nInstance.js"},{"uid":"33dc6614-41","name":"TransWithoutContext.js"},{"uid":"33dc6614-43","name":"initReactI18next.js"},{"uid":"33dc6614-45","name":"context.js"},{"uid":"33dc6614-47","name":"Trans.js"},{"uid":"33dc6614-49","name":"useTranslation.js"},{"uid":"33dc6614-51","name":"withTranslation.js"},{"uid":"33dc6614-53","name":"Translation.js"},{"uid":"33dc6614-55","name":"I18nextProvider.js"},{"uid":"33dc6614-57","name":"useSSR.js"},{"uid":"33dc6614-59","name":"withSSR.js"},{"uid":"33dc6614-61","name":"index.js"}]},{"name":"i18next-browser-languagedetector@8.0.0/node_modules/i18next-browser-languagedetector/dist/esm/i18nextBrowserLanguageDetector.js","uid":"33dc6614-63"},{"name":"i18next-http-backend@2.5.2/node_modules/i18next-http-backend/esm","children":[{"uid":"33dc6614-65","name":"utils.js"},{"uid":"33dc6614-75","name":"getFetch.cjs"},{"uid":"33dc6614-77","name":"request.js"},{"uid":"33dc6614-79","name":"index.js"}]},{"name":"cross-fetch@4.0.0/node_modules/cross-fetch/dist/browser-ponyfill.js","uid":"33dc6614-73"}]},{"uid":"33dc6614-67","name":"\u0000commonjs-dynamic-modules"},{"name":"\u0000/node_modules/.pnpm","children":[{"name":"i18next-http-backend@2.5.2/node_modules/i18next-http-backend/esm/getFetch.cjs?commonjs-module","uid":"33dc6614-69"},{"name":"cross-fetch@4.0.0/node_modules/cross-fetch/dist/browser-ponyfill.js?commonjs-module","uid":"33dc6614-71"}]}]},{"name":"assets/tanstack-DpDh5IPY.js","children":[{"name":"node_modules/.pnpm","children":[{"name":"@tanstack+query-core@5.51.9/node_modules/@tanstack/query-core/build/modern","children":[{"uid":"33dc6614-81","name":"subscribable.js"},{"uid":"33dc6614-83","name":"utils.js"},{"uid":"33dc6614-85","name":"focusManager.js"},{"uid":"33dc6614-87","name":"onlineManager.js"},{"uid":"33dc6614-89","name":"retryer.js"},{"uid":"33dc6614-91","name":"notifyManager.js"},{"uid":"33dc6614-93","name":"removable.js"},{"uid":"33dc6614-95","name":"query.js"},{"uid":"33dc6614-97","name":"queryCache.js"},{"uid":"33dc6614-99","name":"mutation.js"},{"uid":"33dc6614-101","name":"mutationCache.js"},{"uid":"33dc6614-103","name":"infiniteQueryBehavior.js"},{"uid":"33dc6614-105","name":"queryClient.js"},{"uid":"33dc6614-107","name":"queryObserver.js"},{"uid":"33dc6614-109","name":"queriesObserver.js"},{"uid":"33dc6614-111","name":"infiniteQueryObserver.js"},{"uid":"33dc6614-113","name":"mutationObserver.js"},{"uid":"33dc6614-115","name":"hydration.js"},{"uid":"33dc6614-117","name":"types.js"},{"uid":"33dc6614-119","name":"index.js"}]},{"name":"@tanstack+react-query@5.51.11_react@18.3.1/node_modules/@tanstack/react-query/build/modern","children":[{"uid":"33dc6614-121","name":"types.js"},{"uid":"33dc6614-123","name":"QueryClientProvider.js"},{"uid":"33dc6614-125","name":"isRestoring.js"},{"uid":"33dc6614-127","name":"Line truncated
|
||||
|
||||
const run = () => {
|
||||
const width = window.innerWidth;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react",
|
||||
"private": true,
|
||||
"version": "1.1.1",
|
||||
"version": "3.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
"NotAllowed_postUpdate": "Keine Berechtigung",
|
||||
"NotFound_post:postUpdate": "Post nicht gefunden",
|
||||
|
||||
"NotAllowed_delete|PermissionsUser": "Keine Berechtigung",
|
||||
"NotFound_user:delete|PermissionsUser": "Benutzer nicht gefunden",
|
||||
|
||||
"Duplicate_user:register": "Ein Benutzer mit diesem Benutzernamen oder E-Mail existiert schon",
|
||||
|
||||
"username": "Benutzername",
|
||||
@@ -101,5 +104,13 @@
|
||||
|
||||
"Password confirm": "Passwort bestätigen",
|
||||
"Password match": "Passwörter stimmen nicht überein",
|
||||
"Change password": "Passwort ändern"
|
||||
"Change password": "Passwort ändern",
|
||||
|
||||
"Confirm user delete title": "Diesen User löschen?",
|
||||
"Confirm user delete body": "Möchtest du {{name}} wirklich Löschen?",
|
||||
|
||||
"Manage users": "Benutzer verwalten",
|
||||
"Admin": "Administration",
|
||||
"Make Admin": "Administratorrecht erteilen",
|
||||
"Demote Admin": "Administratorrecht entziehen"
|
||||
}
|
||||
@@ -20,6 +20,9 @@
|
||||
"NotAllowed_postUpdate": "Not allowed",
|
||||
"NotFound_post:postUpdate": "Post not found",
|
||||
|
||||
"NotAllowed_delete|PermissionsUser": "Not allowed",
|
||||
"NotFound_user:deleteUserdelete|PermissionsUser": "User not found",
|
||||
|
||||
"Duplicate_user:register": "A user with this username or email already exists",
|
||||
|
||||
"username": "username",
|
||||
@@ -102,5 +105,13 @@
|
||||
|
||||
"Password confirm": "Confirm password",
|
||||
"Password match": "Password do not match",
|
||||
"Change password": "Change password"
|
||||
"Change password": "Change password",
|
||||
|
||||
"Confirm user delete title": "Diesen User löschen?",
|
||||
"Confirm user delete body": "Möchtest du {{name}} wirklich Löschen?",
|
||||
|
||||
"Manage users": "Manage users",
|
||||
"Admin": "Administration",
|
||||
"Make Admin": "Make Admin",
|
||||
"Demote Admin": "Demote Admin"
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
import { createContext, FC, PropsWithChildren, useContext, useEffect, useRef, useState } from 'react';
|
||||
import { ERRORS } from '../components/Error/Errors';
|
||||
import { POST_LIMIT, PROFILE_POST_LIMIT } from '../constanst';
|
||||
import useGuestBookStore from '../store/store';
|
||||
import { PostAuth, PostCreate, PostDelete, PostListAuth, PostListNonAuth, PostNew, PostUpdate } from '../types/Post';
|
||||
import { User, UserCreate, UserImageUpdate, UserUpdate } from '../types/User';
|
||||
import {
|
||||
User,
|
||||
UserCreate,
|
||||
UserDelete,
|
||||
UserImageUpdate,
|
||||
UserList,
|
||||
UserPermissionsUpdate,
|
||||
UserUpdate,
|
||||
} from '../types/User';
|
||||
|
||||
const BASE = 'https://khofmann.userpage.fu-berlin.de/phpCourse/exam/api/';
|
||||
|
||||
@@ -19,11 +28,14 @@ interface ApiContext {
|
||||
updatePost?: (data: PostUpdate, id: number) => Promise<PostAuth>;
|
||||
deletePost?: (id: number) => Promise<PostDelete>;
|
||||
|
||||
users?: (page?: number) => Promise<UserList>;
|
||||
user?: (id?: number) => Promise<User>;
|
||||
createUser?: (data: UserCreate) => Promise<User>;
|
||||
confirmUser?: (code: string) => Promise<User>;
|
||||
updateUser?: (data: UserUpdate, id?: number) => Promise<User>;
|
||||
updateUserImage?: (data: UserImageUpdate, id?: number) => Promise<User>;
|
||||
updateUserPermissions?: (data: UserPermissionsUpdate, id: number) => Promise<User>;
|
||||
deleteUser?: (id: number) => Promise<UserDelete>;
|
||||
|
||||
userPosts?: (id?: number) => Promise<PostListAuth>;
|
||||
}
|
||||
@@ -47,11 +59,14 @@ export const useApi = () => {
|
||||
updatePost,
|
||||
deletePost,
|
||||
|
||||
users,
|
||||
user,
|
||||
createUser,
|
||||
confirmUser,
|
||||
updateUser,
|
||||
updateUserImage,
|
||||
updateUserPermissions,
|
||||
deleteUser,
|
||||
|
||||
userPosts,
|
||||
} = useContext(ApiContext);
|
||||
@@ -63,11 +78,14 @@ export const useApi = () => {
|
||||
newPost &&
|
||||
updatePost &&
|
||||
deletePost &&
|
||||
users &&
|
||||
user &&
|
||||
createUser &&
|
||||
confirmUser &&
|
||||
updateUser &&
|
||||
updateUserImage &&
|
||||
updateUserPermissions &&
|
||||
deleteUser &&
|
||||
userPosts
|
||||
) {
|
||||
return {
|
||||
@@ -82,11 +100,14 @@ export const useApi = () => {
|
||||
updatePost,
|
||||
deletePost,
|
||||
|
||||
users,
|
||||
user,
|
||||
createUser,
|
||||
confirmUser,
|
||||
updateUser,
|
||||
updateUserImage,
|
||||
updateUserPermissions,
|
||||
deleteUser,
|
||||
|
||||
userPosts,
|
||||
};
|
||||
@@ -157,6 +178,12 @@ export const ApiProvider: FC<PropsWithChildren<Record<string, unknown>>> = ({ ch
|
||||
return await (await reAuth(() => _delete(`posts/${id}?l=${POST_LIMIT}`))).json();
|
||||
};
|
||||
|
||||
const users = async (page?: number): Promise<UserList> => {
|
||||
const url = `users?p=${page ?? 0}&l=${POST_LIMIT}`;
|
||||
|
||||
return await (await reAuth(() => getAuth(url))).json();
|
||||
};
|
||||
|
||||
const user = async (id?: number): Promise<User> => {
|
||||
return await (await reAuth(() => getAuth(`users/${id ?? authenticatedUser?.id}`))).json();
|
||||
};
|
||||
@@ -187,10 +214,21 @@ export const ApiProvider: FC<PropsWithChildren<Record<string, unknown>>> = ({ ch
|
||||
return _user;
|
||||
};
|
||||
|
||||
const updateUserPermissions = async (data: UserPermissionsUpdate, id: number): Promise<User> => {
|
||||
const _user = await (
|
||||
await reAuth(() => patchAuth(`users/${id}/permissions`, data as Record<string, unknown>))
|
||||
).json();
|
||||
return _user;
|
||||
};
|
||||
|
||||
const userPosts = async (id?: number): Promise<PostListAuth> => {
|
||||
return await (await reAuth(() => getAuth(`users/${id}/posts?l=${PROFILE_POST_LIMIT}&s=desc`))).json();
|
||||
};
|
||||
|
||||
const deleteUser = async (id: number): Promise<UserDelete> => {
|
||||
return await (await reAuth(() => _delete(`users/${id}?l=${POST_LIMIT}`))).json();
|
||||
};
|
||||
|
||||
/* IMPL */
|
||||
|
||||
const post = async (endpoint: string, body?: Record<string, unknown>, headers?: HeadersInit) => {
|
||||
@@ -284,9 +322,13 @@ export const ApiProvider: FC<PropsWithChildren<Record<string, unknown>>> = ({ ch
|
||||
const ret = await callback();
|
||||
|
||||
return ret;
|
||||
} catch {
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
console.log('[REAUTH] failed once', error);
|
||||
if (error.code !== ERRORS.UNAUTHORIZED) throw error;
|
||||
|
||||
try {
|
||||
console.log('[REAUTH] fail, refreshing');
|
||||
console.log('[REAUTH] failed due to authentication, try refreshing session');
|
||||
// REAUTH
|
||||
await refresh();
|
||||
// DO AGAIN
|
||||
@@ -294,13 +336,13 @@ export const ApiProvider: FC<PropsWithChildren<Record<string, unknown>>> = ({ ch
|
||||
const ret = await callback();
|
||||
|
||||
return ret;
|
||||
} catch (error) {
|
||||
console.log('[REAUTH] terminating session', error);
|
||||
} catch (_error) {
|
||||
console.log('[REAUTH] terminating session', _error);
|
||||
setAuthenticatedUser(undefined);
|
||||
setHasAuth(false);
|
||||
setCurrentSession([undefined, undefined]);
|
||||
token.current = undefined;
|
||||
throw error;
|
||||
throw _error;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -332,11 +374,14 @@ export const ApiProvider: FC<PropsWithChildren<Record<string, unknown>>> = ({ ch
|
||||
updatePost,
|
||||
deletePost,
|
||||
|
||||
users,
|
||||
user,
|
||||
createUser,
|
||||
confirmUser,
|
||||
updateUser,
|
||||
updateUserImage,
|
||||
updateUserPermissions,
|
||||
deleteUser,
|
||||
|
||||
userPosts,
|
||||
}}
|
||||
|
||||
@@ -35,9 +35,7 @@ const PostEditDialog: FC<Props> = ({ post, open, onClose }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: ({ data, id }: { data: PostUpdate; id: number }) => {
|
||||
return Api.updatePost(data, id);
|
||||
},
|
||||
mutationFn: ({ data, id }: { data: PostUpdate; id: number }) => Api.updatePost(data, id),
|
||||
});
|
||||
|
||||
const form = useForm<PostUpdate>({
|
||||
|
||||
@@ -35,9 +35,7 @@ const RegisterDialog: FC<Props> = ({ open, onClose }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: ({ data }: { data: UserCreate }) => {
|
||||
return Api.createUser(data);
|
||||
},
|
||||
mutationFn: ({ data }: { data: UserCreate }) => Api.createUser(data),
|
||||
});
|
||||
|
||||
const form = useForm<UserCreate & { passwordConfirm: string }>({
|
||||
|
||||
@@ -34,9 +34,7 @@ const UserEditDialog: FC<Props> = ({ user, open, onClose }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: ({ data, id }: { data: UserUpdate; id?: number }) => {
|
||||
return Api.updateUser(data, id);
|
||||
},
|
||||
mutationFn: ({ data, id }: { data: UserUpdate; id?: number }) => Api.updateUser(data, id),
|
||||
});
|
||||
|
||||
const form = useForm<UserUpdate>({
|
||||
|
||||
@@ -44,9 +44,7 @@ const UserImageDialog: FC<Props> = ({ user, open, onClose }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: ({ data, id }: { data: UserImageUpdate; id?: number }) => {
|
||||
return Api.updateUserImage(data, id);
|
||||
},
|
||||
mutationFn: ({ data, id }: { data: UserImageUpdate; id?: number }) => Api.updateUserImage(data, id),
|
||||
});
|
||||
|
||||
const form = useForm<UserImageUpdate>({
|
||||
|
||||
@@ -34,9 +34,7 @@ const UserPasswordDialog: FC<Props> = ({ user, open, onClose }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: ({ data, id }: { data: UserUpdate; id?: number }) => {
|
||||
return Api.updateUser(data, id);
|
||||
},
|
||||
mutationFn: ({ data, id }: { data: UserUpdate; id?: number }) => Api.updateUser(data, id),
|
||||
});
|
||||
|
||||
const form = useForm<UserUpdate & { passwordConfirm: string }>({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ErrorOutline } from '@mui/icons-material';
|
||||
import { Grid, Link as MUILink, Typography } from '@mui/material';
|
||||
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
|
||||
import { useQueryClient, useQueryErrorResetBoundary } from '@tanstack/react-query';
|
||||
import { ErrorRouteComponent as TSErrorRouteComponent, useNavigate, useRouter } from '@tanstack/react-router';
|
||||
import { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -13,10 +13,11 @@ const ErrorRouterComponent: TSErrorRouteComponent = ({ error }) => {
|
||||
const router = useRouter();
|
||||
const navigate = useNavigate();
|
||||
const queryErrorResetBoundary = useQueryErrorResetBoundary();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
useEffect(() => {
|
||||
// Reset the query error boundary
|
||||
console.log(queryErrorResetBoundary.isReset());
|
||||
console.log(queryErrorResetBoundary);
|
||||
queryErrorResetBoundary.reset();
|
||||
}, [queryErrorResetBoundary]);
|
||||
|
||||
@@ -34,10 +35,9 @@ const ErrorRouterComponent: TSErrorRouteComponent = ({ error }) => {
|
||||
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<MUILink
|
||||
variant="h6"
|
||||
underline="hover"
|
||||
sx={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
console.log('CLICK AS WELL');
|
||||
queryClient.clear();
|
||||
router.invalidate();
|
||||
navigate({ to: ROUTES.INDEX });
|
||||
}}
|
||||
|
||||
@@ -19,9 +19,7 @@ const PostForm: FC = () => {
|
||||
const Api = useApi();
|
||||
|
||||
const newMutation = useMutation({
|
||||
mutationFn: ({ data }: { data: PostCreate }) => {
|
||||
return Api.newPost(data);
|
||||
},
|
||||
mutationFn: ({ data }: { data: PostCreate }) => Api.newPost(data),
|
||||
});
|
||||
|
||||
const form = useForm<PostCreate>({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Link, Menu, MenuItem, Typography } from '@mui/material';
|
||||
import { Box, Divider, Link, Menu, MenuItem, Typography } from '@mui/material';
|
||||
import { useMatch, useNavigate, useRouter } from '@tanstack/react-router';
|
||||
import { t } from 'i18next';
|
||||
import { FC, useState } from 'react';
|
||||
@@ -69,6 +69,14 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
|
||||
>
|
||||
{t('Log out')}
|
||||
</MenuItem>,
|
||||
Api.authenticatedUser.isAdmin && [
|
||||
<Divider>
|
||||
<Typography variant="caption">{t('Admin')}</Typography>
|
||||
</Divider>,
|
||||
<MenuItem key="users" onClick={() => navigate({ to: ROUTES.USERS })}>
|
||||
{t('Manage users')}
|
||||
</MenuItem>,
|
||||
],
|
||||
]
|
||||
) : register ? (
|
||||
<RegisterDialog open={register} onClose={() => setRegister(false)} />
|
||||
@@ -81,7 +89,6 @@ const UserMenu: FC<Props> = ({ anchorEl, handleClose }) => {
|
||||
<Link
|
||||
sx={{ cursor: 'pointer' }}
|
||||
variant="body1"
|
||||
underline="hover"
|
||||
color="secondary.main"
|
||||
onClick={() => {
|
||||
setRegister(true);
|
||||
|
||||
@@ -44,9 +44,7 @@ const Post: FC<Props> = ({ page = 0, post, disableActions }) => {
|
||||
const Api = useApi();
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: number) => {
|
||||
return Api.deletePost(id);
|
||||
},
|
||||
mutationFn: (id: number) => Api.deletePost(id),
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -41,11 +41,17 @@ const Profile: FC<Props> = ({ user, posts, canEdit }) => {
|
||||
<CardContent>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item sx={{ display: 'flex', flexGrow: 1, justifyContent: 'center' }}>
|
||||
{canEdit ? (
|
||||
<IconButton onClick={() => setImageOpen(true)}>
|
||||
<Avatar alt={user.username} src={`${user.image}`} sx={{ width: '100px', height: '100px' }}>
|
||||
<Person sx={{ width: '60px', height: '60px' }} />
|
||||
</Avatar>
|
||||
</IconButton>
|
||||
) : (
|
||||
<Avatar alt={user.username} src={`${user.image}`} sx={{ width: '100px', height: '100px' }}>
|
||||
<Person sx={{ width: '60px', height: '60px' }} />
|
||||
</Avatar>
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: '120px 1fr', columnGap: 1 }}>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { queryOptions } from '@tanstack/react-query';
|
||||
import { useApi } from '../api/Api';
|
||||
import { ERRORS } from '../components/Error/Errors';
|
||||
|
||||
export const usersQueryOptions = (Api: ReturnType<typeof useApi>, page?: number) =>
|
||||
queryOptions({
|
||||
queryKey: ['users', { page: page ?? 0 }],
|
||||
queryFn: async () => await Api.users(page),
|
||||
retry: (count, error) => ('code' in error && error.code !== ERRORS.UNAUTHORIZED ? count < 3 : false),
|
||||
});
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as IndexImport } from './routes/index'
|
||||
import { Route as UsersIndexImport } from './routes/users/index'
|
||||
import { Route as ProfileIndexImport } from './routes/profile/index'
|
||||
import { Route as ConfirmIndexImport } from './routes/confirm/index'
|
||||
import { Route as ProfileIdImport } from './routes/profile/$id'
|
||||
@@ -23,6 +24,11 @@ const IndexRoute = IndexImport.update({
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const UsersIndexRoute = UsersIndexImport.update({
|
||||
path: '/users/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const ProfileIndexRoute = ProfileIndexImport.update({
|
||||
path: '/profile/',
|
||||
getParentRoute: () => rootRoute,
|
||||
@@ -70,6 +76,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof ProfileIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/users/': {
|
||||
id: '/users/'
|
||||
path: '/users'
|
||||
fullPath: '/users'
|
||||
preLoaderRoute: typeof UsersIndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +93,7 @@ export const routeTree = rootRoute.addChildren({
|
||||
ProfileIdRoute,
|
||||
ConfirmIndexRoute,
|
||||
ProfileIndexRoute,
|
||||
UsersIndexRoute,
|
||||
})
|
||||
|
||||
/* prettier-ignore-end */
|
||||
@@ -93,7 +107,8 @@ export const routeTree = rootRoute.addChildren({
|
||||
"/",
|
||||
"/profile/$id",
|
||||
"/confirm/",
|
||||
"/profile/"
|
||||
"/profile/",
|
||||
"/users/"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
@@ -107,6 +122,9 @@ export const routeTree = rootRoute.addChildren({
|
||||
},
|
||||
"/profile/": {
|
||||
"filePath": "profile/index.tsx"
|
||||
},
|
||||
"/users/": {
|
||||
"filePath": "users/index.tsx"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import { createRouter, ErrorRouteComponent, RouterProvider, useRouter } from '@t
|
||||
import { useEffect } from 'react';
|
||||
import { useApi } from './api/Api';
|
||||
|
||||
import ErrorRouterComponent from './components/Error/ErrorRouterComponent';
|
||||
import NotFoundComponent from './components/NotFound/NotFoundComponent';
|
||||
import { routeTree } from './routeTree.gen';
|
||||
|
||||
//TODO: REAUTH HERE
|
||||
@@ -51,6 +53,8 @@ const router = createRouter({
|
||||
defaultPreloadStaleTime: 0,
|
||||
basepath: process.env.NODE_ENV === 'development' ? 'phpCourse/exam/dist' : '/phpCourse/exam',
|
||||
//defaultErrorComponent: Error,
|
||||
defaultNotFoundComponent: NotFoundComponent,
|
||||
defaultErrorComponent: ErrorRouterComponent,
|
||||
});
|
||||
|
||||
// Register the router instance for type safety
|
||||
|
||||
@@ -3,8 +3,6 @@ import { QueryClient } from '@tanstack/react-query';
|
||||
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
|
||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
||||
import { useApi } from '../api/Api';
|
||||
import ErrorRouterComponent from '../components/Error/ErrorRouterComponent';
|
||||
import NotFoundComponent from '../components/NotFound/NotFoundComponent';
|
||||
|
||||
const Root = () => {
|
||||
return (
|
||||
@@ -17,6 +15,4 @@ const Root = () => {
|
||||
|
||||
export const Route = createRootRouteWithContext<{ queryClient: QueryClient; Api: ReturnType<typeof useApi> }>()({
|
||||
component: Root,
|
||||
notFoundComponent: NotFoundComponent,
|
||||
errorComponent: ErrorRouterComponent,
|
||||
});
|
||||
@@ -15,9 +15,7 @@ const Home = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const confirmMutation = useMutation({
|
||||
mutationFn: ({ code: _code }: { code: string }) => {
|
||||
return Api.confirmUser(_code);
|
||||
},
|
||||
mutationFn: ({ code: _code }: { code: string }) => Api.confirmUser(_code),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -30,7 +30,7 @@ const Home = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if ((page ?? 0) >= postsQuery.pages) {
|
||||
navigate({ to: '/', search: { page: postsQuery.pages - 1 } });
|
||||
navigate({ to: ROUTES.INDEX, search: { page: postsQuery.pages - 1 } });
|
||||
}
|
||||
}, [page]); //eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Divider,
|
||||
Grid,
|
||||
Link as MUILink,
|
||||
Pagination,
|
||||
PaginationItem,
|
||||
Snackbar,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { useMutation, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { createFileRoute, Link, redirect, useNavigate } from '@tanstack/react-router';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useApi } from '../../api/Api';
|
||||
import ErrorComponent from '../../components/Error/ErrorComponent';
|
||||
import { ERRORS } from '../../components/Error/Errors';
|
||||
import HeaderLayout from '../../components/Layouts/HeaderLayout';
|
||||
import { usersQueryOptions } from '../../queries/usersQuery';
|
||||
import { ROUTES } from '../../types/Routes';
|
||||
import { UserPermissionsUpdate } from '../../types/User';
|
||||
|
||||
const Users = () => {
|
||||
const [deleteOpen, setDeleteOpen] = useState(false);
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [_error, setError] = useState<any>();
|
||||
|
||||
const Api = useApi();
|
||||
const { page } = Route.useSearch();
|
||||
const { data: usersQuery, isFetching, failureReason, error } = useSuspenseQuery(usersQueryOptions(Api, page));
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const theme = useTheme();
|
||||
const oneSibling = useMediaQuery(theme.breakpoints.not('xs'), { noSsr: true });
|
||||
|
||||
if (failureReason && 'code' in failureReason && failureReason.code === ERRORS.UNAUTHORIZED) {
|
||||
throw failureReason;
|
||||
}
|
||||
if (error && 'code' in error && error.code === ERRORS.UNAUTHORIZED) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: (id: number) => Api.deleteUser(id),
|
||||
});
|
||||
|
||||
const permissionMutation = useMutation({
|
||||
mutationFn: ({ data, id }: { data: UserPermissionsUpdate; id: number }) => Api.updateUserPermissions(data, id),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if ((page ?? 0) >= usersQuery.pages) {
|
||||
navigate({ to: ROUTES.USERS, search: { page: usersQuery.pages - 1 } });
|
||||
}
|
||||
}, [page]); //eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<HeaderLayout>
|
||||
<Snackbar open={isFetching} message={t('Updating')} />
|
||||
<Grid container spacing={2} sx={{ marginTop: 0 }}>
|
||||
{usersQuery.data.map((user) => (
|
||||
<Grid item xs={12} key={user.id}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
{user.id !== Api.authenticatedUser?.id ? (
|
||||
<MUILink component={Link} to="/profile/$id" params={{ id: user.id }}>
|
||||
{user.username}
|
||||
</MUILink>
|
||||
) : (
|
||||
<Typography>{user.username}</Typography>
|
||||
)}
|
||||
<Typography>{user.email}</Typography>
|
||||
</CardContent>
|
||||
{user.id !== Api.authenticatedUser?.id && (
|
||||
<>
|
||||
<CardActions>
|
||||
<Button size="small" color="error" onClick={() => setDeleteOpen(true)}>
|
||||
{t('Delete')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => {
|
||||
permissionMutation.mutate(
|
||||
{ data: { isAdmin: !user.isAdmin }, id: user.id },
|
||||
{
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['users'],
|
||||
});
|
||||
},
|
||||
onError: setError,
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t(user.isAdmin ? 'Demote Admin' : 'Make Admin')}
|
||||
</Button>
|
||||
<Dialog open={deleteOpen} onClose={() => setDeleteOpen(false)}>
|
||||
<DialogTitle>{t('Confirm user delete title')}</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>{t('Confirm user delete body', { name: user.username })}</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteOpen(false)} autoFocus variant="contained">
|
||||
{t('No')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
deleteMutation.mutate(user.id, {
|
||||
onSuccess: async (data) => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ['users'],
|
||||
});
|
||||
if ((page ?? 0) >= data.pages)
|
||||
navigate({ to: ROUTES.PROFILE, search: { page: data.pages - 1 } });
|
||||
},
|
||||
onError: setError,
|
||||
});
|
||||
setDeleteOpen(false);
|
||||
}}
|
||||
>
|
||||
{t('Yes')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</CardActions>
|
||||
<Snackbar
|
||||
open={deleteMutation.isError || permissionMutation.isError}
|
||||
autoHideDuration={2000}
|
||||
onClose={() => {
|
||||
deleteMutation.reset();
|
||||
permissionMutation.reset();
|
||||
}}
|
||||
TransitionProps={{
|
||||
onExited: () => setError(undefined),
|
||||
}}
|
||||
>
|
||||
<Alert severity="error" variant="filled" sx={{ width: '100%' }}>
|
||||
{error && <ErrorComponent error={_error} context="delete|PermissionsUser" color="white" />}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
<Snackbar open={deleteMutation.isPending} message={t('Deleting')} />
|
||||
<Snackbar open={permissionMutation.isPending} message={t('Updating')} />
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
</Grid>
|
||||
))}
|
||||
<Grid item xs={12}>
|
||||
<Divider variant="middle" />
|
||||
</Grid>
|
||||
<Grid item xs={12} sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Pagination
|
||||
page={(page ?? 0) + 1}
|
||||
count={usersQuery.pages}
|
||||
siblingCount={oneSibling ? 1 : 0}
|
||||
color="primary"
|
||||
renderItem={(item) => (
|
||||
<PaginationItem
|
||||
{...item}
|
||||
component={Link}
|
||||
to="/"
|
||||
search={{ page: (item.page ?? 0) > 0 ? (item.page ?? 1) - 1 : undefined }}
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
onClick={(e) => item.onClick(e as any)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</HeaderLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export const Route = createFileRoute(`${ROUTES.USERS}/`)({
|
||||
loaderDeps: ({ search: { page } }) => ({ page }),
|
||||
loader: ({ context: { queryClient, Api }, deps: { page } }) =>
|
||||
queryClient.ensureQueryData(usersQueryOptions(Api, page)),
|
||||
validateSearch: (search: Record<string, unknown>): { page?: number } => {
|
||||
return {
|
||||
page: search?.page !== undefined ? Number(search?.page ?? 0) : undefined,
|
||||
};
|
||||
},
|
||||
beforeLoad: ({ context: { Api } }) => {
|
||||
if ((!Api.hasAuth && !Api.currentSession[0]) || !Api.authenticatedUser?.isAdmin)
|
||||
throw redirect({ to: ROUTES.INDEX });
|
||||
},
|
||||
component: Users,
|
||||
});
|
||||
@@ -2,4 +2,5 @@ export enum ROUTES {
|
||||
INDEX = '/',
|
||||
PROFILE = '/profile',
|
||||
CONFIRM = '/confirm',
|
||||
USERS = '/users',
|
||||
}
|
||||
@@ -17,6 +17,10 @@ export interface UserUpdate {
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface UserPermissionsUpdate {
|
||||
isAdmin?: boolean;
|
||||
}
|
||||
|
||||
export interface UserCreate {
|
||||
username: string;
|
||||
email: string;
|
||||
@@ -32,3 +36,13 @@ export interface UserImageUpdate {
|
||||
image?: File;
|
||||
predefined?: string;
|
||||
}
|
||||
|
||||
export interface UserList {
|
||||
pages: number;
|
||||
data: User[];
|
||||
}
|
||||
|
||||
export interface UserDelete {
|
||||
pages: number;
|
||||
user: User;
|
||||
}
|
||||
Reference in new issue
Block a user