You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Sources/pyOpenRPA/Orchestrator/Managers/ControlPanel.py

214 lines
9.5 KiB

from ... import Orchestrator
import jinja2
import os
from inspect import signature # For detect count of def args
from ..Web import Basic
class ControlPanel():
"""
Manage your control panel on the orchestrator
.. code-block:: python
# Usage example:
lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestControlPanel",
inJinja2TemplatePathStr="ControlPanel\\test.html", inJinja2TemplateRefreshBool = True)
"""
mControlPanelNameStr = None
mJinja2TemplatePathStr = None
mJinja2TemplateFileNameStr = None
mJinja2Loader = None
mJinja2Env = None
mJinja2Template = None
mJinja2TemplateRefreshBool = None
mBackwardCompatibilityHTMLDef = None
mBackwardCompatibilityJSDef = None
mBackwardCompatibilityJSONDef = None
def __init__(self, inControlPanelNameStr, inJinja2TemplatePathStr = None, inJinja2TemplateRefreshBool = False):
"""
Constructor of the control panel manager
:param inControlPanelNameStr:
:param inJinja2TemplatePathStr:
"""
# Connect self witch pyOpenRPA via ControlPanelNameStr
if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]:
raise Exception(f"Another control panel with name {inControlPanelNameStr} is already exists. Please resolve the error and restart")
Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self
self.Jinja2TemplatePathSet(inJinja2TemplatePathStr = inJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
self.mControlPanelNameStr = inControlPanelNameStr # Set the name of the control panel
def Jinja2TemplatePathSet(self, inJinja2TemplatePathStr):
"""
Create Jinja2 env and load the template html
:param inJinja2TemplatePathStr:
:return:
"""
if inJinja2TemplatePathStr is not None:
lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1])
lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1]
self.mJinja2TemplateFileNameStr = lTemplateFileNameStr
self.mJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr)
self.mJinja2Env = jinja2.Environment(loader=self.mJinja2Loader, trim_blocks=True)
self.mJinja2Template = self.mJinja2Env.get_template(lTemplateFileNameStr)
def Jinja2StrGenerate(self, inDataDict):
"""
Generate the HTML str from the Jinja2. Pass the context inDataDict
:param inDataDict:
:return:
"""
if self.mJinja2TemplateRefreshBool == True:
self.mJinja2Template = self.mJinja2Env.get_template(self.mJinja2TemplateFileNameStr)
lHTMLStr = self.mJinja2Template.render(**inDataDict) # Render the template into str
return lHTMLStr
def DataDictGenerate(self, inRequest):
"""
:return:
"""
lData = {}
return lData
def OnRefreshHTMLStr(self, inRequest):
"""
Event to generate HTML code of the control panel when refresh time is over.
Support backward compatibility for previous versions.
:param inRequest:
:return:
"""
lHTMLStr = None
lL = Orchestrator.OrchestratorLoggerGet()
if self.mBackwardCompatibilityHTMLDef is None:
if self.mJinja2Template is not None:
lDataDict = self.OnRefreshHTMLDataDict(inRequest = inRequest)
# Jinja code
lHTMLStr = self.Jinja2StrGenerate(inDataDict=lDataDict)
else:
lHTMLStr = self.BackwardAdapterHTMLDef(inRequest=inRequest)
# return the str
return lHTMLStr
def OnRefreshHTMLDataDict(self, inRequest):
"""
Event to prepare data context for the futher Jinja2 HTML generation. You can override this def if you want some thing more data
:return: dict
"""
return self.DataDictGenerate(inRequest=inRequest)
def OnRefreshJSONDict(self, inRequest):
"""
Event to transmit some data from server side to the client side in JSON format. Call when page refresh is initialized
:return: Dict type
"""
lResultDict = None
if self.mBackwardCompatibilityJSONDef is None:
pass
else:
lResultDict = self.BackwardAdapterJSONDef(inRequest=inRequest)
return lResultDict
def OnInitJSStr(self, inRequest):
"""
Event when orchestrator web page is init on the client side - you can transmit some java script code is str type to execute it once.
:return: ""
"""
lJSStr = ""
if self.mBackwardCompatibilityJSDef is None:
pass
else:
lJSStr = self.BackwardAdapterJSDef(inRequest=inRequest)
return lJSStr
def BackwardAdapterHTMLDef(self,inRequest):
lGS = Orchestrator.GSettingsGet()
lL = Orchestrator.OrchestratorLoggerGet()
# HTMLRenderDef
lItemHTMLRenderDef = self.mBackwardCompatibilityHTMLDef
lResultStr = ""
if lItemHTMLRenderDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings)
lHTMLResult = None
lDEFSignature = signature(lItemHTMLRenderDef) # Get signature of the def
lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args
try:
if lDEFARGLen == 1: # def (inGSettings)
lHTMLResult = lItemHTMLRenderDef(lGS)
elif lDEFARGLen == 2: # def (inRequest, inGSettings)
lHTMLResult = lItemHTMLRenderDef(inRequest, lGS)
elif lDEFARGLen == 0: # def ()
lHTMLResult = lItemHTMLRenderDef()
# RunFunction
# Backward compatibility up to 1.2.0 - call HTML generator if result has no "HTMLStr"
if type(lHTMLResult) is str:
lResultStr = lHTMLResult
elif "HTMLStr" in lHTMLResult or "JSONDict" in lHTMLResult:
lResultStr = lHTMLResult["HTMLStr"]
else:
# Call backward compatibility HTML generator
lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult)
except Exception as e:
if lL: lL.exception(f"Error in control panel HTMLRenderDef. CP Key {self.mControlPanelNameStr}. Exception are below")
return lResultStr
def BackwardAdapterJSONDef(self,inRequest):
lGS = Orchestrator.GSettingsGet()
lL = Orchestrator.OrchestratorLoggerGet()
# HTMLRenderDef
lItemJSONGeneratorDef = self.mBackwardCompatibilityJSONDef
lResultDict = {}
if lItemJSONGeneratorDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings)
lJSONResult = None
lDEFSignature = signature(lItemJSONGeneratorDef) # Get signature of the def
lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args
try:
if lDEFARGLen == 1: # def (inGSettings)
lJSONResult = lItemJSONGeneratorDef(lGS)
elif lDEFARGLen == 2: # def (inRequest, inGSettings)
lJSONResult = lItemJSONGeneratorDef(inRequest, lGS)
elif lDEFARGLen == 0: # def ()
lJSONResult = lItemJSONGeneratorDef()
# RunFunction
# Backward compatibility up to 1.2.0 - call HTML generator if result has no "HTMLStr"
lType = type(lJSONResult)
if lType is str or lJSONResult is None or lType is int or lType is list or lType is dict or lType is bool or lType is float:
lResultDict = lJSONResult
else:
if lL: lL.warning(f"JSONGenerator return bad type: {str(type(lJSONResult))}, CP Key {self.mControlPanelNameStr}")
except Exception as e:
if lL: lL.exception(
f"Error in control panel JSONGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
return lResultDict
def BackwardAdapterJSDef(self,inRequest):
lGS = Orchestrator.GSettingsGet()
lL = Orchestrator.OrchestratorLoggerGet()
# HTMLRenderDef
lJSInitGeneratorDef = self.mBackwardCompatibilityJSDef
lResultStr = ""
if lJSInitGeneratorDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings)
lJSResult = ""
lDEFSignature = signature(lJSInitGeneratorDef) # Get signature of the def
lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args
try:
if lDEFARGLen == 1: # def (inGSettings)
lJSResult = lJSInitGeneratorDef(lGS)
elif lDEFARGLen == 2: # def (inRequest, inGSettings)
lJSResult = lJSInitGeneratorDef(inRequest, lGS)
elif lDEFARGLen == 0: # def ()
lJSResult = lJSInitGeneratorDef()
if type(lJSResult) is str:
lResultStr = lJSResult # Add delimiter to some cases
else:
if lL: lL.warning(f"JSInitGenerator return bad type: {str(type(lJSResult))}, CP Key {self.mControlPanelNameStr}")
except Exception as e:
if lL: lL.exception(
f"Error in control panel JSInitGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
return lResultStr