diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index ad25315..9b5ffd5 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -386,6 +386,26 @@ jobs: E2E_BASE_URL=http://localhost:5173 \ pnpm --filter @dorfteich/web exec playwright test e2e/graph.spec.ts + - name: Reset login rate limit before create-missing-page pack + run: | + echo "DELETE FROM rate_limits WHERE key LIKE 'login%';" | \ + pnpm --filter @dorfteich/api exec prisma db execute --stdin --url "$DATABASE_URL" + + - name: Run create-missing-page pack + run: | + E2E_BASE_URL=http://localhost:5173 \ + pnpm --filter @dorfteich/web exec playwright test e2e/create-missing-page.spec.ts + + - name: Reset login rate limit before vault-import pack + run: | + echo "DELETE FROM rate_limits WHERE key LIKE 'login%';" | \ + pnpm --filter @dorfteich/api exec prisma db execute --stdin --url "$DATABASE_URL" + + - name: Run vault-import pack + run: | + E2E_BASE_URL=http://localhost:5173 \ + pnpm --filter @dorfteich/web exec playwright test e2e/import-vault.spec.ts + - name: Reset login rate limit before search pack run: | echo "DELETE FROM rate_limits WHERE key LIKE 'login%';" | \ diff --git a/apps/web/e2e/import-vault.spec.ts b/apps/web/e2e/import-vault.spec.ts index 8ea8c4e..1894fb0 100644 --- a/apps/web/e2e/import-vault.spec.ts +++ b/apps/web/e2e/import-vault.spec.ts @@ -45,7 +45,7 @@ test('a pond admin imports an Obsidian vault through the settings dialog', async const pond = await json<{ id: string; slug: string }>(context, '/api/v1/ponds', { name: `Vault Pond ${ts}`, }); - const mount = await json<{ id: string; slug: string; title: string }>( + await json<{ id: string; slug: string; title: string }>( context, `/api/v1/ponds/${pond.id}/pages`, { title: `Vault Mount ${ts}` }, diff --git a/docs/de/features.md b/docs/de/features.md index 7155c06..c30d1b6 100644 --- a/docs/de/features.md +++ b/docs/de/features.md @@ -49,6 +49,13 @@ Familien oder Projekte. Slugs und Links bleiben flach, Verschieben bricht also nie etwas; der ZIP-Export bleibt ebenfalls flach (die Hierarchie ist rein organisatorisch). +- **Obsidian-Vault-Import**: Eine Teich-Administration lädt einen ganzen + Vault als ZIP hoch — Ordner werden zum Seitenbaum, Tags zu Labels, + `[[Wikilinks]]` werden so umgeschrieben, dass sie weiter funktionieren, + und Bilder kommen als Teich-Dateien mit +- **Tote Links sind einen Klick von einer Seite entfernt**: Wer einen Link + auf eine noch nicht existierende Seite öffnet, bekommt sie direkt zum + Anlegen angeboten - **Wissensgraph**: eine interaktive Karte jedes Teichs — Seiten als Knoten, Wikilinks als Kanten, fehlende Ziele als gestrichelte Phantome, die ein Klick anlegt; jede Seite hat zusätzlich einen diff --git a/docs/de/manual/pond-admin-guide.md b/docs/de/manual/pond-admin-guide.md index f36e738..b4b874e 100644 --- a/docs/de/manual/pond-admin-guide.md +++ b/docs/de/manual/pond-admin-guide.md @@ -107,6 +107,49 @@ den passenden Instanz-Schalter aktiviert hat: Ein Teich ohne Freigabe ist über diese Schnittstellen unsichtbar — selbst für die Tokens der eigenen Mitglieder. +## Obsidian-Vault importieren + +Teich-Einstellungen → **Obsidian-Vault importieren** nimmt ein ZIP eines +ganzen Vaults und macht Seiten daraus. Du wählst drei Dinge: + +- **Einhängen unter** — die Seite, unter der der Vault landet (oder die + oberste Ebene). +- **Zusätzliche Labels** — bekommt jede importierte Seite, zusätzlich zu + den Labels aus den Tags des Vaults. +- **YAML-Frontmatter** — entfernen oder als Code-Block am Seitenanfang + behalten. + +Was mit dem Vault passiert: + +- **Ordner werden Seiten.** Jeder Ordner wird eine Container-Seite, die + Notizen hängen darunter — die Vault-Struktur bleibt erhalten. Seiten + verschachteln höchstens sechs Ebenen tief; ist der Vault (samt + Einhänge-Tiefe) tiefer, werden die untersten Ordner-Ebenen zu einer + Seite mit Titel `so/zusammengelegt`. +- **`[[Wikilinks]]` funktionieren weiter.** Obsidian-Links zeigen auf + Notiz-_Namen_, Dorfteich-Links auf Seiten-_Adressen_ — jeder Link wird + deshalb auf die Adresse umgeschrieben, die die Notiz tatsächlich + bekommen hat: `[[Notiz|Anzeigetext]]`, `[[Notiz#Überschrift]]` (der + Überschriften-Teil entfällt) und `[[Ordner/Notiz]]` inklusive. Links + auf Notizen, die es im Vault nicht gibt, werden zu Links auf fehlende + Seiten — genau wie selbst getippt. Tragen zwei Notizen in verschiedenen + Ordnern denselben Namen, zeigt ein einfaches `[[Name]]` auf die, deren + Vault-Pfad alphabetisch zuerst kommt. +- **Tags werden Labels.** Sowohl `tags:` im Frontmatter als auch `#Tags` + im Text (die dabei aus dem Text verschwinden). Verschachtelte Tags wie + `#status/aktiv` werden zu einer Label-Hierarchie. +- **Bilder und Dateien kommen mit.** Bilder, auf die eine Notiz verweist + (`![[bild.png]]` oder `![](media/bild.png)`), werden zu Teich-Dateien + und erscheinen in der Seite; andere erlaubte Dateitypen werden Anhänge. + Sie zählen gegen das Speicher-Kontingent des Teichs. + `![[Andere Notiz]]`-Einbettungen werden zu normalen Links (Dorfteich + bettet keine Seiten ineinander ein). + +Grenzen: Das ZIP darf bis zu 64 MiB groß sein, entpackt bis 256 MiB. +**Ein Import ist Alles-oder-nichts** — schlägt etwas fehl (voller Teich, +kaputtes Archiv), bleibt nichts zurück und du kannst es einfach erneut +versuchen. + ## Dateien Die **Dateiverwaltung** listet die Uploads des Teichs mit ihrer diff --git a/docs/de/manual/user-guide.md b/docs/de/manual/user-guide.md index fc5077f..483dda0 100644 --- a/docs/de/manual/user-guide.md +++ b/docs/de/manual/user-guide.md @@ -81,8 +81,11 @@ Die Werkzeugleiste bleibt beim Scrollen sichtbar. - **Wikilinks:** Tippe `[[seiten-slug]]` oder `[[seiten-slug|angezeigter Text]]`. Links auf Seiten, die es noch nicht gibt, listet die Teich-Startseite unter „Fehlende Seiten" — ein - Klick legt das Ziel an. Das Panel **„Verlinkt von"** einer Seite zeigt - jede Seite, die auf sie verweist. + Klick legt das Ziel an. Genauso kannst du einem solchen Link einfach + folgen: Die Seite öffnet sich mit dem Hinweis, dass es sie noch nicht + gibt, und einem Knopf, der sie **direkt dort anlegt** — danach + funktionieren alle Links auf diese Adresse. Das Panel + **„Verlinkt von"** einer Seite zeigt jede Seite, die auf sie verweist. - **Bilder und Anhänge:** Füge Bilder direkt per Einfügen oder Ziehen in den Text ein. Andere Dateitypen (PDFs usw., soweit die Instanz sie erlaubt) hängst du über das **Büroklammer-Symbol** an die Seite. diff --git a/docs/features.md b/docs/features.md index 8626b7b..fc7e67c 100644 --- a/docs/features.md +++ b/docs/features.md @@ -42,6 +42,11 @@ projects. - **Page tree**: nest pages under pages (up to 6 levels) — slugs and links stay flat, so moving a page never breaks anything; the ZIP export also stays flat (the hierarchy is organizational only) +- **Obsidian vault import**: a pond admin uploads a whole vault as a ZIP — + folders become the page tree, tags become labels, `[[wikilinks]]` are + rewritten so they keep working, and images come along as pond files +- **Dead links are one click from a page**: opening a link to a page that + does not exist yet offers to create it right there - **Knowledge graph**: an interactive map of every pond — pages as nodes, wikilinks as edges, missing targets as dashed phantoms you can create with a click; each page also gets a local neighborhood graph diff --git a/docs/manual/pond-admin-guide.md b/docs/manual/pond-admin-guide.md index 1487a14..af49eb0 100644 --- a/docs/manual/pond-admin-guide.md +++ b/docs/manual/pond-admin-guide.md @@ -95,6 +95,44 @@ the matching instance switch: A pond that has not opted in is invisible through those interfaces, even to its own members' tokens. +## Import an Obsidian vault + +Pond settings → **Import an Obsidian vault** takes a ZIP of a whole vault +and turns it into pages. You choose three things: + +- **Mount under** — the page the vault hangs below (or the top level). +- **Additional labels** — assigned to every imported page, on top of the + labels made from the vault's tags. +- **YAML frontmatter** — removed, or kept as a code block at the top of + the page. + +What happens to the vault: + +- **Folders become pages.** Each folder turns into a container page and + the notes hang below it, mirroring the vault. Pages nest six levels + deep at most; if the vault (plus the mount depth) is deeper, the + deepest folder levels are merged into one page titled `like/this`. +- **`[[Wikilinks]]` keep working.** Obsidian links point at note _names_, + Dorfteich links at page _addresses_, so every link is rewritten to the + address the note actually got — including `[[Note|shown text]]`, + `[[Note#Heading]]` (the heading part is dropped), and + `[[folder/Note]]`. Links to notes that are not in the vault become + missing-page links, exactly as if you had typed them. When two notes in + different folders share a name, a plain `[[Name]]` resolves to the one + whose vault path comes first alphabetically. +- **Tags become labels.** Both `tags:` in the frontmatter and `#tags` in + the text (which are removed from the text). Nested tags like + `#status/active` become a label hierarchy. +- **Images and files come along.** Images referenced by a note + (`![[image.png]]` or `![](media/image.png)`) become pond files shown in + the page; other allowed file types become attachments. They count + against the pond's storage quota. `![[Another note]]` embeds become + plain links (Dorfteich does not transclude pages). + +Limits: the ZIP may be up to 64 MiB, and 256 MiB unpacked. **An import is +all-or-nothing** — if anything fails (a full pond, a broken archive), +nothing is left behind and you can simply try again. + ## Files The **file manager** lists the pond's uploads with their usage (which diff --git a/docs/manual/user-guide.md b/docs/manual/user-guide.md index 5426e74..398050d 100644 --- a/docs/manual/user-guide.md +++ b/docs/manual/user-guide.md @@ -69,8 +69,11 @@ toolbar stays visible while you scroll. overflow menu → Copy/Download Markdown). - **Wikilinks:** type `[[page-slug]]` or `[[page-slug|shown text]]`. Links to pages that do not exist yet are listed on the pond home page - ("phantom pages") — one click creates the target. The **backlinks** - panel of a page shows every page that links to it. + ("phantom pages") — one click creates the target. Following such a link + works too: the page opens with a "this page does not exist yet" notice + and a button that **creates it right there**, and every link pointing at + the address starts working. The **backlinks** panel of a page shows + every page that links to it. - **Images and attachments:** paste or drag images straight into the text. Other file types (PDFs etc., as allowed by the instance) attach to the page via the **paperclip icon**.