Move menu to pinia store
This commit is contained in:
parent
cdf2b2e429
commit
372e6ee8c4
|
@ -9,6 +9,7 @@
|
|||
"@inertiajs/inertia-vue": "^0.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"merge": "^2.1.1",
|
||||
"pinia": "^2.0.35",
|
||||
"portal-vue": "^2.1.7",
|
||||
"postcss-import": "^14.0.1",
|
||||
"svg-sprite": "^2.0.2",
|
||||
|
@ -24,7 +25,7 @@
|
|||
"laravel-mix": "^6.0.1",
|
||||
"postcss": "^8.4.6",
|
||||
"tailwindcss": "^3.2",
|
||||
"vue": "^2.6",
|
||||
"vue": "2.7",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-loader": "^15.9.8",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
|
@ -2601,6 +2602,11 @@
|
|||
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vue/devtools-api": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
|
||||
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
|
||||
|
@ -7425,6 +7431,31 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pinia": {
|
||||
"version": "2.0.35",
|
||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.35.tgz",
|
||||
"integrity": "sha512-P1IKKQWhxGXiiZ3atOaNI75bYlFUbRxtJdhPLX059Z7+b9Z04rnTZdSY8Aph1LA+/4QEMAYHsTQ638Wfe+6K5g==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.5.0",
|
||||
"vue-demi": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.4.0",
|
||||
"typescript": ">=4.4.4",
|
||||
"vue": "^2.6.14 || ^3.2.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
},
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
|
@ -9783,6 +9814,31 @@
|
|||
"vue": "^3.0.0 || ^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-demi": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",
|
||||
"integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vue-eslint-parser": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"laravel-mix": "^6.0.1",
|
||||
"postcss": "^8.4.6",
|
||||
"tailwindcss": "^3.2",
|
||||
"vue": "^2.6",
|
||||
"vue": "2.7",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-loader": "^15.9.8",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
|
@ -29,6 +29,7 @@
|
|||
"@inertiajs/inertia-vue": "^0.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"merge": "^2.1.1",
|
||||
"pinia": "^2.0.35",
|
||||
"portal-vue": "^2.1.7",
|
||||
"postcss-import": "^14.0.1",
|
||||
"svg-sprite": "^2.0.2",
|
||||
|
|
|
@ -9,6 +9,7 @@ import VBool from './components/VBool.vue';
|
|||
import Box from './components/Box.vue';
|
||||
import Heading from './components/Heading.vue';
|
||||
import IconButton from './components/Ui/IconButton.vue';
|
||||
import PageLayout from './components/Page/Layout.vue';
|
||||
import AppLayout from './layouts/AppLayout.vue';
|
||||
import VTooltip from 'v-tooltip';
|
||||
import hasModule from './mixins/hasModule.js';
|
||||
|
@ -17,12 +18,14 @@ import PortalVue from 'portal-vue';
|
|||
import axios from 'axios';
|
||||
import VueAxios from 'vue-axios';
|
||||
import Toasted from 'vue-toasted';
|
||||
import {createPinia, PiniaVuePlugin} from 'pinia';
|
||||
|
||||
Vue.use(plugin);
|
||||
Vue.use(PortalVue);
|
||||
Vue.use(VTooltip);
|
||||
Vue.use(Toasted);
|
||||
Vue.use(VueAxios, axios);
|
||||
Vue.use(PiniaVuePlugin);
|
||||
Vue.component('f-text', () => import(/* webpackChunkName: "form" */ './components/FText'));
|
||||
Vue.component('f-switch', () => import(/* webpackChunkName: "form" */ './components/FSwitch'));
|
||||
Vue.component('f-select', () => import(/* webpackChunkName: "form" */ './components/FSelect'));
|
||||
|
@ -34,9 +37,11 @@ Vue.component('v-label', VLabel);
|
|||
Vue.component('box', Box);
|
||||
Vue.component('heading', Heading);
|
||||
Vue.component('icon-button', IconButton);
|
||||
Vue.component('page-layout', PageLayout);
|
||||
Vue.component('save-button', () => import(/* webpackChunkName: "form" */ './components/SaveButton'));
|
||||
|
||||
const el = document.getElementById('app');
|
||||
const pinia = createPinia();
|
||||
|
||||
Vue.mixin(hasModule);
|
||||
Vue.mixin(hasFlash);
|
||||
|
@ -45,6 +50,7 @@ Vue.component('ILink', ILink);
|
|||
Inertia.on('start', (event) => window.dispatchEvent(new Event('inertiaStart')));
|
||||
|
||||
new Vue({
|
||||
pinia,
|
||||
render: (h) =>
|
||||
h(InertiaApp, {
|
||||
props: {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="grow bg-gray-900 flex flex-col transition-all" :class="{'ml-56': menuStore.visible, 'ml-0': !menuStore.visible}">
|
||||
<div class="h-16 px-6 flex items-center space-x-3 border-b border-gray-600">
|
||||
<a href="#" @click.prevent="menuStore.toggle()" class="lg:hidden">
|
||||
<svg-sprite src="menu" class="text-gray-100 w-5 h-5"></svg-sprite>
|
||||
</a>
|
||||
<span class="text-sm md:text-xl font-semibold text-white leading-none" v-html="$page.props.title"></span>
|
||||
<!--
|
||||
<i-link v-for="(link, index) in filterMenu" :key="index" :href="link.href" class="btn label mr-2" :class="`btn-${link.color}`" v-tooltip="tooltipsVisible ? link.label : ''">
|
||||
<svg-sprite v-show="link.icon" class="w-3 h-3 xl:mr-2" :src="link.icon"></svg-sprite>
|
||||
<span class="hidden xl:inline" v-text="link.label"></span>
|
||||
</i-link>
|
||||
-->
|
||||
<div class="flex grow justify-between">
|
||||
<portal-target name="toolbar-left"> </portal-target>
|
||||
<portal-target name="toolbar-right"> </portal-target>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow flex flex-col">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {menuStore} from '../../stores/menuStore.js';
|
||||
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
menuStore: menuStore(),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -6,8 +6,8 @@
|
|||
<div
|
||||
class="fixed z-40 bg-gray-800 p-6 w-56 top-0 h-screen border-r border-gray-600 border-solid flex flex-col justify-between transition-all"
|
||||
:class="{
|
||||
'-left-[14rem]': !(menuVisible || (!menuVisible && menuOverflowVisible)),
|
||||
'left-0': menuVisible || (!menuVisible && menuOverflowVisible),
|
||||
'-left-[14rem]': !menuStore.isShifted,
|
||||
'left-0': menuStore.isShifted,
|
||||
}"
|
||||
>
|
||||
<div class="grid gap-2">
|
||||
|
@ -21,44 +21,23 @@
|
|||
<v-link href="/setting" menu="setting" icon="setting">Einstellungen</v-link>
|
||||
<v-link @click.prevent="$inertia.post('/logout')" icon="logout" href="/logout">Abmelden</v-link>
|
||||
</div>
|
||||
<a href="#" @click.prevent="menuOverflowVisible = false" v-if="menuOverflowVisible && !menuVisible" class="absolute right-0 top-0 mr-2 mt-2">
|
||||
<a href="#" @click.prevent="menuStore.hide()" v-if="menuStore.hideable" class="absolute right-0 top-0 mr-2 mt-2">
|
||||
<svg-sprite src="close" class="w-5 h-5 text-gray-300"></svg-sprite>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="grow bg-gray-900 flex flex-col transition-all" :class="{'ml-56': menuVisible, 'ml-0': !menuVisible}">
|
||||
<div class="h-16 px-6 flex items-center space-x-3 border-b border-gray-600">
|
||||
<a href="#" @click.prevent="menuOverflowVisible = !menuOverflowVisible" class="lg:hidden">
|
||||
<svg-sprite src="menu" class="text-gray-100 w-5 h-5"></svg-sprite>
|
||||
</a>
|
||||
<span class="text-sm md:text-xl font-semibold text-white leading-none" v-html="$page.props.title"></span>
|
||||
<i-link v-for="(link, index) in filterMenu" :key="index" :href="link.href" class="btn label mr-2" :class="`btn-${link.color}`" v-tooltip="tooltipsVisible ? link.label : ''">
|
||||
<svg-sprite v-show="link.icon" class="w-3 h-3 xl:mr-2" :src="link.icon"></svg-sprite>
|
||||
<span class="hidden xl:inline" v-text="link.label"></span>
|
||||
</i-link>
|
||||
<div class="flex grow justify-between">
|
||||
<portal-target name="toolbar-left"> </portal-target>
|
||||
<portal-target name="toolbar-right"> </portal-target>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow flex flex-col">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VLink from './_VLink.vue';
|
||||
import {debounce} from 'lodash';
|
||||
import {menuStore} from '../stores/menuStore.js';
|
||||
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
menuVisible: true,
|
||||
menuOverflowVisible: false,
|
||||
tooltipsVisible: false,
|
||||
menuStore: menuStore(),
|
||||
};
|
||||
},
|
||||
components: {
|
||||
|
@ -72,36 +51,8 @@ export default {
|
|||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
menuListener() {
|
||||
var x = window.matchMedia('(min-width: 1024px)');
|
||||
|
||||
if (x.matches && !this.menuVisible) {
|
||||
console.log('A');
|
||||
this.menuVisible = true;
|
||||
this.menuOverflowVisible = false;
|
||||
return;
|
||||
}
|
||||
if (!x.matches && this.menuVisible) {
|
||||
this.menuVisible = false;
|
||||
this.menuOverflowVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.tooltipsVisible = !window.matchMedia('(min-width: 1280px)').matches;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
var _self = this;
|
||||
window.addEventListener('resize', this.menuListener);
|
||||
this.menuListener();
|
||||
|
||||
window.addEventListener('inertiaStart', () => {
|
||||
if (!window.matchMedia('(min-width: 1024px)').matches) {
|
||||
_self.menuVisible = false;
|
||||
_self.menuOverflowVisible = false;
|
||||
}
|
||||
});
|
||||
this.menuStore.startInertiaListener();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import {defineStore} from 'pinia';
|
||||
|
||||
export const menuStore = defineStore('menu', {
|
||||
state: () => ({
|
||||
visible: false,
|
||||
overflowVisible: false,
|
||||
tooltipsVisible: false,
|
||||
}),
|
||||
getters: {
|
||||
isShifted: (state) => state.visible || state.overflowVisible,
|
||||
hideable: (state) => state.overflowVisible && !state.visible,
|
||||
},
|
||||
actions: {
|
||||
menuListener() {
|
||||
var x = window.matchMedia('(min-width: 1024px)');
|
||||
|
||||
if (x.matches && !this.visible) {
|
||||
this.visible = true;
|
||||
this.overflowVisible = false;
|
||||
return;
|
||||
}
|
||||
if (!x.matches && this.visible) {
|
||||
this.visible = false;
|
||||
this.overflowVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.tooltipsVisible = !window.matchMedia('(min-width: 1280px)').matches;
|
||||
},
|
||||
startInertiaListener() {
|
||||
var _self = this;
|
||||
|
||||
window.addEventListener('resize', this.menuListener);
|
||||
this.menuListener();
|
||||
|
||||
window.addEventListener('inertiaStart', () => {
|
||||
if (!window.matchMedia('(min-width: 1024px)').matches) {
|
||||
_self.visible = false;
|
||||
_self.overflowVisible = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
toggle() {
|
||||
this.overflowVisible = !this.overflowVisible;
|
||||
},
|
||||
hide() {
|
||||
this.overflowVisible = false;
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,9 +1,11 @@
|
|||
<template>
|
||||
<div class="gap-6 md:grid-cols-2 xl:grid-cols-4 grid p-6">
|
||||
<v-block v-for="(block, index) in blocks" :key="index" :title="block.title">
|
||||
<v-component :data="block.data" :is="block.component"></v-component>
|
||||
</v-block>
|
||||
</div>
|
||||
<page-layout title="Dashboard">
|
||||
<div class="gap-6 md:grid-cols-2 xl:grid-cols-4 grid p-6">
|
||||
<v-block v-for="(block, index) in blocks" :key="index" :title="block.title">
|
||||
<v-component :data="block.data" :is="block.component"></v-component>
|
||||
</v-block>
|
||||
</div>
|
||||
</page-layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
Loading…
Reference in New Issue