Entwickler-Dokumentation
Leitfaden zur Entwicklung von CloudService Plugins.
CloudService - Entwickelt von Andreas Borowczak
|
Aboro IT
Übersicht
CloudService verwendet ein modulares Plugin-System basierend auf Django Apps. Plugins können:
- Dashboard-Widgets hinzufügen
- Datei-Vorschauen bereitstellen
- Eigene Einstellungen haben
- Hooks für verschiedene Events registrieren
Installation
Plugins können auf zwei Arten installiert werden:
- Lokaler Ordner: Plugin in
plugins/installed/ablegen - ZIP-Upload: Plugin als ZIP über die Einstellungen hochladen
Plugin-Struktur
Ein Plugin besteht aus folgenden Dateien:
mein_plugin/
├── __init__.py # Python-Paket (erforderlich)
├── plugin.json # Manifest mit Metadaten (erforderlich)
├── apps.py # Django AppConfig (erforderlich)
├── widget.py # Widget-Provider (optional)
├── handlers.py # Hook-Handler (optional)
└── templates/ # Template-Ordner (optional)
└── mein_plugin/
└── widget.html
Minimale Dateien
__init__.py- Kann leer sein oder default_app_config enthaltenplugin.json- Manifest mit Name, Version, etc.apps.py- Django AppConfig mit ready() Methode
plugin.json Manifest
Die plugin.json definiert alle Plugin-Metadaten:
{
"name": "Mein Plugin",
"slug": "mein-plugin",
"version": "1.0.0",
"author": "Ihr Name",
"description": "Beschreibung des Plugins",
"django_app": {
"app_config": "mein_plugin.apps.MeinPluginConfig"
},
"requirements": {
"django": ">=5.0,<6.0",
"python": ">=3.10"
},
"hooks": {
"ui_dashboard_widget": {
"handler": "mein_plugin.widget.MeinWidgetProvider",
"priority": 10
}
},
"settings": {
"has_settings": true,
"schema": {
"api_key": {
"type": "password",
"label": "API Key",
"required": true
},
"option": {
"type": "select",
"label": "Option",
"options": [
{"value": "a", "label": "Option A"},
{"value": "b", "label": "Option B"}
]
}
}
}
}
Pflichtfelder
| Feld | Beschreibung |
|---|---|
name | Anzeigename des Plugins |
slug | URL-freundliche ID (a-z, 0-9, -) |
version | Semver-Version (1.0.0) |
django_app.app_config | Pfad zur AppConfig-Klasse |
Dashboard Widgets
Widgets werden auf der Landing Page angezeigt. Erstellen Sie eine Widget-Klasse:
# widget.py
from plugins.widgets import DashboardWidgetProvider
class MeinWidgetProvider(DashboardWidgetProvider):
widget_id = "mein_widget"
widget_name = "Mein Widget"
widget_icon = "bi-star" # Bootstrap Icon
widget_size = "medium" # small, medium, large
widget_order = 50 # Sortierung (niedriger = weiter oben)
def get_context(self, request):
"""Daten für das Template."""
return {
'message': 'Hallo Welt!',
'user': request.user.username,
}
def get_template_name(self):
"""Pfad zum Template."""
return 'mein_plugin/widget.html'
def is_visible(self, request):
"""Optional: Widget nur für bestimmte User zeigen."""
return request.user.is_authenticated
Widget-Größen
| Größe | Bootstrap-Klasse | Breite |
|---|---|---|
small | col-md-4 | 1/3 |
medium | col-md-6 | 1/2 |
large | col-md-12 | Volle Breite |
Plugin-Einstellungen
Plugins können konfigurierbare Einstellungen haben:
Schema in plugin.json
"settings": {
"has_settings": true,
"schema": {
"feldname": {
"type": "text|password|number|boolean|select|textarea",
"label": "Anzeigename",
"help": "Hilfetext",
"required": true|false,
"default": "Standardwert",
"placeholder": "Platzhalter",
"options": [...] // Nur für select
}
}
}
Einstellungen im Code lesen
from plugins.models import Plugin
# In Ihrem Widget oder Handler:
plugin = Plugin.objects.get(slug='mein-plugin')
api_key = plugin.settings.get('api_key', '')
option = plugin.settings.get('option', 'default')
Verfügbare Feldtypen
| Typ | HTML-Element | Beschreibung |
|---|---|---|
text | input[text] | Einzeiliger Text |
password | input[password] | Passwort/API-Key |
number | input[number] | Dezimalzahl |
integer | input[number] | Ganzzahl |
boolean | checkbox | Ja/Nein |
select | select | Dropdown |
textarea | textarea | Mehrzeiliger Text |
Hook-System
Hooks erlauben es, auf Events zu reagieren oder Funktionalität zu erweitern:
Hook registrieren (in apps.py)
from django.apps import AppConfig
class MeinPluginConfig(AppConfig):
name = 'mein_plugin'
def ready(self):
from plugins.hooks import hook_registry, UI_DASHBOARD_WIDGET
from mein_plugin.widget import MeinWidgetProvider
hook_registry.register(
UI_DASHBOARD_WIDGET,
MeinWidgetProvider,
priority=10
)
Verfügbare Hooks
| Hook | Beschreibung |
|---|---|
UI_DASHBOARD_WIDGET | Dashboard-Widget hinzufügen |
FILE_PREVIEW_PROVIDER | Dateivorschau-Handler |
UI_FILE_ACTION_BUTTON | Aktions-Button bei Dateien |
UI_MENU_ITEM | Menüeintrag hinzufügen |
STORAGE_FILE_UPLOADED | Event: Datei hochgeladen |
STORAGE_FILE_DELETED | Event: Datei gelöscht |
Templates
Plugin-Templates werden automatisch gefunden wenn sie im richtigen Ordner liegen:
mein_plugin/
└── templates/
└── mein_plugin/
└── widget.html
Widget-Template Beispiel
<div class="mein-widget">
<h4></h4>
<p>Benutzer: </p>
<style>
.mein-widget { padding: 10px; }
</style>
</div>
Verfügbare Variablen
widget_context- Dict von get_context()request- HTTP Requestuser- Aktueller Benutzer
Komplettes Beispiel-Plugin
Hier ein vollständiges Beispiel für ein "Zitat des Tages" Widget:
__init__.py
"""Quote of the Day Plugin"""
default_app_config = 'quote_plugin.apps.QuoteConfig'
plugin.json
{
"name": "Zitat des Tages",
"slug": "quote-plugin",
"version": "1.0.0",
"author": "Entwickler",
"description": "Zeigt ein inspirierendes Zitat an.",
"django_app": {
"app_config": "quote_plugin.apps.QuoteConfig"
}
}
apps.py
from django.apps import AppConfig
class QuoteConfig(AppConfig):
name = 'quote_plugin'
def ready(self):
from plugins.hooks import hook_registry, UI_DASHBOARD_WIDGET
from quote_plugin.widget import QuoteWidgetProvider
hook_registry.register(
UI_DASHBOARD_WIDGET,
QuoteWidgetProvider,
priority=30
)
widget.py
import random
from plugins.widgets import DashboardWidgetProvider
class QuoteWidgetProvider(DashboardWidgetProvider):
widget_id = "quote_widget"
widget_name = "Zitat des Tages"
widget_icon = "bi-quote"
widget_size = "medium"
widget_order = 30
QUOTES = [
("Der Weg ist das Ziel.", "Konfuzius"),
("Wissen ist Macht.", "Francis Bacon"),
("Carpe Diem.", "Horaz"),
]
def get_context(self, request):
quote, author = random.choice(self.QUOTES)
return {'quote': quote, 'author': author}
def get_template_name(self):
return 'quote_plugin/widget.html'
templates/quote_plugin/widget.html
<div class="text-center py-3">
<i class="bi bi-quote display-4 text-primary"></i>
<blockquote class="blockquote mt-3">
<p></p>
<footer class="blockquote-footer">
</footer>
</blockquote>
</div>
Plugin als ZIP verteilen
Um ein Plugin als ZIP zu verteilen:
- Erstellen Sie die Plugin-Ordnerstruktur
- Packen Sie den Ordner als ZIP:
# Linux/Mac zip -r mein_plugin.zip mein_plugin/ # Windows PowerShell Compress-Archive -Path mein_plugin -DestinationPath mein_plugin.zip - Die ZIP-Struktur sollte so aussehen:
mein_plugin.zip └── mein_plugin/ ├── __init__.py ├── plugin.json ├── apps.py └── ...