diff --git a/backend/src/routes/search.js b/backend/src/routes/search.js index f9e0473..6fb6e80 100644 --- a/backend/src/routes/search.js +++ b/backend/src/routes/search.js @@ -15,6 +15,15 @@ router.get('/', authenticate, (req, res) => { ORDER BY title LIMIT 8 `).all(uid, like, like, like); + let folders = []; + try { + folders = db.prepare(` + SELECT id, name, icon FROM link_list_folders + WHERE user_id=? AND LOWER(name) LIKE ? + ORDER BY name LIMIT 5 + `).all(uid, like); + } catch {} + let snippets = []; try { snippets = db.prepare(` @@ -42,7 +51,7 @@ router.get('/', authenticate, (req, res) => { `).all(uid, like); } catch {} - res.json({ links, snippets, calculations, orders }); + res.json({ links, folders, snippets, calculations, orders }); }); module.exports = router; diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 8c51d28..38cc3fe 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1433,9 +1433,11 @@ function ChangelogModal({ user, toast, onClose, onRead }) { function SearchResultItem({ item, idx, activeIdx, onNavigate, onHover }) { const isActive = idx === activeIdx; let icon = '❓', primary = '', secondary = ''; - if (item.type==='tool') { icon=item.icon||'πŸ› '; primary=item.label; secondary=item.sub||'Navigation'; } - if (item.type==='devtool') { icon=item.icon||'πŸ”§'; primary=item.label; secondary='Dev-Tools'; } - if (item.type==='link') { + if (item.type==='tool') { icon=item.icon||'πŸ› '; primary=item.label; secondary=item.sub||'Navigation'; } + if (item.type==='devtool') { icon=item.icon||'πŸ”§'; primary=item.label; secondary=item.sub||'Dev-Tools'; } + if (item.type==='settings') { icon=item.icon||'βš™οΈ'; primary=item.label; secondary=item.sub||'Einstellungen'; } + if (item.type==='folder') { icon=item.icon||'πŸ“'; primary=item.name; secondary='Linkliste – Ordner'; } + if (item.type==='link') { const hasCustom = item.icon && item.icon !== 'πŸ”—'; icon = hasCustom ? item.icon : 'πŸ”—'; primary = item.title; secondary = item.url; @@ -1456,15 +1458,15 @@ function SearchResultItem({ item, idx, activeIdx, onNavigate, onHover }) { overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{secondary} {item.type==='link' && β†—} - {(item.type==='tool'||item.type==='devtool') && β†’} + {(item.type==='tool'||item.type==='devtool'||item.type==='settings'||item.type==='folder'||item.type==='snippet'||item.type==='calc'||item.type==='order') && β†’} ); } // ── Globale Suche ───────────────────────────────────────────────────────────── -// Statischer Such-Index fΓΌr Tools & Dev-Tools Sub-Tools +// Statischer Such-Index – Tools, Dev-Tools Inhalte, Einstellungen const SEARCH_TOOL_INDEX = [ - // Haupt-Tools + // ── Haupt-Tools ── {type:'tool',label:'Dashboard',icon:'🏠',sub:'',id:'dashboard'}, {type:'tool',label:'Bestellungen',icon:'πŸ“¦',sub:'3D-Druck',id:'bestellungen'}, {type:'tool',label:'Kalkulator3D',icon:'πŸ–¨',sub:'3D-Druck',id:'kalkulator3d'}, @@ -1474,18 +1476,54 @@ const SEARCH_TOOL_INDEX = [ {type:'tool',label:'Code-Schnipsel',icon:'πŸ“„',sub:'Werkzeuge',id:'codeschnipsel'}, {type:'tool',label:'CAD-Skizzen',icon:'πŸ“',sub:'Werkzeuge',id:'skizze'}, {type:'tool',label:'Dev-Tools',icon:'πŸ”§',sub:'Werkzeuge',id:'devtools'}, - {type:'tool',label:'Einstellungen',icon:'βš™οΈ',sub:'',id:'admin'}, - // Dev-Tools Sub-Tools + // ── Einstellungen-Sektionen ── + {type:'settings',label:'Einstellungen – Profil',icon:'πŸ‘€',sub:'Einstellungen',section:'profil'}, + {type:'settings',label:'Einstellungen – Sicherheit',icon:'πŸ”’',sub:'Einstellungen',section:'sicherheit'}, + {type:'settings',label:'Einstellungen – Dashboard',icon:'🏠',sub:'Einstellungen',section:'dashboard'}, + {type:'settings',label:'Einstellungen – Benutzer',icon:'πŸ‘₯',sub:'Einstellungen (Admin)',section:'benutzer'}, + {type:'settings',label:'Einstellungen – Backup',icon:'πŸ’Ύ',sub:'Einstellungen (Admin)',section:'backup'}, + // ── Dev-Tools Sub-Tools ── {type:'devtool',label:'Crontab',icon:'⏱',sub:'Dev-Tools',tool:'cron'}, {type:'devtool',label:'Elektro-Rechner',icon:'⚑',sub:'Dev-Tools',tool:'elektro'}, - {type:'devtool',label:'JSON Viewer',icon:'{}',sub:'Dev-Tools',tool:'json'}, + {type:'devtool',label:'Ohmsches Gesetz',icon:'⚑',sub:'Elektro-Rechner',tool:'elektro'}, + {type:'devtool',label:'JSON Viewer & Builder',icon:'{}',sub:'Dev-Tools',tool:'json'}, {type:'devtool',label:'Regex Builder',icon:'πŸ”',sub:'Dev-Tools',tool:'regex'}, {type:'devtool',label:'Text Diff',icon:'Β±',sub:'Dev-Tools',tool:'diff'}, - {type:'devtool',label:'Netzwerk',icon:'🌐',sub:'Dev-Tools',tool:'netzwerk'}, - {type:'devtool',label:'Datetime',icon:'πŸ“…',sub:'Dev-Tools',tool:'datetime'}, - {type:'devtool',label:'Farben',icon:'🎨',sub:'Dev-Tools',tool:'farben'}, - {type:'devtool',label:'Key-Generator',icon:'πŸ”',sub:'Dev-Tools',tool:'keygen'}, + {type:'devtool',label:'Netzwerk-Rechner',icon:'🌐',sub:'Dev-Tools',tool:'netzwerk'}, + {type:'devtool',label:'IP / Subnetz',icon:'🌐',sub:'Netzwerk',tool:'netzwerk'}, + {type:'devtool',label:'Geschwindigkeit MB/s Mbit',icon:'🌐',sub:'Netzwerk',tool:'netzwerk'}, + {type:'devtool',label:'CIDR Tabelle',icon:'🌐',sub:'Netzwerk',tool:'netzwerk'}, + {type:'devtool',label:'Datetime – Uhrzeitrechner',icon:'πŸ“…',sub:'Dev-Tools',tool:'datetime'}, + {type:'devtool',label:'Unix Timestamp',icon:'πŸ“…',sub:'Datetime',tool:'datetime'}, + {type:'devtool',label:'Moseszeit Umrechner',icon:'πŸ“…',sub:'Datetime',tool:'datetime'}, + {type:'devtool',label:'Geburtstagsrechner',icon:'πŸ“…',sub:'Datetime',tool:'datetime'}, + {type:'devtool',label:'Zeitdifferenz',icon:'πŸ“…',sub:'Datetime',tool:'datetime'}, + {type:'devtool',label:'Farb-Rechner',icon:'🎨',sub:'Dev-Tools',tool:'farben'}, + {type:'devtool',label:'HEX RGB HSL Farben',icon:'🎨',sub:'Farben',tool:'farben'}, + {type:'devtool',label:'CMYK Farbkonverter',icon:'🎨',sub:'Farben',tool:'farben'}, {type:'devtool',label:'QR-Code Generator',icon:'β—»',sub:'Dev-Tools',tool:'qrcode'}, + // ── Key-Gen EintrΓ€ge (direkt durchsuchbar) ── + {type:'devtool',label:'Key-Generator',icon:'πŸ”',sub:'Dev-Tools',tool:'keygen'}, + {type:'devtool',label:'Laravel APP_KEY',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'JWT Secret HS256',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'JWT Secret HS512',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'AES-256 Key',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'AES-128 Key',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Generic Secret',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Passwort Generator',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'UUID v4',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'NanoID Generator',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'DB-Passwort Docker',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Hex Token Generator',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Base64 Token',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Base64url Token',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'NEXTAUTH_SECRET',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'Webhook Secret',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'OAuth Secret',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'VAPID Key',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'docker-compose Passwort',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'MYSQL_ROOT_PASSWORD',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, + {type:'devtool',label:'POSTGRES_PASSWORD',icon:'πŸ”',sub:'Key-Gen',tool:'keygen'}, ]; function GlobalSearch({ setActive, setDevToolsNav, mobile }) { @@ -1528,6 +1566,7 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) { const allItems = results ? [ ...results.static, ...(results.links||[]).map(l=>({...l,type:'link'})), + ...(results.folders||[]).map(f=>({...f,type:'folder'})), ...(results.snippets||[]).map(s=>({...s,type:'snippet'})), ...(results.calculations||[]).map(c=>({...c,type:'calc'})), ...(results.orders||[]).map(o=>({...o,type:'order'})), @@ -1535,12 +1574,14 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) { const navigate = (item) => { close(); - if (item.type === 'tool') { setActive(item.id); } - else if (item.type === 'devtool') { setActive('devtools'); setDevToolsNav({tool: item.tool, ts: Date.now()}); } - else if (item.type === 'link') { window.open(item.url, '_blank', 'noopener'); } - else if (item.type === 'snippet') { setActive('codeschnipsel'); } - else if (item.type === 'calc') { setActive('kalkulator3d'); } - else if (item.type === 'order') { setActive('bestellungen'); } + if (item.type === 'tool') { setActive(item.id); } + else if (item.type === 'devtool') { setActive('devtools'); setDevToolsNav({tool: item.tool, ts: Date.now()}); } + else if (item.type === 'settings') { setActive('admin'); setDevToolsNav({section: item.section, ts: Date.now()}); } + else if (item.type === 'link') { window.open(item.url, '_blank', 'noopener'); } + else if (item.type === 'folder') { setActive('linkliste'); } + else if (item.type === 'snippet') { setActive('codeschnipsel'); } + else if (item.type === 'calc') { setActive('kalkulator3d'); } + else if (item.type === 'order') { setActive('bestellungen'); } }; const onKey = e => { @@ -1604,6 +1645,15 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) { {results.links.map((item,i)=>)} )} + {results.folders?.length>0 && ( +
+
LINK-ORDNER
+ {results.folders.map((item,i)=>{ + const off=results.static.length+(results.links||[]).length+(results.folders||[]).length; + return ; + })} +
+ )} {results.snippets?.length>0 && (
CODE-SCHNIPSEL
@@ -1617,7 +1667,7 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
3D-ARCHIV
{results.calculations.map((item,i)=>{ - const off=results.static.length+(results.links||[]).length+(results.snippets||[]).length; + const off=results.static.length+(results.links||[]).length+(results.folders||[]).length+(results.snippets||[]).length; return ; })}
@@ -1626,7 +1676,7 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
BESTELLUNGEN
{results.orders.map((item,i)=>{ - const off=results.static.length+(results.links||[]).length+(results.snippets||[]).length+(results.calculations||[]).length; + const off=results.static.length+(results.links||[]).length+(results.folders||[]).length+(results.snippets||[]).length+(results.calculations||[]).length; return ; })}
@@ -2380,8 +2430,9 @@ const Field = ({ label, type='text', value, onChange, placeholder='', autoCapita
); -function AdminPanel({ toast, mobile, user }) { +function AdminPanel({ toast, mobile, user, nav }) { const [section, setSection] = useState('profil'); + useEffect(() => { if (nav?.section) setSection(nav.section); }, [nav?.ts]); const [pw, setPw] = useState({ current:'', newPw:'', confirm:'' }); const [avatar, setAvatar] = useState(localStorage.getItem('dd_avatar') || null); const [un, setUn] = useState({ newUsername:'', unPw:'' }); @@ -2682,7 +2733,7 @@ export default function App() { )}
{active==='dashboard' && { setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} user={user}/>} - {active==='admin' && } + {active==='admin' && } {activeTool && }