fix(approvals): usertest-panel hardening (0.81.0)

Panel findings against the reworked approvals page, fixed in place:

- Never fabricate the request time: ApprovalRecord.createdAt is
  nullable now; a missing created_at omits the line instead of
  rendering DateTime.now() (which drifted on refresh). Guard:
  approvals_origin_test pins the omit-on-null invariant.
- Copyable errors on approve/reject/batch via showChainErrorSnack
  (the hard project rule) — batch surfaces the first real cause.
- Reject requires a reason: ChainInlineHelp strip + confirm disabled
  while empty, no more silent close-and-nothing-happens.
- Batch approve applies the same no-data confirmation as the single
  path, naming how many selected requests carry no show: data.
- Plainer language: glossary "Vorgang (Flow)", history label FRAGE
  (was PROMPT), no-data hint drops developer jargon.
- One-click copy of the run id; history payload pretty-prints like
  the card.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-07-26 16:05:55 +02:00
parent 28f6fe1a9a
commit f7d7427d91
9 changed files with 411 additions and 122 deletions

View file

@ -2037,7 +2037,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get approvalsNoPayload =>
'Keine Daten zum Prüfen angehängt. Der system.approval-Schritt des Flows bestimmt über sein \"show:\"-Feld, was angezeigt wird — setzen Sie es, um die Daten hinter dieser Entscheidung sichtbar zu machen.';
'Zu dieser Freigabe wurden keine Daten hinterlegt. Sie entscheiden ohne Detailansicht — fragen Sie im Zweifel die Person, die den Vorgang eingerichtet hat. (Technisch: das Feld \"show:\" des Freigabe-Schritts legt fest, was hier erscheint.)';
@override
String get approvalsNoDataConfirmTitle => 'Ohne Prüfdaten freigeben?';
@ -2060,7 +2060,40 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get approvalsIntroHelp =>
'Hier warten pausierte Flows auf Ihre Entscheidung. Jede Karte zeigt, welcher Flow an welchem Schritt hält und welche Daten er Ihnen vorlegt — Freigeben setzt den Flow fort, Ablehnen stoppt ihn mit Ihrer Begründung.';
'Hier warten pausierte Vorgänge (Flows) auf Ihre Entscheidung. Jede Karte zeigt, welcher Vorgang an welchem Schritt hält und welche Daten er Ihnen vorlegt — Freigeben setzt ihn fort, Ablehnen stoppt ihn mit Ihrer Begründung.';
@override
String get approvalsRejectDialogHelp =>
'Die Ablehnung stoppt den Vorgang an diesem Schritt und wird mit Ihrer Begründung im Prüfprotokoll festgehalten.';
@override
String get approvalsRejectReasonHelper =>
'Pflichtfeld — wird im Prüfprotokoll (Audit-Log) festgehalten.';
@override
String get approvalsBatchNoDataTitle => 'Ohne Prüfdaten freigeben?';
@override
String approvalsBatchNoDataBody(num count, Object total) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other:
'Von $total ausgewählten Freigaben haben $count keine Prüfdaten. Sie geben sie ohne Detailansicht frei.',
one:
'Von $total ausgewählten Freigaben hat 1 keine Prüfdaten. Sie geben sie ohne Detailansicht frei.',
);
return '$_temp0';
}
@override
String get approvalsCopyRun => 'Lauf-Kennung kopieren';
@override
String get approvalsRunCopied => 'Lauf-Kennung kopiert';
@override
String get approvalsUnknownReviewer => '(unbekannt)';
@override
String get approvalsOriginLabel => 'HERKUNFT';
@ -2090,8 +2123,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get approvalsRejectDialogTitle => 'Freigabe ablehnen';
@override
String get approvalsRejectReasonLabel =>
'Begründung (im Audit-Log festgehalten)';
String get approvalsRejectReasonLabel => 'Begründung';
@override
String approvalsApprovedToast(String flow, String step) {
@ -2130,7 +2162,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get approvalsDialogReason => 'Begründung';
@override
String get approvalsDialogPrompt => 'PROMPT';
String get approvalsDialogPrompt => 'FRAGE';
@override
String approvalsExpiresIn(int minutes) {