Legacy filter rendering: show only the classic inline filter (#8404)

The page_filter_format setting is meant to be either/or: Modern shows the
Layouts selector with its Edit dialog, Legacy shows the classic inline
filter. Legacy also rendered the Layouts selector row (and its JavaScript),
so the new and the classic filters appeared together.

Stop rendering the Layouts selector in Legacy mode: create_filter() no
longer appends create_layouts(), and create_javascript() only emits the
layouts script in modern mode. The now-unused create_layouts() and
create_layouts_javascript() helpers are removed, and the setting help text
is updated to say the Layouts selector is available in Modern only.
This commit is contained in:
TheWitness authored and GitHub committed 2026-10-16 08:11:50 -04:00
1 parent 91280239f7
commit b2ed6ec337
4 files changed
+8 -127

No files matched your search

+1 -1
View File
@@ -3188,7 +3188,7 @@ $settings_user = [
],
'page_filter_format' => [
'friendly_name' => __('Page Filter Format'),
'description' => __('How table filters are presented. Modern collapses the filter into a Layouts selector with an Edit dialog that holds the filter fields; Legacy shows the classic inline filter. The Layouts selector is available in both.'),
'description' => __('How table filters are presented. Modern collapses the filter into a Layouts selector with an Edit dialog that holds the filter fields; Legacy shows only the classic inline filter. The Layouts selector is available in Modern only.'),
'method' => 'drop_array',
'default' => 'modern',
'array' => [
-96
View File
@@ -752,10 +752,6 @@ class CactiTableFilter {
print '</form>' . PHP_EOL;
}
if ($this->render_layouts) {
print $this->create_layouts();
}
html_filter_end_box();
return (string) ob_get_clean();
@@ -1288,8 +1284,6 @@ class CactiTableFilter {
if ($this->render_layouts) {
if ($this->use_modern_filter()) {
$script .= $this->create_modern_javascript($applyFilter, $changeFunction, $clearFunction);
} else {
$script .= $this->create_layouts_javascript($applyFilter);
}
}
@@ -1361,96 +1355,6 @@ class CactiTableFilter {
'</div>' . PHP_EOL;
}
private function create_layouts() : string {
$page = filter_layouts_page_key($this->form_action != '' ? $this->form_action : get_current_page());
$layouts = filter_layouts_get_available($page);
$can_glob = filter_layouts_can_manage_global();
ob_start();
print "<div class='filterTable even cactiFilterLayouts'>";
print "<div class='filterRow'>";
print "<div class='filterColumn'><div class='filterFieldName'>" . __('Layouts') . '</div></div>';
print "<div class='filterColumn'>";
print $this->layout_select($layouts, $can_glob);
print '</div>';
print $this->layout_button('layout_save', __('Save'), __('Overwrite the selected layout with the current filter'), false, 'ti ti-device-floppy');
print $this->layout_button('layout_new', __('New'), __('Save the current filter as a new layout'), false, 'ti ti-file-plus');
print $this->layout_button('layout_rename', __('Rename'), __('Rename the selected layout'), false, 'ti ti-forms');
print $this->layout_button('layout_delete', __('Delete'), __('Delete the selected layout'), false, 'ti ti-trash');
if ($can_glob) {
print $this->layout_button('layout_publish', __('Publish'), __('Publish the selected layout so all users can see it'), false, 'ti ti-world-up');
}
print '</div>';
print '</div>' . PHP_EOL;
// Hidden name-entry dialog reused by the New and Rename actions.
print "<div id='layoutNameDialog' title='" . __esc('Layout Name') . "' style='display:none;'>";
print "<form id='layoutNameForm' onsubmit='return false;'>";
print "<label for='layout_name'>" . __('Name') . '</label> ';
print "<input type='text' id='layout_name' size='40' maxlength='128' class='ui-state-default ui-corner-all'>";
print '</form></div>' . PHP_EOL;
return (string) ob_get_clean();
}
private function create_layouts_javascript(string $applyFilter) : string {
$page = filter_layouts_page_key($this->form_action != '' ? $this->form_action : get_current_page());
$js = PHP_EOL . "<script type='text/javascript'>" . PHP_EOL;
$js .= 'function layoutFilterUrl() {' . PHP_EOL;
$js .= "\treturn " . $applyFilter . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= 'function layoutSelectedId() {' . PHP_EOL;
$js .= "\treturn parseInt($('#filter_layout').val()) || 0;" . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= 'function layoutPost(layoutAction, extra, onDone) {' . PHP_EOL;
$js .= "\tvar data = $.extend({ action: layoutAction, page: " . json_encode($page) . ', __csrf_magic: csrfMagicToken }, extra);' . PHP_EOL;
$js .= "\t$.post(" . json_encode($page) . ", data, function(result) { if (onDone) { onDone(result); } }, 'json').fail(function() { alert(" . json_encode(__('The layout operation failed.')) . '); });' . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= 'function layoutNameDialog(title, value, onAccept) {' . PHP_EOL;
$js .= "\t$('#layout_name').val(value);" . PHP_EOL;
$js .= "\t$('#layoutNameDialog').dialog({ title: title, modal: true, width: 400, resizable: false, buttons: [" . PHP_EOL;
$js .= "\t\t{ text: " . json_encode(__('OK')) . ", click: function() { var n = $('#layout_name').val(); $(this).dialog('close'); if (n != '') { onAccept(n); } } }," . PHP_EOL;
$js .= "\t\t{ text: " . json_encode(__('Cancel')) . ", click: function() { $(this).dialog('close'); } }" . PHP_EOL;
$js .= "\t] });" . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= 'function layoutEditable() {' . PHP_EOL;
$js .= "\treturn $('#filter_layout option:selected').attr('data-editable') != '0';" . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= 'function layoutResultOk(r) {' . PHP_EOL;
$js .= "\tif (r && r.ok) { return true; } alert(" . json_encode(__('The layout operation failed.')) . '); return false;' . PHP_EOL;
$js .= '}' . PHP_EOL;
$js .= '$(function() {' . PHP_EOL;
$js .= "\t$('#filter_layout').change(function() { var u = $('#filter_layout option:selected').attr('data-url'); if (u != undefined && u != '') { document.location = u; } });" . PHP_EOL;
$js .= "\t$('#layout_new').click(function() { layoutNameDialog(" . json_encode(__('New Layout')) . ", '', function(name) { layoutPost('layout_save', { name: name, url: layoutFilterUrl() }, function(r) { if (layoutResultOk(r) && r.url) { document.location = r.url; } }); }); });" . PHP_EOL;
$js .= "\t$('#layout_save').click(function() { var id = layoutSelectedId(); if (id == 0) { $('#layout_new').click(); return; } if (!layoutEditable()) { alert(" . json_encode(__('You are not permitted to modify this layout.')) . "); return; } layoutPost('layout_save', { id: id, url: layoutFilterUrl() }, function(r) { if (layoutResultOk(r)) { if (r.url) { document.location = r.url; } else { window.location.reload(); } } }); });" . PHP_EOL;
$js .= "\t$('#layout_rename').click(function() { var id = layoutSelectedId(); if (id == 0) { alert(" . json_encode(__('Please select a layout to rename.')) . '); return; } if (!layoutEditable()) { alert(' . json_encode(__('You are not permitted to modify this layout.')) . "); return; } var cur = $('#filter_layout option:selected').attr('data-name'); layoutNameDialog(" . json_encode(__('Rename Layout')) . ", cur, function(name) { layoutPost('layout_rename', { id: id, name: name }, function(r) { if (layoutResultOk(r)) { window.location.reload(); } }); }); });" . PHP_EOL;
$js .= "\t$('#layout_delete').click(function() { var id = layoutSelectedId(); if (id == 0) { alert(" . json_encode(__('Please select a layout to delete.')) . '); return; } if (!layoutEditable()) { alert(' . json_encode(__('You are not permitted to modify this layout.')) . "); return; } var d = $('<div>').append($('<p>').text(" . json_encode(__('Delete the selected layout?')) . ")); $('body').append(d); d.dialog({ title: " . json_encode(__('Delete Layout')) . ', modal: true, width: 420, resizable: false, buttons: [ { text: ' . json_encode(__('Delete')) . ", click: function() { $(this).dialog('close'); layoutPost('layout_delete', { id: id }, function(r) { if (layoutResultOk(r)) { document.location = " . json_encode($page) . '; } }); } }, { text: ' . json_encode(__('Cancel')) . ", click: function() { $(this).dialog('close'); } } ], close: function() { $(this).dialog('destroy').remove(); } }); });" . PHP_EOL;
$js .= "\t$('#layout_publish').click(function() { var id = layoutSelectedId(); if (id == 0) { alert(" . json_encode(__('Please select a layout to publish.')) . "); return; } layoutPost('layout_publish', { id: id }, function(r) { if (layoutResultOk(r)) { window.location.reload(); } }); });" . PHP_EOL;
$js .= '});' . PHP_EOL;
$js .= '</script>' . PHP_EOL;
return $js;
}
/**
* Emit the modern filter JavaScript: the Layouts selector navigation, the
* bar action buttons, and the Edit dialog. The dialog's apply and clear
+1 -29
View File
@@ -25272,14 +25272,6 @@ msgstr ""
msgid "(New Layout)"
msgstr ""
#: lib/html_filter.php
msgid "Overwrite the selected layout with the current filter"
msgstr ""
#: lib/html_filter.php
msgid "Save the current filter as a new layout"
msgstr ""
#: lib/html_filter.php
msgid "Rename the selected layout"
msgstr ""
@@ -25288,10 +25280,6 @@ msgstr ""
msgid "Delete the selected layout"
msgstr ""
#: lib/html_filter.php
msgid "Publish the selected layout so all users can see it"
msgstr ""
#: lib/html_filter.php
msgid "Layout Name"
msgstr ""
@@ -25308,22 +25296,6 @@ msgstr ""
msgid "The layout operation failed."
msgstr ""
#: lib/html_filter.php
msgid "Please select a layout to rename."
msgstr ""
#: lib/html_filter.php
msgid "Please select a layout to delete."
msgstr ""
#: lib/html_filter.php
msgid "Please select a layout to publish."
msgstr ""
#: lib/html_filter.php
msgid "You are not permitted to modify this layout."
msgstr ""
#: lib/html_filter.php
msgid "Delete the selected layout?"
msgstr ""
@@ -25341,7 +25313,7 @@ msgid "Page Filter Format"
msgstr ""
#: include/global_settings.php
msgid "How table filters are presented. Modern collapses the filter into a Layouts selector with an Edit dialog that holds the filter fields; Legacy shows the classic inline filter. The Layouts selector is available in both."
msgid "How table filters are presented. Modern collapses the filter into a Layouts selector with an Edit dialog that holds the filter fields; Legacy shows only the classic inline filter. The Layouts selector is available in Modern only."
msgstr ""
#: include/global_arrays.php
+6 -1
View File
@@ -90,7 +90,7 @@ test('the filter class exposes a render_layouts toggle that preset pages clear',
expect($src)->toContain('public bool $render_layouts = true;');
expect($src)->toContain('in_array($page, filter_layouts_preset_pages(), true)');
expect($src)->toContain('$this->render_layouts = false;');
expect($src)->toContain('if ($this->render_layouts) {');
expect($src)->toContain('$this->render_layouts && $this->filter_format');
});
test('publishing and global management require the Settings/Utilities realm', function () use ($root) {
@@ -137,6 +137,11 @@ test('the filter class renders a legacy or modern layout from the user preferenc
// Modern short-circuits create_filter() before the inline rendering.
expect($src)->toContain('if ($this->use_modern_filter()) {');
expect($src)->toContain('print $this->create_modern_filter();');
// Legacy renders only the classic inline filter: the layouts selector and its
// script helpers are gone.
expect($src)->not->toContain('create_layouts(');
expect($src)->not->toContain('create_layouts_javascript(');
});
test('field rendering is shared so legacy and the modern dialog stay in sync', function () use ($root) {