Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions app/core/plugins.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import logging
from flask import Blueprint, g, abort, redirect, url_for, flash
from flask import Blueprint, g, abort, redirect, url_for, flash, current_app
from functools import wraps
from app.models.feature_system import is_feature_enabled

logger = logging.getLogger(__name__)

class MenuItem:
def __init__(self, label, endpoint, icon, order=100, group=None, required_role=None, feature_name=None, badge_count_key=None, label_is_key=False):
self.label = label
self.endpoint = endpoint
self.icon = icon
self.order = order
self.group = group
self.required_role = required_role
self.feature_name = feature_name
self.badge_count_key = badge_count_key
self.label_is_key = label_is_key # If True, label is a key in app_labels

class Plugin:
def __init__(self, name, blueprint, feature_name=None, url_prefix=None):
def __init__(self, name, blueprint, feature_name=None, url_prefix=None, menu_items=None):
self.name = name
self.blueprint = blueprint
self.feature_name = feature_name or name
self.url_prefix = url_prefix
self.menu_items = menu_items or []

def plugin_required(feature_name):
"""Decorator to check if a feature is enabled for the current department"""
Expand All @@ -27,6 +40,7 @@ def decorated_function(*args, **kwargs):

class PluginManager:
_plugins = {}
_core_menu_items = []

@classmethod
def register(cls, plugin):
Expand All @@ -40,6 +54,37 @@ def check_enabled():
# Redirect or 404
return redirect(url_for('dashboard.index'))

@classmethod
def register_menu_item(cls, menu_item):
cls._core_menu_items.append(menu_item)

@classmethod
def get_menu_items(cls):
all_items = list(cls._core_menu_items)
for plugin in cls._plugins.values():
all_items.extend(plugin.menu_items)

# Sort by order
all_items.sort(key=lambda x: (x.order, x.label))
return all_items

@classmethod
def get_grouped_menu_items(cls):
items = cls.get_menu_items()
groups = {}
for item in items:
group = item.group or 'Sonstiges'
if group not in groups:
groups[group] = []
groups[group].append(item)

# Define group order
group_order = ['Übersicht', 'Inventar', 'Personal', 'Service', 'Allgemein', 'Sonstiges']

# Sort groups based on group_order, then alphabetically for unknown groups
sorted_groups = sorted(groups.items(), key=lambda x: (group_order.index(x[0]) if x[0] in group_order else 999, x[0]))
return sorted_groups

@classmethod
def init_app(cls, app):
for plugin in cls._plugins.values():
Expand Down
6 changes: 4 additions & 2 deletions app/plugins/canteen/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('canteen', bp, 'canteen_plan'))
plugin_manager.register(Plugin('canteen', bp, 'canteen_plan', url_prefix='/canteen', menu_items=[
MenuItem('Kantinenplan', 'canteen.index', 'fas fa-utensils', order=80, group='Allgemein', feature_name='canteen_plan')
]))
6 changes: 4 additions & 2 deletions app/plugins/consumables/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('consumables', bp, 'consumables', url_prefix='/consumables'))
plugin_manager.register(Plugin('consumables', bp, 'consumables', url_prefix='/consumables', menu_items=[
MenuItem('consumables', 'consumables.index', 'fas fa-box-open', order=30, group='Inventar', feature_name='consumables', label_is_key=True)
]))
6 changes: 4 additions & 2 deletions app/plugins/jobs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('jobs', bp, 'job_board', url_prefix='/jobs'))
plugin_manager.register(Plugin('jobs', bp, 'job_board', url_prefix='/jobs', menu_items=[
MenuItem('Jobbörse', 'jobs.job_list', 'fas fa-briefcase', order=70, group='Allgemein', feature_name='job_board')
]))
8 changes: 6 additions & 2 deletions app/plugins/tickets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('tickets', bp, 'ticket_system', url_prefix='/tickets', menu_items=[
MenuItem('tickets', 'tickets.create', 'fas fa-ticket-alt', order=50, group='Service', feature_name='ticket_system', label_is_key=True, badge_count_key='unread_tickets_count'),
MenuItem('Auftragserstellung', 'tickets.public_create_order', 'fas fa-file-alt', order=60, group='Service', feature_name='ticket_system')
]))

plugin_manager.register(Plugin('tickets', bp, 'ticket_system', url_prefix='/tickets'))
from .history_routes import bp as history_bp
plugin_manager.register(Plugin('ticket_history', history_bp, 'ticket_system', url_prefix='/api/tickets'))
6 changes: 4 additions & 2 deletions app/plugins/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('tools', bp, 'tools', url_prefix='/tools'))
plugin_manager.register(Plugin('tools', bp, 'tools', url_prefix='/tools', menu_items=[
MenuItem('tools', 'tools.index', 'fas fa-tools', order=20, group='Inventar', feature_name='tools', label_is_key=True)
]))
7 changes: 5 additions & 2 deletions app/plugins/workers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from .routes import bp
from app.core.plugins import Plugin, plugin_manager
from app.core.plugins import Plugin, plugin_manager, MenuItem

plugin_manager.register(Plugin('workers', bp, 'workers', url_prefix='/workers'))
plugin_manager.register(Plugin('workers', bp, 'workers', url_prefix='/workers', menu_items=[
MenuItem('Mitarbeiter', 'workers.index', 'fas fa-users', order=40, group='Personal', feature_name='workers'),
MenuItem('Wochenberichte', 'workers.timesheet_list', 'fas fa-clock', order=45, group='Personal', feature_name='weekly_reports', badge_count_key='unfilled_timesheet_days')
]))
6 changes: 5 additions & 1 deletion app/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from app.routes.main import bp as main_bp
from app.routes.dashboard import bp as dashboard_bp
from app.routes.setup import bp as setup_bp
from app.core.plugins import plugin_manager
from app.core.plugins import plugin_manager, MenuItem

# Import plugins to register them
import app.plugins.tools
Expand All @@ -33,6 +33,10 @@ def init_app(app):
app.register_blueprint(api_bp)
app.register_blueprint(setup_bp)

# Register Core Menu Items
plugin_manager.register_menu_item(MenuItem('Dashboard', 'dashboard.index', 'fas fa-th-large', order=10, group='Übersicht'))
plugin_manager.register_menu_item(MenuItem('Über Scandy', 'main.about', 'fas fa-info-circle', order=100, group='Allgemein'))

# Register Plugins
plugin_manager.init_app(app)

Expand Down
Loading