diff --git a/addons/point_of_sale/__manifest__.py b/addons/point_of_sale/__manifest__.py
index 89ef744e40a..0e42a7cb1ea 100644
--- a/addons/point_of_sale/__manifest__.py
+++ b/addons/point_of_sale/__manifest__.py
@@ -125,11 +125,11 @@
'point_of_sale/static/src/js/**/*.js',
'web/static/lib/zxing-library/zxing-library.js',
'point_of_sale/static/src/xml/**/*.xml',
+ 'point_of_sale/static/src/app/**/*',
],
# This bundle contains the code responsible for starting the POS UI.
# It is practically the entry point.
'point_of_sale.assets_backend_prod_only': [
- 'point_of_sale/static/src/entry/chrome_adapter.js',
'point_of_sale/static/src/entry/main.js',
'web/static/src/start.js',
'web/static/src/legacy/legacy_setup.js',
diff --git a/addons/point_of_sale/static/src/app/navbar/navbar.js b/addons/point_of_sale/static/src/app/navbar/navbar.js
new file mode 100644
index 00000000000..3e6fe88a877
--- /dev/null
+++ b/addons/point_of_sale/static/src/app/navbar/navbar.js
@@ -0,0 +1,17 @@
+/** @odoo-module */
+
+import PosComponent from "@point_of_sale/js/PosComponent";
+import { usePos } from "@point_of_sale/app/pos_store";
+
+export class Navbar extends PosComponent {
+ static template = "point_of_sale.Navbar";
+ static props = {
+ showCashMoveButton: Boolean,
+ };
+ setup() {
+ this.pos = usePos();
+ }
+ get customerFacingDisplayButtonIsShown() {
+ return this.env.pos.config.iface_customer_facing_display;
+ }
+}
diff --git a/addons/point_of_sale/static/src/app/navbar/navbar.xml b/addons/point_of_sale/static/src/app/navbar/navbar.xml
new file mode 100644
index 00000000000..906623852f6
--- /dev/null
+++ b/addons/point_of_sale/static/src/app/navbar/navbar.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/static/src/app/pos_store.js b/addons/point_of_sale/static/src/app/pos_store.js
new file mode 100644
index 00000000000..b572ab73009
--- /dev/null
+++ b/addons/point_of_sale/static/src/app/pos_store.js
@@ -0,0 +1,41 @@
+/** @odoo-module */
+
+import { registry } from "@web/core/registry";
+import { useService } from "@web/core/utils/hooks";
+import { debounce } from "@web/core/utils/timing";
+import { reactive, useState, toRaw } from "@odoo/owl";
+
+export class PosStore {
+ /** @type {'LOADING' | 'READY' | 'CLOSING'} */
+ uiState = "LOADING";
+ debugWidgetIsShown = true;
+ hasBigScrollBars = false;
+ notification = {
+ isShown: false,
+ message: "",
+ duration: 2000,
+ };
+ loadingSkipButtonIsShown = false;
+ // not using an arrow function here because we need the correct `this`
+ toggleDebugWidget = debounce(function toggleDebugWidget() {
+ this.debugWidgetIsShown = !toRaw(this).debugWidgetIsShown;
+ }, 100);
+ mainScreen = { name: null, component: null };
+ constructor() {
+ this.setup();
+ }
+ // to allow other modules to add things to the store.
+ setup() {}
+}
+
+export const posService = {
+ start() {
+ return reactive(new PosStore());
+ },
+};
+
+registry.category("services").add("pos", posService);
+
+export function usePos() {
+ return useState(useService("pos"));
+}
diff --git a/addons/point_of_sale/static/src/app/sound/sound_service.js b/addons/point_of_sale/static/src/app/sound/sound_service.js
new file mode 100644
index 00000000000..cdcae67b93a
--- /dev/null
+++ b/addons/point_of_sale/static/src/app/sound/sound_service.js
@@ -0,0 +1,45 @@
+/** @odoo-module */
+
+import { Component, reactive, xml } from "@odoo/owl";
+import { registry } from "@web/core/registry";
+
+registry
+ .category("sounds")
+ .add("error", "/point_of_sale/static/src/sounds/error.wav")
+ .add("bell", "/point_of_sale/static/src/sounds/bell.wav");
+
+class SoundContainer extends Component {
+ static template = xml`
+
+ `;
+ static props = {
+ sounds: Object,
+ };
+ onError(sound) {
+ sound.cleanup();
+ const err = new Error(`Couldn't load sound at "${sound.src}"`);
+ throw err;
+ }
+}
+
+export const soundService = {
+ start() {
+ let soundId = 0;
+ const sounds = reactive({});
+ registry.category("main_components").add("SoundContainer", {
+ Component: SoundContainer,
+ props: { sounds },
+ });
+ return {
+ play(name) {
+ const id = soundId++;
+ sounds[id] = {
+ src: registry.category("sounds").get(name),
+ cleanup: () => delete sounds[id],
+ };
+ },
+ };
+ },
+};
+
+registry.category("services").add("sound", soundService);
diff --git a/addons/point_of_sale/static/src/entry/chrome_adapter.js b/addons/point_of_sale/static/src/entry/chrome_adapter.js
deleted file mode 100644
index e69b8be5c43..00000000000
--- a/addons/point_of_sale/static/src/entry/chrome_adapter.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/** @odoo-module */
-
-import { useService } from "@web/core/utils/hooks";
-
-import Chrome from "@point_of_sale/js/Chrome";
-import ProductScreen from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
-import Registries from "@point_of_sale/js/Registries";
-import { PosGlobalState } from "@point_of_sale/js/models";
-import { configureGui } from "@point_of_sale/js/Gui";
-import { registry } from "@web/core/registry";
-import env from "@point_of_sale/js/pos_env";
-import { debounce } from "@web/core/utils/timing";
-import { batched } from "@point_of_sale/js/utils";
-
-const { Component, reactive, markRaw, useExternalListener, useSubEnv, onWillUnmount, xml } = owl;
-
-export class ChromeAdapter extends Component {
- setup() {
- this.PosChrome = Registries.Component.get(Chrome);
- ProductScreen.sortControlButtons();
- const legacyActionManager = useService("legacy_action_manager");
-
- // Instantiate PosGlobalState here to ensure that every extension
- // (or class overloads) is taken into consideration.
- const pos = PosGlobalState.create({ env: markRaw(env) });
-
- this.batchedCustomerDisplayRender = batched(() => {
- reactivePos.send_current_order_to_customer_facing_display();
- });
- const reactivePos = reactive(pos, this.batchedCustomerDisplayRender);
- env.pos = reactivePos;
- env.legacyActionManager = legacyActionManager;
-
- // The proxy requires the instance of PosGlobalState to function properly.
- env.proxy.set_pos(reactivePos);
-
- // TODO: Should we continue on exposing posmodel as global variable?
- // Expose only the reactive version of `pos` when in debug mode.
- window.posmodel = pos.debug ? reactivePos : pos;
-
- this.env = env;
- this.__owl__.childEnv = env;
- useSubEnv({
- get isMobile() {
- return window.innerWidth <= 768;
- },
- });
- let currentIsMobile = this.env.isMobile;
- const updateUI = debounce(() => {
- if (this.env.isMobile !== currentIsMobile) {
- currentIsMobile = this.env.isMobile;
- this.render(true);
- }
- }, 15);
- useExternalListener(window, "resize", updateUI);
- onWillUnmount(updateUI.cancel);
- }
-
- async configureAndStart(chrome) {
- // Add the pos error handler when the chrome component is available.
- registry.category("error_handlers").add(
- "posErrorHandler",
- (env, ...noEnvArgs) => {
- if (chrome) {
- return chrome.errorHandler(this.env, ...noEnvArgs);
- }
- return false;
- },
- { sequence: 0 }
- );
- // Little trick to avoid displaying the block ui during the POS models loading
- const BlockUiFromRegistry = registry.category("main_components").get("BlockUI");
- registry.category("main_components").remove("BlockUI");
- configureGui({ component: chrome });
- await chrome.start();
- registry.category("main_components").add("BlockUI", BlockUiFromRegistry);
-
- // Subscribe to the changes in the models.
- this.batchedCustomerDisplayRender();
- }
-}
-ChromeAdapter.template = xml``;
diff --git a/addons/point_of_sale/static/src/entry/main.js b/addons/point_of_sale/static/src/entry/main.js
index d6b3d4c9fe1..72f106e122e 100644
--- a/addons/point_of_sale/static/src/entry/main.js
+++ b/addons/point_of_sale/static/src/entry/main.js
@@ -2,35 +2,15 @@
import { startWebClient } from "@web/start";
-import { ChromeAdapter } from "@point_of_sale/entry/chrome_adapter";
+import { Chrome } from "@point_of_sale/js/Chrome";
import Registries from "@point_of_sale/js/Registries";
-import { registry } from "@web/core/registry";
-
-const { Component, xml } = owl;
-
-// For consistency's sake, we should trigger"WEB_CLIENT_READY" on the bus when PosApp is mounted
-// But we can't since mail and some other poll react on that cue, and we don't want those services started
-class PosApp extends Component {
- setup() {
- this.Components = registry.category("main_components").getEntries();
- }
-}
-PosApp.template = xml`
-
-
-
-
-
-
-
-
-`;
-PosApp.components = { ChromeAdapter };
function startPosApp() {
Registries.Component.freeze();
Registries.Model.freeze();
- startWebClient(PosApp);
+ // For consistency's sake, we should trigger"WEB_CLIENT_READY" on the bus when PosApp is mounted
+ // But we can't since mail and some other poll react on that cue, and we don't want those services started
+ startWebClient(Registries.Component.get(Chrome));
}
startPosApp();
diff --git a/addons/point_of_sale/static/src/js/Chrome.js b/addons/point_of_sale/static/src/js/Chrome.js
index 3a7c2335559..c9646ff9f42 100644
--- a/addons/point_of_sale/static/src/js/Chrome.js
+++ b/addons/point_of_sale/static/src/js/Chrome.js
@@ -1,7 +1,7 @@
/** @odoo-module */
import { loadCSS } from "@web/core/assets";
-import { useListener, useBus } from "@web/core/utils/hooks";
+import { useListener, useBus, useService } from "@web/core/utils/hooks";
import BarcodeParser from "barcodes.BarcodeParser";
import PosComponent from "@point_of_sale/js/PosComponent";
import NumberBuffer from "@point_of_sale/js/Misc/NumberBuffer";
@@ -16,33 +16,87 @@ import {
} from "@web/core/network/rpc_service";
import { debounce } from "@web/core/utils/timing";
import { Transition } from "@web/core/transition";
+import { MainComponentsContainer } from "@web/core/main_components_container";
+import { WithEnv } from "@web/core/utils/components";
+import { Navbar } from "@point_of_sale/app/navbar/navbar";
-const {
- onError,
+// ChromeAdapter imports
+import ProductScreen from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
+import { PosGlobalState } from "@point_of_sale/js/models";
+import { configureGui } from "@point_of_sale/js/Gui";
+import { registry } from "@web/core/registry";
+import env from "@point_of_sale/js/pos_env";
+
+import {
onMounted,
onWillDestroy,
useExternalListener,
- useRef,
useState,
useSubEnv,
reactive,
-} = owl;
+ markRaw,
+ onWillUnmount,
+} from "@odoo/owl";
+import { usePos } from "@point_of_sale/app/pos_store";
/**
* Chrome is the root component of the PoS App.
*/
-class Chrome extends PosComponent {
+export class Chrome extends PosComponent {
setup() {
+ // BEGIN ChromeAdapter
+ ProductScreen.sortControlButtons();
+ const legacyActionManager = useService("legacy_action_manager");
+
+ // Instantiate PosGlobalState here to ensure that every extension
+ // (or class overloads) is taken into consideration.
+ const pos = PosGlobalState.create({ env: markRaw(env) });
+
+ this.batchedCustomerDisplayRender = batched(() => {
+ reactivePos.send_current_order_to_customer_facing_display();
+ });
+ const reactivePos = reactive(pos, this.batchedCustomerDisplayRender);
+ env.pos = reactivePos;
+ env.legacyActionManager = legacyActionManager;
+
+ // The proxy requires the instance of PosGlobalState to function properly.
+ env.proxy.set_pos(reactivePos);
+
+ // TODO: Should we continue on exposing posmodel as global variable?
+ // Expose only the reactive version of `pos` when in debug mode.
+ window.posmodel = pos.debug ? reactivePos : pos;
+
+ this.wowlEnv = this.env;
+ env.services.pos = this.wowlEnv.services.pos;
+ env.services.sound = this.wowlEnv.services.sound;
+ window.sound = env.services.sound;
+ this.env = env;
+ this.__owl__.childEnv = env;
+ useSubEnv({
+ get isMobile() {
+ return window.innerWidth <= 768;
+ },
+ });
+ let currentIsMobile = this.env.isMobile;
+ const updateUI = debounce(() => {
+ if (this.env.isMobile !== currentIsMobile) {
+ currentIsMobile = this.env.isMobile;
+ this.render(true);
+ }
+ }, 15); // FIXME POSREF use throttleForAnimation?
+ useExternalListener(window, "resize", updateUI);
+ onWillUnmount(updateUI.cancel);
+ // END ChromeAdapter
+
super.setup();
useExternalListener(window, "beforeunload", this._onBeforeUnload);
useListener("show-main-screen", this.__showScreen);
- useListener("toggle-debug-widget", debounce(this._toggleDebugWidget, 100));
- useListener("toggle-mobile-searchbar", this._toggleMobileSearchBar);
useListener("show-temp-screen", this.__showTempScreen);
useListener("close-temp-screen", this.__closeTempScreen);
useListener("close-pos", this._closePos);
useListener("loading-skip-callback", () => this.env.proxy.stop_searching());
- useListener("play-sound", this._onPlaySound);
+ const sound = useService("sound");
+ useListener("play-sound", ({ detail: name }) => sound.play(name));
useListener("set-sync-status", this._onSetSyncStatus);
useListener("show-notification", this._onShowNotification);
useListener("close-notification", this._onCloseNotification);
@@ -50,38 +104,24 @@ class Chrome extends PosComponent {
useBus(this.env.posbus, "start-cash-control", this.openCashControl);
NumberBuffer.activate();
- this.state = useState({
- uiState: "LOADING", // 'LOADING' | 'READY' | 'CLOSING'
- debugWidgetIsShown: true,
- mobileSearchBarIsShown: false,
- hasBigScrollBars: false,
- sound: { src: null },
- notification: {
- isShown: false,
- message: "",
- duration: 2000,
- },
- loadingSkipButtonIsShown: false,
- });
+ this.state = usePos();
- this.mainScreen = useState({ name: null, component: null });
+ this.mainScreen = this.state.mainScreen;
this.mainScreenProps = {};
this.tempScreen = useState({ isShown: false, name: null, component: null });
this.tempScreenProps = {};
- this.progressbar = useRef("progressbar");
-
- this.previous_touch_y_coordinate = -1;
-
- const pos = reactive(
- this.env.pos,
- batched(() => this.render(true))
- );
- useSubEnv({ pos });
+ useSubEnv({
+ pos: reactive(
+ this.env.pos,
+ batched(() => this.render(true)) // FIXME POSREF remove render(true)
+ ),
+ });
onMounted(() => {
// remove default webclient handlers that induce click delay
+ // FIXME POSREF if these handlers shouldn't be there we should not load the files that add them.
$(document).off();
$(window).off();
$("html").off();
@@ -89,32 +129,19 @@ class Chrome extends PosComponent {
});
onWillDestroy(() => {
- this.env.pos.destroy();
+ try {
+ // FIXME POSREF is this needed?
+ this.env.pos.destroy();
+ } catch {
+ // throwing here causes loop
+ }
});
- onError((error) => {
- // error is an OwlError object.
- console.error(error.cause);
- });
-
- this.props.setupIsDone(this);
+ this.start();
}
// GETTERS //
- get customerFacingDisplayButtonIsShown() {
- return this.env.pos.config.iface_customer_facing_display;
- }
-
- /**
- * Used to give the `state.mobileSearchBarIsShown` value to main screen props
- */
- get mainScreenPropsFielded() {
- return Object.assign({}, this.mainScreenProps, {
- mobileSearchBarIsShown: this.state.mobileSearchBarIsShown,
- });
- }
-
/**
* Startup screen can be based on pos config so the startup screen
* is only determined after pos data is completely loaded.
@@ -137,6 +164,18 @@ class Chrome extends PosComponent {
* This will load pos and assign it to the environment.
*/
async start() {
+ registry.category("error_handlers").add(
+ "posErrorHandler",
+ (env, ...noEnvArgs) => {
+ return this.errorHandler(this.env, ...noEnvArgs);
+ },
+ { sequence: 0 }
+ );
+ // Little trick to avoid displaying the block ui during the POS models loading
+ const BlockUiFromRegistry = registry.category("main_components").get("BlockUI");
+ registry.category("main_components").remove("BlockUI");
+ configureGui({ component: this }); // FIXME POSREF
+
try {
await this.env.pos.load_server_data();
await this.setupBarcodeParser();
@@ -186,6 +225,10 @@ class Chrome extends PosComponent {
exitButtonIsShown: true,
});
}
+ registry.category("main_components").add("BlockUI", BlockUiFromRegistry);
+
+ // Subscribe to the changes in the models.
+ this.batchedCustomerDisplayRender();
}
_runBackgroundTasks() {
@@ -228,7 +271,7 @@ class Chrome extends PosComponent {
this.env.proxy
.autoconnect({
force_ip: this.env.pos.config.proxy_ip || undefined,
- progress: function (prog) {},
+ progress: function (prog) { },
})
.then(
() => {
@@ -340,19 +383,19 @@ class Chrome extends PosComponent {
console.warn(error);
const reason = this.env.pos.failed
? this.env._t(
- "Some orders could not be submitted to " +
- "the server due to configuration errors. " +
- "You can exit the Point of Sale, but do " +
- "not close the session before the issue " +
- "has been resolved."
- )
+ "Some orders could not be submitted to " +
+ "the server due to configuration errors. " +
+ "You can exit the Point of Sale, but do " +
+ "not close the session before the issue " +
+ "has been resolved."
+ )
: this.env._t(
- "Some orders could not be submitted to " +
- "the server due to internet connection issues. " +
- "You can exit the Point of Sale, but do " +
- "not close the session before the issue " +
- "has been resolved."
- );
+ "Some orders could not be submitted to " +
+ "the server due to internet connection issues. " +
+ "You can exit the Point of Sale, but do " +
+ "not close the session before the issue " +
+ "has been resolved."
+ );
const { confirmed } = await this.showPopup("ConfirmPopup", {
title: this.env._t("Offline Orders"),
body: reason,
@@ -365,25 +408,6 @@ class Chrome extends PosComponent {
}
}
}
- _toggleDebugWidget() {
- this.state.debugWidgetIsShown = !this.state.debugWidgetIsShown;
- }
- _toggleMobileSearchBar({ detail: isSearchBarEnabled }) {
- if (isSearchBarEnabled !== null) {
- this.state.mobileSearchBarIsShown = isSearchBarEnabled;
- } else {
- this.state.mobileSearchBarIsShown = !this.state.mobileSearchBarIsShown;
- }
- }
- _onPlaySound({ detail: name }) {
- let src;
- if (name === "error") {
- src = "/point_of_sale/static/src/sounds/error.wav";
- } else if (name === "bell") {
- src = "/point_of_sale/static/src/sounds/bell.wav";
- }
- this.state.sound.src = src;
- }
_onSetSyncStatus({ detail: { status, pending } }) {
this.env.pos.synch.status = status;
this.env.pos.synch.pending = pending;
@@ -404,10 +428,6 @@ class Chrome extends PosComponent {
this.env.pos.db.save("TO_REFUND_LINES", this.env.pos.toRefundLines);
}
- get isTicketScreenShown() {
- return this.mainScreen.name === "TicketScreen";
- }
-
// MISC METHODS //
_preloadImages() {
for (const product of this.env.pos.db.get_product_by_category(0)) {
@@ -474,7 +494,7 @@ class Chrome extends PosComponent {
false
);
}
- showCashMoveButton() {
+ get showCashMoveButton() {
return this.env.pos && this.env.pos.config && this.env.pos.config.cash_control;
}
@@ -550,7 +570,15 @@ class Chrome extends PosComponent {
Chrome.template = "Chrome";
Object.defineProperty(Chrome, "components", {
get() {
- return Object.assign({ Transition }, PosComponent.components);
+ return Object.assign(
+ {
+ Transition,
+ MainComponentsContainer,
+ WithEnv,
+ Navbar,
+ },
+ PosComponent.components
+ );
},
});
diff --git a/addons/point_of_sale/static/src/js/ChromeWidgets/DebugWidget.js b/addons/point_of_sale/static/src/js/ChromeWidgets/DebugWidget.js
index 79f874d6bac..d462e44bbc2 100644
--- a/addons/point_of_sale/static/src/js/ChromeWidgets/DebugWidget.js
+++ b/addons/point_of_sale/static/src/js/ChromeWidgets/DebugWidget.js
@@ -5,12 +5,14 @@ import { parse } from "web.field_utils";
import NumberBuffer from "@point_of_sale/js/Misc/NumberBuffer";
import PosComponent from "@point_of_sale/js/PosComponent";
import Registries from "@point_of_sale/js/Registries";
+import { usePos } from "@point_of_sale/app/pos_store";
const { onMounted, onWillUnmount, useRef, useState } = owl;
class DebugWidget extends PosComponent {
setup() {
super.setup();
+ this.pos = usePos();
this.state = useState({
barcodeInput: "",
weightInput: "",
diff --git a/addons/point_of_sale/static/src/js/ChromeWidgets/TicketButton.js b/addons/point_of_sale/static/src/js/ChromeWidgets/TicketButton.js
index de90148561c..611efa518fa 100644
--- a/addons/point_of_sale/static/src/js/ChromeWidgets/TicketButton.js
+++ b/addons/point_of_sale/static/src/js/ChromeWidgets/TicketButton.js
@@ -1,16 +1,23 @@
/** @odoo-module */
+import { usePos } from "@point_of_sale/app/pos_store";
import PosComponent from "@point_of_sale/js/PosComponent";
import Registries from "@point_of_sale/js/Registries";
class TicketButton extends PosComponent {
+ setup() {
+ this.pos = usePos();
+ }
onClick() {
- if (this.props.isTicketScreenShown) {
+ if (this.isTicketScreenShown) {
this.env.posbus.trigger("ticket-button-clicked");
} else {
this.showScreen("TicketScreen");
}
}
+ get isTicketScreenShown() {
+ return this.pos.mainScreen.name === "TicketScreen";
+ }
get count() {
if (this.env.pos) {
return this.env.pos.get_order_list().length;
diff --git a/addons/point_of_sale/static/src/js/Misc/NotificationSound.js b/addons/point_of_sale/static/src/js/Misc/NotificationSound.js
deleted file mode 100644
index 3132dc2b468..00000000000
--- a/addons/point_of_sale/static/src/js/Misc/NotificationSound.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/** @odoo-module */
-
-import { useListener } from "@web/core/utils/hooks";
-import PosComponent from "@point_of_sale/js/PosComponent";
-import Registries from "@point_of_sale/js/Registries";
-
-class NotificationSound extends PosComponent {
- setup() {
- super.setup();
- useListener("ended", () => (this.props.sound.src = null));
- }
-}
-NotificationSound.template = "NotificationSound";
-
-Registries.Component.add(NotificationSound);
-
-export default NotificationSound;
diff --git a/addons/point_of_sale/static/src/js/PosComponent.js b/addons/point_of_sale/static/src/js/PosComponent.js
index 26b5fc3fbe1..1e5d9a425ba 100644
--- a/addons/point_of_sale/static/src/js/PosComponent.js
+++ b/addons/point_of_sale/static/src/js/PosComponent.js
@@ -1,18 +1,10 @@
/** @odoo-module */
import { LegacyComponent } from "@web/legacy/legacy_component";
-const { onRendered } = owl;
let nextId = 0;
class PosComponent extends LegacyComponent {
- setup() {
- onRendered(() => {
- if (this.env.isDebug()) {
- console.log("Rendered:", this.constructor.name);
- }
- });
- }
/**
* This function is available to all Components that inherit this class.
* The goal of this function is to show an awaitable dialog (popup) that
diff --git a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidget.js b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidget.js
index e5d027994a8..6a9805b8298 100644
--- a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidget.js
+++ b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidget.js
@@ -3,8 +3,9 @@
import PosComponent from "@point_of_sale/js/PosComponent";
import { useListener } from "@web/core/utils/hooks";
import Registries from "@point_of_sale/js/Registries";
+import { usePos } from "@point_of_sale/app/pos_store";
-const { onWillUnmount, useState } = owl;
+const { useState } = owl;
class ProductsWidget extends PosComponent {
/**
@@ -18,10 +19,7 @@ class ProductsWidget extends PosComponent {
useListener("clear-search", this._clearSearch);
useListener("update-product-list", this._updateProductList);
this.state = useState({ searchWord: "" });
- onWillUnmount(this.onWillUnmount);
- }
- onWillUnmount() {
- this.trigger("toggle-mobile-searchbar", false);
+ this.pos = usePos();
}
get selectedCategoryId() {
return this.env.pos.selectedCategoryId;
diff --git a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidgetControlPanel.js b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidgetControlPanel.js
index 9d09c8895a4..b8252852c0b 100644
--- a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidgetControlPanel.js
+++ b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidgetControlPanel.js
@@ -5,14 +5,16 @@ import { ConnectionLostError, ConnectionAbortedError } from "@web/core/network/r
import PosComponent from "@point_of_sale/js/PosComponent";
import Registries from "@point_of_sale/js/Registries";
import { debounce } from "@web/core/utils/timing";
+import { usePos } from "@point_of_sale/app/pos_store";
-const { onMounted, onWillUnmount } = owl;
+import { onMounted, onWillUnmount, useState } from "@odoo/owl";
class ProductsWidgetControlPanel extends PosComponent {
setup() {
super.setup();
+ this.pos = usePos();
this.updateSearch = debounce(this.updateSearch, 100);
- this.state = { searchInput: "" };
+ this.state = useState({ searchInput: "", mobileSearchBarIsShown: false });
onMounted(() => {
this.env.posbus.on("search-product-from-info-popup", this, this.searchProductFromInfo);
@@ -25,6 +27,9 @@ class ProductsWidgetControlPanel extends PosComponent {
this.env.posbus.off("search-product-from-info-popup", this);
});
}
+ toggleMobileSearchBar() {
+ this.state.mobileSearchBarIsShown = !this.state.mobileSearchBarIsShown;
+ }
_clearSearch() {
this.state.searchInput = "";
this.trigger("clear-search");
@@ -65,9 +70,6 @@ class ProductsWidgetControlPanel extends PosComponent {
this.trigger("switch-category", 0);
this.trigger("update-search", productName);
}
- _toggleMobileSearchbar() {
- this.trigger("toggle-mobile-searchbar");
- }
async loadProductFromDB() {
if (!this.state.searchInput) {
return;
diff --git a/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js
index 5d4b5407441..1018af53cdd 100644
--- a/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js
+++ b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js
@@ -6,7 +6,7 @@ import { useErrorHandlers } from "@point_of_sale/js/custom_hooks";
import Registries from "@point_of_sale/js/Registries";
import AbstractReceiptScreen from "@point_of_sale/js/Misc/AbstractReceiptScreen";
-const { onMounted, useRef, status } = owl;
+import { onMounted, useRef, status } from "@odoo/owl";
const ReceiptScreen = (AbstractReceiptScreen) => {
class ReceiptScreen extends AbstractReceiptScreen {
diff --git a/addons/point_of_sale/static/src/xml/Chrome.xml b/addons/point_of_sale/static/src/xml/Chrome.xml
index 8f5bbb2a220..9852e5025c9 100644
--- a/addons/point_of_sale/static/src/xml/Chrome.xml
+++ b/addons/point_of_sale/static/src/xml/Chrome.xml
@@ -4,33 +4,16 @@
-
+
+
+ t-props="mainScreenProps" t-key="mainScreen.name" />
@@ -65,8 +48,10 @@
-
+
+
+
diff --git a/addons/point_of_sale/static/src/xml/ChromeWidgets/DebugWidget.xml b/addons/point_of_sale/static/src/xml/ChromeWidgets/DebugWidget.xml
index 23c383f17ae..17b701d3eb9 100644
--- a/addons/point_of_sale/static/src/xml/ChromeWidgets/DebugWidget.xml
+++ b/addons/point_of_sale/static/src/xml/ChromeWidgets/DebugWidget.xml
@@ -7,7 +7,7 @@
-
Electronic Scale
diff --git a/addons/point_of_sale/static/src/xml/ChromeWidgets/TicketButton.xml b/addons/point_of_sale/static/src/xml/ChromeWidgets/TicketButton.xml
index a18774428d9..d423bc12bcd 100644
--- a/addons/point_of_sale/static/src/xml/ChromeWidgets/TicketButton.xml
+++ b/addons/point_of_sale/static/src/xml/ChromeWidgets/TicketButton.xml
@@ -2,7 +2,7 @@
-
diff --git a/addons/point_of_sale/static/src/xml/Screens/ProductScreen/ProductsWidget.xml b/addons/point_of_sale/static/src/xml/Screens/ProductScreen/ProductsWidget.xml
index 4111c0b54fc..069acaff2c4 100644
--- a/addons/point_of_sale/static/src/xml/Screens/ProductScreen/ProductsWidget.xml
+++ b/addons/point_of_sale/static/src/xml/Screens/ProductScreen/ProductsWidget.xml
@@ -3,8 +3,7 @@