Plugin UI Components
Configure how your plugin's data is displayed in the NetAlertX web interface.
Overview
Plugin results are displayed in the UI via the Plugins page and Device details tabs. You control the appearance and functionality of these displays by defining database_column_definitions in your plugin's config.json.
Each column definition specifies: - Which data field to display - How to render it (label, link, color-coded badge, etc.) - What CSS classes to apply - What transformations to apply (regex, string replacement, etc.)
Column Definition Structure
{
"column": "Object_PrimaryID",
"mapped_to_column": "devMac",
"mapped_to_column_data": null,
"css_classes": "col-sm-2",
"show": true,
"type": "device_mac",
"default_value": "",
"options": [],
"options_params": [],
"localized": ["name"],
"name": [
{
"language_code": "en_us",
"string": "MAC Address"
}
]
}
Properties
| Property | Type | Required | Description |
|---|---|---|---|
column |
string | YES | Source column name from data contract (e.g., Object_PrimaryID, Watched_Value1) |
mapped_to_column |
string | no | Target database column if mapping to a table like CurrentScan |
mapped_to_column_data |
object | no | Static value to map instead of using column data |
css_classes |
string | no | Bootstrap CSS classes for width/spacing (e.g., "col-sm-2", "col-sm-6") |
show |
boolean | YES | Whether to display in UI (must be true to appear) |
type |
string | YES | How to render the value (see Render Types) |
default_value |
varies | YES | Default if column is empty |
options |
array | no | Options for select/threshold/replace/regex types |
options_params |
array | no | Dynamic options from SQL or settings |
localized |
array | YES | Which properties need translations (e.g., ["name", "description"]) |
name |
array | YES | Display name in UI (localized strings) |
description |
array | no | Help text in UI (localized strings) |
maxLength |
number | no | Character limit for input fields |
Render Types
Display-Only Types
These render as read-only display elements:
label
Plain text display (read-only).
{
"column": "Watched_Value1",
"show": true,
"type": "label",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Status"}]
}
Output: online
device_mac
Renders as a clickable link to the device with the given MAC address.
{
"column": "ForeignKey",
"show": true,
"type": "device_mac",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Device"}]
}
Input: aa:bb:cc:dd:ee:ff
Output: Clickable link to device details page
device_ip
Resolves an IP address to a MAC address and creates a device link.
{
"column": "Object_SecondaryID",
"show": true,
"type": "device_ip",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Host"}]
}
Input: 192.168.1.100
Output: Link to device with that IP (if known)
device_name_mac
Creates a device link with the target device's name as the link label.
{
"column": "Object_PrimaryID",
"show": true,
"type": "device_name_mac",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Device Name"}]
}
Input: aa:bb:cc:dd:ee:ff
Output: Device name (clickable link to device)
url
Renders as a clickable HTTP/HTTPS link.
{
"column": "Watched_Value1",
"show": true,
"type": "url",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Endpoint"}]
}
Input: https://example.com/api
Output: Clickable link
url_http_https
Creates two links (HTTP and HTTPS) as lock icons for the given IP/hostname.
{
"column": "Object_SecondaryID",
"show": true,
"type": "url_http_https",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Web Links"}]
}
Input: 192.168.1.50
Output: 🔓 HTTP link | 🔒 HTTPS link
textarea_readonly
Multi-line read-only display with newlines preserved.
{
"column": "Extra",
"show": true,
"type": "textarea_readonly",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Details"}]
}
Interactive Types
textbox_save
User-editable text box that persists changes to the database (typically UserData column).
{
"column": "UserData",
"show": true,
"type": "textbox_save",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Notes"}]
}
Styled/Transformed Types
label with threshold
Color-codes values based on ranges. Useful for status codes, latency, capacity percentages.
{
"column": "Watched_Value1",
"show": true,
"type": "threshold",
"options": [
{
"maximum": 199,
"hexColor": "#792D86" // Purple for <199
},
{
"maximum": 299,
"hexColor": "#5B862D" // Green for 200-299
},
{
"maximum": 399,
"hexColor": "#7D862D" // Orange for 300-399
},
{
"maximum": 499,
"hexColor": "#BF6440" // Red-orange for 400-499
},
{
"maximum": 999,
"hexColor": "#D33115" // Dark red for 500+
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "HTTP Status"}]
}
How it works:
- Value 150 → Purple (≤199)
- Value 250 → Green (≤299)
- Value 350 → Orange (≤399)
- Value 450 → Red-orange (≤499)
- Value 550 → Dark red (>500)
replace
Replaces specific values with display strings or HTML.
{
"column": "Watched_Value2",
"show": true,
"type": "replace",
"options": [
{
"equals": "online",
"replacement": "<i class='fa-solid fa-circle' style='color: green;'></i> Online"
},
{
"equals": "offline",
"replacement": "<i class='fa-solid fa-circle' style='color: red;'></i> Offline"
},
{
"equals": "idle",
"replacement": "<i class='fa-solid fa-circle' style='color: yellow;'></i> Idle"
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Status"}]
}
Output Examples:
- "online" → 🟢 Online
- "offline" → 🔴 Offline
- "idle" → 🟡 Idle
regex
Applies a regular expression to extract/transform values.
{
"column": "Watched_Value1",
"show": true,
"type": "regex",
"options": [
{
"type": "regex",
"param": "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "IP Address"}]
}
Input: Host: 192.168.1.100 Port: 8080
Output: 192.168.1.100
eval
Evaluates JavaScript code with access to the column value (use ${value} or {value}).
{
"column": "Watched_Value1",
"show": true,
"type": "eval",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Formatted Value"}]
}
Example with custom formatting:
{
"column": "Watched_Value1",
"show": true,
"type": "eval",
"options": [
{
"type": "eval",
"param": "`<b>${value}</b> units`"
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Value with Units"}]
}
Input: 42
Output: 42 units
Chaining Types
You can chain multiple transformations with dot notation:
{
"column": "Watched_Value3",
"show": true,
"type": "regex.url_http_https",
"options": [
{
"type": "regex",
"param": "([\\d.:]+)" // Extract IP/host
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "HTTP/S Links"}]
}
Flow:
1. Apply regex to extract 192.168.1.50 from input
2. Create HTTP/HTTPS links for that host
Dynamic Options
SQL-Driven Select
Use SQL query results to populate dropdown options:
{
"column": "Watched_Value2",
"show": true,
"type": "select",
"options": ["{value}"],
"options_params": [
{
"name": "value",
"type": "sql",
"value": "SELECT devType as id, devType as name FROM Devices UNION SELECT 'Unknown' as id, 'Unknown' as name ORDER BY id"
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Device Type"}]
}
The SQL query must return exactly 2 columns: - First column (id): Option value - Second column (name): Display label
Setting-Driven Select
Use plugin settings to populate options:
{
"column": "Watched_Value1",
"show": true,
"type": "select",
"options": ["{value}"],
"options_params": [
{
"name": "value",
"type": "setting",
"value": "MYPLN_AVAILABLE_STATUSES"
}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Status"}]
}
Mapping to Database Tables
Mapping to CurrentScan
To import plugin data into the device scan pipeline (for notifications, heuristics, etc.):
- Add
"mapped_to_table": "CurrentScan"at the root level ofconfig.json - Add
"mapped_to_column"property to each column definition
{
"code_name": "my_device_scanner",
"unique_prefix": "MYSCAN",
"mapped_to_table": "CurrentScan",
"database_column_definitions": [
{
"column": "Object_PrimaryID",
"mapped_to_column": "cur_MAC",
"show": true,
"type": "device_mac",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "MAC Address"}]
},
{
"column": "Object_SecondaryID",
"mapped_to_column": "cur_IP",
"show": true,
"type": "device_ip",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "IP Address"}]
},
{
"column": "NameDoesntMatter",
"mapped_to_column": "cur_ScanMethod",
"mapped_to_column_data": {
"value": "MYSCAN"
},
"show": true,
"type": "label",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Scan Method"}]
}
]
}
Using Static Values
Use mapped_to_column_data to map a static value instead of reading from a column:
{
"column": "NameDoesntMatter",
"mapped_to_column": "cur_ScanMethod",
"mapped_to_column_data": {
"value": "MYSCAN"
},
"show": true,
"type": "label",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Discovery Method"}]
}
This always sets cur_ScanMethod to "MYSCAN" regardless of column data.
Filters
Control which rows are displayed based on filter conditions. Filters are applied on the client-side in JavaScript.
{
"data_filters": [
{
"compare_column": "Object_PrimaryID",
"compare_operator": "==",
"compare_field_id": "txtMacFilter",
"compare_js_template": "'{value}'.toString()",
"compare_use_quotes": true
}
]
}
| Property | Description |
|---|---|
compare_column |
The column from plugin results to compare (left side) |
compare_operator |
JavaScript operator: ==, !=, <, >, <=, >=, includes, startsWith |
compare_field_id |
HTML input field ID containing the filter value (right side) |
compare_js_template |
JavaScript template to transform values. Use {value} placeholder |
compare_use_quotes |
If true, wrap result in quotes for string comparison |
Example: Filter by MAC address
{
"data_filters": [
{
"compare_column": "ForeignKey",
"compare_operator": "==",
"compare_field_id": "txtMacFilter",
"compare_js_template": "'{value}'.toString()",
"compare_use_quotes": true
}
]
}
When viewing a device detail page, the txtMacFilter field is populated with that device's MAC, and only rows where ForeignKey == MAC are shown.
Example: Complete Column Definitions
{
"database_column_definitions": [
{
"column": "Object_PrimaryID",
"mapped_to_column": "cur_MAC",
"css_classes": "col-sm-2",
"show": true,
"type": "device_mac",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "MAC Address"}]
},
{
"column": "Object_SecondaryID",
"mapped_to_column": "cur_IP",
"css_classes": "col-sm-2",
"show": true,
"type": "device_ip",
"default_value": "unknown",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "IP Address"}]
},
{
"column": "DateTime",
"css_classes": "col-sm-2",
"show": true,
"type": "label",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Last Seen"}]
},
{
"column": "Watched_Value1",
"css_classes": "col-sm-2",
"show": true,
"type": "threshold",
"options": [
{"maximum": 199, "hexColor": "#792D86"},
{"maximum": 299, "hexColor": "#5B862D"},
{"maximum": 399, "hexColor": "#7D862D"},
{"maximum": 499, "hexColor": "#BF6440"},
{"maximum": 999, "hexColor": "#D33115"}
],
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "HTTP Status"}]
},
{
"column": "Watched_Value2",
"css_classes": "col-sm-1",
"show": true,
"type": "label",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Response Time"}]
},
{
"column": "Extra",
"css_classes": "col-sm-3",
"show": true,
"type": "textarea_readonly",
"default_value": "",
"localized": ["name"],
"name": [{"language_code": "en_us", "string": "Additional Info"}]
}
]
}
CSS Classes
Use Bootstrap grid classes to control column widths in tables:
| Class | Width | Usage |
|---|---|---|
col-sm-1 |
~8% | Very narrow (icons, status) |
col-sm-2 |
~16% | Narrow (MACs, IPs) |
col-sm-3 |
~25% | Medium (names, URLs) |
col-sm-4 |
~33% | Medium-wide (descriptions) |
col-sm-6 |
~50% | Wide (large content) |
Validation Checklist
- All columns have
"show": trueorfalse - Display columns with
"type"specified from supported types - Localized strings include at least
en_us -
mapped_to_columnmatches target table schema (if using mapping) - Options/thresholds have correct structure
- CSS classes are valid Bootstrap grid classes
- Chaining types (e.g.,
regex.url_http_https) are supported combinations
See Also
- Plugin Data Contract - What data fields are available
- Plugin Settings System - Configure user input
- Database Mapping - Map data to core tables
- Debugging Plugins - Troubleshoot display issues