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 5e275075..5d9676c7 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 a646e8f7..9b729cd6 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 c9870ea1..688ebbc8 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 aa395392..a9da184f 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 dc2624f9..437453fd 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 d12cb0a7..c1b7d106 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 437453fd..354016f5 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 a9da184f..2ec07542 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 f7573a28..a4bc95b0 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 99e56421..cd223ffe 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,