draft 1.2.7 (need test)

# Add Orchestrator.StorageExists
# Add Orchestrator.StorageGet
# Create DataGenerator in Managers.ControlPanel for Jinja2 template
dev-linux
Ivan Maslov 3 years ago
parent b7ca9ad446
commit 77bb953c19

@ -26,6 +26,10 @@ Group GSettings...
###################### ######################
Basic defs to work with singleton gSettings. Basic defs to work with singleton gSettings.
Group Storage...
######################
Defs to work with special locations in Orchestrator: Robot, User (TODO), User + Robot (TODO)
Group OS... Group OS...
###################### ######################
Interaction with shell on the Orchestrator user session. Interaction with shell on the Orchestrator user session.

@ -3,30 +3,72 @@ import jinja2
import os import os
from inspect import signature # For detect count of def args from inspect import signature # For detect count of def args
from ..Web import Basic from ..Web import Basic
import operator
import math
class ControlPanel(): class ControlPanel():
""" """
Manage your control panel on the orchestrator Manage your control panel on the orchestrator
Control panel has 3 events types:
- onRefreshHTML - run every n (see settings) second to detect changes in HTML control panel.
- onRefreshJSON - run every n (see settings) second to detect changes in JSON data container to client side.
- onInitJS - run when client reload the Orchestrator web page
.. code-block:: python .. code-block:: python
# Usage example: # Usage example:
lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestControlPanel", lCPManager = Orchestrator.Managers.ControlPanel(inControlPanelNameStr="TestControlPanel",
inJinja2TemplatePathStr="ControlPanel\\test.html", inJinja2TemplateRefreshBool = True) inRefreshHTMLJinja2TemplatePathStr="ControlPanel\\test.html", inJinja2TemplateRefreshBool = True)
If you use Jinja2 you can use next data context:
StorageRobotDict: Orchestrator.StorageRobotGet(inRobotNameStr=self.mRobotNameStr),
ControlPanelInstance: self,
OrchestratorModule:Orchestrator,
RequestInstance: inRequest,
UserInfoDict: Orchestrator.WebUserInfoGet(inRequest=inRequest),
UserUACDict: Orchestrator.UACUserDictGet(inRequest=inRequest),
UserUACCheckDef: inRequest.UACClientCheck,
EnumerateDef: enumerate,
OperatorModule: operator,
MathModule: math
.. code-block:: html
Hello my control panel!
You can use any def from Orchestrator module here in Jinja2 HTML template:
Example: OrchestratorModule.OSCMD(inCMDStr="notepad")
{{MathModule.pi}}
{% if UserInfoDict['UserNameUpperStr']=="ND" %}
YES - IT IS ND
{% endif %}
""" """
mControlPanelNameStr = None mControlPanelNameStr = None
mJinja2TemplatePathStr = None # Jinja2 consolidated
mJinja2TemplateFileNameStr = None
mJinja2Loader = None
mJinja2Env = None
mJinja2Template = None
mJinja2TemplateRefreshBool = None mJinja2TemplateRefreshBool = None
mJinja2DataUpdateDict = None
# RefreshHTML block
mRefreshHTMLJinja2TemplatePathStr = None
mRefreshHTMLJinja2TemplateFileNameStr = None
mRefreshHTMLJinja2Loader = None
mRefreshHTMLJinja2Env = None
mRefreshHTMLJinja2Template = None
# InitJS block
mInitJSJinja2TemplatePathStr = None
mInitJSJinja2TemplateFileNameStr = None
mInitJSJinja2Loader = None
mInitJSJinja2Env = None
mInitJSJinja2Template = None
mBackwardCompatibilityHTMLDef = None mBackwardCompatibilityHTMLDef = None
mBackwardCompatibilityJSDef = None mBackwardCompatibilityJSDef = None
mBackwardCompatibilityJSONDef = None mBackwardCompatibilityJSONDef = None
def __init__(self, inControlPanelNameStr, inJinja2TemplatePathStr = None, inJinja2TemplateRefreshBool = False): mRobotNameStr = None
def __init__(self, inControlPanelNameStr, inRefreshHTMLJinja2TemplatePathStr = None, inJinja2TemplateRefreshBool = False, inRobotNameStr = None):
""" """
Constructor of the control panel manager Constructor of the control panel manager
@ -37,58 +79,119 @@ class ControlPanel():
if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]: 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") raise Exception(f"Another control panel with name {inControlPanelNameStr} is already exists. Please resolve the error and restart")
Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self
self.Jinja2TemplatePathSet(inJinja2TemplatePathStr = inJinja2TemplatePathStr) self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
self.mControlPanelNameStr = inControlPanelNameStr # Set the name of the control panel self.mControlPanelNameStr = inControlPanelNameStr # Set the name of the control panel
self.mRobotNameStr = inRobotNameStr # Set the robot name for robot it execute
def Jinja2DataUpdateDictSet(self, inJinja2DataUpdateDict):
"""
Set the data dict from the Jinja2 context (you can add some new params)
def Jinja2TemplatePathSet(self, inJinja2TemplatePathStr): :param inJinja2DataUpdateDict: dict, which will be appended to main data context
:return: None
"""
self.mJinja2DataUpdateDict = inJinja2DataUpdateDict
def RefreshHTMLJinja2TemplatePathSet(self, inJinja2TemplatePathStr):
""" """
Create Jinja2 env and load the template html Create Jinja2 env and load the template html
:param inJinja2TemplatePathStr: :param inJinja2TemplatePathStr:
:return: :return:
""" """
try:
if inJinja2TemplatePathStr is not None: if inJinja2TemplatePathStr is not None:
lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1]) lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1])
lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1] lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1]
self.mJinja2TemplateFileNameStr = lTemplateFileNameStr self.mRefreshHTMLJinja2TemplateFileNameStr = lTemplateFileNameStr
self.mJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr) self.mRefreshHTMLJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr)
self.mJinja2Env = jinja2.Environment(loader=self.mJinja2Loader, trim_blocks=True) self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True)
self.mJinja2Template = self.mJinja2Env.get_template(lTemplateFileNameStr) self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
def Jinja2StrGenerate(self, inDataDict): def RefreshHTMLJinja2StrGenerate(self, inDataDict):
""" """
Generate the HTML str from the Jinja2. Pass the context inDataDict Generate the HTML str from the Jinja2. Pass the context inDataDict
:param inDataDict: :param inDataDict:
:return: :return:
""" """
if self.mJinja2TemplateRefreshBool == True: if self.mJinja2TemplateRefreshBool == True:
self.mJinja2Template = self.mJinja2Env.get_template(self.mJinja2TemplateFileNameStr) self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(self.mRefreshHTMLJinja2TemplateFileNameStr)
lHTMLStr = self.mJinja2Template.render(**inDataDict) # Render the template into str lHTMLStr = self.mRefreshHTMLJinja2Template.render(**inDataDict) # Render the template into str
return lHTMLStr
def InitJSJinja2TemplatePathSet(self, inJinja2TemplatePathStr):
"""
Create Jinja2 env and load the template html
:param inJinja2TemplatePathStr:
:return:
"""
try:
if inJinja2TemplatePathStr is not None:
lSystemLoaderPathStr = "/".join(inJinja2TemplatePathStr.split("\\")[0:-1])
lTemplateFileNameStr = inJinja2TemplatePathStr.split("\\")[-1]
self.mInitJSJinja2TemplateFileNameStr = lTemplateFileNameStr
self.mInitJSJinja2Loader = jinja2.FileSystemLoader(lSystemLoaderPathStr)
self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True)
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
def InitJSJinja2StrGenerate(self, inDataDict):
"""
Generate the HTML str from the Jinja2. Pass the context inDataDict
:param inDataDict:
:return:
"""
if self.mJinja2TemplateRefreshBool == True:
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(self.mInitJSJinja2TemplateFileNameStr)
lHTMLStr = self.mInitJSJinja2Template.render(**inDataDict) # Render the template into str
return lHTMLStr return lHTMLStr
def DataDictGenerate(self, inRequest): def DataDictGenerate(self, inRequest):
""" """
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: :return:
""" """
lData = {} lData = {
"StorageRobotDict": None,
"ControlPanelInstance":self,
"OrchestratorModule":Orchestrator,
"RequestInstance": inRequest,
"UserInfoDict": Orchestrator.WebUserInfoGet(inRequest=inRequest),
"UserUACDict": Orchestrator.UACUserDictGet(inRequest=inRequest),
"UserUACCheckDef": inRequest.UACClientCheck,
"EnumerateDef": enumerate,
"OperatorModule": operator,
"MathModule": math
}
# Get the robot storage by the robot name (if you set robot name when init)
if self.mRobotNameStr is not None:
lData["StorageRobotDict"] = Orchestrator.StorageRobotGet(inRobotNameStr=self.mRobotNameStr)
# Checkj Jinja2DataUpdateDict
if self.mJinja2DataUpdateDict is not None:
lData.update(self.mJinja2DataUpdateDict)
return lData return lData
def OnRefreshHTMLStr(self, inRequest): def OnRefreshHTMLStr(self, inRequest):
""" """
Event to generate HTML code of the control panel when refresh time is over. Event to generate HTML code of the control panel when refresh time is over.
Support backward compatibility for previous versions. Support backward compatibility for previous versions.
:param inRequest:
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: :return:
""" """
lHTMLStr = None lHTMLStr = None
lL = Orchestrator.OrchestratorLoggerGet() lL = Orchestrator.OrchestratorLoggerGet()
if self.mBackwardCompatibilityHTMLDef is None: if self.mBackwardCompatibilityHTMLDef is None:
if self.mJinja2Template is not None: if self.mRefreshHTMLJinja2Template is not None or (self.mJinja2TemplateRefreshBool == True and self.mRefreshHTMLJinja2TemplateFileNameStr is not None):
lDataDict = self.OnRefreshHTMLDataDict(inRequest = inRequest) lDataDict = self.OnRefreshHTMLDataDict(inRequest = inRequest)
# Jinja code # Jinja code
lHTMLStr = self.Jinja2StrGenerate(inDataDict=lDataDict) lHTMLStr = self.RefreshHTMLJinja2StrGenerate(inDataDict=lDataDict)
else: else:
lHTMLStr = self.BackwardAdapterHTMLDef(inRequest=inRequest) lHTMLStr = self.BackwardAdapterHTMLDef(inRequest=inRequest)
# return the str # return the str
@ -97,14 +200,27 @@ class ControlPanel():
def OnRefreshHTMLDataDict(self, inRequest): 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 Event to prepare data context for the futher Jinja2 HTML generation. You can override this def if you want some thing more data
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: dict :return: dict
""" """
return self.DataDictGenerate(inRequest=inRequest) return self.DataDictGenerate(inRequest=inRequest)
def OnRefreshHTMLHashStr(self, inRequest):
"""
Generate the hash the result output HTML. You can override this function if you know how to optimize HTML rendering.
TODO NEED TO MODIFY ServerSettings to work with Hash because of all defs are need do use Hash
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: None - default, hash function is not determined. Str - hash function is working on!
"""
return None
def OnRefreshJSONDict(self, 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 Event to transmit some data from server side to the client side in JSON format. Call when page refresh is initialized
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: Dict type :return: Dict type
""" """
lResultDict = None lResultDict = None
@ -118,15 +234,28 @@ class ControlPanel():
""" """
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. 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.
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: "" :return: ""
""" """
lJSStr = "" lJSStr = ""
if self.mBackwardCompatibilityJSDef is None: if self.mBackwardCompatibilityJSDef is None:
pass if self.mInitJSJinja2Template is not None or (self.mJinja2TemplateRefreshBool == True and self.mInitJSJinja2TemplateFileNameStr is not None):
lDataDict = self.OnInitJSDataDict(inRequest = inRequest)
# Jinja code
lJSStr = self.InitJSJinja2StrGenerate(inDataDict=lDataDict)
else: else:
lJSStr = self.BackwardAdapterJSDef(inRequest=inRequest) lJSStr = self.BackwardAdapterJSDef(inRequest=inRequest)
return lJSStr return lJSStr
def OnInitJSDataDict(self, inRequest):
"""
Event to prepare data context for the futher Jinja2 JS init generation. You can override this def if you want some thing more data
:param inRequest: request handler (from http.server import BaseHTTPRequestHandler)
:return: dict
"""
return self.DataDictGenerate(inRequest=inRequest)
def BackwardAdapterHTMLDef(self,inRequest): def BackwardAdapterHTMLDef(self,inRequest):
lGS = Orchestrator.GSettingsGet() lGS = Orchestrator.GSettingsGet()
lL = Orchestrator.OrchestratorLoggerGet() lL = Orchestrator.OrchestratorLoggerGet()

@ -49,10 +49,13 @@ def HiddenCPDictGenerate(inRequest, inGSettings):
if lItemKeyStr=="VersionCheck": lUACBool=True # For backward compatibility for the old fron version which not reload page when new orch version is comming if lItemKeyStr=="VersionCheck": lUACBool=True # For backward compatibility for the old fron version which not reload page when new orch version is comming
if lUACBool: # Run function if UAC is TRUE if lUACBool: # Run function if UAC is TRUE
lCPItemDict = {"HTMLStr": None, "JSONDict":None} lCPItemDict = {"HTMLStr": None, "JSONDict":None}
try:
# HTML Render # HTML Render
lCPItemDict["HTMLStr"] = lItemDict.OnRefreshHTMLStr(inRequest=inRequest) lCPItemDict["HTMLStr"] = lItemDict.OnRefreshHTMLStr(inRequest=inRequest)
# JSONGeneratorDef # JSONGeneratorDef
lCPItemDict["JSONDict"] = lItemDict.OnRefreshJSONDict(inRequest=inRequest) lCPItemDict["JSONDict"] = lItemDict.OnRefreshJSONDict(inRequest=inRequest)
except Exception as e:
lL.exception(f"EXCEPTION WHEN HTML/ JSON RENDER")
# Insert CPItemDict in result CPDict # Insert CPItemDict in result CPDict
lCPDict[lItemKeyStr]=lCPItemDict lCPDict[lItemKeyStr]=lCPItemDict
return lCPDict return lCPDict

@ -800,7 +800,7 @@ def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSI
:param inJSONGeneratorDef: :param inJSONGeneratorDef:
:param inJSInitGeneratorDef: :param inJSInitGeneratorDef:
""" """
lCPManager = Managers.ControlPanel(inControlPanelNameStr=inCPKeyStr, inJinja2TemplatePathStr=None) lCPManager = Managers.ControlPanel(inControlPanelNameStr=inCPKeyStr, inRefreshHTMLJinja2TemplatePathStr=None)
# CASE HTMLRender # CASE HTMLRender
if inHTMLRenderDef is not None: lCPManager.mBackwardCompatibilityHTMLDef = inHTMLRenderDef if inHTMLRenderDef is not None: lCPManager.mBackwardCompatibilityHTMLDef = inHTMLRenderDef
# CASE JSONGenerator # CASE JSONGenerator
@ -1085,6 +1085,26 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non
lDict[inKeyList[-1]] += inValue #Set value lDict[inKeyList[-1]] += inValue #Set value
return True return True
def StorageRobotExists(inRobotNameStr):
"""
Check if robot storage exists
:param inRobotNameStr: Robot name (case sensitive)
:return: True - robot storage exist; False - does not exist
"""
return inRobotNameStr in GSettingsGet()["StorageDict"]
def StorageRobotGet(inRobotNameStr):
"""
Get the robot storage by the robot name. If Robot storage is not exist - function will create it
:param inRobotNameStr: Robot name (case sensitive)
:return: Dict
"""
if inRobotNameStr not in GSettingsGet()["StorageDict"]:
GSettingsGet()["StorageDict"][inRobotNameStr]={}
return GSettingsGet()["StorageDict"][inRobotNameStr]
def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None): def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None):
""" """
Create alias for def (can be used in ActivityItem in field Def) Create alias for def (can be used in ActivityItem in field Def)

Loading…
Cancel
Save