Commit f22a6227 authored by Romain Courteaud's avatar Romain Courteaud Committed by Gabriel Monnerat

erp5_document_scanner: Speed up the usability of scannerjs

- Stop relying of CSS hide/show attributes. Instead, only put needed elements in the DOM.

- Upload images asynchronously to improve the usability

Add a tales expression as default field value. The default value is a JSON containing 2 keys:
* the relative_url of an active process
* the list of active process image content to aggregate
By default, when the field is rendered for the first time, this tales expression is evaluated and a new active process is created at that point.
So, default json is like: {active_process: 'portal_activities/1234', image_list: []}
* store the active_process relative_url in the gadget state in the render method
* store the image_list in the gadget state in the render_method
* change getContent method to send a json build from the active_process and image_list state

- Change the gadget checkValidity method to return false when:
  * no thumbnail has been generated
  * a thumbnail upload is in failed state

- POST image cropped to backend
  * change the `extra renderjs` parameters list to pass a Python script to call when a new image is cropped.
  * change the gadget to use jio.util.ajax with the script full url (provided by the server)

- Translate and Update i18n info
- Ajax must return a active process image content UUID
- Add spinner in button to show that we are saving it in background
- Add reference to Active Process. With this, we can search easily active processes used by document scanner and remove them
- Add an alarm which will delete outdated (>5 days old) active_process created by the dialog.
- Improve code to switch cameras in mobiles with more than 2 cameras
- Display intermediate image after get orientation and instantiate Cropper
parent a24f56d6
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document_scanner_preference</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>4.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Document Scanner</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Preference_viewDocumentScannerSetting</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_removeOutdatedActiveProcess</string> </value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>remove_outdated_document_scanner_active_processes</string> </value>
</item>
<item>
<key> <string>periodicity_day_frequency</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1167609600.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Remove Outdated Document Scanner Active Processes</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
.device-selector {
div[data-gadget-url$="gadget_document_scanner.html"] {
text-align: center;
font-size: 19px;
}
div[data-gadget-scope="field_your_document_scanner_gadget"] {
text-align: center;
@media only screen and (max-width: 750px) {
div[data-gadget-url$="gadget_document_scanner.html"] .camera {
max-width: 90%;
}
div[data-gadget-url$="gadget_document_scanner.html"] .thumbnail-list > button {
max-width: 50%;
}
}
.video, .photo, .camera-output {
div[data-gadget-url$="gadget_document_scanner.html"] .photo,
div[data-gadget-url$="gadget_document_scanner.html"] .video,
div[data-gadget-url$="gadget_document_scanner.html"] .camera-output,
div[data-gadget-url$="gadget_document_scanner.html"] .canvas {
max-width: 100%;
width: auto;
max-height: 500px;
......@@ -15,69 +22,110 @@ div[data-gadget-scope="field_your_document_scanner_gadget"] {
text-align: center;
}
.camera-input, .camera-output {
div[data-gadget-url$="gadget_document_scanner.html"] .camera-input {
min-height: 360px;
display: none;
}
.canvas {
display: none;
filter: brightness(1);
}
.page-number {
div[data-gadget-url$="gadget_document_scanner.html"] .page-number {
display: inline;
}
.camera-header {
div[data-gadget-url$="gadget_document_scanner.html"] .camera-header {
font-size: 12pt;
font-weight: 400;
}
.camera-input, .camera-output, .camera-header, .edit-picture {
div[data-gadget-url$="gadget_document_scanner.html"] .camera-input,
div[data-gadget-url$="gadget_document_scanner.html"] .camera-output,
div[data-gadget-url$="gadget_document_scanner.html"] .camera-header,
div[data-gadget-url$="gadget_document_scanner.html"] .edit-picture {
text-align: center;
}
.camera, .camera-input, .camera-output {
div[data-gadget-url$="gadget_document_scanner.html"] .edit-picture {
padding-top: 0.5em;
}
div[data-gadget-url$="gadget_document_scanner.html"] .camera,
div[data-gadget-url$="gadget_document_scanner.html"] .camera-input {
display: inline-block;
}
.capture-button, .reset-button {
display: inline;
margin: 0 2em 0 2em;
div[data-gadget-url$="gadget_document_scanner.html"] .reset-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .confirm-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .edit-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .take-picture-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .capture-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .delete-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .retry-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .change-camera-btn,
div[data-gadget-url$="gadget_document_scanner.html"] .confirm-btn {
color: #212529;
padding: 3pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
display: inline-block;
margin-right: 6pt;
}
.startbutton {
display: block;
margin: 0 auto;
div[data-gadget-url$="gadget_document_scanner.html"] button:disabled,
div[data-gadget-url$="gadget_document_scanner.html"] button[disabled] {
color: #999999;
}
.reset-btn, .confirm-btn, .edit-btn, .take-picture-btn,
.capture-btn, .change-camera-btn, .confirm-btn {
color: #212529;
padding: 3pt;
div[data-gadget-url$="gadget_document_scanner.html"] > .camera > .thumbnail-list {
padding-top: .5em;
}
div[data-gadget-url$="gadget_document_scanner.html"] .show-img {
width: 6em;
height: 6em;
object-fit: cover;
float: left;
}
div[data-gadget-url$="gadget_document_scanner.html"] .show-img ,
div[data-gadget-url$="gadget_document_scanner.html"] .new-btn {
border-radius: 0.325em;
}
div[data-gadget-url$="gadget_document_scanner.html"] .btn-thumbnail ,
div[data-gadget-url$="gadget_document_scanner.html"] .new-btn {
margin-top: 0.2em;
}
div[data-gadget-url$="gadget_document_scanner.html"] button:before {
padding-right: 0.2em;
}
div[data-gadget-url$="gadget_document_scanner.html"] .thumbnail-list > button {
display: inline;
float: left;
margin-left: 0.2em;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
}
.take-picture-btn, .capture-btn, .confirm-btn,
.reset-btn, .confirm-btn, .change-camera-btn, .edit-btn {
display: none;
div[data-gadget-url$="gadget_document_scanner.html"] .upload-error {
border: 3px solid red;
}
.contentarea {
font-size: 16px;
font-family: "Lucida Grande", "Arial", sans-serif;
width: 760px;
div[data-gadget-url$="gadget_document_scanner.html"] .new-btn {
display: inline-grid !important;
width: calc(6em + 1px);
height: calc(6em + 1px);
}
button:disabled,
button[disabled]{
color: #999999;
div[data-gadget-url$="gadget_document_scanner.html"] .img-container {
/* Never limit the container height here */
max-width: 100%;
}
@media only screen and (max-width: 600px) {
body {
max-height: 360px;
}
div[data-gadget-url$="gadget_document_scanner.html"] .btn-thumbnail:before {
color: #000;
position: absolute;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
text-align: center;
font-size: 16pt;
}
......@@ -3,10 +3,13 @@
<head>
<!--
data-i18n=Webcam is not available
data-i18n=Reset
data-i18n=Take Picture
data-i18n=Confirm
data-i18n=Edit
data-i18n=Delete
data-i18n=Save
data-i18n=Capture
data-i18n=Saving
data-i18n=Error
data-i18n=Page
data-i18n=New Page
data-i18n=Change Camera
-->
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
......@@ -14,30 +17,12 @@
<link rel="stylesheet" href="gadget_document_scanner.css">
<link rel="stylesheet" href="cropper.min.css">
<script type="text/javascript" src="cropper.min.js"></script>
<script type="text/javascript" src="domsugar.js"></script>
<script type="text/javascript" src="caman.full.min.js"></script>
<script type="text/javascript" src="gadget_document_scanner.js"></script>
<title>Gadget Document Scanner</title>
</head>
<body>
<div class="camera">
<div class="camera-header">
<h4>Page <label class="page-number">1</label></h4>
</div>
<div class="camera-input">
<video class="video">Webcam is not available</video>
</div>
<canvas class="canvas"></canvas>
<div class="camera-output">
<img class="photo" alt="Photo">
<input class="photoInput" type="hidden">
<input type="hidden" name="page-number" value="1">
</div>
<div class="edit-picture">
<button type="button" class="reset-btn ui-btn-icon-left ui-icon-times"> Reset</button>
<button type="button" class="take-picture-btn ui-btn-icon-left ui-icon-circle"> Take Picture</button>
<button type="button" class="confirm-btn ui-btn-icon-left ui-icon-check"> Confirm</button>
<button type="button" class="edit-btn ui-btn-icon-left ui-icon-pencil"> Edit</button>
<button type="button" class="change-camera-btn ui-icon-refresh ui-btn-icon-left"> Change Camera</button>
</div>
</div>
<div></div>
</body>
</html>
<property_sheet_list>
<portal_type id="Active Process">
<item>Reference</item>
</portal_type>
</property_sheet_list>
\ No newline at end of file
assert context.getPortalType() == "Active Process", "It must be an Active Process"
assert context.getReference() == context.Base_getDocumentScannerDefaultReference(), "Unexpected reference"
context.getPortalObject().portal_activities.manage_delObjects(
ids=[context.getId(),])
......@@ -50,11 +50,11 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>classification=None, synchronous_metadata_discovery=None, cancel_url=None, batch_mode=False, editable_mode=1, group=None, publication_section=None, document_scanner_gadget=None, active_process_url=None, **kw</string> </value>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_storeDocumentFromCameraInActiveProcess</string> </value>
<value> <string>ActiveProcess_removeItselfFromActivityTool</string> </value>
</item>
</dictionary>
</pickle>
......
from Products.ZSQLCatalog.SQLCatalog import SimpleQuery
portal = context.getPortalObject()
portal.portal_catalog.searchAndActivate(
portal_type=["Active Process",],
method_id='ActiveProcess_removeItselfFromActivityTool',
reference=context.Base_getDocumentScannerDefaultReference(),
# Active Process don't have creation date set
modification_date=SimpleQuery(
modification_date=(DateTime()-4).earliestTime(),
comparison_operator="<")
)
......@@ -50,19 +50,11 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_removeActiveProcessFromActivityTool</string> </value>
<value> <string>Alarm_removeOutdatedActiveProcess</string> </value>
</item>
</dictionary>
</pickle>
......
import json
active_process = context.getPortalObject().portal_activities.newActiveProcess(
reference=context.Base_getDocumentScannerDefaultReference())
return json.dumps({
"active_process": active_process.getRelativeUrl(),
"image_list": []
})
<?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>Base_getDocumentScannerDefaultBackendDataAsJSON</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?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>Base_getDocumentScannerDefaultReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -7,6 +7,5 @@ selection_mapping = portal.portal_selections.getSelectionParamsFor(
REQUEST=context.REQUEST) or {}
canvas_data = selection_mapping.get(context.REQUEST["HTTP_USER_AGENT"]) or {}
canvas_data["dialog_method"] = context.Base_storeDocumentFromCameraInActiveProcess.getId()
return json.dumps(canvas_data)
import json
preference_tool = context.getPortalObject().portal_preferences
setting_dict = {
"compression": preference_tool.getPreferredImageScannerConversionCompression(),
"enable_greyscale": preference_tool.getPreferredImageScannerConversionEnableGreyscale(),
"brightness": preference_tool.getPreferredImageScannerConversionBrightness(),
"contrast": preference_tool.getPreferredImageScannerConversionContrast(),
}
return json.dumps(setting_dict)
<?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>Base_getPreferredImageSettingsFromPreference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
"""
Proxy role as Manager is required here to access getResultList
"""
from base64 import decodestring
if REQUEST:
return RuntimeError("You cannot run this script in the url")
......@@ -8,8 +9,9 @@ image_module = context.getPortalObject().image_module
pdf_data_list = []
for result in active_process.getResultList():
if result.reference in image_list:
pdf_data_list.append(
image_module.newContent(data=result.detail,
image_module.newContent(data=decodestring(result.detail),
portal_type="Image",
temp_object=True).convert(format="pdf")[1])
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process, REQUEST=None</string> </value>
<value> <string>active_process, image_list, REQUEST=None</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
......@@ -2,16 +2,26 @@
We need proy role as manager to create a new active process
and post active result
"""
import string
import random
portal = context.getPortalObject()
if REQUEST:
return RuntimeError("You cannot run this script in the url")
reference = context.Base_getDocumentScannerDefaultReference()
if active_process_url:
active_process = portal.restrictedTraverse(active_process_url)
else:
active_process = portal.portal_activities.newActiveProcess()
active_process = portal.portal_activities.newActiveProcess(
reference=reference)
active_process.postActiveResult(detail=detail)
if generate_new_uid:
id_group = (reference, active_process.getUid())
new_uid = portal.portal_ids.generateNewId(id_group=id_group, default=0)
else:
new_uid = None
return active_process
active_process.postActiveResult(detail=detail, reference=new_uid)
return active_process, new_uid
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process_url, detail, REQUEST=None, **kw</string> </value>
<value> <string>active_process_url, detail, generate_new_uid=False, REQUEST=None, **kw</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
......
context.getPortalObject().portal_activities.manage_delObjects(
ids=[active_process.getId(),])
import json
from base64 import decodestring
portal = context.getPortalObject()
translateString = portal.Base_translateString
gadget_data = json.loads(document_scanner_gadget)
image_str = decodestring(gadget_data.pop("input_value"))
preferred_cropped_canvas_data = gadget_data["preferred_cropped_canvas_data"] or {}
selection_mapping = portal.portal_selections.getSelectionParamsFor(
context.Base_getDocumentScannerSelectionName(),
REQUEST=context.REQUEST) or {}
http_user_agent = context.REQUEST["HTTP_USER_AGENT"]
selection_mapping[http_user_agent] = preferred_cropped_canvas_data
portal.portal_selections.setSelectionParamsFor(
context.Base_getDocumentScannerSelectionName(),
selection_mapping,
context.REQUEST
)
if not image_str:
if batch_mode:
if active_process_url:
return portal.restrictedTraverse(active_process_url)
return None
return context.Base_renderForm('Base_viewUploadDocumentFromCameraDialog',
message=translateString('Nothing to capture'))
active_process = context.Base_postDataToActiveResult(
active_process_url,
image_str)
# We need it to fill the form rendered by renderjs
context.REQUEST.form["your_active_process_url"] = active_process.getRelativeUrl()
# We remove it to reduce the size of the response
context.REQUEST.form.pop("field_your_document_scanner_gadget")
context.REQUEST.form.pop('document_scanner_gadget')
if batch_mode:
return active_process
return context.Base_renderForm('Base_viewUploadDocumentFromCameraDialog',
message=translateString('Captured'))
import json
_, uuid = context.Base_postDataToActiveResult(
active_process_url, input_value,
generate_new_uid=True)
return json.dumps({"uuid": uuid})
<?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>input_value, active_process_url, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_storeNewImageCropped</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,9 +5,9 @@ class StringIOWithFileName(StringIO):
kw.get("title") or DateTime().strftime('%d-%m-%Y_%Hh%M'))
portal = context.getPortalObject()
active_process = portal.restrictedTraverse(active_process_url)
active_process = portal.restrictedTraverse(str(active_process_url))
pdf_data_list = context.Base_getTempImageList(active_process)
pdf_data_list = context.Base_getTempImageList(active_process, image_list)
pdf_data = context.ERP5Site_mergePDFList(pdf_data_list=pdf_data_list)
file_object = StringIOWithFileName(pdf_data)
......@@ -26,5 +26,3 @@ else:
for action in action_list:
getattr(doc, action)()
context.Base_removeActiveProcessFromActivityTool(active_process)
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>publication_state, active_process_url=None, **kw</string> </value>
<value> <string>publication_state, active_process_url, image_list, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
import json
data_dict = json.loads(data_json)
portal = context.getPortalObject()
translateString = portal.Base_translateString
active_process = context.Base_storeDocumentFromCameraInActiveProcess(
active_process_url=active_process_url,
batch_mode=True,
**kw)
active_process_url = data_dict.pop("active_process")
image_list = data_dict.pop("image_list")
preferred_cropped_canvas_data = data_dict.pop("preferred_cropped_canvas_data") or {}
selection_mapping = portal.portal_selections.getSelectionParamsFor(
context.Base_getDocumentScannerSelectionName(),
REQUEST=context.REQUEST) or {}
http_user_agent = context.REQUEST["HTTP_USER_AGENT"]
selection_mapping[http_user_agent] = preferred_cropped_canvas_data or {}
portal.portal_selections.setSelectionParamsFor(
context.Base_getDocumentScannerSelectionName(),
selection_mapping,
context.REQUEST
)
# Avoid to pass huge images to the activity
kw.pop("your_document_scanner_gadget", None)
context.activate().Base_uploadDocumentFromCamera(
active_process_url=active_process.getRelativeUrl(),
publication_state=publication_state,
active_process_url=active_process_url,
image_list=image_list,
**kw)
return context.Base_redirect('view',
......
......@@ -50,7 +50,7 @@
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process_url=None, **kw</string> </value>
<value> <string>data_json, publication_state, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
......
......@@ -95,7 +95,6 @@
<key> <string>left</string> </key>
<value>
<list>
<string>your_active_process_url</string>
<string>your_document_scanner_gadget</string>
</list>
</value>
......
......@@ -10,6 +10,7 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>default</string>
<string>gadget_url</string>
<string>renderjs_extra</string>
<string>title</string>
......@@ -51,6 +52,12 @@
<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>
......@@ -61,18 +68,20 @@
</item>
<item>
<key> <string>gadget_url</string> </key>
<value> <string></string> </value>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>renderjs_extra</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
<item>
......@@ -86,6 +95,10 @@
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_gadget_field</string> </value>
......@@ -96,7 +109,7 @@
</item>
<item>
<key> <string>gadget_url</string> </key>
<value> <string>gadget_document_scanner.html</string> </value>
<value> <string></string> </value>
</item>
<item>
<key> <string>renderjs_extra</string> </key>
......@@ -126,12 +139,38 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: [(\'dialog_method\', \'Base_storeDocumentFromCameraInActiveProcess\'), (\'preferred_cropped_canvas_data\', context.Base_getPreferredCropperSettingsFromSelection()),]</string> </value>
<value> <string>python: here.Base_getDocumentScannerDefaultBackendDataAsJSON()</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>string: gadget_document_scanner.html</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: [(\'preferred_image_settings_data\', context.Base_getPreferredImageSettingsFromPreference()), (\'preferred_cropped_canvas_data\', context.Base_getPreferredCropperSettingsFromSelection()), ("store_new_image_cropped_method", \'Base_storeNewImageCropped\')]</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</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/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>Base_edit</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>my_preferred_image_scanner_conversion_enable_greyscale</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list>
<string>my_preferred_image_scanner_conversion_compression</string>
<string>my_preferred_image_scanner_conversion_brightness</string>
<string>my_preferred_image_scanner_conversion_contrast</string>
</list>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Preference_viewDocumentScannerSetting</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>Preference_viewDocumentScannerSettting</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Document Scanner</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </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>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_image_scanner_conversion_brightness</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_float_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</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>Brightness [-100 .. 100]</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>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_image_scanner_conversion_compression</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_float_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</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>Image compression [0 .. 1]</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>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_preferred_image_scanner_conversion_contrast</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_integer_value</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</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>Contrast [-100 .. 100]</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -10,13 +10,13 @@
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>hidden</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>your_active_process_url</string> </value>
<value> <string>my_preferred_image_scanner_conversion_enable_greyscale</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
......@@ -73,20 +73,20 @@
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value>
<value> <string>your_checkbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>hidden</string> </key>
<value> <int>1</int> </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>Enable Greyscale</string> </value>
</item>
</dictionary>
</value>
</item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>caman.full.min.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>caman.full.min.js</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*!
* Cropper.js v1.5.1
* Cropper.js v1.5.6
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2019-03-10T09:55:50.492Z
* Date: 2019-10-04T04:33:44.164Z
*/.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline:1px solid #39f;outline-color:rgba(51,153,255,.75);overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:ew-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:ns-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:ew-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:ns-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:ew-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:ns-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:ew-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:nesw-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nwse-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:nesw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:nwse-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed}
\ No newline at end of file
......@@ -8,7 +8,7 @@
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
......
......@@ -8,7 +8,7 @@
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
<value> <string>must_revalidate_http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
......@@ -16,7 +16,7 @@
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/x-javascript</string> </value>
<value> <string>text/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
......
Accounting Transaction | scan_document
Internal Invoice Transaction | scan_document
Payment Transaction | scan_document
Preference | document_scanner_preference
Purchase Invoice Transaction | scan_document
Sale Invoice Transaction | scan_document
\ No newline at end of file
web_page_module/rjs_gadget_document_scanner_css
web_page_module/rjs_gadget_document_scanner_html
web_page_module/rjs_gadget_document_scanner_js
\ No newline at end of file
portal_alarms/remove_outdated_document_scanner_active_processes
web_page_module/rjs_gadget_document_scanner_css
web_page_module/rjs_gadget_document_scanner_html
web_page_module/rjs_gadget_document_scanner_js
\ No newline at end of file
Active Process | Reference
\ No newline at end of file
......@@ -101,20 +101,15 @@
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td>
</tr>
<tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector("video").readyState == 4</td>
<td>30000</td>
</tr>
<tr>
<td>click</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td>
</tr>
<tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display != "none"</td>
<td>30000</td>
<td>waitForElementPresent</td>
<td>//button[@class="reset-btn ui-btn-icon-left ui-icon-times"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
......@@ -122,9 +117,9 @@
<td></td>
</tr>
<tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display == "none"</td>
<td>30000</td>
<td>waitForElementPresent</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
......@@ -132,9 +127,9 @@
<td></td>
</tr>
<tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display != "none"</td>
<td>3000</td>
<td>waitForElementPresent</td>
<td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td>
<td></td>
</tr>
<tr>
<td>click</td>
......@@ -149,11 +144,6 @@
</div>
<!--tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".page-number").innerText == "2"</td>
<td>30000</td>
</tr-->
<tr>
<td>storeValue</td>
<td>//input[@id="field_your_active_process_url"]</td>
......
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