- Allow and improve viewing of different content types. First type implemented: changelog

This commit is contained in:
Josako
2025-06-03 09:48:50 +02:00
parent 67078ce925
commit b4e58659a8
12 changed files with 748 additions and 16 deletions

View File

@@ -0,0 +1,215 @@
import os
import re
import logging
from packaging import version
from flask import current_app
logger = logging.getLogger(__name__)
class ContentManager:
def __init__(self, app=None):
self.app = app
if app:
self.init_app(app)
def init_app(self, app):
self.app = app
# Controleer of het pad bestaat
if not os.path.exists(app.config['CONTENT_DIR']):
logger.warning(f"Content directory not found at: {app.config['CONTENT_DIR']}")
else:
logger.info(f"Content directory configured at: {app.config['CONTENT_DIR']}")
def get_content_path(self, content_type, major_minor=None, patch=None):
"""
Geef het volledige pad naar een contentbestand
Args:
content_type (str): Type content (bv. 'changelog', 'terms')
major_minor (str, optional): Major.Minor versie (bv. '1.0')
patch (str, optional): Patchnummer (bv. '5')
Returns:
str: Volledige pad naar de content map of bestand
"""
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
if major_minor:
content_path = os.path.join(content_path, major_minor)
if patch:
content_path = os.path.join(content_path, f"{major_minor}.{patch}.md")
return content_path
def _parse_version(self, filename):
"""Parse een versienummer uit een bestandsnaam"""
match = re.match(r'(\d+\.\d+)\.(\d+)\.md', filename)
if match:
return match.group(1), match.group(2)
return None, None
def get_latest_version(self, content_type, major_minor=None):
"""
Verkrijg de laatste versie van een bepaald contenttype
Args:
content_type (str): Type content (bv. 'changelog', 'terms')
major_minor (str, optional): Specifieke major.minor versie, anders de hoogste
Returns:
tuple: (major_minor, patch, full_version) of None als niet gevonden
"""
try:
# Basispad voor dit contenttype
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
if not os.path.exists(content_path):
logger.error(f"Content path does not exist: {content_path}")
return None
# Als geen major_minor opgegeven, vind de hoogste
if not major_minor:
available_versions = os.listdir(content_path)
if not available_versions:
return None
# Sorteer op versienummer (major.minor)
available_versions.sort(key=lambda v: version.parse(v))
major_minor = available_versions[-1]
# Nu we major_minor hebben, zoek de hoogste patch
major_minor_path = os.path.join(content_path, major_minor)
if not os.path.exists(major_minor_path):
logger.error(f"Version path does not exist: {major_minor_path}")
return None
files = os.listdir(major_minor_path)
version_files = []
for file in files:
mm, p = self._parse_version(file)
if mm == major_minor and p:
version_files.append((mm, p, f"{mm}.{p}"))
if not version_files:
return None
# Sorteer op patch nummer
version_files.sort(key=lambda v: int(v[1]))
return version_files[-1]
except Exception as e:
logger.error(f"Error finding latest version for {content_type}: {str(e)}")
return None
def read_content(self, content_type, major_minor=None, patch=None):
"""
Lees content met versieondersteuning
Als major_minor en patch niet zijn opgegeven, wordt de laatste versie gebruikt.
Als alleen major_minor is opgegeven, wordt de laatste patch van die versie gebruikt.
Args:
content_type (str): Type content (bv. 'changelog', 'terms')
major_minor (str, optional): Major.Minor versie (bv. '1.0')
patch (str, optional): Patchnummer (bv. '5')
Returns:
dict: {
'content': str,
'version': str,
'content_type': str
} of None bij fout
"""
try:
# Als geen versie opgegeven, vind de laatste
if not major_minor:
version_info = self.get_latest_version(content_type)
if not version_info:
logger.error(f"No versions found for {content_type}")
return None
major_minor, patch, full_version = version_info
# Als geen patch opgegeven, vind de laatste patch voor deze major_minor
elif not patch:
version_info = self.get_latest_version(content_type, major_minor)
if not version_info:
logger.error(f"No versions found for {content_type} {major_minor}")
return None
major_minor, patch, full_version = version_info
else:
full_version = f"{major_minor}.{patch}"
# Nu hebben we major_minor en patch, lees het bestand
file_path = self.get_content_path(content_type, major_minor, patch)
if not os.path.exists(file_path):
logger.error(f"Content file does not exist: {file_path}")
return None
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
return {
'content': content,
'version': full_version,
'content_type': content_type
}
except Exception as e:
logger.error(f"Error reading content {content_type} {major_minor}.{patch}: {str(e)}")
return None
def list_content_types(self):
"""Lijst alle beschikbare contenttypes op"""
try:
return [d for d in os.listdir(self.app.config['CONTENT_DIR'])
if os.path.isdir(os.path.join(self.app.config['CONTENT_DIR'], d))]
except Exception as e:
logger.error(f"Error listing content types: {str(e)}")
return []
def list_versions(self, content_type):
"""
Lijst alle beschikbare versies voor een contenttype
Returns:
list: Lijst van dicts met versie-informatie
[{'version': '1.0.0', 'path': '/path/to/file', 'date_modified': datetime}]
"""
versions = []
try:
content_path = os.path.join(self.app.config['CONTENT_DIR'], content_type)
if not os.path.exists(content_path):
return []
for major_minor in os.listdir(content_path):
major_minor_path = os.path.join(content_path, major_minor)
if not os.path.isdir(major_minor_path):
continue
for file in os.listdir(major_minor_path):
mm, p = self._parse_version(file)
if mm and p:
file_path = os.path.join(major_minor_path, file)
mod_time = os.path.getmtime(file_path)
versions.append({
'version': f"{mm}.{p}",
'path': file_path,
'date_modified': mod_time
})
# Sorteer op versienummer
versions.sort(key=lambda v: version.parse(v['version']))
return versions
except Exception as e:
logger.error(f"Error listing versions for {content_type}: {str(e)}")
return []