66 lines
2.2 KiB
Python
66 lines
2.2 KiB
Python
"""
|
|
Het plugin-register: het hart van de modulaire architectuur.
|
|
|
|
Elke module (een Django-app) maakt zichzelf bij opstarten bekend door een
|
|
`ModuleSpec` te registreren. Het register houdt bij wélke modules er bestaan,
|
|
wat ze aanbieden (menu-items / uitbreidpunten) en hoe ze van elkaar afhangen.
|
|
|
|
Of een module daadwerkelijk AAN staat, wordt per school bewaard in de database
|
|
(zie models.ModuleState) en is via het beheerscherm in te stellen. Zo is
|
|
modulariteit een echt verkoopargument: de kern is overal gelijk, en een school
|
|
schakelt naar wens modules bij.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MenuItem:
|
|
"""Een navigatie-item dat een module toevoegt aan de app."""
|
|
|
|
label: str
|
|
path: str
|
|
icon: str = "puzzle"
|
|
order: int = 100
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ModuleSpec:
|
|
"""Beschrijving waarmee een module zich aanmeldt bij het register."""
|
|
|
|
key: str # unieke sleutel, bv. "printing"
|
|
name: str # leesbare naam
|
|
description: str = ""
|
|
version: str = "0.1.0"
|
|
category: str = "Overig"
|
|
core: bool = False # kern-module: altijd aan, niet uitschakelbaar
|
|
default_enabled: bool = False # standaard aan na installatie?
|
|
depends_on: tuple[str, ...] = field(default_factory=tuple)
|
|
menu_items: tuple[MenuItem, ...] = field(default_factory=tuple)
|
|
|
|
|
|
class ModuleRegistry:
|
|
"""Centrale verzameling van alle bekende modules (in-memory)."""
|
|
|
|
def __init__(self) -> None:
|
|
self._specs: dict[str, ModuleSpec] = {}
|
|
|
|
def register(self, spec: ModuleSpec) -> None:
|
|
if spec.key in self._specs:
|
|
raise ValueError(f"Module '{spec.key}' is al geregistreerd.")
|
|
self._specs[spec.key] = spec
|
|
|
|
def all(self) -> list[ModuleSpec]:
|
|
return sorted(self._specs.values(), key=lambda s: (s.category, s.name))
|
|
|
|
def get(self, key: str) -> ModuleSpec | None:
|
|
return self._specs.get(key)
|
|
|
|
def dependents_of(self, key: str) -> list[ModuleSpec]:
|
|
"""Modules die deze module nodig hebben."""
|
|
return [s for s in self._specs.values() if key in s.depends_on]
|
|
|
|
|
|
# Eén gedeeld register voor de hele applicatie.
|
|
registry = ModuleRegistry()
|