diff --git a/plist b/plist index 3647dd129..84327d51c 100644 --- a/plist +++ b/plist @@ -1955,6 +1955,7 @@ /usr/local/opnsense/www/js/widgets/BaseWidget.js /usr/local/opnsense/www/js/widgets/Cpu.js /usr/local/opnsense/www/js/widgets/Disk.js +/usr/local/opnsense/www/js/widgets/Firewall.js /usr/local/opnsense/www/js/widgets/InterfaceStatistics.js /usr/local/opnsense/www/js/widgets/Interfaces.js /usr/local/opnsense/www/js/widgets/Memory.js diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php index 68c1f06a3..7caabdcd6 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php @@ -88,6 +88,21 @@ class DashboardController extends ApiControllerBase 'peer' => gettext('Peer'), 'pubkey' => gettext('Public Key'), 'handshake' => gettext('Latest handshake'), + ], + 'firewall' => [ + 'title' => gettext('Firewall'), + 'action' => gettext('Action'), + 'time' => gettext('Time'), + 'interface' => gettext('Interface'), + 'source' => gettext('Source'), + 'destination' => gettext('Destination'), + 'port' => gettext('Port'), + 'matchedrule' => gettext('Matched rule'), + 'click' => gettext('Click to track this rule in Live View'), + 'label' => gettext('Label'), + 'count' => gettext('Count'), + 'livelog' => gettext('Live Log'), + 'events' => gettext('Events'), ] ]; } diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/FirewallController.php b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/FirewallController.php index ab9eb2ccb..e4e390d20 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/FirewallController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/FirewallController.php @@ -58,6 +58,19 @@ class FirewallController extends ApiControllerBase } } + public function streamLogAction() + { + return $this->configdStream( + 'filter stream log', + [], + [ + 'Content-Type: text/event-stream', + 'Cache-Control: no-cache' + ], + 60 + ); + } + /** * retrieve firewall log filter choices * @return array diff --git a/src/opnsense/www/css/dashboard.css b/src/opnsense/www/css/dashboard.css index 88242b37b..4b3cdeab4 100644 --- a/src/opnsense/www/css/dashboard.css +++ b/src/opnsense/www/css/dashboard.css @@ -172,6 +172,13 @@ td { z-index: 20; } +/* CPU widget */ +.cpu-type { + margin-bottom: 10px; + margin-top: 10px; +} +/* ----- */ + /* Custom flex table */ div { box-sizing: border-box; @@ -241,31 +248,26 @@ div { .column .flex-cell:not(:last-child) { border-bottom: solid 1px rgba(217, 79, 0, 0.15); } - - /* ----- */ -.cpu-type { - margin-bottom: 10px; - margin-top: 10px; -} - /* CSS grid responsive table */ -.grid-table { - margin: 2em auto; - width: 95%; -} - .grid-header-container { display: grid; - grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); } .grid-row { display: grid; - grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + background-color: #f7e2d6; /* fade-in color, transitions to transparent */ border-top: 1px solid #f7e2d6; transition: 0.5s; + opacity: 0.4; +} + +.grid-row:hover { + background: #F5F5F5 !important; + transition: 500ms; } .grid-header { @@ -278,5 +280,4 @@ div { padding: 4px; text-align: center; } - /* ----- */ diff --git a/src/opnsense/www/js/widgets/BaseTableWidget.js b/src/opnsense/www/js/widgets/BaseTableWidget.js index dfb404345..b2ef30e56 100644 --- a/src/opnsense/www/js/widgets/BaseTableWidget.js +++ b/src/opnsense/www/js/widgets/BaseTableWidget.js @@ -31,9 +31,7 @@ export default class BaseTableWidget extends BaseWidget { constructor() { super(); - this.options = null; - this.data = []; - + this.tables = {}; this.curSize = null; this.sizeStates = { 0: { @@ -53,63 +51,43 @@ export default class BaseTableWidget extends BaseWidget { } } this.widths = Object.keys(this.sizeStates).sort(); - - this.flextableId = Math.random().toString(36).substring(7); - this.$flextable = null; - this.$headerContainer = null; } _calculateColumnWidth() { - if (this.options !== null && this.data !== null) { - switch (this.options.headerPosition) { - case 'none': - return `calc(100% / ${this.data[0].length})`; - case 'left': - return `calc(100% / 2)`; + for (const [id, tableObj] of Object.entries(this.tables)) { + if (tableObj.options.headerPosition === 'left') { + return `calc(100% / 2)`; + } + + if (tableObj.options.headerPosition === 'top') { + return `calc(100% / ${tableObj.data[0].length})`; } } return ''; } - _constructTable() { - if (this.options === null) { - console.error('No table options set'); - return null; + _rotate(id, newElement) { + let opts = this.tables[id].options; + let data = this.tables[id].data; + + data.unshift(newElement); + if (data.length > opts.rotation) { + data.splice(opts.rotation); } - if (this.options.headerPosition === 'top') { - this.$flextable = $(`
`) - this.$headerContainer = $(``); - - for (const h of this.options.headers) { - this.$headerContainer.append($(` -
+ @${data.rulenr}
+ ${data.label.length > 0 ? 'Label: ' + data.label : ''}
+
+ ${this.translations.click}
+