feat: pages is_favorite, commandbar improvements, wiki ui
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d1286cd717
commit
8bffebfd36
|
|
@ -50,12 +50,29 @@ Beim Tippen werden **Contexts** (Jour Fixes, Projekte, Firmen, Personen) und **W
|
|||
|
||||
## Slash-Commands
|
||||
|
||||
Scope-dynamische Commands verwenden den aktuell aktiven Scope (Privat/Firma). Scope-explizite Varianten mit Präfix `p` (Privat) oder `b` (Business/Firma) überschreiben den aktiven Scope.
|
||||
|
||||
| Command | Funktion |
|
||||
|---------|----------|
|
||||
| `/note [Text]` | Neues Topic im Daily Log erstellen |
|
||||
| `/todo [Text]` | Topic mit Wiedervorlage (heute) im Daily Log |
|
||||
| `/note [Text]` | Neues Topic im Daily Log (aktiver Scope) |
|
||||
| `/pnote [Text]` | Neues Topic im Daily Log (Privat) |
|
||||
| `/bnote [Text]` | Neues Topic im Daily Log (Firma) |
|
||||
| `/todo [Text]` | Topic mit Wiedervorlage heute (aktiver Scope) |
|
||||
| `/ptodo [Text]` | Topic mit Wiedervorlage heute (Privat) |
|
||||
| `/btodo [Text]` | Topic mit Wiedervorlage heute (Firma) |
|
||||
| `/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) |
|
||||
| `/jf [Name]` | Zu passendem Jour-Fix-Kontext springen |
|
||||
|
||||
Scope-spezifische Commands erscheinen in der Bar erst ab dem zweiten Zeichen (`/p...` / `/b...`), um Duplikate mit den scope-dynamischen Commands zu vermeiden.
|
||||
|
||||
Beispiel: `/note Anruf bei Steffen wegen Angebot` → sofort als Topic in `daily-log` gespeichert, ohne den aktuellen Screen zu verlassen.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1.1.68
|
||||
1.1.71
|
||||
|
|
@ -100,7 +100,8 @@
|
|||
|
||||
const actions = [];
|
||||
|
||||
if ("/note".startsWith(cmd)) {
|
||||
// Show scope-dynamic /note only when not narrowed to /pnote or /bnote
|
||||
if ("/note".startsWith(cmd) && !"/pnote".startsWith(cmd) && !"/bnote".startsWith(cmd)) {
|
||||
actions.push({
|
||||
id: "cmd-note",
|
||||
type: "action",
|
||||
|
|
@ -117,7 +118,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/pnote".startsWith(cmd)) {
|
||||
if ("/pnote".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-pnote",
|
||||
type: "action",
|
||||
|
|
@ -133,7 +134,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/bnote".startsWith(cmd)) {
|
||||
if ("/bnote".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-bnote",
|
||||
type: "action",
|
||||
|
|
@ -149,7 +150,8 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/todo".startsWith(cmd)) {
|
||||
// Show scope-dynamic /todo only when not narrowed to /ptodo or /btodo
|
||||
if ("/todo".startsWith(cmd) && !"/ptodo".startsWith(cmd) && !"/btodo".startsWith(cmd)) {
|
||||
actions.push({
|
||||
id: "cmd-todo",
|
||||
type: "action",
|
||||
|
|
@ -166,7 +168,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/ptodo".startsWith(cmd)) {
|
||||
if ("/ptodo".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-ptodo",
|
||||
type: "action",
|
||||
|
|
@ -182,7 +184,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/btodo".startsWith(cmd)) {
|
||||
if ("/btodo".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-btodo",
|
||||
type: "action",
|
||||
|
|
@ -198,7 +200,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/page".startsWith(cmd)) {
|
||||
if ("/page".startsWith(cmd) && !"/ppage".startsWith(cmd) && !"/bpage".startsWith(cmd)) {
|
||||
actions.push({
|
||||
id: "cmd-page",
|
||||
type: "action",
|
||||
|
|
@ -217,7 +219,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/ppage".startsWith(cmd)) {
|
||||
if ("/ppage".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-ppage",
|
||||
type: "action",
|
||||
|
|
@ -235,7 +237,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
if ("/bpage".startsWith(cmd)) {
|
||||
if ("/bpage".startsWith(cmd) && cmd.length > 1) {
|
||||
actions.push({
|
||||
id: "cmd-bpage",
|
||||
type: "action",
|
||||
|
|
|
|||
|
|
@ -96,9 +96,9 @@
|
|||
|
||||
<section class="rounded-lg border border-[#333] bg-[#1a1a1a]">
|
||||
<!-- Tab bar -->
|
||||
<div class="flex border-b border-[#333]">
|
||||
<div class="flex overflow-x-auto border-b border-[#333] scrollbar-none">
|
||||
<button
|
||||
class="flex items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'notebooks' ? 'border-accent text-accent' : 'border-transparent text-muted hover:text-white'}"
|
||||
class="flex shrink-0 items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'notebooks' ? 'border-accent text-accent' : 'border-transparent text-muted hover:text-white'}"
|
||||
onclick={() => setTab('notebooks')}
|
||||
>
|
||||
<span>📓</span>
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
{/if}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'favorites' ? 'border-warning text-warning' : 'border-transparent text-muted hover:text-white'}"
|
||||
class="flex shrink-0 items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'favorites' ? 'border-warning text-warning' : 'border-transparent text-muted hover:text-white'}"
|
||||
onclick={() => setTab('favorites')}
|
||||
>
|
||||
<span>★</span>
|
||||
|
|
@ -118,27 +118,28 @@
|
|||
{/if}
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'recent' ? 'border-[#aaa] text-[#ccc]' : 'border-transparent text-muted hover:text-white'}"
|
||||
class="flex shrink-0 items-center gap-1.5 px-4 py-2.5 text-sm font-semibold transition-colors border-b-2 -mb-px {activeTab === 'recent' ? 'border-[#aaa] text-[#ccc]' : 'border-transparent text-muted hover:text-white'}"
|
||||
onclick={() => setTab('recent')}
|
||||
>
|
||||
<span>✎</span>
|
||||
<span>Zuletzt bearbeitet</span>
|
||||
</button>
|
||||
<!-- Actions (right side) -->
|
||||
{#if activeTab === 'notebooks'}
|
||||
<div class="ml-auto flex items-center gap-2 px-3">
|
||||
<button
|
||||
class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80"
|
||||
onclick={addPage}
|
||||
>+ Seite</button>
|
||||
<button
|
||||
class="rounded bg-white/10 px-3 py-1.5 text-sm font-medium text-muted hover:bg-white/20 hover:text-white"
|
||||
onclick={() => creatingNotebook = true}
|
||||
>+ Notizbuch</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Actions bar (Notebooks tab only) -->
|
||||
{#if activeTab === 'notebooks'}
|
||||
<div class="flex items-center gap-2 border-b border-[#2a2a2a] px-3 py-2">
|
||||
<button
|
||||
class="rounded bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/80"
|
||||
onclick={addPage}
|
||||
>+ Seite</button>
|
||||
<button
|
||||
class="rounded bg-white/10 px-3 py-1.5 text-sm font-medium text-muted hover:bg-white/20 hover:text-white"
|
||||
onclick={() => creatingNotebook = true}
|
||||
>+ Notizbuch</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Notebooks tab -->
|
||||
{#if activeTab === 'notebooks'}
|
||||
<div class="divide-y divide-[#2a2a2a]">
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
-- no-op: is_favorite column added in 0012_chunky_stature.sql
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `pages` ADD `is_favorite` integer DEFAULT false NOT NULL;
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -78,6 +78,20 @@
|
|||
"when": 1771857652883,
|
||||
"tag": "0010_sharp_bishop",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"version": "6",
|
||||
"when": 1771900000000,
|
||||
"tag": "0011_pages_is_favorite",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"version": "6",
|
||||
"when": 1772004047537,
|
||||
"tag": "0012_chunky_stature",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -85,6 +85,7 @@ export const pages = sqliteTable('pages', {
|
|||
title: text('title').notNull(),
|
||||
body: text('body').notNull().default(''),
|
||||
isPrivate: integer('is_private', { mode: 'boolean' }).notNull().default(false),
|
||||
isFavorite: integer('is_favorite', { mode: 'boolean' }).notNull().default(false),
|
||||
sortOrder: integer('sort_order').notNull().default(0),
|
||||
updatedAt: text('updated_at').notNull(),
|
||||
deletedAt: text('deleted_at'),
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ function mapPage(row: typeof pages.$inferSelect): Page {
|
|||
title: row.title,
|
||||
body: row.body,
|
||||
isPrivate: row.isPrivate,
|
||||
isFavorite: row.isFavorite,
|
||||
sortOrder: row.sortOrder,
|
||||
updatedAt: row.updatedAt,
|
||||
deletedAt: row.deletedAt,
|
||||
|
|
@ -276,7 +277,7 @@ export async function pushChanges(request: SyncPushRequest, userId: string): Pro
|
|||
}
|
||||
|
||||
for (const pg of pgs) {
|
||||
const row = { id: pg.id, userId, title: pg.title, body: pg.body, isPrivate: pg.isPrivate, sortOrder: pg.sortOrder, updatedAt: pg.updatedAt, deletedAt: pg.deletedAt, purgedAt: pg.purgedAt ?? null, version: pg.version };
|
||||
const row = { id: pg.id, userId, title: pg.title, body: pg.body, isPrivate: pg.isPrivate, isFavorite: pg.isFavorite ?? false, sortOrder: pg.sortOrder, updatedAt: pg.updatedAt, deletedAt: pg.deletedAt, purgedAt: pg.purgedAt ?? null, version: pg.version };
|
||||
if (await upsertEntity(pages, row, conflicts, 'page', userId)) accepted++;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue