Commit 3b5d36c0 authored by Gabriel Monnerat's avatar Gabriel Monnerat

Speed up the usability of scannerjs

Reduce the time required for a user to scan a multiple pages PDF.

It has been fond that the slowest part of the scanner dialog was to wait for an image to be uploaded before being able to scan another image.
In order to improve this, it has been decided to allow user scanning a document even if the previous image is not yet uploaded.

See merge request !1034
parents ad2062c3 0d988469
Pipeline #8342 failed with stage
in 0 seconds
<?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 {
text-align: center;
font-size: 19px;
}
div[data-gadget-scope="field_your_document_scanner_gadget"] {
text-align: center;
}
.video, .photo, .camera-output {
max-width: 100%;
width: auto;
max-height: 500px;
filter: brightness(1);
text-align: center;
}
.camera-input, .camera-output {
min-height: 360px;
display: none;
}
.canvas {
display: none;
filter: brightness(1);
}
.page-number {
display: inline;
}
.camera-header {
font-size: 12pt;
font-weight: 400;
}
.camera-input, .camera-output, .camera-header, .edit-picture {
text-align: center;
}
.camera, .camera-input, .camera-output {
display: inline-block;
}
.capture-button, .reset-button {
display: inline;
margin: 0 2em 0 2em;
}
.startbutton {
display: block;
margin: 0 auto;
}
.reset-btn, .confirm-btn, .edit-btn, .take-picture-btn,
.capture-btn, .change-camera-btn, .confirm-btn {
color: #212529;
padding: 3pt;
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;
}
.contentarea {
font-size: 16px;
font-family: "Lucida Grande", "Arial", sans-serif;
width: 760px;
}
button:disabled,
button[disabled]{
color: #999999;
}
@media only screen and (max-width: 600px) {
body {
max-height: 360px;
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
div[data-gadget-url$="gadget_document_scanner.html"] {
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%;
}
}
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;
filter: brightness(1);
text-align: center;
}
div[data-gadget-url$="gadget_document_scanner.html"] .camera-input {
min-height: 360px;
}
div[data-gadget-url$="gadget_document_scanner.html"] .page-number {
display: inline;
}
div[data-gadget-url$="gadget_document_scanner.html"] .camera-header {
font-size: 12pt;
font-weight: 400;
}
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;
}
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;
}
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;
}
div[data-gadget-url$="gadget_document_scanner.html"] button:disabled,
div[data-gadget-url$="gadget_document_scanner.html"] button[disabled] {
color: #999999;
}
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;
}
div[data-gadget-url$="gadget_document_scanner.html"] .upload-error {
border: 3px solid red;
}
div[data-gadget-url$="gadget_document_scanner.html"] .new-btn {
display: inline-grid !important;
width: calc(6em + 1px);
height: calc(6em + 1px);
}
div[data-gadget-url$="gadget_document_scanner.html"] .img-container {
/* Never limit the container height here */
max-width: 100%;
}
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 @@ ...@@ -3,10 +3,13 @@
<head> <head>
<!-- <!--
data-i18n=Webcam is not available data-i18n=Webcam is not available
data-i18n=Reset data-i18n=Delete
data-i18n=Take Picture data-i18n=Save
data-i18n=Confirm data-i18n=Capture
data-i18n=Edit data-i18n=Saving
data-i18n=Error
data-i18n=Page
data-i18n=New Page
data-i18n=Change Camera data-i18n=Change Camera
--> -->
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
...@@ -14,30 +17,12 @@ ...@@ -14,30 +17,12 @@
<link rel="stylesheet" href="gadget_document_scanner.css"> <link rel="stylesheet" href="gadget_document_scanner.css">
<link rel="stylesheet" href="cropper.min.css"> <link rel="stylesheet" href="cropper.min.css">
<script type="text/javascript" src="cropper.min.js"></script> <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> <script type="text/javascript" src="gadget_document_scanner.js"></script>
<title>Gadget Document Scanner</title> <title>Gadget Document Scanner</title>
</head> </head>
<body> <body>
<div class="camera"> <div></div>
<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>
</body> </body>
</html> </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 @@ ...@@ -50,11 +50,11 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <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>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Base_storeDocumentFromCameraInActiveProcess</string> </value> <value> <string>ActiveProcess_removeItselfFromActivityTool</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </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 @@ ...@@ -50,19 +50,11 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>active_process</string> </value> <value> <string></string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Base_removeActiveProcessFromActivityTool</string> </value> <value> <string>Alarm_removeOutdatedActiveProcess</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </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( ...@@ -7,6 +7,5 @@ selection_mapping = portal.portal_selections.getSelectionParamsFor(
REQUEST=context.REQUEST) or {} REQUEST=context.REQUEST) or {}
canvas_data = selection_mapping.get(context.REQUEST["HTTP_USER_AGENT"]) 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) 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 Proxy role as Manager is required here to access getResultList
""" """
from base64 import decodestring
if REQUEST: if REQUEST:
return RuntimeError("You cannot run this script in the url") return RuntimeError("You cannot run this script in the url")
...@@ -8,8 +9,9 @@ image_module = context.getPortalObject().image_module ...@@ -8,8 +9,9 @@ image_module = context.getPortalObject().image_module
pdf_data_list = [] pdf_data_list = []
for result in active_process.getResultList(): for result in active_process.getResultList():
if result.reference in image_list:
pdf_data_list.append( pdf_data_list.append(
image_module.newContent(data=result.detail, image_module.newContent(data=decodestring(result.detail),
portal_type="Image", portal_type="Image",
temp_object=True).convert(format="pdf")[1]) temp_object=True).convert(format="pdf")[1])
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <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>
<item> <item>
<key> <string>_proxy_roles</string> </key> <key> <string>_proxy_roles</string> </key>
......
...@@ -2,16 +2,26 @@ ...@@ -2,16 +2,26 @@
We need proy role as manager to create a new active process We need proy role as manager to create a new active process
and post active result and post active result
""" """
import string
import random
portal = context.getPortalObject() portal = context.getPortalObject()
if REQUEST: if REQUEST:
return RuntimeError("You cannot run this script in the url") return RuntimeError("You cannot run this script in the url")
reference = context.Base_getDocumentScannerDefaultReference()
if active_process_url: if active_process_url:
active_process = portal.restrictedTraverse(active_process_url) active_process = portal.restrictedTraverse(active_process_url)
else: 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 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <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>
<item> <item>
<key> <string>_proxy_roles</string> </key> <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): ...@@ -5,9 +5,9 @@ class StringIOWithFileName(StringIO):
kw.get("title") or DateTime().strftime('%d-%m-%Y_%Hh%M')) kw.get("title") or DateTime().strftime('%d-%m-%Y_%Hh%M'))
portal = context.getPortalObject() 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) pdf_data = context.ERP5Site_mergePDFList(pdf_data_list=pdf_data_list)
file_object = StringIOWithFileName(pdf_data) file_object = StringIOWithFileName(pdf_data)
...@@ -26,5 +26,3 @@ else: ...@@ -26,5 +26,3 @@ else:
for action in action_list: for action in action_list:
getattr(doc, action)() getattr(doc, action)()
context.Base_removeActiveProcessFromActivityTool(active_process)
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <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>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
import json
data_dict = json.loads(data_json)
portal = context.getPortalObject() portal = context.getPortalObject()
translateString = portal.Base_translateString translateString = portal.Base_translateString
active_process = context.Base_storeDocumentFromCameraInActiveProcess( active_process_url = data_dict.pop("active_process")
active_process_url=active_process_url, image_list = data_dict.pop("image_list")
batch_mode=True,
**kw) 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 # Avoid to pass huge images to the activity
kw.pop("your_document_scanner_gadget", None) kw.pop("your_document_scanner_gadget", None)
context.activate().Base_uploadDocumentFromCamera( 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) **kw)
return context.Base_redirect('view', return context.Base_redirect('view',
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <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>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -95,7 +95,6 @@ ...@@ -95,7 +95,6 @@
<key> <string>left</string> </key> <key> <string>left</string> </key>
<value> <value>
<list> <list>
<string>your_active_process_url</string>
<string>your_document_scanner_gadget</string> <string>your_document_scanner_gadget</string>
</list> </list>
</value> </value>
......
...@@ -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>default</string>
<string>gadget_url</string> <string>gadget_url</string>
<string>renderjs_extra</string> <string>renderjs_extra</string>
<string>title</string> <string>title</string>
...@@ -51,6 +52,12 @@ ...@@ -51,6 +52,12 @@
<key> <string>tales</string> </key> <key> <string>tales</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>default</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -61,18 +68,20 @@ ...@@ -61,18 +68,20 @@
</item> </item>
<item> <item>
<key> <string>gadget_url</string> </key> <key> <string>gadget_url</string> </key>
<value> <string></string> </value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item> </item>
<item> <item>
<key> <string>renderjs_extra</string> </key> <key> <string>renderjs_extra</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value> </value>
</item> </item>
<item> <item>
...@@ -86,6 +95,10 @@ ...@@ -86,6 +95,10 @@
<key> <string>values</string> </key> <key> <string>values</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_gadget_field</string> </value> <value> <string>my_gadget_field</string> </value>
...@@ -96,7 +109,7 @@ ...@@ -96,7 +109,7 @@
</item> </item>
<item> <item>
<key> <string>gadget_url</string> </key> <key> <string>gadget_url</string> </key>
<value> <string>gadget_document_scanner.html</string> </value> <value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>renderjs_extra</string> </key> <key> <string>renderjs_extra</string> </key>
...@@ -126,12 +139,38 @@ ...@@ -126,12 +139,38 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <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> </item>
</dictionary> </dictionary>
</pickle> </pickle>
</record> </record>
<record id="3" aka="AAAAAAAAAAM="> <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> <pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/> <global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle> </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 @@ ...@@ -10,13 +10,13 @@
<key> <string>delegated_list</string> </key> <key> <string>delegated_list</string> </key>
<value> <value>
<list> <list>
<string>hidden</string> <string>title</string>
</list> </list>
</value> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <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>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
...@@ -73,20 +73,20 @@ ...@@ -73,20 +73,20 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>field_id</string> </key> <key> <string>field_id</string> </key>
<value> <string>my_string_field</string> </value> <value> <string>your_checkbox</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_viewFieldLibrary</string> </value>
</item> </item>
<item>
<key> <string>hidden</string> </key>
<value> <int>1</int> </value>
</item>
<item> <item>
<key> <string>target</string> </key> <key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value> <value> <string>Click to edit the target</string> </value>
</item> </item>
<item>
<key> <string>title</string> </key>
<value> <string>Enable Greyscale</string> </value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </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 * https://fengyuanchen.github.io/cropperjs
* *
* Copyright 2015-present Chen Fengyuan * Copyright 2015-present Chen Fengyuan
* Released under the MIT license * 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} */.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 @@ ...@@ -8,7 +8,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_Cacheable__manager_id</string> </key> <key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value> <value> <string>must_revalidate_http_cache</string> </value>
</item> </item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_Cacheable__manager_id</string> </key> <key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value> <value> <string>must_revalidate_http_cache</string> </value>
</item> </item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>content_type</string> </key>
<value> <string>application/x-javascript</string> </value> <value> <string>text/javascript</string> </value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>precondition</string> </key>
......
Accounting Transaction | scan_document Accounting Transaction | scan_document
Internal Invoice Transaction | scan_document Internal Invoice Transaction | scan_document
Payment Transaction | scan_document Payment Transaction | scan_document
Preference | document_scanner_preference
Purchase Invoice Transaction | scan_document Purchase Invoice Transaction | scan_document
Sale Invoice Transaction | scan_document Sale Invoice Transaction | scan_document
\ No newline at end of file
web_page_module/scanner_gadget_*
\ No newline at end of file
web_page_module/rjs_gadget_document_scanner_css web_page_module/scanner_gadget_*
web_page_module/rjs_gadget_document_scanner_html \ No newline at end of file
web_page_module/rjs_gadget_document_scanner_js
\ No newline at end of file
web_page_module/rjs_gadget_document_scanner_css portal_alarms/remove_outdated_document_scanner_active_processes
web_page_module/rjs_gadget_document_scanner_html web_page_module/scanner_gadget_*
web_page_module/rjs_gadget_document_scanner_js \ No newline at end of file
\ No newline at end of file
Active Process | Reference
\ No newline at end of file
...@@ -68,11 +68,7 @@ ...@@ -68,11 +68,7 @@
<td>field_your_title</td> <td>field_your_title</td>
<td>Test Scan Document <span tal:replace="python: DateTime().ISO()"></span></td> <td>Test Scan Document <span tal:replace="python: DateTime().ISO()"></span></td>
</tr> </tr>
<!--tr>
<td>type</td>
<td>field_your_reference</td>
<td>TESTSCANDOCUMENT<span tal:replace="python: DateTime().ISO()"></span></td>
</tr-->
<tr> <tr>
<td>type</td> <td>type</td>
<td>field_your_language</td> <td>field_your_language</td>
...@@ -95,88 +91,171 @@ ...@@ -95,88 +91,171 @@
</tr> </tr>
<div tal:repeat="item python:range(2)"> <div tal:repeat="item python:range(2)">
<!-- Click on Capture -->
<tr> <tr>
<td>waitForElementPresent</td> <td>waitForElementPresent</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td> <td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector("video").readyState == 4</td>
<td>30000</td>
</tr>
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td> <td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForCondition</td> <td>waitForElementPresent</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display != "none"</td> <td>//div[@class="cropper-wrap-box"]</td>
<td>30000</td> <td></td>
</tr> </tr>
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="reset-btn ui-btn-icon-left ui-icon-times"]</td>
<td></td>
</tr>
<!-- Click on Delete -->
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="reset-btn ui-btn-icon-left ui-icon-times"]</td> <td>//button[@class="reset-btn ui-btn-icon-left ui-icon-times"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForCondition</td> <td>waitForElementPresent</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display == "none"</td> <td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td>30000</td> <td></td>
</tr> </tr>
<!-- Click on Capture again -->
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td> <td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>waitForCondition</td> <td>waitForElementPresent</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".confirm-btn").style.display != "none"</td> <td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td>
<td>3000</td> <td></td>
</tr> </tr>
<!-- Click on Confirm -->
<tr> <tr>
<td>click</td> <td>click</td>
<td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td> <td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td>
<td></td> <td></td>
</tr> </tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" /> <tr>
<tal:block tal:define="notification_configuration python: {'class': 'success', <td>waitForElementPresent</td>
'text': 'Captured'}"> <td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" /> <td></td>
</tal:block> </tr>
<!-- wait upload starts -->
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="btn-thumbnail ui-btn-icon-top ui-icon-spinner"]</td>
<td></td>
</tr>
</div> </div>
<!-- wait upload finish -->
<!--tr>
<td>waitForCondition</td>
<td>selenium.browserbot.getCurrentWindow().document.querySelector(".page-number").innerText == "2"</td>
<td>30000</td>
</tr-->
<tr> <tr>
<td>storeValue</td> <td>waitForElementNotPresent</td>
<td>//input[@id="field_your_active_process_url"]</td> <td>//button[@class="btn-thumbnail ui-btn-icon-top ui-icon-spinner"]</td>
<td>active_process_url</td> <td></td>
</tr> </tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_dialog" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'The document is being created in background.'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tr> <tr>
<td>open</td> <td>assertElementPresent</td>
<td>${base_url}/erp5/Base_assertActiveProcessHasOneImage?active_process_url=${active_process_url}</td> <td>//button[@class="new-btn ui-btn-icon-left ui-icon-plus" and @disabled]</td>
<td></td> <td></td>
</tr> </tr>
<!-- check if first image exists -->
<tr> <tr>
<td>assertTextPresent</td> <td>assertElementPresent</td>
<td>OK</td> <td>//img[@data-page="0" and @class="show-img"]</td>
<td></td>
</tr>
<!-- check if second image exists -->
<tr>
<td>assertElementPresent</td>
<td>//img[@data-page="1" and @class="show-img"]</td>
<td></td>
</tr>
<!-- check if third image does not exists -->
<tr>
<td>assertElementNotPresent</td>
<td>//img[@data-page="2" and @class="show-img"]</td>
<td></td>
</tr>
<!-- open first image -->
<tr>
<td>click</td>
<td>//img[@data-page="0" and @class="show-img"]</td>
<td></td>
</tr>
<!-- check if delete button appears -->
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="delete-btn ui-btn-icon-left ui-icon-times"]</td>
<td></td>
</tr>
<tr>
<td>assertElementNotPresent</td>
<td>//button[@class="new-btn ui-btn-icon-left ui-icon-plus" and @disabled]</td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>click</td>
<td>//button[@class="new-btn ui-btn-icon-left ui-icon-plus"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></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>waitForElementPresent</td>
<td>//div[@class="cropper-wrap-box"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td>
<td></td>
</tr>
<!-- Click on Confirm -->
<tr>
<td>click</td>
<td>//button[@class="confirm-btn ui-btn-icon-left ui-icon-check"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="take-picture-btn ui-btn-icon-left ui-icon-circle"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//button[@class="btn-thumbnail ui-btn-icon-top ui-icon-spinner"]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//img[@data-page="2" and @class="show-img"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementNotPresent</td>
<td>//button[@class="btn-thumbnail ui-btn-icon-top ui-icon-spinner"]</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/submit_dialog" />
<tal:block tal:define="notification_configuration python: {'class': 'success',
'text': 'The document is being created in background.'}">
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_notification" />
</tal:block>
<tal:block metal:use-macro="here/Zuite_CommonTemplateForRenderjsUi/macros/wait_for_content_loaded" />
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" /> <tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" />
...@@ -225,12 +304,12 @@ ...@@ -225,12 +304,12 @@
</tr> </tr>
<tr> <tr>
<td>waitForTextPresent</td> <td>waitForTextPresent</td>
<td>of 2</td> <td>of 3</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<td>assertTextPresent</td> <td>assertTextPresent</td>
<td>of 2</td> <td>of 3</td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
...@@ -239,17 +318,6 @@ ...@@ -239,17 +318,6 @@
<td></td> <td></td>
</tr> </tr>
<!--tr>
<td>open</td>
<td>${base_url}/erp5/Base_removeActiveProcessFromFileSystem?active_process_url=${active_process_url}</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Done</td>
<td></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>testScanDocumentOnMobile</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>Test memory exhausted issue on mobile (expected failure)</unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
test.erp5.testRenderJSDocumentScanner test.erp5.testRenderJSDocumentScanner
test.erp5.testDocumentScanner
\ No newline at end of file
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