Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
144
Merge Requests
144
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
erp5
Commits
6cee3d08
Commit
6cee3d08
authored
Oct 16, 2019
by
Gabriel Monnerat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
erp5_document_scanner: Improve gadget following the design defined by Thierry
parent
9e5652f2
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
139 additions
and
83 deletions
+139
-83
erp5_document_scanner/ActionTemplateItem/portal_types/Sale%20Invoice%20Transaction/scan_document.xml
...rtal_types/Sale%20Invoice%20Transaction/scan_document.xml
+2
-2
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_getPreferredCropperSettingsFromPreference.py
...scanner/Base_getPreferredCropperSettingsFromPreference.py
+5
-3
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_storeDocumentFromCameraInActiveProcess.py
...nt_scanner/Base_storeDocumentFromCameraInActiveProcess.py
+5
-4
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_uploadDocumentFromCamera.py
...ns/erp5_document_scanner/Base_uploadDocumentFromCamera.py
+22
-5
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_viewUploadDocumentFromCameraDialog/your_publication_state.xml
...UploadDocumentFromCameraDialog/your_publication_state.xml
+1
-1
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.css.css
...ins/erp5_document_scanner/gadget_document_scanner.css.css
+11
-10
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.html.html
...s/erp5_document_scanner/gadget_document_scanner.html.html
+7
-5
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.js.js
...skins/erp5_document_scanner/gadget_document_scanner.js.js
+86
-53
No files found.
erp5_document_scanner/ActionTemplateItem/portal_types/Sale%20Invoice%20Transaction/scan_document.xml
View file @
6cee3d08
...
...
@@ -16,13 +16,13 @@
<key>
<string>
categories
</string>
</key>
<value>
<tuple>
<string>
action_type/object_
jio_butt
on
</string>
<string>
action_type/object_
onlyjio_acti
on
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
category
</string>
</key>
<value>
<string>
object_
jio_butt
on
</string>
</value>
<value>
<string>
object_
onlyjio_acti
on
</string>
</value>
</item>
<item>
<key>
<string>
condition
</string>
</key>
...
...
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_getPreferredCropperSettingsFromPreference.py
View file @
6cee3d08
...
...
@@ -7,6 +7,8 @@ if not active_preference:
active_preference
=
portal
.
portal_preferences
.
getActivePreference
()
canvas_data
=
active_preference
and
\
active_preference
.
getPreferredCroppedCanvasData
()
or
\
json
.
dumps
({})
return
canvas_data
json
.
loads
(
active_preference
.
getPreferredCroppedCanvasData
())
or
{}
canvas_data
[
"dialog_method"
]
=
context
.
Base_storeDocumentFromCameraInActiveProcess
.
getId
()
return
json
.
dumps
(
canvas_data
)
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_storeDocumentFromCameraInActiveProcess.py
View file @
6cee3d08
import
json
from
base64
import
decodestring
portal
=
context
.
getPortalObject
()
gadget_data
=
json
.
loads
(
document_scanner_gadget
)
image_str
=
decodestring
(
gadget_data
[
"input_value"
]
)
image_str
=
decodestring
(
gadget_data
.
pop
(
"input_value"
)
)
preferred_cropped_canvas_data
=
json
.
dumps
(
gadget_data
[
"preferred_cropped_canvas_data"
])
active_preference
=
portal
.
portal_preferences
.
getActiveUserPreference
()
...
...
@@ -15,7 +14,7 @@ if active_preference and preferred_cropped_canvas_data:
active_preference
.
setPreferredCroppedCanvasData
(
preferred_cropped_canvas_data
)
if
not
image_str
:
return
context
.
Base_renderForm
(
'Base_viewUploadDocumentFromCamera
Step1
Dialog'
,
return
context
.
Base_renderForm
(
'Base_viewUploadDocumentFromCameraDialog'
,
message
=
'Nothing to capture'
)
if
not
active_process_url
:
...
...
@@ -25,5 +24,7 @@ else:
active_process
=
portal
.
restrictedTraverse
(
active_process_url
)
active_process
.
postActiveResult
(
detail
=
image_str
)
return
context
.
Base_renderForm
(
'Base_viewUploadDocumentFromCameraStep1Dialog'
,
context
.
REQUEST
.
form
.
pop
(
"field_your_document_scanner_gadget"
)
context
.
REQUEST
.
form
.
pop
(
'document_scanner_gadget'
)
return
context
.
Base_renderForm
(
'Base_viewUploadDocumentFromCameraDialog'
,
message
=
'Captured'
)
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_uploadDocumentFromCamera.py
View file @
6cee3d08
...
...
@@ -9,6 +9,7 @@ active_process = portal.restrictedTraverse(active_process_url)
for
result
in
active_process
.
getResultList
():
pdf_data_list
.
append
(
image_module
.
newContent
(
data
=
result
.
detail
,
portal_type
=
"Image"
,
temp_object
=
True
).
convert
(
format
=
"pdf"
)[
1
])
pdf_data
=
context
.
ERP5Site_mergePDFList
(
pdf_data_list
=
pdf_data_list
)
...
...
@@ -19,10 +20,26 @@ extra_document_kw = {
kw
.
get
(
"title"
)
or
DateTime
().
strftime
(
'%d-%m-%Y_%Hh%M'
))
}
context
.
Base_contribute
(
file
=
file_object
,
batch_mode
=
True
,
follow_up_list
=
[
context
.
getRelativeUrl
(),],
extra_document_kw
=
extra_document_kw
,
**
kw
)
doc
=
context
.
Base_contribute
(
file
=
file_object
,
batch_mode
=
True
,
follow_up_list
=
[
context
.
getRelativeUrl
(),],
extra_document_kw
=
extra_document_kw
,
**
kw
)
publication_section
=
kw
.
get
(
"field_your_publication_state"
)
if
publication_section
==
"shared"
:
action_list
=
[
"share"
,]
elif
publication_section
==
"relased"
:
action_list
=
[
"share"
,
"release"
]
elif
publication_section
==
"released"
:
action_list
=
[
"share"
,
"release"
]
elif
publication_section
==
"published"
:
action_list
=
[
"share"
,
"release"
,
"publish"
]
else
:
action_list
=
[]
for
action
in
action_list
:
getattr
(
doc
,
action
)()
portal
.
portal_activities
.
manage_delObjects
(
ids
=
[
active_process
.
getId
(),])
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/Base_viewUploadDocumentFromCameraDialog/your_publication_state.xml
View file @
6cee3d08
...
...
@@ -118,7 +118,7 @@
<dictionary>
<item>
<key>
<string>
_text
</string>
</key>
<value>
<string>
python: [("", ""), ("Draft", "draft"), ("Shared", "shared"), ("Released", "rel
ase"), ("Published", "publish
")]
</string>
</value>
<value>
<string>
python: [("", ""), ("Draft", "draft"), ("Shared", "shared"), ("Released", "rel
eased"), ("Published", "published
")]
</string>
</value>
</item>
</dictionary>
</pickle>
...
...
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.css.css
View file @
6cee3d08
...
...
@@ -29,7 +29,7 @@
font-weight
:
400
;
}
.camera-input
,
.camera-output
,
.camera-header
{
.camera-input
,
.camera-output
,
.camera-header
,
.edit-picture
{
text-align
:
center
;
}
...
...
@@ -47,15 +47,16 @@
margin
:
0
auto
;
}
.startbutton
,
.capture-button
,
.reset-button
{
position
:
relative
;
bottom
:
3em
;
background-color
:
rgba
(
0
,
150
,
0
,
0.5
);
border
:
1px
solid
rgba
(
255
,
255
,
255
,
0.7
);
box-shadow
:
0px
0px
1px
2px
rgba
(
0
,
0
,
0
,
0.2
);
font-size
:
14px
;
font-family
:
"Lucida Grande"
,
"Arial"
,
sans-serif
;
color
:
rgba
(
255
,
255
,
255
,
1.0
);
.reset-btn
,
.confirm-btn
,
.edit-btn
,
.take-picture-btn
,
.capture-btn
,
.change-camera-btn
,
.confirm-btn
{
font-size
:
44px
;
color
:
#212529
;
padding
:
0
16px
0
16px
;
}
.take-picture-btn
,
.capture-btn
,
.confirm-btn
,
.reset-btn
,
.confirm-btn
,
.change-camera-btn
,
.edit-btn
{
display
:
none
;
}
.contentarea
{
...
...
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.html.html
View file @
6cee3d08
...
...
@@ -16,16 +16,18 @@
</div>
<div
class=
"camera-input"
style=
"display: none"
>
<video
class=
"video"
>
Webcam is not available
</video>
<button
type=
"button"
class=
"startbutton"
>
Take a picture!
</button>
</div>
<canvas
class=
"canvas"
></canvas>
<div
class=
"camera-output"
style=
"display: none"
>
<img
class=
"photo"
alt=
"Photo"
>
<input
class=
"photoInput"
type=
"hidden"
>
<div
class=
"edit-picture"
>
<button
class=
"capture-button"
>
Crop
</button>
<button
class=
"reset-button"
>
Reset
</button>
</div>
</div>
<div
class=
"edit-picture"
>
<button
type=
"button"
class=
"reset-btn ui-btn-icon-left ui-icon-times"
></button>
<button
type=
"button"
class=
"take-picture-btn ui-btn-icon-left ui-icon-circle"
></button>
<button
type=
"button"
class=
"confirm-btn ui-btn-icon-left ui-icon-check"
></button>
<button
type=
"button"
class=
"edit-btn ui-btn-icon-left ui-icon-pencil"
></button>
<button
type=
"button"
class=
"change-camera-btn ui-btn-icon-left ui-icon-refresh"
></button>
</div>
</div>
</body>
...
...
erp5_document_scanner/SkinTemplateItem/portal_skins/erp5_document_scanner/gadget_document_scanner.js.js
View file @
6cee3d08
...
...
@@ -10,10 +10,12 @@
video
,
stream
,
canvas
,
dialogMethod
,
photo
,
photoInput
,
deviceId
,
imageCapture
,
pageNumber
=
1
,
cameraList
=
[];
function
readBlobAsDataURL
(
blob
)
{
...
...
@@ -30,6 +32,7 @@
}
function
takePicture
(
el
)
{
var
start
,
end
;
return
RSVP
.
Queue
()
.
push
(
function
()
{
return
imageCapture
.
takePhoto
({
imageWidth
:
imageWidth
});
...
...
@@ -38,21 +41,46 @@
return
readBlobAsDataURL
(
blob
);
})
.
push
(
function
(
result
)
{
photoInput
.
setAttribute
(
"
value
"
,
result
.
split
(
"
,
"
)[
1
]);
photo
.
setAttribute
(
"
src
"
,
result
);
photo
.
setAttribute
(
"
width
"
,
imageWidth
);
photo
.
setAttribute
(
"
height
"
,
imageHeight
);
el
.
querySelector
(
"
.capture-button
"
).
style
.
display
=
""
;
photoInput
.
setAttribute
(
"
value
"
,
result
.
split
(
"
,
"
)[
1
])
;
return
drawCanvas
(
el
,
photo
);
});
}
function
setPageOne
(
root
)
{
root
.
querySelector
(
"
.page-number
"
).
innerText
=
"
1
"
;
root
.
querySelector
(
"
.page-number
"
).
innerText
=
pageNumber
;
root
.
querySelector
(
"
.reset-btn
"
).
style
.
display
=
"
none
"
;
root
.
querySelector
(
"
.take-picture-btn
"
).
style
.
display
=
"
inline-block
"
;
root
.
querySelector
(
"
.confirm-btn
"
).
style
.
display
=
"
none
"
;
root
.
querySelector
(
"
.camera-input
"
).
style
.
display
=
""
;
if
(
cameraList
.
length
>
1
)
{
root
.
querySelector
(
"
.change-camera-btn
"
).
style
.
display
=
"
inline-block
"
;
}
}
function
setPageTwo
(
root
)
{
root
.
querySelector
(
"
.page-number
"
).
innerText
=
"
2
"
;
root
.
querySelector
(
"
.reset-btn
"
).
style
.
display
=
"
inline-block
"
;
root
.
querySelector
(
"
.confirm-btn
"
).
style
.
display
=
"
inline-block
"
;
root
.
querySelector
(
"
.take-picture-btn
"
).
style
.
display
=
"
none
"
;
root
.
querySelector
(
"
.camera-input
"
).
style
.
display
=
"
none
"
;
root
.
querySelector
(
"
.camera-output
"
).
style
.
display
=
""
;
root
.
querySelector
(
"
.change-camera-btn
"
).
style
.
display
=
"
none
"
;
}
function
disableButton
(
root
)
{
[
"
.reset-btn
"
,
"
.take-picture-btn
"
,
"
.confirm-btn
"
,
"
.change-camera-btn
"
].
forEach
(
function
(
e
)
{
root
.
querySelector
(
e
).
disabled
=
true
;
});
}
function
enableButton
(
root
)
{
[
"
.reset-btn
"
,
"
.take-picture-btn
"
,
"
.confirm-btn
"
,
"
.change-camera-btn
"
].
forEach
(
function
(
e
)
{
root
.
querySelector
(
e
).
disabled
=
false
;
});
}
function
drawCanvas
(
gadget
,
img
)
{
...
...
@@ -176,43 +204,40 @@
.
push
(
function
(
photoCapabilities
)
{
imageWidth
=
photoCapabilities
.
imageWidth
.
max
;
imageHeight
=
photoCapabilities
.
imageHeight
.
max
;
root
.
querySelector
(
"
.camera-output
"
).
style
.
maxWidth
=
imageWidth
;
root
.
querySelector
(
"
.camera-output
"
).
style
.
maxHeight
=
imageHeight
;
return
video
.
play
();
})
.
push
(
function
()
{
r
oot
.
querySelector
(
"
.camera-input
"
).
style
.
display
=
""
;
r
eturn
setPageOne
(
root
)
;
});
}
function
startup
(
root
,
device_id
)
{
video
=
root
.
querySelector
(
"
.video
"
);
canvas
=
root
.
querySelector
(
"
.canvas
"
);
photo
=
root
.
querySelector
(
"
.photo
"
);
photo
=
root
.
querySelector
(
"
img
"
);
photoInput
=
root
.
querySelector
(
"
.photoInput
"
);
return
handleUserMedia
(
root
,
device_id
,
gotStream
);
}
function
clearphoto
()
{
var
data
,
context
=
canvas
.
getContext
(
"
2d
"
);
context
.
fillRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
);
data
=
canvas
.
toDataURL
(
"
image/png
"
);
photo
.
setAttribute
(
"
src
"
,
data
);
}
rJS
(
window
)
.
declareAcquiredMethod
(
"
customSubmitDialog
"
,
"
customSubmitDialog
"
)
.
declareAcquiredMethod
(
"
notifySubmitted
"
,
"
notifySubmitted
"
)
.
declareMethod
(
'
render
'
,
function
(
options
)
{
var
root
;
return
this
.
getElement
()
.
push
(
function
(
element
)
{
root
=
element
;
pageNumber
=
1
;
preferredCroppedCanvasData
=
preferredCroppedCanvasData
||
JSON
.
parse
(
options
.
preferred_cropped_canvas_data
);
dialogMethod
=
preferredCroppedCanvasData
.
dialog_method
;
// Clear photo input
element
.
querySelector
(
'
.photoInput
'
).
value
=
""
;
if
(
deviceId
)
{
root
.
querySelector
(
"
.camera-input
"
).
style
.
display
=
""
;
root
.
querySelector
(
"
.capture-button
"
).
style
.
display
=
""
;
root
.
querySelector
(
"
.camera-output
"
).
style
.
display
=
"
none
"
;
}
if
(
!
navigator
.
mediaDevices
)
{
...
...
@@ -224,15 +249,21 @@
var
j
,
device
,
len
=
info_list
.
length
;
for
(
j
=
0
;
j
<
len
;
j
+=
1
)
{
device
=
info_list
[
j
];
if
(
device
.
kind
===
'
videoinput
'
)
{
cameraList
.
push
(
device
);
if
(
cameraList
.
length
===
0
)
{
for
(
j
=
0
;
j
<
len
;
j
+=
1
)
{
device
=
info_list
[
j
];
if
(
device
.
kind
===
'
videoinput
'
)
{
cameraList
.
push
(
device
);
}
}
}
if
(
cameraList
.
length
>=
1
)
{
// trick to select back camera in mobile
deviceId
=
cameraList
[
cameraList
.
length
-
1
].
deviceId
;
}
if
(
deviceId
)
{
return
startup
(
root
,
deviceId
);
}
});
...
...
@@ -240,45 +271,37 @@
.
declareMethod
(
'
getContent
'
,
function
()
{
var
input
=
this
.
element
.
querySelector
(
'
.photoInput
'
),
result
=
{};
result
.
field_your_document_scanner_gadget
=
JSON
.
stringify
({
"
input_value
"
:
input
.
value
,
"
preferred_cropped_canvas_data
"
:
preferredCroppedCanvasData
});
return
result
;
})
/*.onEvent("change", function (evt) {
if (evt.target.type === "select-one") {
return this.getElement()
.push(function (root) {
var display;
if (stream !== undefined) {
// Stop the streams
stream.getTracks().forEach(function (track) {
track.stop();
});
}
if (!evt.target.value) {
display = "none";
} else {
display = "";
}
root.querySelector(".camera-input").style.display = display;
if (evt.target.value) {
return startup(root, evt.target.value);
}
});
}
}, false, true)*/
.
onEvent
(
"
click
"
,
function
(
evt
)
{
var
root
;
var
root
,
newPreferredCroppedCanvasData
,
gadget
=
this
;
if
(
evt
.
target
.
name
===
"
grayscale
"
)
{
return
this
.
getElement
()
.
push
(
function
()
{
return
grayscale
(
canvas
,
photo
);
});
}
if
(
evt
.
target
.
className
===
"
startbutton
"
)
{
if
(
evt
.
target
.
className
.
indexOf
(
"
change-camera-btn
"
)
!==
-
1
)
{
evt
.
preventDefault
();
for
(
var
e
in
cameraList
)
{
if
(
cameraList
[
e
].
deviceId
!==
deviceId
)
{
deviceId
=
cameraList
[
e
].
deviceId
;
break
;
}
}
return
gadget
.
getElement
()
.
push
(
function
(
root
)
{
return
startup
(
root
,
deviceId
);
});
}
if
(
evt
.
target
.
className
.
indexOf
(
"
take-picture-btn
"
)
!==
-
1
)
{
evt
.
preventDefault
();
return
this
.
getElement
()
.
push
(
function
(
el
)
{
...
...
@@ -290,7 +313,7 @@
return
setPageTwo
(
root
);
});
}
if
(
evt
.
target
.
className
===
"
reset-button
"
)
{
if
(
evt
.
target
.
className
.
indexOf
(
"
reset-btn
"
)
!==
-
1
)
{
evt
.
preventDefault
();
return
this
.
getElement
()
.
push
(
function
(
el
)
{
...
...
@@ -300,19 +323,25 @@
return
setPageOne
(
el
);
});
}
if
(
evt
.
target
.
className
===
"
capture-button
"
)
{
if
(
evt
.
target
.
className
.
indexOf
(
"
confirm-btn
"
)
!==
-
1
)
{
evt
.
preventDefault
();
preferredCroppedCanvasData
=
cropper
.
getData
();
newPreferredCroppedCanvasData
=
cropper
.
getData
();
for
(
var
p
in
newPreferredCroppedCanvasData
)
{
if
(
newPreferredCroppedCanvasData
.
hasOwnProperty
(
p
))
{
preferredCroppedCanvasData
[
p
]
=
newPreferredCroppedCanvasData
[
p
];
}
}
return
this
.
getElement
()
.
push
(
function
(
el
)
{
root
=
el
;
disableButton
(
root
);
return
cropper
.
getCroppedCanvas
();
})
.
push
(
function
(
canvas
)
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
canvas
.
toBlob
(
function
(
blob
)
{
resolve
(
blob
);
});
}
,
'
image/jpeg
'
,
0.85
);
});
})
.
push
(
function
(
blob
)
{
...
...
@@ -325,11 +354,15 @@
photo
.
src
=
base64data
;
photoInput
.
value
=
realData
;
root
.
querySelector
(
"
.camera-input
"
).
style
.
display
=
"
none
"
;
root
.
querySelector
(
"
.camera-output
"
).
style
.
display
=
""
;
root
.
querySelector
(
"
.capture-button
"
).
style
.
display
=
"
none
"
;
cropper
.
destroy
();
return
setPageTwo
(
root
);
})
.
push
(
function
()
{
return
gadget
.
customSubmitDialog
(
dialogMethod
);
})
.
push
(
function
()
{
enableButton
(
root
);
pageNumber
=
pageNumber
+
1
;
return
setPageOne
(
root
);
});
}
},
false
,
false
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment