V1 Grid Buttons — Complete Catalog and V2 Porting¶
As of: code audit 2026-07-12 against
httpdocs/(V1, Yii 1.1) andfrontend-v2/+laravel/(V2). Purpose: porting baseline — every button of the V1 main grids with function, RBAC operation and V2 status.
The V1 grids are the most feature-rich part of the application: toolbar buttons, selection buttons (acting on checkbox-selected rows) and row buttons. Every button is bound to an authitem operation. This catalog enumerates all of them and defines the harmonized V2 implementation.
1. Shared V1 infrastructure¶
Each grid consists of three files (admin_v2.php = toolbar + modals + JS, _admin_v2.php = grid widget + selection buttons, _columns_v2.php = columns + row buttons) and uses central helpers: GridViewHelper::renderGrid()/buildBulkActions()/buildMultiDeleteButton() (protected/components/GridViewHelper.php), the row-button factories in GridColumnsHelper (View/Update/Delete/Clone/Report/DCC), KTbBulkActions (selection buttons incl. "Delete selected/Delete all" split) and KCCheckBoxColumn (checkbox column).
Dynamic report buttons (master and detail context, incl. DCC variants) come from report_setting via AdminReportSetting::getReportMasterButtons() / getReportDetailButtons() with role/group filtering — no button is hardcoded. In V2 this already exists as the report-context prop on TableMaster.
2. Button catalog per grid¶
Type legend: T = toolbar (no selection), S = selection button (marked rows), R = row button.
2.1 Inventory (frontendInventory, 25 buttons)¶
| # | Button | Type | Function | RBAC | V2 status |
|---|---|---|---|---|---|
| 1 | Create Inventory | T | new inventory | inventory_edit |
✅ (now permission-gated) |
| 2 | Master reports (dynamic) | T/S | report for selection/all | report_setting roles | ✅ report-context |
| 3–4 | Export All / Export Filtered | T | export | inventory_view |
✅ |
| 5 | Update hierarchy view | T | rebuild hierarchy | inventory_* |
➖ obsolete (V2 computes live) |
| 6–7 | Columns / Filter options | T | column config / filter sidebar | — | ✅ |
| 8 | Change User / Add to Location | S | new location per selected inventory | inventory_rental_edit |
✅ faithfully restored (see §4) |
| 9 | Add to Notepad | S | note per selected inventory | notepad_edit |
🔴 open (follow-up) |
| 10 | Create Order | S | order from selection | bookings_edit |
🔴 open (follow-up) |
| 11 | Download Documents | S | bulk ZIP of documents | document_download |
🔴 open (follow-up, see PR #2780) |
| 12 | METTEAM sync (selected/all) | S | MSSQL sync | configure_METTEAM_synchronisation |
🔴 open (integrations phase) |
| 13 | Delete Selected / Delete all | S | bulk delete | inventory_delete |
✅ harmonized (useGridActions); "delete all over filter" open |
| 14–25 | Row: details, view, QR view, update, clone, add child, show masters/childs/hierarchy, detail reports, delete | R | per row | inventory_view/edit/delete |
partial (view/trace/reports/files ✅; clone/hierarchy buttons open) |
2.2 Calibration (frontendCalibration, 13 buttons)¶
New Calibration (calibration_edit) ✅ · master reports/export/columns/filter ✅ · Delete Selected (calibration_delete) ✅ harmonized · Release Documents per DMS column (dms_edit) 🟡 backend exists (documents/bulk-approve), grid UI open · row: view, update, clone, detail reports, DCC XML validation, delete — view/reports/files ✅; clone + DCC validation in grid open.
2.3 Locations/Rental (frontendRental, 10 buttons)¶
Create Location (location_edit) ✅ (now gated) · master reports/export/columns/filter ✅ · Delete Selected / Delete all (location_delete) ✅ new: POST /locations/bulk-delete (deletes per model → current-record promotion stays correct) · row: view, update, detail reports, delete ✅.
2.4 Inventory→Location subgrid (4 buttons)¶
Create Rental (inventory_rental_edit), row view/update/delete (inventory_rental_view/edit/delete) — ✅ in V2 as the locations tab of the inventory detail page (loan, return, history; PR #2782).
2.5 Customers (frontendCustomer, 8 buttons)¶
Create Customer (customers_edit) ✅ (now gated) · export/columns/filter ✅ · no selection buttons in V1 (checkbox column without action) — V2 additionally offers bulk delete/export (extension) · row: details, inventories link (badge), view, update, delete — details/view ✅; inventories badge open.
2.6 Contacts (frontendContact, 6 buttons)¶
Create/export/columns (contact_edit) ✅ (now gated) · Delete Selected (contact_delete) ✅ new: POST /contacts/bulk-delete; single delete now also requires contact_delete (V1 parity, previously contact_edit) · row: view, update (modal), clone, delete ✅ (delete button now gated); clone: backend duplicate exists, grid button open.
2.7 Orders/Bookings (frontendBooking, 10 buttons)¶
Create Order (bookings_edit) ✅ · master reports/export/columns/filter ✅ · Delete Selected (bookings_delete) ✅ harmonized (now bulk endpoint instead of per-row DELETE loop) · row: details/view/update/detail reports (with "Choose Part" modal)/delete — basics ✅, "Choose Part" open.
2.8 Articles (frontendArticle, 5 buttons)¶
Create (article_edit), columns, Delete Selected (article_delete), row view/update/delete — 🔴 no article grid in V2 yet (domain module open).
2.9 Repairs (frontendRepair, 9 buttons)¶
Create (repair_edit) ✅ · export/columns/filter ✅ · Delete Selected (repair_delete) ✅ new: POST /repairs/bulk-delete · row view/update/detail reports/delete ✅.
2.10 Prices (frontendPrice, 7 buttons)¶
Create (price_create) · columns/filter · Delete Selected (price_delete) ✅ harmonized · row view/update/clone (price_create)/delete — clone button open (backend duplicate exists).
2.11 Device types (frontendType, 8 buttons)¶
New Type (types_create) · Make Types ✅ shipped as "Aus Bestand ableiten" — dialog with preview (POST /device-types/derive), its own operation types_derive instead of types_create, assigned to no role by default · columns/filter · Delete Selected (types_delete) ✅ harmonized (now bulk endpoint) · row inventories badge/view/update/delete — basics ✅.
2.12 Notes (frontendNotepad, 9 buttons)¶
Create (notepad_edit) · export · columns/filter · Delete Selected (notepad_delete) ✅ harmonized · row add/view/view-inventory/update/delete — basics ✅; "send e-mail" checkbox in edit modal open.
Note:
frontendWikiandfrontendTicketdo not exist as V1 grids. Tickets/projects are V2-only developments (button permission gating already implemented there).
Total: ~114 buttons across 12 grids.
3. Selection mechanics (V1 → V2)¶
V1: KCCheckBoxColumn as column 0 (.select-on-check), read via getCheckedRowsIds(). Selection buttons alert on empty selection. The "Delete all" split dropdown processes the complete filtered set with a progress bar. There is no separate "active row" concept — it is a pure multi-select checkbox model; all selection buttons act on all marked rows.
V2: PrimeVue selection (v-model:selection) with a checkbox column whenever bulk actions exist; bulk buttons appear in the toolbar on selection. Since this change, bulk actions and extra columns are filtered against the session operations via the permission field (TableMaster.vue, visibleBulkActions/visibleExtraColumns) — exactly V1's "button only with operation" semantics. "Delete all over the filtered set" is still open.
4. Deep dive: "Add to Location" (V1 "Change User")¶
The most important selection button of the inventory grid — exactly reconstructed V1 flow (frontendInventory/_admin_v2.php:15, FrontendRentalController::actionAddToLocation, FrontendRentalController.php:1716):
- Select inventories via grid checkboxes → "Change User" button (gated:
inventory_rental_edit). - JS POSTs the selected
MTAGs[]toaddToLocation→ the server renders the location form (frontendInventory/location/_form.php) into the modal. The "element selection module" is not a picker grid — element selection is strictly the grid checkbox selection; the modal contains only the form built fromfield_configuration(getEditFields(true)). The selection cannot be changed inside the modal. - Checkbox "Copy values from previous location entry" (
_form.php:79): locks allallow_copy=1fields exceptLTAG, MTAG, L2809, L2810, L2815, status— locked fields are not submitted and are filled per device from its most recent previous entry on save. - Save (
:1718–1809): one new location row per inventory inside a transaction — new LTAG,L2815=1(becomes current location),customer_KTAGfrom the inventory, field defaults viaInventoryHelper::setDefaultValue(). No e-mail in this path.
V2 implementation (this change): the "Standort/Leihe" bulk action in the inventory grid (gated location_edit, since the endpoint POST /locations/bulk-assign runs under it) opens a dialog with the registry-driven location form (DynamicForm resource="locations", same as the location create page). inventory_id/is_active/id are hidden (they come from the selection, are fixed to 1, or generated). The checkbox "copy values from the last location entry" locks the allow_copy fields (except the V1 protection list id, inventory_id, location_date, location_time, is_active, status); locked and empty fields are — as in V1 — not submitted, so the server fills them per device from its last entry or the field defaults. Additionally (V2 extension from PR #2782): optional availability check; occupied devices are skipped and reported.
5. Harmonized V2 architecture¶
All grid buttons now follow one pattern ("master-grid functions", opt-in per page):
| Building block | Purpose | V1 counterpart |
|---|---|---|
TmBulkAction.permission / TmExtraColumn.permission |
RBAC gating per button/column in TableMaster | visible callbacks + accessRules |
useGridActions |
standard selection buttons (delete via bulk-delete endpoint, export) defined once instead of duplicated 10× |
buildMultiDeleteButton |
report-context + useGridReports |
master/detail/label/DCC reports, data-driven | getReportMasterButtons/getReportDetailButtons |
file-context + useGridFiles |
per-row files (DMS categories) | file management columns |
page toolbar with auth.hasPermission() |
gated create/toolbar buttons | accessRules of the create actions |
New backend endpoints (V1 parity): POST /locations/bulk-delete (location_delete, per-model deletes → promotion events), POST /repairs/bulk-delete (repair_delete), POST /contacts/bulk-delete + single delete under contact_delete (previously contact_edit).
Fixed inconsistencies: booking/repair/price/device-type/location/notepad previously deleted via per-row DELETE loops (sometimes despite an existing bulk endpoint) — now uniformly via bulk-delete; buttons were rendered unprotected (backend 403 only) — now permission-gated.
6. Open follow-ups (prioritized)¶
- Add to Notepad (selection → note per inventory,
notepad_edit). - Release Documents in the calibration grid (
dms_edit) — backenddocuments/bulk-approveexists. - Create Order from selection (
bookings_edit). - Bulk download (ZIP) (
document_download) — already noted as follow-up to PR #2780. - Bulk status change from the grid — backend
POST /inventories/status-batchexists without UI. - Clone/duplicate row buttons —
duplicateendpoints exist for inventories/device-types/calibrations/prices/bookings/contacts. - "Delete all over filtered set" with progress (V1: inventory/rental/type).
- ~~Make Types~~ ✅ done (see 2.11) · METTEAM sync buttons (integrations phase), article grid (domain module).