From a15f0ce24b265634b9307a202b9bef38724d8576 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Wed, 5 Aug 2026 07:36:58 +0200 Subject: [PATCH] Point the engine Explore action at the git repository The engine pages' repo metadata (new in the wiki pages API) drives the Explore button and card title links, with the wiki page as fallback. The never-deployed /engines/:slug detail page and its store/api plumbing are gone, and the engines RSS feed links to the repos too. --- .../app/controllers/api/wiki_controller.rb | 1 + apps/api/app/services/rss_service.rb | 3 +- apps/frontend/src/api/wiki.api.ts | 28 +---- apps/frontend/src/i18n/locales/en.ts | 2 - apps/frontend/src/i18n/locales/hu.ts | 2 - .../src/lib/interfaces/wiki.interface.ts | 1 + .../src/page/engines/EngineShowPage.vue | 110 ------------------ .../src/page/engines/EnginesIndexPage.vue | 16 ++- apps/frontend/src/router/engines.router.ts | 1 - apps/frontend/src/stores/engines.store.ts | 22 +--- 10 files changed, 21 insertions(+), 165 deletions(-) delete mode 100644 apps/frontend/src/page/engines/EngineShowPage.vue diff --git a/apps/api/app/controllers/api/wiki_controller.rb b/apps/api/app/controllers/api/wiki_controller.rb index 98ba040..58c32de 100644 --- a/apps/api/app/controllers/api/wiki_controller.rb +++ b/apps/api/app/controllers/api/wiki_controller.rb @@ -20,6 +20,7 @@ class Api::WikiController < ApiController property :locale, String, desc: "Locale code" property :route, String, desc: "URL slug" property :tags, Array, of: String, desc: "Tags" + property :repo, String, desc: "Git repository URL (from page metadata, engines)" property :render, String, desc: "Rendered HTML content" property :content, String, desc: "Raw markdown content" end diff --git a/apps/api/app/services/rss_service.rb b/apps/api/app/services/rss_service.rb index 28f26e3..a42c6fc 100644 --- a/apps/api/app/services/rss_service.rb +++ b/apps/api/app/services/rss_service.rb @@ -62,9 +62,8 @@ class RssService items.each do |page| maker.items.new_item do |item| - slug = page["path"].to_s.split("/").last item.title = page["title"] - item.link = "#{SITE_URL}/engines/#{slug}" + item.link = page["repo"].presence || "#{WIKI_URL}/#{page["path"]}" item.description = page["description"].to_s item.pubDate = Time.parse(page["createdAt"]) rescue Time.current end diff --git a/apps/frontend/src/api/wiki.api.ts b/apps/frontend/src/api/wiki.api.ts index 6a3c799..c91e806 100644 --- a/apps/frontend/src/api/wiki.api.ts +++ b/apps/frontend/src/api/wiki.api.ts @@ -15,6 +15,7 @@ interface RawWikiPage { updatedAt: string createdAt: string locale: string + repo?: string | null } async function fetchPages( @@ -67,10 +68,6 @@ const getBlogPage = async (slug: string): Promise => { } } -// Engine pages live scattered in the wiki tree (infrastructure/, others/, …), -// so the site slug is the last path segment: others/rubbs -> rubbs. -const engineSlug = (path: string): string => path.split('/').filter(Boolean).pop() ?? path - const listEnginePages = async (): Promise => { const pages = await fetchPages('engine', { body: true }) return pages.map((p): WikiPageWithContent => ({ @@ -82,27 +79,10 @@ const listEnginePages = async (): Promise => { updatedAt: p.updatedAt, createdAt: p.createdAt, locale: p.locale, + repo: p.repo ?? null, })) } -const getEnginePage = async (slug: string): Promise => { - const pages = await fetchPages('engine', { body: true }) - - const matched = pages.find((p) => engineSlug(p.path) === slug) - if (!matched) return null - - return { - id: matched.id, - path: matched.path, - title: matched.title || matched.path, - description: matched.description ?? '', - render: matched.render ?? '', - updatedAt: matched.updatedAt, - createdAt: matched.createdAt, - locale: matched.locale, - } -} - const listHowtoPages = async (): Promise => { const pages = await fetchPages('howto', { limit: 30 }) return pages.map((p): WikiPage => ({ @@ -116,5 +96,5 @@ const listHowtoPages = async (): Promise => { })) } -export { WIKI_BASE, engineSlug } -export default { listBlogPages, getBlogPage, listHowtoPages, listEnginePages, getEnginePage } +export { WIKI_BASE } +export default { listBlogPages, getBlogPage, listHowtoPages, listEnginePages } diff --git a/apps/frontend/src/i18n/locales/en.ts b/apps/frontend/src/i18n/locales/en.ts index 2bf4ea5..00918f6 100644 --- a/apps/frontend/src/i18n/locales/en.ts +++ b/apps/frontend/src/i18n/locales/en.ts @@ -180,8 +180,6 @@ export default { new: 'New', explore: 'Explore', openWiki: 'Open in Wiki', - back: 'Back to Engines', - noContent: 'No content available for this engine.', }, howtos: { badge: 'Knowledge Base', diff --git a/apps/frontend/src/i18n/locales/hu.ts b/apps/frontend/src/i18n/locales/hu.ts index d608090..90f1e07 100644 --- a/apps/frontend/src/i18n/locales/hu.ts +++ b/apps/frontend/src/i18n/locales/hu.ts @@ -180,8 +180,6 @@ export default { new: 'Új', explore: 'Felfedezés', openWiki: 'Megnyitás a Wikiben', - back: 'Vissza az Engine-ekhez', - noContent: 'Ehhez az engine-hez nincs elérhető tartalom.', }, howtos: { badge: 'Tudásbázis', diff --git a/apps/frontend/src/lib/interfaces/wiki.interface.ts b/apps/frontend/src/lib/interfaces/wiki.interface.ts index 1cb2a4a..8149a24 100644 --- a/apps/frontend/src/lib/interfaces/wiki.interface.ts +++ b/apps/frontend/src/lib/interfaces/wiki.interface.ts @@ -6,6 +6,7 @@ export interface WikiPage { updatedAt: string createdAt: string locale: string + repo?: string | null } export interface WikiPageWithContent extends WikiPage { diff --git a/apps/frontend/src/page/engines/EngineShowPage.vue b/apps/frontend/src/page/engines/EngineShowPage.vue deleted file mode 100644 index 558ec42..0000000 --- a/apps/frontend/src/page/engines/EngineShowPage.vue +++ /dev/null @@ -1,110 +0,0 @@ - - - - - diff --git a/apps/frontend/src/page/engines/EnginesIndexPage.vue b/apps/frontend/src/page/engines/EnginesIndexPage.vue index 2af16cf..bf9162d 100644 --- a/apps/frontend/src/page/engines/EnginesIndexPage.vue +++ b/apps/frontend/src/page/engines/EnginesIndexPage.vue @@ -48,17 +48,18 @@

- {{ page.title }} + {{ page.title }}

{{ page.description }}

{{ getCleanPreview(page.content) }}

- + + {{ t('engines.explore') }} - + {{ t('engines.openWiki') }} @@ -73,18 +74,23 @@ diff --git a/apps/frontend/src/router/engines.router.ts b/apps/frontend/src/router/engines.router.ts index b67cba8..680afbf 100644 --- a/apps/frontend/src/router/engines.router.ts +++ b/apps/frontend/src/router/engines.router.ts @@ -2,5 +2,4 @@ import type { RouteRecordRaw } from 'vue-router' export const enginesRouter: RouteRecordRaw[] = [ { path: '/engines', name: 'enginesIndex', component: () => import('../page/engines/EnginesIndexPage.vue') }, - { path: '/engines/:slug', name: 'engineShow', component: () => import('../page/engines/EngineShowPage.vue') }, ] diff --git a/apps/frontend/src/stores/engines.store.ts b/apps/frontend/src/stores/engines.store.ts index c9df43d..7359eab 100644 --- a/apps/frontend/src/stores/engines.store.ts +++ b/apps/frontend/src/stores/engines.store.ts @@ -1,40 +1,24 @@ import { defineStore } from 'pinia' import { ref } from 'vue' -import wikiApi, { engineSlug } from '../api/wiki.api' +import wikiApi from '../api/wiki.api' import { isNew } from '../lib/softwareUtils' import { useLoadable } from '../composables/useLoadable' -import type { WikiPageWithContent, WikiPageContent } from '../lib/interfaces/wiki.interface' +import type { WikiPageWithContent } from '../lib/interfaces/wiki.interface' export const useEnginesStore = defineStore('engines', () => { const pages = ref([]) const { loading, error, withCache, invalidate } = useLoadable() - const currentPage = ref(null) - const { loading: pageLoading, error: pageError, withCache: withPageCache } = useLoadable(0) - async function fetch() { await withCache(async () => { pages.value = await wikiApi.listEnginePages() }) } - async function fetchPage(slug: string) { - currentPage.value = null - await withPageCache(async () => { - const result = await wikiApi.getEnginePage(slug) - if (!result) throw new Error('Engine not found') - currentPage.value = result - }) - } - - function getPermalink(path: string): string { - return `/engines/${engineSlug(path)}` - } - function getCleanPreview(content: string): string { if (!content) return '' return content.replace(/[#*`_[\]()>|-]/g, '').replace(/\s+/g, ' ').trim().slice(0, 260) + '...' } - return { pages, loading, error, currentPage, pageLoading, pageError, fetch, fetchPage, isNew, getPermalink, getCleanPreview, invalidate } + return { pages, loading, error, fetch, isNew, getCleanPreview, invalidate } })