Add per-domain global-search toggles
Lets an admin choose which content types appear in global search results, independent of whether the owning plugin is enabled (the existing _require_enabled gating was all-or-nothing per plugin). - settings.py: SEARCH_DOMAINS const (9 result types: application, knowledgebase, employee, equipment, computer, printer, network_device, notification, subnet) + seed keys search_<type>_enabled (boolean, default true) in build_default_settings (covers API seed + CLI). - search.py: global_search loads disabled types in one query (category 'search') and filters the deduped results by type before counts/truncation. Missing key = enabled. - SystemSettings.vue: "Global Search" section, one toggle per domain (mirrors the identifier pattern; create-on-404 fallback so an un-reseeded deploy still works). - Tests: domain included by default, disabled domain excluded, seed creates the 9 keys. 166 tests pass, naming green, build green. Verified live: toggling search_knowledgebase_enabled off drops knowledgebase from search counts and back on restores it. Dev DB seeded (9 keys). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ from sqlalchemy.orm import joinedload
|
||||
|
||||
from shopdb.extensions import db
|
||||
from shopdb.core.models import (
|
||||
Application,
|
||||
Application, Setting,
|
||||
Asset, AssetType, Communication, Vendor, Model
|
||||
)
|
||||
from shopdb.utils.responses import success_response
|
||||
@@ -718,6 +718,16 @@ def global_search():
|
||||
seen_ids[key] = True
|
||||
unique_results.append(r)
|
||||
|
||||
# Drop result types disabled in Settings > Search (search_<type>_enabled).
|
||||
# Missing key = enabled. One query, default-on.
|
||||
disabled_types = {
|
||||
s.key[len('search_'):-len('_enabled')]
|
||||
for s in Setting.query.filter_by(category='search').all()
|
||||
if s.get_typed_value() is False
|
||||
}
|
||||
if disabled_types:
|
||||
unique_results = [r for r in unique_results if r['type'] not in disabled_types]
|
||||
|
||||
# Compute type counts before truncation
|
||||
type_counts = {}
|
||||
for r in unique_results:
|
||||
|
||||
@@ -27,6 +27,22 @@ IDENTIFIER_LABELS = {
|
||||
}
|
||||
IDENTIFIER_ASSETTYPES = ['equipment', 'computer', 'printer', 'network_device']
|
||||
|
||||
# Global-search result types that can be toggled on/off independently of whether
|
||||
# the owning plugin is enabled. Keys match the `type` field on search results;
|
||||
# seed keys are search_<type>_enabled (boolean, default true). Drives the
|
||||
# Settings "Search" toggles and the filter in shopdb/core/api/search.py.
|
||||
SEARCH_DOMAINS = {
|
||||
'application': 'Applications',
|
||||
'knowledgebase': 'Knowledge Base',
|
||||
'employee': 'Employees',
|
||||
'equipment': 'Equipment',
|
||||
'computer': 'PCs',
|
||||
'printer': 'Printers',
|
||||
'network_device': 'Network Devices',
|
||||
'notification': 'Notifications',
|
||||
'subnet': 'Subnets',
|
||||
}
|
||||
|
||||
|
||||
def _is_secret(key: str) -> bool:
|
||||
return 'password' in key or 'token' in key or 'secret' in key
|
||||
@@ -182,7 +198,19 @@ def build_default_settings():
|
||||
for assettype in IDENTIFIER_ASSETTYPES
|
||||
]
|
||||
|
||||
defaults = identifierdefaults + [
|
||||
# Per-domain global-search toggles (search_<type>_enabled).
|
||||
searchdefaults = [
|
||||
{
|
||||
'key': f'search_{key}_enabled',
|
||||
'value': 'true',
|
||||
'valuetype': 'boolean',
|
||||
'category': 'search',
|
||||
'description': f'Include {label} in global search results',
|
||||
}
|
||||
for key, label in SEARCH_DOMAINS.items()
|
||||
]
|
||||
|
||||
defaults = identifierdefaults + searchdefaults + [
|
||||
# Zabbix integration
|
||||
{
|
||||
'key': 'zabbix_enabled',
|
||||
|
||||
Reference in New Issue
Block a user