From ce6f13c3cd3b0b69ce7cea77c58e4f827f1e95d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Mon, 11 Jul 2022 12:49:53 +0000 Subject: [PATCH] [REF] barcodes: simplify 'O-CMD.' implementation With this commit, we simplify the way barcodes prefixed by `O-CMD.` are handled, by simply executing a ui action whenever it happens. The code is much simpler, instead of having to add a widget=barcode_handler in a specific view. Note that it changes the behaviour: now, barcodes are available everywhere, instead of just a selection of form views. This seems more natural, since we consider that the barcode scanner is basically some kind of input device. Part-of: odoo/odoo#95892 --- .../barcodes/static/src/barcode_handlers.js | 87 +++++++++++++++--- .../static/src/js/barcode_form_view.js | 91 ------------------- addons/barcodes/static/tests/barcode_tests.js | 15 ++- 3 files changed, 84 insertions(+), 109 deletions(-) diff --git a/addons/barcodes/static/src/barcode_handlers.js b/addons/barcodes/static/src/barcode_handlers.js index 84b6ffd77d6..20b64281830 100644 --- a/addons/barcodes/static/src/barcode_handlers.js +++ b/addons/barcodes/static/src/barcode_handlers.js @@ -2,29 +2,88 @@ import { registry } from "@web/core/registry"; import { getVisibleElements } from "@web/core/utils/ui"; +import { MacroEngine } from "@web/core/macro"; -export const barcodeAutoClick = { +function clickOnButton(selector) { + const button = document.body.querySelector(selector); + if (button) { + button.click(); + } +} +function updatePager(position) { + const pager = document.body.querySelector("nav.o_pager"); + if (!pager || pager.innerText.includes("-")) { + // we don't change pages if we are in a multi record view + return; + } + let next; + if (position === "first") { + next = 1; + } else { + next = parseInt(pager.querySelector(".o_pager_limit").textContent, 10); + } + let current = parseInt(pager.innerText.split('/')[0], 10); + if (current === next) { + return; + } + const engine = new MacroEngine(); + engine.activate({ + name: "updating pager", + timeout: 1000, + interval: 0, + steps: [ + { + trigger: "span.o_pager_value", + action: "click" + }, + { + trigger: "input.o_pager_value", + action: "text", + value: next + } + ] + }); +} + +const COMMANDS = { + "O-CMD.EDIT": () => clickOnButton(".o_form_button_edit"), + "O-CMD.DISCARD": () => clickOnButton(".o_form_button_cancel"), + "O-CMD.SAVE": () => clickOnButton(".o_form_button_save"), + "O-CMD.PREV": () => clickOnButton(".o_pager_previous"), + "O-CMD.NEXT": () => clickOnButton(".o_pager_next"), + "O-CMD.PAGER-FIRST": () => updatePager("first"), + "O-CMD.PAGER-LAST": () => updatePager("last"), +}; + +export const barcodeGenericHandlers = { dependencies: ["ui", "barcode"], start(env, { ui, barcode }) { barcode.bus.addEventListener("barcode_scanned", (ev) => { const barcode = ev.detail.barcode; - if (!barcode.startsWith("O-BTN.")) { - return; + if (barcode.startsWith("O-BTN.")) { + let targets = []; + try { + // the scanned barcode could be anything, and could crash the queryselectorall + // function + targets = getVisibleElements(ui.activeElement, `[barcode_trigger=${barcode.slice(6)}]`); + } catch (_e) { + console.warn(`Barcode '${barcode}' is not valid`); + } + for (let elem of targets) { + elem.click(); + } } - let targets = []; - try { - // the scanned barcode could be anything, and could crash the queryselectorall - // function - targets = getVisibleElements(ui.activeElement, `[barcode_trigger=${barcode.slice(6)}]`); - } catch (_e) { - console.warn(`Barcode '${barcode}' is not valid`) - } - for (let elem of targets) { - elem.click(); + if (barcode.startsWith("O-CMD.")) { + const fn = COMMANDS[barcode]; + if (fn) { + fn(); + } else { + console.warn(`Barcode '${barcode}' is not a valid command`); + } } }); } }; -registry.category("services").add("barcode_autoclick", barcodeAutoClick); +registry.category("services").add("barcode_handlers", barcodeGenericHandlers); diff --git a/addons/barcodes/static/src/js/barcode_form_view.js b/addons/barcodes/static/src/js/barcode_form_view.js index f2a2c022f54..efb5939d262 100644 --- a/addons/barcodes/static/src/js/barcode_form_view.js +++ b/addons/barcodes/static/src/js/barcode_form_view.js @@ -25,13 +25,6 @@ FormController.include({ this.activeBarcode = { form_view: { commands: { - 'O-CMD.EDIT': this._barcodeEdit.bind(this), - 'O-CMD.DISCARD': this._barcodeDiscard.bind(this), - 'O-CMD.SAVE': this._barcodeSave.bind(this), - 'O-CMD.PREV': this._barcodePagerPrevious.bind(this), - 'O-CMD.NEXT': this._barcodePagerNext.bind(this), - 'O-CMD.PAGER-FIRST': this._barcodePagerFirst.bind(this), - 'O-CMD.PAGER-LAST': this._barcodePagerLast.bind(this), }, }, }; @@ -71,84 +64,6 @@ FormController.include({ return this._barcodeWithoutCandidate(record, barcode, activeBarcode); } }, - /** - * @private - */ - _barcodeDiscard: function () { - return this.discardChanges(); - }, - /** - * @private - */ - _barcodeEdit: function () { - return this._setMode('edit'); - }, - /** - * @private - */ - _barcodePagerFirst: async function () { - return this._updatePage(() => 1); - }, - /** - * @private - */ - _barcodePagerLast: async function () { - return this._updatePage((min, state) => state.count); - }, - /** - * @private - */ - _barcodePagerNext: function () { - return this._updatePage((min, state) => { - min += 1; - if (min > state.count) { - min = 1; - } - return min; - }); - }, - /** - * @private - */ - _barcodePagerPrevious: function () { - return this._updatePage((min, state) => { - min -= 1; - if (min < 1) { - min = state.count; - } - return min; - }); - }, - /** - * Change the current minimum value of the pager using provided function. - * This function will be given the current minimum and state and must return - * the updated value. - * - * @private - * @param {Function(currentMin: Number, state: Object)} updater - */ - _updatePage: async function (updater) { - await this.mutex.exec(() => {}); - const state = this.model.get(this.handle, { raw: true }); - const pagingInfo = this._getPagingInfo(state); - if (!pagingInfo) { - return this.displayNotification({ message: _t('Pager unavailable'), type: 'danger' }); - } - const currentMinimum = updater(pagingInfo.currentMinimum, state); - const limit = pagingInfo.limit; - const reloadParams = state.groupedBy && state.groupedBy.length ? { - groupsLimit: limit, - groupsOffset: currentMinimum - 1, - } : { - limit, - offset: currentMinimum - 1, - }; - await this.reload(reloadParams); - // reset the scroll position to the top on page changed only - if (state.limit === limit) { - this.trigger_up('scrollTo', { top: 0 }); - } - }, /** * Returns true iff the given barcode matches the given record (candidate). * @@ -161,12 +76,6 @@ FormController.include({ _barcodeRecordFilter: function (candidate, barcode, activeBarcode) { return candidate.data.product_barcode === barcode; }, - /** - * @private - */ - _barcodeSave: function () { - return this.saveRecord(); - }, /** * @private * @param {Object} candidate: record in the x2m diff --git a/addons/barcodes/static/tests/barcode_tests.js b/addons/barcodes/static/tests/barcode_tests.js index de86cf10e70..8de9519ea00 100644 --- a/addons/barcodes/static/tests/barcode_tests.js +++ b/addons/barcodes/static/tests/barcode_tests.js @@ -2,10 +2,11 @@ odoo.define('barcodes.tests', function (require) { "use strict"; const {barcodeService} = require("@barcodes/barcode_service"); -const {barcodeAutoClick} = require("@barcodes/barcode_handlers"); +const {barcodeGenericHandlers} = require("@barcodes/barcode_handlers"); const {barcodeRemapperService} = require("@barcodes/js/barcode_events"); const { makeTestEnv } = require("@web/../tests/helpers/mock_env"); const { registry } = require("@web/core/registry"); +const { mockTimeout } = require("@web/../tests/helpers/utils"); var AbstractField = require('web.AbstractField'); var fieldRegistry = require('web.field_registry'); @@ -40,7 +41,7 @@ QUnit.module('Barcodes', { before() { barcodeService.maxTimeBetweenKeysInMs = 0; registry.category("services").add("barcode", barcodeService, { force: true}); - registry.category("services").add("barcode_autoclick", barcodeAutoClick, { force: true}); + registry.category("services").add("barcode_autoclick", barcodeGenericHandlers, { force: true}); // remove this one later registry.category("services").add("barcode_remapper", barcodeRemapperService); this.env = makeTestEnv(); @@ -172,10 +173,12 @@ QUnit.test('edit, save and cancel buttons', async function (assert) { }); QUnit.test('pager buttons', async function (assert) { + const mock = mockTimeout(); assert.expect(5); var form = await createView({ View: FormView, + debug: true, model: 'product', data: this.data, arch: '
', @@ -197,11 +200,15 @@ QUnit.test('pager buttons', async function (assert) { assert.strictEqual(form.$('.o_field_widget').text(), 'Large Cabinet'); // O-CMD.PAGER-LAST simulateBarCode(["O","-","C","M","D",".","P","A","G","E","R","-","L","A","S","T","Enter"]); - await testUtils.nextTick(); + // need to await 2 macro steps + await mock.advanceTime(20); + await mock.advanceTime(20); assert.strictEqual(form.$('.o_field_widget').text(), 'Cabinet with Doors'); // O-CMD.PAGER-FIRST simulateBarCode(["O","-","C","M","D",".","P","A","G","E","R","-","F","I","R","S","T","Enter"]); - await testUtils.nextTick(); + // need to await 2 macro steps + await mock.advanceTime(20); + await mock.advanceTime(20); assert.strictEqual(form.$('.o_field_widget').text(), 'Large Cabinet'); form.destroy();