[{"data":1,"prerenderedAt":14809},["ShallowReactive",2],{"blog-\u002Fblog\u002F2026\u002F07\u002Fcalibration-management-dashboard":3,"blog-all-for-related":14808},{"id":4,"title":5,"authors":6,"body":8,"cta":14783,"date":14787,"description":14788,"extension":14789,"image":14790,"lastUpdated":14791,"meta":14792,"navigation":5833,"path":14797,"seo":14798,"sitemap":14799,"stem":14800,"subtitle":14801,"tags":14802,"tldr":14806,"video":14791,"__hash__":14807},"blog\u002Fblog\u002F2026\u002F07\u002Fcalibration-management-dashboard.md","Tracking Instrument Calibration with a Digital Dashboard",[7],"sumit-shinde",{"type":9,"value":10,"toc":14772},"minimark",[11,15,18,27,30,42,45,60,67,72,75,147,158,162,165,202,205,209,212,235,3297,3308,3311,3416,3431,3438,3442,3452,3558,3562,3565,3568,3581,3594,3628,3675,3689,5668,5694,5703,5707,5716,5776,5785,5792,6162,6168,6193,9633,9644,9650,9659,9663,9666,9678,9917,9924,9936,12616,12623,12628,12637,12648,12652,12655,12710,12722,12729,12740,13242,13252,13265,13314,13387,13398,13690,13693,13768,13775,14473,14516,14699,14713,14725,14734,14738,14741,14769],[12,13,14],"p",{},"Most plants know their calibration status at two moments: when someone updates the spreadsheet, and when an auditor asks. The records already hold enough to do better than that: a last calibration date, an interval, and a next due date for every instrument.",[12,16,17],{},"Most registers also have a status field next to those dates, and reading it seems like the obvious move. But whatever writes that field can fall behind. Then the dashboard reports a compliant plant while due dates quietly pass. This build works out every figure from the due date instead, and counts how often the stored status disagrees with it.",[12,19,20,21,26],{},"For background on calibration records, including what they should contain, how calibration intervals are determined, and why overdue instruments matter, see ",[22,23,25],"a",{"href":24},"\u002Fblog\u002F2026\u002F07\u002Fwhat-is-instrument-calibration\u002F","What Is Instrument Calibration (Equipment Calibration)?",".",[12,28,29],{},"A screen in the quality office is only half the job, though. The moment that matters is when someone picks up a torque wrench, and that person isn't looking at a dashboard. So the same check also runs behind a camera at the station: scan the label, get a verdict.",[12,31,32,37,38],{},[33,34],"img",{"alt":35,"src":36},"Calibration status dashboard showing KPI cards for total equipment, valid, due soon, overdue, upcoming, and compliance percentage","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fcalibration-management-dashboard.png"," ",[39,40,41],"em",{},"The finished dashboard: filters in the app bar, KPI row, and asset detail table on one page.",[12,43,44],{},"In this article, we'll build a calibration application in FlowFuse. It will show plant-level compliance figures, let you filter by department and time window, give an asset-level view of what's due and when, and offer a camera-based tool check for the shop floor.",[46,47,48],"blockquote",{},[12,49,50,54,55,59],{},[51,52,53],"strong",{},"Note:"," This tutorial reads from a ",[56,57,58],"code",{},"calibration_assets"," table in FlowFuse Tables, filled with sample instruments. Everything here works the same against a real calibration register, a CMMS, or an ERP endpoint. Only the query nodes change.",[12,61,62,63,26],{},"You can interact with the live demo here: ",[22,64,66],{"href":65},"https:\u002F\u002Fclever-garden-warbler-2554.flowfuse.cloud\u002Fdashboard\u002Fhome","Try the Calibration Status Dashboard Demo",[68,69,71],"h2",{"id":70},"what-youll-need","What You'll Need",[12,73,74],{},"Before you start building, get these ready:",[76,77,78,85,91,127,141],"ul",{},[79,80,81,84],"li",{},[51,82,83],{},"A FlowFuse account."," [Sign up]({% include \"sign-up-url.njk\" %}) for FlowFuse Cloud, or use a self-hosted instance.",[79,86,87,90],{},[51,88,89],{},"A FlowFuse instance up and running."," If you don't have one yet, create a new instance from your FlowFuse Platform.",[79,92,93,96,97,100,101,104,105,104,108,104,111,104,114,104,117,104,120,104,123,126],{},[51,94,95],{},"FlowFuse Dashboard installed."," This tutorial uses ",[56,98,99],{},"@flowfuse\u002Fnode-red-dashboard"," nodes (",[56,102,103],{},"ui-template",", ",[56,106,107],{},"ui-event",[56,109,110],{},"ui-button",[56,112,113],{},"ui-markdown",[56,115,116],{},"ui-notification",[56,118,119],{},"ui-page",[56,121,122],{},"ui-group",[56,124,125],{},"ui-theme",") to build both pages. Install it from the Palette Manager if it isn't already in your instance.",[79,128,129,132,133,136,137,140],{},[51,130,131],{},"A webcam node and an OCR node."," The Tool Check page uses ",[56,134,135],{},"@sumit_shinde_84\u002Fnode-red-dashboard-2-ui-webcam"," to capture the label and ",[56,138,139],{},"@sumit_shinde_84\u002Fnode-red-contrib-simple-ocr"," to read it. Install both from the Palette Manager.",[79,142,143,146],{},[51,144,145],{},"A device with a camera"," for the Tool Check page, since the scanner works through the browser.",[46,148,149],{},[12,150,151,37,153,157],{},[51,152,53],{},[22,154,156],{"href":155},"\u002Fdocs\u002Fuser\u002Fff-tables\u002F","FlowFuse Tables"," is available to Enterprise tier teams on FlowFuse Cloud, and to Enterprise licensed self-hosted teams running on Kubernetes. If you're on a different tier, use any external database instead, such as Postgres or MySQL, with the standard database nodes from the palette. The SQL here is standard PostgreSQL, and the widgets only care about the shape of the rows, not where they came from.",[68,159,161],{"id":160},"how-the-application-works","How the Application Works",[12,163,164],{},"Before we build anything, let's walk through what the application does. There are two pages, and one idea holding them together.",[166,167,168,178],"ol",{},[79,169,170,173,174,177],{},[51,171,172],{},"Home."," A quality engineer picks a department and how far ahead to look. Six figures across the top show how much equipment there is, and how much of it is valid, due soon, overdue, coming up in the chosen window, and compliant overall. Below that is a list of instruments due inside that window, most urgent first, each with its status, due date, and days remaining. The cards describe the whole register for the chosen department. Only the ",[51,175,176],{},"Upcoming"," figure and the table below respond to the time window.",[79,179,180,183,184,187,188,104,191,104,194,197,198,201],{},[51,181,182],{},"Tool Check."," An operator holds a calibration label up to the camera and presses ",[51,185,186],{},"SCAN",". The app reads the tool ID off the label, looks it up, and shows an answer in the middle of the screen: ",[51,189,190],{},"OK to use",[51,192,193],{},"Do not use",[51,195,196],{},"Not in register",", or ",[51,199,200],{},"Label not readable",". No numbers to interpret and no dashboard to search through.",[12,203,204],{},"The due date is the single source of truth for the whole application. Every KPI figure, every status chip in the table, and the scanner's verdict all come from comparing that date to the current time. That is what stops the office screen and the station gate from ever telling two different stories about the same tool.",[68,206,208],{"id":207},"importing-the-simulated-flow","Importing the Simulated Flow",[12,210,211],{},"Instead of pointing the application at a live calibration register, we'll generate one.",[166,213,214,220],{},[79,215,216,217,26],{},"Import the following flow into FlowFuse and click ",[51,218,219],{},"Deploy",[79,221,222,223,226,227,230,231,234],{},"Click the trigger on ",[51,224,225],{},"Create Table",", then the trigger on ",[51,228,229],{},"Generate & Insert Automotive Calibration Dataset",". ",[51,232,233],{},"Drop Table"," is there for when you want to start over from scratch.",[236,237,239],"render-flow",{":height":238},"300",[240,241,246],"pre",{"className":242,"code":243,"language":244,"meta":245,"style":245},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{% raw %}\n[{\"id\":\"8a0785431b6b7a69\",\"type\":\"group\",\"z\":\"673ee3520831d89e\",\"style\":{\"stroke\":\"#b2b3bd\",\"stroke-opacity\":\"1\",\"fill\":\"#f2f3fb\",\"fill-opacity\":\"0.5\",\"label\":true,\"label-position\":\"nw\",\"color\":\"#32333b\"},\"nodes\":[\"45bd6920b3f0f449\",\"842c753f842b71e6\",\"996c79e5aab802e7\",\"d127e13f8fd0dd03\",\"625821abbf04b74c\",\"7b0b7067116ee8a1\",\"8cc39dc849a910fa\",\"e572d03e9887ce33\",\"82643d26e04f2f09\",\"365ee7bcc61d7f58\"],\"x\":54,\"y\":79,\"w\":892,\"h\":242},{\"id\":\"45bd6920b3f0f449\",\"type\":\"debug\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Result\",\"active\":true,\"tosidebar\":true,\"console\":false,\"tostatus\":false,\"complete\":\"payload\",\"targetType\":\"msg\",\"statusVal\":\"\",\"statusType\":\"auto\",\"x\":850,\"y\":280,\"wires\":[]},{\"id\":\"842c753f842b71e6\",\"type\":\"tables-query\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Create Table\",\"query\":\"CREATE TABLE IF NOT EXISTS calibration_assets (\\n    tool_id TEXT PRIMARY KEY,\\n    equipment_name TEXT NOT NULL,\\n    location TEXT NOT NULL,\\n    department TEXT NOT NULL,\\n    serial_number TEXT NOT NULL,\\n    calibration_interval_months INTEGER NOT NULL,\\n    last_calibration_ts TIMESTAMP NOT NULL,\\n    next_due_ts TIMESTAMP NOT NULL,\\n    status TEXT NOT NULL,\\n    calibration_lab TEXT,\\n    certificate_no TEXT,\\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\\n);\",\"split\":false,\"rowsPerMsg\":1,\"x\":330,\"y\":180,\"wires\":[[\"d127e13f8fd0dd03\"]]},{\"id\":\"996c79e5aab802e7\",\"type\":\"inject\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Trigger\",\"props\":[{\"p\":\"payload\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"payload\":\"\",\"payloadType\":\"date\",\"x\":150,\"y\":180,\"wires\":[[\"842c753f842b71e6\"]]},{\"id\":\"d127e13f8fd0dd03\",\"type\":\"debug\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Result\",\"active\":true,\"tosidebar\":true,\"console\":false,\"tostatus\":false,\"complete\":\"payload\",\"targetType\":\"msg\",\"statusVal\":\"\",\"statusType\":\"auto\",\"x\":850,\"y\":180,\"wires\":[]},{\"id\":\"625821abbf04b74c\",\"type\":\"function\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Generate & Insert Automotive Calibration Dataset\",\"func\":\"\u002F\u002F Generate realistic automotive calibration dataset\\nconst departments = [\\n  { name: 'Assembly', locations: ['Engine Line 1', 'Engine Line 2', 'Transmission Line', 'Final Assembly A', 'Final Assembly B'] },\\n  { name: 'Body Shop', locations: ['BIW Cell 1', 'BIW Cell 2', 'Weld Cell 3', 'Robot Cell 5'] },\\n  { name: 'Paint Shop', locations: ['Pretreatment', 'E-Coat', 'Paint Booth 1', 'Paint Booth 2'] },\\n  { name: 'Powertrain', locations: ['Engine Test Cell', 'Dynamometer Area', 'Cylinder Head Line'] },\\n  { name: 'Quality', locations: ['Inspection Lab', 'Metrology Lab', 'Chassis Inspection', 'Audit Room'] },\\n  { name: 'Tool Room', locations: ['Tool Crib', 'Tool Room', 'Gauge Store'] },\\n  { name: 'Maintenance', locations: ['Hydraulic Shop', 'Electrical Shop', 'Utilities Area'] },\\n  { name: 'R&D', locations: ['NVH Lab', 'Prototype Shop', 'Validation Lab'] }\\n];\\n\\nconst equipment = [\\n  'Torque Wrench 1\u002F2', 'Torque Wrench 3\u002F8', 'Digital Torque Tester',\\n  'Micrometer 0-25 mm', 'Micrometer 25-50 mm', 'Vernier Caliper 150 mm',\\n  'Height Gauge 300 mm', 'Dial Gauge', 'Bore Gauge',\\n  'Thread Plug Gauge M10', 'Thread Plug Gauge M12', 'Thread Ring Gauge M12',\\n  'Pressure Gauge 0-10 bar', 'Pressure Gauge 0-25 bar', 'Digital Pressure Transducer',\\n  'Thermocouple Calibrator', 'Temperature Indicator', 'Infrared Thermometer',\\n  'Sound Level Meter', 'Sound Level Calibrator',\\n  'CMM Probe', 'CMM Reference Sphere', 'Surface Roughness Tester',\\n  'Digital Multimeter', 'Insulation Tester', 'Clamp Meter',\\n  'Flow Meter', 'Mass Flow Controller', 'Load Cell 500 kg',\\n  'Load Cell 2 Ton', 'Force Gauge 1000 N', 'Force Gauge 5000 N',\\n  'Thickness Gauge', 'Coating Thickness Gauge', 'Paint Viscosity Cup'\\n];\\n\\nconst labs = [\\n  'ABC Calibration Lab',\\n  'Metro Metrology',\\n  'Precision Labs',\\n  'National Metrology Services',\\n  'Industrial Calibration Centre'\\n];\\n\\nfunction rand(arr) {\\n  return arr[Math.floor(Math.random() * arr.length)];\\n}\\n\\nfunction randomTimestamp(startDate, endDate) {\\n  const start = startDate.getTime();\\n  const end = endDate.getTime();\\n  const d = new Date(start + Math.random() * (end - start));\\n\\n  \u002F\u002F Working hours 07:00-17:00\\n  d.setHours(7 + Math.floor(Math.random() * 10));\\n  d.setMinutes(Math.floor(Math.random() * 60));\\n  d.setSeconds(Math.floor(Math.random() * 60));\\n  d.setMilliseconds(0);\\n\\n  return d.toISOString().slice(0, 19).replace('T', ' ');\\n}\\n\\nfunction addMonths(ts, months) {\\n  const d = new Date(ts.replace(' ', 'T'));\\n  d.setMonth(d.getMonth() + months);\\n  return d.toISOString().slice(0, 19).replace('T', ' ');\\n}\\n\\nconst today = new Date('2026-07-28T10:00:00');\\n\\nlet values = [];\\n\\nfor (let i = 1; i \u003C= 120; i++) {\\n\\n  const dept = rand(departments);\\n  const location = rand(dept.locations);\\n  const equip = rand(equipment);\\n  const interval = rand([3, 6, 6, 6, 12, 12]);\\n\\n  \u002F\u002F Status distribution\\n  const r = Math.random();\\n  let status;\\n  if (r \u003C 0.10) status = 'Overdue';\\n  else if (r \u003C 0.30) status = 'DueSoon';\\n  else status = 'Valid';\\n\\n  let lastCal;\\n  let nextDue;\\n\\n  if (status === 'Valid') {\\n    lastCal = randomTimestamp(new Date('2026-01-01'), new Date('2026-06-30'));\\n    nextDue = addMonths(lastCal, interval);\\n\\n  } else if (status === 'DueSoon') {\\n\\n    lastCal = randomTimestamp(new Date('2026-01-01'), new Date('2026-05-31'));\\n\\n    const d = new Date(today);\\n    d.setDate(d.getDate() + Math.floor(Math.random() * 14));\\n    d.setHours(8 + Math.floor(Math.random() * 8));\\n    d.setMinutes(Math.floor(Math.random() * 60));\\n    d.setSeconds(0);\\n\\n    nextDue = d.toISOString().slice(0, 19).replace('T', ' ');\\n\\n  } else {\\n\\n    lastCal = randomTimestamp(new Date('2025-01-01'), new Date('2025-12-31'));\\n\\n    const d = new Date(today);\\n    d.setDate(d.getDate() - (1 + Math.floor(Math.random() * 45)));\\n    d.setHours(8 + Math.floor(Math.random() * 8));\\n    d.setMinutes(Math.floor(Math.random() * 60));\\n    d.setSeconds(0);\\n\\n    nextDue = d.toISOString().slice(0, 19).replace('T', ' ');\\n  }\\n\\n  const toolId = 'TL-' + String(i).padStart(4, '0');\\n  const serial = 'SN' + (100000 + i);\\n  const cert = 'CAL-2026-' + String(1000 + i);\\n  const lab = rand(labs);\\n\\n  values.push(\\n    `('${toolId}','${equip}','${location}','${dept.name}','${serial}',${interval},'${lastCal}','${nextDue}','${status}','${lab}','${cert}')`\\n  );\\n}\\n\\nmsg.query = `\\nINSERT INTO calibration_assets\\n(tool_id, equipment_name, location, department, serial_number,\\n calibration_interval_months, last_calibration_ts, next_due_ts,\\n status, calibration_lab, certificate_no)\\nVALUES\\n${values.join(',\\\\n')};\\n`;\\n\\nreturn msg;\",\"outputs\":1,\"timeout\":0,\"noerr\":0,\"initialize\":\"\",\"finalize\":\"\",\"libs\":[],\"x\":430,\"y\":280,\"wires\":[[\"8cc39dc849a910fa\"]]},{\"id\":\"7b0b7067116ee8a1\",\"type\":\"inject\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Trigger\",\"props\":[{\"p\":\"payload\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"payload\":\"\",\"payloadType\":\"date\",\"x\":150,\"y\":280,\"wires\":[[\"625821abbf04b74c\"]]},{\"id\":\"8cc39dc849a910fa\",\"type\":\"tables-query\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Query\",\"query\":\"\",\"split\":false,\"rowsPerMsg\":1,\"x\":710,\"y\":280,\"wires\":[[\"45bd6920b3f0f449\"]]},{\"id\":\"e572d03e9887ce33\",\"type\":\"tables-query\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Drop Table\",\"query\":\"DROP TABLE IF EXISTS calibration_assets;\\n\",\"split\":false,\"rowsPerMsg\":1,\"x\":330,\"y\":120,\"wires\":[[\"365ee7bcc61d7f58\"]]},{\"id\":\"82643d26e04f2f09\",\"type\":\"inject\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Trigger\",\"props\":[{\"p\":\"payload\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"payload\":\"\",\"payloadType\":\"date\",\"x\":150,\"y\":120,\"wires\":[[\"e572d03e9887ce33\"]]},{\"id\":\"365ee7bcc61d7f58\",\"type\":\"debug\",\"z\":\"673ee3520831d89e\",\"g\":\"8a0785431b6b7a69\",\"name\":\"Result\",\"active\":true,\"tosidebar\":true,\"console\":false,\"tostatus\":false,\"complete\":\"payload\",\"targetType\":\"msg\",\"statusVal\":\"\",\"statusType\":\"auto\",\"x\":850,\"y\":120,\"wires\":[]},{\"id\":\"993b160c135046a2\",\"type\":\"global-config\",\"env\":[],\"modules\":{\"@flowfuse\u002Fnr-tables-nodes\":\"0.2.2\"}}]\n{% endraw %}\n","json","",[56,247,248,264,3287],{"__ignoreMap":245},[249,250,253,257,261],"span",{"class":251,"line":252},"line",1,[249,254,256],{"class":255},"sMK4o","{",[249,258,260],{"class":259},"sTEyZ","% raw %",[249,262,263],{"class":255},"}\n",[249,265,267,270,273,277,279,282,284,288,290,293,295,298,300,302,304,307,309,311,313,316,318,320,322,325,327,329,331,334,336,339,341,345,347,349,351,354,356,358,360,363,365,367,369,372,374,376,378,381,383,385,387,390,392,394,396,399,401,403,405,408,410,412,414,417,419,422,424,427,429,431,433,436,438,440,442,445,447,449,451,454,456,459,461,464,466,469,471,474,476,478,480,483,485,487,489,492,494,496,498,501,503,505,507,510,512,514,516,519,521,523,525,528,530,532,534,537,539,541,543,546,548,550,552,555,557,560,562,565,567,569,573,575,577,580,582,584,587,589,591,594,596,598,601,603,605,608,610,612,615,618,620,622,624,626,628,630,632,634,636,638,640,642,644,647,649,651,653,655,657,659,661,663,665,667,669,672,674,676,678,680,682,684,686,689,691,693,695,698,700,702,704,707,709,711,713,716,718,720,722,725,727,730,732,735,737,739,741,744,746,748,750,753,755,757,759,762,764,766,768,771,773,775,777,780,782,784,787,789,791,794,796,798,800,803,805,807,809,811,813,815,818,820,822,824,826,828,831,833,835,838,840,843,845,847,849,851,853,855,857,859,861,863,865,867,869,872,874,876,878,880,882,884,886,888,890,892,894,896,898,900,902,904,906,908,910,912,914,916,918,920,922,924,926,929,931,933,935,938,941,944,946,949,951,954,956,959,961,964,966,969,971,974,976,979,981,984,986,989,991,994,996,999,1001,1004,1006,1008,1010,1013,1015,1017,1019,1022,1024,1026,1028,1030,1032,1034,1036,1038,1041,1043,1045,1047,1049,1051,1054,1056,1058,1060,1062,1065,1067,1069,1071,1074,1076,1078,1080,1082,1084,1086,1088,1090,1092,1094,1096,1098,1100,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127,1129,1131,1133,1135,1137,1139,1141,1143,1145,1147,1149,1152,1154,1156,1158,1161,1163,1166,1168,1170,1172,1174,1176,1178,1180,1183,1185,1188,1190,1192,1194,1196,1198,1201,1203,1205,1207,1209,1211,1214,1216,1218,1220,1223,1225,1227,1230,1232,1234,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1262,1264,1266,1268,1271,1273,1275,1277,1279,1281,1283,1286,1288,1290,1292,1294,1296,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1328,1330,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350,1352,1354,1356,1358,1360,1362,1364,1366,1368,1370,1372,1374,1376,1378,1380,1382,1384,1386,1388,1390,1392,1394,1396,1398,1400,1402,1404,1406,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430,1432,1434,1436,1438,1440,1442,1444,1446,1448,1450,1452,1454,1456,1458,1460,1462,1464,1466,1468,1470,1472,1474,1476,1478,1480,1482,1484,1486,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506,1508,1510,1512,1514,1516,1518,1520,1522,1524,1526,1528,1530,1532,1534,1536,1538,1540,1542,1544,1546,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579,1581,1583,1585,1587,1589,1591,1593,1595,1597,1599,1601,1603,1606,1608,1610,1612,1615,1617,1620,1622,1625,1627,1630,1632,1635,1637,1640,1642,1645,1647,1650,1652,1655,1657,1660,1662,1665,1668,1671,1673,1676,1678,1681,1683,1686,1688,1691,1693,1696,1698,1701,1703,1706,1708,1711,1713,1716,1718,1721,1723,1726,1728,1731,1733,1735,1737,1740,1742,1745,1747,1750,1752,1755,1757,1760,1762,1765,1767,1769,1771,1774,1776,1779,1781,1784,1786,1789,1791,1794,1796,1799,1801,1804,1806,1809,1811,1814,1816,1819,1821,1824,1826,1829,1831,1834,1836,1838,1840,1843,1845,1848,1850,1853,1855,1857,1859,1861,1863,1866,1868,1871,1873,1876,1878,1881,1883,1886,1888,1891,1893,1896,1898,1901,1903,1906,1908,1911,1913,1916,1918,1921,1923,1926,1928,1931,1933,1936,1938,1941,1943,1946,1948,1951,1953,1956,1958,1961,1963,1966,1968,1971,1973,1976,1978,1981,1983,1986,1988,1991,1993,1996,1998,2001,2003,2005,2007,2010,2012,2014,2016,2018,2020,2022,2024,2026,2028,2031,2033,2036,2038,2041,2043,2046,2048,2051,2053,2056,2058,2061,2063,2066,2068,2070,2072,2075,2077,2080,2082,2085,2087,2090,2092,2095,2097,2100,2102,2105,2108,2111,2113,2116,2118,2121,2123,2125,2127,2130,2132,2134,2136,2138,2140,2143,2145,2147,2150,2152,2154,2157,2159,2161,2163,2165,2167,2170,2172,2174,2176,2178,2180,2183,2185,2187,2189,2191,2193,2196,2198,2201,2203,2205,2207,2209,2212,2214,2216,2218,2220,2222,2224,2226,2228,2230,2232,2234,2236,2238,2240,2242,2244,2246,2248,2250,2252,2254,2256,2258,2260,2262,2264,2266,2268,2270,2272,2274,2276,2278,2280,2282,2284,2286,2288,2290,2292,2294,2296,2298,2300,2302,2304,2306,2308,2310,2312,2314,2316,2318,2320,2322,2324,2326,2328,2330,2332,2334,2336,2338,2340,2342,2344,2346,2348,2350,2352,2354,2356,2358,2360,2362,2364,2366,2368,2370,2372,2374,2376,2378,2380,2382,2384,2386,2388,2390,2392,2394,2396,2398,2400,2402,2404,2406,2408,2410,2412,2414,2416,2418,2420,2422,2424,2426,2428,2430,2432,2434,2436,2438,2440,2442,2444,2446,2448,2450,2452,2454,2456,2458,2460,2462,2464,2466,2468,2470,2472,2474,2476,2478,2480,2482,2484,2486,2488,2490,2492,2494,2496,2498,2500,2502,2504,2506,2508,2510,2512,2514,2516,2518,2520,2522,2524,2526,2528,2530,2532,2534,2536,2538,2540,2542,2544,2547,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569,2571,2573,2575,2577,2579,2581,2583,2585,2587,2589,2591,2594,2596,2598,2600,2602,2604,2606,2608,2610,2612,2614,2616,2618,2620,2622,2624,2626,2628,2630,2632,2634,2636,2638,2640,2642,2644,2646,2648,2650,2652,2654,2656,2658,2660,2662,2664,2666,2668,2670,2672,2674,2676,2678,2680,2682,2684,2686,2688,2690,2692,2694,2696,2698,2700,2702,2704,2706,2708,2710,2712,2714,2717,2719,2721,2723,2725,2727,2729,2731,2733,2735,2737,2739,2741,2743,2745,2747,2749,2751,2753,2755,2757,2759,2761,2763,2766,2768,2770,2772,2774,2776,2778,2780,2782,2784,2786,2788,2790,2792,2794,2796,2798,2800,2802,2804,2806,2808,2810,2812,2814,2816,2818,2820,2822,2824,2826,2828,2830,2832,2834,2836,2838,2840,2842,2844,2846,2848,2850,2852,2854,2856,2858,2860,2862,2864,2866,2868,2870,2872,2874,2876,2878,2880,2882,2884,2886,2888,2890,2892,2894,2896,2898,2900,2902,2904,2906,2908,2910,2912,2914,2916,2918,2920,2922,2924,2926,2928,2930,2932,2934,2936,2938,2940,2942,2944,2946,2948,2950,2952,2954,2956,2958,2960,2962,2964,2966,2968,2970,2972,2974,2976,2978,2980,2982,2984,2986,2988,2990,2992,2994,2996,2998,3000,3002,3004,3006,3008,3010,3012,3014,3016,3018,3020,3022,3024,3026,3028,3030,3032,3034,3036,3038,3040,3042,3044,3046,3048,3050,3052,3054,3056,3058,3060,3062,3064,3066,3068,3070,3072,3074,3076,3078,3080,3082,3084,3086,3088,3090,3092,3094,3096,3098,3100,3102,3104,3106,3108,3110,3112,3114,3116,3118,3120,3122,3124,3126,3128,3130,3132,3134,3136,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158,3160,3162,3164,3166,3168,3170,3172,3174,3176,3178,3180,3182,3184,3186,3188,3190,3192,3194,3196,3198,3200,3202,3204,3206,3208,3210,3212,3214,3216,3218,3220,3222,3224,3226,3229,3231,3233,3235,3237,3239,3241,3243,3246,3248,3250,3252,3255,3257,3259,3261,3264,3266,3268,3270,3273,3275,3277,3279,3282,3284],{"class":251,"line":266},2,[249,268,269],{"class":255},"[{",[249,271,272],{"class":255},"\"",[249,274,276],{"class":275},"spNyl","id",[249,278,272],{"class":255},[249,280,281],{"class":255},":",[249,283,272],{"class":255},[249,285,287],{"class":286},"sfazB","8a0785431b6b7a69",[249,289,272],{"class":255},[249,291,292],{"class":255},",",[249,294,272],{"class":255},[249,296,297],{"class":275},"type",[249,299,272],{"class":255},[249,301,281],{"class":255},[249,303,272],{"class":255},[249,305,306],{"class":286},"group",[249,308,272],{"class":255},[249,310,292],{"class":255},[249,312,272],{"class":255},[249,314,315],{"class":275},"z",[249,317,272],{"class":255},[249,319,281],{"class":255},[249,321,272],{"class":255},[249,323,324],{"class":286},"673ee3520831d89e",[249,326,272],{"class":255},[249,328,292],{"class":255},[249,330,272],{"class":255},[249,332,333],{"class":275},"style",[249,335,272],{"class":255},[249,337,338],{"class":255},":{",[249,340,272],{"class":255},[249,342,344],{"class":343},"sBMFI","stroke",[249,346,272],{"class":255},[249,348,281],{"class":255},[249,350,272],{"class":255},[249,352,353],{"class":286},"#b2b3bd",[249,355,272],{"class":255},[249,357,292],{"class":255},[249,359,272],{"class":255},[249,361,362],{"class":343},"stroke-opacity",[249,364,272],{"class":255},[249,366,281],{"class":255},[249,368,272],{"class":255},[249,370,371],{"class":286},"1",[249,373,272],{"class":255},[249,375,292],{"class":255},[249,377,272],{"class":255},[249,379,380],{"class":343},"fill",[249,382,272],{"class":255},[249,384,281],{"class":255},[249,386,272],{"class":255},[249,388,389],{"class":286},"#f2f3fb",[249,391,272],{"class":255},[249,393,292],{"class":255},[249,395,272],{"class":255},[249,397,398],{"class":343},"fill-opacity",[249,400,272],{"class":255},[249,402,281],{"class":255},[249,404,272],{"class":255},[249,406,407],{"class":286},"0.5",[249,409,272],{"class":255},[249,411,292],{"class":255},[249,413,272],{"class":255},[249,415,416],{"class":343},"label",[249,418,272],{"class":255},[249,420,421],{"class":255},":true,",[249,423,272],{"class":255},[249,425,426],{"class":343},"label-position",[249,428,272],{"class":255},[249,430,281],{"class":255},[249,432,272],{"class":255},[249,434,435],{"class":286},"nw",[249,437,272],{"class":255},[249,439,292],{"class":255},[249,441,272],{"class":255},[249,443,444],{"class":343},"color",[249,446,272],{"class":255},[249,448,281],{"class":255},[249,450,272],{"class":255},[249,452,453],{"class":286},"#32333b",[249,455,272],{"class":255},[249,457,458],{"class":255},"},",[249,460,272],{"class":255},[249,462,463],{"class":275},"nodes",[249,465,272],{"class":255},[249,467,468],{"class":255},":[",[249,470,272],{"class":255},[249,472,473],{"class":286},"45bd6920b3f0f449",[249,475,272],{"class":255},[249,477,292],{"class":255},[249,479,272],{"class":255},[249,481,482],{"class":286},"842c753f842b71e6",[249,484,272],{"class":255},[249,486,292],{"class":255},[249,488,272],{"class":255},[249,490,491],{"class":286},"996c79e5aab802e7",[249,493,272],{"class":255},[249,495,292],{"class":255},[249,497,272],{"class":255},[249,499,500],{"class":286},"d127e13f8fd0dd03",[249,502,272],{"class":255},[249,504,292],{"class":255},[249,506,272],{"class":255},[249,508,509],{"class":286},"625821abbf04b74c",[249,511,272],{"class":255},[249,513,292],{"class":255},[249,515,272],{"class":255},[249,517,518],{"class":286},"7b0b7067116ee8a1",[249,520,272],{"class":255},[249,522,292],{"class":255},[249,524,272],{"class":255},[249,526,527],{"class":286},"8cc39dc849a910fa",[249,529,272],{"class":255},[249,531,292],{"class":255},[249,533,272],{"class":255},[249,535,536],{"class":286},"e572d03e9887ce33",[249,538,272],{"class":255},[249,540,292],{"class":255},[249,542,272],{"class":255},[249,544,545],{"class":286},"82643d26e04f2f09",[249,547,272],{"class":255},[249,549,292],{"class":255},[249,551,272],{"class":255},[249,553,554],{"class":286},"365ee7bcc61d7f58",[249,556,272],{"class":255},[249,558,559],{"class":255},"],",[249,561,272],{"class":255},[249,563,564],{"class":275},"x",[249,566,272],{"class":255},[249,568,281],{"class":255},[249,570,572],{"class":571},"sbssI","54",[249,574,292],{"class":255},[249,576,272],{"class":255},[249,578,579],{"class":275},"y",[249,581,272],{"class":255},[249,583,281],{"class":255},[249,585,586],{"class":571},"79",[249,588,292],{"class":255},[249,590,272],{"class":255},[249,592,593],{"class":275},"w",[249,595,272],{"class":255},[249,597,281],{"class":255},[249,599,600],{"class":571},"892",[249,602,292],{"class":255},[249,604,272],{"class":255},[249,606,607],{"class":275},"h",[249,609,272],{"class":255},[249,611,281],{"class":255},[249,613,614],{"class":571},"242",[249,616,617],{"class":255},"},{",[249,619,272],{"class":255},[249,621,276],{"class":275},[249,623,272],{"class":255},[249,625,281],{"class":255},[249,627,272],{"class":255},[249,629,473],{"class":286},[249,631,272],{"class":255},[249,633,292],{"class":255},[249,635,272],{"class":255},[249,637,297],{"class":275},[249,639,272],{"class":255},[249,641,281],{"class":255},[249,643,272],{"class":255},[249,645,646],{"class":286},"debug",[249,648,272],{"class":255},[249,650,292],{"class":255},[249,652,272],{"class":255},[249,654,315],{"class":275},[249,656,272],{"class":255},[249,658,281],{"class":255},[249,660,272],{"class":255},[249,662,324],{"class":286},[249,664,272],{"class":255},[249,666,292],{"class":255},[249,668,272],{"class":255},[249,670,671],{"class":275},"g",[249,673,272],{"class":255},[249,675,281],{"class":255},[249,677,272],{"class":255},[249,679,287],{"class":286},[249,681,272],{"class":255},[249,683,292],{"class":255},[249,685,272],{"class":255},[249,687,688],{"class":275},"name",[249,690,272],{"class":255},[249,692,281],{"class":255},[249,694,272],{"class":255},[249,696,697],{"class":286},"Result",[249,699,272],{"class":255},[249,701,292],{"class":255},[249,703,272],{"class":255},[249,705,706],{"class":275},"active",[249,708,272],{"class":255},[249,710,421],{"class":255},[249,712,272],{"class":255},[249,714,715],{"class":275},"tosidebar",[249,717,272],{"class":255},[249,719,421],{"class":255},[249,721,272],{"class":255},[249,723,724],{"class":275},"console",[249,726,272],{"class":255},[249,728,729],{"class":255},":false,",[249,731,272],{"class":255},[249,733,734],{"class":275},"tostatus",[249,736,272],{"class":255},[249,738,729],{"class":255},[249,740,272],{"class":255},[249,742,743],{"class":275},"complete",[249,745,272],{"class":255},[249,747,281],{"class":255},[249,749,272],{"class":255},[249,751,752],{"class":286},"payload",[249,754,272],{"class":255},[249,756,292],{"class":255},[249,758,272],{"class":255},[249,760,761],{"class":275},"targetType",[249,763,272],{"class":255},[249,765,281],{"class":255},[249,767,272],{"class":255},[249,769,770],{"class":286},"msg",[249,772,272],{"class":255},[249,774,292],{"class":255},[249,776,272],{"class":255},[249,778,779],{"class":275},"statusVal",[249,781,272],{"class":255},[249,783,281],{"class":255},[249,785,786],{"class":255},"\"\"",[249,788,292],{"class":255},[249,790,272],{"class":255},[249,792,793],{"class":275},"statusType",[249,795,272],{"class":255},[249,797,281],{"class":255},[249,799,272],{"class":255},[249,801,802],{"class":286},"auto",[249,804,272],{"class":255},[249,806,292],{"class":255},[249,808,272],{"class":255},[249,810,564],{"class":275},[249,812,272],{"class":255},[249,814,281],{"class":255},[249,816,817],{"class":571},"850",[249,819,292],{"class":255},[249,821,272],{"class":255},[249,823,579],{"class":275},[249,825,272],{"class":255},[249,827,281],{"class":255},[249,829,830],{"class":571},"280",[249,832,292],{"class":255},[249,834,272],{"class":255},[249,836,837],{"class":275},"wires",[249,839,272],{"class":255},[249,841,842],{"class":255},":[]},{",[249,844,272],{"class":255},[249,846,276],{"class":275},[249,848,272],{"class":255},[249,850,281],{"class":255},[249,852,272],{"class":255},[249,854,482],{"class":286},[249,856,272],{"class":255},[249,858,292],{"class":255},[249,860,272],{"class":255},[249,862,297],{"class":275},[249,864,272],{"class":255},[249,866,281],{"class":255},[249,868,272],{"class":255},[249,870,871],{"class":286},"tables-query",[249,873,272],{"class":255},[249,875,292],{"class":255},[249,877,272],{"class":255},[249,879,315],{"class":275},[249,881,272],{"class":255},[249,883,281],{"class":255},[249,885,272],{"class":255},[249,887,324],{"class":286},[249,889,272],{"class":255},[249,891,292],{"class":255},[249,893,272],{"class":255},[249,895,671],{"class":275},[249,897,272],{"class":255},[249,899,281],{"class":255},[249,901,272],{"class":255},[249,903,287],{"class":286},[249,905,272],{"class":255},[249,907,292],{"class":255},[249,909,272],{"class":255},[249,911,688],{"class":275},[249,913,272],{"class":255},[249,915,281],{"class":255},[249,917,272],{"class":255},[249,919,225],{"class":286},[249,921,272],{"class":255},[249,923,292],{"class":255},[249,925,272],{"class":255},[249,927,928],{"class":275},"query",[249,930,272],{"class":255},[249,932,281],{"class":255},[249,934,272],{"class":255},[249,936,937],{"class":286},"CREATE TABLE IF NOT EXISTS calibration_assets (",[249,939,940],{"class":259},"\\n",[249,942,943],{"class":286},"    tool_id TEXT PRIMARY KEY,",[249,945,940],{"class":259},[249,947,948],{"class":286},"    equipment_name TEXT NOT NULL,",[249,950,940],{"class":259},[249,952,953],{"class":286},"    location TEXT NOT NULL,",[249,955,940],{"class":259},[249,957,958],{"class":286},"    department TEXT NOT NULL,",[249,960,940],{"class":259},[249,962,963],{"class":286},"    serial_number TEXT NOT NULL,",[249,965,940],{"class":259},[249,967,968],{"class":286},"    calibration_interval_months INTEGER NOT NULL,",[249,970,940],{"class":259},[249,972,973],{"class":286},"    last_calibration_ts TIMESTAMP NOT NULL,",[249,975,940],{"class":259},[249,977,978],{"class":286},"    next_due_ts TIMESTAMP NOT NULL,",[249,980,940],{"class":259},[249,982,983],{"class":286},"    status TEXT NOT NULL,",[249,985,940],{"class":259},[249,987,988],{"class":286},"    calibration_lab TEXT,",[249,990,940],{"class":259},[249,992,993],{"class":286},"    certificate_no TEXT,",[249,995,940],{"class":259},[249,997,998],{"class":286},"    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP",[249,1000,940],{"class":259},[249,1002,1003],{"class":286},");",[249,1005,272],{"class":255},[249,1007,292],{"class":255},[249,1009,272],{"class":255},[249,1011,1012],{"class":275},"split",[249,1014,272],{"class":255},[249,1016,729],{"class":255},[249,1018,272],{"class":255},[249,1020,1021],{"class":275},"rowsPerMsg",[249,1023,272],{"class":255},[249,1025,281],{"class":255},[249,1027,371],{"class":571},[249,1029,292],{"class":255},[249,1031,272],{"class":255},[249,1033,564],{"class":275},[249,1035,272],{"class":255},[249,1037,281],{"class":255},[249,1039,1040],{"class":571},"330",[249,1042,292],{"class":255},[249,1044,272],{"class":255},[249,1046,579],{"class":275},[249,1048,272],{"class":255},[249,1050,281],{"class":255},[249,1052,1053],{"class":571},"180",[249,1055,292],{"class":255},[249,1057,272],{"class":255},[249,1059,837],{"class":275},[249,1061,272],{"class":255},[249,1063,1064],{"class":255},":[[",[249,1066,272],{"class":255},[249,1068,500],{"class":286},[249,1070,272],{"class":255},[249,1072,1073],{"class":255},"]]},{",[249,1075,272],{"class":255},[249,1077,276],{"class":275},[249,1079,272],{"class":255},[249,1081,281],{"class":255},[249,1083,272],{"class":255},[249,1085,491],{"class":286},[249,1087,272],{"class":255},[249,1089,292],{"class":255},[249,1091,272],{"class":255},[249,1093,297],{"class":275},[249,1095,272],{"class":255},[249,1097,281],{"class":255},[249,1099,272],{"class":255},[249,1101,1102],{"class":286},"inject",[249,1104,272],{"class":255},[249,1106,292],{"class":255},[249,1108,272],{"class":255},[249,1110,315],{"class":275},[249,1112,272],{"class":255},[249,1114,281],{"class":255},[249,1116,272],{"class":255},[249,1118,324],{"class":286},[249,1120,272],{"class":255},[249,1122,292],{"class":255},[249,1124,272],{"class":255},[249,1126,671],{"class":275},[249,1128,272],{"class":255},[249,1130,281],{"class":255},[249,1132,272],{"class":255},[249,1134,287],{"class":286},[249,1136,272],{"class":255},[249,1138,292],{"class":255},[249,1140,272],{"class":255},[249,1142,688],{"class":275},[249,1144,272],{"class":255},[249,1146,281],{"class":255},[249,1148,272],{"class":255},[249,1150,1151],{"class":286},"Trigger",[249,1153,272],{"class":255},[249,1155,292],{"class":255},[249,1157,272],{"class":255},[249,1159,1160],{"class":275},"props",[249,1162,272],{"class":255},[249,1164,1165],{"class":255},":[{",[249,1167,272],{"class":255},[249,1169,12],{"class":343},[249,1171,272],{"class":255},[249,1173,281],{"class":255},[249,1175,272],{"class":255},[249,1177,752],{"class":286},[249,1179,272],{"class":255},[249,1181,1182],{"class":255},"}],",[249,1184,272],{"class":255},[249,1186,1187],{"class":275},"repeat",[249,1189,272],{"class":255},[249,1191,281],{"class":255},[249,1193,786],{"class":255},[249,1195,292],{"class":255},[249,1197,272],{"class":255},[249,1199,1200],{"class":275},"crontab",[249,1202,272],{"class":255},[249,1204,281],{"class":255},[249,1206,786],{"class":255},[249,1208,292],{"class":255},[249,1210,272],{"class":255},[249,1212,1213],{"class":275},"once",[249,1215,272],{"class":255},[249,1217,729],{"class":255},[249,1219,272],{"class":255},[249,1221,1222],{"class":275},"onceDelay",[249,1224,272],{"class":255},[249,1226,281],{"class":255},[249,1228,1229],{"class":571},"0.1",[249,1231,292],{"class":255},[249,1233,272],{"class":255},[249,1235,1236],{"class":275},"topic",[249,1238,272],{"class":255},[249,1240,281],{"class":255},[249,1242,786],{"class":255},[249,1244,292],{"class":255},[249,1246,272],{"class":255},[249,1248,752],{"class":275},[249,1250,272],{"class":255},[249,1252,281],{"class":255},[249,1254,786],{"class":255},[249,1256,292],{"class":255},[249,1258,272],{"class":255},[249,1260,1261],{"class":275},"payloadType",[249,1263,272],{"class":255},[249,1265,281],{"class":255},[249,1267,272],{"class":255},[249,1269,1270],{"class":286},"date",[249,1272,272],{"class":255},[249,1274,292],{"class":255},[249,1276,272],{"class":255},[249,1278,564],{"class":275},[249,1280,272],{"class":255},[249,1282,281],{"class":255},[249,1284,1285],{"class":571},"150",[249,1287,292],{"class":255},[249,1289,272],{"class":255},[249,1291,579],{"class":275},[249,1293,272],{"class":255},[249,1295,281],{"class":255},[249,1297,1053],{"class":571},[249,1299,292],{"class":255},[249,1301,272],{"class":255},[249,1303,837],{"class":275},[249,1305,272],{"class":255},[249,1307,1064],{"class":255},[249,1309,272],{"class":255},[249,1311,482],{"class":286},[249,1313,272],{"class":255},[249,1315,1073],{"class":255},[249,1317,272],{"class":255},[249,1319,276],{"class":275},[249,1321,272],{"class":255},[249,1323,281],{"class":255},[249,1325,272],{"class":255},[249,1327,500],{"class":286},[249,1329,272],{"class":255},[249,1331,292],{"class":255},[249,1333,272],{"class":255},[249,1335,297],{"class":275},[249,1337,272],{"class":255},[249,1339,281],{"class":255},[249,1341,272],{"class":255},[249,1343,646],{"class":286},[249,1345,272],{"class":255},[249,1347,292],{"class":255},[249,1349,272],{"class":255},[249,1351,315],{"class":275},[249,1353,272],{"class":255},[249,1355,281],{"class":255},[249,1357,272],{"class":255},[249,1359,324],{"class":286},[249,1361,272],{"class":255},[249,1363,292],{"class":255},[249,1365,272],{"class":255},[249,1367,671],{"class":275},[249,1369,272],{"class":255},[249,1371,281],{"class":255},[249,1373,272],{"class":255},[249,1375,287],{"class":286},[249,1377,272],{"class":255},[249,1379,292],{"class":255},[249,1381,272],{"class":255},[249,1383,688],{"class":275},[249,1385,272],{"class":255},[249,1387,281],{"class":255},[249,1389,272],{"class":255},[249,1391,697],{"class":286},[249,1393,272],{"class":255},[249,1395,292],{"class":255},[249,1397,272],{"class":255},[249,1399,706],{"class":275},[249,1401,272],{"class":255},[249,1403,421],{"class":255},[249,1405,272],{"class":255},[249,1407,715],{"class":275},[249,1409,272],{"class":255},[249,1411,421],{"class":255},[249,1413,272],{"class":255},[249,1415,724],{"class":275},[249,1417,272],{"class":255},[249,1419,729],{"class":255},[249,1421,272],{"class":255},[249,1423,734],{"class":275},[249,1425,272],{"class":255},[249,1427,729],{"class":255},[249,1429,272],{"class":255},[249,1431,743],{"class":275},[249,1433,272],{"class":255},[249,1435,281],{"class":255},[249,1437,272],{"class":255},[249,1439,752],{"class":286},[249,1441,272],{"class":255},[249,1443,292],{"class":255},[249,1445,272],{"class":255},[249,1447,761],{"class":275},[249,1449,272],{"class":255},[249,1451,281],{"class":255},[249,1453,272],{"class":255},[249,1455,770],{"class":286},[249,1457,272],{"class":255},[249,1459,292],{"class":255},[249,1461,272],{"class":255},[249,1463,779],{"class":275},[249,1465,272],{"class":255},[249,1467,281],{"class":255},[249,1469,786],{"class":255},[249,1471,292],{"class":255},[249,1473,272],{"class":255},[249,1475,793],{"class":275},[249,1477,272],{"class":255},[249,1479,281],{"class":255},[249,1481,272],{"class":255},[249,1483,802],{"class":286},[249,1485,272],{"class":255},[249,1487,292],{"class":255},[249,1489,272],{"class":255},[249,1491,564],{"class":275},[249,1493,272],{"class":255},[249,1495,281],{"class":255},[249,1497,817],{"class":571},[249,1499,292],{"class":255},[249,1501,272],{"class":255},[249,1503,579],{"class":275},[249,1505,272],{"class":255},[249,1507,281],{"class":255},[249,1509,1053],{"class":571},[249,1511,292],{"class":255},[249,1513,272],{"class":255},[249,1515,837],{"class":275},[249,1517,272],{"class":255},[249,1519,842],{"class":255},[249,1521,272],{"class":255},[249,1523,276],{"class":275},[249,1525,272],{"class":255},[249,1527,281],{"class":255},[249,1529,272],{"class":255},[249,1531,509],{"class":286},[249,1533,272],{"class":255},[249,1535,292],{"class":255},[249,1537,272],{"class":255},[249,1539,297],{"class":275},[249,1541,272],{"class":255},[249,1543,281],{"class":255},[249,1545,272],{"class":255},[249,1547,1548],{"class":286},"function",[249,1550,272],{"class":255},[249,1552,292],{"class":255},[249,1554,272],{"class":255},[249,1556,315],{"class":275},[249,1558,272],{"class":255},[249,1560,281],{"class":255},[249,1562,272],{"class":255},[249,1564,324],{"class":286},[249,1566,272],{"class":255},[249,1568,292],{"class":255},[249,1570,272],{"class":255},[249,1572,671],{"class":275},[249,1574,272],{"class":255},[249,1576,281],{"class":255},[249,1578,272],{"class":255},[249,1580,287],{"class":286},[249,1582,272],{"class":255},[249,1584,292],{"class":255},[249,1586,272],{"class":255},[249,1588,688],{"class":275},[249,1590,272],{"class":255},[249,1592,281],{"class":255},[249,1594,272],{"class":255},[249,1596,229],{"class":286},[249,1598,272],{"class":255},[249,1600,292],{"class":255},[249,1602,272],{"class":255},[249,1604,1605],{"class":275},"func",[249,1607,272],{"class":255},[249,1609,281],{"class":255},[249,1611,272],{"class":255},[249,1613,1614],{"class":286},"\u002F\u002F Generate realistic automotive calibration dataset",[249,1616,940],{"class":259},[249,1618,1619],{"class":286},"const departments = [",[249,1621,940],{"class":259},[249,1623,1624],{"class":286},"  { name: 'Assembly', locations: ['Engine Line 1', 'Engine Line 2', 'Transmission Line', 'Final Assembly A', 'Final Assembly B'] },",[249,1626,940],{"class":259},[249,1628,1629],{"class":286},"  { name: 'Body Shop', locations: ['BIW Cell 1', 'BIW Cell 2', 'Weld Cell 3', 'Robot Cell 5'] },",[249,1631,940],{"class":259},[249,1633,1634],{"class":286},"  { name: 'Paint Shop', locations: ['Pretreatment', 'E-Coat', 'Paint Booth 1', 'Paint Booth 2'] },",[249,1636,940],{"class":259},[249,1638,1639],{"class":286},"  { name: 'Powertrain', locations: ['Engine Test Cell', 'Dynamometer Area', 'Cylinder Head Line'] },",[249,1641,940],{"class":259},[249,1643,1644],{"class":286},"  { name: 'Quality', locations: ['Inspection Lab', 'Metrology Lab', 'Chassis Inspection', 'Audit Room'] },",[249,1646,940],{"class":259},[249,1648,1649],{"class":286},"  { name: 'Tool Room', locations: ['Tool Crib', 'Tool Room', 'Gauge Store'] },",[249,1651,940],{"class":259},[249,1653,1654],{"class":286},"  { name: 'Maintenance', locations: ['Hydraulic Shop', 'Electrical Shop', 'Utilities Area'] },",[249,1656,940],{"class":259},[249,1658,1659],{"class":286},"  { name: 'R&D', locations: ['NVH Lab', 'Prototype Shop', 'Validation Lab'] }",[249,1661,940],{"class":259},[249,1663,1664],{"class":286},"];",[249,1666,1667],{"class":259},"\\n\\n",[249,1669,1670],{"class":286},"const equipment = [",[249,1672,940],{"class":259},[249,1674,1675],{"class":286},"  'Torque Wrench 1\u002F2', 'Torque Wrench 3\u002F8', 'Digital Torque Tester',",[249,1677,940],{"class":259},[249,1679,1680],{"class":286},"  'Micrometer 0-25 mm', 'Micrometer 25-50 mm', 'Vernier Caliper 150 mm',",[249,1682,940],{"class":259},[249,1684,1685],{"class":286},"  'Height Gauge 300 mm', 'Dial Gauge', 'Bore Gauge',",[249,1687,940],{"class":259},[249,1689,1690],{"class":286},"  'Thread Plug Gauge M10', 'Thread Plug Gauge M12', 'Thread Ring Gauge M12',",[249,1692,940],{"class":259},[249,1694,1695],{"class":286},"  'Pressure Gauge 0-10 bar', 'Pressure Gauge 0-25 bar', 'Digital Pressure Transducer',",[249,1697,940],{"class":259},[249,1699,1700],{"class":286},"  'Thermocouple Calibrator', 'Temperature Indicator', 'Infrared Thermometer',",[249,1702,940],{"class":259},[249,1704,1705],{"class":286},"  'Sound Level Meter', 'Sound Level Calibrator',",[249,1707,940],{"class":259},[249,1709,1710],{"class":286},"  'CMM Probe', 'CMM Reference Sphere', 'Surface Roughness Tester',",[249,1712,940],{"class":259},[249,1714,1715],{"class":286},"  'Digital Multimeter', 'Insulation Tester', 'Clamp Meter',",[249,1717,940],{"class":259},[249,1719,1720],{"class":286},"  'Flow Meter', 'Mass Flow Controller', 'Load Cell 500 kg',",[249,1722,940],{"class":259},[249,1724,1725],{"class":286},"  'Load Cell 2 Ton', 'Force Gauge 1000 N', 'Force Gauge 5000 N',",[249,1727,940],{"class":259},[249,1729,1730],{"class":286},"  'Thickness Gauge', 'Coating Thickness Gauge', 'Paint Viscosity Cup'",[249,1732,940],{"class":259},[249,1734,1664],{"class":286},[249,1736,1667],{"class":259},[249,1738,1739],{"class":286},"const labs = [",[249,1741,940],{"class":259},[249,1743,1744],{"class":286},"  'ABC Calibration Lab',",[249,1746,940],{"class":259},[249,1748,1749],{"class":286},"  'Metro Metrology',",[249,1751,940],{"class":259},[249,1753,1754],{"class":286},"  'Precision Labs',",[249,1756,940],{"class":259},[249,1758,1759],{"class":286},"  'National Metrology Services',",[249,1761,940],{"class":259},[249,1763,1764],{"class":286},"  'Industrial Calibration Centre'",[249,1766,940],{"class":259},[249,1768,1664],{"class":286},[249,1770,1667],{"class":259},[249,1772,1773],{"class":286},"function rand(arr) {",[249,1775,940],{"class":259},[249,1777,1778],{"class":286},"  return arr[Math.floor(Math.random() * arr.length)];",[249,1780,940],{"class":259},[249,1782,1783],{"class":286},"}",[249,1785,1667],{"class":259},[249,1787,1788],{"class":286},"function randomTimestamp(startDate, endDate) {",[249,1790,940],{"class":259},[249,1792,1793],{"class":286},"  const start = startDate.getTime();",[249,1795,940],{"class":259},[249,1797,1798],{"class":286},"  const end = endDate.getTime();",[249,1800,940],{"class":259},[249,1802,1803],{"class":286},"  const d = new Date(start + Math.random() * (end - start));",[249,1805,1667],{"class":259},[249,1807,1808],{"class":286},"  \u002F\u002F Working hours 07:00-17:00",[249,1810,940],{"class":259},[249,1812,1813],{"class":286},"  d.setHours(7 + Math.floor(Math.random() * 10));",[249,1815,940],{"class":259},[249,1817,1818],{"class":286},"  d.setMinutes(Math.floor(Math.random() * 60));",[249,1820,940],{"class":259},[249,1822,1823],{"class":286},"  d.setSeconds(Math.floor(Math.random() * 60));",[249,1825,940],{"class":259},[249,1827,1828],{"class":286},"  d.setMilliseconds(0);",[249,1830,1667],{"class":259},[249,1832,1833],{"class":286},"  return d.toISOString().slice(0, 19).replace('T', ' ');",[249,1835,940],{"class":259},[249,1837,1783],{"class":286},[249,1839,1667],{"class":259},[249,1841,1842],{"class":286},"function addMonths(ts, months) {",[249,1844,940],{"class":259},[249,1846,1847],{"class":286},"  const d = new Date(ts.replace(' ', 'T'));",[249,1849,940],{"class":259},[249,1851,1852],{"class":286},"  d.setMonth(d.getMonth() + months);",[249,1854,940],{"class":259},[249,1856,1833],{"class":286},[249,1858,940],{"class":259},[249,1860,1783],{"class":286},[249,1862,1667],{"class":259},[249,1864,1865],{"class":286},"const today = new Date('2026-07-28T10:00:00');",[249,1867,1667],{"class":259},[249,1869,1870],{"class":286},"let values = [];",[249,1872,1667],{"class":259},[249,1874,1875],{"class":286},"for (let i = 1; i \u003C= 120; i++) {",[249,1877,1667],{"class":259},[249,1879,1880],{"class":286},"  const dept = rand(departments);",[249,1882,940],{"class":259},[249,1884,1885],{"class":286},"  const location = rand(dept.locations);",[249,1887,940],{"class":259},[249,1889,1890],{"class":286},"  const equip = rand(equipment);",[249,1892,940],{"class":259},[249,1894,1895],{"class":286},"  const interval = rand([3, 6, 6, 6, 12, 12]);",[249,1897,1667],{"class":259},[249,1899,1900],{"class":286},"  \u002F\u002F Status distribution",[249,1902,940],{"class":259},[249,1904,1905],{"class":286},"  const r = Math.random();",[249,1907,940],{"class":259},[249,1909,1910],{"class":286},"  let status;",[249,1912,940],{"class":259},[249,1914,1915],{"class":286},"  if (r \u003C 0.10) status = 'Overdue';",[249,1917,940],{"class":259},[249,1919,1920],{"class":286},"  else if (r \u003C 0.30) status = 'DueSoon';",[249,1922,940],{"class":259},[249,1924,1925],{"class":286},"  else status = 'Valid';",[249,1927,1667],{"class":259},[249,1929,1930],{"class":286},"  let lastCal;",[249,1932,940],{"class":259},[249,1934,1935],{"class":286},"  let nextDue;",[249,1937,1667],{"class":259},[249,1939,1940],{"class":286},"  if (status === 'Valid') {",[249,1942,940],{"class":259},[249,1944,1945],{"class":286},"    lastCal = randomTimestamp(new Date('2026-01-01'), new Date('2026-06-30'));",[249,1947,940],{"class":259},[249,1949,1950],{"class":286},"    nextDue = addMonths(lastCal, interval);",[249,1952,1667],{"class":259},[249,1954,1955],{"class":286},"  } else if (status === 'DueSoon') {",[249,1957,1667],{"class":259},[249,1959,1960],{"class":286},"    lastCal = randomTimestamp(new Date('2026-01-01'), new Date('2026-05-31'));",[249,1962,1667],{"class":259},[249,1964,1965],{"class":286},"    const d = new Date(today);",[249,1967,940],{"class":259},[249,1969,1970],{"class":286},"    d.setDate(d.getDate() + Math.floor(Math.random() * 14));",[249,1972,940],{"class":259},[249,1974,1975],{"class":286},"    d.setHours(8 + Math.floor(Math.random() * 8));",[249,1977,940],{"class":259},[249,1979,1980],{"class":286},"    d.setMinutes(Math.floor(Math.random() * 60));",[249,1982,940],{"class":259},[249,1984,1985],{"class":286},"    d.setSeconds(0);",[249,1987,1667],{"class":259},[249,1989,1990],{"class":286},"    nextDue = d.toISOString().slice(0, 19).replace('T', ' ');",[249,1992,1667],{"class":259},[249,1994,1995],{"class":286},"  } else {",[249,1997,1667],{"class":259},[249,1999,2000],{"class":286},"    lastCal = randomTimestamp(new Date('2025-01-01'), new Date('2025-12-31'));",[249,2002,1667],{"class":259},[249,2004,1965],{"class":286},[249,2006,940],{"class":259},[249,2008,2009],{"class":286},"    d.setDate(d.getDate() - (1 + Math.floor(Math.random() * 45)));",[249,2011,940],{"class":259},[249,2013,1975],{"class":286},[249,2015,940],{"class":259},[249,2017,1980],{"class":286},[249,2019,940],{"class":259},[249,2021,1985],{"class":286},[249,2023,1667],{"class":259},[249,2025,1990],{"class":286},[249,2027,940],{"class":259},[249,2029,2030],{"class":286},"  }",[249,2032,1667],{"class":259},[249,2034,2035],{"class":286},"  const toolId = 'TL-' + String(i).padStart(4, '0');",[249,2037,940],{"class":259},[249,2039,2040],{"class":286},"  const serial = 'SN' + (100000 + i);",[249,2042,940],{"class":259},[249,2044,2045],{"class":286},"  const cert = 'CAL-2026-' + String(1000 + i);",[249,2047,940],{"class":259},[249,2049,2050],{"class":286},"  const lab = rand(labs);",[249,2052,1667],{"class":259},[249,2054,2055],{"class":286},"  values.push(",[249,2057,940],{"class":259},[249,2059,2060],{"class":286},"    `('${toolId}','${equip}','${location}','${dept.name}','${serial}',${interval},'${lastCal}','${nextDue}','${status}','${lab}','${cert}')`",[249,2062,940],{"class":259},[249,2064,2065],{"class":286},"  );",[249,2067,940],{"class":259},[249,2069,1783],{"class":286},[249,2071,1667],{"class":259},[249,2073,2074],{"class":286},"msg.query = `",[249,2076,940],{"class":259},[249,2078,2079],{"class":286},"INSERT INTO calibration_assets",[249,2081,940],{"class":259},[249,2083,2084],{"class":286},"(tool_id, equipment_name, location, department, serial_number,",[249,2086,940],{"class":259},[249,2088,2089],{"class":286}," calibration_interval_months, last_calibration_ts, next_due_ts,",[249,2091,940],{"class":259},[249,2093,2094],{"class":286}," status, calibration_lab, certificate_no)",[249,2096,940],{"class":259},[249,2098,2099],{"class":286},"VALUES",[249,2101,940],{"class":259},[249,2103,2104],{"class":286},"${values.join(',",[249,2106,2107],{"class":259},"\\\\",[249,2109,2110],{"class":286},"n')};",[249,2112,940],{"class":259},[249,2114,2115],{"class":286},"`;",[249,2117,1667],{"class":259},[249,2119,2120],{"class":286},"return msg;",[249,2122,272],{"class":255},[249,2124,292],{"class":255},[249,2126,272],{"class":255},[249,2128,2129],{"class":275},"outputs",[249,2131,272],{"class":255},[249,2133,281],{"class":255},[249,2135,371],{"class":571},[249,2137,292],{"class":255},[249,2139,272],{"class":255},[249,2141,2142],{"class":275},"timeout",[249,2144,272],{"class":255},[249,2146,281],{"class":255},[249,2148,2149],{"class":571},"0",[249,2151,292],{"class":255},[249,2153,272],{"class":255},[249,2155,2156],{"class":275},"noerr",[249,2158,272],{"class":255},[249,2160,281],{"class":255},[249,2162,2149],{"class":571},[249,2164,292],{"class":255},[249,2166,272],{"class":255},[249,2168,2169],{"class":275},"initialize",[249,2171,272],{"class":255},[249,2173,281],{"class":255},[249,2175,786],{"class":255},[249,2177,292],{"class":255},[249,2179,272],{"class":255},[249,2181,2182],{"class":275},"finalize",[249,2184,272],{"class":255},[249,2186,281],{"class":255},[249,2188,786],{"class":255},[249,2190,292],{"class":255},[249,2192,272],{"class":255},[249,2194,2195],{"class":275},"libs",[249,2197,272],{"class":255},[249,2199,2200],{"class":255},":[],",[249,2202,272],{"class":255},[249,2204,564],{"class":275},[249,2206,272],{"class":255},[249,2208,281],{"class":255},[249,2210,2211],{"class":571},"430",[249,2213,292],{"class":255},[249,2215,272],{"class":255},[249,2217,579],{"class":275},[249,2219,272],{"class":255},[249,2221,281],{"class":255},[249,2223,830],{"class":571},[249,2225,292],{"class":255},[249,2227,272],{"class":255},[249,2229,837],{"class":275},[249,2231,272],{"class":255},[249,2233,1064],{"class":255},[249,2235,272],{"class":255},[249,2237,527],{"class":286},[249,2239,272],{"class":255},[249,2241,1073],{"class":255},[249,2243,272],{"class":255},[249,2245,276],{"class":275},[249,2247,272],{"class":255},[249,2249,281],{"class":255},[249,2251,272],{"class":255},[249,2253,518],{"class":286},[249,2255,272],{"class":255},[249,2257,292],{"class":255},[249,2259,272],{"class":255},[249,2261,297],{"class":275},[249,2263,272],{"class":255},[249,2265,281],{"class":255},[249,2267,272],{"class":255},[249,2269,1102],{"class":286},[249,2271,272],{"class":255},[249,2273,292],{"class":255},[249,2275,272],{"class":255},[249,2277,315],{"class":275},[249,2279,272],{"class":255},[249,2281,281],{"class":255},[249,2283,272],{"class":255},[249,2285,324],{"class":286},[249,2287,272],{"class":255},[249,2289,292],{"class":255},[249,2291,272],{"class":255},[249,2293,671],{"class":275},[249,2295,272],{"class":255},[249,2297,281],{"class":255},[249,2299,272],{"class":255},[249,2301,287],{"class":286},[249,2303,272],{"class":255},[249,2305,292],{"class":255},[249,2307,272],{"class":255},[249,2309,688],{"class":275},[249,2311,272],{"class":255},[249,2313,281],{"class":255},[249,2315,272],{"class":255},[249,2317,1151],{"class":286},[249,2319,272],{"class":255},[249,2321,292],{"class":255},[249,2323,272],{"class":255},[249,2325,1160],{"class":275},[249,2327,272],{"class":255},[249,2329,1165],{"class":255},[249,2331,272],{"class":255},[249,2333,12],{"class":343},[249,2335,272],{"class":255},[249,2337,281],{"class":255},[249,2339,272],{"class":255},[249,2341,752],{"class":286},[249,2343,272],{"class":255},[249,2345,1182],{"class":255},[249,2347,272],{"class":255},[249,2349,1187],{"class":275},[249,2351,272],{"class":255},[249,2353,281],{"class":255},[249,2355,786],{"class":255},[249,2357,292],{"class":255},[249,2359,272],{"class":255},[249,2361,1200],{"class":275},[249,2363,272],{"class":255},[249,2365,281],{"class":255},[249,2367,786],{"class":255},[249,2369,292],{"class":255},[249,2371,272],{"class":255},[249,2373,1213],{"class":275},[249,2375,272],{"class":255},[249,2377,729],{"class":255},[249,2379,272],{"class":255},[249,2381,1222],{"class":275},[249,2383,272],{"class":255},[249,2385,281],{"class":255},[249,2387,1229],{"class":571},[249,2389,292],{"class":255},[249,2391,272],{"class":255},[249,2393,1236],{"class":275},[249,2395,272],{"class":255},[249,2397,281],{"class":255},[249,2399,786],{"class":255},[249,2401,292],{"class":255},[249,2403,272],{"class":255},[249,2405,752],{"class":275},[249,2407,272],{"class":255},[249,2409,281],{"class":255},[249,2411,786],{"class":255},[249,2413,292],{"class":255},[249,2415,272],{"class":255},[249,2417,1261],{"class":275},[249,2419,272],{"class":255},[249,2421,281],{"class":255},[249,2423,272],{"class":255},[249,2425,1270],{"class":286},[249,2427,272],{"class":255},[249,2429,292],{"class":255},[249,2431,272],{"class":255},[249,2433,564],{"class":275},[249,2435,272],{"class":255},[249,2437,281],{"class":255},[249,2439,1285],{"class":571},[249,2441,292],{"class":255},[249,2443,272],{"class":255},[249,2445,579],{"class":275},[249,2447,272],{"class":255},[249,2449,281],{"class":255},[249,2451,830],{"class":571},[249,2453,292],{"class":255},[249,2455,272],{"class":255},[249,2457,837],{"class":275},[249,2459,272],{"class":255},[249,2461,1064],{"class":255},[249,2463,272],{"class":255},[249,2465,509],{"class":286},[249,2467,272],{"class":255},[249,2469,1073],{"class":255},[249,2471,272],{"class":255},[249,2473,276],{"class":275},[249,2475,272],{"class":255},[249,2477,281],{"class":255},[249,2479,272],{"class":255},[249,2481,527],{"class":286},[249,2483,272],{"class":255},[249,2485,292],{"class":255},[249,2487,272],{"class":255},[249,2489,297],{"class":275},[249,2491,272],{"class":255},[249,2493,281],{"class":255},[249,2495,272],{"class":255},[249,2497,871],{"class":286},[249,2499,272],{"class":255},[249,2501,292],{"class":255},[249,2503,272],{"class":255},[249,2505,315],{"class":275},[249,2507,272],{"class":255},[249,2509,281],{"class":255},[249,2511,272],{"class":255},[249,2513,324],{"class":286},[249,2515,272],{"class":255},[249,2517,292],{"class":255},[249,2519,272],{"class":255},[249,2521,671],{"class":275},[249,2523,272],{"class":255},[249,2525,281],{"class":255},[249,2527,272],{"class":255},[249,2529,287],{"class":286},[249,2531,272],{"class":255},[249,2533,292],{"class":255},[249,2535,272],{"class":255},[249,2537,688],{"class":275},[249,2539,272],{"class":255},[249,2541,281],{"class":255},[249,2543,272],{"class":255},[249,2545,2546],{"class":286},"Query",[249,2548,272],{"class":255},[249,2550,292],{"class":255},[249,2552,272],{"class":255},[249,2554,928],{"class":275},[249,2556,272],{"class":255},[249,2558,281],{"class":255},[249,2560,786],{"class":255},[249,2562,292],{"class":255},[249,2564,272],{"class":255},[249,2566,1012],{"class":275},[249,2568,272],{"class":255},[249,2570,729],{"class":255},[249,2572,272],{"class":255},[249,2574,1021],{"class":275},[249,2576,272],{"class":255},[249,2578,281],{"class":255},[249,2580,371],{"class":571},[249,2582,292],{"class":255},[249,2584,272],{"class":255},[249,2586,564],{"class":275},[249,2588,272],{"class":255},[249,2590,281],{"class":255},[249,2592,2593],{"class":571},"710",[249,2595,292],{"class":255},[249,2597,272],{"class":255},[249,2599,579],{"class":275},[249,2601,272],{"class":255},[249,2603,281],{"class":255},[249,2605,830],{"class":571},[249,2607,292],{"class":255},[249,2609,272],{"class":255},[249,2611,837],{"class":275},[249,2613,272],{"class":255},[249,2615,1064],{"class":255},[249,2617,272],{"class":255},[249,2619,473],{"class":286},[249,2621,272],{"class":255},[249,2623,1073],{"class":255},[249,2625,272],{"class":255},[249,2627,276],{"class":275},[249,2629,272],{"class":255},[249,2631,281],{"class":255},[249,2633,272],{"class":255},[249,2635,536],{"class":286},[249,2637,272],{"class":255},[249,2639,292],{"class":255},[249,2641,272],{"class":255},[249,2643,297],{"class":275},[249,2645,272],{"class":255},[249,2647,281],{"class":255},[249,2649,272],{"class":255},[249,2651,871],{"class":286},[249,2653,272],{"class":255},[249,2655,292],{"class":255},[249,2657,272],{"class":255},[249,2659,315],{"class":275},[249,2661,272],{"class":255},[249,2663,281],{"class":255},[249,2665,272],{"class":255},[249,2667,324],{"class":286},[249,2669,272],{"class":255},[249,2671,292],{"class":255},[249,2673,272],{"class":255},[249,2675,671],{"class":275},[249,2677,272],{"class":255},[249,2679,281],{"class":255},[249,2681,272],{"class":255},[249,2683,287],{"class":286},[249,2685,272],{"class":255},[249,2687,292],{"class":255},[249,2689,272],{"class":255},[249,2691,688],{"class":275},[249,2693,272],{"class":255},[249,2695,281],{"class":255},[249,2697,272],{"class":255},[249,2699,233],{"class":286},[249,2701,272],{"class":255},[249,2703,292],{"class":255},[249,2705,272],{"class":255},[249,2707,928],{"class":275},[249,2709,272],{"class":255},[249,2711,281],{"class":255},[249,2713,272],{"class":255},[249,2715,2716],{"class":286},"DROP TABLE IF EXISTS calibration_assets;",[249,2718,940],{"class":259},[249,2720,272],{"class":255},[249,2722,292],{"class":255},[249,2724,272],{"class":255},[249,2726,1012],{"class":275},[249,2728,272],{"class":255},[249,2730,729],{"class":255},[249,2732,272],{"class":255},[249,2734,1021],{"class":275},[249,2736,272],{"class":255},[249,2738,281],{"class":255},[249,2740,371],{"class":571},[249,2742,292],{"class":255},[249,2744,272],{"class":255},[249,2746,564],{"class":275},[249,2748,272],{"class":255},[249,2750,281],{"class":255},[249,2752,1040],{"class":571},[249,2754,292],{"class":255},[249,2756,272],{"class":255},[249,2758,579],{"class":275},[249,2760,272],{"class":255},[249,2762,281],{"class":255},[249,2764,2765],{"class":571},"120",[249,2767,292],{"class":255},[249,2769,272],{"class":255},[249,2771,837],{"class":275},[249,2773,272],{"class":255},[249,2775,1064],{"class":255},[249,2777,272],{"class":255},[249,2779,554],{"class":286},[249,2781,272],{"class":255},[249,2783,1073],{"class":255},[249,2785,272],{"class":255},[249,2787,276],{"class":275},[249,2789,272],{"class":255},[249,2791,281],{"class":255},[249,2793,272],{"class":255},[249,2795,545],{"class":286},[249,2797,272],{"class":255},[249,2799,292],{"class":255},[249,2801,272],{"class":255},[249,2803,297],{"class":275},[249,2805,272],{"class":255},[249,2807,281],{"class":255},[249,2809,272],{"class":255},[249,2811,1102],{"class":286},[249,2813,272],{"class":255},[249,2815,292],{"class":255},[249,2817,272],{"class":255},[249,2819,315],{"class":275},[249,2821,272],{"class":255},[249,2823,281],{"class":255},[249,2825,272],{"class":255},[249,2827,324],{"class":286},[249,2829,272],{"class":255},[249,2831,292],{"class":255},[249,2833,272],{"class":255},[249,2835,671],{"class":275},[249,2837,272],{"class":255},[249,2839,281],{"class":255},[249,2841,272],{"class":255},[249,2843,287],{"class":286},[249,2845,272],{"class":255},[249,2847,292],{"class":255},[249,2849,272],{"class":255},[249,2851,688],{"class":275},[249,2853,272],{"class":255},[249,2855,281],{"class":255},[249,2857,272],{"class":255},[249,2859,1151],{"class":286},[249,2861,272],{"class":255},[249,2863,292],{"class":255},[249,2865,272],{"class":255},[249,2867,1160],{"class":275},[249,2869,272],{"class":255},[249,2871,1165],{"class":255},[249,2873,272],{"class":255},[249,2875,12],{"class":343},[249,2877,272],{"class":255},[249,2879,281],{"class":255},[249,2881,272],{"class":255},[249,2883,752],{"class":286},[249,2885,272],{"class":255},[249,2887,1182],{"class":255},[249,2889,272],{"class":255},[249,2891,1187],{"class":275},[249,2893,272],{"class":255},[249,2895,281],{"class":255},[249,2897,786],{"class":255},[249,2899,292],{"class":255},[249,2901,272],{"class":255},[249,2903,1200],{"class":275},[249,2905,272],{"class":255},[249,2907,281],{"class":255},[249,2909,786],{"class":255},[249,2911,292],{"class":255},[249,2913,272],{"class":255},[249,2915,1213],{"class":275},[249,2917,272],{"class":255},[249,2919,729],{"class":255},[249,2921,272],{"class":255},[249,2923,1222],{"class":275},[249,2925,272],{"class":255},[249,2927,281],{"class":255},[249,2929,1229],{"class":571},[249,2931,292],{"class":255},[249,2933,272],{"class":255},[249,2935,1236],{"class":275},[249,2937,272],{"class":255},[249,2939,281],{"class":255},[249,2941,786],{"class":255},[249,2943,292],{"class":255},[249,2945,272],{"class":255},[249,2947,752],{"class":275},[249,2949,272],{"class":255},[249,2951,281],{"class":255},[249,2953,786],{"class":255},[249,2955,292],{"class":255},[249,2957,272],{"class":255},[249,2959,1261],{"class":275},[249,2961,272],{"class":255},[249,2963,281],{"class":255},[249,2965,272],{"class":255},[249,2967,1270],{"class":286},[249,2969,272],{"class":255},[249,2971,292],{"class":255},[249,2973,272],{"class":255},[249,2975,564],{"class":275},[249,2977,272],{"class":255},[249,2979,281],{"class":255},[249,2981,1285],{"class":571},[249,2983,292],{"class":255},[249,2985,272],{"class":255},[249,2987,579],{"class":275},[249,2989,272],{"class":255},[249,2991,281],{"class":255},[249,2993,2765],{"class":571},[249,2995,292],{"class":255},[249,2997,272],{"class":255},[249,2999,837],{"class":275},[249,3001,272],{"class":255},[249,3003,1064],{"class":255},[249,3005,272],{"class":255},[249,3007,536],{"class":286},[249,3009,272],{"class":255},[249,3011,1073],{"class":255},[249,3013,272],{"class":255},[249,3015,276],{"class":275},[249,3017,272],{"class":255},[249,3019,281],{"class":255},[249,3021,272],{"class":255},[249,3023,554],{"class":286},[249,3025,272],{"class":255},[249,3027,292],{"class":255},[249,3029,272],{"class":255},[249,3031,297],{"class":275},[249,3033,272],{"class":255},[249,3035,281],{"class":255},[249,3037,272],{"class":255},[249,3039,646],{"class":286},[249,3041,272],{"class":255},[249,3043,292],{"class":255},[249,3045,272],{"class":255},[249,3047,315],{"class":275},[249,3049,272],{"class":255},[249,3051,281],{"class":255},[249,3053,272],{"class":255},[249,3055,324],{"class":286},[249,3057,272],{"class":255},[249,3059,292],{"class":255},[249,3061,272],{"class":255},[249,3063,671],{"class":275},[249,3065,272],{"class":255},[249,3067,281],{"class":255},[249,3069,272],{"class":255},[249,3071,287],{"class":286},[249,3073,272],{"class":255},[249,3075,292],{"class":255},[249,3077,272],{"class":255},[249,3079,688],{"class":275},[249,3081,272],{"class":255},[249,3083,281],{"class":255},[249,3085,272],{"class":255},[249,3087,697],{"class":286},[249,3089,272],{"class":255},[249,3091,292],{"class":255},[249,3093,272],{"class":255},[249,3095,706],{"class":275},[249,3097,272],{"class":255},[249,3099,421],{"class":255},[249,3101,272],{"class":255},[249,3103,715],{"class":275},[249,3105,272],{"class":255},[249,3107,421],{"class":255},[249,3109,272],{"class":255},[249,3111,724],{"class":275},[249,3113,272],{"class":255},[249,3115,729],{"class":255},[249,3117,272],{"class":255},[249,3119,734],{"class":275},[249,3121,272],{"class":255},[249,3123,729],{"class":255},[249,3125,272],{"class":255},[249,3127,743],{"class":275},[249,3129,272],{"class":255},[249,3131,281],{"class":255},[249,3133,272],{"class":255},[249,3135,752],{"class":286},[249,3137,272],{"class":255},[249,3139,292],{"class":255},[249,3141,272],{"class":255},[249,3143,761],{"class":275},[249,3145,272],{"class":255},[249,3147,281],{"class":255},[249,3149,272],{"class":255},[249,3151,770],{"class":286},[249,3153,272],{"class":255},[249,3155,292],{"class":255},[249,3157,272],{"class":255},[249,3159,779],{"class":275},[249,3161,272],{"class":255},[249,3163,281],{"class":255},[249,3165,786],{"class":255},[249,3167,292],{"class":255},[249,3169,272],{"class":255},[249,3171,793],{"class":275},[249,3173,272],{"class":255},[249,3175,281],{"class":255},[249,3177,272],{"class":255},[249,3179,802],{"class":286},[249,3181,272],{"class":255},[249,3183,292],{"class":255},[249,3185,272],{"class":255},[249,3187,564],{"class":275},[249,3189,272],{"class":255},[249,3191,281],{"class":255},[249,3193,817],{"class":571},[249,3195,292],{"class":255},[249,3197,272],{"class":255},[249,3199,579],{"class":275},[249,3201,272],{"class":255},[249,3203,281],{"class":255},[249,3205,2765],{"class":571},[249,3207,292],{"class":255},[249,3209,272],{"class":255},[249,3211,837],{"class":275},[249,3213,272],{"class":255},[249,3215,842],{"class":255},[249,3217,272],{"class":255},[249,3219,276],{"class":275},[249,3221,272],{"class":255},[249,3223,281],{"class":255},[249,3225,272],{"class":255},[249,3227,3228],{"class":286},"993b160c135046a2",[249,3230,272],{"class":255},[249,3232,292],{"class":255},[249,3234,272],{"class":255},[249,3236,297],{"class":275},[249,3238,272],{"class":255},[249,3240,281],{"class":255},[249,3242,272],{"class":255},[249,3244,3245],{"class":286},"global-config",[249,3247,272],{"class":255},[249,3249,292],{"class":255},[249,3251,272],{"class":255},[249,3253,3254],{"class":275},"env",[249,3256,272],{"class":255},[249,3258,2200],{"class":255},[249,3260,272],{"class":255},[249,3262,3263],{"class":275},"modules",[249,3265,272],{"class":255},[249,3267,338],{"class":255},[249,3269,272],{"class":255},[249,3271,3272],{"class":343},"@flowfuse\u002Fnr-tables-nodes",[249,3274,272],{"class":255},[249,3276,281],{"class":255},[249,3278,272],{"class":255},[249,3280,3281],{"class":286},"0.2.2",[249,3283,272],{"class":255},[249,3285,3286],{"class":255},"}}]\n",[249,3288,3290,3292,3295],{"class":251,"line":3289},3,[249,3291,256],{"class":255},[249,3293,3294],{"class":259},"% endraw %",[249,3296,263],{"class":255},[12,3298,3299,3300,3303,3304,3307],{},"That gives you 120 instruments with IDs from ",[56,3301,3302],{},"TL-0001"," to ",[56,3305,3306],{},"TL-0120",", spread across eight departments: roughly 70% valid, 20% due soon, and 10% overdue. The eight department names are the same ones the filter dropdown offers later.",[12,3309,3310],{},"Everything we build reads from these columns:",[3312,3313,3314,3327],"table",{},[3315,3316,3317],"thead",{},[3318,3319,3320,3324],"tr",{},[3321,3322,3323],"th",{},"Column",[3321,3325,3326],{},"What the application does with it",[3328,3329,3330,3341,3351,3361,3371,3381,3397],"tbody",{},[3318,3331,3332,3338],{},[3333,3334,3335],"td",{},[56,3336,3337],{},"tool_id",[3333,3339,3340],{},"Primary key, and the ID printed on the calibration label that the scanner matches against",[3318,3342,3343,3348],{},[3333,3344,3345],{},[56,3346,3347],{},"next_due_ts",[3333,3349,3350],{},"Every status figure, chip, and scanner verdict comes from comparing this against the current time",[3318,3352,3353,3358],{},[3333,3354,3355],{},[56,3356,3357],{},"status",[3333,3359,3360],{},"The stored label. We deliberately don't trust it, and use it only to spot drift from the dates",[3318,3362,3363,3368],{},[3333,3364,3365],{},[56,3366,3367],{},"department",[3333,3369,3370],{},"Drives the Department filter on the dashboard",[3318,3372,3373,3378],{},[3333,3374,3375],{},[56,3376,3377],{},"equipment_name",[3333,3379,3380],{},"Names the instrument in the table and in the scanner verdict",[3318,3382,3383,3394],{},[3333,3384,3385,104,3388,104,3391],{},[56,3386,3387],{},"location",[56,3389,3390],{},"calibration_interval_months",[56,3392,3393],{},"last_calibration_ts",[3333,3395,3396],{},"Table columns",[3318,3398,3399,3413],{},[3333,3400,3401,104,3404,104,3407,104,3410],{},[56,3402,3403],{},"serial_number",[56,3405,3406],{},"calibration_lab",[56,3408,3409],{},"certificate_no",[56,3411,3412],{},"created_at",[3333,3414,3415],{},"Kept for reference; nothing in this build shows them",[46,3417,3418],{},[12,3419,3420,3422,3423,3426,3427,3430],{},[51,3421,53],{}," Your register will likely name these columns differently. Alias your columns in the ",[56,3424,3425],{},"SELECT"," list, as in ",[56,3428,3429],{},"SELECT gauge_ref AS tool_id, cal_due_date AS next_due_ts, ...",", and every widget will still work. Only the due-date column is essential.",[12,3432,3433,3434,3437],{},"Before running the generator, set its reference date near the top of the function, ",[56,3435,3436],{},"const today = new Date('2026-07-28T10:00:00')",", to roughly today's date. Otherwise everything will land relative to a date in the past.",[68,3439,3441],{"id":3440},"setting-up-the-dashboard-layout","Setting Up the Dashboard Layout",[12,3443,3444,3445,3451],{},"The application has two pages and four groups. Most widgets sit inside a named group. The filter bar is scoped to the page instead, because it appears in the app bar rather than in the grid. See the ",[22,3446,3450],{"href":3447,"rel":3448},"https:\u002F\u002Fdashboard.flowfuse.com\u002Fgetting-started",[3449],"nofollow","Dashboard layout docs"," if you're new to how pages, groups, and bases relate.",[166,3453,3454,3487,3518,3541,3555],{},[79,3455,3456,3457,3459,3460],{},"Create two ",[51,3458,119],{}," nodes. The Dashboard automatically creates a base dashboard the first time you add a Dashboard node to the canvas.",[76,3461,3462,3475],{},[79,3463,3464,3467,3468,3471,3472,26],{},[51,3465,3466],{},"Home"," (path: ",[56,3469,3470],{},"\u002Fhome","): the calibration status dashboard. Set the layout to ",[51,3473,3474],{},"Grid",[79,3476,3477,3467,3480,3483,3484,26],{},[51,3478,3479],{},"Tool Check",[56,3481,3482],{},"\u002Ftool-check","): the scanner. Set the layout to ",[51,3485,3486],{},"Notebook",[79,3488,3489,3490,3492,3493,3495,3496,3499,3500,3503,3504],{},"On the ",[51,3491,3466],{}," page, create two ",[51,3494,122],{}," nodes, both ",[51,3497,3498],{},"12 columns"," wide with ",[51,3501,3502],{},"Show title"," turned off:",[76,3505,3506,3512],{},[79,3507,3508,3511],{},[51,3509,3510],{},"KPIs"," (order 1)",[79,3513,3514,3517],{},[51,3515,3516],{},"Asset Detail"," (order 2)",[79,3519,3489,3520,3522,3523,3525,3526,3528,3529],{},[51,3521,3479],{}," page, create two more ",[51,3524,122],{}," nodes, also ",[51,3527,3498],{}," wide with titles off:",[76,3530,3531,3536],{},[79,3532,3533,3511],{},[51,3534,3535],{},"Scanner",[79,3537,3538,3517],{},[51,3539,3540],{},"Verdict",[79,3542,3543,3544,3547,3548,3303,3551,3554],{},"Open the ",[51,3545,3546],{},"ui-base"," node and set ",[51,3549,3550],{},"Header Content",[51,3552,3553],{},"page",". This shows the app bar, which the filter widget needs.",[79,3556,3557],{},"Set up the ui-theme to suit your needs. The dashboard already comes with a default theme, which you can use for now.",[68,3559,3561],{"id":3560},"building-the-filter-bar","Building the Filter Bar",[12,3563,3564],{},"Two controls drive the page: which department, and how far ahead to look. Both sit in the app bar rather than the grid, so no row of the page is used up by a dropdown.",[12,3566,3567],{},"The department list is read from the register itself, not typed in by hand, so adding a department next year doesn't mean editing a flow. The time windows are fixed, because \"next 30 days\" is a choice this application makes rather than something the data tells you.",[166,3569,3570,3576],{},[79,3571,3572,3573,3575],{},"Add a ",[56,3574,107],{}," node named \"Page Load \u002F Refresh Event\" and select your \"My Dashboard\" ui-base. It fires whenever a page loads.",[79,3577,3572,3578,3580],{},[56,3579,871],{}," node named \"Load Departments\":",[46,3582,3583],{},[12,3584,3585,3588,3589,3593],{},[51,3586,3587],{},"Tip:"," You don't have to write the SQL yourself either. Use ",[22,3590,3592],{"href":3591},"\u002Fblog\u002F2025\u002F09\u002Fai-assistant-flowfuse-tables\u002F","FlowFuse Expert"," and describe what you want the query to return in plain English, and it will generate the SQL for you.",[240,3595,3599],{"className":3596,"code":3597,"language":3598,"meta":245,"style":245},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","SELECT DISTINCT department\nFROM calibration_assets\nWHERE department IS NOT NULL\n  AND btrim(department) \u003C> ''\nORDER BY department;\n","sql",[56,3600,3601,3606,3611,3616,3622],{"__ignoreMap":245},[249,3602,3603],{"class":251,"line":252},[249,3604,3605],{},"SELECT DISTINCT department\n",[249,3607,3608],{"class":251,"line":266},[249,3609,3610],{},"FROM calibration_assets\n",[249,3612,3613],{"class":251,"line":3289},[249,3614,3615],{},"WHERE department IS NOT NULL\n",[249,3617,3619],{"class":251,"line":3618},4,[249,3620,3621],{},"  AND btrim(department) \u003C> ''\n",[249,3623,3625],{"class":251,"line":3624},5,[249,3626,3627],{},"ORDER BY department;\n",[166,3629,3630],{},[79,3631,3632,3633,37,3636,3638,3639,3642,3643,3645,3646,3649,3650,3654,3655,3658,3659,3662,3663,3666,3667,3670,3671,3674],{},"Import the ",[51,3634,3635],{},"App Header Filters",[56,3637,103],{}," below, set its type to ",[51,3640,3641],{},"Widget (Page-Scoped)",", select the ",[51,3644,3466],{}," page, and turn off ",[51,3647,3648],{},"Pass through messages from input to output",". The complete component is provided below, so there's no need to build it yourself. It shows two dropdowns in the header using Vue's ",[22,3651,3653],{"href":3652},"\u002Fblog\u002F2024\u002F08\u002Fcustomise-theming-in-your-dashboards\u002F#adding-elements-in-the-header","Teleport",": ",[51,3656,3657],{},"Department",", filled from the query above, and ",[51,3660,3661],{},"Time Window",". It opens on ",[39,3664,3665],{},"All"," departments and ",[39,3668,3669],{},"Next 90 days",", sends ",[56,3672,3673],{},"{ department, timeWindow }"," on every change, and sends the same on load so the dropdowns and the data always agree.",[46,3676,3677],{},[12,3678,3679,3681,3682,3685,3686,3688],{},[51,3680,3587],{}," Whenever you need a custom Dashboard widget, you don't have to write the Vue code yourself. Use ",[22,3683,3592],{"href":3684},"\u002Fdocs\u002Fuser\u002Fexpert\u002Fnode-red-embedded-ai\u002F#css-and-html-generation-for-flowfuse-dashboard"," and describe the widget in plain English, and it will generate the ",[56,3687,103],{}," for you.",[236,3690,3691],{":height":238},[240,3692,3694],{"className":242,"code":3693,"language":244,"meta":245,"style":245},"{% raw %}\n[{\"id\":\"e263486a1e3ea8ea\",\"type\":\"ui-template\",\"z\":\"1c5b2364213044a7\",\"g\":\"c619d111b9911c0b\",\"group\":\"\",\"page\":\"89515a0645eddeee\",\"ui\":\"\",\"name\":\"App Header Filters\",\"order\":1,\"width\":0,\"height\":0,\"head\":\"\",\"format\":\"\u003Ctemplate>\\n  \u003CTeleport v-if=\\\"mounted\\\" to=\\\"#app-bar-actions\\\">\\n    \u003Cdiv class=\\\"filter-bar\\\">\\n\\n      \u003C!-- Department: options come from the register, not from this file -->\\n      \u003Cv-select v-model=\\\"department\\\" :items=\\\"departments\\\" label=\\\"Department\\\" density=\\\"compact\\\" variant=\\\"solo-filled\\\"\\n        hide-details style=\\\"width: 180px\\\" @update:model-value=\\\"sendFilters\\\">\u003C\u002Fv-select>\\n\\n      \u003C!-- Time Window -->\\n      \u003Cv-select v-model=\\\"timeWindow\\\" :items=\\\"timeWindows\\\" label=\\\"Time Window\\\" density=\\\"compact\\\" variant=\\\"solo-filled\\\"\\n        hide-details style=\\\"width: 200px\\\" @update:model-value=\\\"sendFilters\\\">\u003C\u002Fv-select>\\n\\n    \u003C\u002Fdiv>\\n  \u003C\u002FTeleport>\\n\u003C\u002Ftemplate>\\n\\n\u003Cscript>\\n  export default {\\n    data() {\\n      return {\\n        mounted: false,\\n\\n        \u002F\u002F Filters reset to these on every page load. Nothing is remembered.\\n        \u002F\u002F 90 days is deliberate: at 30 the Upcoming card would just repeat\\n        \u002F\u002F Due soon, and the control would look like it does nothing.\\n        department: 'All',\\n        timeWindow: 'Next 90 days',\\n\\n        \u002F\u002F Replaced by the list read from the register. Starts as just 'All'\\n        \u002F\u002F so the control is usable before the query comes back.\\n        departments: ['All'],\\n\\n        \u002F\u002F Fixed: these are windows the app defines, not data.\\n        timeWindows: [\\n          'Next 7 days',\\n          'Next 30 days',\\n          'Next 90 days',\\n          'All future'\\n        ]\\n      }\\n    },\\n\\n    watch: {\\n      msg: {\\n        handler(msg) { this.applyMsg(msg) },\\n        deep: true\\n      }\\n    },\\n\\n    mounted() {\\n      this.mounted = true;\\n      this.applyMsg(this.msg);\\n      this.$socket.on('msg-input:' + this.id, this.applyMsg);\\n\\n      \u002F\u002F A refresh resets the dropdowns to their defaults, so push those\\n      \u002F\u002F defaults out once. Without this the queries keep reading the previous\\n      \u002F\u002F selection from context, and the numbers wouldn't match the dropdowns.\\n      this.sendFilters();\\n    },\\n\\n    unmounted() {\\n      this.$socket.off('msg-input:' + this.id, this.applyMsg);\\n    },\\n\\n    methods: {\\n      \u002F\u002F Receives the Load Departments rows exactly as the database returns\\n      \u002F\u002F them: [{ department: 'Assembly' }, { department: 'Quality' }, ...]\\n      applyMsg(msg) {\\n        const rows = msg && msg.payload;\\n        if (!Array.isArray(rows)) return;\\n\\n        const names = rows\\n          .map(r => (r && typeof r === 'object') ? r.department : r)\\n          .filter(d => typeof d === 'string' && d.trim() !== '');\\n\\n        \u002F\u002F 'All' is ours, not a row in the table.\\n        if (names.length) {\\n          this.departments = ['All', ...new Set(names)];\\n        }\\n      },\\n\\n      sendFilters() {\\n        this.send({\\n          payload: {\\n            department: this.department,\\n            timeWindow: this.timeWindow\\n          }\\n        });\\n      }\\n    }\\n  }\\n\u003C\u002Fscript>\\n\\n\u003Cstyle>\\n  .filter-bar {\\n    display: flex;\\n    align-items: center;\\n    gap: 12px;\\n    padding-right: 12px;\\n  }\\n\\n  \u002F* Make controls compact in the app bar *\u002F\\n  .filter-bar .v-input {\\n    margin-top: 0 !important;\\n  }\\n\u003C\u002Fstyle>\",\"storeOutMessages\":true,\"passthru\":false,\"resendOnRefresh\":true,\"templateScope\":\"widget:page\",\"className\":\"\",\"x\":810,\"y\":80,\"wires\":[[\"b9c34ba932fa101c\"]]},{\"id\":\"89515a0645eddeee\",\"type\":\"ui-page\",\"name\":\"Home\",\"ui\":\"6481b1c613ec9a93\",\"path\":\"\u002Fhome\",\"icon\":\"home\",\"layout\":\"grid\",\"theme\":\"faac104f34962f3e\",\"breakpoints\":[{\"name\":\"Default\",\"px\":\"0\",\"cols\":\"3\"},{\"name\":\"Tablet\",\"px\":\"576\",\"cols\":\"6\"},{\"name\":\"Small Desktop\",\"px\":\"768\",\"cols\":\"9\"},{\"name\":\"Desktop\",\"px\":\"1024\",\"cols\":\"12\"}],\"order\":1,\"className\":\"\",\"visible\":\"true\",\"disabled\":\"false\"},{\"id\":\"6481b1c613ec9a93\",\"type\":\"ui-base\",\"name\":\"My Dashboard\",\"path\":\"\u002Fdashboard\",\"appIcon\":\"\",\"includeClientData\":true,\"acceptsClientConfig\":[\"ui-notification\",\"ui-control\",\"ui-number-input\",\"ui-file-input\",\"ui-button\",\"ui-button-group\",\"ui-dropdown\",\"ui-radio-group\",\"ui-slider\",\"ui-switch\",\"ui-text\",\"ui-table\",\"ui-gauge\",\"ui-chart\",\"ui-template\",\"ui-markdown\",\"ui-progress\",\"ui-webcam\"],\"showPathInSidebar\":false,\"headerContent\":\"page\",\"navigationStyle\":\"default\",\"titleBarStyle\":\"default\",\"showReconnectNotification\":true,\"notificationDisplayTime\":1,\"showDisconnectNotification\":true,\"allowInstall\":false},{\"id\":\"faac104f34962f3e\",\"type\":\"ui-theme\",\"name\":\"Default Theme\",\"colors\":{\"surface\":\"#ffffff\",\"primary\":\"#1e4e8c\",\"bgPage\":\"#eef1f5\",\"groupBg\":\"#ffffff\",\"groupOutline\":\"#d3dae3\"},\"sizes\":{\"density\":\"default\",\"pagePadding\":\"12px\",\"groupGap\":\"12px\",\"groupBorderRadius\":\"4px\",\"widgetGap\":\"12px\"}},{\"id\":\"6f4ad536fc64beb9\",\"type\":\"global-config\",\"env\":[],\"modules\":{\"@flowfuse\u002Fnode-red-dashboard\":\"1.30.2\"}}]\n{% endraw %}\n",[56,3695,3696,3704,5660],{"__ignoreMap":245},[249,3697,3698,3700,3702],{"class":251,"line":252},[249,3699,256],{"class":255},[249,3701,260],{"class":259},[249,3703,263],{"class":255},[249,3705,3706,3708,3710,3712,3714,3716,3718,3721,3723,3725,3727,3729,3731,3733,3735,3737,3739,3741,3743,3745,3747,3749,3751,3754,3756,3758,3760,3762,3764,3766,3768,3771,3773,3775,3777,3779,3781,3783,3785,3787,3789,3791,3793,3795,3797,3800,3802,3804,3806,3809,3811,3813,3815,3817,3819,3821,3823,3825,3827,3829,3831,3833,3835,3838,3840,3842,3844,3846,3848,3851,3853,3855,3857,3859,3861,3864,3866,3868,3870,3872,3874,3877,3879,3881,3883,3885,3887,3890,3892,3894,3896,3899,3901,3904,3907,3910,3912,3915,3917,3920,3922,3925,3927,3930,3932,3935,3937,3939,3941,3944,3946,3949,3951,3953,3955,3958,3960,3963,3965,3968,3970,3972,3974,3977,3979,3982,3984,3987,3989,3992,3995,3998,4000,4003,4005,4008,4010,4013,4015,4018,4020,4023,4025,4027,4029,4032,4034,4036,4038,4041,4043,4045,4047,4049,4051,4053,4055,4057,4059,4061,4063,4065,4067,4069,4071,4074,4076,4078,4080,4082,4084,4086,4088,4091,4093,4096,4098,4101,4103,4106,4108,4111,4113,4116,4118,4121,4123,4126,4128,4131,4133,4136,4138,4141,4143,4146,4148,4151,4153,4156,4158,4161,4163,4166,4168,4171,4173,4176,4178,4181,4183,4186,4188,4191,4193,4196,4198,4201,4203,4206,4208,4211,4213,4216,4218,4221,4223,4226,4228,4231,4233,4235,4237,4239,4241,4244,4246,4249,4251,4254,4256,4259,4261,4264,4266,4269,4271,4274,4276,4279,4281,4283,4285,4288,4290,4293,4295,4297,4299,4302,4304,4307,4309,4312,4314,4317,4319,4322,4324,4327,4329,4332,4334,4337,4339,4342,4344,4347,4349,4352,4354,4357,4359,4362,4364,4367,4369,4372,4374,4377,4379,4382,4384,4387,4389,4392,4394,4397,4399,4402,4404,4406,4408,4411,4413,4415,4417,4420,4422,4425,4427,4430,4432,4435,4437,4440,4442,4445,4447,4450,4452,4454,4456,4459,4461,4464,4466,4469,4471,4473,4475,4478,4480,4482,4484,4487,4489,4491,4493,4496,4498,4500,4502,4505,4507,4509,4511,4514,4516,4518,4520,4523,4525,4527,4529,4532,4534,4536,4538,4540,4542,4544,4546,4548,4551,4553,4555,4557,4559,4561,4564,4566,4568,4570,4572,4574,4576,4579,4581,4583,4585,4587,4589,4591,4593,4595,4597,4599,4601,4603,4605,4607,4609,4611,4613,4615,4617,4619,4621,4623,4625,4627,4629,4631,4633,4635,4637,4639,4641,4644,4646,4648,4650,4653,4655,4657,4659,4661,4663,4665,4667,4670,4672,4674,4676,4679,4681,4683,4685,4688,4690,4692,4694,4697,4699,4701,4703,4706,4708,4710,4712,4715,4717,4719,4721,4724,4726,4728,4730,4732,4734,4736,4738,4741,4743,4745,4747,4750,4752,4754,4756,4758,4760,4762,4764,4767,4769,4771,4773,4776,4778,4780,4782,4784,4786,4788,4790,4793,4795,4797,4799,4801,4803,4805,4807,4810,4812,4814,4816,4818,4820,4822,4824,4827,4829,4831,4833,4835,4837,4839,4841,4844,4846,4848,4850,4852,4854,4856,4858,4861,4863,4865,4867,4869,4871,4873,4875,4878,4880,4882,4884,4886,4888,4890,4892,4895,4897,4899,4901,4903,4905,4907,4909,4912,4914,4916,4918,4920,4922,4924,4926,4929,4931,4933,4935,4937,4939,4941,4943,4945,4947,4949,4951,4953,4955,4957,4959,4962,4964,4966,4968,4971,4973,4975,4977,4980,4982,4984,4986,4989,4991,4993,4995,4997,4999,5001,5003,5005,5007,5009,5011,5013,5015,5017,5019,5021,5023,5025,5027,5029,5031,5033,5035,5038,5040,5042,5044,5046,5048,5050,5052,5055,5057,5059,5061,5064,5066,5068,5070,5072,5074,5077,5079,5081,5083,5086,5088,5090,5092,5094,5096,5098,5100,5103,5105,5107,5109,5112,5114,5116,5118,5121,5123,5125,5127,5129,5131,5133,5135,5138,5140,5142,5144,5147,5149,5151,5153,5156,5158,5160,5162,5165,5167,5169,5171,5174,5176,5178,5180,5183,5185,5187,5189,5192,5194,5196,5198,5201,5203,5205,5207,5210,5212,5214,5216,5218,5220,5222,5224,5226,5228,5230,5232,5235,5237,5239,5241,5244,5246,5248,5250,5253,5255,5257,5259,5262,5264,5266,5268,5270,5272,5274,5276,5279,5281,5283,5285,5288,5290,5292,5294,5297,5299,5301,5303,5305,5307,5309,5311,5314,5316,5318,5320,5323,5325,5327,5329,5331,5333,5336,5338,5340,5342,5345,5347,5350,5352,5354,5356,5358,5360,5362,5364,5366,5368,5370,5372,5374,5376,5378,5380,5382,5384,5386,5388,5390,5392,5395,5397,5399,5401,5404,5406,5408,5410,5413,5415,5417,5419,5422,5424,5426,5428,5431,5433,5435,5437,5440,5442,5444,5446,5449,5451,5453,5455,5458,5460,5462,5464,5467,5469,5471,5473,5475,5477,5479,5481,5484,5486,5488,5490,5493,5495,5497,5499,5502,5504,5506,5508,5511,5513,5515,5517,5519,5521,5523,5525,5528,5530,5532,5534,5537,5539,5541,5543,5546,5548,5550,5552,5554,5556,5558,5560,5563,5565,5567,5569,5572,5574,5576,5578,5581,5583,5585,5587,5589,5591,5594,5596,5598,5600,5602,5604,5607,5609,5611,5613,5615,5617,5619,5621,5623,5625,5627,5629,5631,5633,5635,5637,5639,5641,5643,5645,5647,5649,5651,5653,5656,5658],{"class":251,"line":266},[249,3707,269],{"class":255},[249,3709,272],{"class":255},[249,3711,276],{"class":275},[249,3713,272],{"class":255},[249,3715,281],{"class":255},[249,3717,272],{"class":255},[249,3719,3720],{"class":286},"e263486a1e3ea8ea",[249,3722,272],{"class":255},[249,3724,292],{"class":255},[249,3726,272],{"class":255},[249,3728,297],{"class":275},[249,3730,272],{"class":255},[249,3732,281],{"class":255},[249,3734,272],{"class":255},[249,3736,103],{"class":286},[249,3738,272],{"class":255},[249,3740,292],{"class":255},[249,3742,272],{"class":255},[249,3744,315],{"class":275},[249,3746,272],{"class":255},[249,3748,281],{"class":255},[249,3750,272],{"class":255},[249,3752,3753],{"class":286},"1c5b2364213044a7",[249,3755,272],{"class":255},[249,3757,292],{"class":255},[249,3759,272],{"class":255},[249,3761,671],{"class":275},[249,3763,272],{"class":255},[249,3765,281],{"class":255},[249,3767,272],{"class":255},[249,3769,3770],{"class":286},"c619d111b9911c0b",[249,3772,272],{"class":255},[249,3774,292],{"class":255},[249,3776,272],{"class":255},[249,3778,306],{"class":275},[249,3780,272],{"class":255},[249,3782,281],{"class":255},[249,3784,786],{"class":255},[249,3786,292],{"class":255},[249,3788,272],{"class":255},[249,3790,3553],{"class":275},[249,3792,272],{"class":255},[249,3794,281],{"class":255},[249,3796,272],{"class":255},[249,3798,3799],{"class":286},"89515a0645eddeee",[249,3801,272],{"class":255},[249,3803,292],{"class":255},[249,3805,272],{"class":255},[249,3807,3808],{"class":275},"ui",[249,3810,272],{"class":255},[249,3812,281],{"class":255},[249,3814,786],{"class":255},[249,3816,292],{"class":255},[249,3818,272],{"class":255},[249,3820,688],{"class":275},[249,3822,272],{"class":255},[249,3824,281],{"class":255},[249,3826,272],{"class":255},[249,3828,3635],{"class":286},[249,3830,272],{"class":255},[249,3832,292],{"class":255},[249,3834,272],{"class":255},[249,3836,3837],{"class":275},"order",[249,3839,272],{"class":255},[249,3841,281],{"class":255},[249,3843,371],{"class":571},[249,3845,292],{"class":255},[249,3847,272],{"class":255},[249,3849,3850],{"class":275},"width",[249,3852,272],{"class":255},[249,3854,281],{"class":255},[249,3856,2149],{"class":571},[249,3858,292],{"class":255},[249,3860,272],{"class":255},[249,3862,3863],{"class":275},"height",[249,3865,272],{"class":255},[249,3867,281],{"class":255},[249,3869,2149],{"class":571},[249,3871,292],{"class":255},[249,3873,272],{"class":255},[249,3875,3876],{"class":275},"head",[249,3878,272],{"class":255},[249,3880,281],{"class":255},[249,3882,786],{"class":255},[249,3884,292],{"class":255},[249,3886,272],{"class":255},[249,3888,3889],{"class":275},"format",[249,3891,272],{"class":255},[249,3893,281],{"class":255},[249,3895,272],{"class":255},[249,3897,3898],{"class":286},"\u003Ctemplate>",[249,3900,940],{"class":259},[249,3902,3903],{"class":286},"  \u003CTeleport v-if=",[249,3905,3906],{"class":259},"\\\"",[249,3908,3909],{"class":286},"mounted",[249,3911,3906],{"class":259},[249,3913,3914],{"class":286}," to=",[249,3916,3906],{"class":259},[249,3918,3919],{"class":286},"#app-bar-actions",[249,3921,3906],{"class":259},[249,3923,3924],{"class":286},">",[249,3926,940],{"class":259},[249,3928,3929],{"class":286},"    \u003Cdiv class=",[249,3931,3906],{"class":259},[249,3933,3934],{"class":286},"filter-bar",[249,3936,3906],{"class":259},[249,3938,3924],{"class":286},[249,3940,1667],{"class":259},[249,3942,3943],{"class":286},"      \u003C!-- Department: options come from the register, not from this file -->",[249,3945,940],{"class":259},[249,3947,3948],{"class":286},"      \u003Cv-select v-model=",[249,3950,3906],{"class":259},[249,3952,3367],{"class":286},[249,3954,3906],{"class":259},[249,3956,3957],{"class":286}," :items=",[249,3959,3906],{"class":259},[249,3961,3962],{"class":286},"departments",[249,3964,3906],{"class":259},[249,3966,3967],{"class":286}," label=",[249,3969,3906],{"class":259},[249,3971,3657],{"class":286},[249,3973,3906],{"class":259},[249,3975,3976],{"class":286}," density=",[249,3978,3906],{"class":259},[249,3980,3981],{"class":286},"compact",[249,3983,3906],{"class":259},[249,3985,3986],{"class":286}," variant=",[249,3988,3906],{"class":259},[249,3990,3991],{"class":286},"solo-filled",[249,3993,3994],{"class":259},"\\\"\\n",[249,3996,3997],{"class":286},"        hide-details style=",[249,3999,3906],{"class":259},[249,4001,4002],{"class":286},"width: 180px",[249,4004,3906],{"class":259},[249,4006,4007],{"class":286}," @update:model-value=",[249,4009,3906],{"class":259},[249,4011,4012],{"class":286},"sendFilters",[249,4014,3906],{"class":259},[249,4016,4017],{"class":286},">\u003C\u002Fv-select>",[249,4019,1667],{"class":259},[249,4021,4022],{"class":286},"      \u003C!-- Time Window -->",[249,4024,940],{"class":259},[249,4026,3948],{"class":286},[249,4028,3906],{"class":259},[249,4030,4031],{"class":286},"timeWindow",[249,4033,3906],{"class":259},[249,4035,3957],{"class":286},[249,4037,3906],{"class":259},[249,4039,4040],{"class":286},"timeWindows",[249,4042,3906],{"class":259},[249,4044,3967],{"class":286},[249,4046,3906],{"class":259},[249,4048,3661],{"class":286},[249,4050,3906],{"class":259},[249,4052,3976],{"class":286},[249,4054,3906],{"class":259},[249,4056,3981],{"class":286},[249,4058,3906],{"class":259},[249,4060,3986],{"class":286},[249,4062,3906],{"class":259},[249,4064,3991],{"class":286},[249,4066,3994],{"class":259},[249,4068,3997],{"class":286},[249,4070,3906],{"class":259},[249,4072,4073],{"class":286},"width: 200px",[249,4075,3906],{"class":259},[249,4077,4007],{"class":286},[249,4079,3906],{"class":259},[249,4081,4012],{"class":286},[249,4083,3906],{"class":259},[249,4085,4017],{"class":286},[249,4087,1667],{"class":259},[249,4089,4090],{"class":286},"    \u003C\u002Fdiv>",[249,4092,940],{"class":259},[249,4094,4095],{"class":286},"  \u003C\u002FTeleport>",[249,4097,940],{"class":259},[249,4099,4100],{"class":286},"\u003C\u002Ftemplate>",[249,4102,1667],{"class":259},[249,4104,4105],{"class":286},"\u003Cscript>",[249,4107,940],{"class":259},[249,4109,4110],{"class":286},"  export default {",[249,4112,940],{"class":259},[249,4114,4115],{"class":286},"    data() {",[249,4117,940],{"class":259},[249,4119,4120],{"class":286},"      return {",[249,4122,940],{"class":259},[249,4124,4125],{"class":286},"        mounted: false,",[249,4127,1667],{"class":259},[249,4129,4130],{"class":286},"        \u002F\u002F Filters reset to these on every page load. Nothing is remembered.",[249,4132,940],{"class":259},[249,4134,4135],{"class":286},"        \u002F\u002F 90 days is deliberate: at 30 the Upcoming card would just repeat",[249,4137,940],{"class":259},[249,4139,4140],{"class":286},"        \u002F\u002F Due soon, and the control would look like it does nothing.",[249,4142,940],{"class":259},[249,4144,4145],{"class":286},"        department: 'All',",[249,4147,940],{"class":259},[249,4149,4150],{"class":286},"        timeWindow: 'Next 90 days',",[249,4152,1667],{"class":259},[249,4154,4155],{"class":286},"        \u002F\u002F Replaced by the list read from the register. Starts as just 'All'",[249,4157,940],{"class":259},[249,4159,4160],{"class":286},"        \u002F\u002F so the control is usable before the query comes back.",[249,4162,940],{"class":259},[249,4164,4165],{"class":286},"        departments: ['All'],",[249,4167,1667],{"class":259},[249,4169,4170],{"class":286},"        \u002F\u002F Fixed: these are windows the app defines, not data.",[249,4172,940],{"class":259},[249,4174,4175],{"class":286},"        timeWindows: [",[249,4177,940],{"class":259},[249,4179,4180],{"class":286},"          'Next 7 days',",[249,4182,940],{"class":259},[249,4184,4185],{"class":286},"          'Next 30 days',",[249,4187,940],{"class":259},[249,4189,4190],{"class":286},"          'Next 90 days',",[249,4192,940],{"class":259},[249,4194,4195],{"class":286},"          'All future'",[249,4197,940],{"class":259},[249,4199,4200],{"class":286},"        ]",[249,4202,940],{"class":259},[249,4204,4205],{"class":286},"      }",[249,4207,940],{"class":259},[249,4209,4210],{"class":286},"    },",[249,4212,1667],{"class":259},[249,4214,4215],{"class":286},"    watch: {",[249,4217,940],{"class":259},[249,4219,4220],{"class":286},"      msg: {",[249,4222,940],{"class":259},[249,4224,4225],{"class":286},"        handler(msg) { this.applyMsg(msg) },",[249,4227,940],{"class":259},[249,4229,4230],{"class":286},"        deep: true",[249,4232,940],{"class":259},[249,4234,4205],{"class":286},[249,4236,940],{"class":259},[249,4238,4210],{"class":286},[249,4240,1667],{"class":259},[249,4242,4243],{"class":286},"    mounted() {",[249,4245,940],{"class":259},[249,4247,4248],{"class":286},"      this.mounted = true;",[249,4250,940],{"class":259},[249,4252,4253],{"class":286},"      this.applyMsg(this.msg);",[249,4255,940],{"class":259},[249,4257,4258],{"class":286},"      this.$socket.on('msg-input:' + this.id, this.applyMsg);",[249,4260,1667],{"class":259},[249,4262,4263],{"class":286},"      \u002F\u002F A refresh resets the dropdowns to their defaults, so push those",[249,4265,940],{"class":259},[249,4267,4268],{"class":286},"      \u002F\u002F defaults out once. Without this the queries keep reading the previous",[249,4270,940],{"class":259},[249,4272,4273],{"class":286},"      \u002F\u002F selection from context, and the numbers wouldn't match the dropdowns.",[249,4275,940],{"class":259},[249,4277,4278],{"class":286},"      this.sendFilters();",[249,4280,940],{"class":259},[249,4282,4210],{"class":286},[249,4284,1667],{"class":259},[249,4286,4287],{"class":286},"    unmounted() {",[249,4289,940],{"class":259},[249,4291,4292],{"class":286},"      this.$socket.off('msg-input:' + this.id, this.applyMsg);",[249,4294,940],{"class":259},[249,4296,4210],{"class":286},[249,4298,1667],{"class":259},[249,4300,4301],{"class":286},"    methods: {",[249,4303,940],{"class":259},[249,4305,4306],{"class":286},"      \u002F\u002F Receives the Load Departments rows exactly as the database returns",[249,4308,940],{"class":259},[249,4310,4311],{"class":286},"      \u002F\u002F them: [{ department: 'Assembly' }, { department: 'Quality' }, ...]",[249,4313,940],{"class":259},[249,4315,4316],{"class":286},"      applyMsg(msg) {",[249,4318,940],{"class":259},[249,4320,4321],{"class":286},"        const rows = msg && msg.payload;",[249,4323,940],{"class":259},[249,4325,4326],{"class":286},"        if (!Array.isArray(rows)) return;",[249,4328,1667],{"class":259},[249,4330,4331],{"class":286},"        const names = rows",[249,4333,940],{"class":259},[249,4335,4336],{"class":286},"          .map(r => (r && typeof r === 'object') ? r.department : r)",[249,4338,940],{"class":259},[249,4340,4341],{"class":286},"          .filter(d => typeof d === 'string' && d.trim() !== '');",[249,4343,1667],{"class":259},[249,4345,4346],{"class":286},"        \u002F\u002F 'All' is ours, not a row in the table.",[249,4348,940],{"class":259},[249,4350,4351],{"class":286},"        if (names.length) {",[249,4353,940],{"class":259},[249,4355,4356],{"class":286},"          this.departments = ['All', ...new Set(names)];",[249,4358,940],{"class":259},[249,4360,4361],{"class":286},"        }",[249,4363,940],{"class":259},[249,4365,4366],{"class":286},"      },",[249,4368,1667],{"class":259},[249,4370,4371],{"class":286},"      sendFilters() {",[249,4373,940],{"class":259},[249,4375,4376],{"class":286},"        this.send({",[249,4378,940],{"class":259},[249,4380,4381],{"class":286},"          payload: {",[249,4383,940],{"class":259},[249,4385,4386],{"class":286},"            department: this.department,",[249,4388,940],{"class":259},[249,4390,4391],{"class":286},"            timeWindow: this.timeWindow",[249,4393,940],{"class":259},[249,4395,4396],{"class":286},"          }",[249,4398,940],{"class":259},[249,4400,4401],{"class":286},"        });",[249,4403,940],{"class":259},[249,4405,4205],{"class":286},[249,4407,940],{"class":259},[249,4409,4410],{"class":286},"    }",[249,4412,940],{"class":259},[249,4414,2030],{"class":286},[249,4416,940],{"class":259},[249,4418,4419],{"class":286},"\u003C\u002Fscript>",[249,4421,1667],{"class":259},[249,4423,4424],{"class":286},"\u003Cstyle>",[249,4426,940],{"class":259},[249,4428,4429],{"class":286},"  .filter-bar {",[249,4431,940],{"class":259},[249,4433,4434],{"class":286},"    display: flex;",[249,4436,940],{"class":259},[249,4438,4439],{"class":286},"    align-items: center;",[249,4441,940],{"class":259},[249,4443,4444],{"class":286},"    gap: 12px;",[249,4446,940],{"class":259},[249,4448,4449],{"class":286},"    padding-right: 12px;",[249,4451,940],{"class":259},[249,4453,2030],{"class":286},[249,4455,1667],{"class":259},[249,4457,4458],{"class":286},"  \u002F* Make controls compact in the app bar *\u002F",[249,4460,940],{"class":259},[249,4462,4463],{"class":286},"  .filter-bar .v-input {",[249,4465,940],{"class":259},[249,4467,4468],{"class":286},"    margin-top: 0 !important;",[249,4470,940],{"class":259},[249,4472,2030],{"class":286},[249,4474,940],{"class":259},[249,4476,4477],{"class":286},"\u003C\u002Fstyle>",[249,4479,272],{"class":255},[249,4481,292],{"class":255},[249,4483,272],{"class":255},[249,4485,4486],{"class":275},"storeOutMessages",[249,4488,272],{"class":255},[249,4490,421],{"class":255},[249,4492,272],{"class":255},[249,4494,4495],{"class":275},"passthru",[249,4497,272],{"class":255},[249,4499,729],{"class":255},[249,4501,272],{"class":255},[249,4503,4504],{"class":275},"resendOnRefresh",[249,4506,272],{"class":255},[249,4508,421],{"class":255},[249,4510,272],{"class":255},[249,4512,4513],{"class":275},"templateScope",[249,4515,272],{"class":255},[249,4517,281],{"class":255},[249,4519,272],{"class":255},[249,4521,4522],{"class":286},"widget:page",[249,4524,272],{"class":255},[249,4526,292],{"class":255},[249,4528,272],{"class":255},[249,4530,4531],{"class":275},"className",[249,4533,272],{"class":255},[249,4535,281],{"class":255},[249,4537,786],{"class":255},[249,4539,292],{"class":255},[249,4541,272],{"class":255},[249,4543,564],{"class":275},[249,4545,272],{"class":255},[249,4547,281],{"class":255},[249,4549,4550],{"class":571},"810",[249,4552,292],{"class":255},[249,4554,272],{"class":255},[249,4556,579],{"class":275},[249,4558,272],{"class":255},[249,4560,281],{"class":255},[249,4562,4563],{"class":571},"80",[249,4565,292],{"class":255},[249,4567,272],{"class":255},[249,4569,837],{"class":275},[249,4571,272],{"class":255},[249,4573,1064],{"class":255},[249,4575,272],{"class":255},[249,4577,4578],{"class":286},"b9c34ba932fa101c",[249,4580,272],{"class":255},[249,4582,1073],{"class":255},[249,4584,272],{"class":255},[249,4586,276],{"class":275},[249,4588,272],{"class":255},[249,4590,281],{"class":255},[249,4592,272],{"class":255},[249,4594,3799],{"class":286},[249,4596,272],{"class":255},[249,4598,292],{"class":255},[249,4600,272],{"class":255},[249,4602,297],{"class":275},[249,4604,272],{"class":255},[249,4606,281],{"class":255},[249,4608,272],{"class":255},[249,4610,119],{"class":286},[249,4612,272],{"class":255},[249,4614,292],{"class":255},[249,4616,272],{"class":255},[249,4618,688],{"class":275},[249,4620,272],{"class":255},[249,4622,281],{"class":255},[249,4624,272],{"class":255},[249,4626,3466],{"class":286},[249,4628,272],{"class":255},[249,4630,292],{"class":255},[249,4632,272],{"class":255},[249,4634,3808],{"class":275},[249,4636,272],{"class":255},[249,4638,281],{"class":255},[249,4640,272],{"class":255},[249,4642,4643],{"class":286},"6481b1c613ec9a93",[249,4645,272],{"class":255},[249,4647,292],{"class":255},[249,4649,272],{"class":255},[249,4651,4652],{"class":275},"path",[249,4654,272],{"class":255},[249,4656,281],{"class":255},[249,4658,272],{"class":255},[249,4660,3470],{"class":286},[249,4662,272],{"class":255},[249,4664,292],{"class":255},[249,4666,272],{"class":255},[249,4668,4669],{"class":275},"icon",[249,4671,272],{"class":255},[249,4673,281],{"class":255},[249,4675,272],{"class":255},[249,4677,4678],{"class":286},"home",[249,4680,272],{"class":255},[249,4682,292],{"class":255},[249,4684,272],{"class":255},[249,4686,4687],{"class":275},"layout",[249,4689,272],{"class":255},[249,4691,281],{"class":255},[249,4693,272],{"class":255},[249,4695,4696],{"class":286},"grid",[249,4698,272],{"class":255},[249,4700,292],{"class":255},[249,4702,272],{"class":255},[249,4704,4705],{"class":275},"theme",[249,4707,272],{"class":255},[249,4709,281],{"class":255},[249,4711,272],{"class":255},[249,4713,4714],{"class":286},"faac104f34962f3e",[249,4716,272],{"class":255},[249,4718,292],{"class":255},[249,4720,272],{"class":255},[249,4722,4723],{"class":275},"breakpoints",[249,4725,272],{"class":255},[249,4727,1165],{"class":255},[249,4729,272],{"class":255},[249,4731,688],{"class":343},[249,4733,272],{"class":255},[249,4735,281],{"class":255},[249,4737,272],{"class":255},[249,4739,4740],{"class":286},"Default",[249,4742,272],{"class":255},[249,4744,292],{"class":255},[249,4746,272],{"class":255},[249,4748,4749],{"class":343},"px",[249,4751,272],{"class":255},[249,4753,281],{"class":255},[249,4755,272],{"class":255},[249,4757,2149],{"class":286},[249,4759,272],{"class":255},[249,4761,292],{"class":255},[249,4763,272],{"class":255},[249,4765,4766],{"class":343},"cols",[249,4768,272],{"class":255},[249,4770,281],{"class":255},[249,4772,272],{"class":255},[249,4774,4775],{"class":286},"3",[249,4777,272],{"class":255},[249,4779,617],{"class":255},[249,4781,272],{"class":255},[249,4783,688],{"class":343},[249,4785,272],{"class":255},[249,4787,281],{"class":255},[249,4789,272],{"class":255},[249,4791,4792],{"class":286},"Tablet",[249,4794,272],{"class":255},[249,4796,292],{"class":255},[249,4798,272],{"class":255},[249,4800,4749],{"class":343},[249,4802,272],{"class":255},[249,4804,281],{"class":255},[249,4806,272],{"class":255},[249,4808,4809],{"class":286},"576",[249,4811,272],{"class":255},[249,4813,292],{"class":255},[249,4815,272],{"class":255},[249,4817,4766],{"class":343},[249,4819,272],{"class":255},[249,4821,281],{"class":255},[249,4823,272],{"class":255},[249,4825,4826],{"class":286},"6",[249,4828,272],{"class":255},[249,4830,617],{"class":255},[249,4832,272],{"class":255},[249,4834,688],{"class":343},[249,4836,272],{"class":255},[249,4838,281],{"class":255},[249,4840,272],{"class":255},[249,4842,4843],{"class":286},"Small Desktop",[249,4845,272],{"class":255},[249,4847,292],{"class":255},[249,4849,272],{"class":255},[249,4851,4749],{"class":343},[249,4853,272],{"class":255},[249,4855,281],{"class":255},[249,4857,272],{"class":255},[249,4859,4860],{"class":286},"768",[249,4862,272],{"class":255},[249,4864,292],{"class":255},[249,4866,272],{"class":255},[249,4868,4766],{"class":343},[249,4870,272],{"class":255},[249,4872,281],{"class":255},[249,4874,272],{"class":255},[249,4876,4877],{"class":286},"9",[249,4879,272],{"class":255},[249,4881,617],{"class":255},[249,4883,272],{"class":255},[249,4885,688],{"class":343},[249,4887,272],{"class":255},[249,4889,281],{"class":255},[249,4891,272],{"class":255},[249,4893,4894],{"class":286},"Desktop",[249,4896,272],{"class":255},[249,4898,292],{"class":255},[249,4900,272],{"class":255},[249,4902,4749],{"class":343},[249,4904,272],{"class":255},[249,4906,281],{"class":255},[249,4908,272],{"class":255},[249,4910,4911],{"class":286},"1024",[249,4913,272],{"class":255},[249,4915,292],{"class":255},[249,4917,272],{"class":255},[249,4919,4766],{"class":343},[249,4921,272],{"class":255},[249,4923,281],{"class":255},[249,4925,272],{"class":255},[249,4927,4928],{"class":286},"12",[249,4930,272],{"class":255},[249,4932,1182],{"class":255},[249,4934,272],{"class":255},[249,4936,3837],{"class":275},[249,4938,272],{"class":255},[249,4940,281],{"class":255},[249,4942,371],{"class":571},[249,4944,292],{"class":255},[249,4946,272],{"class":255},[249,4948,4531],{"class":275},[249,4950,272],{"class":255},[249,4952,281],{"class":255},[249,4954,786],{"class":255},[249,4956,292],{"class":255},[249,4958,272],{"class":255},[249,4960,4961],{"class":275},"visible",[249,4963,272],{"class":255},[249,4965,281],{"class":255},[249,4967,272],{"class":255},[249,4969,4970],{"class":286},"true",[249,4972,272],{"class":255},[249,4974,292],{"class":255},[249,4976,272],{"class":255},[249,4978,4979],{"class":275},"disabled",[249,4981,272],{"class":255},[249,4983,281],{"class":255},[249,4985,272],{"class":255},[249,4987,4988],{"class":286},"false",[249,4990,272],{"class":255},[249,4992,617],{"class":255},[249,4994,272],{"class":255},[249,4996,276],{"class":275},[249,4998,272],{"class":255},[249,5000,281],{"class":255},[249,5002,272],{"class":255},[249,5004,4643],{"class":286},[249,5006,272],{"class":255},[249,5008,292],{"class":255},[249,5010,272],{"class":255},[249,5012,297],{"class":275},[249,5014,272],{"class":255},[249,5016,281],{"class":255},[249,5018,272],{"class":255},[249,5020,3546],{"class":286},[249,5022,272],{"class":255},[249,5024,292],{"class":255},[249,5026,272],{"class":255},[249,5028,688],{"class":275},[249,5030,272],{"class":255},[249,5032,281],{"class":255},[249,5034,272],{"class":255},[249,5036,5037],{"class":286},"My Dashboard",[249,5039,272],{"class":255},[249,5041,292],{"class":255},[249,5043,272],{"class":255},[249,5045,4652],{"class":275},[249,5047,272],{"class":255},[249,5049,281],{"class":255},[249,5051,272],{"class":255},[249,5053,5054],{"class":286},"\u002Fdashboard",[249,5056,272],{"class":255},[249,5058,292],{"class":255},[249,5060,272],{"class":255},[249,5062,5063],{"class":275},"appIcon",[249,5065,272],{"class":255},[249,5067,281],{"class":255},[249,5069,786],{"class":255},[249,5071,292],{"class":255},[249,5073,272],{"class":255},[249,5075,5076],{"class":275},"includeClientData",[249,5078,272],{"class":255},[249,5080,421],{"class":255},[249,5082,272],{"class":255},[249,5084,5085],{"class":275},"acceptsClientConfig",[249,5087,272],{"class":255},[249,5089,468],{"class":255},[249,5091,272],{"class":255},[249,5093,116],{"class":286},[249,5095,272],{"class":255},[249,5097,292],{"class":255},[249,5099,272],{"class":255},[249,5101,5102],{"class":286},"ui-control",[249,5104,272],{"class":255},[249,5106,292],{"class":255},[249,5108,272],{"class":255},[249,5110,5111],{"class":286},"ui-number-input",[249,5113,272],{"class":255},[249,5115,292],{"class":255},[249,5117,272],{"class":255},[249,5119,5120],{"class":286},"ui-file-input",[249,5122,272],{"class":255},[249,5124,292],{"class":255},[249,5126,272],{"class":255},[249,5128,110],{"class":286},[249,5130,272],{"class":255},[249,5132,292],{"class":255},[249,5134,272],{"class":255},[249,5136,5137],{"class":286},"ui-button-group",[249,5139,272],{"class":255},[249,5141,292],{"class":255},[249,5143,272],{"class":255},[249,5145,5146],{"class":286},"ui-dropdown",[249,5148,272],{"class":255},[249,5150,292],{"class":255},[249,5152,272],{"class":255},[249,5154,5155],{"class":286},"ui-radio-group",[249,5157,272],{"class":255},[249,5159,292],{"class":255},[249,5161,272],{"class":255},[249,5163,5164],{"class":286},"ui-slider",[249,5166,272],{"class":255},[249,5168,292],{"class":255},[249,5170,272],{"class":255},[249,5172,5173],{"class":286},"ui-switch",[249,5175,272],{"class":255},[249,5177,292],{"class":255},[249,5179,272],{"class":255},[249,5181,5182],{"class":286},"ui-text",[249,5184,272],{"class":255},[249,5186,292],{"class":255},[249,5188,272],{"class":255},[249,5190,5191],{"class":286},"ui-table",[249,5193,272],{"class":255},[249,5195,292],{"class":255},[249,5197,272],{"class":255},[249,5199,5200],{"class":286},"ui-gauge",[249,5202,272],{"class":255},[249,5204,292],{"class":255},[249,5206,272],{"class":255},[249,5208,5209],{"class":286},"ui-chart",[249,5211,272],{"class":255},[249,5213,292],{"class":255},[249,5215,272],{"class":255},[249,5217,103],{"class":286},[249,5219,272],{"class":255},[249,5221,292],{"class":255},[249,5223,272],{"class":255},[249,5225,113],{"class":286},[249,5227,272],{"class":255},[249,5229,292],{"class":255},[249,5231,272],{"class":255},[249,5233,5234],{"class":286},"ui-progress",[249,5236,272],{"class":255},[249,5238,292],{"class":255},[249,5240,272],{"class":255},[249,5242,5243],{"class":286},"ui-webcam",[249,5245,272],{"class":255},[249,5247,559],{"class":255},[249,5249,272],{"class":255},[249,5251,5252],{"class":275},"showPathInSidebar",[249,5254,272],{"class":255},[249,5256,729],{"class":255},[249,5258,272],{"class":255},[249,5260,5261],{"class":275},"headerContent",[249,5263,272],{"class":255},[249,5265,281],{"class":255},[249,5267,272],{"class":255},[249,5269,3553],{"class":286},[249,5271,272],{"class":255},[249,5273,292],{"class":255},[249,5275,272],{"class":255},[249,5277,5278],{"class":275},"navigationStyle",[249,5280,272],{"class":255},[249,5282,281],{"class":255},[249,5284,272],{"class":255},[249,5286,5287],{"class":286},"default",[249,5289,272],{"class":255},[249,5291,292],{"class":255},[249,5293,272],{"class":255},[249,5295,5296],{"class":275},"titleBarStyle",[249,5298,272],{"class":255},[249,5300,281],{"class":255},[249,5302,272],{"class":255},[249,5304,5287],{"class":286},[249,5306,272],{"class":255},[249,5308,292],{"class":255},[249,5310,272],{"class":255},[249,5312,5313],{"class":275},"showReconnectNotification",[249,5315,272],{"class":255},[249,5317,421],{"class":255},[249,5319,272],{"class":255},[249,5321,5322],{"class":275},"notificationDisplayTime",[249,5324,272],{"class":255},[249,5326,281],{"class":255},[249,5328,371],{"class":571},[249,5330,292],{"class":255},[249,5332,272],{"class":255},[249,5334,5335],{"class":275},"showDisconnectNotification",[249,5337,272],{"class":255},[249,5339,421],{"class":255},[249,5341,272],{"class":255},[249,5343,5344],{"class":275},"allowInstall",[249,5346,272],{"class":255},[249,5348,5349],{"class":255},":false},{",[249,5351,272],{"class":255},[249,5353,276],{"class":275},[249,5355,272],{"class":255},[249,5357,281],{"class":255},[249,5359,272],{"class":255},[249,5361,4714],{"class":286},[249,5363,272],{"class":255},[249,5365,292],{"class":255},[249,5367,272],{"class":255},[249,5369,297],{"class":275},[249,5371,272],{"class":255},[249,5373,281],{"class":255},[249,5375,272],{"class":255},[249,5377,125],{"class":286},[249,5379,272],{"class":255},[249,5381,292],{"class":255},[249,5383,272],{"class":255},[249,5385,688],{"class":275},[249,5387,272],{"class":255},[249,5389,281],{"class":255},[249,5391,272],{"class":255},[249,5393,5394],{"class":286},"Default Theme",[249,5396,272],{"class":255},[249,5398,292],{"class":255},[249,5400,272],{"class":255},[249,5402,5403],{"class":275},"colors",[249,5405,272],{"class":255},[249,5407,338],{"class":255},[249,5409,272],{"class":255},[249,5411,5412],{"class":343},"surface",[249,5414,272],{"class":255},[249,5416,281],{"class":255},[249,5418,272],{"class":255},[249,5420,5421],{"class":286},"#ffffff",[249,5423,272],{"class":255},[249,5425,292],{"class":255},[249,5427,272],{"class":255},[249,5429,5430],{"class":343},"primary",[249,5432,272],{"class":255},[249,5434,281],{"class":255},[249,5436,272],{"class":255},[249,5438,5439],{"class":286},"#1e4e8c",[249,5441,272],{"class":255},[249,5443,292],{"class":255},[249,5445,272],{"class":255},[249,5447,5448],{"class":343},"bgPage",[249,5450,272],{"class":255},[249,5452,281],{"class":255},[249,5454,272],{"class":255},[249,5456,5457],{"class":286},"#eef1f5",[249,5459,272],{"class":255},[249,5461,292],{"class":255},[249,5463,272],{"class":255},[249,5465,5466],{"class":343},"groupBg",[249,5468,272],{"class":255},[249,5470,281],{"class":255},[249,5472,272],{"class":255},[249,5474,5421],{"class":286},[249,5476,272],{"class":255},[249,5478,292],{"class":255},[249,5480,272],{"class":255},[249,5482,5483],{"class":343},"groupOutline",[249,5485,272],{"class":255},[249,5487,281],{"class":255},[249,5489,272],{"class":255},[249,5491,5492],{"class":286},"#d3dae3",[249,5494,272],{"class":255},[249,5496,458],{"class":255},[249,5498,272],{"class":255},[249,5500,5501],{"class":275},"sizes",[249,5503,272],{"class":255},[249,5505,338],{"class":255},[249,5507,272],{"class":255},[249,5509,5510],{"class":343},"density",[249,5512,272],{"class":255},[249,5514,281],{"class":255},[249,5516,272],{"class":255},[249,5518,5287],{"class":286},[249,5520,272],{"class":255},[249,5522,292],{"class":255},[249,5524,272],{"class":255},[249,5526,5527],{"class":343},"pagePadding",[249,5529,272],{"class":255},[249,5531,281],{"class":255},[249,5533,272],{"class":255},[249,5535,5536],{"class":286},"12px",[249,5538,272],{"class":255},[249,5540,292],{"class":255},[249,5542,272],{"class":255},[249,5544,5545],{"class":343},"groupGap",[249,5547,272],{"class":255},[249,5549,281],{"class":255},[249,5551,272],{"class":255},[249,5553,5536],{"class":286},[249,5555,272],{"class":255},[249,5557,292],{"class":255},[249,5559,272],{"class":255},[249,5561,5562],{"class":343},"groupBorderRadius",[249,5564,272],{"class":255},[249,5566,281],{"class":255},[249,5568,272],{"class":255},[249,5570,5571],{"class":286},"4px",[249,5573,272],{"class":255},[249,5575,292],{"class":255},[249,5577,272],{"class":255},[249,5579,5580],{"class":343},"widgetGap",[249,5582,272],{"class":255},[249,5584,281],{"class":255},[249,5586,272],{"class":255},[249,5588,5536],{"class":286},[249,5590,272],{"class":255},[249,5592,5593],{"class":255},"}},{",[249,5595,272],{"class":255},[249,5597,276],{"class":275},[249,5599,272],{"class":255},[249,5601,281],{"class":255},[249,5603,272],{"class":255},[249,5605,5606],{"class":286},"6f4ad536fc64beb9",[249,5608,272],{"class":255},[249,5610,292],{"class":255},[249,5612,272],{"class":255},[249,5614,297],{"class":275},[249,5616,272],{"class":255},[249,5618,281],{"class":255},[249,5620,272],{"class":255},[249,5622,3245],{"class":286},[249,5624,272],{"class":255},[249,5626,292],{"class":255},[249,5628,272],{"class":255},[249,5630,3254],{"class":275},[249,5632,272],{"class":255},[249,5634,2200],{"class":255},[249,5636,272],{"class":255},[249,5638,3263],{"class":275},[249,5640,272],{"class":255},[249,5642,338],{"class":255},[249,5644,272],{"class":255},[249,5646,99],{"class":343},[249,5648,272],{"class":255},[249,5650,281],{"class":255},[249,5652,272],{"class":255},[249,5654,5655],{"class":286},"1.30.2",[249,5657,272],{"class":255},[249,5659,3286],{"class":255},[249,5661,5662,5664,5666],{"class":251,"line":3289},[249,5663,256],{"class":255},[249,5665,3294],{"class":259},[249,5667,263],{"class":255},[166,5669,5670,5682,5688],{"start":3618},[79,5671,3572,5672,5675,5676,3303,5679,26],{},[56,5673,5674],{},"change"," node named \"Save Filters to Global Context\" and set the persistent global ",[56,5677,5678],{},"filters",[56,5680,5681],{},"msg.payload",[79,5683,3572,5684,5687],{},[56,5685,5686],{},"link out"," node named \"Filters Changed\". This is what makes the page respond right away. Changing a dropdown writes the new selection to context, but nothing would redraw until the next poll tick, so the operator would be looking at stale numbers for up to fifteen seconds. The link carries the change straight into the next flow, which re-runs its query and refreshes the page.",[79,5689,5690,5691,26],{},"Wire the nodes: ",[51,5692,5693],{},"Page Load \u002F Refresh Event → Load Departments → App Header Filters → Save Filters to Global Context → Filters Changed",[12,5695,5696,37,5700],{},[33,5697],{"alt":5698,"src":5699},"Placeholder: the app bar showing the Department and Time Window dropdowns","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fheader-dropdown.png",[39,5701,5702],{},"The Department and Time Window dropdowns shown in the app bar, with departments read from the register.",[68,5704,5706],{"id":5705},"working-out-the-kpi-figures-from-the-due-dates","Working Out the KPI Figures from the Due Dates",[12,5708,5709,5710,5712,5713,5715],{},"This is where we stop using the register's ",[56,5711,3357],{}," column. Every figure on the page comes from comparing ",[56,5714,3347],{}," against the current time, and one extra count reports how often the stored status disagrees with that comparison.",[166,5717,5718,5728,5734],{},[79,5719,5720,5721,5723,5724,5727],{},"Add an ",[56,5722,1102],{}," node named \"Poll Data (15 sec)\", set it to repeat every ",[51,5725,5726],{},"15"," seconds and to fire once shortly after deploy, so the page has data before the first tick.",[79,5729,3572,5730,5733],{},[56,5731,5732],{},"link in"," node named \"Filters Changed\" and point it at the link out from the filter bar.",[79,5735,3572,5736,5738,5739,5742,5743,5746,5747],{},[56,5737,5674],{}," node named \"Set Params\". This maps the saved filters onto the ",[56,5740,5741],{},"$department"," and ",[56,5744,5745],{},"$timeWindow"," parameters the SQL reads. Set three rules, in order:",[76,5748,5749,5759,5768],{},[79,5750,5751,5752,3303,5755,5758],{},"Set ",[56,5753,5754],{},"queryParameters",[56,5756,5757],{},"{}"," (JSON): starts clean so old values don't linger.",[79,5760,5751,5761,3303,5764,5767],{},[56,5762,5763],{},"queryParameters.department",[56,5765,5766],{},"filters.department"," (global persistent).",[79,5769,5751,5770,3303,5773,5767],{},[56,5771,5772],{},"queryParameters.timeWindow",[56,5774,5775],{},"filters.timeWindow",[12,5777,5778,37,5782],{},[33,5779],{"alt":5780,"src":5781},"Set Params change node with its three rules","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fset-params.png",[39,5783,5784],{},"The \"Set Params\" change node open in the edit panel, all three rules visible.",[166,5786,5787],{},[79,5788,3572,5789,5791],{},[56,5790,871],{}," node named \"KPI Query\":",[240,5793,5795],{"className":3596,"code":5794,"language":3598,"meta":245,"style":245},"SELECT\n    -- Sent back so the cards label themselves from the data on screen,\n    -- not from whatever the dropdowns happen to show. COALESCE covers the\n    -- first poll after deploy, before any browser has sent a selection.\n    COALESCE($department::text, 'All')          AS filter_department,\n    COALESCE($timeWindow::text, 'Next 90 days') AS filter_window,\n\n    COUNT(*) AS total_assets,\n\n    -- Buckets worked out from next_due_ts instead of the stored status column,\n    -- which drifts whenever whatever writes it falls behind. These three\n    -- don't overlap, and add up to total_assets. The 30-day threshold is a\n    -- policy decision, not a view setting: it does not change with the dropdown.\n    COUNT(*) FILTER (\n        WHERE next_due_ts > NOW() + INTERVAL '30 days'\n    ) AS valid_assets,\n\n    COUNT(*) FILTER (\n        WHERE next_due_ts >= NOW()\n          AND next_due_ts \u003C= NOW() + INTERVAL '30 days'\n    ) AS due_soon_assets,\n\n    COUNT(*) FILTER (\n        WHERE next_due_ts \u003C NOW()\n    ) AS overdue_assets,\n\n    -- The only figure the Time Window dropdown affects. It sends a label, so\n    -- it maps to an interval here; ELSE also catches an unrecognised label.\n    COUNT(*) FILTER (\n        WHERE next_due_ts >= NOW()\n          AND next_due_ts \u003C= NOW() + (\n              CASE COALESCE($timeWindow::text, 'Next 90 days')\n                  WHEN 'Next 7 days'  THEN INTERVAL '7 days'\n                  WHEN 'Next 30 days' THEN INTERVAL '30 days'\n                  WHEN 'Next 90 days' THEN INTERVAL '90 days'\n                  WHEN 'All future'   THEN INTERVAL '100 years'\n                  ELSE INTERVAL '90 days'\n              END\n          )\n    ) AS due_in_window,\n\n    COUNT(*) FILTER (\n        WHERE next_due_ts BETWEEN NOW()\n                            AND NOW() + INTERVAL '7 days'\n    ) AS due_next_7_days,\n\n    -- Compliance means \"inside its calibration interval\", which includes\n    -- tools due soon, since they have not expired yet.\n    ROUND(\n        COUNT(*) FILTER (WHERE next_due_ts >= NOW()) * 100.0\n        \u002F NULLIF(COUNT(*), 0),\n        1\n    ) AS valid_percentage,\n\n    -- Counts records where the stored status and the live date disagree, so\n    -- the drift shows up on the dashboard instead of staying hidden.\n    COUNT(*) FILTER (\n        WHERE (status = 'Overdue') \u003C> (next_due_ts \u003C NOW())\n    ) AS stale_status_count\n\nFROM calibration_assets\n-- Driven by the Department dropdown; 'All' turns the filter off.\nWHERE (COALESCE($department::text, 'All') = 'All'\n       OR department = $department::text);\n",[56,5796,5797,5802,5807,5812,5817,5822,5828,5835,5841,5846,5852,5858,5864,5870,5876,5882,5888,5893,5898,5904,5910,5916,5921,5926,5932,5938,5943,5949,5955,5960,5965,5971,5977,5983,5989,5995,6001,6007,6013,6019,6025,6030,6035,6041,6047,6053,6058,6064,6070,6076,6082,6088,6094,6100,6105,6111,6117,6122,6128,6134,6139,6144,6150,6156],{"__ignoreMap":245},[249,5798,5799],{"class":251,"line":252},[249,5800,5801],{},"SELECT\n",[249,5803,5804],{"class":251,"line":266},[249,5805,5806],{},"    -- Sent back so the cards label themselves from the data on screen,\n",[249,5808,5809],{"class":251,"line":3289},[249,5810,5811],{},"    -- not from whatever the dropdowns happen to show. COALESCE covers the\n",[249,5813,5814],{"class":251,"line":3618},[249,5815,5816],{},"    -- first poll after deploy, before any browser has sent a selection.\n",[249,5818,5819],{"class":251,"line":3624},[249,5820,5821],{},"    COALESCE($department::text, 'All')          AS filter_department,\n",[249,5823,5825],{"class":251,"line":5824},6,[249,5826,5827],{},"    COALESCE($timeWindow::text, 'Next 90 days') AS filter_window,\n",[249,5829,5831],{"class":251,"line":5830},7,[249,5832,5834],{"emptyLinePlaceholder":5833},true,"\n",[249,5836,5838],{"class":251,"line":5837},8,[249,5839,5840],{},"    COUNT(*) AS total_assets,\n",[249,5842,5844],{"class":251,"line":5843},9,[249,5845,5834],{"emptyLinePlaceholder":5833},[249,5847,5849],{"class":251,"line":5848},10,[249,5850,5851],{},"    -- Buckets worked out from next_due_ts instead of the stored status column,\n",[249,5853,5855],{"class":251,"line":5854},11,[249,5856,5857],{},"    -- which drifts whenever whatever writes it falls behind. These three\n",[249,5859,5861],{"class":251,"line":5860},12,[249,5862,5863],{},"    -- don't overlap, and add up to total_assets. The 30-day threshold is a\n",[249,5865,5867],{"class":251,"line":5866},13,[249,5868,5869],{},"    -- policy decision, not a view setting: it does not change with the dropdown.\n",[249,5871,5873],{"class":251,"line":5872},14,[249,5874,5875],{},"    COUNT(*) FILTER (\n",[249,5877,5879],{"class":251,"line":5878},15,[249,5880,5881],{},"        WHERE next_due_ts > NOW() + INTERVAL '30 days'\n",[249,5883,5885],{"class":251,"line":5884},16,[249,5886,5887],{},"    ) AS valid_assets,\n",[249,5889,5891],{"class":251,"line":5890},17,[249,5892,5834],{"emptyLinePlaceholder":5833},[249,5894,5896],{"class":251,"line":5895},18,[249,5897,5875],{},[249,5899,5901],{"class":251,"line":5900},19,[249,5902,5903],{},"        WHERE next_due_ts >= NOW()\n",[249,5905,5907],{"class":251,"line":5906},20,[249,5908,5909],{},"          AND next_due_ts \u003C= NOW() + INTERVAL '30 days'\n",[249,5911,5913],{"class":251,"line":5912},21,[249,5914,5915],{},"    ) AS due_soon_assets,\n",[249,5917,5919],{"class":251,"line":5918},22,[249,5920,5834],{"emptyLinePlaceholder":5833},[249,5922,5924],{"class":251,"line":5923},23,[249,5925,5875],{},[249,5927,5929],{"class":251,"line":5928},24,[249,5930,5931],{},"        WHERE next_due_ts \u003C NOW()\n",[249,5933,5935],{"class":251,"line":5934},25,[249,5936,5937],{},"    ) AS overdue_assets,\n",[249,5939,5941],{"class":251,"line":5940},26,[249,5942,5834],{"emptyLinePlaceholder":5833},[249,5944,5946],{"class":251,"line":5945},27,[249,5947,5948],{},"    -- The only figure the Time Window dropdown affects. It sends a label, so\n",[249,5950,5952],{"class":251,"line":5951},28,[249,5953,5954],{},"    -- it maps to an interval here; ELSE also catches an unrecognised label.\n",[249,5956,5958],{"class":251,"line":5957},29,[249,5959,5875],{},[249,5961,5963],{"class":251,"line":5962},30,[249,5964,5903],{},[249,5966,5968],{"class":251,"line":5967},31,[249,5969,5970],{},"          AND next_due_ts \u003C= NOW() + (\n",[249,5972,5974],{"class":251,"line":5973},32,[249,5975,5976],{},"              CASE COALESCE($timeWindow::text, 'Next 90 days')\n",[249,5978,5980],{"class":251,"line":5979},33,[249,5981,5982],{},"                  WHEN 'Next 7 days'  THEN INTERVAL '7 days'\n",[249,5984,5986],{"class":251,"line":5985},34,[249,5987,5988],{},"                  WHEN 'Next 30 days' THEN INTERVAL '30 days'\n",[249,5990,5992],{"class":251,"line":5991},35,[249,5993,5994],{},"                  WHEN 'Next 90 days' THEN INTERVAL '90 days'\n",[249,5996,5998],{"class":251,"line":5997},36,[249,5999,6000],{},"                  WHEN 'All future'   THEN INTERVAL '100 years'\n",[249,6002,6004],{"class":251,"line":6003},37,[249,6005,6006],{},"                  ELSE INTERVAL '90 days'\n",[249,6008,6010],{"class":251,"line":6009},38,[249,6011,6012],{},"              END\n",[249,6014,6016],{"class":251,"line":6015},39,[249,6017,6018],{},"          )\n",[249,6020,6022],{"class":251,"line":6021},40,[249,6023,6024],{},"    ) AS due_in_window,\n",[249,6026,6028],{"class":251,"line":6027},41,[249,6029,5834],{"emptyLinePlaceholder":5833},[249,6031,6033],{"class":251,"line":6032},42,[249,6034,5875],{},[249,6036,6038],{"class":251,"line":6037},43,[249,6039,6040],{},"        WHERE next_due_ts BETWEEN NOW()\n",[249,6042,6044],{"class":251,"line":6043},44,[249,6045,6046],{},"                            AND NOW() + INTERVAL '7 days'\n",[249,6048,6050],{"class":251,"line":6049},45,[249,6051,6052],{},"    ) AS due_next_7_days,\n",[249,6054,6056],{"class":251,"line":6055},46,[249,6057,5834],{"emptyLinePlaceholder":5833},[249,6059,6061],{"class":251,"line":6060},47,[249,6062,6063],{},"    -- Compliance means \"inside its calibration interval\", which includes\n",[249,6065,6067],{"class":251,"line":6066},48,[249,6068,6069],{},"    -- tools due soon, since they have not expired yet.\n",[249,6071,6073],{"class":251,"line":6072},49,[249,6074,6075],{},"    ROUND(\n",[249,6077,6079],{"class":251,"line":6078},50,[249,6080,6081],{},"        COUNT(*) FILTER (WHERE next_due_ts >= NOW()) * 100.0\n",[249,6083,6085],{"class":251,"line":6084},51,[249,6086,6087],{},"        \u002F NULLIF(COUNT(*), 0),\n",[249,6089,6091],{"class":251,"line":6090},52,[249,6092,6093],{},"        1\n",[249,6095,6097],{"class":251,"line":6096},53,[249,6098,6099],{},"    ) AS valid_percentage,\n",[249,6101,6103],{"class":251,"line":6102},54,[249,6104,5834],{"emptyLinePlaceholder":5833},[249,6106,6108],{"class":251,"line":6107},55,[249,6109,6110],{},"    -- Counts records where the stored status and the live date disagree, so\n",[249,6112,6114],{"class":251,"line":6113},56,[249,6115,6116],{},"    -- the drift shows up on the dashboard instead of staying hidden.\n",[249,6118,6120],{"class":251,"line":6119},57,[249,6121,5875],{},[249,6123,6125],{"class":251,"line":6124},58,[249,6126,6127],{},"        WHERE (status = 'Overdue') \u003C> (next_due_ts \u003C NOW())\n",[249,6129,6131],{"class":251,"line":6130},59,[249,6132,6133],{},"    ) AS stale_status_count\n",[249,6135,6137],{"class":251,"line":6136},60,[249,6138,5834],{"emptyLinePlaceholder":5833},[249,6140,6142],{"class":251,"line":6141},61,[249,6143,3610],{},[249,6145,6147],{"class":251,"line":6146},62,[249,6148,6149],{},"-- Driven by the Department dropdown; 'All' turns the filter off.\n",[249,6151,6153],{"class":251,"line":6152},63,[249,6154,6155],{},"WHERE (COALESCE($department::text, 'All') = 'All'\n",[249,6157,6159],{"class":251,"line":6158},64,[249,6160,6161],{},"       OR department = $department::text);\n",[12,6163,6164,6167],{},[56,6165,6166],{},"stale_status_count"," is the figure worth watching. It counts the rows where the stored status and the due date disagree, which is the number that justifies leaving the status column out of every other calculation.",[166,6169,6170,6179],{"start":3624},[79,6171,3572,6172,6174,6175,6178],{},[56,6173,5686],{}," node named \"Refresh Asset Table\" and wire it from ",[51,6176,6177],{},"Set Params",", so the table below runs on the same selection instead of working it out again.",[79,6180,3632,6181,37,6184,6186,6187,6189,6190,6192],{},[51,6182,6183],{},"KPI Cards",[56,6185,103],{}," below and assign it to the ",[51,6188,3510],{}," group. The complete component is provided below, so there's no need to build it yourself. It shows a header with the active filter and a last-updated time, six cards for total equipment, valid, due soon, overdue, upcoming and compliance, and a three-line summary strip. When ",[56,6191,6166],{}," is above zero it also shows a warning banner naming the number of drifted records.",[236,6194,6195],{":height":238},[240,6196,6198],{"className":242,"code":6197,"language":244,"meta":245,"style":245},"{% raw %}\n[{\"id\":\"1e9b85cd8f2fdc3c\",\"type\":\"ui-template\",\"z\":\"1c5b2364213044a7\",\"g\":\"3ed935d02285b78b\",\"group\":\"05fdb0d422eb75af\",\"page\":\"\",\"ui\":\"\",\"name\":\"KPI Cards\",\"order\":1,\"width\":0,\"height\":0,\"head\":\"\",\"format\":\"\u003Ctemplate>\\n    \u003Cv-container fluid class=\\\"pa-2\\\">\\n\\n        \u003C!-- Header -->\\n        \u003Cv-card class=\\\"pa-4 mb-3\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n            \u003Cv-row align=\\\"center\\\">\\n                \u003Cv-col cols=\\\"12\\\" md=\\\"7\\\">\\n                    \u003Cdiv class=\\\"text-h6 font-weight-bold\\\">ACME Automotive Plant\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-body-2 text-medium-emphasis\\\">\\n                        Calibration &amp; Measurement Status Dashboard\\n                    \u003C\u002Fdiv>\\n                \u003C\u002Fv-col>\\n\\n                \u003Cv-col cols=\\\"12\\\" md=\\\"5\\\" class=\\\"text-md-right\\\">\\n                    \u003Cv-chip v-if=\\\"filters.department\\\" color=\\\"primary\\\" variant=\\\"tonal\\\" size=\\\"small\\\" class=\\\"mr-2\\\">\\n                        \u003Cv-icon start size=\\\"16\\\">mdi-filter-variant\u003C\u002Fv-icon>\\n                        {{ filters.department }} &middot; {{ filters.window }}\\n                    \u003C\u002Fv-chip>\\n                    \u003Cv-chip v-if=\\\"updatedAt\\\" color=\\\"primary\\\" variant=\\\"tonal\\\" size=\\\"small\\\">\\n                        \u003Cv-icon start size=\\\"16\\\">mdi-refresh\u003C\u002Fv-icon>\\n                        Updated {{ updatedAtText }}\\n                    \u003C\u002Fv-chip>\\n                \u003C\u002Fv-col>\\n            \u003C\u002Fv-row>\\n        \u003C\u002Fv-card>\\n\\n        \u003C!-- Loading state until the first query result arrives -->\\n        \u003Cv-alert v-if=\\\"!loaded\\\" type=\\\"info\\\" variant=\\\"tonal\\\" density=\\\"compact\\\" class=\\\"mb-3\\\">\\n            Waiting for calibration data...\\n        \u003C\u002Fv-alert>\\n\\n        \u003C!-- Data quality: the stored status column has drifted from the dates -->\\n        \u003Cv-alert v-if=\\\"kpi.stale_status_count > 0\\\" type=\\\"warning\\\" variant=\\\"tonal\\\"\\n            density=\\\"compact\\\" class=\\\"mb-3\\\">\\n            {{ kpi.stale_status_count }} record(s) have a status field that disagrees with\\n            their due date. Every count here is derived from the date.\\n        \u003C\u002Fv-alert>\\n\\n        \u003C!-- KPI Cards -->\\n        \u003Cv-row dense>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-neutral\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">TOTAL EQUIPMENT\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2\\\">{{ show(kpi.total_assets) }}\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">\\n                        {{ filters.department === 'All' ? 'All departments' : filters.department }}\\n                    \u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-success\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">VALID\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2 text-success\\\">{{ show(kpi.valid_assets) }}\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">Due beyond 30 days\u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-warning\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">DUE SOON\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2 text-warning\\\">{{ show(kpi.due_soon_assets) }}\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">Next 30 days\u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-danger\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">OVERDUE\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2 text-error\\\">{{ show(kpi.overdue_assets) }}\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">Immediate action\u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-info\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">UPCOMING\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2 text-info\\\">{{ show(kpi.due_in_window) }}\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">{{ filters.window }}\u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" sm=\\\"6\\\" md=\\\"2\\\">\\n                \u003Cv-card class=\\\"pa-4 h-100 border-neutral\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">COMPLIANCE\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-h4 font-weight-bold mt-2\\\">{{ show(kpi.valid_percentage) }}%\u003C\u002Fdiv>\\n                    \u003Cdiv class=\\\"text-caption text-medium-emphasis mt-2\\\">Plant health\u003C\u002Fdiv>\\n                \u003C\u002Fv-card>\\n            \u003C\u002Fv-col>\\n\\n        \u003C\u002Fv-row>\\n\\n        \u003C!-- Status Strip -->\\n        \u003Cv-card class=\\\"pa-3 mt-3\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n            \u003Cv-row dense align=\\\"center\\\">\\n                \u003Cv-col cols=\\\"12\\\" md=\\\"4\\\">\\n                    \u003Cdiv class=\\\"d-flex align-center\\\">\\n                        \u003Cv-icon color=\\\"success\\\" class=\\\"mr-2\\\">mdi-check-circle\u003C\u002Fv-icon>\\n                        \u003Cspan class=\\\"text-body-2\\\">\\n                            \u003Cstrong>{{ show(kpi.valid_assets) }}\u003C\u002Fstrong> tools verified for production\\n                        \u003C\u002Fspan>\\n                    \u003C\u002Fdiv>\\n                \u003C\u002Fv-col>\\n\\n                \u003Cv-col cols=\\\"12\\\" md=\\\"4\\\">\\n                    \u003Cdiv class=\\\"d-flex align-center\\\">\\n                        \u003Cv-icon color=\\\"warning\\\" class=\\\"mr-2\\\">mdi-alert\u003C\u002Fv-icon>\\n                        \u003Cspan class=\\\"text-body-2\\\">\\n                            \u003Cstrong>{{ show(kpi.due_next_7_days) }}\u003C\u002Fstrong> tools require calibration within 7 days\\n                        \u003C\u002Fspan>\\n                    \u003C\u002Fdiv>\\n                \u003C\u002Fv-col>\\n\\n                \u003Cv-col cols=\\\"12\\\" md=\\\"4\\\">\\n                    \u003Cdiv class=\\\"d-flex align-center\\\">\\n                        \u003Cv-icon color=\\\"error\\\" class=\\\"mr-2\\\">mdi-close-circle\u003C\u002Fv-icon>\\n                        \u003Cspan class=\\\"text-body-2\\\">\\n                            \u003Cstrong>{{ show(kpi.overdue_assets) }}\u003C\u002Fstrong> tools are overdue and blocked from use\\n                        \u003C\u002Fspan>\\n                    \u003C\u002Fdiv>\\n                \u003C\u002Fv-col>\\n            \u003C\u002Fv-row>\\n        \u003C\u002Fv-card>\\n\\n    \u003C\u002Fv-container>\\n\u003C\u002Ftemplate>\\n\\n\u003Cscript>\\n    export default {\\n        data() {\\n            return {\\n                loaded: false,\\n                updatedAt: null,\\n\\n                \u002F\u002F Echoed back from the query so the cards always describe\\n                \u002F\u002F the data actually on screen, not the pending selection.\\n                filters: {\\n                    department: '',\\n                    window: ''\\n                },\\n\\n                kpi: {\\n                    total_assets: null,\\n                    valid_assets: null,\\n                    due_soon_assets: null,\\n                    overdue_assets: null,\\n                    due_in_window: null,\\n                    due_next_7_days: null,\\n                    stale_status_count: null,\\n                    valid_percentage: null\\n                }\\n            }\\n        },\\n\\n        computed: {\\n            updatedAtText() {\\n                if (!this.updatedAt) return ''\\n                return this.updatedAt.toLocaleTimeString([], {\\n                    hour: '2-digit',\\n                    minute: '2-digit',\\n                    second: '2-digit'\\n                })\\n            }\\n        },\\n\\n        \u002F\u002F Catches the message that Dashboard replays on page load \u002F refresh,\\n        \u002F\u002F which can arrive before the socket listener below is registered.\\n        watch: {\\n            msg: {\\n                handler(msg) { this.applyMsg(msg) },\\n                immediate: true,\\n                deep: true\\n            }\\n        },\\n\\n        mounted() {\\n            this.applyMsg(this.msg)\\n            this.$socket.on('msg-input:' + this.id, this.applyMsg)\\n        },\\n\\n        unmounted() {\\n            this.$socket.off('msg-input:' + this.id, this.applyMsg)\\n        },\\n\\n        methods: {\\n            applyMsg(msg) {\\n                const payload = msg && msg.payload\\n                if (!payload) return\\n\\n                \u002F\u002F The Query node returns an ARRAY of rows unless \\\"Split results\\\"\\n                \u002F\u002F is on with 1 row per message. Take the first row either way.\\n                const row = Array.isArray(payload) ? payload[0] : payload\\n                if (!row || typeof row !== 'object') return\\n\\n                if (row.filter_department) this.filters.department = row.filter_department\\n                if (row.filter_window) this.filters.window = row.filter_window\\n\\n                const next = {}\\n                for (const key of Object.keys(this.kpi)) {\\n                    if (row[key] === undefined || row[key] === null) continue\\n                    \u002F\u002F COUNT() is BIGINT and ROUND() is NUMERIC - pg returns both\\n                    \u002F\u002F as strings, so coerce to Number for display and maths.\\n                    const num = Number(row[key])\\n                    next[key] = Number.isFinite(num) ? num : row[key]\\n                }\\n\\n                this.kpi = { ...this.kpi, ...next }\\n                this.loaded = true\\n                this.updatedAt = new Date()\\n            },\\n\\n            show(value) {\\n                return (value === null || value === undefined) ? '-' : value\\n            }\\n        }\\n    }\\n\u003C\u002Fscript>\\n\\n\u003Cstyle>\\n    \u002F* The ui-theme node only carries the four structural colours, so the\\n       semantic ones are redefined here. This block is unscoped, so it\\n       applies to every widget on the page. *\u002F\\n    :root,\\n    [class*=\\\"v-theme--\\\"] {\\n        --v-theme-success: 21, 128, 61 !important;\\n        --v-theme-warning: 180, 83, 9 !important;\\n        --v-theme-error: 179, 38, 30 !important;\\n        --v-theme-info: 30, 78, 140 !important;\\n\\n        \u002F* Text and icons sitting on top of a filled chip or button. *\u002F\\n        --v-theme-on-success: 255, 255, 255 !important;\\n        --v-theme-on-warning: 255, 255, 255 !important;\\n        --v-theme-on-error: 255, 255, 255 !important;\\n        --v-theme-on-info: 255, 255, 255 !important;\\n    }\\n\\n    .border-neutral {\\n        border-top: 4px solid #8894a6;\\n    }\\n\\n    .border-success {\\n        border-top: 4px solid rgb(var(--v-theme-success));\\n    }\\n\\n    .border-warning {\\n        border-top: 4px solid rgb(var(--v-theme-warning));\\n    }\\n\\n    .border-danger {\\n        border-top: 4px solid rgb(var(--v-theme-error));\\n    }\\n\\n    .border-info {\\n        border-top: 4px solid rgb(var(--v-theme-info));\\n    }\\n\u003C\u002Fstyle>\",\"storeOutMessages\":true,\"passthru\":true,\"resendOnRefresh\":true,\"templateScope\":\"local\",\"className\":\"\",\"x\":800,\"y\":240,\"wires\":[[]]},{\"id\":\"05fdb0d422eb75af\",\"type\":\"ui-group\",\"name\":\"KPIs\",\"page\":\"89515a0645eddeee\",\"width\":\"12\",\"height\":1,\"order\":1,\"showTitle\":false,\"className\":\"\",\"visible\":\"true\",\"disabled\":\"false\",\"groupType\":\"default\"},{\"id\":\"89515a0645eddeee\",\"type\":\"ui-page\",\"name\":\"Home\",\"ui\":\"6481b1c613ec9a93\",\"path\":\"\u002Fhome\",\"icon\":\"home\",\"layout\":\"grid\",\"theme\":\"faac104f34962f3e\",\"breakpoints\":[{\"name\":\"Default\",\"px\":\"0\",\"cols\":\"3\"},{\"name\":\"Tablet\",\"px\":\"576\",\"cols\":\"6\"},{\"name\":\"Small Desktop\",\"px\":\"768\",\"cols\":\"9\"},{\"name\":\"Desktop\",\"px\":\"1024\",\"cols\":\"12\"}],\"order\":1,\"className\":\"\",\"visible\":\"true\",\"disabled\":\"false\"},{\"id\":\"6481b1c613ec9a93\",\"type\":\"ui-base\",\"name\":\"My Dashboard\",\"path\":\"\u002Fdashboard\",\"appIcon\":\"\",\"includeClientData\":true,\"acceptsClientConfig\":[\"ui-notification\",\"ui-control\",\"ui-number-input\",\"ui-file-input\",\"ui-button\",\"ui-button-group\",\"ui-dropdown\",\"ui-radio-group\",\"ui-slider\",\"ui-switch\",\"ui-text\",\"ui-table\",\"ui-gauge\",\"ui-chart\",\"ui-template\",\"ui-markdown\",\"ui-progress\",\"ui-webcam\"],\"showPathInSidebar\":false,\"headerContent\":\"page\",\"navigationStyle\":\"default\",\"titleBarStyle\":\"default\",\"showReconnectNotification\":true,\"notificationDisplayTime\":1,\"showDisconnectNotification\":true,\"allowInstall\":false},{\"id\":\"faac104f34962f3e\",\"type\":\"ui-theme\",\"name\":\"Default Theme\",\"colors\":{\"surface\":\"#ffffff\",\"primary\":\"#1e4e8c\",\"bgPage\":\"#eef1f5\",\"groupBg\":\"#ffffff\",\"groupOutline\":\"#d3dae3\"},\"sizes\":{\"density\":\"default\",\"pagePadding\":\"12px\",\"groupGap\":\"12px\",\"groupBorderRadius\":\"4px\",\"widgetGap\":\"12px\"}},{\"id\":\"057822a3ade579c5\",\"type\":\"global-config\",\"env\":[],\"modules\":{\"@flowfuse\u002Fnode-red-dashboard\":\"1.30.2\"}}]\n{% endraw %}\n",[56,6199,6200,6208,9625],{"__ignoreMap":245},[249,6201,6202,6204,6206],{"class":251,"line":252},[249,6203,256],{"class":255},[249,6205,260],{"class":259},[249,6207,263],{"class":255},[249,6209,6210,6212,6214,6216,6218,6220,6222,6225,6227,6229,6231,6233,6235,6237,6239,6241,6243,6245,6247,6249,6251,6253,6255,6257,6259,6261,6263,6265,6267,6269,6271,6274,6276,6278,6280,6282,6284,6286,6288,6291,6293,6295,6297,6299,6301,6303,6305,6307,6309,6311,6313,6315,6317,6319,6321,6323,6325,6327,6329,6331,6333,6335,6337,6339,6341,6343,6345,6347,6349,6351,6353,6355,6357,6359,6361,6363,6365,6367,6369,6371,6373,6375,6377,6379,6381,6383,6385,6387,6389,6391,6393,6395,6397,6400,6402,6405,6407,6409,6411,6414,6416,6419,6421,6424,6426,6429,6431,6433,6435,6438,6440,6443,6445,6447,6449,6452,6454,6457,6459,6461,6463,6466,6468,6470,6472,6475,6477,6480,6482,6484,6486,6489,6491,6494,6496,6499,6501,6503,6505,6508,6510,6512,6514,6517,6519,6522,6524,6527,6529,6531,6533,6535,6537,6539,6541,6544,6546,6549,6551,6554,6556,6558,6560,6563,6565,6567,6569,6572,6574,6576,6578,6580,6582,6585,6587,6590,6592,6595,6597,6599,6601,6604,6606,6608,6610,6613,6615,6618,6620,6623,6625,6628,6630,6633,6635,6637,6639,6642,6644,6646,6648,6650,6652,6654,6656,6658,6660,6662,6664,6666,6668,6670,6672,6674,6676,6678,6680,6683,6685,6688,6690,6692,6694,6696,6698,6701,6703,6706,6708,6711,6713,6716,6718,6721,6723,6726,6728,6731,6733,6735,6737,6739,6741,6743,6745,6747,6749,6751,6753,6756,6758,6760,6762,6765,6767,6770,6772,6775,6777,6779,6781,6784,6786,6788,6790,6793,6795,6797,6799,6801,6803,6806,6808,6810,6812,6814,6816,6818,6820,6822,6824,6827,6829,6832,6834,6836,6838,6841,6843,6846,6848,6851,6853,6855,6857,6860,6862,6864,6866,6868,6870,6873,6875,6877,6879,6882,6884,6887,6889,6891,6893,6895,6897,6899,6901,6903,6905,6907,6909,6911,6913,6916,6918,6921,6923,6925,6927,6930,6932,6935,6937,6939,6941,6944,6946,6948,6950,6953,6955,6957,6959,6962,6964,6967,6969,6971,6973,6975,6977,6979,6981,6983,6985,6987,6989,6991,6993,6995,6997,6999,7001,7004,7006,7008,7010,7012,7014,7016,7018,7020,7022,7024,7026,7028,7030,7032,7034,7037,7039,7041,7043,7046,7048,7051,7053,7055,7057,7059,7061,7064,7066,7068,7070,7072,7074,7076,7078,7080,7082,7084,7086,7088,7090,7092,7094,7096,7098,7100,7102,7104,7106,7109,7111,7113,7115,7117,7119,7121,7123,7125,7127,7129,7131,7133,7135,7137,7139,7142,7144,7146,7148,7151,7153,7156,7158,7160,7162,7164,7166,7169,7171,7173,7175,7177,7179,7181,7183,7185,7187,7189,7191,7193,7195,7197,7199,7201,7203,7205,7207,7209,7211,7214,7216,7218,7220,7222,7224,7226,7228,7230,7232,7234,7236,7238,7240,7242,7244,7247,7249,7251,7253,7256,7258,7261,7263,7265,7267,7269,7271,7274,7276,7278,7280,7282,7284,7286,7288,7290,7292,7294,7296,7298,7300,7302,7304,7306,7308,7310,7312,7314,7316,7319,7321,7323,7325,7327,7329,7331,7333,7335,7337,7339,7341,7343,7345,7347,7349,7352,7354,7356,7358,7361,7363,7366,7368,7370,7372,7374,7376,7379,7381,7383,7385,7387,7389,7391,7393,7395,7397,7399,7401,7403,7405,7407,7409,7411,7413,7415,7417,7419,7421,7423,7425,7427,7429,7431,7433,7435,7437,7439,7441,7443,7445,7447,7449,7451,7453,7456,7458,7460,7462,7464,7466,7469,7471,7473,7475,7477,7479,7482,7484,7486,7488,7490,7492,7495,7497,7500,7502,7504,7506,7509,7511,7513,7515,7517,7519,7521,7523,7525,7527,7529,7531,7534,7536,7538,7540,7542,7544,7546,7548,7550,7552,7554,7556,7559,7561,7563,7565,7567,7569,7572,7574,7576,7578,7581,7583,7586,7588,7590,7592,7594,7596,7599,7601,7604,7606,7609,7611,7613,7615,7618,7620,7623,7625,7627,7629,7631,7633,7635,7637,7639,7641,7643,7645,7647,7649,7651,7653,7655,7657,7659,7661,7663,7665,7667,7669,7671,7673,7675,7677,7679,7681,7684,7686,7688,7690,7692,7694,7696,7698,7701,7703,7705,7707,7709,7711,7713,7715,7717,7719,7721,7723,7725,7727,7729,7731,7733,7735,7737,7739,7741,7743,7745,7747,7749,7751,7754,7756,7758,7760,7762,7764,7767,7769,7771,7773,7775,7777,7779,7781,7784,7786,7788,7790,7792,7794,7796,7798,7800,7802,7804,7806,7809,7811,7813,7815,7817,7819,7822,7824,7827,7829,7832,7834,7837,7839,7842,7844,7847,7849,7852,7854,7857,7859,7862,7864,7867,7869,7872,7874,7877,7879,7882,7884,7887,7889,7892,7894,7897,7899,7902,7904,7907,7909,7912,7914,7917,7919,7922,7924,7927,7929,7932,7934,7937,7939,7942,7944,7947,7949,7952,7954,7957,7959,7962,7964,7967,7969,7972,7974,7976,7978,7980,7982,7985,7987,7990,7992,7995,7997,8000,8002,8005,8007,8010,8012,8015,8017,8019,8021,8023,8025,8028,8030,8033,8035,8038,8040,8042,8044,8047,8049,8052,8054,8056,8058,8061,8063,8066,8068,8071,8073,8076,8078,8081,8083,8086,8088,8091,8093,8096,8098,8101,8103,8106,8108,8111,8113,8116,8118,8121,8123,8126,8128,8131,8133,8136,8138,8141,8143,8146,8148,8150,8152,8155,8157,8160,8162,8165,8167,8170,8172,8175,8177,8180,8182,8184,8186,8188,8190,8192,8194,8196,8198,8200,8202,8205,8207,8210,8212,8215,8217,8220,8222,8225,8227,8230,8232,8235,8237,8240,8242,8245,8247,8250,8252,8255,8257,8260,8262,8265,8267,8270,8272,8275,8277,8280,8282,8284,8286,8289,8291,8294,8296,8298,8300,8303,8305,8308,8310,8312,8314,8317,8319,8322,8324,8326,8328,8331,8333,8336,8338,8340,8342,8345,8347,8350,8352,8354,8356,8358,8360,8362,8364,8366,8368,8370,8372,8374,8376,8378,8380,8382,8384,8386,8388,8390,8392,8394,8396,8399,8401,8403,8405,8407,8409,8411,8413,8415,8417,8419,8421,8423,8426,8428,8430,8432,8434,8436,8439,8441,8443,8445,8447,8450,8452,8454,8456,8458,8460,8462,8464,8466,8468,8470,8472,8474,8476,8478,8480,8482,8484,8486,8488,8490,8492,8494,8496,8498,8500,8502,8504,8506,8508,8510,8512,8514,8516,8518,8520,8522,8524,8526,8528,8530,8532,8534,8536,8538,8540,8542,8544,8546,8548,8550,8552,8554,8556,8559,8561,8563,8565,8567,8569,8571,8573,8575,8577,8579,8581,8583,8585,8587,8589,8591,8593,8595,8597,8599,8601,8603,8605,8607,8609,8612,8614,8616,8618,8620,8622,8624,8626,8628,8630,8632,8634,8636,8638,8640,8642,8644,8646,8648,8650,8652,8654,8656,8658,8660,8662,8664,8666,8668,8670,8672,8674,8676,8678,8680,8682,8684,8686,8688,8690,8692,8694,8696,8698,8700,8702,8704,8706,8708,8710,8712,8714,8716,8718,8720,8722,8724,8726,8728,8730,8732,8734,8736,8738,8740,8742,8744,8746,8748,8750,8752,8754,8756,8758,8760,8762,8764,8766,8768,8770,8772,8774,8776,8778,8780,8782,8784,8786,8788,8790,8792,8794,8796,8798,8800,8802,8804,8806,8808,8810,8812,8814,8816,8818,8820,8822,8824,8826,8828,8830,8832,8834,8836,8838,8840,8842,8844,8846,8848,8850,8852,8854,8856,8858,8860,8862,8864,8866,8868,8870,8872,8874,8876,8878,8880,8882,8884,8886,8888,8890,8892,8894,8896,8898,8900,8902,8904,8906,8908,8910,8912,8914,8916,8918,8920,8922,8924,8926,8928,8930,8932,8934,8936,8938,8940,8942,8944,8946,8948,8950,8952,8954,8956,8958,8960,8962,8964,8966,8968,8970,8972,8974,8976,8978,8980,8982,8984,8986,8988,8990,8992,8994,8996,8998,9000,9002,9004,9006,9008,9010,9012,9014,9016,9018,9020,9022,9024,9026,9028,9030,9032,9034,9036,9038,9040,9042,9044,9046,9048,9050,9052,9054,9056,9058,9060,9062,9064,9066,9068,9070,9072,9074,9076,9078,9080,9082,9084,9086,9088,9090,9092,9094,9096,9098,9100,9102,9104,9106,9108,9110,9112,9114,9116,9118,9120,9122,9124,9126,9128,9130,9132,9134,9136,9138,9140,9142,9144,9146,9148,9150,9152,9154,9156,9158,9160,9162,9164,9166,9168,9170,9172,9174,9176,9178,9180,9182,9184,9186,9188,9190,9192,9194,9196,9198,9200,9202,9204,9206,9208,9210,9212,9214,9216,9218,9220,9222,9224,9226,9228,9230,9232,9234,9236,9238,9240,9242,9244,9246,9248,9250,9252,9254,9256,9258,9260,9262,9264,9266,9268,9270,9272,9274,9276,9278,9280,9282,9284,9286,9288,9290,9292,9294,9296,9298,9300,9302,9304,9306,9308,9310,9312,9314,9316,9318,9320,9322,9324,9326,9328,9330,9332,9334,9336,9338,9340,9342,9344,9346,9348,9350,9352,9354,9356,9358,9360,9362,9364,9366,9368,9370,9372,9374,9376,9378,9380,9382,9384,9386,9388,9390,9392,9394,9396,9398,9400,9402,9404,9406,9408,9410,9412,9414,9416,9418,9420,9422,9424,9426,9428,9430,9432,9434,9436,9438,9440,9442,9444,9446,9448,9450,9452,9454,9456,9458,9460,9462,9464,9466,9468,9470,9472,9474,9476,9478,9480,9482,9484,9486,9488,9490,9492,9494,9496,9498,9500,9502,9504,9506,9508,9510,9512,9514,9516,9518,9520,9522,9524,9526,9528,9530,9532,9534,9536,9538,9540,9542,9544,9546,9548,9550,9552,9554,9556,9558,9560,9562,9564,9566,9568,9570,9573,9575,9577,9579,9581,9583,9585,9587,9589,9591,9593,9595,9597,9599,9601,9603,9605,9607,9609,9611,9613,9615,9617,9619,9621,9623],{"class":251,"line":266},[249,6211,269],{"class":255},[249,6213,272],{"class":255},[249,6215,276],{"class":275},[249,6217,272],{"class":255},[249,6219,281],{"class":255},[249,6221,272],{"class":255},[249,6223,6224],{"class":286},"1e9b85cd8f2fdc3c",[249,6226,272],{"class":255},[249,6228,292],{"class":255},[249,6230,272],{"class":255},[249,6232,297],{"class":275},[249,6234,272],{"class":255},[249,6236,281],{"class":255},[249,6238,272],{"class":255},[249,6240,103],{"class":286},[249,6242,272],{"class":255},[249,6244,292],{"class":255},[249,6246,272],{"class":255},[249,6248,315],{"class":275},[249,6250,272],{"class":255},[249,6252,281],{"class":255},[249,6254,272],{"class":255},[249,6256,3753],{"class":286},[249,6258,272],{"class":255},[249,6260,292],{"class":255},[249,6262,272],{"class":255},[249,6264,671],{"class":275},[249,6266,272],{"class":255},[249,6268,281],{"class":255},[249,6270,272],{"class":255},[249,6272,6273],{"class":286},"3ed935d02285b78b",[249,6275,272],{"class":255},[249,6277,292],{"class":255},[249,6279,272],{"class":255},[249,6281,306],{"class":275},[249,6283,272],{"class":255},[249,6285,281],{"class":255},[249,6287,272],{"class":255},[249,6289,6290],{"class":286},"05fdb0d422eb75af",[249,6292,272],{"class":255},[249,6294,292],{"class":255},[249,6296,272],{"class":255},[249,6298,3553],{"class":275},[249,6300,272],{"class":255},[249,6302,281],{"class":255},[249,6304,786],{"class":255},[249,6306,292],{"class":255},[249,6308,272],{"class":255},[249,6310,3808],{"class":275},[249,6312,272],{"class":255},[249,6314,281],{"class":255},[249,6316,786],{"class":255},[249,6318,292],{"class":255},[249,6320,272],{"class":255},[249,6322,688],{"class":275},[249,6324,272],{"class":255},[249,6326,281],{"class":255},[249,6328,272],{"class":255},[249,6330,6183],{"class":286},[249,6332,272],{"class":255},[249,6334,292],{"class":255},[249,6336,272],{"class":255},[249,6338,3837],{"class":275},[249,6340,272],{"class":255},[249,6342,281],{"class":255},[249,6344,371],{"class":571},[249,6346,292],{"class":255},[249,6348,272],{"class":255},[249,6350,3850],{"class":275},[249,6352,272],{"class":255},[249,6354,281],{"class":255},[249,6356,2149],{"class":571},[249,6358,292],{"class":255},[249,6360,272],{"class":255},[249,6362,3863],{"class":275},[249,6364,272],{"class":255},[249,6366,281],{"class":255},[249,6368,2149],{"class":571},[249,6370,292],{"class":255},[249,6372,272],{"class":255},[249,6374,3876],{"class":275},[249,6376,272],{"class":255},[249,6378,281],{"class":255},[249,6380,786],{"class":255},[249,6382,292],{"class":255},[249,6384,272],{"class":255},[249,6386,3889],{"class":275},[249,6388,272],{"class":255},[249,6390,281],{"class":255},[249,6392,272],{"class":255},[249,6394,3898],{"class":286},[249,6396,940],{"class":259},[249,6398,6399],{"class":286},"    \u003Cv-container fluid class=",[249,6401,3906],{"class":259},[249,6403,6404],{"class":286},"pa-2",[249,6406,3906],{"class":259},[249,6408,3924],{"class":286},[249,6410,1667],{"class":259},[249,6412,6413],{"class":286},"        \u003C!-- Header -->",[249,6415,940],{"class":259},[249,6417,6418],{"class":286},"        \u003Cv-card class=",[249,6420,3906],{"class":259},[249,6422,6423],{"class":286},"pa-4 mb-3",[249,6425,3906],{"class":259},[249,6427,6428],{"class":286}," elevation=",[249,6430,3906],{"class":259},[249,6432,371],{"class":286},[249,6434,3906],{"class":259},[249,6436,6437],{"class":286}," rounded=",[249,6439,3906],{"class":259},[249,6441,6442],{"class":286},"lg",[249,6444,3906],{"class":259},[249,6446,3924],{"class":286},[249,6448,940],{"class":259},[249,6450,6451],{"class":286},"            \u003Cv-row align=",[249,6453,3906],{"class":259},[249,6455,6456],{"class":286},"center",[249,6458,3906],{"class":259},[249,6460,3924],{"class":286},[249,6462,940],{"class":259},[249,6464,6465],{"class":286},"                \u003Cv-col cols=",[249,6467,3906],{"class":259},[249,6469,4928],{"class":286},[249,6471,3906],{"class":259},[249,6473,6474],{"class":286}," md=",[249,6476,3906],{"class":259},[249,6478,6479],{"class":286},"7",[249,6481,3906],{"class":259},[249,6483,3924],{"class":286},[249,6485,940],{"class":259},[249,6487,6488],{"class":286},"                    \u003Cdiv class=",[249,6490,3906],{"class":259},[249,6492,6493],{"class":286},"text-h6 font-weight-bold",[249,6495,3906],{"class":259},[249,6497,6498],{"class":286},">ACME Automotive Plant\u003C\u002Fdiv>",[249,6500,940],{"class":259},[249,6502,6488],{"class":286},[249,6504,3906],{"class":259},[249,6506,6507],{"class":286},"text-body-2 text-medium-emphasis",[249,6509,3906],{"class":259},[249,6511,3924],{"class":286},[249,6513,940],{"class":259},[249,6515,6516],{"class":286},"                        Calibration &amp; Measurement Status Dashboard",[249,6518,940],{"class":259},[249,6520,6521],{"class":286},"                    \u003C\u002Fdiv>",[249,6523,940],{"class":259},[249,6525,6526],{"class":286},"                \u003C\u002Fv-col>",[249,6528,1667],{"class":259},[249,6530,6465],{"class":286},[249,6532,3906],{"class":259},[249,6534,4928],{"class":286},[249,6536,3906],{"class":259},[249,6538,6474],{"class":286},[249,6540,3906],{"class":259},[249,6542,6543],{"class":286},"5",[249,6545,3906],{"class":259},[249,6547,6548],{"class":286}," class=",[249,6550,3906],{"class":259},[249,6552,6553],{"class":286},"text-md-right",[249,6555,3906],{"class":259},[249,6557,3924],{"class":286},[249,6559,940],{"class":259},[249,6561,6562],{"class":286},"                    \u003Cv-chip v-if=",[249,6564,3906],{"class":259},[249,6566,5766],{"class":286},[249,6568,3906],{"class":259},[249,6570,6571],{"class":286}," color=",[249,6573,3906],{"class":259},[249,6575,5430],{"class":286},[249,6577,3906],{"class":259},[249,6579,3986],{"class":286},[249,6581,3906],{"class":259},[249,6583,6584],{"class":286},"tonal",[249,6586,3906],{"class":259},[249,6588,6589],{"class":286}," size=",[249,6591,3906],{"class":259},[249,6593,6594],{"class":286},"small",[249,6596,3906],{"class":259},[249,6598,6548],{"class":286},[249,6600,3906],{"class":259},[249,6602,6603],{"class":286},"mr-2",[249,6605,3906],{"class":259},[249,6607,3924],{"class":286},[249,6609,940],{"class":259},[249,6611,6612],{"class":286},"                        \u003Cv-icon start size=",[249,6614,3906],{"class":259},[249,6616,6617],{"class":286},"16",[249,6619,3906],{"class":259},[249,6621,6622],{"class":286},">mdi-filter-variant\u003C\u002Fv-icon>",[249,6624,940],{"class":259},[249,6626,6627],{"class":286},"                        {{ filters.department }} &middot; {{ filters.window }}",[249,6629,940],{"class":259},[249,6631,6632],{"class":286},"                    \u003C\u002Fv-chip>",[249,6634,940],{"class":259},[249,6636,6562],{"class":286},[249,6638,3906],{"class":259},[249,6640,6641],{"class":286},"updatedAt",[249,6643,3906],{"class":259},[249,6645,6571],{"class":286},[249,6647,3906],{"class":259},[249,6649,5430],{"class":286},[249,6651,3906],{"class":259},[249,6653,3986],{"class":286},[249,6655,3906],{"class":259},[249,6657,6584],{"class":286},[249,6659,3906],{"class":259},[249,6661,6589],{"class":286},[249,6663,3906],{"class":259},[249,6665,6594],{"class":286},[249,6667,3906],{"class":259},[249,6669,3924],{"class":286},[249,6671,940],{"class":259},[249,6673,6612],{"class":286},[249,6675,3906],{"class":259},[249,6677,6617],{"class":286},[249,6679,3906],{"class":259},[249,6681,6682],{"class":286},">mdi-refresh\u003C\u002Fv-icon>",[249,6684,940],{"class":259},[249,6686,6687],{"class":286},"                        Updated {{ updatedAtText }}",[249,6689,940],{"class":259},[249,6691,6632],{"class":286},[249,6693,940],{"class":259},[249,6695,6526],{"class":286},[249,6697,940],{"class":259},[249,6699,6700],{"class":286},"            \u003C\u002Fv-row>",[249,6702,940],{"class":259},[249,6704,6705],{"class":286},"        \u003C\u002Fv-card>",[249,6707,1667],{"class":259},[249,6709,6710],{"class":286},"        \u003C!-- Loading state until the first query result arrives -->",[249,6712,940],{"class":259},[249,6714,6715],{"class":286},"        \u003Cv-alert v-if=",[249,6717,3906],{"class":259},[249,6719,6720],{"class":286},"!loaded",[249,6722,3906],{"class":259},[249,6724,6725],{"class":286}," type=",[249,6727,3906],{"class":259},[249,6729,6730],{"class":286},"info",[249,6732,3906],{"class":259},[249,6734,3986],{"class":286},[249,6736,3906],{"class":259},[249,6738,6584],{"class":286},[249,6740,3906],{"class":259},[249,6742,3976],{"class":286},[249,6744,3906],{"class":259},[249,6746,3981],{"class":286},[249,6748,3906],{"class":259},[249,6750,6548],{"class":286},[249,6752,3906],{"class":259},[249,6754,6755],{"class":286},"mb-3",[249,6757,3906],{"class":259},[249,6759,3924],{"class":286},[249,6761,940],{"class":259},[249,6763,6764],{"class":286},"            Waiting for calibration data...",[249,6766,940],{"class":259},[249,6768,6769],{"class":286},"        \u003C\u002Fv-alert>",[249,6771,1667],{"class":259},[249,6773,6774],{"class":286},"        \u003C!-- Data quality: the stored status column has drifted from the dates -->",[249,6776,940],{"class":259},[249,6778,6715],{"class":286},[249,6780,3906],{"class":259},[249,6782,6783],{"class":286},"kpi.stale_status_count > 0",[249,6785,3906],{"class":259},[249,6787,6725],{"class":286},[249,6789,3906],{"class":259},[249,6791,6792],{"class":286},"warning",[249,6794,3906],{"class":259},[249,6796,3986],{"class":286},[249,6798,3906],{"class":259},[249,6800,6584],{"class":286},[249,6802,3994],{"class":259},[249,6804,6805],{"class":286},"            density=",[249,6807,3906],{"class":259},[249,6809,3981],{"class":286},[249,6811,3906],{"class":259},[249,6813,6548],{"class":286},[249,6815,3906],{"class":259},[249,6817,6755],{"class":286},[249,6819,3906],{"class":259},[249,6821,3924],{"class":286},[249,6823,940],{"class":259},[249,6825,6826],{"class":286},"            {{ kpi.stale_status_count }} record(s) have a status field that disagrees with",[249,6828,940],{"class":259},[249,6830,6831],{"class":286},"            their due date. Every count here is derived from the date.",[249,6833,940],{"class":259},[249,6835,6769],{"class":286},[249,6837,1667],{"class":259},[249,6839,6840],{"class":286},"        \u003C!-- KPI Cards -->",[249,6842,940],{"class":259},[249,6844,6845],{"class":286},"        \u003Cv-row dense>",[249,6847,1667],{"class":259},[249,6849,6850],{"class":286},"            \u003Cv-col cols=",[249,6852,3906],{"class":259},[249,6854,4928],{"class":286},[249,6856,3906],{"class":259},[249,6858,6859],{"class":286}," sm=",[249,6861,3906],{"class":259},[249,6863,4826],{"class":286},[249,6865,3906],{"class":259},[249,6867,6474],{"class":286},[249,6869,3906],{"class":259},[249,6871,6872],{"class":286},"2",[249,6874,3906],{"class":259},[249,6876,3924],{"class":286},[249,6878,940],{"class":259},[249,6880,6881],{"class":286},"                \u003Cv-card class=",[249,6883,3906],{"class":259},[249,6885,6886],{"class":286},"pa-4 h-100 border-neutral",[249,6888,3906],{"class":259},[249,6890,6428],{"class":286},[249,6892,3906],{"class":259},[249,6894,371],{"class":286},[249,6896,3906],{"class":259},[249,6898,6437],{"class":286},[249,6900,3906],{"class":259},[249,6902,6442],{"class":286},[249,6904,3906],{"class":259},[249,6906,3924],{"class":286},[249,6908,940],{"class":259},[249,6910,6488],{"class":286},[249,6912,3906],{"class":259},[249,6914,6915],{"class":286},"text-caption text-medium-emphasis",[249,6917,3906],{"class":259},[249,6919,6920],{"class":286},">TOTAL EQUIPMENT\u003C\u002Fdiv>",[249,6922,940],{"class":259},[249,6924,6488],{"class":286},[249,6926,3906],{"class":259},[249,6928,6929],{"class":286},"text-h4 font-weight-bold mt-2",[249,6931,3906],{"class":259},[249,6933,6934],{"class":286},">{{ show(kpi.total_assets) }}\u003C\u002Fdiv>",[249,6936,940],{"class":259},[249,6938,6488],{"class":286},[249,6940,3906],{"class":259},[249,6942,6943],{"class":286},"text-caption text-medium-emphasis mt-2",[249,6945,3906],{"class":259},[249,6947,3924],{"class":286},[249,6949,940],{"class":259},[249,6951,6952],{"class":286},"                        {{ filters.department === 'All' ? 'All departments' : filters.department }}",[249,6954,940],{"class":259},[249,6956,6521],{"class":286},[249,6958,940],{"class":259},[249,6960,6961],{"class":286},"                \u003C\u002Fv-card>",[249,6963,940],{"class":259},[249,6965,6966],{"class":286},"            \u003C\u002Fv-col>",[249,6968,1667],{"class":259},[249,6970,6850],{"class":286},[249,6972,3906],{"class":259},[249,6974,4928],{"class":286},[249,6976,3906],{"class":259},[249,6978,6859],{"class":286},[249,6980,3906],{"class":259},[249,6982,4826],{"class":286},[249,6984,3906],{"class":259},[249,6986,6474],{"class":286},[249,6988,3906],{"class":259},[249,6990,6872],{"class":286},[249,6992,3906],{"class":259},[249,6994,3924],{"class":286},[249,6996,940],{"class":259},[249,6998,6881],{"class":286},[249,7000,3906],{"class":259},[249,7002,7003],{"class":286},"pa-4 h-100 border-success",[249,7005,3906],{"class":259},[249,7007,6428],{"class":286},[249,7009,3906],{"class":259},[249,7011,371],{"class":286},[249,7013,3906],{"class":259},[249,7015,6437],{"class":286},[249,7017,3906],{"class":259},[249,7019,6442],{"class":286},[249,7021,3906],{"class":259},[249,7023,3924],{"class":286},[249,7025,940],{"class":259},[249,7027,6488],{"class":286},[249,7029,3906],{"class":259},[249,7031,6915],{"class":286},[249,7033,3906],{"class":259},[249,7035,7036],{"class":286},">VALID\u003C\u002Fdiv>",[249,7038,940],{"class":259},[249,7040,6488],{"class":286},[249,7042,3906],{"class":259},[249,7044,7045],{"class":286},"text-h4 font-weight-bold mt-2 text-success",[249,7047,3906],{"class":259},[249,7049,7050],{"class":286},">{{ show(kpi.valid_assets) }}\u003C\u002Fdiv>",[249,7052,940],{"class":259},[249,7054,6488],{"class":286},[249,7056,3906],{"class":259},[249,7058,6943],{"class":286},[249,7060,3906],{"class":259},[249,7062,7063],{"class":286},">Due beyond 30 days\u003C\u002Fdiv>",[249,7065,940],{"class":259},[249,7067,6961],{"class":286},[249,7069,940],{"class":259},[249,7071,6966],{"class":286},[249,7073,1667],{"class":259},[249,7075,6850],{"class":286},[249,7077,3906],{"class":259},[249,7079,4928],{"class":286},[249,7081,3906],{"class":259},[249,7083,6859],{"class":286},[249,7085,3906],{"class":259},[249,7087,4826],{"class":286},[249,7089,3906],{"class":259},[249,7091,6474],{"class":286},[249,7093,3906],{"class":259},[249,7095,6872],{"class":286},[249,7097,3906],{"class":259},[249,7099,3924],{"class":286},[249,7101,940],{"class":259},[249,7103,6881],{"class":286},[249,7105,3906],{"class":259},[249,7107,7108],{"class":286},"pa-4 h-100 border-warning",[249,7110,3906],{"class":259},[249,7112,6428],{"class":286},[249,7114,3906],{"class":259},[249,7116,371],{"class":286},[249,7118,3906],{"class":259},[249,7120,6437],{"class":286},[249,7122,3906],{"class":259},[249,7124,6442],{"class":286},[249,7126,3906],{"class":259},[249,7128,3924],{"class":286},[249,7130,940],{"class":259},[249,7132,6488],{"class":286},[249,7134,3906],{"class":259},[249,7136,6915],{"class":286},[249,7138,3906],{"class":259},[249,7140,7141],{"class":286},">DUE SOON\u003C\u002Fdiv>",[249,7143,940],{"class":259},[249,7145,6488],{"class":286},[249,7147,3906],{"class":259},[249,7149,7150],{"class":286},"text-h4 font-weight-bold mt-2 text-warning",[249,7152,3906],{"class":259},[249,7154,7155],{"class":286},">{{ show(kpi.due_soon_assets) }}\u003C\u002Fdiv>",[249,7157,940],{"class":259},[249,7159,6488],{"class":286},[249,7161,3906],{"class":259},[249,7163,6943],{"class":286},[249,7165,3906],{"class":259},[249,7167,7168],{"class":286},">Next 30 days\u003C\u002Fdiv>",[249,7170,940],{"class":259},[249,7172,6961],{"class":286},[249,7174,940],{"class":259},[249,7176,6966],{"class":286},[249,7178,1667],{"class":259},[249,7180,6850],{"class":286},[249,7182,3906],{"class":259},[249,7184,4928],{"class":286},[249,7186,3906],{"class":259},[249,7188,6859],{"class":286},[249,7190,3906],{"class":259},[249,7192,4826],{"class":286},[249,7194,3906],{"class":259},[249,7196,6474],{"class":286},[249,7198,3906],{"class":259},[249,7200,6872],{"class":286},[249,7202,3906],{"class":259},[249,7204,3924],{"class":286},[249,7206,940],{"class":259},[249,7208,6881],{"class":286},[249,7210,3906],{"class":259},[249,7212,7213],{"class":286},"pa-4 h-100 border-danger",[249,7215,3906],{"class":259},[249,7217,6428],{"class":286},[249,7219,3906],{"class":259},[249,7221,371],{"class":286},[249,7223,3906],{"class":259},[249,7225,6437],{"class":286},[249,7227,3906],{"class":259},[249,7229,6442],{"class":286},[249,7231,3906],{"class":259},[249,7233,3924],{"class":286},[249,7235,940],{"class":259},[249,7237,6488],{"class":286},[249,7239,3906],{"class":259},[249,7241,6915],{"class":286},[249,7243,3906],{"class":259},[249,7245,7246],{"class":286},">OVERDUE\u003C\u002Fdiv>",[249,7248,940],{"class":259},[249,7250,6488],{"class":286},[249,7252,3906],{"class":259},[249,7254,7255],{"class":286},"text-h4 font-weight-bold mt-2 text-error",[249,7257,3906],{"class":259},[249,7259,7260],{"class":286},">{{ show(kpi.overdue_assets) }}\u003C\u002Fdiv>",[249,7262,940],{"class":259},[249,7264,6488],{"class":286},[249,7266,3906],{"class":259},[249,7268,6943],{"class":286},[249,7270,3906],{"class":259},[249,7272,7273],{"class":286},">Immediate action\u003C\u002Fdiv>",[249,7275,940],{"class":259},[249,7277,6961],{"class":286},[249,7279,940],{"class":259},[249,7281,6966],{"class":286},[249,7283,1667],{"class":259},[249,7285,6850],{"class":286},[249,7287,3906],{"class":259},[249,7289,4928],{"class":286},[249,7291,3906],{"class":259},[249,7293,6859],{"class":286},[249,7295,3906],{"class":259},[249,7297,4826],{"class":286},[249,7299,3906],{"class":259},[249,7301,6474],{"class":286},[249,7303,3906],{"class":259},[249,7305,6872],{"class":286},[249,7307,3906],{"class":259},[249,7309,3924],{"class":286},[249,7311,940],{"class":259},[249,7313,6881],{"class":286},[249,7315,3906],{"class":259},[249,7317,7318],{"class":286},"pa-4 h-100 border-info",[249,7320,3906],{"class":259},[249,7322,6428],{"class":286},[249,7324,3906],{"class":259},[249,7326,371],{"class":286},[249,7328,3906],{"class":259},[249,7330,6437],{"class":286},[249,7332,3906],{"class":259},[249,7334,6442],{"class":286},[249,7336,3906],{"class":259},[249,7338,3924],{"class":286},[249,7340,940],{"class":259},[249,7342,6488],{"class":286},[249,7344,3906],{"class":259},[249,7346,6915],{"class":286},[249,7348,3906],{"class":259},[249,7350,7351],{"class":286},">UPCOMING\u003C\u002Fdiv>",[249,7353,940],{"class":259},[249,7355,6488],{"class":286},[249,7357,3906],{"class":259},[249,7359,7360],{"class":286},"text-h4 font-weight-bold mt-2 text-info",[249,7362,3906],{"class":259},[249,7364,7365],{"class":286},">{{ show(kpi.due_in_window) }}\u003C\u002Fdiv>",[249,7367,940],{"class":259},[249,7369,6488],{"class":286},[249,7371,3906],{"class":259},[249,7373,6943],{"class":286},[249,7375,3906],{"class":259},[249,7377,7378],{"class":286},">{{ filters.window }}\u003C\u002Fdiv>",[249,7380,940],{"class":259},[249,7382,6961],{"class":286},[249,7384,940],{"class":259},[249,7386,6966],{"class":286},[249,7388,1667],{"class":259},[249,7390,6850],{"class":286},[249,7392,3906],{"class":259},[249,7394,4928],{"class":286},[249,7396,3906],{"class":259},[249,7398,6859],{"class":286},[249,7400,3906],{"class":259},[249,7402,4826],{"class":286},[249,7404,3906],{"class":259},[249,7406,6474],{"class":286},[249,7408,3906],{"class":259},[249,7410,6872],{"class":286},[249,7412,3906],{"class":259},[249,7414,3924],{"class":286},[249,7416,940],{"class":259},[249,7418,6881],{"class":286},[249,7420,3906],{"class":259},[249,7422,6886],{"class":286},[249,7424,3906],{"class":259},[249,7426,6428],{"class":286},[249,7428,3906],{"class":259},[249,7430,371],{"class":286},[249,7432,3906],{"class":259},[249,7434,6437],{"class":286},[249,7436,3906],{"class":259},[249,7438,6442],{"class":286},[249,7440,3906],{"class":259},[249,7442,3924],{"class":286},[249,7444,940],{"class":259},[249,7446,6488],{"class":286},[249,7448,3906],{"class":259},[249,7450,6915],{"class":286},[249,7452,3906],{"class":259},[249,7454,7455],{"class":286},">COMPLIANCE\u003C\u002Fdiv>",[249,7457,940],{"class":259},[249,7459,6488],{"class":286},[249,7461,3906],{"class":259},[249,7463,6929],{"class":286},[249,7465,3906],{"class":259},[249,7467,7468],{"class":286},">{{ show(kpi.valid_percentage) }}%\u003C\u002Fdiv>",[249,7470,940],{"class":259},[249,7472,6488],{"class":286},[249,7474,3906],{"class":259},[249,7476,6943],{"class":286},[249,7478,3906],{"class":259},[249,7480,7481],{"class":286},">Plant health\u003C\u002Fdiv>",[249,7483,940],{"class":259},[249,7485,6961],{"class":286},[249,7487,940],{"class":259},[249,7489,6966],{"class":286},[249,7491,1667],{"class":259},[249,7493,7494],{"class":286},"        \u003C\u002Fv-row>",[249,7496,1667],{"class":259},[249,7498,7499],{"class":286},"        \u003C!-- Status Strip -->",[249,7501,940],{"class":259},[249,7503,6418],{"class":286},[249,7505,3906],{"class":259},[249,7507,7508],{"class":286},"pa-3 mt-3",[249,7510,3906],{"class":259},[249,7512,6428],{"class":286},[249,7514,3906],{"class":259},[249,7516,371],{"class":286},[249,7518,3906],{"class":259},[249,7520,6437],{"class":286},[249,7522,3906],{"class":259},[249,7524,6442],{"class":286},[249,7526,3906],{"class":259},[249,7528,3924],{"class":286},[249,7530,940],{"class":259},[249,7532,7533],{"class":286},"            \u003Cv-row dense align=",[249,7535,3906],{"class":259},[249,7537,6456],{"class":286},[249,7539,3906],{"class":259},[249,7541,3924],{"class":286},[249,7543,940],{"class":259},[249,7545,6465],{"class":286},[249,7547,3906],{"class":259},[249,7549,4928],{"class":286},[249,7551,3906],{"class":259},[249,7553,6474],{"class":286},[249,7555,3906],{"class":259},[249,7557,7558],{"class":286},"4",[249,7560,3906],{"class":259},[249,7562,3924],{"class":286},[249,7564,940],{"class":259},[249,7566,6488],{"class":286},[249,7568,3906],{"class":259},[249,7570,7571],{"class":286},"d-flex align-center",[249,7573,3906],{"class":259},[249,7575,3924],{"class":286},[249,7577,940],{"class":259},[249,7579,7580],{"class":286},"                        \u003Cv-icon color=",[249,7582,3906],{"class":259},[249,7584,7585],{"class":286},"success",[249,7587,3906],{"class":259},[249,7589,6548],{"class":286},[249,7591,3906],{"class":259},[249,7593,6603],{"class":286},[249,7595,3906],{"class":259},[249,7597,7598],{"class":286},">mdi-check-circle\u003C\u002Fv-icon>",[249,7600,940],{"class":259},[249,7602,7603],{"class":286},"                        \u003Cspan class=",[249,7605,3906],{"class":259},[249,7607,7608],{"class":286},"text-body-2",[249,7610,3906],{"class":259},[249,7612,3924],{"class":286},[249,7614,940],{"class":259},[249,7616,7617],{"class":286},"                            \u003Cstrong>{{ show(kpi.valid_assets) }}\u003C\u002Fstrong> tools verified for production",[249,7619,940],{"class":259},[249,7621,7622],{"class":286},"                        \u003C\u002Fspan>",[249,7624,940],{"class":259},[249,7626,6521],{"class":286},[249,7628,940],{"class":259},[249,7630,6526],{"class":286},[249,7632,1667],{"class":259},[249,7634,6465],{"class":286},[249,7636,3906],{"class":259},[249,7638,4928],{"class":286},[249,7640,3906],{"class":259},[249,7642,6474],{"class":286},[249,7644,3906],{"class":259},[249,7646,7558],{"class":286},[249,7648,3906],{"class":259},[249,7650,3924],{"class":286},[249,7652,940],{"class":259},[249,7654,6488],{"class":286},[249,7656,3906],{"class":259},[249,7658,7571],{"class":286},[249,7660,3906],{"class":259},[249,7662,3924],{"class":286},[249,7664,940],{"class":259},[249,7666,7580],{"class":286},[249,7668,3906],{"class":259},[249,7670,6792],{"class":286},[249,7672,3906],{"class":259},[249,7674,6548],{"class":286},[249,7676,3906],{"class":259},[249,7678,6603],{"class":286},[249,7680,3906],{"class":259},[249,7682,7683],{"class":286},">mdi-alert\u003C\u002Fv-icon>",[249,7685,940],{"class":259},[249,7687,7603],{"class":286},[249,7689,3906],{"class":259},[249,7691,7608],{"class":286},[249,7693,3906],{"class":259},[249,7695,3924],{"class":286},[249,7697,940],{"class":259},[249,7699,7700],{"class":286},"                            \u003Cstrong>{{ show(kpi.due_next_7_days) }}\u003C\u002Fstrong> tools require calibration within 7 days",[249,7702,940],{"class":259},[249,7704,7622],{"class":286},[249,7706,940],{"class":259},[249,7708,6521],{"class":286},[249,7710,940],{"class":259},[249,7712,6526],{"class":286},[249,7714,1667],{"class":259},[249,7716,6465],{"class":286},[249,7718,3906],{"class":259},[249,7720,4928],{"class":286},[249,7722,3906],{"class":259},[249,7724,6474],{"class":286},[249,7726,3906],{"class":259},[249,7728,7558],{"class":286},[249,7730,3906],{"class":259},[249,7732,3924],{"class":286},[249,7734,940],{"class":259},[249,7736,6488],{"class":286},[249,7738,3906],{"class":259},[249,7740,7571],{"class":286},[249,7742,3906],{"class":259},[249,7744,3924],{"class":286},[249,7746,940],{"class":259},[249,7748,7580],{"class":286},[249,7750,3906],{"class":259},[249,7752,7753],{"class":286},"error",[249,7755,3906],{"class":259},[249,7757,6548],{"class":286},[249,7759,3906],{"class":259},[249,7761,6603],{"class":286},[249,7763,3906],{"class":259},[249,7765,7766],{"class":286},">mdi-close-circle\u003C\u002Fv-icon>",[249,7768,940],{"class":259},[249,7770,7603],{"class":286},[249,7772,3906],{"class":259},[249,7774,7608],{"class":286},[249,7776,3906],{"class":259},[249,7778,3924],{"class":286},[249,7780,940],{"class":259},[249,7782,7783],{"class":286},"                            \u003Cstrong>{{ show(kpi.overdue_assets) }}\u003C\u002Fstrong> tools are overdue and blocked from use",[249,7785,940],{"class":259},[249,7787,7622],{"class":286},[249,7789,940],{"class":259},[249,7791,6521],{"class":286},[249,7793,940],{"class":259},[249,7795,6526],{"class":286},[249,7797,940],{"class":259},[249,7799,6700],{"class":286},[249,7801,940],{"class":259},[249,7803,6705],{"class":286},[249,7805,1667],{"class":259},[249,7807,7808],{"class":286},"    \u003C\u002Fv-container>",[249,7810,940],{"class":259},[249,7812,4100],{"class":286},[249,7814,1667],{"class":259},[249,7816,4105],{"class":286},[249,7818,940],{"class":259},[249,7820,7821],{"class":286},"    export default {",[249,7823,940],{"class":259},[249,7825,7826],{"class":286},"        data() {",[249,7828,940],{"class":259},[249,7830,7831],{"class":286},"            return {",[249,7833,940],{"class":259},[249,7835,7836],{"class":286},"                loaded: false,",[249,7838,940],{"class":259},[249,7840,7841],{"class":286},"                updatedAt: null,",[249,7843,1667],{"class":259},[249,7845,7846],{"class":286},"                \u002F\u002F Echoed back from the query so the cards always describe",[249,7848,940],{"class":259},[249,7850,7851],{"class":286},"                \u002F\u002F the data actually on screen, not the pending selection.",[249,7853,940],{"class":259},[249,7855,7856],{"class":286},"                filters: {",[249,7858,940],{"class":259},[249,7860,7861],{"class":286},"                    department: '',",[249,7863,940],{"class":259},[249,7865,7866],{"class":286},"                    window: ''",[249,7868,940],{"class":259},[249,7870,7871],{"class":286},"                },",[249,7873,1667],{"class":259},[249,7875,7876],{"class":286},"                kpi: {",[249,7878,940],{"class":259},[249,7880,7881],{"class":286},"                    total_assets: null,",[249,7883,940],{"class":259},[249,7885,7886],{"class":286},"                    valid_assets: null,",[249,7888,940],{"class":259},[249,7890,7891],{"class":286},"                    due_soon_assets: null,",[249,7893,940],{"class":259},[249,7895,7896],{"class":286},"                    overdue_assets: null,",[249,7898,940],{"class":259},[249,7900,7901],{"class":286},"                    due_in_window: null,",[249,7903,940],{"class":259},[249,7905,7906],{"class":286},"                    due_next_7_days: null,",[249,7908,940],{"class":259},[249,7910,7911],{"class":286},"                    stale_status_count: null,",[249,7913,940],{"class":259},[249,7915,7916],{"class":286},"                    valid_percentage: null",[249,7918,940],{"class":259},[249,7920,7921],{"class":286},"                }",[249,7923,940],{"class":259},[249,7925,7926],{"class":286},"            }",[249,7928,940],{"class":259},[249,7930,7931],{"class":286},"        },",[249,7933,1667],{"class":259},[249,7935,7936],{"class":286},"        computed: {",[249,7938,940],{"class":259},[249,7940,7941],{"class":286},"            updatedAtText() {",[249,7943,940],{"class":259},[249,7945,7946],{"class":286},"                if (!this.updatedAt) return ''",[249,7948,940],{"class":259},[249,7950,7951],{"class":286},"                return this.updatedAt.toLocaleTimeString([], {",[249,7953,940],{"class":259},[249,7955,7956],{"class":286},"                    hour: '2-digit',",[249,7958,940],{"class":259},[249,7960,7961],{"class":286},"                    minute: '2-digit',",[249,7963,940],{"class":259},[249,7965,7966],{"class":286},"                    second: '2-digit'",[249,7968,940],{"class":259},[249,7970,7971],{"class":286},"                })",[249,7973,940],{"class":259},[249,7975,7926],{"class":286},[249,7977,940],{"class":259},[249,7979,7931],{"class":286},[249,7981,1667],{"class":259},[249,7983,7984],{"class":286},"        \u002F\u002F Catches the message that Dashboard replays on page load \u002F refresh,",[249,7986,940],{"class":259},[249,7988,7989],{"class":286},"        \u002F\u002F which can arrive before the socket listener below is registered.",[249,7991,940],{"class":259},[249,7993,7994],{"class":286},"        watch: {",[249,7996,940],{"class":259},[249,7998,7999],{"class":286},"            msg: {",[249,8001,940],{"class":259},[249,8003,8004],{"class":286},"                handler(msg) { this.applyMsg(msg) },",[249,8006,940],{"class":259},[249,8008,8009],{"class":286},"                immediate: true,",[249,8011,940],{"class":259},[249,8013,8014],{"class":286},"                deep: true",[249,8016,940],{"class":259},[249,8018,7926],{"class":286},[249,8020,940],{"class":259},[249,8022,7931],{"class":286},[249,8024,1667],{"class":259},[249,8026,8027],{"class":286},"        mounted() {",[249,8029,940],{"class":259},[249,8031,8032],{"class":286},"            this.applyMsg(this.msg)",[249,8034,940],{"class":259},[249,8036,8037],{"class":286},"            this.$socket.on('msg-input:' + this.id, this.applyMsg)",[249,8039,940],{"class":259},[249,8041,7931],{"class":286},[249,8043,1667],{"class":259},[249,8045,8046],{"class":286},"        unmounted() {",[249,8048,940],{"class":259},[249,8050,8051],{"class":286},"            this.$socket.off('msg-input:' + this.id, this.applyMsg)",[249,8053,940],{"class":259},[249,8055,7931],{"class":286},[249,8057,1667],{"class":259},[249,8059,8060],{"class":286},"        methods: {",[249,8062,940],{"class":259},[249,8064,8065],{"class":286},"            applyMsg(msg) {",[249,8067,940],{"class":259},[249,8069,8070],{"class":286},"                const payload = msg && msg.payload",[249,8072,940],{"class":259},[249,8074,8075],{"class":286},"                if (!payload) return",[249,8077,1667],{"class":259},[249,8079,8080],{"class":286},"                \u002F\u002F The Query node returns an ARRAY of rows unless ",[249,8082,3906],{"class":259},[249,8084,8085],{"class":286},"Split results",[249,8087,3994],{"class":259},[249,8089,8090],{"class":286},"                \u002F\u002F is on with 1 row per message. Take the first row either way.",[249,8092,940],{"class":259},[249,8094,8095],{"class":286},"                const row = Array.isArray(payload) ? payload[0] : payload",[249,8097,940],{"class":259},[249,8099,8100],{"class":286},"                if (!row || typeof row !== 'object') return",[249,8102,1667],{"class":259},[249,8104,8105],{"class":286},"                if (row.filter_department) this.filters.department = row.filter_department",[249,8107,940],{"class":259},[249,8109,8110],{"class":286},"                if (row.filter_window) this.filters.window = row.filter_window",[249,8112,1667],{"class":259},[249,8114,8115],{"class":286},"                const next = {}",[249,8117,940],{"class":259},[249,8119,8120],{"class":286},"                for (const key of Object.keys(this.kpi)) {",[249,8122,940],{"class":259},[249,8124,8125],{"class":286},"                    if (row[key] === undefined || row[key] === null) continue",[249,8127,940],{"class":259},[249,8129,8130],{"class":286},"                    \u002F\u002F COUNT() is BIGINT and ROUND() is NUMERIC - pg returns both",[249,8132,940],{"class":259},[249,8134,8135],{"class":286},"                    \u002F\u002F as strings, so coerce to Number for display and maths.",[249,8137,940],{"class":259},[249,8139,8140],{"class":286},"                    const num = Number(row[key])",[249,8142,940],{"class":259},[249,8144,8145],{"class":286},"                    next[key] = Number.isFinite(num) ? num : row[key]",[249,8147,940],{"class":259},[249,8149,7921],{"class":286},[249,8151,1667],{"class":259},[249,8153,8154],{"class":286},"                this.kpi = { ...this.kpi, ...next }",[249,8156,940],{"class":259},[249,8158,8159],{"class":286},"                this.loaded = true",[249,8161,940],{"class":259},[249,8163,8164],{"class":286},"                this.updatedAt = new Date()",[249,8166,940],{"class":259},[249,8168,8169],{"class":286},"            },",[249,8171,1667],{"class":259},[249,8173,8174],{"class":286},"            show(value) {",[249,8176,940],{"class":259},[249,8178,8179],{"class":286},"                return (value === null || value === undefined) ? '-' : value",[249,8181,940],{"class":259},[249,8183,7926],{"class":286},[249,8185,940],{"class":259},[249,8187,4361],{"class":286},[249,8189,940],{"class":259},[249,8191,4410],{"class":286},[249,8193,940],{"class":259},[249,8195,4419],{"class":286},[249,8197,1667],{"class":259},[249,8199,4424],{"class":286},[249,8201,940],{"class":259},[249,8203,8204],{"class":286},"    \u002F* The ui-theme node only carries the four structural colours, so the",[249,8206,940],{"class":259},[249,8208,8209],{"class":286},"       semantic ones are redefined here. This block is unscoped, so it",[249,8211,940],{"class":259},[249,8213,8214],{"class":286},"       applies to every widget on the page. *\u002F",[249,8216,940],{"class":259},[249,8218,8219],{"class":286},"    :root,",[249,8221,940],{"class":259},[249,8223,8224],{"class":286},"    [class*=",[249,8226,3906],{"class":259},[249,8228,8229],{"class":286},"v-theme--",[249,8231,3906],{"class":259},[249,8233,8234],{"class":286},"] {",[249,8236,940],{"class":259},[249,8238,8239],{"class":286},"        --v-theme-success: 21, 128, 61 !important;",[249,8241,940],{"class":259},[249,8243,8244],{"class":286},"        --v-theme-warning: 180, 83, 9 !important;",[249,8246,940],{"class":259},[249,8248,8249],{"class":286},"        --v-theme-error: 179, 38, 30 !important;",[249,8251,940],{"class":259},[249,8253,8254],{"class":286},"        --v-theme-info: 30, 78, 140 !important;",[249,8256,1667],{"class":259},[249,8258,8259],{"class":286},"        \u002F* Text and icons sitting on top of a filled chip or button. *\u002F",[249,8261,940],{"class":259},[249,8263,8264],{"class":286},"        --v-theme-on-success: 255, 255, 255 !important;",[249,8266,940],{"class":259},[249,8268,8269],{"class":286},"        --v-theme-on-warning: 255, 255, 255 !important;",[249,8271,940],{"class":259},[249,8273,8274],{"class":286},"        --v-theme-on-error: 255, 255, 255 !important;",[249,8276,940],{"class":259},[249,8278,8279],{"class":286},"        --v-theme-on-info: 255, 255, 255 !important;",[249,8281,940],{"class":259},[249,8283,4410],{"class":286},[249,8285,1667],{"class":259},[249,8287,8288],{"class":286},"    .border-neutral {",[249,8290,940],{"class":259},[249,8292,8293],{"class":286},"        border-top: 4px solid #8894a6;",[249,8295,940],{"class":259},[249,8297,4410],{"class":286},[249,8299,1667],{"class":259},[249,8301,8302],{"class":286},"    .border-success {",[249,8304,940],{"class":259},[249,8306,8307],{"class":286},"        border-top: 4px solid rgb(var(--v-theme-success));",[249,8309,940],{"class":259},[249,8311,4410],{"class":286},[249,8313,1667],{"class":259},[249,8315,8316],{"class":286},"    .border-warning {",[249,8318,940],{"class":259},[249,8320,8321],{"class":286},"        border-top: 4px solid rgb(var(--v-theme-warning));",[249,8323,940],{"class":259},[249,8325,4410],{"class":286},[249,8327,1667],{"class":259},[249,8329,8330],{"class":286},"    .border-danger {",[249,8332,940],{"class":259},[249,8334,8335],{"class":286},"        border-top: 4px solid rgb(var(--v-theme-error));",[249,8337,940],{"class":259},[249,8339,4410],{"class":286},[249,8341,1667],{"class":259},[249,8343,8344],{"class":286},"    .border-info {",[249,8346,940],{"class":259},[249,8348,8349],{"class":286},"        border-top: 4px solid rgb(var(--v-theme-info));",[249,8351,940],{"class":259},[249,8353,4410],{"class":286},[249,8355,940],{"class":259},[249,8357,4477],{"class":286},[249,8359,272],{"class":255},[249,8361,292],{"class":255},[249,8363,272],{"class":255},[249,8365,4486],{"class":275},[249,8367,272],{"class":255},[249,8369,421],{"class":255},[249,8371,272],{"class":255},[249,8373,4495],{"class":275},[249,8375,272],{"class":255},[249,8377,421],{"class":255},[249,8379,272],{"class":255},[249,8381,4504],{"class":275},[249,8383,272],{"class":255},[249,8385,421],{"class":255},[249,8387,272],{"class":255},[249,8389,4513],{"class":275},[249,8391,272],{"class":255},[249,8393,281],{"class":255},[249,8395,272],{"class":255},[249,8397,8398],{"class":286},"local",[249,8400,272],{"class":255},[249,8402,292],{"class":255},[249,8404,272],{"class":255},[249,8406,4531],{"class":275},[249,8408,272],{"class":255},[249,8410,281],{"class":255},[249,8412,786],{"class":255},[249,8414,292],{"class":255},[249,8416,272],{"class":255},[249,8418,564],{"class":275},[249,8420,272],{"class":255},[249,8422,281],{"class":255},[249,8424,8425],{"class":571},"800",[249,8427,292],{"class":255},[249,8429,272],{"class":255},[249,8431,579],{"class":275},[249,8433,272],{"class":255},[249,8435,281],{"class":255},[249,8437,8438],{"class":571},"240",[249,8440,292],{"class":255},[249,8442,272],{"class":255},[249,8444,837],{"class":275},[249,8446,272],{"class":255},[249,8448,8449],{"class":255},":[[]]},{",[249,8451,272],{"class":255},[249,8453,276],{"class":275},[249,8455,272],{"class":255},[249,8457,281],{"class":255},[249,8459,272],{"class":255},[249,8461,6290],{"class":286},[249,8463,272],{"class":255},[249,8465,292],{"class":255},[249,8467,272],{"class":255},[249,8469,297],{"class":275},[249,8471,272],{"class":255},[249,8473,281],{"class":255},[249,8475,272],{"class":255},[249,8477,122],{"class":286},[249,8479,272],{"class":255},[249,8481,292],{"class":255},[249,8483,272],{"class":255},[249,8485,688],{"class":275},[249,8487,272],{"class":255},[249,8489,281],{"class":255},[249,8491,272],{"class":255},[249,8493,3510],{"class":286},[249,8495,272],{"class":255},[249,8497,292],{"class":255},[249,8499,272],{"class":255},[249,8501,3553],{"class":275},[249,8503,272],{"class":255},[249,8505,281],{"class":255},[249,8507,272],{"class":255},[249,8509,3799],{"class":286},[249,8511,272],{"class":255},[249,8513,292],{"class":255},[249,8515,272],{"class":255},[249,8517,3850],{"class":275},[249,8519,272],{"class":255},[249,8521,281],{"class":255},[249,8523,272],{"class":255},[249,8525,4928],{"class":286},[249,8527,272],{"class":255},[249,8529,292],{"class":255},[249,8531,272],{"class":255},[249,8533,3863],{"class":275},[249,8535,272],{"class":255},[249,8537,281],{"class":255},[249,8539,371],{"class":571},[249,8541,292],{"class":255},[249,8543,272],{"class":255},[249,8545,3837],{"class":275},[249,8547,272],{"class":255},[249,8549,281],{"class":255},[249,8551,371],{"class":571},[249,8553,292],{"class":255},[249,8555,272],{"class":255},[249,8557,8558],{"class":275},"showTitle",[249,8560,272],{"class":255},[249,8562,729],{"class":255},[249,8564,272],{"class":255},[249,8566,4531],{"class":275},[249,8568,272],{"class":255},[249,8570,281],{"class":255},[249,8572,786],{"class":255},[249,8574,292],{"class":255},[249,8576,272],{"class":255},[249,8578,4961],{"class":275},[249,8580,272],{"class":255},[249,8582,281],{"class":255},[249,8584,272],{"class":255},[249,8586,4970],{"class":286},[249,8588,272],{"class":255},[249,8590,292],{"class":255},[249,8592,272],{"class":255},[249,8594,4979],{"class":275},[249,8596,272],{"class":255},[249,8598,281],{"class":255},[249,8600,272],{"class":255},[249,8602,4988],{"class":286},[249,8604,272],{"class":255},[249,8606,292],{"class":255},[249,8608,272],{"class":255},[249,8610,8611],{"class":275},"groupType",[249,8613,272],{"class":255},[249,8615,281],{"class":255},[249,8617,272],{"class":255},[249,8619,5287],{"class":286},[249,8621,272],{"class":255},[249,8623,617],{"class":255},[249,8625,272],{"class":255},[249,8627,276],{"class":275},[249,8629,272],{"class":255},[249,8631,281],{"class":255},[249,8633,272],{"class":255},[249,8635,3799],{"class":286},[249,8637,272],{"class":255},[249,8639,292],{"class":255},[249,8641,272],{"class":255},[249,8643,297],{"class":275},[249,8645,272],{"class":255},[249,8647,281],{"class":255},[249,8649,272],{"class":255},[249,8651,119],{"class":286},[249,8653,272],{"class":255},[249,8655,292],{"class":255},[249,8657,272],{"class":255},[249,8659,688],{"class":275},[249,8661,272],{"class":255},[249,8663,281],{"class":255},[249,8665,272],{"class":255},[249,8667,3466],{"class":286},[249,8669,272],{"class":255},[249,8671,292],{"class":255},[249,8673,272],{"class":255},[249,8675,3808],{"class":275},[249,8677,272],{"class":255},[249,8679,281],{"class":255},[249,8681,272],{"class":255},[249,8683,4643],{"class":286},[249,8685,272],{"class":255},[249,8687,292],{"class":255},[249,8689,272],{"class":255},[249,8691,4652],{"class":275},[249,8693,272],{"class":255},[249,8695,281],{"class":255},[249,8697,272],{"class":255},[249,8699,3470],{"class":286},[249,8701,272],{"class":255},[249,8703,292],{"class":255},[249,8705,272],{"class":255},[249,8707,4669],{"class":275},[249,8709,272],{"class":255},[249,8711,281],{"class":255},[249,8713,272],{"class":255},[249,8715,4678],{"class":286},[249,8717,272],{"class":255},[249,8719,292],{"class":255},[249,8721,272],{"class":255},[249,8723,4687],{"class":275},[249,8725,272],{"class":255},[249,8727,281],{"class":255},[249,8729,272],{"class":255},[249,8731,4696],{"class":286},[249,8733,272],{"class":255},[249,8735,292],{"class":255},[249,8737,272],{"class":255},[249,8739,4705],{"class":275},[249,8741,272],{"class":255},[249,8743,281],{"class":255},[249,8745,272],{"class":255},[249,8747,4714],{"class":286},[249,8749,272],{"class":255},[249,8751,292],{"class":255},[249,8753,272],{"class":255},[249,8755,4723],{"class":275},[249,8757,272],{"class":255},[249,8759,1165],{"class":255},[249,8761,272],{"class":255},[249,8763,688],{"class":343},[249,8765,272],{"class":255},[249,8767,281],{"class":255},[249,8769,272],{"class":255},[249,8771,4740],{"class":286},[249,8773,272],{"class":255},[249,8775,292],{"class":255},[249,8777,272],{"class":255},[249,8779,4749],{"class":343},[249,8781,272],{"class":255},[249,8783,281],{"class":255},[249,8785,272],{"class":255},[249,8787,2149],{"class":286},[249,8789,272],{"class":255},[249,8791,292],{"class":255},[249,8793,272],{"class":255},[249,8795,4766],{"class":343},[249,8797,272],{"class":255},[249,8799,281],{"class":255},[249,8801,272],{"class":255},[249,8803,4775],{"class":286},[249,8805,272],{"class":255},[249,8807,617],{"class":255},[249,8809,272],{"class":255},[249,8811,688],{"class":343},[249,8813,272],{"class":255},[249,8815,281],{"class":255},[249,8817,272],{"class":255},[249,8819,4792],{"class":286},[249,8821,272],{"class":255},[249,8823,292],{"class":255},[249,8825,272],{"class":255},[249,8827,4749],{"class":343},[249,8829,272],{"class":255},[249,8831,281],{"class":255},[249,8833,272],{"class":255},[249,8835,4809],{"class":286},[249,8837,272],{"class":255},[249,8839,292],{"class":255},[249,8841,272],{"class":255},[249,8843,4766],{"class":343},[249,8845,272],{"class":255},[249,8847,281],{"class":255},[249,8849,272],{"class":255},[249,8851,4826],{"class":286},[249,8853,272],{"class":255},[249,8855,617],{"class":255},[249,8857,272],{"class":255},[249,8859,688],{"class":343},[249,8861,272],{"class":255},[249,8863,281],{"class":255},[249,8865,272],{"class":255},[249,8867,4843],{"class":286},[249,8869,272],{"class":255},[249,8871,292],{"class":255},[249,8873,272],{"class":255},[249,8875,4749],{"class":343},[249,8877,272],{"class":255},[249,8879,281],{"class":255},[249,8881,272],{"class":255},[249,8883,4860],{"class":286},[249,8885,272],{"class":255},[249,8887,292],{"class":255},[249,8889,272],{"class":255},[249,8891,4766],{"class":343},[249,8893,272],{"class":255},[249,8895,281],{"class":255},[249,8897,272],{"class":255},[249,8899,4877],{"class":286},[249,8901,272],{"class":255},[249,8903,617],{"class":255},[249,8905,272],{"class":255},[249,8907,688],{"class":343},[249,8909,272],{"class":255},[249,8911,281],{"class":255},[249,8913,272],{"class":255},[249,8915,4894],{"class":286},[249,8917,272],{"class":255},[249,8919,292],{"class":255},[249,8921,272],{"class":255},[249,8923,4749],{"class":343},[249,8925,272],{"class":255},[249,8927,281],{"class":255},[249,8929,272],{"class":255},[249,8931,4911],{"class":286},[249,8933,272],{"class":255},[249,8935,292],{"class":255},[249,8937,272],{"class":255},[249,8939,4766],{"class":343},[249,8941,272],{"class":255},[249,8943,281],{"class":255},[249,8945,272],{"class":255},[249,8947,4928],{"class":286},[249,8949,272],{"class":255},[249,8951,1182],{"class":255},[249,8953,272],{"class":255},[249,8955,3837],{"class":275},[249,8957,272],{"class":255},[249,8959,281],{"class":255},[249,8961,371],{"class":571},[249,8963,292],{"class":255},[249,8965,272],{"class":255},[249,8967,4531],{"class":275},[249,8969,272],{"class":255},[249,8971,281],{"class":255},[249,8973,786],{"class":255},[249,8975,292],{"class":255},[249,8977,272],{"class":255},[249,8979,4961],{"class":275},[249,8981,272],{"class":255},[249,8983,281],{"class":255},[249,8985,272],{"class":255},[249,8987,4970],{"class":286},[249,8989,272],{"class":255},[249,8991,292],{"class":255},[249,8993,272],{"class":255},[249,8995,4979],{"class":275},[249,8997,272],{"class":255},[249,8999,281],{"class":255},[249,9001,272],{"class":255},[249,9003,4988],{"class":286},[249,9005,272],{"class":255},[249,9007,617],{"class":255},[249,9009,272],{"class":255},[249,9011,276],{"class":275},[249,9013,272],{"class":255},[249,9015,281],{"class":255},[249,9017,272],{"class":255},[249,9019,4643],{"class":286},[249,9021,272],{"class":255},[249,9023,292],{"class":255},[249,9025,272],{"class":255},[249,9027,297],{"class":275},[249,9029,272],{"class":255},[249,9031,281],{"class":255},[249,9033,272],{"class":255},[249,9035,3546],{"class":286},[249,9037,272],{"class":255},[249,9039,292],{"class":255},[249,9041,272],{"class":255},[249,9043,688],{"class":275},[249,9045,272],{"class":255},[249,9047,281],{"class":255},[249,9049,272],{"class":255},[249,9051,5037],{"class":286},[249,9053,272],{"class":255},[249,9055,292],{"class":255},[249,9057,272],{"class":255},[249,9059,4652],{"class":275},[249,9061,272],{"class":255},[249,9063,281],{"class":255},[249,9065,272],{"class":255},[249,9067,5054],{"class":286},[249,9069,272],{"class":255},[249,9071,292],{"class":255},[249,9073,272],{"class":255},[249,9075,5063],{"class":275},[249,9077,272],{"class":255},[249,9079,281],{"class":255},[249,9081,786],{"class":255},[249,9083,292],{"class":255},[249,9085,272],{"class":255},[249,9087,5076],{"class":275},[249,9089,272],{"class":255},[249,9091,421],{"class":255},[249,9093,272],{"class":255},[249,9095,5085],{"class":275},[249,9097,272],{"class":255},[249,9099,468],{"class":255},[249,9101,272],{"class":255},[249,9103,116],{"class":286},[249,9105,272],{"class":255},[249,9107,292],{"class":255},[249,9109,272],{"class":255},[249,9111,5102],{"class":286},[249,9113,272],{"class":255},[249,9115,292],{"class":255},[249,9117,272],{"class":255},[249,9119,5111],{"class":286},[249,9121,272],{"class":255},[249,9123,292],{"class":255},[249,9125,272],{"class":255},[249,9127,5120],{"class":286},[249,9129,272],{"class":255},[249,9131,292],{"class":255},[249,9133,272],{"class":255},[249,9135,110],{"class":286},[249,9137,272],{"class":255},[249,9139,292],{"class":255},[249,9141,272],{"class":255},[249,9143,5137],{"class":286},[249,9145,272],{"class":255},[249,9147,292],{"class":255},[249,9149,272],{"class":255},[249,9151,5146],{"class":286},[249,9153,272],{"class":255},[249,9155,292],{"class":255},[249,9157,272],{"class":255},[249,9159,5155],{"class":286},[249,9161,272],{"class":255},[249,9163,292],{"class":255},[249,9165,272],{"class":255},[249,9167,5164],{"class":286},[249,9169,272],{"class":255},[249,9171,292],{"class":255},[249,9173,272],{"class":255},[249,9175,5173],{"class":286},[249,9177,272],{"class":255},[249,9179,292],{"class":255},[249,9181,272],{"class":255},[249,9183,5182],{"class":286},[249,9185,272],{"class":255},[249,9187,292],{"class":255},[249,9189,272],{"class":255},[249,9191,5191],{"class":286},[249,9193,272],{"class":255},[249,9195,292],{"class":255},[249,9197,272],{"class":255},[249,9199,5200],{"class":286},[249,9201,272],{"class":255},[249,9203,292],{"class":255},[249,9205,272],{"class":255},[249,9207,5209],{"class":286},[249,9209,272],{"class":255},[249,9211,292],{"class":255},[249,9213,272],{"class":255},[249,9215,103],{"class":286},[249,9217,272],{"class":255},[249,9219,292],{"class":255},[249,9221,272],{"class":255},[249,9223,113],{"class":286},[249,9225,272],{"class":255},[249,9227,292],{"class":255},[249,9229,272],{"class":255},[249,9231,5234],{"class":286},[249,9233,272],{"class":255},[249,9235,292],{"class":255},[249,9237,272],{"class":255},[249,9239,5243],{"class":286},[249,9241,272],{"class":255},[249,9243,559],{"class":255},[249,9245,272],{"class":255},[249,9247,5252],{"class":275},[249,9249,272],{"class":255},[249,9251,729],{"class":255},[249,9253,272],{"class":255},[249,9255,5261],{"class":275},[249,9257,272],{"class":255},[249,9259,281],{"class":255},[249,9261,272],{"class":255},[249,9263,3553],{"class":286},[249,9265,272],{"class":255},[249,9267,292],{"class":255},[249,9269,272],{"class":255},[249,9271,5278],{"class":275},[249,9273,272],{"class":255},[249,9275,281],{"class":255},[249,9277,272],{"class":255},[249,9279,5287],{"class":286},[249,9281,272],{"class":255},[249,9283,292],{"class":255},[249,9285,272],{"class":255},[249,9287,5296],{"class":275},[249,9289,272],{"class":255},[249,9291,281],{"class":255},[249,9293,272],{"class":255},[249,9295,5287],{"class":286},[249,9297,272],{"class":255},[249,9299,292],{"class":255},[249,9301,272],{"class":255},[249,9303,5313],{"class":275},[249,9305,272],{"class":255},[249,9307,421],{"class":255},[249,9309,272],{"class":255},[249,9311,5322],{"class":275},[249,9313,272],{"class":255},[249,9315,281],{"class":255},[249,9317,371],{"class":571},[249,9319,292],{"class":255},[249,9321,272],{"class":255},[249,9323,5335],{"class":275},[249,9325,272],{"class":255},[249,9327,421],{"class":255},[249,9329,272],{"class":255},[249,9331,5344],{"class":275},[249,9333,272],{"class":255},[249,9335,5349],{"class":255},[249,9337,272],{"class":255},[249,9339,276],{"class":275},[249,9341,272],{"class":255},[249,9343,281],{"class":255},[249,9345,272],{"class":255},[249,9347,4714],{"class":286},[249,9349,272],{"class":255},[249,9351,292],{"class":255},[249,9353,272],{"class":255},[249,9355,297],{"class":275},[249,9357,272],{"class":255},[249,9359,281],{"class":255},[249,9361,272],{"class":255},[249,9363,125],{"class":286},[249,9365,272],{"class":255},[249,9367,292],{"class":255},[249,9369,272],{"class":255},[249,9371,688],{"class":275},[249,9373,272],{"class":255},[249,9375,281],{"class":255},[249,9377,272],{"class":255},[249,9379,5394],{"class":286},[249,9381,272],{"class":255},[249,9383,292],{"class":255},[249,9385,272],{"class":255},[249,9387,5403],{"class":275},[249,9389,272],{"class":255},[249,9391,338],{"class":255},[249,9393,272],{"class":255},[249,9395,5412],{"class":343},[249,9397,272],{"class":255},[249,9399,281],{"class":255},[249,9401,272],{"class":255},[249,9403,5421],{"class":286},[249,9405,272],{"class":255},[249,9407,292],{"class":255},[249,9409,272],{"class":255},[249,9411,5430],{"class":343},[249,9413,272],{"class":255},[249,9415,281],{"class":255},[249,9417,272],{"class":255},[249,9419,5439],{"class":286},[249,9421,272],{"class":255},[249,9423,292],{"class":255},[249,9425,272],{"class":255},[249,9427,5448],{"class":343},[249,9429,272],{"class":255},[249,9431,281],{"class":255},[249,9433,272],{"class":255},[249,9435,5457],{"class":286},[249,9437,272],{"class":255},[249,9439,292],{"class":255},[249,9441,272],{"class":255},[249,9443,5466],{"class":343},[249,9445,272],{"class":255},[249,9447,281],{"class":255},[249,9449,272],{"class":255},[249,9451,5421],{"class":286},[249,9453,272],{"class":255},[249,9455,292],{"class":255},[249,9457,272],{"class":255},[249,9459,5483],{"class":343},[249,9461,272],{"class":255},[249,9463,281],{"class":255},[249,9465,272],{"class":255},[249,9467,5492],{"class":286},[249,9469,272],{"class":255},[249,9471,458],{"class":255},[249,9473,272],{"class":255},[249,9475,5501],{"class":275},[249,9477,272],{"class":255},[249,9479,338],{"class":255},[249,9481,272],{"class":255},[249,9483,5510],{"class":343},[249,9485,272],{"class":255},[249,9487,281],{"class":255},[249,9489,272],{"class":255},[249,9491,5287],{"class":286},[249,9493,272],{"class":255},[249,9495,292],{"class":255},[249,9497,272],{"class":255},[249,9499,5527],{"class":343},[249,9501,272],{"class":255},[249,9503,281],{"class":255},[249,9505,272],{"class":255},[249,9507,5536],{"class":286},[249,9509,272],{"class":255},[249,9511,292],{"class":255},[249,9513,272],{"class":255},[249,9515,5545],{"class":343},[249,9517,272],{"class":255},[249,9519,281],{"class":255},[249,9521,272],{"class":255},[249,9523,5536],{"class":286},[249,9525,272],{"class":255},[249,9527,292],{"class":255},[249,9529,272],{"class":255},[249,9531,5562],{"class":343},[249,9533,272],{"class":255},[249,9535,281],{"class":255},[249,9537,272],{"class":255},[249,9539,5571],{"class":286},[249,9541,272],{"class":255},[249,9543,292],{"class":255},[249,9545,272],{"class":255},[249,9547,5580],{"class":343},[249,9549,272],{"class":255},[249,9551,281],{"class":255},[249,9553,272],{"class":255},[249,9555,5536],{"class":286},[249,9557,272],{"class":255},[249,9559,5593],{"class":255},[249,9561,272],{"class":255},[249,9563,276],{"class":275},[249,9565,272],{"class":255},[249,9567,281],{"class":255},[249,9569,272],{"class":255},[249,9571,9572],{"class":286},"057822a3ade579c5",[249,9574,272],{"class":255},[249,9576,292],{"class":255},[249,9578,272],{"class":255},[249,9580,297],{"class":275},[249,9582,272],{"class":255},[249,9584,281],{"class":255},[249,9586,272],{"class":255},[249,9588,3245],{"class":286},[249,9590,272],{"class":255},[249,9592,292],{"class":255},[249,9594,272],{"class":255},[249,9596,3254],{"class":275},[249,9598,272],{"class":255},[249,9600,2200],{"class":255},[249,9602,272],{"class":255},[249,9604,3263],{"class":275},[249,9606,272],{"class":255},[249,9608,338],{"class":255},[249,9610,272],{"class":255},[249,9612,99],{"class":343},[249,9614,272],{"class":255},[249,9616,281],{"class":255},[249,9618,272],{"class":255},[249,9620,5655],{"class":286},[249,9622,272],{"class":255},[249,9624,3286],{"class":255},[249,9626,9627,9629,9631],{"class":251,"line":3289},[249,9628,256],{"class":255},[249,9630,3294],{"class":259},[249,9632,263],{"class":255},[166,9634,9635],{"start":5830},[79,9636,5690,9637,9640,9641,26],{},[51,9638,9639],{},"Poll Data (15 sec) → Set Params → KPI Query → KPI Cards",", and ",[51,9642,9643],{},"Filters Changed → Set Params",[12,9645,9646,9647,9649],{},"Deploy and open ",[56,9648,3470],{},". The six cards fill in, and on the seeded data the drift banner should appear right away, because the generator creates records whose stored status no longer matches their due date.",[12,9651,9652,37,9656],{},[33,9653],{"alt":9654,"src":9655},"the KPI row showing six cards and the summary strip","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fkpi-cards-calibration.png",[39,9657,9658],{},"Six figures worked out from the due dates, with the active filter and refresh time shown in the header.",[68,9660,9662],{"id":9661},"listing-every-instrument-with-days-remaining","Listing Every Instrument with Days Remaining",[12,9664,9665],{},"The cards tell a supervisor how much is overdue. This table tells them which tools, so someone can actually go and collect them. It's a worklist rather than a full register dump, which is why the time window scopes it down.",[166,9667,9668,9673],{},[79,9669,3572,9670,9672],{},[56,9671,5732],{}," node named \"Refresh Asset Table\" and point it at the link out from the KPI flow. Taking the filters from that message instead of reading context again is what keeps the table and the cards working from the same selection.",[79,9674,3572,9675,9677],{},[56,9676,871],{}," node named \"Asset Rows\":",[240,9679,9681],{"className":3596,"code":9680,"language":3598,"meta":245,"style":245},"SELECT\n    -- Sent back so the table can state its own scope in the header.\n    COALESCE($timeWindow::text, 'Next 90 days') AS filter_window,\n\n    tool_id,\n    equipment_name,\n    department,\n    location,\n    serial_number,\n\n    -- Same 30-day policy threshold as the KPI buckets, so a tool never reads\n    -- one status here and another elsewhere. The bare column name still\n    -- refers to the table column.\n    CASE\n        WHEN next_due_ts \u003C NOW() THEN 'Overdue'\n        WHEN next_due_ts \u003C= NOW() + INTERVAL '30 days' THEN 'DueSoon'\n        ELSE 'Valid'\n    END AS status,\n    status AS stored_status,\n\n    last_calibration_ts,\n    next_due_ts,\n    calibration_interval_months,\n    calibration_lab,\n    certificate_no,\n\n    -- Negative for anything already past due, which the widget shows as\n    -- \"12d overdue\" rather than \"-12d\".\n    (next_due_ts::date - CURRENT_DATE) AS days_remaining\n\nFROM calibration_assets\n\n-- This is a worklist, not the whole register: the window scopes it to what\n-- needs attention. Overdue tools have a past due date, so the upper bound\n-- already includes them; no separate clause needed.\nWHERE (COALESCE($department::text, 'All') = 'All'\n       OR department = $department::text)\n  AND next_due_ts \u003C= NOW() + (\n      CASE COALESCE($timeWindow::text, 'Next 90 days')\n          WHEN 'Next 7 days'  THEN INTERVAL '7 days'\n          WHEN 'Next 30 days' THEN INTERVAL '30 days'\n          WHEN 'Next 90 days' THEN INTERVAL '90 days'\n          WHEN 'All future'   THEN INTERVAL '100 years'\n          ELSE INTERVAL '90 days'\n      END\n  )\n\nORDER BY next_due_ts ASC\nLIMIT 500;\n",[56,9682,9683,9687,9692,9696,9700,9705,9710,9715,9720,9725,9729,9734,9739,9744,9749,9754,9759,9764,9769,9774,9778,9783,9788,9793,9798,9803,9807,9812,9817,9822,9826,9830,9834,9839,9844,9849,9853,9858,9863,9868,9873,9878,9883,9888,9893,9898,9903,9907,9912],{"__ignoreMap":245},[249,9684,9685],{"class":251,"line":252},[249,9686,5801],{},[249,9688,9689],{"class":251,"line":266},[249,9690,9691],{},"    -- Sent back so the table can state its own scope in the header.\n",[249,9693,9694],{"class":251,"line":3289},[249,9695,5827],{},[249,9697,9698],{"class":251,"line":3618},[249,9699,5834],{"emptyLinePlaceholder":5833},[249,9701,9702],{"class":251,"line":3624},[249,9703,9704],{},"    tool_id,\n",[249,9706,9707],{"class":251,"line":5824},[249,9708,9709],{},"    equipment_name,\n",[249,9711,9712],{"class":251,"line":5830},[249,9713,9714],{},"    department,\n",[249,9716,9717],{"class":251,"line":5837},[249,9718,9719],{},"    location,\n",[249,9721,9722],{"class":251,"line":5843},[249,9723,9724],{},"    serial_number,\n",[249,9726,9727],{"class":251,"line":5848},[249,9728,5834],{"emptyLinePlaceholder":5833},[249,9730,9731],{"class":251,"line":5854},[249,9732,9733],{},"    -- Same 30-day policy threshold as the KPI buckets, so a tool never reads\n",[249,9735,9736],{"class":251,"line":5860},[249,9737,9738],{},"    -- one status here and another elsewhere. The bare column name still\n",[249,9740,9741],{"class":251,"line":5866},[249,9742,9743],{},"    -- refers to the table column.\n",[249,9745,9746],{"class":251,"line":5872},[249,9747,9748],{},"    CASE\n",[249,9750,9751],{"class":251,"line":5878},[249,9752,9753],{},"        WHEN next_due_ts \u003C NOW() THEN 'Overdue'\n",[249,9755,9756],{"class":251,"line":5884},[249,9757,9758],{},"        WHEN next_due_ts \u003C= NOW() + INTERVAL '30 days' THEN 'DueSoon'\n",[249,9760,9761],{"class":251,"line":5890},[249,9762,9763],{},"        ELSE 'Valid'\n",[249,9765,9766],{"class":251,"line":5895},[249,9767,9768],{},"    END AS status,\n",[249,9770,9771],{"class":251,"line":5900},[249,9772,9773],{},"    status AS stored_status,\n",[249,9775,9776],{"class":251,"line":5906},[249,9777,5834],{"emptyLinePlaceholder":5833},[249,9779,9780],{"class":251,"line":5912},[249,9781,9782],{},"    last_calibration_ts,\n",[249,9784,9785],{"class":251,"line":5918},[249,9786,9787],{},"    next_due_ts,\n",[249,9789,9790],{"class":251,"line":5923},[249,9791,9792],{},"    calibration_interval_months,\n",[249,9794,9795],{"class":251,"line":5928},[249,9796,9797],{},"    calibration_lab,\n",[249,9799,9800],{"class":251,"line":5934},[249,9801,9802],{},"    certificate_no,\n",[249,9804,9805],{"class":251,"line":5940},[249,9806,5834],{"emptyLinePlaceholder":5833},[249,9808,9809],{"class":251,"line":5945},[249,9810,9811],{},"    -- Negative for anything already past due, which the widget shows as\n",[249,9813,9814],{"class":251,"line":5951},[249,9815,9816],{},"    -- \"12d overdue\" rather than \"-12d\".\n",[249,9818,9819],{"class":251,"line":5957},[249,9820,9821],{},"    (next_due_ts::date - CURRENT_DATE) AS days_remaining\n",[249,9823,9824],{"class":251,"line":5962},[249,9825,5834],{"emptyLinePlaceholder":5833},[249,9827,9828],{"class":251,"line":5967},[249,9829,3610],{},[249,9831,9832],{"class":251,"line":5973},[249,9833,5834],{"emptyLinePlaceholder":5833},[249,9835,9836],{"class":251,"line":5979},[249,9837,9838],{},"-- This is a worklist, not the whole register: the window scopes it to what\n",[249,9840,9841],{"class":251,"line":5985},[249,9842,9843],{},"-- needs attention. Overdue tools have a past due date, so the upper bound\n",[249,9845,9846],{"class":251,"line":5991},[249,9847,9848],{},"-- already includes them; no separate clause needed.\n",[249,9850,9851],{"class":251,"line":5997},[249,9852,6155],{},[249,9854,9855],{"class":251,"line":6003},[249,9856,9857],{},"       OR department = $department::text)\n",[249,9859,9860],{"class":251,"line":6009},[249,9861,9862],{},"  AND next_due_ts \u003C= NOW() + (\n",[249,9864,9865],{"class":251,"line":6015},[249,9866,9867],{},"      CASE COALESCE($timeWindow::text, 'Next 90 days')\n",[249,9869,9870],{"class":251,"line":6021},[249,9871,9872],{},"          WHEN 'Next 7 days'  THEN INTERVAL '7 days'\n",[249,9874,9875],{"class":251,"line":6027},[249,9876,9877],{},"          WHEN 'Next 30 days' THEN INTERVAL '30 days'\n",[249,9879,9880],{"class":251,"line":6032},[249,9881,9882],{},"          WHEN 'Next 90 days' THEN INTERVAL '90 days'\n",[249,9884,9885],{"class":251,"line":6037},[249,9886,9887],{},"          WHEN 'All future'   THEN INTERVAL '100 years'\n",[249,9889,9890],{"class":251,"line":6043},[249,9891,9892],{},"          ELSE INTERVAL '90 days'\n",[249,9894,9895],{"class":251,"line":6049},[249,9896,9897],{},"      END\n",[249,9899,9900],{"class":251,"line":6055},[249,9901,9902],{},"  )\n",[249,9904,9905],{"class":251,"line":6060},[249,9906,5834],{"emptyLinePlaceholder":5833},[249,9908,9909],{"class":251,"line":6066},[249,9910,9911],{},"ORDER BY next_due_ts ASC\n",[249,9913,9914],{"class":251,"line":6072},[249,9915,9916],{},"LIMIT 500;\n",[12,9918,9919,9920,9923],{},"Sorting by due date ascending puts the worst offenders at the top, which is the only order that makes a calibration list useful. ",[56,9921,9922],{},"stored_status"," is included but not used by the widget, so it's there when you want to see exactly which records have drifted rather than just how many.",[166,9925,9926],{"start":3289},[79,9927,3632,9928,37,9931,6186,9933,9935],{},[51,9929,9930],{},"Asset Table",[56,9932,103],{},[51,9934,3516],{}," group. The complete component is provided below, so there's no need to build it yourself. It shows a Vuetify data table with a status chip per row, formatted dates, and days remaining shown as \"12d overdue\" or \"due today\". Its header names the active window, so it's clear the list is scoped rather than the full register. Above the table sit a search box and a status toggle with live counts for Overdue, Due soon and Valid, filtering the rows already on the page without hitting the database again. The Department column hides itself when every row belongs to the same department, since a single-department view makes it a fixed value.",[236,9937,9938],{":height":238},[240,9939,9941],{"className":242,"code":9940,"language":244,"meta":245,"style":245},"{% raw %}\n[{\"id\":\"9bb12e97685f0e01\",\"type\":\"ui-template\",\"z\":\"1c5b2364213044a7\",\"g\":\"e7cdada1bef716e5\",\"group\":\"13c06e7c625a1885\",\"page\":\"\",\"ui\":\"\",\"name\":\"Asset Table\",\"order\":1,\"width\":0,\"height\":0,\"head\":\"\",\"format\":\"\u003Ctemplate>\\n    \u003Cv-card class=\\\"pa-4\\\" elevation=\\\"1\\\" rounded=\\\"lg\\\">\\n\\n        \u003C!-- Toolbar -->\\n        \u003Cv-row dense align=\\\"center\\\" class=\\\"mb-2\\\">\\n            \u003Cv-col cols=\\\"12\\\" md=\\\"5\\\">\\n                \u003Cdiv class=\\\"text-subtitle-1 font-weight-bold\\\">\\n                    Asset Detail\u003Cspan v-if=\\\"windowLabel\\\"> &middot; {{ windowLabel }}\u003C\u002Fspan>\\n                \u003C\u002Fdiv>\\n                \u003Cdiv class=\\\"text-caption text-medium-emphasis\\\">\\n                    {{ filteredRows.length }} of {{ rows.length }} due in this window\\n                \u003C\u002Fdiv>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" md=\\\"4\\\">\\n                \u003Cv-btn-toggle v-model=\\\"statusFilter\\\" density=\\\"compact\\\" variant=\\\"outlined\\\" divided mandatory>\\n                    \u003Cv-btn value=\\\"All\\\" size=\\\"small\\\">All\u003C\u002Fv-btn>\\n                    \u003Cv-btn value=\\\"Overdue\\\" size=\\\"small\\\" color=\\\"error\\\">\\n                        Overdue ({{ counts.Overdue }})\\n                    \u003C\u002Fv-btn>\\n                    \u003Cv-btn value=\\\"DueSoon\\\" size=\\\"small\\\" color=\\\"warning\\\">\\n                        Due soon ({{ counts.DueSoon }})\\n                    \u003C\u002Fv-btn>\\n                    \u003Cv-btn value=\\\"Valid\\\" size=\\\"small\\\" color=\\\"success\\\">\\n                        Valid ({{ counts.Valid }})\\n                    \u003C\u002Fv-btn>\\n                \u003C\u002Fv-btn-toggle>\\n            \u003C\u002Fv-col>\\n\\n            \u003Cv-col cols=\\\"12\\\" md=\\\"3\\\">\\n                \u003Cv-text-field v-model=\\\"search\\\" label=\\\"Search assets\\\" density=\\\"compact\\\" variant=\\\"solo-filled\\\"\\n                    hide-details clearable prepend-inner-icon=\\\"mdi-magnify\\\">\u003C\u002Fv-text-field>\\n            \u003C\u002Fv-col>\\n        \u003C\u002Fv-row>\\n\\n        \u003Cv-data-table :headers=\\\"visibleHeaders\\\" :items=\\\"filteredRows\\\" :search=\\\"search\\\" :sort-by=\\\"sortBy\\\"\\n            :items-per-page=\\\"10\\\" density=\\\"compact\\\" item-value=\\\"tool_id\\\" fixed-header height=\\\"420\\\" hover>\\n\\n            \u003Ctemplate #item.status=\\\"{ item }\\\">\\n                \u003Cv-chip :color=\\\"cell(item).status_color\\\" size=\\\"small\\\" variant=\\\"flat\\\">\\n                    {{ cell(item).status }}\\n                \u003C\u002Fv-chip>\\n            \u003C\u002Ftemplate>\\n\\n            \u003Ctemplate #item.last_calibration_ts=\\\"{ item }\\\">\\n                {{ cell(item).last_cal_text }}\\n            \u003C\u002Ftemplate>\\n\\n            \u003Ctemplate #item.next_due_ts=\\\"{ item }\\\">\\n                \u003Cspan :class=\\\"cell(item).days_remaining \u003C 0 ? 'text-error font-weight-bold' : ''\\\">\\n                    {{ cell(item).next_due_text }}\\n                \u003C\u002Fspan>\\n            \u003C\u002Ftemplate>\\n\\n            \u003Ctemplate #item.days_remaining=\\\"{ item }\\\">\\n                \u003Cspan :class=\\\"cell(item).days_remaining \u003C 0 ? 'text-error font-weight-bold' : ''\\\">\\n                    {{ cell(item).days_text }}\\n                \u003C\u002Fspan>\\n            \u003C\u002Ftemplate>\\n\\n            \u003Ctemplate #item.calibration_interval_months=\\\"{ item }\\\">\\n                {{ cell(item).calibration_interval_months }} mo\\n            \u003C\u002Ftemplate>\\n\\n            \u003Ctemplate #no-data>\\n                \u003Cdiv class=\\\"pa-6 text-center text-medium-emphasis\\\">\\n                    No assets match the current filters.\\n                \u003C\u002Fdiv>\\n            \u003C\u002Ftemplate>\\n\\n        \u003C\u002Fv-data-table>\\n    \u003C\u002Fv-card>\\n\u003C\u002Ftemplate>\\n\\n\u003Cscript>\\n    export default {\\n        data() {\\n            return {\\n                rows: [],\\n                windowLabel: '',\\n                search: '',\\n                statusFilter: 'All',\\n                sortBy: [{ key: 'next_due_ts', order: 'asc' }],\\n                headers: [\\n                    { title: 'Tool ID', key: 'tool_id', width: '110px' },\\n                    { title: 'Equipment', key: 'equipment_name' },\\n                    { title: 'Department', key: 'department', width: '130px' },\\n                    { title: 'Location', key: 'location', width: '140px' },\\n                    { title: 'Status', key: 'status', width: '120px' },\\n                    { title: 'Interval', key: 'calibration_interval_months', width: '100px' },\\n                    { title: 'Last calibrated', key: 'last_calibration_ts', width: '140px' },\\n                    { title: 'Next due', key: 'next_due_ts', width: '140px' },\\n                    { title: 'Remaining', key: 'days_remaining', align: 'end', width: '120px' }\\n                ]\\n            }\\n        },\\n\\n        computed: {\\n            filteredRows() {\\n                if (this.statusFilter === 'All') return this.rows\\n                return this.rows.filter(r => r.status === this.statusFilter)\\n            },\\n\\n            \u002F\u002F A single-department view makes that column a constant, so drop it.\\n            visibleHeaders() {\\n                const depts = new Set(this.rows.map(r => r.department))\\n                if (depts.size > 1) return this.headers\\n                return this.headers.filter(h => h.key !== 'department')\\n            },\\n\\n            counts() {\\n                const c = { Overdue: 0, DueSoon: 0, Valid: 0 }\\n                for (const r of this.rows) {\\n                    if (c[r.status] !== undefined) c[r.status]++\\n                }\\n                return c\\n            }\\n        },\\n\\n        watch: {\\n            msg: {\\n                handler(msg) { this.applyMsg(msg) },\\n                immediate: true,\\n                deep: true\\n            }\\n        },\\n\\n        mounted() {\\n            this.applyMsg(this.msg)\\n            this.$socket.on('msg-input:' + this.id, this.applyMsg)\\n        },\\n\\n        unmounted() {\\n            this.$socket.off('msg-input:' + this.id, this.applyMsg)\\n        },\\n\\n        methods: {\\n            applyMsg(msg) {\\n                const payload = msg && msg.payload\\n                if (!Array.isArray(payload)) return\\n\\n                \u002F\u002F Constant across rows; used to caption the table's scope.\\n                if (payload[0] && payload[0].filter_window) {\\n                    this.windowLabel = payload[0].filter_window\\n                }\\n\\n                this.rows = payload\\n                    .filter(r => r && typeof r === 'object')\\n                    .map(r => {\\n                        const days = (r.days_remaining === null || r.days_remaining === undefined)\\n                            ? null\\n                            : Number(r.days_remaining)\\n                        return {\\n                            ...r,\\n                            days_remaining: days,\\n                            last_cal_text: this.fmtDate(r.last_calibration_ts),\\n                            next_due_text: this.fmtDate(r.next_due_ts),\\n                            days_text: this.daysText(days),\\n                            status_color: this.statusColor(r.status)\\n                        }\\n                    })\\n            },\\n\\n            \u002F\u002F Vuetify 3 passes the raw item on some minors and a wrapper on\\n            \u002F\u002F others, so normalise before reading fields.\\n            cell(item) {\\n                return (item && item.raw) ? item.raw : item\\n            },\\n\\n            fmtDate(value) {\\n                if (!value) return '-'\\n                const d = new Date(value)\\n                if (isNaN(d.getTime())) return value\\n                return d.toLocaleDateString([], { day: '2-digit', month: 'short', year: 'numeric' })\\n            },\\n\\n            daysText(days) {\\n                if (days === null) return '-'\\n                if (days \u003C 0) return Math.abs(days) + 'd overdue'\\n                if (days === 0) return 'due today'\\n                return days + 'd'\\n            },\\n\\n            statusColor(status) {\\n                if (status === 'Overdue') return 'error'\\n                if (status === 'DueSoon') return 'warning'\\n                if (status === 'Valid') return 'success'\\n                return 'grey'\\n            }\\n        }\\n    }\\n\u003C\u002Fscript>\",\"storeOutMessages\":true,\"passthru\":false,\"resendOnRefresh\":true,\"templateScope\":\"local\",\"className\":\"\",\"x\":590,\"y\":400,\"wires\":[[]]},{\"id\":\"13c06e7c625a1885\",\"type\":\"ui-group\",\"name\":\"Asset Detail\",\"page\":\"89515a0645eddeee\",\"width\":\"12\",\"height\":1,\"order\":2,\"showTitle\":false,\"className\":\"\",\"visible\":\"true\",\"disabled\":\"false\",\"groupType\":\"default\"},{\"id\":\"89515a0645eddeee\",\"type\":\"ui-page\",\"name\":\"Home\",\"ui\":\"6481b1c613ec9a93\",\"path\":\"\u002Fhome\",\"icon\":\"home\",\"layout\":\"grid\",\"theme\":\"faac104f34962f3e\",\"breakpoints\":[{\"name\":\"Default\",\"px\":\"0\",\"cols\":\"3\"},{\"name\":\"Tablet\",\"px\":\"576\",\"cols\":\"6\"},{\"name\":\"Small Desktop\",\"px\":\"768\",\"cols\":\"9\"},{\"name\":\"Desktop\",\"px\":\"1024\",\"cols\":\"12\"}],\"order\":1,\"className\":\"\",\"visible\":\"true\",\"disabled\":\"false\"},{\"id\":\"6481b1c613ec9a93\",\"type\":\"ui-base\",\"name\":\"My Dashboard\",\"path\":\"\u002Fdashboard\",\"appIcon\":\"\",\"includeClientData\":true,\"acceptsClientConfig\":[\"ui-notification\",\"ui-control\",\"ui-number-input\",\"ui-file-input\",\"ui-button\",\"ui-button-group\",\"ui-dropdown\",\"ui-radio-group\",\"ui-slider\",\"ui-switch\",\"ui-text\",\"ui-table\",\"ui-gauge\",\"ui-chart\",\"ui-template\",\"ui-markdown\",\"ui-progress\",\"ui-webcam\"],\"showPathInSidebar\":false,\"headerContent\":\"page\",\"navigationStyle\":\"default\",\"titleBarStyle\":\"default\",\"showReconnectNotification\":true,\"notificationDisplayTime\":1,\"showDisconnectNotification\":true,\"allowInstall\":false},{\"id\":\"faac104f34962f3e\",\"type\":\"ui-theme\",\"name\":\"Default Theme\",\"colors\":{\"surface\":\"#ffffff\",\"primary\":\"#1e4e8c\",\"bgPage\":\"#eef1f5\",\"groupBg\":\"#ffffff\",\"groupOutline\":\"#d3dae3\"},\"sizes\":{\"density\":\"default\",\"pagePadding\":\"12px\",\"groupGap\":\"12px\",\"groupBorderRadius\":\"4px\",\"widgetGap\":\"12px\"}},{\"id\":\"563dc603fb7848c5\",\"type\":\"global-config\",\"env\":[],\"modules\":{\"@flowfuse\u002Fnode-red-dashboard\":\"1.30.2\"}}]\n{% endraw %}\n",[56,9942,9943,9951,12608],{"__ignoreMap":245},[249,9944,9945,9947,9949],{"class":251,"line":252},[249,9946,256],{"class":255},[249,9948,260],{"class":259},[249,9950,263],{"class":255},[249,9952,9953,9955,9957,9959,9961,9963,9965,9968,9970,9972,9974,9976,9978,9980,9982,9984,9986,9988,9990,9992,9994,9996,9998,10000,10002,10004,10006,10008,10010,10012,10014,10017,10019,10021,10023,10025,10027,10029,10031,10034,10036,10038,10040,10042,10044,10046,10048,10050,10052,10054,10056,10058,10060,10062,10064,10066,10068,10070,10072,10074,10076,10078,10080,10082,10084,10086,10088,10090,10092,10094,10096,10098,10100,10102,10104,10106,10108,10110,10112,10114,10116,10118,10120,10122,10124,10126,10128,10130,10132,10134,10136,10138,10140,10143,10145,10148,10150,10152,10154,10156,10158,10160,10162,10164,10166,10168,10170,10173,10175,10178,10180,10182,10184,10186,10188,10191,10193,10195,10197,10199,10201,10203,10205,10207,10209,10211,10213,10215,10217,10220,10222,10225,10227,10229,10231,10234,10236,10239,10241,10244,10246,10249,10251,10253,10255,10257,10259,10261,10263,10266,10268,10270,10272,10274,10276,10278,10280,10282,10284,10286,10288,10290,10292,10294,10296,10299,10301,10304,10306,10308,10310,10312,10314,10316,10318,10321,10323,10326,10328,10331,10333,10335,10337,10339,10341,10343,10345,10348,10350,10352,10354,10357,10359,10361,10363,10365,10367,10369,10371,10373,10375,10377,10379,10382,10384,10387,10389,10391,10393,10396,10398,10400,10402,10404,10406,10408,10410,10412,10414,10416,10418,10421,10423,10425,10427,10429,10431,10434,10436,10438,10440,10442,10444,10446,10448,10450,10452,10454,10456,10459,10461,10463,10465,10468,10470,10472,10474,10476,10478,10480,10482,10484,10486,10488,10490,10492,10494,10497,10499,10502,10504,10506,10508,10511,10513,10515,10517,10519,10521,10523,10525,10527,10529,10532,10534,10537,10539,10542,10544,10546,10548,10550,10552,10555,10557,10560,10562,10564,10566,10569,10571,10574,10576,10578,10580,10583,10585,10588,10590,10593,10595,10598,10600,10602,10604,10606,10608,10611,10613,10615,10617,10620,10622,10625,10627,10630,10632,10635,10637,10640,10642,10644,10646,10649,10651,10654,10656,10658,10660,10662,10664,10666,10668,10671,10673,10675,10677,10680,10682,10685,10687,10690,10692,10695,10697,10699,10701,10703,10705,10708,10710,10712,10714,10717,10719,10721,10723,10725,10727,10730,10732,10735,10737,10739,10741,10744,10746,10749,10751,10753,10755,10758,10760,10762,10764,10766,10768,10770,10772,10774,10776,10778,10780,10783,10785,10787,10789,10791,10793,10796,10798,10800,10802,10804,10806,10809,10811,10813,10815,10818,10820,10822,10824,10827,10829,10831,10833,10836,10838,10840,10842,10844,10846,10849,10851,10854,10856,10858,10860,10862,10864,10866,10868,10870,10872,10874,10876,10879,10881,10884,10886,10889,10891,10894,10896,10899,10901,10904,10906,10909,10911,10914,10916,10919,10921,10924,10926,10929,10931,10934,10936,10939,10941,10944,10946,10949,10951,10954,10956,10958,10960,10962,10964,10966,10968,10971,10973,10976,10978,10981,10983,10985,10987,10990,10992,10995,10997,11000,11002,11005,11007,11010,11012,11014,11016,11019,11021,11024,11026,11029,11031,11034,11036,11038,11040,11043,11045,11047,11049,11051,11053,11055,11057,11059,11061,11063,11065,11067,11069,11071,11073,11075,11077,11079,11081,11083,11085,11087,11089,11091,11093,11095,11097,11099,11101,11103,11105,11107,11109,11111,11113,11115,11117,11119,11121,11124,11126,11129,11131,11134,11136,11139,11141,11143,11145,11148,11150,11153,11155,11158,11160,11163,11165,11168,11170,11173,11175,11178,11180,11183,11185,11188,11190,11193,11195,11198,11200,11203,11205,11208,11210,11213,11215,11218,11220,11222,11224,11227,11229,11232,11234,11237,11239,11242,11244,11246,11248,11251,11253,11256,11258,11261,11263,11266,11268,11271,11273,11275,11277,11280,11282,11285,11287,11290,11292,11295,11297,11300,11302,11304,11306,11309,11311,11314,11316,11319,11321,11324,11326,11329,11331,11333,11335,11337,11339,11341,11343,11345,11347,11349,11351,11353,11355,11357,11359,11361,11363,11365,11367,11369,11371,11373,11375,11377,11379,11381,11383,11385,11387,11389,11391,11393,11395,11397,11399,11401,11403,11405,11407,11409,11412,11414,11416,11418,11420,11422,11425,11427,11429,11431,11433,11435,11437,11439,11441,11443,11445,11447,11449,11451,11453,11455,11457,11459,11461,11463,11465,11467,11469,11471,11473,11475,11477,11479,11481,11483,11485,11487,11489,11491,11493,11495,11497,11499,11501,11503,11505,11507,11509,11511,11513,11515,11517,11519,11521,11523,11525,11527,11529,11531,11533,11535,11537,11539,11541,11543,11545,11547,11549,11551,11553,11555,11557,11559,11561,11563,11565,11567,11569,11571,11573,11575,11577,11579,11581,11583,11585,11587,11589,11591,11593,11595,11597,11599,11601,11603,11605,11607,11609,11611,11613,11615,11617,11619,11621,11623,11625,11627,11629,11631,11633,11635,11637,11639,11641,11643,11645,11647,11649,11651,11653,11655,11657,11659,11661,11663,11665,11667,11669,11671,11673,11675,11677,11679,11681,11683,11685,11687,11689,11691,11693,11695,11697,11699,11701,11703,11705,11707,11709,11711,11713,11715,11717,11719,11721,11723,11725,11727,11729,11731,11733,11735,11737,11739,11741,11743,11745,11747,11749,11751,11753,11755,11757,11759,11761,11763,11765,11767,11769,11771,11773,11775,11777,11779,11781,11783,11785,11787,11789,11791,11793,11795,11797,11799,11801,11803,11805,11807,11809,11811,11813,11815,11817,11819,11821,11823,11825,11827,11829,11831,11833,11835,11837,11839,11841,11843,11845,11847,11849,11851,11853,11855,11857,11859,11861,11863,11865,11867,11869,11871,11873,11875,11877,11879,11881,11883,11885,11887,11889,11891,11893,11895,11897,11899,11901,11903,11905,11907,11909,11911,11913,11915,11917,11919,11921,11923,11925,11927,11929,11931,11933,11935,11937,11939,11941,11943,11945,11947,11949,11951,11953,11955,11957,11959,11961,11963,11965,11967,11969,11971,11973,11975,11977,11979,11981,11983,11985,11987,11989,11991,11993,11995,11997,11999,12001,12003,12005,12007,12009,12011,12013,12015,12017,12019,12021,12023,12025,12027,12029,12031,12033,12035,12037,12039,12041,12043,12045,12047,12049,12051,12053,12055,12057,12059,12061,12063,12065,12067,12069,12071,12073,12075,12077,12079,12081,12083,12085,12087,12089,12091,12093,12095,12097,12099,12101,12103,12105,12107,12109,12111,12113,12115,12117,12119,12121,12123,12125,12127,12129,12131,12133,12135,12137,12139,12141,12143,12145,12147,12149,12151,12153,12155,12157,12159,12161,12163,12165,12167,12169,12171,12173,12175,12177,12179,12181,12183,12185,12187,12189,12191,12193,12195,12197,12199,12201,12203,12205,12207,12209,12211,12213,12215,12217,12219,12221,12223,12225,12227,12229,12231,12233,12235,12237,12239,12241,12243,12245,12247,12249,12251,12253,12255,12257,12259,12261,12263,12265,12267,12269,12271,12273,12275,12277,12279,12281,12283,12285,12287,12289,12291,12293,12295,12297,12299,12301,12303,12305,12307,12309,12311,12313,12315,12317,12319,12321,12323,12325,12327,12329,12331,12333,12335,12337,12339,12341,12343,12345,12347,12349,12351,12353,12355,12357,12359,12361,12363,12365,12367,12369,12371,12373,12375,12377,12379,12381,12383,12385,12387,12389,12391,12393,12395,12397,12399,12401,12403,12405,12407,12409,12411,12413,12415,12417,12419,12421,12423,12425,12427,12429,12431,12433,12435,12437,12439,12441,12443,12445,12447,12449,12451,12453,12455,12457,12459,12461,12463,12465,12467,12469,12471,12473,12475,12477,12479,12481,12483,12485,12487,12489,12491,12493,12495,12497,12499,12501,12503,12505,12507,12509,12511,12513,12515,12517,12519,12521,12523,12525,12527,12529,12531,12533,12535,12537,12539,12541,12543,12545,12547,12549,12551,12553,12556,12558,12560,12562,12564,12566,12568,12570,12572,12574,12576,12578,12580,12582,12584,12586,12588,12590,12592,12594,12596,12598,12600,12602,12604,12606],{"class":251,"line":266},[249,9954,269],{"class":255},[249,9956,272],{"class":255},[249,9958,276],{"class":275},[249,9960,272],{"class":255},[249,9962,281],{"class":255},[249,9964,272],{"class":255},[249,9966,9967],{"class":286},"9bb12e97685f0e01",[249,9969,272],{"class":255},[249,9971,292],{"class":255},[249,9973,272],{"class":255},[249,9975,297],{"class":275},[249,9977,272],{"class":255},[249,9979,281],{"class":255},[249,9981,272],{"class":255},[249,9983,103],{"class":286},[249,9985,272],{"class":255},[249,9987,292],{"class":255},[249,9989,272],{"class":255},[249,9991,315],{"class":275},[249,9993,272],{"class":255},[249,9995,281],{"class":255},[249,9997,272],{"class":255},[249,9999,3753],{"class":286},[249,10001,272],{"class":255},[249,10003,292],{"class":255},[249,10005,272],{"class":255},[249,10007,671],{"class":275},[249,10009,272],{"class":255},[249,10011,281],{"class":255},[249,10013,272],{"class":255},[249,10015,10016],{"class":286},"e7cdada1bef716e5",[249,10018,272],{"class":255},[249,10020,292],{"class":255},[249,10022,272],{"class":255},[249,10024,306],{"class":275},[249,10026,272],{"class":255},[249,10028,281],{"class":255},[249,10030,272],{"class":255},[249,10032,10033],{"class":286},"13c06e7c625a1885",[249,10035,272],{"class":255},[249,10037,292],{"class":255},[249,10039,272],{"class":255},[249,10041,3553],{"class":275},[249,10043,272],{"class":255},[249,10045,281],{"class":255},[249,10047,786],{"class":255},[249,10049,292],{"class":255},[249,10051,272],{"class":255},[249,10053,3808],{"class":275},[249,10055,272],{"class":255},[249,10057,281],{"class":255},[249,10059,786],{"class":255},[249,10061,292],{"class":255},[249,10063,272],{"class":255},[249,10065,688],{"class":275},[249,10067,272],{"class":255},[249,10069,281],{"class":255},[249,10071,272],{"class":255},[249,10073,9930],{"class":286},[249,10075,272],{"class":255},[249,10077,292],{"class":255},[249,10079,272],{"class":255},[249,10081,3837],{"class":275},[249,10083,272],{"class":255},[249,10085,281],{"class":255},[249,10087,371],{"class":571},[249,10089,292],{"class":255},[249,10091,272],{"class":255},[249,10093,3850],{"class":275},[249,10095,272],{"class":255},[249,10097,281],{"class":255},[249,10099,2149],{"class":571},[249,10101,292],{"class":255},[249,10103,272],{"class":255},[249,10105,3863],{"class":275},[249,10107,272],{"class":255},[249,10109,281],{"class":255},[249,10111,2149],{"class":571},[249,10113,292],{"class":255},[249,10115,272],{"class":255},[249,10117,3876],{"class":275},[249,10119,272],{"class":255},[249,10121,281],{"class":255},[249,10123,786],{"class":255},[249,10125,292],{"class":255},[249,10127,272],{"class":255},[249,10129,3889],{"class":275},[249,10131,272],{"class":255},[249,10133,281],{"class":255},[249,10135,272],{"class":255},[249,10137,3898],{"class":286},[249,10139,940],{"class":259},[249,10141,10142],{"class":286},"    \u003Cv-card class=",[249,10144,3906],{"class":259},[249,10146,10147],{"class":286},"pa-4",[249,10149,3906],{"class":259},[249,10151,6428],{"class":286},[249,10153,3906],{"class":259},[249,10155,371],{"class":286},[249,10157,3906],{"class":259},[249,10159,6437],{"class":286},[249,10161,3906],{"class":259},[249,10163,6442],{"class":286},[249,10165,3906],{"class":259},[249,10167,3924],{"class":286},[249,10169,1667],{"class":259},[249,10171,10172],{"class":286},"        \u003C!-- Toolbar -->",[249,10174,940],{"class":259},[249,10176,10177],{"class":286},"        \u003Cv-row dense align=",[249,10179,3906],{"class":259},[249,10181,6456],{"class":286},[249,10183,3906],{"class":259},[249,10185,6548],{"class":286},[249,10187,3906],{"class":259},[249,10189,10190],{"class":286},"mb-2",[249,10192,3906],{"class":259},[249,10194,3924],{"class":286},[249,10196,940],{"class":259},[249,10198,6850],{"class":286},[249,10200,3906],{"class":259},[249,10202,4928],{"class":286},[249,10204,3906],{"class":259},[249,10206,6474],{"class":286},[249,10208,3906],{"class":259},[249,10210,6543],{"class":286},[249,10212,3906],{"class":259},[249,10214,3924],{"class":286},[249,10216,940],{"class":259},[249,10218,10219],{"class":286},"                \u003Cdiv class=",[249,10221,3906],{"class":259},[249,10223,10224],{"class":286},"text-subtitle-1 font-weight-bold",[249,10226,3906],{"class":259},[249,10228,3924],{"class":286},[249,10230,940],{"class":259},[249,10232,10233],{"class":286},"                    Asset Detail\u003Cspan v-if=",[249,10235,3906],{"class":259},[249,10237,10238],{"class":286},"windowLabel",[249,10240,3906],{"class":259},[249,10242,10243],{"class":286},"> &middot; {{ windowLabel }}\u003C\u002Fspan>",[249,10245,940],{"class":259},[249,10247,10248],{"class":286},"                \u003C\u002Fdiv>",[249,10250,940],{"class":259},[249,10252,10219],{"class":286},[249,10254,3906],{"class":259},[249,10256,6915],{"class":286},[249,10258,3906],{"class":259},[249,10260,3924],{"class":286},[249,10262,940],{"class":259},[249,10264,10265],{"class":286},"                    {{ filteredRows.length }} of {{ rows.length }} due in this window",[249,10267,940],{"class":259},[249,10269,10248],{"class":286},[249,10271,940],{"class":259},[249,10273,6966],{"class":286},[249,10275,1667],{"class":259},[249,10277,6850],{"class":286},[249,10279,3906],{"class":259},[249,10281,4928],{"class":286},[249,10283,3906],{"class":259},[249,10285,6474],{"class":286},[249,10287,3906],{"class":259},[249,10289,7558],{"class":286},[249,10291,3906],{"class":259},[249,10293,3924],{"class":286},[249,10295,940],{"class":259},[249,10297,10298],{"class":286},"                \u003Cv-btn-toggle v-model=",[249,10300,3906],{"class":259},[249,10302,10303],{"class":286},"statusFilter",[249,10305,3906],{"class":259},[249,10307,3976],{"class":286},[249,10309,3906],{"class":259},[249,10311,3981],{"class":286},[249,10313,3906],{"class":259},[249,10315,3986],{"class":286},[249,10317,3906],{"class":259},[249,10319,10320],{"class":286},"outlined",[249,10322,3906],{"class":259},[249,10324,10325],{"class":286}," divided mandatory>",[249,10327,940],{"class":259},[249,10329,10330],{"class":286},"                    \u003Cv-btn value=",[249,10332,3906],{"class":259},[249,10334,3665],{"class":286},[249,10336,3906],{"class":259},[249,10338,6589],{"class":286},[249,10340,3906],{"class":259},[249,10342,6594],{"class":286},[249,10344,3906],{"class":259},[249,10346,10347],{"class":286},">All\u003C\u002Fv-btn>",[249,10349,940],{"class":259},[249,10351,10330],{"class":286},[249,10353,3906],{"class":259},[249,10355,10356],{"class":286},"Overdue",[249,10358,3906],{"class":259},[249,10360,6589],{"class":286},[249,10362,3906],{"class":259},[249,10364,6594],{"class":286},[249,10366,3906],{"class":259},[249,10368,6571],{"class":286},[249,10370,3906],{"class":259},[249,10372,7753],{"class":286},[249,10374,3906],{"class":259},[249,10376,3924],{"class":286},[249,10378,940],{"class":259},[249,10380,10381],{"class":286},"                        Overdue ({{ counts.Overdue }})",[249,10383,940],{"class":259},[249,10385,10386],{"class":286},"                    \u003C\u002Fv-btn>",[249,10388,940],{"class":259},[249,10390,10330],{"class":286},[249,10392,3906],{"class":259},[249,10394,10395],{"class":286},"DueSoon",[249,10397,3906],{"class":259},[249,10399,6589],{"class":286},[249,10401,3906],{"class":259},[249,10403,6594],{"class":286},[249,10405,3906],{"class":259},[249,10407,6571],{"class":286},[249,10409,3906],{"class":259},[249,10411,6792],{"class":286},[249,10413,3906],{"class":259},[249,10415,3924],{"class":286},[249,10417,940],{"class":259},[249,10419,10420],{"class":286},"                        Due soon ({{ counts.DueSoon }})",[249,10422,940],{"class":259},[249,10424,10386],{"class":286},[249,10426,940],{"class":259},[249,10428,10330],{"class":286},[249,10430,3906],{"class":259},[249,10432,10433],{"class":286},"Valid",[249,10435,3906],{"class":259},[249,10437,6589],{"class":286},[249,10439,3906],{"class":259},[249,10441,6594],{"class":286},[249,10443,3906],{"class":259},[249,10445,6571],{"class":286},[249,10447,3906],{"class":259},[249,10449,7585],{"class":286},[249,10451,3906],{"class":259},[249,10453,3924],{"class":286},[249,10455,940],{"class":259},[249,10457,10458],{"class":286},"                        Valid ({{ counts.Valid }})",[249,10460,940],{"class":259},[249,10462,10386],{"class":286},[249,10464,940],{"class":259},[249,10466,10467],{"class":286},"                \u003C\u002Fv-btn-toggle>",[249,10469,940],{"class":259},[249,10471,6966],{"class":286},[249,10473,1667],{"class":259},[249,10475,6850],{"class":286},[249,10477,3906],{"class":259},[249,10479,4928],{"class":286},[249,10481,3906],{"class":259},[249,10483,6474],{"class":286},[249,10485,3906],{"class":259},[249,10487,4775],{"class":286},[249,10489,3906],{"class":259},[249,10491,3924],{"class":286},[249,10493,940],{"class":259},[249,10495,10496],{"class":286},"                \u003Cv-text-field v-model=",[249,10498,3906],{"class":259},[249,10500,10501],{"class":286},"search",[249,10503,3906],{"class":259},[249,10505,3967],{"class":286},[249,10507,3906],{"class":259},[249,10509,10510],{"class":286},"Search assets",[249,10512,3906],{"class":259},[249,10514,3976],{"class":286},[249,10516,3906],{"class":259},[249,10518,3981],{"class":286},[249,10520,3906],{"class":259},[249,10522,3986],{"class":286},[249,10524,3906],{"class":259},[249,10526,3991],{"class":286},[249,10528,3994],{"class":259},[249,10530,10531],{"class":286},"                    hide-details clearable prepend-inner-icon=",[249,10533,3906],{"class":259},[249,10535,10536],{"class":286},"mdi-magnify",[249,10538,3906],{"class":259},[249,10540,10541],{"class":286},">\u003C\u002Fv-text-field>",[249,10543,940],{"class":259},[249,10545,6966],{"class":286},[249,10547,940],{"class":259},[249,10549,7494],{"class":286},[249,10551,1667],{"class":259},[249,10553,10554],{"class":286},"        \u003Cv-data-table :headers=",[249,10556,3906],{"class":259},[249,10558,10559],{"class":286},"visibleHeaders",[249,10561,3906],{"class":259},[249,10563,3957],{"class":286},[249,10565,3906],{"class":259},[249,10567,10568],{"class":286},"filteredRows",[249,10570,3906],{"class":259},[249,10572,10573],{"class":286}," :search=",[249,10575,3906],{"class":259},[249,10577,10501],{"class":286},[249,10579,3906],{"class":259},[249,10581,10582],{"class":286}," :sort-by=",[249,10584,3906],{"class":259},[249,10586,10587],{"class":286},"sortBy",[249,10589,3994],{"class":259},[249,10591,10592],{"class":286},"            :items-per-page=",[249,10594,3906],{"class":259},[249,10596,10597],{"class":286},"10",[249,10599,3906],{"class":259},[249,10601,3976],{"class":286},[249,10603,3906],{"class":259},[249,10605,3981],{"class":286},[249,10607,3906],{"class":259},[249,10609,10610],{"class":286}," item-value=",[249,10612,3906],{"class":259},[249,10614,3337],{"class":286},[249,10616,3906],{"class":259},[249,10618,10619],{"class":286}," fixed-header height=",[249,10621,3906],{"class":259},[249,10623,10624],{"class":286},"420",[249,10626,3906],{"class":259},[249,10628,10629],{"class":286}," hover>",[249,10631,1667],{"class":259},[249,10633,10634],{"class":286},"            \u003Ctemplate #item.status=",[249,10636,3906],{"class":259},[249,10638,10639],{"class":286},"{ item }",[249,10641,3906],{"class":259},[249,10643,3924],{"class":286},[249,10645,940],{"class":259},[249,10647,10648],{"class":286},"                \u003Cv-chip :color=",[249,10650,3906],{"class":259},[249,10652,10653],{"class":286},"cell(item).status_color",[249,10655,3906],{"class":259},[249,10657,6589],{"class":286},[249,10659,3906],{"class":259},[249,10661,6594],{"class":286},[249,10663,3906],{"class":259},[249,10665,3986],{"class":286},[249,10667,3906],{"class":259},[249,10669,10670],{"class":286},"flat",[249,10672,3906],{"class":259},[249,10674,3924],{"class":286},[249,10676,940],{"class":259},[249,10678,10679],{"class":286},"                    {{ cell(item).status }}",[249,10681,940],{"class":259},[249,10683,10684],{"class":286},"                \u003C\u002Fv-chip>",[249,10686,940],{"class":259},[249,10688,10689],{"class":286},"            \u003C\u002Ftemplate>",[249,10691,1667],{"class":259},[249,10693,10694],{"class":286},"            \u003Ctemplate #item.last_calibration_ts=",[249,10696,3906],{"class":259},[249,10698,10639],{"class":286},[249,10700,3906],{"class":259},[249,10702,3924],{"class":286},[249,10704,940],{"class":259},[249,10706,10707],{"class":286},"                {{ cell(item).last_cal_text }}",[249,10709,940],{"class":259},[249,10711,10689],{"class":286},[249,10713,1667],{"class":259},[249,10715,10716],{"class":286},"            \u003Ctemplate #item.next_due_ts=",[249,10718,3906],{"class":259},[249,10720,10639],{"class":286},[249,10722,3906],{"class":259},[249,10724,3924],{"class":286},[249,10726,940],{"class":259},[249,10728,10729],{"class":286},"                \u003Cspan :class=",[249,10731,3906],{"class":259},[249,10733,10734],{"class":286},"cell(item).days_remaining \u003C 0 ? 'text-error font-weight-bold' : ''",[249,10736,3906],{"class":259},[249,10738,3924],{"class":286},[249,10740,940],{"class":259},[249,10742,10743],{"class":286},"                    {{ cell(item).next_due_text }}",[249,10745,940],{"class":259},[249,10747,10748],{"class":286},"                \u003C\u002Fspan>",[249,10750,940],{"class":259},[249,10752,10689],{"class":286},[249,10754,1667],{"class":259},[249,10756,10757],{"class":286},"            \u003Ctemplate #item.days_remaining=",[249,10759,3906],{"class":259},[249,10761,10639],{"class":286},[249,10763,3906],{"class":259},[249,10765,3924],{"class":286},[249,10767,940],{"class":259},[249,10769,10729],{"class":286},[249,10771,3906],{"class":259},[249,10773,10734],{"class":286},[249,10775,3906],{"class":259},[249,10777,3924],{"class":286},[249,10779,940],{"class":259},[249,10781,10782],{"class":286},"                    {{ cell(item).days_text }}",[249,10784,940],{"class":259},[249,10786,10748],{"class":286},[249,10788,940],{"class":259},[249,10790,10689],{"class":286},[249,10792,1667],{"class":259},[249,10794,10795],{"class":286},"            \u003Ctemplate #item.calibration_interval_months=",[249,10797,3906],{"class":259},[249,10799,10639],{"class":286},[249,10801,3906],{"class":259},[249,10803,3924],{"class":286},[249,10805,940],{"class":259},[249,10807,10808],{"class":286},"                {{ cell(item).calibration_interval_months }} mo",[249,10810,940],{"class":259},[249,10812,10689],{"class":286},[249,10814,1667],{"class":259},[249,10816,10817],{"class":286},"            \u003Ctemplate #no-data>",[249,10819,940],{"class":259},[249,10821,10219],{"class":286},[249,10823,3906],{"class":259},[249,10825,10826],{"class":286},"pa-6 text-center text-medium-emphasis",[249,10828,3906],{"class":259},[249,10830,3924],{"class":286},[249,10832,940],{"class":259},[249,10834,10835],{"class":286},"                    No assets match the current filters.",[249,10837,940],{"class":259},[249,10839,10248],{"class":286},[249,10841,940],{"class":259},[249,10843,10689],{"class":286},[249,10845,1667],{"class":259},[249,10847,10848],{"class":286},"        \u003C\u002Fv-data-table>",[249,10850,940],{"class":259},[249,10852,10853],{"class":286},"    \u003C\u002Fv-card>",[249,10855,940],{"class":259},[249,10857,4100],{"class":286},[249,10859,1667],{"class":259},[249,10861,4105],{"class":286},[249,10863,940],{"class":259},[249,10865,7821],{"class":286},[249,10867,940],{"class":259},[249,10869,7826],{"class":286},[249,10871,940],{"class":259},[249,10873,7831],{"class":286},[249,10875,940],{"class":259},[249,10877,10878],{"class":286},"                rows: [],",[249,10880,940],{"class":259},[249,10882,10883],{"class":286},"                windowLabel: '',",[249,10885,940],{"class":259},[249,10887,10888],{"class":286},"                search: '',",[249,10890,940],{"class":259},[249,10892,10893],{"class":286},"                statusFilter: 'All',",[249,10895,940],{"class":259},[249,10897,10898],{"class":286},"                sortBy: [{ key: 'next_due_ts', order: 'asc' }],",[249,10900,940],{"class":259},[249,10902,10903],{"class":286},"                headers: [",[249,10905,940],{"class":259},[249,10907,10908],{"class":286},"                    { title: 'Tool ID', key: 'tool_id', width: '110px' },",[249,10910,940],{"class":259},[249,10912,10913],{"class":286},"                    { title: 'Equipment', key: 'equipment_name' },",[249,10915,940],{"class":259},[249,10917,10918],{"class":286},"                    { title: 'Department', key: 'department', width: '130px' },",[249,10920,940],{"class":259},[249,10922,10923],{"class":286},"                    { title: 'Location', key: 'location', width: '140px' },",[249,10925,940],{"class":259},[249,10927,10928],{"class":286},"                    { title: 'Status', key: 'status', width: '120px' },",[249,10930,940],{"class":259},[249,10932,10933],{"class":286},"                    { title: 'Interval', key: 'calibration_interval_months', width: '100px' },",[249,10935,940],{"class":259},[249,10937,10938],{"class":286},"                    { title: 'Last calibrated', key: 'last_calibration_ts', width: '140px' },",[249,10940,940],{"class":259},[249,10942,10943],{"class":286},"                    { title: 'Next due', key: 'next_due_ts', width: '140px' },",[249,10945,940],{"class":259},[249,10947,10948],{"class":286},"                    { title: 'Remaining', key: 'days_remaining', align: 'end', width: '120px' }",[249,10950,940],{"class":259},[249,10952,10953],{"class":286},"                ]",[249,10955,940],{"class":259},[249,10957,7926],{"class":286},[249,10959,940],{"class":259},[249,10961,7931],{"class":286},[249,10963,1667],{"class":259},[249,10965,7936],{"class":286},[249,10967,940],{"class":259},[249,10969,10970],{"class":286},"            filteredRows() {",[249,10972,940],{"class":259},[249,10974,10975],{"class":286},"                if (this.statusFilter === 'All') return this.rows",[249,10977,940],{"class":259},[249,10979,10980],{"class":286},"                return this.rows.filter(r => r.status === this.statusFilter)",[249,10982,940],{"class":259},[249,10984,8169],{"class":286},[249,10986,1667],{"class":259},[249,10988,10989],{"class":286},"            \u002F\u002F A single-department view makes that column a constant, so drop it.",[249,10991,940],{"class":259},[249,10993,10994],{"class":286},"            visibleHeaders() {",[249,10996,940],{"class":259},[249,10998,10999],{"class":286},"                const depts = new Set(this.rows.map(r => r.department))",[249,11001,940],{"class":259},[249,11003,11004],{"class":286},"                if (depts.size > 1) return this.headers",[249,11006,940],{"class":259},[249,11008,11009],{"class":286},"                return this.headers.filter(h => h.key !== 'department')",[249,11011,940],{"class":259},[249,11013,8169],{"class":286},[249,11015,1667],{"class":259},[249,11017,11018],{"class":286},"            counts() {",[249,11020,940],{"class":259},[249,11022,11023],{"class":286},"                const c = { Overdue: 0, DueSoon: 0, Valid: 0 }",[249,11025,940],{"class":259},[249,11027,11028],{"class":286},"                for (const r of this.rows) {",[249,11030,940],{"class":259},[249,11032,11033],{"class":286},"                    if (c[r.status] !== undefined) c[r.status]++",[249,11035,940],{"class":259},[249,11037,7921],{"class":286},[249,11039,940],{"class":259},[249,11041,11042],{"class":286},"                return c",[249,11044,940],{"class":259},[249,11046,7926],{"class":286},[249,11048,940],{"class":259},[249,11050,7931],{"class":286},[249,11052,1667],{"class":259},[249,11054,7994],{"class":286},[249,11056,940],{"class":259},[249,11058,7999],{"class":286},[249,11060,940],{"class":259},[249,11062,8004],{"class":286},[249,11064,940],{"class":259},[249,11066,8009],{"class":286},[249,11068,940],{"class":259},[249,11070,8014],{"class":286},[249,11072,940],{"class":259},[249,11074,7926],{"class":286},[249,11076,940],{"class":259},[249,11078,7931],{"class":286},[249,11080,1667],{"class":259},[249,11082,8027],{"class":286},[249,11084,940],{"class":259},[249,11086,8032],{"class":286},[249,11088,940],{"class":259},[249,11090,8037],{"class":286},[249,11092,940],{"class":259},[249,11094,7931],{"class":286},[249,11096,1667],{"class":259},[249,11098,8046],{"class":286},[249,11100,940],{"class":259},[249,11102,8051],{"class":286},[249,11104,940],{"class":259},[249,11106,7931],{"class":286},[249,11108,1667],{"class":259},[249,11110,8060],{"class":286},[249,11112,940],{"class":259},[249,11114,8065],{"class":286},[249,11116,940],{"class":259},[249,11118,8070],{"class":286},[249,11120,940],{"class":259},[249,11122,11123],{"class":286},"                if (!Array.isArray(payload)) return",[249,11125,1667],{"class":259},[249,11127,11128],{"class":286},"                \u002F\u002F Constant across rows; used to caption the table's scope.",[249,11130,940],{"class":259},[249,11132,11133],{"class":286},"                if (payload[0] && payload[0].filter_window) {",[249,11135,940],{"class":259},[249,11137,11138],{"class":286},"                    this.windowLabel = payload[0].filter_window",[249,11140,940],{"class":259},[249,11142,7921],{"class":286},[249,11144,1667],{"class":259},[249,11146,11147],{"class":286},"                this.rows = payload",[249,11149,940],{"class":259},[249,11151,11152],{"class":286},"                    .filter(r => r && typeof r === 'object')",[249,11154,940],{"class":259},[249,11156,11157],{"class":286},"                    .map(r => {",[249,11159,940],{"class":259},[249,11161,11162],{"class":286},"                        const days = (r.days_remaining === null || r.days_remaining === undefined)",[249,11164,940],{"class":259},[249,11166,11167],{"class":286},"                            ? null",[249,11169,940],{"class":259},[249,11171,11172],{"class":286},"                            : Number(r.days_remaining)",[249,11174,940],{"class":259},[249,11176,11177],{"class":286},"                        return {",[249,11179,940],{"class":259},[249,11181,11182],{"class":286},"                            ...r,",[249,11184,940],{"class":259},[249,11186,11187],{"class":286},"                            days_remaining: days,",[249,11189,940],{"class":259},[249,11191,11192],{"class":286},"                            last_cal_text: this.fmtDate(r.last_calibration_ts),",[249,11194,940],{"class":259},[249,11196,11197],{"class":286},"                            next_due_text: this.fmtDate(r.next_due_ts),",[249,11199,940],{"class":259},[249,11201,11202],{"class":286},"                            days_text: this.daysText(days),",[249,11204,940],{"class":259},[249,11206,11207],{"class":286},"                            status_color: this.statusColor(r.status)",[249,11209,940],{"class":259},[249,11211,11212],{"class":286},"                        }",[249,11214,940],{"class":259},[249,11216,11217],{"class":286},"                    })",[249,11219,940],{"class":259},[249,11221,8169],{"class":286},[249,11223,1667],{"class":259},[249,11225,11226],{"class":286},"            \u002F\u002F Vuetify 3 passes the raw item on some minors and a wrapper on",[249,11228,940],{"class":259},[249,11230,11231],{"class":286},"            \u002F\u002F others, so normalise before reading fields.",[249,11233,940],{"class":259},[249,11235,11236],{"class":286},"            cell(item) {",[249,11238,940],{"class":259},[249,11240,11241],{"class":286},"                return (item && item.raw) ? item.raw : item",[249,11243,940],{"class":259},[249,11245,8169],{"class":286},[249,11247,1667],{"class":259},[249,11249,11250],{"class":286},"            fmtDate(value) {",[249,11252,940],{"class":259},[249,11254,11255],{"class":286},"                if (!value) return '-'",[249,11257,940],{"class":259},[249,11259,11260],{"class":286},"                const d = new Date(value)",[249,11262,940],{"class":259},[249,11264,11265],{"class":286},"                if (isNaN(d.getTime())) return value",[249,11267,940],{"class":259},[249,11269,11270],{"class":286},"                return d.toLocaleDateString([], { day: '2-digit', month: 'short', year: 'numeric' })",[249,11272,940],{"class":259},[249,11274,8169],{"class":286},[249,11276,1667],{"class":259},[249,11278,11279],{"class":286},"            daysText(days) {",[249,11281,940],{"class":259},[249,11283,11284],{"class":286},"                if (days === null) return '-'",[249,11286,940],{"class":259},[249,11288,11289],{"class":286},"                if (days \u003C 0) return Math.abs(days) + 'd overdue'",[249,11291,940],{"class":259},[249,11293,11294],{"class":286},"                if (days === 0) return 'due today'",[249,11296,940],{"class":259},[249,11298,11299],{"class":286},"                return days + 'd'",[249,11301,940],{"class":259},[249,11303,8169],{"class":286},[249,11305,1667],{"class":259},[249,11307,11308],{"class":286},"            statusColor(status) {",[249,11310,940],{"class":259},[249,11312,11313],{"class":286},"                if (status === 'Overdue') return 'error'",[249,11315,940],{"class":259},[249,11317,11318],{"class":286},"                if (status === 'DueSoon') return 'warning'",[249,11320,940],{"class":259},[249,11322,11323],{"class":286},"                if (status === 'Valid') return 'success'",[249,11325,940],{"class":259},[249,11327,11328],{"class":286},"                return 'grey'",[249,11330,940],{"class":259},[249,11332,7926],{"class":286},[249,11334,940],{"class":259},[249,11336,4361],{"class":286},[249,11338,940],{"class":259},[249,11340,4410],{"class":286},[249,11342,940],{"class":259},[249,11344,4419],{"class":286},[249,11346,272],{"class":255},[249,11348,292],{"class":255},[249,11350,272],{"class":255},[249,11352,4486],{"class":275},[249,11354,272],{"class":255},[249,11356,421],{"class":255},[249,11358,272],{"class":255},[249,11360,4495],{"class":275},[249,11362,272],{"class":255},[249,11364,729],{"class":255},[249,11366,272],{"class":255},[249,11368,4504],{"class":275},[249,11370,272],{"class":255},[249,11372,421],{"class":255},[249,11374,272],{"class":255},[249,11376,4513],{"class":275},[249,11378,272],{"class":255},[249,11380,281],{"class":255},[249,11382,272],{"class":255},[249,11384,8398],{"class":286},[249,11386,272],{"class":255},[249,11388,292],{"class":255},[249,11390,272],{"class":255},[249,11392,4531],{"class":275},[249,11394,272],{"class":255},[249,11396,281],{"class":255},[249,11398,786],{"class":255},[249,11400,292],{"class":255},[249,11402,272],{"class":255},[249,11404,564],{"class":275},[249,11406,272],{"class":255},[249,11408,281],{"class":255},[249,11410,11411],{"class":571},"590",[249,11413,292],{"class":255},[249,11415,272],{"class":255},[249,11417,579],{"class":275},[249,11419,272],{"class":255},[249,11421,281],{"class":255},[249,11423,11424],{"class":571},"400",[249,11426,292],{"class":255},[249,11428,272],{"class":255},[249,11430,837],{"class":275},[249,11432,272],{"class":255},[249,11434,8449],{"class":255},[249,11436,272],{"class":255},[249,11438,276],{"class":275},[249,11440,272],{"class":255},[249,11442,281],{"class":255},[249,11444,272],{"class":255},[249,11446,10033],{"class":286},[249,11448,272],{"class":255},[249,11450,292],{"class":255},[249,11452,272],{"class":255},[249,11454,297],{"class":275},[249,11456,272],{"class":255},[249,11458,281],{"class":255},[249,11460,272],{"class":255},[249,11462,122],{"class":286},[249,11464,272],{"class":255},[249,11466,292],{"class":255},[249,11468,272],{"class":255},[249,11470,688],{"class":275},[249,11472,272],{"class":255},[249,11474,281],{"class":255},[249,11476,272],{"class":255},[249,11478,3516],{"class":286},[249,11480,272],{"class":255},[249,11482,292],{"class":255},[249,11484,272],{"class":255},[249,11486,3553],{"class":275},[249,11488,272],{"class":255},[249,11490,281],{"class":255},[249,11492,272],{"class":255},[249,11494,3799],{"class":286},[249,11496,272],{"class":255},[249,11498,292],{"class":255},[249,11500,272],{"class":255},[249,11502,3850],{"class":275},[249,11504,272],{"class":255},[249,11506,281],{"class":255},[249,11508,272],{"class":255},[249,11510,4928],{"class":286},[249,11512,272],{"class":255},[249,11514,292],{"class":255},[249,11516,272],{"class":255},[249,11518,3863],{"class":275},[249,11520,272],{"class":255},[249,11522,281],{"class":255},[249,11524,371],{"class":571},[249,11526,292],{"class":255},[249,11528,272],{"class":255},[249,11530,3837],{"class":275},[249,11532,272],{"class":255},[249,11534,281],{"class":255},[249,11536,6872],{"class":571},[249,11538,292],{"class":255},[249,11540,272],{"class":255},[249,11542,8558],{"class":275},[249,11544,272],{"class":255},[249,11546,729],{"class":255},[249,11548,272],{"class":255},[249,11550,4531],{"class":275},[249,11552,272],{"class":255},[249,11554,281],{"class":255},[249,11556,786],{"class":255},[249,11558,292],{"class":255},[249,11560,272],{"class":255},[249,11562,4961],{"class":275},[249,11564,272],{"class":255},[249,11566,281],{"class":255},[249,11568,272],{"class":255},[249,11570,4970],{"class":286},[249,11572,272],{"class":255},[249,11574,292],{"class":255},[249,11576,272],{"class":255},[249,11578,4979],{"class":275},[249,11580,272],{"class":255},[249,11582,281],{"class":255},[249,11584,272],{"class":255},[249,11586,4988],{"class":286},[249,11588,272],{"class":255},[249,11590,292],{"class":255},[249,11592,272],{"class":255},[249,11594,8611],{"class":275},[249,11596,272],{"class":255},[249,11598,281],{"class":255},[249,11600,272],{"class":255},[249,11602,5287],{"class":286},[249,11604,272],{"class":255},[249,11606,617],{"class":255},[249,11608,272],{"class":255},[249,11610,276],{"class":275},[249,11612,272],{"class":255},[249,11614,281],{"class":255},[249,11616,272],{"class":255},[249,11618,3799],{"class":286},[249,11620,272],{"class":255},[249,11622,292],{"class":255},[249,11624,272],{"class":255},[249,11626,297],{"class":275},[249,11628,272],{"class":255},[249,11630,281],{"class":255},[249,11632,272],{"class":255},[249,11634,119],{"class":286},[249,11636,272],{"class":255},[249,11638,292],{"class":255},[249,11640,272],{"class":255},[249,11642,688],{"class":275},[249,11644,272],{"class":255},[249,11646,281],{"class":255},[249,11648,272],{"class":255},[249,11650,3466],{"class":286},[249,11652,272],{"class":255},[249,11654,292],{"class":255},[249,11656,272],{"class":255},[249,11658,3808],{"class":275},[249,11660,272],{"class":255},[249,11662,281],{"class":255},[249,11664,272],{"class":255},[249,11666,4643],{"class":286},[249,11668,272],{"class":255},[249,11670,292],{"class":255},[249,11672,272],{"class":255},[249,11674,4652],{"class":275},[249,11676,272],{"class":255},[249,11678,281],{"class":255},[249,11680,272],{"class":255},[249,11682,3470],{"class":286},[249,11684,272],{"class":255},[249,11686,292],{"class":255},[249,11688,272],{"class":255},[249,11690,4669],{"class":275},[249,11692,272],{"class":255},[249,11694,281],{"class":255},[249,11696,272],{"class":255},[249,11698,4678],{"class":286},[249,11700,272],{"class":255},[249,11702,292],{"class":255},[249,11704,272],{"class":255},[249,11706,4687],{"class":275},[249,11708,272],{"class":255},[249,11710,281],{"class":255},[249,11712,272],{"class":255},[249,11714,4696],{"class":286},[249,11716,272],{"class":255},[249,11718,292],{"class":255},[249,11720,272],{"class":255},[249,11722,4705],{"class":275},[249,11724,272],{"class":255},[249,11726,281],{"class":255},[249,11728,272],{"class":255},[249,11730,4714],{"class":286},[249,11732,272],{"class":255},[249,11734,292],{"class":255},[249,11736,272],{"class":255},[249,11738,4723],{"class":275},[249,11740,272],{"class":255},[249,11742,1165],{"class":255},[249,11744,272],{"class":255},[249,11746,688],{"class":343},[249,11748,272],{"class":255},[249,11750,281],{"class":255},[249,11752,272],{"class":255},[249,11754,4740],{"class":286},[249,11756,272],{"class":255},[249,11758,292],{"class":255},[249,11760,272],{"class":255},[249,11762,4749],{"class":343},[249,11764,272],{"class":255},[249,11766,281],{"class":255},[249,11768,272],{"class":255},[249,11770,2149],{"class":286},[249,11772,272],{"class":255},[249,11774,292],{"class":255},[249,11776,272],{"class":255},[249,11778,4766],{"class":343},[249,11780,272],{"class":255},[249,11782,281],{"class":255},[249,11784,272],{"class":255},[249,11786,4775],{"class":286},[249,11788,272],{"class":255},[249,11790,617],{"class":255},[249,11792,272],{"class":255},[249,11794,688],{"class":343},[249,11796,272],{"class":255},[249,11798,281],{"class":255},[249,11800,272],{"class":255},[249,11802,4792],{"class":286},[249,11804,272],{"class":255},[249,11806,292],{"class":255},[249,11808,272],{"class":255},[249,11810,4749],{"class":343},[249,11812,272],{"class":255},[249,11814,281],{"class":255},[249,11816,272],{"class":255},[249,11818,4809],{"class":286},[249,11820,272],{"class":255},[249,11822,292],{"class":255},[249,11824,272],{"class":255},[249,11826,4766],{"class":343},[249,11828,272],{"class":255},[249,11830,281],{"class":255},[249,11832,272],{"class":255},[249,11834,4826],{"class":286},[249,11836,272],{"class":255},[249,11838,617],{"class":255},[249,11840,272],{"class":255},[249,11842,688],{"class":343},[249,11844,272],{"class":255},[249,11846,281],{"class":255},[249,11848,272],{"class":255},[249,11850,4843],{"class":286},[249,11852,272],{"class":255},[249,11854,292],{"class":255},[249,11856,272],{"class":255},[249,11858,4749],{"class":343},[249,11860,272],{"class":255},[249,11862,281],{"class":255},[249,11864,272],{"class":255},[249,11866,4860],{"class":286},[249,11868,272],{"class":255},[249,11870,292],{"class":255},[249,11872,272],{"class":255},[249,11874,4766],{"class":343},[249,11876,272],{"class":255},[249,11878,281],{"class":255},[249,11880,272],{"class":255},[249,11882,4877],{"class":286},[249,11884,272],{"class":255},[249,11886,617],{"class":255},[249,11888,272],{"class":255},[249,11890,688],{"class":343},[249,11892,272],{"class":255},[249,11894,281],{"class":255},[249,11896,272],{"class":255},[249,11898,4894],{"class":286},[249,11900,272],{"class":255},[249,11902,292],{"class":255},[249,11904,272],{"class":255},[249,11906,4749],{"class":343},[249,11908,272],{"class":255},[249,11910,281],{"class":255},[249,11912,272],{"class":255},[249,11914,4911],{"class":286},[249,11916,272],{"class":255},[249,11918,292],{"class":255},[249,11920,272],{"class":255},[249,11922,4766],{"class":343},[249,11924,272],{"class":255},[249,11926,281],{"class":255},[249,11928,272],{"class":255},[249,11930,4928],{"class":286},[249,11932,272],{"class":255},[249,11934,1182],{"class":255},[249,11936,272],{"class":255},[249,11938,3837],{"class":275},[249,11940,272],{"class":255},[249,11942,281],{"class":255},[249,11944,371],{"class":571},[249,11946,292],{"class":255},[249,11948,272],{"class":255},[249,11950,4531],{"class":275},[249,11952,272],{"class":255},[249,11954,281],{"class":255},[249,11956,786],{"class":255},[249,11958,292],{"class":255},[249,11960,272],{"class":255},[249,11962,4961],{"class":275},[249,11964,272],{"class":255},[249,11966,281],{"class":255},[249,11968,272],{"class":255},[249,11970,4970],{"class":286},[249,11972,272],{"class":255},[249,11974,292],{"class":255},[249,11976,272],{"class":255},[249,11978,4979],{"class":275},[249,11980,272],{"class":255},[249,11982,281],{"class":255},[249,11984,272],{"class":255},[249,11986,4988],{"class":286},[249,11988,272],{"class":255},[249,11990,617],{"class":255},[249,11992,272],{"class":255},[249,11994,276],{"class":275},[249,11996,272],{"class":255},[249,11998,281],{"class":255},[249,12000,272],{"class":255},[249,12002,4643],{"class":286},[249,12004,272],{"class":255},[249,12006,292],{"class":255},[249,12008,272],{"class":255},[249,12010,297],{"class":275},[249,12012,272],{"class":255},[249,12014,281],{"class":255},[249,12016,272],{"class":255},[249,12018,3546],{"class":286},[249,12020,272],{"class":255},[249,12022,292],{"class":255},[249,12024,272],{"class":255},[249,12026,688],{"class":275},[249,12028,272],{"class":255},[249,12030,281],{"class":255},[249,12032,272],{"class":255},[249,12034,5037],{"class":286},[249,12036,272],{"class":255},[249,12038,292],{"class":255},[249,12040,272],{"class":255},[249,12042,4652],{"class":275},[249,12044,272],{"class":255},[249,12046,281],{"class":255},[249,12048,272],{"class":255},[249,12050,5054],{"class":286},[249,12052,272],{"class":255},[249,12054,292],{"class":255},[249,12056,272],{"class":255},[249,12058,5063],{"class":275},[249,12060,272],{"class":255},[249,12062,281],{"class":255},[249,12064,786],{"class":255},[249,12066,292],{"class":255},[249,12068,272],{"class":255},[249,12070,5076],{"class":275},[249,12072,272],{"class":255},[249,12074,421],{"class":255},[249,12076,272],{"class":255},[249,12078,5085],{"class":275},[249,12080,272],{"class":255},[249,12082,468],{"class":255},[249,12084,272],{"class":255},[249,12086,116],{"class":286},[249,12088,272],{"class":255},[249,12090,292],{"class":255},[249,12092,272],{"class":255},[249,12094,5102],{"class":286},[249,12096,272],{"class":255},[249,12098,292],{"class":255},[249,12100,272],{"class":255},[249,12102,5111],{"class":286},[249,12104,272],{"class":255},[249,12106,292],{"class":255},[249,12108,272],{"class":255},[249,12110,5120],{"class":286},[249,12112,272],{"class":255},[249,12114,292],{"class":255},[249,12116,272],{"class":255},[249,12118,110],{"class":286},[249,12120,272],{"class":255},[249,12122,292],{"class":255},[249,12124,272],{"class":255},[249,12126,5137],{"class":286},[249,12128,272],{"class":255},[249,12130,292],{"class":255},[249,12132,272],{"class":255},[249,12134,5146],{"class":286},[249,12136,272],{"class":255},[249,12138,292],{"class":255},[249,12140,272],{"class":255},[249,12142,5155],{"class":286},[249,12144,272],{"class":255},[249,12146,292],{"class":255},[249,12148,272],{"class":255},[249,12150,5164],{"class":286},[249,12152,272],{"class":255},[249,12154,292],{"class":255},[249,12156,272],{"class":255},[249,12158,5173],{"class":286},[249,12160,272],{"class":255},[249,12162,292],{"class":255},[249,12164,272],{"class":255},[249,12166,5182],{"class":286},[249,12168,272],{"class":255},[249,12170,292],{"class":255},[249,12172,272],{"class":255},[249,12174,5191],{"class":286},[249,12176,272],{"class":255},[249,12178,292],{"class":255},[249,12180,272],{"class":255},[249,12182,5200],{"class":286},[249,12184,272],{"class":255},[249,12186,292],{"class":255},[249,12188,272],{"class":255},[249,12190,5209],{"class":286},[249,12192,272],{"class":255},[249,12194,292],{"class":255},[249,12196,272],{"class":255},[249,12198,103],{"class":286},[249,12200,272],{"class":255},[249,12202,292],{"class":255},[249,12204,272],{"class":255},[249,12206,113],{"class":286},[249,12208,272],{"class":255},[249,12210,292],{"class":255},[249,12212,272],{"class":255},[249,12214,5234],{"class":286},[249,12216,272],{"class":255},[249,12218,292],{"class":255},[249,12220,272],{"class":255},[249,12222,5243],{"class":286},[249,12224,272],{"class":255},[249,12226,559],{"class":255},[249,12228,272],{"class":255},[249,12230,5252],{"class":275},[249,12232,272],{"class":255},[249,12234,729],{"class":255},[249,12236,272],{"class":255},[249,12238,5261],{"class":275},[249,12240,272],{"class":255},[249,12242,281],{"class":255},[249,12244,272],{"class":255},[249,12246,3553],{"class":286},[249,12248,272],{"class":255},[249,12250,292],{"class":255},[249,12252,272],{"class":255},[249,12254,5278],{"class":275},[249,12256,272],{"class":255},[249,12258,281],{"class":255},[249,12260,272],{"class":255},[249,12262,5287],{"class":286},[249,12264,272],{"class":255},[249,12266,292],{"class":255},[249,12268,272],{"class":255},[249,12270,5296],{"class":275},[249,12272,272],{"class":255},[249,12274,281],{"class":255},[249,12276,272],{"class":255},[249,12278,5287],{"class":286},[249,12280,272],{"class":255},[249,12282,292],{"class":255},[249,12284,272],{"class":255},[249,12286,5313],{"class":275},[249,12288,272],{"class":255},[249,12290,421],{"class":255},[249,12292,272],{"class":255},[249,12294,5322],{"class":275},[249,12296,272],{"class":255},[249,12298,281],{"class":255},[249,12300,371],{"class":571},[249,12302,292],{"class":255},[249,12304,272],{"class":255},[249,12306,5335],{"class":275},[249,12308,272],{"class":255},[249,12310,421],{"class":255},[249,12312,272],{"class":255},[249,12314,5344],{"class":275},[249,12316,272],{"class":255},[249,12318,5349],{"class":255},[249,12320,272],{"class":255},[249,12322,276],{"class":275},[249,12324,272],{"class":255},[249,12326,281],{"class":255},[249,12328,272],{"class":255},[249,12330,4714],{"class":286},[249,12332,272],{"class":255},[249,12334,292],{"class":255},[249,12336,272],{"class":255},[249,12338,297],{"class":275},[249,12340,272],{"class":255},[249,12342,281],{"class":255},[249,12344,272],{"class":255},[249,12346,125],{"class":286},[249,12348,272],{"class":255},[249,12350,292],{"class":255},[249,12352,272],{"class":255},[249,12354,688],{"class":275},[249,12356,272],{"class":255},[249,12358,281],{"class":255},[249,12360,272],{"class":255},[249,12362,5394],{"class":286},[249,12364,272],{"class":255},[249,12366,292],{"class":255},[249,12368,272],{"class":255},[249,12370,5403],{"class":275},[249,12372,272],{"class":255},[249,12374,338],{"class":255},[249,12376,272],{"class":255},[249,12378,5412],{"class":343},[249,12380,272],{"class":255},[249,12382,281],{"class":255},[249,12384,272],{"class":255},[249,12386,5421],{"class":286},[249,12388,272],{"class":255},[249,12390,292],{"class":255},[249,12392,272],{"class":255},[249,12394,5430],{"class":343},[249,12396,272],{"class":255},[249,12398,281],{"class":255},[249,12400,272],{"class":255},[249,12402,5439],{"class":286},[249,12404,272],{"class":255},[249,12406,292],{"class":255},[249,12408,272],{"class":255},[249,12410,5448],{"class":343},[249,12412,272],{"class":255},[249,12414,281],{"class":255},[249,12416,272],{"class":255},[249,12418,5457],{"class":286},[249,12420,272],{"class":255},[249,12422,292],{"class":255},[249,12424,272],{"class":255},[249,12426,5466],{"class":343},[249,12428,272],{"class":255},[249,12430,281],{"class":255},[249,12432,272],{"class":255},[249,12434,5421],{"class":286},[249,12436,272],{"class":255},[249,12438,292],{"class":255},[249,12440,272],{"class":255},[249,12442,5483],{"class":343},[249,12444,272],{"class":255},[249,12446,281],{"class":255},[249,12448,272],{"class":255},[249,12450,5492],{"class":286},[249,12452,272],{"class":255},[249,12454,458],{"class":255},[249,12456,272],{"class":255},[249,12458,5501],{"class":275},[249,12460,272],{"class":255},[249,12462,338],{"class":255},[249,12464,272],{"class":255},[249,12466,5510],{"class":343},[249,12468,272],{"class":255},[249,12470,281],{"class":255},[249,12472,272],{"class":255},[249,12474,5287],{"class":286},[249,12476,272],{"class":255},[249,12478,292],{"class":255},[249,12480,272],{"class":255},[249,12482,5527],{"class":343},[249,12484,272],{"class":255},[249,12486,281],{"class":255},[249,12488,272],{"class":255},[249,12490,5536],{"class":286},[249,12492,272],{"class":255},[249,12494,292],{"class":255},[249,12496,272],{"class":255},[249,12498,5545],{"class":343},[249,12500,272],{"class":255},[249,12502,281],{"class":255},[249,12504,272],{"class":255},[249,12506,5536],{"class":286},[249,12508,272],{"class":255},[249,12510,292],{"class":255},[249,12512,272],{"class":255},[249,12514,5562],{"class":343},[249,12516,272],{"class":255},[249,12518,281],{"class":255},[249,12520,272],{"class":255},[249,12522,5571],{"class":286},[249,12524,272],{"class":255},[249,12526,292],{"class":255},[249,12528,272],{"class":255},[249,12530,5580],{"class":343},[249,12532,272],{"class":255},[249,12534,281],{"class":255},[249,12536,272],{"class":255},[249,12538,5536],{"class":286},[249,12540,272],{"class":255},[249,12542,5593],{"class":255},[249,12544,272],{"class":255},[249,12546,276],{"class":275},[249,12548,272],{"class":255},[249,12550,281],{"class":255},[249,12552,272],{"class":255},[249,12554,12555],{"class":286},"563dc603fb7848c5",[249,12557,272],{"class":255},[249,12559,292],{"class":255},[249,12561,272],{"class":255},[249,12563,297],{"class":275},[249,12565,272],{"class":255},[249,12567,281],{"class":255},[249,12569,272],{"class":255},[249,12571,3245],{"class":286},[249,12573,272],{"class":255},[249,12575,292],{"class":255},[249,12577,272],{"class":255},[249,12579,3254],{"class":275},[249,12581,272],{"class":255},[249,12583,2200],{"class":255},[249,12585,272],{"class":255},[249,12587,3263],{"class":275},[249,12589,272],{"class":255},[249,12591,338],{"class":255},[249,12593,272],{"class":255},[249,12595,99],{"class":343},[249,12597,272],{"class":255},[249,12599,281],{"class":255},[249,12601,272],{"class":255},[249,12603,5655],{"class":286},[249,12605,272],{"class":255},[249,12607,3286],{"class":255},[249,12609,12610,12612,12614],{"class":251,"line":3289},[249,12611,256],{"class":255},[249,12613,3294],{"class":259},[249,12615,263],{"class":255},[166,12617,12618],{"start":3618},[79,12619,5690,12620,26],{},[51,12621,12622],{},"Refresh Asset Table → Asset Rows → Asset Table",[12,12624,9646,12625,12627],{},[56,12626,3470],{},". The table fills in below the cards, most urgent first, with its header naming the window it covers. Change a dropdown and both halves of the page update together.",[12,12629,12630,37,12634],{},[33,12631],{"alt":12632,"src":12633},"the asset detail table with the status toggle and search box","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fcalibration-asset-table.png",[39,12635,12636],{},"Instruments due inside the selected window, soonest due first, with status chips and days remaining.",[46,12638,12639],{},[12,12640,12641,12643,12644,12647],{},[51,12642,53],{}," The toggle counts describe the table, not the register, so they will read lower than the cards above. That's the point of the split: the cards answer \"how are we doing,\" and the table answers \"what needs collecting.\" Select ",[39,12645,12646],{},"All future"," and the two match.",[68,12649,12651],{"id":12650},"checking-a-tool-at-the-station","Checking a Tool at the Station",[12,12653,12654],{},"A dashboard in the quality office doesn't reach the person about to pick up a torque wrench. This page does: hold the calibration label to a camera, press one button, get one answer.",[166,12656,12657,12672,12687,12698],{},[79,12658,3572,12659,12661,12662,12664,12665,12667,12668,12671],{},[56,12660,110],{}," node named \"Scan Label Button\" in the ",[51,12663,3540],{}," group, order 1. Set the label to ",[56,12666,186],{}," and the payload to the string ",[56,12669,12670],{},"capture",", which tells the webcam to take a frame.",[79,12673,3572,12674,12676,12677,12679,12680,5742,12683,12686],{},[56,12675,5243],{}," node in the ",[51,12678,3535],{}," group, with ",[51,12681,12682],{},"Pass through",[51,12684,12685],{},"QR detection"," both off. Leave image width, height and quality blank to use the camera's defaults.",[79,12688,3572,12689,12691,12692,3303,12694,12697],{},[56,12690,5674],{}," node that sets ",[56,12693,5681],{},[56,12695,12696],{},"msg.payload.image",". The webcam outputs an object; the OCR node just needs the image.",[79,12699,3572,12700,12703,12704,12706,12707,12709],{},[56,12701,12702],{},"simple-ocr"," node, then a ",[56,12705,5686],{}," \u002F ",[56,12708,5732],{}," pair to carry the result down to the next row of the canvas.",[46,12711,12712],{},[12,12713,12714,12716,12717,12721],{},[51,12715,3587],{}," OCR keeps this tutorial hardware-free, but if your labels have a barcode or QR code, scanning one is faster and far more reliable than reading printed text. Swap the camera and OCR nodes for a ",[22,12718,12720],{"href":12719},"\u002Fnode-red\u002Fperipheral\u002Fbarcodescanner\u002F","barcode scanner"," and feed the decoded ID straight into \"Set Tool ID,\" and everything downstream will keep working. You can also drop \"Extract Tool ID\" and \"Scan Valid?\", since a scanner either returns an ID or nothing.",[166,12723,12724],{"start":3624},[79,12725,3572,12726,12728],{},[56,12727,1548],{}," node named \"Extract Tool ID\":",[46,12730,12731],{},[12,12732,12733,12735,12736,12739],{},[51,12734,3587],{}," The same goes for function node logic. Describe what you want the function to do in plain English, and ",[22,12737,3592],{"href":12738},"\u002Fdocs\u002Fuser\u002Fexpert\u002Fnode-red-embedded-ai\u002F#function-node-creation"," will generate the code for you.",[240,12741,12745],{"className":12742,"code":12743,"language":12744,"meta":245,"style":245},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Stickers read TL followed by four digits. OCR loses the hyphen and swaps\n\u002F\u002F look-alike characters, so normalise before matching.\nconst text = String(msg.payload?.text || msg.payload || '');\nconst flat = text.toUpperCase().replace(\u002F[^A-Z0-9]\u002Fg, '');\n\nconst FIXES = { O: '0', Q: '0', I: '1', L: '1', S: '5', B: '8', Z: '2', G: '6' };\n\nconst m = flat.match(\u002FT[L1I]([A-Z0-9]{4})\u002F);\nconst digits = m ? m[1].replace(\u002F[A-Z]\u002Fg, c => FIXES[c] || c) : '';\nconst toolId = \u002F^\\d{4}$\u002F.test(digits) ? 'TL-' + digits : null;\n\nmsg.payload = {\n    success: !!toolId,\n    toolId,\n    \u002F\u002F Shows what OCR actually read when a scan fails.\n    rawText: text.replace(\u002F\\s+\u002Fg, ' ').trim()\n};\nreturn msg;\n","javascript",[56,12746,12747,12753,12758,12808,12855,12859,12980,12984,13027,13088,13142,13146,13159,13175,13182,13187,13228,13233],{"__ignoreMap":245},[249,12748,12749],{"class":251,"line":252},[249,12750,12752],{"class":12751},"sHwdD","\u002F\u002F Stickers read TL followed by four digits. OCR loses the hyphen and swaps\n",[249,12754,12755],{"class":251,"line":266},[249,12756,12757],{"class":12751},"\u002F\u002F look-alike characters, so normalise before matching.\n",[249,12759,12760,12763,12766,12769,12773,12776,12778,12780,12783,12786,12789,12792,12794,12797,12799,12802,12805],{"class":251,"line":3289},[249,12761,12762],{"class":275},"const",[249,12764,12765],{"class":259}," text ",[249,12767,12768],{"class":255},"=",[249,12770,12772],{"class":12771},"s2Zo4"," String",[249,12774,12775],{"class":259},"(msg",[249,12777,26],{"class":255},[249,12779,752],{"class":259},[249,12781,12782],{"class":255},"?.",[249,12784,12785],{"class":259},"text ",[249,12787,12788],{"class":255},"||",[249,12790,12791],{"class":259}," msg",[249,12793,26],{"class":255},[249,12795,12796],{"class":259},"payload ",[249,12798,12788],{"class":255},[249,12800,12801],{"class":255}," ''",[249,12803,12804],{"class":259},")",[249,12806,12807],{"class":255},";\n",[249,12809,12810,12812,12815,12817,12820,12822,12825,12828,12830,12833,12836,12839,12842,12845,12847,12849,12851,12853],{"class":251,"line":3618},[249,12811,12762],{"class":275},[249,12813,12814],{"class":259}," flat ",[249,12816,12768],{"class":255},[249,12818,12819],{"class":259}," text",[249,12821,26],{"class":255},[249,12823,12824],{"class":12771},"toUpperCase",[249,12826,12827],{"class":259},"()",[249,12829,26],{"class":255},[249,12831,12832],{"class":12771},"replace",[249,12834,12835],{"class":259},"(",[249,12837,12838],{"class":255},"\u002F[^",[249,12840,12841],{"class":286},"A-Z0-9",[249,12843,12844],{"class":255},"]\u002F",[249,12846,671],{"class":571},[249,12848,292],{"class":255},[249,12850,12801],{"class":255},[249,12852,12804],{"class":259},[249,12854,12807],{"class":255},[249,12856,12857],{"class":251,"line":3624},[249,12858,5834],{"emptyLinePlaceholder":5833},[249,12860,12861,12863,12866,12868,12871,12875,12877,12880,12882,12885,12887,12890,12892,12894,12896,12898,12900,12903,12905,12907,12909,12911,12913,12916,12918,12920,12922,12924,12926,12929,12931,12933,12935,12937,12939,12942,12944,12946,12949,12951,12953,12956,12958,12960,12962,12964,12966,12969,12971,12973,12975,12977],{"class":251,"line":5824},[249,12862,12762],{"class":275},[249,12864,12865],{"class":259}," FIXES ",[249,12867,12768],{"class":255},[249,12869,12870],{"class":255}," {",[249,12872,12874],{"class":12873},"swJcz"," O",[249,12876,281],{"class":255},[249,12878,12879],{"class":255}," '",[249,12881,2149],{"class":286},[249,12883,12884],{"class":255},"'",[249,12886,292],{"class":255},[249,12888,12889],{"class":12873}," Q",[249,12891,281],{"class":255},[249,12893,12879],{"class":255},[249,12895,2149],{"class":286},[249,12897,12884],{"class":255},[249,12899,292],{"class":255},[249,12901,12902],{"class":12873}," I",[249,12904,281],{"class":255},[249,12906,12879],{"class":255},[249,12908,371],{"class":286},[249,12910,12884],{"class":255},[249,12912,292],{"class":255},[249,12914,12915],{"class":12873}," L",[249,12917,281],{"class":255},[249,12919,12879],{"class":255},[249,12921,371],{"class":286},[249,12923,12884],{"class":255},[249,12925,292],{"class":255},[249,12927,12928],{"class":12873}," S",[249,12930,281],{"class":255},[249,12932,12879],{"class":255},[249,12934,6543],{"class":286},[249,12936,12884],{"class":255},[249,12938,292],{"class":255},[249,12940,12941],{"class":12873}," B",[249,12943,281],{"class":255},[249,12945,12879],{"class":255},[249,12947,12948],{"class":286},"8",[249,12950,12884],{"class":255},[249,12952,292],{"class":255},[249,12954,12955],{"class":12873}," Z",[249,12957,281],{"class":255},[249,12959,12879],{"class":255},[249,12961,6872],{"class":286},[249,12963,12884],{"class":255},[249,12965,292],{"class":255},[249,12967,12968],{"class":12873}," G",[249,12970,281],{"class":255},[249,12972,12879],{"class":255},[249,12974,4826],{"class":286},[249,12976,12884],{"class":255},[249,12978,12979],{"class":255}," };\n",[249,12981,12982],{"class":251,"line":5830},[249,12983,5834],{"emptyLinePlaceholder":5833},[249,12985,12986,12988,12991,12993,12996,12998,13001,13003,13006,13009,13012,13015,13018,13020,13023,13025],{"class":251,"line":5837},[249,12987,12762],{"class":275},[249,12989,12990],{"class":259}," m ",[249,12992,12768],{"class":255},[249,12994,12995],{"class":259}," flat",[249,12997,26],{"class":255},[249,12999,13000],{"class":12771},"match",[249,13002,12835],{"class":259},[249,13004,13005],{"class":255},"\u002F",[249,13007,13008],{"class":286},"T",[249,13010,13011],{"class":255},"[",[249,13013,13014],{"class":286},"L1I",[249,13016,13017],{"class":255},"]([",[249,13019,12841],{"class":286},[249,13021,13022],{"class":255},"]{4})\u002F",[249,13024,12804],{"class":259},[249,13026,12807],{"class":255},[249,13028,13029,13031,13034,13036,13038,13041,13044,13046,13049,13051,13053,13055,13058,13061,13063,13065,13067,13071,13074,13077,13079,13082,13084,13086],{"class":251,"line":5843},[249,13030,12762],{"class":275},[249,13032,13033],{"class":259}," digits ",[249,13035,12768],{"class":255},[249,13037,12990],{"class":259},[249,13039,13040],{"class":255},"?",[249,13042,13043],{"class":259}," m[",[249,13045,371],{"class":571},[249,13047,13048],{"class":259},"]",[249,13050,26],{"class":255},[249,13052,12832],{"class":12771},[249,13054,12835],{"class":259},[249,13056,13057],{"class":255},"\u002F[",[249,13059,13060],{"class":286},"A-Z",[249,13062,12844],{"class":255},[249,13064,671],{"class":571},[249,13066,292],{"class":255},[249,13068,13070],{"class":13069},"sHdIc"," c",[249,13072,13073],{"class":275}," =>",[249,13075,13076],{"class":259}," FIXES[c] ",[249,13078,12788],{"class":255},[249,13080,13081],{"class":259}," c) ",[249,13083,281],{"class":255},[249,13085,12801],{"class":255},[249,13087,12807],{"class":255},[249,13089,13090,13092,13095,13097,13100,13104,13107,13110,13113,13115,13117,13120,13123,13125,13127,13130,13132,13135,13137,13139],{"class":251,"line":5848},[249,13091,12762],{"class":275},[249,13093,13094],{"class":259}," toolId ",[249,13096,12768],{"class":255},[249,13098,13099],{"class":255}," \u002F",[249,13101,13103],{"class":13102},"s7zQu","^",[249,13105,13106],{"class":286},"\\d",[249,13108,13109],{"class":255},"{4}",[249,13111,13112],{"class":13102},"$",[249,13114,13005],{"class":255},[249,13116,26],{"class":255},[249,13118,13119],{"class":12771},"test",[249,13121,13122],{"class":259},"(digits) ",[249,13124,13040],{"class":255},[249,13126,12879],{"class":255},[249,13128,13129],{"class":286},"TL-",[249,13131,12884],{"class":255},[249,13133,13134],{"class":255}," +",[249,13136,13033],{"class":259},[249,13138,281],{"class":255},[249,13140,13141],{"class":255}," null;\n",[249,13143,13144],{"class":251,"line":5854},[249,13145,5834],{"emptyLinePlaceholder":5833},[249,13147,13148,13150,13152,13154,13156],{"class":251,"line":5860},[249,13149,770],{"class":259},[249,13151,26],{"class":255},[249,13153,12796],{"class":259},[249,13155,12768],{"class":255},[249,13157,13158],{"class":255}," {\n",[249,13160,13161,13164,13166,13169,13172],{"class":251,"line":5866},[249,13162,13163],{"class":12873},"    success",[249,13165,281],{"class":255},[249,13167,13168],{"class":255}," !!",[249,13170,13171],{"class":259},"toolId",[249,13173,13174],{"class":255},",\n",[249,13176,13177,13180],{"class":251,"line":5872},[249,13178,13179],{"class":259},"    toolId",[249,13181,13174],{"class":255},[249,13183,13184],{"class":251,"line":5878},[249,13185,13186],{"class":12751},"    \u002F\u002F Shows what OCR actually read when a scan fails.\n",[249,13188,13189,13192,13194,13196,13198,13200,13202,13204,13207,13210,13212,13214,13216,13218,13220,13222,13225],{"class":251,"line":5884},[249,13190,13191],{"class":12873},"    rawText",[249,13193,281],{"class":255},[249,13195,12819],{"class":259},[249,13197,26],{"class":255},[249,13199,12832],{"class":12771},[249,13201,12835],{"class":259},[249,13203,13005],{"class":255},[249,13205,13206],{"class":286},"\\s",[249,13208,13209],{"class":255},"+\u002F",[249,13211,671],{"class":571},[249,13213,292],{"class":255},[249,13215,12879],{"class":255},[249,13217,12879],{"class":255},[249,13219,12804],{"class":259},[249,13221,26],{"class":255},[249,13223,13224],{"class":12771},"trim",[249,13226,13227],{"class":259},"()\n",[249,13229,13230],{"class":251,"line":5890},[249,13231,13232],{"class":255},"};\n",[249,13234,13235,13238,13240],{"class":251,"line":5895},[249,13236,13237],{"class":13102},"return",[249,13239,12791],{"class":259},[249,13241,12807],{"class":255},[12,13243,13244,13245,13247,13248,13251],{},"Wire a ",[56,13246,646],{}," node to this as well and leave it enabled. When a scan fails, ",[56,13249,13250],{},"rawText"," shows what the camera actually read, which is the difference between fixing the label and guessing at it.",[46,13253,13254],{},[12,13255,13256,13258,13259,13262,13263,26],{},[51,13257,53],{}," The pattern above expects ",[56,13260,13261],{},"TL"," followed by four digits, because that's what the seeded data uses. Your labels almost certainly look different: a different prefix, more digits, a plant code, or no letters at all. Change the regex and the length check to match your own sticker format before you test this on real tools, or every scan will come back as ",[51,13264,200],{},[166,13266,13267,13285,13309],{"start":5824},[79,13268,3572,13269,13272,13273,13276,13277,13280,13281,13284],{},[56,13270,13271],{},"switch"," node named \"Scan Valid?\" on ",[56,13274,13275],{},"payload.success",", with ",[51,13278,13279],{},"is true"," on the first output and ",[51,13282,13283],{},"otherwise"," on the second. A failed read skips the database entirely.",[79,13286,3572,13287,13289,13290],{},[56,13288,5674],{}," node named \"Set Tool ID\" on the true branch, with two rules:",[76,13291,13292,13300],{},[79,13293,5751,13294,13296,13297],{},[56,13295,5754],{}," to the JSONata ",[56,13298,13299],{},"{ \"toolId\": $trim(payload.toolId) }",[79,13301,5751,13302,13296,13305,13308],{},[56,13303,13304],{},"scannedId",[56,13306,13307],{},"$trim(payload.toolId)",", so the ID survives to the verdict even when no row comes back",[79,13310,3572,13311,13313],{},[56,13312,871],{}," node named \"Look Up Tool\":",[240,13315,13317],{"className":3596,"code":13316,"language":3598,"meta":245,"style":245},"SELECT\n    tool_id,\n    equipment_name,\n\n    -- The safety answer comes from the date, not the stored status flag,\n    -- which can go stale if whatever recalculates it falls behind.\n    (next_due_ts >= NOW()) AS ok_to_use\n\nFROM calibration_assets\n\n-- Deliberately NOT filtered by department or time window: a scan is a\n-- lookup of one tool, not a view. Case, padding and hyphens are all\n-- normalised away, at the cost of the index, which is fine at register size.\nWHERE replace(upper(btrim(tool_id)), '-', '')\n    = replace(upper(btrim($toolId)), '-', '');\n",[56,13318,13319,13323,13327,13331,13335,13340,13345,13350,13354,13358,13362,13367,13372,13377,13382],{"__ignoreMap":245},[249,13320,13321],{"class":251,"line":252},[249,13322,5801],{},[249,13324,13325],{"class":251,"line":266},[249,13326,9704],{},[249,13328,13329],{"class":251,"line":3289},[249,13330,9709],{},[249,13332,13333],{"class":251,"line":3618},[249,13334,5834],{"emptyLinePlaceholder":5833},[249,13336,13337],{"class":251,"line":3624},[249,13338,13339],{},"    -- The safety answer comes from the date, not the stored status flag,\n",[249,13341,13342],{"class":251,"line":5824},[249,13343,13344],{},"    -- which can go stale if whatever recalculates it falls behind.\n",[249,13346,13347],{"class":251,"line":5830},[249,13348,13349],{},"    (next_due_ts >= NOW()) AS ok_to_use\n",[249,13351,13352],{"class":251,"line":5837},[249,13353,5834],{"emptyLinePlaceholder":5833},[249,13355,13356],{"class":251,"line":5843},[249,13357,3610],{},[249,13359,13360],{"class":251,"line":5848},[249,13361,5834],{"emptyLinePlaceholder":5833},[249,13363,13364],{"class":251,"line":5854},[249,13365,13366],{},"-- Deliberately NOT filtered by department or time window: a scan is a\n",[249,13368,13369],{"class":251,"line":5860},[249,13370,13371],{},"-- lookup of one tool, not a view. Case, padding and hyphens are all\n",[249,13373,13374],{"class":251,"line":5866},[249,13375,13376],{},"-- normalised away, at the cost of the index, which is fine at register size.\n",[249,13378,13379],{"class":251,"line":5872},[249,13380,13381],{},"WHERE replace(upper(btrim(tool_id)), '-', '')\n",[249,13383,13384],{"class":251,"line":5878},[249,13385,13386],{},"    = replace(upper(btrim($toolId)), '-', '');\n",[166,13388,13389],{"start":5843},[79,13390,3572,13391,13393,13394,13397],{},[56,13392,1548],{}," node named \"Build Verdict\". Wire ",[51,13395,13396],{},"both"," the query output and the switch's second output into it:",[240,13399,13401],{"className":12742,"code":13400,"language":12744,"meta":245,"style":245},"\u002F\u002F Two paths feed this node: a completed lookup, and a failed scan routed\n\u002F\u002F straight past the query. Tell them apart by payload shape.\nconst p = msg.payload;\n\nif (p?.success === false) {\n    msg.payload = { state: 'scan_failed' };\n    return msg;\n}\n\nconst row = Array.isArray(p) ? p[0] : p;\n\nif (!row?.tool_id) {\n    msg.payload = { state: 'not_found', scannedId: msg.scannedId };\n    return msg;\n}\n\nmsg.payload = {\n    state: row.ok_to_use ? 'ok' : 'blocked',\n    tool: row\n};\nreturn msg;\n",[56,13402,13403,13408,13413,13430,13434,13460,13488,13497,13501,13505,13542,13546,13566,13604,13612,13616,13620,13632,13668,13678,13682],{"__ignoreMap":245},[249,13404,13405],{"class":251,"line":252},[249,13406,13407],{"class":12751},"\u002F\u002F Two paths feed this node: a completed lookup, and a failed scan routed\n",[249,13409,13410],{"class":251,"line":266},[249,13411,13412],{"class":12751},"\u002F\u002F straight past the query. Tell them apart by payload shape.\n",[249,13414,13415,13417,13420,13422,13424,13426,13428],{"class":251,"line":3289},[249,13416,12762],{"class":275},[249,13418,13419],{"class":259}," p ",[249,13421,12768],{"class":255},[249,13423,12791],{"class":259},[249,13425,26],{"class":255},[249,13427,752],{"class":259},[249,13429,12807],{"class":255},[249,13431,13432],{"class":251,"line":3618},[249,13433,5834],{"emptyLinePlaceholder":5833},[249,13435,13436,13439,13442,13444,13447,13450,13454,13457],{"class":251,"line":3624},[249,13437,13438],{"class":13102},"if",[249,13440,13441],{"class":259}," (p",[249,13443,12782],{"class":255},[249,13445,13446],{"class":259},"success ",[249,13448,13449],{"class":255},"===",[249,13451,13453],{"class":13452},"sfNiH"," false",[249,13455,13456],{"class":259},") ",[249,13458,13459],{"class":255},"{\n",[249,13461,13462,13465,13467,13469,13472,13474,13477,13479,13481,13484,13486],{"class":251,"line":5824},[249,13463,13464],{"class":259},"    msg",[249,13466,26],{"class":255},[249,13468,752],{"class":259},[249,13470,13471],{"class":255}," =",[249,13473,12870],{"class":255},[249,13475,13476],{"class":12873}," state",[249,13478,281],{"class":255},[249,13480,12879],{"class":255},[249,13482,13483],{"class":286},"scan_failed",[249,13485,12884],{"class":255},[249,13487,12979],{"class":255},[249,13489,13490,13493,13495],{"class":251,"line":5830},[249,13491,13492],{"class":13102},"    return",[249,13494,12791],{"class":259},[249,13496,12807],{"class":255},[249,13498,13499],{"class":251,"line":5837},[249,13500,263],{"class":255},[249,13502,13503],{"class":251,"line":5843},[249,13504,5834],{"emptyLinePlaceholder":5833},[249,13506,13507,13509,13512,13514,13517,13519,13522,13525,13527,13530,13532,13535,13537,13540],{"class":251,"line":5848},[249,13508,12762],{"class":275},[249,13510,13511],{"class":259}," row ",[249,13513,12768],{"class":255},[249,13515,13516],{"class":259}," Array",[249,13518,26],{"class":255},[249,13520,13521],{"class":12771},"isArray",[249,13523,13524],{"class":259},"(p) ",[249,13526,13040],{"class":255},[249,13528,13529],{"class":259}," p[",[249,13531,2149],{"class":571},[249,13533,13534],{"class":259},"] ",[249,13536,281],{"class":255},[249,13538,13539],{"class":259}," p",[249,13541,12807],{"class":255},[249,13543,13544],{"class":251,"line":5854},[249,13545,5834],{"emptyLinePlaceholder":5833},[249,13547,13548,13550,13553,13556,13559,13561,13564],{"class":251,"line":5860},[249,13549,13438],{"class":13102},[249,13551,13552],{"class":259}," (",[249,13554,13555],{"class":255},"!",[249,13557,13558],{"class":259},"row",[249,13560,12782],{"class":255},[249,13562,13563],{"class":259},"tool_id) ",[249,13565,13459],{"class":255},[249,13567,13568,13570,13572,13574,13576,13578,13580,13582,13584,13587,13589,13591,13594,13596,13598,13600,13602],{"class":251,"line":5866},[249,13569,13464],{"class":259},[249,13571,26],{"class":255},[249,13573,752],{"class":259},[249,13575,13471],{"class":255},[249,13577,12870],{"class":255},[249,13579,13476],{"class":12873},[249,13581,281],{"class":255},[249,13583,12879],{"class":255},[249,13585,13586],{"class":286},"not_found",[249,13588,12884],{"class":255},[249,13590,292],{"class":255},[249,13592,13593],{"class":12873}," scannedId",[249,13595,281],{"class":255},[249,13597,12791],{"class":259},[249,13599,26],{"class":255},[249,13601,13304],{"class":259},[249,13603,12979],{"class":255},[249,13605,13606,13608,13610],{"class":251,"line":5872},[249,13607,13492],{"class":13102},[249,13609,12791],{"class":259},[249,13611,12807],{"class":255},[249,13613,13614],{"class":251,"line":5878},[249,13615,263],{"class":255},[249,13617,13618],{"class":251,"line":5884},[249,13619,5834],{"emptyLinePlaceholder":5833},[249,13621,13622,13624,13626,13628,13630],{"class":251,"line":5890},[249,13623,770],{"class":259},[249,13625,26],{"class":255},[249,13627,12796],{"class":259},[249,13629,12768],{"class":255},[249,13631,13158],{"class":255},[249,13633,13634,13637,13639,13642,13644,13647,13649,13651,13654,13656,13659,13661,13664,13666],{"class":251,"line":5895},[249,13635,13636],{"class":12873},"    state",[249,13638,281],{"class":255},[249,13640,13641],{"class":259}," row",[249,13643,26],{"class":255},[249,13645,13646],{"class":259},"ok_to_use ",[249,13648,13040],{"class":255},[249,13650,12879],{"class":255},[249,13652,13653],{"class":286},"ok",[249,13655,12884],{"class":255},[249,13657,13658],{"class":255}," :",[249,13660,12879],{"class":255},[249,13662,13663],{"class":286},"blocked",[249,13665,12884],{"class":255},[249,13667,13174],{"class":255},[249,13669,13670,13673,13675],{"class":251,"line":5900},[249,13671,13672],{"class":12873},"    tool",[249,13674,281],{"class":255},[249,13676,13677],{"class":259}," row\n",[249,13679,13680],{"class":251,"line":5906},[249,13681,13232],{"class":255},[249,13683,13684,13686,13688],{"class":251,"line":5912},[249,13685,13237],{"class":13102},[249,13687,12791],{"class":259},[249,13689,12807],{"class":255},[12,13691,13692],{},"Four states come out of it, and they're the only four an operator ever sees:",[3312,13694,13695,13707],{},[3315,13696,13697],{},[3318,13698,13699,13702,13705],{},[3321,13700,13701],{},"State",[3321,13703,13704],{},"When",[3321,13706,3540],{},[3328,13708,13709,13723,13737,13751],{},[3318,13710,13711,13715,13718],{},[3333,13712,13713],{},[56,13714,13653],{},[3333,13716,13717],{},"Due date in the future",[3333,13719,13720,13722],{},[51,13721,190],{},", green",[3318,13724,13725,13729,13732],{},[3333,13726,13727],{},[56,13728,13663],{},[3333,13730,13731],{},"Due date has passed",[3333,13733,13734,13736],{},[51,13735,193],{},", red",[3318,13738,13739,13743,13746],{},[3333,13740,13741],{},[56,13742,13586],{},[3333,13744,13745],{},"ID read, no matching row",[3333,13747,13748,13750],{},[51,13749,196],{},", amber",[3318,13752,13753,13757,13764],{},[3333,13754,13755],{},[56,13756,13483],{},[3333,13758,13759,13760,13763],{},"No ",[56,13761,13762],{},"TL-####"," pattern found",[3333,13765,13766,13750],{},[51,13767,200],{},[166,13769,13770],{"start":5848},[79,13771,3572,13772,13774],{},[56,13773,1548],{}," node named \"Format Notification\". It shows what was scanned, the verdict, and what to do about it:",[240,13776,13778],{"className":12742,"code":13777,"language":12744,"meta":245,"style":245},"const v = msg.payload || {};\nconst t = v.tool;\n\n\u002F\u002F timeout 0 on 'blocked' is deliberate: an expired-tool verdict must be\n\u002F\u002F dismissed by a person, not fade out while nobody is watching.\nconst VERDICTS = {\n    ok:          { text: 'OK to use',          do: 'Carry on.',                        color: '#15803d', timeout: 8 },\n    blocked:     { text: 'Do not use',         do: 'Tag it and tell your supervisor.',  color: '#b3261e', timeout: 0 },\n    not_found:   { text: 'Not in register',    do: 'Tell your supervisor.',             color: '#b45309', timeout: 12 },\n    scan_failed: { text: 'Label not readable', do: 'Wipe the label and scan again.',    color: '#b45309', timeout: 8 }\n};\n\nconst cfg = VERDICTS[v.state] || VERDICTS.scan_failed;\n\n\u002F\u002F ui-notification renders raw HTML, so escape what came from the register.\nconst esc = s => String(s ?? '').replace(\u002F[\u003C>&\"]\u002Fg,\n    c => ({ '\u003C': '&lt;', '>': '&gt;', '&': '&amp;', '\"': '&quot;' }[c]));\n\nconst scanned = t\n    ? esc(t.tool_id) + ' - ' + esc(t.equipment_name)\n    : esc(v.scannedId || 'No ID read');\n\nmsg.payload = `\u003Cdiv style=\"font-size:1rem;opacity:.85\">${scanned}\u003C\u002Fdiv>`\n    + `\u003Cdiv style=\"font-size:2rem;font-weight:700;margin:4px 0\">${cfg.text}\u003C\u002Fdiv>`\n    + `\u003Cdiv style=\"font-size:1rem\">${cfg.do}\u003C\u002Fdiv>`;\n\nmsg.color = cfg.color;\nmsg.timeout = cfg.timeout;\nreturn msg;\n",[56,13779,13780,13800,13819,13823,13828,13833,13844,13905,13964,14023,14080,14084,14088,14116,14120,14125,14168,14255,14259,14271,14307,14335,14339,14369,14395,14422,14426,14446,14465],{"__ignoreMap":245},[249,13781,13782,13784,13787,13789,13791,13793,13795,13797],{"class":251,"line":252},[249,13783,12762],{"class":275},[249,13785,13786],{"class":259}," v ",[249,13788,12768],{"class":255},[249,13790,12791],{"class":259},[249,13792,26],{"class":255},[249,13794,12796],{"class":259},[249,13796,12788],{"class":255},[249,13798,13799],{"class":255}," {};\n",[249,13801,13802,13804,13807,13809,13812,13814,13817],{"class":251,"line":266},[249,13803,12762],{"class":275},[249,13805,13806],{"class":259}," t ",[249,13808,12768],{"class":255},[249,13810,13811],{"class":259}," v",[249,13813,26],{"class":255},[249,13815,13816],{"class":259},"tool",[249,13818,12807],{"class":255},[249,13820,13821],{"class":251,"line":3289},[249,13822,5834],{"emptyLinePlaceholder":5833},[249,13824,13825],{"class":251,"line":3618},[249,13826,13827],{"class":12751},"\u002F\u002F timeout 0 on 'blocked' is deliberate: an expired-tool verdict must be\n",[249,13829,13830],{"class":251,"line":3624},[249,13831,13832],{"class":12751},"\u002F\u002F dismissed by a person, not fade out while nobody is watching.\n",[249,13834,13835,13837,13840,13842],{"class":251,"line":5824},[249,13836,12762],{"class":275},[249,13838,13839],{"class":259}," VERDICTS ",[249,13841,12768],{"class":255},[249,13843,13158],{"class":255},[249,13845,13846,13849,13851,13854,13856,13858,13860,13862,13864,13866,13869,13871,13873,13876,13878,13880,13883,13885,13887,13890,13892,13894,13897,13899,13902],{"class":251,"line":5830},[249,13847,13848],{"class":12873},"    ok",[249,13850,281],{"class":255},[249,13852,13853],{"class":255},"          {",[249,13855,12819],{"class":12873},[249,13857,281],{"class":255},[249,13859,12879],{"class":255},[249,13861,190],{"class":286},[249,13863,12884],{"class":255},[249,13865,292],{"class":255},[249,13867,13868],{"class":12873},"          do",[249,13870,281],{"class":255},[249,13872,12879],{"class":255},[249,13874,13875],{"class":286},"Carry on.",[249,13877,12884],{"class":255},[249,13879,292],{"class":255},[249,13881,13882],{"class":12873},"                        color",[249,13884,281],{"class":255},[249,13886,12879],{"class":255},[249,13888,13889],{"class":286},"#15803d",[249,13891,12884],{"class":255},[249,13893,292],{"class":255},[249,13895,13896],{"class":12873}," timeout",[249,13898,281],{"class":255},[249,13900,13901],{"class":571}," 8",[249,13903,13904],{"class":255}," },\n",[249,13906,13907,13910,13912,13915,13917,13919,13921,13923,13925,13927,13930,13932,13934,13937,13939,13941,13944,13946,13948,13951,13953,13955,13957,13959,13962],{"class":251,"line":5837},[249,13908,13909],{"class":12873},"    blocked",[249,13911,281],{"class":255},[249,13913,13914],{"class":255},"     {",[249,13916,12819],{"class":12873},[249,13918,281],{"class":255},[249,13920,12879],{"class":255},[249,13922,193],{"class":286},[249,13924,12884],{"class":255},[249,13926,292],{"class":255},[249,13928,13929],{"class":12873},"         do",[249,13931,281],{"class":255},[249,13933,12879],{"class":255},[249,13935,13936],{"class":286},"Tag it and tell your supervisor.",[249,13938,12884],{"class":255},[249,13940,292],{"class":255},[249,13942,13943],{"class":12873},"  color",[249,13945,281],{"class":255},[249,13947,12879],{"class":255},[249,13949,13950],{"class":286},"#b3261e",[249,13952,12884],{"class":255},[249,13954,292],{"class":255},[249,13956,13896],{"class":12873},[249,13958,281],{"class":255},[249,13960,13961],{"class":571}," 0",[249,13963,13904],{"class":255},[249,13965,13966,13969,13971,13974,13976,13978,13980,13982,13984,13986,13989,13991,13993,13996,13998,14000,14003,14005,14007,14010,14012,14014,14016,14018,14021],{"class":251,"line":5843},[249,13967,13968],{"class":12873},"    not_found",[249,13970,281],{"class":255},[249,13972,13973],{"class":255},"   {",[249,13975,12819],{"class":12873},[249,13977,281],{"class":255},[249,13979,12879],{"class":255},[249,13981,196],{"class":286},[249,13983,12884],{"class":255},[249,13985,292],{"class":255},[249,13987,13988],{"class":12873},"    do",[249,13990,281],{"class":255},[249,13992,12879],{"class":255},[249,13994,13995],{"class":286},"Tell your supervisor.",[249,13997,12884],{"class":255},[249,13999,292],{"class":255},[249,14001,14002],{"class":12873},"             color",[249,14004,281],{"class":255},[249,14006,12879],{"class":255},[249,14008,14009],{"class":286},"#b45309",[249,14011,12884],{"class":255},[249,14013,292],{"class":255},[249,14015,13896],{"class":12873},[249,14017,281],{"class":255},[249,14019,14020],{"class":571}," 12",[249,14022,13904],{"class":255},[249,14024,14025,14028,14030,14032,14034,14036,14038,14040,14042,14044,14047,14049,14051,14054,14056,14058,14061,14063,14065,14067,14069,14071,14073,14075,14077],{"class":251,"line":5848},[249,14026,14027],{"class":12873},"    scan_failed",[249,14029,281],{"class":255},[249,14031,12870],{"class":255},[249,14033,12819],{"class":12873},[249,14035,281],{"class":255},[249,14037,12879],{"class":255},[249,14039,200],{"class":286},[249,14041,12884],{"class":255},[249,14043,292],{"class":255},[249,14045,14046],{"class":12873}," do",[249,14048,281],{"class":255},[249,14050,12879],{"class":255},[249,14052,14053],{"class":286},"Wipe the label and scan again.",[249,14055,12884],{"class":255},[249,14057,292],{"class":255},[249,14059,14060],{"class":12873},"    color",[249,14062,281],{"class":255},[249,14064,12879],{"class":255},[249,14066,14009],{"class":286},[249,14068,12884],{"class":255},[249,14070,292],{"class":255},[249,14072,13896],{"class":12873},[249,14074,281],{"class":255},[249,14076,13901],{"class":571},[249,14078,14079],{"class":255}," }\n",[249,14081,14082],{"class":251,"line":5854},[249,14083,13232],{"class":255},[249,14085,14086],{"class":251,"line":5860},[249,14087,5834],{"emptyLinePlaceholder":5833},[249,14089,14090,14092,14095,14097,14100,14102,14105,14107,14110,14112,14114],{"class":251,"line":5866},[249,14091,12762],{"class":275},[249,14093,14094],{"class":259}," cfg ",[249,14096,12768],{"class":255},[249,14098,14099],{"class":259}," VERDICTS[v",[249,14101,26],{"class":255},[249,14103,14104],{"class":259},"state] ",[249,14106,12788],{"class":255},[249,14108,14109],{"class":259}," VERDICTS",[249,14111,26],{"class":255},[249,14113,13483],{"class":259},[249,14115,12807],{"class":255},[249,14117,14118],{"class":251,"line":5872},[249,14119,5834],{"emptyLinePlaceholder":5833},[249,14121,14122],{"class":251,"line":5878},[249,14123,14124],{"class":12751},"\u002F\u002F ui-notification renders raw HTML, so escape what came from the register.\n",[249,14126,14127,14129,14132,14134,14137,14139,14141,14144,14147,14149,14151,14153,14155,14157,14159,14162,14164,14166],{"class":251,"line":5884},[249,14128,12762],{"class":275},[249,14130,14131],{"class":259}," esc ",[249,14133,12768],{"class":255},[249,14135,14136],{"class":13069}," s",[249,14138,13073],{"class":275},[249,14140,12772],{"class":12771},[249,14142,14143],{"class":259},"(s ",[249,14145,14146],{"class":255},"??",[249,14148,12801],{"class":255},[249,14150,12804],{"class":259},[249,14152,26],{"class":255},[249,14154,12832],{"class":12771},[249,14156,12835],{"class":259},[249,14158,13057],{"class":255},[249,14160,14161],{"class":286},"\u003C>&\"",[249,14163,12844],{"class":255},[249,14165,671],{"class":571},[249,14167,13174],{"class":255},[249,14169,14170,14173,14175,14177,14179,14181,14184,14186,14188,14190,14193,14195,14197,14199,14201,14203,14205,14207,14210,14212,14214,14216,14219,14221,14223,14225,14228,14230,14232,14234,14236,14238,14240,14242,14245,14247,14250,14253],{"class":251,"line":5890},[249,14171,14172],{"class":13069},"    c",[249,14174,13073],{"class":275},[249,14176,13552],{"class":259},[249,14178,256],{"class":255},[249,14180,12879],{"class":255},[249,14182,14183],{"class":12873},"\u003C",[249,14185,12884],{"class":255},[249,14187,281],{"class":255},[249,14189,12879],{"class":255},[249,14191,14192],{"class":286},"&lt;",[249,14194,12884],{"class":255},[249,14196,292],{"class":255},[249,14198,12879],{"class":255},[249,14200,3924],{"class":12873},[249,14202,12884],{"class":255},[249,14204,281],{"class":255},[249,14206,12879],{"class":255},[249,14208,14209],{"class":286},"&gt;",[249,14211,12884],{"class":255},[249,14213,292],{"class":255},[249,14215,12879],{"class":255},[249,14217,14218],{"class":12873},"&",[249,14220,12884],{"class":255},[249,14222,281],{"class":255},[249,14224,12879],{"class":255},[249,14226,14227],{"class":286},"&amp;",[249,14229,12884],{"class":255},[249,14231,292],{"class":255},[249,14233,12879],{"class":255},[249,14235,272],{"class":12873},[249,14237,12884],{"class":255},[249,14239,281],{"class":255},[249,14241,12879],{"class":255},[249,14243,14244],{"class":286},"&quot;",[249,14246,12884],{"class":255},[249,14248,14249],{"class":255}," }",[249,14251,14252],{"class":259},"[c]))",[249,14254,12807],{"class":255},[249,14256,14257],{"class":251,"line":5895},[249,14258,5834],{"emptyLinePlaceholder":5833},[249,14260,14261,14263,14266,14268],{"class":251,"line":5900},[249,14262,12762],{"class":275},[249,14264,14265],{"class":259}," scanned ",[249,14267,12768],{"class":255},[249,14269,14270],{"class":259}," t\n",[249,14272,14273,14276,14279,14282,14284,14286,14289,14291,14294,14296,14298,14300,14302,14304],{"class":251,"line":5906},[249,14274,14275],{"class":255},"    ?",[249,14277,14278],{"class":12771}," esc",[249,14280,14281],{"class":259},"(t",[249,14283,26],{"class":255},[249,14285,13563],{"class":259},[249,14287,14288],{"class":255},"+",[249,14290,12879],{"class":255},[249,14292,14293],{"class":286}," - ",[249,14295,12884],{"class":255},[249,14297,13134],{"class":255},[249,14299,14278],{"class":12771},[249,14301,14281],{"class":259},[249,14303,26],{"class":255},[249,14305,14306],{"class":259},"equipment_name)\n",[249,14308,14309,14312,14314,14317,14319,14322,14324,14326,14329,14331,14333],{"class":251,"line":5912},[249,14310,14311],{"class":255},"    :",[249,14313,14278],{"class":12771},[249,14315,14316],{"class":259},"(v",[249,14318,26],{"class":255},[249,14320,14321],{"class":259},"scannedId ",[249,14323,12788],{"class":255},[249,14325,12879],{"class":255},[249,14327,14328],{"class":286},"No ID read",[249,14330,12884],{"class":255},[249,14332,12804],{"class":259},[249,14334,12807],{"class":255},[249,14336,14337],{"class":251,"line":5918},[249,14338,5834],{"emptyLinePlaceholder":5833},[249,14340,14341,14343,14345,14347,14349,14352,14355,14358,14361,14363,14366],{"class":251,"line":5923},[249,14342,770],{"class":259},[249,14344,26],{"class":255},[249,14346,12796],{"class":259},[249,14348,12768],{"class":255},[249,14350,14351],{"class":255}," `",[249,14353,14354],{"class":286},"\u003Cdiv style=\"font-size:1rem;opacity:.85\">",[249,14356,14357],{"class":255},"${",[249,14359,14360],{"class":259},"scanned",[249,14362,1783],{"class":255},[249,14364,14365],{"class":286},"\u003C\u002Fdiv>",[249,14367,14368],{"class":255},"`\n",[249,14370,14371,14374,14376,14379,14381,14384,14386,14389,14391,14393],{"class":251,"line":5928},[249,14372,14373],{"class":255},"    +",[249,14375,14351],{"class":255},[249,14377,14378],{"class":286},"\u003Cdiv style=\"font-size:2rem;font-weight:700;margin:4px 0\">",[249,14380,14357],{"class":255},[249,14382,14383],{"class":259},"cfg",[249,14385,26],{"class":255},[249,14387,14388],{"class":259},"text",[249,14390,1783],{"class":255},[249,14392,14365],{"class":286},[249,14394,14368],{"class":255},[249,14396,14397,14399,14401,14404,14406,14408,14410,14413,14415,14417,14420],{"class":251,"line":5934},[249,14398,14373],{"class":255},[249,14400,14351],{"class":255},[249,14402,14403],{"class":286},"\u003Cdiv style=\"font-size:1rem\">",[249,14405,14357],{"class":255},[249,14407,14383],{"class":259},[249,14409,26],{"class":255},[249,14411,14412],{"class":259},"do",[249,14414,1783],{"class":255},[249,14416,14365],{"class":286},[249,14418,14419],{"class":255},"`",[249,14421,12807],{"class":255},[249,14423,14424],{"class":251,"line":5940},[249,14425,5834],{"emptyLinePlaceholder":5833},[249,14427,14428,14430,14432,14435,14437,14440,14442,14444],{"class":251,"line":5945},[249,14429,770],{"class":259},[249,14431,26],{"class":255},[249,14433,14434],{"class":259},"color ",[249,14436,12768],{"class":255},[249,14438,14439],{"class":259}," cfg",[249,14441,26],{"class":255},[249,14443,444],{"class":259},[249,14445,12807],{"class":255},[249,14447,14448,14450,14452,14455,14457,14459,14461,14463],{"class":251,"line":5951},[249,14449,770],{"class":259},[249,14451,26],{"class":255},[249,14453,14454],{"class":259},"timeout ",[249,14456,12768],{"class":255},[249,14458,14439],{"class":259},[249,14460,26],{"class":255},[249,14462,2142],{"class":259},[249,14464,12807],{"class":255},[249,14466,14467,14469,14471],{"class":251,"line":5957},[249,14468,13237],{"class":13102},[249,14470,12791],{"class":259},[249,14472,12807],{"class":255},[166,14474,14475,14508],{"start":5854},[79,14476,3572,14477,14479,14480,3303,14483,14486,14487,14490,14491,104,14494,5742,14497,14500,14501,5742,14504,14507],{},[56,14478,116],{}," node named \"Verdict\" and select your ui-base. Set ",[51,14481,14482],{},"Position",[51,14484,14485],{},"center center",", turn off ",[51,14488,14489],{},"Use default colour",", turn on ",[51,14492,14493],{},"Show countdown",[51,14495,14496],{},"Allow dismiss",[51,14498,14499],{},"Allow raw HTML",". The display time and colour on the node are only fallbacks; ",[56,14502,14503],{},"msg.timeout",[56,14505,14506],{},"msg.color"," override them for each verdict.",[79,14509,3572,14510,14512,14513,14515],{},[56,14511,113],{}," node named \"Tool Check Instructions\" in the ",[51,14514,3540],{}," group, order 2:",[240,14517,14521],{"className":14518,"code":14519,"language":14520,"meta":245,"style":245},"language-markdown shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cdiv style=\"text-align: center\">\n\n### Before you use a tool\n\n\u003C\u002Fdiv>\n\n**1** Hold the calibration label flat in front of the camera.\n\n**2** Press **SCAN**.\n\n**3** Read the message in the middle of the screen.\n\n---\n\n**\"OK to use\"**: the tool is inside its calibration interval. Carry on.\n\n**\"Do not use\"**: set the tool aside, tag it, and tell your supervisor. If you have already used it on parts today, say so; those measurements need checking.\n\n**\"Not in register\"** or **\"Label not readable\"**: wipe the label and scan again. If it fails twice, tell your supervisor.\n\n---\n\nAnything other than **\"OK to use\"** means the tool stays out of production.\n","markdown",[56,14522,14523,14528,14532,14540,14544,14549,14553,14567,14571,14591,14595,14606,14610,14615,14619,14631,14635,14647,14651,14673,14677,14681,14685],{"__ignoreMap":245},[249,14524,14525],{"class":251,"line":252},[249,14526,14527],{"class":259},"\u003Cdiv style=\"text-align: center\">\n",[249,14529,14530],{"class":251,"line":266},[249,14531,5834],{"emptyLinePlaceholder":5833},[249,14533,14534,14537],{"class":251,"line":3289},[249,14535,14536],{"class":255},"### ",[249,14538,14539],{"class":343},"Before you use a tool\n",[249,14541,14542],{"class":251,"line":3618},[249,14543,5834],{"emptyLinePlaceholder":5833},[249,14545,14546],{"class":251,"line":3624},[249,14547,14548],{"class":259},"\u003C\u002Fdiv>\n",[249,14550,14551],{"class":251,"line":5824},[249,14552,5834],{"emptyLinePlaceholder":5833},[249,14554,14555,14559,14562,14564],{"class":251,"line":5830},[249,14556,14558],{"class":14557},"sHepR","**",[249,14560,371],{"class":14561},"so75L",[249,14563,14558],{"class":14557},[249,14565,14566],{"class":259}," Hold the calibration label flat in front of the camera.\n",[249,14568,14569],{"class":251,"line":5837},[249,14570,5834],{"emptyLinePlaceholder":5833},[249,14572,14573,14575,14577,14579,14582,14584,14586,14588],{"class":251,"line":5843},[249,14574,14558],{"class":14557},[249,14576,6872],{"class":14561},[249,14578,14558],{"class":14557},[249,14580,14581],{"class":259}," Press ",[249,14583,14558],{"class":14557},[249,14585,186],{"class":14561},[249,14587,14558],{"class":14557},[249,14589,14590],{"class":259},".\n",[249,14592,14593],{"class":251,"line":5848},[249,14594,5834],{"emptyLinePlaceholder":5833},[249,14596,14597,14599,14601,14603],{"class":251,"line":5854},[249,14598,14558],{"class":14557},[249,14600,4775],{"class":14561},[249,14602,14558],{"class":14557},[249,14604,14605],{"class":259}," Read the message in the middle of the screen.\n",[249,14607,14608],{"class":251,"line":5860},[249,14609,5834],{"emptyLinePlaceholder":5833},[249,14611,14612],{"class":251,"line":5866},[249,14613,14614],{"class":255},"---\n",[249,14616,14617],{"class":251,"line":5872},[249,14618,5834],{"emptyLinePlaceholder":5833},[249,14620,14621,14623,14626,14628],{"class":251,"line":5878},[249,14622,14558],{"class":14557},[249,14624,14625],{"class":14561},"\"OK to use\"",[249,14627,14558],{"class":14557},[249,14629,14630],{"class":259},": the tool is inside its calibration interval. Carry on.\n",[249,14632,14633],{"class":251,"line":5884},[249,14634,5834],{"emptyLinePlaceholder":5833},[249,14636,14637,14639,14642,14644],{"class":251,"line":5890},[249,14638,14558],{"class":14557},[249,14640,14641],{"class":14561},"\"Do not use\"",[249,14643,14558],{"class":14557},[249,14645,14646],{"class":259},": set the tool aside, tag it, and tell your supervisor. If you have already used it on parts today, say so; those measurements need checking.\n",[249,14648,14649],{"class":251,"line":5895},[249,14650,5834],{"emptyLinePlaceholder":5833},[249,14652,14653,14655,14658,14660,14663,14665,14668,14670],{"class":251,"line":5900},[249,14654,14558],{"class":14557},[249,14656,14657],{"class":14561},"\"Not in register\"",[249,14659,14558],{"class":14557},[249,14661,14662],{"class":259}," or ",[249,14664,14558],{"class":14557},[249,14666,14667],{"class":14561},"\"Label not readable\"",[249,14669,14558],{"class":14557},[249,14671,14672],{"class":259},": wipe the label and scan again. If it fails twice, tell your supervisor.\n",[249,14674,14675],{"class":251,"line":5906},[249,14676,5834],{"emptyLinePlaceholder":5833},[249,14678,14679],{"class":251,"line":5912},[249,14680,14614],{"class":255},[249,14682,14683],{"class":251,"line":5918},[249,14684,5834],{"emptyLinePlaceholder":5833},[249,14686,14687,14690,14692,14694,14696],{"class":251,"line":5923},[249,14688,14689],{"class":259},"Anything other than ",[249,14691,14558],{"class":14557},[249,14693,14625],{"class":14561},[249,14695,14558],{"class":14557},[249,14697,14698],{"class":259}," means the tool stays out of production.\n",[166,14700,14701],{"start":5866},[79,14702,5690,14703,14706,14707,9640,14710,26],{},[51,14704,14705],{},"Scan Label Button → ui-webcam → change → simple-ocr → Extract Tool ID → Scan Valid?",", then ",[51,14708,14709],{},"Scan Valid? (true) → Set Tool ID → Look Up Tool → Build Verdict",[51,14711,14712],{},"Scan Valid? (otherwise) → Build Verdict → Format Notification → Verdict",[12,14714,9646,14715,14717,14718,14721,14722,14724],{},[56,14716,3482],{}," on a device with a camera. Hold a label reading ",[56,14719,14720],{},"TL-0007",", or one in whatever format you configured above, in front of it and press ",[51,14723,186],{},". Whatever the seeded data says about that tool is what comes back. Because the verdict compares the date instead of reading the status column, it will always agree with the Home page.",[12,14726,14727,37,14731],{},[33,14728],{"alt":14729,"src":14730},"the Tool Check page with the camera preview and SCAN button","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Ftool-check.png",[39,14732,14733],{},"The scanner page: camera preview, one button, and the operator instructions below it.",[68,14735,14737],{"id":14736},"what-next","What Next",[12,14739,14740],{},"You've built a calibration application that answers two different questions from the same data. The office screen tells a quality engineer how the plant stands and what needs collecting this week. The station screen tells an operator whether the tool in their hand is fit to use. Both read the due date, so neither can drift from the other.",[12,14742,14743,14744,14746,14747,14750,14751,14755,14756,5742,14760,14764,14765,26],{},"Right now it runs on generated data. To go live, remove the simulator flow and point the queries at your own register. Just alias your column names in the ",[56,14745,3425],{}," lists, and everything downstream keeps working. If your records sit in a CMMS or ERP behind an API, swap the query nodes for ",[56,14748,14749],{},"http request"," nodes and nothing else changes. From there, the obvious next steps are ones the register already supports: email the overdue list to the calibration lab each Monday, or ",[22,14752,14754],{"href":14753},"\u002Fnode-red\u002Fnotification\u002F","notify"," someone the moment a critical gauge goes overdue instead of waiting for a screen to be looked at. The same approach works for ",[22,14757,14759],{"href":14758},"\u002Fblog\u002F2026\u002F07\u002Fdefect-and-quality-monitoring\u002F","defect tracking",[22,14761,14763],{"href":14762},"\u002Fblog\u002F2026\u002F07\u002Fbuild-downtime-logger\u002F","downtime"," too. See how manufacturers are using it on our ",[22,14766,14768],{"href":14767},"\u002Findustries\u002Fautomotive\u002F","automotive solutions page",[333,14770,14771],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHepR, html code.shiki .sHepR{--shiki-light:#39ADB5;--shiki-light-font-weight:bold;--shiki-default:#89DDFF;--shiki-default-font-weight:bold;--shiki-dark:#89DDFF;--shiki-dark-font-weight:bold}html pre.shiki code .so75L, html code.shiki .so75L{--shiki-light:#E53935;--shiki-light-font-weight:bold;--shiki-default:#F07178;--shiki-default-font-weight:bold;--shiki-dark:#F07178;--shiki-dark-font-weight:bold}",{"title":245,"searchDepth":3618,"depth":3618,"links":14773},[14774,14775,14776,14777,14778,14779,14780,14781,14782],{"id":70,"depth":266,"text":71},{"id":160,"depth":266,"text":161},{"id":207,"depth":266,"text":208},{"id":3440,"depth":266,"text":3441},{"id":3560,"depth":266,"text":3561},{"id":5705,"depth":266,"text":5706},{"id":9661,"depth":266,"text":9662},{"id":12650,"depth":266,"text":12651},{"id":14736,"depth":266,"text":14737},{"type":14784,"title":14785,"description":14786},"contact","See What Your Team Can Build","See it live with our team, and the variety of applications you can build without coding expertise, then scale them across your plant in a single click.","2026-07-31","Build a calibration status dashboard in FlowFuse: work out overdue, due-soon and compliance figures from due dates, filter by department and time window, and let operators check a tool at the station with a camera.","md","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Ftracking-equipement-calibration.png",null,{"excerpt":14793},{"type":9,"value":14794},[14795],[12,14796,14],{},"\u002Fblog\u002F2026\u002F07\u002Fcalibration-management-dashboard",{"title":5,"description":14788},{"loc":14797},"blog\u002F2026\u002F07\u002Fcalibration-management-dashboard","Get overdue and due-soon status from the dates, not from a status column that can go out of date",[14803,14804,14805],"flowfuse","manufacturing","how-to","Build a FlowFuse calibration dashboard that works out overdue, due-soon and compliance figures from the due dates instead of a stored status column, filters by department and time window from the app bar, lists every instrument due in that window with days remaining, and gives operators a camera-based tool check at the station.","35SDlpuw0JM6jB6FqmS1yJh6oKsSfRllY8H3cn3-7tM",[],1785872795871]