tethys.backend/resources/js/Components/AsideMenuItem.vue
Arno Kaimbacher bf9d25ae3e
All checks were successful
CI Pipeline / japa-tests (push) Successful in 53s
- advanced AsideMenuList.vue, AsideMenuItem.vue
- npm updates
- load menu in AsideMenu.vue via main.ts store for saving the satus of menu items
- extended jappa tests: test also permission on dataset controller code
2023-11-29 16:52:41 +01:00

188 lines
5.6 KiB
Vue

<script lang="ts" setup>
import { ref, computed, ComputedRef } from 'vue';
import { Link, usePage } from '@inertiajs/vue3';
// import { Link } from '@inertiajs/inertia-vue3';
import { StyleService } from '@/Stores/style';
import { mdiMinus, mdiPlus } from '@mdi/js';
import { getButtonColor } from '@/colors.js';
import BaseIcon from '@/Components/BaseIcon.vue';
// import AsideMenuList from '@/Components/AsideMenuList.vue';
import { stardust } from '@eidellev/adonis-stardust/client';
import type { User } from '@/Dataset';
const props = defineProps({
item: {
type: Object,
required: true,
},
parentItem: {
type: Object,
required: false,
},
// isDropdownList: Boolean,
});
const user: ComputedRef<User> = computed(() => {
return usePage().props.authUser as User;
});
const itemRoute = computed(() => (props.item && props.item.route ? stardust.route(props.item.route) : ''));
// const isCurrentRoute = computed(() => (props.item && props.item.route ? stardust.isCurrent(props.item.route): false));
// const itemHref = computed(() => (props.item && props.item.href ? props.item.href : ''));
const emit = defineEmits(['menu-click']);
const styleService = StyleService();
const hasColor = computed(() => props.item && props.item.color);
const isDropdownOpen = ref(false);
const isChildSelected = computed(() => {
if (props.item.children && props.item.children.length > 0) {
return children.value.some(childItem => stardust.isCurrent(childItem.route));
}
return false;
});
// const value = computed({
// get: () => props.modelValue,
// set: (value) => emit('update:modelValue', value),
// });
const hasChildren = computed(() => {
// props.item.children?.length > 0
if (props.item.children && props.item.children.length > 0) {
return true;
}
return false;
});
const children = computed(() => {
return props.item.children || [];
});
const componentClass = computed(() => [
hasChildren ? 'py-3 px-6 text-sm font-semibold' : 'py-3 px-6',
hasColor.value ? getButtonColor(props.item.color, false, true) : styleService.asideMenuItemStyle,
]);
// const toggleDropdown = () => {
// // emit('menu-click', event, props.item);
// // console.log(props.item);
// if (hasChildren.value) {
// isDropdownOpen.value = !isDropdownOpen.value;
// }
// // if (props.parentItem?.hasDropdown.value) {
// // props.parentItem.isDropdownActive.value = true;
// // }
// };
const menuClick = (event) => {
emit('menu-click', event, props.item);
if (hasChildren.value) {
// if (isChildSelected.value == false) {
// isDropdownOpen.value = !isDropdownOpen.value;
props.item.isOpen = !props.item.isOpen;
// }
}
};
// const handleChildSelected = () => {
// isChildSelected.value = true;
// };
const activeInactiveStyle = computed(() => {
if (props.item.route && stardust.isCurrent(props.item.route)) {
// console.log(props.item.route);
return styleService.asideMenuItemActiveStyle;
} else {
return null;
}
});
const is = computed(() => {
if (props.item.href) {
return 'a';
}
if (props.item.route) {
return Link;
}
return 'div';
});
const hasRoles = computed(() => {
if (props.item.roles) {
return user.value.roles.some(role => props.item.roles.includes(role.name));
// return test;
}
return true
});
// props.routeName && stardust.isCurrent(props.routeName) ? props.activeColor : null
</script>
<!-- :target="props.item.target ?? null" -->
<template>
<li v-if="hasRoles">
<!-- <component :is="itemHref ? 'div' : Link" :href="itemHref ? itemHref : itemRoute" -->
<component :is="is" :href="itemRoute ? stardust.route(props.item.route) : props.item.href"
class="flex cursor-pointer dark:text-slate-300 dark:hover:text-white menu-item-wrapper" :class="componentClass"
@click="menuClick" v-bind:target="props.item.target ?? null">
<BaseIcon v-if="item.icon" :path="item.icon" class="flex-none menu-item-icon" :class="activeInactiveStyle"
w="w-16" :size="18" />
<div class="menu-item-label">
<span class="grow text-ellipsis line-clamp-1" :class="activeInactiveStyle">
{{ item.label }}
</span>
</div>
<!-- plus icon for expanding sub menu -->
<BaseIcon v-if="hasChildren" :path="props.item.isOpen ? mdiMinus : mdiPlus" class="flex-none"
:class="[activeInactiveStyle]" w="w-12" />
</component>
<div class="menu-item-dropdown"
:class="[styleService.asideMenuDropdownStyle, props.item.isOpen ? 'block dark:bg-slate-800/50' : 'hidden']"
v-if="hasChildren">
<ul>
<!-- <li v-for="( child, index ) in children " :key="index">
<AsideMenuItem :item="child" :key="index"> </AsideMenuItem>
</li> -->
<AsideMenuItem v-for="(childItem, index) in props.item.children" :key="index" :item="childItem" />
</ul>
</div>
<!-- <AsideMenuList v-if="hasChildren" :items="item.children"
:class="[styleService.asideMenuDropdownStyle, isDropdownOpen ? 'block dark:bg-slate-800/50' : 'hidden']" /> -->
</li>
</template>
<style>
.menu-item-wrapper {
display: flex;
align-items: center;
cursor: pointer;
}
/* .menu-item-icon {
font-size: 1.5rem;
margin-right: 10px;
}
.menu-item-label {
font-size: 1.2rem;
font-weight: bold;
}
.menu-item-dropdown {
margin-left: 10px;
} */
</style>