feat(rdocs): auto-scaffold "New Documents" notebook with blank note on first use
- Real spaces: if no notebooks exist after loadNotebooks(), auto-creates a "New Documents" notebook via API with a blank "Untitled" note inside it, expanded and opened for editing - Demo mode: prepends "New Documents" notebook with blank starter note as the first item; auto-opens it on both fresh load and localStorage restore so rDocs always starts with a ready-to-edit blank document Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
10e70ba132
commit
dc30b8f2e6
|
|
@ -354,6 +354,8 @@ class FolkDocsApp extends HTMLElement {
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.render();
|
this.render();
|
||||||
|
// Auto-open first note of first notebook
|
||||||
|
this.autoOpenFirstNote();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -494,7 +496,20 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Starter notebook with a blank note (always first)
|
||||||
|
const starterNote: Note = {
|
||||||
|
id: "demo-note-starter", title: "Untitled", content: "", content_plain: "",
|
||||||
|
content_format: 'tiptap-json',
|
||||||
|
type: "NOTE", tags: null, is_pinned: false, sort_order: 0,
|
||||||
|
created_at: new Date(now).toISOString(), updated_at: new Date(now).toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
this.demoNotebooks = [
|
this.demoNotebooks = [
|
||||||
|
{
|
||||||
|
id: "demo-nb-new", title: "New Documents", description: "",
|
||||||
|
cover_color: "#3b82f6", note_count: "1", updated_at: new Date(now).toISOString(),
|
||||||
|
notes: [starterNote],
|
||||||
|
} as any,
|
||||||
{
|
{
|
||||||
id: "demo-nb-1", title: "Alpine Explorer Planning", description: "Shared knowledge base for our July 2026 trip across France, Switzerland, and Italy",
|
id: "demo-nb-1", title: "Alpine Explorer Planning", description: "Shared knowledge base for our July 2026 trip across France, Switzerland, and Italy",
|
||||||
cover_color: "#f59e0b", note_count: "8", updated_at: new Date(now - hour).toISOString(),
|
cover_color: "#f59e0b", note_count: "8", updated_at: new Date(now - hour).toISOString(),
|
||||||
|
|
@ -522,9 +537,28 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
// Auto-open the blank starter note
|
||||||
|
this.selectedNotebook = { ...this.demoNotebooks[0] };
|
||||||
|
this.selectedNote = starterNote;
|
||||||
|
this.renderNav();
|
||||||
|
this.renderMeta();
|
||||||
|
this.mountEditor(starterNote);
|
||||||
|
|
||||||
this.saveDemoState(); // persist initial state
|
this.saveDemoState(); // persist initial state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Open the first note of the first notebook (used on demo restore and fresh load). */
|
||||||
|
private autoOpenFirstNote() {
|
||||||
|
const firstNb = this.demoNotebooks[0];
|
||||||
|
if (!firstNb?.notes?.length) return;
|
||||||
|
this.selectedNotebook = { ...firstNb };
|
||||||
|
this.selectedNote = firstNb.notes[0];
|
||||||
|
this.renderNav();
|
||||||
|
this.renderMeta();
|
||||||
|
this.mountEditor(firstNb.notes[0]);
|
||||||
|
}
|
||||||
|
|
||||||
private demoSearchNotes(query: string) {
|
private demoSearchNotes(query: string) {
|
||||||
if (!query.trim()) {
|
if (!query.trim()) {
|
||||||
this.searchResults = [];
|
this.searchResults = [];
|
||||||
|
|
@ -1228,6 +1262,40 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
// Auto-scaffold a starter notebook with a blank note on first use
|
||||||
|
if (this.notebooks.length === 0 && !this.error) {
|
||||||
|
await this.scaffoldStarterNotebook();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a "New Documents" notebook with one blank note for first-time users. */
|
||||||
|
private async scaffoldStarterNotebook() {
|
||||||
|
try {
|
||||||
|
const base = this.getApiBase();
|
||||||
|
const res = await fetch(`${base}/api/notebooks`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.authHeaders({ "Content-Type": "application/json" }),
|
||||||
|
body: JSON.stringify({ title: "New Documents", cover_color: "#3b82f6" }),
|
||||||
|
});
|
||||||
|
const nb = await res.json();
|
||||||
|
if (!nb?.id) return;
|
||||||
|
|
||||||
|
// Refresh notebook list so the new notebook appears
|
||||||
|
const listRes = await fetch(`${base}/api/notebooks`, { headers: this.authHeaders() });
|
||||||
|
const listData = await listRes.json();
|
||||||
|
this.notebooks = listData.notebooks || [];
|
||||||
|
this.render();
|
||||||
|
|
||||||
|
// Subscribe and create a blank note inside it
|
||||||
|
this.selectedNotebook = { ...nb, notes: [] };
|
||||||
|
this.expandedNotebooks.add(nb.id);
|
||||||
|
this.notebookNotes.set(nb.id, []);
|
||||||
|
await this.loadNotebook(nb.id);
|
||||||
|
this.createNoteViaSync();
|
||||||
|
} catch {
|
||||||
|
// Non-critical — user can still create manually
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadNotebook(id: string) {
|
private async loadNotebook(id: string) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue