ui: ability to manage device apps via the web UI - #263
Conversation
For the apps management UI we only need the targets file, not a complete TUF metadata package. Signed-off-by: Volodymyr Khoroz <volodymyr.khoroz@foundries.io>
This complements an already existing ability to manage device apps via the CLI. Signed-off-by: Volodymyr Khoroz <volodymyr.khoroz@foundries.io>
There was a problem hiding this comment.
🟡 Changes recommended
There are a couple of correctness gaps (not-found handling for the new TUF file endpoint and whitespace bugs in compose_apps parsing) plus missing test coverage for the new API route.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds a new Web UI flow for viewing and modifying a device’s “apps” (compose apps) configuration, backed by a new API route to fetch per-update TUF metadata files (notably targets.json) and a small storage helper to parse individual TUF metadata files.
Changes:
- Web UI: adds a “Apps” entry on the device page and introduces a new
/configs/device/:uuid/appspage with tag/app selection UX and save/reset behavior. - API/Storage: adds
/updates/{tag}/{update}/tuf/{file}and a storage helper to return a single TUF metadata file as JSON. - Minor cleanup: small formatting/tidy edits plus a couple of shared constants exposed to UI code.
File summaries
| File | Description |
|---|---|
| storage/api/api_storage.go | Refactors TUF metadata reading by adding a helper to load+unmarshal a single TUF metadata file. |
| server/ui/web/templates/style.css | Adds chevron icon CSS used by the new transfer-list controls. |
| server/ui/web/templates/device.html | Adds “Apps” navigation button to the device page. |
| server/ui/web/templates/device_apps.html | New device-apps management page (tag selector, supported/configured app lists, save/reset JS). |
| server/ui/web/handlers.go | Registers the new /configs/device/:uuid/apps UI route. |
| server/ui/web/handlers_device_apps.go | New handler to render the apps page; parses TUF targets for app IDs; parses existing config overrides. |
| server/ui/web/handlers_configs.go | Minor cleanup (removed inline comment / whitespace). |
| server/ui/web/context.go | Exposes CtxGetLog for the new handler’s logging usage. |
| server/ui/api/handlers.go | Registers the new per-file update TUF endpoint route. |
| server/ui/api/handlers_updates.go | Adds /updates/{tag}/{update}/tuf/{file} endpoint and validation for allowed TUF filenames. |
| server/ui/api/handlers_configs.go | Exposes ConfigSotaOverride constant via the UI API package. |
Review details
Suppressed comments (2)
server/ui/api/handlers_updates.go:139
- updateGetTufFile currently turns a missing metadata file into a 500; align with other TUF endpoints by mapping os.ErrNotExist to 404 so the UI can distinguish "not found" from server errors.
meta, err := h.storage.GetUpdateTufMetadataFile(tag, update, file)
if err != nil {
return EchoError(c, err, http.StatusInternalServerError, "failed to get update TUF metadata")
}
return c.JSON(http.StatusOK, meta)
server/ui/web/handlers_device_apps.go:147
- compose_apps parsing doesn't trim whitespace around comma-separated entries, so a value like "app1, app2" will produce an app id with a leading space.
for _, app := range strings.Split(*sota.Pacman.Apps, ",") {
if len(app) > 0 {
apps = append(apps, app)
}
}
- Files reviewed: 11/11 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… page An input with a datalist does not consistently trigger events when selecting the datalist item. Furthermore, there are a lot of cross-browser edge cases when no event gets triggered at all. One inconvenience is that a user needs to either hit <Enter> or defocus after selecting from a dropdown, in order for the change event to get triggered; otherwise an apps list does not get updated. The only way which works consistently across Chromium/WebKit/Gecko is based on a focus/blur watcher. It waits for the user input to pause, and fires a change event. Signed-off-by: Volodymyr Khoroz <volodymyr.khoroz@foundries.io>
Signed-off-by: Volodymyr Khoroz <volodymyr.khoroz@foundries.io>
af17e3c to
2dc0781
Compare
doanac
left a comment
There was a problem hiding this comment.
@MiloCasagrande - I'd like to get your thoughts on this feature
| ConfigFileName string | ||
| CanEdit bool | ||
| }{ | ||
| baseCtx: h.baseCtx(c, fmt.Sprintf("Device \"%s\" Apps", uuid), "devices"), |
There was a problem hiding this comment.
Its a bit of a mouthful - but maybe we should call this "configured apps" apps to be more clear
There was a problem hiding this comment.
Or maybe we should rename "configs" to "Configure" and then put something like "manage updates" as a button under that page
There was a problem hiding this comment.
I'm not very keen to hide this behind the "configs" page - it's one of the most used features in our cloud solution.
Maybe, I can add a link "manage" to these two sections (or just the apps)?
update-server/server/ui/web/templates/device.html
Lines 6 to 17 in ff5635e
There was a problem hiding this comment.
Its a bit of a mouthful - but maybe we should call this "configured apps" apps to be more clear
I was thinking about Apps & Tags, but it already seemed mouthful to me.
There was a problem hiding this comment.
interesting. lets see what Milo thinks. he's also revamping all our views and may have an idea what will fit best within his new changes
By quickly looking at it running locally, the first thing that I noticed is the button that says "Apps", but the new page lets you configure apps and tags. That might be a little bit confusing: we might need to reword the button as suggested, or split the functionalities into two separate pages. Are tags and apps tied together? Can a user select only apps that belong to a tag? If they are not tied, I would suggest to split it in two. Otherwise reword the button, "Apps & Tags" seems fine, as that's what it does. I would suggest adding some contextual help explaining what can be done, just under the checkboxes. Two sentences max, like: "By following a tag you cannot manage apps ..." (I'm just making this up, lacking the context of how this really works). If there are docs for that, we can add a link to the docs for a lengthier explanation. |
|
I like you "manage" link idea |



No description provided.