diff --git a/Sources/Sandbox/OrchestratorTestInit.ipynb b/Sources/Sandbox/OrchestratorTestInit.ipynb index 7cd24ae4..85997a77 100644 --- a/Sources/Sandbox/OrchestratorTestInit.ipynb +++ b/Sources/Sandbox/OrchestratorTestInit.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -37,84 +37,7 @@ "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2020-10-11 00:32:27,869 - Orchestrator - INFO - Link the gSettings in submodules\n", - "2020-10-11 00:32:27,878 - Orchestrator - WARNING - Backward compatibility (v1.1.13 to v1.1.14): Add default 'Autocleaner' structure\n", - "2020-10-11 00:32:27,880 - Orchestrator - WARNING - Backward compatibility (v1.1.13 to v1.1.14): Add default 'Client' structure\n", - "2020-10-11 00:32:27,882 - Orchestrator - WARNING - Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property\n", - "2020-10-11 00:32:27,883 - Orchestrator - WARNING - Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list\n", - "2020-10-11 00:32:27,886 - Orchestrator - WARNING - Backward compatibility (v1.1.20 to v1.2.0): Remove old structure 'Processor'\n", - "2020-10-11 00:32:27,888 - Orchestrator - WARNING - Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'\n", - "2020-10-11 00:32:27,893 - Orchestrator - INFO - Server init. Listen URL: , Listen port: 80\n", - "2020-10-11 00:32:27,893 - Orchestrator - INFO - Web server has been started\n", - "2020-10-11 00:32:27,932 - Orchestrator - INFO - Robot Screen active has been started\n", - "2020-10-11 00:32:27,937 - Orchestrator - INFO - Robot RDP active has been started\n", - "2020-10-11 00:32:27,940 - Orchestrator - INFO - Autocleaner thread has been started\n", - "2020-10-11 00:32:27,942 - Orchestrator - INFO - Orchestrator start activity run\n", - "2020-10-11 00:32:27,944 - Orchestrator - INFO - Scheduler loop start\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "----------------------------------------\n", - "Exception happened during processing of request from ('127.0.0.1', 57154)\n", - "Traceback (most recent call last):\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 650, in process_request_thread\n", - " self.finish_request(request, client_address)\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 476, in finish_request\n", - " HTTPServer.finish_request(self, request, client_address)\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 360, in finish_request\n", - " self.RequestHandlerClass(request, client_address, self)\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 720, in __init__\n", - " self.handle()\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\http\\server.py\", line 426, in handle\n", - " self.handle_one_request()\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\http\\server.py\", line 414, in handle_one_request\n", - " method()\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 336, in do_GET\n", - " lAuthenticateDict = AuthenticateVerify(self)\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 73, in AuthenticateVerify\n", - " \"Password\": lPassword\n", - " File \"..\\pyOpenRPA\\Orchestrator\\ProcessorOld.py\", line 94, in Activity\n", - " lItem[\"Result\"] = Processor.ActivityListExecute(inGSettings = gSettingsDict, inActivityList = [inActivity])\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Processor.py\", line 32, in ActivityListExecute\n", - " if callable(lActivityItem[\"Def\"]): # CHeck if def is callable\n", - "KeyError: 'Def'\n", - "----------------------------------------\n", - "----------------------------------------\n", - "Exception happened during processing of request from ('127.0.0.1', 57158)\n", - "Traceback (most recent call last):\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 650, in process_request_thread\n", - " self.finish_request(request, client_address)\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 476, in finish_request\n", - " HTTPServer.finish_request(self, request, client_address)\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 360, in finish_request\n", - " self.RequestHandlerClass(request, client_address, self)\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\socketserver.py\", line 720, in __init__\n", - " self.handle()\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\http\\server.py\", line 426, in handle\n", - " self.handle_one_request()\n", - " File \"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\python-3.7.2.amd64\\lib\\http\\server.py\", line 414, in handle_one_request\n", - " method()\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 336, in do_GET\n", - " lAuthenticateDict = AuthenticateVerify(self)\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Server.py\", line 73, in AuthenticateVerify\n", - " \"Password\": lPassword\n", - " File \"..\\pyOpenRPA\\Orchestrator\\ProcessorOld.py\", line 94, in Activity\n", - " lItem[\"Result\"] = Processor.ActivityListExecute(inGSettings = gSettingsDict, inActivityList = [inActivity])\n", - " File \"..\\pyOpenRPA\\Orchestrator\\Processor.py\", line 32, in ActivityListExecute\n", - " if callable(lActivityItem[\"Def\"]): # CHeck if def is callable\n", - "KeyError: 'Def'\n", - "----------------------------------------\n" - ] - } - ], + "outputs": [], "source": [ "from pyOpenRPA.Orchestrator import Orchestrator # Import orchestrator main\n", "Orchestrator.Orchestrator(inGSettings=gSettings) # Call the orchestrator" @@ -122,10 +45,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "import os\n", + "t=os.system(\"echo 2313\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t" + ] }, { "cell_type": "code", diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py index d6c7878c..3c15dd6a 100644 --- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py @@ -9,6 +9,7 @@ import uuid # generate UUID4 import time # sleep functions import datetime # datetime functions import threading # Multi-threading +from .Web import Basic # Generate CP # Return {"Key":{"",""}} @@ -38,7 +39,12 @@ def HiddenCPDictGenerate(inRequest, inGSettings): lItemResultDict = lItem["RenderFunction"]() # RunFunction # lResultJSON["RenderRobotList"].append(lItemResultDict) - lCPDict[lItem["KeyStr"]] = lItemResultDict + # Backward compatibility up to 1.2.0 - call HTML generator if result has no "HTMLStr" + if "HTMLStr" in lItemResultDict or "DataDict" in lItemResultDict: + lCPDict[lItem["KeyStr"]] = lItemResultDict # new version + else: + # Call backward compatibility HTML generator + lCPDict[lItem["KeyStr"]] = {"HTMLStr": Basic.HTMLControlPanelBC(inCPDict=lItemResultDict), "DataDict":{}} except Exception as e: if lL: lL.exception(f"Error in control panel. CP item {lItem}. Exception is below") return lCPDict @@ -61,7 +67,8 @@ def HiddenRDPDictGenerate(inRequest, inGSettings): return lRDPDict #v1.2.0 Send data container to the client from the server -# /pyOpenRPA/ServerData return {"HashStr" , "ServerDataDict"} +# /pyOpenRPA/ServerData return {"HashStr" , "ServerDataDict": {"CPKeyStr":{"HTMLStr":"", DataDict:{}}}} + # Client: mGlobal.pyOpenRPA.ServerDataHashStr # Client: mGlobal.pyOpenRPA.ServerDataDict def pyOpenRPA_ServerData(inRequest,inGSettings): @@ -73,7 +80,6 @@ def pyOpenRPA_ServerData(inRequest,inGSettings): lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) # Превращение массива байт в объект lValueStr = (lInputByteArray.decode('utf8')) - # Generate ServerDataDict lFlagDoGenerateBool = True while lFlagDoGenerateBool: @@ -92,6 +98,11 @@ def pyOpenRPA_ServerData(inRequest,inGSettings): time.sleep(inGSettings["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"]) # Return the result if Hash is changed lResult = {"HashStr": lServerDataHashStr, "ServerDataDict": lServerDataDict} + inResponseDict = inRequest.OpenRPAResponseDict + # Send message back to client + message = json.dumps(lResult) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") return lResult diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Basic.py b/Sources/pyOpenRPA/Orchestrator/Web/Basic.py index 96e5992c..cc339d06 100644 --- a/Sources/pyOpenRPA/Orchestrator/Web/Basic.py +++ b/Sources/pyOpenRPA/Orchestrator/Web/Basic.py @@ -23,4 +23,56 @@ def HTMLLinkJSOnClick(inJSOnClickStr, inTitleStr, inColorStr=None): if inColorStr: lCSSStyleStr=f"style=\"color:{inColorStr}\"" inJSOnClickStr= JSEscapeForHTMLInline(inJSStr=inJSOnClickStr) # Escape some symbols for the inline JS lResult=f"{inTitleStr}" - return lResult \ No newline at end of file + return lResult + + +# HTML Generator for the CP up to v.1.2.0 +def HTMLControlPanelBC(inCPDict): + # FooterButtonX2List generation + lFooterButtonX2Str = "" + for lItem in inCPDict["FooterButtonX2List"]: + lFooterButtonX2Str+=f'
{lItem.get("Text","")}
' + # FooterButtonX1List generation + lFooterButtonX1Str = "" + for lItem in inCPDict["FooterButtonX1List"]: + lFooterButtonX1Str+=f'
{lItem.get("Text","")}
' + # BodyKeyValue generation + lBodyKeyValueStr = "" + for lItem in inCPDict["BodyKeyValueList"]: + lBodyKeyValueStr+=f"
  • {lItem['Key']}: {lItem['Value']}
  • " + # Generate consolidated string + lResultHTMLStr = f""" +
    +
    +
    + {inCPDict['HeaderRightText']} +
    +
    + {inCPDict['HeaderLeftText']} + +
    +
    + {inCPDict['SubheaderText']} +
    +
    +
      + {lBodyKeyValueStr} +
    +
    +
    +
    + {inCPDict['FooterText']} +
    +
    +
    + {lFooterButtonX2Str} +
    +
    Add. controls
    +
    + {lFooterButtonX1Str} +
    +
    +
    + """ + + return lResultHTMLStr diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.js b/Sources/pyOpenRPA/Orchestrator/Web/Index.js index 9424361e..1e81769a 100644 --- a/Sources/pyOpenRPA/Orchestrator/Web/Index.js +++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.js @@ -1,4 +1,5 @@ var mGlobal={} +mGlobal.pyOpenRPA = {} window.onload=function() { //document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; //Render existing data @@ -347,8 +348,64 @@ $(document).ready(function() { } } } + + /// v1.2.0 pyOpenRPA ServerData + + mGlobal.pyOpenRPA.ServerDataDict = null + mGlobal.pyOpenRPA.ServerDataHashStr = "" + mGlobal.pyOpenRPA.ServerDataRefreshDef_TechnicalRender = function() + { + lResponseJSON = mGlobal.pyOpenRPA.ServerDataDict + if (lResponseJSON!= null) { + /// New version of control panels + lHTMLCode = '
    ' + for (var lKeyStr in lResponseJSON["CPDict"]){ + lCPDict = lResponseJSON["CPDict"][lKeyStr] + /// Render HTML + if ("HTMLStr" in lCPDict) { + lHTMLCode+=lCPDict["HTMLStr"] + } + } + lHTMLCode += '
    ' + ///Прогрузить новую таблицу + $(".openrpa-control-panel").html(lHTMLCode) + } + } + mGlobal.pyOpenRPA.ServerDataRefreshDef=function() { + try { + $.ajax({ + type: "POST", + headers: {}, + url: 'pyOpenRPA/ServerData', + data: mGlobal.pyOpenRPA.ServerDataHashStr, + success: function(lData,l2,l3) { + try { + var lResponseJSON=JSON.parse(lData) + mGlobal.pyOpenRPA.ServerDataDict = lResponseJSON["ServerDataDict"] + mGlobal.pyOpenRPA.ServerDataHashStr = lResponseJSON["HashStr"] + mGlobal.pyOpenRPA.ServerDataRefreshDef_TechnicalRender() + } + catch(error) { + } + mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive + }, + dataType: "text", + error: function(jqXHR, textStatus, errorThrown ) { + sleep(3000) + mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive + } + }); + } + catch(error) { + sleep(3000) + mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive + } + } + + ///////////////////////////////////////////////////////////// + mGlobal.Monitor.mDatasetLast = null - mGlobal.Monitor.fControlPanelRefresh=function() { + mGlobal.fControlPanelRefresh=function() { try { //var XHR = new XMLHttpRequest(); //XHR.setRequestHeader("Cookies",document.cookie) @@ -385,6 +442,7 @@ $(document).ready(function() { } //mGlobal.Monitor.fControlPanelRefresh() // recursive } + mGlobal.Test=function() { ///Обнулить таблицу lData = [ @@ -723,5 +781,10 @@ $(document).ready(function() { //Main sub mGlobal.OrchestratorModelUpdate() // Cal the update orchestrator model - mGlobal.Monitor.fControlPanelRefresh() + //mGlobal.Monitor.fControlPanelRefresh() + + + /// v1.2.0 pyOpenRPA Init defs + mGlobal.pyOpenRPA.ServerDataRefreshDef() // Init the refresh data def from server side + }); \ No newline at end of file diff --git a/changelog.md b/changelog.md index d2b12c24..c218fee3 100644 --- a/changelog.md +++ b/changelog.md @@ -33,7 +33,9 @@ - - def JSEscapeForHTMLInline(inJSStr): # Escape JS to the safe JS for the inline JS in HTML tags ATTENTION! Use it only if want to paste JS into HTML tag - not in