garm/webapp/assets/_app/immutable/chunks/C89fcOde.js
Gabriel Adrian Samfira eec158b32c Add SPA UI for GARM
This change adds a single page application front-end to GARM. It uses
a generated REST client, built from the swagger definitions, the websocket
interface for live updates of entities and eager loading of everything
except runners, as users may have many runners and we don't want to load
hundreds of runners in memory.

Proper pagination should be implemented in the API, in future commits,
to avoid loading lots of elements for no reason.

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
2025-08-16 09:09:13 +00:00

1 line
11 KiB
JavaScript

import"./DsnmJJEf.js";import{i as dr}from"./B3Pzt0F_.js";import{p as or,E as sr,m as i,o as ir,s,f as le,j as d,r as o,k as t,g as r,n as c,u as m,t as f,x as Ge,z as nr,v as _,e as je,c as u,D as R,B as Be,b as $e,d as lr}from"./D8EpLgQ1.js";import{p as ur,i as E}from"./5WA7h8uK.js";import{r as b,b as ze}from"./CiE1LlKV.js";import{b as v,a as br}from"./C6k1Q4We.js";import{p as gr}from"./D4Caz1gY.js";import{M as cr}from"./qB7B8uiS.js";import{J as mr}from"./DZblzgqm.js";var vr=le('<div class="rounded-md bg-red-50 dark:bg-red-900 p-4"><p class="text-sm font-medium text-red-800 dark:text-red-200"> </p></div>'),pr=le('<div class="flex items-center"><div class="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div> Updating...</div>'),fr=le('<div class="max-w-6xl w-full max-h-[90vh] overflow-y-auto"><div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700"><h2 class="text-xl font-semibold text-gray-900 dark:text-white"> </h2></div> <form class="p-6 space-y-6"><!> <div class="bg-gray-50 dark:bg-gray-900 p-4 rounded-lg"><h3 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Scale Set Information</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm"><div class="flex"><span class="text-gray-500 dark:text-gray-400 w-20 flex-shrink-0">Provider:</span> <span class="text-gray-900 dark:text-white"> </span></div> <div class="flex"><span class="text-gray-500 dark:text-gray-400 w-16 flex-shrink-0">Entity:</span> <span class="text-gray-900 dark:text-white"><!></span></div></div></div> <div><label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Name</label> <input id="name" type="text" placeholder="e.g., my-scale-set" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div class="space-y-4"><h3 class="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">Image & OS Configuration</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label for="image" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Image</label> <input id="image" type="text" placeholder="e.g., ubuntu:22.04" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div><label for="flavor" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Flavor</label> <input id="flavor" type="text" placeholder="e.g., default" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div><label for="osType" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">OS Type</label> <select id="osType" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"><option>Linux</option><option>Windows</option></select></div> <div><label for="osArch" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Architecture</label> <select id="osArch" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"><option>AMD64</option><option>ARM64</option></select></div></div></div> <div class="space-y-4"><h3 class="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">Runner Limits & Timing</h3> <div class="grid grid-cols-1 md:grid-cols-3 gap-4"><div><label for="minIdleRunners" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Min Idle Runners</label> <input id="minIdleRunners" type="number" min="0" placeholder="0" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div><label for="maxRunners" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Max Runners</label> <input id="maxRunners" type="number" min="1" placeholder="10" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div><label for="bootstrapTimeout" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Bootstrap Timeout (min)</label> <input id="bootstrapTimeout" type="number" min="1" placeholder="20" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div></div></div> <div class="space-y-4"><h3 class="text-lg font-medium text-gray-900 dark:text-white border-b border-gray-200 dark:border-gray-700 pb-2">Advanced Settings</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label for="runnerPrefix" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Runner Prefix</label> <input id="runnerPrefix" type="text" placeholder="garm" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div> <div><label for="githubRunnerGroup" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">GitHub Runner Group (optional)</label> <input id="githubRunnerGroup" type="text" placeholder="Default group" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"/></div></div> <div><fieldset><legend class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Extra Specs (JSON)</legend> <!></fieldset></div> <div class="flex items-center"><input id="enabled" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 dark:border-gray-600 rounded"/> <label for="enabled" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">Scale set enabled</label></div></div> <div class="flex justify-end space-x-3 pt-6 border-t border-gray-200 dark:border-gray-700"><button type="button" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 cursor-pointer">Cancel</button> <button type="submit" class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"><!></button></div></form></div>');function Or(Ce,ue){or(ue,!1);let e=ur(ue,"scaleSet",8);const $=sr();let O=i(!1),J=i(""),T=i(e().name||""),I=i(e().image||""),M=i(e().flavor||""),N=i(e().max_runners),A=i(e().min_idle_runners),P=i(e().runner_bootstrap_timeout),U=i(e().runner_prefix||""),h=i(e().os_type||"linux"),k=i(e().os_arch||"amd64"),D=i(e()["github-runner-group"]||""),G=i(e().enabled),g=i("{}");ir(()=>{if(e().extra_specs)try{if(typeof e().extra_specs=="object")s(g,JSON.stringify(e().extra_specs,null,2));else{const l=JSON.parse(e().extra_specs);s(g,JSON.stringify(l,null,2))}}catch{s(g,e().extra_specs||"{}")}});async function Fe(){try{s(O,!0),s(J,"");let l={};if(r(g).trim())try{l=JSON.parse(r(g))}catch{throw new Error("Invalid JSON in extra specs")}const w={name:r(T)!==e().name?r(T):void 0,image:r(I)!==e().image?r(I):void 0,flavor:r(M)!==e().flavor?r(M):void 0,max_runners:r(N)!==e().max_runners?r(N):void 0,min_idle_runners:r(A)!==e().min_idle_runners?r(A):void 0,runner_bootstrap_timeout:r(P)!==e().runner_bootstrap_timeout?r(P):void 0,runner_prefix:r(U)!==e().runner_prefix?r(U):void 0,os_type:r(h)!==e().os_type?r(h):void 0,os_arch:r(k)!==e().os_arch?r(k):void 0,"github-runner-group":r(D)!==e()["github-runner-group"]&&r(D)||void 0,enabled:r(G)!==e().enabled?r(G):void 0,extra_specs:r(g).trim()!==JSON.stringify(e().extra_specs||{},null,2).trim()?l:void 0};Object.keys(w).forEach(p=>{w[p]===void 0&&delete w[p]}),$("submit",w)}catch(l){s(J,l instanceof Error?l.message:"Failed to update scale set")}finally{s(O,!1)}}dr(),cr(Ce,{$$events:{close:()=>$("close")},children:(l,w)=>{var p=fr(),z=d(p),be=d(z),Le=d(be);o(be),o(z);var C=t(z,2),ge=d(C);{var He=a=>{var n=vr(),j=d(n),ne=d(j,!0);o(j),o(n),f(()=>_(ne,r(J))),u(a,n)};E(ge,a=>{r(J)&&a(He)})}var F=t(ge,2),ce=t(d(F),2),L=d(ce),me=t(d(L),2),We=d(me,!0);o(me),o(L);var ve=t(L,2),pe=t(d(ve),2),qe=d(pe);{var Ke=a=>{var n=R();f(()=>_(n,`Repository: ${c(e()),m(()=>e().repo_name)??""}`)),u(a,n)},Qe=a=>{var n=Be(),j=$e(n);{var ne=x=>{var S=R();f(()=>_(S,`Organization: ${c(e()),m(()=>e().org_name)??""}`)),u(x,S)},er=x=>{var S=Be(),rr=$e(S);{var ar=y=>{var B=R();f(()=>_(B,`Enterprise: ${c(e()),m(()=>e().enterprise_name)??""}`)),u(y,B)},tr=y=>{var B=R("Unknown Entity");u(y,B)};E(rr,y=>{c(e()),m(()=>e().enterprise_name)?y(ar):y(tr,!1)},!0)}u(x,S)};E(j,x=>{c(e()),m(()=>e().org_name)?x(ne):x(er,!1)},!0)}u(a,n)};E(qe,a=>{c(e()),m(()=>e().repo_name)?a(Ke):a(Qe,!1)})}o(pe),o(ve),o(ce),o(F);var H=t(F,2),fe=t(d(H),2);b(fe),o(H);var W=t(H,2),xe=t(d(W),2),q=d(xe),ye=t(d(q),2);b(ye),o(q);var K=t(q,2),_e=t(d(K),2);b(_e),o(K);var Q=t(K,2),V=t(d(Q),2);f(()=>{r(h),Ge(()=>{})});var X=d(V);X.value=X.__value="linux";var he=t(X);he.value=he.__value="windows",o(V),o(Q);var ke=t(Q,2),Y=t(d(ke),2);f(()=>{r(k),Ge(()=>{})});var Z=d(Y);Z.value=Z.__value="amd64";var we=t(Z);we.value=we.__value="arm64",o(Y),o(ke),o(xe),o(W);var ee=t(W,2),Se=t(d(ee),2),re=d(Se),Re=t(d(re),2);b(Re),o(re);var ae=t(re,2),Ee=t(d(ae),2);b(Ee),o(ae);var Oe=t(ae,2),Je=t(d(Oe),2);b(Je),o(Oe),o(Se),o(ee);var te=t(ee,2),de=t(d(te),2),oe=d(de),Te=t(d(oe),2);b(Te),o(oe);var Ie=t(oe,2),Me=t(d(Ie),2);b(Me),o(Ie),o(de);var se=t(de,2),Ne=d(se),Ve=t(d(Ne),2);mr(Ve,{rows:4,placeholder:"{}",get value(){return r(g)},set value(a){s(g,a)},$$legacy:!0}),o(Ne),o(se);var Ae=t(se,2),Pe=d(Ae);b(Pe),nr(2),o(Ae),o(te);var Ue=t(te,2),De=d(Ue),ie=t(De,2),Xe=d(ie);{var Ye=a=>{var n=pr();u(a,n)},Ze=a=>{var n=R("Update Scale Set");u(a,n)};E(Xe,a=>{r(O)?a(Ye):a(Ze,!1)})}o(ie),o(Ue),o(C),o(p),f(()=>{_(Le,`Update Scale Set ${c(e()),m(()=>e().name)??""}`),_(We,(c(e()),m(()=>e().provider_name))),ie.disabled=r(O)}),v(fe,()=>r(T),a=>s(T,a)),v(ye,()=>r(I),a=>s(I,a)),v(_e,()=>r(M),a=>s(M,a)),ze(V,()=>r(h),a=>s(h,a)),ze(Y,()=>r(k),a=>s(k,a)),v(Re,()=>r(A),a=>s(A,a)),v(Ee,()=>r(N),a=>s(N,a)),v(Je,()=>r(P),a=>s(P,a)),v(Te,()=>r(U),a=>s(U,a)),v(Me,()=>r(D),a=>s(D,a)),br(Pe,()=>r(G),a=>s(G,a)),je("click",De,()=>$("close")),je("submit",C,gr(Fe)),u(l,p)},$$slots:{default:!0}}),lr()}export{Or as U};