Phase 14: Admin UI
Build the full admin interface: dashboard with KPI widgets, license list/edit screens using WP_List_Table, and a Settings API–backed configuration page.
Files Written
Section titled “Files Written”src/Admin/Menu.phpsrc/Admin/Screens/DashboardScreen.phpsrc/Admin/Screens/LicenseListTable.phpsrc/Admin/Settings/SettingsPage.php
Menu Registration
Section titled “Menu Registration”Menu registers all admin pages in a admin_menu hook and sets up the Settings API in admin_init:
License Manager (top-level)├── Dashboard├── Licenses├── Generators├── Subscriptions├── API Keys└── SettingsAll save handlers call check_admin_referer() and current_user_can('manage_options') before processing any $_POST data.
DashboardScreen
Section titled “DashboardScreen”Four KPI widgets rendered in a 2×2 CSS grid:
| Widget | Data |
|---|---|
| Active Licenses | Count of status = 1 |
| Expiring Soon | Count expiring within 30 days |
| Active Seats | Count of active machines |
| Revenue (MTD) | Sum of completed renewals this month |
Below the KPIs: “Recent Activations” table (last 10 activation log entries) and “Active Anomalies” banner (fires AnalyticsService::detect_anomalies() and highlights any hits).
LicenseListTable
Section titled “LicenseListTable”Extends WP_List_Table. Columns:
| Column | Notes |
|---|---|
cb | Checkbox for bulk actions |
license_key | Truncated: ABCD-****-****-WXYZ + copy button |
status | <span class="wplm-badge wplm-status-{n}"> |
product_id | WooCommerce product name if available |
activation_count | n / max |
expires_at | Human date or “Never” |
created_at | Human date |
Bulk actions: bulk-revoke, bulk-suspend, bulk-export (CSV).
render_page() dispatches to the list view or the edit form based on the presence of $_GET['id'].
Edit form: Shows all license fields (status, max_activations, expires_at, notes), submits via POST to admin-post.php?action=wplm_save_license with nonce wplm_save_license.
SettingsPage
Section titled “SettingsPage”Uses the WordPress Settings API. Six sections:
| Section | Fields |
|---|---|
| General | License server name, site URL override |
| Security | Ed25519 public key display, keypair re-roll button, AES key status |
| Activation | Default max activations, overage strategy, heartbeat interval, zombie window |
| Monitoring | Anomaly detection on/off, thresholds |
| Subscriptions | Default billing periods, trial days, grace period |
| Dunning | Retry schedule (days), max retries, notification emails |
validate_settings() sanitizes all inputs: absint() for integers, sanitize_text_field() for strings, esc_url_raw() for URLs.