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 <noreply@anthropic.com>
This commit is contained in:
@@ -93,6 +93,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Related Knowledge Base -->
|
||||||
|
<div class="section-card" v-if="app.knowledgebase && app.knowledgebase.length">
|
||||||
|
<h3 class="section-title">Knowledge Base ({{ app.knowledgebase.length }})</h3>
|
||||||
|
<div class="kb-list">
|
||||||
|
<a
|
||||||
|
v-for="kb in app.knowledgebase"
|
||||||
|
:key="kb.linkid"
|
||||||
|
:href="kb.linkurl"
|
||||||
|
target="_blank"
|
||||||
|
class="kb-item"
|
||||||
|
>
|
||||||
|
<span class="kb-title">{{ kb.shortdescription }}</span>
|
||||||
|
<span class="kb-keywords" v-if="kb.keywords">{{ kb.keywords }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right Column -->
|
<!-- Right Column -->
|
||||||
|
|||||||
@@ -40,6 +40,19 @@ def _installed_count(appid):
|
|||||||
return ComputerInstalledApp.query.filter_by(appid=appid, isactive=True).count()
|
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():
|
def _require_computer_models():
|
||||||
"""Resolve (Computer, ComputerInstalledApp) or a 503 response tuple.
|
"""Resolve (Computer, ComputerInstalledApp) or a 503 response tuple.
|
||||||
|
|
||||||
@@ -116,6 +129,7 @@ def get_application(app_id: int):
|
|||||||
data = app.to_dict()
|
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['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['installedcount'] = _installed_count(app.appid)
|
||||||
|
data['knowledgebase'] = _related_kb(app.appid)
|
||||||
|
|
||||||
return success_response(data)
|
return success_response(data)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user