No, I try to keep most things consistent like you do, seeing your shared iterations. This was more geared towards widgets in the Dashboard component. If they have it take up half of the screen, there is a lot of space available to make the text bigger.
Alternative Alarm Status Table Styling - Use Pills for Priority and State columns
Disclaimer: I haven’t tested any of this all that thoroughly yet!
I had a request from a customer to change the alarm status table styles. This was a bit of fun (and headache).
This requires CSS and a bit of JS injection (required for the splitting of the State values).
It has a number of parts:
-
Alarm Status Table component which contains specific rowStyles
Alarm Status Table - Copy JSON and Paste into a Flex Container
[ { "type": "ia.display.alarmstatustable", "version": 0, "props": { "refreshRate": 2000, "toolbar": { "enableShelvedTab": false, "enableFilter": false, "toggleableFilter": false, "enablePreFilters": false, "enableConfiguration": false }, "filters": { "active": { "priorities": { "diagnostic": true } } }, "rowStyles": { "activeUnacked": { "base": { "backgroundColor": "white", "color": "hsl(0 0% 5%)", "maxHeight": "3rem", "minHeight": "3rem" }, "priorities": { "low": { "backgroundColor": "white" }, "medium": { "backgroundColor": "white" }, "high": { "backgroundColor": "white" }, "critical": { "backgroundColor": "white" } } }, "activeAcked": { "base": { "backgroundColor": "white", "color": "hsl(0 0% 5%)", "fontWeight": "normal", "maxHeight": "3rem", "minHeight": "3rem" }, "priorities": { "low": { "backgroundColor": "white" }, "medium": { "backgroundColor": "white" }, "high": { "backgroundColor": "white" }, "critical": { "backgroundColor": "white" } } }, "clearUnacked": { "base": { "backgroundColor": "white", "fontWeight": "lighter", "color": "hsl(0 0% 70%)", "maxHeight": "3rem", "minHeight": "3rem" }, "priorities": { "diagnostic": { "backgroundColor": "white", "color": "hsl(0 0% 70%)" }, "low": { "backgroundColor": "white" }, "medium": { "backgroundColor": "white" }, "high": { "backgroundColor": "white" }, "critical": { "backgroundColor": "white" } } }, "clearAcked": { "base": { "backgroundColor": "white", "color": "hsl(0 0% 70%)", "fontWeight": "lighter", "maxHeight": "3rem", "minHeight": "3rem" }, "priorities": { "diagnostic": { "color": "hsl(0 0% 70%)" }, "low": { "backgroundColor": "white" }, "medium": { "backgroundColor": "white" }, "high": { "backgroundColor": "white" }, "critical": { "backgroundColor": "white" } } } }, "dateFormat": "DD MMM yyyy HH:mm z", "activeSortOrder": [ "activeTime" ], "columns": { "active": { "activeTime": { "sort": "descending", "width": 230, "strictWidth": true, "order": 3 }, "displayPath": { "width": 350, "strictWidth": true }, "priority": { "sort": "none", "width": 160, "strictWidth": true, "order": 0 }, "state": { "sort": "none", "width": 320, "strictWidth": true, "order": 4 }, "source": { "enabled": false, "width": 240, "order": 3 }, "name": { "enabled": false, "order": 2 } } }, "columnsAssociated": { "active": [ { "field": "Description", "enabled": true, "width": "", "strictWidth": false, "sort": "none", "order": 2 } ] } }, "meta": { "name": "AlarmStatusTable" }, "position": { "grow": 1, "basis": "400px" }, "custom": {} } ] -
Markdown Javascript injector component which converts the State column text into separate components and adds them into a flex
Markdown JS Injector (State-only mods) - Copy JSON and Paste into the View containing the AST
[ { "type": "ia.display.markdown", "version": 0, "props": { "style": { "flex": "--neutral-40" }, "markdown": { "escapeHtml": false } }, "meta": { "name": "JSInject_ConvertStateColToPillBoxes" }, "position": { "shrink": 0, "basis": 0 }, "custom": { "inlineJavascript": "(() => {\n const styleAlarmStates = () => {\n document.querySelectorAll(\".ia_table__cell[data-column-id=state]:not(.ia_table__head__header__cell) .content > div\").forEach(el => {\n if (el.querySelector(\".custom_alarmStatusTable__stateCol_pill\"))\n return;\n const text = el.textContent.trim();\n if (!text)\n return;\n const parts = text.split(\",\").map(s => s.trim());\n const classMap = {\n \"Active\": \"custom_alarmStatusTable__stateCol_active\",\n \"Cleared\": \"custom_alarmStatusTable__stateCol_cleared\",\n \"Acknowledged\": \"custom_alarmStatusTable__stateCol_ack\",\n \"Unacknowledged\": \"custom_alarmStatusTable__stateCol_unack\"\n };\n const pills = parts.map(part => {\n const stateClass = classMap[part] || \"\";\n return \"<span class=\\\"custom_alarmStatusTable__stateCol_pill \" + stateClass + \"\\\">\" + part + \"</span>\";\n }).join(\"\");\n el.innerHTML = \"<div class=\\\"custom_alarmStatusTable__stateCol_container\\\">\" + pills + \"</div>\";\n });\n };\n const setupObserver = () => {\n let rafId;\n const observer = new MutationObserver(() => {\n if (rafId)\n return;\n rafId = requestAnimationFrame(() => {\n styleAlarmStates();\n rafId = null;\n });\n });\n const tableContainer = document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\");\n if (tableContainer) {\n styleAlarmStates();\n observer.observe(tableContainer, {\n childList: true,\n attributes: true,\n subtree: true,\n attributeFilter: [\"title\", \"style\"]\n });\n }\n };\n setupObserver();\n if (!document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n const waitObserver = new MutationObserver(() => {\n if (document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n waitObserver.disconnect();\n setupObserver();\n }\n });\n waitObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n})();\n" }, "propConfig": { "props.source": { "binding": { "config": { "struct": { "script": "{this.custom.inlineJavascript}" }, "waitOnAll": true }, "transforms": [ { "code": "\tcode = \"<img style='display:none' src='/favicon.ico' onload=\\\"\" + value.script.replace('\"', '"') + '\\\"></img>'\n\t\n\tcode = code.replace(\"\\n\", \"\").replace(\"\\t\", \"\").replace(\"\\n\", \"\").replace(\"\\r\", \"\").replace(\"\\r\", \"\").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \")\n\t\n\treturn code", "type": "script" } ], "type": "expr-struct" } } } } ] -
CSS to add to the Advanced Stylesheet
Stylesheet CSS to define the: alarm priority colours and the state pill styles
/* === Setup the standard colour variables ================================================================================= */ :root { /** Format: --c-<area>-<prop><-modifier>, where 'c' means 'colour' **/ /* Alarm Priority Colours */ --c-alarm-critical: hsl(5 95% 65%); /* red */ --c-alarm-critical-text: white; --c-alarm-high: hsl(30, 98%, 55%); /* orange */ --c-alarm-high-text: white; --c-alarm-medium: hsl(50, 98%, 71%); /* yellow */ --c-alarm-medium-text: hsl(0, 0%, 5%); --c-alarm-low: hsl(200, 88%, 51%); /* blue */ --c-alarm-low-text: white; --c-alarm-diagnostic: hsl(0, 0%, 75%); /* grey */ --c-alarm-diagnostic-text: white; } /* === Alarm Status Table Styles =================================================================== */ /* Allow cell text to word wrap */ .alarmStatusTable .ia_table__cell .content div { white-space: pre-wrap; } /* Make the Priority column show a pill-box with the priority colour in the background */ .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title]){ width: 7rem; border-radius: 50vh; height: 1.7rem; padding: 0.2rem 0.5rem; text-align: center; font-weight: normal; text-transform: uppercase; justify-content: center !important; align-items: center; } .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title="Critical"]) { background-color: var(--c-alarm-critical); color: var(--c-alarm-critical-text); } .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title="High"]) { background-color: var(--c-alarm-high); color: var(--c-alarm-high-text); } .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title="Medium"]) { background-color: var(--c-alarm-medium); color: var(--c-alarm-medium-text); } .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title="Low"]) { background-color: var(--c-alarm-low); color: var(--c-alarm-low-text); } .alarmStatusTable .ia_table__cell[data-column-id="priority"] .content:has([title="Diagnostic"]) { background-color: var(--c-alarm-diagnostic); color: var(--c-alarm-diagnostic-text); } /* defines the flex container housing the two state pills */ .custom_alarmStatusTable__stateCol_container { display: flex; gap: 0.3rem; align-items: center;; } /* styles for the pill containers housing the active/cleared and ack/unack states */ .custom_alarmStatusTable__stateCol_pill { border-top-left-radius: 50vh; border-top-right-radius: 50vh; border-bottom-left-radius: 50vh; border-bottom-right-radius: 50vh; margin: ;height: 150%; padding: 0.2rem 0.5rem; text-transform: uppercase; } /* styles for the ack state */ .custom_alarmStatusTable__stateCol_ack { background-color: #C0C1BE; color: hsl(0 0% 5%); font-weight: normal; } /* styles for the unack state */ .custom_alarmStatusTable__stateCol_unack { background-color: #FFC700; color: hsl(0 0% 5%); font-weight: normal; } /* styles for the active state */ .custom_alarmStatusTable__stateCol_active { background-color: #98E737; color: hsl(0 0% 5%); font-weight: normal; } /* styles for the cleared state */ .custom_alarmStatusTable__stateCol_cleared { background-color: #C0C1BE; color: hsl(0 0% 5%); font-weight: normal; }
If you just want to import a single View, here’s the project export in 8.3.2. You’ll still need to copy in the styling into the adv. stylesheet though.
AlarmStatusTable-AlternateStyling.zip (44.2 KB)
They also wanted the datetime formatted differently as well, in case you want this too. If so, replace the Markdown above with this version:
Markdown JS Injector (State & Datetime mods) - Copy JSON and Paste into the View containing the AST
[
{
"type": "ia.display.markdown",
"version": 0,
"props": {
"style": {
"flex": "--neutral-40"
},
"markdown": {
"escapeHtml": false
}
},
"meta": {
"name": "JSInject_ConvertStateColToPillBoxes"
},
"position": {
"shrink": 0,
"basis": 0
},
"custom": {
"inlineJavascript": "(() => {\n const styleAlarmStates = () => {\n document.querySelectorAll(\".ia_table__cell[data-column-id=state]:not(.ia_table__head__header__cell) .content > div\").forEach(el => {\n if (el.querySelector(\".custom_alarmStatusTable__stateCol_pill\"))\n return;\n const text = el.textContent.trim();\n if (!text)\n return;\n const parts = text.split(\",\").map(s => s.trim());\n const classMap = {\n \"Active\": \"custom_alarmStatusTable__stateCol_active\",\n \"Cleared\": \"custom_alarmStatusTable__stateCol_cleared\",\n \"Acknowledged\": \"custom_alarmStatusTable__stateCol_ack\",\n \"Unacknowledged\": \"custom_alarmStatusTable__stateCol_unack\"\n };\n const pills = parts.map(part => {\n const stateClass = classMap[part] || \"\";\n return \"<span class=\\\"custom_alarmStatusTable__stateCol_pill \" + stateClass + \"\\\">\" + part + \"</span>\";\n }).join(\"\");\n el.innerHTML = \"<div class=\\\"custom_alarmStatusTable__stateCol_container\\\">\" + pills + \"</div>\";\n });\n };\n\n const formatDateTimeCells = () => {\n document.querySelectorAll('.alarmStatusTable .ia_table__cell:not(.ia_table__head__header__cell) .content > div').forEach(div => {\n const title = div.getAttribute('title');\n const datetimeRegex = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}[+-]\\d{4}$/;\n \n if (title && datetimeRegex.test(title) && !div.querySelector('div[style*=\"flex\"]')) {\n const text = div.textContent.trim();\n const parts = text.split(' ');\n \n if (parts.length >= 5) {\n const date = parts.slice(0, 3).join(' ').trim();\n const time = parts.slice(3).join(' ').trim();\n \n div.innerHTML = `\n <div style=\"display: flex; flex-direction: column; gap: 2px; align-items: flex-end;\">\n <div style=\"font-weight: bold;\">${date}</div>\n <div style=\"font-size: 0.9em; color: #666;\">${time}</div>\n </div>\n `;\n }\n }\n });\n };\n\n const setupObserver = () => {\n let rafId;\n const observer = new MutationObserver(() => {\n if (rafId)\n return;\n rafId = requestAnimationFrame(() => {\n styleAlarmStates();\n formatDateTimeCells();\n rafId = null;\n });\n });\n const tableContainer = document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\");\n if (tableContainer) {\n styleAlarmStates();\n formatDateTimeCells();\n observer.observe(tableContainer, {\n childList: true,\n attributes: true,\n subtree: true,\n attributeFilter: [\"title\", \"style\"]\n });\n }\n };\n setupObserver();\n if (!document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n const waitObserver = new MutationObserver(() => {\n if (document.querySelector(\".ReactVirtualized__Grid__innerScrollContainer\")) {\n waitObserver.disconnect();\n setupObserver();\n }\n });\n waitObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n})();"
},
"propConfig": {
"props.source": {
"binding": {
"config": {
"struct": {
"script": "{this.custom.inlineJavascript}"
},
"waitOnAll": true
},
"transforms": [
{
"code": "\tcode = \"<img style='display:none' src='/favicon.ico' onload=\\\"\" + value.script.replace('\"', '"') + '\\\"></img>'\n\t\n\tcode = code.replace(\"\\n\", \"\").replace(\"\\t\", \"\").replace(\"\\n\", \"\").replace(\"\\r\", \"\").replace(\"\\r\", \"\").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \").replace(\" \", \" \")\n\t\n\treturn code",
"type": "script"
}
],
"type": "expr-struct"
}
}
}
}
]

