this is a big slop that might backfire lol... new config system and UI!

This commit is contained in:
legop3
2026-09-14 02:31:12 -04:00
parent 17b1404157
commit bfdb6555d8
108 changed files with 3212 additions and 701 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import{e as E,r as s,j as e,S as P,C as c,L as F}from"./index-B3PBxGLi.js";import{e as I,f as $,i as q}from"./api-C8p-OT8N.js";function R(){const i=E(),[a,m]=s.useState(null),[n,b]=s.useState(""),[d,N]=s.useState(""),[p,C]=s.useState(""),[r,S]=s.useState(""),[f,v]=s.useState(""),[o,w]=s.useState(null),[x,h]=s.useState(!1),[g,l]=s.useState("");s.useEffect(()=>{I(i).then(t=>m(t.required)).catch(t=>l(t.message))},[i]);async function y(t){h(!0),l("");try{await t(),m(!1),l("Setup completed. You can now open the administration application and log in.")}catch(u){const L=Array.isArray(u.validationErrors)?` ${u.validationErrors.map(j=>`${j.path}: ${j.message}`).join("; ")}`:"";l(`${u.message}${L}`)}finally{h(!1)}}function k(t){if(t.preventDefault(),r!==f){l("Passwords do not match.");return}y(()=>$(i,{setupCode:n,username:d,discordId:p,password:r}))}function A(t){t.preventDefault(),o&&y(async()=>q(i,{setupCode:n,fileName:o.name,yaml:await o.text()}))}return e.jsxs("div",{className:"min-h-screen bg-neutral-950 p-1 text-slate-100",children:[e.jsx(P,{}),e.jsxs("main",{className:"mx-auto flex min-h-screen w-full max-w-3xl flex-col justify-center gap-0.5",children:[e.jsxs(c,{title:"MultiRover setup",meta:a===null?"checking":a?"required":"complete",bodyClassName:"space-y-0.5 p-1 text-sm",children:[a?e.jsx("p",{children:"Enter the one-time setup code printed in the server log, then create the first lockdown administrator or import an existing configuration."}):null,a===!1?e.jsx(F,{className:"button-dark inline-block",to:"/admin",children:"Open administration"}):null,g?e.jsx("p",{className:"surface p-1 text-sm text-slate-200",children:g}):null]}),a?e.jsxs(e.Fragment,{children:[e.jsxs(c,{title:"Setup authorization",bodyClassName:"p-1",children:[e.jsx("label",{className:"block text-xs font-semibold text-slate-200",children:"One-time setup code"}),e.jsx("input",{className:"field-input mt-0.5 w-full font-mono",value:n,onChange:t=>b(t.target.value)})]}),e.jsx(c,{title:"Create first administrator",bodyClassName:"p-1",children:e.jsxs("form",{className:"grid gap-0.5 md:grid-cols-2",onSubmit:k,children:[e.jsx("input",{className:"field-input",placeholder:"Username",value:d,onChange:t=>N(t.target.value)}),e.jsx("input",{className:"field-input",placeholder:"Discord id (optional)",value:p,onChange:t=>C(t.target.value)}),e.jsx("input",{className:"field-input",type:"password",placeholder:"Password",value:r,onChange:t=>S(t.target.value)}),e.jsx("input",{className:"field-input",type:"password",placeholder:"Confirm password",value:f,onChange:t=>v(t.target.value)}),e.jsx("button",{className:"button-dark md:col-span-2",type:"submit",disabled:x||!n||!d||!r,children:"Create lockdown administrator"})]})}),e.jsxs(c,{title:"Import legacy configuration",bodyClassName:"space-y-0.5 p-1 text-sm",children:[e.jsx("p",{className:"text-xs text-slate-400",children:"The selected YAML is uploaded directly for one-time validation and import. Its secrets are never displayed back in the browser."}),e.jsxs("form",{className:"flex flex-col gap-0.5 md:flex-row",onSubmit:A,children:[e.jsx("input",{className:"field-input flex-1",type:"file",accept:".yaml,.yml,text/yaml",onChange:t=>w(t.target.files?.[0]||null)}),e.jsx("button",{className:"button-dark",type:"submit",disabled:x||!n||!o,children:"Import selected YAML"})]})]})]}):null]})]})}export{R as default};
//# sourceMappingURL=SetupApp-Ct8z7xZT.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
function r(t,i,a={}){return new Promise((e,s)=>{t.emit(i,a,(n={})=>{if(n?.error){const o=new Error(n.error);o.code=n.code||null,o.validationErrors=n.validationErrors||[],o.currentRevision=n.currentRevision||null,s(o);return}e(n)})})}const d=t=>r(t,"adminConfig:get"),c=(t,i)=>r(t,"adminConfig:confirmPassword",{password:i}),m=(t,i)=>r(t,"adminConfig:updateConfiguration",i),u=(t,i)=>r(t,"adminConfig:restoreRevision",i),g=(t,i)=>r(t,"adminConfig:createAdministrator",i),f=(t,i)=>r(t,"adminConfig:updateAdministrator",i),A=(t,i)=>r(t,"adminConfig:deleteAdministrator",{id:i}),C=t=>r(t,"setup:status"),l=(t,i)=>r(t,"setup:createAdministrator",i),p=(t,i)=>r(t,"setup:importLegacy",i);export{m as a,c as b,g as c,A as d,C as e,l as f,d as g,p as i,u as r,f as u};
//# sourceMappingURL=api-C8p-OT8N.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"api-C8p-OT8N.js","sources":["../../../webui/src/admin/api.js"],"sourcesContent":["// Admin Socket API\n// Purpose: Gives the setup and administration applications one promise-based boundary around acknowledged socket events.\n// Scope: Preserves server error codes and validation details so shared UI infrastructure can respond consistently.\nexport function emitAdminRequest(socket, eventName, payload = {}) {\n return new Promise((resolve, reject) => {\n socket.emit(eventName, payload, (response = {}) => {\n if (response?.error) {\n const error = new Error(response.error);\n error.code = response.code || null;\n error.validationErrors = response.validationErrors || [];\n error.currentRevision = response.currentRevision || null;\n reject(error);\n return;\n }\n resolve(response);\n });\n });\n}\n\nexport const getAdminSnapshot = (socket) => emitAdminRequest(socket, 'adminConfig:get');\nexport const confirmAdminPassword = (socket, password) => emitAdminRequest(socket, 'adminConfig:confirmPassword', { password });\nexport const updateConfiguration = (socket, payload) => emitAdminRequest(socket, 'adminConfig:updateConfiguration', payload);\nexport const restoreConfigurationRevision = (socket, payload) => emitAdminRequest(socket, 'adminConfig:restoreRevision', payload);\nexport const createAdministrator = (socket, payload) => emitAdminRequest(socket, 'adminConfig:createAdministrator', payload);\nexport const updateAdministrator = (socket, payload) => emitAdminRequest(socket, 'adminConfig:updateAdministrator', payload);\nexport const deleteAdministrator = (socket, id) => emitAdminRequest(socket, 'adminConfig:deleteAdministrator', { id });\n\nexport const getSetupStatus = (socket) => emitAdminRequest(socket, 'setup:status');\nexport const createFirstAdministrator = (socket, payload) => emitAdminRequest(socket, 'setup:createAdministrator', payload);\nexport const importLegacyConfiguration = (socket, payload) => emitAdminRequest(socket, 'setup:importLegacy', payload);\n"],"names":["emitAdminRequest","socket","eventName","payload","resolve","reject","response","error","getAdminSnapshot","confirmAdminPassword","password","updateConfiguration","restoreConfigurationRevision","createAdministrator","updateAdministrator","deleteAdministrator","id","getSetupStatus","createFirstAdministrator","importLegacyConfiguration"],"mappings":"AAGO,SAASA,EAAiBC,EAAQC,EAAWC,EAAU,CAAA,EAAI,CAChE,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtCJ,EAAO,KAAKC,EAAWC,EAAS,CAACG,EAAW,CAAA,IAAO,CACjD,GAAIA,GAAU,MAAO,CACnB,MAAMC,EAAQ,IAAI,MAAMD,EAAS,KAAK,EACtCC,EAAM,KAAOD,EAAS,MAAQ,KAC9BC,EAAM,iBAAmBD,EAAS,kBAAoB,CAAA,EACtDC,EAAM,gBAAkBD,EAAS,iBAAmB,KACpDD,EAAOE,CAAK,EACZ,MACF,CACAH,EAAQE,CAAQ,CAClB,CAAC,CACH,CAAC,CACH,CAEY,MAACE,EAAoBP,GAAWD,EAAiBC,EAAQ,iBAAiB,EACzEQ,EAAuB,CAACR,EAAQS,IAAaV,EAAiBC,EAAQ,8BAA+B,CAAE,SAAAS,CAAQ,CAAE,EACjHC,EAAsB,CAACV,EAAQE,IAAYH,EAAiBC,EAAQ,kCAAmCE,CAAO,EAC9GS,EAA+B,CAACX,EAAQE,IAAYH,EAAiBC,EAAQ,8BAA+BE,CAAO,EACnHU,EAAsB,CAACZ,EAAQE,IAAYH,EAAiBC,EAAQ,kCAAmCE,CAAO,EAC9GW,EAAsB,CAACb,EAAQE,IAAYH,EAAiBC,EAAQ,kCAAmCE,CAAO,EAC9GY,EAAsB,CAACd,EAAQe,IAAOhB,EAAiBC,EAAQ,kCAAmC,CAAE,GAAAe,CAAE,CAAE,EAExGC,EAAkBhB,GAAWD,EAAiBC,EAAQ,cAAc,EACpEiB,EAA2B,CAACjB,EAAQE,IAAYH,EAAiBC,EAAQ,4BAA6BE,CAAO,EAC7GgB,EAA4B,CAAClB,EAAQE,IAAYH,EAAiBC,EAAQ,qBAAsBE,CAAO"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -12,8 +12,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<!-- site-metadata:inject -->
<!-- analytics:inject -->
<script type="module" crossorigin src="/assets/index-_6Wi5B-Z.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DJhimuQc.css">
<script type="module" crossorigin src="/assets/index-B3PBxGLi.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-C935Fjdg.css">
</head>
<body>
<div id="root"></div>