docs: update API.md, FRONTEND.md, MODULES.md, CLAUDE.md for Phase 1 and 2 completion

- API.md: add GET /config/schema endpoint docs; add GET|PUT /missions/rotation endpoints;
  fix mission response shape (name/filename/size_bytes/terrain); mark Phase 1+2 as done
- FRONTEND.md: add TagListEditor, useServerConfigSchema, useServerMissionRotation,
  useUpdateMissionRotation; update Mission/Mod type notes; remove planned hooks now live
- MODULES.md: update config_generator and missions_router descriptions
- CLAUDE.md: mark Phase 1 and 2 as Done
This commit is contained in:
Tran G. (Revernomad) Khoa
2026-04-17 20:35:39 +07:00
parent 4aae08420b
commit fe3bd81cae
4 changed files with 118 additions and 27 deletions

108
API.md
View File

@@ -790,6 +790,39 @@ Get all config sections combined. Sensitive fields (passwords) are masked with `
---
### GET /servers/{server_id}/config/schema
Returns per-field widget hints for the frontend config editor. Used by `ConfigEditor` to render the correct UI widget (text box, toggle, select, tag list, etc.) for each field.
**Auth:** Required (any role)
**Response 200:**
```json
{
"success": true,
"data": {
"server": {
"hostname": { "widget": "text", "label": "Server Hostname" },
"max_players": { "widget": "number", "label": "Max Players", "min": 1, "max": 1000 },
"password": { "widget": "password", "label": "Player Password" },
"forced_difficulty": { "widget": "select", "label": "Difficulty Preset", "options": ["Recruit", "Regular", "Veteran", "Custom"] },
"battleye": { "widget": "toggle", "label": "BattleEye Anti-Cheat" },
"motd_lines": { "widget": "textarea", "label": "Message of the Day (one line per row)" },
"admin_uids": { "widget": "tag-list", "label": "Admin Steam UIDs", "placeholder": "76561198000000000" }
},
"rcon": {
"rcon_password": { "widget": "password", "label": "RCon Password" }
}
},
"error": null
}
```
Returns `{}` if the adapter does not implement `get_ui_schema()`.
---
### GET /servers/{server_id}/config/preview
Rendered config for preview. Admin only because it may contain plaintext credentials.
@@ -1182,10 +1215,10 @@ List all available mission/scenario files on disk.
"total": 2,
"missions": [
{
"name": "MyMission.Altis",
"filename": "MyMission.Altis.pbo",
"mission_name": "MyMission.Altis",
"terrain": "Altis",
"file_size": 102400
"size_bytes": 102400,
"terrain": "Altis"
}
]
},
@@ -1226,6 +1259,63 @@ Upload a mission file. **Multipart form-data**. Maximum file size: **500 MB**. F
---
### GET /servers/{server_id}/missions/rotation
Get the current mission rotation from the server config.
**Auth:** Required (any role)
**Response 200:**
```json
{
"success": true,
"data": {
"missions": [
{ "name": "MyMission.Altis", "difficulty": "Regular" },
{ "name": "TvT.Stratis", "difficulty": "Veteran" }
]
},
"error": null
}
```
---
### PUT /servers/{server_id}/missions/rotation
Replace the mission rotation. Uses **optimistic locking** — must include `config_version` from the last server config read.
**Auth:** Admin required
**Request:**
```json
{
"missions": [
{ "name": "MyMission.Altis", "difficulty": "Regular" },
{ "name": "TvT.Stratis", "difficulty": "" }
],
"config_version": 3
}
```
`difficulty` can be `""` for default, or one of `"Recruit"`, `"Regular"`, `"Veteran"`, `"Custom"`.
**Response 200:**
```json
{
"success": true,
"data": { "missions": [ ... ] },
"error": null
}
```
**Error 409:** Config version conflict — re-fetch and retry.
---
### DELETE /servers/{server_id}/missions/{filename}
Delete a mission file by filename. Removes the file from disk.
@@ -1491,20 +1581,20 @@ Implemented via `slowapi` middleware.
## Upcoming Endpoints (UX Enhancement Plan)
These endpoints are planned and will be added during the Arma 3 UX Enhancement implementation. They do not exist yet.
Endpoints planned during the Arma 3 UX Enhancement. ✅ = implemented.
### Phase 1 — Config UI Schema
### Phase 1 — Config UI Schema
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/servers/{server_id}/config/ui-schema` | Bearer | Returns widget hints per field (`widget`, `label`, `placeholder`) for the frontend config editor |
| GET | `/servers/{server_id}/config/schema` | Bearer | Returns widget hints per field for the frontend config editor |
### Phase 2 — Mission Rotation
### Phase 2 — Mission Rotation
| Method | Path | Auth | Description |
|--------|------|------|-------------|
| GET | `/servers/{server_id}/missions/rotation` | Bearer | Get current mission rotation list |
| PUT | `/servers/{server_id}/missions/rotation` | Admin | Replace mission rotation (requires `config_version` for optimistic locking) |
| GET | `/servers/{server_id}/missions/rotation` | Bearer | Get current mission rotation list |
| PUT | `/servers/{server_id}/missions/rotation` | Admin | Replace mission rotation (requires `config_version` for optimistic locking) |
### Phase 4 — Player Kick / Ban

View File

@@ -58,15 +58,15 @@ Types below reflect the **current** API shape. Fields marked `(planned)` will be
| Phase | Feature | Status |
|-------|---------|--------|
| 1 | Config field UI widgets (textarea/toggle/select/tag-list per field) | Pending |
| 2 | Mission rotation table + multi-file upload | Pending |
| 1 | Config field UI widgets (textarea/toggle/select/tag-list per field) | Done |
| 2 | Mission rotation table + multi-file upload | Done |
| 3 | Mod display names (mod.cpp) + split-pane selector | Pending |
| 4 | Player Kick/Ban from Players tab via RCon | Pending |
| 5 | Historical log file browser + live log level filter | Pending |
**New endpoints added by the plan:**
- `GET /api/servers/{id}/config/schema` — per-field widget hints
- `GET|PUT /api/servers/{id}/missions/rotation` — mission rotation
- `GET /api/servers/{id}/config/schema` — per-field widget hints (**implemented**)
- `GET|PUT /api/servers/{id}/missions/rotation` — mission rotation (**implemented**)
- `POST /api/servers/{id}/players/{slot_id}/kick`
- `POST /api/servers/{id}/players/{slot_id}/ban`
- `GET /api/servers/{id}/logfiles`

View File

@@ -65,17 +65,18 @@ frontend/src/
│ ├── servers/
│ │ ├── ServerCard.tsx # Server card with actions
│ │ ├── ServerHeader.tsx # Server name, status, stats grid, lifecycle buttons
│ │ ├── ConfigEditor.tsx # Tabbed config section editor with optimistic locking
│ │ ├── ConfigEditor.tsx # Tabbed config section editor; per-field widgets via useServerConfigSchema
│ │ ├── PlayerTable.tsx # Current players + history with search
│ │ ├── BanTable.tsx # Ban list + create/revoke form
│ │ ├── MissionList.tsx # Mission list + upload/delete .pbo
│ │ ├── MissionList.tsx # Available missions + Mission Rotation sections; multi-file upload
│ │ ├── ModList.tsx # Mod list with enable/disable checkboxes
│ │ └── LogViewer.tsx # Log display with level filter (receives logs as props)
│ ├── settings/
│ │ ├── PasswordChange.tsx # Password change form
│ │ └── UserManager.tsx # User CRUD table (admin only)
│ └── ui/
── StatusLed.tsx # Colored status indicator dot
── StatusLed.tsx # Colored status indicator dot
│ └── TagListEditor.tsx # Dynamic string-list editor (add/remove items)
└── __tests__/
├── api.test.ts # Axios interceptor tests
@@ -129,10 +130,10 @@ App
│ │ │ ├── ServerHeader (status, stats, lifecycle buttons)
│ │ │ ├── Tab bar (Overview, Config, Players, Bans, Missions, Mods, Logs)
│ │ │ ├── OverviewTab (stats grid, executable path)
│ │ │ ├── ConfigEditor (section tabs, edit form, optimistic locking)
│ │ │ ├── ConfigEditor (section tabs, per-field widgets from schema, optimistic locking)
│ │ │ ├── PlayerTable (current + history with search)
│ │ │ ├── BanTable (ban list + create/revoke)
│ │ │ ├── MissionList (upload .pbo, delete)
│ │ │ ├── MissionList (Available + Rotation sections, multi-file upload)
│ │ │ ├── ModList (enable/disable checkboxes)
│ │ │ └── LogViewer (level filter, real-time via WebSocket onEvent)
│ │ ├── /servers/new → CreateServerPage
@@ -169,16 +170,19 @@ All server data flows through TanStack Query hooks:
|---|---|---|---|
| `useServerConfig(id)` | Query | `GET /api/servers/:id/config` | `["servers", id, "config"]` |
| `useServerConfigSection(id, section)` | Query | `GET /api/servers/:id/config/:section` | `["servers", id, "config", section]` |
| `useServerConfigSchema(id)` | Query | `GET /api/servers/:id/config/schema` | `["servers", id, "config", "schema"]` |
| `useServerConfigPreview(id)` | Query | `GET /api/servers/:id/config/preview` | `["servers", id, "config", "preview"]` |
| `useServerPlayers(id)` | Query | `GET /api/servers/:id/players` | `["players", id]` |
| `useServerPlayerHistory(id, opts?)` | Query | `GET /api/servers/:id/players/history` | `["players", id, "history", opts]` |
| `useServerBans(id)` | Query | `GET /api/servers/:id/bans` | `["bans", id]` |
| `useServerMissions(id)` | Query | `GET /api/servers/:id/missions` | `["missions", id]` |
| `useServerMissionRotation(id)` | Query | `GET /api/servers/:id/missions/rotation` | `["missions", id, "rotation"]` |
| `useServerMods(id)` | Query | `GET /api/servers/:id/mods` | `["mods", id]` |
| `useUpdateConfigSection(id, section)` | Mutation | `PUT /api/servers/:id/config/:section` | Invalidates config keys |
| `useCreateBan(id)` | Mutation | `POST /api/servers/:id/bans` | Invalidates `["bans", id]` |
| `useRevokeBan(id)` | Mutation | `DELETE /api/servers/:id/bans/:banId` | Invalidates `["bans", id]` |
| `useUploadMission(id)` | Mutation | `POST /api/servers/:id/missions` (multipart) | Invalidates `["missions", id]` |
| `useUploadMission(id)` | Mutation | `POST /api/servers/:id/missions` (multipart, `File[]`) | Invalidates `["missions", id]` |
| `useUpdateMissionRotation(id)` | Mutation | `PUT /api/servers/:id/missions/rotation` | Invalidates rotation + server config |
| `useDeleteMission(id)` | Mutation | `DELETE /api/servers/:id/missions/:filename` | Invalidates `["missions", id]` |
| `useSetEnabledMods(id)` | Mutation | `PUT /api/servers/:id/mods/enabled` | Invalidates `["mods", id]` |
| `useSendCommand(id)` | Mutation | `POST /api/servers/:id/rcon/command` | No invalidation |
@@ -205,18 +209,15 @@ All server data flows through TanStack Query hooks:
**Key type notes**:
- `Server` type in `useServers.ts` uses `game_port`, `current_players`, `max_players` (matches enriched API response)
- `Mission` type: `{ name, filename, size_bytes }``terrain` field planned (Phase 2 UX enhancement)
- `Mod` type: `{ name, path, size_bytes, enabled }``display_name`, `workshop_id` fields planned (Phase 3 UX enhancement)
- `Mission` type: `{ name, filename, size_bytes, terrain }` — terrain parsed from filename
- `Mod` type: `{ name, path, size_bytes, enabled, display_name, workshop_id }``display_name`/`workshop_id` from mod.cpp/meta.cpp (planned Phase 3)
- `Ban` type: `{ id, server_id, guid, name, reason, banned_by, banned_at, expires_at, is_active, game_data }` (matches API)
- There is no REST endpoint for logs — logs are only pushed via WebSocket events
**Planned hooks (UX Enhancement Plan):**
**Planned hooks (UX Enhancement Plan — remaining):**
| Hook | Phase | Endpoint |
|---|---|---|
| `useConfigUISchema(serverId)` | Phase 1 | `GET /api/servers/:id/config/ui-schema` |
| `useMissionRotation(id)` | Phase 2 | `GET /api/servers/:id/missions/rotation` |
| `useUpdateMissionRotation(id)` | Phase 2 | `PUT /api/servers/:id/missions/rotation` |
| `useKickPlayer(id)` | Phase 4 | `POST /api/servers/:id/players/:slot_id/kick` |
| `useBanPlayer(id)` | Phase 4 | `POST /api/servers/:id/players/:slot_id/ban` |
| `useLogFiles(id)` | Phase 5 | `GET /api/servers/:id/logfiles` |

View File

@@ -49,7 +49,7 @@ All 7 capabilities implemented:
| Module | Class | Purpose |
|---|---|---|
| `adapter.py` | `Arma3Adapter` | Composite adapter declaring all capabilities |
| `config_generator.py` | `Arma3ConfigGenerator` | 5 Pydantic config models, writes server.cfg/basic.cfg/Arma3Profile/beserver.cfg, builds launch args |
| `config_generator.py` | `Arma3ConfigGenerator` | 5 Pydantic config models, writes server.cfg/basic.cfg/Arma3Profile/beserver.cfg, builds launch args, `get_ui_schema()` for per-field widget hints |
| `process_config.py` | `Arma3ProcessConfig` | Allowed executables, port conventions (game+1/+2/+3), directory layout |
| `log_parser.py` | `RPTParser` | Regex-based .rpt log parser, log file resolver |
| `rcon_client.py` | `BERConClient` | BattlEye RCon v2 UDP protocol implementation |
@@ -74,7 +74,7 @@ All 7 capabilities implemented:
| `router.py` | Server CRUD, lifecycle (start/stop/restart/kill), config read/write/preview, RCon command |
| `players_router.py` | Player list, player history |
| `bans_router.py` | Ban CRUD with bans.txt file sync |
| `missions_router.py` | Mission list, .pbo upload (500MB), delete |
| `missions_router.py` | Mission list, .pbo upload (500MB), delete, GET/PUT rotation |
| `mods_router.py` | List mods, set enabled mods |
| `service.py` | `ServerService` — orchestrates all lifecycle operations, config writes, thread management |
| `schemas.py` | Pydantic models: CreateServerRequest, UpdateServerRequest, StopServerRequest |