LedgerSMB icon indicating copy to clipboard operation
LedgerSMB copied to clipboard

The HTML <Title> element is not useful for navigation

Open auspex opened this issue 7 months ago • 4 comments

Version

1.12.9

What browsers are you seeing the problem on?

Chrome, This problem isn't browser related

What happened?

On the login page, the

element is: <pre><code><title>LedgerSMB 1.12.9</title> </code></pre> <p>Once logged in, my title becomes:</p> <pre><code><title>LedgerSMB 1.12.9 -- derek -- coastalvoices</title> </code></pre> <p>on <strong>every</strong> page. This is not useful for those of us who routinely use the back button to navigate.</p> <h3>What should have happened?</h3> <p>I expect the HTML Title to reflect <em>where</em> I am within a website.</p> <p>The current title is a lot of text and most of it not useful.</p> <p>If you're the site admin, you really should know what version of LSMB you're running, and users don't <em>care</em>. Most websites would put that info in a page footer or an 'About' page.</p> <p>Similarly, I probably know who I'm logged in as. Most people won't log in under more than one name, an admin like me might log in as 'admin' and under my own name, but rarely anything else. If you really need to check who you are, it should be in the preferences page (most websites would have a User icon where those would be set).</p> <p>Now, it may well be a good idea to put the database name there — I suspect a lot of people using LSMB are bookkeeping for multiple companies — but I suggest a much better use of the title tag would be:</p> <pre><code><title>LedgerSMB—{DB NAME}—{MENU ENTRY}</title> </code></pre>

auspex avatar Jun 17 '25 15:06 auspex

I've tried this patch:

diff --git a/UI/src/views/LsmbMain.vue b/UI/src/views/LsmbMain.vue
index fd1fcd59e..ff4cb4e80 100644
--- a/UI/src/views/LsmbMain.vue
+++ b/UI/src/views/LsmbMain.vue
@@ -103,12 +103,23 @@ export default {
         }
     },
     async mounted() {
-        window.__lsmbLoadLink = (url) => {
+        window.__lsmbLoadLink = (url, options) => {
             let tgt = url.replace(/^https?:\/\/(?:[^@/]+)/, "");
             if (!tgt.startsWith("/")) {
                 tgt = "/" + tgt;
             }
-            this.$router.push(tgt);
+            let { title } = options;
+            this.$router.push(
+                tgt,
+                () => {
+                    console.log('navigation done');
+                    if (title) {
+                        document.title = title;
+                    }
+                },
+                () => {
+                    console.log('navigation aborted?');
+            });
         };
         await Promise.all([
             this.menuStore.initialize(),
@@ -183,7 +194,7 @@ export default {
                     if (url.charAt(0) !== "/") {
                         url = "/" + url;
                     }
-                    window.__lsmbLoadLink(url);
+                    window.__lsmbLoadLink(url, { title: n.label });
                 }
             }
         }

However, neither "console" statement is being called, which makes this a little less than trivial to solve problem...

ehuelsmann avatar Jun 20 '25 21:06 ehuelsmann

Ok. the above patch is based on old documentation. this.$router.push() returns a promise on Vue-Router 4.x and doesn't take an onComplete argument anymore.

ehuelsmann avatar Jun 20 '25 21:06 ehuelsmann

The patch below produces: "LedgerSMB () | MenuLevel1 > MenuLevel2 > ... > MenuLevelN"; e.g. "LedgerSMB (test) | Contacts > Add Entity".

diff --git a/UI/src/views/LsmbMain.vue b/UI/src/views/LsmbMain.vue
index fd1fcd59e..e7f80cf08 100644
--- a/UI/src/views/LsmbMain.vue
+++ b/UI/src/views/LsmbMain.vue
@@ -103,12 +103,21 @@ export default {
         }
     },
     async mounted() {
-        window.__lsmbLoadLink = (url) => {
+        window.__lsmbLoadLink = (url, options) => {
             let tgt = url.replace(/^https?:\/\/(?:[^@/]+)/, "");
             if (!tgt.startsWith("/")) {
                 tgt = "/" + tgt;
             }
-            this.$router.push(tgt);
+            let { title } = options;
+            this.$router
+                .push(tgt)
+                .then(
+                    () => {
+                        console.log('navigation done');
+                        if (title) {
+                            document.title = `LedgerSMB (${lsmbConfig.company}) | ${title}`;
+                        }
+                });
         };
         await Promise.all([
             this.menuStore.initialize(),
@@ -183,7 +192,14 @@ export default {
                     if (url.charAt(0) !== "/") {
                         url = "/" + url;
                     }
-                    window.__lsmbLoadLink(url);
+                    let label = n.label;
+                    let p = n.parent;
+                    while (p) {
+                        let parent = this.menuStore.nodeById(p);
+                        label = `${parent.label} > ${label}`;
+                        p = parent.parent;
+                    }
+                    window.__lsmbLoadLink(url, { title: label });
                 }
             }
         }

ehuelsmann avatar Jun 20 '25 21:06 ehuelsmann

I thought I'd give it a try, but I'm not at all familiar with Vue and it's definitely not as simple as injecting that LsmbMain.vue file into my docker container.

auspex avatar Jul 14 '25 14:07 auspex