Skip to the content.

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:

Completed Phases

Phase 1: Core Simple GridColumns ✅

Created/verified GridColumns classes for simple entities:

Phase 2: Core Complex GridColumns ✅

Phase 3: Core Controller Updates ✅

Added DataverseGridTrait and gridData() method to:

Controllers already done (before this work):

Phase 4: Core Template Migrations ✅

Updated index.php templates to use dv_grid element:

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:

Files to create:

Templates to update:

Phase 7: Awards Plugin - Template Migration ✅ GridColumns Complete

Location: plugins/Awards/ Status: GridColumns complete, template migration needed

GridColumns classes exist:

Controllers to verify/update:

Templates to update:

Phase 8: Officers Plugin - Template Migration ✅ GridColumns Complete

Location: plugins/Officers/ Status: OfficersGridColumns complete, template migration needed

GridColumns classes exist:

Controllers to verify/update:

Templates to update:

Phase 9: Waivers Plugin - Template Migration ✅ GridColumns Complete

Location: plugins/Waivers/ Status: WaiverTypesGridColumns complete, template migration needed

GridColumns classes exist:

Controllers to verify/update:

Templates to update:

Phase 10: Tab-Based Grids

Grids embedded in view pages as tabs (e.g., Member Roles tab, Member Warrants tab).

Already Done:

Additional Core GridColumns Available:

To Investigate:


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

  1. AppSettingsController line 154: Type error with setLayout(false) - should be setLayout(null). Pre-existing issue, not caused by this migration.

  2. 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: