UNPKG

node-red-contrib-automation-controller

Version:
985 lines (836 loc) 38.3 kB
<script type="text/html" data-template-name="automation controller"> <!-- name --> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="label.name"></span></label> <input type="text" id="node-input-name" data-i18n="[placeholder]text.name"> </div> <!-- in value --> <div class="form-row"> <label for="node-input-inputValue" data-i18n="label.input"></label> <input type="text" id="node-input-inputValue" style="width:70%"> <input type="hidden" id="node-input-inputType"> </div> <!-- behavior --> <div class="form-row"> <label for="node-rule-behavior" data-i18n="rule.behavior"></label> <select style="width:70%" id="node-rule-behavior"> <option value="sng" data-i18n="rule.behave.sng"></option> <option value="mul" data-i18n="rule.behave.mul"></option> <option value="can" data-i18n="rule.behave.can"></option> </select> </div> <!-- seperate outputs --> <div class="form-row"> <label for="node-input-seperated">&nbsp;</label> <label style="width:70%"> <input id="node-input-seperated" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.seperated"></span> <input type="hidden" id="node-input-outputs" value="1"> </label> </div> <!-- tabs --> <span id="rules" class="button-group"><button id="rules-create" type="button" class="red-ui-button toggle rules-group">+</button></span> <!-- index --> <div class="form-row" style="margin-top: 10px"> <label for="node-rule-index" data-i18n="label.idx"></label> <label id="node-rule-index"></label> </div> <!-- name --> <div class="form-row" style="margin-top: 10px"> <label for="node-rule-name" data-i18n="rule.name"></label> <input type="text" id="node-rule-name"> </div> <!-- match mode --> <div class="form-row"> <label for="node-rule-matchMode" data-i18n="rule.match"></label> <select style="width:70%" id="node-rule-matchMode"> <option value="event" data-i18n="rule.matches.event"></option> <option value="state" data-i18n="rule.matches.state"></option> </select> </div> <!-- active --> <div class="form-row"> <label id="node-rule-activeLbl" for="node-rule-active"></label> <input type="text" id="node-rule-active" style="width:70%"> <input type="hidden" id="node-rule-activeJS"> </div> <!-- inactive --> <div class="form-row" id="node-inactiveRow"> <label for="node-rule-inactive" data-i18n="label.imatch"></label> <input type="text" id="node-rule-inactive" style="width:70%"> <input type="hidden" id="node-rule-inactiveJS"> </div> <!-- cool down --> <div class="form-row" id="node-cool"> <label for="node-rule-cool-time"><i class="fa fa-stop-circle-o"></i> <span data-i18n="label.cooldown"></span></label> <input id="node-rule-cool-time" type="number" style="width: 70px"> <select style="width:150px" id="node-rule-cool-unit"> <option value="ms" data-i18n="date.time.ms"></option> <option value="s" data-i18n="date.time.s"></option> <option value="m" data-i18n="date.time.m"></option> <option value="h" data-i18n="date.time.h"></option> <option value="d" data-i18n="date.time.d"></option> </select><br/> </div> <!-- reset timeout --> <div class="form-row" id="node-resEvent"> <label for="node-rule-resEvent-time"><i class="fa fa-undo"></i> <span data-i18n="label.resEvent"></span></label> <input id="node-rule-resEvent-time" type="number" style="width: 70px"> <select style="width:150px" id="node-rule-resEvent-unit"> <option value="ms" data-i18n="date.time.ms"></option> <option value="s" data-i18n="date.time.s"></option> <option value="m" data-i18n="date.time.m"></option> <option value="h" data-i18n="date.time.h"></option> <option value="d" data-i18n="date.time.d"></option> </select><br/> </div> <!-- timeout --> <div class="form-row" id="node-toRow"> <label for="node-rule-timeOut-time"><i class="fa fa-stop-circle-o"></i> <span data-i18n="label.timeOut"></span></label> <input id="node-rule-timeOut-time" type="number" style="width: 70px"> <select style="width:150px" id="node-rule-timeOut-unit"> <option value="ms" data-i18n="date.time.ms"></option> <option value="s" data-i18n="date.time.s"></option> <option value="m" data-i18n="date.time.m"></option> <option value="h" data-i18n="date.time.h"></option> <option value="d" data-i18n="date.time.d"></option> </select><br/> </div> <!-- trigger --> <div class="form-row" id="node-triggerActive"> <label for="node-rule-triggerActive">&nbsp;</label> <label style="width:70%"> <input id="node-rule-triggerActive" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.triggerActive"></span> </label> </div> <!-- repeat message --> <div class="form-row" id="node-repMsg"> <label for="node-rule-repMsg" data-i18n="label.repMsg"></label> <input type="text" id="node-rule-repMsg" style="width:70%"> </div> <!-- repeat --> <div class="form-row" id="node-timeRow"> <label for="node-rule-repeat-time"><i class="fa fa-repeat"></i> <span data-i18n="label.repeat"></span></label> <input id="node-rule-repeat-time" type="number" style="width: 70px"> <select style="width:150px" id="node-rule-repeat-unit"> <option value="ms" data-i18n="date.time.ms"></option> <option value="s" data-i18n="date.time.s"></option> <option value="m" data-i18n="date.time.m"></option> <option value="h" data-i18n="date.time.h"></option> <option value="d" data-i18n="date.time.d"></option> </select><br/> </div> <!-- onInactive --> <div class="form-row" id="node-onInactive"> <label for="node-rule-onInactive" data-i18n="label.sendInactive"></label> <input type="text" id="node-rule-onInactive" style="width:70%"> <input type="hidden" id="node-rule-onInactiveJS"> </div> <!-- reset --> <div class="form-row" id="node-resetInitial"> <label for="node-rule-resetInitial">&nbsp;</label> <label style="width:70%"> <input id="node-rule-resetInitial" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.resetInitial"></span> </label> </div> <!-- out value --> <div class="form-row"> <label for="node-rule-output" data-i18n="label.output"></label> <input type="text" id="node-rule-output" style="width:70%"> <input type="hidden" id="node-rule-outputJS"> </div> <!-- mode --> <div class="form-row"> <label for="node-rule-mode" data-i18n="rule.mode"></label> <select style="width:70%" id="node-rule-mode"></select> </div> <div class="rules red-ui-editableList-border" style="margin-bottom: 10px; padding: 5px"> <!-- rule: single --> <div id="rules-single"> <div class="form-row"> <label for="node-rule-sValue" data-i18n="label.value"></label> <input id="node-rule-sValue" type="text"> <input id="node-rule-sValueJS" type="hidden"> </div> </div> <!-- rule: iterate --> <div id="rules-iterate"> <div class="form-row"> <label for="node-rule-iInit" data-i18n="label.init" style="width: 90px"></label> <input id="node-rule-iInit" type="text"> <input id="node-rule-iInitJS" type="hidden"> </div> <div class="form-row"> <label for="node-rule-iMin" data-i18n="label.min" style="width: 90px"></label> <input id="node-rule-iMin" type="text"> </div> <div class="form-row"> <label for="node-rule-iMax" data-i18n="label.max" style="width: 90px"></label> <input id="node-rule-iMax" type="text"> </div> <div class="form-row"> <label for="node-rule-iSteps" data-i18n="label.steps" style="width: 90px"></label> <input id="node-rule-iSteps" type="text"> </div> <div class="form-row"> <label for="node-rule-iCycle">&nbsp;</label> <label style="width:70%"> <input id="node-rule-iCycle" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.cycle"></span> </label> </div> <div class="form-row"> <label for="node-rule-iEdge">&nbsp;</label> <label style="width:70%"> <input id="node-rule-iEdge" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.enedge"></span> </label> </div> </div> <!-- rule: bounce --> <div id="rules-bounce"> <div class="form-row"> <label for="node-rule-bInit" data-i18n="label.init" style="width: 90px"></label> <input id="node-rule-bInit" type="text"> <input id="node-rule-bInitJS" type="hidden"> </div> <div class="form-row"> <label for="node-rule-bIPos">&nbsp;</label> <label style="width:70%"> <input id="node-rule-bIPos" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.ipos"></span> </label> </div> <div class="form-row"> <label for="node-rule-bMin" data-i18n="label.min" style="width: 90px"></label> <input id="node-rule-bMin" type="text"> </div> <div class="form-row"> <label for="node-rule-bMax" data-i18n="label.max" style="width: 90px"></label> <input id="node-rule-bMax" type="text"> </div> <div class="form-row"> <label for="node-rule-bUp" data-i18n="label.sup" style="width: 90px"></label> <input id="node-rule-bUp" type="text"> </div> <div class="form-row"> <label for="node-rule-bDown" data-i18n="label.sdown" style="width: 90px"></label> <input id="node-rule-bDown" type="text"> </div> <div class="form-row"> <label for="node-rule-bEdge">&nbsp;</label> <label style="width:70%"> <input id="node-rule-bEdge" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.enedge"></span> </label> </div> </div> <!-- rule: fixed --> <div id="rules-fixed"> <div class="form-row"> <label for="node-rule-fInit" data-i18n="label.inix" style="width: 90px"></label> <input id="node-rule-fInit" type="text"> <input id="node-rule-fInitJS" type="hidden"> </div> <div class="form-row"> <label for="node-rule-fValues">&nbsp;</label> <div id="node-rule-fValues" style="display: inline-block; background-color: #eee2; border: 1px solid #ccc; border-bottom: 0px none"></div> </div> <div class="form-row"> <label for="node-rule-fadd">&nbsp;</label> <button id="node-rule-fadd">+</button> </div> <div class="form-row"> <label for="node-rule-fCycle">&nbsp;</label> <label style="width:70%"> <input id="node-rule-fCycle" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.cycle"></span> </label> </div> </div> <!-- rule: linked --> <div id="rules-linked"> <div class="form-row"> <label for="node-rule-lLink" data-i18n="label.lrule" style="width: 90px"></label> <select id="node-rule-lLink"></select> </div> <div class="form-row"> <label for="node-rule-lNeg">&nbsp;</label> <label style="width:70%"> <input id="node-rule-lNeg" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.neg"></span> </label> </div> <div class="form-row"> <label for="node-rule-lUpRule">&nbsp;</label> <label style="width:70%"> <input id="node-rule-lUpRule" type="checkbox" style="display:inline-block; width:15px; vertical-align:baseline;"> <span data-i18n="label.upRule"></span> </label> </div> </div> <!-- delete --> <div class="form-row"> <label for="node-rule-delete">&nbsp;</label> <button id="node-rule-delete" class="red-ui-button primary" data-i18n="label.delete"></button> </div> </script> <script type="text/javascript"> (function() { const MAX_TABS = 10; const RULE_ENGINES = ["single", "iterate", "bounce", "fixed","linked"]; const defRule = { resetInitial: true, matchMode: 'event', active: 'active', activeType: 'str', inactive: 'inactive', inactiveType: 'str', onInactive: '', onInactiveType: 'nul', triggerActive: true, mode: 'iterate', output: 'payload', outputType: 'msg', repMsg: '', repMsgType: 'payl', cool: 0, coolType: 'ms', resEvent: 0, resEventType: 'm', rep: 500, repType: 'ms', to: 60, toType: 's', sValue: '1', sValueType: 'num', iInit: '0', iInitType: 'num', iMin: '0', iMinType: 'num', iMax: '255', iMaxType: 'num', iSteps: '1', iStepsType: 'num', iCycle: true, iEdge: false, bInit: '0', bInitType: 'num', bIPos: true, bMin: '0', bMinType: 'num', bMax: '255', bMaxType: 'num', bUp: '1', bUpType: 'num', bDown: '1', bDownType: 'num', bEdge: true, fInit: '0', fInitType: 'num', fValues: [ {v:'0', t:'num', js:''} ], fCycle: true, lLink: '', lNeg: true, lUpRule: true }; var selectedRule = 0; var opt = {}; var buildEditor = function(id, value, defaultValue) { var editor = RED.editor.createEditor({ id: id, mode: 'ace/mode/nrjavascript', value: value || defaultValue || "", globals: { msg:true, context:true, RED: true, util: true, flow: true, global: true, console: true, Buffer: true, setTimeout: true, clearTimeout: true, setInterval: true, clearInterval: true } }); if (defaultValue && value === "") { editor.moveCursorTo(defaultValue.split("\n").length - 1, 0); } return editor; }; function addFixedRow(node,v,t,js) { var pa = $('#node-rule-fValues'); var freeId = getFreeRuleId('#node-rule-fValues', 'node-rule-fField'); if (v===undefined) { v = freeId; t = 'num'; js = ''; } var e = document.createElement('div'); var s = document.createElement('label'); var i = document.createElement('input'); var ijs = document.createElement('input'); var r = document.createElement('button'); e.style.whiteSpace = "nowrap"; s.innerText = node._("label.index").replaceAll('%1', pa.children().length); e.id = 'node-rule-fField' + freeId; e.style.paddingTop = '8px'; e.style.paddingBottom = '8px'; e.style.borderBottom = '1px solid #ccc'; e.style.width = "330px"; i.style.width = "200px"; i.id = 'node-rule-fValue' + freeId; i.type = 'text'; ijs.id = 'node-rule-fValue' + freeId + 'JS'; ijs.type = 'hidden'; i.value = v; r.innerText = '-'; r.onclick = me=>removeFixedRow(e); e.append(s); e.append(' '); e.append(i); e.append(ijs); e.append(r); pa.append(e); $(i).typedInput({default:'num',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env',opt.js]}); $(i).typedInput('value', v); $(i).typedInput('type', t); $(ijs).val(js); updateFixedRowButtons(); } function removeFixedRow(re) { var pa = document.getElementById('node-rule-fValues'); pa.removeChild(re); for (var i = pa.children.length - 1; i >= 0; i--) { pa.children[i].children[0].innerText = 'Value ' + i +':'; } updateFixedRowButtons(); } function updateFixedRowButtons() { var pa = document.getElementById('node-rule-fValues'); var show = (pa.children.length>1); var p = pa.children[0]; for (var i=0; i<p.children.length; i++) { if (p.children[i].tagName.toUpperCase() == 'BUTTON') { p.children[i].style.display = show?"":"none"; } } } function getFreeRuleId(p,c) { var o = []; $(p).children().each((idx, e) => o.push( parseInt(e.id.replace(c,'')) ) ); var i = 0; while (i < o.length) { if (o.indexOf(i) == -1) return i; i++; } return i; } function findRule(node, id) { return (node.nrules || []).find(itm=> itm.id==id || itm.eid==id); } function createRule(node, selected) { var id = getFreeRuleId('#rules', 'rules-custom'); var rule = Object.assign({ id: id, rid: 100000+Math.floor(Math.random() * 1000000), eid:'rules-custom' + id, name: 'rule ' + id }, defRule); // Add output var currentOutputs = JSON.parse(node.outputCount.val()||"{}"); currentOutputs[rule.rid] = node.nrules.length; node.outputCount.val(JSON.stringify(currentOutputs)); // Connect and add rule node.nrules.push(rule); addRuleTab(node, rule, selected===true); } function addRuleTab(node, rule, selected, beforeElem) { var e = document.createElement('button'); e.id = rule.eid; e.className = 'red-ui-button toggle rules-group'; var img = document.createElement('i'); var lbl = document.createElement('span'); img.className = 'fa fa-expand'; lbl.innerText = rule.name; e.append(img); e.append(' '); e.append(lbl); $(e).on('click', function() { selectRuleTab(node, this); }); if (!!beforeElem) beforeElem = $(beforeElem); else beforeElem = $("#rules-create"); beforeElem.before(e); var count = beforeElem.parent().children().length; if (selected !== false || count==0) selectRuleTab(node,e); else updateCurrentTab(node); // Hide + on max tabs if (count > MAX_TABS) $("#rules-create").hide(); $("#node-rule-delete").show(); } function removeRuleTab(node, rule) { var idx = -1; for (var i = 0; i < node.nrules.length; i++) { if (rule === node.nrules[i]) { idx = i; break; } } if (idx == -1) { RED.notify('Invalid index, rule not found?',"error"); return; } node.nrules.splice(idx, 1); if (idx >= node.nrules.length) idx=node.nrules.length - 1; $('#' + rule.eid).remove(); selectRuleTab(node, document.getElementById(node.nrules[idx].eid)); // Remove output var currentOutputs = JSON.parse(node.outputCount.val()||"{}"); var n = -1; for (var i=0; i<node.nrules.length; i++) { currentOutputs[node.nrules[i].rid] = ++n; } currentOutputs[rule.rid] = -1; node.outputCount.val(JSON.stringify(currentOutputs)); $("#rules-create").show(); if ($("#rules-create").parent().children().length < 3) $("#node-rule-delete").hide(); } function selectRuleTab(node, e) { $(".rules-group").removeClass("selected"); $(e).addClass("selected"); saveData(node); selectedRule = findRule(node, e.id); loadData(node); updateCurrentTab(node); } function updateCurrentTab(node) { var e = document.getElementById(selectedRule.eid); const RULE_MODES = {event: 'fa-compress', state: 'fa-expand'}; updateMatchMode(node); refreshRuleEngineList(node); refreshRuleList(node); e.children[0].className = 'fa ' + RULE_MODES[$('#node-rule-matchMode').val()]; e.children[1].innerText = $('#node-rule-name').val(); if ($('#node-rule-iCycle').is(":checked")) { $('#node-rule-iMin').show(); } else { $('#node-rule-iMin').hide(); } } function updateMatchMode(node) { var v = $('#node-rule-matchMode').val(); switch (v) { case 'event': $('#node-cool').show(); $('#node-resEvent').show(); $('#node-inactiveRow').hide(); $('#node-triggerActive').hide(); $('#node-toRow').hide(); $('#node-timeRow').hide(); $('#node-resetInitial').hide(); $('#node-onInactive').hide(); $('#node-repMsg').hide(); $('#node-rule-activeLbl').text(node._('label.match')); break; case 'state': $('#node-cool').hide(); $('#node-resEvent').hide(); $('#node-inactiveRow').show(); $('#node-triggerActive').show(); $('#node-toRow').show(); $('#node-timeRow').show(); $('#node-resetInitial').show(); $('#node-onInactive').show(); $('#node-repMsg').show(); $('#node-rule-activeLbl').text(node._('label.amatch')); break; } } function refreshRuleEngineList(node) { var r = []; for (var i = 0; i < RULE_ENGINES.length; i++) { if (RULE_ENGINES[i]=='linked' && node.nrules!=undefined && node.nrules.length<=1) continue; r.push(RULE_ENGINES[i]); } refreshList(node, 'node-rule-mode', r, 'rule.modes.'); } function refreshRuleList(node) { var r = [], t = []; for (var i = 0; i < node.nrules.length; i++) { if (node.nrules[i]==selectedRule) continue; r.push(node.nrules[i].id); t.push(node.nrules[i].name); } refreshList(node, 'node-rule-lLink', r, t); } function refreshList(node, listName, data, txt) { var locTxt = Array.isArray(txt); var l = $('#'+listName); var sel = l.val(); var s = ''; for (var i=0; i<data.length; i++) { s+='<option value="'+data[i]+'"' + ((data[i]==sel)?' selected':'') + '>' + (locTxt ? txt[i] : node._(txt+data[i])) + '</option>'; } l.html(s); } function read(id, rule, check) { if (check !== true) { $('#node-rule-' + id).typedInput('type', 'str' ); $('#node-rule-' + id).typedInput('value', '' ); $('#node-rule-' + id).typedInput('type', rule[id + 'Type'] || 'num' ); $('#node-rule-' + id).typedInput('value', rule[id] || '' ); } else { $('#node-rule-' + id).prop("checked", rule[id] ); } } function write(id, rule, check) { var b = rule[id], bt=rule[id+'Type']; if (check !== true) { rule[id + 'Type'] = $('#node-rule-' + id).typedInput('type'); rule[id] = $('#node-rule-' + id).typedInput('value'); } else { rule[id] = $('#node-rule-' + id).prop("checked"); } } function loadData(node, rule) { if (!rule) rule = selectedRule; for (var i = 0; i < node.nrules.length; i++) if (node.nrules[i]==rule) $('#node-rule-index').text(i); $('#node-rule-name').val(rule.name); $('#node-rule-matchMode').val(rule.matchMode); $('#node-rule-mode').val(rule.mode); updateMode(rule.mode); read('output', rule); $('#node-rule-outputJS').val(rule.outputJS); read('active', rule); $('#node-rule-activeJS').val(rule.activeJS); read('inactive', rule); $('#node-rule-inactiveJS').val(rule.inactiveJS); read('triggerActive', rule, true); read('resetInitial', rule, true); read('onInactive', rule); $('#node-rule-onInactiveJS').val(rule.onInactiveJS); read('repMsg', rule); read('sValue', rule); $('#node-rule-sValueJS').val(rule.sValueJS); read('iInit', rule); $('#node-rule-iInitJS').val(rule.iInitJS); read('iMin', rule); read('iMax', rule); read('iSteps', rule); read('iCycle', rule, true); read('iEdge', rule, true); read('bInit', rule); $('#node-rule-bInitJS').val(rule.bInitJS); read('bIPos', rule, true); read('bMin', rule); read('bMax', rule); read('bUp', rule); read('bDown', rule); read('bEdge', rule, true); read('fInit', rule); $('#node-rule-fInitJS').val(rule.fInitJS); read('fCycle', rule, true); refreshRuleList(node); $('#node-rule-lLink').val(rule.lLink); read('lNeg', rule, true); read('lUpRule', rule, true); $('#node-rule-fValues').empty(); (rule.fValues || []).forEach( v => addFixedRow(node, v.v, v.t, v.js) ); $('#node-rule-cool-time').val(rule.cool); $('#node-rule-cool-unit').val(rule.coolType); $('#node-rule-resEvent-time').val(rule.resEvent); $('#node-rule-resEvent-unit').val(rule.resEventType); $('#node-rule-timeOut-time').val(rule.to); $('#node-rule-timeOut-unit').val(rule.toType); $('#node-rule-repeat-time').val(rule.rep); $('#node-rule-repeat-unit').val(rule.repType); } function saveData(node, rule) { if (!rule) rule = selectedRule; if (!rule) return; rule.name = $('#node-rule-name').val(); rule.matchMode = $('#node-rule-matchMode').val(); rule.mode = $('#node-rule-mode').val(); write('output', rule); rule.outputJS = rule.outputType=='js' ? $('#node-rule-outputJS').val() : ''; write('active', rule); rule.activeJS = rule.activeType=='js' ? $('#node-rule-activeJS').val() : ''; write('inactive', rule); rule.inactiveJS = rule.inactiveType=='js' ? $('#node-rule-inactiveJS').val() : ''; write('triggerActive', rule, true); write('resetInitial', rule, true); write('onInactive', rule); rule.onInactiveJS = rule.onInactiveType=='js' ? $('#node-rule-onInactiveJS').val() : ''; write('repMsg', rule); write('sValue', rule); rule.sValueJS = rule.sValueType=='js' ? $('#node-rule-sValueJS').val() : ''; write('iInit', rule); rule.iInitJS = rule.iInitType=='js' ? $('#node-rule-iInitJS').val() : ''; write('iMin', rule); write('iMax', rule); write('iSteps', rule); write('iCycle', rule, true); write('iEdge', rule, true); write('bInit', rule); rule.bInitJS = rule.bInitType=='js' ? $('#node-rule-bInitJS').val() : ''; write('bIPos', rule, true); write('bMin', rule); write('bMax', rule); write('bUp', rule); write('bDown', rule); write('bEdge', rule, true); write('fInit', rule); rule.fInitJS = rule.fInitType=='js' ? $('#node-rule-fInitJS').val() : ''; write('fCycle', rule, true); rule.lLink = $('#node-rule-lLink').val(); write('lNeg', rule, true); write('lUpRule', rule, true); rule.fValues = []; $('#node-rule-fValues').children().each((idx,e)=>{ var id = e.id.replace('node-rule-fField', ''); e = $('#node-rule-fValue' + id); var js = $('#node-rule-fValue' + id + 'JS'); rule.fValues.push({ v: e.typedInput('value'), t: e.typedInput('type'), js: js.val() }); }); rule.cool = $('#node-rule-cool-time').val(); rule.coolType = $('#node-rule-cool-unit').val(); rule.resEvent = $('#node-rule-resEvent-time').val(); rule.resEventType = $('#node-rule-resEvent-unit').val(); rule.to = $('#node-rule-timeOut-time').val(); rule.toType = $('#node-rule-timeOut-unit').val(); rule.rep = $('#node-rule-repeat-time').val(); rule.repType = $('#node-rule-repeat-unit').val(); } function updateMode(e) { if (!!e.target) e = e.target.value; // Show the correct mode components. RULE_ENGINES.forEach( m => (e==m)?$('#rules-'+m).show():$('#rules-'+m).hide() ); } function updateOutputs(node, upr) { var mout = $("#node-input-seperated").is(":checked"); var outs = {}; if (mout) { for (var i = 0; i < node.nrules.length; i++) { if (upr) node.nrules[i].rid = i; outs[node.nrules[i].rid] = i; } } else { outs[0] = 0; } node.outputCount = $("#node-input-outputs").val(JSON.stringify(outs)); } RED.nodes.registerType('automation controller', { category: 'function', color:"#a6cb6f", defaults: { name: {value:"" }, inputType: {value:"msg"}, inputValue: {value:"payload", validate: RED.validators.typedInput("inputType")}, repeatMsg: {value:"lat"}, seperated: {value:true}, behavior: {value:"mul"}, rules:{value:[]}, outputs: {value:1} }, align:"right", inputs:1, outputs:1, icon: "font-awesome/fa-hand-paper-o", outputLabels: function(i) { return this.seperated ? this.rules[i].name : "output"; }, label: function() { return this.name||this._("node.name"); }, labelStyle: function() { return this.name?"node_label_italic":""; }, oneditprepare: function() { var node = this; refreshRuleEngineList(node); var hJSEditor = function(editor) { return function(e) { if (e) e.preventDefault(); var value = editor.val(); RED.editor.editJavaScript({ value: value, width: "Infinity", cursor: 0, mode: "ace/mode/nrjavascript", complete: function(v,cursor) { editor.val(v); } }) } }; $("#node-input-inputValue").typedInput({ type:"msg", types:["msg","flow","global","env"], typeField: "#node-input-inputType" }); $('#node-rule-behavior').val(this.behavior); opt.nothing = {value:"nul",label:this._("option.nothing"),hasValue:false}; opt.original = {value:"pay",label:this._("option.original"),hasValue:false}; opt.latest = {value:"payl",label:this._("option.latest"),hasValue:false}; opt.rule = {value:"payr",label:this._("option.latestRule"),hasValue:false}; opt.js = {value:"js",label:this._("option.js"),hasValue:false,expand:function(){ hJSEditor($('#'+this.bindings[0].id+'JS'))(); }}; // Setup fields $("#node-rule-output").typedInput( { default:"msg", types:['msg','flow','global',opt.js] }); $("#node-rule-active").typedInput( { default:"str", types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env',opt.js] }); $("#node-rule-inactive").typedInput( { default:"str", types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env',opt.js] }); $("#node-rule-onInactive").typedInput( { default:"str", types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env',opt.js,opt.nothing] }); $("#node-rule-repMsg").typedInput( { default:'payl', types:['json',opt.original,opt.rule,opt.latest] }); $("#node-rule-sValue").typedInput({ default:"num", types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env', opt.js] }); $("#node-rule-iInit").typedInput( { default:"num", types:['num','msg','flow','global','env', opt.js] }); $("#node-rule-iMin").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-iMax").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-iSteps").typedInput({ default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-bInit").typedInput( { default:"num", types:['num','msg','flow','global','env', opt.js] }); $("#node-rule-bMin").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-bMax").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-bUp").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-bDown").typedInput( { default:"num", types:['num','msg','flow','global','env'] }); $("#node-rule-fInit").typedInput( { default:"num", types:['num','msg','flow','global','env', opt.js] }); // Connect listeners $('#node-rule-iCycle').on('change', ev=>updateCurrentTab(node)); $('#node-rule-name').on('change', ev=>updateCurrentTab(node)); $('#node-rule-matchMode').on('change', ev=>updateCurrentTab(node)); $('#node-rule-mode').on('change', updateMode); $("#node-rule-fadd").on('click', ()=>addFixedRow(node)); $("#node-rule-delete").on('click', ()=>removeRuleTab(node, selectedRule)); // Prepare new rules (will be applied to "rules" when saving) node.nrules = Object.assign(!!node.rules ? node.rules.slice() : []); // Add previous tabs $("#rules-create").show(); $("#node-rule-delete").hide(); // Add tabs for (var i = 0; i < node.nrules.length; i++) addRuleTab(node, node.nrules[i], i==0); updateOutputs(node, true); $("#node-input-seperated").on("click", () => updateOutputs(node, false)); if (node.nrules.length == 0) createRule(node, true); // Connect create new tab $("#rules-create").on("click", () => createRule(node) ); }, oneditsave: function() { this.behavior = $('#node-rule-behavior').val(); saveData(this); delete this.outputCount; selectedRule = undefined; this.rules = this.nrules; delete this.nrules; }, oneditcancel: function() { selectedRule = undefined; delete this.nrules; } }); })(); </script>