From 6d843e46e1934087e2e41a459fea747535798db8 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Mon, 13 Jul 2026 13:44:23 -0400 Subject: [PATCH] Applications: show related knowledge-base articles on the app detail Classic ShopDB listed an application's related KB articles on its page; the flask app detail didn't, even though KB articles carry an appid FK. get_application now returns a knowledgebase list (KB rows linked by appid; lazy + plugin-guarded so core stays decoupled), and ApplicationDetail.vue renders a Knowledge Base section linking each article. Verified: an app returns its linked KB (e.g. 77 articles) and the section renders. Co-Authored-By: Claude Opus 4.8 --- .../views/applications/ApplicationDetail.vue | 17 +++++++++++++++++ shopdb/core/api/applications.py | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/frontend/src/views/applications/ApplicationDetail.vue b/frontend/src/views/applications/ApplicationDetail.vue index 180bb46..1f93ab3 100644 --- a/frontend/src/views/applications/ApplicationDetail.vue +++ b/frontend/src/views/applications/ApplicationDetail.vue @@ -93,6 +93,23 @@ + + +
+

Knowledge Base ({{ app.knowledgebase.length }})

+ +
diff --git a/shopdb/core/api/applications.py b/shopdb/core/api/applications.py index ed0c05d..8e4d1ba 100644 --- a/shopdb/core/api/applications.py +++ b/shopdb/core/api/applications.py @@ -40,6 +40,19 @@ def _installed_count(appid): return ComputerInstalledApp.query.filter_by(appid=appid, isactive=True).count() +def _related_kb(appid): + """Knowledge Base articles linked to this app, [] when the KB plugin is + absent. Lazy + guarded so core stays decoupled from the plugin.""" + try: + from plugins.knowledgebase.models import KnowledgeBase + except ImportError: + return [] + rows = KnowledgeBase.query.filter_by(appid=appid, isactive=True).order_by( + KnowledgeBase.shortdescription).all() + return [{'linkid': k.linkid, 'shortdescription': k.shortdescription, + 'linkurl': k.linkurl, 'keywords': k.keywords} for k in rows] + + def _require_computer_models(): """Resolve (Computer, ComputerInstalledApp) or a 503 response tuple. @@ -116,6 +129,7 @@ def get_application(app_id: int): data = app.to_dict() data['versions'] = [v.to_dict() for v in app.versions.filter_by(isactive=True).order_by(AppVersion.version.desc()).all()] data['installedcount'] = _installed_count(app.appid) + data['knowledgebase'] = _related_kb(app.appid) return success_response(data)