{ "custom": { "forceModeRefresh": false, "setDatesScript": null }, "params": { "endDate": "2021-02-11 00:00:00", "refreshDelay": 30, "startDate": "2021-02-10 00:00:00" }, "propConfig": { "custom.forceModeRefresh": { "persistent": true }, "custom.setDatesScript": { "binding": { "config": { "expression": "toBoolean(now({view.params.refreshDelay}*1000))\r\n\u0026\u0026{view.custom.forceModeRefresh}" }, "transforms": [ { "code": "\tnow \u003d system.date.now()\n\tcurrentDay \u003d system.date.getDate(system.date.getYear(now), system.date.getMonth(now), system.date.getDayOfMonth(now))\n\tpreviousDay \u003d system.date.addDays(currentDay, -1)\n\tnextDay \u003d system.date.addDays(currentDay, 1)\n\tstartDate \u003d self.getChild(\"root\").getChild(\"StartDateTime\")\n\tendDate \u003d self.getChild(\"root\").getChild(\"EndDateTime\")\n\tvalue \u003d self.getChild(\"root\").getChild(\"Mode\").props.value\n\t\n\t# Retrieve shifts table:\n\tshifts \u003d utils.datasetToJSON(system.tag.readBlocking([\"[default]Gateway/Shifts\"])[0].value)\n\t# Filter for shifts that are enabled and for today:\n\tcurrentDayOfWeek \u003d system.date.getDayOfWeek(now)\n\tcurrentDayOfWeek \u003d \"is\" + [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"][currentDayOfWeek-1]\n\tshifts \u003d [shift for shift in shifts if shift[\"Enabled\"] and shift[currentDayOfWeek]]\n\t# Build SORTS list:\n\tSORTS \u003d [{ \"name\": shift[\"Name\"], \"start\": [shift[\"StartHour\"],shift[\"StartMinute\"]], \"actualEnd\": [shift[\"EndHour\"],shift[\"EndMinute\"]] } for shift in shifts]\n\tSORTS.sort(key\u003dlambda x: x[\"start\"])\n\t# Add end time based on next sort:\n\tfor i in range(len(SORTS) - 1):\n\t\tSORTS[i][\"end\"] \u003d SORTS[i+1][\"start\"]\n\tSORTS[-1][\"end\"] \u003d SORTS[0][\"start\"]\n\t\n\tstart \u003d startDate.props.value\n\tend \u003d endDate.props.value\n\t\n\tif value \u003d\u003d \"past30min\":\n\t\tstart \u003d system.date.addMinutes(now, -30)\n\t\tend \u003d now\n\t\n\telif value \u003d\u003d \"pastHour\":\n\t\tstart \u003d system.date.addHours(now, -1)\n\t\tend \u003d now\n\t\n\telif value \u003d\u003d \"past2Hours\":\n\t\tstart \u003d system.date.addHours(now, -2)\n\t\tend \u003d now\n\t\n\telif value \u003d\u003d \"past4Hours\":\n\t\tstart \u003d system.date.addHours(now, -4)\n\t\tend \u003d now\n\t\n\telif value \u003d\u003d \"past8Hours\":\n\t\tstart \u003d system.date.addHours(now, -8)\n\t\tend \u003d now\n\t\n\telif value \u003d\u003d \"currentDay\":\n\t\tstart \u003d currentDay\n\t\tend \u003d system.date.addDays(currentDay, 1)\n\t\n\telif value \u003d\u003d \"previousDay\":\n\t\tstart \u003d previousDay\n\t\tend \u003d currentDay\n\t\t\n\telse:\n\t\t# Resolve sort:\n\t\tif value \u003d\u003d \"currentShift\":\n\t\t\tsort \u003d SORTS[-1] # Default to last sort (assumes last sort includes midnight)\n\t\t\tfor i, s in enumerate(SORTS[::-1]):\n\t\t\t\tif system.date.isAfter(now, system.date.setTime(currentDay, s[\"start\"][0], s[\"start\"][1], 0)):\n\t\t\t\t\tsort \u003d s\n\t\t\t\t\tbreak\n\t\t\t# Apply:\n\t\t\tstart \u003d system.date.setTime(currentDay, sort[\"start\"][0], sort[\"start\"][1], 0)\n\t\t\tend \u003d system.date.setTime(currentDay, sort[\"actualEnd\"][0], sort[\"actualEnd\"][1], 0)\n\t\telif value \u003d\u003d \"previousShift\":\n\t\t\tsort \u003d SORTS[-2] # Default to second to last sort (assumes last sort includes midnight)\n\t\t\tSORTS_REV \u003d SORTS[:]\n\t\t\tSORTS_REV.sort(key\u003dlambda x: x[\"end\"])\n\t\t\tfor i, s in enumerate(SORTS_REV[::-1]):\n\t\t\t\tif system.date.isAfter(now, system.date.setTime(currentDay, s[\"end\"][0], s[\"end\"][1], 0)):\n\t\t\t\t\tsort \u003d s\n\t\t\t\t\tbreak\n\t\t\t# Apply:\n\t\t\tstart \u003d system.date.setTime(currentDay, sort[\"start\"][0], sort[\"start\"][1], 0)\n\t\t\tend \u003d system.date.setTime(currentDay, sort[\"actualEnd\"][0], sort[\"actualEnd\"][1], 0)\n\t\telse:\n\t\t\tfor s in SORTS:\n\t\t\t\tif s[\"name\"] \u003d\u003d value:\n\t\t\t\t\t# Apply:\n\t\t\t\t\tstart \u003d system.date.setTime(currentDay, s[\"start\"][0], s[\"start\"][1], 0)\n\t\t\t\t\tend \u003d system.date.setTime(currentDay, s[\"actualEnd\"][0], s[\"actualEnd\"][1], 0)\n\t\t\t\t\tbreak\n\n\t\t# Increase end if before start:\n\t\tif system.date.isAfter(start, end):\n\t\t\tend \u003d system.date.addDays(end, 1)\n\t\t# If current time is before startDate, then subtract one day to show last occurrence of that sort:\n\t\tif system.date.isBefore(now, start):\n\t\t\tstart \u003d system.date.addDays(start, -1)\n\t\t\tend \u003d system.date.addDays(end, -1)\n\t\t\t\n\t# Apply:\n\tif startDate.props.value !\u003d start or endDate.props.value !\u003d end or (system.date.isAfter(now, start) and system.date.isBefore(now, system.date.addMinutes(end, 1))):\n\t\tstartDate.props.value \u003d start\n\t\tendDate.props.value \u003d end\n\t\tself.session.custom.timewidget \u003d {\n\t\t\t\"startDate\": start,\n\t\t\t\"endDate\": end,\n\t\t\t\"mode\": value,\n\t\t\t\"update\": now\n\t\t}\n\t\n\treturn value", "type": "script" } ], "type": "expr" }, "persistent": true }, "params.endDate": { "binding": { "config": { "path": "/root/EndDateTime.props.formattedValues.datetime" }, "type": "property" }, "paramDirection": "output", "persistent": true }, "params.refreshDelay": { "paramDirection": "input", "persistent": true }, "params.startDate": { "binding": { "config": { "path": "/root/StartDateTime.props.formattedValues.datetime" }, "type": "property" }, "paramDirection": "output", "persistent": true } }, "props": { "defaultSize": { "height": 40, "width": 550 } }, "root": { "children": [ { "meta": { "name": "StartLabel" }, "position": { "height": 20, "width": 40, "x": 180, "y": 10 }, "props": { "style": { "color": "#fff", "fontSize": "14px", "textAlign": "right" }, "text": "Start:" }, "type": "ia.display.label" }, { "events": { "component": { "onActionPerformed": { "config": { "script": "\ttimewidget \u003d self.session.custom.timewidget\n\thours \u003d system.date.hoursBetween(self.props.value, timewidget.endDate)\n\tsystem.perspective.print(hours)\n\tnewVal \u003d {\n\t\t\"startDate\": self.props.value,\n\t\t\"endDate\": timewidget.endDate,\n\t\t\"mode\": timewidget.mode\n\t}\n\tif hours \u003e 7*24:\n\t\t# Cap endDate to within 7 days of startDate:\n\t\tnewVal[\"endDate\"] \u003d system.date.addDays(self.props.value, 7)\n\t# Apply changes:\n\tself.session.custom.timewidget \u003d newVal" }, "scope": "G", "type": "script" } } }, "meta": { "name": "StartDateTime" }, "position": { "height": 20, "width": 135, "x": 225, "y": 10 }, "propConfig": { "props.enabled": { "binding": { "config": { "path": "../Mode.props.value" }, "transforms": [ { "expression": "{value} \u003d \"custom\"", "type": "expression" } ], "type": "property" } }, "props.value": { "binding": { "config": { "path": "session.custom.timewidget.startDate" }, "type": "property" } } }, "props": { "format": "YYYY-MM-DD HH:mm:ss", "formattedValue": "2021-06-01 20:00:00", "formattedValues": { "date": "2021-02-10", "datetime": "2021-02-10 00:00:00", "time": "00:00:00" }, "inputProps": { "style": { "fontSize": "12px" } } }, "type": "ia.input.date-time-input" }, { "events": { "component": { "onActionPerformed": { "config": { "script": "\ttimewidget \u003d self.session.custom.timewidget\n\thours \u003d system.date.hoursBetween(timewidget.startDate, self.props.value)\n\tnewVal \u003d {\n\t\t\"startDate\": timewidget.startDate,\n\t\t\"endDate\": self.props.value,\n\t\t\"mode\": timewidget.mode\n\t}\n\tif hours \u003e 7*24:\n\t\t# Cap startDate to within 7 days of endDate:\n\t\tnewVal[\"startDate\"] \u003d system.date.addDays(self.props.value, -7)\n\t# Apply changes:\n\tself.session.custom.timewidget \u003d newVal" }, "scope": "G", "type": "script" } } }, "meta": { "name": "EndDateTime" }, "position": { "height": 20, "width": 135, "x": 410, "y": 10 }, "propConfig": { "props.enabled": { "binding": { "config": { "path": "../Mode.props.value" }, "transforms": [ { "expression": "{value} \u003d \"custom\"", "type": "expression" } ], "type": "property" } }, "props.value": { "binding": { "config": { "path": "session.custom.timewidget.endDate" }, "type": "property" } } }, "props": { "format": "YYYY-MM-DD HH:mm:ss", "formattedValue": "2021-06-02 20:00:00", "formattedValues": { "date": "2021-02-11", "datetime": "2021-02-11 00:00:00", "time": "00:00:00" }, "inputProps": { "style": { "fontSize": "12px" } } }, "type": "ia.input.date-time-input" }, { "meta": { "name": "EndLabel" }, "position": { "height": 20, "width": 40, "x": 365, "y": 10 }, "props": { "style": { "color": "#fff", "fontSize": "14px", "textAlign": "right" }, "text": "End:" }, "type": "ia.display.label" }, { "meta": { "name": "ModeLabel" }, "position": { "height": 20, "width": 45, "x": 5, "y": 10 }, "props": { "style": { "color": "#fff", "fontSize": "14px", "textAlign": "right" }, "text": "Period:" }, "type": "ia.display.label" }, { "events": { "component": { "onActionPerformed": { "config": { "script": "\tself.session.custom.timewidget.mode \u003d self.props.value\n\tself.view.custom.forceModeRefresh \u003d not self.view.custom.forceModeRefresh" }, "scope": "G", "type": "script" } } }, "meta": { "name": "Mode" }, "position": { "height": 20, "width": 120, "x": 55, "y": 10 }, "propConfig": { "props.options": { "binding": { "config": { "fallbackDelay": 2.5, "mode": "direct", "tagPath": "[default]Gateway/Shifts" }, "transforms": [ { "code": "\t# Add default relative options:\n\toptions \u003d [\n\t { \"value\": \"past30min\", \"label\": \"Past 30min\" },\n\t { \"value\": \"pastHour\", \"label\": \"Past Hour\" },\n\t { \"value\": \"past2Hours\", \"label\": \"Past 2 Hours\" },\n\t { \"value\": \"past4Hours\", \"label\": \"Past 4 Hours\" },\n\t { \"value\": \"past8Hours\", \"label\": \"Past 8 Hours\" },\n\t { \"value\": \"currentDay\", \"label\": \"Current Day\" },\n\t { \"value\": \"previousDay\", \"label\": \"Previous Day\" },\n\t { \"value\": \"currentShift\", \"label\": \"Current Shift\" },\n\t { \"value\": \"previousShift\", \"label\": \"Previous Shift\" }\n\t]\n\t# Add shifts:\n\tshifts \u003d utils.datasetToJSON(value)\n\t# Filter for shifts that are enabled and for today:\n\tcurrentDayOfWeek \u003d system.date.getDayOfWeek(system.date.now())\n\tcurrentDayOfWeek \u003d \"is\" + [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"][currentDayOfWeek-1]\n\tshifts \u003d [shift for shift in shifts if shift[\"Enabled\"] and shift[currentDayOfWeek]]\n\t# Add shifts to options:\n\tfor shift in shifts:\n\t\tif shift[\"Enabled\"]:\n\t\t\toptions.append({ \"value\": shift[\"Name\"], \"label\": \"Shift: \" + shift[\"Name\"] })\n\t# Add custom:\n\toptions.append({ \"value\": \"custom\", \"label\": \"Custom\" })\n\t# Return options:\n\treturn options", "type": "script" } ], "type": "tag" } }, "props.value": { "binding": { "config": { "struct": { "mode": "{session.custom.timewidget.mode}", "options": "{this.props.options}" }, "waitOnAll": true }, "transforms": [ { "code": "\tif value.options !\u003d None:\n\t\tfor option in value.options:\n\t\t\tif option.value \u003d\u003d value.mode:\n\t\t\t\treturn value.mode\n\t# Value isn\u0027t in options, default to currentDay:\n\treturn \"currentDay\"", "type": "script" } ], "type": "expr-struct" } } }, "props": { "dropdownOptionStyle": { "fontSize": "11px" }, "style": { "fontSize": "10px" } }, "type": "ia.input.dropdown" } ], "meta": { "name": "root" }, "props": { "style": { "overflow": "hidden" } }, "type": "ia.container.coord" } }