@jant/core 0.6.14 → 0.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/commands/import-site.js +88 -13
- package/bin/commands/migrate.js +55 -0
- package/bin/commands/posts/rebuild-html.js +184 -0
- package/bin/commands/site/snapshot/import.js +14 -10
- package/bin/lib/d1-query.js +23 -5
- package/bin/lib/migration-runner.js +29 -7
- package/bin/lib/node-database.js +32 -0
- package/bin/lib/site-snapshot.js +347 -46
- package/bin/lib/sql-export.js +1 -1
- package/bin/lib/thread-collection-migration.js +326 -0
- package/dist/app-C75Zc8dD.js +6 -0
- package/dist/{app-2i7-WQHg.js → app-C7_4oab9.js} +7774 -6425
- package/dist/client/.vite/manifest.json +8 -8
- package/dist/client/_assets/chunks/{url-pLre2DM_.js → url-CU9pEbk5.js} +1 -1
- package/dist/client/_assets/{client-BvID5ucz.js → client-Bq0vre8Y.js} +59 -38
- package/dist/client/_assets/client-D3VZyG4L.css +2 -0
- package/dist/client/_assets/client-auth-F2rb9WfF.js +5571 -0
- package/dist/{env-OHRKGcMj.js → env-BPYViDJJ.js} +1 -1
- package/dist/{export-DWn149b7.js → export-Dl5KCiEs.js} +1348 -128
- package/dist/{github-api-BgSiE71w.js → github-api-BNF35Lkx.js} +1 -1
- package/dist/{github-app-BbklkFmU.js → github-app-DdiD-bC4.js} +1 -1
- package/dist/{github-sync-C0zyF6XS.js → github-sync-Bqg62IvV.js} +3 -3
- package/dist/{github-sync-Ckk0sJxK.js → github-sync-HdK2EgvJ.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/node.js +7 -7
- package/dist/{url-BMYO-Zlt.js → url-CbLAtlZe.js} +517 -12
- package/package.json +11 -10
- package/src/__tests__/bin/posts-rebuild-html.test.ts +137 -0
- package/src/__tests__/dev-navigation-defaults.test.ts +22 -0
- package/src/__tests__/export-hugo-build.test.ts +63 -4
- package/src/__tests__/export-import-roundtrip.test.ts +6 -4
- package/src/__tests__/export-service.test.ts +142 -9
- package/src/__tests__/helpers/app.ts +3 -0
- package/src/__tests__/helpers/export-fixtures.ts +2 -0
- package/src/__tests__/import-site-command.test.ts +65 -0
- package/src/__tests__/mise-config.test.ts +22 -0
- package/src/__tests__/vite-config.test.ts +45 -0
- package/src/app.tsx +16 -3
- package/src/client/__tests__/collection-created-notice.test.ts +36 -0
- package/src/client/__tests__/collection-form-bridge.test.ts +10 -1
- package/src/client/__tests__/collection-page-actions.test.ts +71 -2
- package/src/client/__tests__/compose-bridge.test.ts +316 -2
- package/src/client/__tests__/compose-shortcuts.test.ts +20 -0
- package/src/client/__tests__/feed-video-player.test.ts +16 -1
- package/src/client/__tests__/footnote-rail.test.ts +472 -0
- package/src/client/__tests__/hydrate-partial.test.ts +3 -0
- package/src/client/__tests__/toast.test.ts +82 -1
- package/src/client/collection-created-notice.ts +66 -0
- package/src/client/collection-form-bridge.ts +17 -0
- package/src/client/collection-navigation.ts +44 -0
- package/src/client/collection-page-actions.ts +57 -1
- package/src/client/components/__tests__/compose-format-convert.test.ts +0 -19
- package/src/client/components/__tests__/jant-collection-directory.test.ts +155 -6
- package/src/client/components/__tests__/jant-command-palette.test.ts +51 -0
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +2268 -206
- package/src/client/components/__tests__/jant-compose-editor.test.ts +147 -59
- package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +114 -64
- package/src/client/components/__tests__/jant-config-editor.test.ts +405 -0
- package/src/client/components/__tests__/jant-media-lightbox.test.ts +121 -0
- package/src/client/components/__tests__/jant-nav-manager.test.ts +538 -2
- package/src/client/components/__tests__/jant-post-form.test.ts +2 -2
- package/src/client/components/__tests__/jant-post-menu.test.ts +47 -5
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/client/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-manager-types.ts +9 -3
- package/src/client/components/compose-format-convert.ts +5 -1
- package/src/client/components/compose-types.ts +55 -3
- package/src/client/components/jant-collection-directory.ts +165 -30
- package/src/client/components/jant-command-palette.ts +14 -7
- package/src/client/components/jant-compose-dialog.ts +1542 -694
- package/src/client/components/jant-compose-editor.ts +237 -99
- package/src/client/components/jant-compose-fullscreen.ts +27 -9
- package/src/client/components/jant-config-editor.ts +722 -0
- package/src/client/components/jant-media-lightbox.ts +100 -18
- package/src/client/components/jant-nav-manager.ts +1283 -54
- package/src/client/components/jant-post-form.ts +3 -3
- package/src/client/components/jant-post-menu.ts +177 -95
- package/src/client/components/nav-manager-types.ts +51 -2
- package/src/client/components/post-form-types.ts +1 -1
- package/src/client/compose-bridge.ts +147 -123
- package/src/client/compose-launch.ts +13 -0
- package/src/client/compose-shortcuts.ts +5 -1
- package/src/client/feed-video-player.ts +62 -2
- package/src/client/footnote-rail.ts +478 -0
- package/src/client/hydrate-partial.ts +2 -0
- package/src/client/media-lightbox-events.ts +63 -0
- package/src/client/post-refresh.ts +135 -0
- package/src/client/site-header-fragment.ts +38 -0
- package/src/client/tiptap/__tests__/blockquote-editing.test.ts +201 -0
- package/src/client/tiptap/__tests__/clear-formatting.test.ts +168 -0
- package/src/client/tiptap/__tests__/link-input-rules.test.ts +121 -0
- package/src/client/tiptap/__tests__/list-editing.test.ts +447 -0
- package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +727 -4
- package/src/client/tiptap/__tests__/table-controls.test.ts +263 -0
- package/src/client/tiptap/__tests__/table-size-picker.test.ts +179 -0
- package/src/client/tiptap/bubble-menu.ts +88 -10
- package/src/client/tiptap/continuous-lists.ts +102 -0
- package/src/client/tiptap/create-editor.ts +3 -0
- package/src/client/tiptap/extensions.ts +14 -5
- package/src/client/tiptap/link-input-rules.ts +4 -4
- package/src/client/tiptap/markdown-clipboard.ts +608 -11
- package/src/client/tiptap/slash-commands.ts +8 -1
- package/src/client/tiptap/structural-keymap.ts +211 -0
- package/src/client/tiptap/tab-indent.ts +8 -22
- package/src/client/tiptap/table-control-labels.ts +30 -0
- package/src/client/tiptap/table-controls.ts +537 -0
- package/src/client/tiptap/table-size-picker.ts +254 -0
- package/src/client/toast.ts +133 -39
- package/src/client-auth.ts +1 -0
- package/src/client.ts +1 -0
- package/src/db/__tests__/backfill-thread-activity.test.ts +234 -0
- package/src/db/__tests__/d1-query.test.ts +43 -1
- package/src/db/__tests__/migration-runner.test.ts +63 -0
- package/src/db/__tests__/migrations.test.ts +469 -0
- package/src/db/__tests__/thread-activity.test.ts +113 -0
- package/src/db/__tests__/thread-collection-migration.test.ts +364 -0
- package/src/db/backfills/0005_split_thread_activity_from_quiet_replies.sql +68 -0
- package/src/db/migrations/0027_old_blue_blade.sql +39 -0
- package/src/db/migrations/0028_superb_post.sql +2 -0
- package/src/db/migrations/0029_boring_magma.sql +1 -0
- package/src/db/migrations/0030_typical_vivisector.sql +50 -0
- package/src/db/migrations/0031_many_ego.sql +3 -0
- package/src/db/migrations/meta/0027_snapshot.json +2511 -0
- package/src/db/migrations/meta/0028_snapshot.json +2511 -0
- package/src/db/migrations/meta/0029_snapshot.json +2519 -0
- package/src/db/migrations/meta/0030_snapshot.json +2541 -0
- package/src/db/migrations/meta/0031_snapshot.json +2562 -0
- package/src/db/migrations/meta/_journal.json +35 -0
- package/src/db/migrations/pg/0025_moaning_epoch.sql +39 -0
- package/src/db/migrations/pg/0026_talented_killer_shrike.sql +2 -0
- package/src/db/migrations/pg/0027_short_cannonball.sql +1 -0
- package/src/db/migrations/pg/0028_perfect_sharon_carter.sql +27 -0
- package/src/db/migrations/pg/0029_rare_hairball.sql +3 -0
- package/src/db/migrations/pg/meta/0025_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0026_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0027_snapshot.json +3211 -0
- package/src/db/migrations/pg/meta/0028_snapshot.json +3248 -0
- package/src/db/migrations/pg/meta/0029_snapshot.json +3289 -0
- package/src/db/migrations/pg/meta/_journal.json +35 -0
- package/src/db/pg/schema.ts +46 -20
- package/src/db/rehearsal-fixtures/demo-current.json +39 -4
- package/src/db/rehearsal-fixtures/demo-current.sql +121 -6
- package/src/db/schema.ts +48 -20
- package/src/db/thread-activity.ts +101 -0
- package/src/i18n/__tests__/detect.test.ts +8 -2
- package/src/i18n/detect.ts +14 -5
- package/src/i18n/locales/public/en.po +222 -51
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +216 -45
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +216 -45
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +513 -10
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +515 -12
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +515 -12
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/lib/__tests__/api-settings.test.ts +299 -0
- package/src/lib/__tests__/constants.test.ts +5 -0
- package/src/lib/__tests__/feed-policy.test.ts +25 -0
- package/src/lib/__tests__/feed.test.ts +168 -0
- package/src/lib/__tests__/footnotes-upgrade.test.ts +181 -0
- package/src/lib/__tests__/markdown-roundtrip-embed.test.ts +61 -0
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +32 -4
- package/src/lib/__tests__/markdown.test.ts +24 -6
- package/src/lib/__tests__/navigation.test.ts +59 -2
- package/src/lib/__tests__/post-body-html.test.ts +176 -0
- package/src/lib/__tests__/post-display.test.ts +64 -0
- package/src/lib/__tests__/resolve-config.test.ts +113 -1
- package/src/lib/__tests__/slug.test.ts +18 -0
- package/src/lib/__tests__/summary.test.ts +82 -0
- package/src/lib/__tests__/timeline.test.ts +109 -70
- package/src/lib/__tests__/timezones.test.ts +31 -3
- package/src/lib/__tests__/tiptap-render.test.ts +268 -9
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +6 -0
- package/src/lib/__tests__/translit.test.ts +87 -0
- package/src/lib/__tests__/url.test.ts +53 -0
- package/src/lib/__tests__/view.test.ts +53 -0
- package/src/lib/__tests__/worker-response-cache.test.ts +18 -1
- package/src/lib/api-settings.ts +239 -12
- package/src/lib/collection-sort.ts +7 -5
- package/src/lib/constants.ts +2 -0
- package/src/lib/feed-path.ts +25 -0
- package/src/lib/feed-policy.ts +64 -0
- package/src/lib/feed.ts +113 -11
- package/src/lib/footnotes.ts +264 -0
- package/src/lib/github-sync-site-config.ts +2 -0
- package/src/lib/hugo-markdown.ts +15 -3
- package/src/lib/jant-branding.ts +1 -0
- package/src/lib/link-preview.ts +25 -0
- package/src/lib/markdown-manager.ts +193 -5
- package/src/lib/markdown.ts +10 -3
- package/src/lib/navigation.ts +16 -3
- package/src/lib/post-body-html.ts +131 -0
- package/src/lib/post-display.ts +47 -8
- package/src/lib/render.tsx +9 -2
- package/src/lib/resolve-config.ts +100 -16
- package/src/lib/schemas.ts +133 -1
- package/src/lib/settings-paths.ts +5 -0
- package/src/lib/site-skill.ts +78 -0
- package/src/lib/summary.ts +16 -5
- package/src/lib/timeline.ts +137 -131
- package/src/lib/timezones.ts +54 -14
- package/src/lib/tiptap-render.ts +359 -83
- package/src/lib/translit.ts +288 -0
- package/src/lib/url.ts +123 -12
- package/src/lib/view.ts +58 -20
- package/src/lib/worker-response-cache.ts +11 -18
- package/src/middleware/__tests__/public-content-access.test.ts +91 -0
- package/src/middleware/config.ts +2 -2
- package/src/middleware/public-content-access.ts +87 -0
- package/src/node/__tests__/cli-export.test.ts +14 -0
- package/src/node/__tests__/cli-migrate.test.ts +6 -0
- package/src/node/__tests__/cli-site-snapshot.test.ts +205 -2
- package/src/node/__tests__/cli-snapshot-meta.test.ts +100 -0
- package/src/node/index.ts +2 -1
- package/src/preset.css +16 -2
- package/src/routes/__tests__/compose.test.ts +51 -0
- package/src/routes/__tests__/site-skill.test.ts +112 -0
- package/src/routes/api/__tests__/collections.test.ts +91 -19
- package/src/routes/api/__tests__/mcp.test.ts +65 -1
- package/src/routes/api/__tests__/nav-items.test.ts +91 -0
- package/src/routes/api/__tests__/palette.test.ts +44 -0
- package/src/routes/api/__tests__/public-access.test.ts +81 -0
- package/src/routes/api/__tests__/settings.test.ts +217 -0
- package/src/routes/api/collections.ts +22 -26
- package/src/routes/api/export.ts +2 -0
- package/src/routes/api/internal/__tests__/post-body-html.test.ts +163 -0
- package/src/routes/api/internal/__tests__/sites.test.ts +35 -2
- package/src/routes/api/internal/post-body-html.ts +43 -0
- package/src/routes/api/internal/sites.ts +24 -0
- package/src/routes/api/nav-items.ts +24 -1
- package/src/routes/api/posts.ts +14 -10
- package/src/routes/api/public/__tests__/archive.test.ts +35 -0
- package/src/routes/api/public/__tests__/posts.test.ts +246 -0
- package/src/routes/api/public/archive.ts +4 -0
- package/src/routes/api/public/posts.ts +48 -24
- package/src/routes/api/search.ts +3 -0
- package/src/routes/api/settings.ts +33 -0
- package/src/routes/auth/__tests__/setup.test.ts +7 -4
- package/src/routes/compose.tsx +8 -3
- package/src/routes/dash/settings.tsx +45 -2
- package/src/routes/feed/__tests__/feed.test.ts +210 -6
- package/src/routes/feed/__tests__/sitemap.test.ts +68 -1
- package/src/routes/feed/feed.ts +23 -14
- package/src/routes/pages/__tests__/archive-params.test.ts +384 -3
- package/src/routes/pages/__tests__/collection-routing.test.ts +63 -5
- package/src/routes/pages/__tests__/collections.test.ts +9 -9
- package/src/routes/pages/__tests__/featured.test.ts +6 -2
- package/src/routes/pages/__tests__/preview.test.ts +176 -0
- package/src/routes/pages/__tests__/search.test.ts +69 -0
- package/src/routes/pages/archive.tsx +90 -22
- package/src/routes/pages/collection.tsx +32 -19
- package/src/routes/pages/collections.tsx +6 -1
- package/src/routes/pages/page.tsx +86 -11
- package/src/routes/site-skill.ts +18 -0
- package/src/services/__tests__/auth.test.ts +7 -5
- package/src/services/__tests__/collection.test.ts +190 -44
- package/src/services/__tests__/navigation.test.ts +229 -21
- package/src/services/__tests__/post-timeline.test.ts +249 -39
- package/src/services/__tests__/post.test.ts +844 -5
- package/src/services/__tests__/search.test.ts +48 -1
- package/src/services/__tests__/settings.test.ts +8 -0
- package/src/services/__tests__/site-admin.test.ts +121 -1
- package/src/services/auth.ts +2 -2
- package/src/services/bootstrap.ts +3 -2
- package/src/services/collection.ts +224 -167
- package/src/services/export-theme/assets/client-site.css +1 -1
- package/src/services/export-theme/assets/client-site.js +46 -25
- package/src/services/export-theme/layouts/_default/list.html +18 -4
- package/src/services/export-theme/layouts/_default/rss.xml +8 -12
- package/src/services/export-theme/layouts/featured/list.html +5 -4
- package/src/services/export-theme/layouts/partials/featured-thread.html +56 -0
- package/src/services/export-theme/layouts/partials/footer.html +1 -1
- package/src/services/export-theme/layouts/partials/media-gallery.html +1 -0
- package/src/services/export-theme/styles/main.css +30 -2
- package/src/services/export.ts +94 -85
- package/src/services/mcp.ts +37 -27
- package/src/services/media.ts +1 -1
- package/src/services/navigation.ts +185 -46
- package/src/services/path.ts +4 -1
- package/src/services/post.ts +1142 -342
- package/src/services/search.ts +17 -2
- package/src/services/settings.ts +2 -10
- package/src/services/site-admin.ts +63 -43
- package/src/style-cjk-jp.css +1 -1
- package/src/style-cjk-kr.css +1 -1
- package/src/style-cjk-tc.css +1 -1
- package/src/style-cjk.css +1 -1
- package/src/styles/components.css +540 -14
- package/src/styles/site-media.css +111 -19
- package/src/styles/tokens.css +76 -10
- package/src/styles/ui.css +2227 -1347
- package/src/types/bindings.ts +3 -0
- package/src/types/config.ts +243 -12
- package/src/types/constants.ts +22 -1
- package/src/types/entities.ts +14 -8
- package/src/types/operations.ts +18 -10
- package/src/types/props.ts +20 -2
- package/src/types/raw-assets.d.ts +5 -0
- package/src/types/views.ts +22 -4
- package/src/ui/__tests__/font-themes.test.ts +42 -30
- package/src/ui/compose/ComposeDialog.tsx +109 -19
- package/src/ui/dash/appearance/NavigationContent.tsx +332 -4
- package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +23 -0
- package/src/ui/dash/settings/ConfigEditorContent.tsx +578 -0
- package/src/ui/dash/settings/GeneralContent.tsx +15 -5
- package/src/ui/dash/settings/SettingsRootContent.tsx +21 -1
- package/src/ui/dash/settings/__tests__/ConfigEditorContent.test.tsx +98 -0
- package/src/ui/dash/settings/__tests__/SettingsRootContent.test.tsx +15 -0
- package/src/ui/feed/CuratedThreadPreview.tsx +16 -4
- package/src/ui/feed/LinkCard.tsx +2 -12
- package/src/ui/feed/LinkPreview.tsx +2 -7
- package/src/ui/feed/NoteCard.tsx +10 -20
- package/src/ui/feed/PostStatusBadges.tsx +42 -3
- package/src/ui/feed/QuoteCard.tsx +2 -12
- package/src/ui/feed/ThreadPreview.tsx +26 -34
- package/src/ui/feed/TimelineFeed.tsx +2 -2
- package/src/ui/feed/__tests__/thread-preview.test.ts +197 -56
- package/src/ui/feed/__tests__/timeline-cards.test.ts +178 -3
- package/src/ui/feed/thread-preview-state.ts +5 -7
- package/src/ui/font-themes.ts +74 -26
- package/src/ui/layouts/BaseLayout.tsx +22 -8
- package/src/ui/layouts/__tests__/BaseLayout.test.tsx +64 -1
- package/src/ui/pages/ArchivePage.tsx +131 -24
- package/src/ui/pages/CollectionPage.tsx +101 -22
- package/src/ui/pages/CollectionsPage.tsx +3 -1
- package/src/ui/pages/PostPage.tsx +39 -12
- package/src/ui/pages/SearchPage.tsx +6 -14
- package/src/ui/pages/__tests__/ArchivePage.test.tsx +70 -0
- package/src/ui/pages/__tests__/PostPage.test.tsx +88 -0
- package/src/ui/shared/CollectionDirectory.tsx +13 -9
- package/src/ui/shared/CollectionsManager.tsx +17 -7
- package/src/ui/shared/DraftPreviewBar.tsx +49 -0
- package/src/ui/shared/HomePageBranding.tsx +2 -2
- package/src/ui/shared/MediaGallery.tsx +1 -0
- package/src/ui/shared/PostFooter.tsx +38 -13
- package/src/ui/shared/__tests__/home-page-branding.test.tsx +1 -1
- package/src/ui/shared/__tests__/media-gallery.test.ts +1 -0
- package/src/ui/shared/__tests__/navigation-labels.test.ts +2 -2
- package/src/ui/shared/__tests__/post-footer.test.ts +15 -0
- package/src/ui/shared/collection-management-labels.ts +33 -2
- package/src/ui/shared/custom-icons.ts +5 -0
- package/src/ui/shared/navigation-labels.ts +2 -4
- package/src/ui/shared/post-article-attributes.ts +52 -0
- package/dist/app-DZDlmh7C.js +0 -6
- package/dist/client/_assets/client-Cevfpm8H.css +0 -2
- package/dist/client/_assets/client-auth-v3yvhbgZ.js +0 -4736
- package/src/client/tiptap/wrapping-input-rules.ts +0 -102
|
@@ -327,7 +327,7 @@ describe("JantPostMenu", () => {
|
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
if (
|
|
330
|
-
url === "/api/collections/collection-1/
|
|
330
|
+
url === "/api/collections/collection-1/threads/post-1" &&
|
|
331
331
|
method === "DELETE"
|
|
332
332
|
) {
|
|
333
333
|
selectedIds.splice(0, 1);
|
|
@@ -397,7 +397,7 @@ describe("JantPostMenu", () => {
|
|
|
397
397
|
keydown(requireElement(options[0] ?? null, "expected first option"), " ");
|
|
398
398
|
await Promise.resolve();
|
|
399
399
|
await menu.updateComplete;
|
|
400
|
-
expect(menu.
|
|
400
|
+
expect(menu._threadCollectionIds).toEqual([]);
|
|
401
401
|
|
|
402
402
|
options = Array.from(
|
|
403
403
|
menu.querySelectorAll<HTMLButtonElement>(".post-menu-picker-option"),
|
|
@@ -412,6 +412,48 @@ describe("JantPostMenu", () => {
|
|
|
412
412
|
expect(document.activeElement).toBe(searchInput);
|
|
413
413
|
});
|
|
414
414
|
|
|
415
|
+
it("derives Child action scope from Thread identity", async () => {
|
|
416
|
+
const { menu, trigger } = await createMenu();
|
|
417
|
+
const article = requireElement(
|
|
418
|
+
trigger.closest<HTMLElement>("article[data-post]"),
|
|
419
|
+
"expected post article",
|
|
420
|
+
);
|
|
421
|
+
article.dataset.postId = "reply-1";
|
|
422
|
+
article.dataset.threadRootId = "post-1";
|
|
423
|
+
document.body.insertAdjacentHTML(
|
|
424
|
+
"afterbegin",
|
|
425
|
+
'<div data-collection-id="collection-1"></div>',
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
click(trigger);
|
|
429
|
+
await menu.updateComplete;
|
|
430
|
+
|
|
431
|
+
expect(menu.textContent).toContain("Edit");
|
|
432
|
+
expect(menu.textContent).toContain("Add to Featured");
|
|
433
|
+
expect(menu.textContent).toContain("Delete");
|
|
434
|
+
expect(menu.querySelector("[data-post-menu-open-collections]")).toBeNull();
|
|
435
|
+
expect(menu.querySelector("[data-post-menu-open-visibility]")).toBeNull();
|
|
436
|
+
expect(menu.textContent).not.toContain("Pin this post");
|
|
437
|
+
expect(menu.textContent).not.toContain("Pin in collection");
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it("blocks the collection shortcut for a Child without a reply marker", async () => {
|
|
441
|
+
const fetchMock = vi.mocked(globalThis.fetch);
|
|
442
|
+
const { menu, trigger } = await createMenu();
|
|
443
|
+
const article = requireElement(
|
|
444
|
+
trigger.closest<HTMLElement>("article[data-post]"),
|
|
445
|
+
"expected post article",
|
|
446
|
+
);
|
|
447
|
+
article.dataset.postId = "reply-1";
|
|
448
|
+
article.dataset.threadRootId = "post-1";
|
|
449
|
+
|
|
450
|
+
menu.openCollectionsForPost(article);
|
|
451
|
+
await menu.updateComplete;
|
|
452
|
+
|
|
453
|
+
expect(menu.textContent?.trim()).toBe("");
|
|
454
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
455
|
+
});
|
|
456
|
+
|
|
415
457
|
it("closes the collection picker with Enter without toggling the focused option", async () => {
|
|
416
458
|
const selectedIds = ["collection-1"];
|
|
417
459
|
const fetchMock = vi.fn(
|
|
@@ -466,7 +508,7 @@ describe("JantPostMenu", () => {
|
|
|
466
508
|
keydown(firstOption, "Enter");
|
|
467
509
|
await menu.updateComplete;
|
|
468
510
|
|
|
469
|
-
expect(menu.
|
|
511
|
+
expect(menu._threadCollectionIds).toEqual(["collection-1"]);
|
|
470
512
|
expect(menu.textContent?.trim()).toBe("");
|
|
471
513
|
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
|
472
514
|
});
|
|
@@ -564,7 +606,7 @@ describe("JantPostMenu", () => {
|
|
|
564
606
|
}
|
|
565
607
|
|
|
566
608
|
if (
|
|
567
|
-
url === "/api/collections/collection-3/
|
|
609
|
+
url === "/api/collections/collection-3/threads" &&
|
|
568
610
|
method === "POST"
|
|
569
611
|
) {
|
|
570
612
|
selectedIds.push("collection-3");
|
|
@@ -572,7 +614,7 @@ describe("JantPostMenu", () => {
|
|
|
572
614
|
}
|
|
573
615
|
|
|
574
616
|
if (
|
|
575
|
-
url === "/api/collections/collection-2/
|
|
617
|
+
url === "/api/collections/collection-2/threads/post-1" &&
|
|
576
618
|
method === "DELETE"
|
|
577
619
|
) {
|
|
578
620
|
const index = selectedIds.indexOf("collection-2");
|
|
@@ -51,9 +51,9 @@ const labels: SettingsLabels = {
|
|
|
51
51
|
contentLanguagePreview: "Readers and search engines see",
|
|
52
52
|
dashboardLanguage: "Dashboard language",
|
|
53
53
|
dashboardLanguageHelp: "The language this admin dashboard shows in.",
|
|
54
|
-
cjkFont: "CJK
|
|
54
|
+
cjkFont: "CJK fallback",
|
|
55
55
|
cjkFontHelp:
|
|
56
|
-
"
|
|
56
|
+
"Used when the content language has no built-in font profile. Your font theme still controls serif and sans styling.",
|
|
57
57
|
timeZone: "Time Zone",
|
|
58
58
|
feeds: "Feeds",
|
|
59
59
|
mainRssFeed: "Main RSS feed",
|
|
@@ -96,9 +96,9 @@ const labels: SettingsLabels = {
|
|
|
96
96
|
contentLanguagePreview: "Readers and search engines see",
|
|
97
97
|
dashboardLanguage: "Dashboard language",
|
|
98
98
|
dashboardLanguageHelp: "The language this admin dashboard shows in.",
|
|
99
|
-
cjkFont: "CJK
|
|
99
|
+
cjkFont: "CJK fallback",
|
|
100
100
|
cjkFontHelp:
|
|
101
|
-
"
|
|
101
|
+
"Used when the content language has no built-in font profile. Your font theme still controls serif and sans styling.",
|
|
102
102
|
timeZone: "Time Zone",
|
|
103
103
|
feeds: "Feeds",
|
|
104
104
|
mainRssFeed: "Main RSS feed",
|
|
@@ -137,7 +137,7 @@ const timezones: SettingsTimezone[] = [
|
|
|
137
137
|
];
|
|
138
138
|
|
|
139
139
|
const cjkFonts: SettingsCjkFont[] = [
|
|
140
|
-
{ value: "off", label: "
|
|
140
|
+
{ value: "off", label: "Follow content language" },
|
|
141
141
|
{ value: "zh-Hans", label: "简体中文 (Simplified Chinese)" },
|
|
142
142
|
];
|
|
143
143
|
|
|
@@ -17,6 +17,12 @@ export interface CollectionManagerLabels {
|
|
|
17
17
|
dividerLabelPlaceholder: string;
|
|
18
18
|
newCollection: string;
|
|
19
19
|
edit: string;
|
|
20
|
+
addToNavigation: string;
|
|
21
|
+
addingToNavigation: string;
|
|
22
|
+
addedToNavigation: string;
|
|
23
|
+
editNavigation: string;
|
|
24
|
+
addToNavigationFailed: string;
|
|
25
|
+
notNow: string;
|
|
20
26
|
label: string;
|
|
21
27
|
url: string;
|
|
22
28
|
linkLabelPlaceholder: string;
|
|
@@ -31,8 +37,8 @@ export interface CollectionManagerLabels {
|
|
|
31
37
|
deleteLink: string;
|
|
32
38
|
confirmDeleteLink: string;
|
|
33
39
|
cancel: string;
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
threadSingular: string;
|
|
41
|
+
threadPlural: string;
|
|
36
42
|
emptyState: string;
|
|
37
43
|
orderSaved: string;
|
|
38
44
|
saved: string;
|
|
@@ -50,7 +56,7 @@ export interface ManagedCollection {
|
|
|
50
56
|
title: string;
|
|
51
57
|
description: string | null;
|
|
52
58
|
sortOrder: string;
|
|
53
|
-
|
|
59
|
+
threadCount: number;
|
|
54
60
|
recentActivityAt: number;
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -249,7 +249,11 @@ export function convertComposeFormat(
|
|
|
249
249
|
if (prepend.length) content.unshift(...prepend);
|
|
250
250
|
|
|
251
251
|
out.bodyJson = content.length ? { type: "doc", content } : null;
|
|
252
|
-
|
|
252
|
+
// A title carried in from another format has nowhere to show unless the note's
|
|
253
|
+
// title field is open, so opening it is the only way not to drop it. The
|
|
254
|
+
// toggle is otherwise left alone, so note → link → note keeps the user's
|
|
255
|
+
// choice instead of resetting it.
|
|
256
|
+
if (to === "note" && out.title.trim().length > 0) out.showTitle = true;
|
|
253
257
|
|
|
254
258
|
return out;
|
|
255
259
|
}
|
|
@@ -7,9 +7,22 @@
|
|
|
7
7
|
|
|
8
8
|
import type { JSONContent } from "@tiptap/core";
|
|
9
9
|
import type { CollectionFormLabels } from "./collection-types.js";
|
|
10
|
+
import type { TableControlLabels } from "../tiptap/table-control-labels.js";
|
|
10
11
|
|
|
11
12
|
export type ComposeFormat = "note" | "link" | "quote";
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* What one composer row says about itself. An editor owns its fields, so it
|
|
16
|
+
* owns these two answers too — the dialog reduces them over the rows it has
|
|
17
|
+
* instead of reading editors back out of the DOM while it renders.
|
|
18
|
+
*/
|
|
19
|
+
export interface ComposeRowStatus {
|
|
20
|
+
/** Anything worth keeping: the check behind "discard this?" and autosave. */
|
|
21
|
+
hasContent: boolean;
|
|
22
|
+
/** Enough to publish this row: its format's requirements met, fields valid. */
|
|
23
|
+
publishable: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
export interface ComposeAttachment {
|
|
14
27
|
clientId: string;
|
|
15
28
|
file: File;
|
|
@@ -24,6 +37,12 @@ export interface ComposeAttachment {
|
|
|
24
37
|
status: "pending" | "processing" | "uploading" | "done" | "error";
|
|
25
38
|
progress: number | null;
|
|
26
39
|
mediaId: string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Server URL of the uploaded file, set when the upload completes. Unlike
|
|
42
|
+
* `previewUrl` (a blob URL revoked on editor reset) it stays valid, so
|
|
43
|
+
* draft restore can rehydrate the attachment after the dialog closed.
|
|
44
|
+
*/
|
|
45
|
+
remoteUrl: string | null;
|
|
27
46
|
alt: string;
|
|
28
47
|
error: string | null;
|
|
29
48
|
/** Text content preview for text files (first ~100 chars) */
|
|
@@ -46,6 +65,7 @@ export interface AttachedTextItem {
|
|
|
46
65
|
|
|
47
66
|
export interface DraftItem {
|
|
48
67
|
id: string;
|
|
68
|
+
slug: string;
|
|
49
69
|
format: ComposeFormat;
|
|
50
70
|
title: string | null;
|
|
51
71
|
bodyText: string | null;
|
|
@@ -62,6 +82,23 @@ export interface DraftItem {
|
|
|
62
82
|
}[];
|
|
63
83
|
}
|
|
64
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Snapshot of a media attachment whose upload completed. Stored in the local
|
|
87
|
+
* draft (and passed by the bridge on failure restore) so uploaded images
|
|
88
|
+
* survive a failed publish or a page reload — the bytes are already on the
|
|
89
|
+
* server, only the reference needs restoring.
|
|
90
|
+
*/
|
|
91
|
+
export interface LocalDraftMedia {
|
|
92
|
+
clientId: string;
|
|
93
|
+
mediaId: string;
|
|
94
|
+
url: string;
|
|
95
|
+
mimeType: string;
|
|
96
|
+
name?: string;
|
|
97
|
+
alt?: string;
|
|
98
|
+
summary?: string | null;
|
|
99
|
+
chars?: number | null;
|
|
100
|
+
}
|
|
101
|
+
|
|
65
102
|
export interface LocalDraft {
|
|
66
103
|
format: ComposeFormat;
|
|
67
104
|
title: string;
|
|
@@ -85,9 +122,15 @@ export interface LocalDraft {
|
|
|
85
122
|
summary: string;
|
|
86
123
|
}>;
|
|
87
124
|
attachmentOrder?: string[];
|
|
125
|
+
mediaAttachments?: LocalDraftMedia[];
|
|
88
126
|
/** Present when the draft is a multi-post thread */
|
|
89
127
|
threadItems?: Array<{
|
|
90
128
|
format: ComposeFormat;
|
|
129
|
+
/** Per-post publish date; empty means "follows the thread". */
|
|
130
|
+
publishedAtInput?: string;
|
|
131
|
+
publishedAtTimeMinutes?: number | null;
|
|
132
|
+
/** Per-post permalink; empty means the server assigns a random id. */
|
|
133
|
+
slug?: string;
|
|
91
134
|
title: string;
|
|
92
135
|
bodyJson: JSONContent | null;
|
|
93
136
|
url: string;
|
|
@@ -100,6 +143,7 @@ export interface LocalDraft {
|
|
|
100
143
|
summary: string;
|
|
101
144
|
}>;
|
|
102
145
|
attachmentOrder?: string[];
|
|
146
|
+
mediaAttachments?: LocalDraftMedia[];
|
|
103
147
|
}>;
|
|
104
148
|
savedAt: number;
|
|
105
149
|
}
|
|
@@ -180,6 +224,8 @@ export interface ComposeLabels {
|
|
|
180
224
|
discardChangesConfirm: string;
|
|
181
225
|
drafts: string;
|
|
182
226
|
draftsEmpty: string;
|
|
227
|
+
previewDraft: string;
|
|
228
|
+
draftActions: string;
|
|
183
229
|
deleteDraft: string;
|
|
184
230
|
draftDeleted: string;
|
|
185
231
|
publishFailedDraft: string;
|
|
@@ -225,10 +271,11 @@ export interface ComposeLabels {
|
|
|
225
271
|
threadLimitReached: string;
|
|
226
272
|
showMore: string;
|
|
227
273
|
showLess: string;
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
274
|
+
closeCompose: string;
|
|
275
|
+
editing: string;
|
|
276
|
+
composeDialogLabel: string;
|
|
231
277
|
slashHint: string;
|
|
278
|
+
tableControls: TableControlLabels;
|
|
232
279
|
collectionFormLabels: CollectionFormLabels;
|
|
233
280
|
}
|
|
234
281
|
|
|
@@ -250,6 +297,7 @@ export interface ComposeFullscreenOpenDetail {
|
|
|
250
297
|
selection?: ComposeEditorSelection | null;
|
|
251
298
|
labels?: ComposeLabels;
|
|
252
299
|
replyContext?: ComposeFullscreenReplyContext | null;
|
|
300
|
+
editorIndex?: number;
|
|
253
301
|
}
|
|
254
302
|
|
|
255
303
|
export interface ComposeFullscreenCloseDetail {
|
|
@@ -258,6 +306,8 @@ export interface ComposeFullscreenCloseDetail {
|
|
|
258
306
|
showTitle: boolean;
|
|
259
307
|
selection?: ComposeEditorSelection | null;
|
|
260
308
|
replyExpanded: boolean;
|
|
309
|
+
intent?: "publish";
|
|
310
|
+
editorIndex?: number;
|
|
261
311
|
}
|
|
262
312
|
|
|
263
313
|
export type ComposeVisibility = "public" | "latest_hidden" | "private";
|
|
@@ -293,6 +343,8 @@ export interface ComposeSubmitDetail {
|
|
|
293
343
|
collectionIds: string[];
|
|
294
344
|
attachments: ComposeSubmitAttachment[];
|
|
295
345
|
editPostId?: string;
|
|
346
|
+
/** Identifies an existing server draft loaded through the drafts workflow. */
|
|
347
|
+
draftSourceId?: string;
|
|
296
348
|
replyToId?: string;
|
|
297
349
|
quietReply?: boolean;
|
|
298
350
|
replyThreadRootId?: string;
|
|
@@ -27,13 +27,16 @@ import {
|
|
|
27
27
|
} from "../sortable-list.js";
|
|
28
28
|
import { showConfirmDialog } from "../confirm.js";
|
|
29
29
|
import { publicPath } from "../runtime-paths.js";
|
|
30
|
-
import { showToast } from "../toast.js";
|
|
30
|
+
import { showToast, showToastWithAction } from "../toast.js";
|
|
31
|
+
import { addCollectionToNavigation } from "../collection-navigation.js";
|
|
32
|
+
import { consumeCollectionCreatedNotice } from "../collection-created-notice.js";
|
|
31
33
|
import { getDividerCollectionGroup } from "../../lib/collection-groups.js";
|
|
32
34
|
import {
|
|
33
35
|
getCollectionEditPath,
|
|
34
36
|
getCollectionSelectionPath,
|
|
35
37
|
getCollectionsDirectoryPath,
|
|
36
38
|
} from "../../lib/collection-paths.js";
|
|
39
|
+
import { NAVIGATION_SETTINGS_PATH } from "../../lib/settings-paths.js";
|
|
37
40
|
import { render as renderMarkdown } from "../../lib/markdown.js";
|
|
38
41
|
import { formatRelativeAge, toISOString } from "../../lib/time.js";
|
|
39
42
|
import {
|
|
@@ -53,7 +56,7 @@ interface CollectionsResponse {
|
|
|
53
56
|
title: string;
|
|
54
57
|
description: string | null;
|
|
55
58
|
sortOrder: string;
|
|
56
|
-
|
|
59
|
+
threadCount: number;
|
|
57
60
|
recentActivityAt: number;
|
|
58
61
|
}>;
|
|
59
62
|
directoryItems?: Array<{
|
|
@@ -77,6 +80,10 @@ export class JantCollectionsManager extends LitElement {
|
|
|
77
80
|
static properties = {
|
|
78
81
|
items: { type: Array },
|
|
79
82
|
labels: { type: Object },
|
|
83
|
+
navigationCollectionIds: {
|
|
84
|
+
type: Array,
|
|
85
|
+
attribute: "navigation-collection-ids",
|
|
86
|
+
},
|
|
80
87
|
|
|
81
88
|
_items: { state: true },
|
|
82
89
|
_reorderMode: { state: true },
|
|
@@ -91,12 +98,14 @@ export class JantCollectionsManager extends LitElement {
|
|
|
91
98
|
_newLinkUrl: { state: true },
|
|
92
99
|
_newLinkDescription: { state: true },
|
|
93
100
|
_addingLink: { state: true },
|
|
94
|
-
_hoveringId: { state: true },
|
|
95
101
|
_showItemMenuId: { state: true },
|
|
102
|
+
_addingToNavigationId: { state: true },
|
|
103
|
+
_createdCollectionId: { state: true },
|
|
96
104
|
};
|
|
97
105
|
|
|
98
106
|
declare items: CollectionManagerItem[];
|
|
99
107
|
declare labels: CollectionManagerLabels;
|
|
108
|
+
declare navigationCollectionIds: string[];
|
|
100
109
|
|
|
101
110
|
declare _items: CollectionManagerItem[];
|
|
102
111
|
declare _reorderMode: boolean;
|
|
@@ -111,8 +120,9 @@ export class JantCollectionsManager extends LitElement {
|
|
|
111
120
|
declare _newLinkUrl: string;
|
|
112
121
|
declare _newLinkDescription: string;
|
|
113
122
|
declare _addingLink: boolean;
|
|
114
|
-
declare _hoveringId: string | null;
|
|
115
123
|
declare _showItemMenuId: string | null;
|
|
124
|
+
declare _addingToNavigationId: string | null;
|
|
125
|
+
declare _createdCollectionId: string | null;
|
|
116
126
|
|
|
117
127
|
#sortable: { destroy(): void } | null = null;
|
|
118
128
|
#initialized = false;
|
|
@@ -189,12 +199,17 @@ export class JantCollectionsManager extends LitElement {
|
|
|
189
199
|
connectedCallback() {
|
|
190
200
|
super.connectedCallback();
|
|
191
201
|
this.#bindManagerRoot();
|
|
202
|
+
const createdCollectionId = consumeCollectionCreatedNotice();
|
|
203
|
+
if (createdCollectionId) {
|
|
204
|
+
this._createdCollectionId = createdCollectionId;
|
|
205
|
+
}
|
|
192
206
|
}
|
|
193
207
|
|
|
194
208
|
constructor() {
|
|
195
209
|
super();
|
|
196
210
|
this.items = [];
|
|
197
211
|
this.labels = {} as CollectionManagerLabels;
|
|
212
|
+
this.navigationCollectionIds = [];
|
|
198
213
|
|
|
199
214
|
this._items = [];
|
|
200
215
|
this._reorderMode = false;
|
|
@@ -209,8 +224,9 @@ export class JantCollectionsManager extends LitElement {
|
|
|
209
224
|
this._newLinkUrl = "";
|
|
210
225
|
this._newLinkDescription = "";
|
|
211
226
|
this._addingLink = false;
|
|
212
|
-
this._hoveringId = null;
|
|
213
227
|
this._showItemMenuId = null;
|
|
228
|
+
this._addingToNavigationId = null;
|
|
229
|
+
this._createdCollectionId = null;
|
|
214
230
|
}
|
|
215
231
|
|
|
216
232
|
protected update(
|
|
@@ -247,7 +263,7 @@ export class JantCollectionsManager extends LitElement {
|
|
|
247
263
|
|
|
248
264
|
#countLabel(count: number) {
|
|
249
265
|
return `${count} ${
|
|
250
|
-
count === 1 ? this.labels.
|
|
266
|
+
count === 1 ? this.labels.threadSingular : this.labels.threadPlural
|
|
251
267
|
}`;
|
|
252
268
|
}
|
|
253
269
|
|
|
@@ -323,7 +339,7 @@ export class JantCollectionsManager extends LitElement {
|
|
|
323
339
|
title: collection.title,
|
|
324
340
|
description: collection.description,
|
|
325
341
|
sortOrder: collection.sortOrder,
|
|
326
|
-
|
|
342
|
+
threadCount: collection.threadCount ?? 0,
|
|
327
343
|
recentActivityAt: collection.recentActivityAt,
|
|
328
344
|
});
|
|
329
345
|
}
|
|
@@ -666,6 +682,32 @@ export class JantCollectionsManager extends LitElement {
|
|
|
666
682
|
}
|
|
667
683
|
}
|
|
668
684
|
|
|
685
|
+
async #addCollectionToNavigation(collectionId: string) {
|
|
686
|
+
if (!collectionId || this._addingToNavigationId) return;
|
|
687
|
+
|
|
688
|
+
const usesInlineNotice = this._createdCollectionId === collectionId;
|
|
689
|
+
this._showItemMenuId = null;
|
|
690
|
+
this._addingToNavigationId = collectionId;
|
|
691
|
+
document.removeEventListener("click", this.#closeItemMenu);
|
|
692
|
+
|
|
693
|
+
try {
|
|
694
|
+
await addCollectionToNavigation(collectionId);
|
|
695
|
+
this.navigationCollectionIds = [
|
|
696
|
+
...new Set([...this.navigationCollectionIds, collectionId]),
|
|
697
|
+
];
|
|
698
|
+
if (!usesInlineNotice) {
|
|
699
|
+
showToastWithAction(this.labels.addedToNavigation, {
|
|
700
|
+
label: this.labels.editNavigation,
|
|
701
|
+
href: publicPath(NAVIGATION_SETTINGS_PATH),
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
} catch {
|
|
705
|
+
showToast(this.labels.addToNavigationFailed, "error");
|
|
706
|
+
} finally {
|
|
707
|
+
this._addingToNavigationId = null;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
669
711
|
#toggleLinkEdit(item: CollectionManagerItem) {
|
|
670
712
|
if (item.type !== "link") return;
|
|
671
713
|
|
|
@@ -839,13 +881,17 @@ export class JantCollectionsManager extends LitElement {
|
|
|
839
881
|
${collection.description
|
|
840
882
|
? html`
|
|
841
883
|
<div class="collection-directory-description prose">
|
|
842
|
-
${unsafeHTML(
|
|
884
|
+
${unsafeHTML(
|
|
885
|
+
renderMarkdown(collection.description, {
|
|
886
|
+
namespace: collection.id,
|
|
887
|
+
}),
|
|
888
|
+
)}
|
|
843
889
|
</div>
|
|
844
890
|
`
|
|
845
891
|
: nothing}
|
|
846
892
|
<p class="collection-directory-summary">
|
|
847
893
|
<span class="collection-directory-meta"
|
|
848
|
-
>${this.#countLabel(collection.
|
|
894
|
+
>${this.#countLabel(collection.threadCount)}</span
|
|
849
895
|
>
|
|
850
896
|
<span class="collection-directory-meta-separator" aria-hidden="true"
|
|
851
897
|
>/</span
|
|
@@ -895,24 +941,17 @@ export class JantCollectionsManager extends LitElement {
|
|
|
895
941
|
<div
|
|
896
942
|
class=${classMap({
|
|
897
943
|
"group relative": true,
|
|
944
|
+
"collection-directory-managed-row": true,
|
|
898
945
|
"z-50":
|
|
899
946
|
this._showItemMenuId === item.id || this._editingLinkId === item.id,
|
|
900
947
|
})}
|
|
901
|
-
@mouseenter=${() => {
|
|
902
|
-
this._hoveringId = item.id;
|
|
903
|
-
}}
|
|
904
|
-
@mouseleave=${() => {
|
|
905
|
-
if (this._hoveringId === item.id) this._hoveringId = null;
|
|
906
|
-
}}
|
|
907
948
|
>
|
|
908
949
|
<div
|
|
909
950
|
class="collection-directory-item collection-directory-item-manageable"
|
|
910
951
|
>
|
|
911
952
|
${body}
|
|
912
953
|
</div>
|
|
913
|
-
${this
|
|
914
|
-
? this.#renderItemMenu(item)
|
|
915
|
-
: nothing}
|
|
954
|
+
${this.#renderItemMenu(item)}
|
|
916
955
|
</div>
|
|
917
956
|
`;
|
|
918
957
|
}
|
|
@@ -1036,7 +1075,9 @@ export class JantCollectionsManager extends LitElement {
|
|
|
1036
1075
|
${item.description
|
|
1037
1076
|
? html`
|
|
1038
1077
|
<div class="collection-directory-description prose">
|
|
1039
|
-
${unsafeHTML(
|
|
1078
|
+
${unsafeHTML(
|
|
1079
|
+
renderMarkdown(item.description, { namespace: item.id }),
|
|
1080
|
+
)}
|
|
1040
1081
|
</div>
|
|
1041
1082
|
`
|
|
1042
1083
|
: html`
|
|
@@ -1084,25 +1125,17 @@ export class JantCollectionsManager extends LitElement {
|
|
|
1084
1125
|
<div
|
|
1085
1126
|
class=${classMap({
|
|
1086
1127
|
"group relative": true,
|
|
1128
|
+
"collection-directory-managed-row": true,
|
|
1087
1129
|
"z-50":
|
|
1088
1130
|
this._showItemMenuId === item.id || this._editingLinkId === item.id,
|
|
1089
1131
|
})}
|
|
1090
|
-
@mouseenter=${() => {
|
|
1091
|
-
this._hoveringId = item.id;
|
|
1092
|
-
}}
|
|
1093
|
-
@mouseleave=${() => {
|
|
1094
|
-
if (this._hoveringId === item.id) this._hoveringId = null;
|
|
1095
|
-
}}
|
|
1096
1132
|
>
|
|
1097
1133
|
<div
|
|
1098
1134
|
class="collection-directory-item collection-directory-item-link collection-directory-item-manageable"
|
|
1099
1135
|
>
|
|
1100
1136
|
${body}
|
|
1101
1137
|
</div>
|
|
1102
|
-
${this
|
|
1103
|
-
? this.#renderItemMenu(item)
|
|
1104
|
-
: nothing}
|
|
1105
|
-
${this.#renderLinkEditPanel(item)}
|
|
1138
|
+
${this.#renderItemMenu(item)} ${this.#renderLinkEditPanel(item)}
|
|
1106
1139
|
</div>
|
|
1107
1140
|
`;
|
|
1108
1141
|
}
|
|
@@ -1166,6 +1199,31 @@ export class JantCollectionsManager extends LitElement {
|
|
|
1166
1199
|
>
|
|
1167
1200
|
${this.labels.edit}
|
|
1168
1201
|
</a>
|
|
1202
|
+
${this.navigationCollectionIds.includes(collection.id)
|
|
1203
|
+
? html`
|
|
1204
|
+
<a
|
|
1205
|
+
href=${publicPath(NAVIGATION_SETTINGS_PATH)}
|
|
1206
|
+
class="collections-page-menu-item"
|
|
1207
|
+
>
|
|
1208
|
+
${this.labels.editNavigation}
|
|
1209
|
+
</a>
|
|
1210
|
+
`
|
|
1211
|
+
: html`
|
|
1212
|
+
<button
|
|
1213
|
+
type="button"
|
|
1214
|
+
class="collections-page-menu-item"
|
|
1215
|
+
?disabled=${this._addingToNavigationId ===
|
|
1216
|
+
collection.id}
|
|
1217
|
+
@click=${() =>
|
|
1218
|
+
void this.#addCollectionToNavigation(
|
|
1219
|
+
collection.id,
|
|
1220
|
+
)}
|
|
1221
|
+
>
|
|
1222
|
+
${this._addingToNavigationId === collection.id
|
|
1223
|
+
? this.labels.addingToNavigation
|
|
1224
|
+
: this.labels.addToNavigation}
|
|
1225
|
+
</button>
|
|
1226
|
+
`}
|
|
1169
1227
|
<button
|
|
1170
1228
|
type="button"
|
|
1171
1229
|
class="collections-page-menu-item collections-page-menu-item-danger"
|
|
@@ -1398,9 +1456,86 @@ export class JantCollectionsManager extends LitElement {
|
|
|
1398
1456
|
`;
|
|
1399
1457
|
}
|
|
1400
1458
|
|
|
1459
|
+
#renderCreatedCollectionNotice() {
|
|
1460
|
+
if (!this._createdCollectionId) return nothing;
|
|
1461
|
+
|
|
1462
|
+
const collection = this._items.find(
|
|
1463
|
+
(item) => item.collection?.id === this._createdCollectionId,
|
|
1464
|
+
)?.collection;
|
|
1465
|
+
if (!collection) return nothing;
|
|
1466
|
+
|
|
1467
|
+
const isInNavigation = this.navigationCollectionIds.includes(collection.id);
|
|
1468
|
+
|
|
1469
|
+
return html`
|
|
1470
|
+
<section
|
|
1471
|
+
class="collection-created-notice"
|
|
1472
|
+
role="status"
|
|
1473
|
+
aria-labelledby="collection-created-notice-title"
|
|
1474
|
+
>
|
|
1475
|
+
<p
|
|
1476
|
+
id="collection-created-notice-title"
|
|
1477
|
+
class="collection-created-notice-message"
|
|
1478
|
+
>
|
|
1479
|
+
${isInNavigation
|
|
1480
|
+
? this.labels.addedToNavigation
|
|
1481
|
+
: this.labels.formLabels.createdLabel}
|
|
1482
|
+
</p>
|
|
1483
|
+
<div class="collection-created-notice-actions">
|
|
1484
|
+
${isInNavigation
|
|
1485
|
+
? html`
|
|
1486
|
+
<a
|
|
1487
|
+
href=${publicPath(NAVIGATION_SETTINGS_PATH)}
|
|
1488
|
+
class="collection-created-notice-action collection-created-notice-action-primary"
|
|
1489
|
+
>
|
|
1490
|
+
${this.labels.editNavigation}
|
|
1491
|
+
</a>
|
|
1492
|
+
`
|
|
1493
|
+
: html`
|
|
1494
|
+
<button
|
|
1495
|
+
type="button"
|
|
1496
|
+
class="collection-created-notice-action collection-created-notice-action-primary"
|
|
1497
|
+
?disabled=${this._addingToNavigationId === collection.id}
|
|
1498
|
+
@click=${() =>
|
|
1499
|
+
void this.#addCollectionToNavigation(collection.id)}
|
|
1500
|
+
>
|
|
1501
|
+
${this._addingToNavigationId === collection.id
|
|
1502
|
+
? this.labels.addingToNavigation
|
|
1503
|
+
: this.labels.addToNavigation}
|
|
1504
|
+
</button>
|
|
1505
|
+
`}
|
|
1506
|
+
<button
|
|
1507
|
+
type="button"
|
|
1508
|
+
class="collection-created-notice-dismiss"
|
|
1509
|
+
aria-label=${this.labels.notNow}
|
|
1510
|
+
title=${this.labels.notNow}
|
|
1511
|
+
@click=${() => {
|
|
1512
|
+
this._createdCollectionId = null;
|
|
1513
|
+
}}
|
|
1514
|
+
>
|
|
1515
|
+
<svg
|
|
1516
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
1517
|
+
width="14"
|
|
1518
|
+
height="14"
|
|
1519
|
+
viewBox="0 0 24 24"
|
|
1520
|
+
fill="none"
|
|
1521
|
+
stroke="currentColor"
|
|
1522
|
+
stroke-width="2"
|
|
1523
|
+
stroke-linecap="round"
|
|
1524
|
+
stroke-linejoin="round"
|
|
1525
|
+
aria-hidden="true"
|
|
1526
|
+
>
|
|
1527
|
+
<path d="M18 6 6 18" />
|
|
1528
|
+
<path d="m6 6 12 12" />
|
|
1529
|
+
</svg>
|
|
1530
|
+
</button>
|
|
1531
|
+
</div>
|
|
1532
|
+
</section>
|
|
1533
|
+
`;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1401
1536
|
render() {
|
|
1402
1537
|
return html`
|
|
1403
|
-
${this.#renderCreateLinkForm()}
|
|
1538
|
+
${this.#renderCreatedCollectionNotice()} ${this.#renderCreateLinkForm()}
|
|
1404
1539
|
${this.#hasDirectoryContent()
|
|
1405
1540
|
? html`
|
|
1406
1541
|
<div id="collections-manager-list" class="collection-directory">
|