Init project
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 250 250" style="enable-background:new 0 0 250 250;" xml:space="preserve">
|
||||
<g>
|
||||
<polygon class="st0" points="124,12 90.4,46 109.9,65.3 125,49.9 125,13 "/>
|
||||
<path class="st1" d="M184.1,71.4L125,13v36.9l0.1-0.1l36.3,35.8c21.9,19.8,19.8,39,19.8,39s1.3,18.1-20.4,38.2l-35.6,36.1l-0.2-0.2
|
||||
v38.8l0.4,0.4l59.4-60.1c0,0,22.7-23.6,22.5-53.4C207.1,94.7,184.1,71.4,184.1,71.4z"/>
|
||||
</g>
|
||||
<path class="st2" d="M92.9,121.9l29.2,28.5c0,0,1.5-1.6,2.9-4.6c2.6-5.1,5.1-14.1,0-25.3c-2.4-5.3-6.6-11.1-13.4-17.2
|
||||
c-0.1-0.1-0.1-0.1-0.2-0.2l-19.5-19l-0.4-0.4l-17.7,19.5C76.9,106.5,87.9,116.7,92.9,121.9z"/>
|
||||
<path class="st0" d="M73.8,103.4L73.8,103.4C73.8,103.4,73.8,103.4,73.8,103.4C73.8,103.3,73.8,103.3,73.8,103.4l17.7-19.6l-8.6-8.5
|
||||
L72.4,65.2L61.4,75.9c0,0,0,0,0,0c-1.2,1.4-18.6,21.2-19.2,49.6c0.1,29.8,23.2,53.1,23.2,53.1l59.7,58.9v-38.8l-37-34.3
|
||||
c-21.9-19.8-19.8-39-19.8-39S67.1,115.9,73.8,103.4L73.8,103.4z"/>
|
||||
<g class="st3">
|
||||
<path class="st4" d="M91.9,84.2l-0.4-0.4l-17.7,19.5c1.7,1.8,6,5.8,10.3,9.9l7.9-29L91.9,84.2z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
<style type="text/css">
|
||||
.st0{fill:#488C51;}
|
||||
.st1{fill:#26685D;}
|
||||
.st2{fill:#28675C;}
|
||||
.st3{opacity:0.5;}
|
||||
.st4{fill:#333333;}
|
||||
</style>
|
||||
@@ -0,0 +1,36 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TheFooter.vue
|
||||
Description: Footer component
|
||||
Component Name: TheFooter
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template functional>
|
||||
<footer class="the-footer flex-wrap justify-between" :class="classes">
|
||||
<p>
|
||||
<span>COPYRIGHT ©</span>
|
||||
<span>{{ new Date().getFullYear() }} </span>
|
||||
<a href="https://1.envato.market/vuexy_admin" target="_blank" rel="nofollow">Pixinvent</a>
|
||||
<span class="hidden sm:inline-block">, All rights Reserved</span>
|
||||
</p>
|
||||
<span class="md:flex hidden items-center">
|
||||
<span>Hand-crafted & Made with</span>
|
||||
<feather-icon icon="HeartIcon" svgClasses="stroke-current text-danger w-6 h-6" class="ml-2" />
|
||||
</span>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'the-footer',
|
||||
props: {
|
||||
classes: {
|
||||
type: String
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,37 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: VxBreadcrumb.vue
|
||||
Description: Breadcrumb component
|
||||
Component Name: VxBreadcrumb
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template functional>
|
||||
<div class="vx-breadcrumb" :class="data.staticClass">
|
||||
<ul class="flex flex-wrap items-center">
|
||||
<li class="inline-flex items-end">
|
||||
<router-link to="/">
|
||||
<feather-icon icon="HomeIcon" svgClasses="h-5 w-5 mb-1 stroke-current text-primary" />
|
||||
</router-link>
|
||||
<span class="breadcrumb-separator mx-2"><feather-icon :icon="props.isRTL ? 'ChevronsLeftIcon' : 'ChevronsRightIcon'" svgClasses="w-4 h-4" /></span>
|
||||
</li>
|
||||
<li v-for="(link, index) in props.route.meta.breadcrumb.slice(1,-1)" :key="index" class="inline-flex items-center">
|
||||
<router-link :to="link.url" v-if="link.url">{{ link.title }}</router-link>
|
||||
<span class="text-primary cursor-default" v-else>{{ link.title }}</span>
|
||||
<span class="breadcrumb-separator mx-2 flex items-start"><feather-icon :icon="props.isRTL ? 'ChevronsLeftIcon' : 'ChevronsRightIcon'" svgClasses="w-4 h-4" /></span>
|
||||
</li>
|
||||
<li class="inline-flex">
|
||||
<span v-if="props.route.meta.breadcrumb.slice(-1)[0].active" class="cursor-default">{{ props.route.meta.breadcrumb.slice(-1)[0].title }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
name: 'vx-breadcrumb'
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,371 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TheCustomizer.vue
|
||||
Description: Template Customizer
|
||||
Component Name: TheCustomizer
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div id="theme-customizer">
|
||||
|
||||
<!-- Open Customizer Button -->
|
||||
<vs-button
|
||||
@click.stop="active=!active"
|
||||
color="primary"
|
||||
type="filled"
|
||||
class="customizer-btn"
|
||||
icon-pack="feather"
|
||||
icon="icon-settings" />
|
||||
|
||||
<!-- Customizer Content -->
|
||||
<vs-sidebar
|
||||
click-not-close
|
||||
hidden-background
|
||||
position-right
|
||||
v-model="active"
|
||||
class="items-no-padding">
|
||||
<div class="h-full">
|
||||
|
||||
<div class="customizer-header mt-6 flex items-center justify-between px-6">
|
||||
<div>
|
||||
<h4>THEME CUSTOMIZER</h4>
|
||||
<small>Customize & Preview in Real Time</small>
|
||||
</div>
|
||||
<feather-icon icon="XIcon" @click.stop="active = false" class="cursor-pointer"></feather-icon>
|
||||
</div>
|
||||
|
||||
<vs-divider class="mb-0" />
|
||||
|
||||
<component :is="scrollbarTag" class="scroll-area--customizer pt-4 pb-6" :settings="settings" :key="$vs.rtl">
|
||||
|
||||
<div class="px-6">
|
||||
|
||||
<!-- Layout Type -->
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-2">Layout Type</h5>
|
||||
<div>
|
||||
<vs-radio v-model="layoutType" vs-value="vertical" class="mr-4" vs-name="layout-type-vertical">Vertical</vs-radio>
|
||||
<vs-radio v-model="layoutType" vs-value="horizontal" class="mr-4" vs-name="layout-type-horizontal">Horizontal</vs-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- THEME COLORS -->
|
||||
<div>
|
||||
<h5 class="mb-4">Theme Color</h5>
|
||||
<ul class="clearfix">
|
||||
|
||||
<!-- Color Square -->
|
||||
<li
|
||||
v-for="color in themeColors"
|
||||
:key="color"
|
||||
:style="{backgroundColor: color}"
|
||||
:class="{'shadow-outline': color == primaryColor}"
|
||||
class="w-10 cursor-pointer h-10 rounded-lg m-2 float-left"
|
||||
@click="updatePrimaryColor(color)" />
|
||||
|
||||
<!-- Custom Color Square -->
|
||||
<li
|
||||
:style="{backgroundColor: customPrimaryColor}"
|
||||
:class="{'shadow-outline': customPrimaryColor == primaryColor}"
|
||||
class="w-10 cursor-pointer h-10 rounded-lg m-2 float-left"
|
||||
@click="updatePrimaryColor(customPrimaryColor)" />
|
||||
<li class="float-left"><input class="w-10 cursor-pointer h-10 rounded-lg m-2" v-model="customPrimaryColor" type="color" /></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /THEME COLORS -->
|
||||
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- THEME -->
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-2">Theme Mode</h5>
|
||||
<div>
|
||||
<vs-radio v-model="themeMode" vs-value="light" class="mr-4" vs-name="theme-mode-light">Light</vs-radio>
|
||||
<vs-radio v-model="themeMode" vs-value="dark" class="mr-4" vs-name="theme-mode-dark">Dark</vs-radio>
|
||||
<vs-radio
|
||||
v-if="layoutType === 'vertical'"
|
||||
v-model="themeMode"
|
||||
vs-value="semi-dark"
|
||||
vs-name="theme-mode-semi-dark">Semi Dark</vs-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<template v-if="layoutType === 'vertical'">
|
||||
|
||||
<!-- COLLAPSE SIDEBAR -->
|
||||
<div class="mt-4 flex justify-between">
|
||||
<h5>Collapse Sidebar</h5>
|
||||
<vs-switch v-model="reduced_sidebar" />
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
</template>
|
||||
|
||||
<!-- NAVBAR COLOR -->
|
||||
|
||||
<template v-if="layoutType === 'vertical'">
|
||||
|
||||
<div class="mt-4">
|
||||
<h5>Navbar Color</h5>
|
||||
<ul class="clearfix">
|
||||
|
||||
<!-- WHITE COLOR -->
|
||||
<li
|
||||
:style="{background: navbarColorInitial}"
|
||||
class="w-10 m-2 h-10 rounded-lg float-left cursor-pointer border border-solid d-theme-border-grey-light"
|
||||
:class="navbarColorOptionClasses(navbarColorInitial)"
|
||||
@click="navbarColorLocal = navbarColorInitial " />
|
||||
|
||||
<!-- THEME COLORS -->
|
||||
<li
|
||||
v-for="color in themeColors"
|
||||
:key="color"
|
||||
:style="{backgroundColor: color}"
|
||||
:class="navbarColorOptionClasses(color)"
|
||||
class="w-10 cursor-pointer h-10 rounded-lg m-2 float-left"
|
||||
@click="navbarColorLocal = color" />
|
||||
|
||||
<!-- CUSTOM COLOR -->
|
||||
<li
|
||||
:style="{backgroundColor: customNavbarColor}"
|
||||
:class="navbarColorOptionClasses(navbarColorOptionClasses)"
|
||||
class="w-10 cursor-pointer h-10 rounded-lg m-2 float-left"
|
||||
@click="navbarColorLocal = customNavbarColor" />
|
||||
|
||||
<li class="float-left">
|
||||
<input class="w-10 cursor-pointer h-10 rounded-lg m-2" v-model="customNavbarColor" type="color" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /NAVBAR COLOR -->
|
||||
|
||||
<vs-divider />
|
||||
|
||||
</template>
|
||||
|
||||
<!-- NAVBAR TYPE -->
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-2">{{ (layoutType === 'vertical' || windowWidth < 1200) ? "Navbar" : "Nav Menu" }} Type</h5>
|
||||
<div>
|
||||
<vs-radio
|
||||
v-if="layoutType === 'vertical' || windowWidth < 1200"
|
||||
v-model="navbarTypeLocal"
|
||||
vs-value="hidden"
|
||||
class="mr-4"
|
||||
vs-name="navbar-type-hidden">Hidden</vs-radio>
|
||||
|
||||
<vs-radio v-model="navbarTypeLocal" vs-value="static" class="mr-4" vs-name="navbar-type-static">Static</vs-radio>
|
||||
<vs-radio v-model="navbarTypeLocal" vs-value="sticky" vs-name="navbar-type-sticky" class="mr-4">Sticky</vs-radio>
|
||||
<vs-radio v-model="navbarTypeLocal" vs-value="floating" vs-name="navbar-type-floating">Floating</vs-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- FOOTER TYPE -->
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-2">Footer Type</h5>
|
||||
<div>
|
||||
<vs-radio v-model="footerTypeLocal" vs-value="hidden" class="mr-4" vs-name="footer-type-hidden">Hidden</vs-radio>
|
||||
<vs-radio v-model="footerTypeLocal" vs-value="static" class="mr-4" vs-name="footer-type-static">Static</vs-radio>
|
||||
<vs-radio v-model="footerTypeLocal" vs-value="sticky" vs-name="footer-type-sticky">Sticky</vs-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- RTL -->
|
||||
<div class="mt-4 flex justify-between">
|
||||
<h5 class="mb-2">RTL</h5>
|
||||
<vs-switch v-model="rtl" />
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- SHOW SCROLL TO TOP -->
|
||||
<div class="mt-4 flex justify-between">
|
||||
<h5 class="mb-2">Hide Scroll To Top</h5>
|
||||
<vs-switch v-model="hideScrollToTopLocal" />
|
||||
</div>
|
||||
|
||||
<vs-divider />
|
||||
|
||||
<!-- ROUTER ANIMATION -->
|
||||
<div class="mt-4">
|
||||
<h5 class="mb-2">Router Animation {{ routerTransitionLocal }}</h5>
|
||||
<vs-select v-model="routerTransitionLocal">
|
||||
<vs-select-item
|
||||
v-for="(item,index) in routerTransitionsList"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
:text="item.text" />
|
||||
</vs-select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</component>
|
||||
</div>
|
||||
</vs-sidebar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
footerType : { type: String, required: true },
|
||||
hideScrollToTop : { type: Boolean, required: true },
|
||||
navbarType : { type: String, required: true },
|
||||
navbarColor : { type: String, required: true, default: '#fff' },
|
||||
routerTransition : { type: String, required: true }
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
active : false,
|
||||
customPrimaryColor : '#3DC9B3',
|
||||
customNavbarColor : '#3DC9B3',
|
||||
routerTransitionsList: [
|
||||
{ text: 'Zoom Fade', value: 'zoom-fade' },
|
||||
{ text: 'Slide Fade', value: 'slide-fade' },
|
||||
{ text: 'Fade Bottom', value: 'fade-bottom' },
|
||||
{ text: 'Fade', value: 'fade' },
|
||||
{ text: 'Zoom Out', value: 'zoom-out' },
|
||||
{ text: 'None', value: 'none' }
|
||||
],
|
||||
settings: {
|
||||
maxScrollbarLength : 60,
|
||||
wheelSpeed : .60
|
||||
},
|
||||
themeColors: ['#7367F0', '#28C76F', '#EA5455', '#FF9F43', '#1E1E1E']
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
layoutType (val) {
|
||||
|
||||
// Reset unsupported options
|
||||
if (val === 'horizontal') {
|
||||
if (this.themeMode === 'semi-dark') this.themeMode = 'light'
|
||||
if (this.navbarType === 'hidden') this.navbarTypeLocal = 'floating'
|
||||
this.$emit('updateNavbarColor', '#fff')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
footerTypeLocal: {
|
||||
get () { return this.footerType },
|
||||
set (val) { this.$emit('updateFooter', val) }
|
||||
},
|
||||
hideScrollToTopLocal: {
|
||||
get () { return this.hideScrollToTop },
|
||||
set (val) { this.$emit('toggleHideScrollToTop', val) }
|
||||
},
|
||||
navbarColorInitial () {
|
||||
return this.$store.state.theme === 'dark' ? '#10163a' : '#fff'
|
||||
},
|
||||
navbarColorOptionClasses () {
|
||||
return (color) => {
|
||||
const classes = {}
|
||||
if (color === this.navbarColorLocal) classes['shadow-outline'] = true
|
||||
if (this.navbarTypeLocal === 'static') classes['cursor-not-allowed'] = true
|
||||
return classes
|
||||
}
|
||||
},
|
||||
navbarColorLocal: {
|
||||
get () { return this.navbarColor },
|
||||
set (val) {
|
||||
if (this.navbarType === 'static') return
|
||||
this.$emit('updateNavbarColor', val)
|
||||
}
|
||||
},
|
||||
navbarTypeLocal: {
|
||||
get () { return this.navbarType },
|
||||
set (val) { this.$emit('updateNavbar', val) }
|
||||
},
|
||||
layoutType: {
|
||||
get () { return this.$store.state.mainLayoutType },
|
||||
set (val) { this.$store.commit('UPDATE_MAIN_LAYOUT_TYPE', val) }
|
||||
},
|
||||
primaryColor: {
|
||||
get () { return this.$store.state.themePrimaryColor },
|
||||
set (val) { this.$store.commit('UPDATE_PRIMARY_COLOR', val) }
|
||||
},
|
||||
reduced_sidebar: {
|
||||
get () { return this.$store.state.reduceButton },
|
||||
set (val) { this.$store.commit('TOGGLE_REDUCE_BUTTON', val) }
|
||||
},
|
||||
routerTransitionLocal: {
|
||||
get () { return this.routerTransition },
|
||||
set (val) { this.$emit('updateRouterTransition', val) }
|
||||
},
|
||||
rtl: {
|
||||
get () { return this.$vs.rtl },
|
||||
set (val) { this.$vs.rtl = val }
|
||||
},
|
||||
themeMode: {
|
||||
get () { return this.$store.state.theme },
|
||||
set (val) { this.$store.dispatch('updateTheme', val) }
|
||||
},
|
||||
scrollbarTag () { return this.$store.state.is_touch_device ? 'div' : 'VuePerfectScrollbar' },
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updatePrimaryColor (color) {
|
||||
this.primaryColor = color
|
||||
this.$vs.theme({ primary: color })
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VuePerfectScrollbar
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
#theme-customizer {
|
||||
.vs-sidebar {
|
||||
position: fixed;
|
||||
z-index: 52000;
|
||||
width: 400px;
|
||||
max-width: 90vw;
|
||||
// @apply shadow-lg;
|
||||
box-shadow: 0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.customizer-btn {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
z-index: 50000;
|
||||
|
||||
.vs-icon {
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-area--customizer {
|
||||
height: calc(100% - 5rem);
|
||||
|
||||
&:not(.ps) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<div class="relative">
|
||||
<div class="vx-navbar-wrapper nav-menu-wrapper">
|
||||
<vs-navbar class="vx-navbar navbar-custom navbar-skelton" :color="navbarColor">
|
||||
|
||||
<ul class="menu-items flex flex-wrap w-full items-center">
|
||||
<li
|
||||
class = "menu-item"
|
||||
v-for = "(item, index) in navMenuItems"
|
||||
:key = "index"
|
||||
:class = "{'mr-2': !(navMenuItems.length === index+1)}">
|
||||
|
||||
<!-- If header -->
|
||||
<template v-if="item.header">
|
||||
<h-nav-menu-header :header="item" class="menu-header relative" />
|
||||
</template>
|
||||
|
||||
<!-- If it's group -->
|
||||
<template v-else-if="item.submenu">
|
||||
<h-nav-menu-group
|
||||
class="menu-group relative py-4"
|
||||
bottom
|
||||
:key ="`group-${index}`"
|
||||
:group ="item"
|
||||
:groupIndex ="index"
|
||||
:open ="checkGrpChildrenActive(item)" />
|
||||
</template>
|
||||
|
||||
<!-- If it's link -->
|
||||
<div v-else-if="item.url" class="menu-link">
|
||||
<h-nav-menu-item
|
||||
class = "relative py-4 cursor-pointer"
|
||||
:to = "item.slug !== 'external' ? item.url : null"
|
||||
:href = "item.slug === 'external' ? item.url : null"
|
||||
:icon = "item.icon"
|
||||
:target = "item.target"
|
||||
:isDisabled = "item.isDisabled"
|
||||
:slug = "item.slug">
|
||||
<span class="truncate">{{ $t(item.i18n) || item.name }}</span>
|
||||
<vs-chip :color="item.tagColor" v-if="item.tag">{{ item.tag }}</vs-chip>
|
||||
</h-nav-menu-item>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</vs-navbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HNavMenuGroup from './HorizontalNavMenuGroup.vue'
|
||||
import HNavMenuHeader from './HorizontalNavMenuHeader.vue'
|
||||
import HNavMenuItem from './HorizontalNavMenuItem.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
// navbarColor : { type: String, default: "#fff", },
|
||||
navMenuItems : { type: Array, required: true }
|
||||
},
|
||||
components: {
|
||||
HNavMenuGroup,
|
||||
HNavMenuHeader,
|
||||
HNavMenuItem
|
||||
},
|
||||
computed: {
|
||||
navbarColor () {
|
||||
return this.$store.state.theme === 'dark' ? '#10163a' : '#fff'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkGrpChildrenActive (group) {
|
||||
const path = this.$route.fullPath
|
||||
let active = false
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
|
||||
if (group.submenu) {
|
||||
group.submenu.forEach((item) => {
|
||||
if (active) return true
|
||||
if ((path === item.url || routeParent === item.slug) && item.url) { active = true } else if (item.submenu) { this.checkGrpChildrenActive(item) }
|
||||
})
|
||||
}
|
||||
|
||||
return active
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/horizontalNavMenu.scss";
|
||||
.v-nav-menu .vs-sidebar--item .router-link-active span {
|
||||
color: #fff;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div
|
||||
class = "h-nav-group relative"
|
||||
:class = "[
|
||||
{'h-nav-group-open' : openItems },
|
||||
{'h-nav-group-active' : open },
|
||||
{'disabled-item pointer-events-none': group.isDisabled }
|
||||
]"
|
||||
@mouseover = "mouseover"
|
||||
@mouseleave = "mouseout">
|
||||
|
||||
<!-- Group Label -->
|
||||
<div class="group-header w-full flex items-center">
|
||||
<span class="flex items-center w-full">
|
||||
|
||||
<!-- Group Icon -->
|
||||
<feather-icon
|
||||
v-if = "group.icon || (this.groupIndex > Math.floor(this.groupIndex))"
|
||||
:icon = "group.icon || 'CircleIcon'"
|
||||
:svgClasses = "iconClasses" />
|
||||
|
||||
<!-- Group Name -->
|
||||
<span class="truncate mr-3 select-none">{{ $t(group.i18n) || group.name }}</span>
|
||||
</span>
|
||||
|
||||
<!-- Group Collapse Icon -->
|
||||
<feather-icon
|
||||
:class = "[{'rotate90' : openItems}, 'feather-grp-header-arrow']"
|
||||
:icon = "bottom ? 'ChevronDownIcon' : $vs.rtl ? 'ChevronLeftIcon' : 'ChevronRightIcon'"
|
||||
svg-classes= "w-4 h-4" />
|
||||
</div>
|
||||
<!-- /Group Label -->
|
||||
|
||||
<!-- Group Items -->
|
||||
<transition name="fade-bottom-2x">
|
||||
<ul :style="styleItems" class="h-nav-group-items h-nav-menu-dd absolute shadow-drop py-2" v-show="openItems" ref="childDropdown">
|
||||
<li v-for="(groupItem, index) in group.submenu" :key="index">
|
||||
|
||||
<h-nav-menu-group
|
||||
v-if = "groupItem.submenu"
|
||||
:group = "groupItem"
|
||||
:groupIndex = "Number(`${groupIndex}.${index+1}`)"
|
||||
:open = "isGroupActive(groupItem)"
|
||||
:openHover = "openHover" />
|
||||
|
||||
|
||||
<h-nav-menu-item
|
||||
v-else
|
||||
icon-small
|
||||
:index = "groupIndex + '.' + index"
|
||||
:to = "groupItem.slug !== 'external' ? groupItem.url : null"
|
||||
:href = "groupItem.slug === 'external' ? groupItem.url : null"
|
||||
:icon = "itemIcon"
|
||||
:slug = "groupItem.slug"
|
||||
:target = "groupItem.target">
|
||||
<span class="truncate">{{ $t(groupItem.i18n) || groupItem.name }}</span>
|
||||
<vs-chip class="ml-auto" :color="groupItem.tagColor" v-if="groupItem.tag">{{ groupItem.tag }}</vs-chip>
|
||||
</h-nav-menu-item>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</transition>
|
||||
<!-- /Group Items -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// import VNavMenuItem from './VerticalNavMenuItem.vue'
|
||||
import HNavMenuItem from './HorizontalNavMenuItem.vue'
|
||||
|
||||
export default {
|
||||
name : 'h-nav-menu-group',
|
||||
props : {
|
||||
openHover : { type: Boolean, default: true },
|
||||
open : { type: Boolean, default: false },
|
||||
group : { type: Object },
|
||||
groupIndex : { type: Number },
|
||||
bottom : { type: Boolean, default: false }
|
||||
},
|
||||
components: {
|
||||
HNavMenuItem
|
||||
},
|
||||
data: () => ({
|
||||
openItems : false,
|
||||
hovered: false,
|
||||
dropLeft: false
|
||||
}),
|
||||
computed: {
|
||||
iconClasses () {
|
||||
let classes = 'mr-3 '
|
||||
classes += this.groupIndex % 1 !== 0 ? 'w-3 h-3' : 'w-5 h-5'
|
||||
return classes
|
||||
},
|
||||
styleItems () {
|
||||
const style = {}
|
||||
if (this.bottom) {
|
||||
style.top = '100%'
|
||||
style.left = '0'
|
||||
} else {
|
||||
style.top = '12px'
|
||||
style.left = '100%'
|
||||
}
|
||||
|
||||
if (this.dropLeft) {
|
||||
style.left = null
|
||||
style.right = '100%'
|
||||
}
|
||||
|
||||
if (this.$vs.rtl) {
|
||||
const temp = style.left
|
||||
style.left = style.right
|
||||
style.right = temp
|
||||
}
|
||||
|
||||
return style
|
||||
},
|
||||
itemIcon () {
|
||||
// return (index) => {
|
||||
// // if (!((index.match(/\./g) || []).length > 1)) return "CircleIcon"
|
||||
// }
|
||||
return 'CircleIcon'
|
||||
},
|
||||
isGroupActive () {
|
||||
return (item) => {
|
||||
const path = this.$route.fullPath
|
||||
let open = false
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
|
||||
const func = (item) => {
|
||||
if (item.submenu) {
|
||||
item.submenu.forEach((item) => {
|
||||
if ((path === item.url || routeParent === item.slug) && item.url) { open = true } else if (item.submenu) { func(item) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func(item)
|
||||
return open
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
hovered (val) {
|
||||
this.$nextTick(() => {
|
||||
if (val) {
|
||||
const dd = this.$refs.childDropdown
|
||||
|
||||
if (window.innerHeight - dd.getBoundingClientRect().top - dd.getBoundingClientRect().height - 28 < 1) {
|
||||
const maxHeight = window.innerHeight - dd.getBoundingClientRect().top - 70
|
||||
dd.style.maxHeight = `${maxHeight}px`
|
||||
dd.style.overflowY = 'auto'
|
||||
dd.style.overflowX = 'hidden'
|
||||
}
|
||||
|
||||
if (dd.getBoundingClientRect().left + dd.offsetWidth - (window.innerWidth - 16) >= 0 || this.$parent.dropLeft) {
|
||||
this.dropLeft = true
|
||||
}
|
||||
|
||||
if (this.$vs.rtl) {
|
||||
if (dd.getBoundingClientRect().right - dd.offsetWidth - 16 < 0) {
|
||||
this.dropLeft = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.dropLeft = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
mouseover () {
|
||||
this.hovered = true
|
||||
if (this.openHover) {
|
||||
this.showChildren()
|
||||
}
|
||||
},
|
||||
mouseout () {
|
||||
this.hovered = false
|
||||
if (this.openHover) {
|
||||
this.showChildren(false)
|
||||
}
|
||||
},
|
||||
showChildren (val = true) {
|
||||
this.openItems = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/horizontalNavMenuGroup.scss"
|
||||
</style>
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div
|
||||
class="nav-header py-4"
|
||||
@mouseover = "hovered"
|
||||
@mouseleave = "hovered(false)"
|
||||
@click = "showChildren = !showChildren">
|
||||
|
||||
<!-- header -->
|
||||
<div
|
||||
class="header-label flex items-center cursor-pointer relative px-5 py-2"
|
||||
:class="[
|
||||
{'text-white bg-primary-gradient header-active': isHeaderActive},
|
||||
{'header-open': isHovered || showChildren}
|
||||
]">
|
||||
<feather-icon :icon="header.icon" svgClasses="h-5 w-5" class="mr-3" />
|
||||
<span class="whitespace-no-wrap">{{ $t(header.i18n) || header.header }}</span>
|
||||
<feather-icon icon="ChevronDownIcon" svgClasses="h-4 w-4" class="ml-1" />
|
||||
</div>
|
||||
|
||||
<!-- Children -->
|
||||
<transition name="fade-top-2x">
|
||||
<ul class="header-children h-nav-menu-dd shadow-drop text-intial absolute shadow-lg py-2" :class="{'dd-right': dropRight}" v-show="showChildren" ref="headerDropdown">
|
||||
<li v-for="(item, index) in header.items" :key="item.name">
|
||||
<template v-if="!item.submenu">
|
||||
<h-nav-menu-item
|
||||
:to="item.slug != 'external' ? item.url : ''"
|
||||
:href="item.slug == 'external' ? item.url : ''"
|
||||
:icon="item.icon" :target="item.target"
|
||||
:isDisabled="item.isDisabled"
|
||||
:slug="item.slug">
|
||||
<span class="truncate">{{ $t(item.i18n) || item.name }}</span>
|
||||
<vs-chip :color="item.tagColor" v-if="item.tag">{{ item.tag }}</vs-chip>
|
||||
</h-nav-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h-nav-menu-group
|
||||
openHover
|
||||
:key="`group-${index}`"
|
||||
:group="item"
|
||||
:groupIndex="index"
|
||||
:open="checkGrpChildrenActive(item)" />
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HNavMenuGroup from './HorizontalNavMenuGroup.vue'
|
||||
import HNavMenuItem from './HorizontalNavMenuItem.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
header: {
|
||||
type: Object,
|
||||
requried: true
|
||||
},
|
||||
openOnHover: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
HNavMenuGroup,
|
||||
HNavMenuItem
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showChildren: false,
|
||||
isHovered: false,
|
||||
dropRight: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isHeaderActive () {
|
||||
const path = this.$route.fullPath
|
||||
let active = false
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
|
||||
this.header.items.forEach((item) => {
|
||||
|
||||
// If item is group
|
||||
if (item.submenu) {
|
||||
if (this.checkGrpChildrenActive(item)) { active = true }
|
||||
} else if (item.url) {
|
||||
if (path === item.url || routeParent === item.slug) { active = true }
|
||||
}
|
||||
})
|
||||
|
||||
return active
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
showChildren () {
|
||||
this.$nextTick(() => {
|
||||
if (this.showChildren) {
|
||||
const dd = this.$refs.headerDropdown
|
||||
if (dd.getBoundingClientRect().left + dd.offsetWidth - (window.innerWidth - 16) >= 0) {
|
||||
this.dropRight = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkGrpChildrenActive (group) {
|
||||
|
||||
const path = this.$route.fullPath
|
||||
let active = false
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
|
||||
if (group.submenu) {
|
||||
group.submenu.forEach((item) => {
|
||||
if ((path === item.url || routeParent === item.slug) && item.slug) active = true
|
||||
else if (item.submenu) { if (this.checkGrpChildrenActive(item)) active = true }
|
||||
})
|
||||
}
|
||||
|
||||
return active
|
||||
},
|
||||
hovered (val = true) {
|
||||
this.isHovered = val
|
||||
if (this.openOnHover) {
|
||||
val ? this.showChildren = true : this.showChildren = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/horizontalNavMenuHeader.scss";
|
||||
</style>
|
||||
@@ -0,0 +1,72 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: VerticalNavMenuItem.vue
|
||||
Description: Vertical NavMenu item component. Extends vuesax framework's 'vs-sidebar-item' component
|
||||
Component Name: VerticalNavMenuItem
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="canSee"
|
||||
class="h-nav-menu-item"
|
||||
:class="[
|
||||
{'h-nav-active-item text-primary font-medium' : activeLink},
|
||||
{'disabled-item pointer-events-none' : isDisabled},
|
||||
]" >
|
||||
|
||||
<router-link
|
||||
v-if="to"
|
||||
exact
|
||||
:class="[{'router-link-active': activeLink}, 'nav-link flex items-center']"
|
||||
:to="to"
|
||||
:target="target" >
|
||||
<vs-icon v-if="!featherIcon" :icon-pack="iconPack" :icon="icon" />
|
||||
<feather-icon v-else :class="iconClasses" :icon="icon" />
|
||||
<slot />
|
||||
</router-link>
|
||||
|
||||
<a v-else :target="target" :href="href" class="nav-link flex items-center">
|
||||
<vs-icon v-if="!featherIcon" :icon-pack="iconPack" :icon="icon" />
|
||||
<feather-icon v-else :class="iconClasses" :icon="icon" />
|
||||
<slot />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'v-nav-menu-item',
|
||||
props: {
|
||||
icon : { type: String, default: '' },
|
||||
iconSmall : { type: Boolean, default: false },
|
||||
iconPack : { type: String, default: 'material-icons' },
|
||||
href : { type: [String, null], default: '#' },
|
||||
to : { type: [String, Object, null], default: null },
|
||||
slug : { type: String, default: null },
|
||||
index : { type: [String, Number], default: null },
|
||||
featherIcon : { type: Boolean, default: true },
|
||||
target : { type: String, default: '_self' },
|
||||
isDisabled : { type: Boolean, default: false }
|
||||
},
|
||||
computed: {
|
||||
iconClasses () {
|
||||
return this.iconSmall ? 'w-3 h-3 mr-3' : 'w-5 h-5 mr-3'
|
||||
},
|
||||
canSee () {
|
||||
this.$acl.check(this.$store.state.AppActiveUser.userRole)
|
||||
return this.to ? this.$acl.check(this.$router.match(this.to).meta.rule) : true
|
||||
},
|
||||
activeLink () {
|
||||
return !!((this.to === this.$route.path || this.$route.meta.parent === this.slug) && this.to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/horizontalNavMenuItem.scss";
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TheNavbar.vue
|
||||
Description: Navbar component
|
||||
Component Name: TheNavbar
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="relative">
|
||||
<div class="vx-navbar-wrapper navbar-full p-0">
|
||||
<vs-navbar class="navbar-custom navbar-skelton" :class="navbarClasses" :style="navbarStyle" :color="navbarColor">
|
||||
|
||||
<bookmarks :navbarColor="navbarColor" v-if="windowWidth >= 992" />
|
||||
|
||||
<router-link tag="div" to="/" class="vx-logo cursor-pointer mx-auto flex items-center">
|
||||
<logo class="w-10 mr-4 fill-current text-primary" />
|
||||
<span class="vx-logo-text text-primary">کنسولی</span>
|
||||
</router-link>
|
||||
|
||||
<search-bar />
|
||||
|
||||
<profile-drop-down />
|
||||
|
||||
</vs-navbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Bookmarks from './components/Bookmarks.vue'
|
||||
import I18n from './components/I18n.vue'
|
||||
import SearchBar from './components/SearchBar.vue'
|
||||
import CartDropDown from './components/CartDropDown.vue'
|
||||
import NotificationDropDown from './components/NotificationDropDown.vue'
|
||||
import ProfileDropDown from './components/ProfileDropDown.vue'
|
||||
import Logo from '../Logo.vue'
|
||||
|
||||
export default {
|
||||
name: 'the-navbar-horizontal',
|
||||
props: {
|
||||
logo: { type: String },
|
||||
navbarType: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Logo,
|
||||
Bookmarks,
|
||||
I18n,
|
||||
SearchBar,
|
||||
CartDropDown,
|
||||
NotificationDropDown,
|
||||
ProfileDropDown
|
||||
},
|
||||
computed: {
|
||||
navbarColor () {
|
||||
let color = '#fff'
|
||||
if (this.navbarType === 'sticky') color = '#f7f7f7'
|
||||
else if (this.navbarType === 'static') {
|
||||
if (this.scrollY < 50) {
|
||||
color = '#f7f7f7'
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isThemedark === 'dark') {
|
||||
if (color === '#fff') {
|
||||
color = '#10163a'
|
||||
} else {
|
||||
color = '#262c49'
|
||||
}
|
||||
}
|
||||
|
||||
return color
|
||||
},
|
||||
isThemedark () { return this.$store.state.theme },
|
||||
navbarStyle () { return this.navbarType === 'static' ? {transition: 'all .25s ease-in-out'} : {} },
|
||||
navbarClasses () { return this.scrollY > 5 && this.navbarType === 'static' ? null : 'd-theme-dark-light-bg shadow-none' },
|
||||
scrollY () { return this.$store.state.scrollY },
|
||||
verticalNavMenuWidth () { return this.$store.state.verticalNavMenuWidth },
|
||||
windowWidth () { return this.$store.state.windowWidth }
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: TheNavbar.vue
|
||||
Description: Navbar component
|
||||
Component Name: TheNavbar
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="relative">
|
||||
|
||||
<div class="vx-navbar-wrapper" :class="classObj">
|
||||
|
||||
<vs-navbar class="vx-navbar navbar-custom navbar-skelton" :color="navbarColorLocal" :class="textColor">
|
||||
|
||||
<!-- SM - OPEN SIDEBAR BUTTON -->
|
||||
<feather-icon class="sm:inline-flex xl:hidden cursor-pointer p-2" icon="MenuIcon" @click.stop="showSidebar" />
|
||||
|
||||
<!-- <search-bar />-->
|
||||
|
||||
<vs-spacer />
|
||||
|
||||
<profile-drop-down />
|
||||
|
||||
|
||||
</vs-navbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import Bookmarks from './components/Bookmarks.vue'
|
||||
import I18n from './components/I18n.vue'
|
||||
import SearchBar from './components/SearchBar.vue'
|
||||
import CartDropDown from './components/CartDropDown.vue'
|
||||
import NotificationDropDown from './components/NotificationDropDown.vue'
|
||||
import ProfileDropDown from './components/ProfileDropDown.vue'
|
||||
|
||||
export default {
|
||||
name: 'the-navbar-vertical',
|
||||
props: {
|
||||
navbarColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Bookmarks,
|
||||
I18n,
|
||||
SearchBar,
|
||||
CartDropDown,
|
||||
NotificationDropDown,
|
||||
ProfileDropDown
|
||||
},
|
||||
computed: {
|
||||
navbarColorLocal () {
|
||||
return this.$store.state.theme === 'dark' && this.navbarColor === '#fff' ? '#10163a' : this.navbarColor
|
||||
},
|
||||
verticalNavMenuWidth () {
|
||||
return this.$store.state.verticalNavMenuWidth
|
||||
},
|
||||
textColor () {
|
||||
return {'text-white': (this.navbarColor !== '#10163a' && this.$store.state.theme === 'dark') || (this.navbarColor !== '#fff' && this.$store.state.theme !== 'dark')}
|
||||
},
|
||||
windowWidth () {
|
||||
return this.$store.state.windowWidth
|
||||
},
|
||||
|
||||
// NAVBAR STYLE
|
||||
classObj () {
|
||||
if (this.verticalNavMenuWidth === 'default') return 'navbar-default'
|
||||
else if (this.verticalNavMenuWidth === 'reduced') return 'navbar-reduced'
|
||||
else if (this.verticalNavMenuWidth) return 'navbar-full'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showSidebar () {
|
||||
this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', true)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div class="navbar-bookmarks flex items-center">
|
||||
<!-- STARRED PAGES - FIRST 10 -->
|
||||
<ul class="vx-navbar__starred-pages">
|
||||
<draggable v-model="starredPagesLimited" :group="{name: 'pinList'}" class="flex cursor-move">
|
||||
<li class="starred-page" v-for="page in starredPagesLimited" :key="page.url">
|
||||
<vx-tooltip :text="page.title" position="bottom" delay=".3s">
|
||||
<feather-icon :svgClasses="['h-6 w-6 stroke-current', textColor]" class="p-2 cursor-pointer" :icon="page.icon" @click="$router.push(page.url).catch(() => {})" />
|
||||
</vx-tooltip>
|
||||
</li>
|
||||
</draggable>
|
||||
</ul>
|
||||
|
||||
<!-- STARRED PAGES MORE -->
|
||||
<div class="vx-navbar__starred-pages--more-dropdown" v-if="starredPagesMore.length">
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<feather-icon icon="ChevronDownIcon" svgClasses="h-4 w-4" class="cursor-pointer p-2"></feather-icon>
|
||||
<vs-dropdown-menu>
|
||||
<ul class="vx-navbar__starred-pages-more--list">
|
||||
<draggable v-model="starredPagesMore" :group="{name: 'pinList'}" class="cursor-move">
|
||||
<li class="starred-page--more flex items-center cursor-pointer" v-for="page in starredPagesMore" :key="page.url" @click="$router.push(page.url).catch(() => {})">
|
||||
<feather-icon class="ml-2 mr-1" :icon="page.icon" :svgClasses="['h-5 w-5 stroke-current', textColor]"></feather-icon>
|
||||
<span class="px-2 pt-2 pb-1">{{ page.title }}</span>
|
||||
</li>
|
||||
</draggable>
|
||||
</ul>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="bookmark-container">
|
||||
<feather-icon icon="StarIcon" :svgClasses="['stoke-current text-warning', textColor]" class="cursor-pointer p-2" @click.stop="showBookmarkPagesDropdown = !showBookmarkPagesDropdown" />
|
||||
<div v-click-outside="outside" class="absolute bookmark-list w-1/3 xl:w-1/4 mt-4" v-if="showBookmarkPagesDropdown">
|
||||
<vx-auto-suggest
|
||||
ref="bookmarkAutoSuggest"
|
||||
:autoFocus="true"
|
||||
:data="navbarSearchAndPinList"
|
||||
:initalData="{pages: starredPagesLimited.concat(starredPagesMore)}"
|
||||
:searchLimit="5"
|
||||
placeholder="Explore Vuexy..."
|
||||
inputClassses="w-full"
|
||||
show-action
|
||||
show-pinned
|
||||
hideGroupTitle
|
||||
background-overlay
|
||||
@input="hnd_search_query_update"
|
||||
@selected="selected">
|
||||
|
||||
<!-- Pages Suggestion -->
|
||||
<template v-slot:pages="{ suggestion }">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-end leading-none py-1">
|
||||
<feather-icon :icon="suggestion.icon" svgClasses="h-5 w-5" class="mr-4" />
|
||||
<span class="mt-1">{{ suggestion.title }}</span>
|
||||
</div>
|
||||
<feather-icon
|
||||
icon="StarIcon"
|
||||
:svgClasses="[{'text-warning': suggestion.is_bookmarked}, 'h-5 w-5 stroke-current mt-1']"
|
||||
@click.stop="actionClicked(suggestion)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</vx-auto-suggest>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
import VxAutoSuggest from '@/components/vx-auto-suggest/VxAutoSuggest.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
navbarColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
draggable,
|
||||
VxAutoSuggest
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showBookmarkPagesDropdown : false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route' () {
|
||||
if (this.showBookmarkPagesDropdown) this.showBookmarkPagesDropdown = false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
navbarSearchAndPinList () {
|
||||
return {pages: this.$store.state.navbarSearchAndPinList['pages']}
|
||||
},
|
||||
starredPages () {
|
||||
return this.$store.state.starredPages
|
||||
},
|
||||
starredPagesLimited: {
|
||||
get () {
|
||||
return this.starredPages.slice(0, 10)
|
||||
},
|
||||
set (list) {
|
||||
this.$store.dispatch('arrangeStarredPagesLimited', list)
|
||||
}
|
||||
},
|
||||
starredPagesMore: {
|
||||
get () {
|
||||
return this.starredPages.slice(10)
|
||||
},
|
||||
set (list) {
|
||||
this.$store.dispatch('arrangeStarredPagesMore', list)
|
||||
}
|
||||
},
|
||||
textColor () {
|
||||
return {'text-white': this.$store.state.mainLayoutType === 'vertical' && this.navbarColor !== (this.$store.state.theme === 'dark' ? '#10163a' : '#fff') }
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selected (obj) {
|
||||
this.$store.commit('TOGGLE_CONTENT_OVERLAY', false)
|
||||
this.showBookmarkPagesDropdown = false
|
||||
this.$router.push(obj.pages.url).catch(() => {})
|
||||
},
|
||||
actionClicked (item) {
|
||||
this.$store.dispatch('updateStarredPage', { url: item.url, val: !item.is_bookmarked })
|
||||
// this.$refs.bookmarkAutoSuggest.filterData()
|
||||
},
|
||||
outside () {
|
||||
this.showBookmarkPagesDropdown = false
|
||||
},
|
||||
hnd_search_query_update (query) {
|
||||
// Show overlay if any character is entered
|
||||
this.$store.commit('TOGGLE_CONTENT_OVERLAY', !!query)
|
||||
}
|
||||
},
|
||||
directives: {
|
||||
'click-outside': {
|
||||
bind (el, binding) {
|
||||
const bubble = binding.modifiers.bubble
|
||||
const handler = (e) => {
|
||||
/* eslint-disable no-mixed-operators */
|
||||
if (bubble || !el.contains(e.target) && el !== e.target) {
|
||||
/* eslint-enable no-mixed-operators */
|
||||
binding.value(e)
|
||||
}
|
||||
}
|
||||
el.__vueClickOutside__ = handler
|
||||
document.addEventListener('click', handler)
|
||||
},
|
||||
|
||||
unbind (el) {
|
||||
document.removeEventListener('click', el.__vueClickOutside__)
|
||||
el.__vueClickOutside__ = null
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<!-- CART DROPDOWN -->
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<feather-icon icon="ShoppingCartIcon" class="cursor-pointer ml-4 mr-6 mt-1" :badge="cartItems.length" />
|
||||
<vs-dropdown-menu class="cart-dropdown vx-navbar-dropdown" :class="{'dropdown-custom': cartItems.length}">
|
||||
|
||||
<!-- IF CART HAVE ITEMS: HEADER -->
|
||||
<template v-if="cartItems.length">
|
||||
<div class="notification-header text-center p-5 bg-primary text-white">
|
||||
<h3 class="text-white">{{ cartItems.length }} Item<span v-show="cartItems.length > 1">s</span></h3>
|
||||
<p class="opacity-75">In Your Cart</p>
|
||||
</div>
|
||||
|
||||
<!-- CART ITEMS -->
|
||||
<component :is="scrollbarTag" ref="mainSidebarPs" class="scroll-area--cart-items-dropdowm p-0 mb-10" :settings="settings" :key="$vs.rtl">
|
||||
<ul class="bordered-items">
|
||||
<li
|
||||
v-for="item in cartItems"
|
||||
:key="item.objectID"
|
||||
class="vx-row no-gutter cart-item cursor-pointer"
|
||||
@click="$router.push({name: 'ecommerce-item-detail-view', params: {item_id: item.objectID }}).catch(() => {})">
|
||||
|
||||
<!-- IMG COL -->
|
||||
<div class="vx-col w-1/5 item-img-container bg-white flex items-center justify-center">
|
||||
<img :src="item.image" alt="item" class="cart-dropdown-item-img p-4">
|
||||
</div>
|
||||
|
||||
<!-- INFO COL -->
|
||||
<div class="vx-col w-4/5 pr-4 pl-2 py-4 flex flex-col justify-center">
|
||||
<span class="font-medium block cart-item-title truncate">{{ item.name }}</span>
|
||||
<small class="truncate mb-2">{{ item.description }}</small>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium">{{ item.quantity }} <small>x</small> ${{ item.price }}</span>
|
||||
<feather-icon icon="XIcon" svgClasses="h-4 w-4 cursor-pointer text-danger" class="hover:text-danger" @click.stop="removeItemFromCart(item)" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</component>
|
||||
<div
|
||||
class=" checkout-footer fixed bottom-0 rounded-b-lg text-primary font-semibold w-full p-2 text-center border border-b-0 border-l-0 border-r-0 border-solid d-theme-border-grey-light cursor-pointer"
|
||||
@click="$router.push('/apps/eCommerce/checkout').catch(() => {})">
|
||||
|
||||
<span class="flex items-center justify-center">
|
||||
<feather-icon icon="ShoppingCartIcon" svgClasses="h-4 w-4" />
|
||||
<span class="ml-2">Checkout</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- IF CART IS EMPTY -->
|
||||
<template v-else>
|
||||
<p class="p-4">Your Cart Is Empty.</p>
|
||||
</template>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VuePerfectScrollbar
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
settings: { // perfectscrollbar settings
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: .60
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// CART DROPDOWN
|
||||
cartItems () {
|
||||
return this.$store.state.eCommerce.cartItems.slice().reverse()
|
||||
},
|
||||
scrollbarTag () {
|
||||
return this.$store.getters.scrollbarTag
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeItemFromCart (item) {
|
||||
this.$store.dispatch('eCommerce/toggleItemInCart', item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<span class="cursor-pointer flex items-center i18n-locale">
|
||||
<img class="h-4 w-5" :src="i18n_locale_img" :alt="$i18n.locale" />
|
||||
<span class="hidden sm:block ml-2">{{ getCurrentLocaleData.lang }}</span>
|
||||
</span>
|
||||
<vs-dropdown-menu class="w-48 i18n-dropdown vx-navbar-dropdown">
|
||||
<vs-dropdown-item @click="updateLocale('en')"><img class="h-4 w-5 mr-1" src="@/assets/images/flags/en.png" alt="en" /> English</vs-dropdown-item>
|
||||
<vs-dropdown-item @click="updateLocale('fr')"><img class="h-4 w-5 mr-1" src="@/assets/images/flags/fr.png" alt="fr" /> French</vs-dropdown-item>
|
||||
<vs-dropdown-item @click="updateLocale('de')"><img class="h-4 w-5 mr-1" src="@/assets/images/flags/de.png" alt="de" /> German</vs-dropdown-item>
|
||||
<vs-dropdown-item @click="updateLocale('pt')"><img class="h-4 w-5 mr-1" src="@/assets/images/flags/pt.png" alt="pt" /> Portuguese</vs-dropdown-item>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
i18n_locale_img () {
|
||||
return require(`@/assets/images/flags/${this.$i18n.locale}.png`)
|
||||
},
|
||||
getCurrentLocaleData () {
|
||||
const locale = this.$i18n.locale
|
||||
if (locale === 'en') return { flag: 'us', lang: 'English' }
|
||||
else if (locale === 'pt') return { flag: 'br', lang: 'Portuguese' }
|
||||
else if (locale === 'fr') return { flag: 'fr', lang: 'French' }
|
||||
else if (locale === 'de') return { flag: 'de', lang: 'German' }
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateLocale (locale) {
|
||||
this.$i18n.locale = locale
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
|
||||
|
||||
|
||||
<template>
|
||||
<!-- NOTIFICATIONS -->
|
||||
<vs-dropdown vs-custom-content vs-trigger-click class="cursor-pointer">
|
||||
<feather-icon icon="BellIcon" class="cursor-pointer mt-1 sm:mr-6 mr-2" :badge="unreadNotifications.length" />
|
||||
|
||||
<vs-dropdown-menu class="notification-dropdown dropdown-custom vx-navbar-dropdown">
|
||||
|
||||
<div class="notification-top text-center p-5 bg-primary text-white">
|
||||
<h3 class="text-white">{{ unreadNotifications.length }} پیام جدید</h3>
|
||||
<p class="opacity-75">رویداد ها</p>
|
||||
</div>
|
||||
|
||||
<component :is="scrollbarTag" ref="mainSidebarPs" class="scroll-area--nofications-dropdown p-0 mb-10" :settings="settings" :key="$vs.rtl">
|
||||
<ul class="bordered-items">
|
||||
<li v-for="ntf in unreadNotifications" :key="ntf.index" class="flex justify-between px-4 py-4 notification cursor-pointer">
|
||||
<div class="flex items-start">
|
||||
<feather-icon :icon="ntf.icon" :svgClasses="[`text-${ntf.category}`, 'stroke-current mr-1 h-6 w-6']"></feather-icon>
|
||||
<div class="mx-2">
|
||||
<span class="font-medium block notification-title" :class="[`text-${ntf.category}`]">{{ ntf.title }}</span>
|
||||
<small>{{ ntf.msg }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<small class="mt-1 whitespace-no-wrap">{{ elapsedTime(ntf.time) }}</small>
|
||||
</li>
|
||||
</ul>
|
||||
</component>
|
||||
|
||||
<div class="
|
||||
checkout-footer
|
||||
fixed
|
||||
bottom-0
|
||||
rounded-b-lg
|
||||
text-primary
|
||||
w-full
|
||||
p-2
|
||||
font-semibold
|
||||
text-center
|
||||
border
|
||||
border-b-0
|
||||
border-l-0
|
||||
border-r-0
|
||||
border-solid
|
||||
d-theme-border-grey-light
|
||||
cursor-pointer">
|
||||
<span>نمایش تمامی اعلان ها</span>
|
||||
</div>
|
||||
</vs-dropdown-menu>
|
||||
</vs-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VuePerfectScrollbar
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
unreadNotifications: [
|
||||
{
|
||||
index : 0,
|
||||
title : 'تحویل سفارش',
|
||||
msg : 'سفارش #25550 به محمد محسنی تحویل داده شد',
|
||||
icon : 'MessageSquareIcon',
|
||||
time : this.randomDate({sec: 10}),
|
||||
category : 'primary'
|
||||
},
|
||||
{ index : 1,
|
||||
title : 'سفارش جدید',
|
||||
msg : 'سفارش #45550 برای محمد شایسته ',
|
||||
icon : 'PackageIcon',
|
||||
time : this.randomDate({sec: 40}),
|
||||
category : 'success'
|
||||
},
|
||||
{ index : 2,
|
||||
title : 'لغو سفارش',
|
||||
msg : 'سفارش #45550 برای محمد شایسته ',
|
||||
icon : 'AlertOctagonIcon',
|
||||
time : this.randomDate({min: 1}),
|
||||
category : 'danger'
|
||||
}
|
||||
],
|
||||
settings: {
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed: .60
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag }
|
||||
},
|
||||
methods: {
|
||||
elapsedTime (startTime) {
|
||||
const x = new Date(startTime)
|
||||
const now = new Date()
|
||||
let timeDiff = now - x
|
||||
timeDiff /= 1000
|
||||
|
||||
const seconds = Math.round(timeDiff)
|
||||
timeDiff = Math.floor(timeDiff / 60)
|
||||
|
||||
const minutes = Math.round(timeDiff % 60)
|
||||
timeDiff = Math.floor(timeDiff / 60)
|
||||
|
||||
const hours = Math.round(timeDiff % 24)
|
||||
timeDiff = Math.floor(timeDiff / 24)
|
||||
|
||||
const days = Math.round(timeDiff % 365)
|
||||
timeDiff = Math.floor(timeDiff / 365)
|
||||
|
||||
const years = timeDiff
|
||||
|
||||
if (years > 0) {
|
||||
return `${years + (years > 1 ? ' سال ' : ' سال ')}پیش`
|
||||
} else if (days > 0) {
|
||||
return `${days + (days > 1 ? ' روز ' : ' روز ')}پیش`
|
||||
} else if (hours > 0) {
|
||||
return `${hours + (hours > 1 ? ' ساعت ' : ' ساعت ')}پیش`
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes + (minutes > 1 ? ' دقیقه ' : ' دقیقه ')}پیش`
|
||||
} else if (seconds > 0) {
|
||||
return seconds + (seconds > 1 ? 'چند ثانیه پیش' : 'همین الان')
|
||||
}
|
||||
|
||||
return 'همین الان'
|
||||
},
|
||||
// Method for creating dummy notification time
|
||||
randomDate ({ hr, min, sec }) {
|
||||
const date = new Date()
|
||||
|
||||
if (hr) date.setHours(date.getHours() - hr)
|
||||
if (min) date.setMinutes(date.getMinutes() - min)
|
||||
if (sec) date.setSeconds(date.getSeconds() - sec)
|
||||
|
||||
return date
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="the-navbar__user-meta flex items-center">
|
||||
<ADropdown :trigger="['click']" style="z-index: 250000">
|
||||
<div class="flex items-center">
|
||||
<div class="flex justify-start">
|
||||
<p class="font-semibold mb-0">
|
||||
{{ username }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="con-img ml-3">
|
||||
<feather-icon icon="UserIcon" class="cursor-pointer" svg-classes="text-primary"/>
|
||||
</div>
|
||||
</div>
|
||||
<ACard slot="overlay">
|
||||
<ul style="min-width: 9rem;z-index: 25000">
|
||||
<li
|
||||
@click="logout"
|
||||
class="flex py-2 px-4 cursor-pointer hover:bg-primary hover:text-white">
|
||||
<feather-icon icon="LogOutIcon" svgClasses="w-4 h-4"/>
|
||||
<span class="ml-2">خروج از حساب کاربری</span>
|
||||
</li>
|
||||
</ul>
|
||||
</ACard>
|
||||
</ADropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import 'firebase/auth';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
activeUserInfo() {
|
||||
const j = localStorage.getItem('user');
|
||||
if (!j || j == 'undefined') {
|
||||
return {};
|
||||
}
|
||||
const s = JSON.parse(j || '{}');
|
||||
return s;
|
||||
},
|
||||
// username() {
|
||||
// return this.activeUserInfo.name;
|
||||
// },
|
||||
username(){
|
||||
const data = localStorage.getItem('user')
|
||||
console.log(data,'dayaaaaaaa');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
if (localStorage.getItem('accessToken')) {
|
||||
localStorage.removeItem('user');
|
||||
localStorage.removeItem('accessToken');
|
||||
}
|
||||
this.$router.push('/auth/login').catch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<div class="search-full-container w-full h-full absolute left-0 top-0" :class="{'flex': showFullSearch}" v-show="showFullSearch">
|
||||
<vx-auto-suggest
|
||||
ref="navbarSearch"
|
||||
:autoFocus="showFullSearch"
|
||||
:data="navbarSearchAndPinList"
|
||||
search_key="title"
|
||||
background-overlay
|
||||
class="w-full"
|
||||
inputClassses="w-full vs-input-no-border vs-input-no-shdow-focus"
|
||||
icon="SearchIcon"
|
||||
placeholder="جستجو کنید..."
|
||||
@input="hnd_search_query_update"
|
||||
@selected="selected"
|
||||
@closeSearchbar="showFullSearch = false">
|
||||
|
||||
<template v-slot:group="{ group_name }">
|
||||
<p class="font-semibold text-primary">{{ group_name | title }}</p>
|
||||
</template>
|
||||
|
||||
<!-- Pages Suggestion -->
|
||||
<template v-slot:pages="{ suggestion }">
|
||||
<div class="flex items-end leading-none py-1">
|
||||
<feather-icon :icon="suggestion.icon" svgClasses="h-5 w-5" class="mr-4" />
|
||||
<span class="mt-1">{{ suggestion.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <!– Files Suggestion –>-->
|
||||
<!-- <template v-slot:files="{ suggestion }">-->
|
||||
<!-- <div class="flex items-center justify-between">-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <div class="img-container w-8 mr-3 flex">-->
|
||||
<!-- <img :src="require(`@/assets/images/file-icons/${suggestion.file_ext}.png`)" :alt="suggestion.file_name" class="responsive">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="leading-none mt-1">-->
|
||||
<!-- <p class="mb-1">{{ suggestion.file_name }}</p>-->
|
||||
<!-- <small>by {{ suggestion.from }}</small>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <small>{{ suggestion.size }}</small>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- <!– Contacts Suggestion –>-->
|
||||
<!-- <template v-slot:contacts="{ suggestion }">-->
|
||||
<!-- <div class="flex items-center justify-between">-->
|
||||
<!-- <div class="flex items-center">-->
|
||||
<!-- <img :src="suggestion.img" :alt="suggestion.name" class="w-8 h-8 mr-3 rounded-full">-->
|
||||
<!-- <div class="leading-none mt-1">-->
|
||||
<!-- <p>{{ suggestion.name }}</p>-->
|
||||
<!-- <small>{{ suggestion.email }}</small>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <small>{{ suggestion.time }}</small>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- No Items Slot -->
|
||||
<template v-slot:noResult="{ group_name }">
|
||||
<div class="flex items-center">
|
||||
<feather-icon icon="InfoIcon" svgClasses="h-5 w-5" class="mr-4" />
|
||||
<span>No results found.</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</vx-auto-suggest>
|
||||
|
||||
<div class="absolute right-0 h-full z-50">
|
||||
<feather-icon
|
||||
icon="XIcon"
|
||||
class="px-4 cursor-pointer h-full close-search-icon"
|
||||
@click="showFullSearch = false" />
|
||||
</div>
|
||||
</div>
|
||||
<feather-icon icon="SearchIcon" @click="showFullSearch = true" class="cursor-pointer navbar-fuzzy-search mr-8" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VxAutoSuggest from '@/components/vx-auto-suggest/VxAutoSuggest.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VxAutoSuggest
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
navbarSearchAndPinList: this.$store.state.navbarSearchAndPinList,
|
||||
showFullSearch: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selected (item) {
|
||||
if (item.pages) this.$router.push(item.pages.url).catch(() => {})
|
||||
this.showFullSearch = false
|
||||
},
|
||||
hnd_search_query_update (query) {
|
||||
// Show overlay if any character is entered
|
||||
this.$store.commit('TOGGLE_CONTENT_OVERLAY', !!query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,152 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
pages: {
|
||||
key: "title",
|
||||
data: [
|
||||
// DASHBOARDS
|
||||
{title: "Analytics Dashboard", url: "/dashboard/analytics", icon: "HomeIcon", is_bookmarked: false},
|
||||
{title: "eCommerce Dashboard", url: "/dashboard/ecommerce", icon: "HomeIcon", is_bookmarked: false},
|
||||
|
||||
// APPS
|
||||
{title: "Todo", url: "/apps/todo", icon: "CheckSquareIcon", is_bookmarked: true},
|
||||
{title: "Chat", url: "/apps/chat", icon: "MessageSquareIcon", is_bookmarked: true},
|
||||
{title: "Email", url: "/apps/email", icon: "MailIcon", is_bookmarked: true},
|
||||
{title: "Calendar", url: "/apps/calendar/vue-simple-calendar", icon: "CalendarIcon", is_bookmarked: true},
|
||||
{title: "E-Commerce Shop", url: "/apps/eCommerce/shop", icon: "ShoppingCartIcon", is_bookmarked: true},
|
||||
{title: "E-Commerce Item Detail", url: "/apps/eCommerce/item", icon: "SmartphoneIcon", is_bookmarked: false},
|
||||
{title: "E-Commerce Wish List", url: "/apps/eCommerce/wish-list", icon: "HeartIcon", is_bookmarked: false},
|
||||
{title: "E-Commerce Checkout", url: "/apps/eCommerce/checkout", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "User List", url: "/apps/user/user-list", icon: "ListIcon", is_bookmarked: false},
|
||||
{title: "User View", url: "/apps/user/user-view/268", icon: "UserIcon", is_bookmarked: false},
|
||||
{title: "User Edit", url: "/apps/user/user-edit/268", icon: "EditIcon", is_bookmarked: false},
|
||||
|
||||
// UI ELEMENTS
|
||||
{title: "Data List - List View", url: "/ui-elements/data-list/list-view", icon: "ListIcon", is_bookmarked: false},
|
||||
{title: "Data List - Thumb View", url: "/ui-elements/data-list/thumb-view", icon: "ImageIcon", is_bookmarked: false},
|
||||
{title: "Vuesax Grid", url: "/ui-elements/grid/vuesax", icon: "LayoutIcon", is_bookmarked: false},
|
||||
{title: "Tailwind Grid", url: "/ui-elements/grid/tailwind", icon: "LayoutIcon", is_bookmarked: false},
|
||||
{title: "Colors", url: "/ui-elements/colors", icon: "DropletIcon", is_bookmarked: false},
|
||||
{title: "Basic Cards", url: "/ui-elements/card/basic", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Statistics Card", url: "/ui-elements/card/statistics", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Analytics Cards", url: "/ui-elements/card/analytics", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Card Actions", url: "/ui-elements/card/card-actions", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Card Colors", url: "/ui-elements/card/card-colors", icon: "FeatherIcon", is_bookmarked: false},
|
||||
{title: "Table", url: "/ui-elements/table", icon: "GridIcon", is_bookmarked: false},
|
||||
{title: "agGrid Table", url: "/ui-elements/ag-grid-table", icon: "GridIcon", is_bookmarked: false},
|
||||
{title: "Alert Component", url: "/components/alert", icon: "AlertTriangleIcon", is_bookmarked: false},
|
||||
{title: "Avatar Component", url: "/components/avatar", icon: "UserIcon", is_bookmarked: false},
|
||||
{title: "Breadcrumb Component", url: "/components/breadcrumb", icon: "NavigationIcon", is_bookmarked: false},
|
||||
{title: "Button Component", url: "/components/button", icon: "BoldIcon", is_bookmarked: false},
|
||||
{title: "Button Group Component", url: "/components/button-group", icon: "BoldIcon", is_bookmarked: false},
|
||||
{title: "Chip Component", url: "/components/chip", icon: "TagIcon", is_bookmarked: false},
|
||||
{title: "Collapse Component", url: "/components/collapse", icon: "PlusIcon", is_bookmarked: false},
|
||||
{title: "Dialogs Component", url: "/components/dialogs", icon: "CopyIcon", is_bookmarked: false},
|
||||
{title: "Divider Component", url: "/components/divider", icon: "MinusIcon", is_bookmarked: false},
|
||||
{title: "DropDown Component", url: "/components/dropdown", icon: "MoreHorizontalIcon", is_bookmarked: false},
|
||||
{title: "List Component", url: "/components/list", icon: "ListIcon", is_bookmarked: false},
|
||||
{title: "Loading Component", url: "/components/loading", icon: "LoaderIcon", is_bookmarked: false},
|
||||
{title: "Navbar Component", url: "/components/navbar", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Notifications Component", url: "/components/notifications", icon: "BellIcon", is_bookmarked: false},
|
||||
{title: "Pagination Component", url: "/components/pagination", icon: "ChevronsRightIcon", is_bookmarked: false},
|
||||
{title: "Popup Component", url: "/components/popup", icon: "CopyIcon", is_bookmarked: false},
|
||||
{title: "Progress Component", url: "/components/progress", icon: "SlidersIcon", is_bookmarked: false},
|
||||
{title: "Sidebar Component", url: "/components/sidebar", icon: "SidebarIcon", is_bookmarked: false},
|
||||
{title: "Slider Component", url: "/components/slider", icon: "SlidersIcon", is_bookmarked: false},
|
||||
{title: "Tabs Component", url: "/components/tabs", icon: "CreditCardIcon", is_bookmarked: false},
|
||||
{title: "Tooltip Component", url: "/components/tooltip", icon: "AlertCircleIcon", is_bookmarked: false},
|
||||
{title: "Upload Component", url: "/components/upload", icon: "UploadIcon", is_bookmarked: false},
|
||||
|
||||
// FORMS
|
||||
// {title: "Select Form Element", url: "/forms/form-elements/select", icon: "CheckIcon", is_bookmarked: false},
|
||||
{title: "Switch Form Element", url: "/forms/form-elements/switch", icon: "ToggleLeftIcon", is_bookmarked: false},
|
||||
{title: "Checkbox Form Element", url: "/forms/form-elements/checkbox", icon: "CheckSquareIcon", is_bookmarked: false},
|
||||
{title: "Radio Form Element", url: "/forms/form-elements/radio", icon: "DiscIcon", is_bookmarked: false},
|
||||
{title: "Input Form Element", url: "/forms/form-elements/input", icon: "TypeIcon", is_bookmarked: false},
|
||||
{title: "Number Input Form Element", url: "/forms/form-elements/number-input", icon: "TypeIcon", is_bookmarked: false},
|
||||
{title: "Textarea Form Element", url: "/forms/form-elements/textarea", icon: "TypeIcon", is_bookmarked: false},
|
||||
{title: "Form Layouts", url: "/forms/form-layouts", icon: "LayoutIcon", is_bookmarked: false},
|
||||
{title: "Form Wizard", url: "/forms/form-wizard", icon: "GitCommitIcon", is_bookmarked: false},
|
||||
{title: "Form Validation", url: "/forms/form-validation", icon: "CheckSquareIcon", is_bookmarked: false},
|
||||
{title: "Form Input Group", url: "/forms/form-input-group", icon: "MenuIcon", is_bookmarked: false},
|
||||
|
||||
// PAGES
|
||||
{title: "Login Page", url: "/pages/login", icon: "LockIcon", is_bookmarked: false},
|
||||
{title: "Register Page", url: "/pages/register", icon: "UserPlusIcon", is_bookmarked: false},
|
||||
{title: "Forgot Password Page", url: "/pages/forgot-password", icon: "HelpCircleIcon", is_bookmarked: false},
|
||||
{title: "Reset Password Page", url: "/pages/reset-password", icon: "UnlockIcon", is_bookmarked: false},
|
||||
{title: "Lock Screen Page", url: "/pages/lock-screen", icon: "LockIcon", is_bookmarked: false},
|
||||
{title: "Coming Soon Page", url: "/pages/comingsoon", icon: "ClockIcon", is_bookmarked: false},
|
||||
{title: "404 Page", url: "/pages/error-404", icon: "MonitorIcon", is_bookmarked: false},
|
||||
{title: "500 Page", url: "/pages/error-500", icon: "MonitorIcon", is_bookmarked: false},
|
||||
{title: "Not Authorized Page", url: "/pages/not-authorized", icon: "XCircleIcon", is_bookmarked: false},
|
||||
{title: "Maintenance Page", url: "/pages/maintenance", icon: "MonitorIcon", is_bookmarked: false},
|
||||
{title: "Profile Page", url: "/pages/profile", icon: "UserIcon", is_bookmarked: false},
|
||||
{title: "User Settings", url: "/pages/user-settings", icon: "SettingsIcon", is_bookmarked: false},
|
||||
{title: "FAQ Page", url: "/pages/faq", icon: "HelpCircleIcon", is_bookmarked: false},
|
||||
{title: "KnowledgeBase Page", url: "/pages/knowledge-base", icon: "BookIcon", is_bookmarked: false},
|
||||
{title: "Search Page", url: "/pages/search", icon: "SearchIcon", is_bookmarked: false},
|
||||
{title: "Invoice Page", url: "/pages/invoice", icon: "FileIcon", is_bookmarked: false},
|
||||
|
||||
// CHARTS & MAPS
|
||||
{title: "Apex Charts", url: "/charts-and-maps/charts/apex-charts", icon: "PieChartIcon", is_bookmarked: false},
|
||||
{title: "chartjs", url: "/charts-and-maps/charts/chartjs", icon: "PieChartIcon", is_bookmarked: false},
|
||||
{title: "echarts", url: "/charts-and-maps/charts/echarts", icon: "PieChartIcon", is_bookmarked: false},
|
||||
{title: "Google Map", url: "/charts-and-maps/maps/google-map", icon: "MapIcon", is_bookmarked: false},
|
||||
|
||||
// EXTENSIONS
|
||||
{title: "Select Extension", url: "/extensions/select", icon: "CheckIcon", is_bookmarked: false},
|
||||
{title: "Quill Editor", url: "/extensions/quill-editor", icon: "EditIcon", is_bookmarked: false},
|
||||
{title: "Drag & Drop", url: "/extensions/drag-and-drop", icon: "CopyIcon", is_bookmarked: false},
|
||||
{title: "Datepicker", url: "/extensions/datepicker", icon: "CalendarIcon", is_bookmarked: false},
|
||||
{title: "Datetime Picker", url: "/extensions/datetime-picker", icon: "ClockIcon", is_bookmarked: false},
|
||||
{title: "Access Control", url: "/extensions/access-control", icon: "LockIcon", is_bookmarked: false},
|
||||
{title: "I18n", url: "/extensions/i18n", icon: "GlobeIcon", is_bookmarked: false},
|
||||
{title: "Carousel", url: "/extensions/carousel", icon: "LayersIcon", is_bookmarked: false},
|
||||
{title: "Clipboard", url: "/extensions/clipboard", icon: "CopyIcon", is_bookmarked: false},
|
||||
{title: "Context Menu", url: "/extensions/context-menu", icon: "MoreHorizontalIcon", is_bookmarked: false},
|
||||
{title: "Star Rating", url: "/extensions/star-ratings", icon: "StarIcon", is_bookmarked: false},
|
||||
{title: "Autocomplete", url: "/extensions/autocomplete", icon: "Edit3Icon", is_bookmarked: false},
|
||||
{title: "Tree", url: "/extensions/tree", icon: "GitPullRequestIcon", is_bookmarked: false},
|
||||
{title: "Import", url: "/import-export/import", icon: "FileTextIcon", is_bookmarked: false},
|
||||
{title: "Export", url: "/import-export/export", icon: "ExternalLinkIcon", is_bookmarked: false},
|
||||
{title: "Export Selected", url: "/import-export/export-selected", icon: "ExternalLinkIcon", is_bookmarked: false},
|
||||
]
|
||||
},
|
||||
files: {
|
||||
key:"file_name",
|
||||
data: [
|
||||
{ file_name: "Joe's CV", from:"Stacy Watson", file_ext:"doc", size:"1.7 mb" },
|
||||
{ file_name: "Passport Image", from:"Ben Sinitiere", file_ext:"jpg", size:" 52 kb" },
|
||||
{ file_name: "Questions", from:"Charleen Patti", file_ext:"doc", size:"1.5 gb" },
|
||||
{ file_name: "Parenting Guide", from:"Doyle Blatteau", file_ext:"doc", size:"2.3 mb" },
|
||||
{ file_name: "Class Notes", from:"Gwen Greenlow", file_ext:"doc", size:" 30 kb" },
|
||||
{ file_name: "Class Attendance", from:"Tom Alred", file_ext:"xls", size:"52 mb" },
|
||||
{ file_name: "Company Salary", from:"Nellie Dezan", file_ext:"xls", size:"29 mb" },
|
||||
{ file_name: "Company Logo", from:"Steve Sheldon", file_ext:"jpg", size:"1.3 mb" },
|
||||
{ file_name: "Crime Rates", from:"Sherlock Holmes", file_ext:"xls", size:"37 kb" },
|
||||
{ file_name: "Ulysses", from:"Theresia Wrenne", file_ext:"pdf", size:"7.2 mb" },
|
||||
{ file_name: "War and Peace", from:"Goldie Highnote", file_ext:"pdf", size:"10.5 mb" },
|
||||
{ file_name: "Vedas", from:"Ajay Patel", file_ext:"pdf", size:"8.3 mb" },
|
||||
{ file_name: "The Trial", from:"Sirena Linkert", file_ext:"pdf", size:"1.5 mb" },
|
||||
]
|
||||
},
|
||||
contacts: {
|
||||
key:"name",
|
||||
data: [
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-4.jpg"), name: "Rena Brant", email: "nephrod@preany.co.uk", time: "21/05/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-2.jpg"), name: "Mariano Packard", email: "seek@sparaxis.org", time: "14/01/2018" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-24.jpg"), name: "Risa Montufar", email: "vagary@unblist.org", time: "10/08/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-15.jpg"), name: "Maragaret Cimo", email: "designed@insanely.net", time: "01/12/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-7.jpg"), name: "Jona Prattis", email: "unwieldable@unblist.org", time: "21/05/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-5.jpg"), name: "Edmond Chicon", email: "museist@anaphyte.co.uk", time: "15/11/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-25.jpg"), name: "Abbey Darden", email: "astema@defectively.co.uk", time: "07/05/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-10.jpg"), name: "Seema Moallankamp", email: "fernando@storkish.co.uk", time: "13/08/2017" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-2.jpg"), name: "Charleen Warmington", email: "furphy@cannibal.net", time: "11/08/1891" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-25.jpg"), name: "Geri Linch", email: "insignia@markab.org", time: "18/01/2015" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-23.jpg"), name: "Shellie Muster", email: "maxillary@equalize.co.uk", time: "26/07/2019" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-20.jpg"), name: "Jesenia Vanbramer", email: "hypotony@phonetist.net", time: "12/09/2017" },
|
||||
{ img: require("@/assets/images/portrait/small/avatar-s-23.jpg"), name: "Mardell Channey", email: "peseta@myrica.com", time: "11/11/2019" },
|
||||
]
|
||||
},
|
||||
}
|
||||
/* eslint-enable */
|
||||
@@ -0,0 +1,355 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: VerticalNavMenu.vue
|
||||
Description: Vertical NavMenu Component
|
||||
Component Name: VerticalNavMenu
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="parentx">
|
||||
|
||||
<vs-sidebar
|
||||
class="v-nav-menu items-no-padding"
|
||||
v-model="isVerticalNavMenuActive"
|
||||
ref="verticalNavMenu"
|
||||
default-index="-1"
|
||||
:click-not-close="clickNotClose"
|
||||
:reduce-not-rebound="reduceNotRebound"
|
||||
:parent="parent"
|
||||
:hiddenBackground="clickNotClose"
|
||||
:reduce="reduce"
|
||||
v-hammer:swipe="onMenuSwipe">
|
||||
|
||||
<div @mouseenter="mouseEnter" @mouseleave="mouseLeave">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="header-sidebar flex items-end justify-between" slot="header">
|
||||
|
||||
<!-- Logo -->
|
||||
<router-link tag="div" class="vx-logo cursor-pointer flex items-center" to="/">
|
||||
<img src="../../../../public/logo.svg" width="75px"/>
|
||||
<span class="vx-logo-text text-primary" v-show="isMouseEnter || !reduce" v-if="title">{{ title }}</span>
|
||||
</router-link>
|
||||
<!-- /Logo -->
|
||||
|
||||
<!-- Menu Buttons -->
|
||||
<div>
|
||||
<!-- Close Button -->
|
||||
<template v-if="showCloseButton">
|
||||
<feather-icon icon="XIcon" class="m-0 cursor-pointer" @click="$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', false)" />
|
||||
</template>
|
||||
|
||||
<!-- Toggle Buttons -->
|
||||
<template v-else-if="!showCloseButton && !verticalNavMenuItemsMin">
|
||||
<!-- <feather-icon-->
|
||||
<!-- id="btnVNavMenuMinToggler"-->
|
||||
<!-- class="mr-0 cursor-pointer"-->
|
||||
<!-- :icon="reduce ? 'CircleIcon' : 'DiscIcon'"-->
|
||||
<!-- svg-classes="stroke-current text-primary"-->
|
||||
<!-- @click="toggleReduce(!reduce)" />-->
|
||||
</template>
|
||||
</div>
|
||||
<!-- /Menu Toggle Buttons -->
|
||||
</div>
|
||||
<!-- /Header -->
|
||||
|
||||
<!-- Header Shadow -->
|
||||
<div class="shadow-bottom" v-show="showShadowBottom" />
|
||||
|
||||
<!-- Menu Items -->
|
||||
<component :is="scrollbarTag" ref="verticalNavMenuPs" class="scroll-area-v-nav-menu pt-2" :settings="settings" @ps-scroll-y="psSectionScroll" @scroll="psSectionScroll" :key="$vs.rtl">
|
||||
<template v-for="(item, index) in menuItemsUpdated">
|
||||
|
||||
<!-- Group Header -->
|
||||
<span v-if="item.header && !verticalNavMenuItemsMin" class="navigation-header truncate" :key="`header-${index}`">
|
||||
{{ $t(item.i18n) || item.header }}
|
||||
</span>
|
||||
<!-- /Group Header -->
|
||||
|
||||
<template v-else-if="!item.header">
|
||||
|
||||
<!-- Nav-Item -->
|
||||
<v-nav-menu-item
|
||||
v-if="!item.submenu"
|
||||
:key="`item-${index}`"
|
||||
:index="index"
|
||||
:to="item.slug !== 'external' ? item.url : null"
|
||||
:href="item.slug === 'external' ? item.url : null"
|
||||
:icon="item.icon" :target="item.target"
|
||||
:isDisabled="item.isDisabled"
|
||||
:slug="item.slug">
|
||||
<span v-show="!verticalNavMenuItemsMin" class="truncate">{{ $t(item.i18n) || item.name }}</span>
|
||||
<vs-chip class="ml-auto" :color="item.tagColor" v-if="item.tag && (isMouseEnter || !reduce)">{{ item.tag }}</vs-chip>
|
||||
</v-nav-menu-item>
|
||||
|
||||
<!-- Nav-Group -->
|
||||
<template v-else>
|
||||
<v-nav-menu-group
|
||||
:key="`group-${index}`"
|
||||
:openHover="openGroupHover"
|
||||
:group="item"
|
||||
:groupIndex="index"
|
||||
:open="isGroupActive(item)" />
|
||||
</template>
|
||||
<!-- /Nav-Group -->
|
||||
</template>
|
||||
</template>
|
||||
</component>
|
||||
<!-- /Menu Items -->
|
||||
</div>
|
||||
</vs-sidebar>
|
||||
|
||||
<!-- Swipe Gesture -->
|
||||
<div
|
||||
v-if="!isVerticalNavMenuActive"
|
||||
class="v-nav-menu-swipe-area"
|
||||
v-hammer:swipe="onSwipeAreaSwipe" />
|
||||
<!-- /Swipe Gesture -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import VuePerfectScrollbar from 'vue-perfect-scrollbar'
|
||||
import VNavMenuGroup from './VerticalNavMenuGroup.vue'
|
||||
import VNavMenuItem from './VerticalNavMenuItem.vue'
|
||||
|
||||
import Logo from '../Logo.vue'
|
||||
|
||||
export default {
|
||||
name: 'v-nav-menu',
|
||||
components: {
|
||||
VNavMenuGroup,
|
||||
VNavMenuItem,
|
||||
VuePerfectScrollbar,
|
||||
Logo
|
||||
},
|
||||
props: {
|
||||
logo: { type: String },
|
||||
openGroupHover: { type: Boolean, default: false },
|
||||
parent: { type: String },
|
||||
reduceNotRebound: { type: Boolean, default: true },
|
||||
navMenuItems: { type: Array, required: true },
|
||||
title: { type: String }
|
||||
},
|
||||
data: () => ({
|
||||
clickNotClose : false, // disable close navMenu on outside click
|
||||
isMouseEnter : false,
|
||||
reduce : false, // determines if navMenu is reduce - component property
|
||||
showCloseButton : false, // show close button in smaller devices
|
||||
settings : { // perfectScrollbar settings
|
||||
maxScrollbarLength: 60,
|
||||
wheelSpeed : 1,
|
||||
swipeEasing : true
|
||||
},
|
||||
showShadowBottom : false
|
||||
}),
|
||||
computed: {
|
||||
isGroupActive () {
|
||||
return (item) => {
|
||||
const path = this.$route.fullPath
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
let open = false
|
||||
|
||||
const func = (item) => {
|
||||
if (item.submenu) {
|
||||
item.submenu.forEach((item) => {
|
||||
if (item.url && (path === item.url || routeParent === item.slug)) { open = true } else if (item.submenu) { func(item) }
|
||||
})
|
||||
}
|
||||
}
|
||||
func(item)
|
||||
return open
|
||||
}
|
||||
},
|
||||
menuItemsUpdated () {
|
||||
const clone = this.navMenuItems.slice()
|
||||
|
||||
for (const [index, item] of this.navMenuItems.entries()) {
|
||||
if (item.header && item.items.length && (index || 1)) {
|
||||
const i = clone.findIndex(ix => ix.header === item.header)
|
||||
for (const [subIndex, subItem] of item.items.entries()) {
|
||||
clone.splice(i + 1 + subIndex, 0, subItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(clone
|
||||
)
|
||||
|
||||
return clone
|
||||
},
|
||||
isVerticalNavMenuActive: {
|
||||
get () { return this.$store.state.isVerticalNavMenuActive },
|
||||
set (val) { this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', val) }
|
||||
},
|
||||
layoutType () { return this.$store.state.mainLayoutType },
|
||||
reduceButton: {
|
||||
get () { return this.$store.state.reduceButton },
|
||||
set (val) { this.$store.commit('TOGGLE_REDUCE_BUTTON', val) }
|
||||
},
|
||||
isVerticalNavMenuReduced () { return Boolean(this.reduce && this.reduceButton) },
|
||||
verticalNavMenuItemsMin () { return this.$store.state.verticalNavMenuItemsMin },
|
||||
scrollbarTag () { return this.$store.getters.scrollbarTag },
|
||||
windowWidth () { return this.$store.state.windowWidth }
|
||||
},
|
||||
watch: {
|
||||
'$route' () {
|
||||
if (this.isVerticalNavMenuActive && this.showCloseButton) this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', false)
|
||||
},
|
||||
reduce (val) {
|
||||
const verticalNavMenuWidth = val ? 'reduced' : this.$store.state.windowWidth < 1200 ? 'no-nav-menu' : 'default'
|
||||
this.$store.dispatch('updateVerticalNavMenuWidth', verticalNavMenuWidth)
|
||||
|
||||
setTimeout(function () {
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
}, 100)
|
||||
},
|
||||
layoutType () { this.setVerticalNavMenuWidth() },
|
||||
reduceButton () { this.setVerticalNavMenuWidth() },
|
||||
windowWidth () { this.setVerticalNavMenuWidth() }
|
||||
},
|
||||
methods: {
|
||||
onMenuSwipe (event) {
|
||||
if (event.direction === 4 && this.$vs.rtl) {
|
||||
|
||||
// Swipe Right
|
||||
if (this.isVerticalNavMenuActive && this.showCloseButton) this.isVerticalNavMenuActive = false
|
||||
|
||||
} else if (event.direction === 2 && !this.$vs.rtl) {
|
||||
|
||||
// Swipe Left
|
||||
if (this.isVerticalNavMenuActive && this.showCloseButton) this.isVerticalNavMenuActive = false
|
||||
}
|
||||
},
|
||||
onSwipeAreaSwipe (event) {
|
||||
|
||||
if (event.direction === 4 && !this.$vs.rtl) {
|
||||
|
||||
// Swipe Right
|
||||
if (!this.isVerticalNavMenuActive && this.showCloseButton) this.isVerticalNavMenuActive = true
|
||||
} else if (event.direction === 2 && this.$vs.rtl) {
|
||||
|
||||
// Swipe Left
|
||||
if (!this.isVerticalNavMenuActive && this.showCloseButton) this.isVerticalNavMenuActive = true
|
||||
}
|
||||
},
|
||||
psSectionScroll () {
|
||||
const scroll_el = this.$refs.verticalNavMenuPs.$el || this.$refs.verticalNavMenuPs
|
||||
this.showShadowBottom = scroll_el.scrollTop > 0
|
||||
},
|
||||
mouseEnter () {
|
||||
if (this.reduce) this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', false)
|
||||
this.isMouseEnter = true
|
||||
},
|
||||
mouseLeave () {
|
||||
if (this.reduce) this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', true)
|
||||
this.isMouseEnter = false
|
||||
},
|
||||
setVerticalNavMenuWidth () {
|
||||
|
||||
if (this.windowWidth > 1200) {
|
||||
if (this.layoutType === 'vertical') {
|
||||
|
||||
// Set reduce
|
||||
this.reduce = !!this.reduceButton
|
||||
|
||||
// Open NavMenu
|
||||
this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', true)
|
||||
|
||||
// Set Menu Items Only Icon Mode
|
||||
const verticalNavMenuItemsMin = !!(this.reduceButton && !this.isMouseEnter)
|
||||
this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', verticalNavMenuItemsMin)
|
||||
|
||||
// Menu Action buttons
|
||||
this.clickNotClose = true
|
||||
this.showCloseButton = false
|
||||
|
||||
const verticalNavMenuWidth = this.isVerticalNavMenuReduced ? 'reduced' : 'default'
|
||||
this.$store.dispatch('updateVerticalNavMenuWidth', verticalNavMenuWidth)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Close NavMenu
|
||||
this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', false)
|
||||
|
||||
// Reduce button
|
||||
if (this.reduceButton) this.reduce = false
|
||||
|
||||
// Menu Action buttons
|
||||
this.showCloseButton = true
|
||||
this.clickNotClose = false
|
||||
|
||||
// Update NavMenu Width
|
||||
this.$store.dispatch('updateVerticalNavMenuWidth', 'no-nav-menu')
|
||||
|
||||
// Remove Only Icon in Menu
|
||||
this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', false)
|
||||
|
||||
|
||||
// if(this.layoutType === 'vertical' || (this.layoutType === 'horizontal' && this.windowWidth < 1200))
|
||||
// if (this.windowWidth < 1200) {
|
||||
|
||||
// // Close NavMenu
|
||||
// this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', false)
|
||||
|
||||
// // Reduce button
|
||||
// if (this.reduceButton) this.reduce = false
|
||||
|
||||
// // Menu Action buttons
|
||||
// this.showCloseButton = true
|
||||
// this.clickNotClose = false
|
||||
|
||||
// // Update NavMenu Width
|
||||
// this.$store.dispatch('updateVerticalNavMenuWidth', 'no-nav-menu')
|
||||
|
||||
// // Remove Only Icon in Menu
|
||||
// this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', false)
|
||||
|
||||
// } else {
|
||||
|
||||
// // Set reduce
|
||||
// this.reduce = this.reduceButton ? true : false
|
||||
|
||||
// // Open NavMenu
|
||||
// this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', true)
|
||||
|
||||
// // Set Menu Items Only Icon Mode
|
||||
// const verticalNavMenuItemsMin = (this.reduceButton && !this.isMouseEnter) ? true : false
|
||||
// this.$store.commit('UPDATE_VERTICAL_NAV_MENU_ITEMS_MIN', verticalNavMenuItemsMin)
|
||||
|
||||
// // Menu Action buttons
|
||||
// this.clickNotClose = true
|
||||
// this.showCloseButton = false
|
||||
|
||||
// const verticalNavMenuWidth = this.isVerticalNavMenuReduced ? "reduced" : "default"
|
||||
// this.$store.dispatch('updateVerticalNavMenuWidth', verticalNavMenuWidth)
|
||||
// }
|
||||
},
|
||||
toggleReduce (val) {
|
||||
this.reduceButton = val
|
||||
this.setVerticalNavMenuWidth()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.setVerticalNavMenuWidth()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/verticalNavMenu.scss";
|
||||
|
||||
.cursor-pointer.navbar-fuzzy-search.mr-8.feather-icon.select-none.relative{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,239 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: VerticalNavMenuGroup.vue
|
||||
Description: Vertical NavMenu Group Component. Extends vuesax framework's 'vs-sidebar-group' component
|
||||
Component Name: VerticalNavMenuGroup
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div
|
||||
class = "vs-sidebar-group"
|
||||
:class = "[
|
||||
{'vs-sidebar-group-open' : openItems },
|
||||
{'vs-sidebar-group-active' : open },
|
||||
{'disabled-item pointer-events-none': group.isDisabled }
|
||||
]"
|
||||
@mouseover = "mouseover"
|
||||
@mouseout = "mouseout">
|
||||
|
||||
<!-- Group Label -->
|
||||
<div @click="clickGroup" class="group-header w-full">
|
||||
<span class="flex items-center w-full">
|
||||
|
||||
<!-- Group Icon -->
|
||||
<feather-icon
|
||||
v-if = "group.icon || (this.groupIndex > Math.floor(this.groupIndex))"
|
||||
:icon = "group.icon || 'CircleIcon'"
|
||||
:svgClasses = "{ 'w-3 h-3' : this.groupIndex % 1 != 0 }" />
|
||||
|
||||
<!-- Group Name -->
|
||||
<span v-show="!verticalNavMenuItemsMin" class="truncate mr-3 select-none">{{ $t(group.i18n) || group.name }}</span>
|
||||
|
||||
<!-- Group Tag -->
|
||||
<vs-chip class="ml-auto mr-4" :color="group.tagColor" v-if="group.tag && !verticalNavMenuItemsMin">{{ group.tag }}</vs-chip>
|
||||
</span>
|
||||
|
||||
<!-- Group Collapse Icon -->
|
||||
<feather-icon
|
||||
v-show = "!verticalNavMenuItemsMin"
|
||||
:class = "[{'rotate90' : openItems}, 'feather-grp-header-arrow']"
|
||||
:icon = "$vs.rtl ? 'ChevronLeftIcon' : 'ChevronRightIcon'"
|
||||
svg-classes= "w-4 h-4" />
|
||||
|
||||
<!-- Group Tooltip -->
|
||||
<span class="vs-sidebar--tooltip">{{ $t(group.i18n) || group.name }}</span>
|
||||
</div>
|
||||
<!-- /Group Label -->
|
||||
|
||||
<!-- Group Items -->
|
||||
<ul ref="items" :style="styleItems" class="vs-sidebar-group-items">
|
||||
<li v-for="(groupItem, index) in group.submenu" :key="index">
|
||||
|
||||
<!-- If item is group -->
|
||||
<v-nav-menu-group
|
||||
v-if = "groupItem.submenu"
|
||||
:group = "groupItem"
|
||||
:groupIndex = "Number(`${groupIndex}.${index+1}`)"
|
||||
:open = "isGroupActive(groupItem)"
|
||||
:openHover = "openHover" />
|
||||
|
||||
<!-- Else: Item -->
|
||||
<v-nav-menu-item
|
||||
v-else
|
||||
icon-small
|
||||
:index = "groupIndex + '.' + index"
|
||||
:to="groupItem.slug !== 'external' ? groupItem.url : null"
|
||||
:href="groupItem.slug === 'external' ? groupItem.url : null"
|
||||
:icon = "itemIcon(groupIndex + '.' + index)"
|
||||
:slug = "groupItem.slug"
|
||||
:target = "groupItem.target">
|
||||
<span class="truncate">{{ $t(groupItem.i18n) || groupItem.name }}</span>
|
||||
<vs-chip class="ml-auto" :color="groupItem.tagColor" v-if="groupItem.tag">{{ groupItem.tag }}</vs-chip>
|
||||
</v-nav-menu-item>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /Group Items -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import VNavMenuItem from './VerticalNavMenuItem.vue'
|
||||
|
||||
export default {
|
||||
name : 'v-nav-menu-group',
|
||||
props : {
|
||||
openHover : { type: Boolean, default: false },
|
||||
open : { type: Boolean, default: false },
|
||||
group : { type: Object },
|
||||
groupIndex : { type: Number }
|
||||
},
|
||||
components: {
|
||||
VNavMenuItem
|
||||
},
|
||||
data: () => ({
|
||||
maxHeight : '0px',
|
||||
openItems : false
|
||||
}),
|
||||
computed: {
|
||||
verticalNavMenuItemsMin () { return this.$store.state.verticalNavMenuItemsMin },
|
||||
styleItems () {
|
||||
return { maxHeight: this.maxHeight }
|
||||
},
|
||||
itemIcon () {
|
||||
return (index) => {
|
||||
if (!((index.match(/\./g) || []).length > 1)) return 'CircleIcon'
|
||||
}
|
||||
},
|
||||
isGroupActive () {
|
||||
return (item) => {
|
||||
const path = this.$route.fullPath
|
||||
let open = false
|
||||
const routeParent = this.$route.meta ? this.$route.meta.parent : undefined
|
||||
|
||||
const func = (item) => {
|
||||
if (item.submenu) {
|
||||
item.submenu.forEach((item) => {
|
||||
if ((path === item.url || routeParent === item.slug) && item.url) { open = true } else if (item.submenu) { func(item) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func(item)
|
||||
return open
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// OPEN & CLOSES DROPDOWN ON ROUTE CHANGE
|
||||
'$route' () {
|
||||
if (this.verticalNavMenuItemsMin) return
|
||||
|
||||
const scrollHeight = this.scrollHeight
|
||||
|
||||
// Collapse Group
|
||||
if (this.openItems && !this.open) {
|
||||
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = `${0}px`
|
||||
}, 50)
|
||||
|
||||
// Expand Group
|
||||
} else if (this.open) {
|
||||
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = 'none'
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
maxHeight () {
|
||||
this.openItems = this.maxHeight !== '0px'
|
||||
},
|
||||
// OPEN AND CLOSES DROPDOWN MENU ON NavMenu COLLAPSE AND DEFAULT VIEW
|
||||
'$store.state.verticalNavMenuItemsMin' (val) {
|
||||
const scrollHeight = this.$refs.items.scrollHeight
|
||||
|
||||
if (!val && this.open) {
|
||||
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = 'none'
|
||||
}, 300)
|
||||
} else {
|
||||
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = '0px'
|
||||
}, 50)
|
||||
}
|
||||
if (val && this.open) {
|
||||
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = '0px'
|
||||
}, 250)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickGroup () {
|
||||
if (!this.openHover) {
|
||||
|
||||
const thisScrollHeight = this.$refs.items.scrollHeight
|
||||
|
||||
if (this.maxHeight === '0px') {
|
||||
this.maxHeight = `${thisScrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = 'none'
|
||||
}, 300)
|
||||
|
||||
} else {
|
||||
this.maxHeight = `${thisScrollHeight}px`
|
||||
setTimeout(() => {
|
||||
this.maxHeight = `${0}px`
|
||||
}, 50)
|
||||
}
|
||||
|
||||
this.$parent.$children.map((child) => {
|
||||
if (child.isGroupActive) {
|
||||
if (child !== this && !child.open && child.maxHeight !== '0px') {
|
||||
setTimeout(() => {
|
||||
child.maxHeight = `${0}px`
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mouseover () {
|
||||
if (this.openHover) {
|
||||
const scrollHeight = this.$refs.items.scrollHeight
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
}
|
||||
},
|
||||
mouseout () {
|
||||
if (this.openHover) {
|
||||
const scrollHeight = 0
|
||||
this.maxHeight = `${scrollHeight}px`
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.openItems = this.open
|
||||
if (this.open) { this.maxHeight = 'none' }
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/scss/vuexy/components/verticalNavMenuGroup.scss"
|
||||
</style>
|
||||
@@ -0,0 +1,67 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: VerticalNavMenuItem.vue
|
||||
Description: Vertical NavMenu item component. Extends vuesax framework's 'vs-sidebar-item' component
|
||||
Component Name: VerticalNavMenuItem
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="canSee"
|
||||
class="vs-sidebar--item"
|
||||
:class="[
|
||||
{'vs-sidebar-item-active' : activeLink},
|
||||
{'disabled-item pointer-events-none' : isDisabled}
|
||||
]" >
|
||||
|
||||
<router-link
|
||||
tabindex="-1"
|
||||
v-if="to"
|
||||
exact
|
||||
:class="[{'router-link-active': activeLink}]"
|
||||
:to="to"
|
||||
:target="target" >
|
||||
<vs-icon v-if="!featherIcon" :icon-pack="iconPack" :icon="icon" />
|
||||
<feather-icon v-else :class="{'w-3 h-3': iconSmall}" :icon="icon" />
|
||||
<slot />
|
||||
</router-link>
|
||||
|
||||
<a v-else :target="target" :href="href" tabindex="-1">
|
||||
<vs-icon v-if="!featherIcon" :icon-pack="iconPack" :icon="icon" />
|
||||
<feather-icon v-else :class="{'w-3 h-3': iconSmall}" :icon="icon" />
|
||||
<slot />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'v-nav-menu-item',
|
||||
props: {
|
||||
icon : { type: String, default: '' },
|
||||
iconSmall : { type: Boolean, default: false },
|
||||
iconPack : { type: String, default: 'material-icons' },
|
||||
href : { type: [String, null], default: '#' },
|
||||
to : { type: [String, Object, null], default: null },
|
||||
slug : { type: String, default: null },
|
||||
index : { type: [String, Number], default: null },
|
||||
featherIcon : { type: Boolean, default: true },
|
||||
target : { type: String, default: '_self' },
|
||||
isDisabled : { type: Boolean, default: false }
|
||||
},
|
||||
computed: {
|
||||
canSee () {
|
||||
this.$acl.check(this.$store.state.AppActiveUser.userRole)
|
||||
return this.to ? this.$acl.check(this.$router.match(this.to).meta.rule) : true
|
||||
},
|
||||
activeLink () {
|
||||
return !!((this.to === this.$route.path || this.$route.meta.parent === this.slug) && this.to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/dashboard',
|
||||
name: 'داشبرد',
|
||||
icon: 'HomeIcon',
|
||||
i18n: 'داشبرد',
|
||||
slug: "config",
|
||||
},
|
||||
{
|
||||
url: '/config',
|
||||
icon: 'LayersIcon',
|
||||
i18n: 'پیکر بندی',
|
||||
slug: 'config',
|
||||
},
|
||||
{
|
||||
url: "/proposal",
|
||||
name: "proposal",
|
||||
slug: "proposal",
|
||||
icon: "AlignJustifyIcon",
|
||||
i18n: "درخواست ها",
|
||||
},
|
||||
{
|
||||
url: "/personel",
|
||||
name: "personel",
|
||||
slug: "personel",
|
||||
icon: "AlignJustifyIcon",
|
||||
i18n: "اطلاعات پرسنلی",
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div
|
||||
ref="convstooltip"
|
||||
class="con-vs-tooltip"
|
||||
@mouseleave="mouseleavex"
|
||||
@mouseenter="mouseenterx"
|
||||
@mouseup="destroy" >
|
||||
<transition name="tooltip-fade">
|
||||
<div
|
||||
v-show="active"
|
||||
ref="vstooltip"
|
||||
:class="[`vs-tooltip-${positionx || position}`,`vs-tooltip-${color}`, {'after-none': noneAfter}]"
|
||||
:style="style"
|
||||
class="vs-tooltip">
|
||||
<h4 v-if="title">{{ title }}</h4>
|
||||
{{ text }}
|
||||
</div>
|
||||
</transition>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import utils from '@/assets/utils'
|
||||
import _color from '@/assets/utils/color.js'
|
||||
export default {
|
||||
name:'vx-tooltip',
|
||||
props:{
|
||||
title:{
|
||||
default:null,
|
||||
type:[String, Number]
|
||||
},
|
||||
text:{
|
||||
default:null,
|
||||
type:[String, Number]
|
||||
},
|
||||
color:{
|
||||
default:null,
|
||||
type:String
|
||||
},
|
||||
position:{
|
||||
default:'top',
|
||||
type:String
|
||||
},
|
||||
delay:{
|
||||
default:'0s',
|
||||
type:[Number, String]
|
||||
}
|
||||
},
|
||||
data:() => ({
|
||||
cords:{},
|
||||
active:false,
|
||||
widthx: 'auto',
|
||||
positionx: null,
|
||||
noneAfter: false
|
||||
}),
|
||||
computed:{
|
||||
style () {
|
||||
return {
|
||||
left:this.cords.left,
|
||||
top:this.cords.top,
|
||||
transitionDelay: this.active ? this.delay : '0s',
|
||||
background:_color.getColor(this.color, 1),
|
||||
width: this.widthx
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
mouseenterx () {
|
||||
this.active = true
|
||||
this.$nextTick(() => {
|
||||
utils.insertBody(this.$refs.vstooltip)
|
||||
this.changePosition(this.$refs.convstooltip, this.$refs.vstooltip)
|
||||
})
|
||||
},
|
||||
mouseleavex () {
|
||||
this.active = false
|
||||
},
|
||||
changePosition (elxEvent, tooltip) {
|
||||
this.noneAfter = false
|
||||
this.positionx = null
|
||||
const elx = elxEvent.closest('.con-vs-tooltip')
|
||||
const scrollTopx = window.pageYOffset || document.documentElement.scrollTop
|
||||
let topx = elx.getBoundingClientRect().top + scrollTopx - tooltip.clientHeight - 4
|
||||
let leftx = elx.getBoundingClientRect().left - tooltip.clientWidth / 2 + elx.clientWidth / 2
|
||||
const widthx = elx.clientWidth
|
||||
|
||||
if (this.position == 'bottom') {
|
||||
topx = elx.getBoundingClientRect().top + scrollTopx + elx.clientHeight + 4
|
||||
} else if (this.position == 'left') {
|
||||
leftx = elx.getBoundingClientRect().left - tooltip.clientWidth - 4
|
||||
topx = elx.getBoundingClientRect().top + scrollTopx + elx.clientHeight / 2 - tooltip.clientHeight / 2
|
||||
if (Math.sign(leftx) == -1) {
|
||||
leftx = elx.getBoundingClientRect().left
|
||||
topx = elx.getBoundingClientRect().top + scrollTopx + elx.clientHeight + 4
|
||||
this.positionx = 'bottom'
|
||||
this.noneAfter = true
|
||||
}
|
||||
} else if (this.position == 'right') {
|
||||
leftx = elx.getBoundingClientRect().left + elx.clientWidth + 4
|
||||
topx = elx.getBoundingClientRect().top + scrollTopx + elx.clientHeight / 2 - tooltip.clientHeight / 2
|
||||
if (window.innerWidth - (leftx + tooltip.clientWidth) <= 20) {
|
||||
leftx = elx.getBoundingClientRect().left - tooltip.clientWidth / 2 - 10
|
||||
topx = elx.getBoundingClientRect().top + scrollTopx + elx.clientHeight + 4
|
||||
this.positionx = 'bottom'
|
||||
this.noneAfter = true
|
||||
}
|
||||
}
|
||||
this.cords = {
|
||||
left: `${leftx}px`,
|
||||
top: `${topx}px`,
|
||||
width: `${widthx}px`
|
||||
}
|
||||
},
|
||||
destroy () {
|
||||
this.active = false
|
||||
this.$nextTick(() => {
|
||||
if (this.active) {
|
||||
utils.removeBody(this.$refs.vstooltip)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!-- =========================================================================================
|
||||
File Name: FullPage.vue
|
||||
Description: Full page layout
|
||||
----------------------------------------------------------------------------------------
|
||||
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
|
||||
Author: Pixinvent
|
||||
Author URL: http://www.themeforest.net/user/pixinvent
|
||||
========================================================================================== -->
|
||||
|
||||
|
||||
<template>
|
||||
<div class="layout--full-page">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,265 @@
|
||||
|
||||
<template>
|
||||
<div class="layout--main" :class="[layoutTypeClass, navbarClasses, footerClasses, {'no-scroll': isAppPage}]">
|
||||
|
||||
<vx-tour :steps="steps" v-if="!disableThemeTour && (windowWidth >= 1200 && mainLayoutType === 'vertical' && verticalNavMenuWidth == 'default')" />
|
||||
|
||||
<v-nav-menu
|
||||
:navMenuItems = "navMenuItems"
|
||||
title = ""
|
||||
parent = ".layout--main" />
|
||||
|
||||
<div id="content-area" :class="[contentAreaClass, {'show-overlay': bodyOverlay}]">
|
||||
<div id="content-overlay" />
|
||||
|
||||
<!-- Navbar -->
|
||||
<template v-if="mainLayoutType === 'horizontal' && windowWidth >= 1200">
|
||||
<the-navbar-horizontal
|
||||
:navbarType= "navbarType"
|
||||
:class="[
|
||||
{'text-white' : isNavbarDark && !isThemeDark},
|
||||
{'text-base' : !isNavbarDark && isThemeDark}
|
||||
]" />
|
||||
|
||||
<div style="height: 62px" v-if="navbarType === 'static'"></div>
|
||||
|
||||
<h-nav-menu
|
||||
:class="[
|
||||
{'text-white' : isNavbarDark && !isThemeDark},
|
||||
{'text-base' : !isNavbarDark && isThemeDark}
|
||||
]"
|
||||
:navMenuItems="navMenuItems" />
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<the-navbar-vertical
|
||||
:navbarColor="navbarColor"
|
||||
:class="[
|
||||
{'text-white' : isNavbarDark && !isThemeDark},
|
||||
{'text-base' : !isNavbarDark && isThemeDark}
|
||||
]" />
|
||||
</template>
|
||||
<!-- /Navbar -->
|
||||
|
||||
<div class="content-wrapper">
|
||||
|
||||
<div class="router-view">
|
||||
<div class="router-content">
|
||||
|
||||
<transition :name="routerTransition">
|
||||
|
||||
<div v-if="$route.meta.breadcrumb || $route.meta.pageTitle" class="router-header flex flex-wrap items-center mb-6">
|
||||
<div
|
||||
class="content-area__heading"
|
||||
:class="{'pr-4 border-0 md:border-r border-solid border-grey-light' : $route.meta.breadcrumb}">
|
||||
<h2 class="mb-1">{{ routeTitle }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- BREADCRUMB -->
|
||||
<vx-breadcrumb class="ml-4 md:block hidden" v-if="$route.meta.breadcrumb" :route="$route" :isRTL="$vs.rtl" />
|
||||
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<div class="content-area__content">
|
||||
|
||||
<back-to-top bottom="5%" :right="$vs.rtl ? 'calc(100% - 2.2rem - 38px)' : '30px'" visibleoffset="500" v-if="!hideScrollToTop">
|
||||
<vs-button icon-pack="feather" icon="icon-arrow-up" class="shadow-lg btn-back-to-top" />
|
||||
</back-to-top>
|
||||
|
||||
<transition :name="routerTransition" mode="out-in">
|
||||
<router-view @changeRouteTitle="changeRouteTitle" @setAppClasses="(classesStr) => $emit('setAppClasses', classesStr)" />
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<the-footer />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import BackToTop from 'vue-backtotop'
|
||||
import HNavMenu from '@/layouts/components/horizontal-nav-menu/HorizontalNavMenu.vue'
|
||||
import navMenuItems from '@/layouts/components/vertical-nav-menu/navMenuItems.js'
|
||||
import TheCustomizer from '@/layouts/components/customizer/TheCustomizer.vue'
|
||||
import TheNavbarHorizontal from '@/layouts/components/navbar/TheNavbarHorizontal.vue'
|
||||
import TheNavbarVertical from '@/layouts/components/navbar/TheNavbarVertical.vue'
|
||||
import TheFooter from '@/layouts/components/TheFooter.vue'
|
||||
import themeConfig from '@/../themeConfig.js'
|
||||
import VNavMenu from '@/layouts/components/vertical-nav-menu/VerticalNavMenu.vue'
|
||||
|
||||
const VxTour = () => import('@/components/VxTour.vue')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BackToTop,
|
||||
HNavMenu,
|
||||
TheCustomizer,
|
||||
TheFooter,
|
||||
TheNavbarHorizontal,
|
||||
TheNavbarVertical,
|
||||
VNavMenu,
|
||||
VxTour
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
disableCustomizer : themeConfig.disableCustomizer,
|
||||
disableThemeTour : themeConfig.disableThemeTour,
|
||||
dynamicWatchers : {},
|
||||
footerType : themeConfig.footerType || 'static',
|
||||
hideScrollToTop : themeConfig.hideScrollToTop,
|
||||
isNavbarDark : false,
|
||||
navbarColor : themeConfig.navbarColor || '#fff',
|
||||
navbarType : themeConfig.navbarType || 'floating',
|
||||
navMenuItems,
|
||||
routerTransition : themeConfig.routerTransition || 'none',
|
||||
routeTitle : this.$route.meta.pageTitle,
|
||||
steps: [
|
||||
{
|
||||
target : '#btnVNavMenuMinToggler',
|
||||
content : 'Toggle Collapse Sidebar.'
|
||||
},
|
||||
{
|
||||
target : '.vx-navbar__starred-pages',
|
||||
content : 'Create your own bookmarks. You can also re-arrange them using drag & drop.'
|
||||
},
|
||||
{
|
||||
target : '.i18n-locale',
|
||||
content : 'You can change language from here.'
|
||||
},
|
||||
{
|
||||
target : '.navbar-fuzzy-search',
|
||||
content : 'Try fuzzy search to visit pages in flash.'
|
||||
},
|
||||
{
|
||||
target : '.customizer-btn',
|
||||
content : 'Customize template based on your preference',
|
||||
params : {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target : '.vs-button.buy-now',
|
||||
content : 'Buy this awesomeness at affordable price!',
|
||||
params : {
|
||||
placement: 'top'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route' () {
|
||||
this.routeTitle = this.$route.meta.pageTitle
|
||||
},
|
||||
isThemeDark (val) {
|
||||
const color = this.navbarColor === '#fff' && val ? '#10163a' : '#fff'
|
||||
this.updateNavbarColor(color)
|
||||
},
|
||||
'$store.state.mainLayoutType' (val) {
|
||||
this.setNavMenuVisibility(val)
|
||||
this.disableThemeTour = true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bodyOverlay () { return this.$store.state.bodyOverlay },
|
||||
contentAreaClass () {
|
||||
if (this.mainLayoutType === 'vertical') {
|
||||
if (this.verticalNavMenuWidth === 'default') return 'content-area-reduced'
|
||||
else if (this.verticalNavMenuWidth === 'reduced') return 'content-area-lg'
|
||||
else return 'content-area-full'
|
||||
} else return 'content-area-full'
|
||||
},
|
||||
footerClasses () {
|
||||
return {
|
||||
'footer-hidden': this.footerType === 'hidden',
|
||||
'footer-sticky': this.footerType === 'sticky',
|
||||
'footer-static': this.footerType === 'static'
|
||||
}
|
||||
},
|
||||
isAppPage () {
|
||||
return this.$route.meta.no_scroll
|
||||
},
|
||||
isThemeDark () { return this.$store.state.theme === 'dark' },
|
||||
layoutTypeClass () { return `main-${this.mainLayoutType}` },
|
||||
mainLayoutType () { return this.$store.state.mainLayoutType },
|
||||
navbarClasses () {
|
||||
return {
|
||||
'navbar-hidden' : this.navbarType === 'hidden',
|
||||
'navbar-sticky' : this.navbarType === 'sticky',
|
||||
'navbar-static' : this.navbarType === 'static',
|
||||
'navbar-floating' : this.navbarType === 'floating'
|
||||
}
|
||||
},
|
||||
verticalNavMenuWidth () { return this.$store.state.verticalNavMenuWidth },
|
||||
windowWidth () { return this.$store.state.windowWidth }
|
||||
},
|
||||
methods: {
|
||||
changeRouteTitle (title) {
|
||||
this.routeTitle = title
|
||||
},
|
||||
updateNavbar (val) {
|
||||
if (val === 'static') this.updateNavbarColor(this.isThemeDark ? '#10163a' : '#fff')
|
||||
this.navbarType = val
|
||||
},
|
||||
updateNavbarColor (val) {
|
||||
this.navbarColor = val
|
||||
if (val === '#fff') this.isNavbarDark = false
|
||||
else this.isNavbarDark = true
|
||||
},
|
||||
updateFooter (val) {
|
||||
this.footerType = val
|
||||
},
|
||||
updateRouterTransition (val) {
|
||||
this.routerTransition = val
|
||||
},
|
||||
setNavMenuVisibility (layoutType) {
|
||||
if ((layoutType === 'horizontal' && this.windowWidth >= 1200) || (layoutType === 'vertical' && this.windowWidth < 1200)) {
|
||||
this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', false)
|
||||
this.$store.dispatch('updateVerticalNavMenuWidth', 'no-nav-menu')
|
||||
} else {
|
||||
this.$store.commit('TOGGLE_IS_VERTICAL_NAV_MENU_ACTIVE', true)
|
||||
}
|
||||
},
|
||||
toggleHideScrollToTop (val) {
|
||||
this.hideScrollToTop = val
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const color = this.navbarColor === '#fff' && this.isThemeDark ? '#10163a' : this.navbarColor
|
||||
this.updateNavbarColor(color)
|
||||
this.setNavMenuVisibility(this.$store.state.mainLayoutType)
|
||||
|
||||
// Dynamic Watchers for tour
|
||||
// Reason: Once tour is disabled it is not required to enable it.
|
||||
// So, watcher is required for just disabling it.
|
||||
this.dynamicWatchers.windowWidth = this.$watch('$store.state.windowWidth', (val) => {
|
||||
if (val < 1200) {
|
||||
this.disableThemeTour = true
|
||||
this.dynamicWatchers.windowWidth()
|
||||
}
|
||||
})
|
||||
|
||||
this.dynamicWatchers.verticalNavMenuWidth = this.$watch('$store.state.verticalNavMenuWidth', () => {
|
||||
this.disableThemeTour = true
|
||||
this.dynamicWatchers.verticalNavMenuWidth()
|
||||
})
|
||||
|
||||
this.dynamicWatchers.rtl = this.$watch('$vs.rtl', () => {
|
||||
this.disableThemeTour = true
|
||||
this.dynamicWatchers.rtl()
|
||||
})
|
||||
},
|
||||
beforeDestroy () {
|
||||
Object.keys(this.dynamicWatchers).map(i => {
|
||||
this.dynamicWatchers[i]()
|
||||
delete this.dynamicWatchers[i]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user