- Added a file input for PDF uploads with validation for file type and size. - Implemented file size formatting and user feedback for selected files. - Created upload and cancel methods with placeholder for future API integration. feat: Create PaymentForm.vue for handling payments - Developed a form for entering payment details including date, amount, method, and notes. - Integrated currency formatting and dropdown for payment methods. - Implemented save and cancel actions with API call for saving payment data. docs: Add documentation for dynamic plugin menus and permissions - Provided guidelines for defining menu items and permissions in plugins. - Explained the process for synchronizing permissions and integrating menus in the frontend. - Included examples and best practices for plugin development. feat: Add database migrations for invoices, invoice items, and payments - Created migration scripts to define the database schema for invoices, invoice items, and payments. - Established foreign key relationships between invoices and related entities. feat: Implement command for synchronizing plugin permissions - Developed a console command to synchronize plugin permissions with the database. - Added options for dry-run and force synchronization for unlicensed modules. feat: Create API controller for plugin menu items - Implemented API endpoints to retrieve plugin menu items in both flat and grouped formats. - Ensured access control with role-based permissions for API access. feat: Develop service for managing plugin menu items - Created a service to collect and manage menu items from installed plugins. - Implemented methods for retrieving flat and grouped menu items for frontend use. feat: Add service for synchronizing plugin permissions - Developed a service to handle the synchronization of plugin permissions with the database. - Included logic for creating and updating permission modules based on plugin definitions.
93 lines
3.0 KiB
Vue
93 lines
3.0 KiB
Vue
<script setup>
|
|
import { ref, onMounted } from 'vue';
|
|
import { useAuthStore } from '../stores/auth';
|
|
import AppMenuItem from './AppMenuItem.vue';
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
// Core-Menü (immer vorhanden)
|
|
const coreMenu = [
|
|
{
|
|
label: 'Home',
|
|
items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }]
|
|
},
|
|
{
|
|
label: 'CRM',
|
|
items: [
|
|
{ label: 'Kontakte', icon: 'pi pi-fw pi-users', to: '/contacts' },
|
|
{ label: 'Projekte', icon: 'pi pi-fw pi-briefcase', to: '/projects' },
|
|
{ label: 'Tätigkeiten', icon: 'pi pi-fw pi-list-check', to: '/project-tasks' }
|
|
]
|
|
}
|
|
];
|
|
|
|
// Administration-Menü (immer vorhanden)
|
|
const adminMenu = {
|
|
label: 'Administration',
|
|
visible: () => authStore.isAdmin,
|
|
items: [
|
|
{ label: 'Projekt-Status', icon: 'pi pi-fw pi-tag', to: '/project-statuses' },
|
|
{ label: 'Benutzerverwaltung', icon: 'pi pi-fw pi-user-edit', to: '/users' },
|
|
{ label: 'Rollenverwaltung', icon: 'pi pi-fw pi-shield', to: '/roles' },
|
|
{ label: 'Einstellungen', icon: 'pi pi-fw pi-cog', to: '/settings' }
|
|
]
|
|
};
|
|
|
|
// Dynamisches Menü (wird geladen)
|
|
const model = ref([...coreMenu]);
|
|
|
|
// Plugin-Menüs laden
|
|
const loadPluginMenus = async () => {
|
|
try {
|
|
const response = await fetch('/api/plugin-menu/grouped');
|
|
const data = await response.json();
|
|
|
|
if (data.success && data.data) {
|
|
// Plugin-Menüs als eigene Gruppen hinzufügen
|
|
Object.entries(data.data).forEach(([groupLabel, items]) => {
|
|
// Konvertiere zu PrimeVue Menü-Format
|
|
const menuGroup = {
|
|
label: groupLabel,
|
|
items: items.map(item => ({
|
|
label: item.label,
|
|
icon: item.icon ? `pi pi-fw ${item.icon}` : 'pi pi-fw pi-circle',
|
|
to: item.to,
|
|
...(item.items && { items: item.items }),
|
|
// Wenn Permission definiert, prüfen
|
|
...(item.permission && {
|
|
visible: () => authStore.hasPermission(item.permission)
|
|
})
|
|
}))
|
|
};
|
|
|
|
model.value.push(menuGroup);
|
|
});
|
|
}
|
|
|
|
// Administration-Menü am Ende hinzufügen
|
|
model.value.push(adminMenu);
|
|
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden der Plugin-Menüs:', error);
|
|
// Fallback: Nur Core + Admin Menü
|
|
model.value = [...coreMenu, adminMenu];
|
|
}
|
|
};
|
|
|
|
// Beim Mount laden
|
|
onMounted(() => {
|
|
loadPluginMenus();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<ul class="layout-menu">
|
|
<template v-for="(item, i) in model" :key="item">
|
|
<app-menu-item v-if="!item.separator && (!item.visible || item.visible())" :item="item" :index="i"></app-menu-item>
|
|
<li v-if="item.separator" class="menu-separator"></li>
|
|
</template>
|
|
</ul>
|
|
</template>
|
|
|
|
<style lang="scss" scoped></style>
|