fix(ux): quick wins from the usertest medium list
Some checks are pending
Security / Security check (push) Waiting to run
Some checks are pending
Security / Security check (push) Waiting to run
- audit type filter: 'Alle'/'All' capitalized like every other label - settings -> setup wizard: close Settings first (one modal layer), stronger wizard scrim - try-out setup profile discloses the upgrade path to a regulated profile - store maturity pills explain themselves on hover (experimental/ published/planned) Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
ae97b88257
commit
eab58c0b68
8 changed files with 93 additions and 26 deletions
|
|
@ -317,6 +317,9 @@
|
||||||
"storeStatusAll": "Alle",
|
"storeStatusAll": "Alle",
|
||||||
"storeStatusPublished": "stabil",
|
"storeStatusPublished": "stabil",
|
||||||
"storeStatusAlpha": "experimentell",
|
"storeStatusAlpha": "experimentell",
|
||||||
|
"storeStatusAlphaHelp": "Frühe Version: läuft, wird aber noch weiterentwickelt und ist nicht für den regulierten Produktivbetrieb freigegeben.",
|
||||||
|
"storeStatusPublishedHelp": "Vom Herausgeber für den allgemeinen Einsatz freigegeben.",
|
||||||
|
"storeStatusPlannedHelp": "Angekündigt, aber noch nicht verfügbar.",
|
||||||
"storeStatusPlanned": "geplant",
|
"storeStatusPlanned": "geplant",
|
||||||
"storeInstalledOnly": "Installiert",
|
"storeInstalledOnly": "Installiert",
|
||||||
"storeCategoryLabel": "Kategorie",
|
"storeCategoryLabel": "Kategorie",
|
||||||
|
|
@ -555,7 +558,7 @@
|
||||||
"auditTitle": "Protokoll",
|
"auditTitle": "Protokoll",
|
||||||
"auditNoEvents": "Noch keine Ereignisse",
|
"auditNoEvents": "Noch keine Ereignisse",
|
||||||
"auditNoEventsHint": "Starten Sie einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.",
|
"auditNoEventsHint": "Starten Sie einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.",
|
||||||
"auditFilterAll": "alle",
|
"auditFilterAll": "Alle",
|
||||||
"auditFilterFlow": "Flow",
|
"auditFilterFlow": "Flow",
|
||||||
"auditFilterStep": "Schritt",
|
"auditFilterStep": "Schritt",
|
||||||
"auditFilterModule": "Modul",
|
"auditFilterModule": "Modul",
|
||||||
|
|
@ -1778,7 +1781,7 @@
|
||||||
"setupReviewTitle": "Das wird Ch∆In einrichten",
|
"setupReviewTitle": "Das wird Ch∆In einrichten",
|
||||||
"setupChooseFreeText": "Oder beschreiben Sie einfach, was Sie vorhaben",
|
"setupChooseFreeText": "Oder beschreiben Sie einfach, was Sie vorhaben",
|
||||||
"setupScenTryingOut": "Erst mal ausprobieren",
|
"setupScenTryingOut": "Erst mal ausprobieren",
|
||||||
"setupScenTryingOutSub": "Ein unkomplizierter Arbeitsplatz auf diesem Rechner — ohne Signaturpflicht, ohne Schreibschutz für das Prüfprotokoll.",
|
"setupScenTryingOutSub": "Ein unkomplizierter Arbeitsplatz auf diesem Rechner — ohne Signaturpflicht, ohne Schreibschutz für das Prüfprotokoll. Später jederzeit hochstufbar: die Einrichtung erneut ausführen und ein reguliertes Profil wählen.",
|
||||||
"setupScenTeamHub": "Ein Team-Server",
|
"setupScenTeamHub": "Ein Team-Server",
|
||||||
"setupScenTeamHubSub": "Ein abgesicherter Hub für mehrere Personen — signierte Module, Ressourcen-Grenzen.",
|
"setupScenTeamHubSub": "Ein abgesicherter Hub für mehrere Personen — signierte Module, Ressourcen-Grenzen.",
|
||||||
"setupScenRegulated": "Regulierter Produktivbetrieb",
|
"setupScenRegulated": "Regulierter Produktivbetrieb",
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,9 @@
|
||||||
"storeStatusAll": "All",
|
"storeStatusAll": "All",
|
||||||
"storeStatusPublished": "stable",
|
"storeStatusPublished": "stable",
|
||||||
"storeStatusAlpha": "experimental",
|
"storeStatusAlpha": "experimental",
|
||||||
|
"storeStatusAlphaHelp": "Early version: it works, but it is still evolving and not cleared for regulated production use.",
|
||||||
|
"storeStatusPublishedHelp": "Cleared by the publisher for general use.",
|
||||||
|
"storeStatusPlannedHelp": "Announced, but not available yet.",
|
||||||
"storeStatusPlanned": "coming soon",
|
"storeStatusPlanned": "coming soon",
|
||||||
"storeInstalledOnly": "Installed",
|
"storeInstalledOnly": "Installed",
|
||||||
"storeCategoryLabel": "Category",
|
"storeCategoryLabel": "Category",
|
||||||
|
|
@ -573,7 +576,7 @@
|
||||||
"auditTitle": "Audit",
|
"auditTitle": "Audit",
|
||||||
"auditNoEvents": "No events yet",
|
"auditNoEvents": "No events yet",
|
||||||
"auditNoEventsHint": "Run a flow to populate the audit stream.\nEvents appear here within seconds.",
|
"auditNoEventsHint": "Run a flow to populate the audit stream.\nEvents appear here within seconds.",
|
||||||
"auditFilterAll": "all",
|
"auditFilterAll": "All",
|
||||||
"auditFilterFlow": "flow",
|
"auditFilterFlow": "flow",
|
||||||
"auditFilterStep": "step",
|
"auditFilterStep": "step",
|
||||||
"auditFilterModule": "module",
|
"auditFilterModule": "module",
|
||||||
|
|
@ -1817,7 +1820,7 @@
|
||||||
"setupReviewTitle": "This is what Ch∆In will set up",
|
"setupReviewTitle": "This is what Ch∆In will set up",
|
||||||
"setupChooseFreeText": "Or just describe what you want to do",
|
"setupChooseFreeText": "Or just describe what you want to do",
|
||||||
"setupScenTryingOut": "Just trying it out",
|
"setupScenTryingOut": "Just trying it out",
|
||||||
"setupScenTryingOutSub": "A straightforward workstation on this machine — no signature requirement, no write-protected audit log.",
|
"setupScenTryingOutSub": "A straightforward workstation on this machine — no signature requirement, no write-protected audit log. You can upgrade any time: run the setup again and pick a regulated profile.",
|
||||||
"setupScenTeamHub": "A shared team hub",
|
"setupScenTeamHub": "A shared team hub",
|
||||||
"setupScenTeamHubSub": "A secured hub for several people — signed modules, resource limits.",
|
"setupScenTeamHubSub": "A secured hub for several people — signed modules, resource limits.",
|
||||||
"setupScenRegulated": "Regulated production",
|
"setupScenRegulated": "Regulated production",
|
||||||
|
|
|
||||||
|
|
@ -1466,6 +1466,24 @@ abstract class AppLocalizations {
|
||||||
/// **'experimental'**
|
/// **'experimental'**
|
||||||
String get storeStatusAlpha;
|
String get storeStatusAlpha;
|
||||||
|
|
||||||
|
/// No description provided for @storeStatusAlphaHelp.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Early version: it works, but it is still evolving and not cleared for regulated production use.'**
|
||||||
|
String get storeStatusAlphaHelp;
|
||||||
|
|
||||||
|
/// No description provided for @storeStatusPublishedHelp.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Cleared by the publisher for general use.'**
|
||||||
|
String get storeStatusPublishedHelp;
|
||||||
|
|
||||||
|
/// No description provided for @storeStatusPlannedHelp.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Announced, but not available yet.'**
|
||||||
|
String get storeStatusPlannedHelp;
|
||||||
|
|
||||||
/// No description provided for @storeStatusPlanned.
|
/// No description provided for @storeStatusPlanned.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
@ -2093,7 +2111,7 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @auditFilterAll.
|
/// No description provided for @auditFilterAll.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'all'**
|
/// **'All'**
|
||||||
String get auditFilterAll;
|
String get auditFilterAll;
|
||||||
|
|
||||||
/// No description provided for @auditFilterFlow.
|
/// No description provided for @auditFilterFlow.
|
||||||
|
|
@ -5470,7 +5488,7 @@ abstract class AppLocalizations {
|
||||||
/// No description provided for @setupScenTryingOutSub.
|
/// No description provided for @setupScenTryingOutSub.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'A straightforward workstation on this machine — no signature requirement, no write-protected audit log.'**
|
/// **'A straightforward workstation on this machine — no signature requirement, no write-protected audit log. You can upgrade any time: run the setup again and pick a regulated profile.'**
|
||||||
String get setupScenTryingOutSub;
|
String get setupScenTryingOutSub;
|
||||||
|
|
||||||
/// No description provided for @setupScenTeamHub.
|
/// No description provided for @setupScenTeamHub.
|
||||||
|
|
|
||||||
|
|
@ -793,6 +793,18 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get storeStatusAlpha => 'experimentell';
|
String get storeStatusAlpha => 'experimentell';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusAlphaHelp =>
|
||||||
|
'Frühe Version: läuft, wird aber noch weiterentwickelt und ist nicht für den regulierten Produktivbetrieb freigegeben.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusPublishedHelp =>
|
||||||
|
'Vom Herausgeber für den allgemeinen Einsatz freigegeben.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusPlannedHelp =>
|
||||||
|
'Angekündigt, aber noch nicht verfügbar.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get storeStatusPlanned => 'geplant';
|
String get storeStatusPlanned => 'geplant';
|
||||||
|
|
||||||
|
|
@ -1164,7 +1176,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
'Starten Sie einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.';
|
'Starten Sie einen Flow, um den Audit-Stream zu füllen.\nEreignisse erscheinen innerhalb von Sekunden.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get auditFilterAll => 'alle';
|
String get auditFilterAll => 'Alle';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get auditFilterFlow => 'Flow';
|
String get auditFilterFlow => 'Flow';
|
||||||
|
|
@ -3237,7 +3249,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get setupScenTryingOutSub =>
|
String get setupScenTryingOutSub =>
|
||||||
'Ein unkomplizierter Arbeitsplatz auf diesem Rechner — ohne Signaturpflicht, ohne Schreibschutz für das Prüfprotokoll.';
|
'Ein unkomplizierter Arbeitsplatz auf diesem Rechner — ohne Signaturpflicht, ohne Schreibschutz für das Prüfprotokoll. Später jederzeit hochstufbar: die Einrichtung erneut ausführen und ein reguliertes Profil wählen.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get setupScenTeamHub => 'Ein Team-Server';
|
String get setupScenTeamHub => 'Ein Team-Server';
|
||||||
|
|
|
||||||
|
|
@ -806,6 +806,17 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get storeStatusAlpha => 'experimental';
|
String get storeStatusAlpha => 'experimental';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusAlphaHelp =>
|
||||||
|
'Early version: it works, but it is still evolving and not cleared for regulated production use.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusPublishedHelp =>
|
||||||
|
'Cleared by the publisher for general use.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get storeStatusPlannedHelp => 'Announced, but not available yet.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get storeStatusPlanned => 'coming soon';
|
String get storeStatusPlanned => 'coming soon';
|
||||||
|
|
||||||
|
|
@ -1181,7 +1192,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
'Run a flow to populate the audit stream.\nEvents appear here within seconds.';
|
'Run a flow to populate the audit stream.\nEvents appear here within seconds.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get auditFilterAll => 'all';
|
String get auditFilterAll => 'All';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get auditFilterFlow => 'flow';
|
String get auditFilterFlow => 'flow';
|
||||||
|
|
@ -3237,7 +3248,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get setupScenTryingOutSub =>
|
String get setupScenTryingOutSub =>
|
||||||
'A straightforward workstation on this machine — no signature requirement, no write-protected audit log.';
|
'A straightforward workstation on this machine — no signature requirement, no write-protected audit log. You can upgrade any time: run the setup again and pick a regulated profile.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get setupScenTeamHub => 'A shared team hub';
|
String get setupScenTeamHub => 'A shared team hub';
|
||||||
|
|
|
||||||
|
|
@ -897,6 +897,25 @@ String _statusDisplayName(BuildContext ctx, String wire) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maturity pill with an inline explanation on hover — "experimental"
|
||||||
|
/// alone left buyers guessing what it means for production use
|
||||||
|
/// (usertest finding). Unknown wire values get a plain pill.
|
||||||
|
Widget _statusPill(BuildContext ctx, String wire) {
|
||||||
|
final l = AppLocalizations.of(ctx)!;
|
||||||
|
final pill = ChainPill(
|
||||||
|
label: _statusDisplayName(ctx, wire),
|
||||||
|
tone: _toneForStatus(wire),
|
||||||
|
);
|
||||||
|
final help = switch (wire) {
|
||||||
|
'published' => l.storeStatusPublishedHelp,
|
||||||
|
'alpha' => l.storeStatusAlphaHelp,
|
||||||
|
'planned' => l.storeStatusPlannedHelp,
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
if (help == null) return pill;
|
||||||
|
return Tooltip(message: help, child: pill);
|
||||||
|
}
|
||||||
|
|
||||||
/// Multi-line ask-and-search input. Drives the toolbar's
|
/// Multi-line ask-and-search input. Drives the toolbar's
|
||||||
/// primary action: substring keyword search on every keystroke
|
/// primary action: substring keyword search on every keystroke
|
||||||
/// (cheap, identical to the legacy `_SearchField`) plus an
|
/// (cheap, identical to the legacy `_SearchField`) plus an
|
||||||
|
|
@ -1925,10 +1944,7 @@ class _FeaturedTile extends StatelessWidget {
|
||||||
),
|
),
|
||||||
const SizedBox(width: ChainSpace.xs),
|
const SizedBox(width: ChainSpace.xs),
|
||||||
if (item.status.isNotEmpty)
|
if (item.status.isNotEmpty)
|
||||||
ChainPill(
|
_statusPill(context, item.status),
|
||||||
label: _statusDisplayName(context, item.status),
|
|
||||||
tone: _toneForStatus(item.status),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (item.installed)
|
if (item.installed)
|
||||||
ChainPill(
|
ChainPill(
|
||||||
|
|
@ -2114,10 +2130,7 @@ class _StoreCardState extends State<_StoreCard> {
|
||||||
icon: Icons.check,
|
icon: Icons.check,
|
||||||
)
|
)
|
||||||
else if (item.status.isNotEmpty)
|
else if (item.status.isNotEmpty)
|
||||||
ChainPill(
|
_statusPill(context, item.status),
|
||||||
label: _statusDisplayName(context, item.status),
|
|
||||||
tone: _toneForStatus(item.status),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: ChainSpace.sm),
|
const SizedBox(height: ChainSpace.sm),
|
||||||
|
|
@ -2490,13 +2503,7 @@ class _StoreDetailSheetState extends State<_StoreDetailSheet> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (item.status.isNotEmpty)
|
if (item.status.isNotEmpty)
|
||||||
ChainPill(
|
_statusPill(context, item.status),
|
||||||
label: _statusDisplayName(
|
|
||||||
context,
|
|
||||||
item.status,
|
|
||||||
),
|
|
||||||
tone: _toneForStatus(item.status),
|
|
||||||
),
|
|
||||||
if (item.category.isNotEmpty)
|
if (item.category.isNotEmpty)
|
||||||
ChainPill(
|
ChainPill(
|
||||||
label: _categoryDisplayName(
|
label: _categoryDisplayName(
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,16 @@ class _FaiSettingsDialogState extends State<ChainSettingsDialog> {
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: OutlinedButton.icon(
|
child: OutlinedButton.icon(
|
||||||
onPressed: () => GuidedSetupDialog.show(context),
|
onPressed: () {
|
||||||
|
// One modal layer at a time: close Settings first so the
|
||||||
|
// wizard doesn't float over a half-visible dialog with
|
||||||
|
// stray text fragments around it (usertest finding).
|
||||||
|
final nav = Navigator.of(context);
|
||||||
|
nav.pop(false);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (nav.context.mounted) GuidedSetupDialog.show(nav.context);
|
||||||
|
});
|
||||||
|
},
|
||||||
icon: const Icon(Icons.auto_fix_high, size: 18),
|
icon: const Icon(Icons.auto_fix_high, size: 18),
|
||||||
label: Text(l.settingsRunSetup),
|
label: Text(l.settingsRunSetup),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,10 @@ class GuidedSetupDialog extends StatefulWidget {
|
||||||
return showDialog<void>(
|
return showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
|
// Stronger than the default scrim: the wizard is a focused,
|
||||||
|
// multi-step flow — whatever lies beneath must read as
|
||||||
|
// background, not as competing UI.
|
||||||
|
barrierColor: Colors.black.withValues(alpha: 0.72),
|
||||||
builder: (_) => GuidedSetupDialog(shell: shell),
|
builder: (_) => GuidedSetupDialog(shell: shell),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue