Resource Management
This page covers how to manage resources in the admin panel: clients, brands, campaigns (production runs), trackers, and locations.
Campaign Management (Clients, Brands, Campaigns)
Clients, brands, and campaigns (production runs) are all managed from a single page — Campaign Management, at /clients — rather than separate list pages. It presents four linked, drill-down columns:
- Clients: paginated and searchable
- Brands: brands belonging to the selected client
- Campaigns: parent production runs ("batches") belonging to the selected brand
- Child runs: child production runs belonging to the selected campaign/parent batch
Selecting an item in one column loads and enables the next column. Each column supports adding, editing, and deleting items (edit/delete actions appear on hovering a card), plus its own text filter. On narrower screens the four columns stack into full-width, independently scrollable rows instead of sitting side by side, and selecting an item auto-scrolls the next column into view.
Clients
- Create, edit, and delete clients
- Each client card shows its brand count
- Deleting a client is blocked (with a reason shown in the UI) while it still has brands
Brands
- Create, edit, and delete brands for the selected client
- Each brand card shows its campaign (production run) count
- Deleting a brand is blocked while it still has campaigns
Campaigns (Production Runs)
- Create, edit, and delete campaigns for the selected brand
- Each campaign card shows its date range, number of child runs, and total tracker count (own + all children), plus a status badge (for example, active/upcoming/ended, derived from its start/end dates)
- Each campaign card links directly to its trackers (
/trackers/{id}) and to its locations, pre-filtered to that campaign (/locations?campaign_id={id}) - Deleting a campaign is blocked while it has trackers assigned or child runs
Child Runs
- Create, edit, and delete child runs under the selected campaign/parent batch
- Child runs behave like campaigns for tracker/location purposes but are nested under a parent's date window
- Creating or editing a child run pre-fills the parent's date window as context
CSV Import
Trackers are imported into a specific campaign or child run, not the top-level page. See the Tracker CSV Import guide.
Tracker Management
There's no longer a standalone, global "Trackers" list — the /trackers route now points users to Campaign Management, since a tracker always belongs to a specific campaign or child run. From there, opening a campaign or child run's tracker link (/trackers/{id}) shows that run's tracker view, which allows you to:
- View trackers in a sortable list or card layout (toggle persists per browser)
- Sort by tracker name, MAC address, or last report received time (ascending/descending)
- Create, edit, and delete trackers within that run
- Move one or more trackers to a different run — by drag-and-drop onto a radial "move wheel," by pasting a list of tracker identifiers (paste-select), or via the move dialog
- Import trackers from a CSV file (see below)
- Export the current run's trackers to CSV
Location Management
The admin panel allows you to manage two types of locations with customizable geofence settings, from the /locations page:
Delivery Locations
Delivery locations are places where trackers are delivered. The delivery locations section allows you to:
- Create new delivery locations
- Edit existing delivery locations
- Delete delivery locations
- View delivery locations on a map with geofence visualization
- Configure custom geofence sizes for each location
Storage Locations
Storage locations are places where trackers are stored. The storage locations section allows you to:
- Create new storage locations
- Edit existing storage locations
- Delete storage locations
- View storage locations on a map with geofence visualization
- Configure custom geofence sizes for each location
Locations can be filtered by brand and by campaign, and the campaign filter is pre-applied when arriving from a campaign card's "locations" link (/locations?campaign_id={id}) in Campaign Management.
Geofence Configuration
Both delivery and storage locations support customizable geofence sizes:
Geofence Settings
- Default Size: 100 meters
- Range: 100m to 1000m
- Increments: 50m steps (100m, 150m, 200m, 250m, etc.)
- Purpose: Defines the radius around each location for geofence detection
Setting Geofence Size
- When creating or editing a location, use the "Geofence Size (meters)" dropdown
- Select from predefined options ranging from 100m (Default) to 1000m (Maximum)
- The map will show a real-time preview of the geofence circle
- The geofence size is displayed in the location details view
Map Visualization
- Interactive Maps: Both create/edit and detail view pages show the geofence as a colored circle
- Color Coding: Blue circles for delivery locations, green circles for storage locations
- Real-time Updates: The circle size updates immediately when changing the geofence setting
- Transparency: Semi-transparent fill allows viewing map details underneath
Relationship Navigation
The admin panel implements a consistent pattern for navigating between related resources using clickable cards and links, rather than a dedicated "field" component per relationship:
- Client → Brands: selecting a client card in Campaign Management loads its brands into the next column
- Brand → Campaigns: selecting a brand card loads its campaigns into the next column
- Campaign → Child runs: selecting a campaign card loads its child runs into the next column
- Campaign/Child run → Trackers: each campaign/child-run card links directly to
/trackers/{id} - Campaign/Child run → Locations: each campaign/child-run card links directly to
/locations?campaign_id={id} - User → Clients: each user card shows the clients they have access to as chips
Sorting and Caching
The admin panel supports sorting data in tables/cards by various columns. The sorting functionality is implemented both in the frontend and backend:
- Frontend Implementation:
- Each list/card view maintains its own sorting state (field and order), persisted to local storage per view
- Visual indicators show the current sort field and direction
- Clicking a sortable column header (or card-sort menu option) toggles between ascending and descending order
-
Clicking a different column/option sets that as the new sort field with ascending order
-
Backend Implementation:
- API endpoints accept
sort_fieldandsort_orderparameters - Sorting is applied before pagination to ensure consistent results
- Special handling for null values ensures they appear at the end of sorted lists
-
For relationship-based sorting, the backend performs additional queries to fetch the related data for sorting
-
Caching Mechanism:
- The backend implements a comprehensive caching strategy that properly handles sorted data
- Cache keys include sorting parameters to ensure different sort configurations get different cache entries
- Sorting is applied before caching, so cached data is already properly sorted
- When retrieving from cache, the correctly sorted data is returned without needing to re-sort
- Cache invalidation occurs when records are created, updated, or deleted