Fix WebUI tests

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2025-10-09 11:40:12 +00:00 committed by Gabriel
parent e50a36cbca
commit c1259719ea
91 changed files with 1234 additions and 223 deletions

View file

@ -77,6 +77,6 @@ jobs:
- name: Run GARM Go Tests
run: make go-test
# - name: Run web UI tests
# run: |
# make webui-test
- name: Run web UI tests
run: |
make webui-test

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as D}from"./TJn6xDN9.js";import{p as P,f as I,d as s,r as n,s as u,u as l,q as i,t as w,e as S,b as N,c as A}from"./DniTuB_0.js";import{d as f,c as F}from"./CKHGi7RD.js";import{p as d}from"./DbNhg6mG.js";import{D as E,G,A as j}from"./DSa_5ZRu.js";import{E as q}from"./C3rmHwOU.js";import{S as g}from"./AK_XcbnN.js";var L=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 O(y,a){P(a,!1);let e=d(a,"instances",8),h=d(a,"entityType",8),v=d(a,"onDeleteInstance",8);const b=[{key:"name",title:"Name",cellComponent:q,cellProps:{entityType:"instance",nameField:"name"}},{key:"status",title:"Status",cellComponent:g,cellProps:{statusType:"instance",statusField:"status"}},{key:"runner_status",title:"Runner Status",cellComponent:g,cellProps:{statusType:"instance",statusField:"runner_status"}},{key:"created",title:"Created",cellComponent:G,cellProps:{field:"created_at",type:"date"}},{key:"actions",title:"Actions",align:"right",cellComponent:j,cellProps:{actions:[{type:"delete",label:"Delete",title:"Delete instance",ariaLabel:"Delete instance",action:"delete"}]}}],x={entityType:"instance",primaryText:{field:"name",isClickable:!0,href:"/instances/{name}"},secondaryText:{field:"provider_id"},badges:[{type:"status",field:"status"}],actions:[{type:"delete",handler:t=>m(t)}]};function m(t){v()(t)}function C(t){m(t.detail.item)}D();var r=L(),p=s(r),o=s(p),c=s(o),T=s(c);n(c);var _=u(c,2);n(o);var k=u(o,2);E(k,{get columns(){return b},get data(){return e()},loading:!1,error:"",searchTerm:"",showSearch:!1,showPagination:!1,currentPage:1,get perPage(){return i(e()),l(()=>e().length)},totalPages:1,get totalItems(){return i(e()),l(()=>e().length)},itemName:"instances",emptyTitle:"No instances running",get emptyMessage(){return`No instances running for this ${h()??""}.`},emptyIconType:"cog",get mobileCardConfig(){return x},$$events:{delete:C}}),n(p),n(r),w(t=>{S(T,`Instances (${i(e()),l(()=>e().length)??""})`),F(_,"href",t)},[()=>(i(f),l(()=>f("/instances")))]),N(y,r),A()}export{O as I};
import"./DsnmJJEf.js";import{i as D}from"./TJn6xDN9.js";import{p as P,f as I,d as s,r as n,s as u,u as l,q as i,t as w,e as S,b as N,c as A}from"./DniTuB_0.js";import{d as f,c as F}from"./DD3srElq.js";import{p as d}from"./DbNhg6mG.js";import{D as E,G,A as j}from"./QtGwBUod.js";import{E as q}from"./D3pbRQAB.js";import{S as g}from"./Dn_Ue57e.js";var L=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 O(y,a){P(a,!1);let e=d(a,"instances",8),h=d(a,"entityType",8),v=d(a,"onDeleteInstance",8);const b=[{key:"name",title:"Name",cellComponent:q,cellProps:{entityType:"instance",nameField:"name"}},{key:"status",title:"Status",cellComponent:g,cellProps:{statusType:"instance",statusField:"status"}},{key:"runner_status",title:"Runner Status",cellComponent:g,cellProps:{statusType:"instance",statusField:"runner_status"}},{key:"created",title:"Created",cellComponent:G,cellProps:{field:"created_at",type:"date"}},{key:"actions",title:"Actions",align:"right",cellComponent:j,cellProps:{actions:[{type:"delete",label:"Delete",title:"Delete instance",ariaLabel:"Delete instance",action:"delete"}]}}],x={entityType:"instance",primaryText:{field:"name",isClickable:!0,href:"/instances/{name}"},secondaryText:{field:"provider_id"},badges:[{type:"status",field:"status"}],actions:[{type:"delete",handler:t=>m(t)}]};function m(t){v()(t)}function C(t){m(t.detail.item)}D();var r=L(),p=s(r),o=s(p),c=s(o),T=s(c);n(c);var _=u(c,2);n(o);var k=u(o,2);E(k,{get columns(){return b},get data(){return e()},loading:!1,error:"",searchTerm:"",showSearch:!1,showPagination:!1,currentPage:1,get perPage(){return i(e()),l(()=>e().length)},totalPages:1,get totalItems(){return i(e()),l(()=>e().length)},itemName:"instances",emptyTitle:"No instances running",get emptyMessage(){return`No instances running for this ${h()??""}.`},emptyIconType:"cog",get mobileCardConfig(){return x},$$events:{delete:C}}),n(p),n(r),w(t=>{S(T,`Instances (${i(e()),l(()=>e().length)??""})`),F(_,"href",t)},[()=>(i(f),l(()=>f("/instances")))]),N(y,r),A()}export{O as I};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as D}from"./TJn6xDN9.js";import{p as E,E as B,l as t,q as s,g as e,m as o,h as P,f as T,t as q,i as S,b as F,c as G,u as I,d as _,k as a,r as z}from"./DniTuB_0.js";import{i as J,h as K,s as N,j as O}from"./CKHGi7RD.js";import{l as j,p as l}from"./DbNhg6mG.js";var Q=T('<button><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><!></svg></button>');function Z(C,i){const M=j(i,["children","$$slots","$$events","$$legacy"]),L=j(M,["action","disabled","title","ariaLabel","size"]);E(i,!1);const u=o(),h=o(),k=o(),f=o(),g=o(),v=o(),n=o(),m=o(),b=o(),A=B();let r=l(i,"action",8,"edit"),x=l(i,"disabled",8,!1),w=l(i,"title",8,""),y=l(i,"ariaLabel",8,""),c=l(i,"size",8,"md");function H(){x()||A("click")}t(()=>{},()=>{a(u,"transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50")}),t(()=>s(c()),()=>{a(h,{sm:"p-1",md:"p-2"}[c()])}),t(()=>s(r()),()=>{a(k,{edit:"text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300 focus:ring-indigo-500",delete:"text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300 focus:ring-red-500",view:"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300 focus:ring-gray-500",add:"text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300 focus:ring-green-500",copy:"text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 focus:ring-blue-500",download:"text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 focus:ring-blue-500"}[r()])}),t(()=>s(c()),()=>{a(f,c()==="sm"?"h-4 w-4":"h-5 w-5")}),t(()=>(e(u),e(h),e(k)),()=>{a(g,[e(u),e(h),e(k)].join(" "))}),t(()=>{},()=>{a(v,{edit:'<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" />',delete:'<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" />',view:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />',add:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />',copy:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />',download:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />'})}),t(()=>{},()=>{a(n,{edit:"Edit",delete:"Delete",view:"View",add:"Add",copy:"Clone",download:"Download"})}),t(()=>(s(w()),e(n),s(r())),()=>{a(m,w()||e(n)[r()])}),t(()=>(s(y()),e(n),s(r())),()=>{a(b,y()||`${e(n)[r()]} item`)}),P(),D();var d=Q();J(d,()=>({type:"button",class:e(g),disabled:x(),title:e(m),"aria-label":e(b),...L}));var p=_(d),V=_(p);K(V,()=>(e(v),s(r()),I(()=>e(v)[r()])),!0),z(p),z(d),q(()=>N(p,0,O(e(f)))),S("click",d,H),F(C,d),G()}export{Z as A};
import"./DsnmJJEf.js";import{i as D}from"./TJn6xDN9.js";import{p as E,E as B,l as t,q as s,g as e,m as o,h as P,f as T,t as q,i as S,b as F,c as G,u as I,d as _,k as a,r as z}from"./DniTuB_0.js";import{i as J,h as K,s as N,j as O}from"./DD3srElq.js";import{l as j,p as l}from"./DbNhg6mG.js";var Q=T('<button><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><!></svg></button>');function Z(C,i){const M=j(i,["children","$$slots","$$events","$$legacy"]),L=j(M,["action","disabled","title","ariaLabel","size"]);E(i,!1);const u=o(),h=o(),k=o(),f=o(),g=o(),v=o(),n=o(),m=o(),b=o(),A=B();let r=l(i,"action",8,"edit"),x=l(i,"disabled",8,!1),w=l(i,"title",8,""),y=l(i,"ariaLabel",8,""),c=l(i,"size",8,"md");function H(){x()||A("click")}t(()=>{},()=>{a(u,"transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50")}),t(()=>s(c()),()=>{a(h,{sm:"p-1",md:"p-2"}[c()])}),t(()=>s(r()),()=>{a(k,{edit:"text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300 focus:ring-indigo-500",delete:"text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300 focus:ring-red-500",view:"text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300 focus:ring-gray-500",add:"text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300 focus:ring-green-500",copy:"text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 focus:ring-blue-500",download:"text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 focus:ring-blue-500"}[r()])}),t(()=>s(c()),()=>{a(f,c()==="sm"?"h-4 w-4":"h-5 w-5")}),t(()=>(e(u),e(h),e(k)),()=>{a(g,[e(u),e(h),e(k)].join(" "))}),t(()=>{},()=>{a(v,{edit:'<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" />',delete:'<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" />',view:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />',add:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />',copy:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />',download:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />'})}),t(()=>{},()=>{a(n,{edit:"Edit",delete:"Delete",view:"View",add:"Add",copy:"Clone",download:"Download"})}),t(()=>(s(w()),e(n),s(r())),()=>{a(m,w()||e(n)[r()])}),t(()=>(s(y()),e(n),s(r())),()=>{a(b,y()||`${e(n)[r()]} item`)}),P(),D();var d=Q();J(d,()=>({type:"button",class:e(g),disabled:x(),title:e(m),"aria-label":e(b),...L}));var p=_(d),V=_(p);K(V,()=>(e(v),s(r()),I(()=>e(v)[r()])),!0),z(p),z(d),q(()=>N(p,0,O(e(f)))),S("click",d,H),F(C,d),G()}export{Z as A};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as q}from"./TJn6xDN9.js";import{p as A,E as F,f as y,s as l,d as t,r as a,z as $,D as b,b as o,t as p,e as n,c as G}from"./DniTuB_0.js";import{p as v,i as H}from"./DbNhg6mG.js";import{M as I}from"./DKx8ztAw.js";import{B as w}from"./CKHGi7RD.js";var J=y('<p class="mt-1 font-medium text-gray-900 dark:text-white"> </p>'),K=y('<div class="max-w-xl w-full p-6"><div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 dark:bg-red-900 mb-4"><svg class="h-6 w-6 text-red-600 dark:text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg></div> <div class="text-center"><h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white mb-2"> </h3> <div class="text-sm text-gray-500 dark:text-gray-400"><p> </p> <!></div></div> <div class="mt-6 flex justify-end space-x-3"><!> <!></div></div>');function W(D,s){A(s,!1);let M=v(s,"title",8),j=v(s,"message",8),g=v(s,"itemName",8,""),d=v(s,"loading",8,!1);const c=F();function B(){c("confirm")}q(),I(D,{$$events:{close:()=>c("close")},children:(C,O)=>{var m=K(),f=l(t(m),2),u=t(f),P=t(u,!0);a(u);var h=l(u,2),x=t(h),z=t(x,!0);a(x);var E=l(x,2);{var L=e=>{var i=J(),r=t(i,!0);a(i),p(()=>n(r,g())),o(e,i)};H(E,e=>{g()&&e(L)})}a(h),a(f);var _=l(f,2),k=t(_);w(k,{variant:"secondary",get disabled(){return d()},$$events:{click:()=>c("close")},children:(e,i)=>{$();var r=b("Cancel");o(e,r)},$$slots:{default:!0}});var N=l(k,2);w(N,{variant:"danger",get disabled(){return d()},get loading(){return d()},$$events:{click:B},children:(e,i)=>{$();var r=b();p(()=>n(r,d()?"Deleting...":"Delete")),o(e,r)},$$slots:{default:!0}}),a(_),a(m),p(()=>{n(P,M()),n(z,j())}),o(C,m)},$$slots:{default:!0}}),G()}export{W as D};
import"./DsnmJJEf.js";import{i as q}from"./TJn6xDN9.js";import{p as A,E as F,f as y,s as l,d as t,r as a,z as $,D as b,b as o,t as p,e as n,c as G}from"./DniTuB_0.js";import{p as v,i as H}from"./DbNhg6mG.js";import{M as I}from"./PC4wJWhj.js";import{B as w}from"./DD3srElq.js";var J=y('<p class="mt-1 font-medium text-gray-900 dark:text-white"> </p>'),K=y('<div class="max-w-xl w-full p-6"><div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 dark:bg-red-900 mb-4"><svg class="h-6 w-6 text-red-600 dark:text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg></div> <div class="text-center"><h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white mb-2"> </h3> <div class="text-sm text-gray-500 dark:text-gray-400"><p> </p> <!></div></div> <div class="mt-6 flex justify-end space-x-3"><!> <!></div></div>');function W(D,s){A(s,!1);let M=v(s,"title",8),j=v(s,"message",8),g=v(s,"itemName",8,""),d=v(s,"loading",8,!1);const c=F();function B(){c("confirm")}q(),I(D,{$$events:{close:()=>c("close")},children:(C,O)=>{var m=K(),f=l(t(m),2),u=t(f),P=t(u,!0);a(u);var h=l(u,2),x=t(h),z=t(x,!0);a(x);var E=l(x,2);{var L=e=>{var i=J(),r=t(i,!0);a(i),p(()=>n(r,g())),o(e,i)};H(E,e=>{g()&&e(L)})}a(h),a(f);var _=l(f,2),k=t(_);w(k,{variant:"secondary",get disabled(){return d()},$$events:{click:()=>c("close")},children:(e,i)=>{$();var r=b("Cancel");o(e,r)},$$slots:{default:!0}});var N=l(k,2);w(N,{variant:"danger",get disabled(){return d()},get loading(){return d()},$$events:{click:B},children:(e,i)=>{$();var r=b();p(()=>n(r,d()?"Deleting...":"Delete")),o(e,r)},$$slots:{default:!0}}),a(_),a(m),p(()=>{n(P,M()),n(z,j())}),o(C,m)},$$slots:{default:!0}}),G()}export{W as D};

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
const w=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function x(t){const s=[];return{pattern:t==="/"?/^\/$/:new RegExp(`^${_(t).map(a=>{const i=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(a);if(i)return s.push({name:i[1],matcher:i[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const c=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(a);if(c)return s.push({name:c[1],matcher:c[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!a)return;const n=a.split(/\[(.+?)\](?!\])/);return"/"+n.map((e,u)=>{if(u%2){if(e.startsWith("x+"))return h(String.fromCharCode(parseInt(e.slice(2),16)));if(e.startsWith("u+"))return h(String.fromCharCode(...e.slice(2).split("-").map(g=>parseInt(g,16))));const o=w.exec(e),[,l,p,m,d]=o;return s.push({name:m,matcher:d,optional:!!l,rest:!!p,chained:p?u===1&&n[0]==="":!1}),p?"([^]*?)":l?"([^/]*)?":"([^/]+?)"}return h(e)}).join("")}).join("")}/?$`),params:s}}function $(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function _(t){return t.slice(1).split("/").filter($)}function j(t,s,f){const a={},i=t.slice(1),c=i.filter(r=>r!==void 0);let n=0;for(let r=0;r<s.length;r+=1){const e=s[r];let u=i[r-n];if(e.chained&&e.rest&&n&&(u=i.slice(r-n,r+1).filter(o=>o).join("/"),n=0),u===void 0){e.rest&&(a[e.name]="");continue}if(!e.matcher||f[e.matcher](u)){a[e.name]=u;const o=s[r+1],l=i[r+1];o&&!o.rest&&o.optional&&l&&e.chained&&(n=0),!o&&!l&&Object.keys(a).length===c.length&&(n=0);continue}if(e.optional&&e.chained){n++;continue}return}if(!n)return a}function h(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}const b=/\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;function k(t,s){return"/"+_(t).map(a=>a.replace(b,(i,c,n,r)=>{const e=s[r];if(!e){if(c||n&&e!==void 0)return"";throw new Error(`Missing parameter '${r}' in route ${t}`)}if(e.startsWith("/")||e.endsWith("/"))throw new Error(`Parameter '${r}' in route ${t} cannot start or end with a slash -- this would cause an invalid route like foo//bar`);return e})).filter(Boolean).join("/")}const v=globalThis.__sveltekit_1bvrx0w?.base??"/ui",C=globalThis.__sveltekit_1bvrx0w?.assets??v;export{C as a,v as b,j as e,x as p,k as r};
const w=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function x(t){const s=[];return{pattern:t==="/"?/^\/$/:new RegExp(`^${m(t).map(a=>{const i=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(a);if(i)return s.push({name:i[1],matcher:i[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const c=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(a);if(c)return s.push({name:c[1],matcher:c[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!a)return;const n=a.split(/\[(.+?)\](?!\])/);return"/"+n.map((e,l)=>{if(l%2){if(e.startsWith("x+"))return h(String.fromCharCode(parseInt(e.slice(2),16)));if(e.startsWith("u+"))return h(String.fromCharCode(...e.slice(2).split("-").map(g=>parseInt(g,16))));const o=w.exec(e),[,u,p,_,d]=o;return s.push({name:_,matcher:d,optional:!!u,rest:!!p,chained:p?l===1&&n[0]==="":!1}),p?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return h(e)}).join("")}).join("")}/?$`),params:s}}function $(t){return t!==""&&!/^\([^)]+\)$/.test(t)}function m(t){return t.slice(1).split("/").filter($)}function j(t,s,f){const a={},i=t.slice(1),c=i.filter(r=>r!==void 0);let n=0;for(let r=0;r<s.length;r+=1){const e=s[r];let l=i[r-n];if(e.chained&&e.rest&&n&&(l=i.slice(r-n,r+1).filter(o=>o).join("/"),n=0),l===void 0){e.rest&&(a[e.name]="");continue}if(!e.matcher||f[e.matcher](l)){a[e.name]=l;const o=s[r+1],u=i[r+1];o&&!o.rest&&o.optional&&u&&e.chained&&(n=0),!o&&!u&&Object.keys(a).length===c.length&&(n=0);continue}if(e.optional&&e.chained){n++;continue}return}if(!n)return a}function h(t){return t.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}const b=/\[(\[)?(\.\.\.)?(\w+?)(?:=(\w+))?\]\]?/g;function k(t,s){return"/"+m(t).map(a=>a.replace(b,(i,c,n,r)=>{const e=s[r];if(!e){if(c||n&&e!==void 0)return"";throw new Error(`Missing parameter '${r}' in route ${t}`)}if(e.startsWith("/")||e.endsWith("/"))throw new Error(`Parameter '${r}' in route ${t} cannot start or end with a slash -- this would cause an invalid route like foo//bar`);return e})).filter(Boolean).join("/")}const v=globalThis.__sveltekit_mlwef0?.base??"/ui",C=globalThis.__sveltekit_mlwef0?.assets??v;export{C as a,v as b,j as e,x as p,k as r};

View file

@ -1 +1 @@
import{F as w}from"./DniTuB_0.js";import{g as r}from"./CKHGi7RD.js";const m=!0,z=m,I=()=>window.location.port==="5173",b={isAuthenticated:!1,user:null,loading:!0,needsInitialization:!1},n=w(b);function f(t,a,e=7){const i=new Date;i.setTime(i.getTime()+e*24*60*60*1e3),document.cookie=`${t}=${a};expires=${i.toUTCString()};path=/;SameSite=Lax`}function d(t){const a=t+"=",e=document.cookie.split(";");for(let i=0;i<e.length;i++){let o=e[i];for(;o.charAt(0)===" ";)o=o.substring(1,o.length);if(o.indexOf(a)===0)return o.substring(a.length,o.length)}return null}function g(t){document.cookie=`${t}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/`}const c={async login(t,a){try{n.update(i=>({...i,loading:!0}));const e=await r.login({username:t,password:a});z&&(f("garm_token",e.token),f("garm_user",t)),r.setToken(e.token),n.set({isAuthenticated:!0,user:t,loading:!1,needsInitialization:!1})}catch(e){throw n.update(i=>({...i,loading:!1})),e}},logout(){g("garm_token"),g("garm_user"),n.set({isAuthenticated:!1,user:null,loading:!1,needsInitialization:!1})},async init(){try{n.update(e=>({...e,loading:!0})),await c.checkInitializationStatus();const t=d("garm_token"),a=d("garm_user");if(t&&a&&(r.setToken(t),await c.checkAuth())){n.set({isAuthenticated:!0,user:a,loading:!1,needsInitialization:!1});return}n.update(e=>({...e,loading:!1,needsInitialization:!1}))}catch{n.update(a=>({...a,loading:!1}))}},async checkInitializationStatus(){try{const t={Accept:"application/json"},a=d("garm_token"),e=I();e&&a&&(t.Authorization=`Bearer ${a}`);const i=await fetch("/api/v1/login",{method:"GET",headers:t,credentials:e?"omit":"include"});if(!i.ok){if(i.status===409&&(await i.json()).error==="init_required")throw n.update(s=>({...s,needsInitialization:!0,loading:!1})),new Error("Initialization required");return}return}catch(t){if(t instanceof Error&&t.message==="Initialization required")throw t;return}},async checkAuth(){try{return await c.checkInitializationStatus(),await r.getControllerInfo(),!0}catch(t){return t instanceof Error&&t.message==="Initialization required"?!1:t?.response?.status===409&&t?.response?.data?.error==="init_required"?(n.update(a=>({...a,needsInitialization:!0,loading:!1})),!1):(c.logout(),!1)}},async initialize(t,a,e,i,o){try{n.update(u=>({...u,loading:!0}));const s=await r.firstRun({username:t,email:a,password:e,full_name:i||t});await c.login(t,e);const l=window.location.origin,h=o?.metadataUrl||`${l}/api/v1/metadata`,p=o?.callbackUrl||`${l}/api/v1/callbacks`,k=o?.webhookUrl||`${l}/webhooks`;await r.updateController({metadata_url:h,callback_url:p,webhook_url:k}),n.update(u=>({...u,needsInitialization:!1}))}catch(s){throw n.update(l=>({...l,loading:!1})),s}}};export{n as a,c as b};
import{F as w}from"./DniTuB_0.js";import{g as r}from"./DD3srElq.js";const m=!0,z=m,I=()=>window.location.port==="5173",b={isAuthenticated:!1,user:null,loading:!0,needsInitialization:!1},n=w(b);function f(t,a,e=7){const i=new Date;i.setTime(i.getTime()+e*24*60*60*1e3),document.cookie=`${t}=${a};expires=${i.toUTCString()};path=/;SameSite=Lax`}function d(t){const a=t+"=",e=document.cookie.split(";");for(let i=0;i<e.length;i++){let o=e[i];for(;o.charAt(0)===" ";)o=o.substring(1,o.length);if(o.indexOf(a)===0)return o.substring(a.length,o.length)}return null}function g(t){document.cookie=`${t}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/`}const c={async login(t,a){try{n.update(i=>({...i,loading:!0}));const e=await r.login({username:t,password:a});z&&(f("garm_token",e.token),f("garm_user",t)),r.setToken(e.token),n.set({isAuthenticated:!0,user:t,loading:!1,needsInitialization:!1})}catch(e){throw n.update(i=>({...i,loading:!1})),e}},logout(){g("garm_token"),g("garm_user"),n.set({isAuthenticated:!1,user:null,loading:!1,needsInitialization:!1})},async init(){try{n.update(e=>({...e,loading:!0})),await c.checkInitializationStatus();const t=d("garm_token"),a=d("garm_user");if(t&&a&&(r.setToken(t),await c.checkAuth())){n.set({isAuthenticated:!0,user:a,loading:!1,needsInitialization:!1});return}n.update(e=>({...e,loading:!1,needsInitialization:!1}))}catch{n.update(a=>({...a,loading:!1}))}},async checkInitializationStatus(){try{const t={Accept:"application/json"},a=d("garm_token"),e=I();e&&a&&(t.Authorization=`Bearer ${a}`);const i=await fetch("/api/v1/login",{method:"GET",headers:t,credentials:e?"omit":"include"});if(!i.ok){if(i.status===409&&(await i.json()).error==="init_required")throw n.update(s=>({...s,needsInitialization:!0,loading:!1})),new Error("Initialization required");return}return}catch(t){if(t instanceof Error&&t.message==="Initialization required")throw t;return}},async checkAuth(){try{return await c.checkInitializationStatus(),await r.getControllerInfo(),!0}catch(t){return t instanceof Error&&t.message==="Initialization required"?!1:t?.response?.status===409&&t?.response?.data?.error==="init_required"?(n.update(a=>({...a,needsInitialization:!0,loading:!1})),!1):(c.logout(),!1)}},async initialize(t,a,e,i,o){try{n.update(u=>({...u,loading:!0}));const s=await r.firstRun({username:t,email:a,password:e,full_name:i||t});await c.login(t,e);const l=window.location.origin,h=o?.metadataUrl||`${l}/api/v1/metadata`,p=o?.callbackUrl||`${l}/api/v1/callbacks`,k=o?.webhookUrl||`${l}/webhooks`;await r.updateController({metadata_url:h,callback_url:p,webhook_url:k}),n.update(u=>({...u,needsInitialization:!1}))}catch(s){throw n.update(l=>({...l,loading:!1})),s}}};export{n as a,c as b};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as F}from"./TJn6xDN9.js";import{p as G,E as I,f as x,t as _,b as r,c as J,d as s,r as i,s as k,u as K,e as f,A as N,a as O,z as Q,D as R}from"./DniTuB_0.js";import{p as o,i as b}from"./DbNhg6mG.js";import{e as S,f as T,B as U}from"./CKHGi7RD.js";var V=x('<div class="mt-4 sm:mt-0 flex items-center space-x-4"><!></div>'),W=x('<div class="mt-4 sm:mt-0 flex items-center space-x-4"><!></div>'),X=x('<div class="sm:flex sm:items-center sm:justify-between"><div><h1 class="text-2xl font-bold text-gray-900 dark:text-white"> </h1> <p class="mt-2 text-sm text-gray-700 dark:text-gray-300"> </p></div> <!></div>');function st(g,t){const w=S(t);G(t,!1);const y=I();let A=o(t,"title",8),P=o(t,"description",8),h=o(t,"actionLabel",8,null),j=o(t,"showAction",8,!0);function z(){y("action")}F();var n=X(),l=s(n),c=s(l),B=s(c,!0);i(c);var p=k(c,2),D=s(p,!0);i(p),i(l);var E=k(l,2);{var H=e=>{var a=V(),v=s(a);T(v,t,"actions",{}),i(a),r(e,a)},L=e=>{var a=N(),v=O(a);{var M=d=>{var m=W(),q=s(m);U(q,{variant:"primary",icon:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />',$$events:{click:z},children:(C,Y)=>{Q();var u=R();_(()=>f(u,h())),r(C,u)},$$slots:{default:!0}}),i(m),r(d,m)};b(v,d=>{j()&&h()&&d(M)},!0)}r(e,a)};b(E,e=>{K(()=>w.actions)?e(H):e(L,!1)})}i(n),_(()=>{f(B,A()),f(D,P())}),r(g,n),J()}export{st as P};
import"./DsnmJJEf.js";import{i as F}from"./TJn6xDN9.js";import{p as G,E as I,f as x,t as _,b as r,c as J,d as s,r as i,s as k,u as K,e as f,A as N,a as O,z as Q,D as R}from"./DniTuB_0.js";import{p as o,i as b}from"./DbNhg6mG.js";import{e as S,f as T,B as U}from"./DD3srElq.js";var V=x('<div class="mt-4 sm:mt-0 flex items-center space-x-4"><!></div>'),W=x('<div class="mt-4 sm:mt-0 flex items-center space-x-4"><!></div>'),X=x('<div class="sm:flex sm:items-center sm:justify-between"><div><h1 class="text-2xl font-bold text-gray-900 dark:text-white"> </h1> <p class="mt-2 text-sm text-gray-700 dark:text-gray-300"> </p></div> <!></div>');function st(g,t){const w=S(t);G(t,!1);const y=I();let A=o(t,"title",8),P=o(t,"description",8),h=o(t,"actionLabel",8,null),j=o(t,"showAction",8,!0);function z(){y("action")}F();var n=X(),l=s(n),c=s(l),B=s(c,!0);i(c);var p=k(c,2),D=s(p,!0);i(p),i(l);var E=k(l,2);{var H=e=>{var a=V(),v=s(a);T(v,t,"actions",{}),i(a),r(e,a)},L=e=>{var a=N(),v=O(a);{var M=d=>{var m=W(),q=s(m);U(q,{variant:"primary",icon:'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />',$$events:{click:z},children:(C,Y)=>{Q();var u=R();_(()=>f(u,h())),r(C,u)},$$slots:{default:!0}}),i(m),r(d,m)};b(v,d=>{j()&&h()&&d(M)},!0)}r(e,a)};b(E,e=>{K(()=>w.actions)?e(H):e(L,!1)})}i(n),_(()=>{f(B,A()),f(D,P())}),r(g,n),J()}export{st as P};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import"./TJn6xDN9.js";import{f as k,d as a,s as m,r as i,t as g,e as f,b as v,z as p,D as z}from"./DniTuB_0.js";import{p as t,i as u}from"./DbNhg6mG.js";import{s as Y,h as Z,B as H}from"./CKHGi7RD.js";var $=k('<div class="flex-shrink-0"><!></div>'),ee=k('<div class="mt-4 sm:mt-0 flex space-x-3"><!> <!></div>'),te=k('<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 se(j,e){let E=t(e,"title",8),M=t(e,"subtitle",8),D=t(e,"forgeIcon",8,""),h=t(e,"onEdit",8,null),x=t(e,"onDelete",8,null),B=t(e,"editLabel",8,"Edit"),C=t(e,"deleteLabel",8,"Delete"),P=t(e,"editVariant",8,"secondary"),A=t(e,"deleteVariant",8,"danger"),q=t(e,"editDisabled",8,!1),F=t(e,"deleteDisabled",8,!1),G=t(e,"editIcon",8,"<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'/>"),J=t(e,"deleteIcon",8,"<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'/>"),K=t(e,"titleClass",8,"");var _=te(),y=a(_),w=a(y),b=a(w),I=a(b);{var N=l=>{var d=$(),c=a(d);Z(c,D),i(d),v(l,d)};u(I,l=>{D()&&l(N)})}var L=m(I,2),o=a(L),O=a(o,!0);i(o);var V=m(o,2),Q=a(V,!0);i(V),i(L),i(b);var R=m(b,2);{var S=l=>{var d=ee(),c=a(d);{var T=r=>{H(r,{get variant(){return P()},size:"md",get disabled(){return q()},get icon(){return G()},$$events:{click(...s){h()?.apply(this,s)}},children:(s,X)=>{p();var n=z();g(()=>f(n,B())),v(s,n)},$$slots:{default:!0}})};u(c,r=>{h()&&r(T)})}var U=m(c,2);{var W=r=>{H(r,{get variant(){return A()},size:"md",get disabled(){return F()},get icon(){return J()},$$events:{click(...s){x()?.apply(this,s)}},children:(s,X)=>{p();var n=z();g(()=>f(n,C())),v(s,n)},$$slots:{default:!0}})};u(U,r=>{x()&&r(W)})}i(d),v(l,d)};u(R,l=>{(h()||x())&&l(S)})}i(w),i(y),i(_),g(()=>{Y(o,1,`text-2xl font-bold text-gray-900 dark:text-white ${K()??""}`),f(O,E()),f(Q,M())}),v(j,_)}export{se as D};
import"./DsnmJJEf.js";import"./TJn6xDN9.js";import{f as k,d as a,s as m,r as i,t as g,e as f,b as v,z as p,D as z}from"./DniTuB_0.js";import{p as t,i as u}from"./DbNhg6mG.js";import{s as Y,h as Z,B as H}from"./DD3srElq.js";var $=k('<div class="flex-shrink-0"><!></div>'),ee=k('<div class="mt-4 sm:mt-0 flex space-x-3"><!> <!></div>'),te=k('<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 se(j,e){let E=t(e,"title",8),M=t(e,"subtitle",8),D=t(e,"forgeIcon",8,""),h=t(e,"onEdit",8,null),x=t(e,"onDelete",8,null),B=t(e,"editLabel",8,"Edit"),C=t(e,"deleteLabel",8,"Delete"),P=t(e,"editVariant",8,"secondary"),A=t(e,"deleteVariant",8,"danger"),q=t(e,"editDisabled",8,!1),F=t(e,"deleteDisabled",8,!1),G=t(e,"editIcon",8,"<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'/>"),J=t(e,"deleteIcon",8,"<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'/>"),K=t(e,"titleClass",8,"");var _=te(),y=a(_),w=a(y),b=a(w),I=a(b);{var N=l=>{var d=$(),c=a(d);Z(c,D),i(d),v(l,d)};u(I,l=>{D()&&l(N)})}var L=m(I,2),o=a(L),O=a(o,!0);i(o);var V=m(o,2),Q=a(V,!0);i(V),i(L),i(b);var R=m(b,2);{var S=l=>{var d=ee(),c=a(d);{var T=r=>{H(r,{get variant(){return P()},size:"md",get disabled(){return q()},get icon(){return G()},$$events:{click(...s){h()?.apply(this,s)}},children:(s,X)=>{p();var n=z();g(()=>f(n,B())),v(s,n)},$$slots:{default:!0}})};u(c,r=>{h()&&r(T)})}var U=m(c,2);{var W=r=>{H(r,{get variant(){return A()},size:"md",get disabled(){return F()},get icon(){return J()},$$events:{click(...s){x()?.apply(this,s)}},children:(s,X)=>{p();var n=z();g(()=>f(n,C())),v(s,n)},$$slots:{default:!0}})};u(U,r=>{x()&&r(W)})}i(d),v(l,d)};u(R,l=>{(h()||x())&&l(S)})}i(w),i(y),i(_),g(()=>{Y(o,1,`text-2xl font-bold text-gray-900 dark:text-white ${K()??""}`),f(O,E()),f(Q,M())}),v(j,_)}export{se as D};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as ae}from"./TJn6xDN9.js";import{p as se,E as re,l as M,q as ie,k as r,g as t,m as k,h as le,f as p,d as v,s as A,r as f,b as l,c as oe,A as T,a as B,z as q,D as V,t as E,e as F,u as ne}from"./DniTuB_0.js";import{p as N,i as m}from"./DbNhg6mG.js";import{g as h,B as G}from"./CKHGi7RD.js";import{t as y}from"./CBJzOE8U.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),he=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 _e(H,g){se(g,!1);const x=k();let u=N(g,"entityType",8),s=N(g,"entityId",8),R=N(g,"entityName",8),i=k(null),o=k(!1),b=k(!0);const O=re();async function _(){if(s())try{r(b,!0),u()==="repository"?r(i,await h.getRepositoryWebhookInfo(s())):r(i,await h.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),u()==="repository"?await h.installRepositoryWebhook(s()):await h.installOrganizationWebhook(s()),y.success("Webhook Installed",`Webhook for ${u()} ${R()} 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),u()==="repository"?await h.uninstallRepositoryWebhook(s()):await h.uninstallOrganizationWebhook(s()),y.success("Webhook Uninstalled",`Webhook for ${u()} ${R()} has been uninstalled successfully.`),await _(),O("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=ue(),P=v(w),j=v(P),W=v(j),D=A(v(W),2),Q=v(D);{var X=e=>{var d=ce();l(e,d)},Y=e=>{var d=T(),z=B(d);{var I=a=>{var n=fe(),C=A(B(n),2);{var c=U=>{var $=ve(),te=v($);f($),E(()=>F(te,`URL: ${t(i),ne(()=>t(i).url||"N/A")??""}`)),l(U,$)};m(C,U=>{t(i)&&U(c)})}l(a,n)},S=a=>{var n=he();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=A(W,2),Z=v(L);{var ee=e=>{var d=T(),z=B(d);{var I=a=>{G(a,{variant:"danger",size:"sm",get disabled(){return t(o)},$$events:{click:K},children:(n,C)=>{q();var c=V();E(()=>F(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,C)=>{q();var c=V();E(()=>F(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(j),f(P),f(w),l(H,w),oe()}export{_e as W};
import"./DsnmJJEf.js";import{i as ae}from"./TJn6xDN9.js";import{p as se,E as re,l as M,q as ie,k as r,g as t,m as k,h as le,f as p,d as v,s as A,r as f,b as l,c as oe,A as T,a as B,z as q,D as V,t as E,e as F,u as ne}from"./DniTuB_0.js";import{p as N,i as m}from"./DbNhg6mG.js";import{g as h,B as G}from"./DD3srElq.js";import{t as y}from"./CBJzOE8U.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),he=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 _e(H,g){se(g,!1);const x=k();let u=N(g,"entityType",8),s=N(g,"entityId",8),R=N(g,"entityName",8),i=k(null),o=k(!1),b=k(!0);const O=re();async function _(){if(s())try{r(b,!0),u()==="repository"?r(i,await h.getRepositoryWebhookInfo(s())):r(i,await h.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),u()==="repository"?await h.installRepositoryWebhook(s()):await h.installOrganizationWebhook(s()),y.success("Webhook Installed",`Webhook for ${u()} ${R()} 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),u()==="repository"?await h.uninstallRepositoryWebhook(s()):await h.uninstallOrganizationWebhook(s()),y.success("Webhook Uninstalled",`Webhook for ${u()} ${R()} has been uninstalled successfully.`),await _(),O("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=ue(),P=v(w),j=v(P),W=v(j),D=A(v(W),2),Q=v(D);{var X=e=>{var d=ce();l(e,d)},Y=e=>{var d=T(),z=B(d);{var I=a=>{var n=fe(),C=A(B(n),2);{var c=U=>{var $=ve(),te=v($);f($),E(()=>F(te,`URL: ${t(i),ne(()=>t(i).url||"N/A")??""}`)),l(U,$)};m(C,U=>{t(i)&&U(c)})}l(a,n)},S=a=>{var n=he();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=A(W,2),Z=v(L);{var ee=e=>{var d=T(),z=B(d);{var I=a=>{G(a,{variant:"danger",size:"sm",get disabled(){return t(o)},$$events:{click:K},children:(n,C)=>{q();var c=V();E(()=>F(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,C)=>{q();var c=V();E(()=>F(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(j),f(P),f(w),l(H,w),oe()}export{_e as W};

View file

@ -1 +1 @@
import{s as e}from"./BAMHjnwW.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"./DeKGyprh.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 H}from"./TJn6xDN9.js";import{p as J,l as j,h as K,f as g,t as h,b as k,c as L,s as u,d as r,k as z,m as E,r as a,q as l,u as p,g as _,e as y}from"./DniTuB_0.js";import{p as d,i as I}from"./DbNhg6mG.js";import{c as M,s as P,d as n}from"./CKHGi7RD.js";var Q=g('<div class="group relative flex-shrink-0"><svg class="w-4 h-4 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> <div class="absolute left-0 top-full mt-1 z-10 invisible group-hover:visible opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none w-64"><div class="bg-gray-900 dark:bg-gray-700 text-white text-xs rounded-md px-3 py-2 shadow-lg"><div class="font-semibold mb-1">Description:</div> <div class="whitespace-pre-wrap break-words max-h-32 overflow-y-auto"> </div></div></div></div>'),S=g('<div class="text-sm text-gray-500 dark:text-gray-400 truncate"> </div>'),V=g('<div class="w-full min-w-0 text-sm font-medium"><div class="flex items-center gap-1.5"><a> </a> <!></div> <!></div>');function te(C,i){J(i,!1);const m=E(),b=E();let e=d(i,"item",8),s=d(i,"entityType",8,"repository"),N=d(i,"showOwner",8,!1),O=d(i,"showId",8,!1),T=d(i,"fontMono",8,!1);function q(){if(!e())return"Unknown";switch(s()){case"repository":return N()?`${e().owner||"Unknown"}/${e().name||"Unknown"}`:e().name||"Unknown";case"organization":case"enterprise":return e().name||"Unknown";case"pool":return O()?e().id||"Unknown":e().name||"Unknown";case"scaleset":return e().name||"Unknown";case"instance":return e().name||"Unknown";case"template":return e().name||"Unknown";case"object":return e().name||"Unknown";default:return e().name||e().id||"Unknown"}}function B(){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 n(`/repositories/${t}`);case"organization":return n(`/organizations/${t}`);case"enterprise":return n(`/enterprises/${t}`);case"pool":return n(`/pools/${t}`);case"scaleset":return n(`/scalesets/${t}`);case"instance":return n(`/instances/${encodeURIComponent(t)}`);case"template":return n(`/templates/${t}`);case"object":return n(`/objects/${t}`);default:return"#"}}j(()=>{},()=>{z(m,q())}),j(()=>{},()=>{z(b,B())}),K(),H();var f=V(),w=r(f),c=r(w),D=r(c,!0);a(c);var R=u(c,2);{var $=t=>{var o=Q(),v=u(r(o),2),x=r(v),U=u(r(x),2),G=r(U,!0);a(U),a(x),a(v),a(o),h(()=>y(G,(l(e()),p(()=>e().description)))),k(t,o)};I(R,t=>{l(s()),l(e()),p(()=>s()==="object"&&e()?.description)&&t($)})}a(w);var A=u(w,2);{var F=t=>{var o=S(),v=r(o,!0);a(o),h(()=>y(v,(l(e()),p(()=>e().provider_id)))),k(t,o)};I(A,t=>{l(s()),l(e()),p(()=>s()==="instance"&&e()?.provider_id)&&t(F)})}a(f),h(()=>{M(c,"href",_(b)),P(c,1,`truncate text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 ${T()?"font-mono":""}`),M(c,"title",_(m)),y(D,_(m))}),k(C,f),L()}export{te as E};
import"./DsnmJJEf.js";import{i as H}from"./TJn6xDN9.js";import{p as J,l as j,h as K,f as g,t as h,b as k,c as L,s as u,d as r,k as z,m as E,r as a,q as l,u as p,g as _,e as y}from"./DniTuB_0.js";import{p as d,i as I}from"./DbNhg6mG.js";import{c as M,s as P,d as n}from"./DD3srElq.js";var Q=g('<div class="group relative flex-shrink-0"><svg class="w-4 h-4 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> <div class="absolute left-0 top-full mt-1 z-10 invisible group-hover:visible opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none w-64"><div class="bg-gray-900 dark:bg-gray-700 text-white text-xs rounded-md px-3 py-2 shadow-lg"><div class="font-semibold mb-1">Description:</div> <div class="whitespace-pre-wrap break-words max-h-32 overflow-y-auto"> </div></div></div></div>'),S=g('<div class="text-sm text-gray-500 dark:text-gray-400 truncate"> </div>'),V=g('<div class="w-full min-w-0 text-sm font-medium"><div class="flex items-center gap-1.5"><a> </a> <!></div> <!></div>');function te(C,i){J(i,!1);const m=E(),b=E();let e=d(i,"item",8),s=d(i,"entityType",8,"repository"),N=d(i,"showOwner",8,!1),O=d(i,"showId",8,!1),T=d(i,"fontMono",8,!1);function q(){if(!e())return"Unknown";switch(s()){case"repository":return N()?`${e().owner||"Unknown"}/${e().name||"Unknown"}`:e().name||"Unknown";case"organization":case"enterprise":return e().name||"Unknown";case"pool":return O()?e().id||"Unknown":e().name||"Unknown";case"scaleset":return e().name||"Unknown";case"instance":return e().name||"Unknown";case"template":return e().name||"Unknown";case"object":return e().name||"Unknown";default:return e().name||e().id||"Unknown"}}function B(){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 n(`/repositories/${t}`);case"organization":return n(`/organizations/${t}`);case"enterprise":return n(`/enterprises/${t}`);case"pool":return n(`/pools/${t}`);case"scaleset":return n(`/scalesets/${t}`);case"instance":return n(`/instances/${encodeURIComponent(t)}`);case"template":return n(`/templates/${t}`);case"object":return n(`/objects/${t}`);default:return"#"}}j(()=>{},()=>{z(m,q())}),j(()=>{},()=>{z(b,B())}),K(),H();var f=V(),w=r(f),c=r(w),D=r(c,!0);a(c);var R=u(c,2);{var $=t=>{var o=Q(),v=u(r(o),2),x=r(v),U=u(r(x),2),G=r(U,!0);a(U),a(x),a(v),a(o),h(()=>y(G,(l(e()),p(()=>e().description)))),k(t,o)};I(R,t=>{l(s()),l(e()),p(()=>s()==="object"&&e()?.description)&&t($)})}a(w);var A=u(w,2);{var F=t=>{var o=S(),v=r(o,!0);a(o),h(()=>y(v,(l(e()),p(()=>e().provider_id)))),k(t,o)};I(A,t=>{l(s()),l(e()),p(()=>s()==="instance"&&e()?.provider_id)&&t(F)})}a(f),h(()=>{M(c,"href",_(b)),P(c,1,`truncate text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 ${T()?"font-mono":""}`),M(c,"title",_(m)),y(D,_(m))}),k(C,f),L()}export{te as E};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as j}from"./TJn6xDN9.js";import{p as E,E as G,f as S,d as t,r,s as g,u,q as p,z as m,t as q,e as z,i as f,b as D,c as H}from"./DniTuB_0.js";import{h as y,s as h}from"./CKHGi7RD.js";import{p as v}from"./DbNhg6mG.js";import{g as o}from"./YbkgTiK_.js";var I=S('<fieldset><legend class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> </legend> <div class="grid grid-cols-2 gap-4"><button type="button"><!> <span class="mt-2 text-sm font-medium text-gray-900 dark:text-white">GitHub</span></button> <button type="button"><!> <span class="mt-2 text-sm font-medium text-gray-900 dark:text-white">Gitea</span></button></div></fieldset>');function M(x,s){E(s,!1);const k=G();let i=v(s,"selectedForgeType",12,""),_=v(s,"label",8,"Select Forge Type");function n(c){i(c),k("select",c)}j();var d=I(),l=t(d),F=t(l,!0);r(l);var b=g(l,2),e=t(b),w=t(e);y(w,()=>(p(o),u(()=>o("github","w-8 h-8")))),m(2),r(e);var a=g(e,2),T=t(a);y(T,()=>(p(o),u(()=>o("gitea","w-8 h-8")))),m(2),r(a),r(b),r(d),q(()=>{z(F,_()),h(e,1,`flex flex-col items-center justify-center p-6 border-2 rounded-lg transition-colors cursor-pointer ${i()==="github"?"border-blue-500 bg-blue-50 dark:bg-blue-900":"border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"}`),h(a,1,`flex flex-col items-center justify-center p-6 border-2 rounded-lg transition-colors cursor-pointer ${i()==="gitea"?"border-blue-500 bg-blue-50 dark:bg-blue-900":"border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"}`)}),f("click",e,()=>n("github")),f("click",a,()=>n("gitea")),D(x,d),H()}export{M as F};
import"./DsnmJJEf.js";import{i as j}from"./TJn6xDN9.js";import{p as E,E as G,f as S,d as t,r,s as g,u,q as p,z as m,t as q,e as z,i as f,b as D,c as H}from"./DniTuB_0.js";import{h as y,s as h}from"./DD3srElq.js";import{p as v}from"./DbNhg6mG.js";import{g as o}from"./LMA6-4d1.js";var I=S('<fieldset><legend class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> </legend> <div class="grid grid-cols-2 gap-4"><button type="button"><!> <span class="mt-2 text-sm font-medium text-gray-900 dark:text-white">GitHub</span></button> <button type="button"><!> <span class="mt-2 text-sm font-medium text-gray-900 dark:text-white">Gitea</span></button></div></fieldset>');function M(x,s){E(s,!1);const k=G();let i=v(s,"selectedForgeType",12,""),_=v(s,"label",8,"Select Forge Type");function n(c){i(c),k("select",c)}j();var d=I(),l=t(d),F=t(l,!0);r(l);var b=g(l,2),e=t(b),w=t(e);y(w,()=>(p(o),u(()=>o("github","w-8 h-8")))),m(2),r(e);var a=g(e,2),T=t(a);y(T,()=>(p(o),u(()=>o("gitea","w-8 h-8")))),m(2),r(a),r(b),r(d),q(()=>{z(F,_()),h(e,1,`flex flex-col items-center justify-center p-6 border-2 rounded-lg transition-colors cursor-pointer ${i()==="github"?"border-blue-500 bg-blue-50 dark:bg-blue-900":"border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"}`),h(a,1,`flex flex-col items-center justify-center p-6 border-2 rounded-lg transition-colors cursor-pointer ${i()==="gitea"?"border-blue-500 bg-blue-50 dark:bg-blue-900":"border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"}`)}),f("click",e,()=>n("github")),f("click",a,()=>n("gitea")),D(x,d),H()}export{M as F};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as _}from"./TJn6xDN9.js";import{p as k,f as E,t as C,u as i,q as t,e as f,b as P,c as j,s as q,d as l,r as o}from"./DniTuB_0.js";import{c as z}from"./CKHGi7RD.js";import{p as n}from"./DbNhg6mG.js";import{j as x,e as c,i as u}from"./YbkgTiK_.js";var N=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 F(d,r){k(r,!1);let e=n(r,"item",8),m=n(r,"eagerCache",8,null);_();var s=N(),a=l(s),v=l(a,!0);o(a);var p=q(a,2),g=l(p,!0);o(p),o(s),C((h,b,y)=>{z(a,"href",h),f(v,b),f(g,y)},[()=>(t(x),t(e()),i(()=>x(e()))),()=>(t(c),t(e()),t(m()),i(()=>c(e(),m()))),()=>(t(u),t(e()),i(()=>u(e())))]),P(d,s),j()}export{F as P};
import"./DsnmJJEf.js";import{i as _}from"./TJn6xDN9.js";import{p as k,f as E,t as C,u as i,q as t,e as f,b as P,c as j,s as q,d as l,r as o}from"./DniTuB_0.js";import{c as z}from"./DD3srElq.js";import{p as n}from"./DbNhg6mG.js";import{j as x,e as c,i as u}from"./LMA6-4d1.js";var N=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 F(d,r){k(r,!1);let e=n(r,"item",8),m=n(r,"eagerCache",8,null);_();var s=N(),a=l(s),v=l(a,!0);o(a);var p=q(a,2),g=l(p,!0);o(p),o(s),C((h,b,y)=>{z(a,"href",h),f(v,b),f(g,y)},[()=>(t(x),t(e()),i(()=>x(e()))),()=>(t(c),t(e()),t(m()),i(()=>c(e(),m()))),()=>(t(u),t(e()),i(()=>u(e())))]),P(d,s),j()}export{F as P};

View file

@ -1,4 +1,4 @@
import"./DsnmJJEf.js";import{i as g}from"./TJn6xDN9.js";import{p as x,l as k,k as d,m as w,q as y,h as J,f as b,d as z,x as L,s as j,g as c,r as q,t as B,b as f,c as C}from"./DniTuB_0.js";import{p as o,i as E}from"./DbNhg6mG.js";import{c as n,s as M}from"./CKHGi7RD.js";import{b as N}from"./CCQwxxp9.js";var O=b('<div class="absolute top-2 right-2"><svg class="w-4 h-4 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg></div>'),S=b('<div class="relative"><textarea style="tab-size: 2;" spellcheck="false"></textarea> <!></div>');function I(m,r){x(r,!1);let t=o(r,"value",12,""),p=o(r,"placeholder",8,"{}"),u=o(r,"rows",8,4),i=o(r,"disabled",8,!1),a=w(!0);k(()=>y(t()),()=>{if(t().trim())try{JSON.parse(t()),d(a,!0)}catch{d(a,!1)}else d(a,!0)}),J(),g();var l=S(),e=z(l);L(e);var v=j(e,2);{var h=s=>{var _=O();f(s,_)};E(v,s=>{c(a)||s(h)})}q(l),B(()=>{n(e,"placeholder",p()),n(e,"rows",u()),e.disabled=i(),M(e,1,`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 font-mono text-sm resize-none
import"./DsnmJJEf.js";import{i as g}from"./TJn6xDN9.js";import{p as x,l as k,k as d,m as w,q as y,h as J,f as b,d as z,x as L,s as j,g as c,r as q,t as B,b as f,c as C}from"./DniTuB_0.js";import{p as o,i as E}from"./DbNhg6mG.js";import{c as n,s as M}from"./DD3srElq.js";import{b as N}from"./CCQwxxp9.js";var O=b('<div class="absolute top-2 right-2"><svg class="w-4 h-4 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg></div>'),S=b('<div class="relative"><textarea style="tab-size: 2;" spellcheck="false"></textarea> <!></div>');function I(m,r){x(r,!1);let t=o(r,"value",12,""),p=o(r,"placeholder",8,"{}"),u=o(r,"rows",8,4),i=o(r,"disabled",8,!1),a=w(!0);k(()=>y(t()),()=>{if(t().trim())try{JSON.parse(t()),d(a,!0)}catch{d(a,!1)}else d(a,!0)}),J(),g();var l=S(),e=z(l);L(e);var v=j(e,2);{var h=s=>{var _=O();f(s,_)};E(v,s=>{c(a)||s(h)})}q(l),B(()=>{n(e,"placeholder",p()),n(e,"rows",u()),e.disabled=i(),M(e,1,`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 font-mono text-sm resize-none
${c(a)?"border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white":"border-red-300 dark:border-red-600 bg-red-50 dark:bg-red-900/20 text-red-900 dark:text-red-100"}
${i()?"opacity-50 cursor-not-allowed":""}
`)}),N(e,t),f(m,l),C()}export{I as J};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as k}from"./TJn6xDN9.js";import{p as c,l as u,q as g,h as f,f as m,t as p,b as w,c as _,k as v,m as h,d as z,r as B,g as j,e as q}from"./DniTuB_0.js";import{s as V,j as A}from"./CKHGi7RD.js";import{p as a}from"./DbNhg6mG.js";var C=m("<span> </span>");function I(d,e){c(e,!1);const n=h();let t=a(e,"variant",8,"gray"),l=a(e,"size",8,"sm"),i=a(e,"text",8),s=a(e,"ring",8,!1);const o={success:"bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200",error:"bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200",warning:"bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200",info:"bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200",gray:"bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200",blue:"bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200",green:"bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200",red:"bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200",yellow:"bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200",secondary:"bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200"},b={success:"ring-green-600/20 dark:ring-green-400/30",error:"ring-red-600/20 dark:ring-red-400/30",warning:"ring-yellow-600/20 dark:ring-yellow-400/30",info:"ring-blue-600/20 dark:ring-blue-400/30",gray:"ring-gray-500/20 dark:ring-gray-400/30",blue:"ring-blue-600/20 dark:ring-blue-400/30",green:"ring-green-600/20 dark:ring-green-400/30",red:"ring-red-600/20 dark:ring-red-400/30",yellow:"ring-yellow-600/20 dark:ring-yellow-400/30",secondary:"ring-gray-500/20 dark:ring-gray-400/30"},y={sm:"px-2 py-1 text-xs",md:"px-2.5 py-0.5 text-xs"};u(()=>(g(t()),g(l()),g(s())),()=>{v(n,["inline-flex items-center rounded-full font-semibold",o[t()],y[l()],s()?`ring-1 ring-inset ${b[t()]}`:""].filter(Boolean).join(" "))}),f(),k();var r=C(),x=z(r,!0);B(r),p(()=>{V(r,1,A(j(n))),q(x,i())}),w(d,r),_()}export{I as B};
import"./DsnmJJEf.js";import{i as k}from"./TJn6xDN9.js";import{p as c,l as u,q as g,h as f,f as m,t as p,b as w,c as _,k as v,m as h,d as z,r as B,g as j,e as q}from"./DniTuB_0.js";import{s as V,j as A}from"./DD3srElq.js";import{p as a}from"./DbNhg6mG.js";var C=m("<span> </span>");function I(d,e){c(e,!1);const n=h();let t=a(e,"variant",8,"gray"),l=a(e,"size",8,"sm"),i=a(e,"text",8),s=a(e,"ring",8,!1);const o={success:"bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200",error:"bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200",warning:"bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200",info:"bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200",gray:"bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200",blue:"bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200",green:"bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200",red:"bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200",yellow:"bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200",secondary:"bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200"},b={success:"ring-green-600/20 dark:ring-green-400/30",error:"ring-red-600/20 dark:ring-red-400/30",warning:"ring-yellow-600/20 dark:ring-yellow-400/30",info:"ring-blue-600/20 dark:ring-blue-400/30",gray:"ring-gray-500/20 dark:ring-gray-400/30",blue:"ring-blue-600/20 dark:ring-blue-400/30",green:"ring-green-600/20 dark:ring-green-400/30",red:"ring-red-600/20 dark:ring-red-400/30",yellow:"ring-yellow-600/20 dark:ring-yellow-400/30",secondary:"ring-gray-500/20 dark:ring-gray-400/30"},y={sm:"px-2 py-1 text-xs",md:"px-2.5 py-0.5 text-xs"};u(()=>(g(t()),g(l()),g(s())),()=>{v(n,["inline-flex items-center rounded-full font-semibold",o[t()],y[l()],s()?`ring-1 ring-inset ${b[t()]}`:""].filter(Boolean).join(" "))}),f(),k();var r=C(),x=z(r,!0);B(r),p(()=>{V(r,1,A(j(n))),q(x,i())}),w(d,r),_()}export{I as B};

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as v}from"./TJn6xDN9.js";import{p as w,l as m,q as s,g as r,m as g,h as x,A as h,a as T,b as S,c as A,k,u}from"./DniTuB_0.js";import{k as B}from"./DSa_5ZRu.js";import{p}from"./DbNhg6mG.js";import{B as C}from"./7xg7bIQm.js";import{k as b}from"./YbkgTiK_.js";import{f as E}from"./ow_oMtSd.js";function z(_,i){w(i,!1);const c=g(),n=g();let e=p(i,"item",8),d=p(i,"statusType",8,"entity"),a=p(i,"statusField",8,"status");m(()=>(s(e()),s(a())),()=>{k(c,e()?.[a()]||"unknown")}),m(()=>(s(e()),s(d()),r(c),s(a())),()=>{k(n,(()=>{if(!e())return{variant:"error",text:"Unknown"};switch(d()){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 l=h(),y=T(l);B(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)}})}),S(_,l),A()}export{z as S};
import"./DsnmJJEf.js";import{i as v}from"./TJn6xDN9.js";import{p as w,l as m,q as s,g as r,m as g,h as x,A as h,a as T,b as S,c as A,k,u}from"./DniTuB_0.js";import{k as B}from"./QtGwBUod.js";import{p}from"./DbNhg6mG.js";import{B as C}from"./DcQdHuVc.js";import{k as b}from"./LMA6-4d1.js";import{f as E}from"./ow_oMtSd.js";function z(_,i){w(i,!1);const c=g(),n=g();let e=p(i,"item",8),d=p(i,"statusType",8,"entity"),a=p(i,"statusField",8,"status");m(()=>(s(e()),s(a())),()=>{k(c,e()?.[a()]||"unknown")}),m(()=>(s(e()),s(d()),r(c),s(a())),()=>{k(n,(()=>{if(!e())return{variant:"error",text:"Unknown"};switch(d()){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 l=h(),y=T(l);B(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)}})}),S(_,l),A()}export{z as S};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import"./TJn6xDN9.js";import{f as l,s as h,d as n,r as f,t as N,e as w,b as r,A as x,a as y}from"./DniTuB_0.js";import{p,i as b}from"./DbNhg6mG.js";import{s as O}from"./CKHGi7RD.js";var P=l('<div class="absolute top-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-t-gray-900"></div>'),Q=l('<div class="absolute bottom-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-900"></div>'),R=l('<div class="absolute right-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-l-gray-900"></div>'),S=l('<div class="absolute left-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-r-gray-900"></div>'),U=l('<div class="relative group"><svg class="w-3 h-3 text-gray-400 cursor-help" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> <div><div class="font-semibold mb-1"> </div> <div class="text-gray-300"> </div> <!></div></div>');function $(k,s){let z=p(s,"title",8),M=p(s,"content",8),t=p(s,"position",8,"top"),T=p(s,"width",8,"w-80");var m=U(),u=h(n(m),2),_=n(u),j=n(_,!0);f(_);var c=h(_,2),A=n(c,!0);f(c);var B=h(c,2);{var C=a=>{var i=P();r(a,i)},q=a=>{var i=x(),D=y(i);{var E=o=>{var v=Q();r(o,v)},F=o=>{var v=x(),G=y(v);{var H=e=>{var d=R();r(e,d)},I=e=>{var d=x(),J=y(d);{var K=g=>{var L=S();r(g,L)};b(J,g=>{t()==="right"&&g(K)},!0)}r(e,d)};b(G,e=>{t()==="left"?e(H):e(I,!1)},!0)}r(o,v)};b(D,o=>{t()==="bottom"?o(E):o(F,!1)},!0)}r(a,i)};b(B,a=>{t()==="top"?a(C):a(q,!1)})}f(u),f(m),N(()=>{O(u,1,`absolute ${t()==="top"?"bottom-full":t()==="bottom"?"top-full":t()==="left"?"right-full top-1/2 -translate-y-1/2":"left-full top-1/2 -translate-y-1/2"} left-1/2 transform -translate-x-1/2 ${t()==="top"?"mb-2":t()==="bottom"?"mt-2":"mx-2"} ${T()??""} p-3 bg-gray-900 text-white text-xs rounded-lg shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50`),w(j,z()),w(A,M())}),r(k,m)}export{$ as T};
import"./DsnmJJEf.js";import"./TJn6xDN9.js";import{f as l,s as h,d as n,r as f,t as N,e as w,b as r,A as x,a as y}from"./DniTuB_0.js";import{p,i as b}from"./DbNhg6mG.js";import{s as O}from"./DD3srElq.js";var P=l('<div class="absolute top-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-t-gray-900"></div>'),Q=l('<div class="absolute bottom-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-b-gray-900"></div>'),R=l('<div class="absolute right-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-l-gray-900"></div>'),S=l('<div class="absolute left-full top-1/2 transform -translate-y-1/2 border-4 border-transparent border-r-gray-900"></div>'),U=l('<div class="relative group"><svg class="w-3 h-3 text-gray-400 cursor-help" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> <div><div class="font-semibold mb-1"> </div> <div class="text-gray-300"> </div> <!></div></div>');function $(k,s){let z=p(s,"title",8),M=p(s,"content",8),t=p(s,"position",8,"top"),T=p(s,"width",8,"w-80");var m=U(),u=h(n(m),2),_=n(u),j=n(_,!0);f(_);var c=h(_,2),A=n(c,!0);f(c);var B=h(c,2);{var C=a=>{var i=P();r(a,i)},q=a=>{var i=x(),D=y(i);{var E=o=>{var v=Q();r(o,v)},F=o=>{var v=x(),G=y(v);{var H=e=>{var d=R();r(e,d)},I=e=>{var d=x(),J=y(d);{var K=g=>{var L=S();r(g,L)};b(J,g=>{t()==="right"&&g(K)},!0)}r(e,d)};b(G,e=>{t()==="left"?e(H):e(I,!1)},!0)}r(o,v)};b(D,o=>{t()==="bottom"?o(E):o(F,!1)},!0)}r(a,i)};b(B,a=>{t()==="top"?a(C):a(q,!1)})}f(u),f(m),N(()=>{O(u,1,`absolute ${t()==="top"?"bottom-full":t()==="bottom"?"top-full":t()==="left"?"right-full top-1/2 -translate-y-1/2":"left-full top-1/2 -translate-y-1/2"} left-1/2 transform -translate-x-1/2 ${t()==="top"?"mb-2":t()==="bottom"?"mt-2":"mx-2"} ${T()??""} p-3 bg-gray-900 text-white text-xs rounded-lg shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50`),w(j,z()),w(A,M())}),r(k,m)}export{$ as T};

View file

@ -1 +1 @@
import{s as t,p as r}from"./BAMHjnwW.js";const e={get data(){return r.data},get error(){return r.error},get form(){return r.form},get params(){return r.params},get route(){return r.route},get state(){return r.state},get status(){return r.status},get url(){return r.url}};t.updated.check;const s=e;export{s as p};
import{s as t,p as r}from"./DeKGyprh.js";const e={get data(){return r.data},get error(){return r.error},get form(){return r.form},get params(){return r.params},get route(){return r.route},get state(){return r.state},get status(){return r.status},get url(){return r.url}};t.updated.check;const s=e;export{s as p};

View file

@ -1,4 +1,4 @@
import{d as o}from"./CKHGi7RD.js";function l(r){if(!r)return"N/A";try{return(typeof r=="string"?new Date(r):r).toLocaleString()}catch{return"Invalid Date"}}function f(r,e="w-4 h-4"){return r==="gitea"?`<svg class="${e}" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 640 640"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6M125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1m300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8s2 16.3 9.1 20c7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3s17.4 1.7 22.5-5.3c5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8z" style="fill:#609926"/></svg>`:r==="github"?`<div class="inline-flex ${e}"><svg class="${e} dark:hidden" width="98" height="96" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg><svg class="${e} hidden dark:block" width="98" height="96" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg></div>`:`<svg class="${e} text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
import{d as o}from"./DD3srElq.js";function l(r){if(!r)return"N/A";try{return(typeof r=="string"?new Date(r):r).toLocaleString()}catch{return"Invalid Date"}}function f(r,e="w-4 h-4"){return r==="gitea"?`<svg class="${e}" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 640 640"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6M125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1m300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8s2 16.3 9.1 20c7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3s17.4 1.7 22.5-5.3c5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8z" style="fill:#609926"/></svg>`:r==="github"?`<div class="inline-flex ${e}"><svg class="${e} dark:hidden" width="98" height="96" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg><svg class="${e} hidden dark:block" width="98" height="96" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 96"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg></div>`:`<svg class="${e} text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>`}function d(r,e){if(r.repo_name)return r.repo_name;if(r.org_name)return r.org_name;if(r.enterprise_name)return r.enterprise_name;if(r.repo_id&&!r.repo_name&&e?.repositories){const n=e.repositories.find(t=>t.id===r.repo_id);return n?`${n.owner}/${n.name}`:"Unknown Entity"}if(r.org_id&&!r.org_name&&e?.organizations){const n=e.organizations.find(t=>t.id===r.org_id);return n&&n.name?n.name:"Unknown Entity"}if(r.enterprise_id&&!r.enterprise_name&&e?.enterprises){const n=e.enterprises.find(t=>t.id===r.enterprise_id);return n&&n.name?n.name:"Unknown Entity"}return"Unknown Entity"}function p(r){return r.repo_id?"repository":r.org_id?"organization":r.enterprise_id?"enterprise":"unknown"}function g(r){return r.repo_id?o(`/repositories/${r.repo_id}`):r.org_id?o(`/organizations/${r.org_id}`):r.enterprise_id?o(`/enterprises/${r.enterprise_id}`):"#"}function w(r){r&&(r.scrollTop=r.scrollHeight)}function m(r){return{newPerPage:r,newCurrentPage:1}}function v(r){return r.pool_manager_status?.running?{text:"Running",variant:"success"}:{text:"Stopped",variant:"error"}}function _(r){switch(r.toLowerCase()){case"error":return{text:"Error",variant:"error"};case"warning":return{text:"Warning",variant:"warning"};case"info":return{text:"Info",variant:"info"};default:return{text:r,variant:"info"}}}function i(r,e,n){if(!e.trim())return r;const t=e.toLowerCase();return r.filter(s=>typeof n=="function"?n(s).toLowerCase().includes(t):n.some(a=>s[a]?.toString().toLowerCase().includes(t)))}function h(r,e){return i(r,e,["name","owner"])}function x(r,e){return i(r,e,["name"])}function k(r,e){return i(r,e,n=>[n.name||"",n.description||"",n.endpoint?.name||""].join(" "))}function E(r,e){return i(r,e,["name","description","base_url","api_base_url"])}function L(r,e,n){return r.slice((e-1)*n,e*n)}export{E as a,l as b,m as c,_ as d,d as e,k as f,f as g,i as h,p as i,g as j,v as k,x as l,h as m,L as p,w as s};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as u}from"./TJn6xDN9.js";import{p as v,E as m,f as h,d as r,r as d,i as t,b as k,c as g}from"./DniTuB_0.js";import{f as b}from"./CKHGi7RD.js";var w=h('<div class="fixed inset-0 bg-black/30 dark:bg-black/50 overflow-y-auto h-full w-full z-50 flex items-center justify-center p-4" role="dialog" aria-modal="true" tabindex="-1"><div class="relative mx-auto bg-white dark:bg-gray-800 rounded-lg shadow-lg" role="document"><!></div></div>');function M(s,i){v(i,!1);const l=m();function n(){l("close")}function c(o){o.stopPropagation()}function f(o){o.key==="Escape"&&l("close")}u();var a=w(),e=r(a),p=r(e);b(p,i,"default",{}),d(e),d(a),t("click",e,c),t("click",a,n),t("keydown",a,f),k(s,a),g()}export{M};
import"./DsnmJJEf.js";import{i as u}from"./TJn6xDN9.js";import{p as v,E as m,f as h,d as r,r as d,i as t,b as k,c as g}from"./DniTuB_0.js";import{f as b}from"./DD3srElq.js";var w=h('<div class="fixed inset-0 bg-black/30 dark:bg-black/50 overflow-y-auto h-full w-full z-50 flex items-center justify-center p-4" role="dialog" aria-modal="true" tabindex="-1"><div class="relative mx-auto bg-white dark:bg-gray-800 rounded-lg shadow-lg" role="document"><!></div></div>');function M(s,i){v(i,!1);const l=m();function n(){l("close")}function c(o){o.stopPropagation()}function f(o){o.key==="Escape"&&l("close")}u();var a=w(),e=r(a),p=r(e);b(p,i,"default",{}),d(e),d(a),t("click",e,c),t("click",a,n),t("keydown",a,f),k(s,a),g()}export{M};

View file

@ -1 +1 @@
import"./DsnmJJEf.js";import{i as _}from"./TJn6xDN9.js";import{p as h,f as x,t as u,b as g,c as k,s as w,d as o,u as d,q as e,r,e as y}from"./DniTuB_0.js";import{h as b}from"./CKHGi7RD.js";import{p as m}from"./DbNhg6mG.js";import{g as l}from"./YbkgTiK_.js";var z=x('<div class="flex items-center"><div class="flex-shrink-0 mr-2"><!></div> <div class="text-sm text-gray-900 dark:text-white"> </div></div>');function U(v,i){h(i,!1);let t=m(i,"item",8),s=m(i,"iconSize",8,"w-5 h-5");_();var a=z(),n=o(a),f=o(n);b(f,()=>(e(l),e(t()),e(s()),d(()=>l(t()?.endpoint?.endpoint_type||t()?.endpoint_type||"unknown",s())))),r(n);var p=w(n,2),c=o(p,!0);r(p),r(a),u(()=>y(c,(e(t()),d(()=>t()?.endpoint?.name||t()?.endpoint_name||t()?.endpoint_type||"Unknown")))),g(v,a),k()}export{U as E};
import"./DsnmJJEf.js";import{i as _}from"./TJn6xDN9.js";import{p as h,f as x,t as u,b as g,c as k,s as w,d as o,u as d,q as e,r,e as y}from"./DniTuB_0.js";import{h as b}from"./DD3srElq.js";import{p as m}from"./DbNhg6mG.js";import{g as l}from"./LMA6-4d1.js";var z=x('<div class="flex items-center"><div class="flex-shrink-0 mr-2"><!></div> <div class="text-sm text-gray-900 dark:text-white"> </div></div>');function U(v,i){h(i,!1);let t=m(i,"item",8),s=m(i,"iconSize",8,"w-5 h-5");_();var a=z(),n=o(a),f=o(n);b(f,()=>(e(l),e(t()),e(s()),d(()=>l(t()?.endpoint?.endpoint_type||t()?.endpoint_type||"unknown",s())))),r(n);var p=w(n,2),c=o(p,!0);r(p),r(a),u(()=>y(c,(e(t()),d(()=>t()?.endpoint?.name||t()?.endpoint_name||t()?.endpoint_type||"Unknown")))),g(v,a),k()}export{U as E};

View file

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

View file

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

View file

@ -1 +1 @@
import"../chunks/DsnmJJEf.js";import{i as h}from"../chunks/TJn6xDN9.js";import{p as c,f as l,a as v,t as u,b as _,c as d,d as s,r as e,s as g,e as p}from"../chunks/DniTuB_0.js";import{p as o}from"../chunks/BD7zbze4.js";var x=l("<h1> </h1> <p> </p>",1);function q(i,m){c(m,!1),h();var t=x(),r=v(t),f=s(r,!0);e(r);var a=g(r,2),n=s(a,!0);e(a),u(()=>{p(f,o.status),p(n,o.error?.message)}),_(i,t),d()}export{q as component};
import"../chunks/DsnmJJEf.js";import{i as h}from"../chunks/TJn6xDN9.js";import{p as c,f as l,a as v,t as u,b as _,c as d,d as s,r as e,s as g,e as p}from"../chunks/DniTuB_0.js";import{p as o}from"../chunks/H2nrvwx_.js";var x=l("<h1> </h1> <p> </p>",1);function q(i,m){c(m,!1),h();var t=x(),r=v(t),f=s(r,!0);e(r);var a=g(r,2),n=s(a,!0);e(a),u(()=>{p(f,o.status),p(n,o.error?.message)}),_(i,t),d()}export{q as component};

View file

@ -1 +1 @@
import"../chunks/DsnmJJEf.js";import{i as Z}from"../chunks/TJn6xDN9.js";import{p as ee,o as ae,l as re,h as te,f as K,j as se,t as _,g as a,i as k,b as w,c as de,$ as oe,s as d,D as ie,m as f,d as r,u as q,q as B,k as i,r as t,z as D,e as I}from"../chunks/DniTuB_0.js";import{i as le,s as ne,a as ce}from"../chunks/DbNhg6mG.js";import{B as me,d as l,c as T,r as U}from"../chunks/CKHGi7RD.js";import{b as C}from"../chunks/CCQwxxp9.js";import{p as ue}from"../chunks/D4Caz1gY.js";import{g as H}from"../chunks/BAMHjnwW.js";import{a as pe,b as ve}from"../chunks/CKWet9X1.js";import{e as fe}from"../chunks/BZiHL9L3.js";var ge=K('<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>'),he=K('<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 Ae(W,F){ee(F,!1);const[J,N]=ne(),$=()=>ce(pe,"$authStore",J);let m=f(""),u=f(""),o=f(!1),n=f("");ae(()=>{O()});function O(){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(n,"Please enter both username and password");return}i(o,!0),i(n,"");try{await ve.login(a(m),a(u)),H(l("/"))}catch(e){i(n,fe(e))}finally{i(o,!1)}}function L(e){e.key==="Enter"&&M()}re(()=>($(),l),()=>{$().isAuthenticated&&H(l("/"))}),te(),Z();var g=he();se(e=>{oe.title="Login - GARM"});var z=r(g),h=r(z),A=r(h),S=r(A),Q=d(S,2);t(A),D(4),t(h);var b=d(h,2),x=r(b),y=r(x),p=d(r(y),2);U(p),t(y);var P=d(y,2),v=d(r(P),2);U(v),t(P),t(x);var G=d(x,2);{var V=e=>{var s=ge(),c=r(s),E=d(r(c),2),j=r(E),Y=r(j,!0);t(j),t(E),t(c),t(s),_(()=>I(Y,a(n))),w(e,s)};le(G,e=>{a(n)&&e(V)})}var R=d(G,2),X=r(R);me(X,{type:"submit",variant:"primary",size:"md",fullWidth:!0,get disabled(){return a(o)},get loading(){return a(o)},children:(e,s)=>{D();var c=ie();_(()=>I(c,a(o)?"Signing in...":"Sign in")),w(e,c)},$$slots:{default:!0}}),t(R),t(b),t(z),t(g),_((e,s)=>{T(S,"src",e),T(Q,"src",s),p.disabled=a(o),v.disabled=a(o)},[()=>(B(l),q(()=>l("/assets/garm-light.svg"))),()=>(B(l),q(()=>l("/assets/garm-dark.svg")))]),C(p,()=>a(m),e=>i(m,e)),k("keypress",p,L),C(v,()=>a(u),e=>i(u,e)),k("keypress",v,L),k("submit",b,ue(M)),w(W,g),de(),N()}export{Ae as component};
import"../chunks/DsnmJJEf.js";import{i as Z}from"../chunks/TJn6xDN9.js";import{p as ee,o as ae,l as re,h as te,f as K,j as se,t as _,g as a,i as k,b as w,c as de,$ as oe,s as d,D as ie,m as f,d as r,u as q,q as B,k as i,r as t,z as D,e as I}from"../chunks/DniTuB_0.js";import{i as le,s as ne,a as ce}from"../chunks/DbNhg6mG.js";import{B as me,d as l,c as T,r as U}from"../chunks/DD3srElq.js";import{b as C}from"../chunks/CCQwxxp9.js";import{p as ue}from"../chunks/D4Caz1gY.js";import{g as H}from"../chunks/DeKGyprh.js";import{a as pe,b as ve}from"../chunks/B_3mRBsj.js";import{e as fe}from"../chunks/BZiHL9L3.js";var ge=K('<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>'),he=K('<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 Ae(W,F){ee(F,!1);const[J,N]=ne(),$=()=>ce(pe,"$authStore",J);let m=f(""),u=f(""),o=f(!1),n=f("");ae(()=>{O()});function O(){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(n,"Please enter both username and password");return}i(o,!0),i(n,"");try{await ve.login(a(m),a(u)),H(l("/"))}catch(e){i(n,fe(e))}finally{i(o,!1)}}function L(e){e.key==="Enter"&&M()}re(()=>($(),l),()=>{$().isAuthenticated&&H(l("/"))}),te(),Z();var g=he();se(e=>{oe.title="Login - GARM"});var z=r(g),h=r(z),A=r(h),S=r(A),Q=d(S,2);t(A),D(4),t(h);var b=d(h,2),x=r(b),y=r(x),p=d(r(y),2);U(p),t(y);var P=d(y,2),v=d(r(P),2);U(v),t(P),t(x);var G=d(x,2);{var V=e=>{var s=ge(),c=r(s),E=d(r(c),2),j=r(E),Y=r(j,!0);t(j),t(E),t(c),t(s),_(()=>I(Y,a(n))),w(e,s)};le(G,e=>{a(n)&&e(V)})}var R=d(G,2),X=r(R);me(X,{type:"submit",variant:"primary",size:"md",fullWidth:!0,get disabled(){return a(o)},get loading(){return a(o)},children:(e,s)=>{D();var c=ie();_(()=>I(c,a(o)?"Signing in...":"Sign in")),w(e,c)},$$slots:{default:!0}}),t(R),t(b),t(z),t(g),_((e,s)=>{T(S,"src",e),T(Q,"src",s),p.disabled=a(o),v.disabled=a(o)},[()=>(B(l),q(()=>l("/assets/garm-light.svg"))),()=>(B(l),q(()=>l("/assets/garm-dark.svg")))]),C(p,()=>a(m),e=>i(m,e)),k("keypress",p,L),C(v,()=>a(u),e=>i(u,e)),k("keypress",v,L),k("submit",b,ue(M)),w(W,g),de(),N()}export{Ae as component};

View file

@ -1 +1 @@
{"version":"1759875121700"}
{"version":"1760009955548"}

View file

@ -71,11 +71,11 @@
})();
</script>
<link rel="modulepreload" href="/ui/_app/immutable/entry/start.2BsGx4lO.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/BAMHjnwW.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/start.STBCHZlH.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DeKGyprh.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DniTuB_0.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/Bgk7vDU7.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/app.CFZCb0-q.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/BSR16q_V.js">
<link rel="modulepreload" href="/ui/_app/immutable/entry/app.ckt_VgS1.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DsnmJJEf.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/DbNhg6mG.js">
<link rel="modulepreload" href="/ui/_app/immutable/chunks/BZLWIdPw.js">
@ -85,7 +85,7 @@
<div style="display: contents">
<script>
{
__sveltekit_1bvrx0w = {
__sveltekit_mlwef0 = {
base: "/ui",
assets: "/ui"
};
@ -93,8 +93,8 @@
const element = document.currentScript.parentElement;
Promise.all([
import("/ui/_app/immutable/entry/start.2BsGx4lO.js"),
import("/ui/_app/immutable/entry/app.CFZCb0-q.js")
import("/ui/_app/immutable/entry/start.STBCHZlH.js"),
import("/ui/_app/immutable/entry/app.ckt_VgS1.js")
]).then(([kit, app]) => {
kit.start(app, element);
});

View file

@ -72,7 +72,12 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => '<svg data-forge="github"></svg>'),
filterCredentials: vi.fn((credentials, searchTerm) => {
if (!searchTerm) return credentials;
@ -89,7 +94,8 @@ vi.mock('$lib/utils/common.js', () => ({
getAuthTypeBadge: vi.fn((authType) => authType === 'pat' ? 'PAT' : 'App'),
getEntityStatusBadge: vi.fn(() => 'active'),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -47,7 +47,12 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => 'github'),
filterCredentials: vi.fn((credentials) => credentials),
changePerPage: vi.fn((perPage) => ({ newPerPage: perPage, newCurrentPage: 1 })),
@ -55,7 +60,8 @@ vi.mock('$lib/utils/common.js', () => ({
getAuthTypeBadge: vi.fn(() => 'PAT'),
getEntityStatusBadge: vi.fn(() => 'active'),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -51,7 +51,12 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}));
// Mock utilities
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => 'github'),
filterCredentials: vi.fn((credentials) => credentials),
changePerPage: vi.fn((perPage) => ({ newPerPage: perPage, newCurrentPage: 1 })),
@ -59,7 +64,8 @@ vi.mock('$lib/utils/common.js', () => ({
getAuthTypeBadge: vi.fn(() => 'PAT'),
getEntityStatusBadge: vi.fn(() => 'active'),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -69,7 +69,12 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => '<svg data-forge="github"></svg>'),
filterEndpoints: vi.fn((endpoints, searchTerm) => {
if (!searchTerm) return endpoints;
@ -84,7 +89,8 @@ vi.mock('$lib/utils/common.js', () => ({
return items.slice(start, start + perPage);
}),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -47,13 +47,19 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => 'github'),
filterEndpoints: vi.fn((endpoints) => endpoints),
changePerPage: vi.fn((perPage) => ({ newPerPage: perPage, newCurrentPage: 1 })),
paginateItems: vi.fn((items) => items),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -51,13 +51,19 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
}));
// Mock utilities
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn(() => 'github'),
filterEndpoints: vi.fn((endpoints) => endpoints),
changePerPage: vi.fn((perPage) => ({ newPerPage: perPage, newCurrentPage: 1 })),
paginateItems: vi.fn((items) => items),
formatDate: vi.fn((date) => date)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -36,17 +36,17 @@
async function loadEnterprise() {
if (!enterpriseId) return;
try {
loading = true;
error = '';
const [ent, entPools, entInstances] = await Promise.all([
garmApi.getEnterprise(enterpriseId),
garmApi.listEnterprisePools(enterpriseId).catch(() => []),
garmApi.listEnterpriseInstances(enterpriseId).catch(() => [])
]);
enterprise = ent;
pools = entPools;
instances = entInstances;

View file

@ -80,6 +80,27 @@ const mockInstances = [
})
];
// Mock eager cache store
vi.mock('$lib/stores/eager-cache.js', () => ({
eagerCache: {
subscribe: vi.fn((callback) => {
callback({
enterprises: [],
organizations: [],
repositories: [],
loaded: {},
loading: {},
errorMessages: {}
});
return () => {};
})
},
eagerCacheManager: {
getEnterprises: vi.fn(),
retryResource: vi.fn()
}
}));
// Reset any component mocks that might be set by setup.ts
vi.unmock('$lib/components/UpdateEntityModal.svelte');
vi.unmock('$lib/components/DeleteModal.svelte');
@ -118,10 +139,13 @@ vi.mock('$lib/stores/websocket.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn(() => 'github'),
formatDate: vi.fn((date) => date)
}));
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// No need to mock anything, use all real functions
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')
@ -149,16 +173,13 @@ describe('Comprehensive Integration Tests for Enterprise Details Page', () => {
describe('Component Rendering and Data Display', () => {
it('should render enterprise details page with real components', async () => {
render(EnterpriseDetailsPage);
const { container } = render(EnterpriseDetailsPage);
// Wait for enterprise data to load and render
await waitFor(() => {
// Wait for enterprise data to load
expect(garmApi.getEnterprise).toHaveBeenCalledWith('ent-123');
});
expect(screen.getByRole('heading', { name: 'test-enterprise' })).toBeInTheDocument();
}, { timeout: 5000 });
// Should render the enterprise name in the breadcrumb and header
expect(screen.getByRole('heading', { name: 'test-enterprise' })).toBeInTheDocument();
// Should render the enterprise details
expect(screen.getByText('Endpoint: github.com • GitHub Enterprise')).toBeInTheDocument();
});
@ -177,14 +198,12 @@ describe('Comprehensive Integration Tests for Enterprise Details Page', () => {
it('should render all major sections when data is loaded', async () => {
render(EnterpriseDetailsPage);
await waitFor(() => {
expect(garmApi.getEnterprise).toHaveBeenCalledWith('ent-123');
});
// Should have all major sections
expect(screen.getByText('Pools (2)')).toBeInTheDocument();
expect(screen.getByText('Instances (2)')).toBeInTheDocument();
expect(screen.getByText('Events')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('Pools (2)')).toBeInTheDocument();
expect(screen.getByText('Instances (2)')).toBeInTheDocument();
expect(screen.getByText('Events')).toBeInTheDocument();
});
});
});
@ -395,7 +414,9 @@ describe('Comprehensive Integration Tests for Enterprise Details Page', () => {
// The component properly sets up websocket integration to receive real-time updates
// This is verified by the subscription calls above and by the component's ability
// to display data that would be updated via websockets
expect(screen.getByRole('heading', { name: 'test-enterprise' })).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByRole('heading', { name: 'test-enterprise' })).toBeInTheDocument();
});
});
});

View file

@ -47,10 +47,13 @@ vi.mock('$lib/stores/websocket.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn(() => 'github'),
formatDate: vi.fn((date) => date)
}));
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Use all real functions
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -0,0 +1,161 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render } from '@testing-library/svelte';
import EnterpriseDetailsPage from './+page.svelte';
import { createMockEnterprise } from '../../../test/factories.js';
// Mock all external dependencies
vi.mock('$app/stores', () => ({
page: {
subscribe: vi.fn((callback) => {
callback({ params: { id: 'ent-123' } });
return () => {};
})
}
}));
vi.mock('$app/navigation', () => ({
goto: vi.fn()
}));
vi.mock('$app/paths', () => ({
resolve: vi.fn((path) => path)
}));
vi.mock('$lib/api/client.js', () => ({
garmApi: {
getEnterprise: vi.fn(),
listEnterprisePools: vi.fn(),
listEnterpriseInstances: vi.fn(),
updateEnterprise: vi.fn(),
deleteEnterprise: vi.fn(),
deleteInstance: vi.fn(),
createEnterprisePool: vi.fn()
}
}));
vi.mock('$lib/stores/toast.js', () => ({
toastStore: {
success: vi.fn(),
error: vi.fn()
}
}));
vi.mock('$lib/stores/websocket.js', () => ({
websocketStore: {
subscribeToEntity: vi.fn(() => () => {}),
subscribe: vi.fn(() => () => {})
}
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn(() => 'github'),
formatDate: vi.fn((date) => date)
}));
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')
}));
const mockEnterprise = createMockEnterprise({
id: 'ent-123',
name: 'test-enterprise',
endpoint: {
name: 'github.com'
},
pool_manager_status: { running: true, failure_reason: undefined }
});
describe('Enterprise Details Page - Render Tests', () => {
beforeEach(async () => {
vi.clearAllMocks();
// Set up default API mocks
const { garmApi } = await import('$lib/api/client.js');
(garmApi.getEnterprise as any).mockResolvedValue(mockEnterprise);
(garmApi.listEnterprisePools as any).mockResolvedValue([]);
(garmApi.listEnterpriseInstances as any).mockResolvedValue([]);
});
describe('Basic Rendering', () => {
it('should render without crashing', () => {
const { container } = render(EnterpriseDetailsPage);
expect(container).toBeInTheDocument();
});
it('should have proper document structure', () => {
const { container } = render(EnterpriseDetailsPage);
expect(container.querySelector('div')).toBeInTheDocument();
});
it('should render breadcrumb navigation', () => {
const { container } = render(EnterpriseDetailsPage);
const breadcrumb = container.querySelector('[aria-label="Breadcrumb"]');
expect(breadcrumb).toBeInTheDocument();
});
it('should render loading state initially', () => {
const { container } = render(EnterpriseDetailsPage);
// Component should render some form of loading indicator or content
expect(container).toBeInTheDocument();
});
});
describe('Component Lifecycle', () => {
it('should mount successfully', () => {
const { component } = render(EnterpriseDetailsPage);
expect(component).toBeDefined();
});
it('should unmount without errors', () => {
const { unmount } = render(EnterpriseDetailsPage);
expect(() => unmount()).not.toThrow();
});
it('should handle component updates', async () => {
const { component } = render(EnterpriseDetailsPage);
// Component should handle reactive updates
expect(component).toBeDefined();
});
it('should set up websocket subscriptions on mount', async () => {
const { websocketStore } = await import('$lib/stores/websocket.js');
render(EnterpriseDetailsPage);
// Wait for component mount and subscription setup
await new Promise(resolve => setTimeout(resolve, 0));
// Should call subscription setup
expect(websocketStore.subscribeToEntity).toHaveBeenCalled();
});
});
describe('DOM Structure', () => {
it('should create proper DOM hierarchy', () => {
const { container } = render(EnterpriseDetailsPage);
// Should have main container with proper spacing
const mainDiv = container.querySelector('div.space-y-6');
expect(mainDiv).toBeInTheDocument();
});
it('should render svelte:head for page title', async () => {
const { garmApi } = await import('$lib/api/client.js');
// Mock enterprise data for the title
(garmApi.getEnterprise as any).mockResolvedValue(mockEnterprise);
render(EnterpriseDetailsPage);
// Initially should show generic title (before enterprise loads)
expect(document.title).toContain('Enterprise Details - GARM');
// Wait for enterprise data to load and title to update
await new Promise(resolve => setTimeout(resolve, 100));
// Should now show enterprise-specific title
expect(document.title).toContain('test-enterprise - Enterprise Details - GARM');
});
});
});

View file

@ -52,10 +52,13 @@ vi.mock('$lib/stores/websocket.js', () => ({
}));
// Mock utilities
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn(() => 'github'),
formatDate: vi.fn((date) => date)
}));
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Use all real functions
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((err) => err.message || 'Unknown error')

View file

@ -87,7 +87,12 @@ vi.mock('$lib/components/cells', () => ({
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
@ -95,7 +100,8 @@ vi.mock('$lib/utils/common.js', () => ({
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -0,0 +1,173 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import { createMockEnterprise } from '../../test/factories.js';
// Mock all external dependencies but keep the component rendering real
vi.mock('$lib/api/client.js', () => ({
garmApi: {
createEnterprise: vi.fn(),
updateEnterprise: vi.fn(),
deleteEnterprise: vi.fn(),
listEnterprises: vi.fn()
}
}));
vi.mock('$lib/stores/eager-cache.js', () => ({
eagerCache: {
subscribe: vi.fn((callback) => {
callback({
enterprises: [],
credentials: [],
loaded: { enterprises: true, credentials: true },
loading: { enterprises: false, credentials: false },
errorMessages: { enterprises: '', credentials: '' }
});
return () => {};
})
},
eagerCacheManager: {
getEnterprises: vi.fn(),
retryResource: vi.fn(),
getCredentials: vi.fn()
}
}));
vi.mock('$lib/stores/toast.js', () => ({
toastStore: {
success: vi.fn(),
error: vi.fn(),
info: vi.fn(),
warning: vi.fn()
}
}));
vi.mock('$app/paths', () => ({
resolve: vi.fn((path) => path)
}));
vi.mock('$app/environment', () => ({
browser: false,
dev: true,
building: false
}));
vi.mock('$lib/components/CreateEnterpriseModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/UpdateEntityModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/DeleteModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/PageHeader.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/DataTable.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/Badge.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/ActionButton.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/cells', () => ({
EntityCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
EndpointCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
StatusCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
ActionsCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
term ? items.filter((item: any) =>
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')
}));
import EnterprisesPage from './+page.svelte';
describe('Enterprises Page Rendering Tests', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('Component Rendering', () => {
it('should render without crashing', () => {
const { container } = render(EnterprisesPage);
expect(container).toBeInTheDocument();
});
it('should render as a valid DOM element', () => {
const { container } = render(EnterprisesPage);
expect(container.firstChild).toBeInstanceOf(HTMLElement);
});
it('should have proper document title', () => {
render(EnterprisesPage);
expect(document.title).toBe('Enterprises - GARM');
});
it('should render with correct structure', () => {
const { container } = render(EnterprisesPage);
expect(container.firstChild).toHaveClass('space-y-6');
});
it('should handle empty state rendering', () => {
render(EnterprisesPage);
// Component should render even with no enterprises
expect(document.body).toBeInTheDocument();
});
});
describe('Component Lifecycle', () => {
it('should mount successfully', () => {
const component = render(EnterprisesPage);
expect(component.component).toBeDefined();
});
it('should unmount without errors', () => {
const { unmount } = render(EnterprisesPage);
expect(() => unmount()).not.toThrow();
});
});
describe('DOM Structure Validation', () => {
it('should create proper HTML structure', () => {
const { container } = render(EnterprisesPage);
// Should have main container
expect(container.querySelector('.space-y-6')).toBeInTheDocument();
});
it('should handle conditional rendering', () => {
const { container } = render(EnterprisesPage);
// Component should render without any modals open initially
expect(container).toBeInTheDocument();
});
it('should render with proper accessibility structure', () => {
const { container } = render(EnterprisesPage);
// Basic accessibility checks
expect(container).toBeInTheDocument();
});
});
});

View file

@ -90,7 +90,12 @@ vi.mock('$lib/components/cells', () => ({
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
@ -98,7 +103,8 @@ vi.mock('$lib/utils/common.js', () => ({
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -0,0 +1,522 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import { createMockEnterprise } from '../../test/factories.js';
// Mock all external dependencies
vi.mock('$lib/api/client.js', () => ({
garmApi: {
createEnterprise: vi.fn(),
updateEnterprise: vi.fn(),
deleteEnterprise: vi.fn(),
listEnterprises: vi.fn()
}
}));
vi.mock('$lib/stores/eager-cache.js', () => ({
eagerCache: {
subscribe: vi.fn((callback) => {
callback({
enterprises: [],
credentials: [],
loaded: { enterprises: true, credentials: true },
loading: { enterprises: false, credentials: false },
errorMessages: { enterprises: '', credentials: '' }
});
return () => {};
})
},
eagerCacheManager: {
getEnterprises: vi.fn(),
retryResource: vi.fn(),
getCredentials: vi.fn()
}
}));
vi.mock('$lib/stores/toast.js', () => ({
toastStore: {
success: vi.fn(),
error: vi.fn(),
info: vi.fn(),
warning: vi.fn()
}
}));
// Mock SvelteKit modules
vi.mock('$app/paths', () => ({
resolve: vi.fn((path) => path)
}));
vi.mock('$app/environment', () => ({
browser: false,
dev: true,
building: false
}));
// Mock all child components
vi.mock('$lib/components/CreateEnterpriseModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/UpdateEntityModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/DeleteModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/PageHeader.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/DataTable.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/Badge.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/ActionButton.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/components/cells', () => ({
EntityCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
EndpointCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
StatusCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
ActionsCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() })),
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
term ? items.filter((item: any) =>
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')
}));
import EnterprisesPage from './+page.svelte';
describe('Enterprises Page Unit Tests', () => {
let mockEnterprises: any[];
beforeEach(() => {
vi.clearAllMocks();
mockEnterprises = [
createMockEnterprise({
id: 'ent-1',
name: 'test-enterprise',
pool_manager_status: { running: true, failure_reason: undefined }
}),
createMockEnterprise({
id: 'ent-2',
name: 'another-enterprise',
pool_manager_status: { running: false, failure_reason: undefined }
})
];
});
describe('Component Structure', () => {
it('should render enterprises page', () => {
const { container } = render(EnterprisesPage);
expect(container).toBeInTheDocument();
});
it('should set correct page title', () => {
render(EnterprisesPage);
expect(document.title).toBe('Enterprises - GARM');
});
it('should have enterprises state variables', async () => {
const component = render(EnterprisesPage);
expect(component).toBeDefined();
});
});
describe('Data Management', () => {
it('should initialize with correct default values', () => {
const { container } = render(EnterprisesPage);
// Component should render without errors and set up initial state
expect(container).toBeInTheDocument();
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle enterprises data from eager cache', () => {
const { container } = render(EnterprisesPage);
// Component should render structure for handling cache data
expect(container.querySelector('.space-y-6')).toBeInTheDocument();
});
});
describe('Search and Filtering', () => {
it('should filter enterprises by search term', async () => {
const { filterByName } = await import('$lib/utils/common.js');
const filtered = filterByName(mockEnterprises, 'test');
expect(filterByName).toHaveBeenCalledWith(mockEnterprises, 'test');
expect(filtered).toHaveLength(1);
expect(filtered[0].name).toBe('test-enterprise');
});
it('should return all enterprises when search term is empty', async () => {
const { filterByName } = await import('$lib/utils/common.js');
const filtered = filterByName(mockEnterprises, '');
expect(filterByName).toHaveBeenCalledWith(mockEnterprises, '');
expect(filtered).toHaveLength(2);
});
it('should handle case-insensitive search', async () => {
const { filterByName } = await import('$lib/utils/common.js');
filterByName(mockEnterprises, 'TEST');
expect(filterByName).toHaveBeenCalledWith(mockEnterprises, 'TEST');
});
it('should reset to first page when searching', () => {
render(EnterprisesPage);
// Component should reset currentPage to 1 when search term changes
expect(document.title).toBe('Enterprises - GARM');
});
});
describe('Pagination Logic', () => {
it('should calculate total pages correctly', () => {
const enterprises = Array(75).fill(null).map((_, i) =>
createMockEnterprise({ id: `ent-${i}`, name: `ent-${i}` })
);
const perPage = 25;
const totalPages = Math.ceil(enterprises.length / perPage);
expect(totalPages).toBe(3);
});
it('should calculate paginated enterprises correctly', () => {
const enterprises = Array(75).fill(null).map((_, i) =>
createMockEnterprise({ id: `ent-${i}`, name: `ent-${i}` })
);
const currentPage = 2;
const perPage = 25;
const start = (currentPage - 1) * perPage;
const paginatedEnterprises = enterprises.slice(start, start + perPage);
expect(paginatedEnterprises).toHaveLength(25);
expect(paginatedEnterprises[0].name).toBe('ent-25');
expect(paginatedEnterprises[24].name).toBe('ent-49');
});
it('should adjust current page when it exceeds total pages', () => {
// When filtering reduces results, current page should adjust
const totalPages = 2;
let currentPage = 5;
if (currentPage > totalPages && totalPages > 0) {
currentPage = totalPages;
}
expect(currentPage).toBe(2);
});
it('should handle empty results gracefully', () => {
const enterprises: any[] = [];
const perPage = 25;
const totalPages = Math.ceil(enterprises.length / perPage);
expect(totalPages).toBe(0);
});
});
describe('Modal Management', () => {
it('should have correct initial modal states', () => {
render(EnterprisesPage);
// Component should render without modal states
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle create modal opening', () => {
render(EnterprisesPage);
// Component should handle modal state management
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle update modal opening with enterprise', () => {
render(EnterprisesPage);
// Component should handle update modal state
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle delete modal opening with enterprise', () => {
render(EnterprisesPage);
// Component should handle delete modal state
expect(document.title).toBe('Enterprises - GARM');
});
it('should close all modals', () => {
render(EnterprisesPage);
// Component should handle modal closing
expect(document.title).toBe('Enterprises - GARM');
});
});
describe('API Integration', () => {
it('should call createEnterprise API', async () => {
const { garmApi } = await import('$lib/api/client.js');
render(EnterprisesPage);
const entParams = {
name: 'new-enterprise',
credentials_name: 'test-creds',
webhook_secret: 'secret123',
pool_balancer_type: 'roundrobin'
};
await garmApi.createEnterprise(entParams);
expect(garmApi.createEnterprise).toHaveBeenCalledWith(entParams);
});
it('should call updateEnterprise API', async () => {
const { garmApi } = await import('$lib/api/client.js');
render(EnterprisesPage);
const updateParams = { webhook_secret: 'new-secret' };
await garmApi.updateEnterprise('ent-1', updateParams);
expect(garmApi.updateEnterprise).toHaveBeenCalledWith('ent-1', updateParams);
});
it('should call deleteEnterprise API', async () => {
const { garmApi } = await import('$lib/api/client.js');
render(EnterprisesPage);
await garmApi.deleteEnterprise('ent-1');
expect(garmApi.deleteEnterprise).toHaveBeenCalledWith('ent-1');
});
});
describe('Toast Notifications', () => {
it('should show success toast for enterprise creation', async () => {
const { toastStore } = await import('$lib/stores/toast.js');
render(EnterprisesPage);
toastStore.success('Enterprise Created', 'Enterprise test-enterprise has been created successfully.');
expect(toastStore.success).toHaveBeenCalledWith(
'Enterprise Created',
'Enterprise test-enterprise has been created successfully.'
);
});
it('should show success toast for enterprise update', async () => {
const { toastStore } = await import('$lib/stores/toast.js');
render(EnterprisesPage);
toastStore.success('Enterprise Updated', 'Enterprise test-enterprise has been updated successfully.');
expect(toastStore.success).toHaveBeenCalledWith(
'Enterprise Updated',
'Enterprise test-enterprise has been updated successfully.'
);
});
it('should show success toast for enterprise deletion', async () => {
const { toastStore } = await import('$lib/stores/toast.js');
render(EnterprisesPage);
toastStore.success('Enterprise Deleted', 'Enterprise test-enterprise has been deleted successfully.');
expect(toastStore.success).toHaveBeenCalledWith(
'Enterprise Deleted',
'Enterprise test-enterprise has been deleted successfully.'
);
});
it('should show error toast for API failures', async () => {
const { toastStore } = await import('$lib/stores/toast.js');
render(EnterprisesPage);
toastStore.error('Delete Failed', 'Enterprise deletion failed');
expect(toastStore.error).toHaveBeenCalledWith('Delete Failed', 'Enterprise deletion failed');
});
});
describe('DataTable Configuration', () => {
it('should have correct column configuration', () => {
render(EnterprisesPage);
// DataTable should be configured with proper columns
const expectedColumns = [
{ key: 'name', title: 'Name' },
{ key: 'endpoint', title: 'Endpoint' },
{ key: 'credentials', title: 'Credentials' },
{ key: 'status', title: 'Status' },
{ key: 'actions', title: 'Actions', align: 'right' }
];
expect(expectedColumns).toHaveLength(5);
});
it('should have correct mobile card configuration', () => {
render(EnterprisesPage);
// Mobile card should be configured for enterprises
const config = {
entityType: 'enterprise',
primaryText: { field: 'name', isClickable: true, href: '/enterprises/{id}' }
};
expect(config.entityType).toBe('enterprise');
expect(config.primaryText.field).toBe('name');
expect(config.primaryText.isClickable).toBe(true);
});
});
describe('Event Handlers', () => {
it('should handle table search event', () => {
render(EnterprisesPage);
// handleTableSearch should update searchTerm and reset page
const mockEvent = { detail: { term: 'test-search' } };
expect(mockEvent.detail.term).toBe('test-search');
});
it('should handle table page change event', () => {
render(EnterprisesPage);
// handleTablePageChange should update currentPage
const mockEvent = { detail: { page: 3 } };
expect(mockEvent.detail.page).toBe(3);
});
it('should handle table per-page change event', () => {
render(EnterprisesPage);
// handleTablePerPageChange should update perPage and reset page
const mockEvent = { detail: { perPage: 50 } };
expect(mockEvent.detail.perPage).toBe(50);
});
it('should handle edit action event', () => {
render(EnterprisesPage);
// handleEdit should call openUpdateModal
const mockEnterprise = createMockEnterprise();
const mockEvent = { detail: { item: mockEnterprise } };
expect(mockEvent.detail.item).toBe(mockEnterprise);
});
it('should handle delete action event', () => {
render(EnterprisesPage);
// handleDelete should call openDeleteModal
const mockEnterprise = createMockEnterprise();
const mockEvent = { detail: { item: mockEnterprise } };
expect(mockEvent.detail.item).toBe(mockEnterprise);
});
});
describe('Error Handling', () => {
it('should handle API errors in enterprise creation', async () => {
const { extractAPIError } = await import('$lib/utils/apiError');
render(EnterprisesPage);
const error = new Error('Creation failed');
const extractedError = extractAPIError(error);
expect(extractAPIError).toHaveBeenCalledWith(error);
expect(extractedError).toBe('Creation failed');
});
it('should handle enterprises loading errors', () => {
render(EnterprisesPage);
// Component should render without errors during error states
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle retry functionality', async () => {
const { eagerCacheManager } = await import('$lib/stores/eager-cache.js');
render(EnterprisesPage);
await eagerCacheManager.retryResource('enterprises');
expect(eagerCacheManager.retryResource).toHaveBeenCalledWith('enterprises');
});
});
describe('Utility Functions', () => {
it('should get correct forge icon', async () => {
const { getForgeIcon } = await import('$lib/utils/common.js');
const githubIcon = getForgeIcon('github');
expect(getForgeIcon).toHaveBeenCalledWith('github');
expect(githubIcon).toContain('svg');
});
it('should get entity status badge', async () => {
const { getEntityStatusBadge } = await import('$lib/utils/common.js');
const enterprise = createMockEnterprise({
pool_manager_status: { running: true, failure_reason: undefined }
});
const badge = getEntityStatusBadge(enterprise);
expect(getEntityStatusBadge).toHaveBeenCalledWith(enterprise);
expect(badge).toEqual({ variant: 'success', text: 'Running' });
});
});
describe('Reactive Statements', () => {
it('should update filtered enterprises when search term changes', () => {
render(EnterprisesPage);
// Component should handle reactive filtering
expect(document.title).toBe('Enterprises - GARM');
});
it('should recalculate total pages when filtered enterprises change', () => {
render(EnterprisesPage);
// Component should handle reactive pagination
expect(document.title).toBe('Enterprises - GARM');
});
it('should adjust current page when total pages change', () => {
render(EnterprisesPage);
// Component should handle page adjustments
expect(document.title).toBe('Enterprises - GARM');
});
it('should update paginated enterprises when page or filter changes', () => {
render(EnterprisesPage);
// Component should handle reactive pagination updates
expect(document.title).toBe('Enterprises - GARM');
});
});
describe('Lifecycle Management', () => {
it('should load enterprises on mount', () => {
render(EnterprisesPage);
// Component should load without errors on mount
expect(document.title).toBe('Enterprises - GARM');
});
it('should handle mount errors gracefully', () => {
render(EnterprisesPage);
// Component should handle mount errors gracefully
expect(document.title).toBe('Enterprises - GARM');
});
it('should subscribe to eager cache', () => {
render(EnterprisesPage);
// Component should set up cache subscription
expect(document.title).toBe('Enterprises - GARM');
});
});
});

View file

@ -98,7 +98,12 @@ vi.mock('$lib/utils/status.js', () => ({
})
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
formatDate: vi.fn((date) => {
const d = new Date(date);
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString();
@ -112,7 +117,8 @@ vi.mock('$lib/utils/common.js', () => ({
default: return { variant: 'info', text: 'Info' };
}
})
}));
};
});
// Global setup for each test
let garmApi: any;

View file

@ -57,14 +57,20 @@ vi.mock('$lib/utils/status.js', () => ({
})
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
formatDate: vi.fn((date) => new Date(date).toLocaleString()),
scrollToBottomEvents: vi.fn(),
getEventLevelBadge: vi.fn((level) => ({
variant: level === 'error' ? 'danger' : level === 'warning' ? 'warning' : 'info',
text: level.toUpperCase()
}))
}));
};
});
const mockInstance = createMockInstance({
id: 'inst-123',

View file

@ -62,14 +62,20 @@ vi.mock('$lib/utils/status.js', () => ({
})
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
formatDate: vi.fn((date) => new Date(date).toLocaleString()),
scrollToBottomEvents: vi.fn(),
getEventLevelBadge: vi.fn((level) => ({
variant: level === 'error' ? 'danger' : level === 'warning' ? 'warning' : 'info',
text: level.toUpperCase()
}))
}));
};
});
const mockInstance = createMockInstance({
id: 'inst-123',

View file

@ -106,6 +106,13 @@
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// Show success toast
toastStore.add({
type: 'success',
title: 'Download started',
message: `Downloading "${object.name}"...`
});
} catch (err) {
const errorMsg = extractAPIError(err);
toastStore.add({

View file

@ -76,7 +76,8 @@ describe('Object Detail Page - Integration Tests', () => {
describe('Delete Functionality', () => {
it('should open delete modal when delete button is clicked', async () => {
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
// Wait for page to load (File Information heading appears)
await waitFor(() => screen.getByText('File Information'));
const deleteButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButton);
@ -89,7 +90,7 @@ describe('Object Detail Page - Integration Tests', () => {
it('should close delete modal when cancel is clicked', async () => {
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Open delete modal
const deleteButton = screen.getByRole('button', { name: 'Delete' });
@ -110,16 +111,16 @@ describe('Object Detail Page - Integration Tests', () => {
(garmApi.deleteFileObject as any).mockResolvedValue(undefined);
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Open delete modal
const deleteButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButton);
const deleteButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButtons[0]); // Click the first one (page button)
await waitFor(() => screen.getByText(/Are you sure/i));
// Confirm deletion
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(confirmButton);
// Confirm deletion (get all Delete buttons, the second one is in the modal)
const confirmButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButtons[1]); // Click the second one (modal button)
// Should call delete API
await waitFor(() => {
@ -134,15 +135,15 @@ describe('Object Detail Page - Integration Tests', () => {
(garmApi.deleteFileObject as any).mockResolvedValue(undefined);
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Delete object
const deleteButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButton);
const deleteButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButtons[0]); // Click page button
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(confirmButton);
const confirmButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButtons[1]); // Click modal confirm button
// Should navigate to list
await waitFor(() => {
@ -157,15 +158,15 @@ describe('Object Detail Page - Integration Tests', () => {
(garmApi.deleteFileObject as any).mockResolvedValue(undefined);
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Delete object
const deleteButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButton);
const deleteButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButtons[0]); // Click page button
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(confirmButton);
const confirmButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButtons[1]); // Click modal confirm button
// Should show success toast
await waitFor(() => {
@ -185,15 +186,15 @@ describe('Object Detail Page - Integration Tests', () => {
(garmApi.deleteFileObject as any).mockRejectedValue(new Error('Delete failed'));
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Try to delete
const deleteButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButton);
const deleteButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(deleteButtons[0]); // Click page button
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(confirmButton);
const confirmButtons = screen.getAllByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButtons[1]); // Click modal confirm button
// Should show error toast
await waitFor(() => {
@ -219,7 +220,7 @@ describe('Object Detail Page - Integration Tests', () => {
const removeChildSpy = vi.spyOn(document.body, 'removeChild');
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
const downloadButton = screen.getByRole('button', { name: 'Download' });
await fireEvent.click(downloadButton);
@ -239,7 +240,7 @@ describe('Object Detail Page - Integration Tests', () => {
});
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
const downloadButton = screen.getByRole('button', { name: 'Download' });
await fireEvent.click(downloadButton);
@ -263,7 +264,7 @@ describe('Object Detail Page - Integration Tests', () => {
});
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
const downloadButton = screen.getByRole('button', { name: 'Download' });
await fireEvent.click(downloadButton);
@ -284,7 +285,7 @@ describe('Object Detail Page - Integration Tests', () => {
const { garmApi } = await import('$lib/api/client.js');
render(ObjectDetailPage);
await waitFor(() => screen.getByText('test-file.bin'));
await waitFor(() => screen.getByText('File Information'));
// Initially loaded once
expect(garmApi.getFileObject).toHaveBeenCalledTimes(1);

View file

@ -177,7 +177,7 @@ describe('Objects Page - Integration Tests', () => {
// Confirm deletion
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
const confirmButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButton);
// Should call delete API
@ -200,7 +200,7 @@ describe('Objects Page - Integration Tests', () => {
await fireEvent.click(deleteButtons[0]);
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
const confirmButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButton);
// Should reload list
@ -315,7 +315,7 @@ describe('Objects Page - Integration Tests', () => {
await fireEvent.click(deleteButtons[0]);
await waitFor(() => screen.getByText(/Are you sure/i));
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
const confirmButton = screen.getByRole('button', { name: 'Delete' });
await fireEvent.click(confirmButton);
// Should show error toast

View file

@ -92,9 +92,15 @@ vi.mock('$lib/components/CreatePoolModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -92,9 +92,15 @@ vi.mock('$lib/components/CreatePoolModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -88,7 +88,12 @@ vi.mock('$lib/components/cells', () => ({
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
@ -96,7 +101,8 @@ vi.mock('$lib/utils/common.js', () => ({
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -90,7 +90,12 @@ vi.mock('$lib/components/cells', () => ({
GenericCell: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`),
getEntityStatusBadge: vi.fn(() => ({ variant: 'success', text: 'Running' })),
filterByName: vi.fn((items, term) =>
@ -98,7 +103,8 @@ vi.mock('$lib/utils/common.js', () => ({
item.name.toLowerCase().includes(term.toLowerCase())
) : items
)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -92,9 +92,15 @@ vi.mock('$lib/components/CreatePoolModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -92,9 +92,15 @@ vi.mock('$lib/components/CreatePoolModal.svelte', () => ({
default: vi.fn(() => ({ destroy: vi.fn(), $$set: vi.fn() }))
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((type) => `<svg data-forge="${type}"></svg>`)
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error) => error.message || 'API Error')

View file

@ -18,8 +18,8 @@ vi.mock('$lib/stores/eager-cache.js', () => ({
subscribe: vi.fn((callback) => {
callback({
repositories: [
createMockRepository({ name: 'test-repo-1', owner: 'owner-1' }),
createMockGiteaRepository({ name: 'gitea-repo', owner: 'owner-2' })
createMockRepository({ id: 'repo-1', name: 'test-repo-1', owner: 'owner-1' }),
createMockGiteaRepository({ id: 'repo-2', name: 'gitea-repo', owner: 'owner-2' })
],
loaded: { repositories: true },
loading: { repositories: false },
@ -43,7 +43,12 @@ vi.mock('$lib/stores/toast.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((endpointType: string) => {
if (endpointType === 'github') {
return '<div class="github-icon">GitHub Icon</div>';
@ -71,7 +76,8 @@ vi.mock('$lib/utils/common.js', () => ({
const start = (currentPage - 1) * perPage;
return items.slice(start, start + perPage);
})
}));
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error: any) => {

View file

@ -40,35 +40,40 @@ vi.mock('$lib/stores/toast.js', () => ({
}
}));
vi.mock('$lib/utils/common.js', () => ({
getForgeIcon: vi.fn((endpointType: string) => {
if (endpointType === 'github') {
return '<div class="github-icon">GitHub Icon</div>';
} else if (endpointType === 'gitea') {
return '<svg class="gitea-icon">Gitea Icon</svg>';
}
return '<svg class="unknown-icon">Unknown Icon</svg>';
}),
changePerPage: vi.fn((newPerPage: number) => ({
newPerPage,
newCurrentPage: 1
})),
getEntityStatusBadge: vi.fn((entity: any) => ({
text: entity?.pool_manager_status?.running ? 'Running' : 'Stopped',
variant: entity?.pool_manager_status?.running ? 'success' : 'error'
})),
filterRepositories: vi.fn((repositories: any[], searchTerm: string) => {
if (!searchTerm) return repositories;
return repositories.filter((repo: any) =>
repo.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
repo.owner.toLowerCase().includes(searchTerm.toLowerCase())
);
}),
paginateItems: vi.fn((items: any[], currentPage: number, perPage: number) => {
const start = (currentPage - 1) * perPage;
return items.slice(start, start + perPage);
})
}));
vi.mock('$lib/utils/common.js', async (importOriginal) => {
const actual = await importOriginal() as any;
return {
...actual,
// Override only specific functions for testing
getForgeIcon: vi.fn((endpointType: string) => {
if (endpointType === 'github') {
return '<div class="github-icon">GitHub Icon</div>';
} else if (endpointType === 'gitea') {
return '<svg class="gitea-icon">Gitea Icon</svg>';
}
return '<svg class="unknown-icon">Unknown Icon</svg>';
}),
changePerPage: vi.fn((newPerPage: number) => ({
newPerPage,
newCurrentPage: 1
})),
getEntityStatusBadge: vi.fn((entity: any) => ({
text: entity?.pool_manager_status?.running ? 'Running' : 'Stopped',
variant: entity?.pool_manager_status?.running ? 'success' : 'error'
})),
filterRepositories: vi.fn((repositories: any[], searchTerm: string) => {
if (!searchTerm) return repositories;
return repositories.filter((repo: any) =>
repo.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
repo.owner.toLowerCase().includes(searchTerm.toLowerCase())
);
}),
paginateItems: vi.fn((items: any[], currentPage: number, perPage: number) => {
const start = (currentPage - 1) * perPage;
return items.slice(start, start + perPage);
})
};
});
vi.mock('$lib/utils/apiError', () => ({
extractAPIError: vi.fn((error: any) => {

View file

@ -25,8 +25,8 @@ vi.mock('$app/environment', () => ({
// Simple component mocks that render as basic divs
vi.mock('$lib/components/CreateRepositoryModal.svelte', () => ({
default: function MockCreateRepositoryModal(options: any) {
const target = options.target;
default: function MockCreateRepositoryModal(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'create-repository-modal');
@ -42,8 +42,8 @@ vi.mock('$lib/components/CreateRepositoryModal.svelte', () => ({
}));
vi.mock('$lib/components/UpdateEntityModal.svelte', () => ({
default: function MockUpdateEntityModal(options: any) {
const target = options.target;
default: function MockUpdateEntityModal(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'update-entity-modal');
@ -58,6 +58,9 @@ vi.mock('$lib/components/UpdateEntityModal.svelte', () => ({
}
}));
// DeleteModal is NOT mocked - use real component
// Modal content and buttons need to work correctly
/*
vi.mock('$lib/components/DeleteModal.svelte', () => ({
default: function MockDeleteModal(anchor: any, props: any) {
const target = anchor?.parentNode;
@ -74,6 +77,7 @@ vi.mock('$lib/components/DeleteModal.svelte', () => ({
};
}
}));
*/
// PageHeader is NOT mocked - use real component to support slots
// Slots don't work properly with mocked Svelte components
@ -262,40 +266,42 @@ vi.mock('$lib/components/DataTable.svelte', () => ({
}));
*/
// Mock cell components
// Cell components are NOT mocked - use real components
// Mocked cells don't render actual data values
/*
vi.mock('$lib/components/cells', () => ({
EntityCell: function MockEntityCell(options: any) {
const target = options.target;
EntityCell: function MockEntityCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'entity-cell');
div.textContent = 'Entity Cell';
div.textContent = props?.value || 'Entity Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
EndpointCell: function MockEndpointCell(options: any) {
const target = options.target;
EndpointCell: function MockEndpointCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'endpoint-cell');
div.textContent = 'Endpoint Cell';
div.textContent = props?.value || 'Endpoint Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
StatusCell: function MockStatusCell(options: any) {
const target = options.target;
StatusCell: function MockStatusCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'status-cell');
div.textContent = 'Status Cell';
div.textContent = props?.value || 'Status Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
ActionsCell: function MockActionsCell(options: any) {
const target = options.target;
ActionsCell: function MockActionsCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'actions-cell');
@ -304,34 +310,35 @@ vi.mock('$lib/components/cells', () => ({
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
GenericCell: function MockGenericCell(options: any) {
const target = options.target;
GenericCell: function MockGenericCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'generic-cell');
div.textContent = 'Generic Cell';
div.textContent = props?.value || 'Generic Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
InstancePoolCell: function MockInstancePoolCell(options: any) {
const target = options.target;
InstancePoolCell: function MockInstancePoolCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'instance-pool-cell');
div.textContent = 'Instance Pool Cell';
div.textContent = props?.value || 'Instance Pool Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
},
TagsCell: function MockTagsCell(options: any) {
const target = options.target;
TagsCell: function MockTagsCell(anchor: any, props: any) {
const target = anchor?.parentNode;
if (target) {
const div = document.createElement('div');
div.setAttribute('data-testid', 'tags-cell');
div.textContent = 'Tags Cell';
div.textContent = props?.tags?.join(', ') || 'Tags Cell';
target.appendChild(div);
}
return { $destroy: vi.fn(), $set: vi.fn(), $on: vi.fn() };
}
}));
}));
*/