145 lines
5.5 KiB
Vue
Executable File
145 lines
5.5 KiB
Vue
Executable File
<template>
|
|
<div :class="['layout-sidebar', { active: active }]">
|
|
<router-link to="/" class="logo">
|
|
<img :src="'demo/images/primevue-logo-' + `${$appState.darkTheme ? 'light' : 'dark'}` + '.svg'" alt="primevue logo" />
|
|
</router-link>
|
|
<div class="layout-sidebar-filter p-fluid">
|
|
<AutoComplete
|
|
v-model="selectedRoute"
|
|
:suggestions="filteredRoutes"
|
|
@complete="searchRoute($event)"
|
|
@item-select="onItemSelect($event)"
|
|
scrollHeight="300px"
|
|
placeholder="Search"
|
|
field="name"
|
|
optionGroupLabel="name"
|
|
optionGroupChildren="children"
|
|
appendTo="self"
|
|
>
|
|
</AutoComplete>
|
|
</div>
|
|
<div class="layout-menu">
|
|
<template v-for="item of menu" :key="item.name">
|
|
<div class="menu-category">
|
|
{{ item.name }}
|
|
<Tag v-if="item.badge" :value="item.badge"></Tag>
|
|
</div>
|
|
<div v-if="item.children && item.children.length" class="menu-items">
|
|
<template v-for="child of item.children" :key="child.name">
|
|
<a v-if="child.href" :href="child.href" target="_blank">{{ child.name }}</a>
|
|
<router-link v-if="child.to" :to="child.to">
|
|
{{ child.name }}
|
|
<Tag v-if="child.badge" :value="child.badge"></Tag>
|
|
</router-link>
|
|
<template v-if="child.children">
|
|
<router-link v-slot="{ isActive }" :to="child.children[0].to" custom>
|
|
<div>
|
|
<a tabindex="0" @click="toggleSubmenu($event, child.meta[0])">
|
|
{{ child.name }}
|
|
<Tag v-if="child.badge" :value="child.badge"></Tag>
|
|
</a>
|
|
<transition name="p-toggleable-content">
|
|
<div v-show="isSubmenuActive(child.meta[0], isActive)" class="p-toggleable-content">
|
|
<ul>
|
|
<li v-for="(submenuitem, i) of child.children" :key="i">
|
|
<router-link :to="submenuitem.to">
|
|
{{ submenuitem.name }}
|
|
<Tag v-if="submenuitem.badge" :value="submenuitem.badge"></Tag>
|
|
</router-link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</router-link>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
<div v-if="item.banner" class="menu-image">
|
|
<a :href="item.url">
|
|
<img :src="darkTheme ? item.imageDark : item.imageLight" />
|
|
</a>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import menudata from '@/assets/menu/menu.json';
|
|
import { FilterMatchMode, FilterService } from 'primevue/api';
|
|
|
|
export default {
|
|
props: {
|
|
active: Boolean
|
|
},
|
|
data() {
|
|
return {
|
|
activeSubmenus: {},
|
|
menu: menudata.data,
|
|
filteredRoutes: null,
|
|
selectedRoute: null,
|
|
routes: []
|
|
};
|
|
},
|
|
mounted() {
|
|
this.menu.forEach((route) => {
|
|
let childRoute = { ...route };
|
|
|
|
childRoute.children = childRoute.children.filter((child) => {
|
|
if (child.meta) {
|
|
this.routes.push(child);
|
|
}
|
|
|
|
return !child.meta;
|
|
});
|
|
|
|
this.routes.push(childRoute);
|
|
});
|
|
},
|
|
methods: {
|
|
toggleSubmenu(event, name) {
|
|
this.activeSubmenus[name] = this.activeSubmenus[name] ? false : true;
|
|
this.activeSubmenus = { ...this.activeSubmenus };
|
|
event.preventDefault();
|
|
},
|
|
isSubmenuActive(name, routerIsActive) {
|
|
if (this.activeSubmenus[name]) {
|
|
return true;
|
|
} else if (routerIsActive) {
|
|
this.activeSubmenus[name] = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
searchRoute(event) {
|
|
let query = event.query;
|
|
let filteredRoutes = [];
|
|
|
|
for (let route of this.routes) {
|
|
let filteredItems = FilterService.filter(route.children, ['to', 'href'], query, FilterMatchMode.CONTAINS);
|
|
|
|
if (filteredItems && filteredItems.length) {
|
|
filteredRoutes.push({ name: route.name, children: filteredItems });
|
|
}
|
|
}
|
|
|
|
this.filteredRoutes = filteredRoutes;
|
|
},
|
|
onItemSelect(event) {
|
|
this.selectedRoute = null;
|
|
|
|
if (event.value.to) this.$router.push(event.value.to);
|
|
else if (event.value.href) window.location.href = event.value.href;
|
|
}
|
|
},
|
|
computed: {
|
|
darkTheme() {
|
|
return this.$appState.darkTheme === true;
|
|
}
|
|
}
|
|
};
|
|
</script>
|