and here it is hooked up to CRON-PLUS (to generate dynamic schedules)...
[{"id":"ba591917.ba3828","type":"ui_template","z":"42ea7bd7.2e3c24","group":"dce9e7a2.d20c78","name":"TimeSheet js css","order":5,"width":0,"height":0,"format":"\n\n<link rel=\"stylesheet\" href=\"https://www.jqueryscript.net/demo/Table-Based-jQuery-Calendar-Schedule-Plugin-TimeSheet/css/TimeSheet.css\" type=\"text/css\" media=\"screen\">\n<script type=\"text/javascript\" src=\"https://www.jqueryscript.net/demo/Table-Based-jQuery-Calendar-Schedule-Plugin-TimeSheet/js/TimeSheet.js\"></script>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","x":450,"y":960,"wires":[[]]},{"id":"52c4340b.74d2cc","type":"ui_template","z":"42ea7bd7.2e3c24","group":"6d01ec93.b1d374","name":"","order":4,"width":"12","height":"14","format":"<div>\n <div style=\"padding:15px 0 10px;\">\n <button class=\"J_sheetControl\" id=\"J_timingDisable\">Disable</button>\n <button class=\"J_sheetControl\" id=\"J_timingEnable\">Enable</button>\n <button class=\"J_sheetControl\" id=\"J_timingClean\">Clean</button>\n <button class=\"J_sheetControl\" id=\"J_timingSubmit\">Submit</button>\n <button class=\"J_sheetControl\" id=\"J_timingIsFull\">IsFull</button>\n <div style=\"padding:15px 0 5px;\">\n <input type=\"text\" placeholder=\"0,0\" id=\"J_cellIndex\" value=\"0,0\"/>\n <button class=\"J_sheetControl\" id=\"J_timingGetCell\">GetCell</button>\n </div>\n <div style=\"padding:10px 0;\">\n <input type=\"number\" placeholder=\"0\" id=\"J_rowIndex\" value=\"0\"/>\n <button class=\"J_sheetControl\" id=\"J_timingGetRow\">GetRow</button>\n </div>\n </div>\n <div id=\"J_calenderWrapper\">\n <table>\n <thead></thead>\n <tbody id=\"J_timedSheet\">\n \n </tbody>\n </table>\n </div>\n</div>\n\n<script type=\"text/javascript\">\n\n var dimensions = [7,24];\n\n var yAxis = [\n {name:\"Mon\"},{name:\"Tue\"},{name:\"Wed\"},{name:\"Thu\"},{name:\"Fru\"},\n {name:\"Sat\"},{name:\"Sun\"}\n ];\n\n var xAxis = [\n {name:\"00\",title:\"00-01\"},{name:\"01\",title:\"01-02\"},{name:\"02\",title:\"02-03\"},{name:\"03\",title:\"03-04\"},\n {name:\"04\",title:\"04-05\"},{name:\"05\",title:\"05-06\"},{name:\"06\",title:\"06-07\"},{name:\"07\",title:\"07-08\"},\n {name:\"08\",title:\"08-09\"},{name:\"09\",title:\"09-10\"},{name:\"10\",title:\"10-11\"},{name:\"11\",title:\"11-12\"},\n {name:\"12\",title:\"12-13\"},{name:\"13\",title:\"13-14\"},{name:\"14\",title:\"14-15\"},{name:\"15\",title:\"15-16\"},\n {name:\"16\",title:\"16-17\"},{name:\"17\",title:\"17-18\"},{name:\"18\",title:\"18-19\"},{name:\"19\",title:\"19-20\"},\n {name:\"20\",title:\"20-21\"},{name:\"21\",title:\"21-22\"},{name:\"22\",title:\"22-23\"},{name:\"23\",title:\"23-00\"}\n ];\n\n var sheetData = [\n [1,1,1,0,1,0,1,1,0,1,1,0,1,1,1,0,0,1,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,0,0,1,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0],\n [0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,0,0,1,0,0,0,0,0,0], \n ];\n\n var updateRemark = function(sheet){\n\n var sheetStates = sheet.getSheetStates();\n var rowsCount = dimensions[0];\n var colsCount = dimensions[1];\n var rowRemark = [];\n var rowRemarkLen = 0;\n var remarkHTML = '';\n\n for(var row= 0, rowStates=[]; row<rowsCount; ++row){\n rowRemark = [];\n rowStates = sheetStates[row];\n for(var col=0; col<colsCount; ++col){\n if(rowStates[col]===0 && rowStates[col-1]===1){\n rowRemark[rowRemarkLen-1] += (col<=10?'0':'')+col+':00';\n }else if(rowStates[col]===1 && (rowStates[col-1]===0 || rowStates[col-1]===undefined)){\n rowRemarkLen = rowRemark.push((col<=10?'0':'')+col+':00-');\n }\n if(rowStates[col]===1 && col===colsCount-1){\n rowRemark[rowRemarkLen-1] += '00:00';\n }\n }\n remarkHTML = rowRemark.join(\",\");\n sheet.setRemark(row,remarkHTML==='' ? sheet.getDefaultRemark() : remarkHTML);\n }\n };\n\n (function(scope) {\ndebugger\n var sheet = $(\"#J_timedSheet\").TimeSheet({\n data: {\n dimensions : dimensions,\n colHead : xAxis,\n rowHead : yAxis,\n sheetHead : {name:\"Date\\\\Time\"},\n sheetData : sheetData\n },\n remarks : {\n title : \"Description\",\n default : \"N/A\"\n },\n end : function(ev,selectedArea){\n updateRemark(sheet);\n }\n });\n\n updateRemark(sheet);\n\n $(\"#J_timingDisable\").click(function(ev){\n sheet.disable();\n });\n\n $(\"#J_timingEnable\").click(function(ev){\n sheet.enable();\n });\n\n $(\"#J_timingClean\").click(function(ev){\n sheet.clean();\n });\n\n $(\"#J_timingSubmit\").click(function(ev){\n\n var sheetStates = sheet.getSheetStates();\n var rowsCount = dimensions[0];\n var $submitDataDisplay = $(\"#J_dataDisplay\") ;\n scope.send({ topic: \"sheet/all\", payload: sheetStates });\n \n });\n\n $(\"#J_timingIsFull\").click(function(ev){\n alert(sheet.isFull());\n });\n\n $(\"#J_timingGetCell\").click(function(ev){\n var cellIndex = $(\"#J_cellIndex\").val().split(',');\n var cellData = sheet.getCellState(cellIndex);\n var $dataDisplay = $(\"#J_dataDisplay\") ;\n scope.send({ topic: \"sheet/cell/\" + cellIndex[0] + \"/\" + cellIndex[1], payload: cellData });\n });\n\n $(\"#J_timingGetRow\").click(function(ev){\n var rowIndex = $(\"#J_rowIndex\").val();\n var rowData = sheet.getRowStates(rowIndex);\n var $dataDisplay = $(\"#J_dataDisplay\") ;\n scope.send({ topic: \"sheet/row/\" + rowIndex, payload: rowData });\n });\n\n\n\n })(scope);\n</script>\n\n\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","x":420,"y":1000,"wires":[["3fb2a061.51fcd","e76906a0.c7c718"]]},{"id":"3fb2a061.51fcd","type":"debug","z":"42ea7bd7.2e3c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":610,"y":1000,"wires":[]},{"id":"dc325ddd.d276c","type":"cronplus","z":"42ea7bd7.2e3c24","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[],"x":840,"y":1120,"wires":[[]]},{"id":"e76906a0.c7c718","type":"switch","z":"42ea7bd7.2e3c24","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"sheet/all","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":590,"y":1060,"wires":[["931be6f6.1fc0e8"]]},{"id":"931be6f6.1fc0e8","type":"function","z":"42ea7bd7.2e3c24","name":"generate cron schedules","func":"var days = [\"MON\", \"TUE\", \"WED\", \"THU\", \"FRI\", \"SAT\", \"SUN\"]\nvar dynamicCronCommands = [{ topic: \"remove-all-dynamic\", payload: { \"command\":\"remove-all-dynamic\"} }];\n\nfor (let index = 0; index < msg.payload.length; index++) {\n const sched = msg.payload[index];\n var ons = generateDynamicCronCmd(sched,index, \"on\");//on schedule\n var offs = generateDynamicCronCmd(sched, index, \"off\");//off schedule\n dynamicCronCommands.push(ons);\n dynamicCronCommands.push(offs);\n}\n\n\n\nfunction generateDynamicCronCmd(data, dayIndex, on_or_off) {\n var dayName = days[dayIndex];\n var on_or_off_int = (on_or_off == \"on\" || on_or_off == \"ON\" || on_or_off == 1) ? 1 : 0;\n var scheduleName = dayName + \"_\" + on_or_off;\n var cronExpression = `0 0 ${arrayToCronHourString(data, on_or_off_int)} * * ${dayName} *`;\n var cmd = {\n \"command\" : \"add\",\n \"name\": scheduleName,\n \"topic\": scheduleName,\n \"expression\": cronExpression,\n \"expressionType\": \"cron\",\n \"payloadType\": \"str\",\n \"payload\": on_or_off_int,\n }\n return cmd;\n}\n\n\nfunction arrayToCronHourString(arr, ifValue) {\n var result = [];\n for (let index = 0; index < arr.length; index++) {\n const element = arr[index];\n if(element == ifValue) {\n result.push(index)\n }\n }\n return result.join(\",\")\n}\nmsg.payload = dynamicCronCommands;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":800,"y":1060,"wires":[["8e712d91.f9ebc","dc325ddd.d276c"]]},{"id":"8e712d91.f9ebc","type":"debug","z":"42ea7bd7.2e3c24","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1010,"y":1060,"wires":[]},{"id":"14b42658.01e6ea","type":"inject","z":"42ea7bd7.2e3c24","name":"remove-all-dynamic","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"remove-all-dynamic","payload":"","payloadType":"date","x":470,"y":1120,"wires":[["dc325ddd.d276c"]]},{"id":"dce9e7a2.d20c78","type":"ui_group","name":"Object detection","tab":"5132060d.4cde48","order":1,"disp":true,"width":"7","collapse":false},{"id":"6d01ec93.b1d374","type":"ui_group","name":"UserEntry","tab":"5132060d.4cde48","order":2,"disp":true,"width":"12","collapse":false},{"id":"5132060d.4cde48","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]