Skip to content

[feature:gsoc26] Add persistent checkbox, pending filter and retry-state fields to the firmware upgrader admin UI #427

Description

@Eeshu-Yadav

Is your feature request related to a problem? Please describe.

Sub-issues 01–06 build the entire persistence machinery, but none of it is visible in the admin yet. An operator opening the mass-upgrade confirmation page sees no is_persistent checkbox, the operation list has no way to find pending ops, the detail page doesn't show retry_count or next_retry_at, the batch list doesn't show whether a batch is persistent, and the WebSocket-driven progress display renders pending ops with the wrong indicator (it'd default to the in-progress spinner).

This sub-issue is the admin-side polish: form, list view, detail view, list filters, and the static CSS/JS that makes the pending status visually distinct.

Describe the solution I would implement

I would like to extend the admin form, list, detail, and frontend assets so every persistence affordance the rest of the work introduces is actually reachable.

  1. Add an is_persistent BooleanField to BatchUpgradeConfirmationForm:

    • initial=True so the checkbox is pre-checked when an operator opens the page.
    • required=False so unchecking it submits False (Django populates cleaned_data["is_persistent"] either way).
    • help_text explaining the retry-until-online behaviour.
    • Add "is_persistent" to the form's Meta.fields.
  2. Update BuildAdmin.upgrade_selected (admin.py:185–301):

    • The existing pattern reads each form input from request.POST, rebuilds BatchUpgradeConfirmationForm with that data, calls form.full_clean(), then reads form.cleaned_data to invoke build.batch_upgrade(...). I'd extend it: read is_persistent from request.POST, include it in the form data, then pass persistent=form.cleaned_data["is_persistent"] to batch_upgrade().
    • Update Build.batch_upgrade() (base/models.py:164–191) from (self, firmwareless, upgrade_options=None, group=None, location=None) to add is_is_persistent=True, and set the value on the BatchUpgradeOperation instance before batch.full_clean().
  3. Update UpgradeOperationAdmin:

    • list_display: add is_persistent and retry_count.
    • list_filter: add is_persistent. The existing status filter automatically picks up "pending" once sub-issue 01 extends STATUS_CHOICES.
    • readonly_fields and fields: add is_persistent, retry_count, next_retry_at so they render as read-only on the detail form.
  4. Update BatchUpgradeOperationAdmin:

    • Add is_persistent to list_display so admins can tell persistent batches apart at a glance.
    • Add is_persistent to readonly_fields for the detail view — UI-level reinforcement of sub-issue 01's model-level immutability guard.
  5. Add frontend handling for the new pending status under openwisp_firmware_upgrader/static/firmware-upgrader/:

    • CSS: a .status-pending class (e.g., orange/amber) visually distinct from the in-progress spinner.
    • JS: map pending in the WebSocket message handler to a "waiting for device" indicator, and consume the new pending field that sub-issue 03 adds to the batch-status WebSocket payload. The per-op UpgradeProgressPublisher already forwards instance.status verbatim, but the consumer-side snapshot methods and publish_batch_status payload shape are getting changes in sub-issue 03 — not "no Python change", just changes localised there.
  6. Update the batch detail page progress display to surface the pending count alongside completed (e.g., "5 complete, 2 pending out of 7"), reading from sub-issue 03's new pending_count property on AbstractBatchUpgradeOperation.

  7. The admin's cancel UI is a template button (templates/admin/upgrade_selected_confirmation.html:97, JS handler in admin/js/cancel.js) that calls the REST API endpoint UpgradeOperationCancelView at api/views.py:381–451 — there's no Django admin action for cancellation. Once sub-issue 03 extends _CANCELLABLE_STATUS, the shared instance.cancel() model method covers pending ops, so the button works without any admin-side change. Templates use get_status_display() rather than hardcoded status strings, so no template edits are required either.

  8. Admin tests (Django test client, not Selenium — that lives in sub-issue 09) covering: form renders the checkbox pre-checked; submitting with is_is_persistent=False/True produces a correctly-flagged batch and propagates to children; ?status=pending filter returns only pending ops; detail page exposes the new read-only fields; batch list shows the is_persistent column; cancel button transitions a pending op to cancelled.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestgsoc-ideaIssues part of Google Summer of Code project

Type

No fields configured for Task.

Projects

Status
ToDo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions