Suche: Benutzer findbar, Klick oeffnet Chat direkt
This commit is contained in:
@@ -222,9 +222,16 @@ router.get('/', authenticate, (req, res) => {
|
||||
ORDER BY created_at DESC LIMIT 5
|
||||
`).all(uid, like, like));
|
||||
|
||||
// Andere Benutzer – für Chat-Navigation (nur Benutzernamen, keine sensiblen Daten)
|
||||
const users = safe(() => db.prepare(`
|
||||
SELECT id, username FROM users
|
||||
WHERE id != ? AND LOWER(username) LIKE ?
|
||||
ORDER BY username LIMIT 5
|
||||
`).all(uid, like));
|
||||
|
||||
res.json({ links, folders, snippets, calculations, orders, todos, notes,
|
||||
board_items, changelog, files, file_folders, push_schedules,
|
||||
calendar_feeds, calendar_events, qr_codes });
|
||||
calendar_feeds, calendar_events, qr_codes, users });
|
||||
});
|
||||
|
||||
// Debug-Endpoint: Kalender-Cache inspizieren
|
||||
|
||||
@@ -1481,6 +1481,7 @@ function SearchResultItem({ item, idx, activeIdx, onNavigate, onHover }) {
|
||||
if (item.type==='calendar_feed') { icon='📅'; primary=item.name; secondary='Kalender-Abo'; }
|
||||
if (item.type==='calendar_event') { icon='📆'; primary=item.summary; secondary=`${item.feed_name||'Kalender'}${item.start_dt?' · '+formatIcalDate(item.start_dt):''}`; }
|
||||
if (item.type==='qr') { icon='◻'; primary=item.label||item.url; secondary=`QR-Code · ${item.url}`; }
|
||||
if (item.type==='user') { icon='💬'; primary=item.username; secondary='Nachricht schreiben → Chat öffnen'; }
|
||||
return (
|
||||
<div onClick={()=>onNavigate(item)} onMouseEnter={()=>onHover(idx)}
|
||||
style={{display:'flex',alignItems:'center',gap:10,padding:'9px 14px',cursor:'pointer',
|
||||
@@ -1642,6 +1643,7 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
|
||||
...(results.calendar_feeds||[]).map(f=>({...f,type:'calendar_feed'})),
|
||||
...(results.calendar_events||[]).map(e=>({...e,type:'calendar_event'})),
|
||||
...(results.qr_codes||[]).map(q=>({...q,type:'qr'})),
|
||||
...(results.users||[]).map(u=>({...u,type:'user'})),
|
||||
] : [];
|
||||
|
||||
const navigate = (item) => {
|
||||
@@ -1661,7 +1663,8 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
|
||||
else if (item.type === 'file' || item.type === 'file_folder') { setActive('dateien'); }
|
||||
else if (item.type === 'push') { setActive('dashboard'); }
|
||||
else if (item.type === 'calendar_feed' || item.type === 'calendar_event') { setActive('dashboard'); }
|
||||
else if (item.type === 'qr') { setActive('devtools'); setDevToolsNav({tool:'qrcode', ts: Date.now()}); }
|
||||
else if (item.type === 'qr') { setActive('devtools'); setDevToolsNav({tool:'qrcode', ts: Date.now()}); }
|
||||
else if (item.type === 'user') { setActive('nachrichten'); setDevToolsNav({userId: item.id, ts: Date.now()}); }
|
||||
};
|
||||
|
||||
const onKey = e => {
|
||||
@@ -1800,6 +1803,12 @@ function GlobalSearch({ setActive, setDevToolsNav, mobile }) {
|
||||
{results.qr_codes.map((item,i)=>(<SearchResultItem key={`qr${i}`} item={{...item,type:'qr'}} idx={0} activeIdx={-1} onNavigate={navigate} onHover={()=>{}}/>))}
|
||||
</div>
|
||||
)}
|
||||
{results.users?.length>0 && (
|
||||
<div>
|
||||
<div style={{padding:'7px 14px 4px',color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:9,letterSpacing:1}}>BENUTZER / CHAT</div>
|
||||
{results.users.map((item,i)=>(<SearchResultItem key={`u${i}`} item={{...item,type:'user'}} idx={0} activeIdx={-1} onNavigate={navigate} onHover={()=>{}}/>))}
|
||||
</div>
|
||||
)}
|
||||
{results.notes?.length>0 && (
|
||||
<div>
|
||||
<div style={{padding:'7px 14px 4px',color:'rgba(255,255,255,0.3)',fontFamily:'monospace',fontSize:9,letterSpacing:1}}>NOTIZEN</div>
|
||||
@@ -2889,7 +2898,7 @@ export default function App() {
|
||||
<main style={mainStyle}>
|
||||
{active==='dashboard' && <Dashboard toast={toast} mobile={mobile} setActive={setActive} setDevToolsNav={setDevToolsNav} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} user={user}/>}
|
||||
{active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user} nav={devToolsNav}/>}
|
||||
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'?{nav:devToolsNav}:{})}/>}
|
||||
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'||activeTool.id==='nachrichten'?{nav:devToolsNav}:{})}/>}
|
||||
</main>
|
||||
</div>
|
||||
{mobile && (
|
||||
|
||||
@@ -70,7 +70,7 @@ function EmojiPicker({ onSelect, onClose }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default function Nachrichten({ toast, mobile }) {
|
||||
export default function Nachrichten({ toast, mobile, nav }) {
|
||||
const [kp, setKp] = useState(null);
|
||||
const [initError, setInitError] = useState(false);
|
||||
const [users, setUsers] = useState([]);
|
||||
@@ -217,7 +217,13 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
|
||||
// ── Handlers ─────────────────────────────────────────────────────────────────
|
||||
const loadUsers = async () => {
|
||||
try { setUsers(await api('/tools/nachrichten/users')); } catch {}
|
||||
try { const u = await api('/tools/nachrichten/users'); setUsers(u);
|
||||
// Nav aus Suche: direkt zu User springen
|
||||
if (nav?.userId) {
|
||||
const target = u.find(x => x.id === nav.userId);
|
||||
if (target) setActiveUser(target);
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
|
||||
const loadMessages = async userId => {
|
||||
|
||||
Reference in New Issue
Block a user