fix: Admin-UX aus dem Review – Live-Gruppenfeedback, Protokollfilter, Divi-Hinweis, Rollen-Rückfrage
- Tools: „Ganze Gruppe“ und „Nur lesen“ wirken sofort auf die Zeilen (Option „wie Gruppe (…)“, gesperrte Selects mit Hinweis), der Server bleibt die Wahrheit; Markup trägt die nötigen data-Attribute. - Protokoll: Filter in eigenem Block über der Tabelle (Core blendet .tablenav .actions auf Telefonen aus); „Protokoll leeren“ nur bei Einträgen, rechtsbündig, mit Gesamtzahl über ChangeLog::count(). - Divi: Beschreibung unter „Prüfung starten“, Button primär solange ungetestet ohne frischen Bericht. - Zugriff: Rückfrage vor dem Speichern ohne Rolle oder ohne eigene Rolle. - Verbindung: HTTPS-Hinweis nicht doppelt neben der Statusliste. - Mobil: breitere Einstellungs-Spalte im Tools-Reiter. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
cc72f9b946
commit
1b73f0652a
+54
-16
@@ -87,7 +87,12 @@ final class ToolsTab implements AdminTab
|
||||
echo '<form method="post" action="options.php">';
|
||||
settings_fields(self::GROUP);
|
||||
submit_button(null, 'primary', 'submit-top');
|
||||
echo '<div class="lit-mcp-groups">';
|
||||
// The admin script mirrors a group's mode onto its rows before saving; it needs the label pattern.
|
||||
printf(
|
||||
'<div class="lit-mcp-groups" data-like-group="%s">',
|
||||
/* translators: %s: mode inherited from the group */
|
||||
esc_attr__('wie Gruppe (%s)', 'wp-lit-mcp')
|
||||
);
|
||||
$closed = $this->savedClosedBoxes();
|
||||
foreach ($groups as $group => $abilities) {
|
||||
$this->renderGroup($policy, $group, $labels[$group] ?? $group, $abilities, $closed);
|
||||
@@ -174,7 +179,12 @@ final class ToolsTab implements AdminTab
|
||||
? $count > 0 && $modes[ExposurePolicy::DISABLED] === $count
|
||||
: in_array($boxId, $closedBoxes, true);
|
||||
|
||||
printf('<div id="%s" class="postbox lit-mcp-group%s">', esc_attr($boxId), $closed ? ' closed' : '');
|
||||
printf(
|
||||
'<div id="%s" class="postbox lit-mcp-group%s" data-group="%s">',
|
||||
esc_attr($boxId),
|
||||
$closed ? ' closed' : '',
|
||||
esc_attr($group)
|
||||
);
|
||||
echo '<div class="postbox-header">';
|
||||
printf(
|
||||
'<h2 class="hndle">%s <span class="count">(%s)</span> <span class="lit-mcp-group-summary">%s</span></h2>',
|
||||
@@ -236,7 +246,8 @@ final class ToolsTab implements AdminTab
|
||||
|
||||
echo '<div class="lit-mcp-group-controls">';
|
||||
printf(
|
||||
'<span class="lit-mcp-control"><label for="%1$s">%2$s</label> <select name="%3$s[%4$s]" id="%1$s">',
|
||||
'<span class="lit-mcp-control"><label for="%1$s">%2$s</label>'
|
||||
. ' <select name="%3$s[%4$s]" class="lit-mcp-group-mode" id="%1$s">',
|
||||
esc_attr($selectId),
|
||||
esc_html__('Ganze Gruppe', 'wp-lit-mcp'),
|
||||
esc_attr(ExposurePolicy::OPTION),
|
||||
@@ -257,7 +268,8 @@ final class ToolsTab implements AdminTab
|
||||
}
|
||||
echo '</select></span>';
|
||||
printf(
|
||||
'<span class="lit-mcp-control"><label><input type="checkbox" name="%s[%s]" value="1"%s> %s</label></span>',
|
||||
'<span class="lit-mcp-control"><label>'
|
||||
. '<input type="checkbox" class="lit-mcp-group-readonly" name="%s[%s]" value="1"%s> %s</label></span>',
|
||||
esc_attr(ExposurePolicy::OPTION),
|
||||
esc_attr(ExposurePolicy::READONLY_PREFIX . $group),
|
||||
checked($policy->isReadonly($group), true, false),
|
||||
@@ -277,13 +289,16 @@ final class ToolsTab implements AdminTab
|
||||
$own = $policy->toolOverride($name);
|
||||
$locked = $policy->disabledByReadonly($ability);
|
||||
$required = in_array($name, ExposurePolicy::REQUIRED, true);
|
||||
$writes = ($ability->annotations()['readonly'] ?? false) !== true && ! $required;
|
||||
$selectId = 'lit-mcp-tool-' . self::idPart($name);
|
||||
/* translators: %s: default mode */
|
||||
$defaultLabel = sprintf(__('Standard (%s)', 'wp-lit-mcp'), $this->modeLabel($policy->defaultMode($ability)));
|
||||
|
||||
printf(
|
||||
'<tr><td class="column-tool"><strong>%1$s</strong><br><span class="lit-mcp-tool-name">%2$s</span></td>'
|
||||
. '<td class="column-kind">%3$s</td><td class="column-mode">'
|
||||
. '<label class="screen-reader-text" for="%4$s">%5$s</label>'
|
||||
. '<select name="%6$s[%7$s]"%8$s id="%4$s">',
|
||||
. '<select name="%6$s[%7$s]" class="lit-mcp-tool-mode" data-default-label="%9$s"%10$s%8$s id="%4$s">',
|
||||
esc_html($ability->label()),
|
||||
esc_html($name),
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in kind().
|
||||
@@ -296,7 +311,10 @@ final class ToolsTab implements AdminTab
|
||||
)),
|
||||
esc_attr(ExposurePolicy::OPTION),
|
||||
esc_attr($name),
|
||||
$locked ? ' disabled' : ''
|
||||
$locked ? ' disabled' : '',
|
||||
esc_attr($defaultLabel),
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- fixed attribute names only.
|
||||
self::scriptFlags($name, $writes, $required)
|
||||
);
|
||||
$inherited = $this->modeLabel($policy->inheritedMode($ability));
|
||||
printf(
|
||||
@@ -305,8 +323,7 @@ final class ToolsTab implements AdminTab
|
||||
esc_html($groupOverride && ! $required
|
||||
/* translators: %s: mode inherited from the group */
|
||||
? sprintf(__('wie Gruppe (%s)', 'wp-lit-mcp'), $inherited)
|
||||
/* translators: %s: default mode */
|
||||
: sprintf(__('Standard (%s)', 'wp-lit-mcp'), $this->modeLabel($policy->defaultMode($ability))))
|
||||
: $defaultLabel)
|
||||
);
|
||||
foreach (ExposurePolicy::MODES as $mode) {
|
||||
if (! ExposurePolicy::isAllowed($name, $mode)) {
|
||||
@@ -331,18 +348,39 @@ final class ToolsTab implements AdminTab
|
||||
);
|
||||
}
|
||||
|
||||
$note = match (true) {
|
||||
$locked => __('Durch „Nur lesen“ aus', 'wp-lit-mcp'),
|
||||
$own === null && $policy->groupModeAdjusted($ability)
|
||||
=> __('„indirekt“ geht hier nicht – bleibt direkt', 'wp-lit-mcp'),
|
||||
default => '',
|
||||
};
|
||||
if ($note !== '') {
|
||||
echo '<p class="description">' . esc_html($note) . '</p>';
|
||||
if ($writes) {
|
||||
// Always in the row so the admin script can show it as soon as "nur lesen" is switched on.
|
||||
printf(
|
||||
'<p class="description lit-mcp-readonly-note"%s>%s</p>',
|
||||
$locked ? '' : ' hidden',
|
||||
esc_html__('Durch „Nur lesen“ aus', 'wp-lit-mcp')
|
||||
);
|
||||
}
|
||||
if ($own === null && $policy->groupModeAdjusted($ability)) {
|
||||
echo '<p class="description">'
|
||||
. esc_html__('„indirekt“ geht hier nicht – bleibt direkt', 'wp-lit-mcp')
|
||||
. '</p>';
|
||||
}
|
||||
echo '</td></tr>';
|
||||
}
|
||||
|
||||
/** Data attributes telling the admin script how a row reacts to its group's controls. */
|
||||
private static function scriptFlags(string $name, bool $writes, bool $required): string
|
||||
{
|
||||
$flags = '';
|
||||
if ($writes) {
|
||||
$flags .= ' data-writes="1"';
|
||||
}
|
||||
if ($required) {
|
||||
$flags .= ' data-required="1"';
|
||||
}
|
||||
if (in_array($name, ExposurePolicy::DIRECT_ONLY, true)) {
|
||||
$flags .= ' data-direct-only="1"';
|
||||
}
|
||||
|
||||
return $flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* "liest" / "schreibt" / "überschreibt" / "löscht" / "Papierkorb" with a dashicon. The
|
||||
* "destructive" annotation is a broad hint (deleting, replacing, swapping, ruling S47),
|
||||
|
||||
Reference in New Issue
Block a user