mirror of
https://github.com/opnsense/core.git
synced 2026-06-09 00:42:36 -04:00
tabulator: Improve responsiveness via minWidth() for grid and flex css for action row (#9240)
* firewall/automation: Small viewport layout for action bar * bootgrid: Add minWidth and maxWidth and wire minWidth into firewall/automation/filter page for better responsiveness * Make header even more responsive by allowing selectpickers to shrink and stretch in a flexbox, but only to a certain limit * Generalize the action bar flex css so it improves all pages * Add global default for minWidth since its an issue in all grids. * Give width precedence over minWidth, fix some minWidth in firewall page * Give search bar some left padding so when it collides with left elements there is some spacing * Fix flex behavior for elements inside the button group, fix log.volt * dnsmasq leases.volt fix flex behavior of selectpickers * kea leases4.volt leases6.volt fix flex behavior of selectpickers * dnsmasq settings.volt fix flex behavior of selectpickers * alias alias.volt fix flex behavior of selectpickers * virtual IP vip.volt fix flex behavior of selectpickers * filter.volt fix flex behavior of selectpickers * wireguard general.volt diagnostics.volt fix flex behavior of selectpickers * Simplify by creating a new layout css file which can store layout focused bootgrid changes without regenerating themes * Give the search bar some love too, allow it to be bigger and shrink
This commit is contained in:
parent
cddb65dc31
commit
7f6f768c30
24 changed files with 164 additions and 46 deletions
1
plist
1
plist
|
|
@ -2084,6 +2084,7 @@
|
|||
/usr/local/opnsense/www/css/jqtree.css
|
||||
/usr/local/opnsense/www/css/jquery.bootgrid.css
|
||||
/usr/local/opnsense/www/css/nv.d3.css
|
||||
/usr/local/opnsense/www/css/opnsense-bootgrid-layout.css
|
||||
/usr/local/opnsense/www/css/opnsense-bootgrid.css
|
||||
/usr/local/opnsense/www/css/tabulator.min.css
|
||||
/usr/local/opnsense/www/css/tokenize2.css
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ class ControllerBase extends ControllerRoot
|
|||
'/css/bootstrap-dialog.css',
|
||||
'/css/tabulator.min.css',
|
||||
'/css/opnsense-bootgrid.css',
|
||||
'/css/opnsense-bootgrid-layout.css',
|
||||
// Font awesome
|
||||
'/ui/assets/fontawesome/css/all.min.css',
|
||||
'/ui/assets/fontawesome/css/v4-shims.min.css',
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@
|
|||
<advanced>true</advanced>
|
||||
<grid_view>
|
||||
<visible>false</visible>
|
||||
<type>boolean</type>
|
||||
<formatter>boolean</formatter>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -69,6 +71,7 @@
|
|||
<help>You may enter a description here for your reference (not parsed).</help>
|
||||
<grid_view>
|
||||
<sequence>110</sequence>
|
||||
<min-width>100</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -129,6 +132,8 @@
|
|||
<advanced>true</advanced>
|
||||
<grid_view>
|
||||
<visible>false</visible>
|
||||
<type>boolean</type>
|
||||
<formatter>boolean</formatter>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -186,6 +191,7 @@
|
|||
<grid_view>
|
||||
<formatter>alias</formatter>
|
||||
<sequence>50</sequence>
|
||||
<min-width>100</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -195,8 +201,10 @@
|
|||
<help>Source port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
<style>port_selector</style>
|
||||
<grid_view>
|
||||
<label>Port</label>
|
||||
<sequence>60</sequence>
|
||||
<formatter>alias</formatter>
|
||||
<min-width>60</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -216,6 +224,7 @@
|
|||
<grid_view>
|
||||
<formatter>alias</formatter>
|
||||
<sequence>70</sequence>
|
||||
<min-width>100</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -225,8 +234,10 @@
|
|||
<help>Destination port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
<style>port_selector</style>
|
||||
<grid_view>
|
||||
<label>Port</label>
|
||||
<sequence>80</sequence>
|
||||
<formatter>alias</formatter>
|
||||
<min-width>60</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
@ -575,6 +586,7 @@
|
|||
<grid_view>
|
||||
<formatter>statistics</formatter>
|
||||
<sequence>115</sequence>
|
||||
<min-width>200</min-width>
|
||||
</grid_view>
|
||||
</field>
|
||||
<field>
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#zone-selection-wrapper").detach().prependTo('#grid-clients-header > .row > .actionBar > .actions');
|
||||
$("#zone-selection-wrapper").detach().insertBefore('#grid-clients-header .search');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -138,14 +138,10 @@
|
|||
});
|
||||
</script>
|
||||
<style>
|
||||
#grid_services-header .actionBar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#grid_services-header .actionBar > #sync_container {
|
||||
margin-right: auto;
|
||||
#grid_services-header .actionBar #act_restart_all {
|
||||
flex: 0 0 auto !important;
|
||||
width: auto !important;
|
||||
align-self: center !important;
|
||||
}
|
||||
</style>
|
||||
<section class="page-content-main">
|
||||
|
|
|
|||
|
|
@ -129,8 +129,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#inactive-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar');
|
||||
$("#interface-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#inactive-selection-wrapper").detach().insertBefore('#grid-leases-header .search');
|
||||
$("#interface-selection-wrapper").detach().insertAfter('#grid-leases-header .search');
|
||||
|
||||
updateServiceControlUI('dhcpv4');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@
|
|||
search:'/api/dhcpv6/leases/search_prefix/'
|
||||
});
|
||||
|
||||
$("#inactive-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar');
|
||||
$("#interface-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#inactive-selection-wrapper").detach().insertBefore('#grid-leases-header .search');
|
||||
$("#interface-selection-wrapper").detach().insertAfter('#grid-leases-header .search');
|
||||
|
||||
if (window.location.hash != "") {
|
||||
$('a[href="' + window.location.hash + '"]').click();
|
||||
|
|
|
|||
|
|
@ -152,12 +152,9 @@
|
|||
|
||||
updateServiceControlUI('{{service}}');
|
||||
|
||||
// move filter into action header
|
||||
$("#filter_container").detach().prependTo('#grid-log-header > .row > .actionBar > .actions');
|
||||
$(".filter_act").tooltip();
|
||||
|
||||
$("#export-wrapper").detach().appendTo('#grid-log-header > .row > .actionBar > .btn-group');
|
||||
$("#exportbtn").tooltip();
|
||||
// Move filters directly into the actionBar instead of nested groups for better flex behavior
|
||||
$("#filter_container").detach().insertAfter('#grid-log-header .search');
|
||||
$("#export-wrapper").detach().appendTo('#grid-log-header .actionBar');
|
||||
|
||||
function switch_mode(value) {
|
||||
let select = $("#severity_filter");
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
$('#grid-vips').bootgrid('reload');
|
||||
});
|
||||
|
||||
$("#mode_filter_container").detach().prependTo('#grid-vips-header > .row > .actionBar > .actions');
|
||||
$("#mode_filter_container").detach().insertAfter('#grid-vips-header .search');
|
||||
|
||||
$(".carp_action").each(function(){
|
||||
$(this).SimpleActionButton({onAction: function(data, status){
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#interface-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#protocol-selection-wrapper").detach().insertBefore("#interface-selection-wrapper");
|
||||
$("#interface-selection-wrapper").detach().insertAfter('#grid-leases-header .search');
|
||||
$("#protocol-selection-wrapper").detach().insertAfter("#interface-selection-wrapper");
|
||||
|
||||
updateServiceControlUI('dnsmasq');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@
|
|||
let header = $("#" + grid_id + "-header");
|
||||
let $actionBar = header.find('.actionBar');
|
||||
if ($actionBar.length) {
|
||||
$('#tag_select_container').detach().insertBefore($actionBar.find('.search'));
|
||||
$('#tag_select_container').detach().insertAfter($actionBar.find('.search'));
|
||||
$('#tag_select_container').show();
|
||||
}
|
||||
}
|
||||
|
|
@ -281,16 +281,6 @@
|
|||
tbody.collapsible > tr > td:first-child {
|
||||
padding-left: 30px;
|
||||
}
|
||||
#tag_select_clear {
|
||||
border-right: none;
|
||||
}
|
||||
#tag_select_container {
|
||||
margin-right: 20px;
|
||||
}
|
||||
#tag_select_container .bootstrap-select > .dropdown-toggle {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="tag_select_container" class="btn-group" style="display: none;">
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@
|
|||
});
|
||||
|
||||
// move filter into action header
|
||||
$("#type_filter_container").detach().prependTo('#grid-aliases-header > .row > .actionBar > .actions');
|
||||
$("#type_filter_container").detach().insertAfter('#grid-aliases-header .search');
|
||||
// alias size in service container
|
||||
$("#aliases_stat").detach().prependTo('#service_status_container');
|
||||
$("#service_status_container").css('width', '250px');
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
$("#reconfigureAct").SimpleActionButton();
|
||||
|
||||
// move filter into action header
|
||||
$("#type_filter_container").detach().prependTo('#grid-rules-header > .row > .actionBar > .actions');
|
||||
$("#type_filter_container").detach().insertAfter('#grid-rules-header .search');
|
||||
$("#category_filter").change(function(){
|
||||
$('#grid-rules').bootgrid('reload');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@
|
|||
$("#interface_select_container").show();
|
||||
|
||||
// move selectpickers into action bar
|
||||
$("#interface_select_container").detach().insertBefore('#{{formGridFilterRule["table_id"]}}-header > .row > .actionBar > .search');
|
||||
$("#interface_select_container").detach().insertBefore('#{{formGridFilterRule["table_id"]}}-header .search');
|
||||
$('#interface_select').on('changed.bs.select', function () {
|
||||
// Skip grid reload during reconfigureAct and initial page load
|
||||
if (!interfaceInitialized || reconfigureActInProgress) return;
|
||||
|
|
@ -978,6 +978,41 @@
|
|||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/* Action bar specific layout */
|
||||
#interface_select_container,
|
||||
#type_filter_container {
|
||||
float: none !important;
|
||||
flex: 1 1 150px;
|
||||
min-width: 0;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
#interface_select_container .bootstrap-select,
|
||||
#type_filter_container .bootstrap-select {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .btn-group {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
#interface_select_container,
|
||||
#type_filter_container {
|
||||
flex: 1 1 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#dialogFilterRule-header #inspect_toggle_container,
|
||||
#dialogFilterRule-header #tree_toggle_container,
|
||||
#dialogFilterRule-header #tree_expand_container {
|
||||
flex: 1 1 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.stats-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -993,11 +1028,11 @@
|
|||
<!-- filters -->
|
||||
<div class="hidden">
|
||||
<div id="type_filter_container" class="btn-group">
|
||||
<select id="category_filter" data-title="{{ lang._('Categories') }}" class="selectpicker" data-live-search="true" data-size="30" multiple data-width="300px" data-container="body">
|
||||
<select id="category_filter" data-title="{{ lang._('Categories') }}" class="selectpicker" data-live-search="true" data-size="30" multiple data-container="body">
|
||||
</select>
|
||||
</div>
|
||||
<div id="interface_select_container" class="btn-group">
|
||||
<select id="interface_select" class="selectpicker" data-live-search="true" data-size="30" data-width="300px" data-container="body">
|
||||
<select id="interface_select" class="selectpicker" data-live-search="true" data-size="30" data-container="body">
|
||||
</select>
|
||||
</div>
|
||||
<div id="inspect_toggle_container" class="btn-group">
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
$("#pool_filter_container").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#pool_filter_container").detach().insertAfter('#grid-leases-header .search');
|
||||
$("#pool_filter").change(function(){
|
||||
$('#grid-leases').bootgrid('reload');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@
|
|||
)
|
||||
);
|
||||
|
||||
$("#mode_filter_container").detach().prependTo('#{{formGridVip["table_id"]}}-header > .row > .actionBar > .actions');
|
||||
$("#mode_filter_container").detach().insertAfter('#{{formGridVip["table_id"]}}-header .search');
|
||||
|
||||
/**
|
||||
* select an unassigned carp vhid
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#interface-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#interface-selection-wrapper").detach().insertAfter('#grid-leases-header .search');
|
||||
|
||||
updateServiceControlUI('kea');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#interface-selection-wrapper").detach().prependTo('#grid-leases-header > .row > .actionBar > .actions');
|
||||
$("#interface-selection-wrapper").detach().insertAfter('#grid-leases-header .search');
|
||||
|
||||
updateServiceControlUI('kea');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@
|
|||
$('#grid-sessions').bootgrid('reload');
|
||||
});
|
||||
|
||||
$("#type_filter_container").detach().prependTo('#grid-sessions-header > .row > .actionBar > .actions');
|
||||
$("#type_filter_container").detach().insertAfter('#grid-sessions-header .search');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
$("#filter_container").detach().prependTo('#{{formGridCert['table_id']}}-header > .row > .actionBar > .actions');
|
||||
$("#filter_container").detach().insertAfter('#{{formGridCert['table_id']}}-header .search');
|
||||
$(".cert_filter").change(function(){
|
||||
$("#{{formGridCert['table_id']}}").bootgrid('reload');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
||||
$("#type_filter_container").detach().prependTo('#grid-sessions-header > .row > .actionBar > .actions');
|
||||
$("#type_filter_container").detach().insertAfter('#grid-sessions-header .search');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
/**
|
||||
* Quick instance filter on top
|
||||
*/
|
||||
$("#filter_container").detach().prependTo('#{{formGridWireguardClient["table_id"]}}-header > .row > .actionBar > .actions');
|
||||
$("#filter_container").detach().insertAfter('#{{formGridWireguardClient["table_id"]}}-header .search');
|
||||
$("#server_filter").change(function(){
|
||||
$('#{{formGridWireguardClient['table_id']}}').bootgrid('reload');
|
||||
});
|
||||
|
|
|
|||
76
src/opnsense/www/css/opnsense-bootgrid-layout.css
Normal file
76
src/opnsense/www/css/opnsense-bootgrid-layout.css
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* For universal layout adjustments that do not need theme compilation.
|
||||
* No color or other variables allowed, only static layout changes.
|
||||
* Avoids having to recompile/fix themes.
|
||||
* /
|
||||
|
||||
/* Action Bar responsive style */
|
||||
.bootgrid-header .actionBar {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar > .search {
|
||||
margin-left: auto;
|
||||
padding-left: 20px;
|
||||
flex: 0 1 400px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar > .btn-group,
|
||||
.bootgrid-header .actionBar > .actions .btn-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.bootgrid-header .actionBar {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar > * {
|
||||
flex: 1 1 100%;
|
||||
margin: 0;
|
||||
float: none;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .bootstrap-select,
|
||||
.bootgrid-header .actionBar .bootstrap-select > .dropdown-toggle,
|
||||
.bootgrid-header .actionBar .btn,
|
||||
.bootgrid-header .actionBar .search .input-group,
|
||||
.bootgrid-header .actionBar .search .form-control {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .search {
|
||||
flex: 1 1 100%;
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .search .input-group {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .actions,
|
||||
.bootgrid-header .actionBar .actions-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.bootgrid-header .actionBar .actions > *,
|
||||
.bootgrid-header .actionBar .actions-group > * {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -486,6 +486,8 @@ class UIBootgrid {
|
|||
visible: data.visible ?? true,
|
||||
sequence: data.sequence ?? null,
|
||||
width: val.width,
|
||||
minWidth: data.minWidth || 80,
|
||||
maxWidth: data.maxWidth ?? null,
|
||||
editable: false,
|
||||
sortable: data.sortable ?? true
|
||||
}
|
||||
|
|
@ -564,6 +566,13 @@ class UIBootgrid {
|
|||
col['maxWidth'] = field.width;
|
||||
} else if (field.width) {
|
||||
col['width'] = field.width;
|
||||
} else {
|
||||
if (field.minWidth) {
|
||||
col['minWidth'] = field.minWidth;
|
||||
}
|
||||
if (field.maxWidth) {
|
||||
col['maxWidth'] = field.maxWidth;
|
||||
}
|
||||
}
|
||||
|
||||
result.push(col);
|
||||
|
|
|
|||
Loading…
Reference in a new issue