diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py index f60809c4..e9b6cc76 100644 --- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py +++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py @@ -16,6 +16,7 @@ import importlib from importlib import util import threading # Multi-threading for RobotRDPActive from .RobotRDPActive import RobotRDPActive #Start robot rdp active +from .RobotScreenActive import Monitor #Start robot screen active import uuid # Generate uuid #Единый глобальный словарь (За основу взять из Settings.py) @@ -54,6 +55,12 @@ lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict) lThreadServer.start() if lL: lL.info("Web server has been started") #Logging +# Init the RobotScreenActive in another thread +lRobotScreenActiveThread = threading.Thread(target= Monitor.CheckScreen) +lRobotScreenActiveThread.daemon = True # Run the thread in daemon mode. +lRobotScreenActiveThread.start() # Start the thread execution. +if lL: lL.info("Robot Screen active has been started") #Logging + # Init the RobotRDPActive in another thread lRobotRDPActiveThread = threading.Thread(target= RobotRDPActive.RobotRDPActive, kwargs={"inGSettings":gSettingsDict}) lRobotRDPActiveThread.daemon = True # Run the thread in daemon mode. diff --git a/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat new file mode 100644 index 00000000..c9dffba5 --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat @@ -0,0 +1,3 @@ +for /f "skip=1 tokens=3" %%s in ('query user %USERNAME%') do ( + %windir%\System32\tscon.exe %%s /dest:console +) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py new file mode 100644 index 00000000..50683680 --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py @@ -0,0 +1,14 @@ +import time #lib to create delay +from . import Screen # module to detect screen exists +#Check screen every 1 second +def CheckScreen(inIntervalSeconds=1): + while True: + #Check if screen exist + if not Screen.Exists(): + #Send os command to create console version (base screen) + Screen.ConsoleScreenBase() + #Delay to create console screen + time.sleep(2) + #Delay + time.sleep(inIntervalSeconds) + return None \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py new file mode 100644 index 00000000..1d5ffecc --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py @@ -0,0 +1,20 @@ +from PIL import ImageGrab +import os # to execute cmd commands +#Check if screen is exists +def Exists(): + #Try to get 1 px from screen + try: + #Take 1 px + ImageGrab.grab(bbox=(0,0,1,1)) + #Screen is exists - return True + return True + #Catch exception + except Exception: + #Screen does not exists - return false + return False +#Make console session +def ConsoleScreenBase(): + #Get script folder path + lFolderPath = "/".join(__file__.split("\\")[:-1]) + #Send command to cmd + os.system(os.path.join(lFolderPath,"ConsoleStart.bat")) \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py new file mode 100644 index 00000000..e871045a --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py @@ -0,0 +1,16 @@ +#Run example +#cd %~dp0..\..\Sources +#..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe -m pyOpenRPA.Tools.RobotScreenActive +#pause >nul +#Import parent folder to import current / other packages +######################################################### +import sys +import subprocess #start process async +import os #path, run, remove +import time #timer +import importlib +#lFolderPath = "\\".join(__file__.split("\\")[:-4]) +lFolderPath = "/".join(__file__.split("/")[:-4]) +sys.path.insert(0, lFolderPath) +from pyOpenRPA.Tools.RobotScreenActive import Monitor +Monitor.CheckScreen() \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.js b/Sources/pyOpenRPA/Orchestrator/Web/Index.js new file mode 100644 index 00000000..67502015 --- /dev/null +++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.js @@ -0,0 +1,646 @@ +var mGlobal={} +$(document).ready(function() { + // fix main menu to page on passing + $('.main.menu').visibility({ + type: 'fixed' + }); + $('.overlay').visibility({ + type: 'fixed', + offset: 80 + }); + + // lazy load images + $('.image').visibility({ + type: 'image', + transition: 'vertical flip in', + duration: 500 + }); + + // show dropdown on hover + $('.main.menu .ui.dropdown').dropdown({ + on: 'hover' + }); + function clone(obj) { + var copy; + + // Handle the 3 simple types, and null or undefined + if (null == obj || "object" != typeof obj) return obj; + + // Handle Date + if (obj instanceof Date) { + copy = new Date(); + copy.setTime(obj.getTime()); + return copy; + } + + // Handle Array + if (obj instanceof Array) { + copy = []; + for (var i = 0, len = obj.length; i < len; i++) { + copy[i] = clone(obj[i]); + } + return copy; + } + + // Handle Object + if (obj instanceof Object) { + copy = {}; + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]); + } + return copy; + } + throw new Error("Unable to copy obj! Its type isn't supported."); + } + //For data storage key + mGlobal["DataStorage"] = {} + + String.prototype.replaceAll = function(search, replace){ + return this.split(search).join(replace); + } + mGlobal.GeneralGenerateHTMLCodeHandlebars=function(inInnerTemplateSelector,inData) { + lHTMLTemplate=$(inInnerTemplateSelector)[0].innerHTML + //console.log(lHTMLTemplate) + //Компиляция + var template = Handlebars.compile(lHTMLTemplate); + //Вставка данных + var lHTMLResult = template(inData); + return lHTMLResult + } + mGlobal.GeneralGenerateHTMLCode=function(inTemplateHTMLSelector,inItemDictionary,inKeywordPrefix="::",inKeywordPostfix="::") { + ///Получить заготовку + lTemplateHTMLCode=$(inTemplateHTMLSelector)[0].outerHTML + ///Определить ключь экранирования специальных ключевых слов + ///Выполнить циклические замены, если там есть пожходящие ключи + lResultHTMLCode=lTemplateHTMLCode + for(var lKey in inItemDictionary) { + lHTMLKey=inKeywordPrefix+lKey+inKeywordPostfix; + lResultHTMLCode=lResultHTMLCode.replaceAll(lHTMLKey,inItemDictionary[lKey]) + } + ///Вернуть результат + return lResultHTMLCode + } + ////////////////////////// + /////Info JS module + ////////////////////////// + mGlobal.Info={}; + + mGlobal.Info.TableActivityLogScheduleListRefresh=function() { + + } + ////////////////////////// + /////Controller JS module + ////////////////////////// + mGlobal.Controller={}; + mGlobal.Controller.CMDRunText=function(inCMDText) { + ///Подготовить конфигурацию + lData = [ + {"Type":"CMDStart", "Command": inCMDText} + ] + ///Обнулить таблицу + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3){}, + dataType: "text" + }); + } + mGlobal.Controller.CMDRun=function() { + ///Обнулить таблицу + lCMDCode=$(".openrpa-controller-cmd-run-input")[0].value + ///Подготовить конфигурацию + lData = [ + {"Type":"CMDStart", "Command": lCMDCode } + ] + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Отправить запрос на формирование таблицы + //lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result) + }, + dataType: "text" + }); + } + mGlobal.Controller.CMDRunGUILogout=function() { + ///Обнулить таблицу + lCMDCode="for /f \"skip=1 tokens=2\" %s in ('query user %USERNAME%') do (tscon \\dest:console)" + //lCMDCode = lCMDCode.replace(/\\n/g, "\\n") + // .replace(/\\'/g, "\\'") + // .replace(/\\"/g, '\\"') + // .replace(/\\&/g, "\\&") + // .replace(/\\r/g, "\\r") + // .replace(/\\t/g, "\\t") + // .replace(/\\b/g, "\\b") + // .replace(/\\f/g, "\\f") + // .replace('"', "\\\""); + ///Подготовить конфигурацию + lData = [ + {"Type":"CMDStart", "Command": lCMDCode } + ] + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Отправить запрос на формирование таблицы + //lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result) + }, + dataType: "text" + }); + } + ///Перезагрузить Orchestrator + mGlobal.Controller.OrchestratorRestart=function() { + ///Подготовить конфигурацию + lData = [ + {"Type":"OrchestratorRestart"} + ] + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + }, + dataType: "text" + }); + } + ////////////////////////// + /////Monitor JS module + ////////////////////////// + mGlobal.Monitor={}; + mGlobal.Monitor.ScreenshotModal={}; + mGlobal.Monitor.GenerateUniqueID=function(inPrefix="tempUID=") { + return inPrefix+Math.round(Math.random()*1000)+"-"+Math.round(Math.random()*10000)+"-"+Math.round(Math.random()*1000) + } + //inHostURI: http://localhost:8081 + mGlobal.Monitor.ScreenshotModal.Show=function(inHostURI=" ") { + $('.ui.modal.daemon-screenshot').modal('show'); + + //Функция обновления картинки + lScreenshotUpdate=function() { + lScreenshotSrc=inHostURI+"/GetScreenshot?"+mGlobal.Monitor.GenerateUniqueID() + $(".daemon-screenshot img").attr('src', lScreenshotSrc); + } + + mGlobal.Monitor.ScreenshotModal.timerId=setInterval(lScreenshotUpdate,1500) + } + mGlobal.Monitor.ScreenshotModal.Close=function() { + clearInterval(mGlobal.Monitor.ScreenshotModal.timerId); + } + ///Monitor + mGlobal.Monitor.DaemonList={} + mGlobal.Monitor.DaemonList.fRefreshTable=function() { + ///Загрузка данных + $.ajax({ + type: "GET", + url: 'Monitor/JSONDaemonListGet', + data: '', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Сформировать HTML код новой таблицы + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-monitor-table-general",lResponseJSON) + ///Очистить дерево + //mGlobal.ElementTree.fClear(); + ///Прогрузить новую таблицу + $(".openrpa-monitor").html(lHTMLCode) + }, + dataType: "text" + }); + } + //////////////////////////////// + ///////Control panel + /////////////////////////////// + ///Refresh control panel + mGlobal.Monitor.fControlPanelRefresh=function() { + ///Загрузка данных + $.ajax({ + type: "GET", + url: 'Monitor/ControlPanelDictGet', + data: '', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Escape onclick + /// RenderRobotList + lResponseJSON["RenderRobotList"].forEach( + function(lItem){ + if ('FooterButtonX2List' in lItem) { + /// FooterButtonX2List + lItem["FooterButtonX2List"].forEach( + function(lItem2){ + if ('OnClick' in lItem) { + lOnClickEscaped = lItem["OnClick"]; + lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + lItem["OnClick"] = lOnClickEscaped; + } + } + ); + /// FooterButtonX1List + lItem["FooterButtonX1List"].forEach( + function(lItem2){ + if ('OnClick' in lItem) { + lOnClickEscaped = lItem["OnClick"]; + lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + lItem["OnClick"] = lOnClickEscaped; + } + } + ); + } + } + ); + ///Сформировать HTML код новой таблицы + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-control-panel",lResponseJSON) + //Присвоить ответ в mGlobal.Monitor.mResponseList + mGlobal.Monitor.mResponseList = lResponseJSON + ///Set result in mGlobal.DataStorage + lResponseJSON["RenderRobotList"].forEach( + function(lItem){ + if ('DataStorageKey' in lItem) { + mGlobal["DataStorage"][lItem['DataStorageKey']]=lItem + } + } + ) + ///Очистить дерево + //mGlobal.ElementTree.fClear(); + ///Прогрузить новую таблицу + $(".openrpa-control-panel").html(lHTMLCode) + }, + dataType: "text" + }); + } + /// + mGlobal.Monitor.mControlPanelAutoUpdateSeconds=3; + mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=3; + mGlobal.Monitor.fControlPanelAutoUpdateRun=function(inRefreshSeconds) { + mGlobal.Monitor.mControlPanelAutoUpdateSeconds=inRefreshSeconds; + //Функция обновления текста кнопки обновления + lControlPanelUpdate=function() { + mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent-1 + if (mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent==-1) { + mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent=mGlobal.Monitor.mControlPanelAutoUpdateSeconds; + mGlobal.Monitor.fControlPanelRefresh() + } + $(".openrpa-control-panel-general .openrpa-refresh-button").html("Refresh "+mGlobal.Monitor.mControlPanelAutoUpdateSecondsCurrent); + } + mGlobal.Monitor.mControlPanelAutoUpdateTimerId=setInterval(lControlPanelUpdate,1000) + } + mGlobal.Monitor.fControlPanelRefresh() + mGlobal.Monitor.fControlPanelAutoUpdateRun(3); + //////////////////////////////// + /////// /Orchestrator/RobotRDPActive/ControlPanelDictGet + /////////////////////////////// + mGlobal.RobotRDPActive = {} + ///Refresh control panel + mGlobal.RobotRDPActive.fControlPanelRefresh=function() { + ///Загрузка данных + $.ajax({ + type: "GET", + url: 'Orchestrator/RobotRDPActive/ControlPanelDictGet', + data: '', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Сформировать HTML код новой таблицы + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON) + //Присвоить ответ в mGlobal.RobotRDPActive.mResponseList + mGlobal.RobotRDPActive.mResponseList = lResponseJSON + ///Прогрузить новую таблицу + $(".openrpa-robotrdpactive-control-panel").html(lHTMLCode) + }, + dataType: "text" + }); + } + /// + mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds=3; + mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=3; + mGlobal.RobotRDPActive.fControlPanelAutoUpdateRun=function(inRefreshSeconds) { + mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds=inRefreshSeconds; + //Функция обновления текста кнопки обновления + lControlPanelUpdate=function() { + mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent-1 + if (mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent==-1) { + mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent=mGlobal.RobotRDPActive.mControlPanelAutoUpdateSeconds; + mGlobal.RobotRDPActive.fControlPanelRefresh() + } + $(".openrpa-robotrdpactive-control-panel-general .openrpa-refresh-button").html("Refresh "+mGlobal.RobotRDPActive.mControlPanelAutoUpdateSecondsCurrent); + } + mGlobal.RobotRDPActive.mControlPanelAutoUpdateTimerId=setInterval(lControlPanelUpdate,1000) + } + mGlobal.RobotRDPActive.fControlPanelRefresh() + mGlobal.RobotRDPActive.fControlPanelAutoUpdateRun(3); + mGlobal.Test=function() { + ///Обнулить таблицу + lData = [ + { + "Type":"GlobalDictKeyListValueSet", + "key_list":["Storage","Robot_R01"], + "value":{ + "RunDateTimeString":"Test1", + "StepCurrentName":"Test2", + "StepCurrentDuration":"Test3" + } + } + ] + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + //console.log(lData) + }, + dataType: "text" + }); + } + /////////////////////////////// + ///Processor functions + /////////////////////////////// + mGlobal.Processor = {} + mGlobal.Processor.ServerValueAppend = function(inKeyList,inValue) { + lData = [ + { + "Type":"GlobalDictKeyListValueAppend", + "KeyList": inKeyList, + "Value": inValue + } + ] + ///Обнулить таблицу + $('.ui.modal.basic .content').html(""); + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///TODO Show error if exist error + }, + dataType: "text" + }); + } + mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) { + lData = [ + { + "Type":"GlobalDictKeyListValueSet", + "KeyList": inKeyList, + "Value": inValue + } + ] + ///Обнулить таблицу + $('.ui.modal.basic .content').html(""); + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///TODO Show error if exist error + }, + dataType: "text" + }); + } + mGlobal.Processor.ServerValueOperatorPlus = function(inKeyList,inValue) { + lData = [ + { + "Type":"GlobalDictKeyListValueOperator+", + "KeyList": inKeyList, + "Value": inValue + } + ] + ///Обнулить таблицу + $('.ui.modal.basic .content').html(""); + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///TODO Show error if exist error + }, + dataType: "text" + }); + } + mGlobal.Processor.Send = function(inData) { + lData = inData + $.ajax({ + type: "POST", + url: 'Utils/Processor', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///TODO Show error if exist error + }, + dataType: "text" + }); + } + mGlobal.Server= {} + mGlobal.Server.JSONGet=function(inMethod, inURL, inDataJSON, inCallback) + { + $.ajax({ + type: inMethod, + url: inURL, + data: JSON.stringify(inDataJSON), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + inCallback(lResponseJSON) + }, + dataType: "text" + }); + } + + ///////////////// + ///Modal + /////////////////// + mGlobal.Modal={} + ///////////////////////////////////////////////////// + mGlobal.Modal.TableFilter={} + mGlobal.Modal.TableFilter.Show=function(inJSON) { + //{ + // "Title":"", + // "Headers":["Header1","Header2"], + // "Rows": [["Cell1","Cell2"],["Cell2-1","Cell2-2"]], + // "FilterOnKeyUp": "" //Fill here in function + //} + //Set js handler to Search field + inJSON["FilterOnKeyUp"]="mGlobal.Modal.TableFilter.FilterUpdate(this.value);" + ///Set value + mGlobal.Modal.TableFilter.mDataJSON = inJSON + //Render HTML + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",inJSON); + ///Установить HTML код + $('.ui.modal.basic .content').html(lHTMLCode); + $('.ui.modal.basic').modal('show'); + //DO widest modal for table with scroll x + $("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["width"]="1300px" + $("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["overflow"]="scroll" + } + //Service function + mGlobal.Modal.TableFilter.FilterUpdate=function(inFilterValue) { + //Get JSON, apply filter, clone data + lDataJSON = clone(mGlobal.Modal.TableFilter.mDataJSON) + delete lDataJSON["Rows"] + lDataJSON["Rows"]=[] + //Filter code [any occurence in the row is ok for push! ] + mGlobal.Modal.TableFilter.mDataJSON["Rows"].forEach( + function(inElement) { + lFlagElementAppend = false + inElement.forEach( + function(inElement2) { + if (String(inElement2).includes(inFilterValue)) { + lFlagElementAppend = true + } + } + ) + if (lFlagElementAppend) { + lDataJSON["Rows"].push(inElement) + } + } + ) + //Clear Filter Title property (fixed in html) + delete lDataJSON["FilterOnKeyUp"] + delete lDataJSON["Title"] + //Search the table element [replace only table html] + lElement = $('.ui.modals.active .content table.table')[0] + lElementParentElement = lElement.parentNode + lElement.parentNode.removeChild(lElement); + //Render HTML + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",lDataJSON); + ///Установить HTML код + lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode); + } + ///////////////////////////////////////////////////////////// + mGlobal.Modal.ListFilter={} + mGlobal.Modal.ListFilter.Show=function(inJSON) { + //{ + // "Title":"", + // "List":[{"Header":"","Description":""}], + // "FilterOnKeyUp": "" //Fill here in function + //} + //Set js handler to Search field + inJSON["FilterOnKeyUp"]="mGlobal.Modal.ListFilter.FilterUpdate(this.value);" + ///Set value + mGlobal.Modal.ListFilter.mDataJSON = inJSON + //Render HTML + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",inJSON); + ///Установить HTML код + $('.ui.modal.basic .content').html(lHTMLCode); + $('.ui.modal.basic').modal('show'); + } + //Service function + mGlobal.Modal.ListFilter.FilterUpdate=function(inFilterValue) { + //Get JSON, apply filter, clone data + lDataJSON = clone(mGlobal.Modal.ListFilter.mDataJSON) + delete lDataJSON["List"] + lDataJSON["List"]=[] + //Filter code [any occurence in the row is ok for push! ] + mGlobal.Modal.ListFilter.mDataJSON["List"].forEach( + function(inElement) { + lFlagElementAppend = false + if (String(inElement["Header"]).includes(inFilterValue)) { + lFlagElementAppend = true + } + if (String(inElement["Description"]).includes(inFilterValue)) { + lFlagElementAppend = true + } + if (lFlagElementAppend) { + lDataJSON["List"].push(inElement) + } + } + ) + //Clear Filter Title property (fixed in html) + delete lDataJSON["FilterOnKeyUp"] + delete lDataJSON["Title"] + //Search the table element [replace only table html] + lElement = $('.ui.modals.active .content div.ui.inverted.segment')[0] + lElementParentElement = lElement.parentNode + lElement.parentNode.removeChild(lElement); + //Render HTML + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",lDataJSON); + ///Установить HTML код + lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode); + } + mGlobal.UserRoleHierarchyDict = null // Put here the user role hierarchy + // UAC Ask + mGlobal.UserRoleAsk=function(inList) { + var lResult = true; // Init flag + var lRoleHierarchyDict = mGlobal.UserRoleHierarchyDict; // get the Hierarchy + // Try to get value from key list + var lKeyValue = lRoleHierarchyDict; // Init the base + var lListLength = inList.length; + for (var i = 0; i 0) { // false - if Dict has some elements + lResult = false; // Set the False Flag + } else { + lResult = true; // Set the true flag + } + break; // Stop the loop + } + } else { // Has element with no detalization - return true + lResult = true; // Set the flag + break; // Close the loop + } + } + return lResult; // Return the result + } + // Check user roles and update the Orchestrator UI + mGlobal.UserRoleUpdate=function() { + $.ajax({ + type: "POST", + url: 'Orchestrator/UserRoleHierarchyGet', + data: "", + success: + function(lData,l2,l3) + { + var lUACAsk = mGlobal.UserRoleAsk // Alias + var lResponseDict=JSON.parse(lData) + mGlobal.UserRoleHierarchyDict = lResponseDict // set the user role hierarchy + //Turn on the Lookmachine screenshot button + if (lUACAsk(["Orchestrator","Controls","LookMachineScreenshots"])) { + $(".openrpa-control-lookmachinescreenshot").show() //Show button + } + //Turn on the restart orchestrator button + if (lUACAsk(["Orchestrator","Controls","RestartOrchestrator"])) { + $(".openrpa-control-restartorchestrator").show() //Show button + } + //Turn on the rdp session list + if (lUACAsk(["Orchestrator","RDPActive","ListRead"])) { + $(".openrpa-rdpactive-title").show() //Show section + $(".openrpa-robotrdpactive-control-panel-general").show() //Show section + } + }, + dataType: "text" + }); + } + mGlobal.UserRoleUpdate() // Cal the update User Roles function +}); \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml index 0dd8106d..7a3b535c 100644 --- a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml +++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml @@ -775,29 +775,39 @@ -
-
-

Controls

-
-
-

...

-
-
- -
- -
+
- - - +

+ +
+ Administration +
+

+ + + +