From e59f193ffc14efac4a5fbc548feb399963558e4d Mon Sep 17 00:00:00 2001 From: jwed Date: Sat, 23 May 2026 16:06:49 -0400 Subject: [PATCH] feat(nav): surface AP Groups page; always-fresh device data on edit pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AP Groups page (ApGroups.vue + ApGroupController + UnifiApiClient CRUD methods) has been built but never declared in composer.json's pages list, so it was hidden from the menu. Added it at sort_order=6, between WiFi Networks and Portal. The WiFi Networks page already has per-SSID AP-group assignment via the existing updateApGroups route — that wires into UniFi's standard ap_group_ids field on wlanconf. (UniFi doesn't expose per-AP-only assignment separately; the convention is "make a one-AP group for this AP and assign the SSID to it.") For the "always pull from UniFi on load" guarantee: - getWlans() and getApGroups() are already uncached — fresh on every page load - getDevices() (feeds the AP picker for group membership) is cached for unifi.cache_ttl seconds; both ApGroupController::index and WifiController::index now Cache::forget('unifi:devices') before reading so the device list is always fresh v1.3.0. Co-Authored-By: Claude Opus 4.7 (1M context) --- composer.json | 7 ++++--- src/Http/Controllers/ApGroupController.php | 7 +++++++ src/Http/Controllers/WifiController.php | 5 +++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 82bcb43..d733a49 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dashboard/unifi", "description": "UniFi network management, WiFi stats, and captive portal authentication for the Dashboard platform", - "version": "1.0.0", + "version": "1.3.0", "type": "library", "license": "MIT", "autoload": { @@ -27,8 +27,9 @@ { "label": "Devices", "route_name": "unifi.devices", "icon": "cpu-chip", "permission": "unifi.stats", "sort_order": 3 }, { "label": "Clients", "route_name": "unifi.clients", "icon": "users", "permission": "unifi.stats", "sort_order": 4 }, { "label": "WiFi Networks", "route_name": "unifi.wifi", "icon": "wifi", "permission": "unifi.manage", "sort_order": 5 }, - { "label": "Portal", "route_name": "unifi.portal.settings", "icon": "shield-check", "permission": "unifi.auth", "sort_order": 6 }, - { "label": "Webhooks", "route_name": "unifi.webhooks.index", "icon": "bell-alert", "permission": "unifi.settings", "sort_order": 7 }, + { "label": "AP Groups", "route_name": "unifi.ap-groups.index", "icon": "rectangle-stack", "permission": "unifi.manage", "sort_order": 6 }, + { "label": "Portal", "route_name": "unifi.portal.settings", "icon": "shield-check", "permission": "unifi.auth", "sort_order": 7 }, + { "label": "Webhooks", "route_name": "unifi.webhooks.index", "icon": "bell-alert", "permission": "unifi.settings", "sort_order": 8 }, { "label": "Settings", "route_name": "unifi.settings", "icon": "cog-6-tooth", "permission": "unifi.settings", "sort_order": 99 } ], "permissions": [ diff --git a/src/Http/Controllers/ApGroupController.php b/src/Http/Controllers/ApGroupController.php index 81609b1..2ead2e9 100644 --- a/src/Http/Controllers/ApGroupController.php +++ b/src/Http/Controllers/ApGroupController.php @@ -5,12 +5,19 @@ namespace Dashboard\Unifi\Http\Controllers; use Dashboard\Unifi\Services\UnifiApiClient; use Illuminate\Http\Request; use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\Cache; use Inertia\Inertia; class ApGroupController extends Controller { public function index(UnifiApiClient $unifi) { + // Always pull fresh from the controller on this page so the + // operator never edits against a stale snapshot. getApGroups() + // and getWlans() aren't cached, but getDevices() (which feeds + // the AP picker) is — bust it explicitly. + Cache::forget('unifi:devices'); + try { $groups = collect($unifi->getApGroups())->map(fn ($g) => [ 'id' => $g['_id'], diff --git a/src/Http/Controllers/WifiController.php b/src/Http/Controllers/WifiController.php index 7af6f31..f8019fa 100644 --- a/src/Http/Controllers/WifiController.php +++ b/src/Http/Controllers/WifiController.php @@ -13,6 +13,11 @@ class WifiController extends Controller { public function index(UnifiApiClient $unifi) { + // Always pull fresh device data on this page so AP-group / SSID + // edits never go out against a stale snapshot. getWlans() and + // getApGroups() aren't cached, but getDevices() is. + \Illuminate\Support\Facades\Cache::forget('unifi:devices'); + try { $wlans = collect($unifi->getWlans())->map(fn ($w) => $this->mapWlan($w))->values();