main.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. window.pdfjsLib.GlobalWorkerOptions.workerSrc = '/printer_bridge/static/lib/js/pdf.worker.js';
  2. // Tools
  3. openerp.pdfJs = window.pdfjsLib || _.noop();
  4. openerp.printJs = window.printJS || _.noop();
  5. openerp.html2canvas = window.html2canvas || _.noop();
  6. /**
  7. *
  8. * @param {*} instance
  9. * @param {*} local
  10. */
  11. openerp.printer_bridge = function (instance, local) {
  12. // Clase que maneja el socket de conexión entre odoo y el programa de impresión cliente encargada de la impresión directa
  13. var SocketManager = instance.web.Class.extend({
  14. init: function () {
  15. this.socket = null;
  16. this.start();
  17. },
  18. start: function () {
  19. this.open_socket();
  20. },
  21. open_socket: function () {
  22. var self = this;
  23. var setup = self.setup_socket = function (config) {
  24. self.config = config;
  25. self.config.is_mobile = self.is_mobile_browser()
  26. if (!self.config.is_mobile) {
  27. self.socket = io(location.protocol + '//' + config.host + ':' + config.port, {
  28. path: config.path
  29. });
  30. self.socket.on('connect', self.handle_connect);
  31. self.socket.on('error', self.handle_error);
  32. self.socket.on('connect_error', self.handle_connect_error);
  33. self.socket.on('request_printer_name', self.handle_printer_selection);
  34. self.socket.on('show_print_status', self.handle_print_status);
  35. self.socket.on('download_data', self.handle_download_data);
  36. }
  37. }
  38. this.get_socket_config().then(setup);
  39. },
  40. update_config: function () {
  41. instance.web.blockUI();
  42. var self = this;
  43. this.get_socket_config().then(function (config) {
  44. instance.web.unblockUI();
  45. self.config = _.extend(self.config, config);
  46. self.socket.destroy();
  47. self.setup_socket(config);
  48. });
  49. },
  50. handle_connect: function () {
  51. $('#printer-status').removeClass();
  52. $('#printer-status').addClass('printer-status-online');
  53. },
  54. handle_error: function (e) {
  55. instance.webclient.crashmanager.show_message(e);
  56. },
  57. handle_connect_error: function (e) {
  58. $('#printer-status').removeClass();
  59. $('#printer-status').addClass('printer-status-offline');
  60. },
  61. handle_printer_selection: function (data) {
  62. instance.web.unblockUI();
  63. var self = this;
  64. if (data.printers && data.printers.length === 0) {
  65. instance.web.notification.do_notify('Impresión', 'No hay impresoras instaladas');
  66. return;
  67. }
  68. var widget = new PrinterSelectionDialog(data);
  69. widget.get_selection().then(function (request) {
  70. self.emit('request_print', request);
  71. });
  72. },
  73. handle_print_status: function (data) {
  74. instance.web.unblockUI();
  75. if (_.isEqual(data.status, 'failed')) {
  76. instance.web.notification.do_warn('Impresión', 'Ha fallado la cola de impresión');
  77. return;
  78. }
  79. if (_.isEqual(data.status, 'canceled')) {
  80. instance.web.notification.do_notify('Impresión', 'Se ha cancelado la impresión');
  81. return;
  82. }
  83. if (_.isEqual(data.status, 'unknown')) {
  84. instance.web.notification.do_warn('Impresión', 'Imposible imprimir un formato de datos desconocido');
  85. return;
  86. }
  87. if (_.isEqual(data.status, 'printing')) {
  88. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' está imprimiendo');
  89. return;
  90. }
  91. if (_.isEqual(data.status, 'printed')) {
  92. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' finalizó la impresión');
  93. return;
  94. }
  95. if (_.isEqual(data.status, 'error')) {
  96. instance.web.notification.do_warn('Impresión', 'Ocurrió un error al imprimir: ' + data.printer, data.cause);
  97. }
  98. },
  99. handle_download_data: function (data) {
  100. instance.web.blockUI();
  101. instance.pdfJs.getDocument({
  102. data: atob(data)
  103. }).then(function (pdf) {
  104. if (local.socket_manager.config.action_download_pdf) {
  105. pdf.getData().then(function (data) {
  106. instance.web.unblockUI();
  107. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  108. var a = document.createElement('a');
  109. a.href = url;
  110. a.download = 'download.pdf';
  111. a.target = '_parent';
  112. a.click();
  113. });
  114. return;
  115. }
  116. preview_pdf(null, pdf);
  117. });
  118. },
  119. get_socket_config: function () {
  120. var url = '/printer_bridge/socket_config';
  121. return this.get_from_server(url);
  122. },
  123. get_from_server: function (url) {
  124. instance.web.blockUI();
  125. return $.Deferred(function (d) {
  126. instance.web.jsonRpc(url, 'call').done(function () {
  127. instance.web.unblockUI();
  128. d.resolve.apply(d, arguments);
  129. }).fail(function (e) {
  130. instance.web.unblockUI();
  131. d.reject.apply(d, arguments);
  132. });
  133. });
  134. },
  135. is_mobile_browser: function () {
  136. var userAgent = navigator.userAgent;
  137. return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4));
  138. },
  139. request_print: function (data, print_directly) {
  140. if (!data) {
  141. instance.web.notification.do_warn('Impresión', 'No hay datos para imprimir');
  142. return;
  143. }
  144. if (!this.socket || !this.socket.connected) {
  145. instance.web.notification.do_warn('Impresión', 'La impresora no está preparada');
  146. return;
  147. }
  148. instance.web.blockUI();
  149. var mime_type = 'data:application/pdf;base64,';
  150. if (data instanceof Uint8Array) {
  151. var Uint8ArrayToStr = function (u8a) {
  152. var CHUNK_SZ = 0x8000;
  153. var c = [];
  154. for (var i = 0; i < u8a.length; i += CHUNK_SZ) {
  155. c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
  156. }
  157. return c.join('');
  158. }
  159. try {
  160. data = Uint8ArrayToStr(data);
  161. data = btoa(data);
  162. data = mime_type + data;
  163. } catch (error) {
  164. instance.web.unblockUI();
  165. instance.webclient.crashmanager.show_message(error);
  166. return;
  167. }
  168. }
  169. if (!data.startsWith(mime_type)) {
  170. data = mime_type + data;
  171. }
  172. try {
  173. atob(data.replace(mime_type, ''));
  174. this.socket.emit('request_print', {
  175. print_directly: print_directly || this.config.print_directly,
  176. data: data
  177. });
  178. } catch (error) {
  179. instance.web.unblockUI();
  180. instance.webclient.crashmanager.show_message(error);
  181. }
  182. }
  183. });
  184. // Diálogo que sirve para descargar del repositorio el programa cliente
  185. var DownloadPrinterTools = instance.web.Widget.extend({
  186. template: 'DownloadPrinterTools',
  187. events: {
  188. 'click .download_button': 'handle_download'
  189. },
  190. init: function (parent) {
  191. this._super(parent);
  192. },
  193. start: function () {
  194. this.renderElement();
  195. this.$el.appendTo($('body'));
  196. this.$el.on('hidden.bs.modal', this, this.on_hide);
  197. if (this.is_linux_platform()) {
  198. this.$('.download_logo_windows').css('display', 'none');
  199. this.$('.windows_download_button').css('display', 'none');
  200. }
  201. if (this.is_win_platform()) {
  202. this.$('.download_logo_linux').css('display', 'none');
  203. this.$('.linux_download_button').css('display', 'none');
  204. }
  205. this.$el.modal('show');
  206. },
  207. on_hide: function (e) {
  208. var self = e.data;
  209. self.$el.remove();
  210. self.destroy();
  211. },
  212. is_win_platform: function () {
  213. return /^Win(?:32|64)$/.test(navigator.platform);
  214. },
  215. is_linux_platform: function () {
  216. return /^Linux\sx86(?:|_64)$/.test(navigator.platform);
  217. },
  218. handle_download: function (e) {
  219. var download_url = 'https://repo.eiru.com.py/attachments/';
  220. if (this.is_linux_platform()) {
  221. download_url += '70cb88da-3e74-404c-966d-b105750ad61d';
  222. }
  223. if (this.is_win_platform()) {
  224. download_url += 'fff8d20d-f062-4920-b9a6-258c241bcad3';
  225. }
  226. var a = document.createElement('a');
  227. a.href = download_url;
  228. a.target = '_parent';
  229. a.click();
  230. this.$el.modal('hide');
  231. }
  232. });
  233. // Icono de notificación en la barra superior del sistema
  234. var PrinterTopNotificator = instance.web.Widget.extend({
  235. template: 'PrinterTopNotificator',
  236. events: {
  237. 'click .printer_status_notificator': 'handle_click'
  238. },
  239. init: function (parent) {
  240. this._super(parent);
  241. },
  242. handle_click: function (e) {
  243. e.preventDefault();
  244. if (local.socket_manager.socket.disconnected) {
  245. var widget = new DownloadPrinterTools(this);
  246. widget.start();
  247. }
  248. }
  249. });
  250. // Diálogo de impresión cuando la impresión directa no está disponible
  251. var PrinterUnavailableDialog = instance.web.Widget.extend({
  252. template: 'PrinterUnavailableDialog',
  253. events: {
  254. 'click li': 'on_download'
  255. },
  256. init: function (parent) {
  257. this._super(parent);
  258. this.start();
  259. var config = local.socket_manager.config;
  260. this.preview_pdf = config.action_preview_pdf || false;
  261. },
  262. start: function () {
  263. this.defer = $.Deferred();
  264. this.render_widget();
  265. },
  266. render_widget: function () {
  267. this.renderElement();
  268. $('body').append(this.$el);
  269. this.$el.on('hidden.bs.modal', this, this.on_hide);
  270. this.$el.modal('show');
  271. },
  272. on_download: function () {
  273. this.download_pdf = true;
  274. this.$el.modal('hide');
  275. },
  276. on_hide: function (e) {
  277. var self = e.data;
  278. self.defer.resolve(!!self.download_pdf);
  279. self.destroy();
  280. self.$el.remove();
  281. },
  282. can_download: function () {
  283. return this.defer;
  284. }
  285. });
  286. // Diálogo de selección de la impresora que se encargará de la impresión
  287. var PrinterSelectionDialog = instance.web.Widget.extend({
  288. template: 'PrinterSelectionDialog',
  289. events: {
  290. 'click li': 'on_select'
  291. },
  292. init: function (data) {
  293. var config = local.socket_manager.config;
  294. this.download_pdf = config.action_download_pdf || false;
  295. this.preview_pdf = config.action_preview_pdf || false;
  296. this.printers = data.printers || [];
  297. this.id = data.id;
  298. this.start();
  299. },
  300. start: function () {
  301. this.defer = $.Deferred();
  302. this.render_widget();
  303. },
  304. render_widget: function () {
  305. this.renderElement();
  306. $('body').append(this.$el);
  307. this.$el.on('hidden.bs.modal', this, this.on_hide);
  308. this.$el.modal('show');
  309. },
  310. get_selection: function () {
  311. return this.defer;
  312. },
  313. on_select: function (e) {
  314. var $el = $(e.target).closest('li');
  315. var name = $el.data('name');
  316. this.selected_printer = name;
  317. this.$el.modal('hide');
  318. },
  319. on_hide: function (e) {
  320. var self = e.data;
  321. self.defer.resolve({
  322. id: self.id,
  323. printer: self.selected_printer,
  324. print_directly: true
  325. });
  326. self.$el.remove();
  327. }
  328. });
  329. // Pequeño visor pdf
  330. var PdfViewerDialog = instance.web.Widget.extend({
  331. template: 'PdfViewerDialog',
  332. events: {
  333. 'click a.btn': 'on_action'
  334. },
  335. init: function (parent, source, name) {
  336. this._super(parent);
  337. this.source = source;
  338. this.name = name;
  339. this.set('current_page', -1);
  340. this.on('change:current_page', this, this.render_page);
  341. if (_.isObject(this.source)) {
  342. this.pdf = source;
  343. this.render_widget();
  344. return;
  345. }
  346. var matchReportUrl = this.source.match(/(?:\/(?:web\/)?report(?:\/pdf)?)/);
  347. if (matchReportUrl) {
  348. var self = this;
  349. instance.web.blockUI();
  350. instance.pdfJs.getDocument(self.source).then(function (pdf) {
  351. self.pdf = pdf;
  352. self.render_widget();
  353. });
  354. return;
  355. }
  356. var matchMimeType = this.source.match(/data:[a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+.*,/);
  357. if (matchMimeType && this.source.startsWith('data:application/pdf;base64,')) {
  358. this.source = this.source.replace(matchMimeType[0], '');
  359. }
  360. try {
  361. this.source = {
  362. data: atob(this.source)
  363. }
  364. } catch (e) {
  365. instance.webclient.crashmanager.show_message('Unknown data format');
  366. return;
  367. }
  368. instance.web.blockUI();
  369. var self = this;
  370. instance.pdfJs.getDocument(this.source).then(function (pdf) {
  371. self.pdf = pdf;
  372. self.render_widget();
  373. }).catch(function (error) {
  374. instance.web.unblockUI();
  375. instance.webclient.crashmanager.show_message(error);
  376. });
  377. },
  378. render_widget: function () {
  379. this.renderElement();
  380. $('body').append(this.$el);
  381. this.$el.on('shown.bs.modal', this, this.render_pdf);
  382. this.$el.on('hidden.bs.modal', this, this.on_hide);
  383. this.$el.modal('show');
  384. },
  385. render_pdf: function (e) {
  386. var self = e.data;
  387. if (!self.pdf) {
  388. instance.web.unblockUI();
  389. instance.web.notification.do_warn('No hay archivo PDF');
  390. return;
  391. }
  392. self.set('current_page', 1);
  393. },
  394. render_page: function () {
  395. var self = this;
  396. var current_page = self.get('current_page');
  397. self.pdf.getPage(current_page).then(function (page) {
  398. var scale = 1;
  399. var viewport = page.getViewport(scale);
  400. var $canvas = self.$el.find('canvas');
  401. var context = $canvas.get(0).getContext('2d');
  402. $canvas.attr('height', viewport.height);
  403. $canvas.attr('width', viewport.width);
  404. page.render({
  405. canvasContext: context,
  406. viewport: viewport
  407. }).then(function () {
  408. self.$('.page_counter').text('Página ' + current_page + ' de ' + self.pdf.numPages);
  409. instance.web.unblockUI();
  410. });
  411. }, function (error) {
  412. instance.web.unblockUI();
  413. instance.webclient.crashmanager.show_message(error);
  414. });
  415. },
  416. on_hide: function (e) {
  417. var self = e.data;
  418. if (self.pdf) {
  419. self.pdf.destroy();
  420. }
  421. self.destroy();
  422. self.$el.remove();
  423. },
  424. on_action: function (e) {
  425. e.preventDefault();
  426. var action = $(e.target).closest('a').data('action');
  427. this['on_' + action]();
  428. },
  429. on_next: function () {
  430. var current_page = this.get('current_page');
  431. if (current_page >= this.pdf.numPages) {
  432. return;
  433. }
  434. this.set('current_page', current_page + 1);
  435. },
  436. on_previous: function () {
  437. var current_page = this.get('current_page');
  438. if (current_page <= 1) {
  439. return;
  440. }
  441. this.set('current_page', current_page - 1);
  442. },
  443. on_print: function () {
  444. var self = this;
  445. if (!self.pdf) {
  446. return;
  447. }
  448. instance.web.blockUI();
  449. self.pdf.getData().then(function (data) {
  450. instance.web.unblockUI();
  451. if (local.socket_manager.socket.connected) {
  452. local.socket_manager.request_print(data, true);
  453. return;
  454. }
  455. instance.printJs({
  456. printable: instance.pdfJs.createObjectURL(data, 'application/pdf')
  457. });
  458. });
  459. },
  460. on_download: function () {
  461. var self = this;
  462. if (!self.pdf) {
  463. return;
  464. }
  465. self.pdf.getMetadata().then(function (metadata) {
  466. self.pdf.getData().then(function (data) {
  467. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  468. var a = document.createElement('a');
  469. a.href = url;
  470. a.download = (self.name || metadata.contentDispositionFilename || 'document') + '.pdf';
  471. a.target = '_parent';
  472. a.click();
  473. });
  474. });
  475. }
  476. });
  477. // Dispara el visor pdf
  478. var preview_pdf = function (owner, data, name) {
  479. new PdfViewerDialog(owner, data, name);
  480. };
  481. // Dispara la descarga del pdf
  482. var download_pdf = function (source) {
  483. var matchMimeType = source.match(/data:[a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+.*,/);
  484. if (!matchMimeType) {
  485. instance.webclient.crashmanager.show_message('Formato no válido para la impresión');
  486. return;
  487. }
  488. if (!source.startsWith(matchMimeType[0])) {
  489. instance.webclient.crashmanager.show_message('Formato no válido para la impresión');
  490. return;
  491. }
  492. var a = document.createElement('a');
  493. a.href = source;
  494. a.download = 'documento.pdf';
  495. a.target = '_parent';
  496. a.click();
  497. };
  498. // Dispara la impresión directa o descarga pdf
  499. local.print = function (data) {
  500. var config = this.socket_manager.config;
  501. if (config.is_mobile) {
  502. download_pdf(data);
  503. return;
  504. }
  505. if (config.action_download_pdf) {
  506. download_pdf(data);
  507. return;
  508. }
  509. if (this.socket_manager.socket.disconnected) {
  510. var widget = new PrinterUnavailableDialog();
  511. widget.can_download().then(function (can_download) {
  512. if (!can_download) {
  513. return;
  514. }
  515. if (config.action_preview_pdf) {
  516. preview_pdf(null, data, null);
  517. return;
  518. }
  519. download_pdf(data);
  520. });
  521. return;
  522. }
  523. this.socket_manager.request_print(data);
  524. };
  525. // Test
  526. local.TicketTestPage = instance.web.Widget.extend({
  527. template: 'TicketTestPage',
  528. events: {
  529. 'click .ticket-test-btn': 'print_test'
  530. },
  531. print_test: function (e) {
  532. e.preventDefault();
  533. var wrapper = document.createElement('div');
  534. wrapper.innerHTML = openerp.web.qweb.render('EiruPosTicket');
  535. wrapper.setAttribute('id', 'ticket_wrapper')
  536. $('body').append(wrapper);
  537. var ticket_el = document.querySelector('.eiru_pos_ticket');
  538. var factor = 3.779;
  539. instance.html2canvas(ticket_el, {
  540. logging: false,
  541. width: 70 * factor
  542. }).then(function (canvas) {
  543. $(wrapper).remove();
  544. var dataURL = canvas.toDataURL('image/png');
  545. var width = canvas.width / factor;
  546. var height = canvas.height / factor;
  547. var doc = new jsPDF({
  548. unit: 'mm',
  549. format: [height, 70]
  550. });
  551. doc.addImage(dataURL, 'PNG', 0, 0, width, height);
  552. var data = doc.output('datauristring');
  553. local.print(data);
  554. });
  555. }
  556. });
  557. instance.web.client_actions.add('printer_bridge.test_ticket', 'instance.printer_bridge.TicketTestPage');
  558. if (instance.web) {
  559. if (instance.web.UserMenu) {
  560. instance.web.UserMenu.include({
  561. do_update: function () {
  562. var printer = new PrinterTopNotificator(this);
  563. printer.appendTo($('.oe_systray'));
  564. local.socket_manager = new SocketManager();
  565. local.print_directly = local.socket_manager.request_print;
  566. return this._super.apply(this, arguments);
  567. }
  568. });
  569. }
  570. if (instance.web.FormView) {
  571. instance.web.FormView.include({
  572. record_saved: function (r) {
  573. if (this.model === 'res.users') {
  574. local.socket_manager.update_config();
  575. }
  576. return this._super.apply(this, arguments);
  577. }
  578. });
  579. }
  580. if (instance.web.ActionManager) {
  581. instance.web.ActionManager.include({
  582. trigger_preview_pdf: function (action) {
  583. var self = this;
  584. var regex = /^(?:qweb-(pdf|html)|controller)$/;
  585. if (_.has(action, 'report_type') && regex.test(action.report_type)) {
  586. var format = action.report_type.match(regex)[1];
  587. var url = (format || action.report_file) && ('/report/' + format + '/' + action.report_name);
  588. if (_.isEmpty(action.data) && _.has(action.context, 'active_ids')) {
  589. url += '/' + action.context.active_ids.join(',');
  590. } else {
  591. url += '?options=' + encodeURIComponent(JSON.stringify(action.data)) + '&context=' + encodeURIComponent(JSON.stringify(action.context));
  592. }
  593. preview_pdf(self, url, action.name);
  594. return;
  595. }
  596. var params = {
  597. action: JSON.stringify(action),
  598. token: (new Date()).getTime()
  599. };
  600. preview_pdf(self, this.session.url('/web/report', params), action.name);
  601. },
  602. trigger_download_pdf: function (action) {
  603. var regex = /^(?:qweb-(pdf|html)|controller)$/;
  604. var url = null;
  605. instance.web.blockUI();
  606. if (_.has(action, 'report_type') && regex.test(action.report_type)) {
  607. var format = action.report_type.match(regex)[1];
  608. url = (format || action.report_file) && ('/report/' + format + '/' + action.report_name);
  609. if (_.isEmpty(action.data) && _.has(action.context, 'active_ids')) {
  610. url += '/' + action.context.active_ids.join(',');
  611. } else {
  612. url += '?options=' + encodeURIComponent(JSON.stringify(action.data)) + '&context=' + encodeURIComponent(JSON.stringify(action.context));
  613. }
  614. }
  615. if (!url) {
  616. var params = {
  617. action: JSON.stringify(action),
  618. token: (new Date()).getTime()
  619. };
  620. url = this.session.url('/web/report', params);
  621. }
  622. instance.pdfJs.getDocument(url).then(function (pdf) {
  623. pdf.getData().then(function (data) {
  624. instance.web.unblockUI();
  625. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  626. var a = document.createElement('a');
  627. a.href = url;
  628. a.download = (action.name || action.report_name) + '.pdf';
  629. a.target = '_parent';
  630. a.click();
  631. pdf.destroy();
  632. });
  633. });
  634. },
  635. trigger_print_pdf: function (action) {
  636. var url = '/printer_bridge/get_pdf';
  637. var ctx = _.clone(action.context);
  638. ctx.report_name = action.report_name;
  639. instance.web.jsonRpc(url, 'call', {
  640. context: ctx
  641. }).done(function (result) {
  642. local.socket_manager.request_print(result.data);
  643. }).fail(function (e) {
  644. instance.webclient.crashmanager.show_message(e);
  645. });
  646. },
  647. ir_actions_report_xml: function (action, options) {
  648. var self = this;
  649. var config = local.socket_manager.config;
  650. var eval_contexts = ([instance.session.user_context] || []).concat([action.context]);
  651. action.context = instance.web.pyeval.eval('contexts', eval_contexts);
  652. if (config.is_mobile) {
  653. this.trigger_preview_pdf(action);
  654. return;
  655. }
  656. if (config.action_download_pdf) {
  657. self.trigger_download_pdf(action);
  658. return;
  659. }
  660. if (local.socket_manager.socket.disconnected) {
  661. var widget = new PrinterUnavailableDialog(this);
  662. widget.can_download().then(function (can_download) {
  663. if (!can_download) {
  664. return;
  665. }
  666. if (config.action_preview_pdf) {
  667. self.trigger_preview_pdf(action);
  668. return;
  669. }
  670. self.trigger_download_pdf(action);
  671. });
  672. return;
  673. }
  674. self.trigger_print_pdf(action);
  675. }
  676. });
  677. }
  678. }
  679. }