From 259d1b86d0b7c99d0638f55e73122f0aff006a77 Mon Sep 17 00:00:00 2001 From: Gayan Sandamal Date: Thu, 26 Sep 2024 10:27:46 +0530 Subject: [PATCH 1/5] Added app icon field to ui base --- docs/nodes/config/ui-base.md | 1 + nodes/config/locales/en-US/ui_base.html | 7 +++++++ nodes/config/locales/en-US/ui_base.json | 1 + nodes/config/ui_base.html | 14 ++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/docs/nodes/config/ui-base.md b/docs/nodes/config/ui-base.md index 5e275075d..5d9676c75 100644 --- a/docs/nodes/config/ui-base.md +++ b/docs/nodes/config/ui-base.md @@ -2,6 +2,7 @@ description: Configure the base UI settings of Node-RED Dashboard 2.0 to tailor the dashboard environment to your needs. props: Path: The endpoint proceeding the host of Node-RED where your UI will be accessible + App Icon: Allows you to set a custom icon for your application. Provide the URL to the App Icon, which will be displayed as the app icon and in the browser tab. Include Page Path in Label: The side navigation lists all available Pages for the Dashboard. By default, this will just show the page name, but this option allows you to also show the page's path. Side Navigation Style: The style the side navigation menu should use (default, fixed, icon, temporary, none) --- diff --git a/nodes/config/locales/en-US/ui_base.html b/nodes/config/locales/en-US/ui_base.html index a646e8f78..9b729cd60 100644 --- a/nodes/config/locales/en-US/ui_base.html +++ b/nodes/config/locales/en-US/ui_base.html @@ -17,4 +17,11 @@ +
+ App Icon + URL +
+
+ You can provide a custom URL for your application's icon, which will be displayed as the app icon and in the browser tab. +
diff --git a/nodes/config/locales/en-US/ui_base.json b/nodes/config/locales/en-US/ui_base.json index c9870ea12..688ebbc87 100644 --- a/nodes/config/locales/en-US/ui_base.json +++ b/nodes/config/locales/en-US/ui_base.json @@ -4,6 +4,7 @@ "label": { "uiName": "UI Name", "path": "Path", + "appIcon": "App Icon", "category": "dashboard 2", "dashboard2": "Dashboard 2.0", "editSettings": "Edit Settings", diff --git a/nodes/config/ui_base.html b/nodes/config/ui_base.html index aa3953925..a9da184f8 100644 --- a/nodes/config/ui_base.html +++ b/nodes/config/ui_base.html @@ -326,6 +326,9 @@ value: '/dashboard', required: true }, + appIcon: { + value: '' + }, includeClientData: { value: true }, @@ -349,6 +352,7 @@ return `${this.name} [${this.path}]` || 'UI Config' }, oneditprepare: function () { + debugger // backward compatibility for navigation style if (!this.titleBarStyle) { // set to default @@ -364,6 +368,10 @@ // update the jquery checkbox $('#node-config-input-showPageTitle').prop('checked', true) } + + if (this.appIcon) { + $('#node-config-input-appIcon').val(this.appIcon) + } }, onpaletteadd: function () { // add the Dashboard 2.0 sidebar @@ -391,6 +399,7 @@ icon: null, color: null, isSubflowInstance: false, + appIcon: node.appIcon, node } if (hasProperty(node, 'group')) { item.group = node.group } @@ -1988,6 +1997,11 @@ This option is currently disabled and still in-development. +
+ + + Enter the url of your app icon here +
From 3cfb5cbd0b681b7575210964e65e08ea95c72a64 Mon Sep 17 00:00:00 2001 From: Gayan Sandamal Date: Thu, 26 Sep 2024 16:15:13 +0530 Subject: [PATCH 2/5] Override favicon if the app icon is available --- ui/src/layouts/Baseline.vue | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ui/src/layouts/Baseline.vue b/ui/src/layouts/Baseline.vue index dc2624f9b..437453fd3 100644 --- a/ui/src/layouts/Baseline.vue +++ b/ui/src/layouts/Baseline.vue @@ -154,6 +154,9 @@ export default { appBarStyle: function () { return this.dashboard.titleBarStyle || 'default' }, + appIcon () { + return this.dashboard.appIcon + }, navigationStyle: function () { const style = this.dashboard.navigationStyle if (![null, 'default', 'fixed', 'icon', 'temporary', 'none'].includes(style)) { @@ -184,6 +187,34 @@ export default { this.rail = true } } + }, + appIcon: { + immediate: true, + handler (url) { + // extract the file extension from the URL + const getFileTypeFromURL = (url) => { + const segments = url.split('.') + const extension = segments[segments.length - 1] + return extension.toLowerCase() + } + if (url) { + const fileType = getFileTypeFromURL(url) + // The existing rel types in the index.html + const relTypes = ['icon', 'alternate icon', 'apple-touch-icon'] + relTypes.forEach((relType) => { + // iterate through the rel types and update the link tag + const link = document.querySelector(`link[rel="${relType}"]`) + // remove the type and href attributes + link.removeAttribute('type') + link.removeAttribute('href') + if (link) { + // set the type and href attributes + link.setAttribute('type', `image/${fileType}`) + link.setAttribute('href', url) + } + }) + } + } } }, mounted () { From 64c98d5829543800aa39490d9e2f56671e0e313c Mon Sep 17 00:00:00 2001 From: Gayan Sandamal Date: Mon, 30 Sep 2024 12:24:06 +0530 Subject: [PATCH 3/5] fixed favicon flashing issue --- ui/index.html | 2 +- ui/src/layouts/Baseline.vue | 26 +++++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/ui/index.html b/ui/index.html index d12cb0a7a..c1b7d106e 100644 --- a/ui/index.html +++ b/ui/index.html @@ -5,7 +5,7 @@ Node-RED Dashboard 2.0 - + diff --git a/ui/src/layouts/Baseline.vue b/ui/src/layouts/Baseline.vue index 437453fd3..354016f50 100644 --- a/ui/src/layouts/Baseline.vue +++ b/ui/src/layouts/Baseline.vue @@ -89,8 +89,8 @@ function getContrast (bg) { // http://www.w3.org/TR/AERT#color-contrast const brightness = Math.round(((parseInt(bgRgb[0]) * 299) + - (parseInt(bgRgb[1]) * 587) + - (parseInt(bgRgb[2]) * 114)) / 1000) + (parseInt(bgRgb[1]) * 587) + + (parseInt(bgRgb[2]) * 114)) / 1000) const textColor = (brightness > 125) ? '#000000' : '#ffffff' return textColor @@ -197,22 +197,34 @@ export default { const extension = segments[segments.length - 1] return extension.toLowerCase() } + // The existing rel types in the index.html + const relTypes = ['icon', 'alternate icon', 'apple-touch-icon'] if (url) { const fileType = getFileTypeFromURL(url) - // The existing rel types in the index.html - const relTypes = ['icon', 'alternate icon', 'apple-touch-icon'] relTypes.forEach((relType) => { // iterate through the rel types and update the link tag const link = document.querySelector(`link[rel="${relType}"]`) - // remove the type and href attributes - link.removeAttribute('type') - link.removeAttribute('href') if (link) { // set the type and href attributes link.setAttribute('type', `image/${fileType}`) link.setAttribute('href', url) } }) + } else { + relTypes.forEach((relType) => { + // iterate through the rel types and update the link tag + const link = document.querySelector(`link[rel="${relType}"]`) + if (relType === 'icon') { + link.setAttribute('type', 'image/x-icon') + link.setAttribute('href', '/dashboard/favicon.ico') + } else if (relType === 'alternate icon') { + link.setAttribute('type', 'image/svg+xml') + link.setAttribute('href', '/dashboard/favicon.svg') + } else if (relType === 'apple-touch-icon') { + link.setAttribute('type', 'image/png') + link.setAttribute('href', '/dashboard/apple-touch-icon.png') + } + }) } } } From 73ddbf6729e0dcf472ea235248354b20d4777ebb Mon Sep 17 00:00:00 2001 From: Gayan Sandamal Date: Mon, 30 Sep 2024 22:24:51 +0530 Subject: [PATCH 4/5] Removed unwanted debugger --- nodes/config/ui_base.html | 1 - 1 file changed, 1 deletion(-) diff --git a/nodes/config/ui_base.html b/nodes/config/ui_base.html index a9da184f8..2ec075423 100644 --- a/nodes/config/ui_base.html +++ b/nodes/config/ui_base.html @@ -352,7 +352,6 @@ return `${this.name} [${this.path}]` || 'UI Config' }, oneditprepare: function () { - debugger // backward compatibility for navigation style if (!this.titleBarStyle) { // set to default From 320b961205881b3a9e920d121ff3599ab24eba90 Mon Sep 17 00:00:00 2001 From: Gayan Sandamal Date: Mon, 7 Oct 2024 16:49:23 +0530 Subject: [PATCH 5/5] Customizable PWA icon support --- nodes/config/ui_base.js | 22 ++++++++++++++++++++++ vite.config.js | 5 +---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/nodes/config/ui_base.js b/nodes/config/ui_base.js index f7573a283..a4bc95b09 100644 --- a/nodes/config/ui_base.js +++ b/nodes/config/ui_base.js @@ -139,6 +139,28 @@ module.exports = function (RED) { res.sendFile(path.join(__dirname, '../../dist/index.html')) }) + uiShared.app.get('/dashboard/manifest.webmanifest', (req, res) => { + const hasAppIcon = (config.appIcon && config.appIcon.trim() !== '') + const manifest = { + name: 'Node-RED Dashboard 2.0', + short_name: 'Dashboard', + start_url: './', + display: 'standalone', + background_color: '#ffffff', + lang: 'en', + scope: './', + description: 'Node-RED Dashboard 2.0', + theme_color: '#ffffff', + icons: [ + { src: hasAppIcon ? config.appIcon : 'pwa-64x64.png', sizes: '64x64', type: 'image/png' }, + { src: hasAppIcon ? config.appIcon : 'pwa-192x192.png', sizes: '192x192', type: 'image/png' }, + { src: hasAppIcon ? config.appIcon : 'pwa-512x512.png', sizes: '512x512', type: 'image/png' }, + { src: hasAppIcon ? config.appIcon : 'pwa-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' } + ] + } + return res.json(manifest) + }) + uiShared.app.get(config.path + '/*', uiShared.httpMiddleware, (req, res) => { res.sendFile(path.join(__dirname, '../../dist/index.html')) }) diff --git a/vite.config.js b/vite.config.js index 99e56421f..cd223ffe9 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,9 +1,6 @@ import vue from '@vitejs/plugin-vue' import { defineConfig } from 'vite' import { VitePWA } from 'vite-plugin-pwa' - -import manifest from './manifest.json' - /** * Vite is used to build the UI for the dashboard, * is is not used for the nodes themselves. @@ -24,7 +21,7 @@ export default defineConfig({ registerType: 'autoUpdate', injectRegister: false, - manifest, + manifest: false, injectManifest: { maximumFileSizeToCacheInBytes: 3000000,