From e9cffcc2ac8140512b3ca5c71c5f135903d82eff Mon Sep 17 00:00:00 2001
From: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>
Date: Tue, 25 Jul 2023 17:17:54 +0000
Subject: [PATCH] Bug 34417: Allow breadcrumbs to accept dynamic values

This patch is an example of allowing a breadcrumb to accept a dynamic value such as an agreement or license name.
---
 .../js/vue/components/ERM/AgreementsShow.vue  |  4 +
 .../js/vue/components/ERM/LicensesShow.vue    |  4 +
 .../prog/js/vue/components/NavigationItem.vue |  9 +-
 .../intranet-tmpl/prog/js/vue/routes/erm.js   | 93 +++++++++++++------
 .../prog/js/vue/stores/navigation.js          | 26 +++++-
 5 files changed, 101 insertions(+), 35 deletions(-)

diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue
index 34e77e98b8d..134f3c84cdc 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/AgreementsShow.vue
@@ -342,6 +342,8 @@ export default {
 
         const { setConfirmationDialog, setMessage } = inject("mainStore")
 
+        const navigationStore = inject("navigationStore")
+
         const AVStore = inject("AVStore")
         const { get_lib_from_av } = AVStore
 
@@ -351,6 +353,7 @@ export default {
             get_lib_from_av,
             setConfirmationDialog,
             setMessage,
+            navigationStore,
         }
     },
     data() {
@@ -387,6 +390,7 @@ export default {
             client.agreements.get(agreement_id).then(
                 agreement => {
                     this.agreement = agreement
+                    this.navigationStore.setBreadcrumbParameter(agreement.name)
                     this.initialized = true
                 },
                 error => {}
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/LicensesShow.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/LicensesShow.vue
index 19c853f4aa0..9773bf8628d 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/LicensesShow.vue
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/LicensesShow.vue
@@ -155,6 +155,8 @@ export default {
 
         const { setConfirmationDialog, setMessage } = inject("mainStore")
 
+        const navigationStore = inject("navigationStore")
+
         const AVStore = inject("AVStore")
         const { get_lib_from_av } = AVStore
 
@@ -164,6 +166,7 @@ export default {
             get_lib_from_av,
             setConfirmationDialog,
             setMessage,
+            navigationStore,
         }
     },
     data() {
@@ -194,6 +197,7 @@ export default {
             client.licenses.get(license_id).then(
                 license => {
                     this.license = license
+                    this.navigationStore.setBreadcrumbParameter(license.name)
                     this.initialized = true
                 },
                 error => {}
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue
index baa20e5e643..67dd4dcde68 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue
@@ -9,7 +9,7 @@
                 <template v-if="item.icon">
                     <i :class="`${item.icon}`"></i>&nbsp;
                 </template>
-                <span v-if="item.title">{{ $__(item.title) }}</span>
+                <span v-if="item.title.text">{{ $__(item.title.text) }}</span>
             </router-link>
             <router-link
                 v-else-if="item.path"
@@ -19,7 +19,7 @@
                 <template v-if="item.icon">
                     <i :class="`${item.icon}`"></i>&nbsp;
                 </template>
-                <span v-if="item.title">{{ $__(item.title) }}</span>
+                <span v-if="item.title">{{ $__(item.title.text) }}</span>
             </router-link>
             <a
                 v-else-if="item.href"
@@ -29,14 +29,14 @@
                 <template v-if="item.icon">
                     <i :class="`${item.icon}`"></i>&nbsp;
                 </template>
-                <span v-if="item.title">{{ $__(item.title) }}</span>
+                <span v-if="item.title">{{ $__(item.title.text) }}</span>
             </a>
             <span v-else :class="{ disabled: item.disabled }">
                 <template v-if="item.icon">
                     <i :class="`${item.icon}`"></i>&nbsp;
                 </template>
                 <span class="item-last" v-if="item.title">{{
-                    $__(item.title)
+                    $__(item.title.text)
                 }}</span>
             </span>
         </span>
@@ -44,6 +44,7 @@
             <NavigationItem
                 v-for="(item, key) in item.children"
                 :item="item"
+                :key="key"
             ></NavigationItem>
         </ul>
     </li>
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js
index dbd78f57f66..2447f585fe2 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js
@@ -37,7 +37,7 @@ export const routes = [
         path: "/cgi-bin/koha/erm/erm.pl",
         is_default: true,
         is_base: true,
-        title: $__("E-resource management"),
+        title: { dynamic: false, text: $__("E-resource management") },
         children: [
             {
                 path: "",
@@ -47,7 +47,7 @@ export const routes = [
             },
             {
                 path: "/cgi-bin/koha/erm/agreements",
-                title: $__("Agreements"),
+                title: { dynamic: false, text: $__("Agreements") },
                 icon: "fa fa-check-circle",
                 is_end_node: true,
                 children: [
@@ -60,25 +60,25 @@ export const routes = [
                         path: ":agreement_id",
                         name: "AgreementsShow",
                         component: markRaw(AgreementsShow),
-                        title: $__("Show agreement"),
+                        title: { dynamic: true, text: $__("Show agreement") },
                     },
                     {
                         path: "add",
                         name: "AgreementsFormAdd",
                         component: markRaw(AgreementsFormAdd),
-                        title: $__("Add agreement"),
+                        title: { dynamic: false, text: $__("Add agreement") },
                     },
                     {
                         path: "edit/:agreement_id",
                         name: "AgreementsFormAddEdit",
                         component: markRaw(AgreementsFormAdd),
-                        title: $__("Edit agreement"),
+                        title: { dynamic: true, text: $__("Edit agreement") },
                     },
                 ],
             },
             {
                 path: "/cgi-bin/koha/erm/licenses",
-                title: $__("Licenses"),
+                title: { dynamic: false, text: $__("Licenses") },
                 icon: "fa fa-gavel",
                 is_end_node: true,
                 children: [
@@ -91,37 +91,40 @@ export const routes = [
                         path: ":license_id",
                         name: "LicensesShow",
                         component: markRaw(LicensesShow),
-                        title: $__("Show license"),
+                        title: { dynamic: true, text: $__("Show license") },
                     },
                     {
                         path: "add",
                         name: "LicensesFormAdd",
                         component: markRaw(LicensesFormAdd),
-                        title: $__("Add license"),
+                        title: { dynamic: false, text: $__("Add license") },
                     },
                     {
                         path: "edit/:license_id",
                         name: "LicensesFormAddEdit",
                         component: markRaw(LicensesFormAdd),
-                        title: $__("Edit license"),
+                        title: { dynamic: true, text: $__("Edit license") },
                     },
                 ],
             },
             {
                 path: "/cgi-bin/koha/erm/eholdings",
-                title: $__("eHoldings"),
+                title: { dynamic: false, text: $__("eHoldings") },
                 icon: "fa fa-crosshairs",
                 disabled: true,
                 children: [
                     {
                         path: "local",
-                        title: $__("Local"),
+                        title: { dynamic: false, text: $__("Local") },
                         icon: "fa-solid fa-location-dot",
                         disabled: true,
                         children: [
                             {
                                 path: "packages",
-                                title: $__("Packages"),
+                                title: {
+                                    dynamic: false,
+                                    text: $__("Packages"),
+                                },
                                 icon: "fa fa-archive",
                                 is_end_node: true,
                                 children: [
@@ -138,7 +141,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalPackagesShow
                                         ),
-                                        title: $__("Show package"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Show package"),
+                                        },
                                     },
                                     {
                                         path: "add",
@@ -146,7 +152,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalPackagesFormAdd
                                         ),
-                                        title: $__("Add package"),
+                                        title: {
+                                            dynamic: false,
+                                            text: $__("Add package"),
+                                        },
                                     },
                                     {
                                         path: "edit/:package_id",
@@ -154,13 +163,16 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalPackagesFormAdd
                                         ),
-                                        title: $__("Edit package"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Edit package"),
+                                        },
                                     },
                                 ],
                             },
                             {
                                 path: "titles",
-                                title: $__("Titles"),
+                                title: { dynamic: false, text: $__("Titles") },
                                 icon: "fa-solid fa-arrow-down-a-z",
                                 is_end_node: true,
                                 children: [
@@ -177,7 +189,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalTitlesShow
                                         ),
-                                        title: $__("Show title"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Show title"),
+                                        },
                                     },
                                     {
                                         path: "add",
@@ -185,7 +200,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalTitlesFormAdd
                                         ),
-                                        title: $__("Add title"),
+                                        title: {
+                                            dynamic: false,
+                                            text: $__("Add title"),
+                                        },
                                     },
                                     {
                                         path: "edit/:title_id",
@@ -193,7 +211,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalTitlesFormAdd
                                         ),
-                                        title: $__("Edit title"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Edit title"),
+                                        },
                                     },
                                     {
                                         path: "import",
@@ -201,7 +222,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalTitlesFormImport
                                         ),
-                                        title: $__("Import from a list"),
+                                        title: {
+                                            dynamic: false,
+                                            text: $__("Import from a list"),
+                                        },
                                     },
                                     {
                                         path: "/cgi-bin/koha/erm/eholdings/local/resources/:resource_id",
@@ -209,7 +233,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsLocalResourcesShow
                                         ),
-                                        title: $__("Resource"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Resource"),
+                                        },
                                     },
                                 ],
                             },
@@ -217,13 +244,16 @@ export const routes = [
                     },
                     {
                         path: "ebsco",
-                        title: $__("EBSCO"),
+                        title: { dynamic: false, text: $__("EBSCO") },
                         icon: "fa fa-globe",
                         disabled: true,
                         children: [
                             {
                                 path: "packages",
-                                title: $__("Packages"),
+                                title: {
+                                    dynamic: false,
+                                    text: $__("Packages"),
+                                },
                                 icon: "fa fa-archive",
                                 is_end_node: true,
                                 children: [
@@ -240,13 +270,16 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsEBSCOPackagesShow
                                         ),
-                                        title: $__("Show package"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Show package"),
+                                        },
                                     },
                                 ],
                             },
                             {
                                 path: "titles",
-                                title: $__("Titles"),
+                                title: { dynamic: true, text: $__("Titles") },
                                 icon: "fa-solid fa-arrow-down-a-z",
                                 is_end_node: true,
                                 children: [
@@ -263,7 +296,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsEBSCOTitlesShow
                                         ),
-                                        title: $__("Show title"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Show title"),
+                                        },
                                     },
                                     {
                                         path: "/cgi-bin/koha/erm/eholdings/ebsco/resources/:resource_id",
@@ -271,7 +307,10 @@ export const routes = [
                                         component: markRaw(
                                             EHoldingsEBSCOResourcesShow
                                         ),
-                                        title: $__("Resource"),
+                                        title: {
+                                            dynamic: true,
+                                            text: $__("Resource"),
+                                        },
                                         is_navigation_item: false,
                                     },
                                 ],
diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js
index b252923f108..747eac5c8f6 100644
--- a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js
+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js
@@ -11,6 +11,7 @@ export const useNavigationStore = defineStore("navigation", {
         },
         current: null,
         params: {},
+        breadcrumbParameter: null,
     }),
     actions: {
         setRoutes(routesDef) {
@@ -68,11 +69,18 @@ export const useNavigationStore = defineStore("navigation", {
                 child.meta.self = child;
             }
         },
+        setBreadcrumbParameter(param) {
+            this.breadcrumbParameter = param;
+        },
     },
     getters: {
         breadcrumbs() {
             if (this.current)
-                return _buildFromCurrentMatches(this.current, this.routeState);
+                return _buildFromCurrentMatches(
+                    this.current,
+                    this.routeState,
+                    this.breadcrumbParameter
+                );
 
             return _getBaseElements(this.routeState);
 
@@ -100,14 +108,18 @@ export const useNavigationStore = defineStore("navigation", {
                 );
             }
 
-            function _buildFromCurrentMatches(currentMatches, routeState) {
+            function _buildFromCurrentMatches(
+                currentMatches,
+                routeState,
+                param
+            ) {
                 return [
                     {
                         ...routeState,
                         icon: null,
                         children: null,
                     },
-                    ..._mapMatches(currentMatches),
+                    ..._mapMatches(currentMatches, param),
                 ];
             }
 
@@ -115,16 +127,22 @@ export const useNavigationStore = defineStore("navigation", {
                 return child.is_base || (child.path && child.path !== "");
             }
 
-            function _mapMatches(currentMatches) {
+            function _mapMatches(currentMatches, param) {
                 return currentMatches
                     .filter(match => _isBaseOrNotStub(match.meta.self))
                     .map(match => ({
                         ...match.meta.self,
+                        title: _setTitle(match.meta.self, param),
                         icon: null,
                         path: match.path,
                         children: null,
                     }));
             }
+
+            function _setTitle(self, param) {
+                const title = self.title.dynamic ? param : self.title.text;
+                return { dynamic: self.title.dynamic, text: title };
+            }
         },
         leftNavigation() {
             return _getNavigationElements(this.routeState);
-- 
2.25.1