Dataverse Grid Migration - Work In Progress
Last Updated: December 2, 2025
Branch: DVTables
Status: Core Complete, Plugin GridColumns Complete, Template Migration Pending
Overview
Migrating all entity listing pages from legacy table-based templates to the modern Dataverse Grid system with:
- Lazy-loading Turbo Frames
- Column picker for visibility control
- Advanced filtering and sorting
- CSV export capability
- Consistent UI patterns
Completed Phases
Phase 1: Core Simple GridColumns ✅
Created/verified GridColumns classes for simple entities:
RolesGridColumns- Fixedis_systemfield name (wasis_system_role)PermissionsGridColumns- FixedSCOPE_BRANCH_AND_CHILDRENconstantEmailTemplatesGridColumns- Existed, no changes neededGatheringTypesGridColumns- Existed, no changes neededGatheringActivitiesGridColumns- Existed, no changes neededWarrantPeriodsGridColumns- Existed, no changes needed
Phase 2: Core Complex GridColumns ✅
BranchesGridColumns- Haspathcolumn for hierarchy displayAppSettingsGridColumns- Hasvalue_previewfor truncated values
Phase 3: Core Controller Updates ✅
Added DataverseGridTrait and gridData() method to:
RolesControllerPermissionsControllerEmailTemplatesControllerGatheringTypesControllerGatheringActivitiesControllerWarrantPeriodsControllerBranchesController- Special: includescomputeBranchPaths()method for hierarchy
Controllers already done (before this work):
MembersControllerWarrantsControllerAppSettingsController
Phase 4: Core Template Migrations ✅
Updated index.php templates to use dv_grid element:
templates/Roles/index.phptemplates/Permissions/index.phptemplates/EmailTemplates/index.php- Includes sync/discover buttonstemplates/GatheringTypes/index.phptemplates/GatheringActivities/index.phptemplates/WarrantPeriods/index.php- Includes add modaltemplates/Branches/index.phptemplates/AppSettings/index.php- Includes add modal
Phase 5: Core Routes ✅
No explicit routes needed - CakePHP’s fallback routes handle gridData action automatically.
Pending Phases
Phase 6: Activities Plugin - Template Migration
Location: plugins/Activities/
Status: GridColumns classes needed
Controllers to update:
ActivitiesController- Main activities listingActivityGroupsController- Activity group management
Files to create:
plugins/Activities/src/KMP/GridColumns/ActivitiesGridColumns.phpplugins/Activities/src/KMP/GridColumns/ActivityGroupsGridColumns.php
Templates to update:
plugins/Activities/templates/Activities/index.phpplugins/Activities/templates/ActivityGroups/index.php
Phase 7: Awards Plugin - Template Migration ✅ GridColumns Complete
Location: plugins/Awards/
Status: GridColumns complete, template migration needed
GridColumns classes exist:
- ✅
plugins/Awards/src/KMP/GridColumns/AwardsGridColumns.php - ✅
plugins/Awards/src/KMP/GridColumns/RecommendationsGridColumns.php
Controllers to verify/update:
AwardsController- Award types listingRecommendationsController- Already has DataverseGrid workAwardsDomainController- Domain management (GridColumns may be needed)
Templates to update:
plugins/Awards/templates/Awards/index.phpplugins/Awards/templates/Recommendations/index.phpplugins/Awards/templates/AwardsDomain/index.php
Phase 8: Officers Plugin - Template Migration ✅ GridColumns Complete
Location: plugins/Officers/
Status: OfficersGridColumns complete, template migration needed
GridColumns classes exist:
- ✅
plugins/Officers/src/KMP/GridColumns/OfficersGridColumns.php
Controllers to verify/update:
OfficersController- Officers listingOfficesController- Office types listing (GridColumns may be needed)DepartmentsController- Uses coreDepartmentsGridColumns
Templates to update:
plugins/Officers/templates/Officers/index.phpplugins/Officers/templates/Offices/index.php
Phase 9: Waivers Plugin - Template Migration ✅ GridColumns Complete
Location: plugins/Waivers/
Status: WaiverTypesGridColumns complete, template migration needed
GridColumns classes exist:
- ✅
plugins/Waivers/src/KMP/GridColumns/WaiverTypesGridColumns.php
Controllers to verify/update:
WaiversController- Waiver types listing
Templates to update:
plugins/Waivers/templates/WaiverTypes/index.php
Phase 10: Tab-Based Grids
Grids embedded in view pages as tabs (e.g., Member Roles tab, Member Warrants tab).
Already Done:
MembersController::memberRolesGridData()- Roles tab on member viewMembersController::memberWarrantsGridData()- Warrants tab on member view
Additional Core GridColumns Available:
MemberRolesGridColumns- For member roles tabWarrantRostersGridColumns- For warrant rostersGatheringAttendancesGridColumns- For gathering attendance tabs
To Investigate:
- Check if other view pages have tab-based listings that need migration
- Branch view page may have member listing tab
- Role view page may have member listing tab
Implementation Pattern Reference
Controller Pattern
use DataverseGridTrait;
public function initialize(): void
{
parent::initialize();
$this->Authorization->authorizeModel('index', 'add', 'gridData');
}
public function index()
{
// Empty - dv_grid element lazy-loads via gridData
}
public function gridData(CsvExportService $csvExportService)
{
$result = $this->processDataverseGrid([
'gridKey' => 'EntityName.index.main',
'gridColumnsClass' => \App\KMP\GridColumns\EntityNameGridColumns::class,
'baseQuery' => $this->EntityName->find(),
'tableName' => 'EntityName',
'defaultSort' => ['EntityName.name' => 'asc'],
'defaultPageSize' => 25,
'showAllTab' => false,
'canAddViews' => false,
'canFilter' => true,
'canExportCsv' => true,
]);
if (!empty($result['isCsvExport'])) {
return $this->handleCsvExport($result, $csvExportService, 'entity-name');
}
$this->set([
'entityNames' => $result['data'],
'gridState' => $result['gridState'],
// ... other vars
]);
$turboFrame = $this->request->getHeaderLine('Turbo-Frame');
if ($turboFrame === 'entity-name-grid-table') {
$this->set('data', $result['data']);
$this->set('tableFrameId', 'entity-name-grid-table');
$this->viewBuilder()->disableAutoLayout();
$this->viewBuilder()->setTemplate('../element/dv_grid_table');
} else {
$this->set('data', $result['data']);
$this->set('frameId', 'entity-name-grid');
$this->viewBuilder()->disableAutoLayout();
$this->viewBuilder()->setTemplate('../element/dv_grid_content');
}
}
Template Pattern
<?= $this->element('dv_grid', [
'gridKey' => 'EntityName.index.main',
'frameId' => 'entity-name-grid',
'dataUrl' => $this->Url->build(['action' => 'gridData']),
]) ?>
GridColumns Pattern
class EntityNameGridColumns extends BaseGridColumns
{
public static function getColumns(): array
{
return [
'id' => [...],
'name' => [
'key' => 'name',
'label' => 'Name',
'type' => 'string',
'sortable' => true,
'filterable' => true,
'searchable' => true,
'defaultVisible' => true,
'clickAction' => 'navigate:/entity-name/view/:id',
],
// ... more columns
];
}
}
Known Issues
-
AppSettingsController line 154: Type error with
setLayout(false)- should besetLayout(null). Pre-existing issue, not caused by this migration. -
BranchesController path computation: Currently loads all parent branches to compute paths. May need optimization for very large hierarchies.
Testing Checklist
For each migrated grid, verify:
- Grid loads via lazy-loading Turbo Frame
- Sorting works on sortable columns
- Filtering works (both search box and dropdown filters)
- Pagination works
- Column picker shows/hides columns correctly
- CSV export downloads correct data
- Click actions navigate to correct pages
- Add button works (if applicable)
- No JavaScript console errors