From patchwork Sat Apr 1 14:43:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo-Andres Hofmann X-Patchwork-Id: 6755 Return-Path: Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) client-signature ECDSA (P-384)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4Ppg0K3MyBz3x2l for ; Sat, 1 Apr 2023 14:44:17 +0000 (UTC) Received: from mail02.haj.ipfire.org (mail02.haj.ipfire.org [172.28.1.201]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) client-signature ECDSA (P-384)) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4Ppg0H6PFKzq1; Sat, 1 Apr 2023 14:44:15 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4Ppg0H5sQ1z2yVy; Sat, 1 Apr 2023 14:44:15 +0000 (UTC) Received: from mail01.ipfire.org (mail01.haj.ipfire.org [172.28.1.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) client-signature ECDSA (P-384)) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4Ppg0H017Rz2xxv for ; Sat, 1 Apr 2023 14:44:15 +0000 (UTC) Received: from arche.uberspace.de (arche.uberspace.de [185.26.156.147]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail01.ipfire.org (Postfix) with ESMTPS id 4Ppg0G3jNkz2wv for ; Sat, 1 Apr 2023 14:44:14 +0000 (UTC) Authentication-Results: mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=VbZvHkpE; spf=pass (mail01.ipfire.org: domain of hofmann@leo-andres.de designates 185.26.156.147 as permitted sender) smtp.mailfrom=hofmann@leo-andres.de; dmarc=pass (policy=quarantine) header.from=leo-andres.de ARC-Seal: i=1; s=202003rsa; d=lists.ipfire.org; t=1680360254; a=rsa-sha256; cv=none; b=x6tZNyx0i4/hJ+w2kYlyyzelBOolPOfi6QvkyAig05djd7k1jR38SCIYxePO8Nm0+d0IBX RwCFb25Z3SRMyqNk422RoAdSTB0hRxuj0wO1tnKqW2LGRD4K4i3rtv0KYvosKVaq9xNP7T +Y6oVtk5mbCJru+/92hbGQyADolStspixOxSuJuI6mbOM0AbYTwBYZhx5Vsi+1YtuQX8Op 8WEZs1q/z/SCCdvjpF0R2LUUaZwz/5eMmWMAdW7UD5NysrbMCJ6wJcThV+FPK68DvSvJTo CmfooAyazL6Vcqb43ql9VkVsNYD+JmmEkZsQE+LrKVLW8oKXHNEtW6wm8Md7XA== ARC-Authentication-Results: i=1; mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=VbZvHkpE; spf=pass (mail01.ipfire.org: domain of hofmann@leo-andres.de designates 185.26.156.147 as permitted sender) smtp.mailfrom=hofmann@leo-andres.de; dmarc=pass (policy=quarantine) header.from=leo-andres.de ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=lists.ipfire.org; s=202003rsa; t=1680360254; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=biZz4j601YMuP4tOpgznPCr5ewwBiqIcJSeDIx1vUNE=; b=unQi4RfK1K36EmohcCQpQ8AhEnFL62QwpsHPdUeEnXxPaYGtSeo6mVmWdIK3UAs7l9p0QO 6FYXHfWg+E9ynAIXYOkaZjcCImwgzZLeWgr2gOsSXMlYVFz3HZcrLjCFwOTiUyaLYXP8H7 q4WcaDAMHaNyzleECA2nWsXFUQzch90kSoHZkNKI0TaWX/tC3kECdzrOW1qPkCrVo6OoSn PvU481bzJwvMtj/QvzDh//E9Z7ncsLJG6bXgxGEAZVJ6WPuJSDQsnhrIWoOhT+TCb1gMfv 9RYfLtc3+9nHqN3LhCzRYAvNAs9sxRWZvLi1DbOd2higDIfKZWTQWJyKq3r5wg== Received: (qmail 16911 invoked by uid 990); 1 Apr 2023 14:44:14 -0000 From: Leo-Andres Hofmann To: development@lists.ipfire.org Subject: [PATCH 2/4] WUI: Refactor rrdimage JavaScript Date: Sat, 1 Apr 2023 16:43:41 +0200 Message-Id: <20230401144343.1483-2-hofmann@leo-andres.de> X-Mailer: git-send-email 2.37.1.windows.1 In-Reply-To: <20230401144343.1483-1-hofmann@leo-andres.de> References: <20230401144343.1483-1-hofmann@leo-andres.de> MIME-Version: 1.0 X-Rspamd-Bar: ----- X-Rspamd-Report: R_MISSING_CHARSET(0.5) MIME_GOOD(-0.1) REPLY(-4) MID_CONTAINS_FROM(1) BAYES_HAM(-3) X-Rspamd-Score: -5.6 Received: from unknown (HELO unkown) (::1) by arche.uberspace.de (Haraka/3.0.1) with ESMTPSA; Sat, 01 Apr 2023 16:44:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=leo-andres.de; s=uberspace; h=from; bh=cUpyadozx2C35+T29bVMovaI846cu36tsPMur9v/vm0=; b=VbZvHkpEIKtHj70HScUCjXS7/FONsB4Hng1whCYCnZUI/l4cGOSsEcqqrd/EheS6lN24qdtuMG IDj13ZpEZ/CQaS7NBPu7EJkiKOUxMSJFr6uKjK5nft/Ry0VDhCpvQFdoF4irLFrxvSmpvg+eVvSd ElLwYR2vZZRfKaebmEKSsa5IW4sFCEck/o7G3la+hq4q0YR8O5pM1xr8LtS/VRynZOb3LkeYsxTI EcF7Y87ILKdNC7ZN8VZ9Dcr0lvhsC6rEAwOGJZtwAGlToMPXimfZzX2O1Fml1pE8KQMmT+bYJ2Kn x8gbs07wPjvqcSFvnznAoIoxIN7jle+moB9YIsZmdxT7Hl1WphEGzdaACa5ZmBvJhSJXH1UFSKQw AR0z2qQ2l4DUEAFy+kRSundVUzLIJgm6vdpsRqAq4ekjsQyhi90KDM8BQjFKVDfE7gMXEDHy4Rt6 mojenonR9f+Ga1d7rxYYylMl/UbRShu7aulXYUV4Gh7SSeHuLT/jgdG7XqGZBveQpOc6rHm0JWbS ulBKTPge6QT1JyLzVmf2XvgnUHdMnQMGdF4D++ofDurYTBGJH1Sm7OH4KZ7zfxp2TjsDze5W2rTk cbHjTNCs8S+rPNjD+lGtw9k778wAal1b5ljRI1J8mU/z5JE5W1sWd47wCOKk6Nu6diBGKzmsxoW7 Q= X-Rspamd-Action: no action X-Rspamd-Server: mail01.haj.ipfire.org X-Rspamd-Queue-Id: 4Ppg0G3jNkz2wv X-Spamd-Result: default: False [-5.90 / 11.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[99.99%]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; MX_INVALID(0.50)[]; DMARC_POLICY_ALLOW(-0.50)[leo-andres.de,quarantine]; R_DKIM_ALLOW(-0.20)[leo-andres.de:s=uberspace]; R_SPF_ALLOW(-0.20)[+ip4:185.26.156.0/24:c]; ONCE_RECEIVED(0.10)[]; MIME_GOOD(-0.10)[text/plain]; IP_REPUTATION_HAM(-0.00)[asn: 205766(0.00), country: DE(-0.00), ip: 185.26.156.147(0.00)]; RCVD_VIA_SMTP_AUTH(0.00)[]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_SOME(0.00)[]; FROM_HAS_DN(0.00)[]; ASN(0.00)[asn:205766, ipnet:185.26.156.0/24, country:DE]; RCVD_COUNT_ONE(0.00)[1]; FROM_EQ_ENVFROM(0.00)[]; ARC_SIGNED(0.00)[lists.ipfire.org:s=202003rsa:i=1]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; DKIM_REPUTATION(0.00)[0]; RCPT_COUNT_TWO(0.00)[2]; DKIM_TRACE(0.00)[leo-andres.de:+]; RCVD_IN_DNSWL_NONE(0.00)[185.26.156.147:from]; RCVD_TLS_ALL(0.00)[] X-BeenThere: development@lists.ipfire.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: IPFire development talk List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: development-bounces@lists.ipfire.org Sender: "Development" This migrates the rrdimage.js functions to the new WUI framework and improves some functions. Signed-off-by: Leo-Andres Hofmann --- config/cfgroot/graphs.pl | 2 +- html/html/include/rrdimage.js | 122 ------------------- html/html/include/wui_rrdimage.mjs | 103 +++++++++++++++- html/html/themes/ipfire/include/functions.pl | 1 - 4 files changed, 102 insertions(+), 126 deletions(-) delete mode 100644 html/html/include/rrdimage.js diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 9803dd124..a637e1a6a 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -118,7 +118,7 @@ END # Print range select buttons foreach my $range (@time_ranges) { print < +
  • END } diff --git a/html/html/include/rrdimage.js b/html/html/include/rrdimage.js deleted file mode 100644 index c6f5930c9..000000000 --- a/html/html/include/rrdimage.js +++ /dev/null @@ -1,122 +0,0 @@ -/*############################################################################# -# # -# IPFire.org - A linux based firewall # -# Copyright (C) 2007-2021 IPFire Team # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -#############################################################################*/ - -// "onclick" event handler for graph time range select button -// buttonObj: reference to the button -function rrdimage_selectRange(buttonObj) { - if(! (buttonObj && ('range' in buttonObj.dataset))) { - return; //required parameters are missing - } - - // Get selected time range from button - const range = buttonObj.dataset.range; - - // Get surrounding div box and select new range - let graphBox = $(buttonObj).closest('div'); - _rrdimg_setRange(graphBox, range); -} - -// Document loaded: Process all graphs, start reload timers -$(function() { - $('div.rrdimage').each(function() { - let graphBox = $(this); - _rrdimg_setRange(graphBox, graphBox.data('defaultRange'), true); - }); -}); - -//--- Internal functions --- - -// Set or update graph time range, start automatic reloading -// graphBox: jQuery object, reference to graph div box -// range: time range (day, hour, ...) -// initMode: don't immediately reload graph, but force timers and attributes update -function _rrdimg_setRange(graphBox, range, initMode = false) { - if(! ((graphBox instanceof jQuery) && (graphBox.length === 1))) { - return; //graphBox element missing - } - - // Check range parameter, default to "day" on error - if(! ["hour", "day", "week", "month", "year"].includes(range)) { - range = "day"; - } - - // Check if the time range is changed - if((graphBox.data('range') !== range) || initMode) { - graphBox.data('range', range); //Store new range - - // Update button highlighting - graphBox.find('button').removeClass('selected'); - graphBox.find(`button[data-range="${range}"]`).addClass('selected'); - } - - // Clear pending reload timer to prevent multiple image reloads - let timerId = graphBox.data('reloadTimer'); - if(timerId !== undefined) { - window.clearInterval(timerId); - graphBox.removeData('reloadTimer'); - } - - // Determine auto reload interval (in seconds), - // interval = 0 disables auto reloading by default - let interval = 0; - switch(range) { - case 'hour': - interval = 60; - break; - - case 'day': - case 'week': - interval = 300; - break; - } - - // Start reload timer and store reference - if(interval > 0) { - timerId = window.setInterval(function(graphRef) { - _rrdimg_reload(graphRef); - }, interval * 1000, graphBox); - graphBox.data('reloadTimer', timerId); - } - - // Always reload image unless disabled by init mode - if(! initMode) { - _rrdimg_reload(graphBox); - } -} - -// Reload graph image, add timestamp to prevent caching -// graphBox: jQuery object (graph element must be valid) -function _rrdimg_reload(graphBox) { - const origin = graphBox.data('origin'); - const graph = graphBox.data('graph'); - const timestamp = Date.now(); - - // Get user selected range or fall back to default - let range = graphBox.data('range'); - if(! range) { - range = graphBox.data('defaultRange'); - } - - // Generate new image URL with timestamp - const imageUrl = `/cgi-bin/getrrdimage.cgi?origin=${origin}&graph=${graph}&range=${range}×tamp=${timestamp}`; - - // Get graph image and set new URL - graphBox.children('img').first().attr('src', imageUrl); -} diff --git a/html/html/include/wui_rrdimage.mjs b/html/html/include/wui_rrdimage.mjs index 5254b1e98..64b34dfac 100644 --- a/html/html/include/wui_rrdimage.mjs +++ b/html/html/include/wui_rrdimage.mjs @@ -24,7 +24,106 @@ import {WUIcore_moduleBase as WUI_module} from "./wui_core.mjs"; //--- RRDtool graph images --- export class WUImodule_rrdimage extends WUI_module { - constructor(translations) { - super(translations); + + // DOMContentLoaded/jQuery.ready event handler + _handleDOMReady() { + super._handleDOMReady(); + + // Process all graphs, start reload timers + $("div.rrdimage").each((i, divElem) => { + const $graphBox = $(divElem); + this.#updateProperties($graphBox, $graphBox.data("defaultRange"), true); + + // Attach event listeners to buttons + $graphBox.find("button[data-range]").each((j, buttonElem) => { + const $rangeBtn = $(buttonElem); + $rangeBtn.on(`click.${this.namespace}`, {"graphBox": $graphBox, "range": $rangeBtn.data("range")}, this.#handleRangeClick.bind(this)); + }); + }); + } + + // Graph range select button "click" event handler + #handleRangeClick(event) { + event.preventDefault(); + + this.#updateProperties(event.data["graphBox"], event.data["range"]); + } + + // Update graph range + // $graphBox: jQuery object, reference to a single graph div box + // range: time range (day, hour, ...) + setRange($graphBox, range) { + if(($graphBox instanceof jQuery) && ($graphBox.length === 1)) { + this.#updateProperties($graphBox, range); + } + } + + // Update graph range properties, configure automatic reloading + // $graphBox: jQuery object, reference to graph div box + // range: time range (day, hour, ...) + // initialize: don't immediately reload graph, but force timers and attributes update + #updateProperties($graphBox, range, initialize = false) { + // Check range parameter, default to "day" on error + if(! ["hour", "day", "week", "month", "year"].includes(range)) { + range = "day"; + } + + // Check if the time range is changed + if(($graphBox.data("range") !== range) || initialize) { + $graphBox.data("range", range); //Store new range + + // Update button highlighting + $graphBox.find("button[data-range]").removeClass("selected"); + $graphBox.find(`button[data-range="${range}"]`).addClass("selected"); + } + + // Clear pending reload timer to prevent multiple image reloads + let timerId = $graphBox.data("reloadTimer"); + if(typeof timerId !== "undefined") { + window.clearInterval(timerId); + $graphBox.removeData("reloadTimer"); + } + + // Determine auto reload interval (in seconds), + // interval = 0 disables auto reloading by default + let interval = 0; + switch(range) { + case "hour": + interval = 60; + break; + + case "day": + case "week": + interval = 300; + break; + } + + // Start reload timer and store reference + if(interval > 0) { + timerId = window.setInterval(this.#reloadImage.bind(this), interval * 1000, $graphBox); + $graphBox.data("reloadTimer", timerId); + } + + // Always reload image unless disabled by init mode + if(! initialize) { + this.#reloadImage($graphBox); + } + } + + // Reload graph image, add timestamp to prevent caching + // $graphBox: jQuery object (graph element must be valid/previously processed by updateRange) + #reloadImage($graphBox) { + const origin = $graphBox.data("origin"); + const graph = $graphBox.data("graph"); + + // Get user selected range or fall back to default + const range = $graphBox.data("range") ?? $graphBox.data("defaultRange"); + + // Generate new image URL with timestamp + const timestamp = Date.now(); + const imageUrl = `/cgi-bin/getrrdimage.cgi?origin=${origin}&graph=${graph}&range=${range}×tamp=${timestamp}`; + + // Get graph image and set new URL + $graphBox.children("img").first().attr("src", imageUrl); } } diff --git a/html/html/themes/ipfire/include/functions.pl b/html/html/themes/ipfire/include/functions.pl index 445597e51..bc66d7fdb 100644 --- a/html/html/themes/ipfire/include/functions.pl +++ b/html/html/themes/ipfire/include/functions.pl @@ -115,7 +115,6 @@ print < - $extrahead