From 2cb4c24e40d7af09690b7c51027a8e67363faadb Mon Sep 17 00:00:00 2001 From: beo3000 Date: Wed, 25 Feb 2026 17:08:54 +0100 Subject: [PATCH] upd commandbar --- docs/feature-commandbar.md | 21 +- .../src/lib/components/CommandBar.svelte | 107 +++++++--- ka-note/client/src/routes/help/+page.svelte | 190 ++++++++++++++++++ ka-note/server/ka-note.db-shm | Bin 32768 -> 32768 bytes ka-note/server/ka-note.db-wal | Bin 267832 -> 317272 bytes 5 files changed, 278 insertions(+), 40 deletions(-) create mode 100644 ka-note/client/src/routes/help/+page.svelte diff --git a/docs/feature-commandbar.md b/docs/feature-commandbar.md index cc86c48..20602b2 100644 --- a/docs/feature-commandbar.md +++ b/docs/feature-commandbar.md @@ -63,16 +63,17 @@ Scope-dynamische Commands verwenden den aktuell aktiven Scope (Privat/Firma). Sc | `/page [Titel]` | Neue Wiki-Seite erstellen (aktiver Scope) | | `/ppage [Titel]` | Neue Wiki-Seite erstellen (Privat) | | `/bpage [Titel]` | Neue Wiki-Seite erstellen (Firma) | -| `/person [Name]` | Neuen Personen-Kontext erstellen (aktiver Scope) | -| `/pperson [Name]` | Neuen Personen-Kontext erstellen (Privat) | -| `/bperson [Name]` | Neuen Personen-Kontext erstellen (Firma) | -| `/firma [Name]` | Neuen Firmen-Kontext erstellen (aktiver Scope) | -| `/pfirma [Name]` | Neuen Firmen-Kontext erstellen (Privat) | -| `/bfirma [Name]` | Neuen Firmen-Kontext erstellen (Firma) | +| `/per [Name]` | Neuen Personen-Kontext erstellen; Name → Title Case, setzt `meta.fullName` | +| `/firma [Name]` | Neuen Firmen-Kontext erstellen | | `/jf [Name]` | Zu passendem Jour-Fix-Kontext springen | +| `/sidebar` | Sidebar ein-/ausblenden | +| `/home` | Zurück zur Journal-Startseite (`/`) | +| `/help` | Hilfeseite öffnen (`/help`) | Scope-spezifische Commands erscheinen in der Bar erst ab dem zweiten Zeichen (`/p...` / `/b...`), um Duplikate mit den scope-dynamischen Commands zu vermeiden. +Wenn kein Text angegeben wird, erscheint ein Browser-`prompt()` zur Eingabe — `Enter` auf einem Befehl ohne Text löst also direkt eine Aktion aus. + Beispiel: `/note Anruf bei Steffen wegen Angebot` → sofort als Topic in `daily-log` gespeichert, ohne den aktuellen Screen zu verlassen. --- @@ -134,12 +135,13 @@ In-Memory: `label.toLowerCase().includes(query)` — reicht für typische Datenm ## Scope -**In Scope:** +**Implementiert:** - Navigation zu Contexts und Wiki-Seiten -- Slash-Commands: `/note`, `/todo`, `/jf` +- Slash-Commands: `/note`, `/pnote`, `/bnote`, `/todo`, `/ptodo`, `/btodo`, `/page`, `/ppage`, `/bpage`, `/per`, `/firma`, `/jf`, `/sidebar`, `/home`, `/help` - Recent-Items (sessionStorage) -- Tastatursteuerung +- Tastatursteuerung inkl. Enter ohne Text (Browser-Prompt) - Responsive (Modal auf Mobile funktioniert) +- `/per` setzt automatisch Title Case und `meta.fullName` **Out of Scope (v1):** - Fuzzy-Suche / Treffergewichtung @@ -147,6 +149,7 @@ In-Memory: `label.toLowerCase().includes(query)` — reicht für typische Datenm - Server-seitige Volltextsuche - Persistente "Favourites" in der Bar - Konfigurierbarer Shortcut +- Scope-Varianten für `/per` und `/firma` (`/pper`, `/bper`, ...) --- diff --git a/ka-note/client/src/lib/components/CommandBar.svelte b/ka-note/client/src/lib/components/CommandBar.svelte index cfa75e3..98b751d 100644 --- a/ka-note/client/src/lib/components/CommandBar.svelte +++ b/ka-note/client/src/lib/components/CommandBar.svelte @@ -92,6 +92,11 @@ } } + function promptIfEmpty(current: string, label: string): string { + if (current) return current; + return window.prompt(`${label}:`) ?? ""; + } + const results = $derived.by(() => { const q = query.trim().toLowerCase(); @@ -114,9 +119,10 @@ : `Neu: Notiz (${$currentScope === "private" ? "Privat" : "Firma"})`, badge: "BEFEHL", action: async () => { - if (!text) return; + const t = promptIfEmpty(text, "Titel der Notiz"); + if (!t) return; const isPrivateScope = $currentScope === "private"; - await executeNoteCommand(text, isPrivateScope); + await executeNoteCommand(t, isPrivateScope); }, }); } @@ -131,8 +137,9 @@ : "Neu: Notiz (Privat)", badge: "BEFEHL", action: async () => { - if (!text) return; - await executeNoteCommand(text, true); + const t = promptIfEmpty(text, "Titel der Notiz"); + if (!t) return; + await executeNoteCommand(t, true); }, }); } @@ -147,8 +154,9 @@ : "Neu: Notiz (Firma)", badge: "BEFEHL", action: async () => { - if (!text) return; - await executeNoteCommand(text, false); + const t = promptIfEmpty(text, "Titel der Notiz"); + if (!t) return; + await executeNoteCommand(t, false); }, }); } @@ -164,9 +172,10 @@ : `Neu: Todo (${$currentScope === "private" ? "Privat" : "Firma"})`, badge: "BEFEHL", action: async () => { - if (!text) return; + const t = promptIfEmpty(text, "Titel des Todos"); + if (!t) return; const isPrivateScope = $currentScope === "private"; - await executeTodoCommand(text, isPrivateScope); + await executeTodoCommand(t, isPrivateScope); }, }); } @@ -181,8 +190,9 @@ : "Neu: Todo (Privat)", badge: "BEFEHL", action: async () => { - if (!text) return; - await executeTodoCommand(text, true); + const t = promptIfEmpty(text, "Titel des Todos"); + if (!t) return; + await executeTodoCommand(t, true); }, }); } @@ -197,8 +207,9 @@ : "Neu: Todo (Firma)", badge: "BEFEHL", action: async () => { - if (!text) return; - await executeTodoCommand(text, false); + const t = promptIfEmpty(text, "Titel des Todos"); + if (!t) return; + await executeTodoCommand(t, false); }, }); } @@ -213,13 +224,14 @@ : `Neu: Wiki-Seite (${$currentScope === "private" ? "Privat" : "Firma"})`, badge: "BEFEHL", action: async () => { - if (!text) return; - if (await pageNameExists(text)) { - alert(`Wiki-Seite "${text}" existiert bereits.`); + const t = promptIfEmpty(text, "Titel der Wiki-Seite"); + if (!t) return; + if (await pageNameExists(t)) { + alert(`Wiki-Seite "${t}" existiert bereits.`); return; } const isPrivateScope = $currentScope === "private"; - const page = await createPage(text, isPrivateScope); + const page = await createPage(t, isPrivateScope); closeBar(); goto(`/wiki/${page.id}`); }, @@ -236,12 +248,13 @@ : `Neu: Wiki-Seite (Privat)`, badge: "BEFEHL", action: async () => { - if (!text) return; - if (await pageNameExists(text)) { - alert(`Wiki-Seite "${text}" existiert bereits.`); + const t = promptIfEmpty(text, "Titel der Wiki-Seite"); + if (!t) return; + if (await pageNameExists(t)) { + alert(`Wiki-Seite "${t}" existiert bereits.`); return; } - const page = await createPage(text, true); + const page = await createPage(t, true); closeBar(); goto(`/wiki/${page.id}`); }, @@ -258,12 +271,13 @@ : `Neu: Wiki-Seite (Firma)`, badge: "BEFEHL", action: async () => { - if (!text) return; - if (await pageNameExists(text)) { - alert(`Wiki-Seite "${text}" existiert bereits.`); + const t = promptIfEmpty(text, "Titel der Wiki-Seite"); + if (!t) return; + if (await pageNameExists(t)) { + alert(`Wiki-Seite "${t}" existiert bereits.`); return; } - const page = await createPage(text, false); + const page = await createPage(t, false); closeBar(); goto(`/wiki/${page.id}`); }, @@ -278,14 +292,16 @@ label: text ? `Person: "${text}"` : `Neu: Person`, badge: "BEFEHL", action: async () => { - if (!text) return; - const fullName = `Person ${text}`; + const raw = promptIfEmpty(text, "Name der Person"); + if (!raw) return; + const displayName = raw.replace(/\b\w/g, (c) => c.toUpperCase()); + const fullName = `Person ${displayName}`; if (await contextNameExists(fullName, "person")) { - alert(`Person "${text}" existiert bereits.`); + alert(`Person "${displayName}" existiert bereits.`); return; } const id = newId(); - await upsertContext({ id, name: fullName, type: "person" }); + await upsertContext({ id, name: fullName, type: "person", meta: { fullName: displayName, email: "", phone: "", duSince: "", personSubType: "colleague" } }); closeBar(); goto(`/context/${id}`); }, @@ -300,10 +316,11 @@ label: text ? `Firma: "${text}"` : `Neu: Firma`, badge: "BEFEHL", action: async () => { - if (!text) return; - const fullName = `Firma ${text}`; + const t = promptIfEmpty(text, "Name der Firma"); + if (!t) return; + const fullName = `Firma ${t}`; if (await contextNameExists(fullName, "company")) { - alert(`Firma "${text}" existiert bereits.`); + alert(`Firma "${t}" existiert bereits.`); return; } const id = newId(); @@ -327,6 +344,34 @@ }); } + if ("/home".startsWith(cmd)) { + actions.push({ + id: "cmd-home", + type: "action", + icon: "🏠", + label: "Journal (Startseite)", + badge: "BEFEHL", + action: () => { + closeBar(); + goto("/"); + }, + }); + } + + if ("/help".startsWith(cmd)) { + actions.push({ + id: "cmd-help", + type: "action", + icon: "❓", + label: "Hilfe & Befehle anzeigen", + badge: "BEFEHL", + action: () => { + closeBar(); + goto("/help"); + }, + }); + } + if ("/jf".startsWith(cmd)) { actions.push({ id: "cmd-jf", diff --git a/ka-note/client/src/routes/help/+page.svelte b/ka-note/client/src/routes/help/+page.svelte new file mode 100644 index 0000000..581d9b6 --- /dev/null +++ b/ka-note/client/src/routes/help/+page.svelte @@ -0,0 +1,190 @@ + + +
+
+

Hilfe & Befehle

+ +
+ + +
+

Command Bar

+

+ Öffnen mit Ctrl+K. + Tippe einen Befehl mit / oder suche direkt nach Kontexten und Wiki-Seiten. +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BefehlBeschreibung
Neuanlage
/note [Titel]Neue Notiz (aktueller Scope)
/pnote [Titel]Neue Notiz (Privat)
/bnote [Titel]Neue Notiz (Firma)
/todo [Titel]Neues Todo (aktueller Scope)
/ptodo [Titel]Neues Todo (Privat)
/btodo [Titel]Neues Todo (Firma)
/page [Titel]Neue Wiki-Seite (aktueller Scope)
/ppage [Titel]Neue Wiki-Seite (Privat)
/bpage [Titel]Neue Wiki-Seite (Firma)
/per [Name]Neue Person anlegen
/firma [Name]Neue Firma anlegen
Navigation
/jf [Suche]Zu einem Jour-Fix-Meeting springen
/homeZurück zur Journal-Startseite
/helpDiese Hilfeseite öffnen
UI
/sidebarSidebar ein-/ausblenden
Suche (ohne /)
[Suchbegriff]Kontexte und Wiki-Seiten durchsuchen
(leer)Zuletzt besuchte Kontexte anzeigen
+
+
+ + +
+

Tastenkürzel

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KürzelFunktion
Ctrl+KCommand Bar öffnen/schließen
Ctrl+BSidebar ein-/ausblenden
↑ ↓In Command Bar navigieren
EnterAusgewählten Befehl ausführen
EscCommand Bar schließen
+
+
+ + +
+

Inline-Tags im Text

+
+ + + + + + + + + + + + + + + + + + + + + +
SyntaxBedeutung
-> NAMEZuweisung an Person
@P:PROJEKTProjektreferenz
@NAMEErwähnung einer Person
+
+
+
diff --git a/ka-note/server/ka-note.db-shm b/ka-note/server/ka-note.db-shm index 929a951e9e0e26880749b9747acd1927a72a2577..ca173d7dd2b7fb9b9df787c76fbc19cb26905795 100644 GIT binary patch delta 213 zcmZo@U}|V!s+V}A%K!q*K+MR%AP@+oCjs&0Ph29ef2>}Yr|!F{JwsS-rGPrW)aNbE zq^buR1qL8<|04mYFcX98#ztwz$uW!uo98fcIBdS+$iv3!$>7TnxOpL?DC6c|9(>HK sZVX-wen9?9rpe#@1X$e}yczs~+{av--$nkDX7yn3VF=j#v6P<+0DP!HbpQYW delta 194 zcmZo@U}|V!s+V}A%K!q55G>#dq$dG!azvM6{HZF&Jaykq?HR&y&)0mZ(KvQNkW}?R zqrd=U?tdfz6=q^^+}J41xcLkthr{Ftj0T&pIP$PFEi4vdlN%fa_*d)y-FBfiyN!#1fkBA(`{e%((p-Gme13d} zd?LKxHzuCuoqT|gSHLvH(A3J*$jZb*&(y#uN@)7Q#mvIn#h)<0WaQ6V73jXLVwyGB z2!8R&{SQ^QJ3eFn&Nq4WhX>PNn=te8GgY5Wblszp#>=^#L5Ow1Wc`IeTaK`uWXopb zV_mQ@v4pigM~F96)?AWJbL{& z_AVs6+fc*1ZDV2-YkeatQh?hs(kQ^;K0u2IQ%;!In6~TvVP@izdp(KgMV_Ui6wN|@ zMTTma;#Z!0kOjiLw?HYK2a(cwZ*5Fm15WF@kfdT^WniRdVqqL5EW>Qei0*ut>rpa- zW{e3R^G&97unqiNz>J{2xl!N_-{b{vd8R*8V0;V73|wNFGIJj6Py|JeFv}iLQr1u2{2OhT|YfTkdY_3x&hTN}LRJS2jf7FEi4vd07F^^CIA2c