Bugzilla – Attachment 149710 Details for
Bug 33169
Improve vue breadcrumbs and left-hand menu
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 33169: Build breadcrumbs and left-hand side menu from routes definition
Bug-33169-Build-breadcrumbs-and-left-hand-side-men.patch (text/plain), 53.89 KB, created by
Agustín Moyano
on 2023-04-14 22:46:52 UTC
(
hide
)
Description:
Bug 33169: Build breadcrumbs and left-hand side menu from routes definition
Filename:
MIME Type:
Creator:
Agustín Moyano
Created:
2023-04-14 22:46:52 UTC
Size:
53.89 KB
patch
obsolete
>From c7ae7751cd6a8158ff496f5cafa194a5f1136b50 Mon Sep 17 00:00:00 2001 >From: Agustin Moyano <agustinmoyano@theke.io> >Date: Mon, 6 Mar 2023 16:44:44 -0300 >Subject: [PATCH] Bug 33169: Build breadcrumbs and left-hand side menu from > routes definition > >--- > .../prog/js/vue/components/Breadcrumbs.vue | 49 ++ > .../prog/js/vue/components/ERM/Main.vue | 124 +--- > .../prog/js/vue/components/LeftMenu.vue | 67 ++ > .../prog/js/vue/components/NavigationItem.vue | 65 ++ > .../intranet-tmpl/prog/js/vue/i18n/index.js | 9 + > .../intranet-tmpl/prog/js/vue/modules/erm.ts | 31 +- > .../intranet-tmpl/prog/js/vue/routes/erm.js | 613 +++++------------- > .../prog/js/vue/stores/navigation.js | 211 ++++++ > 8 files changed, 621 insertions(+), 548 deletions(-) > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/Breadcrumbs.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/LeftMenu.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/i18n/index.js > create mode 100644 koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js > >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/Breadcrumbs.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Breadcrumbs.vue >new file mode 100644 >index 0000000000..e4377221a9 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/Breadcrumbs.vue >@@ -0,0 +1,49 @@ >+<template> >+ <nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb"> >+ <ol> >+ <template v-for="(item, idx) in breadcrumbs" v-bind:key="idx"> >+ <NavigationItem >+ v-if="idx < breadcrumbs.length - 1" >+ :item="item" >+ ></NavigationItem> >+ <NavigationItem >+ v-else >+ :item="{ >+ ...item, >+ disabled: true, >+ path: undefined, >+ href: undefined, >+ }" >+ ></NavigationItem> >+ </template> >+ </ol> >+ </nav> >+</template> >+ >+<script> >+import { inject } from "vue" >+import { storeToRefs } from "pinia" >+import NavigationItem from "./NavigationItem.vue" >+export default { >+ name: "Breadcrumbs", >+ setup: () => { >+ const navigationStore = inject("navigationStore") >+ const { breadcrumbs } = storeToRefs(navigationStore) >+ return { >+ breadcrumbs, >+ } >+ }, >+ components: { >+ NavigationItem, >+ }, >+} >+</script> >+ >+<style> >+#breadcrumbs .disabled { >+ padding: 0.6em 0.3em; >+ text-decoration: none; >+ color: #000; >+ pointer-events: none; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/Main.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/Main.vue >index 71685ee443..5aafe6f6eb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/Main.vue >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/ERM/Main.vue >@@ -1,7 +1,7 @@ > <template> > <div v-if="initialized && sysprefs.ERMModule == 1"> > <div id="sub-header"> >- <Breadcrumb /> >+ <Breadcrumbs /> > <Help /> > </div> > <div class="main container-fluid"> >@@ -14,100 +14,10 @@ > </div> > > <div class="col-sm-2 col-sm-pull-10"> >- <aside> >- <div id="navmenu"> >- <div id="navmenulist"> >- <h5>{{ $__("E-resource management") }}</h5> >- <ul> >- <li> >- <router-link >- :to="{ name: 'AgreementsList' }" >- > >- <i class="fa fa-check-circle-o"></i> >- {{ $__("Agreements") }}</router-link >- > >- </li> >- <li> >- <router-link >- :to="{ name: 'LicensesList' }" >- > >- <i class="fa fa-gavel"></i> >- {{ $__("Licenses") }}</router-link >- > >- </li> >- <li> >- <router-link >- to="/cgi-bin/koha/erm/eholdings" >- class="disabled" >- > >- <i class="fa fa-crosshairs"></i> >- {{ $__("eHoldings") }} >- </router-link> >- </li> >- >- <li> >- <ul> >- <li >- v-for="provider in sysprefs.ERMProviders" >- :key="provider" >- > >- <router-link >- v-if="provider == 'local'" >- :to="`/cgi-bin/koha/erm/eholdings/local`" >- class="disabled" >- > >- <i >- class="fa fa-map-marker" >- ></i> >- {{ >- $__("Local") >- }}</router-link >- > >- <router-link >- v-else-if=" >- provider == 'ebsco' >- " >- :to="`/cgi-bin/koha/erm/eholdings/ebsco`" >- class="disabled" >- > >- <i class="fa fa-globe"></i> >- {{ >- $__("EBSCO") >- }}</router-link >- > >- <ul> >- <li> >- <router-link >- :to="`/cgi-bin/koha/erm/eholdings/${provider}/packages`" >- > >- <i >- class="fa fa-archive" >- ></i> >- {{ >- $__("Packages") >- }}</router-link >- > >- </li> >- <li> >- <router-link >- :to="`/cgi-bin/koha/erm/eholdings/${provider}/titles`" >- > >- <i >- class="fa fa-sort-alpha-asc" >- ></i> >- {{ >- $__("Titles") >- }}</router-link >- > >- </li> >- </ul> >- </li> >- </ul> >- </li> >- </ul> >- </div> >- </div> >- </aside> >+ <LeftMenu >+ :title="$__('E-resource management')" >+ :condition="filterProviders" >+ ></LeftMenu> > </div> > </div> > </div> >@@ -119,9 +29,10 @@ > > <script> > import { inject } from "vue" >-import Breadcrumb from "../../components/Breadcrumb.vue" >-import Help from "../../components/Help.vue" >-import Dialog from "../../components/Dialog.vue" >+import Breadcrumbs from "../Breadcrumbs.vue" >+import Help from "../Help.vue" >+import LeftMenu from "../LeftMenu.vue" >+import Dialog from "../Dialog.vue" > import { APIClient } from "../../fetch/api-client.js" > import "vue-select/dist/vue-select.css" > import { storeToRefs } from "pinia" >@@ -241,10 +152,25 @@ export default { > this.initialized = true > }) > }, >+ methods: { >+ async filterProviders(navigationTree) { >+ const eHoldings = navigationTree.find( >+ element => element.path === "/cgi-bin/koha/erm/eholdings" >+ ) >+ const providers = this.sysprefs.ERMProviders >+ eHoldings.children = eHoldings.children.filter(element => >+ providers >+ .map(provider => `${eHoldings.path}/${provider}`) >+ .includes(element.path) >+ ) >+ return navigationTree >+ }, >+ }, > components: { >- Breadcrumb, >+ Breadcrumbs, > Dialog, > Help, >+ LeftMenu, > }, > } > </script> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/LeftMenu.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/LeftMenu.vue >new file mode 100644 >index 0000000000..147402b067 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/LeftMenu.vue >@@ -0,0 +1,67 @@ >+<template> >+ <aside> >+ <div id="navmenu"> >+ <div id="navmenulist"> >+ <h5>{{ $__(title) }}</h5> >+ <ul> >+ <NavigationItem >+ v-for="(item, key) in navigationTree" >+ v-bind:key="key" >+ :item="item" >+ ></NavigationItem> >+ </ul> >+ </div> >+ </div> >+ </aside> >+</template> >+ >+<script> >+import { inject } from "vue" >+import NavigationItem from "./NavigationItem.vue" >+export default { >+ name: "LeftMenu", >+ data() { >+ return { >+ navigationTree: this.leftNavigation, >+ } >+ }, >+ setup: () => { >+ const navigationStore = inject("navigationStore") >+ const { leftNavigation } = navigationStore >+ return { >+ leftNavigation, >+ } >+ }, >+ async beforeMount() { >+ if (this.condition) >+ this.navigationTree = await this.condition(this.navigationTree) >+ }, >+ props: { >+ title: String, >+ condition: Function, >+ }, >+ components: { >+ NavigationItem, >+ }, >+} >+</script> >+ >+<style scoped> >+#navmenulist a.router-link-active { >+ font-weight: 700; >+} >+#menu ul ul, >+#navmenulist ul ul { >+ padding-left: 2em; >+ font-size: 100%; >+} >+ >+#navmenulist ul li a.disabled { >+ color: #666; >+ pointer-events: none; >+ font-weight: 700; >+} >+#navmenulist ul li a.disabled.router-link-active { >+ color: #000; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue b/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue >new file mode 100644 >index 0000000000..4f9e36a151 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/components/NavigationItem.vue >@@ -0,0 +1,65 @@ >+<template> >+ <li> >+ <span> >+ <router-link >+ v-if="item.name" >+ :to="{ name: item.name }" >+ :class="{ disabled: item.disabled }" >+ > >+ <template v-if="item.icon"> >+ <i :class="`fa ${item.icon}`"></i> >+ </template> >+ <span v-if="item.title">{{ $__(item.title) }}</span> >+ </router-link> >+ <router-link >+ v-else-if="item.path" >+ :to="item.path" >+ :class="{ disabled: item.disabled }" >+ > >+ <template v-if="item.icon"> >+ <i :class="`fa ${item.icon}`"></i> >+ </template> >+ <span v-if="item.title">{{ $__(item.title) }}</span> >+ </router-link> >+ <a >+ v-else-if="item.href" >+ :href="item.href" >+ :class="{ disabled: item.disabled }" >+ > >+ <template v-if="item.icon"> >+ <i :class="`fa ${item.icon}`"></i> >+ </template> >+ <span v-if="item.title">{{ $__(item.title) }}</span> >+ </a> >+ <span v-else :class="{ disabled: item.disabled }"> >+ <template v-if="item.icon"> >+ <i :class="`fa ${item.icon}`"></i> >+ </template> >+ <span class="item-last" v-if="item.title">{{ >+ $__(item.title) >+ }}</span> >+ </span> >+ </span> >+ <ul v-if="item.children && item.children.length"> >+ <NavigationItem >+ v-for="(item, key) in item.children" >+ :item="item" >+ ></NavigationItem> >+ </ul> >+ </li> >+</template> >+ >+<script> >+export default { >+ name: "NavigationItem", >+ props: { >+ item: Object, >+ }, >+} >+</script> >+ >+<style> >+span.item-last { >+ padding: 7px 3px; >+} >+</style> >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/i18n/index.js b/koha-tmpl/intranet-tmpl/prog/js/vue/i18n/index.js >new file mode 100644 >index 0000000000..8dc89f12d1 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/i18n/index.js >@@ -0,0 +1,9 @@ >+export const $__ = (key) => { >+ return window["__"](key); >+}; >+ >+export default { >+ install: (app, options) => { >+ app.config.globalProperties.$__ = $__ >+ }, >+}; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >index ee438d4d37..c95fda92e8 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/modules/erm.ts >@@ -17,28 +17,27 @@ library.add(faPlus, faMinus, faPencil, faTrash, faSpinner); > > import App from "../components/ERM/Main.vue"; > >-import { routes } from "../routes/erm"; >- >-const router = createRouter({ >- history: createWebHistory(), >- linkActiveClass: "current", >- routes, >-}); >+import { routes as routesDef } from "../routes/erm"; > > import { useMainStore } from "../stores/main"; > import { useVendorStore } from "../stores/vendors"; > import { useAVStore } from "../stores/authorised-values"; > import { useERMStore } from "../stores/erm"; >+import { useNavigationStore } from "../stores/navigation"; >+import i18n from "../i18n"; > > const pinia = createPinia(); > >-const i18n = { >- install: (app, options) => { >- app.config.globalProperties.$__ = (key) => { >- return window["__"](key); >- }; >- }, >-}; >+const mainStore = useMainStore(pinia); >+const AVStore = useAVStore(pinia); >+const navigationStore = useNavigationStore(pinia); >+const routes = navigationStore.setRoutes(routesDef); >+ >+const router = createRouter({ >+ history: createWebHistory(), >+ linkExactActiveClass: "current", >+ routes, >+}); > > const app = createApp(App); > >@@ -51,10 +50,9 @@ const rootComponent = app > > app.config.unwrapInjectedRef = true; > app.provide("vendorStore", useVendorStore(pinia)); >-const mainStore = useMainStore(pinia); > app.provide("mainStore", mainStore); >-const AVStore = useAVStore(pinia); > app.provide("AVStore", AVStore); >+app.provide("navigationStore", navigationStore); > const ERMStore = useERMStore(pinia); > app.provide("ERMStore", ERMStore); > >@@ -62,6 +60,7 @@ app.mount("#erm"); > > const { removeMessages } = mainStore; > router.beforeEach((to, from) => { >+ navigationStore.$patch({current: to.meta.self}); > removeMessages(); // This will actually flag the messages as displayed already > }); > router.afterEach((to, from) => { >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 26f9f8f829..92b8ab010e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/routes/erm.js >@@ -1,3 +1,5 @@ >+import { markRaw } from "vue"; >+ > import Home from "../components/ERM/Home.vue"; > import AgreementsList from "../components/ERM/AgreementsList.vue"; > import AgreementsShow from "../components/ERM/AgreementsShow.vue"; >@@ -19,100 +21,12 @@ import LicensesList from "../components/ERM/LicensesList.vue"; > import LicensesShow from "../components/ERM/LicensesShow.vue"; > import LicensesFormAdd from "../components/ERM/LicensesFormAdd.vue"; > >-const breadcrumbs = { >- home: { >- text: "Home", // $t("Home") >- path: "/cgi-bin/koha/mainpage.pl", >- }, >- erm_home: { >- text: "E-resource management", // $t("E-resource management") >- path: "/cgi-bin/koha/erm/erm.pl", >- }, >- agreements: { >- text: "Agreements", // $t("Agreements") >- path: "/cgi-bin/koha/erm/agreements", >- }, >- eholdings: { >- home: { >- text: "eHoldings", // $t("eHoldings") >- }, >- local: { >- home: { >- text: "Local", // $t("Local") >- }, >- titles: { >- text: "Titles", // $t("Titles") >- path: "/cgi-bin/koha/erm/eholdings/local/titles", >- }, >- packages: { >- text: "Packages", // $t("Packages") >- path: "/cgi-bin/koha/erm/eholdings/local/packages", >- }, >- }, >- ebsco: { >- home: { >- text: "EBSCO", // $t("EBSCO") >- }, >- titles: { >- text: "Titles", // $t("Titles") >- path: "/cgi-bin/koha/erm/eholdings/ebsco/titles", >- }, >- packages: { >- text: "Packages", // $t("Packages") >- path: "/cgi-bin/koha/erm/eholdings/ebsco/packages", >- }, >- }, >- }, >- licenses: { >- text: "Licenses", // $t("Licenses") >- path: "/cgi-bin/koha/erm/licenses", >- }, >-}; >-const breadcrumb_paths = { >- agreements: [ >- breadcrumbs.home, >- breadcrumbs.erm_home, >- breadcrumbs.agreements, >- ], >- eholdings: [ >- breadcrumbs.home, >- breadcrumbs.erm_home, >- breadcrumbs.eholdings.home, >- ], >- eholdings_local: [ >- breadcrumbs.home, >- breadcrumbs.erm_home, >- breadcrumbs.eholdings.home, >- breadcrumbs.eholdings.local.home, >- ], >- eholdings_ebsco: [ >- breadcrumbs.home, >- breadcrumbs.erm_home, >- breadcrumbs.eholdings.home, >- breadcrumbs.eholdings.ebsco.home, >- ], >- licenses: [breadcrumbs.home, breadcrumbs.erm_home, breadcrumbs.licenses], >-}; >- >-function build_breadcrumb(parent_breadcrumb, current) { >- let breadcrumb = parent_breadcrumb.flat(Infinity); >- if (current) { >- breadcrumb.push({ >- text: current, >- }); >- } >- return breadcrumb; >-} >+import { $__ } from "../i18n"; > > export const routes = [ >- { >- path: "/cgi-bin/koha/mainpage.pl", >- beforeEnter(to, from, next) { >- window.location.href = "/cgi-bin/koha/mainpage.pl"; >- }, >- }, > { > path: "/cgi-bin/koha/admin/background_jobs/:id", >+ is_base: true, > beforeEnter(to, from, next) { > window.location.href = > "/cgi-bin/koha/admin/background_jobs.pl?op=view&id=" + >@@ -121,388 +35,221 @@ export const routes = [ > }, > { > path: "/cgi-bin/koha/erm/erm.pl", >- name: "Home", >- component: Home, >- meta: { >- breadcrumb: () => [breadcrumbs.home, breadcrumbs.erm_home], >- }, >- }, >- { >- path: "/cgi-bin/koha/erm/agreements", >+ is_default: true, >+ is_base: true, >+ title: $__('E-resource management'), > children: [ > { > path: "", >- name: "AgreementsList", >- component: AgreementsList, >- meta: { >- breadcrumb: () => breadcrumb_paths.agreements, >- }, >+ name: "Home", >+ component: markRaw(Home), >+ is_navigation_item: false, > }, > { >- path: ":agreement_id", >- name: "AgreementsShow", >- component: AgreementsShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.agreements, >- "Show agreement" // $t("Show agreement") >- ), >- }, >- }, >- { >- path: "add", >- name: "AgreementsFormAdd", >- component: AgreementsFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.agreements, >- "Add agreement" // $t("Add agreement") >- ), >- }, >- }, >- { >- path: "edit/:agreement_id", >- name: "AgreementsFormAddEdit", >- component: AgreementsFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.agreements, >- "Edit agreement" // $t("Edit agreement") >- ), >- }, >- }, >- ], >- }, >- { >- path: "/cgi-bin/koha/erm/eholdings", >- meta: { >- breadcrumb: () => breadcrumb_paths.eholdings, >- }, >- children: [ >- { >- path: "", >- meta: { >- breadcrumb: () => breadcrumb_paths.eholdings, >- }, >- }, >- { >- path: "local", >+ path: "/cgi-bin/koha/erm/agreements", >+ title: $__('Agreements'), >+ icon: 'fa-check-circle-o', >+ is_end_node: true, > children: [ > { > path: "", >- meta: { >- breadcrumb: () => breadcrumb_paths.eholdings_local, >- }, >+ name: "AgreementsList", >+ component: markRaw(AgreementsList), > }, > { >- path: "packages", >- children: [ >- { >- path: "", >- name: "EHoldingsLocalPackagesList", >- component: EHoldingsLocalPackagesList, >- meta: { >- breadcrumb: () => >- build_breadcrumb([ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .packages, >- ]), >- }, >- }, >- { >- path: ":package_id", >- name: "EHoldingsLocalPackagesShow", >- component: EHoldingsLocalPackagesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .packages, >- ], >- "Show package" // $t("Show package") >- ), >- }, >- }, >- { >- path: "add", >- name: "EHoldingsLocalPackagesFormAdd", >- component: EHoldingsLocalPackagesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .packages, >- ], >- "Add package" // $t("Add package") >- ), >- }, >- }, >- { >- path: "edit/:package_id", >- name: "EHoldingsLocalPackagesFormAddEdit", >- component: EHoldingsLocalPackagesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .packages, >- ], >- "Edit package" // $t("Edit package") >- ), >- }, >- }, >- ], >+ path: ":agreement_id", >+ name: "AgreementsShow", >+ component: markRaw(AgreementsShow), >+ title: $__('Show agreement'), > }, > { >- path: "titles", >- children: [ >- { >- path: "", >- name: "EHoldingsLocalTitlesList", >- component: EHoldingsLocalTitlesList, >- meta: { >- breadcrumb: () => >- build_breadcrumb([ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local.titles, >- ]), >- }, >- }, >- { >- path: ":title_id", >- name: "EHoldingsLocalTitlesShow", >- component: EHoldingsLocalTitlesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .titles, >- ], >- "Show title" // $t("Show title") >- ), >- }, >- }, >- { >- path: "add", >- name: "EHoldingsLocalTitlesFormAdd", >- component: EHoldingsLocalTitlesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .titles, >- ], >- "Add title" // $t("Add title") >- ), >- }, >- }, >- { >- path: "edit/:title_id", >- name: "EHoldingsLocalTitlesFormAddEdit", >- component: EHoldingsLocalTitlesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .titles, >- ], >- "Edit title" // $t("Edit title") >- ), >- }, >- }, >- { >- path: "import", >- name: "EHoldingsLocalTitlesFormImport", >- component: EHoldingsLocalTitlesFormImport, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local >- .titles, >- ], >- "Import from a list" // $t("Import from a list") >- ), >- }, >- }, >- ], >+ path: "add", >+ name: "AgreementsFormAdd", >+ component: markRaw(AgreementsFormAdd), >+ title: $__('Add agreement'), > }, > { >- path: "resources/:resource_id", >- name: "EHoldingsLocalResourcesShow", >- component: EHoldingsLocalResourcesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_local, >- breadcrumbs.eholdings.local.titles, >- ], >- "Resource" // $t("Resource") >- ), >- }, >+ path: "edit/:agreement_id", >+ name: "AgreementsFormAddEdit", >+ component: markRaw(AgreementsFormAdd), >+ title: $__('Edit agreement'), > }, > ], > }, > { >- path: "ebsco", >+ path: "/cgi-bin/koha/erm/licenses", >+ title: $__('Licenses'), >+ icon: "fa-gavel", >+ is_end_node: true, > children: [ > { > path: "", >- meta: { >- breadcrumb: () => breadcrumb_paths.eholdings_ebsco, >- }, >+ name: "LicensesList", >+ component: markRaw(LicensesList), >+ }, >+ { >+ path: ":license_id", >+ name: "LicensesShow", >+ component: markRaw(LicensesShow), >+ title: $__('Show license'), >+ }, >+ { >+ path: "add", >+ name: "LicensesFormAdd", >+ component: markRaw(LicensesFormAdd), >+ title: $__('Add license'), > }, > { >- path: "packages", >+ path: "edit/:license_id", >+ name: "LicensesFormAddEdit", >+ component: markRaw(LicensesFormAdd), >+ title: $__('Edit license'), >+ }, >+ ], >+ }, >+ { >+ path: "/cgi-bin/koha/erm/eholdings", >+ title: $__('eHoldings'), >+ icon: 'fa-crosshairs', >+ disabled: true, >+ children: [ >+ { >+ path: "local", >+ title: $__('Local'), >+ icon: "fa-map-marker", >+ disabled: true, > children: [ > { >- path: "", >- name: "EHoldingsEBSCOPackagesList", >- component: EHoldingsEBSCOPackagesList, >- meta: { >- breadcrumb: () => >- build_breadcrumb([ >- breadcrumb_paths.eholdings_ebsco, >- breadcrumbs.eholdings.ebsco >- .packages, >- ]), >- }, >+ path: "packages", >+ title: $__('Packages'), >+ icon: "fa-archive", >+ is_end_node: true, >+ children: [ >+ { >+ path: "", >+ name: "EHoldingsLocalPackagesList", >+ component: markRaw(EHoldingsLocalPackagesList), >+ }, >+ { >+ path: ":package_id", >+ name: "EHoldingsLocalPackagesShow", >+ component: markRaw(EHoldingsLocalPackagesShow), >+ title: $__('Show package'), >+ }, >+ { >+ path: "add", >+ name: "EHoldingsLocalPackagesFormAdd", >+ component: markRaw(EHoldingsLocalPackagesFormAdd), >+ title: $__('Add package'), >+ }, >+ { >+ path: "edit/:package_id", >+ name: "EHoldingsLocalPackagesFormAddEdit", >+ component: markRaw(EHoldingsLocalPackagesFormAdd), >+ title: $__('Edit package'), >+ }, >+ ], > }, > { >- path: ":package_id", >- name: "EHoldingsEBSCOPackagesShow", >- component: EHoldingsEBSCOPackagesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_ebsco, >- breadcrumbs.eholdings.ebsco >- .packages, >- ], >- "Show package" // $t("Show package") >- ), >- }, >+ path: "titles", >+ title: $__('Titles'), >+ icon: "fa-sort-alpha-asc", >+ is_end_node: true, >+ children: [ >+ { >+ path: "", >+ name: "EHoldingsLocalTitlesList", >+ component: markRaw(EHoldingsLocalTitlesList), >+ }, >+ { >+ path: ":title_id", >+ name: "EHoldingsLocalTitlesShow", >+ component: markRaw(EHoldingsLocalTitlesShow), >+ title: $__('Show title'), >+ }, >+ { >+ path: "add", >+ name: "EHoldingsLocalTitlesFormAdd", >+ component: markRaw(EHoldingsLocalTitlesFormAdd), >+ title: $__('Add title'), >+ }, >+ { >+ path: "edit/:title_id", >+ name: "EHoldingsLocalTitlesFormAddEdit", >+ component: markRaw(EHoldingsLocalTitlesFormAdd), >+ title: $__('Edit title'), >+ }, >+ { >+ path: "import", >+ name: "EHoldingsLocalTitlesFormImport", >+ component: markRaw(EHoldingsLocalTitlesFormImport), >+ title: $__('Import from a list'), >+ }, >+ { >+ path: "/cgi-bin/koha/erm/eholdings/local/resources/:resource_id", >+ name: "EHoldingsLocalResourcesShow", >+ component: markRaw(EHoldingsLocalResourcesShow), >+ title: $__('Resource'), >+ }, >+ ], > }, > ], > }, > { >- path: "titles", >+ path: "ebsco", >+ title: $__('EBSCO'), >+ icon: 'fa-globe', >+ disabled: true, > children: [ > { >- path: "", >- name: "EHoldingsEBSCOTitlesList", >- component: EHoldingsEBSCOTitlesList, >- meta: { >- breadcrumb: () => >- build_breadcrumb([ >- breadcrumb_paths.eholdings_ebsco, >- breadcrumbs.eholdings.ebsco.titles, >- ]), >- }, >+ path: "packages", >+ title: $__('Packages'), >+ icon: "fa-archive", >+ is_end_node: true, >+ children: [ >+ { >+ path: "", >+ name: "EHoldingsEBSCOPackagesList", >+ component: markRaw(EHoldingsEBSCOPackagesList), >+ }, >+ { >+ path: ":package_id", >+ name: "EHoldingsEBSCOPackagesShow", >+ component: markRaw(EHoldingsEBSCOPackagesShow), >+ title: $__('Show package'), >+ }, >+ ], > }, > { >- path: ":title_id", >- name: "EHoldingsEBSCOTitlesShow", >- component: EHoldingsEBSCOTitlesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_ebsco, >- breadcrumbs.eholdings.ebsco >- .titles, >- ], >- "Show title" // $t("Show title") >- ), >- }, >+ path: "titles", >+ title: $__('Titles'), >+ icon: "fa-sort-alpha-asc", >+ is_end_node: true, >+ children: [ >+ { >+ path: "", >+ name: "EHoldingsEBSCOTitlesList", >+ component: markRaw(EHoldingsEBSCOTitlesList), >+ }, >+ { >+ path: ":title_id", >+ name: "EHoldingsEBSCOTitlesShow", >+ component: markRaw(EHoldingsEBSCOTitlesShow), >+ title: $__('Show title'), >+ }, >+ { >+ path: "/cgi-bin/koha/erm/eholdings/ebsco/resources/:resource_id", >+ name: "EHoldingsEBSCOResourcesShow", >+ component: markRaw(EHoldingsEBSCOResourcesShow), >+ title: $__('Resource'), >+ is_navigation_item: false, >+ }, >+ ], > }, > ], > }, >- { >- path: "resources/:resource_id", >- name: "EHoldingsEBSCOResourcesShow", >- component: EHoldingsEBSCOResourcesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- [ >- breadcrumb_paths.eholdings_ebsco, >- breadcrumbs.eholdings.ebsco.titles, >- ], >- "Resource" // $t("Resource") >- ), >- }, >- }, > ], > }, >- ], >- }, >- { >- path: "/cgi-bin/koha/erm/licenses", >- children: [ >- { >- path: "", >- name: "LicensesList", >- component: LicensesList, >- meta: { >- breadcrumb: () => breadcrumb_paths.licenses, >- }, >- }, >- { >- path: ":license_id", >- name: "LicensesShow", >- component: LicensesShow, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.licenses, >- "Show license" // $t("Show license") >- ), >- }, >- }, >- { >- path: "add", >- name: "LicensesFormAdd", >- component: LicensesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.licenses, >- "Add license" // $t("Add license") >- ), >- }, >- }, >- { >- path: "edit/:license_id", >- name: "LicensesFormAddEdit", >- component: LicensesFormAdd, >- meta: { >- breadcrumb: () => >- build_breadcrumb( >- breadcrumb_paths.licenses, >- "Edit license" // $t("Edit license") >- ), >- }, >- }, >- ], >+ ] > }, > ]; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js >new file mode 100644 >index 0000000000..4e46f8cef3 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/js/vue/stores/navigation.js >@@ -0,0 +1,211 @@ >+import { >+ defineStore >+} from "pinia"; >+ >+export const useNavigationStore = defineStore("navigation", { >+ state: () => ({ >+ routeState: { >+ alt: "Home", >+ href: "/cgi-bin/koha/mainpage.pl", >+ is_navigation_item: false, >+ is_base: true, >+ children: [] >+ }, >+ current: null, >+ }), >+ actions: { >+ setRoutes(routesDef) { >+ if (!Array.isArray(routesDef)) { >+ routesDef = [routesDef] >+ } >+ this.routeState.children = routesDef >+ _traverseChildren(this.routeState) >+ >+ return this.navigationRoutes >+ >+ // Function declarations >+ >+ function _traverseChildren(parent) { >+ if (isParent(parent)) { >+ parent.children.forEach(child => { >+ _setChildDefaults(parent, child); >+ _traverseChildren(child) >+ }) >+ } >+ } >+ >+ function _setChildDefaults(parent, child) { >+ child.parent = parent; >+ if (isRoutable(child)) { >+ _setMetadata(child); >+ } >+ if (parent.children.length === 1 && parent.is_base) { >+ _setBaseAndNavigationDefaults(child, { >+ is_base: true, >+ is_navigation_item: false >+ }); >+ } else { >+ _setBaseAndNavigationDefaults(child, { >+ is_base: false, >+ is_navigation_item: true >+ }); >+ } >+ } >+ >+ function _setBaseAndNavigationDefaults(child, { >+ is_base, >+ is_navigation_item >+ }) { >+ child.is_base = child.is_base !== undefined ? child.is_base : is_base; >+ child.is_navigation_item = child.is_navigation_item !== undefined ? child.is_navigation_item : is_navigation_item; >+ } >+ >+ function _setMetadata(child) { >+ if (!child.meta) >+ child.meta = {}; >+ child.meta.self = child; >+ } >+ } >+ }, >+ getters: { >+ breadcrumbs() { >+ if (this.current) >+ return _traverseParent(this.current) >+ >+ return _getBaseElements(this.routeState) >+ >+ // Function declarations >+ >+ function _getBaseElements(parent) { >+ if (!parent.is_base) return [] >+ let next = {} >+ if (isParent(parent)) { >+ next = _defineNextElement(parent) >+ } >+ return [{ >+ ...parent, >+ children: null >+ }, ..._getBaseElements(next)] >+ } >+ >+ function _defineNextElement(parent) { >+ return parent.children.find(child => child.is_default) || parent.children[0]; >+ } >+ >+ function _traverseParent(child) { >+ let breadcrumbs = [] >+ let builtPath = child.path >+ if (child.parent) { >+ breadcrumbs = _traverseParent(child.parent) >+ builtPath = _buildPath(builtPath, breadcrumbs); >+ } >+ if (_isBaseOrNotStub(child)) breadcrumbs.push({ >+ ...child, >+ icon: null, >+ path: builtPath, >+ children: null >+ }) >+ return breadcrumbs >+ } >+ >+ function _isBaseOrNotStub(child) { >+ return child.is_base || (child.path && child.path !== ''); >+ } >+ >+ function _buildPath(builtPath, breadcrumbs) { >+ if (!isAbsolutePath(builtPath)) { >+ const { >+ path: parentPath >+ } = breadcrumbs[breadcrumbs.length - 1]; >+ if (parentPath !== undefined) { >+ builtPath = '' + parentPath + addSlashIfNotPresent(parentPath) + builtPath; >+ } >+ } >+ return builtPath; >+ } >+ }, >+ leftNavigation() { >+ return _getNavigationElements(this.routeState) >+ >+ // Function declarations >+ >+ function _getNavigationElements(parent, prevPath = '') { >+ if (_isBaseAndNoChildren(parent)) return []; >+ if (parent.is_base) >+ return _buildChildNavigationElements(parent).flat(Infinity) >+ >+ const builtPath = _buildPath(prevPath, parent); >+ >+ let children = [] >+ if (!parent.is_end_node && isParent(parent)) { >+ children = _buildChildNavigationElements(parent, builtPath) >+ } >+ >+ return { >+ ...parent, >+ path: builtPath ? builtPath : parent.path, >+ children >+ } >+ } >+ >+ function _buildPath(prevPath, element) { >+ let builtPath; >+ >+ if (isRoutable(element) && isAbsolutePath(element.path)) { >+ builtPath = element.path; >+ } else { >+ if (prevPath) >+ builtPath = '' + prevPath + addSlashIfNotPresent(prevPath); >+ if (isRoutable(element)) >+ builtPath = '' + builtPath + element.path; >+ } >+ >+ return builtPath; >+ } >+ >+ function _buildChildNavigationElements(parent, builtPath) { >+ return parent.children >+ .filter(child => child.is_base || child.is_navigation_item) >+ .map(child => _getNavigationElements(child, builtPath)); >+ } >+ >+ function _isBaseAndNoChildren(parent) { >+ return parent.is_base && (!parent.children || !parent.children.length); >+ } >+ }, >+ navigationRoutes() { >+ let routes = _toRoute(this.routeState) >+ return Array.isArray(routes) ? routes : [routes] >+ >+ // Function declarations >+ >+ function _toRoute(parent) { >+ if (!isRoutable(parent)) >+ return _getRoutableChildren(parent) >+ return parent >+ } >+ >+ function _getRoutableChildren(parent) { >+ return parent.children >+ .map(child => _toRoute(child)) >+ .flat(Infinity); >+ } >+ } >+ } >+}) >+ >+function addSlashIfNotPresent(path) { >+ return /\/$/.test(path) ? '' : '/'; >+} >+ >+function isRoutable(element) { >+ return element.path !== undefined || element.name !== undefined; >+} >+ >+function isParent(parent) { >+ return parent.children && parent.children.length; >+} >+ >+function isAbsolutePath(path) { >+ return /^\//.test(path); >+} >-- >2.25.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 33169
:
147962
|
148044
|
148081
|
148097
|
149710
|
149744
|
151530
|
151797
|
152068
|
152539
|
152540
|
152541
|
153889
|
153890
|
157785
|
157806
|
157807