From f26c8895bd2db95fb71b8ef7642da55b6f46d2a6 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Sat, 14 Sep 2019 15:14:03 +0530 Subject: [PATCH] feat: API to scan and get barcode from camera (#8415) * feat: API to scan and get barcode from camera - frappe.barcode.scan_barcode * fix: Use cordova barcodeScanner in mobile app * style: Undefined variable and no console --- frappe/public/build.json | 6 +- .../public/js/frappe/barcode_scanner/index.js | 23 +++ .../js/frappe/barcode_scanner/quagga.js | 94 ++++++++++++ frappe/public/less/controls.less | 17 ++- package.json | 1 + yarn.lock | 138 +++++++++++++++++- 6 files changed, 274 insertions(+), 5 deletions(-) create mode 100644 frappe/public/js/frappe/barcode_scanner/index.js create mode 100644 frappe/public/js/frappe/barcode_scanner/quagga.js diff --git a/frappe/public/build.json b/frappe/public/build.json index 6cd7410e22..2c502c5f72 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -209,7 +209,8 @@ "public/js/frappe/chat.js", "public/js/frappe/social/social_factory.js", "public/js/frappe/utils/energy_point_utils.js", - "public/js/frappe/ui/chart.js" + "public/js/frappe/ui/chart.js", + "public/js/frappe/barcode_scanner/index.js" ], "css/module.min.css": [ "public/less/module.less" @@ -321,5 +322,8 @@ ], "js/modules.min.js": [ "public/js/frappe/views/modules_home.js" + ], + "js/barcode_scanner.min.js": [ + "public/js/frappe/barcode_scanner/quagga.js" ] } diff --git a/frappe/public/js/frappe/barcode_scanner/index.js b/frappe/public/js/frappe/barcode_scanner/index.js new file mode 100644 index 0000000000..c5e7a7600f --- /dev/null +++ b/frappe/public/js/frappe/barcode_scanner/index.js @@ -0,0 +1,23 @@ +frappe.provide('frappe.barcode'); + +frappe.barcode.scan_barcode = function() { + return new Promise((resolve, reject) => { + if ( + window.cordova && + window.cordova.plugins && + window.cordova.plugins.barcodeScanner + ) { + window.cordova.plugins.barcodeScanner.scan(result => { + if (!result.cancelled) { + resolve(result.text); + } + }, reject); + } else { + frappe.require('/assets/js/barcode_scanner.min.js', () => { + frappe.barcode.get_barcode().then(barcode => { + resolve(barcode); + }); + }); + } + }); +}; diff --git a/frappe/public/js/frappe/barcode_scanner/quagga.js b/frappe/public/js/frappe/barcode_scanner/quagga.js new file mode 100644 index 0000000000..fcab3b4dbe --- /dev/null +++ b/frappe/public/js/frappe/barcode_scanner/quagga.js @@ -0,0 +1,94 @@ +import Quagga from 'quagga/dist/quagga'; +frappe.provide('frappe.barcode'); + +Quagga.onProcessed(function(result) { + let drawingCtx = Quagga.canvas.ctx.overlay, + drawingCanvas = Quagga.canvas.dom.overlay; + + if (result) { + if (result.boxes) { + drawingCtx.clearRect( + 0, + 0, + parseInt(drawingCanvas.getAttribute('width')), + parseInt(drawingCanvas.getAttribute('height')) + ); + result.boxes + .filter(function(box) { + return box !== result.box; + }) + .forEach(function(box) { + Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { + color: 'green', + lineWidth: 2 + }); + }); + } + + if (result.box) { + Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { + color: '#00F', + lineWidth: 2 + }); + } + + if (result.codeResult && result.codeResult.code) { + Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { + color: 'red', + lineWidth: 3 + }); + } + } +}); + +frappe.barcode.get_barcode = function() { + return new Promise(resolve => { + let d = new frappe.ui.Dialog({ + title: __('Scan Barcode'), + fields: [ + { + fieldtype: 'HTML', + fieldname: 'scan_area' + } + ], + on_page_show() { + let $scan_area = d.get_field('scan_area').$wrapper; + $scan_area.addClass('barcode-scanner'); + + Quagga.init( + { + inputStream: { + name: 'Live', + type: 'LiveStream', + target: $scan_area.get(0) + }, + decoder: { + readers: ['code_128_reader'] + } + }, + function(err) { + if (err) { + // eslint-disable-next-line + console.log(err); + return; + } + // eslint-disable-next-line + console.log('Initialization finished. Ready to start'); + Quagga.start(); + } + ); + + Quagga.onDetected(function(result) { + let code = result.codeResult.code; + if (code) { + Quagga.stop(); + d.hide(); + resolve(code); + } + }); + } + }); + + d.show(); + }); +}; diff --git a/frappe/public/less/controls.less b/frappe/public/less/controls.less index 07e4ab3ccd..809c271dfc 100644 --- a/frappe/public/less/controls.less +++ b/frappe/public/less/controls.less @@ -130,4 +130,19 @@ max-height: 200px; overflow: auto; } -} \ No newline at end of file +} + +.barcode-scanner { + position: relative; + + & > canvas, & > video { + max-width: 100%; + width: 100%; + } + + canvas.drawing, canvas.drawingBuffer { + position: absolute; + left: 0; + top: 0; + } +} diff --git a/package.json b/package.json index d937545f6c..755ea58889 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "jsbarcode": "^3.9.0", "moment": "^2.20.1", "moment-timezone": "^0.5.21", + "quagga": "^0.12.1", "quill": "2.0.0-dev.2", "qz-tray": "^2.0.8", "redis": "^2.8.0", diff --git a/yarn.lock b/yarn.lock index d357ff4db9..9aaf86d703 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1145,6 +1145,13 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +cwise-compiler@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/cwise-compiler/-/cwise-compiler-1.1.3.tgz#f4d667410e850d3a313a7d2db7b1e505bb034cc5" + integrity sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU= + dependencies: + uniq "^1.0.0" + cypress-file-upload@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.1.0.tgz#9da7ed60619631231bd2caaf9844874e7cec6f69" @@ -1203,6 +1210,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz#18ae979a6a0ca994b0625853916d2662bbae0b1a" + integrity sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo= + date-fns@^1.27.2: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" @@ -1844,6 +1856,23 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== +get-pixels@^3.2.3: + version "3.3.2" + resolved "https://registry.yarnpkg.com/get-pixels/-/get-pixels-3.3.2.tgz#3f62fb8811932c69f262bba07cba72b692b4ff03" + integrity sha512-6ar+8yPxRd1pskEcl2GSEu1La0+xYRjjnkby6AYiRDDwZ0tJbPQmHnSeH9fGLskT8kvR0OukVgtZLcsENF9YKQ== + dependencies: + data-uri-to-buffer "0.0.3" + jpeg-js "^0.3.2" + mime-types "^2.0.1" + ndarray "^1.0.13" + ndarray-pack "^1.1.1" + node-bitmap "0.0.1" + omggif "^1.0.5" + parse-data-uri "^0.2.0" + pngjs "^3.3.3" + request "^2.44.0" + through "^2.3.4" + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -1873,6 +1902,21 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +gl-mat2@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gl-mat2/-/gl-mat2-1.0.1.tgz#142505730a5c2fe1e9f25d9ece3d0d6cc2710a30" + integrity sha1-FCUFcwpcL+Hp8l2ezj0NbMJxCjA= + +gl-vec2@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/gl-vec2/-/gl-vec2-1.3.0.tgz#83d472ed46034de8e09cbc857123fb6c81c51199" + integrity sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A== + +gl-vec3@^1.0.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gl-vec3/-/gl-vec3-1.1.3.tgz#a47c62f918774a06cbed1b65bcd0288ecbb03826" + integrity sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw== + glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -2220,6 +2264,11 @@ invert-kv@^1.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= +iota-array@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/iota-array/-/iota-array-1.0.0.tgz#81ef57fe5d05814cd58c2483632a99c30a0e8087" + integrity sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc= + ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" @@ -2254,7 +2303,7 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-buffer@^1.1.5: +is-buffer@^1.0.2, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -2503,6 +2552,11 @@ jest-worker@^24.0.0: merge-stream "^1.0.1" supports-color "^6.1.0" +jpeg-js@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.3.6.tgz#c40382aac9506e7d1f2d856eb02f6c7b2a98b37c" + integrity sha512-MUj2XlMB8kpe+8DJUGH/3UJm4XpI8XEgZQ+CiHDeyrGoKPdW/8FJv6ku+3UiYm5Fz3CWaL+iXmD8Q4Ap6aC1Jw== + js-base64@^2.1.8, js-base64@^2.1.9: version "2.5.1" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" @@ -2750,6 +2804,11 @@ lodash@4.17.11, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.11, lodash@^4.17.5, resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== +lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + log-symbols@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -2907,11 +2966,23 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== + mime-db@~1.38.0: version "1.38.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== +mime-types@^2.0.1: + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== + dependencies: + mime-db "1.40.0" + mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.22" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" @@ -3022,6 +3093,27 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +ndarray-linear-interpolate@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ndarray-linear-interpolate/-/ndarray-linear-interpolate-1.0.0.tgz#78bc92b85b9abc15b6e67ee65828f9e2137ae72b" + integrity sha1-eLySuFuavBW25n7mWCj54hN65ys= + +ndarray-pack@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ndarray-pack/-/ndarray-pack-1.2.1.tgz#8caebeaaa24d5ecf70ff86020637977da8ee585a" + integrity sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo= + dependencies: + cwise-compiler "^1.1.2" + ndarray "^1.0.13" + +ndarray@^1.0.13, ndarray@^1.0.18: + version "1.0.18" + resolved "https://registry.yarnpkg.com/ndarray/-/ndarray-1.0.18.tgz#b60d3a73224ec555d0faa79711e502448fd3f793" + integrity sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M= + dependencies: + iota-array "^1.0.0" + is-buffer "^1.0.2" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -3032,6 +3124,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-bitmap@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/node-bitmap/-/node-bitmap-0.0.1.tgz#180eac7003e0c707618ef31368f62f84b2a69091" + integrity sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE= + node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -3204,6 +3301,11 @@ object.values@^1.1.0: function-bind "^1.1.1" has "^1.0.3" +omggif@^1.0.5: + version "1.0.10" + resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" + integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -3305,6 +3407,13 @@ parchment@quilljs/parchment#487850f7eb030a6c4e750ba809e58b09444e0bdb: version "2.0.0-dev" resolved "https://codeload.github.com/quilljs/parchment/tar.gz/487850f7eb030a6c4e750ba809e58b09444e0bdb" +parse-data-uri@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/parse-data-uri/-/parse-data-uri-0.2.0.tgz#bf04d851dd5c87b0ab238e5d01ace494b604b4c9" + integrity sha1-vwTYUd1ch7CrI45dAazklLYEtMk= + dependencies: + data-uri-to-buffer "0.0.3" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -3427,6 +3536,11 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pngjs@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -3882,6 +3996,19 @@ qs@^6.5.1: resolved "https://registry.yarnpkg.com/qs/-/qs-6.6.0.tgz#a99c0f69a8d26bf7ef012f871cdabb0aee4424c2" integrity sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA== +quagga@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/quagga/-/quagga-0.12.1.tgz#6f48c56ed992dc5fdeb90dbee7069c2e1cdde8b7" + integrity sha1-b0jFbtmS3F/euQ2+5wacLhzd6Lc= + dependencies: + get-pixels "^3.2.3" + gl-mat2 "^1.0.0" + gl-vec2 "^1.0.0" + gl-vec3 "^1.0.3" + lodash "^4.17.4" + ndarray "^1.0.18" + ndarray-linear-interpolate "^1.0.0" + querystring@0.2.0, querystring@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -4115,7 +4242,7 @@ request@2.87.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -request@^2.83.0, request@^2.87.0, request@^2.88.0: +request@^2.44.0, request@^2.83.0, request@^2.87.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -4857,6 +4984,11 @@ throttleit@~0.0.2: resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8= +through@^2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" @@ -4991,7 +5123,7 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^0.4.3" -uniq@^1.0.1: +uniq@^1.0.0, uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=