main.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. window.pdfjsLib.GlobalWorkerOptions.workerSrc = '/print_engine/static/lib/js/pdf.worker.js';
  2. openerp.pdfJs = window.pdfjsLib || {};
  3. openerp.print_engine = function (instance, local) {
  4. local.SocketManager = instance.web.Class.extend({
  5. init: function () {
  6. this.socket = null;
  7. this.start();
  8. },
  9. start: function () {
  10. this.open_socket();
  11. },
  12. open_socket: function () {
  13. var self = this;
  14. var setup_socket = function (config) {
  15. self.config = config;
  16. self.config.is_mobile = self.is_mobile_browser()
  17. if (!self.config.is_mobile) {
  18. self.socket = io(location.protocol + '//' + config.host + ':' + config.port, {
  19. path: config.path
  20. });
  21. self.socket.on('connect', self.handle_connect);
  22. self.socket.on('error', self.handle_error);
  23. self.socket.on('connect_error', self.handle_connect_error);
  24. self.socket.on('request_printer_name', self.handle_printer_selection);
  25. self.socket.on('show_print_status', self.handle_print_status);
  26. }
  27. }
  28. this.get_socket_config().then(setup_socket);
  29. },
  30. handle_connect: function () {
  31. $('#printer-status').removeClass();
  32. $('#printer-status').addClass('printer-status-online');
  33. },
  34. handle_error: function (e) {
  35. console.log(e);
  36. },
  37. handle_connect_error: function (e) {
  38. $('#printer-status').removeClass();
  39. $('#printer-status').addClass('printer-status-offline');
  40. },
  41. handle_printer_selection: function (data) {
  42. instance.web.unblockUI();
  43. var self = this;
  44. if (data.printers && data.printer.length === 0) {
  45. instance.web.notification.do_notify('Impresión', 'No hay impresoras instaladas');
  46. return;
  47. }
  48. var widget = new local.PrinterSelectionWidget(data);
  49. widget.get_selection().then(function (new_request) {
  50. self.emit('request_print', new_request);
  51. });
  52. },
  53. handle_print_status: function (data) {
  54. instance.web.unblockUI();
  55. if (_.isEqual(data.status, 'failed')) {
  56. instance.web.notification.do_warn('Impresión', 'Ha fallado la cola de impresión');
  57. return;
  58. }
  59. if (_.isEqual(data.status, 'canceled')) {
  60. instance.web.notification.do_notify('Impresión', 'Se ha cancelado la impresión');
  61. return;
  62. }
  63. if (_.isEqual(data.status, 'unknown')) {
  64. instance.web.notification.do_warn('Impresión', 'Imposible imprimir un formato de datos desconocido');
  65. return;
  66. }
  67. if (_.isEqual(data.status, 'printing')) {
  68. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' está imprimiendo');
  69. return;
  70. }
  71. if (_.isEqual(data.status, 'printed')) {
  72. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' finalizó la impresión');
  73. return;
  74. }
  75. if (_.isEqual(data.status, 'error')) {
  76. instance.web.notification.do_warn('Impresión', 'Ocurrió un error al imprimir: ' + data.printer);
  77. }
  78. },
  79. get_socket_config: function () {
  80. var url = '/print_engine/socket_config';
  81. return this.get_from_server(url);
  82. },
  83. get_from_server: function (url) {
  84. instance.web.blockUI();
  85. return $.Deferred(function (d) {
  86. instance.web.jsonRpc(url, 'call').done(function () {
  87. instance.web.unblockUI();
  88. d.resolve.apply(d, arguments);
  89. }).fail(function (e) {
  90. instance.web.unblockUI();
  91. d.reject.apply(d, arguments);
  92. });
  93. });
  94. },
  95. is_mobile_browser: function () {
  96. var userAgent = navigator.userAgent;
  97. 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));
  98. },
  99. request_print: function (data) {
  100. if (!this.socket || !this.socket.connected) {
  101. instance.web.notification.do_warn('Impresión', 'La impresora no está preparada');
  102. return;
  103. }
  104. instance.web.blockUI();
  105. try {
  106. this.socket.emit('request_print', {
  107. print_directly: this.config.print_directly,
  108. data: data
  109. });
  110. } catch (e) {
  111. instance.web.unblockUI();
  112. instance.webclient.crashmanager.show_message(e);
  113. }
  114. }
  115. });
  116. local.PrinterTopWidget = instance.web.Widget.extend({
  117. template: 'PrinterTopWidget',
  118. init: function (parent) {
  119. this._super(parent);
  120. }
  121. });
  122. local.PrinterUnavailableWidget = instance.web.Widget.extend({
  123. template: 'PrinterUnavailableWidget',
  124. events: {
  125. 'click li': 'on_download'
  126. },
  127. init: function (parent) {
  128. this._super(parent);
  129. this.start();
  130. },
  131. start: function () {
  132. this.defer = $.Deferred();
  133. this.render_widget();
  134. },
  135. render_widget: function () {
  136. this.renderElement();
  137. $('body').append(this.$el);
  138. this.$el.on('hidden.bs.modal', this, this.on_hide);
  139. this.$el.modal('show');
  140. },
  141. on_download: function () {
  142. this.download_pdf = true;
  143. this.$el.modal('hide');
  144. },
  145. on_hide: function (e) {
  146. var self = e.data;
  147. self.defer.resolve(!!self.download_pdf);
  148. self.destroy();
  149. self.$el.remove();
  150. },
  151. can_download: function () {
  152. return this.defer;
  153. }
  154. });
  155. local.PrinterSelectionWidget = instance.web.Widget.extend({
  156. template: 'PrinterSelectionWidget',
  157. events: {
  158. 'click li': 'on_select'
  159. },
  160. printers: [],
  161. init: function (data) {
  162. this.id = data.id;
  163. this.printers = data.printers;
  164. this.start();
  165. },
  166. start: function () {
  167. this.defer = $.Deferred();
  168. this.render_widget();
  169. },
  170. render_widget: function () {
  171. this.renderElement();
  172. $('body').append(this.$el);
  173. this.$el.on('hidden.bs.modal', this, this.on_hide);
  174. this.$el.modal('show');
  175. },
  176. get_selection: function () {
  177. return this.defer;
  178. },
  179. on_select: function (e) {
  180. var $el = $(e.target).closest('li');
  181. var name = $el.data('name');
  182. this.selected_printer = name;
  183. this.$el.modal('hide');
  184. },
  185. on_hide: function (e) {
  186. var self = e.data;
  187. self.defer.resolve({
  188. id: self.id,
  189. printer: self.selected_printer,
  190. print_directly: true
  191. });
  192. self.destroy();
  193. self.$el.remove();
  194. }
  195. });
  196. local.PdfViewerDialog = instance.web.Widget.extend({
  197. template: 'PdfViewerDialog',
  198. events: {
  199. 'click a.btn': 'on_action'
  200. },
  201. init: function (parent, url) {
  202. this._super(parent);
  203. var self = this;
  204. instance.web.blockUI();
  205. instance.pdfJs.getDocument(url).then(function (pdf) {
  206. self.pdf = pdf;
  207. self.set('current_page', -1);
  208. self.on('change:current_page', self, self.render_page);
  209. self.render_widget();
  210. });
  211. },
  212. render_widget: function () {
  213. this.renderElement();
  214. $('body').append(this.$el);
  215. this.$el.on('shown.bs.modal', this, this.render_pdf);
  216. this.$el.on('hidden.bs.modal', this, this.on_hide);
  217. this.$el.modal('show');
  218. },
  219. render_pdf: function (e) {
  220. var self = e.data;
  221. if (!self.pdf) {
  222. instance.web.notification.do_warn('No hay archivo PDF');
  223. return;
  224. }
  225. self.set('current_page', 1);
  226. },
  227. render_page: function () {
  228. var self = this;
  229. var current_page = self.get('current_page');
  230. self.pdf.getPage(current_page).then(function (page) {
  231. var scale = 1;
  232. var viewport = page.getViewport(scale);
  233. var $canvas = self.$el.find('canvas');
  234. var context = $canvas.get(0).getContext('2d');
  235. $canvas.attr('height', viewport.height);
  236. $canvas.attr('width', viewport.width);
  237. page.render({
  238. canvasContext: context,
  239. viewport: viewport
  240. }).then(function () {
  241. self.$('.page_counter').text('Página ' + current_page + ' de ' + self.pdf.numPages);
  242. instance.web.unblockUI();
  243. });
  244. }, function (error) {
  245. instance.web.unblockUI();
  246. instance.webclient.crashmanager.show_message(error);
  247. });
  248. },
  249. on_hide: function (e) {
  250. var self = e.data;
  251. if (self.pdf) {
  252. self.pdf.destroy();
  253. }
  254. self.destroy();
  255. self.$el.remove();
  256. },
  257. on_action: function (e) {
  258. e.preventDefault();
  259. var action = $(e.target).closest('a').data('action');
  260. this['on_' + action]();
  261. },
  262. on_next: function () {
  263. var current_page = this.get('current_page');
  264. if (current_page >= this.pdf.numPages) {
  265. return;
  266. }
  267. this.set('current_page', current_page + 1);
  268. },
  269. on_previous: function () {
  270. var current_page = this.get('current_page');
  271. if (current_page <= 1) {
  272. return;
  273. }
  274. this.set('current_page', current_page - 1);
  275. },
  276. on_print: function () {
  277. console.log(this);
  278. console.log('print');
  279. },
  280. on_download: function () {
  281. var self = this;
  282. if (!self.pdf) {
  283. return;
  284. }
  285. this.pdf.getData().then(function (data) {
  286. console.log(data);
  287. var newBlob = new Blob(data, {
  288. type: 'application/pdf'
  289. });
  290. var objUrl = URL.createObjectURL(newBlob);
  291. var $a = $('a');
  292. $a.attr('href', objUrl);
  293. $a.attr('target', '_parent');
  294. console.log($a);
  295. $a.appendTo(self.$el);
  296. $a.click();
  297. $a.remove();
  298. });
  299. }
  300. });
  301. if (instance.web) {
  302. if (instance.web.UserMenu) {
  303. instance.web.UserMenu.include({
  304. do_update: function () {
  305. var printer = new local.PrinterTopWidget(this);
  306. printer.appendTo($('.oe_systray'));
  307. local.socket_manager = new local.SocketManager();
  308. return this._super.apply(this, arguments);
  309. }
  310. });
  311. }
  312. if (instance.web.ActionManager) {
  313. instance.web.ActionManager.include({
  314. trigger_preview_pdf: function (action) {
  315. var self = this;
  316. var regex = /^(?:qweb-(pdf|html)|controller)$/;
  317. if (_.has(action, 'report_type') && regex.test(action.report_type)) {
  318. var format = action.report_type.match(regex)[1];
  319. var url = (format || action.report_file) && ('/report/' + format + '/' + action.report_name);
  320. if (_.isEmpty(action.data) && _.has(action.context, 'active_ids')) {
  321. url += '/' + action.context.active_ids.join(',');
  322. } else {
  323. url += '?options=' + encodeURIComponent(JSON.stringify(action.data)) + '&context=' + encodeURIComponent(JSON.stringify(action.context));
  324. }
  325. new local.PdfViewerDialog(self, url);
  326. return;
  327. }
  328. var params = {
  329. action: JSON.stringify(action),
  330. token: (new Date()).getTime()
  331. };
  332. new local.PdfViewerDialog(self, this.session.url('/web/report', params));
  333. },
  334. trigger_download_pdf: function (action) {
  335. console.log(action);
  336. },
  337. ir_actions_report_xml: function (action, options) {
  338. var self = this;
  339. var config = instance.print_engine.socket_manager.config;
  340. var eval_contexts = ([instance.session.user_context] || []).concat([action.context]);
  341. action.context = instance.web.pyeval.eval('contexts', eval_contexts);
  342. if (config.is_mobile) {
  343. this.trigger_preview_pdf(action);
  344. return;
  345. }
  346. if (instance.print_engine.socket_manager.socket.disconnected) {
  347. var widget = new local.PrinterUnavailableWidget(this);
  348. widget.can_download().then(function (can_download) {
  349. if (!can_download) {
  350. return;
  351. }
  352. if (config.action_preview_pdf) {
  353. self.trigger_preview_pdf(action);
  354. return;
  355. }
  356. self.trigger_download_pdf(action);
  357. });
  358. return;
  359. }
  360. var url = '/print_engine/get_pdf';
  361. var ctx = _.clone(action.context);
  362. ctx.report_name = action.report_name;
  363. instance.web.jsonRpc(url, 'call', {
  364. context: ctx
  365. }).done(function (result) {
  366. instance.print_engine.socket_manager.request_print(result.data);
  367. }).fail(function (e) {
  368. instance.webclient.crashmanager.show_message(e);
  369. });
  370. }
  371. });
  372. }
  373. }
  374. }