|
| 1 | +"""``PipelineAdmin`` — the many-actions fixture that pins the detail-page |
| 2 | +toolbar wrapping behaviour (#672). |
| 3 | +
|
| 4 | +The point of this admin is purely the *number* and *width* of its actions. |
| 5 | +Stock Django ``@admin.action`` declarations only: |
| 6 | +
|
| 7 | +* **12 batch actions** — default (queryset-shaped) third parameter, so the API |
| 8 | + signature classifier marks them ``target: "batch"``. They render BOTH in the |
| 9 | + changelist multi-select dropdown AND as buttons on the detail page. |
| 10 | +* **2 detail-only actions** — ``obj_id`` / ``str``-shaped third parameter, so |
| 11 | + the classifier marks them ``target: "detail"``. They render ONLY as detail |
| 12 | + buttons, never in the changelist dropdown. |
| 13 | +
|
| 14 | +14 buttons (several with long descriptions) on one detail page cannot fit on a |
| 15 | +single row at 1280/1024/768/480 px. Before #672 the toolbar overflowed |
| 16 | +horizontally and pushed the H1 title + breadcrumb off-screen; now the SPA |
| 17 | +stacks the header as three full-width rows and ``flex-wrap``s the toolbar. |
| 18 | +""" |
| 19 | + |
| 20 | +from __future__ import annotations |
| 21 | + |
| 22 | +from django.contrib import admin |
| 23 | +from django.contrib import messages |
| 24 | + |
| 25 | +from examples.many_actions.models import Pipeline |
| 26 | + |
| 27 | + |
| 28 | +@admin.register(Pipeline) |
| 29 | +class PipelineAdmin(admin.ModelAdmin): |
| 30 | + list_display = ("name", "status") |
| 31 | + actions = [ |
| 32 | + "recompute_derived_field_a", |
| 33 | + "recompute_derived_field_b", |
| 34 | + "recompute_derived_field_c", |
| 35 | + "rerun_pipeline_step_1", |
| 36 | + "rerun_pipeline_step_2", |
| 37 | + "rerun_pipeline_step_3", |
| 38 | + "invalidate_downstream_cache", |
| 39 | + "mark_as_reviewed_by_operator", |
| 40 | + "mark_as_pending_operator_review", |
| 41 | + "export_selected_rows_as_csv", |
| 42 | + "export_selected_rows_as_json", |
| 43 | + "notify_owner_of_selected_rows", |
| 44 | + ] |
| 45 | + |
| 46 | + # --- 12 batch actions (changelist dropdown + detail button) ----------- # |
| 47 | + |
| 48 | + @admin.action(description="Recompute Derived Field A") |
| 49 | + def recompute_derived_field_a(self, request, queryset): # noqa: ANN001 |
| 50 | + self.message_user(request, "Recomputed Derived Field A.", level=messages.SUCCESS) |
| 51 | + |
| 52 | + @admin.action(description="Recompute Derived Field B") |
| 53 | + def recompute_derived_field_b(self, request, queryset): # noqa: ANN001 |
| 54 | + self.message_user(request, "Recomputed Derived Field B.", level=messages.SUCCESS) |
| 55 | + |
| 56 | + @admin.action(description="Recompute Derived Field C") |
| 57 | + def recompute_derived_field_c(self, request, queryset): # noqa: ANN001 |
| 58 | + self.message_user(request, "Recomputed Derived Field C.", level=messages.SUCCESS) |
| 59 | + |
| 60 | + @admin.action(description="Re-run Pipeline Step 1") |
| 61 | + def rerun_pipeline_step_1(self, request, queryset): # noqa: ANN001 |
| 62 | + self.message_user(request, "Re-ran Pipeline Step 1.", level=messages.SUCCESS) |
| 63 | + |
| 64 | + @admin.action(description="Re-run Pipeline Step 2") |
| 65 | + def rerun_pipeline_step_2(self, request, queryset): # noqa: ANN001 |
| 66 | + self.message_user(request, "Re-ran Pipeline Step 2.", level=messages.SUCCESS) |
| 67 | + |
| 68 | + @admin.action(description="Re-run Pipeline Step 3") |
| 69 | + def rerun_pipeline_step_3(self, request, queryset): # noqa: ANN001 |
| 70 | + self.message_user(request, "Re-ran Pipeline Step 3.", level=messages.SUCCESS) |
| 71 | + |
| 72 | + @admin.action(description="Invalidate Downstream Cache") |
| 73 | + def invalidate_downstream_cache(self, request, queryset): # noqa: ANN001 |
| 74 | + self.message_user(request, "Invalidated downstream cache.", level=messages.SUCCESS) |
| 75 | + |
| 76 | + @admin.action(description="Mark As Reviewed By Operator") |
| 77 | + def mark_as_reviewed_by_operator(self, request, queryset): # noqa: ANN001 |
| 78 | + queryset.update(status="reviewed") |
| 79 | + |
| 80 | + @admin.action(description="Mark As Pending Operator Review") |
| 81 | + def mark_as_pending_operator_review(self, request, queryset): # noqa: ANN001 |
| 82 | + queryset.update(status="pending_review") |
| 83 | + |
| 84 | + @admin.action(description="Export Selected Rows As CSV") |
| 85 | + def export_selected_rows_as_csv(self, request, queryset): # noqa: ANN001 |
| 86 | + self.message_user(request, "Exported as CSV.", level=messages.SUCCESS) |
| 87 | + |
| 88 | + @admin.action(description="Export Selected Rows As JSON") |
| 89 | + def export_selected_rows_as_json(self, request, queryset): # noqa: ANN001 |
| 90 | + self.message_user(request, "Exported as JSON.", level=messages.SUCCESS) |
| 91 | + |
| 92 | + @admin.action(description="Notify Owner Of Selected Rows") |
| 93 | + def notify_owner_of_selected_rows(self, request, queryset): # noqa: ANN001 |
| 94 | + self.message_user(request, "Notified owners.", level=messages.SUCCESS) |
| 95 | + |
| 96 | + # --- 2 detail-only actions (detail button only) ----------------------- # |
| 97 | + # `obj_id` / `str`-shaped third parameter → classifier marks `detail`. |
| 98 | + |
| 99 | + @admin.action(description="Open Detailed Audit View For This Pipeline Run") |
| 100 | + def open_detailed_audit_view(self, request, obj_id: str): # noqa: ANN001 |
| 101 | + self.message_user(request, f"Opened audit view for {obj_id}.", level=messages.INFO) |
| 102 | + |
| 103 | + @admin.action(description="Replay Last Operation On This Pipeline Run") |
| 104 | + def replay_last_operation(self, request, obj_id: str): # noqa: ANN001 |
| 105 | + self.message_user(request, f"Replayed last operation on {obj_id}.", level=messages.INFO) |
0 commit comments