From 04c14ad4ab1b2b3c3aa87d0d40d65d15b5e372bc Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Mon, 8 Jul 2024 23:20:42 -0400 Subject: [PATCH] updates --- site/bun.lockb | Bin 129185 -> 129899 bytes site/package.json | 1 + site/src/components/command-dialog.tsx | 40 +-- site/src/components/login.tsx | 25 +- site/src/components/routes/home.tsx | 66 ++--- site/src/components/routes/server.tsx | 8 +- .../components/server-table/data-table.tsx | 234 ++++++++++++------ site/src/components/ui/alert-dialog.tsx | 139 +++++++++++ site/src/lib/stores.ts | 11 + site/src/main.tsx | 77 ++++-- 10 files changed, 432 insertions(+), 169 deletions(-) create mode 100644 site/src/components/ui/alert-dialog.tsx diff --git a/site/bun.lockb b/site/bun.lockb index 3763ac44891541fa5d46fab39e89f1b330f24573..c35f27c6b99c0cc45b8df84507c2bda1e302f77b 100755 GIT binary patch delta 21518 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 delta 20867 zcmeHvd0bUh*Z&Nsiful?SAX=Jkj^`IXWhPf^}4Wj3ntDe+BL2@knP$>3CQ= zA%9{C8T}%(Q3wm0ND_3q-UP;<>k}Sr2nn5qCe&RIZ%M+R%Q<%H7-wm2LCM723C@yy zDW8uw_?PvB0&=pnAb%|B?5NQeU~+0;Q?<3?Ir?tutICfl99uZfSyD0-G&yq(q4NX& z5twKf2(slUFj?^*jXxH-po|_c^q0A^1Jni)z!XiRNyS$oKu)ayP5H9`m<)Xna)iqQ zRRa$KQ@cOX(=bRiY0%WmO4Pv-S7s|of~T%Z)Kfnmt<@ZP0QDG(GS?Gr zBndoM%eIo#0=NWpD6pZOB!vN2Y7HFVlcFSGa;GIQLhstqUX}L*P3~TTJQTaW(Awp8 zRKr+Wg7pBM?g34PWB_|fWs=K^0+Pn%8L4{Urr|c=lftb~giyNP0H%S?Eh?D;J<@gn z8KBcIgC;%BDAn`ZBk-tJuSaMk=wMn{ZjZpE7*&DpK~1dcxo(K=@$2AIsCCa*f=2Sy zMof>89+7>hr^vi+Q6sPlIEy@Z1O>ulfXM>~FbTHmqGsYOV2Z#vV4Au55a>g4`;aMP z%f~b{m;J*EAJJkeFb&>NjqU+Vrndra4$Od&Ag-EZH3@bC6Mqdb63R6bn37=_Fs-F2 z8V&;{xds~jRg&7zeqba?nQJQwv~1*;jF?zhlqbE{TOHIFfyu??8lJA>#H>Ufrd9I7}@m{3eBKkfrh7OIA6mVz!ckV8t$awU=81+;W%Uq z&Cg)qdx4wvS7*NmFlFVnRF!{5!$Z^HU=b>CadQ?q^YYWcphzSFlSeR0QCNx5q6wXc zNRgt_OXYU4JYPAM@n(ecJgMe2-z6mhPRukvTELDDi#t(rNl!AkYsHvG-;4Gqb=mO}* zk`zl<)rgTr&QaB1kehc~p2tBUg=1X??<%)0D@6ZD7}q|qY1}sflYKLQq1QDke{9Lr zvANPiCBx zCar!pmL%vmxF+!$*}rfb)KIua7Z(*zC@d*`8Z?DxA#gL`i+QTmGeMJCtI-{WYcVj< zbYbuVPDgzNaFo`5#wc~La)D`yuy1rWx@g>(>6PNf+VFB88!O>eJ~nwB!~GWO8}J&F z#c-DKY+oz$<>kIM){j@={1!L)+1NUsg|jCw_p`}E+$1SZZz3-N)gP1_U+ZUKCwP{> zjfL`Zf18|ZR8=$X^tG_{+!SDAH9QMvGcOOY$@Yel)D10-e67DlUI?lusD>mh9|qM6 zR1;p4lfcVOHuf^FGTDqxaqE=CPxvOX{yZztCUekai-CHVKL*tu6nYG>82vB|kToT; z0X)lWlOF+%)F(^P-w{yMpW?Xehats^q)`Jks-fc3a$X)}V@G&ZkWFrk6rgaqDONf_ zQGW)7DzB}pfd?l+bye!t`dH)ujIkQCwLunnFeuXE&TBxe0Y#P=6)opMQ9IO`EEpxTn3bU~#JPYStRF-cdrO6g}ejDxv8a%Nj$5iO-@6ik`0W9hFOf|pgQvkpG5gkE#GOj$ex&-6f8G# znx*mbR+Ls%I0ti6Ynxn#S(t!&cg2&pczJ7^@dxk*(h$nMk>nHtnb(9`C^DYhG<^L}PjrGP@N zpu6>;uv}=_(I8ND*Mmk#?xs=52spVARBcAEPkDKJo9u&ShI;j&n9BV@sbf#ne2r3V z_z)EJstl&=6QquXq~vQRC`w%xhLWhopvZo8RvZRJLjnp~Jh04@AL;;h=T(t5c9fes*;rei)yZaD z+(OBgfJFIIlt?G$VMhyV$4yZ-IUB25q{<7o$a6Icb01OoHz+mh*0#17u7>i!Xe+bu ztY{l6<>k>f`DBTOtWZi=^IluJ>f0alkPw>BR63fEk~RWJoS#5xBLGzckRrWF%5XiFuS&Mcb}YGCpdq{#l;#DfGoZBag6e@w zJaq>Tp@@U($17|}9w<Zlc<)X|~dPlCFS++gv%yc@1@T_ni{)mR5wS#TXPb+^e)Fkk~~4a)_k z`5BVn0iw<^6Q+Qghh+0KP_AHlJtpv>9KwO41OX(=*ZN ziLSGh(nyq4-gcBS6rN9tB<1jm-brpK6e_H0l$=T_5m)ydrL+>IQA+71O8H7D4`VS* zDebH+h4oO>^-OX@L9INAlG?uo+3cVO@?w-|YBRbR7(VXFtM9iOk0Ph~^Aq`WdC3id+}WY_&9_wzR#rWK7j+*&trk-)2~w$^+A^av1W5 zrV*xGfJH6`}4pDtn!4kddXru1S)~&1SB$dUiE;D_2s5? zn_=|>JUiWLsD6O2O1HA+yei$s^0;Y$&G1}0&mLekRHgG(1FXi73~C)5muPH({L52H zZ=m#`QffMg97e62i4rX;M&;76926#qb|EX{=J3j1p!I zdO3;GNFMA+a?7M8fK;zW3Bl2phOa@XX7tOFq->?p^C+b#rRLd^G*l@)jFQsccmyT2 zw&@UxEOj#yrS4QRyf}mhW?Bu`hVbl6tDG{l_6mrr;}lTpDnS>6-JmGs4V0@~L!Omo zlkd+_ukKhd!f`7^l%oGAN{W8gf@fvha7S96ZIkC??ZOI1SJX(0{4S`DieGg1`ZXxk z-jrb!)Esl7JO`y(&kaY0@xVAM^Ws@UZE`B6JgLGW9%^A_ylSY;uwyt6%(2QhP=(Az zxNBfjx)Z(7(j?D72~(fuJyxClpt{nkV{C}^B0;%?TB!sHc!Zgj0Y%V{&dlutnKPma=a@(N0W zsTTK~S-FX20g|%!AvFLt1L*iY%upW$@B<*ik^zA1RgU`D4IDVG=uK3sX^~QndKi}z z9Q7ErG$~F7kfLq?GO#Crj{2Ak>IEQ-&`A7Ho2Vv5UIS4bpeyo2Pk;rf5sE>`{V9qKBVbYFSt7ys8XiPcfAWYha07wp#L^*p?{;454xmCPf7RcR(?Kj{2BFGyy;gN;F&wOvjyYL+~F4klyJ4I_j|Ezsewm zGXR8V0_Y%24P5{_TmVuy2SA3*1CacD03C#hzlaDN^)bmU1`u8XpkoPzh#D*hPz49j zL74a}h`@0tOopvgYE?|~PXb8KYU1X(GHv=35klYaf$sGkW0-OR6{|tcI zeF32QuPB`;&n^NeeSQH@#T5--1119uXhrohFe&mREw^E6=LNnI*cX^Y{4_bj)Q+A` z5pE7lRUwR8@rVij^qffwC!U6hZVj5E-4>YCMrb$&_#V*7z$BLfOmf|U{eUxp$=qSU zp1?)GBv%Yfa^p2zqTz{5i^B{s=pamfKdRw*z>Pr*t)4I`T&3X(U^4I-jeZW8I(h+^ z4#HG?5hpV2RbZ;$04xK)!!WH#;TABO0w2-@DuKz<&our8U^@PCT=pjv`@;|;x$zg^ zvcF2vpV5OMDUC5ob^II4N)^q?oOD3=!1F^@xzH|e@&h+(E-3sfZJ%eGq90< zyCkAOM}15Uk~DsOOv%|De5&sO+<=c6?a!x=_9`RcJ~+|5&(I_W0uz5QPUJ$CMh^id z*M@2Q5x}G|7nqLvnD}{GeZE#-ACsO!1KoP4g<4DvAJQ5SrecwX$7+1S1|B@gpLd+( zL7=!XL8~Q9vuiRiX`7<)36ne1H2!prPnh_MlG`w~cWH8jiJk>atVcCIut9R?*NZ|F z4U530cynM9e?k)@tQF}wkpk4M89>MHVbT)>pw%h{Kzi!mCxIloOc|d4j~gbE|7-7; zps%;YyN_*3>(k#iO*CM4x>=&&5T6p{@0%uy#@{zh2mz(T-#1Nv-!##5xb<%B@0%uy zNd229T3Y|UX;SW;pa(=MQ-$&bxTKcO7gupM~=tUWM~s9=*lE z_VIaJ9DME;Pkw%jogLs^-gB^nd>PJ%_&J;p^KM%mtdf`Ge1w0G^GCeTHV40dn9D9S%G_%EGytZ@~FDmv=hYXWWVN3BC#Elid4#2Rp?J zaX!tr<6Of{A2`_Od_2x)_#T|U;GrKn*jYXm=P!9B&R_9%yBzFmJ`3k_ylR(&f4a+) zC-1hiZ}`03@M1T-0Ck>s+2h~|dpvo?9y`0p&w=_HRO((k`<|EYb?}vYJ^6J|Kk`2N z;LASvvd_+b=2t*n29>kl&MxtF`yKqn{hr+OfSq08SqB_E^MEJc0_s;TA9Qe!gPwfM zK|8z7H-UN^RPZ6Y;ikkNIy9IU9P;D`4%r#wro#>%aM+X2IBaJP_#RNZK}A&BnUPPe zbnq#ap8NzTci!%ZgSS26$rl~5GnrR``V>_1M|O4(pZ5_Q{0I($^5k7UhJzo&!H?~% z2|owwYf!02?aZ5(ABBTQ;UK7Hyw5Q>cnl66v*W)nu7J7>D(4eB^XKb6frFpG!B6eX z#IrtygP+1dP-ZSy!NDpxSY^j!^i81N1{GXwXCb_>+QAE|;UB0_ZaNPCj>Es>b{5X} zfZ7cz;xjvI#ixD-|2~6%pxW?uC*a=+_;>U^>LFQDlApDy_$3H^TMe7Q{%?aOBS|q_^;op zCmwZviabgCCu2XJ{$n%av?TnHMK2CUIvVN!OSY%y#)Cioz>LdM@tc`PpS4k~ul^5M zxkZJM50$7tc!q8azH}cm?#6DZC-l6)xYt!T3opR$8B6_}2$8jm6{OX1-6BY33H3-GAMOV;GPMS3D@mP~t7k7-r-&lV+MwDU;Y zxTK19;P6NPW2S8Rl6()1=PTAiMGXDqoeQ9OS&H}y!dRUJfcD{sLFI6O6F?hLv?}&Wdd-2BC}D* z1Uv&}xe%rexS4>J;FSYb0bGDtfJXo{D`x{}3eEte0fqo*zxjDU9@?%3{UqQCz&`*B z0m}g)sDBQamLn{v_?Hc=4e=;!5t~ww+#jI$Az&APmKa)6XazB&-S@!%0aO910fzu@ z03HU=)L#IY2Ur4_19%)jbDVfIul4%HC>NwaA&zZ*Rop0PVr-1Hg>X+|zP^`H@gsmb z)7Q^)Z_Vq*+PDXlf(QSkO08}yZ~{Ple?K!fym^>N;oFDV*fue!4;xZ;1e^XyJ|qL;*~IPJl=NT{V0m zA4ZQ9=(2JJ#Cre|qIKdX$}|)P06iw5`Ed`x13-^SsFPqo5I_Q41)?_B0c6-Uz^{NC z02&&4k*6V`0e}IhKhkZaM+$CQ1u+Py6EY+~qsaih(?%#$qLVUGq_-jCs7$hC97Twp z|1<_nL78akoF)oQm?i*v4%Dm+Cm(=6fD}9g!6E=X1k#Psc|=o3bTMrSXak_9J?#K( z0j&YV>i}pEAU=fJ6K)`l$}v(zq%u=H%~fQA>&1?b z%+L7A+}gk%jERhnj8bQ}4{D~(IDTl9&#r%=CR(j|SxiGywq5)qm8Aw%K?CyC^}cj2 zCdWok8Lr#D5E2{WV`7-|*@sNv- zSNwH~i;#=gUlj|AZJN;PaLWn^#7D+Zr1ZDX(yr`$^If+Qt29%hv7(7?1DHt+PG^CJ zn+?Q-bVT8XK|G(%Ml!QtkD_1wRkaRBpPf)S`t_mIuc}sQ9BbBJC3|k(n(+4hpRsD% z(QiAkWB^NL6U7O1V%A?#d-S#ZL+!hyZBi6PMOv`73GWO9dY9;x!BWlo8)uCwYN}_u zpNWMWjX13BE7n7R9TmT3K%f4mS@MtDHth9^FMymym0K=44P>Uy`m1N{JKcZn@(>>y zA`2o5!#?p;ZqHl`@}Ai6ZuOp1N*7AZzw#6_2OL7Hi zzk&9+d%LGnpMCuWw5G)Cf~&QdH3)K@#39JBS>oIvH0~vW2P;;OreV}yP|I8R@4MB-%oL=*vbHU-Rm080hMz{W zSU82we)JJ3nJmVvzx4L6dyn0?+2d#&Bru04oK3|ds9;0I3z^WLkLel+{Vs7FT(ka8 zoFo0?)SMso)YLU|iY8gil%~HV_u|wW#j$J5-P~w?M$;76--^3l#9kX0*0UN-DdS;N zaDY01m#hq4PL&4tMpJ_kzP}!nes`l*lw=QDYPl+0cC# z0Sv(c;e-HNA*PX>{#M_J@hy{6?rD+$MVPNNR0qYY5Qx{`FX`WD$1|qAJAIU%6dUef zUA)><3xNJ+VK!TRy!WN2$7x1Fw<^FE2s;Hze^W5)!_EW#)A!1^ki$eEXM#i-1XvqU zJ_Nb;ia0O?xi(9fhoaTO5H*-JHx9hgHqLV;TG65a?Q2CE1lT*GVkq+uj*=#~P{(C> zpWJ)G<_)4Tq`ZQDMWloL?=W1O5O!}-iH7m|D}Z0WIKRoUV+~<IMNG7B`5=vEXL%(D76c*CWi%TWmYN1KZu%@;vxy0 z5*wV%Wca3~I9_Rc8Igy~j?^EE{gx@R5PVM8+#& zP@OPbYAsF*|#0@8>=9&%ALTZl2Oqt)XFgLae85{%lZNiqsK$^ScD} z_Asj<(i~%T<}+27S%2;G_{3*>-rOBOTeUS7w*Idesg0sK__y1tM*p`){^@wtb9aYe zg?i}zL^|Ku;5&0QH*SqzvY!5TpE>#quV(%dLi6RH_MWa~g z9qLs*T0L_U*P%5+e_eNAG~aNndUv^ET}&h<#UC1?EHXX~mFt1xN@Rdi{=zd4l`nms5_@3{|cc zx6e@Bq`Mp2Qan9QH}*&Mp9X8o4KnEG$(72r-wyLIn}eja+sC*(oFOpUw84<<8WKn|2}zZa%$%O*@V}W{l>Ps#aOrT z?)j^k@ITVw5D}$FVg23vdmH6jg9<_})g{~=z1GsNUe9LzE&g{eJ$Gelb=LYi4Xea; z>Oz0-|JkQPraWD-W=fsFt(S)IKX$xczuN6oZKFTvrEZ#Q!TYcKZYAED#9|Fs!o|0f za1W(_lwe(2aOLXdM>gX+5FLq|ee5NQkja?z8q&geOOoGyA^&5?Z%fcySIt{=-|Bi9lxkQxgf_O-pO+^>}5S+)Pmn zfzJB3DK0-)J~M9h-kWs-`qwMI?AFTT=N>)ZudAs^7Vpi35&HKomd^^xnmOs`wsjJ% z#P?)G4{=W!jL^TA5&Uo(J3IZTt4?mJut6YR|G>uF2~V~;F}IIroq+z~h?6I`R=gCm zrHdQGkH%>F6%s5Kk#7A<6JM<;{b8-`m(6to-NbeX;P&n~$?0FJi0Zy-*jo*o80zGv zh$b!sLjSbIT(_4ChIx0LQYWB){KCWA+Tm^X#QwUP4ZXyJE*8*P|6WGG)vM71_IA#% zlhD7Yu|v9WU+Z&*l)9Spy~N9CYu3NP(Y|ThShnEI+BykeaSDdT>mTjliQk4lv}o1b zIsyH&9=m^Wg-rkFAYNCKE+S^Z>5;wFU$O(NhdTrXd%sX8FkLtyU|8N;OrOO9g7goG z6b*mo=CNg)ur;EG`MuuaHAuwk4}^d0ChljXMR_Gu3m=O~hvZGmpFf_#vP1;@2HYk0C{Sg+M_FF}fcwj<%C;HbuzDaaC z_r&y`TVqK4}eXW(@3)iA>NxG9nizefXdBRamrVVk5LO?%wl6 z1)8!D(QOX%HDbRaHcC_yCtZ9)d!721FWSdPU&tQ3uB~D=<~Sbzh>+PBn5PGbuCrOc zApKJsEBtnE2 z|A5GSpBMFNzx^%RiLyk-U<9zyv}hshU6mmk&p|e?Lvt@Q|K_1-bL6g_pRN;BVqr3D z$`C^#7^HuqL>l?t`{$RA|4fO1vK@3fLo9`a;bw;T*Blmu-M$lZV8WdfFa~KfTX;VX z6IKiq9Uq5$p%@0Tv;HlX2dln|?7t>(UY#Xt2IJ8)Y`nC(NzI(M_b#fd**;jj@;JIa zGgz#i2aGtmmN35tcv7c?BS`S@l%l=9*T3E zUZsWh4`tHb42e_GfEvZovGTP=Bf$vMR{g0 zSd5;J*)v8wJs(-1GHZQ%Pn-ugNdGv^;`u3*&-y2+Q8QhKax}qyQLyPG+m4z!taQP#aIRO4+p(* zrFr#I*Hdp}&kqj)Fteldui5M<>t9oRYV(6yKbXr$#WXZE-`-RmINHRVB3>ok`gd<$ z$ZD7Q!N~VtRsx9)XgnOwSN>1K<+*88eDi%}Un(`qELkY7FJ_~dvaI+vq?xEDYk(FU zvwf60w=eZuaxwagaP_H$GG%i`+ESQx_X#pXFbHVbuPej`2{qHXjixMCpRgq?5et{H z?%t)&!lKEAWApACa-{Wz4jbC67d1;+2wN}MG8Phc%v)V~jt`plPsd9wOf{fsn`M^& zpvE_S;!d9T7TuRIYhWK-I*30zA$~ub()dQf615lkvRJi@&3P+nIh&RER { const down = (e: KeyboardEvent) => { @@ -45,6 +48,7 @@ export function CommandPalette() { > Home + ⌘H { @@ -55,27 +59,31 @@ export function CommandPalette() { PocketBase ⌘P - - - { - navigate('/server/kagemusha') - setOpen((open) => !open) + window.location.href = 'https://github.com/henrygd' }} > - - Kagemusha - - navigate('/server/rashomon')}> - - Rashomon - - navigate('/server/ikiru')}> - - Ikiru + + Documentation + ⌘D + + + {servers.map((server) => ( + { + navigate(`/server/${server.name}`) + setOpen((open) => !open) + }} + > + + {server.name} + + ))} + ) diff --git a/site/src/components/login.tsx b/site/src/components/login.tsx index afea7ea4..7041337c 100644 --- a/site/src/components/login.tsx +++ b/site/src/components/login.tsx @@ -11,7 +11,11 @@ export default function LoginPage() {
- + {/* */}

Welcome back

Enter your email to sign in to your account @@ -33,19 +37,12 @@ export default function LoginPage() { }} >

- Melon - - - + placeholder +
{/*
diff --git a/site/src/components/routes/home.tsx b/site/src/components/routes/home.tsx index 9c189911..fb780724 100644 --- a/site/src/components/routes/home.tsx +++ b/site/src/components/routes/home.tsx @@ -1,47 +1,56 @@ -import { useEffect, useState } from 'preact/hooks' -import { pb } from '@/lib/stores' -import { SystemRecord } from '@/types' +import { useEffect } from 'preact/hooks' +import { $servers, pb } from '@/lib/stores' import { DataTable } from '../server-table/data-table' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../ui/card' +import { useStore } from '@nanostores/preact' +import { SystemRecord } from '@/types' export function Home() { - const [systems, setSystems] = useState([] as SystemRecord[]) + const servers = useStore($servers) + // const [systems, setSystems] = useState([] as SystemRecord[]) useEffect(() => { document.title = 'Home' }, []) useEffect(() => { - pb.collection('systems') - .getFullList({ - sort: 'name', - }) - .then((items) => { - setSystems(items) - }) + console.log('servers', servers) + }, [servers]) - // pb.collection('systems').subscribe('*', (e) => { - // setSystems((curSystems) => { - // const i = curSystems.findIndex((s) => s.id === e.record.id) - // if (i > -1) { - // const newSystems = [...curSystems] - // newSystems[i] = e.record - // return newSystems - // } else { - // return [...curSystems, e.record] - // } - // }) - // }) - // return () => pb.collection('systems').unsubscribe('*') + useEffect(() => { + pb.collection('systems').subscribe('*', (e) => { + const curServers = $servers.get() + const newServers = [] + console.log('e', e) + if (e.action === 'delete') { + for (const server of curServers) { + if (server.id !== e.record.id) { + newServers.push(server) + } + } + } else { + let found = 0 + for (const server of curServers) { + if (server.id === e.record.id) { + found = newServers.push(e.record) + } else { + newServers.push(server) + } + } + if (!found) { + newServers.push(e.record) + } + } + $servers.set(newServers) + }) + return () => pb.collection('systems').unsubscribe('*') }, []) - // if (!systems.length) return <>Loading... - return ( <> - All Systems + All Servers Press{' '} @@ -51,10 +60,9 @@ export function Home() { - + - {/*
{JSON.stringify(systems, null, 2)}
*/} ) } diff --git a/site/src/components/routes/server.tsx b/site/src/components/routes/server.tsx index 72e62f06..f4e4ed5c 100644 --- a/site/src/components/routes/server.tsx +++ b/site/src/components/routes/server.tsx @@ -6,7 +6,7 @@ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '../ui export function ServerDetail() { const [_, params] = useRoute('/server/:name') - const [node, setNode] = useState({} as SystemRecord) + const [server, setServer] = useState({} as SystemRecord) useEffect(() => { document.title = params!.name @@ -16,7 +16,7 @@ export function ServerDetail() { pb.collection('systems') .getFirstListItem(`name="${params!.name}"`) .then((record) => { - setNode(record) + setServer(record) }) }) @@ -24,11 +24,11 @@ export function ServerDetail() { <> - {node.name} + {server.name} 5.342.34.234 -
{JSON.stringify(node, null, 2)}
+
{JSON.stringify(server, null, 2)}
diff --git a/site/src/components/server-table/data-table.tsx b/site/src/components/server-table/data-table.tsx index 101160bc..b5ac83fe 100644 --- a/site/src/components/server-table/data-table.tsx +++ b/site/src/components/server-table/data-table.tsx @@ -32,10 +32,23 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from '@/components/ui/alert-dialog' + import { SystemRecord } from '@/types' -import { MoreHorizontal, ArrowUpDown, Copy, RefreshCcw } from 'lucide-react' -import { Link } from 'wouter-preact' -import { useState } from 'preact/hooks' +import { MoreHorizontal, ArrowUpDown, Copy, RefreshCcw, Eye } from 'lucide-react' +import { useMemo, useState } from 'preact/hooks' +import { navigate } from 'wouter-preact/use-browser-location' +import { $servers, pb } from '@/lib/stores' +import { useStore } from '@nanostores/preact' function CellFormatter(info: CellContext) { const val = info.getValue() as number @@ -73,76 +86,91 @@ function sortableHeader(column: Column, name: string) { ) } -export function DataTable({ data }: { data: SystemRecord[] }) { - const columns: ColumnDef[] = [ - { - // size: 70, - accessorKey: 'name', - cell: (info) => ( - - {info.getValue() as string}{' '} - - {/* */} - - ), - header: ({ column }) => sortableHeader(column, 'Node'), - }, - { - accessorKey: 'stats.cpu', - cell: CellFormatter, - header: ({ column }) => sortableHeader(column, 'CPU'), - }, - { - accessorKey: 'stats.memPct', - cell: CellFormatter, - header: ({ column }) => sortableHeader(column, 'Memory'), - }, - { - accessorKey: 'stats.diskPct', - cell: CellFormatter, - header: ({ column }) => sortableHeader(column, 'Disk'), - }, - { - id: 'actions', - size: 32, - maxSize: 32, - cell: ({ row }) => { - const system = row.original +export function DataTable() { + const data = useStore($servers) + const [liveUpdates, setLiveUpdates] = useState(true) + const [deleteServer, setDeleteServer] = useState({} as SystemRecord) - return ( -
- - - - - - Actions - - - View details - - - navigator.clipboard.writeText(system.id)}> - Copy IP address - - - Delete node - - -
- ) + const columns: ColumnDef[] = useMemo( + () => [ + { + // size: 70, + accessorKey: 'name', + cell: (info) => ( + + {info.getValue() as string}{' '} + + {/* */} + + ), + header: ({ column }) => sortableHeader(column, 'Server'), }, - }, - ] + { + accessorKey: 'stats.cpu', + cell: CellFormatter, + header: ({ column }) => sortableHeader(column, 'CPU'), + }, + { + accessorKey: 'stats.memPct', + cell: CellFormatter, + header: ({ column }) => sortableHeader(column, 'Memory'), + }, + { + accessorKey: 'stats.diskPct', + cell: CellFormatter, + header: ({ column }) => sortableHeader(column, 'Disk'), + }, + { + id: 'actions', + size: 32, + maxSize: 32, + cell: ({ row }) => { + const system = row.original + + return ( +
+ + + + + + Actions + { + navigate(`/server/${system.name}`) + }} + > + View details + + navigator.clipboard.writeText(system.id)}> + Copy IP address + + + { + setDeleteServer(system) + }} + > + Delete server + + + +
+ ) + }, + }, + ], + [] + ) const [sorting, setSorting] = useState([]) @@ -172,16 +200,32 @@ export function DataTable({ data }: { data: SystemRecord[] }) { onChange={(event: Event) => table.getColumn('name')?.setFilterValue(event.target.value)} className="max-w-sm" /> - +
+ {liveUpdates || ( + + )} + +
@@ -203,7 +247,7 @@ export function DataTable({ data }: { data: SystemRecord[] }) { {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( - + {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} @@ -221,6 +265,32 @@ export function DataTable({ data }: { data: SystemRecord[] }) {
+ + + + + Are you sure you want to delete {deleteServer.name}? + + + This action cannot be undone. This will permanently delete all current records for{' '} + {deleteServer.name} from the database. + + + + setDeleteServer({} as SystemRecord)}> + Cancel + + { + setDeleteServer({} as SystemRecord) + pb.collection('systems').delete(deleteServer.id) + }} + > + Continue + + + +
) } diff --git a/site/src/components/ui/alert-dialog.tsx b/site/src/components/ui/alert-dialog.tsx new file mode 100644 index 00000000..8722561c --- /dev/null +++ b/site/src/components/ui/alert-dialog.tsx @@ -0,0 +1,139 @@ +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/site/src/lib/stores.ts b/site/src/lib/stores.ts index 165c7dc4..ab469ee7 100644 --- a/site/src/lib/stores.ts +++ b/site/src/lib/stores.ts @@ -1,3 +1,14 @@ import PocketBase from 'pocketbase' +import { atom } from 'nanostores' +import { SystemRecord } from '@/types' export const pb = new PocketBase('/') +// @ts-ignore +pb.authStore.storageKey = 'pb_admin_auth' + +export const $authenticated = atom(pb.authStore.isValid) +export const $servers = atom([] as SystemRecord[]) + +pb.authStore.onChange(() => { + $authenticated.set(pb.authStore.isValid) +}) diff --git a/site/src/main.tsx b/site/src/main.tsx index 0497a9eb..cbafbde9 100644 --- a/site/src/main.tsx +++ b/site/src/main.tsx @@ -4,42 +4,71 @@ import { Link, Route, Switch } from 'wouter-preact' import { Home } from './components/routes/home.tsx' import { ThemeProvider } from './components/theme-provider.tsx' import LoginPage from './components/login.tsx' -import { pb } from './lib/stores.ts' +import { $authenticated, $servers, pb } from './lib/stores.ts' import { ServerDetail } from './components/routes/server.tsx' import { ModeToggle } from './components/mode-toggle.tsx' import { CommandPalette } from './components/command-dialog.tsx' +import { cn } from './lib/utils.ts' +import { buttonVariants } from './components/ui/button.tsx' +import { Github } from 'lucide-react' +import { useStore } from '@nanostores/preact' +import { useEffect } from 'preact/hooks' +import { SystemRecord } from './types' -// import { ModeToggle } from './components/mode-toggle.tsx' +const App = () => { + const authenticated = useStore($authenticated) -// const ls = localStorage.getItem('auth') -// console.log('ls', ls) -// @ts-ignore -pb.authStore.storageKey = 'pb_admin_auth' + return {authenticated ?
: } +} -console.log('pb.authStore', pb.authStore) +const Main = () => { + // const servers = useStore($servers) -const App = () => {pb.authStore.isValid ?
: } + useEffect(() => { + console.log('fetching servers') + pb.collection('systems') + .getFullList({ sort: '+name' }) + .then((records) => { + $servers.set(records) + }) + }, []) -const Main = () => ( -
-
- -
+ return ( +
+
+ {/* + + */} +
+ + + + +
+
- {/* + {/* Routes below are matched exclusively - the first matched route gets rendered */} - - + + - - - {/* Default route in a switch */} - 404: No such page! - - -
-) + + {/* Default route in a switch */} + 404: No such page! + + +
+ ) +} render(, document.getElementById('app')!)