Skip to content

V1 Grid Buttons — Complete Catalog and V2 Porting

As of: code audit 2026-07-12 against httpdocs/ (V1, Yii 1.1) and frontend-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: frontendWiki and frontendTicket do 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):

  1. Select inventories via grid checkboxes → "Change User" button (gated: inventory_rental_edit).
  2. JS POSTs the selected MTAGs[] to addToLocation → 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 from field_configuration (getEditFields(true)). The selection cannot be changed inside the modal.
  3. Checkbox "Copy values from previous location entry" (_form.php:79): locks all allow_copy=1 fields except LTAG, MTAG, L2809, L2810, L2815, status — locked fields are not submitted and are filled per device from its most recent previous entry on save.
  4. Save (:1718–1809): one new location row per inventory inside a transaction — new LTAG, L2815=1 (becomes current location), customer_KTAG from the inventory, field defaults via InventoryHelper::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)

  1. Add to Notepad (selection → note per inventory, notepad_edit).
  2. Release Documents in the calibration grid (dms_edit) — backend documents/bulk-approve exists.
  3. Create Order from selection (bookings_edit).
  4. Bulk download (ZIP) (document_download) — already noted as follow-up to PR #2780.
  5. Bulk status change from the grid — backend POST /inventories/status-batch exists without UI.
  6. Clone/duplicate row buttonsduplicate endpoints exist for inventories/device-types/calibrations/prices/bookings/contacts.
  7. "Delete all over filtered set" with progress (V1: inventory/rental/type).
  8. ~~Make Types~~ ✅ done (see 2.11) · METTEAM sync buttons (integrations phase), article grid (domain module).