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 929a951..ca173d7 100644 Binary files a/ka-note/server/ka-note.db-shm and b/ka-note/server/ka-note.db-shm differ diff --git a/ka-note/server/ka-note.db-wal b/ka-note/server/ka-note.db-wal index 3d638a1..283b297 100644 Binary files a/ka-note/server/ka-note.db-wal and b/ka-note/server/ka-note.db-wal differ