|
|
|
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
|