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