From patchwork Sat Apr 1 14:43:40 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: 6754 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) server-digest SHA384 client-signature ECDSA (P-384) client-digest SHA384) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by web04.haj.ipfire.org (Postfix) with ESMTPS id 4Ppg0H6hwhz3x2l for ; Sat, 1 Apr 2023 14:44:15 +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) server-digest SHA384 client-signature ECDSA (P-384) client-digest SHA384) (Client CN "mail02.haj.ipfire.org", Issuer "R3" (verified OK)) by mail01.ipfire.org (Postfix) with ESMTPS id 4Ppg0G0BDzz1Yy; Sat, 1 Apr 2023 14:44:13 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4Ppg0F5CZ0z2yTC; Sat, 1 Apr 2023 14:44:13 +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) server-digest SHA384 client-signature ECDSA (P-384) client-digest SHA384) (Client CN "mail01.haj.ipfire.org", Issuer "R3" (verified OK)) by mail02.haj.ipfire.org (Postfix) with ESMTPS id 4Ppg0C5lnbz2xkd for ; Sat, 1 Apr 2023 14:44:11 +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 4Ppg061Y9qzhR for ; Sat, 1 Apr 2023 14:44:06 +0000 (UTC) Authentication-Results: mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=P8oW7Py1; 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=1680360246; a=rsa-sha256; cv=none; b=iPIMgDSXQTRVdyscmFaIuzMm0t308PvywJXRy7cXjQ/qfMApz9+E0yeKPsR/nBGHEEmKzt 0givyAxs9Qu/7KqBo0Zo6d6DL4ES6wq5F7tfP5WYAU5BL27Ojt0FMOkyivgOXNCTAMec59 e/OFguRXi/pbD35+hweGKS1y5Hx+RFDqqxNsAuVKP8yqDpsesAeZm3QIc/ELcAQSMI9VQ5 xSCS5Gm3GQVJziPYRRc0vJ4/NuEhwraO/IhsdG1ybvbPK5Df63+CvuZkelpp/iNuwO/gd7 3BcK5z8oOq8unAP0stG0q5AApyxRew4fB/E/yt72CHutxIm9viEEPyW7IxxZfQ== ARC-Authentication-Results: i=1; mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=P8oW7Py1; 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=1680360246; 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:dkim-signature; bh=uM5JVXSF2KPheTIyllS1Bn3E3mj+qZlWsGyeqsouC5U=; b=VGKUWR8ER/26n7h40o/o4neTn8MVg+jj6Q0iGi4x74oShbw7G7UkwkTvehU+xGSa4yWeUH o6Cp3hw+1rysX0aL+8KcYZoCF459BTQmQc9J6XFsFxGnhzp1iO5Z82cuB/idV5P4O2kz6u sY7hCaVIiYlsc7hDvDB/Tj2X2Zj9wJ7A+/f41qzo5pIuevBqWc9Zlh2qOGyoiKmOeIBiIC 0mXfLAPRkVhNXT48s5Kqc97TYaPMTNf7OcqBZ516LANOXjlGr5Sdf21rD7kea5bK35a+zs a5xOw1ouWcvBQHYYlfSby4q40LB0t+aDnH8uVsPZtnslRPUZg2wWI6v08k35Vg== Received: (qmail 16765 invoked by uid 990); 1 Apr 2023 14:44:04 -0000 From: Leo-Andres Hofmann To: development@lists.ipfire.org Subject: [PATCH 1/4] WUI: Start implementing a simple JavaScript framework Date: Sat, 1 Apr 2023 16:43:40 +0200 Message-Id: <20230401144343.1483-1-hofmann@leo-andres.de> X-Mailer: git-send-email 2.37.1.windows.1 MIME-Version: 1.0 X-Rspamd-Bar: - X-Rspamd-Report: R_MISSING_CHARSET(0.5) MIME_GOOD(-0.1) MID_CONTAINS_FROM(1) BAYES_HAM(-3) X-Rspamd-Score: -1.6 Received: from unknown (HELO unkown) (::1) by arche.uberspace.de (Haraka/3.0.1) with ESMTPSA; Sat, 01 Apr 2023 16:44:04 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=leo-andres.de; s=uberspace; h=from; bh=KLY2XwQkND6bno44TK+3oc/UJQ0CZvJZy9UsIUnHiFc=; b=P8oW7Py1HMAf/+eticrvQ41U8QMmV765pMEbnEhlvRgENNQrqdWk007s+BDU0esZWXcQ5Vj4zm rqyt2aTmWa1zFW2wRk8MdvKl7VPUo3v6mepQtxeWYdkpWSaQN/4XCT3Xw3ouTjxltIeqe1y+ag5O zWDJAfG+M+ikQ7M//+n+JNLPh+T1ZN39Iekcsv7pZrj5SHcrHz577bVe5k0JAl4oBd5vjBD+qNa8 YGrCgxR0RnNBeuI/KTQw+XS5OR3FAvdg+ZpI8nnF7+5SZR2OyLx2szWwxNHPl88BItWijJcqNVi0 yvWRlwU1xSgzCJcV2wwFpqbiv0Ch2x9Hk+eF05yxxj/WD/ABmPTo3kC1s8jffYkcNp3wvfD8DFR1 OqFaY+gF79ozgld1uGIc88Vp5KUEj5z8lahIk/WZbrML0T+2yAhTYuQVDmssxJ/ZkZiDCNVjpidF 7Hv0bLoiLjJssVSu8DoseBY/0KLX5LXSdRewPOGnj2NHos+sYI0wwEeSETCz0v/d5NX1yaoDOgyO LmLYnIYlO06GIT8l/e2Ads1xlNVH0TWclYijsndKSKnpY4aMrBciKXLldT5IUZCBxMrm2BaomjcV C4jyEs88qiikXPtLHKYCWQODpAmnvwzvOWxWWiTMjy70dCZmwXgpnrgKJJ/trpnjToQK9EucoI8J 0= X-Rspamd-Action: no action X-Rspamd-Server: mail01.haj.ipfire.org X-Rspamd-Queue-Id: 4Ppg061Y9qzhR X-Spamd-Result: default: False [-1.90 / 11.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]; MIME_GOOD(-0.10)[text/plain]; ONCE_RECEIVED(0.10)[]; IP_REPUTATION_HAM(-0.00)[asn: 205766(0.00), country: DE(-0.00), ip: 185.26.156.147(0.00)]; RCVD_TLS_ALL(0.00)[]; RCVD_IN_DNSWL_NONE(0.00)[185.26.156.147:from]; ASN(0.00)[asn:205766, ipnet:185.26.156.0/24, country:DE]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_ONE(0.00)[1]; MIME_TRACE(0.00)[0:+]; TO_MATCH_ENVRCPT_SOME(0.00)[]; DKIM_TRACE(0.00)[leo-andres.de:+]; FROM_HAS_DN(0.00)[]; ARC_NA(0.00)[]; RCPT_COUNT_TWO(0.00)[2]; TO_DN_SOME(0.00)[]; DKIM_REPUTATION(0.00)[0]; ARC_SIGNED(0.00)[lists.ipfire.org:s=202003rsa:i=1]; RCVD_VIA_SMTP_AUTH(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 patch is an effort to modernize and unify the WUI JavaScript. It will be possible to share e.g. translation strings and common functions between the different modules. This uses native ES6 modules that are supported by all major browsers. Therefore, no change to the toolchain is necessary. Signed-off-by: Leo-Andres Hofmann --- Hi all, this patchset brings new modern Javascript modules to the webinterface. Still on my to-do/wish list: - run make.sh lang - convert pakfire.js to a module - convert/rewrite refreshInetInfo.js, maybe add load displays to all interfaces in index.cgi I hope this is in a presentable state to see where it is headed. Let me know what you think and as always thanks for reading/testing/reviewing :) Best, Leo config/etc/mime.types | 1 + html/html/include/wui.js | 47 ++++++ html/html/include/wui_core.mjs | 154 +++++++++++++++++++ html/html/include/wui_rrdimage.mjs | 30 ++++ html/html/themes/ipfire/include/functions.pl | 3 +- 5 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 html/html/include/wui.js create mode 100644 html/html/include/wui_core.mjs create mode 100644 html/html/include/wui_rrdimage.mjs diff --git a/config/etc/mime.types b/config/etc/mime.types index af82d4886..bb3816db9 100644 --- a/config/etc/mime.types +++ b/config/etc/mime.types @@ -252,6 +252,7 @@ multipart/voice-message text/css css text/directory text/enriched +text/javascript mjs text/plain asc txt text/prs.lines.tag text/rfc822-headers diff --git a/html/html/include/wui.js b/html/html/include/wui.js new file mode 100644 index 000000000..e65924e29 --- /dev/null +++ b/html/html/include/wui.js @@ -0,0 +1,47 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2023 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 . # +# # +#############################################################################*/ + +// IPFire Web User Interface +// Collection of JavaScript functions and modules (requires jQuery) + +import {WUIcore_i18n as WUI_i18n} from "./wui_core.mjs"; + +import {WUImodule_rrdimage as WUI_rrdimage} from "./wui_rrdimage.mjs"; + +//--- WUI main class --- +class WUImain { + constructor() { + //- Public properties - + // Translation strings + this.i18n = new WUI_i18n(); + + //- Modules - + // RRDtool graph images + this.rrdimage = new WUI_rrdimage(this.i18n); + + //- Defaults - + // These modules are available on every page: + this.rrdimage.enabled = true; + } +} + +//### Initialize WUI ### +const wui = new WUImain(); +export default wui; diff --git a/html/html/include/wui_core.mjs b/html/html/include/wui_core.mjs new file mode 100644 index 000000000..b7b729396 --- /dev/null +++ b/html/html/include/wui_core.mjs @@ -0,0 +1,154 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2023 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 . # +# # +#############################################################################*/ + +// IPFire Web User Interface - JavaScript module +// Core functions & module helpers + +//--- Module template --- +// Make sure that overridden functions are still executed with super()! +export class WUIcore_moduleBase { + //- Private properties - + #enabled; // Activation state, disabled by default + #readyState; // Loading state similar to Document.readyState + #namespace; // Namespace derived from the class name (without "WUImod_" prefix) + + //- Class constructor - + constructor(translations) { + this.i18n = translations; + + this.#enabled = false; + + this.#readyState = "loading"; + this.#namespace = this.constructor.name.slice(10); + } + + // Module activation state + // Note: Because a module likely changes the DOM, it is not intended that it can + // be cleanly disabled again. Disabling it anyway will trigger "_handleModuleDestroy". + set enabled(state) { + if(this.#enabled !== state) { + this.#enabled = state; + + if(state) { + this._handleModuleEnable(); + } else { + this._handleModuleDestroy(); + } + } + } + get enabled() { + return this.#enabled; + } + + // Module loading state + // loading: Instance created + // interactive: Module enabled, document not ready + // complete: DOMContentLoaded/jQuery.ready event fired + // destroyed: Module disabled, event handlers removed + get readyState() { + return this.#readyState; + } + + // Module namespace + get namespace() { + return this.#namespace; + } + + //### Protected properties ### + + // Module activation state event handlers + _handleModuleEnable() { + if(this.#readyState === "loading") { + this.#readyState = "interactive"; + + // Attach jQuery.ready event + $(this._handleDOMReady.bind(this)); + } + } + _handleModuleDestroy() { + this.#readyState = "destroyed"; + + // Attempt to remove all event handlers of this module + $("body").off(`.${this.namespace}`); + } + + // DOMContentLoaded/jQuery.ready event handler + // The module must be enabled for this event to be triggered once + _handleDOMReady() { + this.#readyState = "complete"; + } + + // Translations quick access in module namespace + _i18n(key) { + return this.i18n.get(key, this.namespace); + } +} + +//--- Simple translation strings helper --- +export class WUIcore_i18n { + //- Private properties - + #strings; + + //- Class constructor - + constructor() { + this.#strings = Object.create(null); //Object without prototypes + } + + // Default module prefix for general translations + get #mainModule() { + return "wui"; + } + + // Get translation + get(key, module = this.#mainModule) { + const index = `${module}%${key}`; + + if(Object.hasOwn(this.#strings, index)) { + return this.#strings[index]; + } + return `(missing string '${key}' in '${module}')`; + } + + // Add translation + add(key, value, module = this.#mainModule) { + if(typeof value === "string" || typeof value === "number") { + this.#strings[`${module}%${key}`] = value; + } + } + + // Load key/translation JS object + // Format: {"key": "translation"} + load(translations, module = this.#mainModule) { + if(translations instanceof Object) { + Object.entries(translations).forEach(([key, value]) => { + this.add(key, value, module); + }); + } + } +} + +//--- Static utility functions --- +export class WUIcore_utilities { + // Reload document (clears POST/GET data from history) + static reloadDocument() { + const url = window.location.origin + window.location.pathname; + window.location.replace(url); + } +} diff --git a/html/html/include/wui_rrdimage.mjs b/html/html/include/wui_rrdimage.mjs new file mode 100644 index 000000000..5254b1e98 --- /dev/null +++ b/html/html/include/wui_rrdimage.mjs @@ -0,0 +1,30 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2023 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 . # +# # +#############################################################################*/ + +// IPFire Web User Interface - JavaScript module + +import {WUIcore_moduleBase as WUI_module} from "./wui_core.mjs"; + +//--- RRDtool graph images --- +export class WUImodule_rrdimage extends WUI_module { + constructor(translations) { + super(translations); + } +} diff --git a/html/html/themes/ipfire/include/functions.pl b/html/html/themes/ipfire/include/functions.pl index cbd05d109..445597e51 100644 --- a/html/html/themes/ipfire/include/functions.pl +++ b/html/html/themes/ipfire/include/functions.pl @@ -113,7 +113,8 @@ print <$headline - $title - + + $extrahead 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 END diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index 729516538..df9deda53 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -84,6 +84,10 @@ 'ConnSched up' => 'Up', 'ConnSched weekdays' => 'Days of the week:', 'Daily' => 'Daily', +'dialog confirm title' => 'Permanently save changes?', +'dialog confirm subheading' => 'The following action cannot be undone:', +'dialog confirm submit' => 'Yes, continue', +'dialog confirm cancel' => 'No, cancel', 'Disabled' => 'Disabled', 'Edit an existing route' => 'Edit an existing route', 'Enter TOS' => 'Activate or deactivate TOS-bits
    and then press Save.', From patchwork Sat Apr 1 14:43:43 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: 6757 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 4Ppg0R4qNZz3x2l for ; Sat, 1 Apr 2023 14:44:23 +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 4Ppg0R0gzxz2wx; Sat, 1 Apr 2023 14:44:23 +0000 (UTC) Received: from mail02.haj.ipfire.org (localhost [127.0.0.1]) by mail02.haj.ipfire.org (Postfix) with ESMTP id 4Ppg0R0Bnqz2yVy; Sat, 1 Apr 2023 14:44:23 +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 4Ppg0Q3jGDz2xxv for ; Sat, 1 Apr 2023 14:44:22 +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 4Ppg0Q2j30zhR for ; Sat, 1 Apr 2023 14:44:22 +0000 (UTC) Authentication-Results: mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=JAMi5nEC; 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=1680360262; a=rsa-sha256; cv=none; b=jeiSnRveo0KcBwHTJtqC+b8GX/sh4pKBl1YNMWHxJh7FKp+GuNv8OzAOb8OsFCvdcFUCcu kdCeQcOkXSTBeQJm53bsfX9QrktpcTnHnA3He31ydMQqnhpsJ7uwqvqS6s5C7y1ICmH00E 59P06ujw6rfMZR7y4cSmMpVtPgTIU9RaWTsHcZDBlrvm1gmPTA4h2rb3oKEITLOwA/oh2D zvj8ULDfP73nyCrOH1YnO/R343iTevipGieG/dDlftfClppJ5cmJ5P4kIfXcNUi1YVAdPi bWLh6HahhpfjEV7CGSDjU1CHVeDkrOPn2cECwl9pbg/1nuuzBi/btIrFH/wHiw== ARC-Authentication-Results: i=1; mail01.ipfire.org; dkim=pass header.d=leo-andres.de header.s=uberspace header.b=JAMi5nEC; 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=1680360262; 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=Ea0wH8BKqTPoWM5LjIwsdzJ2i3RcIPEW0RvTl1cHAE4=; b=Cse0f4qFlLwGvhEJmNs8tV/1+Vnjo6CXpqGMdpn6Ct9MqXRtCHax2hpbA3m/oUW0glZtBp Ld+mWlQ4lDxxlGNxKKr1/NPd/KHHVO4qYx7eIMdttWHOqJcIok4VOLeQwyVe2i4H4aWznU fxeSkX6MGk10GNLEMpSCuIdH/AYi//9JMXv1SaRlHKlZmH0pbjuHlAZvqeJ3xZrEJI7aFp aWns6huPI+EbkBfOe8Z/lvdC5QraOjfpGIzha9oZSYGcRK8oZKam2fDzCXz2xjz6tCZ2Y9 7rUoErQiGeXHOofW10qndr4DZq/ielUAw1o/sr8A8+Ti9d5zH04wL1E5pXN06A== Received: (qmail 17060 invoked by uid 990); 1 Apr 2023 14:44:22 -0000 From: Leo-Andres Hofmann To: development@lists.ipfire.org Subject: [PATCH 4/4] ovpnmain.cgi: Add confirm dialog to delete form Date: Sat, 1 Apr 2023 16:43:43 +0200 Message-Id: <20230401144343.1483-4-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:21 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=leo-andres.de; s=uberspace; h=from; bh=n7MrDMvdavYq4K9LxdLT3A8AJLWpZewmwIekqXiuu/I=; b=JAMi5nEC7hq0qUnru6N4Y228Zs58hWlhh2CgsxtNDNSZKBuTRcXTkNtjvESxDF0JojKbjuzE6y GxA3AaBe5khxgUlZqgxgNOJmcmGIv7nK8Bc/8xz0GKFZbpxRHHFzxuv/BNMdiXTaMVtZ4ndHiX/X lElEkMUHaxDuOFgptmBtW+WsEiR3mN9l+kouSr0oZeLaL21tWfgypoI9SIz/ke+IYtkct0/oEIc9 BU2G7UHjJa2edFbjC9TgdIYTRLKJSB84WEJu4Hdjv8UgqaP5388bPSkmcS5Jv5dyQbA40KQkwe8d n+h3s9vGnPyeZhfQkFJkAna7VU8REBr09wRvxlN1lNrXBEZHF+k46rt4mbOMUHrxb08K1N4hLjd3 Kdrfre1BSAVHOOcpOjPAqz7CwXAD0anfgGImUpqP658HYluQVrgjYuPK2zd+N71HN8Uj/1BmRp00 qLcPABETROm35QJtLRg0nKgiuHpv6IrXpSVegP1FxJVvodUDaGqPijqfzlWCnqOm4xzHVZDGENzP /5tNKUx3LIf5yyiBdhDtmg+uG8hLKh2osu2BQynAjcJ+5tDiDPWVAp7ix6TOMNRVQgGa3GKeu6DM Je5O63v2ISlVEaiTpGybFQPI/oF/SinN62c3djd3LQSv3XfyYWvEOqpMsL8XksxFS8hMOY70eiuw 4= X-Rspamd-Action: no action X-Rspamd-Server: mail01.haj.ipfire.org X-Rspamd-Queue-Id: 4Ppg0Q2j30zhR X-Spamd-Result: default: False [-5.90 / 11.00]; REPLY(-4.00)[]; BAYES_HAM(-3.00)[99.98%]; 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 adds a confirmation dialog to the delete buttons, thus preventing users from accidentally removing certificates that are still in use. Fixes: #13058 Signed-off-by: Leo-Andres Hofmann --- html/cgi-bin/ovpnmain.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/cgi-bin/ovpnmain.cgi b/html/cgi-bin/ovpnmain.cgi index 87bda4f1e..b0f00fa57 100644 --- a/html/cgi-bin/ovpnmain.cgi +++ b/html/cgi-bin/ovpnmain.cgi @@ -5539,7 +5539,7 @@ END -
    +