Files
stellars-jupyterhub-ds/doc/ui-template-customization.md
stellarshenson 12953ee4d6 feat: add optional volume descriptions for UI
Added VOLUME_DESCRIPTIONS config dict allowing optional user-friendly
descriptions for volumes shown in management UI.

Changes:
- Added VOLUME_DESCRIPTIONS dict in jupyterhub_config.py (optional, co-defined
  with DOCKER_SPAWNER_VOLUMES)
- Exposed volume_descriptions via c.JupyterHub.template_vars
- Updated home.html to conditionally display descriptions if defined
- If volume not in VOLUME_DESCRIPTIONS, no description shown (UI remains agnostic)

Configuration example:
VOLUME_DESCRIPTIONS = {
    'home': 'User home directory files, configurations',
    'workspace': 'Project files, notebooks, code',
    'cache': 'Temporary files, pip cache, conda cache'
}

Documentation:
- Updated .claude/CLAUDE.md with Manage Volumes implementation details
- Simplified Restart Server section for consistency
- Added template variables to doc/ui-template-customization.md

UI now shows volume name, Docker volume path, and optional description
(if configured). Fully backward compatible - descriptions are optional.
2025-11-09 22:50:13 +01:00

59 lines
1.9 KiB
Markdown

# UI Template Customization
JupyterHub templates extended using Jinja2 to add custom UI features (server restart, volume management, notifications). Templates placed in `services/jupyterhub/templates/` and copied to `/srv/jupyterhub/templates/` during Docker build.
**Key Technical Facts**:
- Templates extend base using `{% extends "page.html" %}`
- Override blocks: `{% block main %}`, `{% block script %}`
- Changes require Docker rebuild with `--no-cache` flag
- JupyterHub 5.4.2 uses Bootstrap 5 (not Bootstrap 4)
**Template Variables** (via `c.JupyterHub.template_vars`):
- `user_volume_suffixes`: List of volume suffixes from `DOCKER_SPAWNER_VOLUMES`
- `volume_descriptions`: Optional dict mapping suffixes to descriptions
**JavaScript Integration**:
All custom JavaScript wrapped in RequireJS to ensure library loading:
```javascript
require(["jquery"], function($) {
"use strict";
// Custom code here
});
```
**Bootstrap 5 Modal Syntax**:
```html
<button data-bs-toggle="modal" data-bs-target="#myModal">
<i class="fa fa-rotate" aria-hidden="true"></i> Restart
</button>
```
**CSRF Protection**:
All POST requests include XSRF token via `X-XSRFToken` header:
```javascript
headers: { 'X-XSRFToken': getCookie('_xsrf') }
```
**Custom Handlers** (registered in `jupyterhub_config.py`):
```python
c.JupyterHub.extra_handlers = [
(r'/api/users/([^/]+)/manage-volumes', ManageVolumesHandler),
(r'/api/users/([^/]+)/restart-server', RestartServerHandler),
(r'/api/notifications/broadcast', BroadcastNotificationHandler),
(r'/notifications', NotificationsPageHandler),
]
```
**Font Awesome Icons**:
- Restart: `fa fa-rotate`
- Volumes: `fa fa-database`
- Stop: `fa fa-stop`
- Start: `fa fa-play`
**Build Process**:
```bash
docker compose build --no-cache jupyterhub
docker stop stellars-jupyterhub-ds-jupyterhub && docker rm stellars-jupyterhub-ds-jupyterhub
docker compose up -d jupyterhub
```