Bug 33169: Build breadcrumbs and left-hand side menu from routes definition

Signed-off-by: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Agustin Moyano 2023-03-06 16:44:44 -03:00 committed by Tomas Cohen Arazi
parent a40c512bf0
commit 13fbc155d2
No known key found for this signature in database
GPG Key ID: 0A272EA1B2F3C15F
8 changed files with 630 additions and 556 deletions

View File

@ -0,0 +1,53 @@
<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"
:params="params"
></NavigationItem>
<NavigationItem
v-else
:item="{
...item,
disabled: true,
path: undefined,
href: undefined,
}"
:params="params"
></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)
const { params } = navigationStore
return {
breadcrumbs,
params,
}
},
components: {
NavigationItem,
},
}
</script>
<style>
#breadcrumbs .disabled {
padding: 0.6em 0.3em;
text-decoration: none;
color: #000;
pointer-events: none;
}
</style>

View File

@ -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"></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-solid fa-location-dot"
></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-solid fa-arrow-down-a-z"
></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"
@ -248,10 +159,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>

View File

@ -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>

View File

@ -0,0 +1,66 @@
<template>
<li>
<span>
<router-link
v-if="item.name"
:to="{ name: item.name, params }"
:class="{ disabled: item.disabled }"
>
<template v-if="item.icon">
<i :class="`fa ${item.icon}`"></i>&nbsp;
</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>&nbsp;
</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>&nbsp;
</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>&nbsp;
</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,
params: Object,
},
}
</script>
<style>
span.item-last {
padding: 7px 3px;
}
</style>

View File

@ -0,0 +1,9 @@
export const $__ = (key) => {
return window["__"](key);
};
export default {
install: (app, options) => {
app.config.globalProperties.$__ = $__
},
};

View File

@ -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.matched, params: to.params||{}});
removeMessages(); // This will actually flag the messages as displayed already
});
router.afterEach((to, from) => {

View File

@ -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: "packages",
children: [
{
path: "",
name: "EHoldingsEBSCOPackagesList",
component: EHoldingsEBSCOPackagesList,
meta: {
breadcrumb: () =>
build_breadcrumb([
breadcrumb_paths.eholdings_ebsco,
breadcrumbs.eholdings.ebsco
.packages,
]),
},
},
{
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: ":license_id",
name: "LicensesShow",
component: markRaw(LicensesShow),
title: $__('Show license'),
},
{
path: "titles",
children: [
{
path: "",
name: "EHoldingsEBSCOTitlesList",
component: EHoldingsEBSCOTitlesList,
meta: {
breadcrumb: () =>
build_breadcrumb([
breadcrumb_paths.eholdings_ebsco,
breadcrumbs.eholdings.ebsco.titles,
]),
},
},
{
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: "add",
name: "LicensesFormAdd",
component: markRaw(LicensesFormAdd),
title: $__('Add license'),
},
{
path: "resources/:resource_id",
name: "EHoldingsEBSCOResourcesShow",
component: EHoldingsEBSCOResourcesShow,
meta: {
breadcrumb: () =>
build_breadcrumb(
[
breadcrumb_paths.eholdings_ebsco,
breadcrumbs.eholdings.ebsco.titles,
],
"Resource" // $t("Resource")
),
},
path: "edit/:license_id",
name: "LicensesFormAddEdit",
component: markRaw(LicensesFormAdd),
title: $__('Edit license'),
},
],
},
],
},
{
path: "/cgi-bin/koha/erm/licenses",
children: [
{
path: "",
name: "LicensesList",
component: LicensesList,
meta: {
breadcrumb: () => breadcrumb_paths.licenses,
},
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: "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: "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: "ebsco",
title: $__('EBSCO'),
icon: 'fa-globe',
disabled: true,
children: [
{
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: "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: ":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")
),
},
},
],
]
},
];

View File

@ -0,0 +1,207 @@
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,
params: {},
}),
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 _buildFromCurrentMatches(this.current, this.routeState)
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 _buildFromCurrentMatches(currentMatches, routeState) {
return [
{
...routeState,
icon: null,
children: null
},
..._mapMatches(currentMatches)
];
}
function _isBaseOrNotStub(child) {
return child.is_base || (child.path && child.path !== '');
}
function _mapMatches(currentMatches) {
return currentMatches
.filter((match) => _isBaseOrNotStub(match.meta.self))
.map((match) => ({
...match.meta.self,
icon: null,
path: match.path,
children: null
}));
}
},
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);
}