Hi Adolf,
Thanks for the heads up!
Am 13.04.2023 um 13:42 schrieb Adolf Belka:
Hi Leo,
On 12/04/2023 09:14, Leo-Andres Hofmann wrote:
Hi Michael,
Am 11.04.2023 um 14:58 schrieb Michael Tremer:
Hello,
Thanks for the patchset.
It is a lot of code to look through indeed.
Yes, I'm aware this is a bit unannounced and a lot of code. Thank you for looking at it!
On 1 Apr 2023, at 15:43, Leo-Andres Hofmannhofmann@leo-andres.de wrote:
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 Hofmannhofmann@leo-andres.de
Hi all,
this patchset brings new modern Javascript modules to the webinterface.
I suppose there is no way around this.
My thinking was: At the moment, the web interface is quite old-fashined and uses relatively little javascript, scattered in multiple files. But new features are still added on a fairly regular basis. So I think it makes sense to start a good structure now rather than later.
Is this all written from scratch? Did you base this on anything or use some existing code as inspiration?
This is written from scratch, in the sense that it is not just a modified copy of some existing library. However, I have read the documentation of other libraries before, and there are only so many reasonable ways to implement this. So I haven't tried to reinvent the wheel, and you'll certainly be able to find similarities to existing libraries. But the actual source code in this patchset is 100% my own work.
- The module.enable/readyState logic is inspired by jQuery's .ready
and the HTML DOM readyState property
- The i18n class is based on the work I did for pakfire.js and
extended to work with the module concept
- To learn how to create the CSS overlay window, I followed the
w3schools tutorial "Overlay"
I have done some changes on the dhcp.cgi and urlxlrator.cgi pages to replace bgcolor, which was deprecated in HTML 4.x and no longer supported at all in HTML 5, with its CSS equivalent approach. I used your CSS approach on the zone config cgi page as the basis for what I changed.
My plan was to go through the other cgi pages doing the same type of changes.
Should I hold on that until you have made this change to the CSS approach with the CSS Overlay?
I mostly add new things here, so I don't think this could be a problem. You can go ahead!
By the way, if you want to make things a bit easier for yourself: Check out the nth-child CSS selector: "tr:nth-child(2n+3)" With this, you can do the color assignment for odd/even rows entirely in CSS and remove all the uncessary "if ($id % 2) color1..., else color2..." Perl code. Then you only need to print a plain HTML table, everything else is done by the browser.
Best, Leo
Regards, Adolf.
- The async/await interface for the dialog box is inspired by
jQuery's deferred.then() interface for Ajax calls, but implemented with native JS
Are they any existing libraries that could be useful for example pulling in the translation?
I looked at a few popular libraries, but in my opinion they are too extensive and do not fit well with the existing web interface. (jquery.i18n, Polyglot, ...) For example, some libraries I found prefer to load the texts from a JSON file. This would result in additional language files parallel to the existing system. Besides, dynamically changing translations based on user agent settings may break the form field mapping: if ($cgiparams{'ACTION'} eq $Lang::tr{'save'} )... If we didn't have to pay attention to many specifics of the old CGIs, I would also prefer an existing library.
Best, Leo
-Michael
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 Teaminfo@ipfire.org # +# # +# 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, seehttp://www.gnu.org/licenses/. # +# # +#############################################################################*/
+// 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 Teaminfo@ipfire.org # +# # +# 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<http://www. gnu.org/licenses/>. # +# # +#############################################################################*/
+// 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 Teaminfo@ipfire.org # +# # +# 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, seehttp://www.gnu.org/licenses/. # +# # +#############################################################################*/
+// 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 <<END;
<title>$headline - $title</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="shortcut icon" href="/favicon.ico" /> - <script type="text/javascript" src="/include/jquery.js"></script> + <script src="/include/jquery.js"></script> + <script src="/include/wui.js" type="module"></script> <script src="/include/rrdimage.js"></script>
$extrahead
2.37.1.windows.1