Commit abca29ca authored by Xiaowu Zhang's avatar Xiaowu Zhang

ERP5Configurator&erp5_configurator: add check/fix existing site action

parent cb252da9
REQUEST = context.REQUEST
erp5_site_id = context.getPortalObject().getId()
js_string = """
// Initialisation
window.onload = init;
function getNewXMLHTTP() {
try {
return new XMLHttpRequest();
} catch(e) {
try {
var aObj = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
var aObj = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return false;
}
}
}
return aObj;
}
function checkClientInstallation() {
time_out = window.setTimeout( "checkClientInstallation()", 5000 );
var xhr_object = null;
xhr_object = getNewXMLHTTP();
xhr_object.onreadystatechange = function()
{
var status = document.getElementById('client_installation_status');
if(xhr_object.readyState == 4)
{
if(xhr_object.status == 200)
{
status.innerHTML = xhr_object.responseText;
}
else
status.innerHTML = "Error code " + xhr_object.status;
};
}
active_process_id = document.querySelector('input[name="active_process_id"]').getAttribute('value')
xhr_object.open( "GET",
"portal_configurator/getCheckingStatusReport?active_process_id=" + active_process_id,
true);
//xhr_object.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr_object.setRequestHeader("Content-Type", "text/html");
xhr_object.setRequestHeader("Cache-Control", "no-cache" )
xhr_object.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" )
xhr_object.send(null);
}
function init() {
checkClientInstallation();
}
"""
return js_string
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ConfiguratorTool_generateCheckingJavaScript</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Generate JavaScript code which will query wizard to get installation status</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ConfiguratorTool_viewCheckingResultRenderer</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<div>
<tal:block tal:condition="python: options.get('active_process_id') is not None">
<tal:block tal:define="result_list python: here.getPortalObject().portal_activities[options.get('active_process_id')].getResultList()">
<tal:block tal:condition="python: len(result_list)">
<ol>
<tal:block tal:repeat="result python: result_list[0].result">
<li tal:content="result"></li>
</tal:block>
</ol>
</tal:block>
</tal:block>
</tal:block>
</div>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ConfiguratorTool_viewCheckingStatus</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode>Installation Status Report Renderer</unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<tal:block tal:replace="nothing"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
</tal:block>
<tal:block metal:define-macro="master">
<tal:block
tal:define="object_uid here/getUid | nothing;
object_path here/getPath | nothing;
form nocall: form | nothing;
form_id form/id | nothing;
form_action python: form and form.action not in ('', None) and here.portal_membership.checkPermission('Modify portal content', here) and form.action or nothing;
local_parameter_list local_parameter_list | python: {};
dummy python: local_parameter_list.update({'object_uid': object_uid, 'object_path': object_path, 'form_id': form_id});
title string:${template/title_or_id} - ${here/Title};
">
<script type="text/javascript"
language="javascript"
tal:content="here/ConfiguratorTool_generateCheckingJavaScript"/>
<div id="client_installation_status"
style="background-color: #FFFFFF;
padding: 0.5em;
border-top: 1px solid #000000;
width: 480px;">
Loading ...
</div>
</tal:block>
</tal:block>
\ No newline at end of file
...@@ -45,6 +45,13 @@ ...@@ -45,6 +45,13 @@
<input type='hidden' name='field_your_business_configuration' tal:attributes='value python: request.get("business_configuration")'> <input type='hidden' name='field_your_business_configuration' tal:attributes='value python: request.get("business_configuration")'>
<tal:block tal:replace="structure python: options.get('form_html')" /> <br/> <tal:block tal:replace="structure python: options.get('form_html')" /> <br/>
<tal:block tal:condition="python: options.get('active_process_id') is not None">
<input type="hidden"
name="active_process_id"
value="active_process_id"
tal:attributes="value python: options.get('active_process_id')"/>
</tal:block>
<tal:block tal:condition="python: options.get('previous') is not None"> <tal:block tal:condition="python: options.get('previous') is not None">
<input type="Submit" <input type="Submit"
value="Previous" value="Previous"
......
...@@ -34,11 +34,15 @@ from Products.ERP5Type import Permissions, PropertySheet ...@@ -34,11 +34,15 @@ from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Configurator.Tool.ConfiguratorTool import _validateFormToRequest from Products.ERP5Configurator.Tool.ConfiguratorTool import _validateFormToRequest
from Products.ERP5.Document.Item import Item from Products.ERP5.Document.Item import Item
from Products.CMFActivity.ActiveResult import ActiveResult
## Workflow states definitions ## Workflow states definitions
INITIAL_STATE_TITLE = 'Start' INITIAL_STATE_TITLE = 'Start'
DOWNLOAD_STATE_TITLE = 'Download' DOWNLOAD_STATE_TITLE = 'Download'
END_STATE_TITLE = 'End' END_STATE_TITLE = 'End'
CHECK_EXISTING_SITE_STATE_TITLE = 'Check Existing Site'
FIX_EXISTING_SITE_STATE_TITLE = 'Fix Existing Site'
class BusinessConfiguration(Item): class BusinessConfiguration(Item):
""" """
...@@ -87,6 +91,18 @@ class BusinessConfiguration(Item): ...@@ -87,6 +91,18 @@ class BusinessConfiguration(Item):
""" """
return self.getCurrentStateTitle() == END_STATE_TITLE return self.getCurrentStateTitle() == END_STATE_TITLE
security.declareProtected(Permissions.View, 'isCheckExistingSiteConfigurationState')
def isCheckExistingSiteConfigurationState(self):
""" Check if the Business Configuration is on check existing site State
"""
return self.getCurrentStateTitle() == CHECK_EXISTING_SITE_STATE_TITLE
security.declareProtected(Permissions.View, 'isFixExistingSiteConfigurationState')
def isFixExistingSiteConfigurationState(self):
""" Check if the Business Configuration is on fix existing site State
"""
return self.getCurrentStateTitle() == FIX_EXISTING_SITE_STATE_TITLE
security.declareProtected(Permissions.ModifyPortalContent, \ security.declareProtected(Permissions.ModifyPortalContent, \
'initializeWorkflow') 'initializeWorkflow')
def initializeWorkflow(self): def initializeWorkflow(self):
...@@ -165,7 +181,11 @@ class BusinessConfiguration(Item): ...@@ -165,7 +181,11 @@ class BusinessConfiguration(Item):
## exec next transition for this business configuration ## exec next transition for this business configuration
self._executeTransition() self._executeTransition()
transition = self.getNextTransition() transition = self.getNextTransition()
return None, None, None, None return None, None, None, None, "download"
elif self.isFixExistingSiteConfigurationState():
self._executeTransition()
transition = self.getNextTransition()
return None, None, None, None, "fix existing site"
if form_id is None: if form_id is None:
## go on until you find a form ## go on until you find a form
self._executeTransition() self._executeTransition()
...@@ -182,9 +202,9 @@ class BusinessConfiguration(Item): ...@@ -182,9 +202,9 @@ class BusinessConfiguration(Item):
translate = self.Base_translateString translate = self.Base_translateString
if self._isAlreadyConfSaveInWorkflowHistory(transition): if self._isAlreadyConfSaveInWorkflowHistory(transition):
previous = translate("Previous") previous = translate("Previous")
return previous, form_html, form_title, \ if self.isCheckExistingSiteConfigurationState():
translate(transition.getTitle()) return previous, form_html, form_title, translate(transition.getTitle()), "check existing site"
return previous, form_html, form_title, translate(transition.getTitle()), "show"
security.declarePrivate('_renderFormInContext') security.declarePrivate('_renderFormInContext')
def _renderFormInContext(self, form_id, context, validation_errors): def _renderFormInContext(self, form_id, context, validation_errors):
html = "" html = ""
...@@ -358,3 +378,46 @@ class BusinessConfiguration(Item): ...@@ -358,3 +378,46 @@ class BusinessConfiguration(Item):
if self.portal_workflow.isTransitionPossible(self, 'install'): if self.portal_workflow.isTransitionPossible(self, 'install'):
self.activate(after_tag=kw["tag"]).install() self.activate(after_tag=kw["tag"]).install()
security.declareProtected(Permissions.ModifyPortalContent, 'getCheckResult')
def getCheckResult(self, active_process_url_list):
result_list = []
for active_process_url in active_process_url_list:
active_process = self.restrictedTraverse(active_process_url)
for result in active_process.getResultList():
result_list += result.result
result_list = [x if type(x) == str else str(x.getMessage()) for x in result_list]
return result_list
security.declareProtected(Permissions.ModifyPortalContent, 'checkExistingSite')
def checkExistingSite(self, active_process_url):
"""
Build list of business templates according to already saved
Configuration Saves (i.e. user input).
This is the actual implementation which can be used from workflow
actions and Configurator requets
"""
kw = dict(tag="start_configuration_%s" % self.getId(),
after_method_id=["updateBusinessTemplateFromUrl",
"immediateReindexObject"])
# build
configuration_save_list = self.contentValues(portal_type='Configuration Save')
configuration_save_list.sort(lambda x, y: cmp(x.getIntIndex(x.getIntId()),
y.getIntIndex(y.getIntId())))
active_process_list = []
for configuration_save in configuration_save_list:
# XXX: check which items are configure-able
configuration_item_list = configuration_save.contentValues()
configuration_item_list.sort(lambda x, y: cmp(x.getIntId(), y.getIntId()))
for configurator_item in configuration_item_list:
active_process = self.portal_activities.newActiveProcess()
configurator_item.activate(**kw).checkConsistency(
filter={"constraint_type":"configuration"})
kw["after_tag"] = kw["tag"]
kw["tag"] = "configurator_item_%s_%s" % (configurator_item.getId(),
configurator_item.getUid())
kw["active_process"] = active_process.getRelativeUrl()
active_process_list.append(kw["active_process"])
self.activate(
active_process=active_process_url,
after_tag=kw["after_tag"],
after_method_id = ["fixConsistency", 'immediateReindexObject']).getCheckResult(active_process_list)
...@@ -38,6 +38,7 @@ from Products.ERP5Configurator import _dtmldir ...@@ -38,6 +38,7 @@ from Products.ERP5Configurator import _dtmldir
from Products.Formulator.Errors import FormValidationError from Products.Formulator.Errors import FormValidationError
from DateTime import DateTime from DateTime import DateTime
referer = None referer = None
installation_status = {'bt5': {'current': 0, installation_status = {'bt5': {'current': 0,
'all': 0, }, 'all': 0, },
...@@ -137,6 +138,21 @@ class ConfiguratorTool(BaseTool): ...@@ -137,6 +138,21 @@ class ConfiguratorTool(BaseTool):
next=response['next']) next=response['next'])
elif response["command"] == "install": elif response["command"] == "install":
return self.startInstallation(bc, REQUEST=REQUEST) return self.startInstallation(bc, REQUEST=REQUEST)
elif response["command"] == "check existing site":
global installation_status
# init installation status
installation_status['bt5']['all'] = 1
installation_status['bt5']['current'] = 0
installation_status['activity_list'] = []
active_process = self.portal_activities.newActiveProcess()
bc.activate(tag='initialERP5Setup'
).checkExistingSite(active_process.getRelativeUrl())
return self.ConfiguratorTool_dialogForm(previous=response['previous'],
form_html=response["data"],
next=response['next'],
active_process_id = active_process.getId())
elif response["command"] == "fix existing site":
return self.startInstallation(bc, REQUEST=REQUEST)
def _next(self, business_configuration, kw): def _next(self, business_configuration, kw):
""" Return next configuration form and validate previous. """ """ Return next configuration form and validate previous. """
...@@ -144,7 +160,6 @@ class ConfiguratorTool(BaseTool): ...@@ -144,7 +160,6 @@ class ConfiguratorTool(BaseTool):
need_validation = 1 need_validation = 1
validation_errors = None validation_errors = None
response = {} response = {}
business_configuration.initializeWorkflow() business_configuration.initializeWorkflow()
## initial state no previous form to validate ## initial state no previous form to validate
...@@ -251,7 +266,7 @@ class ConfiguratorTool(BaseTool): ...@@ -251,7 +266,7 @@ class ConfiguratorTool(BaseTool):
if business_configuration.getNextTransition() == None: if business_configuration.getNextTransition() == None:
### client can not continue at the momen ### client can not continue at the momen
return self._terminateConfigurationProcess(response) return self._terminateConfigurationProcess(response)
response["previous"], html, form_title, response["next"] \ response["previous"], html, form_title, response["next"], command \
= business_configuration._displayNextForm() = business_configuration._displayNextForm()
else: else:
## validation passed ## validation passed
...@@ -262,13 +277,15 @@ class ConfiguratorTool(BaseTool): ...@@ -262,13 +277,15 @@ class ConfiguratorTool(BaseTool):
return self._terminateConfigurationProcess(response) return self._terminateConfigurationProcess(response)
## validation failure ## validation failure
rendered = True rendered = True
response["previous"], html, form_title, response["next"] =\ response["previous"], html, form_title, response["next"], command =\
business_configuration._displayNextForm( business_configuration._displayNextForm(
validation_errors=validation_errors) validation_errors=validation_errors)
if html is None: if command == "download":
## we have no more forms proceed to build ## we have no more forms proceed to build
response.update(command="install", data=None) response.update(command="install", data=None)
elif command == 'fix existing site':
response.update(command="fix existing site", data=None)
else: else:
## we have more forms ## we have more forms
next_state = self.restrictedTraverse(business_configuration.getNextTransition()\ next_state = self.restrictedTraverse(business_configuration.getNextTransition()\
...@@ -277,7 +294,7 @@ class ConfiguratorTool(BaseTool): ...@@ -277,7 +294,7 @@ class ConfiguratorTool(BaseTool):
form_html = html, form_html = html,
current_state = next_state, current_state = next_state,
business_configuration = business_configuration) business_configuration = business_configuration)
response.update(command = "show", data = html_data) response.update(command = command, data = html_data)
return response return response
def _terminateConfigurationProcess(self, response): def _terminateConfigurationProcess(self, response):
...@@ -312,7 +329,7 @@ class ConfiguratorTool(BaseTool): ...@@ -312,7 +329,7 @@ class ConfiguratorTool(BaseTool):
return self.ConfiguratorTool_dialogForm(form_html = form_html, return self.ConfiguratorTool_dialogForm(form_html = form_html,
next = "Next") next = "Next")
response['previous'], form_html, form_title, response['next'] = \ response['previous'], form_html, form_title, response['next'], command = \
business_configuration._displayPreviousForm() business_configuration._displayPreviousForm()
next_state = self.restrictedTraverse( next_state = self.restrictedTraverse(
...@@ -347,6 +364,27 @@ class ConfiguratorTool(BaseTool): ...@@ -347,6 +364,27 @@ class ConfiguratorTool(BaseTool):
'text/html; charset=utf-8') 'text/html; charset=utf-8')
return html return html
security.declarePublic('getCheckingStatusReport')
def getCheckingStatusReport(self,
active_process_id=None, REQUEST=None):
""" Query local ERP5 instance for checking status.
"""
global installation_status
portal_activities = self.getPortalObject().portal_activities
if 0 == len(portal_activities.getMessageList()):
html = self.ConfiguratorTool_viewCheckingResultRenderer(active_process_id=active_process_id)
else:
# only if bt5s are installed start tracking number of activities
activity_list = portal_activities.getMessageList()
installation_status['activity_list'].append(len(activity_list))
html = self.ConfiguratorTool_viewRunningInstallationMessage(
installation_status = installation_status)
# set encoding as this is usually called from asynchronous JavaScript call
self.REQUEST.RESPONSE.setHeader('Content-Type',
'text/html; charset=utf-8')
return html
security.declareProtected(Permissions.ModifyPortalContent, 'startInstallation') security.declareProtected(Permissions.ModifyPortalContent, 'startInstallation')
def startInstallation(self, business_configuration, REQUEST): def startInstallation(self, business_configuration, REQUEST):
""" Start installation process as an activity which will """ Start installation process as an activity which will
...@@ -364,3 +402,4 @@ class ConfiguratorTool(BaseTool): ...@@ -364,3 +402,4 @@ class ConfiguratorTool(BaseTool):
active_process=active_process, tag='initialERP5Setup' active_process=active_process, tag='initialERP5Setup'
).build() ).build()
return self.ConfiguratorTool_viewInstallationStatus(REQUEST) return self.ConfiguratorTool_viewInstallationStatus(REQUEST)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment