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