Files
function/lib/mithril.py
Peter Stockings d4c0c0f262 Add home dashboard and Mithril rendering support
- Create new home route with comprehensive dashboard statistics
- Implement Mithril rendering support with new `mithril_loader.html` template
- Add new routes for home and test pages in `app.py`
- Create `lib/mithril.py` with Mithril rendering and error handling utilities
- Update dashboard template to use new home route
- Add detailed dashboard view with timer and HTTP function statistics
2025-02-20 23:35:46 +11:00

83 lines
2.9 KiB
Python

from flask import render_template, jsonify, request, session
from functools import wraps
import time
class MithrilError(Exception):
def __init__(self, message, code=400):
self.message = message
self.code = code
class Mithril:
_shared_data = {}
@classmethod
def share(cls, key, value):
"""Add shared data that will be available to all components"""
cls._shared_data[key] = value
@staticmethod
def render(component_name, props=None):
"""Render a Mithril component"""
instance = Mithril(component_name, props or {})
return instance()
@classmethod
def error_handler(cls, error_handler):
"""Decorator to register a global error handler"""
cls._error_handler = error_handler
return error_handler
def __init__(self, component_name, props=None):
self.component_name = component_name
self.props = props or {}
self.version = int(time.time()) # Simple asset versioning
def _prepare_response_data(self):
"""Prepare the data to be sent to the frontend"""
return {
'component': self.component_name,
'props': self.props,
'shared': self._shared_data,
'version': self.version,
'errors': session.get('errors', {}), # Flash-style errors
'flash': session.get('flash', []) # Flash messages
}
def __call__(self):
try:
response_data = self._prepare_response_data()
# Clear flash data after preparing response
session.pop('errors', None)
session.pop('flash', None)
if request.headers.get('X-Mithril-Request'):
return jsonify(response_data)
return render_template('mithril_loader.html', **response_data)
except Exception as e:
if hasattr(self, '_error_handler'):
return self._error_handler(e)
raise
@classmethod
def form(cls, route):
"""Decorator for handling form submissions"""
def decorator(f):
@wraps(f)
def wrapped(*args, **kwargs):
try:
if request.headers.get('X-Mithril-Request'):
form_data = request.get_json()
else:
form_data = request.form
return f(form_data, *args, **kwargs)
except MithrilError as e:
session['errors'] = {'message': e.message}
if request.headers.get('X-Mithril-Request'):
return jsonify({'errors': {'message': e.message}}), e.code
return cls.redirect_back()
return wrapped
return decorator