feat(studio): pending-approvals sidebar badge + per-category settings help
Some checks failed
Security / Security check (push) Failing after 1s

Two operator-attention improvements:

  - The sidebar's Approvals item gains a small accent-coloured
    badge (e.g. '2', '9+') when there are pending approvals,
    polled on the same 5 s tick the health check uses. Operators
    no longer need to open the Approvals page to discover new
    pending decisions; the badge surfaces them at the rail
    level.

  - The Settings dialog's per-category panel titles grow an
    optional help icon (?) that opens the matching bundled
    docs explainer via showFaiDoc. Wired for General →
    architecture, Security → security, Maintenance → audit.
    Other categories deliberately stay un-iced for now —
    Appearance / System AI / Integrations don't yet have a
    standalone bundled doc, and showing a broken help icon
    would be worse than showing none.

Studio bumped to 0.69.0.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-09 09:41:14 +02:00
parent 5aae3285df
commit 7511867774
3 changed files with 95 additions and 15 deletions

View file

@ -11,6 +11,7 @@ import '../data/hub_auth_token.dart';
import '../data/registry_token.dart';
import '../data/system_actions.dart';
import '../l10n/app_localizations.dart';
import '../pages/welcome.dart' show showFaiDoc;
import '../theme/theme.dart';
import '../theme/tokens.dart';
import 'fai_error_box.dart';
@ -394,17 +395,35 @@ class _FaiSettingsDialogState extends State<FaiSettingsDialog> {
);
}
Widget _panelTitle(String title, String subtitle, ThemeData theme) {
Widget _panelTitle(
String title,
String subtitle,
ThemeData theme, {
String? docSlug,
}) {
return Padding(
padding: const EdgeInsets.only(bottom: FaiSpace.lg),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
Row(
children: [
Expanded(
child: Text(
title,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w700,
),
),
),
if (docSlug != null)
IconButton(
icon: const Icon(Icons.help_outline, size: 18),
tooltip: AppLocalizations.of(context)!.helpTooltip,
onPressed: () => showFaiDoc(context, docSlug),
visualDensity: VisualDensity.compact,
),
],
),
const SizedBox(height: 4),
Text(
@ -424,6 +443,7 @@ class _FaiSettingsDialogState extends State<FaiSettingsDialog> {
l.settingsTitle,
l.settingsHubEndpointHint,
theme,
docSlug: 'architecture',
),
TextField(
controller: _host,
@ -618,6 +638,7 @@ class _FaiSettingsDialogState extends State<FaiSettingsDialog> {
l.settingsSecurityPanelTitle,
l.settingsSecurityPanelBody,
theme,
docSlug: 'security',
),
_RegistryCredentialsPanel(
configuredChars: _registryTokenChars,
@ -639,6 +660,7 @@ class _FaiSettingsDialogState extends State<FaiSettingsDialog> {
l.settingsMaintenancePanelTitle,
l.settingsMaintenancePanelBody,
theme,
docSlug: 'audit',
),
_MaintenancePanel(
onResetDone: () async {