Merge pull request #485 from gabriel-samfira/ui-fixes

Slightly better error handling
This commit is contained in:
Gabriel 2025-08-17 10:42:33 +03:00 committed by GitHub
commit 102c430e1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
95 changed files with 296 additions and 195 deletions

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import{s as e}from"./CTf6mQoE.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p};
import{s as e}from"./DXCC0cSN.js";const r=()=>{const s=e;return{page:{subscribe:s.page.subscribe},navigating:{subscribe:s.navigating.subscribe},updated:s.updated}},b={subscribe(s){return r().page.subscribe(s)}};export{b as p};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as U}from"./B3Pzt0F_.js";import{f as I,j as t,k as p,r as a,t as P,v as b,c as u,z as N,D as A,p as W,u as z,n as H,d as X}from"./D8EpLgQ1.js";import{p as s,i as T}from"./5WA7h8uK.js";import{s as Y,h as Z,B as F,c as $}from"./CiE1LlKV.js";import{b as ee}from"./CoIRRsD9.js";import{D as te,G as ae,a as se}from"./C9DJVOi1.js";import{E as ne}from"./B7ITzBt8.js";import{S as B}from"./BE4wujub.js";var le=I('<div class="flex-shrink-0"><!></div>'),ie=I('<div class="mt-4 sm:mt-0 flex space-x-3"><!> <!></div>'),re=I('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="sm:flex sm:items-center sm:justify-between"><div class="flex items-center space-x-3"><!> <div><h1> </h1> <p class="text-sm text-gray-500 dark:text-gray-400"> </p></div></div> <!></div></div></div>');function ye(L,e){let n=s(e,"title",8),S=s(e,"subtitle",8),_=s(e,"forgeIcon",8,""),f=s(e,"onEdit",8,null),h=s(e,"onDelete",8,null),k=s(e,"editLabel",8,"Edit"),j=s(e,"deleteLabel",8,"Delete"),g=s(e,"titleClass",8,"");var c=re(),v=t(c),m=t(v),y=t(m),C=t(y);{var E=i=>{var r=le(),w=t(r);Z(w,_),a(r),u(i,r)};T(C,i=>{_()&&i(E)})}var l=p(C,2),D=t(l),G=t(D,!0);a(D);var M=p(D,2),V=t(M,!0);a(M),a(l),a(y);var R=p(y,2);{var q=i=>{var r=ie(),w=t(r);{var J=o=>{F(o,{variant:"secondary",size:"md",icon:"<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z'/>",$$events:{click(...d){f()?.apply(this,d)}},children:(d,Q)=>{N();var x=A();P(()=>b(x,k())),u(d,x)},$$slots:{default:!0}})};T(w,o=>{f()&&o(J)})}var K=p(w,2);{var O=o=>{F(o,{variant:"danger",size:"md",icon:"<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16'/>",$$events:{click(...d){h()?.apply(this,d)}},children:(d,Q)=>{N();var x=A();P(()=>b(x,j())),u(d,x)},$$slots:{default:!0}})};T(K,o=>{h()&&o(O)})}a(r),u(i,r)};T(R,i=>{(f()||h())&&i(q)})}a(m),a(v),a(c),P(()=>{Y(D,1,`text-2xl font-bold text-gray-900 dark:text-white ${g()??""}`),b(G,n()),b(V,S())}),u(L,c)}var oe=I('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="flex items-center justify-between mb-4"><h2 class="text-lg font-medium text-gray-900 dark:text-white"> </h2> <a class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300">View all instances</a></div> <!></div></div>');function xe(L,e){W(e,!1);let n=s(e,"instances",8),S=s(e,"entityType",8),_=s(e,"onDeleteInstance",8);const f=[{key:"name",title:"Name",cellComponent:ne,cellProps:{entityType:"instance",nameField:"name"}},{key:"status",title:"Status",cellComponent:B,cellProps:{statusType:"instance",statusField:"status"}},{key:"runner_status",title:"Runner Status",cellComponent:B,cellProps:{statusType:"instance",statusField:"runner_status"}},{key:"created",title:"Created",cellComponent:ae,cellProps:{field:"created_at",type:"date"}},{key:"actions",title:"Actions",align:"right",cellComponent:se,cellProps:{actions:[{type:"delete",label:"Delete",title:"Delete instance",ariaLabel:"Delete instance",action:"delete"}]}}],h={entityType:"instance",primaryText:{field:"name",isClickable:!0,href:"/instances/{name}"},secondaryText:{field:"provider_id"},badges:[{type:"status",field:"status"}],actions:[{type:"delete",handler:l=>k(l)}]};function k(l){_()(l)}function j(l){k(l.detail.item)}U();var g=oe(),c=t(g),v=t(c),m=t(v),y=t(m);a(m);var C=p(m,2);a(v);var E=p(v,2);te(E,{get columns(){return f},get data(){return n()},loading:!1,error:"",searchTerm:"",showSearch:!1,showPagination:!1,currentPage:1,get perPage(){return H(n()),z(()=>n().length)},totalPages:1,get totalItems(){return H(n()),z(()=>n().length)},itemName:"instances",emptyTitle:"No instances running",get emptyMessage(){return`No instances running for this ${S()??""}.`},emptyIconType:"cog",get mobileCardConfig(){return h},$$events:{delete:j}}),a(c),a(g),P(()=>{b(y,`Instances (${H(n()),z(()=>n().length)??""})`),$(C,"href",`${ee}/instances`)}),u(L,g),X()}export{ye as D,xe as I};
import"./DsnmJJEf.js";import{i as U}from"./B3Pzt0F_.js";import{f as I,j as t,k as p,r as a,t as P,v as b,c as u,z as N,D as A,p as W,u as z,n as H,d as X}from"./D8EpLgQ1.js";import{p as s,i as T}from"./5WA7h8uK.js";import{s as Y,h as Z,B as F,c as $}from"./CiE1LlKV.js";import{b as ee}from"./CRhkqW2i.js";import{D as te,G as ae,a as se}from"./BrNfsPe8.js";import{E as ne}from"./D4PaGKsV.js";import{S as B}from"./MCv1Wq2q.js";var le=I('<div class="flex-shrink-0"><!></div>'),ie=I('<div class="mt-4 sm:mt-0 flex space-x-3"><!> <!></div>'),re=I('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="sm:flex sm:items-center sm:justify-between"><div class="flex items-center space-x-3"><!> <div><h1> </h1> <p class="text-sm text-gray-500 dark:text-gray-400"> </p></div></div> <!></div></div></div>');function ye(L,e){let n=s(e,"title",8),S=s(e,"subtitle",8),_=s(e,"forgeIcon",8,""),f=s(e,"onEdit",8,null),h=s(e,"onDelete",8,null),k=s(e,"editLabel",8,"Edit"),j=s(e,"deleteLabel",8,"Delete"),g=s(e,"titleClass",8,"");var c=re(),v=t(c),m=t(v),y=t(m),C=t(y);{var E=i=>{var r=le(),w=t(r);Z(w,_),a(r),u(i,r)};T(C,i=>{_()&&i(E)})}var l=p(C,2),D=t(l),G=t(D,!0);a(D);var M=p(D,2),V=t(M,!0);a(M),a(l),a(y);var R=p(y,2);{var q=i=>{var r=ie(),w=t(r);{var J=o=>{F(o,{variant:"secondary",size:"md",icon:"<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z'/>",$$events:{click(...d){f()?.apply(this,d)}},children:(d,Q)=>{N();var x=A();P(()=>b(x,k())),u(d,x)},$$slots:{default:!0}})};T(w,o=>{f()&&o(J)})}var K=p(w,2);{var O=o=>{F(o,{variant:"danger",size:"md",icon:"<path stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16'/>",$$events:{click(...d){h()?.apply(this,d)}},children:(d,Q)=>{N();var x=A();P(()=>b(x,j())),u(d,x)},$$slots:{default:!0}})};T(K,o=>{h()&&o(O)})}a(r),u(i,r)};T(R,i=>{(f()||h())&&i(q)})}a(m),a(v),a(c),P(()=>{Y(D,1,`text-2xl font-bold text-gray-900 dark:text-white ${g()??""}`),b(G,n()),b(V,S())}),u(L,c)}var oe=I('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="flex items-center justify-between mb-4"><h2 class="text-lg font-medium text-gray-900 dark:text-white"> </h2> <a class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300">View all instances</a></div> <!></div></div>');function xe(L,e){W(e,!1);let n=s(e,"instances",8),S=s(e,"entityType",8),_=s(e,"onDeleteInstance",8);const f=[{key:"name",title:"Name",cellComponent:ne,cellProps:{entityType:"instance",nameField:"name"}},{key:"status",title:"Status",cellComponent:B,cellProps:{statusType:"instance",statusField:"status"}},{key:"runner_status",title:"Runner Status",cellComponent:B,cellProps:{statusType:"instance",statusField:"runner_status"}},{key:"created",title:"Created",cellComponent:ae,cellProps:{field:"created_at",type:"date"}},{key:"actions",title:"Actions",align:"right",cellComponent:se,cellProps:{actions:[{type:"delete",label:"Delete",title:"Delete instance",ariaLabel:"Delete instance",action:"delete"}]}}],h={entityType:"instance",primaryText:{field:"name",isClickable:!0,href:"/instances/{name}"},secondaryText:{field:"provider_id"},badges:[{type:"status",field:"status"}],actions:[{type:"delete",handler:l=>k(l)}]};function k(l){_()(l)}function j(l){k(l.detail.item)}U();var g=oe(),c=t(g),v=t(c),m=t(v),y=t(m);a(m);var C=p(m,2);a(v);var E=p(v,2);te(E,{get columns(){return f},get data(){return n()},loading:!1,error:"",searchTerm:"",showSearch:!1,showPagination:!1,currentPage:1,get perPage(){return H(n()),z(()=>n().length)},totalPages:1,get totalItems(){return H(n()),z(()=>n().length)},itemName:"instances",emptyTitle:"No instances running",get emptyMessage(){return`No instances running for this ${S()??""}.`},emptyIconType:"cog",get mobileCardConfig(){return h},$$events:{delete:j}}),a(c),a(g),P(()=>{b(y,`Instances (${H(n()),z(()=>n().length)??""})`),$(C,"href",`${ee}/instances`)}),u(L,g),X()}export{ye as D,xe as I};

View file

@ -0,0 +1 @@
function n(e){let s="An unexpected error occurred";if(e&&typeof e=="object"){if("response"in e&&e.response&&typeof e.response=="object"){const a=e.response;if("data"in a&&a.data&&typeof a.data=="object"){const t=a.data,r=t.error&&t.error.trim()?t.error:"",i=t.details&&t.details.trim()?t.details:"";if(r&&i)return`${r}. ${i}`;if(r)return r;if(i)return i}if("status"in a){const t=a.status;switch(t){case 400:s="Bad request - please check your input";break;case 401:s="Unauthorized - please log in again";break;case 403:s="Access denied - insufficient permissions";break;case 404:s="Resource not found";break;case 409:s="Conflict - resource already exists or is in use";break;case 422:s="Validation failed - please check your input";break;case 500:s="Internal server error - please try again later";break;default:s=`Request failed with status ${t}`}}}else if(e instanceof Error&&e.message&&!e.message.includes("status code"))return e.message}return s}export{n as e};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
import"./DsnmJJEf.js";import{i as ae}from"./B3Pzt0F_.js";import{p as se,E as re,l as M,n as ie,s as r,g as t,m as k,a as le,f as p,j as v,k as $,r as f,c as l,d as oe,B as T,b as E,z as V,D as q,t as F,v as N,u as ne}from"./D8EpLgQ1.js";import{p as R,i as m}from"./5WA7h8uK.js";import{g as u,B as G}from"./CiE1LlKV.js";import{t as y}from"./BEkVdVE1.js";import{e as de}from"./BZiHL9L3.js";var ce=p('<div class="flex items-center"><div class="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600 mr-2"></div> <span class="text-sm text-gray-500 dark:text-gray-400">Checking...</span></div>'),ve=p('<div class="ml-4 text-xs text-gray-500 dark:text-gray-400"> </div>'),fe=p('<div class="flex items-center"><svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path></svg> <span class="text-sm text-green-700 dark:text-green-300">Webhook installed</span></div> <!>',1),ue=p('<div class="flex items-center"><svg class="w-4 h-4 text-gray-400 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm0-2a6 6 0 100-12 6 6 0 000 12zm0-10a1 1 0 011 1v3a1 1 0 01-2 0V7a1 1 0 011-1z" clip-rule="evenodd"></path></svg> <span class="text-sm text-gray-500 dark:text-gray-400">No webhook installed</span></div>'),he=p('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="flex items-center justify-between"><div><h3 class="text-lg font-medium text-gray-900 dark:text-white">Webhook Status</h3> <div class="mt-1 flex items-center"><!></div></div> <div class="flex space-x-2"><!></div></div></div></div>');function _e(H,g){se(g,!1);const x=k();let h=R(g,"entityType",8),s=R(g,"entityId",8),j=R(g,"entityName",8),i=k(null),o=k(!1),b=k(!0);const A=re();async function _(){if(s())try{r(b,!0),h()==="repository"?r(i,await u.getRepositoryWebhookInfo(s())):r(i,await u.getOrganizationWebhookInfo(s()))}catch(e){e&&typeof e=="object"&&"response"in e&&e.response?.status===404?r(i,null):(console.warn("Failed to check webhook status:",e),r(i,null))}finally{r(b,!1)}}async function J(){if(s())try{r(o,!0),h()==="repository"?await u.installRepositoryWebhook(s()):await u.installOrganizationWebhook(s()),y.success("Webhook Installed",`Webhook for ${h()} ${j()} has been installed successfully.`),await _(),A("webhookStatusChanged",{installed:!0})}catch(e){y.error("Webhook Installation Failed",e instanceof Error?e.message:"Failed to install webhook.")}finally{r(o,!1)}}async function K(){if(s())try{r(o,!0),h()==="repository"?await u.uninstallRepositoryWebhook(s()):await u.uninstallOrganizationWebhook(s()),y.success("Webhook Uninstalled",`Webhook for ${h()} ${j()} has been uninstalled successfully.`),await _(),A("webhookStatusChanged",{installed:!1})}catch(e){y.error("Webhook Uninstall Failed",de(e))}finally{r(o,!1)}}M(()=>ie(s()),()=>{s()&&_()}),M(()=>t(i),()=>{r(x,t(i)&&t(i).active)}),le(),ae();var w=he(),O=v(w),P=v(O),W=v(P),D=$(v(W),2),Q=v(D);{var X=e=>{var d=ce();l(e,d)},Y=e=>{var d=T(),z=E(d);{var I=a=>{var n=fe(),B=$(E(n),2);{var c=C=>{var U=ve(),te=v(U);f(U),F(()=>N(te,`URL: ${t(i),ne(()=>t(i).url||"N/A")??""}`)),l(C,U)};m(B,C=>{t(i)&&C(c)})}l(a,n)},S=a=>{var n=ue();l(a,n)};m(z,a=>{t(x)?a(I):a(S,!1)},!0)}l(e,d)};m(Q,e=>{t(b)?e(X):e(Y,!1)})}f(D),f(W);var L=$(W,2),Z=v(L);{var ee=e=>{var d=T(),z=E(d);{var I=a=>{G(a,{variant:"danger",size:"sm",get disabled(){return t(o)},$$events:{click:K},children:(n,B)=>{V();var c=q();F(()=>N(c,t(o)?"Uninstalling...":"Uninstall")),l(n,c)},$$slots:{default:!0}})},S=a=>{G(a,{variant:"primary",size:"sm",get disabled(){return t(o)},$$events:{click:J},children:(n,B)=>{V();var c=q();F(()=>N(c,t(o)?"Installing...":"Install Webhook")),l(n,c)},$$slots:{default:!0}})};m(z,a=>{t(x)?a(I):a(S,!1)})}l(e,d)};m(Z,e=>{t(b)||e(ee)})}f(L),f(P),f(O),f(w),l(H,w),oe()}export{_e as W};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as b}from"./B3Pzt0F_.js";import{p as k,f as E,t as C,u as i,n as t,v as n,c as j,d as P,k as z,j as l,r as o}from"./D8EpLgQ1.js";import{c as N}from"./CiE1LlKV.js";import{p as f}from"./5WA7h8uK.js";import"./CoIRRsD9.js";import{j as x,e as c,i as u}from"./BGVHQGl-.js";var T=E('<div class="flex flex-col"><a class="text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300"> </a> <span class="text-xs text-gray-500 dark:text-gray-400 capitalize"> </span></div>');function G(d,r){k(r,!1);let e=f(r,"item",8),m=f(r,"eagerCache",8,null);b();var s=T(),a=l(s),v=l(a,!0);o(a);var p=z(a,2),g=l(p,!0);o(p),o(s),C((h,y,_)=>{N(a,"href",h),n(v,y),n(g,_)},[()=>(t(x),t(e()),i(()=>x(e()))),()=>(t(c),t(e()),t(m()),i(()=>c(e(),m()))),()=>(t(u),t(e()),i(()=>u(e())))]),j(d,s),P()}export{G as P};
import"./DsnmJJEf.js";import{i as b}from"./B3Pzt0F_.js";import{p as k,f as E,t as C,u as i,n as t,v as n,c as j,d as P,k as z,j as l,r as o}from"./D8EpLgQ1.js";import{c as N}from"./CiE1LlKV.js";import{p as f}from"./5WA7h8uK.js";import"./CRhkqW2i.js";import{j as x,e as c,i as u}from"./BGVHQGl-.js";var T=E('<div class="flex flex-col"><a class="text-sm font-medium text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300"> </a> <span class="text-xs text-gray-500 dark:text-gray-400 capitalize"> </span></div>');function G(d,r){k(r,!1);let e=f(r,"item",8),m=f(r,"eagerCache",8,null);b();var s=T(),a=l(s),v=l(a,!0);o(a);var p=z(a,2),g=l(p,!0);o(p),o(s),C((h,y,_)=>{N(a,"href",h),n(v,y),n(g,_)},[()=>(t(x),t(e()),i(()=>x(e()))),()=>(t(c),t(e()),t(m()),i(()=>c(e(),m()))),()=>(t(u),t(e()),i(()=>u(e())))]),j(d,s),P()}export{G as P};

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

View file

@ -0,0 +1 @@
const s=globalThis.__sveltekit_xtz33p?.base??"/ui",t=globalThis.__sveltekit_xtz33p?.assets??s;export{t as a,s as b};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
const s=globalThis.__sveltekit_13hoftk?.base??"/ui",t=globalThis.__sveltekit_13hoftk?.assets??s;export{t as a,s as b};

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as j}from"./B3Pzt0F_.js";import{p as R,l as w,a as q,f as g,t as v,c as k,d as A,k as B,j as u,s as _,m as y,r as m,n as f,u as b,g as d,v as h}from"./D8EpLgQ1.js";import{p as o,i as D}from"./5WA7h8uK.js";import{c as U,s as F}from"./CiE1LlKV.js";import{b as r}from"./CoIRRsD9.js";var G=g('<div class="text-sm text-gray-500 dark:text-gray-400 truncate"> </div>'),H=g('<div class="w-full min-w-0 text-sm font-medium"><a> </a> <!></div>');function V(x,n){R(n,!1);const i=y(),p=y();let e=o(n,"item",8),s=o(n,"entityType",8,"repository"),$=o(n,"showOwner",8,!1),E=o(n,"showId",8,!1),I=o(n,"fontMono",8,!1);function z(){if(!e())return"Unknown";switch(s()){case"repository":return $()?`${e().owner||"Unknown"}/${e().name||"Unknown"}`:e().name||"Unknown";case"organization":case"enterprise":return e().name||"Unknown";case"pool":return E()?e().id||"Unknown":e().name||"Unknown";case"scaleset":return e().name||"Unknown";case"instance":return e().name||"Unknown";default:return e().name||e().id||"Unknown"}}function C(){if(!e())return"#";let t;switch(s()){case"instance":t=e().name;break;default:t=e().id||e().name;break}if(!t)return"#";switch(s()){case"repository":return`${r}/repositories/${t}`;case"organization":return`${r}/organizations/${t}`;case"enterprise":return`${r}/enterprises/${t}`;case"pool":return`${r}/pools/${t}`;case"scaleset":return`${r}/scalesets/${t}`;case"instance":return`${r}/instances/${encodeURIComponent(t)}`;default:return"#"}}w(()=>{},()=>{_(i,z())}),w(()=>{},()=>{_(p,C())}),q(),j();var c=H(),a=u(c),M=u(a,!0);m(a);var N=B(a,2);{var O=t=>{var l=G(),T=u(l,!0);m(l),v(()=>h(T,(f(e()),b(()=>e().provider_id)))),k(t,l)};D(N,t=>{f(s()),f(e()),b(()=>s()==="instance"&&e()?.provider_id)&&t(O)})}m(c),v(()=>{U(a,"href",d(p)),F(a,1,`block w-full truncate text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 ${I()?"font-mono":""}`),U(a,"title",d(i)),h(M,d(i))}),k(x,c),A()}export{V as E};
import"./DsnmJJEf.js";import{i as j}from"./B3Pzt0F_.js";import{p as R,l as w,a as q,f as g,t as v,c as k,d as A,k as B,j as u,s as _,m as y,r as m,n as f,u as b,g as d,v as h}from"./D8EpLgQ1.js";import{p as o,i as D}from"./5WA7h8uK.js";import{c as U,s as F}from"./CiE1LlKV.js";import{b as r}from"./CRhkqW2i.js";var G=g('<div class="text-sm text-gray-500 dark:text-gray-400 truncate"> </div>'),H=g('<div class="w-full min-w-0 text-sm font-medium"><a> </a> <!></div>');function V(x,n){R(n,!1);const i=y(),p=y();let e=o(n,"item",8),s=o(n,"entityType",8,"repository"),$=o(n,"showOwner",8,!1),E=o(n,"showId",8,!1),I=o(n,"fontMono",8,!1);function z(){if(!e())return"Unknown";switch(s()){case"repository":return $()?`${e().owner||"Unknown"}/${e().name||"Unknown"}`:e().name||"Unknown";case"organization":case"enterprise":return e().name||"Unknown";case"pool":return E()?e().id||"Unknown":e().name||"Unknown";case"scaleset":return e().name||"Unknown";case"instance":return e().name||"Unknown";default:return e().name||e().id||"Unknown"}}function C(){if(!e())return"#";let t;switch(s()){case"instance":t=e().name;break;default:t=e().id||e().name;break}if(!t)return"#";switch(s()){case"repository":return`${r}/repositories/${t}`;case"organization":return`${r}/organizations/${t}`;case"enterprise":return`${r}/enterprises/${t}`;case"pool":return`${r}/pools/${t}`;case"scaleset":return`${r}/scalesets/${t}`;case"instance":return`${r}/instances/${encodeURIComponent(t)}`;default:return"#"}}w(()=>{},()=>{_(i,z())}),w(()=>{},()=>{_(p,C())}),q(),j();var c=H(),a=u(c),M=u(a,!0);m(a);var N=B(a,2);{var O=t=>{var l=G(),T=u(l,!0);m(l),v(()=>h(T,(f(e()),b(()=>e().provider_id)))),k(t,l)};D(N,t=>{f(s()),f(e()),b(()=>s()==="instance"&&e()?.provider_id)&&t(O)})}m(c),v(()=>{U(a,"href",d(p)),F(a,1,`block w-full truncate text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 ${I()?"font-mono":""}`),U(a,"title",d(i)),h(M,d(i))}),k(x,c),A()}export{V as E};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
import"./DsnmJJEf.js";import{i as ae}from"./B3Pzt0F_.js";import{p as se,E as re,l as P,n as ie,s as r,g as t,m as k,a as le,f as p,j as v,k as U,r as f,c as l,d as oe,B as T,b as $,z as V,D as q,t as E,v as N,u as ne}from"./D8EpLgQ1.js";import{p as R,i as m}from"./5WA7h8uK.js";import{g as u,B as G}from"./CiE1LlKV.js";import{t as y}from"./BEkVdVE1.js";var de=p('<div class="flex items-center"><div class="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600 mr-2"></div> <span class="text-sm text-gray-500 dark:text-gray-400">Checking...</span></div>'),ce=p('<div class="ml-4 text-xs text-gray-500 dark:text-gray-400"> </div>'),ve=p('<div class="flex items-center"><svg class="w-4 h-4 text-green-500 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path></svg> <span class="text-sm text-green-700 dark:text-green-300">Webhook installed</span></div> <!>',1),fe=p('<div class="flex items-center"><svg class="w-4 h-4 text-gray-400 mr-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm0-2a6 6 0 100-12 6 6 0 000 12zm0-10a1 1 0 011 1v3a1 1 0 01-2 0V7a1 1 0 011-1z" clip-rule="evenodd"></path></svg> <span class="text-sm text-gray-500 dark:text-gray-400">No webhook installed</span></div>'),ue=p('<div class="bg-white dark:bg-gray-800 shadow rounded-lg"><div class="px-4 py-5 sm:p-6"><div class="flex items-center justify-between"><div><h3 class="text-lg font-medium text-gray-900 dark:text-white">Webhook Status</h3> <div class="mt-1 flex items-center"><!></div></div> <div class="flex space-x-2"><!></div></div></div></div>');function ye(H,g){se(g,!1);const x=k();let h=R(g,"entityType",8),s=R(g,"entityId",8),j=R(g,"entityName",8),i=k(null),o=k(!1),b=k(!0);const O=re();async function _(){if(s())try{r(b,!0),h()==="repository"?r(i,await u.getRepositoryWebhookInfo(s())):r(i,await u.getOrganizationWebhookInfo(s()))}catch(e){e&&typeof e=="object"&&"response"in e&&e.response?.status===404?r(i,null):(console.warn("Failed to check webhook status:",e),r(i,null))}finally{r(b,!1)}}async function J(){if(s())try{r(o,!0),h()==="repository"?await u.installRepositoryWebhook(s()):await u.installOrganizationWebhook(s()),y.success("Webhook Installed",`Webhook for ${h()} ${j()} has been installed successfully.`),await _(),O("webhookStatusChanged",{installed:!0})}catch(e){y.error("Webhook Installation Failed",e instanceof Error?e.message:"Failed to install webhook.")}finally{r(o,!1)}}async function K(){if(s())try{r(o,!0),h()==="repository"?await u.uninstallRepositoryWebhook(s()):await u.uninstallOrganizationWebhook(s()),y.success("Webhook Uninstalled",`Webhook for ${h()} ${j()} has been uninstalled successfully.`),await _(),O("webhookStatusChanged",{installed:!1})}catch(e){y.error("Webhook Uninstall Failed",e instanceof Error?e.message:"Failed to uninstall webhook.")}finally{r(o,!1)}}P(()=>ie(s()),()=>{s()&&_()}),P(()=>t(i),()=>{r(x,t(i)&&t(i).active)}),le(),ae();var w=ue(),A=v(w),D=v(A),W=v(D),L=U(v(W),2),Q=v(L);{var X=e=>{var d=de();l(e,d)},Y=e=>{var d=T(),z=$(d);{var I=a=>{var n=ve(),B=U($(n),2);{var c=C=>{var F=ce(),te=v(F);f(F),E(()=>N(te,`URL: ${t(i),ne(()=>t(i).url||"N/A")??""}`)),l(C,F)};m(B,C=>{t(i)&&C(c)})}l(a,n)},S=a=>{var n=fe();l(a,n)};m(z,a=>{t(x)?a(I):a(S,!1)},!0)}l(e,d)};m(Q,e=>{t(b)?e(X):e(Y,!1)})}f(L),f(W);var M=U(W,2),Z=v(M);{var ee=e=>{var d=T(),z=$(d);{var I=a=>{G(a,{variant:"danger",size:"sm",get disabled(){return t(o)},$$events:{click:K},children:(n,B)=>{V();var c=q();E(()=>N(c,t(o)?"Uninstalling...":"Uninstall")),l(n,c)},$$slots:{default:!0}})},S=a=>{G(a,{variant:"primary",size:"sm",get disabled(){return t(o)},$$events:{click:J},children:(n,B)=>{V();var c=q();E(()=>N(c,t(o)?"Installing...":"Install Webhook")),l(n,c)},$$slots:{default:!0}})};m(z,a=>{t(x)?a(I):a(S,!1)})}l(e,d)};m(Z,e=>{t(b)||e(ee)})}f(M),f(D),f(A),f(w),l(H,w),oe()}export{ye as W};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as v}from"./B3Pzt0F_.js";import{p as w,l as m,n as s,g as r,m as g,a as x,B as h,b as T,c as B,d as S,s as k,u}from"./D8EpLgQ1.js";import{k as A}from"./C9DJVOi1.js";import{p as d}from"./5WA7h8uK.js";import{k as b,B as C}from"./BGVHQGl-.js";import{f as E}from"./ow_oMtSd.js";function q(_,i){w(i,!1);const c=g(),n=g();let e=d(i,"item",8),l=d(i,"statusType",8,"entity"),a=d(i,"statusField",8,"status");m(()=>(s(e()),s(a())),()=>{k(c,e()?.[a()]||"unknown")}),m(()=>(s(e()),s(l()),r(c),s(a())),()=>{k(n,(()=>{if(!e())return{variant:"error",text:"Unknown"};switch(l()){case"entity":return b(e());case"instance":let t="secondary";switch(r(c).toLowerCase()){case"running":t="success";break;case"stopped":t="info";break;case"creating":case"pending_create":t="warning";break;case"deleting":case"pending_delete":case"pending_force_delete":t="warning";break;case"error":case"deleted":t="error";break;case"active":case"online":t="success";break;case"idle":t="info";break;case"pending":case"installing":t="warning";break;case"failed":case"terminated":case"offline":t="error";break;case"unknown":default:t="secondary";break}return{variant:t,text:E(r(c))};case"enabled":return{variant:e().enabled?"success":"error",text:e().enabled?"Enabled":"Disabled"};case"custom":const o=e()[a()]||"Unknown";if(a()==="auth-type"){const f=o==="pat"||!o?"pat":"app";return{variant:f==="pat"?"success":"info",text:f==="pat"?"PAT":"App"}}return{variant:"info",text:o};default:return b(e())}})())}),x(),v();var p=h(),y=T(p);A(y,()=>(s(e()),s(a()),u(()=>`${e()?.name||"item"}-${e()?.[a()]||"status"}-${e()?.updated_at||"time"}`)),t=>{C(t,{get variant(){return r(n),u(()=>r(n).variant)},get text(){return r(n),u(()=>r(n).text)}})}),B(_,p),S()}export{q as S};
import"./DsnmJJEf.js";import{i as v}from"./B3Pzt0F_.js";import{p as w,l as m,n as s,g as r,m as g,a as x,B as h,b as T,c as B,d as S,s as k,u}from"./D8EpLgQ1.js";import{k as A}from"./BrNfsPe8.js";import{p as d}from"./5WA7h8uK.js";import{k as b,B as C}from"./BGVHQGl-.js";import{f as E}from"./ow_oMtSd.js";function q(_,i){w(i,!1);const c=g(),n=g();let e=d(i,"item",8),l=d(i,"statusType",8,"entity"),a=d(i,"statusField",8,"status");m(()=>(s(e()),s(a())),()=>{k(c,e()?.[a()]||"unknown")}),m(()=>(s(e()),s(l()),r(c),s(a())),()=>{k(n,(()=>{if(!e())return{variant:"error",text:"Unknown"};switch(l()){case"entity":return b(e());case"instance":let t="secondary";switch(r(c).toLowerCase()){case"running":t="success";break;case"stopped":t="info";break;case"creating":case"pending_create":t="warning";break;case"deleting":case"pending_delete":case"pending_force_delete":t="warning";break;case"error":case"deleted":t="error";break;case"active":case"online":t="success";break;case"idle":t="info";break;case"pending":case"installing":t="warning";break;case"failed":case"terminated":case"offline":t="error";break;case"unknown":default:t="secondary";break}return{variant:t,text:E(r(c))};case"enabled":return{variant:e().enabled?"success":"error",text:e().enabled?"Enabled":"Disabled"};case"custom":const o=e()[a()]||"Unknown";if(a()==="auth-type"){const f=o==="pat"||!o?"pat":"app";return{variant:f==="pat"?"success":"info",text:f==="pat"?"PAT":"App"}}return{variant:"info",text:o};default:return b(e())}})())}),x(),v();var p=h(),y=T(p);A(y,()=>(s(e()),s(a()),u(()=>`${e()?.name||"item"}-${e()?.[a()]||"status"}-${e()?.updated_at||"time"}`)),t=>{C(t,{get variant(){return r(n),u(()=>r(n).variant)},get text(){return r(n),u(()=>r(n).text)}})}),B(_,p),S()}export{q as S};

View file

@ -1 +0,0 @@
import{l as o,a as r}from"../chunks/CTf6mQoE.js";export{o as load_css,r as start};

View file

@ -0,0 +1 @@
import{l as o,a as r}from"../chunks/DXCC0cSN.js";export{o as load_css,r as start};

View file

@ -1 +1 @@
import"../chunks/DsnmJJEf.js";import{i as u}from"../chunks/B3Pzt0F_.js";import{p as h,f as g,b as v,t as d,c as l,d as _,j as s,r as a,k as x,v as o}from"../chunks/D8EpLgQ1.js";import{s as k,p}from"../chunks/CTf6mQoE.js";const $={get error(){return p.error},get status(){return p.status}};k.updated.check;const i=$;var b=g("<h1> </h1> <p> </p>",1);function y(m,c){h(c,!1),u();var r=b(),t=v(r),n=s(t,!0);a(t);var e=x(t,2),f=s(e,!0);a(e),d(()=>{o(n,i.status),o(f,i.error?.message)}),l(m,r),_()}export{y as component};
import"../chunks/DsnmJJEf.js";import{i as u}from"../chunks/B3Pzt0F_.js";import{p as h,f as g,b as v,t as d,c as l,d as _,j as s,r as a,k as x,v as o}from"../chunks/D8EpLgQ1.js";import{s as k,p}from"../chunks/DXCC0cSN.js";const $={get error(){return p.error},get status(){return p.status}};k.updated.check;const i=$;var b=g("<h1> </h1> <p> </p>",1);function y(m,c){h(c,!1),u();var r=b(),t=v(r),n=s(t,!0);a(t);var e=x(t,2),f=s(e,!0);a(e),d(()=>{o(n,i.status),o(f,i.error?.message)}),l(m,r),_()}export{y as component};

View file

@ -0,0 +1 @@
import"../chunks/DsnmJJEf.js";import{i as X}from"../chunks/B3Pzt0F_.js";import{p as Y,o as Z,l as ee,a as ae,f as C,h as re,t as _,g as a,e as k,c as w,d as te,$ as se,k as d,D as de,m as f,j as r,s as i,r as t,z as B,v as D}from"../chunks/D8EpLgQ1.js";import{i as oe,s as ie,a as le}from"../chunks/5WA7h8uK.js";import{B as ne,r as q,c as I}from"../chunks/CiE1LlKV.js";import{b as T}from"../chunks/C6k1Q4We.js";import{p as ce}from"../chunks/D4Caz1gY.js";import{g as U}from"../chunks/DXCC0cSN.js";import{b as c}from"../chunks/CRhkqW2i.js";import{a as me,b as ue}from"../chunks/duD3WMbl.js";import{e as pe}from"../chunks/BZiHL9L3.js";var ve=C('<div class="rounded-md bg-red-50 dark:bg-red-900 p-4"><div class="flex"><div class="flex-shrink-0"><svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path></svg></div> <div class="ml-3"><p class="text-sm font-medium text-red-800 dark:text-red-200"> </p></div></div></div>'),fe=C('<div class="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900 py-12 px-4 sm:px-6 lg:px-8"><div class="max-w-md w-full space-y-8"><div><div class="mx-auto h-48 w-auto flex justify-center"><img alt="GARM" class="h-48 w-auto dark:hidden"/> <img alt="GARM" class="h-48 w-auto hidden dark:block"/></div> <h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900 dark:text-white">Sign in to GARM</h2> <p class="mt-2 text-center text-sm text-gray-600 dark:text-gray-400">GitHub Actions Runner Manager</p></div> <form class="mt-8 space-y-6"><div class="rounded-md shadow-sm -space-y-px"><div><label for="username" class="sr-only">Username</label> <input id="username" name="username" type="text" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-700 rounded-t-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm" placeholder="Username"/></div> <div><label for="password" class="sr-only">Password</label> <input id="password" name="password" type="password" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-700 rounded-b-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm" placeholder="Password"/></div></div> <!> <div><!></div></form></div></div>');function ze(H,K){Y(K,!1);const[W,F]=ie(),$=()=>le(me,"$authStore",W);let m=f(""),u=f(""),o=f(!1),l=f("");Z(()=>{J()});function J(){const e=localStorage.getItem("theme");let s=!1;e==="dark"?s=!0:e==="light"?s=!1:s=window.matchMedia("(prefers-color-scheme: dark)").matches,s?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")}async function M(){if(!a(m)||!a(u)){i(l,"Please enter both username and password");return}i(o,!0),i(l,"");try{await ue.login(a(m),a(u)),U(`${c}/`)}catch(e){i(l,pe(e))}finally{i(o,!1)}}function L(e){e.key==="Enter"&&M()}ee(()=>($(),c),()=>{$().isAuthenticated&&U(`${c}/`)}),ae(),X();var g=fe();re(e=>{se.title="Login - GARM"});var z=r(g),h=r(z),A=r(h),S=r(A),N=d(S,2);t(A),B(4),t(h);var b=d(h,2),x=r(b),y=r(x),p=d(r(y),2);q(p),t(y);var P=d(y,2),v=d(r(P),2);q(v),t(P),t(x);var G=d(x,2);{var O=e=>{var s=ve(),n=r(s),E=d(r(n),2),j=r(E),V=r(j,!0);t(j),t(E),t(n),t(s),_(()=>D(V,a(l))),w(e,s)};oe(G,e=>{a(l)&&e(O)})}var R=d(G,2),Q=r(R);ne(Q,{type:"submit",variant:"primary",size:"md",fullWidth:!0,get disabled(){return a(o)},get loading(){return a(o)},children:(e,s)=>{B();var n=de();_(()=>D(n,a(o)?"Signing in...":"Sign in")),w(e,n)},$$slots:{default:!0}}),t(R),t(b),t(z),t(g),_(()=>{I(S,"src",`${c??""}/assets/garm-light.svg`),I(N,"src",`${c??""}/assets/garm-dark.svg`),p.disabled=a(o),v.disabled=a(o)}),T(p,()=>a(m),e=>i(m,e)),k("keypress",p,L),T(v,()=>a(u),e=>i(u,e)),k("keypress",v,L),k("submit",b,ce(M)),w(H,g),te(),F()}export{ze as component};

View file

@ -1 +0,0 @@
import"../chunks/DsnmJJEf.js";import{i as X}from"../chunks/B3Pzt0F_.js";import{p as Y,o as Z,l as ee,a as ae,f as H,h as re,t as _,g as a,e as k,c as w,d as te,$ as se,k as d,D as de,m as f,j as r,s as i,r as t,z as B,v as D}from"../chunks/D8EpLgQ1.js";import{i as oe,s as ie,a as le}from"../chunks/5WA7h8uK.js";import{B as ne,r as q,c as T}from"../chunks/CiE1LlKV.js";import{b as U}from"../chunks/C6k1Q4We.js";import{p as ce}from"../chunks/D4Caz1gY.js";import{g as C}from"../chunks/CTf6mQoE.js";import{b as c}from"../chunks/CoIRRsD9.js";import{a as me,b as ue}from"../chunks/duD3WMbl.js";var pe=H('<div class="rounded-md bg-red-50 dark:bg-red-900 p-4"><div class="flex"><div class="flex-shrink-0"><svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path></svg></div> <div class="ml-3"><p class="text-sm font-medium text-red-800 dark:text-red-200"> </p></div></div></div>'),ve=H('<div class="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900 py-12 px-4 sm:px-6 lg:px-8"><div class="max-w-md w-full space-y-8"><div><div class="mx-auto h-48 w-auto flex justify-center"><img alt="GARM" class="h-48 w-auto dark:hidden"/> <img alt="GARM" class="h-48 w-auto hidden dark:block"/></div> <h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900 dark:text-white">Sign in to GARM</h2> <p class="mt-2 text-center text-sm text-gray-600 dark:text-gray-400">GitHub Actions Runner Manager</p></div> <form class="mt-8 space-y-6"><div class="rounded-md shadow-sm -space-y-px"><div><label for="username" class="sr-only">Username</label> <input id="username" name="username" type="text" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-700 rounded-t-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm" placeholder="Username"/></div> <div><label for="password" class="sr-only">Password</label> <input id="password" name="password" type="password" required class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-white bg-white dark:bg-gray-700 rounded-b-md focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm" placeholder="Password"/></div></div> <!> <div><!></div></form></div></div>');function Le(I,K){Y(K,!1);const[W,F]=ie(),$=()=>le(me,"$authStore",W);let m=f(""),u=f(""),o=f(!1),l=f("");Z(()=>{J()});function J(){const e=localStorage.getItem("theme");let s=!1;e==="dark"?s=!0:e==="light"?s=!1:s=window.matchMedia("(prefers-color-scheme: dark)").matches,s?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")}async function L(){if(!a(m)||!a(u)){i(l,"Please enter both username and password");return}i(o,!0),i(l,"");try{await ue.login(a(m),a(u)),C(`${c}/`)}catch(e){i(l,e instanceof Error?e.message:"Login failed")}finally{i(o,!1)}}function M(e){e.key==="Enter"&&L()}ee(()=>($(),c),()=>{$().isAuthenticated&&C(`${c}/`)}),ae(),X();var g=ve();re(e=>{se.title="Login - GARM"});var z=r(g),h=r(z),S=r(h),A=r(S),N=d(A,2);t(S),B(4),t(h);var b=d(h,2),x=r(b),y=r(x),p=d(r(y),2);q(p),t(y);var G=d(y,2),v=d(r(G),2);q(v),t(G),t(x);var P=d(x,2);{var O=e=>{var s=pe(),n=r(s),E=d(r(n),2),j=r(E),V=r(j,!0);t(j),t(E),t(n),t(s),_(()=>D(V,a(l))),w(e,s)};oe(P,e=>{a(l)&&e(O)})}var R=d(P,2),Q=r(R);ne(Q,{type:"submit",variant:"primary",size:"md",fullWidth:!0,get disabled(){return a(o)},get loading(){return a(o)},children:(e,s)=>{B();var n=de();_(()=>D(n,a(o)?"Signing in...":"Sign in")),w(e,n)},$$slots:{default:!0}}),t(R),t(b),t(z),t(g),_(()=>{T(A,"src",`${c??""}/assets/garm-light.svg`),T(N,"src",`${c??""}/assets/garm-dark.svg`),p.disabled=a(o),v.disabled=a(o)}),U(p,()=>a(m),e=>i(m,e)),k("keypress",p,M),U(v,()=>a(u),e=>i(u,e)),k("keypress",v,M),k("submit",b,ce(L)),w(I,g),te(),F()}export{Le as component};

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

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

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

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
{"version":"1755334486454"}
{"version":"1755415870786"}

View file

@ -71,11 +71,11 @@
})();
</script>
<link rel="modulepreload" href="/ui/_app/immutable/entry/start.CI0Cdear.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/CTf6mQoE.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/start.S-sEy6br.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DXCC0cSN.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/D8EpLgQ1.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/CoIRRsD9.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/app.kAVAdeq9.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/CRhkqW2i.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/app.OegKHTwb.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DsnmJJEf.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/5WA7h8uK.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/CCSWcuVN.js">
@ -85,7 +85,7 @@
<div style="display: contents">
<script>
{
__sveltekit_13hoftk = {
__sveltekit_xtz33p = {
base: "/ui",
assets: "/ui"
};
@ -93,8 +93,8 @@
const element = document.currentScript.parentElement;
Promise.all([
import("/ui/_app/immutable/entry/start.CI0Cdear.js"),
import("/ui/_app/immutable/entry/app.kAVAdeq9.js")
import("/ui/_app/immutable/entry/start.S-sEy6br.js"),
import("/ui/_app/immutable/entry/app.OegKHTwb.js")
]).then(([kit, app]) => {
kit.start(app, element);
});

View file

@ -1,8 +1,8 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { CreateEnterpriseParams, ForgeCredentials } from '$lib/api/generated/api.js';
import type { CreateEnterpriseParams } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
const dispatch = createEventDispatcher<{
@ -37,7 +37,7 @@
try {
await eagerCacheManager.getCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
}
}
}
@ -68,7 +68,7 @@
dispatch('submit', submitData);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create enterprise';
error = extractAPIError(err);
loading = false;
}
}

View file

@ -1,10 +1,9 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { CreateOrgParams, ForgeCredentials } from '$lib/api/generated/api.js';
import type { CreateOrgParams } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import { getForgeIcon } from '$lib/utils/common.js';
import ForgeTypeSelector from './ForgeTypeSelector.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
const dispatch = createEventDispatcher<{
@ -42,7 +41,7 @@
try {
await eagerCacheManager.getCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
}
}
}

View file

@ -9,6 +9,7 @@
Provider
} from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import JsonEditor from './JsonEditor.svelte';
const dispatch = createEventDispatcher<{
@ -51,7 +52,7 @@
loadingProviders = true;
providers = await garmApi.listProviders();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load providers';
error = extractAPIError(err);
} finally {
loadingProviders = false;
}
@ -76,7 +77,7 @@
break;
}
} catch (err) {
error = err instanceof Error ? err.message : `Failed to load ${entityLevel}s`;
error = extractAPIError(err);
} finally {
loadingEntities = false;
}
@ -162,7 +163,7 @@
dispatch('submit', params);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create pool';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -1,9 +1,8 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { CreateRepoParams, ForgeCredentials } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import { getForgeIcon } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import ForgeTypeSelector from './ForgeTypeSelector.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
@ -43,7 +42,7 @@
try {
await eagerCacheManager.getCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
}
}
}
@ -118,7 +117,7 @@
dispatch('submit', submitData);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create repository';
error = extractAPIError(err);
loading = false;
}
}

View file

@ -10,6 +10,7 @@
} from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import JsonEditor from './JsonEditor.svelte';
import { extractAPIError } from '$lib/utils/apiError';
const dispatch = createEventDispatcher<{
close: void;
@ -45,7 +46,7 @@
loadingProviders = true;
providers = await garmApi.listProviders();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load providers';
error = extractAPIError(err);
} finally {
loadingProviders = false;
}
@ -70,7 +71,7 @@
break;
}
} catch (err) {
error = err instanceof Error ? err.message : `Failed to load ${entityLevel}s`;
error = extractAPIError(err);
} finally {
loadingEntities = false;
}
@ -137,7 +138,7 @@
}
dispatch('submit', createdScaleSet);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create scale set';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -1,6 +1,6 @@
<script lang="ts">
import type { Repository, Organization, Enterprise } from '$lib/api/generated/api.js';
import { formatDate, getEntityStatusBadge } from '$lib/utils/common.js';
import { formatDate } from '$lib/utils/common.js';
import Badge from './Badge.svelte';
type Entity = Repository | Organization | Enterprise;

View file

@ -1,6 +1,6 @@
<script lang="ts">
import type { EntityEvent } from '$lib/api/generated/api.js';
import { formatDate, getEventLevelBadge } from '$lib/utils/common.js';
import { formatDate } from '$lib/utils/common.js';
import Badge from './Badge.svelte';
export let events: EntityEvent[] | undefined;

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import { extractAPIError } from '$lib/utils/apiError';
import type { Enterprise, UpdateEntityParams, ForgeCredentials } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
@ -35,7 +36,7 @@
loading = true;
credentials = await garmApi.listAllCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
} finally {
loading = false;
}
@ -69,7 +70,7 @@
dispatch('submit', submitData);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update enterprise';
error = extractAPIError(err);
loading = false;
}
}

View file

@ -2,6 +2,7 @@
import { createEventDispatcher, onMount } from 'svelte';
import type { Repository, Organization, Enterprise, ForgeCredentials, UpdateEntityParams } from '$lib/api/generated/api.js';
import { garmApi } from '$lib/api/client.js';
import { extractAPIError } from '$lib/utils/apiError';
import Modal from './Modal.svelte';
type Entity = Repository | Organization | Enterprise;
@ -49,7 +50,7 @@
loadingCredentials = true;
credentials = await garmApi.listCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
} finally {
loadingCredentials = false;
}
@ -101,7 +102,7 @@
dispatch('submit', params);
} catch (err) {
error = err instanceof Error ? err.message : `Failed to update ${entityType}`;
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import { extractAPIError } from '$lib/utils/apiError';
import type { Organization, UpdateEntityParams, ForgeCredentials } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
@ -38,7 +39,7 @@
loading = true;
credentials = await garmApi.listAllCredentials();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load credentials';
error = extractAPIError(err);
} finally {
loading = false;
}
@ -72,7 +73,7 @@
dispatch('submit', submitData);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update organization';
error = extractAPIError(err)
loading = false;
}
}

View file

@ -3,6 +3,7 @@
import type { Pool, UpdatePoolParams } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import JsonEditor from './JsonEditor.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import { eagerCache } from '$lib/stores/eager-cache.js';
export let pool: Pool;
@ -132,7 +133,7 @@
dispatch('submit', params);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update pool';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -1,5 +1,6 @@
<script lang="ts">
import { createEventDispatcher, onMount } from 'svelte';
import { createEventDispatcher } from 'svelte';
import { extractAPIError } from '$lib/utils/apiError';
import type { Repository, UpdateEntityParams } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
@ -39,7 +40,7 @@
dispatch('submit', params);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update repository';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -2,6 +2,7 @@
import { createEventDispatcher, onMount } from 'svelte';
import type { ScaleSet, CreateScaleSetParams } from '$lib/api/generated/api.js';
import Modal from './Modal.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import JsonEditor from './JsonEditor.svelte';
export let scaleSet: ScaleSet;
@ -87,7 +88,7 @@
dispatch('submit', params);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update scale set';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -4,6 +4,7 @@
import { toastStore } from '$lib/stores/toast.js';
import Button from './Button.svelte';
import { createEventDispatcher } from 'svelte';
import { extractAPIError } from '$lib/utils/apiError';
export let entityType: 'repository' | 'organization';
export let entityId: string;
@ -93,7 +94,7 @@
} catch (err) {
toastStore.error(
'Webhook Uninstall Failed',
err instanceof Error ? err.message : 'Failed to uninstall webhook.'
extractAPIError(err)
);
} finally {
loading = false;

View file

@ -0,0 +1,88 @@
import type { APIErrorResponse } from '$lib/api/generated/api';
/**
* Extracts error message from API error response
* @param error - The error object from API call
* @returns Human-readable error message
*
* @example
* ```typescript
* try {
* await garmApi.deletePool(poolId);
* } catch (error) {
* const message = extractAPIError(error);
* // Will return "Pool deletion failed. Pool has active runners" if both error and details exist
* // Or just "Pool deletion failed" if only error exists
* // Or just "Pool has active runners" if only details exist
* toastStore.error('Delete Failed', message);
* }
* ```
*/
export function extractAPIError(error: any): string {
// Default fallback message
let errorMessage = 'An unexpected error occurred';
// Try to extract APIErrorResponse from the error
if (error && typeof error === 'object') {
// Check if it's an axios error with response
if ('response' in error && error.response && typeof error.response === 'object') {
const response = error.response;
// Check if response has data with APIErrorResponse structure
if ('data' in response && response.data && typeof response.data === 'object') {
const apiError = response.data as APIErrorResponse;
// Build message from available fields
const errorPart = apiError.error && apiError.error.trim() ? apiError.error : '';
const detailsPart = apiError.details && apiError.details.trim() ? apiError.details : '';
if (errorPart && detailsPart) {
// Both available - combine them
return `${errorPart}. ${detailsPart}`;
} else if (errorPart) {
// Only error available
return errorPart;
} else if (detailsPart) {
// Only details available
return detailsPart;
}
}
// If no APIErrorResponse, try to get status-based message
if ('status' in response) {
const status = response.status;
switch (status) {
case 400:
errorMessage = 'Bad request - please check your input';
break;
case 401:
errorMessage = 'Unauthorized - please log in again';
break;
case 403:
errorMessage = 'Access denied - insufficient permissions';
break;
case 404:
errorMessage = 'Resource not found';
break;
case 409:
errorMessage = 'Conflict - resource already exists or is in use';
break;
case 422:
errorMessage = 'Validation failed - please check your input';
break;
case 500:
errorMessage = 'Internal server error - please try again later';
break;
default:
errorMessage = `Request failed with status ${status}`;
}
}
}
// Check if it's a direct Error object with a meaningful message
else if (error instanceof Error && error.message && !error.message.includes('status code')) {
return error.message;
}
}
return errorMessage;
}

View file

@ -5,7 +5,8 @@
import { websocketStore, type WebSocketEvent } from '$lib/stores/websocket.js';
import { eagerCacheManager, eagerCache } from '$lib/stores/eager-cache.js';
import ControllerInfoCard from '$lib/components/ControllerInfoCard.svelte';
import type { Repository, Organization, Pool, Instance, ControllerInfo } from '$lib/api/generated/api.js';
import { extractAPIError } from '$lib/utils/apiError';
import type { ControllerInfo } from '$lib/api/generated/api.js';
// Start with zero values for immediate render
let stats = {
@ -84,7 +85,7 @@
controllerInfo = controller;
}
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load dashboard data';
error = extractAPIError(err);
console.error('Dashboard error:', err);
}

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { ForgeCredentials, ForgeEndpoint, CreateGithubCredentialsParams, GithubPAT, GithubApp } from '$lib/api/generated/api.js';
// AuthType constants
@ -10,15 +10,11 @@
import PageHeader from '$lib/components/PageHeader.svelte';
import ForgeTypeSelector from '$lib/components/ForgeTypeSelector.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
import Button from '$lib/components/Button.svelte';
import SearchBar from '$lib/components/SearchBar.svelte';
import LoadingState from '$lib/components/LoadingState.svelte';
import ErrorState from '$lib/components/ErrorState.svelte';
import EmptyState from '$lib/components/EmptyState.svelte';
import DataTable from '$lib/components/DataTable.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, filterCredentials, changePage, changePerPage, paginateItems, getAuthTypeBadge } from '$lib/utils/common.js';
import { getForgeIcon, filterCredentials, changePerPage, paginateItems, getAuthTypeBadge } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import Badge from '$lib/components/Badge.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '$lib/components/cells';
@ -287,7 +283,7 @@
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create credentials';
error = extractAPIError(err);
}
}
@ -320,7 +316,7 @@
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update credentials';
error = extractAPIError(err);
}
}
@ -339,9 +335,11 @@
'Credentials Deleted',
`Credentials ${deletingCredential?.name || 'Unknown'} have been deleted successfully.`
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete credentials';
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
} finally {
closeModals();
}
}

View file

@ -1,22 +1,18 @@
<svelte:window on:keydown={handleKeydown} />
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { ForgeEndpoint } from '$lib/api/generated/api.js';
import PageHeader from '$lib/components/PageHeader.svelte';
import ForgeTypeSelector from '$lib/components/ForgeTypeSelector.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
import Button from '$lib/components/Button.svelte';
import SearchBar from '$lib/components/SearchBar.svelte';
import LoadingState from '$lib/components/LoadingState.svelte';
import ErrorState from '$lib/components/ErrorState.svelte';
import EmptyState from '$lib/components/EmptyState.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, filterEndpoints, changePage, changePerPage, paginateItems } from '$lib/utils/common.js';
import { getForgeIcon, filterEndpoints, changePerPage, paginateItems } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import DataTable from '$lib/components/DataTable.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '$lib/components/cells';
import { EndpointCell, ActionsCell, GenericCell } from '$lib/components/cells';
let loading = true;
let endpoints: ForgeEndpoint[] = [];
@ -334,7 +330,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create endpoint';
error = extractAPIError(err);
}
}
@ -366,7 +362,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to update endpoint';
error = extractAPIError(err);
}
}
@ -384,10 +380,11 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
'Endpoint Deleted',
`Endpoint ${deletingEndpoint.name} has been deleted successfully.`
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete endpoint';
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
}
closeModals();
}
function handleFileUpload(event: Event) {

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { Enterprise, CreateEnterpriseParams, UpdateEntityParams } from '$lib/api/generated/api.js';
import { base } from '$app/paths';
@ -10,6 +10,7 @@
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, getEntityStatusBadge, filterByName } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import Badge from '$lib/components/Badge.svelte';
import DataTable from '$lib/components/DataTable.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
@ -59,7 +60,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
);
showCreateModal = false;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create enterprise';
error = extractAPIError(err);
throw err; // Let the modal handle the error
}
}
@ -93,7 +94,8 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
showDeleteModal = false;
selectedEnterprise = null;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete enterprise';
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
}
}

View file

@ -16,6 +16,7 @@
import { websocketStore, type WebSocketEvent } from '$lib/stores/websocket.js';
import { toastStore } from '$lib/stores/toast.js';
import CreatePoolModal from '$lib/components/CreatePoolModal.svelte';
import { extractAPIError } from '$lib/utils/apiError';
import type { CreatePoolParams } from '$lib/api/generated/api.js';
let enterprise: Enterprise | null = null;
@ -94,7 +95,11 @@
await garmApi.deleteEnterprise(enterprise.id!);
goto(`${base}/enterprises`);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete enterprise';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
);
}
showDeleteModal = false;
}
@ -111,7 +116,7 @@
showDeleteInstanceModal = false;
selectedInstance = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete instance';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage

View file

@ -4,6 +4,7 @@
import { base } from '$app/paths';
import { auth, authStore } from '$lib/stores/auth.js';
import { toastStore } from '$lib/stores/toast.js';
import { extractAPIError } from '$lib/utils/apiError';
import Button from '$lib/components/Button.svelte';
let username = 'admin';
@ -68,7 +69,7 @@
// Redirect to dashboard
goto(`${base}/`);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to initialize GARM';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -7,7 +7,8 @@
import { websocketStore, type WebSocketEvent } from '$lib/stores/websocket.js';
import { toastStore } from '$lib/stores/toast.js';
import DataTable from '$lib/components/DataTable.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, InstancePoolCell } from '$lib/components/cells';
import { extractAPIError } from '$lib/utils/apiError';
import { EntityCell, StatusCell, ActionsCell, GenericCell, InstancePoolCell } from '$lib/components/cells';
let instances: Instance[] = [];
let loading = true;
@ -71,18 +72,14 @@
'Instance Deleted',
`Instance ${instanceToDelete.name} has been deleted successfully.`
);
} catch (err) {
error = extractAPIError(err);
} finally {
showDeleteModal = false;
instanceToDelete = null;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete instance';
}
}
function handleStatusFilterChange(event: Event) {
statusFilter = (event.target as HTMLSelectElement).value;
currentPage = 1;
}
// DataTable configuration
const columns = [
{

View file

@ -9,6 +9,7 @@
import { websocketStore, type WebSocketEvent } from '$lib/stores/websocket.js';
import { formatStatusText, getStatusBadgeClass } from '$lib/utils/status.js';
import { formatDate, scrollToBottomEvents, getEventLevelBadge } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import Badge from '$lib/components/Badge.svelte';
let instance: Instance | null = null;
@ -41,14 +42,11 @@
await garmApi.deleteInstance(instance.name!);
goto(`${base}/instances`);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete instance';
error = extractAPIError(err);
}
showDeleteModal = false;
}
function handleInstanceEvent(event: WebSocketEvent) {
if (!instance) return;

View file

@ -4,6 +4,7 @@
import { base } from '$app/paths';
import { auth, authStore } from '$lib/stores/auth.js';
import Button from '$lib/components/Button.svelte';
import { extractAPIError } from '$lib/utils/apiError';
let username = '';
let password = '';
@ -53,7 +54,7 @@
await auth.login(username, password);
goto(`${base}/`);
} catch (err) {
error = err instanceof Error ? err.message : 'Login failed';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { Organization, CreateOrgParams, UpdateEntityParams } from '$lib/api/generated/api.js';
import { base } from '$app/paths';
@ -10,6 +10,7 @@
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, getEntityStatusBadge, filterByName } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import Badge from '$lib/components/Badge.svelte';
import DataTable from '$lib/components/DataTable.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
@ -48,6 +49,11 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
currentPage * perPage
);
function closeModals() {
showCreateModal = false;
showDeleteModal = false;
showUpdateModal = false;
}
async function handleCreateOrganization(event: CustomEvent<CreateOrgParams & { install_webhook?: boolean; auto_generate_secret?: boolean }>) {
try {
@ -87,7 +93,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
);
showCreateModal = false;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create organization';
error = extractAPIError(err);
throw err; // Let the modal handle the error
}
}
@ -118,10 +124,12 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '
'Organization Deleted',
`Organization ${selectedOrganization.name} has been deleted successfully.`
);
showDeleteModal = false;
selectedOrganization = null;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete organization';
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
} finally {
closeModals();
}
}

View file

@ -10,6 +10,7 @@
import EntityInformation from '$lib/components/EntityInformation.svelte';
import DetailHeader from '$lib/components/DetailHeader.svelte';
import { getForgeIcon } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import PoolsSection from '$lib/components/PoolsSection.svelte';
import InstancesSection from '$lib/components/InstancesSection.svelte';
import EventsSection from '$lib/components/EventsSection.svelte';
@ -51,7 +52,7 @@
pools = orgPools;
instances = orgInstances;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load organization';
error = extractAPIError(err);
} finally {
loading = false;
}
@ -95,7 +96,11 @@
await garmApi.deleteOrganization(organization.id!);
goto(`${base}/organizations`);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete organization';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
);
}
showDeleteModal = false;
}
@ -112,7 +117,7 @@
showDeleteInstanceModal = false;
selectedInstance = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete instance';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage

View file

@ -1,18 +1,16 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { Pool, CreatePoolParams, UpdatePoolParams, Provider } from '$lib/api/generated/api.js';
import { base } from '$app/paths';
import type { Pool, UpdatePoolParams } from '$lib/api/generated/api.js';
import PageHeader from '$lib/components/PageHeader.svelte';
import CreatePoolModal from '$lib/components/CreatePoolModal.svelte';
import UpdatePoolModal from '$lib/components/UpdatePoolModal.svelte';
import DeleteModal from '$lib/components/DeleteModal.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, truncateImageName, getEntityName, getEntityType, getEntityUrl, filterEntities, getEnabledStatusBadge } from '$lib/utils/common.js';
import Badge from '$lib/components/Badge.svelte';
import { getEntityName, filterEntities } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import DataTable from '$lib/components/DataTable.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEntityCell } from '$lib/components/cells';
let pools: Pool[] = [];
@ -49,16 +47,14 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
currentPage * perPage
);
async function handleCreatePool(params: CreatePoolParams) {
try {
error = '';
// The actual creation will be handled by the modal based on entity type
// No need to reload - eager cache websocket will handle the update
showCreateModal = false;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create pool';
throw err; // Let the modal handle the error
}
async function handleCreatePool() {
// The actual creation is already handled by the modal
// This function is called after successful creation
toastStore.success(
'Pool Created',
'Pool has been created successfully.'
);
showCreateModal = false;
}
async function handleUpdatePool(params: UpdatePoolParams) {
@ -74,7 +70,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
});
selectedPool = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to update pool';
const errorMessage = extractAPIError(err);
toastStore.add({
type: 'error',
title: 'Update Failed',
@ -98,8 +94,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
});
selectedPool = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete pool';
error = errorMessage;
const errorMessage = extractAPIError(err);
toastStore.add({
type: 'error',
title: 'Delete Failed',
@ -316,7 +311,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
{#if showCreateModal}
<CreatePoolModal
on:close={() => showCreateModal = false}
on:submit={(e) => handleCreatePool(e.detail)}
on:submit={() => handleCreatePool()}
/>
{/if}

View file

@ -13,6 +13,7 @@
import type { Instance } from '$lib/api/generated/api.js';
import { toastStore } from '$lib/stores/toast.js';
import { formatDate, getForgeIcon, getEntityName, getEntityType, getEntityUrl } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
let pool: Pool | null = null;
let loading = true;
@ -33,7 +34,7 @@
error = '';
pool = await garmApi.getPool(poolId);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load pool';
error = extractAPIError(err);
} finally {
loading = false;
}
@ -52,7 +53,7 @@
`Pool ${pool.id} has been updated successfully.`
);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to update pool';
const errorMessage = extractAPIError(err);
toastStore.error(
'Update Failed',
errorMessage
@ -66,7 +67,7 @@
await garmApi.deletePool(pool.id!);
goto(`${base}/pools`);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete pool';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
@ -83,10 +84,8 @@
'Instance Deleted',
`Instance ${selectedInstance.name} has been deleted successfully.`
);
showDeleteInstanceModal = false;
selectedInstance = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete instance';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
@ -101,7 +100,6 @@
showDeleteInstanceModal = true;
}
function formatExtraSpecs(extraSpecs: any): string {
if (!extraSpecs) return '{}';
try {

View file

@ -1,18 +1,15 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { Repository, ForgeCredentials, CreateRepoParams, UpdateEntityParams } from '$lib/api/generated/api.js';
import type { Repository, CreateRepoParams, UpdateEntityParams } from '$lib/api/generated/api.js';
import CreateRepositoryModal from '$lib/components/CreateRepositoryModal.svelte';
import UpdateEntityModal from '$lib/components/UpdateEntityModal.svelte';
import DeleteModal from '$lib/components/DeleteModal.svelte';
import LoadingState from '$lib/components/LoadingState.svelte';
import ErrorState from '$lib/components/ErrorState.svelte';
import EmptyState from '$lib/components/EmptyState.svelte';
import PageHeader from '$lib/components/PageHeader.svelte';
import Button from '$lib/components/Button.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, changePage, changePerPage, getEntityStatusBadge, filterRepositories, paginateItems } from '$lib/utils/common.js';
import { getForgeIcon, changePerPage, getEntityStatusBadge, filterRepositories, paginateItems } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import DataTable from '$lib/components/DataTable.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell } from '$lib/components/cells';
@ -20,8 +17,6 @@
let loading = true;
let error = '';
let searchTerm = '';
let credentials: ForgeCredentials[] = [];
let credentialsLoading = false;
// Modal states
let showCreateModal = false;
@ -98,7 +93,6 @@
showDeleteModal = true;
}
function closeModals() {
showCreateModal = false;
showEditModal = false;
@ -146,7 +140,7 @@
`Repository ${createdRepo.owner}/${createdRepo.name} has been created successfully.`
);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create repository';
error = extractAPIError(err);
throw err; // Let the modal handle the error display
}
}
@ -178,9 +172,11 @@
'Repository Deleted',
`Repository ${deletingRepository.owner}/${deletingRepository.name} has been deleted successfully.`
);
closeModals();
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete repository';
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
} finally {
closeModals();
}
}

View file

@ -11,6 +11,7 @@
import DetailHeader from '$lib/components/DetailHeader.svelte';
import PoolsSection from '$lib/components/PoolsSection.svelte';
import { getForgeIcon } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import InstancesSection from '$lib/components/InstancesSection.svelte';
import EventsSection from '$lib/components/EventsSection.svelte';
import WebhookSection from '$lib/components/WebhookSection.svelte';
@ -51,7 +52,7 @@
pools = repoPools;
instances = repoInstances;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to load repository';
error = extractAPIError(err);
} finally {
loading = false;
}
@ -95,7 +96,11 @@
await garmApi.deleteRepository(repository.id!);
goto(`${base}/repositories`);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete repository';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
);
}
showDeleteModal = false;
}
@ -112,7 +117,7 @@
showDeleteInstanceModal = false;
selectedInstance = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete instance';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { onMount } from 'svelte';
import { garmApi } from '$lib/api/client.js';
import type { ScaleSet, CreateScaleSetParams } from '$lib/api/generated/api.js';
import { base } from '$app/paths';
@ -9,11 +9,10 @@
import DeleteModal from '$lib/components/DeleteModal.svelte';
import { eagerCache, eagerCacheManager } from '$lib/stores/eager-cache.js';
import { toastStore } from '$lib/stores/toast.js';
import { getForgeIcon, getEntityName, getEntityType, getEntityUrl, filterEntities, getEnabledStatusBadge } from '$lib/utils/common.js';
import Badge from '$lib/components/Badge.svelte';
import DataTable from '$lib/components/DataTable.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEntityCell } from '$lib/components/cells';
import { getEntityName, filterEntities } from '$lib/utils/common.js';
import { extractAPIError } from '$lib/utils/apiError';
import DataTable from '$lib/components/DataTable.svelte';
import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEntityCell } from '$lib/components/cells';
let scaleSets: ScaleSet[] = [];
let loading = true;
@ -60,7 +59,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
'Scale set has been created successfully.'
);
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to create scale set';
error = extractAPIError(err);
throw err; // Let the modal handle the error
}
}
@ -90,10 +89,12 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
'Scale Set Deleted',
`Scale set ${selectedScaleSet.name} has been deleted successfully.`
);
} catch (err) {
const errorMessage = extractAPIError(err);
toastStore.error('Delete Failed', errorMessage);
} finally {
showDeleteModal = false;
selectedScaleSet = null;
} catch (err) {
error = err instanceof Error ? err.message : 'Failed to delete scale set';
}
}
@ -126,7 +127,7 @@ import { EntityCell, EndpointCell, StatusCell, ActionsCell, GenericCell, PoolEnt
// Cache error is already handled by the eager cache system
// We don't need to set error here anymore since it's in the cache state
console.error('Failed to load scale sets:', err);
error = err instanceof Error ? err.message : 'Failed to load scale sets';
error = extractAPIError(err);
} finally {
loading = false;
}

View file

@ -12,6 +12,7 @@
import { websocketStore, type WebSocketEvent } from '$lib/stores/websocket.js';
import { toastStore } from '$lib/stores/toast.js';
import type { Instance } from '$lib/api/generated/api.js';
import { extractAPIError } from '$lib/utils/apiError';
import { formatDate, getForgeIcon, getEntityName, getEntityType, getEntityUrl } from '$lib/utils/common.js';
let scaleSet: ScaleSet | null = null;
@ -60,7 +61,7 @@
await garmApi.deleteScaleSet(scaleSet.id!);
goto(`${base}/scalesets`);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete scale set';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage
@ -77,12 +78,8 @@
'Instance Deleted',
`Instance ${selectedInstance.name} has been deleted successfully.`
);
// Reload scale set to update instances list
await loadScaleSet();
showDeleteInstanceModal = false;
selectedInstance = null;
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Failed to delete instance';
const errorMessage = extractAPIError(err);
toastStore.error(
'Delete Failed',
errorMessage