exchange work

This commit is contained in:
2026-09-15 13:06:45 -05:00
parent 8a3a0acb75
commit 58610c1e1a
265 changed files with 33534 additions and 69 deletions

View File

@@ -0,0 +1,118 @@
# Alarm Analysis Dashboard
A drop-in Ignition Perspective dashboard that turns the **alarm journal** into
actionable alarm-management metrics: alarm rate, MTTA/MTTR, flood episodes,
chattering and standing alarms, a Pareto of bad actors, a day/hour heatmap, and
an overall alarm-health score graded AF against ISA-18.2 style targets.
It reads the journal through `system.alarm.queryJournal` / `system.alarm.queryStatus`
only. There are **no tags, no named queries, no SQL and no database connection**
if the gateway has an alarm journal profile with data in it, the dashboard works.
---
## Requirements
* Ignition **8.1.20+** with the **Perspective** module.
* An **alarm journal profile** that is receiving data (Gateway → Config → Alarming →
Journal). Any journal store works; the resource never talks to the database directly.
* No third-party modules, no Python packages, no gateway scripting configuration.
## Install
1. In the Designer, open the project you want the resource in and choose
**File → Import…**, or use **Config → Projects → Import** on the Gateway
web page to bring the download in as its own project.
2. Import the resource. Everything lands under namespaced folders, so nothing in
an existing project is overwritten:
| Resource | Location |
|---|---|
| Views | `Exchange/AlarmAnalysis/…` |
| Style classes | `exchange/alarm-analysis/…` |
| Project library | `exchange/alarmAnalysis/{alarms, calc, fmt}` |
| Page | `/alarm-analysis``Exchange/AlarmAnalysis/Dashboard` |
3. **Save** the project.
4. Open a Perspective session and browse to **`/alarm-analysis`**.
That is the whole installation. The dashboard holds all of its own state on the
`Dashboard` view, so importing it does **not** add session custom properties,
client tags or global variables to your project.
### If you imported into an existing project
* The page URL `/alarm-analysis` is added to your project's page configuration.
If that URL is already taken, change it in **Project Browser → Perspective →
Page Configuration**; the view path it should point at is
`Exchange/AlarmAnalysis/Dashboard`.
* Nothing else in your project is touched — every resource is namespaced.
### If you want it on its own page shell
Embed `Exchange/AlarmAnalysis/Dashboard` in any view or dock. It takes no
parameters and sizes itself to its container (design size 1600×900).
## Using it
| Tab | What it shows |
|---|---|
| **Overview** | Headline KPIs vs the previous equal-length period, alarm-rate chart, priority mix, top sources, and plain-language insights. |
| **Analysis** | Day/hour heatmap, flood episodes, MTTA/MTTR trend, and priority distribution against the ISA 80/15/5 target. |
| **Bad Actors** | Pareto of the worst offenders plus chattering, standing and fleeting alarm tables. Click a row for the per-source drill-down. |
| **Journal** | Paged, filtered journal browser with CSV export and a per-event detail popup. |
* The **range selector** and **Refresh** in the header set the analysis window.
* The **filter bar** (Priority / Area / State / Search) applies to every tab except
Overview, which deliberately stays a plant-wide summary.
* **Shift Report** renders a plain-text handover summary for the previous shift,
ready to copy into a log.
* Clicking a source anywhere drills through to that source in **Bad Actors**;
clicking a Bad Actors row opens the per-source history popup.
## Tuning
All thresholds live in one place — `exchange.alarmAnalysis.calc.DEFAULTS`:
| Key | Default | Meaning |
|---|---|---|
| `target_per_hr` | `6.0` | ISA target alarm rate per operator per hour |
| `flood_per_10min` | `10` | Activations per 10 min that start a flood episode |
| `chatter_per_hr` | `10.0` | Re-triggers per hour that mark a source as chattering |
| `chatter_gap_s` | `120` | Median gap below which re-triggers count as chatter |
| `fleeting_s` | `10` | Active duration below which an alarm counts as fleeting |
| `standing_hours` | `24` | Age above which an active alarm counts as standing |
| `priority_target` | `80/15/5` | ISA low/medium/high priority mix |
| `health_weights` | see source | Weighting of the five health sub-scores |
| `max_events` | `50000` | Hard cap on journal rows read per query |
Edit the dict in the Designer's script library, or pass an override dict as the
`opts` argument of any `calc` function.
## Script library
| Module | Responsibility |
|---|---|
| `exchange.alarmAnalysis.alarms` | Talks to `system.alarm`; the only module that does I/O. Entry points used by the views: `getDashboardBundle`, `getJournalPage`, `journalCsv`, `getSourceDetail`, `getEventData`, `getShiftReportText`. |
| `exchange.alarmAnalysis.calc` | Pure analytics — correlation, binning, floods, chatter, MTTA/MTTR, Pareto, health score. No Ignition API calls, so it is unit-testable. |
| `exchange.alarmAnalysis.fmt` | Display formatting and the natural-language insight/shift-report text. |
Every public function carries a docstring, so the Designer's autocomplete
documents the API.
## Notes and limits
* The journal is queried for **twice** the selected window (current plus the
equal-length prior period) so every KPI can show a delta. A very wide range over
a busy plant is bounded by `max_events`; when that cap is hit the header shows a
*truncated* chip.
* Alarm instances are correlated by journal event id when the journal supplies
one, and by a per-source active/clear state machine otherwise. The mode in use
is reported in `bundle.meta.correlation_mode`.
* "Active now", unacked and shelved counts come from live alarm status, so they
reflect the present moment rather than the selected window.
* Scripts are Jython 2.7 compatible (no f-strings, no `typing`, no `statistics`).
## License
Provided as-is under the terms of the Ignition Exchange.

View File

@@ -0,0 +1,9 @@
{
"pages": {
"/alarm-analysis": {
"title": "Alarm Analysis",
"viewPath": "Exchange/AlarmAnalysis/Dashboard"
}
},
"sharedDocks": {}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"config.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,74 @@
{
"custom": {},
"propConfig": {
"props.auth": {
"access": "PRIVATE",
"persistent": false
},
"props.device.accelerometer": {
"access": "SYSTEM",
"persistent": false
},
"props.device.identifier": {
"access": "SYSTEM",
"persistent": false
},
"props.device.timezone": {
"access": "SYSTEM",
"persistent": false
},
"props.device.type": {
"access": "SYSTEM",
"persistent": false
},
"props.device.userAgent": {
"access": "SYSTEM",
"persistent": false
},
"props.gateway": {
"access": "SYSTEM",
"persistent": false
},
"props.geolocation.data": {
"access": "SYSTEM",
"persistent": false
},
"props.geolocation.permissionGranted": {
"access": "SYSTEM",
"persistent": false
},
"props.host": {
"access": "SYSTEM",
"persistent": false
},
"props.id": {
"access": "SYSTEM",
"persistent": false
},
"props.lastActivity": {
"access": "SYSTEM",
"persistent": false
},
"props.offline.capable": {
"access": "SYSTEM",
"persistent": false
},
"props.offline.enabled": {
"access": "SYSTEM",
"persistent": false
},
"props.offline.lastSynced": {
"access": "SYSTEM",
"persistent": false
}
},
"props": {
"device": {},
"geolocation": {},
"locale": "en-US",
"offline": {},
"securityLevels": [],
"theme": "light-cool",
"timeZoneId": "America/Chicago"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"props.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,12 @@
{
"base": {
"style": {
"color": "var(--neutral-70)",
"fontSize": "12px",
"fontWeight": "bold",
"letterSpacing": "0.08em",
"marginBottom": "8px",
"textTransform": "uppercase"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "var(--neutral-10)",
"borderRadius": "8px",
"boxShadow": "0 1px 3px rgba(0,0,0,0.12)",
"padding": "12px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,13 @@
{
"base": {
"style": {
"backgroundColor": "#D6455026",
"borderRadius": "10px",
"color": "#D64550",
"fontSize": "11px",
"fontWeight": "bold",
"paddingLeft": "6px",
"paddingRight": "6px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,13 @@
{
"base": {
"style": {
"backgroundColor": "var(--neutral-30)",
"borderRadius": "10px",
"color": "var(--neutral-70)",
"fontSize": "11px",
"fontWeight": "bold",
"paddingLeft": "6px",
"paddingRight": "6px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,13 @@
{
"base": {
"style": {
"backgroundColor": "#2E9E5B26",
"borderRadius": "10px",
"color": "#2E9E5B",
"fontSize": "11px",
"fontWeight": "bold",
"paddingLeft": "6px",
"paddingRight": "6px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,9 @@
{
"base": {
"style": {
"color": "var(--neutral-50)",
"fontStyle": "italic",
"textAlign": "center"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#2E9E5B",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#7CB342",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#E5C453",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#E8883A",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#D64550",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#8A94A6",
"borderRadius": "8px",
"color": "#FFFFFF",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,8 @@
{
"base": {
"style": {
"backgroundColor": "var(--neutral-20)",
"padding": "12px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#D6455026",
"borderRadius": "6px",
"color": "#D64550",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#8A94A626",
"borderRadius": "6px",
"color": "#8A94A6",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#E8883A26",
"borderRadius": "6px",
"color": "#E8883A",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#5B9BD526",
"borderRadius": "6px",
"color": "#5B9BD5",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "#E5C45326",
"borderRadius": "6px",
"color": "#E5C453",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,15 @@
{
"base": {
"style": {
"backgroundColor": "#D64550",
"borderRadius": "4px",
"color": "#FFFFFF",
"fontSize": "12px",
"fontWeight": "bold",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,15 @@
{
"base": {
"style": {
"backgroundColor": "#8A94A6",
"borderRadius": "4px",
"color": "#FFFFFF",
"fontSize": "12px",
"fontWeight": "bold",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,15 @@
{
"base": {
"style": {
"backgroundColor": "#E8883A",
"borderRadius": "4px",
"color": "#FFFFFF",
"fontSize": "12px",
"fontWeight": "bold",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,15 @@
{
"base": {
"style": {
"backgroundColor": "#5B9BD5",
"borderRadius": "4px",
"color": "#FFFFFF",
"fontSize": "12px",
"fontWeight": "bold",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,15 @@
{
"base": {
"style": {
"backgroundColor": "#E5C453",
"borderRadius": "4px",
"color": "#FFFFFF",
"fontSize": "12px",
"fontWeight": "bold",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,8 @@
{
"base": {
"style": {
"backgroundColor": "#3B7DD818",
"color": "#3B7DD8"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,9 @@
{
"base": {
"style": {
"backgroundColor": "#D6455018",
"color": "#D64550",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,8 @@
{
"base": {
"style": {
"backgroundColor": "#2E9E5B18",
"color": "#2E9E5B"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,16 @@
{
"base": {
"style": {
"borderBottomColor": "#3B7DD8",
"borderBottomStyle": "solid",
"borderBottomWidth": "3px",
"color": "var(--neutral-90)",
"cursor": "pointer",
"fontWeight": "bold",
"paddingBottom": "6px",
"paddingLeft": "16px",
"paddingRight": "16px",
"paddingTop": "8px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,23 @@
{
"base": {
"style": {
"borderBottomColor": "rgba(0,0,0,0)",
"borderBottomStyle": "solid",
"borderBottomWidth": "3px",
"color": "var(--neutral-60)",
"cursor": "pointer",
"paddingBottom": "6px",
"paddingLeft": "16px",
"paddingRight": "16px",
"paddingTop": "8px"
}
},
"variants": [
{
"pseudo": "hover",
"style": {
"color": "var(--neutral-90)"
}
}
]
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,9 @@
{
"base": {
"style": {
"color": "var(--neutral-90)",
"fontSize": "28px",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,9 @@
{
"base": {
"style": {
"color": "var(--neutral-90)",
"fontSize": "22px",
"fontWeight": "bold"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,8 @@
{
"base": {
"style": {
"color": "var(--neutral-60)",
"fontSize": "12px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"style.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,10 @@
{
"base": {
"style": {
"backgroundColor": "var(--neutral-10)",
"borderRadius": "8px",
"boxShadow": "0 1px 3px rgba(0,0,0,0.12)",
"padding": "8px"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,93 @@
{
"custom": {},
"params": {
"icon": null,
"message": null
},
"propConfig": {
"params.icon": {
"paramDirection": "input",
"persistent": false
},
"params.message": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "48px",
"shrink": 0
},
"propConfig": {
"props.path": {
"binding": {
"config": {
"path": "view.params.icon"
},
"transforms": [
{
"code": "\treturn 'material/' + (value or 'inbox')",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"color": "var(--neutral-50)",
"path": "material/inbox",
"style": {
"fontSize": "40px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Msg"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.message"
},
"transforms": [
{
"code": "\treturn value or 'No alarm events in the selected range'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/empty-state/empty"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"alignItems": "center",
"justifyContent": "center"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {
"lastModificationSignature": "44b87b06b842940d391b9bafd34557de0ac8a5005f6ee91844ac9dd2f18c0f04",
"lastModification": {
"actor": "admin",
"timestamp": "2026-07-16T20:14:21Z"
}
}
}

View File

@@ -0,0 +1,136 @@
{
"custom": {},
"params": {
"health": null
},
"propConfig": {
"params.health": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Grade"
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\tg = value['grade']\n\texcept:\n\t\tg = None\n\treturn 'exchange/alarm-analysis/grade/' + (g.lower() if g in ['A', 'B', 'C', 'D', 'F'] else 'na')",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['grade'] or 'N/A'\n\texcept:\n\t\treturn 'N/A'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "30px",
"paddingBottom": "2px",
"paddingLeft": "14px",
"paddingRight": "14px",
"paddingTop": "2px",
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "Title"
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold"
},
"text": "Alarm Health"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Score"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\ts = value['score']\n\t\treturn 'Score %d - click for detail' % round(s) if s is not None else 'no data in range'\n\texcept:\n\t\treturn 'no data in range'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "ScoreCol"
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.openPopup('exchange.alarmAnalysis.healthScore', 'Exchange/AlarmAnalysis/Popups/HealthScore', params = {'health': self.view.params.health}, showCloseIcon = True, draggable = True)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"style": {
"alignItems": "center",
"cursor": "pointer",
"gap": "10px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,94 @@
{
"custom": {},
"params": {
"count": null,
"max": null
},
"propConfig": {
"params.count": {
"paramDirection": "input",
"persistent": false
},
"params.max": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Cell"
},
"position": {
"grow": 1
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "view.params.count"
},
"transforms": [
{
"code": "\ttry:\n\t\tm = self.view.params.max\n\t\tc = value or 0\n\t\tif not m or m <= 0 or c <= 0:\n\t\t\treturn 'rgba(59,125,216,0.06)'\n\t\ta = 0.15 + 0.85 * (float(c) / m)\n\t\treturn 'rgba(59,125,216,%.2f)' % min(a, 1.0)\n\texcept:\n\t\treturn 'rgba(59,125,216,0.06)'",
"type": "script"
}
],
"type": "property"
}
},
"props.style.color": {
"binding": {
"config": {
"path": "view.params.count"
},
"transforms": [
{
"code": "\ttry:\n\t\tm = self.view.params.max\n\t\tif m and value and float(value) / m > 0.55:\n\t\t\treturn '#FFFFFF'\n\texcept:\n\t\tpass\n\treturn 'var(--neutral-90)'",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.count"
},
"transforms": [
{
"code": "\treturn '' if not value else value",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"borderRadius": "2px",
"fontSize": "10px",
"marginBottom": "1px",
"marginRight": "1px",
"textAlign": "center"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "row",
"style": {
"alignItems": "stretch"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,121 @@
{
"custom": {},
"params": {
"icon": null,
"severity": null,
"tab": null,
"text": null
},
"propConfig": {
"params.icon": {
"paramDirection": "input",
"persistent": false
},
"params.severity": {
"paramDirection": "input",
"persistent": false
},
"params.tab": {
"paramDirection": "input",
"persistent": false
},
"params.text": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Icon"
},
"position": {
"basis": "24px",
"shrink": 0
},
"propConfig": {
"props.color": {
"binding": {
"config": {
"path": "view.params.severity"
},
"transforms": [
{
"code": "\tcolors = {0: '#D64550', 1: '#E8883A', 2: '#3B7DD8', 3: 'var(--neutral-60)'}\n\treturn colors.get(value, 'var(--neutral-60)')",
"type": "script"
}
],
"type": "property"
}
},
"props.path": {
"binding": {
"config": {
"path": "view.params.icon"
},
"transforms": [
{
"code": "\treturn 'material/' + (value or 'insights')",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"path": "material/insights",
"style": {
"fontSize": "18px"
}
},
"type": "ia.display.icon"
},
{
"meta": {
"name": "Text"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.text"
},
"transforms": [
{
"code": "\treturn value or ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "row",
"style": {
"alignItems": "center",
"gap": "8px",
"paddingBottom": "4px",
"paddingTop": "4px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {
"lastModificationSignature": "75b1aa709e8638ac045f15b7a6d3543d023b8f3e886e2f9f1c263c0390c4fe9d",
"lastModification": {
"actor": "admin",
"timestamp": "2026-07-16T20:45:13Z"
}
}
}

View File

@@ -0,0 +1,204 @@
{
"custom": {},
"params": {
"delta": null,
"label": null,
"unit": null,
"value": null
},
"propConfig": {
"params.delta": {
"paramDirection": "input",
"persistent": false
},
"params.label": {
"paramDirection": "input",
"persistent": false
},
"params.unit": {
"paramDirection": "input",
"persistent": false
},
"params.value": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Lbl"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.label"
},
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted",
"lineHeight": "1.1"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "Value"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.value"
},
"transforms": [
{
"code": "\treturn value if value is not None else '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/kpi",
"lineHeight": "1.1"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Unit"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.unit"
},
"transforms": [
{
"code": "\treturn value or ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted",
"lineHeight": "1.1"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "ValueRow"
},
"position": {
"basis": "auto",
"grow": 1,
"shrink": 1
},
"props": {
"style": {
"alignItems": "baseline",
"gap": "4px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Chip"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.delta"
},
"transforms": [
{
"code": "\treturn value is not None",
"type": "script"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.delta"
},
"transforms": [
{
"code": "\tbase = 'exchange/alarm-analysis/chip/flat'\n\ttry:\n\t\tif value and value['good'] == True:\n\t\t\tbase = 'exchange/alarm-analysis/chip/good'\n\t\telif value and value['good'] == False:\n\t\t\tbase = 'exchange/alarm-analysis/chip/bad'\n\texcept:\n\t\tpass\n\treturn base",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.delta"
},
"transforms": [
{
"code": "\tif not value:\n\t\treturn ''\n\ttry:\n\t\tchip = exchange.alarmAnalysis.fmt.deltaChip(value)\n\t\treturn '%s %s' % (chip['arrow'], chip['text'])\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"alignSelf": "flex-start",
"padding": "0 6px"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"justifyContent": "space-between",
"overflow": "hidden",
"padding": "6px 12px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,137 @@
{
"custom": {},
"params": {
"count": null,
"pct": null,
"priorityName": null
},
"propConfig": {
"params.count": {
"paramDirection": "input",
"persistent": false
},
"params.pct": {
"paramDirection": "input",
"persistent": false
},
"params.priorityName": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Name"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.priorityName"
},
"transforms": [
{
"code": "\treturn value or 'Unknown'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Count"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.count"
},
"transforms": [
{
"code": "\treturn exchange.alarmAnalysis.fmt.num(value)",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/big"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Pct"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.pct"
},
"transforms": [
{
"code": "\treturn exchange.alarmAnalysis.fmt.pct(value) + ' of events' if value is not None else ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.priorityName"
},
"transforms": [
{
"code": "\tnames = ['Diagnostic', 'Low', 'Medium', 'High', 'Critical']\n\tn = value if value in names else 'Diagnostic'\n\treturn 'exchange/alarm-analysis/card exchange/alarm-analysis/priority-soft/' + n.lower()",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"direction": "column",
"style": {
"alignItems": "center",
"classes": "exchange/alarm-analysis/card",
"gap": "2px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,207 @@
{
"custom": {},
"params": {
"detail": null,
"key": null,
"label": null,
"score": null,
"weight": null
},
"propConfig": {
"params.detail": {
"paramDirection": "input",
"persistent": false
},
"params.key": {
"paramDirection": "input",
"persistent": false
},
"params.label": {
"paramDirection": "input",
"persistent": false
},
"params.score": {
"paramDirection": "input",
"persistent": false
},
"params.weight": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "Lbl"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.label"
},
"transforms": [
{
"code": "\treturn value or ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Score"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.score"
},
"transforms": [
{
"code": "\treturn '%d' % round(value) if value is not None else 'N/A'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "TopRow"
},
"props": {
"direction": "row",
"style": {
"justifyContent": "space-between"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [],
"meta": {
"name": "Fill"
},
"propConfig": {
"props.style.backgroundColor": {
"binding": {
"config": {
"path": "view.params.score"
},
"transforms": [
{
"code": "\ttry:\n\t\ts = float(value)\n\texcept:\n\t\treturn 'var(--neutral-40)'\n\tif s >= 80:\n\t\treturn '#2E9E5B'\n\tif s >= 60:\n\t\treturn '#E5C453'\n\treturn '#D64550'",
"type": "script"
}
],
"type": "property"
}
},
"props.style.width": {
"binding": {
"config": {
"path": "view.params.score"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn '%d%%' % max(0, min(100, round(value)))\n\texcept:\n\t\treturn '0%'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"direction": "row",
"style": {
"borderRadius": "4px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "Track"
},
"position": {
"basis": "8px",
"shrink": 0
},
"props": {
"direction": "row",
"style": {
"backgroundColor": "var(--neutral-30)",
"borderRadius": "4px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "Detail"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.detail"
},
"transforms": [
{
"code": "\treturn value or ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"gap": "2px",
"paddingBottom": "8px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,192 @@
{
"custom": {},
"params": {
"count": null,
"label": null,
"pct": null,
"rank": null,
"source": null
},
"propConfig": {
"params.count": {
"paramDirection": "input",
"persistent": false
},
"params.label": {
"paramDirection": "input",
"persistent": false
},
"params.pct": {
"paramDirection": "input",
"persistent": false
},
"params.rank": {
"paramDirection": "input",
"persistent": false
},
"params.source": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"meta": {
"name": "Rank"
},
"position": {
"basis": "24px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.rank"
},
"transforms": [
{
"code": "\treturn '#%s' % value if value is not None else ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Lbl"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.label"
},
"transforms": [
{
"code": "\treturn value or ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Count"
},
"position": {
"basis": "56px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.count"
},
"transforms": [
{
"code": "\treturn exchange.alarmAnalysis.fmt.num(value)",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "13px",
"fontWeight": "bold",
"textAlign": "right"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Pct"
},
"position": {
"basis": "48px",
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.pct"
},
"transforms": [
{
"code": "\treturn exchange.alarmAnalysis.fmt.pct(value) if value is not None else ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted",
"textAlign": "right"
}
},
"type": "ia.display.label"
}
],
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.sendMessage('exchange.alarmAnalysis.focusSource', payload = {'source': self.view.params.source}, scope = 'page')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"direction": "row",
"style": {
"alignItems": "center",
"borderBottomColor": "var(--neutral-30)",
"borderBottomStyle": "solid",
"borderBottomWidth": "1px",
"cursor": "pointer",
"gap": "8px",
"paddingBottom": "4px",
"paddingTop": "4px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,74 @@
{
"custom": {},
"params": {
"index": null,
"selectedTab": null,
"title": null
},
"propConfig": {
"params.index": {
"paramDirection": "input",
"persistent": false
},
"params.selectedTab": {
"paramDirection": "input",
"persistent": false
},
"params.title": {
"paramDirection": "input",
"persistent": false
}
},
"props": {},
"root": {
"children": [
{
"events": {
"dom": {
"onClick": {
"config": {
"script": "\tsystem.perspective.sendMessage('exchange.alarmAnalysis.setTab', payload = {'index': self.view.params.index}, scope = 'page')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "Btn"
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"expression": "if({view.params.index} = {view.params.selectedTab}, 'exchange/alarm-analysis/tab/active', 'exchange/alarm-analysis/tab/inactive')"
},
"type": "expr"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.title"
},
"type": "property"
}
}
},
"props": {},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "row",
"style": {
"alignItems": "center",
"justifyContent": "center"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {
"lastModificationSignature": "04bdfb9c4eecc4f8cf35a85994e6790ef8d62a1d1aa00553e4dc4193e171a110",
"lastModification": {
"actor": "admin",
"timestamp": "2026-07-16T20:31:35Z"
}
}
}

View File

@@ -0,0 +1,487 @@
{
"custom": {
"bundle": null,
"query": {
"areas": [],
"endMs": 0,
"priorities": [],
"rangePreset": "8h",
"refreshToken": 0,
"search": "",
"startMs": 0,
"states": []
},
"ui": {
"badActorFocus": "",
"selectedTab": 0
}
},
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tq = self.view.custom.query\n\tif not q.startMs or q.startMs == 0:\n\t\tnow = system.date.toMillis(system.date.now())\n\t\tq.endMs = now\n\t\tq.startMs = now - 8 * 3600 * 1000\n\t\tq.rangePreset = '8h'"
},
"scope": "G",
"type": "script"
}
}
},
"params": {},
"propConfig": {
"custom.bundle": {
"binding": {
"config": {
"expression": "{view.custom.query.refreshToken} + '|' + {view.custom.query.startMs} + '|' + {view.custom.query.endMs}"
},
"transforms": [
{
"code": "\tq = self.view.custom.query\n\tif not q.startMs or not q.endMs:\n\t\treturn None\n\treturn exchange.alarmAnalysis.alarms.getDashboardBundle(q.startMs, q.endMs, {'priorities': list(q.priorities), 'areas': list(q.areas), 'states': list(q.states), 'search': q.search})",
"type": "script"
}
],
"type": "expr"
}
},
"custom.query": {
"persistent": false
},
"custom.ui": {
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 900,
"width": 1600
}
},
"root": {
"children": [
{
"meta": {
"name": "Header"
},
"position": {
"basis": "150px",
"shrink": 0
},
"propConfig": {
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
},
"props.params.query": {
"binding": {
"config": {
"path": "view.custom.query"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Shell/Header"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "FilterBar"
},
"position": {
"basis": "auto",
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.ui.selectedTab} != 0"
},
"type": "expr"
}
},
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
},
"props.params.query": {
"binding": {
"config": {
"path": "view.custom.query"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Shell/FilterBar",
"style": {
"minHeight": "56px"
}
},
"type": "ia.display.view"
},
{
"children": [
{
"meta": {
"name": "TabBtn0"
},
"position": {
"basis": "140px",
"shrink": 0
},
"propConfig": {
"props.params.selectedTab": {
"binding": {
"config": {
"path": "view.custom.ui.selectedTab"
},
"type": "property"
}
}
},
"props": {
"params": {
"index": 0,
"title": "Overview"
},
"path": "Exchange/AlarmAnalysis/Components/TabButton"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabBtn1"
},
"position": {
"basis": "140px",
"shrink": 0
},
"propConfig": {
"props.params.selectedTab": {
"binding": {
"config": {
"path": "view.custom.ui.selectedTab"
},
"type": "property"
}
}
},
"props": {
"params": {
"index": 1,
"title": "Analysis"
},
"path": "Exchange/AlarmAnalysis/Components/TabButton"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabBtn2"
},
"position": {
"basis": "140px",
"shrink": 0
},
"propConfig": {
"props.params.selectedTab": {
"binding": {
"config": {
"path": "view.custom.ui.selectedTab"
},
"type": "property"
}
}
},
"props": {
"params": {
"index": 2,
"title": "Bad Actors"
},
"path": "Exchange/AlarmAnalysis/Components/TabButton"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabBtn3"
},
"position": {
"basis": "140px",
"shrink": 0
},
"propConfig": {
"props.params.selectedTab": {
"binding": {
"config": {
"path": "view.custom.ui.selectedTab"
},
"type": "property"
}
}
},
"props": {
"params": {
"index": 3,
"title": "Journal"
},
"path": "Exchange/AlarmAnalysis/Components/TabButton"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "TabBar"
},
"position": {
"basis": "42px",
"shrink": 0
},
"props": {
"style": {
"borderBottomColor": "var(--neutral-40)",
"borderBottomStyle": "solid",
"borderBottomWidth": "1px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "TabOverview"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.ui.selectedTab} = 0"
},
"type": "expr"
}
},
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Tabs/Overview"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabAnalysis"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.ui.selectedTab} = 1"
},
"type": "expr"
}
},
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Tabs/Analysis"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabBadActors"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.ui.selectedTab} = 2"
},
"type": "expr"
}
},
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
},
"props.params.focus": {
"binding": {
"config": {
"path": "view.custom.ui.badActorFocus"
},
"type": "property"
}
},
"props.params.query": {
"binding": {
"config": {
"path": "view.custom.query"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Tabs/BadActors"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "TabJournal"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"expression": "{view.custom.ui.selectedTab} = 3"
},
"type": "expr"
}
},
"props.params.bundle": {
"binding": {
"config": {
"path": "view.custom.bundle"
},
"type": "property"
}
},
"props.params.query": {
"binding": {
"config": {
"path": "view.custom.query"
},
"type": "property"
}
}
},
"props": {
"path": "Exchange/AlarmAnalysis/Tabs/Journal"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "TabContent"
},
"position": {
"grow": 1
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/page-bg",
"gap": "10px"
}
},
"scripts": {
"customMethods": [],
"extensionFunctions": null,
"messageHandlers": [
{
"messageType": "exchange.alarmAnalysis.setTab",
"pageScope": true,
"script": "\ttry:\n\t\tself.view.custom.ui.selectedTab = int(payload['index'])\n\texcept:\n\t\tpass",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.focusSource",
"pageScope": true,
"script": "\ttry:\n\t\tself.view.custom.ui.badActorFocus = payload['source'] or ''\n\t\tself.view.custom.ui.selectedTab = 2\n\texcept:\n\t\tpass",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.clearFocus",
"pageScope": true,
"script": "\tself.view.custom.ui.badActorFocus = ''",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.applyFilters",
"pageScope": true,
"script": "\tq = self.view.custom.query\n\ttry:\n\t\tq.priorities = list(payload['priorities'] or [])\n\t\tq.areas = list(payload['areas'] or [])\n\t\tq.states = list(payload['states'] or [])\n\t\tq.search = str(payload['search'] or '')\n\texcept:\n\t\tpass\n\tq.refreshToken = q.refreshToken + 1",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.clearFilters",
"pageScope": true,
"script": "\tq = self.view.custom.query\n\tq.priorities = []\n\tq.areas = []\n\tq.states = []\n\tq.search = ''\n\tq.refreshToken = q.refreshToken + 1",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.setRange",
"pageScope": true,
"script": "\tspans = {'4h': 4, '8h': 8, '24h': 24, '7d': 168}\n\ttry:\n\t\tpreset = payload['preset']\n\texcept:\n\t\treturn\n\tif preset not in spans:\n\t\treturn\n\tq = self.view.custom.query\n\tnow = system.date.toMillis(system.date.now())\n\tq.endMs = now\n\tq.startMs = now - spans[preset] * 3600 * 1000\n\tq.rangePreset = preset\n\tq.refreshToken = q.refreshToken + 1",
"sessionScope": false,
"viewScope": false
},
{
"messageType": "exchange.alarmAnalysis.refresh",
"pageScope": true,
"script": "\tq = self.view.custom.query\n\tspans = {'4h': 4, '8h': 8, '24h': 24, '7d': 168}\n\tnow = system.date.toMillis(system.date.now())\n\thours = spans.get(q.rangePreset)\n\tif hours is not None:\n\t\tspan = hours * 3600 * 1000\n\telse:\n\t\tspan = q.endMs - q.startMs\n\tif span > 0:\n\t\tq.endMs = now\n\t\tq.startMs = now - span\n\tq.refreshToken = q.refreshToken + 1",
"sessionScope": false,
"viewScope": false
}
]
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {
"lastModificationSignature": "1d6feda3a22e57c52a032bea5ed828b0b7836e249e46a68faa58af39207b9119",
"lastModification": {
"actor": "admin",
"timestamp": "2026-07-16T20:41:00Z"
}
}
}

View File

@@ -0,0 +1,805 @@
{
"custom": {
"detail": null
},
"params": {
"endMs": null,
"label": null,
"source": null,
"startMs": null
},
"propConfig": {
"custom.detail": {
"binding": {
"config": {
"expression": "{view.params.source} + '|' + {view.params.startMs} + '|' + {view.params.endMs}"
},
"transforms": [
{
"code": "\ttry:\n\t\tsrc = self.view.params.source\n\texcept:\n\t\tsrc = None\n\tif not src:\n\t\treturn None\n\ttry:\n\t\treturn exchange.alarmAnalysis.alarms.getSourceDetail(src, self.view.params.startMs, self.view.params.endMs)\n\texcept:\n\t\treturn None",
"type": "script"
}
],
"type": "expr"
}
},
"params.endMs": {
"paramDirection": "input",
"persistent": false
},
"params.label": {
"paramDirection": "input",
"persistent": false
},
"params.source": {
"paramDirection": "input",
"persistent": false
},
"params.startMs": {
"paramDirection": "input",
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 660,
"width": 720
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "LblTitle"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.label"
},
"transforms": [
{
"code": "\tif value:\n\t\treturn value\n\ttry:\n\t\treturn self.view.params.source or 'Alarm Detail'\n\texcept:\n\t\treturn 'Alarm Detail'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/big"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "LblArea"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['area'] or ''\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "HeaderCol"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"meta": {
"name": "KpiCount"
},
"position": {
"basis": "100px",
"grow": 1
},
"propConfig": {
"props.params.value": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn exchange.alarmAnalysis.fmt.num(value['stats']['count'])\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"label": "Activations"
},
"path": "Exchange/AlarmAnalysis/Components/KpiCard"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "KpiTta"
},
"position": {
"basis": "100px",
"grow": 1
},
"propConfig": {
"props.params.value": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn exchange.alarmAnalysis.fmt.dur(value['stats']['avg_tta_ms'])\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"label": "Avg Time to Ack"
},
"path": "Exchange/AlarmAnalysis/Components/KpiCard"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "KpiActive"
},
"position": {
"basis": "100px",
"grow": 1
},
"propConfig": {
"props.params.value": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn exchange.alarmAnalysis.fmt.dur(value['stats']['avg_active_ms'])\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"label": "Avg Active Time"
},
"path": "Exchange/AlarmAnalysis/Components/KpiCard"
},
"type": "ia.display.view"
},
{
"meta": {
"name": "KpiFleeting"
},
"position": {
"basis": "100px",
"grow": 1
},
"propConfig": {
"props.params.value": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn exchange.alarmAnalysis.fmt.num(value['stats']['fleeting_count'])\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"label": "Fleeting"
},
"path": "Exchange/AlarmAnalysis/Components/KpiCard"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "StatsRow"
},
"position": {
"basis": "88px",
"shrink": 0
},
"props": {
"style": {
"gap": "10px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblDailyTitle"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/card-title"
},
"text": "Daily activity"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "RepDaily"
},
"position": {
"basis": "72px",
"shrink": 0
},
"propConfig": {
"props.instances": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\tdaily = list(value['daily'] or [])\n\texcept:\n\t\tdaily = []\n\tcounts = []\n\tfor d in daily:\n\t\ttry:\n\t\t\tcounts.append(int(d['count']))\n\t\texcept:\n\t\t\tcounts.append(0)\n\tif not counts:\n\t\treturn []\n\tm = max(counts)\n\treturn [{'count': c, 'max': m} for c in counts]",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"elementPosition": {
"basis": "8px"
},
"path": "Exchange/AlarmAnalysis/Components/HeatmapCell",
"style": {
"gap": "2px"
},
"useDefaultViewHeight": false,
"useDefaultViewWidth": false
},
"type": "ia.display.flex-repeater"
},
{
"meta": {
"name": "LblDailyRange"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\tdaily = list(value['daily'] or [])\n\texcept:\n\t\tdaily = []\n\tif not daily:\n\t\treturn 'No activity in range'\n\ttry:\n\t\treturn 'Activations per day, %s - %s' % (exchange.alarmAnalysis.fmt.dayClock(daily[0]['t0']), exchange.alarmAnalysis.fmt.dayClock(daily[-1]['t0']))\n\texcept:\n\t\treturn 'Activations per day'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "CardDaily"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "6px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblAckTitle"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/card-title"
},
"text": "Top ack users"
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "Ack0"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn len(value['stats']['top_ack_users']) > 0\n\texcept:\n\t\treturn False",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\tu = value['stats']['top_ack_users'][0]\n\t\treturn '%s (%d)' % (u['user'], u['count'])\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/chip/flat",
"paddingBottom": "2px",
"paddingTop": "2px"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Ack1"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn len(value['stats']['top_ack_users']) > 1\n\texcept:\n\t\treturn False",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\tu = value['stats']['top_ack_users'][1]\n\t\treturn '%s (%d)' % (u['user'], u['count'])\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/chip/flat",
"paddingBottom": "2px",
"paddingTop": "2px"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "Ack2"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn len(value['stats']['top_ack_users']) > 2\n\texcept:\n\t\treturn False",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\tu = value['stats']['top_ack_users'][2]\n\t\treturn '%s (%d)' % (u['user'], u['count'])\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/chip/flat",
"paddingBottom": "2px",
"paddingTop": "2px"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "LblNoAcks"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn len(value['stats']['top_ack_users']) == 0\n\texcept:\n\t\treturn True",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "No acknowledgements in range"
},
"type": "ia.display.label"
}
],
"meta": {
"name": "AckRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"style": {
"gap": "6px"
},
"wrap": "wrap"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "CardAcks"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "6px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblEvTitle"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/card-title"
},
"text": "Recent events"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "TblEvents"
},
"position": {
"grow": 1
},
"propConfig": {
"props.data": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\tout = []\n\ttry:\n\t\trows = list(value['events'] or [])\n\texcept:\n\t\trows = []\n\tfor r in rows[:25]:\n\t\ttry:\n\t\t\tout.append({'time_label': r['time_label'], 'state_label': r['state_label'], 'ack_user': r['ack_user'] or ''})\n\t\texcept:\n\t\t\tpass\n\treturn out",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"cells": {
"style": {
"padding": "5px"
}
},
"columns": [
{
"field": "time_label",
"header": {
"title": "Time"
},
"render": "string",
"sortable": false,
"strictWidth": true,
"width": 160
},
{
"field": "state_label",
"header": {
"title": "State"
},
"render": "string",
"sortable": false,
"strictWidth": true,
"width": 110
},
{
"field": "ack_user",
"header": {
"title": "Ack by"
},
"render": "string",
"sortable": false
}
],
"emptyMessage": {
"noData": {
"text": "No events in range"
}
},
"pager": {
"bottom": false
}
},
"type": "ia.display.table"
}
],
"meta": {
"name": "CardEvents"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "6px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "BodyCol"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\tif value is None:\n\t\treturn False\n\ttry:\n\t\treturn not value['error']\n\texcept:\n\t\treturn True",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"direction": "column",
"style": {
"gap": "10px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "EmptyWrap"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.custom.detail"
},
"transforms": [
{
"code": "\tif value is None:\n\t\treturn True\n\ttry:\n\t\treturn bool(value['error'])\n\texcept:\n\t\treturn False",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"icon": "notifications_off",
"message": "No journal data for this alarm in the selected range"
},
"path": "Exchange/AlarmAnalysis/Components/EmptyState"
},
"type": "ia.display.view"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup('exchange.alarmAnalysis.alarmDetail')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnClose"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"text": "Close"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FooterRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/page-bg",
"gap": "10px",
"padding": "16px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,665 @@
{
"custom": {
"props": []
},
"params": {
"event": null
},
"propConfig": {
"custom.props": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\tev = value\n\tif not ev:\n\t\treturn []\n\ttry:\n\t\tres = exchange.alarmAnalysis.alarms.getEventData(ev['id'], ev['time_ms'], ev['source'])\n\t\treturn res['props'] or []\n\texcept:\n\t\treturn []",
"type": "script"
}
],
"type": "property"
}
},
"params.event": {
"paramDirection": "input",
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 580,
"width": 580
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "LblTitle"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['label'] or value['source'] or 'Event Detail'\n\texcept:\n\t\treturn 'Event Detail'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/big"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "ChipState"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\treturn value is not None",
"type": "script"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\ts = value['state']\n\texcept:\n\t\ts = None\n\tif s == 'ack':\n\t\treturn 'exchange/alarm-analysis/state/acked'\n\tif s == 'clear':\n\t\treturn 'exchange/alarm-analysis/state/cleared'\n\treturn 'exchange/alarm-analysis/state/active'",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['state_label'] or ''\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"borderRadius": "10px",
"fontSize": "11px",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "ChipPriority"
},
"position": {
"shrink": 0
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\treturn value is not None",
"type": "script"
}
],
"type": "property"
}
},
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\tp = value['priority_name']\n\texcept:\n\t\tp = None\n\tif p not in ['Diagnostic', 'Low', 'Medium', 'High', 'Critical']:\n\t\tp = 'Diagnostic'\n\treturn 'exchange/alarm-analysis/priority/' + p.lower()",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['priority_name'] or ''\n\texcept:\n\t\treturn ''",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"borderRadius": "10px",
"fontSize": "11px",
"paddingBottom": "2px",
"paddingLeft": "8px",
"paddingRight": "8px",
"paddingTop": "2px"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "HeaderRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"style": {
"gap": "8px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"children": [
{
"children": [
{
"meta": {
"name": "K"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "Time"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "V"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['time_label'] or exchange.alarmAnalysis.fmt.dayClock(value['time_ms'])\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {},
"type": "ia.display.label"
}
],
"meta": {
"name": "RowTime"
},
"props": {
"style": {
"gap": "8px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "K"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "Source"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "V"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['source'] or '--'\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"overflowWrap": "anywhere"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "RowSource"
},
"props": {
"style": {
"gap": "8px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "K"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "Area"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "V"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['area'] or '--'\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {},
"type": "ia.display.label"
}
],
"meta": {
"name": "RowArea"
},
"props": {
"style": {
"gap": "8px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "K"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "Ack by"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "V"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['ack_user'] or '--'\n\texcept:\n\t\treturn '--'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {},
"type": "ia.display.label"
}
],
"meta": {
"name": "RowAck"
},
"props": {
"style": {
"gap": "8px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "CardCore"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "4px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblPropsTitle"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/card-title"
},
"text": "Event properties"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "TblProps"
},
"position": {
"grow": 1
},
"propConfig": {
"props.data": {
"binding": {
"config": {
"path": "view.custom.props"
},
"transforms": [
{
"code": "\tout = []\n\tfor p in (value or []):\n\t\ttry:\n\t\t\tv = p['value']\n\t\t\tout.append({'name': '%s' % p['name'], 'value': '' if v is None else '%s' % v})\n\t\texcept:\n\t\t\tpass\n\treturn out",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"cells": {
"style": {
"padding": "5px"
}
},
"columns": [
{
"field": "name",
"header": {
"title": "Property"
},
"render": "string",
"sortable": false,
"strictWidth": true,
"width": 180
},
{
"field": "value",
"header": {
"title": "Value"
},
"render": "string",
"sortable": false
}
],
"emptyMessage": {
"noData": {
"text": "No extended properties for this event"
}
},
"pager": {
"bottom": false,
"top": false
}
},
"type": "ia.display.table"
}
],
"meta": {
"name": "CardProps"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "6px"
}
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "BodyCol"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\treturn value is not None",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"direction": "column",
"style": {
"gap": "10px"
}
},
"type": "ia.container.flex"
},
{
"meta": {
"name": "EmptyWrap"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.event"
},
"transforms": [
{
"code": "\treturn value is None",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"icon": "info",
"message": "No event selected"
},
"path": "Exchange/AlarmAnalysis/Components/EmptyState"
},
"type": "ia.display.view"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup('exchange.alarmAnalysis.eventDetail')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnClose"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"primary": true,
"text": "Close"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FooterRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"custom": {},
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/page-bg",
"gap": "10px",
"padding": "16px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,318 @@
{
"custom": {},
"params": {
"health": null
},
"propConfig": {
"params.health": {
"paramDirection": "input",
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 540,
"width": 540
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "GradeChip"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.style.classes": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\tg = value['grade']\n\texcept:\n\t\tg = None\n\treturn 'exchange/alarm-analysis/grade/' + (g.lower() if g in ['A', 'B', 'C', 'D', 'F'] else 'na')",
"type": "script"
}
],
"type": "property"
}
},
"props.text": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['grade'] or 'N/A'\n\texcept:\n\t\treturn 'N/A'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontSize": "38px",
"paddingBottom": "4px",
"paddingLeft": "18px",
"paddingRight": "18px",
"paddingTop": "4px",
"textAlign": "center"
}
},
"type": "ia.display.label"
},
{
"children": [
{
"meta": {
"name": "LblTitle"
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/big"
},
"text": "Alarm Health Score"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "LblScore"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\ts = value['score']\n\texcept:\n\t\ts = None\n\tif s is None:\n\t\treturn 'No data in selected range'\n\treturn 'Overall score %s / 100' % exchange.alarmAnalysis.fmt.num(s, 1)",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "TitleCol"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"justify": "center"
},
"type": "ia.container.flex"
}
],
"meta": {
"name": "HeaderRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"style": {
"gap": "14px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblSubsTitle"
},
"position": {
"shrink": 0
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/card-title"
},
"text": "Component scores"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "RepSubs"
},
"position": {
"grow": 1
},
"propConfig": {
"props.instances": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\tsubs = value['subs'] or []\n\texcept:\n\t\tsubs = []\n\tout = []\n\tfor s in subs:\n\t\ttry:\n\t\t\tout.append({'key': s['key'], 'label': s['label'], 'score': s['score'], 'weight': s['weight'], 'detail': s['detail']})\n\t\texcept:\n\t\t\tpass\n\treturn out",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"direction": "column",
"elementPosition": {
"basis": "64px",
"grow": 0,
"shrink": 0
},
"path": "Exchange/AlarmAnalysis/Components/ScoreBar",
"style": {
"overflowY": "auto"
},
"useDefaultViewHeight": false,
"useDefaultViewWidth": false
},
"type": "ia.display.flex-repeater"
},
{
"meta": {
"name": "EmptyWrap"
},
"position": {
"grow": 1
},
"propConfig": {
"position.display": {
"binding": {
"config": {
"path": "view.params.health"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn not (value and value['subs'])\n\texcept:\n\t\treturn True",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"params": {
"icon": "assessment",
"message": "No health data in the selected range"
},
"path": "Exchange/AlarmAnalysis/Components/EmptyState"
},
"type": "ia.display.view"
}
],
"meta": {
"name": "CardSubs"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"gap": "6px"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblCaption"
},
"position": {
"grow": 1,
"shrink": 1
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"text": "Weighted ISA-18.2 composite: rate, flood, chattering, standing, priority mix"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup('exchange.alarmAnalysis.healthScore')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnClose"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"primary": true,
"text": "Close"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FooterRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"justify": "space-between",
"style": {
"gap": "12px"
}
},
"type": "ia.container.flex"
}
],
"custom": {},
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/page-bg",
"gap": "12px",
"padding": "16px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,210 @@
{
"custom": {
"report": null
},
"params": {
"refreshToken": null
},
"propConfig": {
"custom.report": {
"binding": {
"config": {
"expression": "{view.params.refreshToken}"
},
"transforms": [
{
"code": "\ttry:\n\t\tr = exchange.alarmAnalysis.alarms.getShiftReportText()\n\t\tif r and r['text']:\n\t\t\treturn r\n\texcept:\n\t\tpass\n\treturn {'text': 'Report unavailable', 'start_ms': 0, 'end_ms': 0, 'label': ''}",
"type": "script"
}
],
"type": "expr"
}
},
"params.refreshToken": {
"paramDirection": "input",
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 560,
"width": 620
}
},
"root": {
"children": [
{
"children": [
{
"meta": {
"name": "LblTitle"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.custom.report"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['label'] or 'Shift Report'\n\texcept:\n\t\treturn 'Shift Report'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/big"
}
},
"type": "ia.display.label"
},
{
"meta": {
"name": "LblWindow"
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.custom.report"
},
"transforms": [
{
"code": "\ttry:\n\t\ts = value['start_ms']\n\t\te = value['end_ms']\n\texcept:\n\t\treturn ''\n\tif not s or not e:\n\t\treturn ''\n\treturn '%s - %s' % (exchange.alarmAnalysis.fmt.dayClock(s), exchange.alarmAnalysis.fmt.dayClock(e))",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "HeaderCol"
},
"position": {
"shrink": 0
},
"props": {
"direction": "column"
},
"type": "ia.container.flex"
},
{
"children": [
{
"meta": {
"name": "LblText"
},
"position": {
"shrink": 0
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.custom.report"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn value['text'] or 'Report unavailable'\n\texcept:\n\t\treturn 'Report unavailable'",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"fontFamily": "monospace",
"fontSize": "12px",
"lineHeight": "1.5",
"whiteSpace": "pre-wrap"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "CardText"
},
"position": {
"grow": 1
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/card",
"overflowY": "auto"
}
},
"type": "ia.container.flex"
},
{
"children": [
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tsystem.perspective.closePopup('exchange.alarmAnalysis.shiftReport')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnClose"
},
"position": {
"basis": "90px",
"shrink": 0
},
"props": {
"primary": true,
"text": "Close"
},
"type": "ia.input.button"
}
],
"meta": {
"name": "FooterRow"
},
"position": {
"shrink": 0
},
"props": {
"alignItems": "center",
"justify": "flex-end"
},
"type": "ia.container.flex"
}
],
"custom": {},
"meta": {
"name": "root"
},
"props": {
"direction": "column",
"style": {
"classes": "exchange/alarm-analysis/page-bg",
"gap": "12px",
"padding": "16px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,10 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {}
}

View File

@@ -0,0 +1,282 @@
{
"custom": {},
"params": {
"bundle": null,
"query": null
},
"propConfig": {
"params.bundle": {
"paramDirection": "input",
"persistent": false
},
"params.query": {
"paramDirection": "input",
"persistent": false
}
},
"props": {
"defaultSize": {
"height": 56,
"width": 1600
}
},
"root": {
"children": [
{
"meta": {
"name": "DdPriority"
},
"position": {
"basis": "170px",
"shrink": 0
},
"propConfig": {
"props.options": {
"binding": {
"config": {
"path": "view.params.bundle.meta.priorities_seen"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn [{'value': p['value'], 'label': p['label']} for p in (value or [])]\n\texcept:\n\t\treturn []",
"type": "script"
}
],
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"path": "view.params.query.priorities"
},
"type": "property"
}
}
},
"props": {
"multiSelect": true,
"placeholder": {
"text": "Priority"
},
"style": {
"maxWidth": "280px"
},
"wrapMultiSelectValues": true
},
"type": "ia.input.dropdown"
},
{
"meta": {
"name": "DdArea"
},
"position": {
"basis": "170px",
"shrink": 0
},
"propConfig": {
"props.options": {
"binding": {
"config": {
"path": "view.params.bundle.meta.areas"
},
"transforms": [
{
"code": "\ttry:\n\t\treturn [{'value': a, 'label': a} for a in (value or [])]\n\texcept:\n\t\treturn []",
"type": "script"
}
],
"type": "property"
}
},
"props.value": {
"binding": {
"config": {
"path": "view.params.query.areas"
},
"type": "property"
}
}
},
"props": {
"multiSelect": true,
"placeholder": {
"text": "Area"
},
"style": {
"maxWidth": "280px"
},
"wrapMultiSelectValues": true
},
"type": "ia.input.dropdown"
},
{
"meta": {
"name": "DdState"
},
"position": {
"basis": "170px",
"shrink": 0
},
"propConfig": {
"props.value": {
"binding": {
"config": {
"path": "view.params.query.states"
},
"type": "property"
}
}
},
"props": {
"multiSelect": true,
"options": [
{
"label": "Active",
"value": "active"
},
{
"label": "Cleared",
"value": "cleared"
},
{
"label": "Acked",
"value": "acked"
},
{
"label": "Unacked",
"value": "unacked"
}
],
"placeholder": {
"text": "State"
},
"style": {
"maxWidth": "280px"
},
"wrapMultiSelectValues": true
},
"type": "ia.input.dropdown"
},
{
"meta": {
"name": "TxtSearch"
},
"position": {
"basis": "240px",
"shrink": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.query.search"
},
"type": "property"
}
}
},
"props": {
"deferUpdates": true,
"placeholder": "Search source/label..."
},
"type": "ia.input.text-field"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\ttry:\n\t\tfilters = {\n\t\t\t'priorities': list(self.getSibling('DdPriority').props.value or []),\n\t\t\t'areas': list(self.getSibling('DdArea').props.value or []),\n\t\t\t'states': list(self.getSibling('DdState').props.value or []),\n\t\t\t'search': str(self.getSibling('TxtSearch').props.text or '')\n\t\t}\n\texcept:\n\t\tfilters = {'priorities': [], 'areas': [], 'states': [], 'search': ''}\n\tsystem.perspective.sendMessage('exchange.alarmAnalysis.applyFilters', payload = filters, scope = 'page')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnApply"
},
"position": {
"basis": "80px",
"shrink": 0
},
"props": {
"primary": true,
"text": "Apply"
},
"type": "ia.input.button"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\ttry:\n\t\tself.getSibling('DdPriority').props.value = []\n\t\tself.getSibling('DdArea').props.value = []\n\t\tself.getSibling('DdState').props.value = []\n\t\tself.getSibling('TxtSearch').props.text = ''\n\texcept:\n\t\tpass\n\tsystem.perspective.sendMessage('exchange.alarmAnalysis.clearFilters', payload = {}, scope = 'page')"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "BtnClear"
},
"position": {
"basis": "80px",
"shrink": 0
},
"props": {
"primary": false,
"text": "Clear"
},
"type": "ia.input.button"
},
{
"meta": {
"name": "LblEventCount"
},
"position": {
"grow": 1
},
"propConfig": {
"props.text": {
"binding": {
"config": {
"path": "view.params.bundle"
},
"transforms": [
{
"code": "\ttry:\n\t\tn = value['meta']['event_count']\n\texcept:\n\t\tn = None\n\tif n is None:\n\t\treturn ''\n\treturn '%s events in range' % exchange.alarmAnalysis.fmt.num(n)",
"type": "script"
}
],
"type": "property"
}
}
},
"props": {
"style": {
"classes": "exchange/alarm-analysis/text/muted"
},
"textStyle": {
"textAlign": "right"
}
},
"type": "ia.display.label"
}
],
"meta": {
"name": "root"
},
"props": {
"alignItems": "center",
"direction": "row",
"style": {
"classes": "exchange/alarm-analysis/toolbar",
"gap": "8px"
}
},
"type": "ia.container.flex"
}
}

View File

@@ -0,0 +1,16 @@
{
"scope": "G",
"version": 1,
"restricted": false,
"overridable": true,
"files": [
"view.json"
],
"attributes": {
"lastModificationSignature": "ad9c36584854ed67b341f681e7992b6264caf658ed334102fa088a1cc84012fd",
"lastModification": {
"actor": "admin",
"timestamp": "2026-07-16T20:47:54Z"
}
}
}

Some files were not shown because too many files have changed in this diff Show More