User-Befund, und er trifft einen echten Modellierungsfehler von gestern: "Eine durchgedachte Idee wird ja sowieso mit meinem Ja zu einem IDE-Repo." Stimmt — /ideen/weiterfuehren macht aus der durchdachten Idee GENAU die IDE-Projekt-Karte, die der Repo-Weg direkt anlegt. Es sind zwei Stufen EINES Weges, keine zwei Achsen. Der Haken von gestern war deshalb falsch: "Die Box, allein" + "nur denken" war anklickbar, submit() setzte dann aber still welt:"ide" und schob einen in die Zed-Welt, ohne das zu sagen. Genau die versteckte Umschaltung, die anderswo in diesem Repo als Fassade gilt. Jetzt GENAU EINE Auswahl aus drei, in zwei Bereichen: Du baust selbst, in Zed [Erst durchdenken] [Direkt ein Repo] Oder die Box macht es [Die Box baut allein] Die falsche Kombination ist damit strukturell unmoeglich, nicht nur unwahrscheinlich. Nebengewinn: beim Durchdenken entfallen Tiefe und Ziel am Eingang. Die Weiter-Leiste fragt beides ohnehin beim "gefaellt mir" — und dann weiss man, was das Ding ueberhaupt wird. Vorher entschied man LXC-oder-Docker, bevor ein Konzept existierte. Ausgewaehlt ist immer eine KARTE, nie ein Bereich — der Bereich gruppiert nur, was denselben Weg geht. Voreinstellung ist "Erst durchdenken": die Wahl, die am wenigsten anlegt. Der Einordner ueberschreibt sie ohnehin in ~500 ms. API unveraendert; alle drei Abbildungen gegen den alten Vertrag geprueft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as A,Y as P,l as B,b as M,u as D,r as z,j as e,Z as T,e as a,$ as g,a0 as b,a1 as W,x as f,a2 as j,W as G,X as I,C as N,g as y,q as i}from"./index-DI19YZ2i.js";/**
|
import{c as A,Y as P,l as B,b as M,u as D,r as z,j as e,Z as T,e as a,$ as g,a0 as b,a1 as W,x as f,a2 as j,W as G,X as I,C as N,g as y,q as i}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as W,ab as H,ac as T,u as F,b as G,r as b,j as e,a3 as O,e as y,L as p,C as z,a9 as P,K as q,U as I,V,ad as K,X as E,T as C,D as M,M as R,g as $,ae as _,q as U}from"./index-DI19YZ2i.js";import{S,H as Q}from"./SectionLabel-DJ0JNfWI.js";/**
|
import{c as W,ab as H,ac as T,u as F,b as G,r as b,j as e,a3 as O,e as y,L as p,C as z,a9 as P,K as q,U as I,V,ad as K,X as E,T as C,D as M,M as R,g as $,ae as _,q as U}from"./index-BITRSHQi.js";import{S,H as Q}from"./SectionLabel-CxnAJzn3.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as m,ai as S,r as c,j as e,aj as z,L as g,U as M,ak as C,ae as D,al as A,am as B,an as Z,e as E,ao as L,u as R,b as q,g as k,q as T}from"./index-DI19YZ2i.js";import{R as j}from"./rotate-ccw-CBUivZG3.js";/**
|
import{c as m,ai as S,r as c,j as e,aj as z,L as g,U as M,ak as C,ae as D,al as A,am as B,an as Z,e as E,ao as L,u as R,b as q,g as k,q as T}from"./index-BITRSHQi.js";import{R as j}from"./rotate-ccw-Bqk2RuMY.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as v,r as c,I,J as A,j as e,K as h,x as B,B as H,D as E,M as z,e as M,L as T,N as F,C as K}from"./index-DI19YZ2i.js";import{F as O}from"./folder-open-DKNPWUub.js";import{C as R}from"./circle-x-5Vi9Kek6.js";import{C as W}from"./copy-CsXXFqkj.js";/**
|
import{c as v,r as c,I,J as A,j as e,K as h,x as B,B as H,D as E,M as z,e as M,L as T,N as F,C as K}from"./index-BITRSHQi.js";import{F as O}from"./folder-open-Cf0PzlLv.js";import{C as R}from"./circle-x-BCNcRD6W.js";import{C as W}from"./copy-CxQj3NkO.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as h,ap as b,r as i,j as e,L as g,aq as f,a2 as j,U as k,e as o,D as N,M as v,N as w,g as y}from"./index-DI19YZ2i.js";import{B as S}from"./book-open-CqxVgaj6.js";import{C as z}from"./circle-x-5Vi9Kek6.js";/**
|
import{c as h,ap as b,r as i,j as e,L as g,aq as f,a2 as j,U as k,e as o,D as N,M as v,N as w,g as y}from"./index-BITRSHQi.js";import{B as S}from"./book-open-DbieW73t.js";import{C as z}from"./circle-x-BCNcRD6W.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as p,j as e,r as M,x as C,a6 as z,a7 as k,a8 as y,a0 as v,a9 as L,W as G,aa as T,a2 as D,e as f,U as B}from"./index-DI19YZ2i.js";import{B as w}from"./book-open-CqxVgaj6.js";import{a as N,L as P,C as E,Z as R}from"./zap-CVKHAOl9.js";import{L as I}from"./layers-DQdxWFgI.js";/**
|
import{c as p,j as e,r as M,x as C,a6 as z,a7 as k,a8 as y,a0 as v,a9 as L,W as G,aa as T,a2 as D,e as f,U as B}from"./index-BITRSHQi.js";import{B as w}from"./book-open-DbieW73t.js";import{a as N,L as P,C as E,Z as R}from"./zap-Bie21ltg.js";import{L as I}from"./layers-C0bwoJh5.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+30
File diff suppressed because one or more lines are too long
-30
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
import{Y as b,u as f,$ as h,r as d,j as e,e as c,Z as g,T as p,a3 as j,a4 as N,g as v,a5 as w,q as x}from"./index-DI19YZ2i.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView};
|
import{Y as b,u as f,$ as h,r as d,j as e,e as c,Z as g,T as p,a3 as j,a4 as N,g as v,a5 as w,q as x}from"./index-BITRSHQi.js";function y(){const{data:s}=b(),m=f(),r=s!=null&&s.box_console_url?h(s.box_console_url):void 0,a=s==null?void 0:s.box_console_reachable,[l,o]=d.useState(!1),[i,n]=d.useState("");async function u(){o(!0),n("");try{const t=await v("/api/maintenance/restart",{method:"POST",body:JSON.stringify({service:"box-console"})});n(t.ok?"Neu gestartet — einen Moment, dann lädt das Terminal.":`Fehlgeschlagen: ${t.err||"Unbekannter Fehler"}`),w(m,x.agentStatus,x.services)}catch(t){n(`Fehlgeschlagen: ${(t==null?void 0:t.message)||t}`)}finally{o(!1)}}return e.jsxs("div",{className:"flex h-full flex-col gap-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Konsole"}),e.jsx("p",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:"Direkte Shell auf der Box — wie ein SSH-Fenster, mitten im Browser."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground",children:[e.jsx("span",{className:c("h-2 w-2 rounded-full",a?"bg-emerald-500 animate-pulse":"bg-amber-500")}),a?"online":"offline"]}),r&&e.jsxs("a",{href:r,target:"_blank",rel:"noopener",className:"flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground",children:[e.jsx(g,{className:"h-3.5 w-3.5"})," In neuem Tab"]})]})]}),r?e.jsxs("div",{className:"relative min-h-[58vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25",children:[a===!1&&e.jsxs("div",{className:"absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center",children:[e.jsx(p,{className:"h-8 w-8 text-amber-400"}),e.jsx("div",{className:"text-sm font-semibold text-amber-300",children:"Konsole nicht erreichbar"}),e.jsxs("p",{className:"max-w-sm text-[11px] leading-normal text-muted-foreground",children:["Der Terminal-Dienst (",e.jsx("code",{className:"font-mono text-primary",children:"box-console"}),") läuft gerade nicht."]}),e.jsxs("button",{onClick:u,disabled:l,className:"flex h-9 items-center gap-1.5 rounded-lg border border-amber-500/40 bg-amber-500/10 px-4 text-[11px] font-bold uppercase tracking-wide text-amber-300 transition-all hover:bg-amber-500/20 cursor-pointer disabled:opacity-50",children:[e.jsx(j,{className:c("h-3.5 w-3.5",l&&"animate-spin")})," Dienst neu starten"]}),i&&e.jsx("p",{className:"max-w-sm text-[11px] text-muted-foreground",children:i})]}),e.jsx("iframe",{src:r,title:"Box-Konsole",className:"h-full w-full border-0",style:{minHeight:"58vh"}})]}):e.jsxs("div",{className:"flex min-h-[58vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground",children:[e.jsx(N,{className:"mr-2 h-4 w-4"})," Lade Konsole…"]})]})}export{y as KonsoleView};
|
||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GraphView-JdSE2NmA.js","assets/index-DI19YZ2i.js","assets/index-DLBMFIff.css"])))=>i.map(i=>d[i]);
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/GraphView-BroxK768.js","assets/index-BITRSHQi.js","assets/index-DCSDaWJZ.css"])))=>i.map(i=>d[i]);
|
||||||
var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,configurable:!0,writable:!0,value:c}):d[i]=c;var J=(d,i,c)=>ke(d,typeof i!="symbol"?i+"":i,c);import{c as h,r as s,j as e,u as ve,b as Ne,O as W,Q as Se,C as X,R as Ce,S as Ee,P as Me,U as O,e as x,V as ze,W as De,X as Z,A as Y,_ as Oe,g as j}from"./index-DI19YZ2i.js";import{C as ee}from"./copy-CsXXFqkj.js";import{S as _e}from"./send-CpIJWZ5L.js";import{B as Ge}from"./book-open-CqxVgaj6.js";/**
|
var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,configurable:!0,writable:!0,value:c}):d[i]=c;var J=(d,i,c)=>ke(d,typeof i!="symbol"?i+"":i,c);import{c as h,r as s,j as e,u as ve,b as Ne,O as W,Q as Se,C as X,R as Ce,S as Ee,P as Me,U as O,e as x,V as ze,W as De,X as Z,A as Y,_ as Oe,g as j}from"./index-BITRSHQi.js";import{C as ee}from"./copy-CxQj3NkO.js";import{S as _e}from"./send-ByEkObSZ.js";import{B as Ge}from"./book-open-DbieW73t.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
@@ -34,7 +34,7 @@ var je=Object.defineProperty;var ke=(d,i,c)=>i in d?je(d,i,{enumerable:!0,config
|
|||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
* See the LICENSE file in the root directory of this source tree.
|
* See the LICENSE file in the root directory of this source tree.
|
||||||
*/const Pe=h("User",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);class te extends s.Component{constructor(){super(...arguments);J(this,"state",{error:null})}static getDerivedStateFromError(c){return{error:c}}render(){return this.state.error?e.jsxs("div",{className:"h-[480px] rounded-2xl border border-red-500/20 bg-red-500/5 p-6 text-xs text-red-400 overflow-auto",children:[e.jsx("div",{className:"font-semibold mb-2",children:"Graph konnte nicht gerendert werden"}),e.jsx("pre",{className:"whitespace-pre-wrap break-words text-[11px] leading-relaxed",children:this.state.error.message})]}):this.props.children}}const se=s.lazy(()=>Oe(()=>import("./GraphView-JdSE2NmA.js"),__vite__mapDeps([0,1,2])).then(d=>({default:d.GraphView}))),k=["identity","knowledge","rules","events"],v=new Set(["auto","agent","hermes"]),N={identity:{label:"Identität",icon:Pe,bg:"bg-cyan-500/10",text:"text-cyan-400"},knowledge:{label:"Wissen",icon:De,bg:"bg-indigo-500/10",text:"text-indigo-400"},rules:{label:"Regeln",icon:Le,bg:"bg-violet-500/10",text:"text-violet-400"},events:{label:"Ereignisse",icon:ze,bg:"bg-amber-500/10",text:"text-amber-400"}},ne={label:"Gedächtnis",icon:Ge,text:"text-muted-foreground"},Re={identity:"border-l-cyan-500/80",knowledge:"border-l-indigo-500/80",rules:"border-l-violet-500/80",events:"border-l-amber-500/80"},_={identity:"#00f5ff",knowledge:"#3b82f6",rules:"#d946ef",events:"#fbbf24"},ae=`Hi Hermes! Lass uns ein kurzes Onboarding machen, damit du dich künftig an mich erinnerst. Stell mir nacheinander ein paar kurze Fragen zu:
|
*/const Pe=h("User",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]);class te extends s.Component{constructor(){super(...arguments);J(this,"state",{error:null})}static getDerivedStateFromError(c){return{error:c}}render(){return this.state.error?e.jsxs("div",{className:"h-[480px] rounded-2xl border border-red-500/20 bg-red-500/5 p-6 text-xs text-red-400 overflow-auto",children:[e.jsx("div",{className:"font-semibold mb-2",children:"Graph konnte nicht gerendert werden"}),e.jsx("pre",{className:"whitespace-pre-wrap break-words text-[11px] leading-relaxed",children:this.state.error.message})]}):this.props.children}}const se=s.lazy(()=>Oe(()=>import("./GraphView-BroxK768.js"),__vite__mapDeps([0,1,2])).then(d=>({default:d.GraphView}))),k=["identity","knowledge","rules","events"],v=new Set(["auto","agent","hermes"]),N={identity:{label:"Identität",icon:Pe,bg:"bg-cyan-500/10",text:"text-cyan-400"},knowledge:{label:"Wissen",icon:De,bg:"bg-indigo-500/10",text:"text-indigo-400"},rules:{label:"Regeln",icon:Le,bg:"bg-violet-500/10",text:"text-violet-400"},events:{label:"Ereignisse",icon:ze,bg:"bg-amber-500/10",text:"text-amber-400"}},ne={label:"Gedächtnis",icon:Ge,text:"text-muted-foreground"},Re={identity:"border-l-cyan-500/80",knowledge:"border-l-indigo-500/80",rules:"border-l-violet-500/80",events:"border-l-amber-500/80"},_={identity:"#00f5ff",knowledge:"#3b82f6",rules:"#d946ef",events:"#fbbf24"},ae=`Hi Hermes! Lass uns ein kurzes Onboarding machen, damit du dich künftig an mich erinnerst. Stell mir nacheinander ein paar kurze Fragen zu:
|
||||||
1) wer ich bin und woran ich gerade arbeite,
|
1) wer ich bin und woran ich gerade arbeite,
|
||||||
2) wie ich angesprochen werden möchte,
|
2) wie ich angesprochen werden möchte,
|
||||||
3) meine bevorzugten Tools, Sprachen und Arbeitsweise,
|
3) meine bevorzugten Tools, Sprachen und Arbeitsweise,
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as q,u as oe,a as Fe,b as ge,j as e,f as ue,d as Re,e as w,g as K,q as P,h as Ie,r as N,C as Y,L as Oe,i as Pe,B as le,k as Te,E as Be,l as de,m as Ge,n as $e,o as He,p as ee,X as pe,P as Qe,H as fe,T as re,s as Ue,t as Ve,v as V,w as We,S as ye,x as Ze,y as Je,z as Xe,A as Ye,D as De,F as et,G as tt}from"./index-DI19YZ2i.js";import{C as rt}from"./code-xml-C9b7xGyM.js";import{R as st}from"./rotate-ccw-CBUivZG3.js";import{C as be,Z as ie,L as nt,a as at}from"./zap-CVKHAOl9.js";import{L as ot}from"./layers-DQdxWFgI.js";/**
|
import{c as q,u as oe,a as Fe,b as ge,j as e,f as ue,d as Re,e as w,g as K,q as P,h as Ie,r as N,C as Y,L as Oe,i as Pe,B as le,k as Te,E as Be,l as de,m as Ge,n as $e,o as He,p as ee,X as pe,P as Qe,H as fe,T as re,s as Ue,t as Ve,v as V,w as We,S as ye,x as Ze,y as Je,z as Xe,A as Ye,D as De,F as et,G as tt}from"./index-BITRSHQi.js";import{C as rt}from"./code-xml-B8Mgduyw.js";import{R as st}from"./rotate-ccw-Bqk2RuMY.js";import{C as be,Z as ie,L as nt,a as at}from"./zap-Bie21ltg.js";import{L as ot}from"./layers-C0bwoJh5.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as s,j as e}from"./index-DI19YZ2i.js";/**
|
import{c as s,j as e}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{ar as y,r as x,g as L,j as e,L as v,S,ag as W,U as C,e as w,as as E}from"./index-DI19YZ2i.js";import{F as M}from"./folder-open-DKNPWUub.js";const D={"":"Allgemein",traeume:"Träume",muster:"Muster","skill-kandidaten":"Skill-Kandidaten","skill-kandidaten/beauftragt":"Skill-Kandidaten · beauftragt","skill-kandidaten/verworfen":"Skill-Kandidaten · verworfen"};function T(){const{data:o,isLoading:h}=y(),[l,f]=x.useState(null),[d,r]=x.useState(null),[u,i]=x.useState(!1),[a,p]=x.useState(""),t=x.useMemo(()=>(o==null?void 0:o.files)??[],[o]),m=x.useMemo(()=>{const s=new Map;for(const n of t)s.set(n.name.toLowerCase(),n.path);return s},[t]),g=x.useMemo(()=>{if(!a.trim())return t;const s=a.toLowerCase();return t.filter(n=>n.title.toLowerCase().includes(s)||n.path.toLowerCase().includes(s))},[t,a]),b=x.useMemo(()=>{const s=[];for(const n of g){const c=s.find(k=>k.dir===n.dir);c?c.files.push(n):s.push({dir:n.dir,files:[n]})}return s.sort((n,c)=>n.dir===""?-1:c.dir===""?1:n.dir.localeCompare(c.dir))},[g]);x.useEffect(()=>{if(!l&&t.length){const s=t.find(n=>n.path.toLowerCase()==="index.md");f((s==null?void 0:s.path)??t[0].path)}},[t,l]),x.useEffect(()=>{l&&(i(!0),L(`/api/wissen/datei?pfad=${encodeURIComponent(l)}`).then(r).catch(()=>r({path:l,content:"*(Notiz nicht ladbar)*",mtime:0})).finally(()=>i(!1)))},[l]);const j=s=>{const n=m.get(s.toLowerCase());n&&f(n)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Wissen"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki."})]}),o&&!o.available&&e.jsx("div",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/5 p-4 text-xs text-amber-300",children:"Der Wissens-Vault liegt auf der Box (~/wissens-vault) — im lokalen Dev-Modus nicht verfügbar."}),h&&e.jsxs("div",{className:"flex items-center gap-2 rounded-2xl border border-border/60 bg-card/30 p-6 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Vault wird geladen …"]}),(o==null?void 0:o.available)&&t.length===0&&e.jsx("div",{className:"rounded-2xl border border-dashed border-border/60 bg-card/20 p-8 text-center text-xs text-muted-foreground",children:"Noch keine Notizen. Der nächtliche Traum (03:15) legt sie an — morgen früh steht hier die erste."}),t.length>0&&e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row",children:[e.jsxs("aside",{className:"w-full shrink-0 space-y-3 lg:w-72",children:[e.jsxs("div",{className:"relative",children:[e.jsx("input",{value:a,onChange:s=>p(s.target.value),type:"search",placeholder:"Notizen durchsuchen…","aria-label":"Notizen durchsuchen",className:"h-9 w-full rounded-lg border border-border/60 bg-card/45 pl-8 pr-3 text-xs text-foreground outline-none focus:ring-1 focus:ring-primary/50"}),e.jsx(S,{className:"absolute left-2.5 top-2.5 h-3.5 w-3.5 text-muted-foreground"})]}),e.jsx("div",{className:"max-h-[70vh] space-y-3 overflow-y-auto pr-1 scrollbar-thin",children:b.map(({dir:s,files:n})=>e.jsxs("div",{children:[e.jsxs("p",{className:"mb-1 flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider text-muted-foreground/60",children:[e.jsx(M,{className:"h-3 w-3"})," ",D[s]??s]}),e.jsx("div",{className:"space-y-0.5",children:n.map(c=>e.jsxs("button",{onClick:()=>f(c.path),className:w("flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-xs transition-all cursor-pointer",l===c.path?"bg-primary/15 text-primary":"text-muted-foreground hover:bg-accent hover:text-foreground"),children:[e.jsx(W,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{className:"truncate",title:c.title,children:c.name}),c.neu&&e.jsxs("span",{className:"ml-auto flex items-center gap-0.5 rounded bg-violet-500/15 px-1 py-0.5 text-[8px] font-bold uppercase text-violet-300",children:[e.jsx(C,{className:"h-2.5 w-2.5"}),"neu"]})]},c.path))})]},s||"__root"))})]}),e.jsx("div",{className:"min-w-0 flex-1 mc-card p-5",children:u?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Notiz wird geladen …"]}):d?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between border-b border-border/40 pb-2",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-mono text-[11px] text-muted-foreground",children:[e.jsx(E,{className:"h-3.5 w-3.5"})," ",d.path]}),d.mtime>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground/60",children:["Stand ",new Date(d.mtime*1e3).toLocaleString("de-DE",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"})]})]}),e.jsx(z,{text:d.content,onWikiLink:j,known:m})]}):null})]})]})}function z({text:o,onWikiLink:h,known:l}){const f=o.split(`
|
import{ar as y,r as x,g as L,j as e,L as v,S,ah as W,U as C,e as w,as as E}from"./index-BITRSHQi.js";import{F as M}from"./folder-open-Cf0PzlLv.js";const D={"":"Allgemein",traeume:"Träume",muster:"Muster","skill-kandidaten":"Skill-Kandidaten","skill-kandidaten/beauftragt":"Skill-Kandidaten · beauftragt","skill-kandidaten/verworfen":"Skill-Kandidaten · verworfen"};function T(){const{data:o,isLoading:h}=y(),[l,f]=x.useState(null),[d,r]=x.useState(null),[u,i]=x.useState(!1),[a,p]=x.useState(""),t=x.useMemo(()=>(o==null?void 0:o.files)??[],[o]),m=x.useMemo(()=>{const s=new Map;for(const n of t)s.set(n.name.toLowerCase(),n.path);return s},[t]),g=x.useMemo(()=>{if(!a.trim())return t;const s=a.toLowerCase();return t.filter(n=>n.title.toLowerCase().includes(s)||n.path.toLowerCase().includes(s))},[t,a]),b=x.useMemo(()=>{const s=[];for(const n of g){const c=s.find(k=>k.dir===n.dir);c?c.files.push(n):s.push({dir:n.dir,files:[n]})}return s.sort((n,c)=>n.dir===""?-1:c.dir===""?1:n.dir.localeCompare(c.dir))},[g]);x.useEffect(()=>{if(!l&&t.length){const s=t.find(n=>n.path.toLowerCase()==="index.md");f((s==null?void 0:s.path)??t[0].path)}},[t,l]),x.useEffect(()=>{l&&(i(!0),L(`/api/wissen/datei?pfad=${encodeURIComponent(l)}`).then(r).catch(()=>r({path:l,content:"*(Notiz nicht ladbar)*",mtime:0})).finally(()=>i(!1)))},[l]);const j=s=>{const n=m.get(s.toLowerCase());n&&f(n)};return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent",children:"Wissen"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Was sich die Box nachts erschließt — Traum-Notizen, Muster und Skill-Ideen aus dem Wissens-Vault, verlinkt wie ein Wiki."})]}),o&&!o.available&&e.jsx("div",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/5 p-4 text-xs text-amber-300",children:"Der Wissens-Vault liegt auf der Box (~/wissens-vault) — im lokalen Dev-Modus nicht verfügbar."}),h&&e.jsxs("div",{className:"flex items-center gap-2 rounded-2xl border border-border/60 bg-card/30 p-6 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Vault wird geladen …"]}),(o==null?void 0:o.available)&&t.length===0&&e.jsx("div",{className:"rounded-2xl border border-dashed border-border/60 bg-card/20 p-8 text-center text-xs text-muted-foreground",children:"Noch keine Notizen. Der nächtliche Traum (03:15) legt sie an — morgen früh steht hier die erste."}),t.length>0&&e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row",children:[e.jsxs("aside",{className:"w-full shrink-0 space-y-3 lg:w-72",children:[e.jsxs("div",{className:"relative",children:[e.jsx("input",{value:a,onChange:s=>p(s.target.value),type:"search",placeholder:"Notizen durchsuchen…","aria-label":"Notizen durchsuchen",className:"h-9 w-full rounded-lg border border-border/60 bg-card/45 pl-8 pr-3 text-xs text-foreground outline-none focus:ring-1 focus:ring-primary/50"}),e.jsx(S,{className:"absolute left-2.5 top-2.5 h-3.5 w-3.5 text-muted-foreground"})]}),e.jsx("div",{className:"max-h-[70vh] space-y-3 overflow-y-auto pr-1 scrollbar-thin",children:b.map(({dir:s,files:n})=>e.jsxs("div",{children:[e.jsxs("p",{className:"mb-1 flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider text-muted-foreground/60",children:[e.jsx(M,{className:"h-3 w-3"})," ",D[s]??s]}),e.jsx("div",{className:"space-y-0.5",children:n.map(c=>e.jsxs("button",{onClick:()=>f(c.path),className:w("flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-xs transition-all cursor-pointer",l===c.path?"bg-primary/15 text-primary":"text-muted-foreground hover:bg-accent hover:text-foreground"),children:[e.jsx(W,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{className:"truncate",title:c.title,children:c.name}),c.neu&&e.jsxs("span",{className:"ml-auto flex items-center gap-0.5 rounded bg-violet-500/15 px-1 py-0.5 text-[8px] font-bold uppercase text-violet-300",children:[e.jsx(C,{className:"h-2.5 w-2.5"}),"neu"]})]},c.path))})]},s||"__root"))})]}),e.jsx("div",{className:"min-w-0 flex-1 mc-card p-5",children:u?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(v,{className:"h-4 w-4 animate-spin"})," Notiz wird geladen …"]}):d?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between border-b border-border/40 pb-2",children:[e.jsxs("span",{className:"flex items-center gap-1.5 font-mono text-[11px] text-muted-foreground",children:[e.jsx(E,{className:"h-3.5 w-3.5"})," ",d.path]}),d.mtime>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground/60",children:["Stand ",new Date(d.mtime*1e3).toLocaleString("de-DE",{day:"2-digit",month:"2-digit",hour:"2-digit",minute:"2-digit"})]})]}),e.jsx(z,{text:d.content,onWikiLink:j,known:m})]}):null})]})]})}function z({text:o,onWikiLink:h,known:l}){const f=o.split(`
|
||||||
`),d=[];let r=[],u=null;const i=a=>{r.length&&(d.push(e.jsx("ul",{className:"mb-3 ml-4 list-disc space-y-1",children:r},a)),r=[])};return f.forEach((a,p)=>{const t=`l${p}`;if(u!==null){a.trimEnd()==="```"?(d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-foreground/85",children:u.join(`
|
`),d=[];let r=[],u=null;const i=a=>{r.length&&(d.push(e.jsx("ul",{className:"mb-3 ml-4 list-disc space-y-1",children:r},a)),r=[])};return f.forEach((a,p)=>{const t=`l${p}`;if(u!==null){a.trimEnd()==="```"?(d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px] leading-relaxed text-foreground/85",children:u.join(`
|
||||||
`)},t)),u=null):u.push(a);return}if(a.trimStart().startsWith("```")){i(t),u=[];return}const m=a.trimEnd();if(!m.trim()){i(t);return}const g=m.match(/^(#{1,4})\s+(.*)$/);if(g){i(t);const j=g[1].length,s=j===1?"text-lg font-bold mt-1 mb-3":j===2?"text-base font-bold mt-4 mb-2":"text-sm font-bold mt-3 mb-1.5";d.push(e.jsx("p",{className:w(s,"font-space text-foreground"),children:N(g[2],h,l,t)},t));return}const b=m.match(/^\s*[-*•]\s+(.*)$/);if(b){r.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:N(b[1],h,l,t)},t));return}i(t),d.push(e.jsx("p",{className:"mb-2 text-xs leading-relaxed text-foreground/85",children:N(m,h,l,t)},t))}),i("end"),u!==null&&d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px]",children:u.join(`
|
`)},t)),u=null):u.push(a);return}if(a.trimStart().startsWith("```")){i(t),u=[];return}const m=a.trimEnd();if(!m.trim()){i(t);return}const g=m.match(/^(#{1,4})\s+(.*)$/);if(g){i(t);const j=g[1].length,s=j===1?"text-lg font-bold mt-1 mb-3":j===2?"text-base font-bold mt-4 mb-2":"text-sm font-bold mt-3 mb-1.5";d.push(e.jsx("p",{className:w(s,"font-space text-foreground"),children:N(g[2],h,l,t)},t));return}const b=m.match(/^\s*[-*•]\s+(.*)$/);if(b){r.push(e.jsx("li",{className:"text-xs leading-relaxed text-foreground/85",children:N(b[1],h,l,t)},t));return}i(t),d.push(e.jsx("p",{className:"mb-2 text-xs leading-relaxed text-foreground/85",children:N(m,h,l,t)},t))}),i("end"),u!==null&&d.push(e.jsx("pre",{className:"mb-3 overflow-x-auto rounded-xl border border-border/50 bg-background/50 p-3 font-mono text-[11px]",children:u.join(`
|
||||||
`)},"code-end")),e.jsx("div",{className:"max-w-3xl",children:d})}function N(o,h,l,f){return o.split(/(\[\[[^\]]+\]\]|\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g).map((r,u)=>{const i=`${f}-${u}`,a=r.match(/^\[\[([^\]|]+)(?:\|([^\]]+))?\]\]$/);if(a){const p=a[1].trim(),t=(a[2]??a[1]).trim();return l.has(p.toLowerCase())?e.jsx("button",{onClick:()=>h(p),className:"rounded bg-primary/10 px-1 text-primary underline decoration-primary/40 underline-offset-2 hover:bg-primary/20 cursor-pointer",children:t},i):e.jsx("span",{className:"rounded bg-background/40 px-1 text-muted-foreground",title:"Notiz existiert (noch) nicht",children:t},i)}return r.startsWith("**")&&r.endsWith("**")?e.jsx("b",{className:"font-semibold text-foreground",children:r.slice(2,-2)},i):r.startsWith("*")&&r.endsWith("*")&&r.length>2?e.jsx("i",{children:r.slice(1,-1)},i):r.startsWith("`")&&r.endsWith("`")?e.jsx("code",{className:"rounded bg-background/50 px-1 font-mono text-[11px] text-teal-300",children:r.slice(1,-1)},i):e.jsx("span",{children:r},i)})}export{T as WissenView};
|
`)},"code-end")),e.jsx("div",{className:"max-w-3xl",children:d})}function N(o,h,l,f){return o.split(/(\[\[[^\]]+\]\]|\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g).map((r,u)=>{const i=`${f}-${u}`,a=r.match(/^\[\[([^\]|]+)(?:\|([^\]]+))?\]\]$/);if(a){const p=a[1].trim(),t=(a[2]??a[1]).trim();return l.has(p.toLowerCase())?e.jsx("button",{onClick:()=>h(p),className:"rounded bg-primary/10 px-1 text-primary underline decoration-primary/40 underline-offset-2 hover:bg-primary/20 cursor-pointer",children:t},i):e.jsx("span",{className:"rounded bg-background/40 px-1 text-muted-foreground",title:"Notiz existiert (noch) nicht",children:t},i)}return r.startsWith("**")&&r.endsWith("**")?e.jsx("b",{className:"font-semibold text-foreground",children:r.slice(2,-2)},i):r.startsWith("*")&&r.endsWith("*")&&r.length>2?e.jsx("i",{children:r.slice(1,-1)},i):r.startsWith("`")&&r.endsWith("`")?e.jsx("code",{className:"rounded bg-background/50 px-1 font-mono text-[11px] text-teal-300",children:r.slice(1,-1)},i):e.jsx("span",{children:r},i)})}export{T as WissenView};
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as a}from"./index-DI19YZ2i.js";/**
|
import{c as a}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c}from"./index-DI19YZ2i.js";/**
|
import{c}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as e}from"./index-DI19YZ2i.js";/**
|
import{c as e}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c}from"./index-DI19YZ2i.js";/**
|
import{c}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as a}from"./index-DI19YZ2i.js";/**
|
import{c as a}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+2
-2
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as a}from"./index-DI19YZ2i.js";/**
|
import{c as a}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as t}from"./index-DI19YZ2i.js";/**
|
import{c as t}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as a}from"./index-DI19YZ2i.js";/**
|
import{c as a}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as a}from"./index-DI19YZ2i.js";/**
|
import{c as a}from"./index-BITRSHQi.js";/**
|
||||||
* @license lucide-react v0.460.0 - ISC
|
* @license lucide-react v0.460.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
Vendored
+2
-2
@@ -7,8 +7,8 @@
|
|||||||
<link rel="manifest" href="/manifest.webmanifest" />
|
<link rel="manifest" href="/manifest.webmanifest" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<title>Mission Control 2.0</title>
|
<title>Mission Control 2.0</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DI19YZ2i.js"></script>
|
<script type="module" crossorigin src="/assets/index-BITRSHQi.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DLBMFIff.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DCSDaWJZ.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
+129
-101
@@ -67,20 +67,23 @@ function IdeenSection() {
|
|||||||
const qc = useQueryClient()
|
const qc = useQueryClient()
|
||||||
const { showAlert, showConfirm, dialogElement } = useDialog()
|
const { showAlert, showConfirm, dialogElement } = useDialog()
|
||||||
const [text, setText] = useState("")
|
const [text, setText] = useState("")
|
||||||
// Zwei UNABHÄNGIGE Entscheidungen statt vier sich ausschliessender Modi (25.07.2026):
|
// GENAU EINE Auswahl aus drei, in zwei Bereichen (26.07.2026):
|
||||||
// wer — baut die Box selbst, oder bekommst du ein Repo für Zed?
|
// denken → du baust selbst, aber erst ein Konzept. Auf „gefällt mir" wird daraus ein Repo.
|
||||||
// nurDenken — soll erst nur ein Konzept entstehen? (passt zu beidem)
|
// repo → du baust selbst, Konzept + Gitea-Repo sofort.
|
||||||
// Vorher hiessen die Knöpfe BOX/IDEE/IDE:SIMPEL/IDE:GRÜNDLICH und pressten beides in eine
|
// box → die Box baut, Ergebnis kommt als Patch-Vorschlag.
|
||||||
// Reihe — das brauchte 116 Wörter Beipackzettel darunter. Die Abbildung auf die
|
//
|
||||||
// unveränderte API passiert in submit().
|
// Vorher (25.07.) waren das zwei angeblich unabhängige Dimensionen: „wer baut" plus ein
|
||||||
const [wer, setWer] = useState<"box" | "zed">("box")
|
// Haken „nur denken". Das war FALSCH modelliert — `weiterfuehren` macht aus einer
|
||||||
|
// durchdachten Idee genau die IDE-Projekt-Karte, die `repo` direkt anlegt. Es sind also
|
||||||
|
// zwei Stufen EINES Weges, nicht zwei Achsen. Und die Kombination box+denken schob einen
|
||||||
|
// still in die IDE-Welt (submit setzte welt:"ide"), ohne das irgendwo zu sagen.
|
||||||
|
const [modus, setModus] = useState<"denken" | "repo" | "box">("denken")
|
||||||
const [tiefe, setTiefe] = useState<"schlank" | "gruendlich">("schlank")
|
const [tiefe, setTiefe] = useState<"schlank" | "gruendlich">("schlank")
|
||||||
const [nurDenken, setNurDenken] = useState(false)
|
|
||||||
// Kam die aktuelle Auswahl von der Box? Nur fürs Etikett „Vorschlag" — sobald du selbst
|
// Kam die aktuelle Auswahl von der Box? Nur fürs Etikett „Vorschlag" — sobald du selbst
|
||||||
// klickst, verschwindet es, damit nie unklar ist, wessen Entscheidung da steht.
|
// klickst, verschwindet es, damit nie unklar ist, wessen Entscheidung da steht.
|
||||||
const [vorgeschlagen, setVorgeschlagen] = useState(false)
|
const [vorgeschlagen, setVorgeschlagen] = useState(false)
|
||||||
const isIde = wer === "zed" || nurDenken // beides läuft über das projektstart-Profil
|
const isIde = modus !== "box" // denken UND repo laufen über das projektstart-Profil
|
||||||
const isProjekt = wer === "zed" && !nurDenken // nur DANN sind Tiefe und Ziel wirksam
|
const isProjekt = modus === "repo" // nur DANN sind Tiefe und Ziel jetzt schon nötig
|
||||||
// Ziel-Plattform des Projekts (nur IDE-Welt): läuft es als LXC-Dienst oder in Docker?
|
// Ziel-Plattform des Projekts (nur IDE-Welt): läuft es als LXC-Dienst oder in Docker?
|
||||||
const [ziel, setZiel] = useState<"lxc" | "docker">("lxc")
|
const [ziel, setZiel] = useState<"lxc" | "docker">("lxc")
|
||||||
const [sending, setSending] = useState(false)
|
const [sending, setSending] = useState(false)
|
||||||
@@ -105,9 +108,10 @@ function IdeenSection() {
|
|||||||
const r = await api<{ ok: boolean; wer?: "box" | "zed"; tiefe?: "schlank" | "gruendlich"; nur_denken?: boolean }>(
|
const r = await api<{ ok: boolean; wer?: "box" | "zed"; tiefe?: "schlank" | "gruendlich"; nur_denken?: boolean }>(
|
||||||
"/api/ideen/einordnen", { method: "POST", body: JSON.stringify({ text: t }) })
|
"/api/ideen/einordnen", { method: "POST", body: JSON.stringify({ text: t }) })
|
||||||
if (verworfen || !r?.ok) return
|
if (verworfen || !r?.ok) return
|
||||||
if (r.wer) setWer(r.wer)
|
// Die drei Karten aus der Einordnung ableiten: eine Frage („lohnt sich…?") wird zum
|
||||||
|
// Durchdenken, ein eigenständiges Programm zum Repo, alles am Heimlabor zur Box.
|
||||||
|
setModus(r.nur_denken ? "denken" : r.wer === "zed" ? "repo" : "box")
|
||||||
if (r.tiefe) setTiefe(r.tiefe)
|
if (r.tiefe) setTiefe(r.tiefe)
|
||||||
setNurDenken(!!r.nur_denken)
|
|
||||||
setVorgeschlagen(true)
|
setVorgeschlagen(true)
|
||||||
} catch { /* stumm — die Voreinstellung bleibt einfach stehen */ }
|
} catch { /* stumm — die Voreinstellung bleibt einfach stehen */ }
|
||||||
}, 700)
|
}, 700)
|
||||||
@@ -128,12 +132,13 @@ function IdeenSection() {
|
|||||||
const titel = t.length > 160 ? t.slice(0, 157) + "…" : t
|
const titel = t.length > 160 ? t.slice(0, 157) + "…" : t
|
||||||
await api("/api/ideen", { method: "POST", body: JSON.stringify({
|
await api("/api/ideen", { method: "POST", body: JSON.stringify({
|
||||||
titel, notiz: t.length > 160 ? t : "",
|
titel, notiz: t.length > 160 ? t : "",
|
||||||
// Abbildung auf die unveränderte API: „nur denken" läuft immer über die IDE-Welt,
|
// Abbildung auf die unveränderte API. Tiefe und Ziel gehen NUR beim Repo-Weg mit —
|
||||||
// weil dort das Profil sitzt, das denkt statt baut.
|
// beim Durchdenken fragt die Weiter-Leiste sie später beim „gefällt mir", und dann
|
||||||
|
// weiss man mehr als jetzt.
|
||||||
welt: isIde ? "ide" : "box",
|
welt: isIde ? "ide" : "box",
|
||||||
tiefe: isProjekt ? (tiefe === "gruendlich" ? "gruendlich" : "simpel") : "",
|
tiefe: isProjekt ? (tiefe === "gruendlich" ? "gruendlich" : "simpel") : "",
|
||||||
ziel: isProjekt ? ziel : "", // eine Idee braucht noch keine Plattform
|
ziel: isProjekt ? ziel : "",
|
||||||
art: nurDenken ? "idee" : "projekt",
|
art: modus === "denken" ? "idee" : "projekt",
|
||||||
}) })
|
}) })
|
||||||
setText("")
|
setText("")
|
||||||
setVorgeschlagen(false)
|
setVorgeschlagen(false)
|
||||||
@@ -466,96 +471,90 @@ function IdeenSection() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Wer baut das? Zwei Karten statt vier Kürzel — jede sagt, was DU danach bekommst. */}
|
{/* ZWEI BEREICHE, drei Karten — ausgewaehlt ist immer genau EINE Karte, nie ein
|
||||||
|
ganzer Bereich. Der Bereich gruppiert nur, was denselben Weg geht: „durchdenken"
|
||||||
|
und „Repo" sind zwei Stufen desselben Wegs (weiterfuehren macht aus der einen die
|
||||||
|
andere), waehrend die Box-Welt etwas voellig anderes tut. */}
|
||||||
<div>
|
<div>
|
||||||
<p className="mb-1.5 text-[11px] text-muted-foreground/70">Wer baut das?</p>
|
<p className="mb-2 text-[11px] text-muted-foreground/70">Was soll damit passieren?</p>
|
||||||
<div className="grid gap-2 sm:grid-cols-2">
|
|
||||||
{([
|
|
||||||
{ id: "box" as const, icon: Hammer, titel: "Die Box, allein",
|
|
||||||
text: "Sie baut es und legt dir das Ergebnis als Vorschlag hin — nichts geht ohne deinen Klick live." },
|
|
||||||
{ id: "zed" as const, icon: Code2, titel: "Ich, in Zed",
|
|
||||||
text: "Du bekommst ein fertiges Repo mit Konzept und Doku. Den Code schreibst du selbst." },
|
|
||||||
]).map((k) => {
|
|
||||||
const aktiv = wer === k.id
|
|
||||||
return (
|
|
||||||
<button key={k.id}
|
|
||||||
onClick={() => { setWer(k.id); setVorgeschlagen(false) }}
|
|
||||||
disabled={nurDenken}
|
|
||||||
className={cn("rounded-xl border p-3 text-left transition-all cursor-pointer disabled:cursor-default",
|
|
||||||
nurDenken ? "border-border/30 opacity-40"
|
|
||||||
: aktiv ? "border-primary/60 bg-primary/5" : "border-border/50 hover:border-border")}>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<k.icon className={cn("h-4 w-4 shrink-0", aktiv && !nurDenken ? "text-primary" : "text-muted-foreground")} />
|
|
||||||
<span className="text-xs font-semibold text-foreground">{k.titel}</span>
|
|
||||||
{aktiv && vorgeschlagen && !nurDenken && (
|
|
||||||
<span className="ml-auto shrink-0 rounded border border-primary/40 bg-primary/10 px-1.5 py-0.5 text-[10px] font-bold text-primary">
|
|
||||||
Vorschlag
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<p className="mt-1 text-[11px] leading-relaxed text-muted-foreground">{k.text}</p>
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
{nurDenken && (
|
|
||||||
<p className="mt-1.5 text-[10px] text-muted-foreground/60">
|
|
||||||
Wer baut, entscheidest du, wenn das Konzept da ist.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tiefe und Ziel wirken NUR beim Repo-Weg — deshalb erscheinen sie auch nur dort.
|
<div className="rounded-xl border border-border/40 bg-background/20 p-3">
|
||||||
Ein Schalter, der nichts tut, ist schlimmer als keiner. */}
|
<div className="mb-2 flex items-center gap-2">
|
||||||
{isProjekt && (
|
<Code2 className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
|
<span className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||||
<span className="text-[11px] text-muted-foreground/70">Wie gründlich?</span>
|
Du baust selbst, in Zed
|
||||||
<div className="flex rounded-lg border border-border/60 p-0.5">
|
</span>
|
||||||
{([["schlank", "schlank"], ["gruendlich", "gründlich"]] as const).map(([id, label]) => (
|
</div>
|
||||||
<button key={id} onClick={() => { setTiefe(id); setVorgeschlagen(false) }}
|
<div className="grid gap-2 sm:grid-cols-2">
|
||||||
className={cn("rounded px-2.5 py-1 text-[10px] font-bold uppercase tracking-wide transition-all cursor-pointer",
|
{([
|
||||||
tiefe === id ? "bg-primary/15 text-primary" : "text-muted-foreground/60 hover:text-foreground")}>
|
{ id: "denken" as const, icon: Lightbulb, titel: "Erst durchdenken",
|
||||||
{label}
|
text: "Du bekommst ein Konzept. Gefällt es dir, wird auf Klick ein Repo daraus." },
|
||||||
</button>
|
{ id: "repo" as const, icon: GitFork, titel: "Direkt ein Repo",
|
||||||
|
text: "Konzept und Gitea-Repo in einem Zug — wenn du es ohnehin bauen willst." },
|
||||||
|
]).map((k) => (
|
||||||
|
<Wahl key={k.id} k={k} aktiv={modus === k.id} vorgeschlagen={vorgeschlagen}
|
||||||
|
onWahl={() => { setModus(k.id); setVorgeschlagen(false) }} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[10px] text-muted-foreground/60">
|
|
||||||
{tiefe === "gruendlich"
|
|
||||||
? "mehrere Fach-Rollen, bis zu 3 Denk-Runden, mehrfacher Härtetest — dauert entsprechend"
|
|
||||||
: "2 Rollen, eine Denk-Runde — ein paar Minuten"}
|
|
||||||
</span>
|
|
||||||
<span className="ml-auto flex items-center gap-1.5">
|
|
||||||
<span className="text-[11px] text-muted-foreground/70">Läuft als</span>
|
|
||||||
<div className="flex rounded-lg border border-border/40 p-0.5">
|
|
||||||
{([["lxc", "LXC"], ["docker", "Docker"]] as const).map(([id, label]) => (
|
|
||||||
<button key={id} onClick={() => setZiel(id)}
|
|
||||||
title={id === "lxc"
|
|
||||||
? "Dienst in einem eigenen Proxmox-LXC (systemd, kein Docker). Wird vom Backup-Server automatisch mitgesichert."
|
|
||||||
: "Natives Docker: Dockerfile + compose, portabel und pipeline-tauglich."}
|
|
||||||
className={cn("rounded px-2 py-0.5 text-[10px] font-semibold transition-all cursor-pointer",
|
|
||||||
ziel === id ? "bg-foreground/10 text-foreground" : "text-muted-foreground/50 hover:text-foreground/80")}>
|
|
||||||
{label}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Orthogonal zu allem darüber: erst denken, bauen später entscheiden. */}
|
{/* Tiefe und Ziel nur beim Repo-Weg: beim Durchdenken fragt die Weiter-Leiste
|
||||||
<label className="flex cursor-pointer items-start gap-2 border-t border-border/30 pt-3">
|
sie spaeter — dann weisst du, was das Ding ueberhaupt wird. */}
|
||||||
<input type="checkbox" checked={nurDenken}
|
{modus === "repo" && (
|
||||||
onChange={(e) => { setNurDenken(e.target.checked); setVorgeschlagen(false) }}
|
<div className="mt-3 flex flex-wrap items-center gap-x-3 gap-y-2 border-t border-border/30 pt-3">
|
||||||
className="mt-0.5 h-3.5 w-3.5 shrink-0 accent-sky-400 cursor-pointer" />
|
<span className="text-[11px] text-muted-foreground/70">Wie gründlich?</span>
|
||||||
<span className="min-w-0">
|
<div className="flex rounded-lg border border-border/60 p-0.5">
|
||||||
<span className="text-xs font-semibold text-foreground">Erst nur durchdenken, noch nichts anlegen</span>
|
{([["schlank", "schlank"], ["gruendlich", "gründlich"]] as const).map(([id, label]) => (
|
||||||
<span className="mt-0.5 block text-[11px] leading-relaxed text-muted-foreground">
|
<button key={id} onClick={() => { setTiefe(id); setVorgeschlagen(false) }}
|
||||||
Die Box arbeitet die Idee mit Produkt-Blick aus — was ist es, für wen, was gibt es
|
className={cn("rounded px-2.5 py-1 text-[10px] font-bold uppercase tracking-wide transition-all cursor-pointer",
|
||||||
schon, was wäre der kleinste sinnvolle Wurf, was spricht dagegen. Ergebnis ist ein
|
tiefe === id ? "bg-primary/15 text-primary" : "text-muted-foreground/60 hover:text-foreground")}>
|
||||||
Konzept: kein Repo, kein Code, kein Bau-Druck.
|
{label}
|
||||||
</span>
|
</button>
|
||||||
</span>
|
))}
|
||||||
</label>
|
</div>
|
||||||
|
<span className="text-[10px] text-muted-foreground/60">
|
||||||
|
{tiefe === "gruendlich"
|
||||||
|
? "mehrere Fach-Rollen, bis zu 3 Denk-Runden, mehrfacher Härtetest"
|
||||||
|
: "2 Rollen, eine Denk-Runde — ein paar Minuten"}
|
||||||
|
</span>
|
||||||
|
<span className="ml-auto flex items-center gap-1.5">
|
||||||
|
<span className="text-[11px] text-muted-foreground/70">Läuft als</span>
|
||||||
|
<div className="flex rounded-lg border border-border/40 p-0.5">
|
||||||
|
{([["lxc", "LXC"], ["docker", "Docker"]] as const).map(([id, label]) => (
|
||||||
|
<button key={id} onClick={() => setZiel(id)}
|
||||||
|
title={id === "lxc"
|
||||||
|
? "Dienst in einem eigenen Proxmox-LXC (systemd, kein Docker). Wird vom Backup-Server automatisch mitgesichert."
|
||||||
|
: "Natives Docker: Dockerfile + compose, portabel und pipeline-tauglich."}
|
||||||
|
className={cn("rounded px-2 py-0.5 text-[10px] font-semibold transition-all cursor-pointer",
|
||||||
|
ziel === id ? "bg-foreground/10 text-foreground" : "text-muted-foreground/50 hover:text-foreground/80")}>
|
||||||
|
{label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{modus === "denken" && (
|
||||||
|
<p className="mt-2.5 flex items-start gap-1.5 border-t border-border/30 pt-2.5 text-[10px] leading-relaxed text-muted-foreground/60">
|
||||||
|
<HelpCircle className="mt-px h-3 w-3 shrink-0" />
|
||||||
|
Wie gründlich und wo es läuft, fragt die Box erst beim „gefällt mir" — dann weißt du mehr.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-2 rounded-xl border border-border/40 bg-background/20 p-3">
|
||||||
|
<div className="mb-2 flex items-center gap-2">
|
||||||
|
<Hammer className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||||
|
<span className="text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||||
|
Oder die Box macht es
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Wahl
|
||||||
|
k={{ id: "box", icon: Hammer, titel: "Die Box baut allein",
|
||||||
|
text: "Für dein Heimlabor — Mission Control, Lucy, Rippy, Wartung, Doku. Das Ergebnis kommt als Patch-Vorschlag ins Auftragsbuch; nichts geht ohne deinen Klick live." }}
|
||||||
|
aktiv={modus === "box"} vorgeschlagen={vorgeschlagen}
|
||||||
|
onWahl={() => { setModus("box"); setVorgeschlagen(false) }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<p className="flex items-center gap-2 text-xs text-muted-foreground"><Loader2 className="h-3.5 w-3.5 animate-spin" /> Queue wird geladen …</p>
|
<p className="flex items-center gap-2 text-xs text-muted-foreground"><Loader2 className="h-3.5 w-3.5 animate-spin" /> Queue wird geladen …</p>
|
||||||
)}
|
)}
|
||||||
@@ -633,6 +632,35 @@ function IdeenSection() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eine der drei Auswahl-Karten. Der Text steht AN der Option, nicht in einer Legende
|
||||||
|
// darunter — man liest nur, was zu dem gehört, was man gerade anschaut.
|
||||||
|
function Wahl({ k, aktiv, vorgeschlagen, onWahl }: {
|
||||||
|
k: { id: string; icon: typeof Hammer; titel: string; text: string }
|
||||||
|
aktiv: boolean
|
||||||
|
vorgeschlagen: boolean
|
||||||
|
onWahl: () => void
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={onWahl}
|
||||||
|
className={cn("rounded-xl border p-3 text-left transition-all cursor-pointer",
|
||||||
|
aktiv ? "border-primary/60 bg-primary/5" : "border-border/50 hover:border-border")}>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<k.icon className={cn("h-4 w-4 shrink-0", aktiv ? "text-primary" : "text-muted-foreground")} />
|
||||||
|
<span className="text-xs font-semibold text-foreground">{k.titel}</span>
|
||||||
|
{/* Etikett nur an der AUSGEWÄHLTEN Karte und nur solange der Vorschlag unberührt
|
||||||
|
ist — sonst wäre nie klar, wessen Entscheidung gerade dasteht. */}
|
||||||
|
{aktiv && vorgeschlagen && (
|
||||||
|
<span className="ml-auto shrink-0 rounded border border-primary/40 bg-primary/10 px-1.5 py-0.5 text-[10px] font-bold text-primary">
|
||||||
|
Vorschlag
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="mt-1 text-[11px] leading-relaxed text-muted-foreground">{k.text}</p>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Karten-Familie (verkettete Karten = ein Projekt) als Block: Fortschritt oben, dann die
|
// Karten-Familie (verkettete Karten = ein Projekt) als Block: Fortschritt oben, dann die
|
||||||
// AKTIVEN Karten in Ausführungs-Reihenfolge, Wartende und Fertige zusammengeklappt.
|
// AKTIVEN Karten in Ausführungs-Reihenfolge, Wartende und Fertige zusammengeklappt.
|
||||||
// Ersetzt für Ketten die flache Erstellzeit-Liste (User: „Reihenfolge komplett durcheinander").
|
// Ersetzt für Ketten die flache Erstellzeit-Liste (User: „Reihenfolge komplett durcheinander").
|
||||||
|
|||||||
Reference in New Issue
Block a user