Commit cc202866 authored by Jérome Perrin's avatar Jérome Perrin

CRM / Support Request App time tracking and bug fixes

This is a mix of features to help time tracking and reporting with small unrelated bug fixes and improvements.

To help time tracking we show the time on support request with hour:minutes everywhere and set a stop date automatically. We also add interaction so that "user doing" is automatically added to the support request so that we can see "who did" and make reports based on this.

Bug fixes/unrelated features:
 * when project does not have supply lines, show all services members of the support request use. Also change to pass relative URL of services, usually we don't pass IDs, but relative URLs. This is a visible/breaking change, because it's now required to configure services use. Because it's also required in erp5_crm, I expect it would not break too much. 
 * momentjs' related time was not refreshed, so they kept displaying "a few second ago" even hours later
 * don't set HTML source as post title
 * prevent double submit of comments in support request app.


/reviewed-on nexedi/erp5!780
parents f08c7dd1 10bfde3a
...@@ -157,6 +157,9 @@ ...@@ -157,6 +157,9 @@
<string>your_report_ticket_type</string> <string>your_report_ticket_type</string>
<string>your_dialog_ticket_simulation_state</string> <string>your_dialog_ticket_simulation_state</string>
<string>my_file_field</string> <string>my_file_field</string>
<string>my_ticket_stop_date</string>
<string>my_support_request_start_date</string>
<string>my_support_request_stop_date</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>date_only</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_support_request_start_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>date_only</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_ticket_start_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>date_only</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_support_request_stop_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>date_only</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_ticket_stop_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>description</string>
<string>title</string> <string>title</string>
</list> </list>
</value> </value>
...@@ -73,7 +74,7 @@ ...@@ -73,7 +74,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>The date at which the ticket was created.</string> </value> <value> <string>The Date when processing of this ticket started.</string> </value>
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>description</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_ticket_stop_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>description</string> </key>
<value> <string>The Date when processing of this ticket finished.</string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_stop_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>End Date</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_stop_date</string> </value> <value> <string>my_ticket_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
<item> <item>
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list/> <list>
<string>editable</string>
</list>
</value> </value>
</item> </item>
<item> <item>
...@@ -69,13 +71,17 @@ ...@@ -69,13 +71,17 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date_time_field</string> </value> <value> <string>my_support_request_start_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
<item> <item>
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list/> <list>
<string>editable</string>
</list>
</value> </value>
</item> </item>
<item> <item>
...@@ -69,13 +71,17 @@ ...@@ -69,13 +71,17 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date_time_field</string> </value> <value> <string>my_support_request_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_ticket_start_date</string> </value> <value> <string>my_support_request_start_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_stop_date</string> </value> <value> <string>my_support_request_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
......
portal = context.getPortalObject()
event_portal_type_list = portal.getPortalEventTypeList()
for i in portal.portal_catalog(portal_type=event_portal_type_list,
follow_up_uid=context.getUid()):
i.activate().updateLocalRolesOnSecurityGroups()
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_stop_date</string> </value> <value> <string>my_ticket_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
......
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class TestSupportRequestnterractions(ERP5TypeTestCase):
def createPersonUser(self, roles=()):
person = self.portal.person_module.newContent(
portal_type='Person',)
person.newContent(
portal_type='Assignment').open()
login = person.newContent(
portal_type='ERP5 Login',
reference=self.newPassword(),
password=self.newPassword())
for _ in range(5): # try to get a non-used login
if login.checkConsistency():
login.setReference(self.newPassword())
login.validate()
person.validate()
self.tic()
for role in roles:
self.portal.acl_users.zodb_roles.assignRoleToPrincipal(
role, person.getUserId())
return person
def test_SupportRequest_setSource_on_open(self):
"""The user opening a support request will automatically be set as
"Operation Manager" on the support request.
"""
support_request = self.portal.support_request_module.newContent(
portal_type='Support Request',
title=self.id())
support_request.submit()
self.tic()
self.assertIsNone(support_request.getSource())
person = self.createPersonUser(('Assignor', ))
self.login(person.getUserId())
self.portal.portal_workflow.doActionFor(
support_request,
'validate_action')
self.assertEqual(person, support_request.getSourceValue())
def test_SupportRequest_setStopDate_on_close(self):
"""The stop date is set to now() when closing a support request
"""
support_request = self.portal.support_request_module.newContent(
portal_type='Support Request',
title=self.id())
support_request.validate()
self.tic()
self.assertIsNone(support_request.getStopDate())
self.portal.portal_workflow.doActionFor(
support_request,
'invalidate_action')
self.assertIsNotNone(support_request.getStopDate())
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testCRMSupportRequest</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testCRMSupportRequest</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
</pickle>
<pickle>
<tuple>
<none/>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</tuple>
</pickle>
</record>
</ZopeData>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string>Update local roles when changing the related persons / organisations.</string> </value> <value> <string>Interactions on tickets</string> </value>
</item> </item>
<item> <item>
<key> <string>groups</string> </key> <key> <string>groups</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>SupportRequest_invalidate</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SupportRequest_invalidate</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>invalidate</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<list>
<string>Support Request</string>
</list>
</value>
</item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>actbox_category</string> </key>
<value> <string>workflow</string> </value>
</item>
<item>
<key> <string>actbox_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>actbox_url</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>activate_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>after_script_name</string> </key>
<value>
<list>
<string>SupportRequest_setSource</string>
</list>
</value>
</item>
<item>
<key> <string>before_commit_script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>guard</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SupportRequest_setSource</string> </value>
</item>
<item>
<key> <string>method_id</string> </key>
<value>
<list>
<string>validate</string>
</list>
</value>
</item>
<item>
<key> <string>once_per_transaction</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>portal_type_filter</string> </key>
<value>
<list>
<string>Support Request</string>
</list>
</value>
</item>
<item>
<key> <string>portal_type_group_filter</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>script_name</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>temporary_document_disallowed</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>trigger_type</string> </key>
<value> <int>2</int> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string></string> </value> <value> <string>sci</string> </value>
</item> </item>
<item> <item>
<key> <string>_proxy_roles</string> </key> <key> <string>_proxy_roles</string> </key>
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Ticket_updateRelatedEventLocalRole</string> </value> <value> <string>SupportRequest_invalidate</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
"""User opening the support request will be set a source.
"""
support_request = sci['object']
portal = support_request.getPortalObject()
user = portal.portal_membership.getAuthenticatedMember().getUserValue()
if user is not None and not support_request.getSource():
support_request.setSourceValue(user)
<?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>sci</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SupportRequest_setSource</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
object = state_change['object'] """Update local roles on ticket and all events related to the ticket.
object.updateLocalRolesOnSecurityGroups() """
object.activate(group_method_id=None).Ticket_updateRelatedEventLocalRole() support_request = state_change['object']
portal = support_request.getPortalObject()
support_request.updateLocalRolesOnSecurityGroups()
portal.portal_catalog.activate(activity='SQLQueue').searchAndActivate(
portal_type=portal.getPortalEventTypeList(),
follow_up_uid=support_request.getUid(),
method_id='updateLocalRolesOnSecurityGroups')
test.erp5.testCRMSupportRequest
\ No newline at end of file
erp5_full_text_mroonga_catalog
\ No newline at end of file
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
<item> <item>
<key> <string>text_content</string> </key> <key> <string>text_content</string> </key>
<value> <string>CACHE MANIFEST\n <value> <string>CACHE MANIFEST\n
# v1.0.3\n # v1.0.4\n
CACHE:\n CACHE:\n
font-awesome/font-awesome-webfont.woff2\n font-awesome/font-awesome-webfont.woff2\n
echarts-all.js\n echarts-all.js\n
...@@ -360,7 +360,7 @@ NETWORK:\n ...@@ -360,7 +360,7 @@ NETWORK:\n
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1536561147.11</float> <float>1536561148.11</float>
<string>GMT+9</string> <string>GMT+9</string>
</tuple> </tuple>
</state> </state>
......
...@@ -37,8 +37,8 @@ ...@@ -37,8 +37,8 @@
<ul data-role="listview" class="ui-listview" data-enhanced="true"> <ul data-role="listview" class="ui-listview" data-enhanced="true">
<li class="ui-first-child"><a href="#" class="ui-btn ui-btn-icon-left ui-icon-home" data-i18n="Home">Home</a></li> <li class="ui-first-child"><a href="#" class="ui-btn ui-btn-icon-left ui-icon-home" data-i18n="Home">Home</a></li>
<li><a href="{{supportrequest_href}}" class="ui-btn ui-btn-icon-left ui-icon-gear" data-i18n="Support Requests">Support Requests</a></li> <li><a href="{{supportrequest_href}}" class="ui-btn ui-btn-icon-left ui-icon-life-ring" data-i18n="Support Requests">Support Requests</a></li>
<li><a href="{{preference_href}}" class="ui-btn ui-btn-icon-left ui-icon-gear" data-i18n="Preferences">Preferences</a></li> <li><a href="{{preference_href}}" class="ui-btn ui-btn-icon-left ui-icon-sliders" data-i18n="Preferences">Preferences</a></li>
<li class="ui-last-child"><a href="{{logout_href}}" class="ui-btn ui-btn-icon-left ui-icon-power-off" data-i18n="Logout" accesskey="o">Logout</a></li> <li class="ui-last-child"><a href="{{logout_href}}" class="ui-btn ui-btn-icon-left ui-icon-power-off" data-i18n="Logout" accesskey="o">Logout</a></li>
</ul> </ul>
<dl></dl> <dl></dl>
......
...@@ -204,11 +204,10 @@ ...@@ -204,11 +204,10 @@
.declareJob('submitPostComment', function () { .declareJob('submitPostComment', function () {
var gadget = this, var gadget = this,
submitButton = null, submitButton = null,
queue = null, queue = null;
editor = null;
return gadget.getDeclaredGadget("editor") return gadget.getDeclaredGadget("editor")
.push(function (e) { .push(function (e) {
editor = e;
return e.getContent(); return e.getContent();
}) })
.push(function (content) { .push(function (content) {
...@@ -218,8 +217,11 @@ ...@@ -218,8 +217,11 @@
submitButton = gadget.element.querySelector("input[type=submit]"); submitButton = gadget.element.querySelector("input[type=submit]");
submitButton.disabled = true; submitButton.disabled = true;
submitButton.classList.add("ui-disabled");
function enableSubmitButton() { function enableSubmitButton() {
submitButton.disabled = false; submitButton.disabled = false;
submitButton.classList.remove("ui-disabled");
} }
queue = gadget.notifySubmitted({message: "Posting comment"}) queue = gadget.notifySubmitted({message: "Posting comment"})
.push(function () { .push(function () {
...@@ -231,6 +233,10 @@ ...@@ -231,6 +233,10 @@
data.append("predecessor", ''); data.append("predecessor", '');
data.append("data", content.comment); data.append("data", content.comment);
data.append("file", file_blob); data.append("file", file_blob);
// reset the file upload, otherwise next comment would upload same file again
choose_file_html_element.value = "";
// XXX: Hack, call jIO.util.ajax directly to pass the file blob // XXX: Hack, call jIO.util.ajax directly to pass the file blob
// Because the jio_putAttachment will call readBlobAsText, which // Because the jio_putAttachment will call readBlobAsText, which
// will broke the binary file. Call the jIO.util.ajax directly // will broke the binary file. Call the jIO.util.ajax directly
...@@ -245,19 +251,27 @@ ...@@ -245,19 +251,27 @@
}); });
}) })
.push(function () { .push(function () {
return gadget.notifySubmitted({message: "Comment added", status: "success"}); return new RSVP.Queue().push(function () {
}) gadget.notifySubmitted({message: "Comment added", status: "success"});
.push(function () { }).push(function () {
editor.changeState({value: ''})
.push(function () {
return gadget.redirect({command: 'reload'}); return gadget.redirect({command: 'reload'});
}); });
}, function (e) {
enableSubmitButton();
return gadget.notifySubmitted({message: "Error:" + e, status: "error"});
}); });
queue.push(enableSubmitButton, enableSubmitButton);
return queue; return queue;
}); });
}) })
.onLoop(function () {
// update relative time
this.element.querySelectorAll("li>time").forEach(
function (element) {
element.textContent = moment(element.getAttribute('datetime')).fromNow();
}
);
}, 5000)
.onEvent('submit', function () { .onEvent('submit', function () {
this.submitPostComment(); return this.submitPostComment();
}); });
}(window, rJS, RSVP, calculatePageTitle, moment, Handlebars)); }(window, rJS, RSVP, calculatePageTitle, moment, Handlebars));
\ No newline at end of file
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1539140577.69</float> <float>1539946621.33</float>
<string>GMT+9</string> <string>GMT+9</string>
</tuple> </tuple>
</state> </state>
......
...@@ -8,12 +8,13 @@ project_object = portal.project_module[project] ...@@ -8,12 +8,13 @@ project_object = portal.project_module[project]
support_request = portal.support_request_module.newContent( support_request = portal.support_request_module.newContent(
portal_type='Support Request', portal_type='Support Request',
title=title, title=title,
resource="service_module/" + resource, resource=resource,
destination_decision_value=logged_in_user_value, destination_decision_value=logged_in_user_value,
source_decision_value = project_object.getSourceDecisionValue(), source_decision_value = project_object.getSourceDecisionValue(),
source_section_value = project_object.getSourceSectionValue(), source_section_value = project_object.getSourceSectionValue(),
source_project_value = project_object, source_project_value = project_object,
destination_value = project_object.getDestinationValue(), destination_value = project_object.getDestinationValue(),
destination_section_value = project_object.getDestinationSectionValue(),
start_date=now, start_date=now,
) )
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>default</string>
<string>editable</string> <string>editable</string>
</list> </list>
</value> </value>
...@@ -53,10 +52,6 @@ ...@@ -53,10 +52,6 @@
<key> <string>tales</string> </key> <key> <string>tales</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>editable</string> </key> <key> <string>editable</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -80,23 +75,17 @@ ...@@ -80,23 +75,17 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>default</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>editable</string> </key> <key> <string>editable</string> </key>
<value> <int>0</int> </value> <value> <int>0</int> </value>
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date</string> </value> <value> <string>my_support_request_start_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
<item> <item>
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list/> <list>
<string>editable</string>
</list>
</value> </value>
</item> </item>
<item> <item>
...@@ -69,13 +71,17 @@ ...@@ -69,13 +71,17 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date_time_field</string> </value> <value> <string>my_support_request_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -81,11 +81,11 @@ ...@@ -81,11 +81,11 @@
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date</string> </value> <value> <string>my_support_request_start_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
<item> <item>
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list/> <list>
<string>editable</string>
</list>
</value> </value>
</item> </item>
<item> <item>
...@@ -69,13 +71,17 @@ ...@@ -69,13 +71,17 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_date_time_field</string> </value> <value> <string>my_support_request_stop_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value> <value> <string>Base_viewCRMFieldLibrary</string> </value>
</item> </item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
......
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: here.SupportRequest_getSupportTypeList(request.get("field_your_project", None)) or [(\'\', \'\')]</string> </value> <value> <string>python: context.SupportRequest_getSupportTypeList(request.get("your_project", None))</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
portal = context.getPortalObject() portal = context.getPortalObject()
project = None
if project_id: if project_id:
project_list = portal.portal_catalog(portal_type="Project", id=project_id, limit=1) project = portal.project_module[project_id]
else:
project_list = portal.portal_catalog(portal_type="Project", validation_state="validated", limit=1)
try:
project = project_list[0]
except IndexError:
project = None
result = context.SupportRequest_getSupportTypeListFromProjectValue(project) result = context.SupportRequest_getSupportTypeListFromProjectValue(project)
if json_flag: if json_flag:
from json import dumps from json import dumps
container.REQUEST.RESPONSE.setHeader('content-type', 'application/json')
return dumps(result) return dumps(result)
return result return result
"""Returns the services that can be used on support request for this project.
"""
# /!\ proxy role ! # /!\ proxy role !
portal = context.getPortalObject() portal = context.getPortalObject()
result = [] item_list = portal.Ticket_getResourceItemList(
portal_type='Support Request',
include_context=False,
)
allowed_resource_relative_url_set = set([])
# if this project has supplies, only allow projects from the supplies.
if project_value is not None: if project_value is not None:
sale_supply_list = portal.portal_catalog(portal_type="Sale Supply", destination_project_uid=project_value.getUid()) sale_supply_list = portal.portal_catalog(portal_type="Sale Supply", destination_project_uid=project_value.getUid())
for sale_supply in sale_supply_list: for sale_supply in sale_supply_list:
...@@ -8,6 +17,9 @@ if project_value is not None: ...@@ -8,6 +17,9 @@ if project_value is not None:
for supply_line in sale_supply_line_list: for supply_line in sale_supply_line_list:
service = supply_line.getResourceValue() service = supply_line.getResourceValue()
if service is not None: if service is not None:
result.append((service.getTitle(), service.getId())) allowed_resource_relative_url_set.add(service.getRelativeUrl())
if allowed_resource_relative_url_set:
return [('', '')] + [item for item in item_list if item[1] in allowed_resource_relative_url_set]
return result # otherwise return all support request services
return item_list
...@@ -98,6 +98,7 @@ ...@@ -98,6 +98,7 @@
<string>my_destination_decision_title</string> <string>my_destination_decision_title</string>
<string>my_source_section_title</string> <string>my_source_section_title</string>
<string>my_source_decision_title</string> <string>my_source_decision_title</string>
<string>my_source_title</string>
<string>my_source_project_title</string> <string>my_source_project_title</string>
<string>my_destination_title</string> <string>my_destination_title</string>
<string>your_preferred_editor</string> <string>your_preferred_editor</string>
...@@ -109,6 +110,7 @@ ...@@ -109,6 +110,7 @@
<value> <value>
<list> <list>
<string>my_start_date</string> <string>my_start_date</string>
<string>my_stop_date</string>
<string>my_resource</string> <string>my_resource</string>
<string>my_translated_simulation_state_title</string> <string>my_translated_simulation_state_title</string>
</list> </list>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_source_title</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_ticket_source_title</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
</item> </item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_ticket_start_date</string> </value> <value> <string>my_support_request_start_date</string> </value>
</item> </item>
<item> <item>
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>default</string>
<string>editable</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_stop_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_support_request_stop_date</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewCRMFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: context.hasStopDate() and context.getStopDate() or None</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Certain services are used in the CRM to categorize tickets and events</string> </value>
</item>
<item>
<key> <string>effective_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1252530000.0</float>
<string>GMT+3</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>crm</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>CRM</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Categorizes all services which are listed in CRM Events. The value of this category must be set in the system preferences of the CRM</string> </value>
</item>
<item>
<key> <string>effective_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1252530000.0</float>
<string>GMT+3</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>event</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Event</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Services used to classify support requests</string> </value>
</item>
<item>
<key> <string>effective_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1252530000.0</float>
<string>GMT+3</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>support_request</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Support Request</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
...@@ -198,6 +198,37 @@ post ingested when submitting a new support request. ...@@ -198,6 +198,37 @@ post ingested when submitting a new support request.
<td>Post test 2</td> <td>Post test 2</td>
</tr> </tr>
<!-- The post show a relative time -->
<tr>
<td>assertText</td>
<td>//ol[@id="post_list"]//li[3]/time</td>
<td>a few seconds ago</td>
</tr>
<!-- This relative time will be updated periodically.
To prove this, we break the text, wait 6 seconds - because this is refreshed every 5 seconds
and check that the relative time was updated.
-->
<tr>
<td>assertEval</td>
<td>(function(){
selenium.browserbot.findElement('//ol[@id="post_list"]//li[3]/time').textContent = "this will be updated";
return "ok";
})()</td>
<td>ok</td>
</tr>
<tr>
<td>pause</td> <!-- we are waiting for the next onLoop tic -->
<td>6000</td>
<td></td>
</tr>
<tr>
<td>assertText</td>
<td>//ol[@id="post_list"]//li[3]/time</td>
<td>a few seconds ago</td>
</tr>
</tbody></table> </tbody></table>
</body> </body>
</html> </html>
\ 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>testDoubleSubmitComment</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>
<html>
<head>
<title tal:content="template/title_or_id">The title</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Support Request Zuite</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_SupportRequestUITemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_officejs_support_request_ui/</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Submit New Support Request']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n="[value]Proceed"]</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>//input[@name='field_your_title']</td>
<td>test</td>
</tr>
<tr>
<td>select</td>
<td>field_your_project</td>
<td>RobotMaking</td>
</tr>
<tr>
<td>waitForTextPresent</td>
<td>FeatureRequire</td>
<td></td>
</tr>
<tr>
<td>select</td>
<td>field_your_resource</td>
<td>FeatureRequire</td>
</tr>
<tal:block tal:define="text_content string:First Post Content">
<tal:block metal:use-macro="container/Zuite_CommonTemplateForRenderjsUi/macros/type_ckeditor_text_content"/>
</tal:block>
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Proceed']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Proceed']</td>
<td></td>
</tr>
<tr>
<td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td>
<td>First Post Content</td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n="[value]Post Comment"]</td>
<td></td>
</tr>
<tal:block tal:define="text_content string:Second Post Content">
<tal:block metal:use-macro="container/Zuite_CommonTemplateForRenderjsUi/macros/type_ckeditor_text_content"/>
</tal:block>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Post Comment']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//input[@data-i18n='[value]Post Comment' and @disabled and contains(@class, "ui-disabled")]</td>
<td></td>
</tr>
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'Comment added'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" />
</tal:block>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Post Comment']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Post Comment']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//input[@data-i18n='[value]Post Comment']</td>
<td></td>
</tr>
<tr>
<td>store</td>
<td>javascript{selenium.browserbot.getCurrentWindow().location.href}</td>
<td>current_location</td>
</tr>
<tr>
<td>open</td>
<td tal:content="string:${here/portal_url}/Zuite_waitForActivities"/>
<td/>
</tr>
<tr>
<td>waitForTextPresent</td>
<td>Done.</td>
<td/>
</tr>
<tr>
<td>open</td>
<td>${current_location}</td>
<td></td>
</tr>
<!-- The second post was submitted only once. -->
<tr>
<td>waitForText</td>
<td>//ol[@id="post_list"]//li[1]/p</td>
<td>First Post Content</td>
</tr>
<tr>
<td>waitForText</td>
<td>//ol[@id="post_list"]//li[2]/p</td>
<td>Second Post Content</td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//ol[@id="post_list"]//li[3]/p</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
<td>//input[@name='field_your_title']</td> <td>//input[@name='field_your_title']</td>
<td>test</td> <td>test</td>
</tr> </tr>
<tr>
<td>select</td>
<td>field_your_resource</td>
<td>FeatureRequire</td>
</tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//input[@data-i18n='[value]Proceed']</td> <td>//input[@data-i18n='[value]Proceed']</td>
......
...@@ -52,6 +52,14 @@ ...@@ -52,6 +52,14 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>use/crm/support_request</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
<value> <value>
......
...@@ -52,6 +52,14 @@ ...@@ -52,6 +52,14 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>use/crm/support_request</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
<value> <value>
......
...@@ -52,6 +52,15 @@ ...@@ -52,6 +52,15 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>use/crm/support_request</string>
<string>use/crm/event</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
<value> <value>
......
...@@ -52,6 +52,14 @@ ...@@ -52,6 +52,14 @@
</tuple> </tuple>
</value> </value>
</item> </item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>use/crm/support_request</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
<value> <value>
...@@ -134,7 +142,7 @@ ...@@ -134,7 +142,7 @@
</item> </item>
<item> <item>
<key> <string>actor</string> </key> <key> <string>actor</string> </key>
<value> <string>zope</string> </value> <value> <string>ERP5TypeTestCase</string> </value>
</item> </item>
<item> <item>
<key> <string>comment</string> </key> <key> <string>comment</string> </key>
...@@ -148,7 +156,7 @@ ...@@ -148,7 +156,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>959.51044.44143.58299</string> </value> <value> <string>970.45649.9094.60364</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -166,8 +174,8 @@ ...@@ -166,8 +174,8 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1498204434.87</float> <float>1538917270.12</float>
<string>UTC</string> <string>GMT+9</string>
</tuple> </tuple>
</state> </state>
</object> </object>
......
...@@ -15,6 +15,13 @@ if pref.getPreferenceState() == 'disabled': ...@@ -15,6 +15,13 @@ if pref.getPreferenceState() == 'disabled':
# use fck editor, we test with this # use fck editor, we test with this
pref.setPreferredTextEditor('fck_editor') pref.setPreferredTextEditor('fck_editor')
if portal.portal_preferences.getPreferredSupportRequestUse() != 'crm/support_request':
system_preference = portal.portal_preferences.default_system_preference
system_preference.setPreferredSupportRequestUse('crm/support_request')
portal.portal_caches.clearAllCache()
# set a preferred event resource, so that the web message we create # set a preferred event resource, so that the web message we create
# gets indexed properly in stock table. # gets indexed properly in stock table.
# XXX This ressource does not make much sense though, using something like # XXX This ressource does not make much sense though, using something like
......
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
<td>${base_url}/ERP5Site_setupSupportRequestPreference</td><td></td></tr> <td>${base_url}/ERP5Site_setupSupportRequestPreference</td><td></td></tr>
<tr><td>assertTextPresent</td> <tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr> <td>Done.</td><td></td></tr>
<tr><td>openAndWait</td>
<td>${base_url}/Zuite_waitForActivities</td><td></td></tr>
<tr><td>assertTextPresent</td>
<td>Done.</td><td></td></tr>
</tal:block> </tal:block>
<tal:block metal:define-macro="cleanup_module"> <tal:block metal:define-macro="cleanup_module">
......
...@@ -98,9 +98,7 @@ class TestSupportRequestCreateNewSupportRequest(SupportRequestTestCase): ...@@ -98,9 +98,7 @@ class TestSupportRequestCreateNewSupportRequest(SupportRequestTestCase):
self.getWebSite().SupportRequestModule_createSupportRequest( self.getWebSite().SupportRequestModule_createSupportRequest(
description='<b>Help !!!</b>', description='<b>Help !!!</b>',
file=None, file=None,
# FIXME: resource passed by the UI should be full relative URL resource=self.portal.service_module.erp5_officejs_support_request_ui_test_service_001.getRelativeUrl(),
resource='erp5_officejs_support_request_ui_test_service_001',
# resource=self.portal.service_module.erp5_officejs_support_request_ui_test_service_001.getRelativeUrl(),
title=self.id(), title=self.id(),
project='erp5_officejs_support_request_ui_test_project_001', project='erp5_officejs_support_request_ui_test_project_001',
# FIXME: project passed by the UI should be full relative URL # FIXME: project passed by the UI should be full relative URL
...@@ -169,9 +167,7 @@ class TestSupportRequestCreateNewSupportRequest(SupportRequestTestCase): ...@@ -169,9 +167,7 @@ class TestSupportRequestCreateNewSupportRequest(SupportRequestTestCase):
self.getWebSite().SupportRequestModule_createSupportRequest( self.getWebSite().SupportRequestModule_createSupportRequest(
description='<b>Look at this file !</b>', description='<b>Look at this file !</b>',
file=FileUpload("the text content"), file=FileUpload("the text content"),
# FIXME: resource passed by the UI should be full relative URL resource=self.portal.service_module.erp5_officejs_support_request_ui_test_service_001.getRelativeUrl(),
resource='erp5_officejs_support_request_ui_test_service_001',
# resource=self.portal.service_module.erp5_officejs_support_request_ui_test_service_001.getRelativeUrl(),
title=self.id(), title=self.id(),
project='erp5_officejs_support_request_ui_test_project_001', project='erp5_officejs_support_request_ui_test_project_001',
# FIXME: project passed by the UI should be full relative URL # FIXME: project passed by the UI should be full relative URL
......
...@@ -2,6 +2,9 @@ organisation_module/erp5_officejs_support_request_ui_test_organization_001 ...@@ -2,6 +2,9 @@ organisation_module/erp5_officejs_support_request_ui_test_organization_001
organisation_module/erp5_officejs_support_request_ui_test_organization_002 organisation_module/erp5_officejs_support_request_ui_test_organization_002
person_module/erp5_officejs_support_request_ui_test_person_001 person_module/erp5_officejs_support_request_ui_test_person_001
person_module/erp5_officejs_support_request_ui_test_person_002 person_module/erp5_officejs_support_request_ui_test_person_002
portal_categories/use/crm
portal_categories/use/crm/event
portal_categories/use/crm/support_request
portal_tests/officejs_support_request_ui_zuite portal_tests/officejs_support_request_ui_zuite
portal_tests/officejs_support_request_ui_zuite/** portal_tests/officejs_support_request_ui_zuite/**
project_module/erp5_officejs_support_request_ui_test_project_001 project_module/erp5_officejs_support_request_ui_test_project_001
......
return context.PostModule_createHTMLPost( return context.PostModule_createHTMLPost(
title=data.splitlines()[0][:30] if data else None,
source_reference=source_reference, source_reference=source_reference,
data=data, data=data,
follow_up=follow_up, follow_up=follow_up,
......
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