diff --git a/open_workshop_dokuwiki/README.md b/open_workshop_dokuwiki/README.md index cad0deb..d134354 100644 --- a/open_workshop_dokuwiki/README.md +++ b/open_workshop_dokuwiki/README.md @@ -308,3 +308,108 @@ Daten: {name}|{status_smiley}|{ows_machine_id.category_icon}|{partner_id}|{mod Spalten: Name|Status|Tags|Hersteller|Standort|Doku Daten: {name}|{status_smiley}|{tags_list}|{partner_id}|{location}|{wiki_doku_link} ``` + +--- + +# Best Practices: DokuWiki Seitenstruktur + +## Erweiterbare Dokumentation ohne Umbenennung + +### Problem +Benutzer möchten zu Equipment-Seiten eigene Unterseiten hinzufügen, ohne die von Odoo generierten Seiten umbenennen zu müssen. + +### Lösung: Parallele Seite + Namespace + +DokuWiki erlaubt **gleichzeitig** eine Seite und einen gleichnamigen Namespace: +- Datei: `equipment.txt` (von Odoo generiert) +- Verzeichnis: `equipment/` (für Benutzer-Unterseiten) + +**Die Seite `equipment.txt` hat Vorrang und bleibt die Haupt-Equipment-Seite!** + +### Empfohlene Struktur + +``` +werkstatt/ausruestung/doku/ +├── analog-oscilloscope-hm303-6.txt # Von Odoo generiert +├── analog-oscilloscope-hm303-6/ # Benutzer erstellt (optional) +│ ├── kalibrierung.txt # Benutzer-Unterseite +│ ├── messungen.txt # Benutzer-Unterseite +│ └── bilder/ # Weitere Unter-Namespaces möglich +│ └── oszillogramme.txt +├── cnc-fraese-xyz.txt # Von Odoo generiert +└── cnc-fraese-xyz/ # Benutzer-Namespace (optional) + ├── programme.txt + └── werkzeuge.txt +``` + +### Wichtige Regeln + +#### ✅ DO: Unterverzeichnis OHNE start.txt + +``` +equipment/ +├── subpage1.txt +├── subpage2.txt +└── weitere/ + └── details.txt +``` + +**Vorteile:** +- Breadcrumb zeigt: `Home » Werkstatt » Ausrüstung » Equipment » Subpage1` +- Keine Duplikation oder Verwirrung +- Equipment-Hauptseite bleibt `equipment.txt` + +#### ❌ DON'T: Unterverzeichnis MIT start.txt + +``` +equipment/ +├── start.txt # ❌ NICHT erstellen! +├── subpage1.txt +└── subpage2.txt +``` + +**Probleme:** +- Breadcrumb wird verwirrend: `Equipment` könnte auf zwei Seiten verweisen +- `equipment` und `equipment:start` zeigen unterschiedliche Inhalte +- Benutzer wissen nicht, welche Seite die "richtige" ist + +### Catlist für Unterseiten-Auflistung + +In der Odoo-generierten Hauptseite kann eine catlist-Anweisung eingefügt werden: + +```dokuwiki +===== Dokumentation: Analog Oscilloscope HM303-6 ===== + +... Equipment-Details ... + +==== Weitere Dokumentation ==== + + +``` + +**Syntax-Erklärung:** +- `.:namespace` → Relativer Namespace (Punkt + Doppelpunkt!) +- `-noNSInBold` → Namespace-Präfix nicht fett darstellen +- `-sortByTitle` → Alphabetisch sortieren +- `-exclude:{ns1 ns2}` → Optional: Namespaces ausschließen + +**Ergebnis:** +- Zeigt alle Unterseiten im `equipment/` Verzeichnis +- Automatisch aktualisiert wenn Benutzer neue Seiten erstellen +- Kein manuelles Pflegen von Links nötig + +### Workflow + +1. **Odoo synchronisiert** → Erstellt/aktualisiert `equipment.txt` +2. **Benutzer erstellt Unterseiten** → Erstellt Verzeichnis `equipment/` und fügt Seiten hinzu +3. **Catlist zeigt automatisch** → Alle Unterseiten werden auf der Hauptseite gelistet +4. **Keine Konflikte** → Odoo überschreibt nur `equipment.txt`, nie das `equipment/` Verzeichnis + +### Vorteile dieser Struktur + +- ✅ Odoo-Seiten bleiben unverändert und zentral verwaltbar +- ✅ Benutzer können frei Unterseiten erstellen ohne Odoo-Sync zu stören +- ✅ Keine Namenskollisionen oder Breadcrumb-Probleme +- ✅ Automatische Verlinkung via catlist +- ✅ Skalierbar: Beliebig viele Unterseiten und Unter-Namespaces möglich +- ✅ Klare Trennung: Was von Odoo kommt vs. was von Benutzern kommt diff --git a/open_workshop_dokuwiki/models/dokuwiki_client.py b/open_workshop_dokuwiki/models/dokuwiki_client.py index 455f51c..76ea37d 100644 --- a/open_workshop_dokuwiki/models/dokuwiki_client.py +++ b/open_workshop_dokuwiki/models/dokuwiki_client.py @@ -6,19 +6,42 @@ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) +# Connection Cache (pro Request wiederverwendet) +_connection_cache = {} + class DokuWikiClient(models.AbstractModel): """ Wrapper für DokuWiki XML-RPC API Client. Managed die Verbindung zum DokuWiki und stellt Methoden für Seitenoperationen bereit. + + Performance-Optimierung: Verbindungen werden gecached und wiederverwendet + um den Overhead von XML-RPC Verbindungsaufbauten zu minimieren. """ _name = 'dokuwiki.client' _description = 'DokuWiki API Client' @api.model - def _get_wiki_connection(self): + def _get_cache_key(self): + """ + Generiert einen Cache-Key basierend auf den Verbindungsparametern. + + Returns: + str: Cache-Key (URL + User) + """ + IrConfigParameter = self.env['ir.config_parameter'].sudo() + wiki_url = IrConfigParameter.get_param('dokuwiki.url', '') + wiki_user = IrConfigParameter.get_param('dokuwiki.user', '') + return f"{wiki_url}:{wiki_user}" + + @api.model + def _get_wiki_connection(self, use_cache=True): """ Erstellt eine DokuWiki-Verbindung mit Credentials aus System-Parametern. + Verbindungen werden gecached und wiederverwendet für bessere Performance. + + Args: + use_cache (bool): Wenn True, wird eine gecachte Verbindung wiederverwendet Returns: DokuWiki: Verbundenes DokuWiki-Client-Objekt @@ -46,12 +69,34 @@ class DokuWikiClient(models.AbstractModel): if not wiki_url.startswith(('http://', 'https://')): raise UserError(f"DokuWiki URL muss mit http:// oder https:// beginnen: {wiki_url}") + # Cache-Key generieren + cache_key = self._get_cache_key() + + # Gecachte Verbindung wiederverwenden wenn möglich + if use_cache and cache_key in _connection_cache: + try: + # Teste ob Verbindung noch lebt + cached_wiki = _connection_cache[cache_key] + _ = cached_wiki.version # Test-Call + _logger.debug(f"Wiederverwendung gecachter DokuWiki-Verbindung: {wiki_url}") + return cached_wiki + except Exception as e: + _logger.warning(f"Gecachte Verbindung ungültig, erstelle neue: {e}") + del _connection_cache[cache_key] + + # Neue Verbindung erstellen try: - _logger.info(f"Verbinde zu DokuWiki: {wiki_url} (User: {wiki_user})") + _logger.info(f"Neue DokuWiki-Verbindung: {wiki_url} (User: {wiki_user})") wiki = DokuWiki(wiki_url, wiki_user, wiki_password) # Test-Verbindung version = wiki.version _logger.info(f"DokuWiki-Verbindung erfolgreich: Version {version}") + + # In Cache speichern + if use_cache: + _connection_cache[cache_key] = wiki + _logger.debug(f"Verbindung im Cache gespeichert: {cache_key}") + return wiki except DokuWikiError as e: error_details = f"URL: {wiki_url}, User: {wiki_user}, Fehler: {e}" @@ -70,6 +115,15 @@ class DokuWikiClient(models.AbstractModel): except Exception as e: _logger.error(f"Unerwarteter Fehler bei DokuWiki-Verbindung: {e}", exc_info=True) raise UserError(f"Unerwarteter Fehler: {e}") + + @api.model + def clear_connection_cache(self): + """ + Löscht den Verbindungs-Cache (z.B. nach Konfigurationsänderungen). + """ + global _connection_cache + _connection_cache.clear() + _logger.info("DokuWiki Verbindungs-Cache geleert") @api.model def create_page(self, page_id, content, summary="Erstellt von Odoo"): diff --git a/open_workshop_dokuwiki/models/maintenance_equipment.py b/open_workshop_dokuwiki/models/maintenance_equipment.py index 5071bc7..9b3099c 100644 --- a/open_workshop_dokuwiki/models/maintenance_equipment.py +++ b/open_workshop_dokuwiki/models/maintenance_equipment.py @@ -7,6 +7,8 @@ from odoo.exceptions import UserError _logger = logging.getLogger(__name__) +# Cache für Wiki-Templates (wird beim Server-Neustart geleert) +_template_cache = {} class MaintenanceEquipment(models.Model): """ @@ -242,17 +244,24 @@ class MaintenanceEquipment(models.Model): str: Gerenderter Wiki-Markup-Inhalt """ self.ensure_one() + global _template_cache dokuwiki_client = self.env['dokuwiki.client'] template_page_id = 'werkstatt:ausruestung:c_template' try: - # Template aus Wiki laden - template_content = dokuwiki_client.get_page(template_page_id) - if not template_content: - _logger.warning(f"Template {template_page_id} nicht gefunden, verwende Fallback") - return self._generate_wiki_main_page_content_fallback(view_type) + # Template aus Cache oder Wiki laden + if template_page_id not in _template_cache: + template_content = dokuwiki_client.get_page(template_page_id) + if not template_content: + _logger.warning(f"Template {template_page_id} nicht gefunden, verwende Fallback") + return self._generate_wiki_main_page_content_fallback(view_type) + + _template_cache[template_page_id] = template_content + _logger.info(f"Template geladen und gecacht: {template_page_id} ({len(template_content)} Zeichen)") + else: + _logger.debug(f"Template aus Cache verwendet: {template_page_id}") - _logger.info(f"Template geladen: {template_page_id} ({len(template_content)} Zeichen)") + template_content = _template_cache[template_page_id] # Werte-Dictionary vorbereiten values = self._prepare_template_values(view_type)