Commit Graph

83 Commits

Author SHA1 Message Date
stellarshenson
4b2fc084bf fix: use separate SQLite database for activity monitor
- ActivityMonitor now uses /data/activity_samples.sqlite instead of
  JupyterHub's main database to avoid SQLite locking conflicts
- Fixes "database is locked" errors that prevented login when both
  JupyterHub and ActivityMonitor wrote simultaneously
- Added "Last Active" column to activity table showing relative time
2026-01-20 19:04:39 +01:00
stellarshenson
66de0e7c5c fix: activity bar UI redesign and sample cleanup enforcement
- Redesign activity bar as thin continuous bar (80x8px) with subtle dividers
- Fix inconsistent timestamp text ("Last updated" vs "Measured")
- Fix sample cleanup to always run on record_sample(), not just on inserts
- Ensures samples older than RETENTION_DAYS are properly pruned
2026-01-20 18:53:03 +01:00
stellarshenson
60eb59a854 docs: clarify sample update vs insert behavior in docstring 2026-01-20 17:21:31 +01:00
stellarshenson
aecd6821c7 fix: update last sample on refresh instead of inserting new one 2026-01-20 17:21:15 +01:00
stellarshenson
a0dee35bd6 fix: add spinner to refresh button and show relative time 2026-01-20 17:16:00 +01:00
stellarshenson
5e563af39b feat: add Activity Monitor admin page with 3-state status and reset functionality
- Add ActivitySample SQLAlchemy model for database persistence
- Add ActivityMonitor singleton with scoring, reset, lifecycle methods
- Add JUPYTERHUB_ACTIVITYMON_INACTIVE_AFTER env var (default 60 min)
- Update defaults: SAMPLE_INTERVAL=600s, RETENTION_DAYS=7
- Fix score calculation to use measured samples only (not theoretical max)
- Add 3-state status: green (active), yellow (inactive), red (offline)
- Add recently_active field in API response
- Add Reset button with confirmation dialog
- Fix green color (explicit #28a745 instead of text-success)
- Add ThreadPoolExecutor for non-blocking Docker stats
- Remove old background sampler code (on-demand sampling now)
- Bump version to 3.7.0
2026-01-20 17:08:23 +01:00
stellarshenson
d2ff63b2e1 fix: use spawner.orm_spawner.last_activity (Server object has no last_activity) 2026-01-20 10:05:53 +01:00
stellarshenson
5d24f17900 fix: use server.last_activity instead of user.last_activity for idle tracking
- user.last_activity updates on Hub page access (causes timer reset on refresh)
- server.last_activity only updates on actual JupyterLab activity
- Matches what jupyterhub-idle-culler uses for culling decisions
2026-01-20 10:01:52 +01:00
stellarshenson
b440a7fe07 fix: show max extension error as disappearing warning alert, remove duplicate static text 2026-01-18 21:58:25 +01:00
stellarshenson
439472999d fix: show max hours in extension limit warning message 2026-01-18 21:45:24 +01:00
stellarshenson
3264c26d6b fix: keep extend button enabled when max reached (backend handles rejection) 2026-01-18 21:22:44 +01:00
stellarshenson
6762a5739a fix: truncate excess extension hours instead of rejecting request
- Truncate requested hours to max available instead of returning error
- Add 'truncated' flag in API response with detailed message
- UI shows warning alert (yellow) when truncated, success (green) otherwise
- Warning displays 4 seconds vs 2 seconds for normal success
- Fixed extend button re-enable after successful extension
2026-01-18 21:18:47 +01:00
stellarshenson
42180502e7 fix: extension now ADDS hours (cumulative), added detailed logging 2026-01-18 21:11:34 +01:00
stellarshenson
63efb1a264 fix: simplify session extension - reset activity and SET hours (not add) 2026-01-18 21:04:24 +01:00
stellarshenson
61807cac1f fix: session extension now adds hours instead of resetting timer 2026-01-18 21:03:09 +01:00
stellarshenson
de3863ef5e fix: use offset-naive datetime for last_activity to match JupyterHub internal format 2026-01-18 21:01:28 +01:00
stellarshenson
1d5fb93c49 feat: improve session extension UI with numeric input and idle note 2026-01-18 20:56:58 +01:00
stellarshenson
e0ceed8004 feat: add idle culler session extension and harmonize env settings
Session Extension Feature:
- Add JUPYTERHUB_IDLE_CULLER_MAX_EXTENSION env var (default 24h)
- Add SessionInfoHandler and ExtendSessionHandler API endpoints
- Add Session Status card to home page with countdown timer
- Extension tracking in spawner state (resets on server restart)
- Color-coded warnings (yellow <1h, red <30min)

Environment Settings Harmonization:
- Add all ENV defaults to Dockerfile
- Add idle culler settings to compose.yml
- Standardize logo as JUPYTERHUB_LOGO_URI with file:// prefix
- Update NVIDIA_IMAGE to nvidia/cuda:13.0.2-base-ubuntu24.04
2026-01-18 20:28:33 +01:00
stellarshenson
1db8ed1129 feat: rename JUPYTERHUB_SERVICE_GLANCES to JUPYTERHUB_SERVICE_RESOURCES_MONITOR 2026-01-18 18:18:29 +01:00
stellarshenson
940ac7e0d9 feat: add version footer to home page
Display Stellars JupyterHub DS and JupyterHub versions in footer.
Uses short version format (major.minor.patch) only.
2026-01-14 17:30:40 +01:00
stellarshenson
181e2ac5f4 chore: cleanup templates directory structure
- Remove unused *.html from services/jupyterhub/templates/
- Keep only certs/ subdirectory in templates/
- Rename templates_enhanced to html_templates_enhanced
- Update Dockerfile COPY paths
2026-01-14 17:19:12 +01:00
stellarshenson
9e52c3c36a feat: xkcdpass password generation with configurable options
- Move settings_dictionary.yml to services/jupyterhub/conf/
- Replace hardcoded word list with xkcdpass library
- Add JUPYTERHUB_AUTOGENERATED_PASSWORD_WORDS (default: 4)
- Add JUPYTERHUB_AUTOGENERATED_PASSWORD_DELIMITER (default: "-")
- Fix ENABLE_SIGNUP to JUPYTERHUB_SIGNUP_ENABLED in Dockerfile
2026-01-14 17:11:27 +01:00
stellarshenson
d8a306a0d5 feat: externalize settings metadata to YAML dictionary
- Add config/settings_dictionary.yml with category-based structure
- Categories as top-level keys (JupyterHub Core, Docker Spawner, etc.)
- Each setting has name, description, default, optional empty_display
- Update SettingsPageHandler to load from YAML file
- Add pyyaml to Dockerfile pip dependencies
- Refactor pip install to heredoc format with echo message
2026-01-14 16:43:26 +01:00
stellarshenson
022e970dbf feat: standardize env vars with JUPYTERHUB_ prefix, add admin settings page
- Rename 13 environment variables to use JUPYTERHUB_ prefix:
  - ENABLE_GPU_SUPPORT -> JUPYTERHUB_GPU_ENABLED
  - ENABLE_JUPYTERHUB_SSL -> JUPYTERHUB_SSL_ENABLED
  - ENABLE_SERVICE_* -> JUPYTERHUB_SERVICE_*
  - ENABLE_SIGNUP -> JUPYTERHUB_SIGNUP_ENABLED
  - DOCKER_NOTEBOOK_IMAGE -> JUPYTERHUB_NOTEBOOK_IMAGE
  - DOCKER_NETWORK_NAME -> JUPYTERHUB_NETWORK_NAME
  - NVIDIA_AUTODETECT_IMAGE -> JUPYTERHUB_NVIDIA_IMAGE
  - IDLE_CULLER_* -> JUPYTERHUB_IDLE_CULLER_*
- Add SettingsPageHandler with admin-only access at /settings
- Add Settings link to admin navbar
- Sync templates from templates_enhanced to templates
- Update README.md and CLAUDE.md documentation
- No backward compatibility for old variable names
2026-01-14 16:39:34 +01:00
stellarshenson
a40bb19f5b feat: add Notifications link to admin navbar 2026-01-14 16:17:26 +01:00
stellarshenson
4b6ac08ab0 feat: idle server culler for automatic shutdown of inactive servers
- Add jupyterhub-idle-culler package to Dockerfile
- Configure as managed JupyterHub service with role-based scopes
- Environment variables: IDLE_CULLER_ENABLED, IDLE_CULLER_TIMEOUT,
  IDLE_CULLER_CULL_EVERY, IDLE_CULLER_MAX_AGE
- Default: disabled, 24h timeout, 10min check interval
- Bump version to 3.6.0
2026-01-14 16:15:21 +01:00
stellarshenson
cd9c6bf7fa feat: selective notification recipients
Add ability to send notifications to selected servers instead of all.
- New ActiveServersHandler at GET /api/notifications/active-servers
- BroadcastNotificationHandler accepts optional recipients array
- UI with "Send to all" checkbox and server selection list
- Select All/Deselect All buttons, dynamic button text
- Backward compatible - sends to all if recipients not specified
2026-01-14 12:46:49 +01:00
stellarshenson
ad789d7632 fix: lowercase hex encoding for docker volume names 2026-01-08 14:24:06 +01:00
stellarshenson
5e633a9841 fix: encode usernames for docker volume/container names
Use escapism library (same as DockerSpawner) to encode special
characters in usernames when constructing Docker volume and container
names. Fixes volume reset for users with dots in names (e.g., user.name).
2026-01-08 13:37:53 +01:00
stellarshenson
36933afe2b chore: further enhanced display of logo 2026-01-07 03:05:16 +01:00
stellarshenson
a6686ab4a2 feat: custom logo support and authorization handler fix
- Add JUPYTERHUB_LOGO_FILE config for custom logo (served at /hub/logo)
- Fix CustomAuthorizationAreaHandler with @needs_scope decorator
- Import orm inside get() method to fix NameError
- Simplify page.html logo block (always use base_url/logo)
2026-01-07 01:44:54 +01:00
stellarshenson
8be73942da feat: server-side authorization discard button protection
- Add StellarsNativeAuthenticator subclass with CustomAuthorizationAreaHandler
- Pass hub_usernames set to template for Jinja2 conditional logic
- Remove JavaScript API call approach (was clunky with XSRF token handling)
- Fix Bootstrap 5 table hover color override (target td/th explicitly)
2026-01-07 01:16:52 +01:00
stellarshenson
8a420cbb63 feat: document mnemonic passwords and fix table hover styling 2026-01-07 00:44:00 +01:00
stellarshenson
3607c5cb4c fix: use Bootstrap CSS variable for table hover opacity 2026-01-07 00:21:44 +01:00
stellarshenson
20ed13baab fix: reduce spacing before Shutdown Hub button 2026-01-06 23:58:04 +01:00
stellarshenson
6378b68821 fix: admin panel styling and replace eye emoji with icons 2026-01-06 23:55:02 +01:00
stellarshenson
4094e04a67 fix: further admin panel styling refinements
- Reduce user row hover to nearly invisible (0.003 alpha)
- Fix Add Users button: stock colors in light mode, explicit in dark mode
- Make collapse buttons more compact (0.2rem 0.3rem)
- Add username label left padding
- Update journal
2026-01-06 22:54:24 +01:00
stellarshenson
ddc9cb8382 fix: refine admin panel styling - buttons, hover, spacing
- Fix Add Users button to use stock btn-light colors (size only)
- Disable hover on expanded card tables via box-shadow override
- Add padding:0 to expanded user detail td cells
- Make collapse buttons more compact (0.2rem 0.3rem)
- Add left padding to username labels
- Add groups page styling (list items, card footer)
2026-01-06 22:47:22 +01:00
stellarshenson
c1ae9938c1 feat: comprehensive UI styling for notifications, admin panel, tokens
- Add notifications page styling (form, textarea, results table)
- Unify button font sizes to 0.8rem across all pages
- Set collapsed user card padding to 0
- Add subtle hover effect on admin user rows (0.015 alpha)
- Style Add Users form panel with dark mode support
- Style authorization and token pages consistently
2026-01-06 22:26:19 +01:00
stellarshenson
f1a8b5e6ce feat: add custom logo support via JUPYTERHUB_CUSTOM_LOGO_URI env var 2026-01-06 21:45:40 +01:00
stellarshenson
e0f5bf11e3 feat: add compact styling inspired by Stellars Sublime theme 2026-01-06 21:43:41 +01:00
stellarshenson
79a09db50d chore: comment out console logs in admin template 2026-01-06 21:31:46 +01:00
stellarshenson
bd63c72fd4 feat: add per-row copy icon in credentials modal 2026-01-06 21:30:07 +01:00
stellarshenson
bc99236162 fix: move spinner functions before fetch interceptor 2026-01-06 21:18:25 +01:00
stellarshenson
bc76c4f767 feat: add loading spinner during credentials fetch 2026-01-06 21:15:42 +01:00
stellarshenson
f5b8a5717e fix: credentials modal - buttons on top, scrollable list, plain styling 2026-01-06 21:13:19 +01:00
stellarshenson
6f85208352 fix: change credentials endpoint from /api/users to /api/admin 2026-01-06 21:00:21 +01:00
stellarshenson
d5cfbebed5 fix: URL handling in admin fetch interceptor and nav links
- Handle URL objects (not just strings) in fetch interceptor
- Strip query params before checking isUserCreation endpoint
- Remove duplicate 'hub' prefix from authorize/change-password links
2026-01-06 20:52:12 +01:00
stellarshenson
7ee223b193 fix: Dockerfile to copy from templates_enhanced (was reverted) 2026-01-06 20:46:04 +01:00
stellarshenson
6370255746 fix: handle URL objects in fetch interceptor 2026-01-06 20:39:38 +01:00