Wallboard Designer — Setup & Widget Guide
Real-time wallboards for contact centers, ops floors, and command centers. Full CRUD over layouts, widgets, and displays via a WallboardEngine class and /crm/api/wallboard.php JSON endpoint. Wire your TVs, monitors, and supervisor desks to the same shared layouts that update in real time.
Overview
Wallboard Designer lets tenant admins build grid-based real-time dashboards — the kind you'd put on TVs around a call center or ops floor. Each wallboard is a layout containing widgets. Widgets can be numeric metrics, charts, tables, gauges, maps, clocks, text, images, iframes, or lists. A display device points at one layout and auto-refreshes on a configurable interval.
V2's scope is the CRUD backbone: creating, reading, updating, deleting, duplicating. The visual drag-and-drop designer canvas is a V2.1 deliverable; for now, widget positions are set via the API or the placement fields on each widget row.
What's new in V2
Full CRUD surface
WallboardEngine ships createLayout, updateLayout, deleteLayout, duplicateLayout, setDefaultLayout, addWidget, updateWidget, removeWidget, addDisplay, removeDisplay, and seedDefaultsForTenant. /crm/api/wallboard.php is the JSON endpoint that wraps each method. Every operation validates tenant ownership before INSERT / UPDATE / DELETE.
Tenant stats from the canonical tables
WallboardEngine::tenantStats() queries wallboard_layouts, wallboard_widgets, wallboard_displays, and wallboard_alerts directly. Real numbers, real tenant scope, real-time refresh.
Tenant isolation on every write
Every engine method validates the layout_id / widget_id / display_id against the current tenant before the INSERT. Cross-tenant crafted POSTs silently match zero rows and return a "not found" error without leaking whether the row exists elsewhere.
Admin gates on destructive actions
Only tenant admins (role_id 1/2/3) can delete a layout, set the tenant default, or register a display. Non-admin agents can create their own layouts and edit layouts they created.
Idempotent seeder
/admin/view-wallboard-state.php has a Seed defaults button that populates 6 widget templates, 3 themes, and a starter layout for any tenant with zero of either. Uses INSERT ... WHERE NOT EXISTS so re-running doesn't create duplicates.
State viewer for supervisor oversight
Six sections: schema health, activity stats, layouts, displays, widget templates, recent alerts. Sysadmin-only. No MySQL CLI needed for any ops or audit task.
Layouts
A layout is a single wallboard. Key fields on wallboard_layouts:
- layout_name — up to 200 chars
- grid_columns / grid_rows — up to 96×48 cells. Widget positions live in this coordinate system.
- background_color — 7-char hex (validated via
WallboardEngine::normalizeHexColor()) - is_public — visible to every tenant user (true) or just creator + admins (false)
- is_default — exactly one per tenant at a time; setDefaultLayout clears the flag from others in a transaction
- rotation_enabled / rotation_interval_seconds / rotation_sequence — auto-rotate between layouts on a display (V2.1 wires this into the public view endpoint)
Widgets
Widgets live inside a layout. Ten types: metric, chart, table, gauge, map, clock, text, image, iframe, list. Key fields:
- position_x / position_y / width / height — grid cells. A 24-column grid with a 6-wide widget at x=0 means the widget takes the left quarter of the screen.
- z_index — overlap ordering
- data_source — free-form string identifying where the widget's data comes from (api, database, custom)
- refresh_interval_seconds — how often the widget re-queries (5-3600)
- display_config — JSON blob with type-specific settings. Charts store chart type, thresholds, axes; tables store column lists; gauges store min/max/threshold colors.
- background_color / text_color / border_* / opacity — per-widget styling overrides
Display devices
A display is a physical TV / monitor running a browser. Register each one in the Display Management tab or via add_display API:
- device_name / device_location — "Ops floor TV 1" / "Second floor lobby"
- device_identifier — you can supply your own (MAC address, unique string) or let V2 auto-generate one like
RUBI-A1B2C3D4 - assigned_layout_id — which wallboard this display shows (can be reassigned at any time)
- screen_width / screen_height / orientation — helps future V2.1 designer render in the right aspect ratio
- auto_refresh_enabled / refresh_interval_minutes — browser-side refresh cadence
- last_heartbeat / status — V2.1 will ship the heartbeat endpoint; status flips online / offline / error
Permissions
| Action | Non-admin agent | Tenant admin (1/2/3) |
|---|---|---|
| List layouts | ✅ all tenant layouts | ✅ all tenant layouts |
| Create layout | ✅ | ✅ |
| Edit layout | ⚠️ only their own | ✅ any |
| Delete layout | ❌ | ✅ |
| Set tenant default | ❌ | ✅ |
| Add / remove display | ❌ | ✅ |
| Add / edit / remove widget | ✅ on their own layouts | ✅ on any tenant layout |
| Seed defaults | ❌ | ✅ (via sysadmin state viewer) |
Quick start ≈ 15 minutes
- Activate the module at RubiMine. $99.99/mo.
- Sysadmin verifies schema at
/admin/run-wallboard-v2-migration.php. All 8 tables should show ✅. - Seed defaults from /admin/view-wallboard-state.php. Picks tenant, clicks Seed. Starter layout + 6 templates + 3 themes land in one click.
- Open the CRM Wallboards tab as a tenant admin. The starter layout "My First Wallboard" appears in the grid.
- Click Create Wallboard to add another. Name, description, grid dims, background color — save.
- Register a display in the Display Management tab. Supply name, location, resolution, and the layout to show.
- Star your tenant default — clicking the star sets the tenant-wide default layout, which any new display without an assignment falls back to.
API endpoints
All on /crm/api/wallboard.php. Session-authenticated, tenant-scoped.
Layouts
POST action=list_layouts POST action=get_layout (layout_id) → includes widgets array POST action=create_layout (layout_name, layout_description?, grid_columns?, grid_rows?, background_color?, is_public?) POST action=update_layout (layout_id, layout_name?, ...) POST action=set_default_layout (layout_id) — admin only POST action=delete_layout (layout_id) — admin only POST action=duplicate_layout (layout_id)
Widgets
POST action=add_widget (layout_id, widget_type, widget_title?, position_x?, position_y?, width?, height?, data_source?, refresh_interval_seconds?, display_config?) POST action=update_widget (widget_id, ...) POST action=remove_widget (widget_id)
Templates / themes / displays
POST action=list_widget_templates POST action=list_themes POST action=list_displays POST action=add_display (device_name, device_location?, device_identifier?, screen_width?, screen_height?, orientation?, assigned_layout_id?) — admin only POST action=remove_display (display_id) — admin only
Known limitations (V2)
- Visual drag-and-drop designer — the Designer tab's grid canvas is still a V1 placeholder. V2 ships CRUD; V2.1 adds drag-to-place / drag-to-resize / snap-to-grid.
- Public view endpoint —
/wallboard-view.php?display=<identifier>for display devices to render without a login session is a V2.1 ship. Today, display devices need a logged-in session. - Heartbeat endpoint — display status stays at "offline" because the heartbeat receiver isn't live. V2.1 adds
POST /api/wallboard/heartbeat. - Widget data fetching — the engine stores
data_source+data_querybut doesn't execute them server-side. Widgets are expected to fetch their own data (e.g. via Chart.js + a separate API endpoint). A unifiedPOST action=fetch_widget_datais on the V2.1 roadmap. - Alert rules —
wallboard_alert_history+ alert_condition field exist but nothing evaluates them yet. V2.1 will add a cron-driven alert evaluator. - Rotation —
rotation_enabled+rotation_sequenceare stored but the public view doesn't rotate yet. Part of the V2.1 view endpoint. - Data sources —
wallboard_data_sourcestable exists for future database / API / webhook sources; V2 doesn't populate it automatically.
Frequently asked questions
What does the engine do?
tenantStats() reads the canonical wallboard_layouts, wallboard_widgets, wallboard_displays, and wallboard_alerts tables for live counts.How is tenant isolation enforced?
WHERE id = ? AND tenant_id = ?; cross-tenant deletes match zero rows.Can agents edit admin wallboards?
What widget types are supported?
How do display devices work?
wallboard_displays with an identifier, assigned layout, resolution, refresh interval. Heartbeat endpoint is V2.1.Is the drag-and-drop designer in V2?
How do I seed a new tenant?
/admin/view-wallboard-state.php, pick the tenant and click Seed. Idempotent (INSERT ... WHERE NOT EXISTS). Seeds 6 templates + 3 themes + one starter layout.How do public wallboards work?
How much does this cost?
Ready to build wallboards that actually persist?
Activate, verify schema, seed, create. Your first wallboard in 15 minutes.