diff --git a/backend/public/assets/index-0d7bc5f7.js b/backend/public/assets/index-55cb988b.js similarity index 99% rename from backend/public/assets/index-0d7bc5f7.js rename to backend/public/assets/index-55cb988b.js index 4bc151f..28c4132 100644 --- a/backend/public/assets/index-0d7bc5f7.js +++ b/backend/public/assets/index-55cb988b.js @@ -783,4 +783,4 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho Zielversion: ${Je}. Während des Updates befindet sich StackPulse im Wartungsmodus. Fortfahren?`)))try{X(""),_(!0),await C(),e({variant:"info",title:"Update gestartet",description:"Das Portainer-Update wurde gestartet."})}catch(Nt){const zt=((gt=(mt=Nt.response)==null?void 0:mt.data)==null?void 0:gt.error)||Nt.message||"Portainer-Update konnte nicht gestartet werden";X(zt),e({variant:"error",title:"Update fehlgeschlagen",description:zt})}finally{_(!1)}},[j,P,ft,C,e]);Z.useCallback(async Je=>{var zt,hr,Tr,rn;if(!Je)return;if(j||P){e({variant:"warning",title:"Aktion nicht möglich",description:"Während des Wartungsmodus sind Bereinigungen deaktiviert."});return}const mt=(zt=Je.canonical)==null?void 0:zt.Id;if(!mt)return;const gt=(Je.duplicates||[]).map(yn=>yn.Id).filter(Boolean);if(!gt.length)return;const Nt=((hr=Je.canonical)==null?void 0:hr.Name)||Je.name||`Stack ${mt}`;if(!(typeof window<"u"&&!window.confirm(`Bereinigung für "${Nt}" starten? -Es werden ${gt.length} Duplikate entfernt: ${gt.join(", ")}`))){xt(String(mt));try{const ee=(await Nr.post("/api/maintenance/duplicates/cleanup",{canonicalId:mt,duplicateIds:gt})).data??{};if(ee.success===!1)throw new Error(ee.error||"Bereinigung fehlgeschlagen");const n=Array.isArray(ee.results)?ee.results.filter(o=>o.status==="deleted").map(o=>o.id):gt;e({variant:"success",title:"Bereinigung abgeschlossen",description:`${Nt} – entfernte IDs: ${n.join(", ")}`}),await Ct({silent:!0})}catch(yn){const ee=((rn=(Tr=yn.response)==null?void 0:Tr.data)==null?void 0:rn.error)||yn.message||"Bereinigung fehlgeschlagen";e({variant:"error",title:"Bereinigung fehlgeschlagen",description:ee})}finally{xt(null)}}},[Ct,j,e,P]);const Gn=t!=null&&t.activatedAt?Ws(t.activatedAt):null,yr=t!=null&&t.updatedAt?Ws(t.updatedAt):null,gn=(r==null?void 0:r.status)??(P?"running":"idle"),_o=EV[gn]??gn,Uo=Bs[gn]??Bs.idle,bn=r!=null&&r.stage?MV[r.stage]??r.stage:"–",po=(r==null?void 0:r.logs)??[],Gr=(r==null?void 0:r.targetVersion)??"-",ho=(r==null?void 0:r.resultVersion)??"-",Rn=r!=null&&r.startedAt?Ws(r.startedAt):"-",Oo=r!=null&&r.finishedAt?Ws(r.finishedAt):"-",vn=(r==null?void 0:r.message)??(P?"Update läuft…":""),zr=P||v||l;return te.jsxs("div",{className:"mt-12 mb-8 flex flex-col gap-12",children:[(j||P)&&te.jsx("div",{className:"rounded-lg border border-cyan-500/60 bg-cyan-900/30 px-4 py-3 text-sm text-bluegray-100",children:te.jsxs("div",{className:"flex flex-col gap-1",children:[te.jsxs("span",{children:["Wartungsmodus aktiv",R?` – ${R}`:P?" – Portainer-Update läuft":"","."]}),P&&te.jsxs("span",{className:"text-xs text-indigo-900",children:["Phase: ",bn]})]})}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"mb-8 p-6",children:te.jsx(De.Typography,{variant:"h6",color:"white",className:"flex items-center justify-between",children:te.jsx("span",{children:"Portainer"})})}),te.jsxs(De.CardBody,{className:"flex flex-col gap-4 p-4 pt-0",children:[te.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[te.jsxs("div",{children:[te.jsx("h2",{className:"block antialiased font-sans text-lg font-semibold",children:"Portainer Status"}),te.jsx("p",{className:"block antialiased font-sans text-sm font-light leading-normal text-inherit",children:Bt?"Status wird geprüft…":Tt||(P?"Portainer wird aktuell aktualisiert.":(ft==null?void 0:ft.updateAvailable)===!0?"Es ist ein Update für Portainer verfügbar.":"Portainer ist auf dem aktuellen Stand.")}),Ur&&!Bt&&te.jsxs("p",{className:"mt-1 text-xs text-gray-500 block antialiased font-sans",children:["Stand: ",Ur.toLocaleString("de-DE",{hour:"2-digit",minute:"2-digit",second:"2-digit"})]})]}),te.jsx("div",{className:"flex items-center gap-3",children:te.jsx(De.Button,{onClick:()=>ct({silent:!1}),disabled:Bt||br,className:"w-full",children:"Status aktualisieren"})})]}),te.jsx("div",{className:"flex flex-col gap-4 mt-5 space-y-4 block antialiased font-sans text-sm font-light leading-normal text-inherit",children:!Bt&&!Tt&&ft&&te.jsxs("div",{className:"",children:[te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Installierte Version"}),te.jsx("span",{className:"font-medium",children:ft.currentVersion??"Unbekannt"})]}),te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Neueste Version"}),te.jsx("span",{className:"font-medium",children:ft.latestVersion??"Unbekannt"})]}),te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Status"}),te.jsx("span",{className:`rounded-full px-3 py-0.5 text-xs font-semibold ${ft.updateAvailable===!0?Bs.error:ft.updateAvailable===!1?Bs.success:Bs.idle}`,children:ft.updateAvailable===!0?"Update verfügbar":ft.updateAvailable===!1?"Aktuell":"Unbekannt"})]}),ft.edition&&te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{className:"text-gray-400",children:"Edition"}),te.jsx("span",{className:"font-medium",children:ft.edition})]}),ft.build&&te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{className:"text-gray-400",children:"Build"}),te.jsx("span",{className:"font-medium",children:ft.build})]}),((tn=ft.errors)==null?void 0:tn.latestVersion)&&te.jsxs("div",{className:"rounded-md mt-8 border border-red-500/40 bg-red-900/40 px-3 py-2 text-xs",children:["Neueste Version konnte nicht ermittelt werden: ",ft.errors.latestVersion]}),((mn=ft.errors)==null?void 0:mn.container)&&te.jsxs("div",{className:"rounded-md mt-8 border border-red-500/40 bg-red-900/40 px-3 py-2 text-xs",children:["Container-Details konnten nicht ermittelt werden: ",ft.errors.container]})]})}),te.jsxs("div",{className:"mt-6 grid gap-6 lg:grid-cols-2 xl:grid-cols-3",children:[te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsx("div",{className:"flex items-center justify-between",children:te.jsx("h3",{className:"text-sm font-semibold",children:"SSH-Verbindung"})}),te.jsxs("div",{className:"mt-3 grid gap-3 text-sm",children:[te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide",children:"Host"}),te.jsx("input",{type:"text",value:U.host,onChange:Je=>_t("host",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]}),te.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Port"}),te.jsx("input",{type:"number",min:"1",value:U.port,onChange:Je=>_t("port",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]}),te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Benutzer"}),te.jsx("input",{type:"text",value:U.username,onChange:Je=>_t("username",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]})]}),te.jsxs("div",{className:"grid gap-1",children:[te.jsxs("div",{className:"flex items-center justify-between text-xs uppercase tracking-wide ",children:[te.jsx("label",{htmlFor:"maintenance-ssh-password",className:"cursor-pointer",children:"Passwort"}),te.jsx("button",{type:"button",onClick:()=>me(Je=>!Je),disabled:xe||ce||ye||P,className:"text-[11px] font-medium text-blue-500 transition hover:text-blue-800 disabled:opacity-50",children:pe?"Verbergen":"Anzeigen"})]}),te.jsx("input",{id:"maintenance-ssh-password",type:pe?"text":"password",value:U.password,onChange:Je=>_t("password",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none",placeholder:"Passwort für den SSH-Benutzer",autoComplete:"off",spellCheck:!1}),ae&&!U.password&&te.jsx("span",{className:"text-[11px] ",children:"Ein Passwort ist gespeichert. Neuer Inhalt ersetzt es oder lösche die Konfiguration unten."})]}),te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Weitere SSH-Argumente"}),te.jsx("textarea",{rows:3,value:U.extraSshArgs,onChange:Je=>_t("extraSshArgs",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 font-mono text-[11px] focus:border-purple-500 focus:outline-none",placeholder:"je Zeile ein Argument (optional)"})]})]}),te.jsxs("div",{className:"mt-4 grid gap-2",children:[te.jsx(De.Button,{onClick:Jt,disabled:xe||ce||ye||P,className:"mt-3 w-full",children:xe?"Speichern…":"SSH-Konfiguration speichern"}),te.jsx(De.Button,{onClick:Po,disabled:xe||ce||ye||P,className:"w-full bg-teal-500",children:ce?"Test läuft…":"Verbindung testen"}),te.jsx(De.Button,{onClick:hn,disabled:xe||ce||ye||P,className:"w-full",color:"purple",children:ye?"Löschen…":"SSH-Einstellungen löschen"})]}),Me&&te.jsx("p",{className:`mt-3 text-xs ${Me.success?"text-green-800":"text-red-800"}`,children:Me.success?"SSH-Verbindung erfolgreich.":`SSH-Verbindung fehlgeschlagen: ${Me.error}`})]}),te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("h3",{className:"text-sm font-semibold",children:"Update-Skript"}),te.jsxs("span",{className:"text-xs",children:["Quelle: ",Ye]})]}),te.jsx("textarea",{value:y,onChange:Je=>p(Je.target.value),rows:10,disabled:v||P,className:"mt-3 w-full rounded-md border border-gray-700/20 px-3 py-2 font-mono text-xs focus:border-purple-500 focus:outline-none"}),te.jsxs("div",{className:"mt-3 grid gap-2",children:[te.jsx(De.Button,{onClick:Et,disabled:!_e||v||P,className:"mt-3 w-full",children:"Speichern"}),te.jsx(De.Button,{color:"purple",onClick:$t,disabled:!a||a.source!=="custom"||v||P,className:"w-full",children:"Standard wiederherstellen"})]}),(a==null?void 0:a.customUpdatedAt)&&te.jsxs("p",{className:"mt-2 text-xs text-gray-500",children:["Zuletzt geändert: ",Ws(a.customUpdatedAt)]})]}),te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("h3",{className:"text-sm font-semibold",children:"Update-Status"}),te.jsx("span",{className:`rounded-full px-3 py-0.5 text-xs font-semibold ${Uo}`,children:_o})]}),te.jsxs("div",{className:"mt-3 grid gap-2 text-xs",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Phase"}),te.jsx("span",{className:"font-medium",children:bn})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Ziel-Version"}),te.jsx("span",{className:"font-medium",children:Gr})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Installierte Version"}),te.jsx("span",{className:"font-medium",children:ho})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Gestartet"}),te.jsx("span",{children:Rn})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Beendet"}),te.jsx("span",{children:Oo})]}),vn&&te.jsx("div",{className:"rounded-md border border-green-700 bg-green-800 px-3 py-2 text-xs text-white",children:vn}),(r==null?void 0:r.error)&&te.jsx("div",{className:"rounded-md border border-red-500/60 bg-red-900/40 px-3 py-2 text-xs text-red-200",children:r.error}),M&&te.jsx("div",{className:"rounded-md border border-red-500/60 bg-red-900/40 px-3 py-2 text-xs text-red-200",children:M})]}),te.jsx("div",{className:"mt-3 h-40 overflow-y-auto rounded-md border border-gray-700/20 bg-gray-950/70 p-3 font-mono text-[11px] leading-relaxed",children:po.length===0?te.jsx("p",{className:"text-gray-500",children:"Noch keine Protokolle vorhanden."}):po.map((Je,mt)=>te.jsxs("div",{className:"mb-2 last:mb-0",children:[te.jsxs("span",{className:"text-gray-500",children:["[",NV(Je.timestamp),"]"]})," ",te.jsx("span",{className:(RV[Je.level]??"text-gray-300")+" whitespace-normal break-words",style:{overflowWrap:"anywhere",wordBreak:"normal"},children:Je.message})]},`${Je.timestamp}-${mt}`))}),te.jsx(De.Button,{onClick:Mn,disabled:zr||m,className:"mt-3 w-full",children:m?"Update wird gestartet…":"Portainer aktualisieren"})]})]})]})]}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{color:"transparent",floated:!1,shadow:!1,className:"m-0 p-4 block antialiased font-sans",children:te.jsx(De.Typography,{variant:"h5",color:"blue-gray",className:"block antialiased font-sans",children:"Wartungsmodus"})}),te.jsxs(De.CardBody,{className:"flex flex-col gap-4 p-4",children:[te.jsxs("div",{className:"flex items-start justify-between gap-4",children:[te.jsxs("div",{className:"space-y-1",children:[te.jsx("p",{className:"text-sm text-blue-gray-200",children:"Schaltet StackPulse für Benutzer in den Wartungsmodus."}),R?te.jsxs("p",{className:"text-xs text-gray-500",children:["Hinweis: ",R]}):null,te.jsx("p",{className:"text-xs text-gray-500",children:j?`Aktiv seit ${Gn??"-"}.`:`Zuletzt geändert: ${yr??"-"}.`}),P&&te.jsx("p",{className:"text-xs text-amber-600",children:"Portainer-Update läuft – Umschalten vorübergehend gesperrt."}),te.jsxs("p",{className:"text-xs text-gray-500",children:["Status: ",j?"Aktiv":"Inaktiv"]})]}),te.jsx(De.Switch,{checked:j,disabled:H||l||P,onChange:Je=>Dr(Je.target.checked),ripple:!1,color:"amber"})]}),H&&te.jsx("p",{className:"text-xs text-gray-500",children:"Wartungsmodus wird aktualisiert…"})]})]})]})}const qs=Xn.forwardRef(({value:e,onValueSelect:t,onClick:r,onKeyDown:a,...s},l)=>{const{setOpen:f}=De.useSelect(),b=Z.useCallback(()=>{(typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame:F=>setTimeout(F,0))(()=>{f(!0)})},[f]),C=Z.useCallback(()=>{typeof t=="function"&&t(e)},[t,e]),T=Z.useCallback(I=>{typeof r=="function"&&r(I),C(),b()},[r,C,b]),O=Z.useCallback(I=>{typeof a=="function"&&a(I),(I.key==="Enter"||I.key===" ")&&(C(),b())},[a,C,b]);return te.jsx(De.Option,{...s,value:e,ref:l,onClick:T,onKeyDown:O})});qs.displayName="StickyOption";const LV={success:"text-green-400",warning:"text-yellow-400",error:"text-red-400",started:"text-blue-300"},jV=e=>{if(!e)return"-";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString("de-DE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})},Ux=e=>{if(e)return e.replace("T"," ")},Gx="redeployLogFilters",on="__all__",Bu="- Alle -",$x="50",G_=[{value:"10",label:"10"},{value:"25",label:"25"},{value:"50",label:"50"},{value:"100",label:"100"},{value:"all",label:"Alle"}],qx=new Set(G_.map(e=>e.value)),Fp={Einzeln:"Einzeln",Alle:"Alle",Auswahl:"Auswahl",single:"Einzeln",all:"Alle",selection:"Auswahl"},DV=e=>!!(e.stacks&&e.stacks.length||e.statuses&&e.statuses.length||e.endpoints&&e.endpoints.length||e.redeployTypes&&e.redeployTypes.length||e.message&&e.message.trim()||e.from&&e.from.trim()||e.to&&e.to.trim());function zV(){const[e,t]=Z.useState([]),[r,a]=Z.useState(0),[s,l]=Z.useState(!0),[f,b]=Z.useState(""),[C,T]=Z.useState(!1),[O,I]=Z.useState([]),[F,z]=Z.useState([]),[j,R]=Z.useState([]),[P,y]=Z.useState([]),[p,v]=Z.useState([]),[g,m]=Z.useState([]),[_,M]=Z.useState([]),[X,H]=Z.useState([]),[W,U]=Z.useState(""),[K,ae]=Z.useState(""),[ne,pe]=Z.useState(""),[me,xe]=Z.useState(!1),[be,ce]=Z.useState(!1),[he,ye]=Z.useState(!1),[Pe,Me]=Z.useState(0),[Re,Le]=Z.useState($x),[_e,Ye]=Z.useState(1),Fe=Z.useCallback(()=>{},[]),Ne=Z.useCallback(Ee=>{const We=Array.isArray(Ee)?Ee:(Ee==null?void 0:Ee.items)??[],ct=new Map,Ct=new Set,_t=new Set,ht=new Set;We.forEach(Et=>{if(Et.stackId){const $t=String(Et.stackId),Jt=Et.stackName||`Stack ${$t}`;ct.set($t,Jt)}Et.status&&Ct.add(Et.status),Et.endpoint!==null&&Et.endpoint!==void 0&&Et.endpoint!==""&&_t.add(String(Et.endpoint)),Et.redeployType&&ht.add(Et.redeployType)}),I(Array.from(ct.entries()).map(([Et,$t])=>({value:Et,label:$t})).sort((Et,$t)=>Et.label.localeCompare($t.label))),z(Array.from(Ct).sort()),R(Array.from(_t).sort((Et,$t)=>Et.localeCompare($t,void 0,{numeric:!0}))),y(Array.from(ht).sort()),ye(!0)},[]),Xe=Z.useMemo(()=>{const Ee=new Map;return O.forEach(We=>{Ee.set(We.value,We.label)}),Ee},[O]);Z.useEffect(()=>{he&&v(Ee=>{const We=Ee.filter(ct=>O.some(Ct=>Ct.value===ct));return We.length===Ee.length?Ee:We})},[he,O]),Z.useEffect(()=>{he&&m(Ee=>{const We=Ee.filter(ct=>F.includes(ct));return We.length===Ee.length?Ee:We})},[he,F]),Z.useEffect(()=>{he&&M(Ee=>{const We=Ee.filter(ct=>j.includes(ct));return We.length===Ee.length?Ee:We})},[he,j]),Z.useEffect(()=>{he&&H(Ee=>{const We=Ee.filter(ct=>P.includes(ct));return We.length===Ee.length?Ee:We})},[he,P]),Z.useEffect(()=>{if(typeof window>"u"){ce(!0);return}try{const Ee=window.localStorage.getItem(Gx);if(Ee){const We=JSON.parse(Ee),ct=(We==null?void 0:We.filters)??We??{},Ct=(We==null?void 0:We.pagination)??{};v(ct.stacks||[]),m(ct.statuses||[]),M(ct.endpoints||[]),H(ct.redeployTypes||[]),U(ct.message||""),ae(ct.from||""),pe(ct.to||""),xe(DV(ct));const _t=Ct.perPage;if(_t!==void 0){const Et=String(_t);qx.has(Et)&&Le(Et)}const ht=Ct.page;typeof ht=="number"&&ht>0&&Ye(ht)}}catch(Ee){console.error("❌ Fehler beim Laden der gespeicherten Log-Filter:",Ee)}finally{ce(!0)}},[]);const Ve=Z.useCallback(()=>{const Ee={};p.length&&(Ee.stackIds=p.join(",")),g.length&&(Ee.statuses=g.join(",")),_.length&&(Ee.endpoints=_.join(",")),X.length&&(Ee.redeployTypes=X.join(",")),W.trim()&&(Ee.message=W.trim());const We=Ux(K);We&&(Ee.from=We);const ct=Ux(ne);return ct&&(Ee.to=ct),Ee},[p,g,_,X,W,K,ne]);Z.useEffect(()=>{if(!be)return;let Ee=!1;return Nr.get("/api/logs",{params:{perPage:"all",page:1}}).then(We=>{Ee||Ne(We.data)}).catch(We=>{Ee||console.error("⚠️ Konnte Filteroptionen nicht aktualisieren:",We)}),()=>{Ee=!0}},[be,Ne,Pe]);const Ke=Z.useMemo(()=>({stacks:p,statuses:g,endpoints:_,redeployTypes:X,message:W,from:K,to:ne}),[p,g,_,X,W,K,ne]);Z.useEffect(()=>{if(!be)return;const Ee={...Ve()};Re==="all"?(Ee.perPage="all",Ee.page=1):(Ee.perPage=Re,Ee.page=_e);let We=!1;return l(!0),b(""),Nr.get("/api/logs",{params:Ee}).then(ct=>{if(We)return;const Ct=ct.data||{},_t=Array.isArray(Ct)?Ct:Ct.items??[],ht=Array.isArray(Ct)?_t.length:Ct.total??_t.length;if(t(_t),a(ht),Re==="all")_e!==1&&Ye(1);else{const Et=Math.max(1,Math.ceil((ht||0)/Number(Re))),$t=Math.min(Math.max(_e,1),Et);$t!==_e&&Ye($t)}}).catch(ct=>{We||(console.error("❌ Fehler beim Laden der Logs:",ct),b("Fehler beim Laden der Redeploy-Logs"))}).finally(()=>{We||l(!1)}),()=>{We=!0}},[be,Ve,Ne,Pe,Re,_e]),Z.useEffect(()=>{if(be&&!(typeof window>"u"))try{window.localStorage.setItem(Gx,JSON.stringify({filters:Ke,pagination:{perPage:Re,page:_e}}))}catch(Ee){console.error("⚠️ Konnte Filter nicht speichern:",Ee)}},[be,Ke,Re,_e]);const tt=Ee=>We=>{var _t;if(typeof We=="string"){const ht=We;if(ht==="")return;Ee(Et=>ht===on?[]:Et.includes(ht)?Et.filter($t=>$t!==ht):[...Et,ht]),Ye(1);return}const ct=(_t=We==null?void 0:We.target)==null?void 0:_t.selectedOptions;if(!ct)return;const Ct=Array.from(ct).map(ht=>ht.value);Ct.includes(on)?Ee([]):Ee(Ct),Ye(1)},Ze=(Ee,We)=>{Ee(ct=>ct.filter(Ct=>Ct!==We)),Ye(1)},qe=()=>{v([]),m([]),M([]),H([]),U(""),ae(""),pe(""),xe(!1),Ye(1)},it=()=>{xe(Ee=>!Ee)},xt=Ee=>{const We=Ee.target.value;qx.has(We)&&(Le(We),Ye(1))},At=Ee=>{if(Re==="all"||Ee<1)return;const We=Math.max(1,Math.ceil((r||0)/Number(Re)));Ee>We||Ye(Ee)},Vt=Z.useMemo(()=>{const Ee=O.filter(We=>We.value!==on);return[{value:on,label:Bu},...Ee]},[O]),Mt=Z.useMemo(()=>{const Ee=F.filter(We=>We!==on).map(We=>({value:We,label:We}));return[{value:on,label:Bu},...Ee]},[F]),ft=Z.useMemo(()=>{const Ee=j.filter(We=>We!==on).map(We=>({value:We,label:We}));return[{value:on,label:Bu},...Ee]},[j]),Qt=Z.useMemo(()=>{const Ee=P.filter(We=>We!==on).map(We=>({value:We,label:Fp[We]??We}));return[{value:on,label:Bu},...Ee]},[P]),Bt=Z.useMemo(()=>{let Ee=0;return p.length&&(Ee+=p.length),g.length&&(Ee+=g.length),_.length&&(Ee+=_.length),X.length&&(Ee+=X.length),W.trim()&&(Ee+=1),K&&(Ee+=1),ne&&(Ee+=1),Ee},[p,g,_,W,K,ne]),Rt=Z.useMemo(()=>{if(Re==="all")return 1;const Ee=Number(Re)||Number($x);return Math.max(1,Math.ceil((r||0)/Ee))},[Re,r]),Tt=Z.useMemo(()=>r===0?0:Re==="all"?1:(_e-1)*Number(Re)+1,[r,Re,_e]),Ut=Z.useMemo(()=>r===0?0:Re==="all"?r:Math.min(r,(_e-1)*Number(Re)+e.length),[r,Re,_e,e.length]),br=async Ee=>{if(window.confirm("Diesen Log-Eintrag dauerhaft löschen?")){T(!0),b("");try{await Nr.delete(`/api/logs/${Ee}`),Me(We=>We+1)}catch(We){console.error("❌ Fehler beim Löschen des Logs:",We),b("Fehler beim Löschen des Redeploy-Logs")}finally{T(!1)}}},Gt=async()=>{if(e.length&&window.confirm("Alle angezeigten Logs (entsprechend Filter) löschen?")){T(!0),b("");try{const Ee={...Ve(),ids:e.map(We=>We.id).join(",")};await Nr.delete("/api/logs",{params:Ee}),Me(We=>We+1)}catch(Ee){console.error("❌ Fehler beim Löschen der gefilterten Logs:",Ee),b("Fehler beim Löschen der gefilterten Logs")}finally{T(!1)}}},Ur=async Ee=>{T(!0),b("");try{const We=await Nr.get("/api/logs/export",{params:{...Ve(),format:Ee},responseType:"blob"}),ct=We.headers["content-type"]||(Ee==="sql"?"application/sql":"text/plain"),_t=(We.headers["content-disposition"]||"").match(/filename="?([^";]+)"?/i),ht=(_t==null?void 0:_t[1])||`redeploy-logs.${Ee}`,Et=new Blob([We.data],{type:ct}),$t=window.URL.createObjectURL(Et),Jt=document.createElement("a");Jt.href=$t,Jt.download=ht,document.body.appendChild(Jt),Jt.click(),Jt.remove(),window.URL.revokeObjectURL($t)}catch(We){console.error("❌ Fehler beim Export der Logs:",We),b("Fehler beim Export der Redeploy-Logs")}finally{T(!1)}};return Xn.useState(!1),te.jsxs("div",{className:"mt-12 mb-8 flex flex-col gap-12",children:[te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"p-6 pt-2 pb-2",children:te.jsx(De.Typography,{variant:"h6",color:"white",children:te.jsxs("button",{onClick:it,className:"flex w-full items-center justify-between",children:[te.jsxs("span",{className:"flex items-center gap-2",children:[te.jsx("span",{children:"Filter und Optionen"}),Bt>0&&te.jsxs("span",{className:"rounded-full bg-blue-gray-500/80 px-2 py-0.5 text-xs text-white",children:[Bt," aktiv"]})]}),te.jsx("span",{className:"text-xs uppercase tracking-wide text-gray-400",children:me?"Ausblenden":"Anzeigen"})]})})}),te.jsx(De.CardBody,{children:me&&te.jsxs("div",{children:[te.jsxs("div",{className:"flex flex-wrap gap-2",children:[te.jsx(De.Button,{onClick:()=>Ur("txt"),disabled:C||s,className:"w-full md:flex-1",children:"Export TXT"}),te.jsx(De.Button,{onClick:()=>Ur("sql"),disabled:C||s,className:"w-full md:flex-1",children:"Export SQL"}),te.jsx(De.Button,{color:"red",onClick:Gt,disabled:C||s||e.length===0,className:"w-full md:flex-1",children:"Angezeigte löschen"})]}),te.jsxs("div",{className:"flex flex-wrap gap-2 mt-10",children:[te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Stacks",children:Vt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(v),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:p.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300 ",children:"Alle Stacks"}):te.jsx("span",{children:p.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(v,Ee),className:"rounded-full bg-purple-500/80 px-2 py-0.5 text-white transition hover:bg-purple-500/90 focus:outline-none focus:ring-2 focus:ring-purple-300 cursor-pointer",title:"Filter entfernen",children:Xe.get(Ee)??`Stack ${Ee}`},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Status",children:Mt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(m),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:g.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Status"}):te.jsx("span",{children:g.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(m,Ee),className:"rounded-full bg-brown-500/80 px-2 py-0.5 text-white transition hover:bg-brown-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:Ee},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Redeploy-Typ",children:Qt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(H),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:X.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Typen"}):te.jsx("span",{children:X.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(H,Ee),className:"rounded-full bg-brown-500/80 px-2 py-0.5 text-white transition hover:bg-brown-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:Fp[Ee]??Ee},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Endpoints",children:ft.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(M),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:_.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Endpoints"}):te.jsx("span",{children:_.map(Ee=>te.jsxs("button",{type:"button",onClick:()=>Ze(M,Ee),className:"rounded-full bg-teal-500/80 px-2 py-0.5 text-white transition hover:bg-teal-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:["Endpoint ",Ee]},Ee))})})]})]}),te.jsx("div",{className:"flex flex-wrap gap-2 mt-5",children:te.jsx("div",{className:"grid gap-4 flex-1",children:te.jsx(De.Input,{value:W,onChange:Ee=>{U(Ee.target.value),Ye(1)},variant:"static",label:"Nachricht (Freitext)",placeholder:"Suche"})})}),te.jsxs("div",{className:"flex flex-col md:flex-row flex-wrap gap-4 mt-8",children:[te.jsx("div",{className:"flex-1",children:te.jsx(De.Input,{type:"datetime-local",variant:"static",label:"Von",value:K,onChange:Ee=>{ae(Ee.target.value),Ye(1)},className:"w-full"})}),te.jsx("div",{className:"flex-1",children:te.jsx(De.Input,{type:"datetime-local",variant:"static",label:"Bis",value:ne,onChange:Ee=>{pe(Ee.target.value),Ye(1)},className:"w-full"})}),te.jsx("div",{className:"flex-1",children:te.jsx(De.Button,{onClick:qe,disabled:C||s,className:"w-full",children:"Zurücksetzen"})})]})]})})]}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"mb-8 p-6",children:te.jsxs(De.Typography,{variant:"h6",color:"white",className:"flex items-center justify-between",children:[te.jsx("span",{children:"Logs"}),te.jsxs("div",{className:"flex items-center gap-2",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide text-gray-400",children:"Einträge pro Seite:"}),te.jsx("select",{value:Re,onChange:xt,className:"rounded-md border border-gray-700 bg-gray-900 px-2 py-1 text-sm text-gray-100 focus:border-purple-500 focus:outline-none focus:ring-1 focus:ring-purple-500",children:G_.map(({value:Ee,label:We})=>te.jsx("option",{value:Ee,children:We},Ee))})]})]})}),te.jsx(De.CardBody,{className:"overflow-x-scroll px-0 pt-0 pb-2",children:te.jsxs("table",{className:"w-full min-w-[640px] table-auto",children:[te.jsx("thead",{children:te.jsx("tr",{children:["Zeitpunkt","Stack","Art","Status","Nachricht","Endpoint","Aktionen"].map(Ee=>te.jsx("th",{className:"border-b border-blue-gray-50 py-3 px-5 text-left",children:te.jsx(De.Typography,{variant:"small",className:"text-[11px] font-bold uppercase text-blue-gray-400",children:Ee})},Ee))})}),te.jsx("tbody",{children:e.map(Ee=>{const We=LV[Ee.status]||"text-blue-300",ct="py-3 px-5",Ct=Ee.stackName||"Unbekannt",_t=Ct!=="---"&&Ee.stackId!==void 0&&Ee.stackId!==null,ht=Ee.redeployType?Fp[Ee.redeployType]??Ee.redeployType:"---";return te.jsxs("tr",{children:[te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",className:"mb-1 block text-xs font-medium text-blue-gray-600",children:jV(Ee.timestamp)})}),te.jsx("td",{className:ct,children:te.jsxs("div",{className:"flex flex-col",children:[te.jsx("span",{className:"font-medium",children:Ct}),te.jsx(De.Typography,{variant:"small",children:_t&&te.jsxs("span",{className:"text-xs text-gray-400",children:["ID: ",Ee.stackId]})})]})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:ht})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",className:`font-semibold ${We}`,children:Ee.status})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:Ee.message||"-"})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:Ee.endpoint??"-"})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:te.jsx("button",{onClick:()=>br(Ee.id),disabled:C,className:"rounded-md border border-red-600 px-3 py-1 text-xs text-red-300 transition hover:bg-red-600/20 disabled:opacity-60",children:"Löschen"})})})]},Ee.id)})})]})})]}),te.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[te.jsx("span",{children:r===0?"Keine Einträge":Re==="all"?`Zeige alle ${r} Einträge`:`Zeige ${Tt.toLocaleString()} – ${Ut.toLocaleString()} von ${r.toLocaleString()} Einträgen`}),Re!=="all"&&te.jsxs("div",{className:"flex items-center gap-2",children:[te.jsx("button",{onClick:()=>At(_e-1),disabled:_e<=1||C,className:"rounded-md border border-slate-300 p-2.5 text-center text-sm transition-all shadow-sm hover:shadow-lg text-slate-600 hover:text-white hover:bg-slate-800 hover:border-slate-800 focus:text-white focus:bg-slate-800 focus:border-slate-800 active:border-slate-800 active:text-white active:bg-slate-800 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none",children:te.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",className:"w-4 h-4",children:te.jsx("path",{d:"M11.03 3.97a.75.75 0 0 1 0 1.06l-6.22 6.22H21a.75.75 0 0 1 0 1.5H4.81l6.22 6.22a.75.75 0 1 1-1.06 1.06l-7.5-7.5a.75.75 0 0 1 0-1.06l7.5-7.5a.75.75 0 0 1 1.06 0Z"})})}),te.jsxs("p",{className:"text-slate-600",children:["Seite ",te.jsx("strong",{className:"text-slate-800",children:_e})," / ",te.jsx("strong",{className:"text-slate-800",children:Rt})]}),te.jsx("button",{onClick:()=>At(_e+1),disabled:_e>=Rt||C,className:"rounded-md border border-slate-300 p-2.5 text-center text-sm transition-all shadow-sm hover:shadow-lg text-slate-600 hover:text-white hover:bg-slate-800 hover:border-slate-800 focus:text-white focus:bg-slate-800 focus:border-slate-800 active:border-slate-800 active:text-white active:bg-slate-800 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none",type:"button",children:te.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",className:"w-4 h-4",children:te.jsx("path",{d:"M12.97 3.97a.75.75 0 0 1 1.06 0l7.5 7.5a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 1 1-1.06-1.06l6.22-6.22H3a.75.75 0 0 1 0-1.5h16.19l-6.22-6.22a.75.75 0 0 1 0-1.06Z"})})})]})]})]})}const Vp={className:"w-5 h-5 text-inherit"},gg=[{layout:"dashboard",pages:[{icon:te.jsx($N,{...Vp}),name:"stacks",path:"/stacks",element:te.jsx(UF,{})},{icon:te.jsx(aI,{...Vp}),name:"maintenance",path:"/maintenance",element:te.jsx(IV,{})},{icon:te.jsx(jN,{...Vp}),name:"logs",path:"/logs",element:te.jsx(zV,{})}]}];function $_(){const[e,t]=Jd(),{sidenavType:r}=e;return te.jsxs("div",{className:"min-h-screen bg-blue-gray-50/50",children:[te.jsx(ef,{routes:gg,brandImg:r==="dark"?"/img/logo-ct.png":"/img/logo-ct-dark.png"}),te.jsxs("div",{className:"p-4 xl:ml-80",children:[te.jsx(h_,{}),te.jsx(g_,{}),te.jsx(De.IconButton,{size:"lg",color:"white",className:"fixed bottom-8 right-8 z-40 rounded-full shadow-blue-gray-900/10",ripple:!1,onClick:()=>yb(t,!0),children:te.jsx(CC,{className:"h-5 w-5"})}),te.jsx(h0,{children:gg.map(({layout:a,pages:s})=>a==="dashboard"&&s.map(({path:l,element:f})=>te.jsx(ji,{exact:!0,path:l,element:f})))}),te.jsx("div",{className:"text-blue-gray-600",children:te.jsx(b_,{})})]})]})}$_.displayName="/src/layout/dashboard.jsx";function q_(){return te.jsx("div",{className:"relative min-h-screen w-full",children:te.jsx(h0,{children:gg.map(({layout:e,pages:t})=>e==="auth"&&t.map(({path:r,element:a})=>te.jsx(ji,{exact:!0,path:r,element:a})))})})}q_.displayName="/src/layout/Auth.jsx";function FV(){return te.jsxs(h0,{children:[te.jsx(ji,{path:"/dashboard/*",element:te.jsx($_,{})}),te.jsx(ji,{path:"/auth/*",element:te.jsx(q_,{})}),te.jsx(ji,{path:"*",element:te.jsx(ZR,{to:"/dashboard/home",replace:!0})})]})}Bp.createRoot(document.getElementById("root")).render(te.jsx(Xn.StrictMode,{children:te.jsx(aN,{children:te.jsx(OV,{children:te.jsx(TV,{children:te.jsx(De.ThemeProvider,{children:te.jsx(mb,{children:te.jsx(FV,{})})})})})})})); +Es werden ${gt.length} Duplikate entfernt: ${gt.join(", ")}`))){xt(String(mt));try{const ee=(await Nr.post("/api/maintenance/duplicates/cleanup",{canonicalId:mt,duplicateIds:gt})).data??{};if(ee.success===!1)throw new Error(ee.error||"Bereinigung fehlgeschlagen");const n=Array.isArray(ee.results)?ee.results.filter(o=>o.status==="deleted").map(o=>o.id):gt;e({variant:"success",title:"Bereinigung abgeschlossen",description:`${Nt} – entfernte IDs: ${n.join(", ")}`}),await Ct({silent:!0})}catch(yn){const ee=((rn=(Tr=yn.response)==null?void 0:Tr.data)==null?void 0:rn.error)||yn.message||"Bereinigung fehlgeschlagen";e({variant:"error",title:"Bereinigung fehlgeschlagen",description:ee})}finally{xt(null)}}},[Ct,j,e,P]);const Gn=t!=null&&t.activatedAt?Ws(t.activatedAt):null,yr=t!=null&&t.updatedAt?Ws(t.updatedAt):null,gn=(r==null?void 0:r.status)??(P?"running":"idle"),_o=EV[gn]??gn,Uo=Bs[gn]??Bs.idle,bn=r!=null&&r.stage?MV[r.stage]??r.stage:"–",po=(r==null?void 0:r.logs)??[],Gr=(r==null?void 0:r.targetVersion)??"-",ho=(r==null?void 0:r.resultVersion)??"-",Rn=r!=null&&r.startedAt?Ws(r.startedAt):"-",Oo=r!=null&&r.finishedAt?Ws(r.finishedAt):"-",vn=(r==null?void 0:r.message)??(P?"Update läuft…":""),zr=P||v||l;return te.jsxs("div",{className:"mt-12 mb-8 flex flex-col gap-12",children:[(j||P)&&te.jsx("div",{className:"rounded-lg border border-cyan-500/60 bg-cyan-900/30 px-4 py-3 text-sm text-bluegray-100",children:te.jsxs("div",{className:"flex flex-col gap-1",children:[te.jsxs("span",{children:["Wartungsmodus aktiv",R?` – ${R}`:P?" – Portainer-Update läuft":"","."]}),P&&te.jsxs("span",{className:"text-xs text-indigo-900",children:["Phase: ",bn]})]})}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"mb-8 p-6",children:te.jsx(De.Typography,{variant:"h6",color:"white",className:"flex items-center justify-between",children:te.jsx("span",{children:"Portainer"})})}),te.jsxs(De.CardBody,{className:"flex flex-col gap-4 p-4 pt-0",children:[te.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[te.jsxs("div",{children:[te.jsx("h2",{className:"block antialiased font-sans text-lg font-semibold",children:"Portainer Status"}),te.jsx("p",{className:"block antialiased font-sans text-sm font-light leading-normal text-inherit",children:Bt?"Status wird geprüft…":Tt||(P?"Portainer wird aktuell aktualisiert.":(ft==null?void 0:ft.updateAvailable)===!0?"Es ist ein Update für Portainer verfügbar.":"Portainer ist auf dem aktuellen Stand.")}),Ur&&!Bt&&te.jsxs("p",{className:"mt-1 text-xs text-gray-500 block antialiased font-sans",children:["Stand: ",Ur.toLocaleString("de-DE",{hour:"2-digit",minute:"2-digit",second:"2-digit"})]})]}),te.jsx("div",{className:"flex items-center gap-3",children:te.jsx(De.Button,{onClick:()=>ct({silent:!1}),disabled:Bt||br,className:"w-full",children:"Status aktualisieren"})})]}),te.jsx("div",{className:"flex flex-col gap-4 mt-5 space-y-4 block antialiased font-sans text-sm font-light leading-normal text-inherit",children:!Bt&&!Tt&&ft&&te.jsxs("div",{className:"",children:[te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Installierte Version"}),te.jsx("span",{className:"font-medium",children:ft.currentVersion??"Unbekannt"})]}),te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Neueste Version"}),te.jsx("span",{className:"font-medium",children:ft.latestVersion??"Unbekannt"})]}),te.jsxs("div",{className:"flex items-center justify-between space-y-2",children:[te.jsx("span",{children:"Status"}),te.jsx("span",{className:`rounded-full px-3 py-0.5 text-xs font-semibold ${ft.updateAvailable===!0?Bs.error:ft.updateAvailable===!1?Bs.success:Bs.idle}`,children:ft.updateAvailable===!0?"Update verfügbar":ft.updateAvailable===!1?"Aktuell":"Unbekannt"})]}),ft.edition&&te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{className:"text-gray-400",children:"Edition"}),te.jsx("span",{className:"font-medium",children:ft.edition})]}),ft.build&&te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{className:"text-gray-400",children:"Build"}),te.jsx("span",{className:"font-medium",children:ft.build})]}),((tn=ft.errors)==null?void 0:tn.latestVersion)&&te.jsxs("div",{className:"rounded-md mt-8 border border-red-500/40 bg-red-900/40 px-3 py-2 text-xs",children:["Neueste Version konnte nicht ermittelt werden: ",ft.errors.latestVersion]}),((mn=ft.errors)==null?void 0:mn.container)&&te.jsxs("div",{className:"rounded-md mt-8 border border-red-500/40 bg-red-900/40 px-3 py-2 text-xs",children:["Container-Details konnten nicht ermittelt werden: ",ft.errors.container]})]})}),te.jsxs("div",{className:"mt-6 grid gap-6 lg:grid-cols-2 xl:grid-cols-3",children:[te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsx("div",{className:"flex items-center justify-between",children:te.jsx("h3",{className:"text-sm font-semibold",children:"SSH-Verbindung"})}),te.jsxs("div",{className:"mt-3 grid gap-3 text-sm",children:[te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide",children:"Host"}),te.jsx("input",{type:"text",value:U.host,onChange:Je=>_t("host",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]}),te.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Port"}),te.jsx("input",{type:"number",min:"1",value:U.port,onChange:Je=>_t("port",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]}),te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Benutzer"}),te.jsx("input",{type:"text",value:U.username,onChange:Je=>_t("username",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none"})]})]}),te.jsxs("div",{className:"grid gap-1",children:[te.jsxs("div",{className:"flex items-center justify-between text-xs uppercase tracking-wide ",children:[te.jsx("label",{htmlFor:"maintenance-ssh-password",className:"cursor-pointer",children:"Passwort"}),te.jsx("button",{type:"button",onClick:()=>me(Je=>!Je),disabled:xe||ce||ye||P,className:"text-[11px] font-medium text-blue-500 transition hover:text-blue-800 disabled:opacity-50",children:pe?"Verbergen":"Anzeigen"})]}),te.jsx("input",{id:"maintenance-ssh-password",type:pe?"text":"password",value:U.password,onChange:Je=>_t("password",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none",placeholder:"Passwort für den SSH-Benutzer",autoComplete:"off",spellCheck:!1}),ae&&!U.password&&te.jsx("span",{className:"text-[11px] ",children:"Ein Passwort ist gespeichert. Neuer Inhalt ersetzt es oder lösche die Konfiguration unten."})]}),te.jsxs("label",{className:"grid gap-1",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide ",children:"Weitere SSH-Argumente"}),te.jsx("textarea",{rows:3,value:U.extraSshArgs,onChange:Je=>_t("extraSshArgs",Je.target.value),disabled:xe||ce||ye||P,className:"w-full rounded-md border border-gray-700 bg-gray-950/70 px-3 py-2 font-mono text-[11px] focus:border-purple-500 focus:outline-none",placeholder:"je Zeile ein Argument (optional)"})]})]}),te.jsxs("div",{className:"mt-4 grid gap-2",children:[te.jsx(De.Button,{onClick:Jt,disabled:xe||ce||ye||P,className:"mt-3 w-full",children:xe?"Speichern…":"SSH-Konfiguration speichern"}),te.jsx(De.Button,{onClick:Po,disabled:xe||ce||ye||P,className:"w-full bg-teal-500",children:ce?"Test läuft…":"Verbindung testen"}),te.jsx(De.Button,{onClick:hn,disabled:xe||ce||ye||P,className:"w-full",color:"purple",children:ye?"Löschen…":"SSH-Einstellungen löschen"})]}),Me&&te.jsx("p",{className:`mt-3 text-xs ${Me.success?"text-green-800":"text-red-800"}`,children:Me.success?"SSH-Verbindung erfolgreich.":`SSH-Verbindung fehlgeschlagen: ${Me.error}`})]}),te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("h3",{className:"text-sm font-semibold",children:"Update-Skript"}),te.jsxs("span",{className:"text-xs",children:["Quelle: ",Ye]})]}),te.jsx("textarea",{value:y,onChange:Je=>p(Je.target.value),rows:10,disabled:v||P,className:"mt-3 w-full rounded-md border border-gray-700/20 px-3 py-2 font-mono text-xs focus:border-purple-500 focus:outline-none"}),te.jsxs("div",{className:"mt-3 grid gap-2",children:[te.jsx(De.Button,{onClick:Et,disabled:!_e||v||P,className:"mt-3 w-full",children:"Speichern"}),te.jsx(De.Button,{color:"purple",onClick:$t,disabled:!a||a.source!=="custom"||v||P,className:"w-full",children:"Standard wiederherstellen"})]}),(a==null?void 0:a.customUpdatedAt)&&te.jsxs("p",{className:"mt-2 text-xs text-gray-500",children:["Zuletzt geändert: ",Ws(a.customUpdatedAt)]})]}),te.jsxs("div",{className:"rounded-md border border-gray-700/20 p-4",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("h3",{className:"text-sm font-semibold",children:"Update-Status"}),te.jsx("span",{className:`rounded-full px-3 py-0.5 text-xs font-semibold ${Uo}`,children:_o})]}),te.jsxs("div",{className:"mt-3 grid gap-2 text-xs",children:[te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Phase"}),te.jsx("span",{className:"font-medium",children:bn})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Ziel-Version"}),te.jsx("span",{className:"font-medium",children:Gr})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Installierte Version"}),te.jsx("span",{className:"font-medium",children:ho})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Gestartet"}),te.jsx("span",{children:Rn})]}),te.jsxs("div",{className:"flex items-center justify-between",children:[te.jsx("span",{children:"Beendet"}),te.jsx("span",{children:Oo})]}),vn&&te.jsx("div",{className:"rounded-md border border-green-700 bg-green-800 px-3 py-2 text-xs text-white",children:vn}),(r==null?void 0:r.error)&&te.jsx("div",{className:"rounded-md border border-red-500/60 bg-red-900/40 px-3 py-2 text-xs text-red-200",children:r.error}),M&&te.jsx("div",{className:"rounded-md border border-red-500/60 bg-red-900/40 px-3 py-2 text-xs text-red-200",children:M})]}),te.jsx("div",{className:"mt-3 h-40 overflow-y-auto rounded-md border border-gray-700/20 bg-gray-950/70 p-3 font-mono text-[11px] leading-relaxed",children:po.length===0?te.jsx("p",{className:"text-gray-500",children:"Noch keine Protokolle vorhanden."}):po.map((Je,mt)=>te.jsxs("div",{className:"mb-2 last:mb-0",children:[te.jsxs("span",{className:"text-gray-500",children:["[",NV(Je.timestamp),"]"]})," ",te.jsx("span",{className:(RV[Je.level]??"text-gray-300")+" whitespace-normal break-words",style:{overflowWrap:"anywhere",wordBreak:"normal"},children:Je.message})]},`${Je.timestamp}-${mt}`))}),te.jsx(De.Button,{onClick:Mn,disabled:zr||m,className:"mt-3 w-full",children:m?"Update wird gestartet…":"Portainer aktualisieren"})]})]})]})]}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{color:"transparent",floated:!1,shadow:!1,className:"m-0 p-4 block antialiased font-sans",children:te.jsx(De.Typography,{variant:"h5",color:"blue-gray",className:"block antialiased font-sans",children:"Wartungsmodus"})}),te.jsxs(De.CardBody,{className:"flex flex-col gap-4 p-4",children:[te.jsxs("div",{className:"flex items-start justify-between gap-4",children:[te.jsxs("div",{className:"space-y-1",children:[te.jsx("p",{className:"text-sm text-blue-gray-200",children:"Schaltet StackPulse für Benutzer in den Wartungsmodus."}),R?te.jsxs("p",{className:"text-xs text-gray-500",children:["Hinweis: ",R]}):null,te.jsx("p",{className:"text-xs text-gray-500",children:j?`Aktiv seit ${Gn??"-"}.`:`Zuletzt geändert: ${yr??"-"}.`}),P&&te.jsx("p",{className:"text-xs text-amber-600",children:"Portainer-Update läuft – Umschalten vorübergehend gesperrt."}),te.jsxs("p",{className:"text-xs text-gray-500",children:["Status: ",j?"Aktiv":"Inaktiv"]})]}),te.jsx(De.Switch,{checked:j,disabled:H||l||P,onChange:Je=>Dr(Je.target.checked),ripple:!1,color:"amber"})]}),H&&te.jsx("p",{className:"text-xs text-gray-500",children:"Wartungsmodus wird aktualisiert…"})]})]})]})}const qs=Xn.forwardRef(({value:e,onValueSelect:t,onClick:r,onKeyDown:a,...s},l)=>{const{setOpen:f}=De.useSelect(),b=Z.useCallback(()=>{(typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame:F=>setTimeout(F,0))(()=>{f(!0)})},[f]),C=Z.useCallback(()=>{typeof t=="function"&&t(e)},[t,e]),T=Z.useCallback(I=>{typeof r=="function"&&r(I),C(),b()},[r,C,b]),O=Z.useCallback(I=>{typeof a=="function"&&a(I),(I.key==="Enter"||I.key===" ")&&(C(),b())},[a,C,b]);return te.jsx(De.Option,{...s,value:e,ref:l,onClick:T,onKeyDown:O})});qs.displayName="StickyOption";const LV={success:"text-green-400",warning:"text-yellow-400",error:"text-red-400",started:"text-blue-300"},jV=e=>{if(!e)return"-";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString("de-DE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})},Ux=e=>{if(e)return e.replace("T"," ")},Gx="redeployLogFilters",on="__all__",Bu="- Alle -",$x="50",G_=[{value:"10",label:"10"},{value:"25",label:"25"},{value:"50",label:"50"},{value:"100",label:"100"},{value:"all",label:"Alle"}],qx=new Set(G_.map(e=>e.value)),Fp={Einzeln:"Einzeln",Alle:"Alle",Auswahl:"Auswahl",single:"Einzeln",all:"Alle",selection:"Auswahl"},DV=e=>!!(e.stacks&&e.stacks.length||e.statuses&&e.statuses.length||e.endpoints&&e.endpoints.length||e.redeployTypes&&e.redeployTypes.length||e.message&&e.message.trim()||e.from&&e.from.trim()||e.to&&e.to.trim());function zV(){const[e,t]=Z.useState([]),[r,a]=Z.useState(0),[s,l]=Z.useState(!0),[f,b]=Z.useState(""),[C,T]=Z.useState(!1),[O,I]=Z.useState([]),[F,z]=Z.useState([]),[j,R]=Z.useState([]),[P,y]=Z.useState([]),[p,v]=Z.useState([]),[g,m]=Z.useState([]),[_,M]=Z.useState([]),[X,H]=Z.useState([]),[W,U]=Z.useState(""),[K,ae]=Z.useState(""),[ne,pe]=Z.useState(""),[me,xe]=Z.useState(!1),[be,ce]=Z.useState(!1),[he,ye]=Z.useState(!1),[Pe,Me]=Z.useState(0),[Re,Le]=Z.useState($x),[_e,Ye]=Z.useState(1),Fe=Z.useCallback(()=>{},[]),Ne=Z.useCallback(Ee=>{const We=Array.isArray(Ee)?Ee:(Ee==null?void 0:Ee.items)??[],ct=new Map,Ct=new Set,_t=new Set,ht=new Set;We.forEach(Et=>{if(Et.stackId){const $t=String(Et.stackId),Jt=Et.stackName||`Stack ${$t}`;ct.set($t,Jt)}Et.status&&Ct.add(Et.status),Et.endpoint!==null&&Et.endpoint!==void 0&&Et.endpoint!==""&&_t.add(String(Et.endpoint)),Et.redeployType&&ht.add(Et.redeployType)}),I(Array.from(ct.entries()).map(([Et,$t])=>({value:Et,label:$t})).sort((Et,$t)=>Et.label.localeCompare($t.label))),z(Array.from(Ct).sort()),R(Array.from(_t).sort((Et,$t)=>Et.localeCompare($t,void 0,{numeric:!0}))),y(Array.from(ht).sort()),ye(!0)},[]),Xe=Z.useMemo(()=>{const Ee=new Map;return O.forEach(We=>{Ee.set(We.value,We.label)}),Ee},[O]);Z.useEffect(()=>{he&&v(Ee=>{const We=Ee.filter(ct=>O.some(Ct=>Ct.value===ct));return We.length===Ee.length?Ee:We})},[he,O]),Z.useEffect(()=>{he&&m(Ee=>{const We=Ee.filter(ct=>F.includes(ct));return We.length===Ee.length?Ee:We})},[he,F]),Z.useEffect(()=>{he&&M(Ee=>{const We=Ee.filter(ct=>j.includes(ct));return We.length===Ee.length?Ee:We})},[he,j]),Z.useEffect(()=>{he&&H(Ee=>{const We=Ee.filter(ct=>P.includes(ct));return We.length===Ee.length?Ee:We})},[he,P]),Z.useEffect(()=>{if(typeof window>"u"){ce(!0);return}try{const Ee=window.localStorage.getItem(Gx);if(Ee){const We=JSON.parse(Ee),ct=(We==null?void 0:We.filters)??We??{},Ct=(We==null?void 0:We.pagination)??{};v(ct.stacks||[]),m(ct.statuses||[]),M(ct.endpoints||[]),H(ct.redeployTypes||[]),U(ct.message||""),ae(ct.from||""),pe(ct.to||""),xe(DV(ct));const _t=Ct.perPage;if(_t!==void 0){const Et=String(_t);qx.has(Et)&&Le(Et)}const ht=Ct.page;typeof ht=="number"&&ht>0&&Ye(ht)}}catch(Ee){console.error("❌ Fehler beim Laden der gespeicherten Log-Filter:",Ee)}finally{ce(!0)}},[]);const Ve=Z.useCallback(()=>{const Ee={};p.length&&(Ee.stackIds=p.join(",")),g.length&&(Ee.statuses=g.join(",")),_.length&&(Ee.endpoints=_.join(",")),X.length&&(Ee.redeployTypes=X.join(",")),W.trim()&&(Ee.message=W.trim());const We=Ux(K);We&&(Ee.from=We);const ct=Ux(ne);return ct&&(Ee.to=ct),Ee},[p,g,_,X,W,K,ne]);Z.useEffect(()=>{if(!be)return;let Ee=!1;return Nr.get("/api/logs",{params:{perPage:"all",page:1}}).then(We=>{Ee||Ne(We.data)}).catch(We=>{Ee||console.error("⚠️ Konnte Filteroptionen nicht aktualisieren:",We)}),()=>{Ee=!0}},[be,Ne,Pe]);const Ke=Z.useMemo(()=>({stacks:p,statuses:g,endpoints:_,redeployTypes:X,message:W,from:K,to:ne}),[p,g,_,X,W,K,ne]);Z.useEffect(()=>{if(!be)return;const Ee={...Ve()};Re==="all"?(Ee.perPage="all",Ee.page=1):(Ee.perPage=Re,Ee.page=_e);let We=!1;return l(!0),b(""),Nr.get("/api/logs",{params:Ee}).then(ct=>{if(We)return;const Ct=ct.data||{},_t=Array.isArray(Ct)?Ct:Ct.items??[],ht=Array.isArray(Ct)?_t.length:Ct.total??_t.length;if(t(_t),a(ht),Re==="all")_e!==1&&Ye(1);else{const Et=Math.max(1,Math.ceil((ht||0)/Number(Re))),$t=Math.min(Math.max(_e,1),Et);$t!==_e&&Ye($t)}}).catch(ct=>{We||(console.error("❌ Fehler beim Laden der Logs:",ct),b("Fehler beim Laden der Redeploy-Logs"))}).finally(()=>{We||l(!1)}),()=>{We=!0}},[be,Ve,Ne,Pe,Re,_e]),Z.useEffect(()=>{if(be&&!(typeof window>"u"))try{window.localStorage.setItem(Gx,JSON.stringify({filters:Ke,pagination:{perPage:Re,page:_e}}))}catch(Ee){console.error("⚠️ Konnte Filter nicht speichern:",Ee)}},[be,Ke,Re,_e]);const tt=Ee=>We=>{var _t;if(typeof We=="string"){const ht=We;if(ht==="")return;Ee(Et=>ht===on?[]:Et.includes(ht)?Et.filter($t=>$t!==ht):[...Et,ht]),Ye(1);return}const ct=(_t=We==null?void 0:We.target)==null?void 0:_t.selectedOptions;if(!ct)return;const Ct=Array.from(ct).map(ht=>ht.value);Ct.includes(on)?Ee([]):Ee(Ct),Ye(1)},Ze=(Ee,We)=>{Ee(ct=>ct.filter(Ct=>Ct!==We)),Ye(1)},qe=()=>{v([]),m([]),M([]),H([]),U(""),ae(""),pe(""),xe(!1),Ye(1)},it=()=>{xe(Ee=>!Ee)},xt=Ee=>{const We=Ee.target.value;qx.has(We)&&(Le(We),Ye(1))},At=Ee=>{if(Re==="all"||Ee<1)return;const We=Math.max(1,Math.ceil((r||0)/Number(Re)));Ee>We||Ye(Ee)},Vt=Z.useMemo(()=>{const Ee=O.filter(We=>We.value!==on);return[{value:on,label:Bu},...Ee]},[O]),Mt=Z.useMemo(()=>{const Ee=F.filter(We=>We!==on).map(We=>({value:We,label:We}));return[{value:on,label:Bu},...Ee]},[F]),ft=Z.useMemo(()=>{const Ee=j.filter(We=>We!==on).map(We=>({value:We,label:We}));return[{value:on,label:Bu},...Ee]},[j]),Qt=Z.useMemo(()=>{const Ee=P.filter(We=>We!==on).map(We=>({value:We,label:Fp[We]??We}));return[{value:on,label:Bu},...Ee]},[P]),Bt=Z.useMemo(()=>{let Ee=0;return p.length&&(Ee+=p.length),g.length&&(Ee+=g.length),_.length&&(Ee+=_.length),X.length&&(Ee+=X.length),W.trim()&&(Ee+=1),K&&(Ee+=1),ne&&(Ee+=1),Ee},[p,g,_,W,K,ne]),Rt=Z.useMemo(()=>{if(Re==="all")return 1;const Ee=Number(Re)||Number($x);return Math.max(1,Math.ceil((r||0)/Ee))},[Re,r]),Tt=Z.useMemo(()=>r===0?0:Re==="all"?1:(_e-1)*Number(Re)+1,[r,Re,_e]),Ut=Z.useMemo(()=>r===0?0:Re==="all"?r:Math.min(r,(_e-1)*Number(Re)+e.length),[r,Re,_e,e.length]),br=async Ee=>{if(window.confirm("Diesen Log-Eintrag dauerhaft löschen?")){T(!0),b("");try{await Nr.delete(`/api/logs/${Ee}`),Me(We=>We+1)}catch(We){console.error("❌ Fehler beim Löschen des Logs:",We),b("Fehler beim Löschen des Redeploy-Logs")}finally{T(!1)}}},Gt=async()=>{if(e.length&&window.confirm("Alle angezeigten Logs (entsprechend Filter) löschen?")){T(!0),b("");try{const Ee={...Ve(),ids:e.map(We=>We.id).join(",")};await Nr.delete("/api/logs",{params:Ee}),Me(We=>We+1)}catch(Ee){console.error("❌ Fehler beim Löschen der gefilterten Logs:",Ee),b("Fehler beim Löschen der gefilterten Logs")}finally{T(!1)}}},Ur=async Ee=>{T(!0),b("");try{const We=await Nr.get("/api/logs/export",{params:{...Ve(),format:Ee},responseType:"blob"}),ct=We.headers["content-type"]||(Ee==="sql"?"application/sql":"text/plain"),_t=(We.headers["content-disposition"]||"").match(/filename="?([^";]+)"?/i),ht=(_t==null?void 0:_t[1])||`redeploy-logs.${Ee}`,Et=new Blob([We.data],{type:ct}),$t=window.URL.createObjectURL(Et),Jt=document.createElement("a");Jt.href=$t,Jt.download=ht,document.body.appendChild(Jt),Jt.click(),Jt.remove(),window.URL.revokeObjectURL($t)}catch(We){console.error("❌ Fehler beim Export der Logs:",We),b("Fehler beim Export der Redeploy-Logs")}finally{T(!1)}};return Xn.useState(!1),te.jsxs("div",{className:"mt-12 mb-8 flex flex-col gap-12",children:[te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"p-6 pt-2 pb-2",children:te.jsx(De.Typography,{variant:"h6",color:"white",children:te.jsxs("button",{onClick:it,className:"flex w-full items-center justify-between",children:[te.jsxs("span",{className:"flex items-center gap-2",children:[te.jsx("span",{children:"Filter und Optionen"}),Bt>0&&te.jsxs("span",{className:"rounded-full bg-blue-gray-500/80 px-2 py-0.5 text-xs text-white",children:[Bt," aktiv"]})]}),te.jsx("span",{className:"text-xs uppercase tracking-wide text-gray-400",children:me?"Ausblenden":"Anzeigen"})]})})}),te.jsx(De.CardBody,{children:me&&te.jsxs("div",{children:[te.jsxs("div",{className:"flex flex-wrap gap-2",children:[te.jsx(De.Button,{onClick:()=>Ur("txt"),disabled:C||s,className:"w-full md:flex-1",children:"Export TXT"}),te.jsx(De.Button,{onClick:()=>Ur("sql"),disabled:C||s,className:"w-full md:flex-1",children:"Export SQL"}),te.jsx(De.Button,{color:"sunsetCoral",onClick:Gt,disabled:C||s||e.length===0,className:"w-full md:flex-1",children:"Angezeigte löschen"})]}),te.jsxs("div",{className:"flex flex-wrap gap-2 mt-10",children:[te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Stacks",children:Vt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(v),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:p.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300 ",children:"Alle Stacks"}):te.jsx("span",{children:p.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(v,Ee),className:"rounded-full bg-purple-500/80 px-2 py-0.5 text-white transition hover:bg-purple-500/90 focus:outline-none focus:ring-2 focus:ring-purple-300 cursor-pointer",title:"Filter entfernen",children:Xe.get(Ee)??`Stack ${Ee}`},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Status",children:Mt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(m),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:g.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Status"}):te.jsx("span",{children:g.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(m,Ee),className:"rounded-full bg-brown-500/80 px-2 py-0.5 text-white transition hover:bg-brown-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:Ee},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Redeploy-Typ",children:Qt.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(H),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:X.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Typen"}):te.jsx("span",{children:X.map(Ee=>te.jsx("button",{type:"button",onClick:()=>Ze(H,Ee),className:"rounded-full bg-brown-500/80 px-2 py-0.5 text-white transition hover:bg-brown-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:Fp[Ee]??Ee},Ee))})})]}),te.jsxs("div",{className:"grid gap-4 flex-1",children:[te.jsx(De.Select,{multiple:!0,onChange:Fe,className:"text-gray-500",variant:"static",dismiss:{itemPress:!1},label:"Endpoints",children:ft.map(({value:Ee,label:We})=>te.jsx(qs,{value:Ee,onValueSelect:tt(M),className:`text-black-600 ${Ee===on?"font-semibold text-black-800":""}`,children:We},Ee))}),te.jsx("div",{className:"mt-2 mb-2 min-h-[1.5rem] text-xs text-gray-400",children:_.length===0?te.jsx("span",{className:"rounded-full bg-gray-700/60 px-2 py-0.5 text-gray-300",children:"Alle Endpoints"}):te.jsx("span",{children:_.map(Ee=>te.jsxs("button",{type:"button",onClick:()=>Ze(M,Ee),className:"rounded-full bg-teal-500/80 px-2 py-0.5 text-white transition hover:bg-teal-500/90 focus:outline-none focus:ring-2 focus:ring-brown-300 cursor-pointer",title:"Filter entfernen",children:["Endpoint ",Ee]},Ee))})})]})]}),te.jsx("div",{className:"flex flex-wrap gap-2 mt-5",children:te.jsx("div",{className:"grid gap-4 flex-1",children:te.jsx(De.Input,{value:W,onChange:Ee=>{U(Ee.target.value),Ye(1)},variant:"static",label:"Nachricht (Freitext)",placeholder:"Suche"})})}),te.jsxs("div",{className:"flex flex-col md:flex-row flex-wrap gap-4 mt-8",children:[te.jsx("div",{className:"flex-1",children:te.jsx(De.Input,{type:"datetime-local",variant:"static",label:"Von",value:K,onChange:Ee=>{ae(Ee.target.value),Ye(1)},className:"w-full"})}),te.jsx("div",{className:"flex-1",children:te.jsx(De.Input,{type:"datetime-local",variant:"static",label:"Bis",value:ne,onChange:Ee=>{pe(Ee.target.value),Ye(1)},className:"w-full"})}),te.jsx("div",{className:"flex-1",children:te.jsx(De.Button,{onClick:qe,disabled:C||s,className:"w-full",children:"Zurücksetzen"})})]})]})})]}),te.jsxs(De.Card,{children:[te.jsx(De.CardHeader,{variant:"gradient",color:"gray",className:"mb-8 p-6",children:te.jsxs(De.Typography,{variant:"h6",color:"white",className:"flex items-center justify-between",children:[te.jsx("span",{children:"Logs"}),te.jsxs("div",{className:"flex items-center gap-2",children:[te.jsx("span",{className:"text-xs uppercase tracking-wide text-gray-400",children:"Einträge pro Seite:"}),te.jsx("select",{value:Re,onChange:xt,className:"rounded-md border border-gray-700 bg-gray-900 px-2 py-1 text-sm text-gray-100 focus:border-purple-500 focus:outline-none focus:ring-1 focus:ring-purple-500",children:G_.map(({value:Ee,label:We})=>te.jsx("option",{value:Ee,children:We},Ee))})]})]})}),te.jsx(De.CardBody,{className:"overflow-x-scroll px-0 pt-0 pb-2",children:te.jsxs("table",{className:"w-full min-w-[640px] table-auto",children:[te.jsx("thead",{children:te.jsx("tr",{children:["Zeitpunkt","Stack","Art","Status","Nachricht","Endpoint","Aktionen"].map(Ee=>te.jsx("th",{className:"border-b border-blue-gray-50 py-3 px-5 text-left",children:te.jsx(De.Typography,{variant:"small",className:"text-[11px] font-bold uppercase text-blue-gray-400",children:Ee})},Ee))})}),te.jsx("tbody",{children:e.map(Ee=>{const We=LV[Ee.status]||"text-blue-300",ct="py-3 px-5",Ct=Ee.stackName||"Unbekannt",_t=Ct!=="---"&&Ee.stackId!==void 0&&Ee.stackId!==null,ht=Ee.redeployType?Fp[Ee.redeployType]??Ee.redeployType:"---";return te.jsxs("tr",{children:[te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",className:"mb-1 block text-xs font-medium text-blue-gray-600",children:jV(Ee.timestamp)})}),te.jsx("td",{className:ct,children:te.jsxs("div",{className:"flex flex-col",children:[te.jsx("span",{className:"font-medium",children:Ct}),te.jsx(De.Typography,{variant:"small",children:_t&&te.jsxs("span",{className:"text-xs text-gray-400",children:["ID: ",Ee.stackId]})})]})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:ht})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",className:`font-semibold ${We}`,children:Ee.status})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:Ee.message||"-"})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:Ee.endpoint??"-"})}),te.jsx("td",{className:ct,children:te.jsx(De.Typography,{variant:"small",children:te.jsx("button",{onClick:()=>br(Ee.id),disabled:C,className:"rounded-md border border-red-600 px-3 py-1 text-xs text-red-300 transition hover:bg-red-600/20 disabled:opacity-60",children:"Löschen"})})})]},Ee.id)})})]})})]}),te.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[te.jsx("span",{children:r===0?"Keine Einträge":Re==="all"?`Zeige alle ${r} Einträge`:`Zeige ${Tt.toLocaleString()} – ${Ut.toLocaleString()} von ${r.toLocaleString()} Einträgen`}),Re!=="all"&&te.jsxs("div",{className:"flex items-center gap-2",children:[te.jsx("button",{onClick:()=>At(_e-1),disabled:_e<=1||C,className:"rounded-md border border-slate-300 p-2.5 text-center text-sm transition-all shadow-sm hover:shadow-lg text-slate-600 hover:text-white hover:bg-slate-800 hover:border-slate-800 focus:text-white focus:bg-slate-800 focus:border-slate-800 active:border-slate-800 active:text-white active:bg-slate-800 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none",children:te.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",className:"w-4 h-4",children:te.jsx("path",{d:"M11.03 3.97a.75.75 0 0 1 0 1.06l-6.22 6.22H21a.75.75 0 0 1 0 1.5H4.81l6.22 6.22a.75.75 0 1 1-1.06 1.06l-7.5-7.5a.75.75 0 0 1 0-1.06l7.5-7.5a.75.75 0 0 1 1.06 0Z"})})}),te.jsxs("p",{className:"text-slate-600",children:["Seite ",te.jsx("strong",{className:"text-slate-800",children:_e})," / ",te.jsx("strong",{className:"text-slate-800",children:Rt})]}),te.jsx("button",{onClick:()=>At(_e+1),disabled:_e>=Rt||C,className:"rounded-md border border-slate-300 p-2.5 text-center text-sm transition-all shadow-sm hover:shadow-lg text-slate-600 hover:text-white hover:bg-slate-800 hover:border-slate-800 focus:text-white focus:bg-slate-800 focus:border-slate-800 active:border-slate-800 active:text-white active:bg-slate-800 disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none",type:"button",children:te.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",className:"w-4 h-4",children:te.jsx("path",{d:"M12.97 3.97a.75.75 0 0 1 1.06 0l7.5 7.5a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 1 1-1.06-1.06l6.22-6.22H3a.75.75 0 0 1 0-1.5h16.19l-6.22-6.22a.75.75 0 0 1 0-1.06Z"})})})]})]})]})}const Vp={className:"w-5 h-5 text-inherit"},gg=[{layout:"dashboard",pages:[{icon:te.jsx($N,{...Vp}),name:"stacks",path:"/stacks",element:te.jsx(UF,{})},{icon:te.jsx(aI,{...Vp}),name:"maintenance",path:"/maintenance",element:te.jsx(IV,{})},{icon:te.jsx(jN,{...Vp}),name:"logs",path:"/logs",element:te.jsx(zV,{})}]}];function $_(){const[e,t]=Jd(),{sidenavType:r}=e;return te.jsxs("div",{className:"min-h-screen bg-blue-gray-50/50",children:[te.jsx(ef,{routes:gg,brandImg:r==="dark"?"/img/logo-ct.png":"/img/logo-ct-dark.png"}),te.jsxs("div",{className:"p-4 xl:ml-80",children:[te.jsx(h_,{}),te.jsx(g_,{}),te.jsx(De.IconButton,{size:"lg",color:"white",className:"fixed bottom-8 right-8 z-40 rounded-full shadow-blue-gray-900/10",ripple:!1,onClick:()=>yb(t,!0),children:te.jsx(CC,{className:"h-5 w-5"})}),te.jsx(h0,{children:gg.map(({layout:a,pages:s})=>a==="dashboard"&&s.map(({path:l,element:f})=>te.jsx(ji,{exact:!0,path:l,element:f})))}),te.jsx("div",{className:"text-blue-gray-600",children:te.jsx(b_,{})})]})]})}$_.displayName="/src/layout/dashboard.jsx";function q_(){return te.jsx("div",{className:"relative min-h-screen w-full",children:te.jsx(h0,{children:gg.map(({layout:e,pages:t})=>e==="auth"&&t.map(({path:r,element:a})=>te.jsx(ji,{exact:!0,path:r,element:a})))})})}q_.displayName="/src/layout/Auth.jsx";function FV(){return te.jsxs(h0,{children:[te.jsx(ji,{path:"/dashboard/*",element:te.jsx($_,{})}),te.jsx(ji,{path:"/auth/*",element:te.jsx(q_,{})}),te.jsx(ji,{path:"*",element:te.jsx(ZR,{to:"/dashboard/home",replace:!0})})]})}Bp.createRoot(document.getElementById("root")).render(te.jsx(Xn.StrictMode,{children:te.jsx(aN,{children:te.jsx(OV,{children:te.jsx(TV,{children:te.jsx(De.ThemeProvider,{children:te.jsx(mb,{children:te.jsx(FV,{})})})})})})})); diff --git a/backend/public/index.html b/backend/public/index.html index 905629b..22e5d4b 100644 --- a/backend/public/index.html +++ b/backend/public/index.html @@ -32,7 +32,7 @@ - +
diff --git a/frontend/src/pages/dashboard/logs.jsx b/frontend/src/pages/dashboard/logs.jsx index e57d47f..0dcf8e1 100644 --- a/frontend/src/pages/dashboard/logs.jsx +++ b/frontend/src/pages/dashboard/logs.jsx @@ -668,10 +668,9 @@ export function Logs() { className="w-full md:flex-1"> Export SQL @@ -1015,7 +1014,7 @@ export function Logs() { diff --git a/frontend/src/pages/dashboard/maintenance.jsx b/frontend/src/pages/dashboard/maintenance.jsx index c5afd16..45377c3 100644 --- a/frontend/src/pages/dashboard/maintenance.jsx +++ b/frontend/src/pages/dashboard/maintenance.jsx @@ -856,7 +856,7 @@ export function Maintenance() { @@ -864,8 +864,7 @@ export function Maintenance() { @@ -900,7 +899,7 @@ export function Maintenance() { color="purple" onClick={handleScriptReset} disabled={!scriptConfig || scriptConfig.source !== "custom" || scriptSaving || updateRunning} - className="w-full"> + className="w-full hover:bg-sunsetCoral-600 bg-sunsetCoral-500"> Standard wiederherstellen diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs index 9eaae0e..2b92378 100644 --- a/frontend/tailwind.config.cjs +++ b/frontend/tailwind.config.cjs @@ -10,127 +10,27 @@ module.exports = withMT({ green: colors.green, slate: colors.slate, orange: colors.orange, // falls du z. B. text-orange-300 brauchst - // Zusätzliche Farben - arcticBlue: { - 50: '#f2f9fd', - 100: '#e6f3fb', - 200: '#cce6f7', - 300: '#99ceef', - 400: '#66b6e7', - 500: '#339ede', - 600: '#1f86c3', - 700: '#16699b', - 800: '#0f4b6f', - 900: '#082d43', - }, - roseQuartz: { - 50: '#fdf7f9', - 100: '#faeff3', - 200: '#f5dfe6', - 300: '#ecbfd0', - 400: '#e08dad', - 500: '#d45b89', - 600: '#b94771', - 700: '#8e3556', - 800: '#63233b', - 900: '#391324', - }, - citrusPunch: { - 50: '#fffdf6', - 100: '#fffbe9', - 200: '#fff5cc', - 300: '#ffeb99', - 400: '#ffe066', - 500: '#ffd633', - 600: '#e6bd00', - 700: '#b39300', - 800: '#806900', - 900: '#4d3f00', - }, - midnightPlum: { - 50: '#faf7fb', - 100: '#f4ecf6', - 200: '#e4cfee', - 300: '#cba0de', - 400: '#a869cc', - 500: '#8431b9', - 600: '#6d299b', - 700: '#521f74', - 800: '#38154d', - 900: '#1f0b28', - }, - sandstone: { - 50: '#fbf9f7', - 100: '#f6f2ee', - 200: '#ece3da', - 300: '#d8c6b3', - 400: '#c0a27f', - 500: '#a87e4b', - 600: '#906a3e', - 700: '#6b4f2f', - 800: '#47341f', - 900: '#241a10', - }, - emeraldMist: { - 50: '#f3faf7', - 100: '#e7f6ef', - 200: '#ccecdc', - 300: '#9ddabf', - 400: '#6ec8a3', - 500: '#3fb586', - 600: '#359771', - 700: '#2a765a', - 800: '#1f5442', - 900: '#13332a', - }, - velvetRed: { - 50: '#fdf7f7', - 100: '#faeeee', - 200: '#f4d6d6', - 300: '#e7a8a8', - 400: '#d56666', - 500: '#c32424', - 600: '#a61e1e', - 700: '#801717', - 800: '#590f0f', - 900: '#330808', - }, - stormGrey: { - 50: '#f7f8fa', - 100: '#eef0f3', - 200: '#d9dce2', - 300: '#b6bbc8', - 400: '#8b91a4', - 500: '#606780', - 600: '#4f556b', - 700: '#3e4456', - 800: '#2c313f', - 900: '#1b1e29', - }, - neonLime: { - 50: '#f7ffe6', - 100: '#eeffc9', - 200: '#dbff96', - 300: '#c2ff52', - 400: '#a8ff0e', - 500: '#8de600', - 600: '#74bf00', - 700: '#5b9900', - 800: '#426f00', - 900: '#294600', - }, - skyMauve: { - 50: '#faf8fc', - 100: '#f4f0f9', - 200: '#e5dbf2', - 300: '#c9b2e6', - 400: '#a27dd4', - 500: '#7b48c2', - 600: '#633aa0', - 700: '#4b2b7c', - 800: '#341d58', - 900: '#1e1035', - } + auroraTeal: {50:'#f0fafb',100:'#e0f5f7',200:'#c3ecef',300:'#9de0e4',400:'#6ad3d8',500:'#38c6cc',600:'#2aa9b0',700:'#1f8d94',800:'#166e76',900:'#0c4f58'}, + sunsetCoral: {50:'#fff6f5',100:'#ffece9',200:'#ffd7d3',300:'#ffb8b5',400:'#ff9189',500:'#ff6a5d',600:'#e65048',700:'#b93d38',800:'#8a2c28',900:'#5c1c1a'}, + lavenderSmoke: {50:'#faf8fc',100:'#f5f1f9',200:'#ece2f3',300:'#dac4e6',400:'#b88acf',500:'#9670b8',600:'#7a5894',700:'#5d4373',800:'#412f52',900:'#291e38'}, + mossGreen: {50:'#f5faf2',100:'#ebf5e5',200:'#d9ebca',300:'#b8d99e',400:'#8cc56f',500:'#60b240',600:'#4d8f33',700:'#3b6b27',800:'#2a491d',900:'#1c3012'}, + deepOceanBlue: {50:'#f4faff',100:'#e9f5ff',200:'#cfe6ff',300:'#add1ff',400:'#7ab9ff',500:'#479fff',600:'#3c86e6',700:'#305eaf',800:'#23437f',900:'#162a50'}, + warmAmberGlow: {50:'#fff9f2',100:'#fff3e5',200:'#ffe6cc',300:'#ffcc99',400:'#ffad4d',500:'#ff8f00',600:'#e67600',700:'#b35a00',800:'#804000',900:'#4d2600'}, + peachMist: {50:'#fff8f7',100:'#fff0ed',200:'#ffe1db',300:'#ffc2b7',400:'#ff9a87',500:'#ff7257',600:'#e65f4b',700:'#b34938',800:'#803622',900:'#4d230f'}, + slatePurple: {50:'#f7f5fa',100:'#efe9f5',200:'#ded1ea',300:'#bdb3d5',400:'#9584b5',500:'#6d5795',600:'#5c4a7c',700:'#473861',800:'#322648',900:'#1f1530'}, + mintTea: {50:'#f2fcfa',100:'#e5f9f6',200:'#ccefee',300:'#99dfdc',400:'#66cfc9',500:'#33bfb6',600:'#2aa395',700:'#228174',800:'#195953',900:'#103330'}, + copperRust: {50:'#faf7f6',100:'#f5efee',200:'#ebe0dc',300:'#d6c1b8',400:'#b28a86',500:'#8d4d55',600:'#7a444b',700:'#5f3338',800:'#442426',900:'#2d1718'}, + // Neue 10 + arcticBlue: {50:'#f2f9fd',100:'#e6f3fb',200:'#cce6f7',300:'#99ceef',400:'#66b6e7',500:'#339ede',600:'#1f86c3',700:'#16699b',800:'#0f4b6f',900:'#082d43'}, + roseQuartz: {50:'#fdf7f9',100:'#faeff3',200:'#f5dfe6',300:'#ecbfd0',400:'#e08dad',500:'#d45b89',600:'#b94771',700:'#8e3556',800:'#63233b',900:'#391324'}, + citrusPunch: {50:'#fffdf6',100:'#fffbe9',200:'#fff5cc',300:'#ffeb99',400:'#ffe066',500:'#ffd633',600:'#e6bd00',700:'#b39300',800:'#806900',900:'#4d3f00'}, + midnightPlum: {50:'#faf7fb',100:'#f4ecf6',200:'#e4cfee',300:'#cba0de',400:'#a869cc',500:'#8431b9',600:'#6d299b',700:'#521f74',800:'#38154d',900:'#1f0b28'}, + sandstone: {50:'#fbf9f7',100:'#f6f2ee',200:'#ece3da',300:'#d8c6b3',400:'#c0a27f',500:'#a87e4b',600:'#906a3e',700:'#6b4f2f',800:'#47341f',900:'#241a10'}, + emeraldMist: {50:'#f3faf7',100:'#e7f6ef',200:'#ccecdc',300:'#9ddabf',400:'#6ec8a3',500:'#3fb586',600:'#359771',700:'#2a765a',800:'#1f5442',900:'#13332a'}, + velvetRed: {50:'#fdf7f7',100:'#faeeee',200:'#f4d6d6',300:'#e7a8a8',400:'#d56666',500:'#c32424',600:'#a61e1e',700:'#801717',800:'#590f0f',900:'#330808'}, + stormGrey: {50:'#f7f8fa',100:'#eef0f3',200:'#d9dce2',300:'#b6bbc8',400:'#8b91a4',500:'#606780',600:'#4f556b',700:'#3e4456',800:'#2c313f',900:'#1b1e29'}, + neonLime: {50:'#f7ffe6',100:'#eeffc9',200:'#dbff96',300:'#c2ff52',400:'#a8ff0e',500:'#8de600',600:'#74bf00',700:'#5b9900',800:'#426f00',900:'#294600'}, + skyMauve: {50:'#faf8fc',100:'#f4f0f9',200:'#e5dbf2',300:'#c9b2e6',400:'#a27dd4',500:'#7b48c2',600:'#633aa0',700:'#4b2b7c',800:'#341d58',900:'#1e1035'}, }, }, },