panel: redesign web UI and make syncing responsive
Web UI (panel/frontend/index.html) rewritten: - Cards update in place from a single /status poll instead of being rebuilt on every action, so open tabs, unsaved compose/route edits, logs and the file browser position survive refreshes. Polling speeds up while an operation runs and pauses in background tabs; a header indicator shows when the panel last synced and detects an expired Authelia session. - New-app dialog (starter / compose / git), suggested port and domain, proper confirm dialogs (the old "OK = keep volumes" remove prompt is gone), toasts, an activity drawer with operation output, overflow menu, search, status filters, keyboard shortcuts, deep links, dark mode and mobile layout. - Tabs: overview (containers + routes), compose editor (dirty tracking, Ctrl+S), logs with follow, validated routes editor, file browser with drag-and-drop upload, backups, and a git source tab (deployed commit, check for updates, sync & deploy). API (panel/panel-api.py): - ThreadingHTTPServer so a long deploy no longer blocks every other request. - Per-app operation lock; concurrent writes to a busy app return 409. - GET /status: all apps, routes and container status in one request (statuses gathered in parallel); status reports running/partial/stopped. - Git sync is fetch + hard reset instead of pull-or-reclone, keeps the stored token, reports before/after commits; GET /apps/<name>/repo[?fetch=1]. - Any http(s) git host (e.g. Forgejo), default branch detection, git timeouts, no credential prompts, tokens redacted from errors, and manifest values validated before being written into the bash-sourced manifest. panelctl: - flock around routes.caddy rewrites (util-linux added to the service path). - deploy returns compose output so failures are visible in the UI. - inspect-volumes no longer fails for apps without named podman volumes, which broke the file browser. Docs: README/API.md updated; fixed outdated panelctl init examples. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UbWSNkXxZhYf7eqHTyx3Bf
This commit is contained in:
parent
85e29b8734
commit
2d3b30d078
5 changed files with 2741 additions and 1326 deletions
72
API.md
72
API.md
|
|
@ -12,6 +12,7 @@ Default bind: `127.0.0.1:9911`
|
|||
|--------|------|-------------|
|
||||
| GET | `/` | Web UI (served from `frontend/index.html`) |
|
||||
| GET | `/health` | Health check |
|
||||
| GET | `/status` | All apps with routes, container status and running operation (what the UI polls) |
|
||||
|
||||
### Apps — Read
|
||||
|
||||
|
|
@ -25,6 +26,13 @@ Default bind: `127.0.0.1:9911`
|
|||
| GET | `/apps/<name>/logs?tail=N` | Fetch last N log lines (default 100) |
|
||||
| GET | `/apps/<name>/backups` | List available backups |
|
||||
| GET | `/apps/<name>/backups/<file>` | Download backup zip |
|
||||
| GET | `/apps/<name>/repo` | Git source info (URL, branch, deployed commit, local changes) |
|
||||
| GET | `/apps/<name>/repo?fetch=1` | Same, plus fetches the remote and reports `behind` / `remote` |
|
||||
| GET | `/apps/<name>/volumes` | Volumes the file browser can open |
|
||||
| GET | `/apps/<name>/volume/files?vol=&path=` | List a folder in a volume |
|
||||
| GET | `/apps/<name>/volume/download?vol=&path=` | Download a file from a volume |
|
||||
| PUT | `/apps/<name>/volume/files?vol=&path=` | Upload a file (raw body) |
|
||||
| DELETE | `/apps/<name>/volume/files?vol=&path=` | Delete a file or folder |
|
||||
|
||||
### Apps — Write
|
||||
|
||||
|
|
@ -41,6 +49,70 @@ Default bind: `127.0.0.1:9911`
|
|||
| POST | `/apps/<name>/backup` | Create volume backup (zip) |
|
||||
| POST | `/apps/<name>/restore` | Restore from backup |
|
||||
| POST | `/apps/<name>/remove` | Remove app |
|
||||
| POST | `/apps/<name>/repo-pull` | Git apps: fetch branch, hard-reset checkout to it, redeploy |
|
||||
| POST | `/apps/<name>/volume-clear` | Stop the app and empty its default data folder |
|
||||
|
||||
Write operations are serialised per app. While one runs, another write to the
|
||||
same app returns `409` with `{"ok": false, "error": "...", "busy": "deploy"}`.
|
||||
`deploy` returns the compose output in `stdout` (or `stderr` on failure).
|
||||
|
||||
### Create app (git repository)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "blog",
|
||||
"routes": [{"domain": "blog.srazka.com", "upstream": "127.0.0.1:18090"}],
|
||||
"auth": true,
|
||||
"source_type": "github",
|
||||
"github_url": "https://git.srazka.com/reudy-net/blog.git",
|
||||
"github_branch": "",
|
||||
"github_pat": ""
|
||||
}
|
||||
```
|
||||
|
||||
Any http(s) git host works. An empty branch uses the repository's default branch.
|
||||
The compose file must be at the repository root.
|
||||
|
||||
### Sync response (`repo-pull`)
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"stdout": "HEAD is now at d7df557 Bump image tag\n...compose output...",
|
||||
"before": {"sha": "4fb7976...", "short": "4fb7976", "subject": "Initial compose", "author": "reudy", "time": 1790460618},
|
||||
"after": {"sha": "d7df557...", "short": "d7df557", "subject": "Bump image tag", "author": "reudy", "time": 1790460643},
|
||||
"changed": true
|
||||
}
|
||||
```
|
||||
|
||||
### Status response (`/status`)
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"time": 1790460650,
|
||||
"apps": [
|
||||
{
|
||||
"name": "whoami",
|
||||
"routes": [{"domain": "whoami.srazka.com", "upstream": "127.0.0.1:18080"}],
|
||||
"auth": true,
|
||||
"compose_file": "/var/lib/containers/stacks/whoami/compose.yaml",
|
||||
"repo_url": "",
|
||||
"repo_branch": "",
|
||||
"busy": null,
|
||||
"status": {
|
||||
"state": "running",
|
||||
"running": true,
|
||||
"running_count": 1,
|
||||
"total": 1,
|
||||
"containers": [{"name": "whoami-app-1", "state": "running", "status": "Up 3 minutes", "image": "docker.io/traefik/whoami:latest", "running": true}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`state` is one of `running`, `partial` (some containers down), `stopped` or `unknown`.
|
||||
|
||||
## Example payloads
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue