[REF] pos*, web: use reactivity to react to changes in UI size
pos*: point_of_sale, pos_restaurant, pos_sale Previously the pos would rerender the entire UI when the window was resized. In practice, most components do not care about the size of the UI for their rendering, and so we're doing a lot of needless work, and also using an owl feature (deep renders) whose perennity is not certain (we may want to remove the ability to do deep renders completely in the future). This commit changes the pos code to use the ui service `isSmall` field, makes the ui service reactive so that components can subscribe to changes inside of it with `useState`, and makes the ui service update its internal state at most once per animation frame, instead of after 100ms without resizing, so that resizing the viewport results in a smoother user experience. closes odoo/odoo#121343 Signed-off-by: adgu-odoo <adgu@odoo.com>
This commit is contained in:
@@ -31,6 +31,7 @@ export class Navbar extends Component {
|
||||
};
|
||||
setup() {
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.debug = useService("debug");
|
||||
this.popup = useService("popup");
|
||||
this.notification = useService("pos_notification");
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="pos-topheader">
|
||||
<div t-if="pos.tempScreen" class="block-top-header" />
|
||||
<div class="pos-branding">
|
||||
<img t-if="!env.isMobile" class="pos-logo" t-on-click="() => debug.toggleWidget()" src="/point_of_sale/static/src/img/logo.png" alt="Logo" />
|
||||
<img t-if="!ui.isSmall" class="pos-logo" t-on-click="() => debug.toggleWidget()" src="/point_of_sale/static/src/img/logo.png" alt="Logo" />
|
||||
</div>
|
||||
<div class="pos-rightheader">
|
||||
<div class="status-buttons">
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { throttleForAnimation } from "@web/core/utils/timing";
|
||||
import { Transition } from "@web/core/transition";
|
||||
import { MainComponentsContainer } from "@web/core/main_components_container";
|
||||
import { ErrorHandler } from "@web/core/utils/components";
|
||||
import { Navbar } from "@point_of_sale/app/navbar/navbar";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import {
|
||||
useExternalListener,
|
||||
useSubEnv,
|
||||
reactive,
|
||||
onWillUnmount,
|
||||
Component,
|
||||
onMounted,
|
||||
} from "@odoo/owl";
|
||||
import { reactive, Component, onMounted } from "@odoo/owl";
|
||||
|
||||
/**
|
||||
* Chrome is the root component of the PoS App.
|
||||
@@ -30,22 +22,6 @@ export class Chrome extends Component {
|
||||
const reactivePos = reactive(this.pos.globalState);
|
||||
// TODO: Should we continue on exposing posmodel as global variable?
|
||||
window.posmodel = reactivePos;
|
||||
// FIXME POSREF: remove
|
||||
useSubEnv({
|
||||
get isMobile() {
|
||||
return window.innerWidth <= 768;
|
||||
},
|
||||
});
|
||||
let currentIsMobile = this.env.isMobile;
|
||||
const updateUI = throttleForAnimation(() => {
|
||||
if (this.env.isMobile !== currentIsMobile) {
|
||||
currentIsMobile = this.env.isMobile;
|
||||
// FIXME POSREF use reactive mobile instead
|
||||
this.render(true);
|
||||
}
|
||||
});
|
||||
useExternalListener(window, "resize", updateUI);
|
||||
onWillUnmount(updateUI.cancel);
|
||||
|
||||
// prevent backspace from performing a 'back' navigation
|
||||
document.addEventListener("keydown", (ev) => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
// Previously UsernameWidget
|
||||
export class CashierName extends Component {
|
||||
@@ -9,6 +10,7 @@ export class CashierName extends Component {
|
||||
|
||||
setup() {
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
get username() {
|
||||
const { name } = this.pos.globalState.get_cashier();
|
||||
|
||||
@@ -12,6 +12,7 @@ export class ProxyStatus extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
const hardwareProxy = useService("hardware_proxy");
|
||||
this.connectionInfo = useState(hardwareProxy.connectionInfo);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component, useExternalListener, useState } from "@odoo/owl";
|
||||
import { useAutofocus } from "@web/core/utils/hooks";
|
||||
import { useAutofocus, useService } from "@web/core/utils/hooks";
|
||||
|
||||
/**
|
||||
* This is a simple configurable search bar component. It has search fields
|
||||
@@ -29,7 +29,7 @@ export class SearchBar extends Component {
|
||||
static template = "point_of_sale.SearchBar";
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
this.ui = useState(useService("ui"));
|
||||
useAutofocus();
|
||||
useExternalListener(window, "click", this._hideOptions);
|
||||
this.filterOptionsList = [...this.props.config.filter.options.keys()];
|
||||
@@ -65,9 +65,7 @@ export class SearchBar extends Component {
|
||||
if (["ArrowUp", "ArrowDown"].includes(event.key)) {
|
||||
this.state.selectedSearchFieldId = this._fieldIdToSelect(event.key);
|
||||
} else if (event.key === "Enter" || this.state.searchInput == "") {
|
||||
this._onClickSearchField(
|
||||
this.searchFieldsList[this.state.selectedSearchFieldId],
|
||||
);
|
||||
this._onClickSearchField(this.searchFieldsList[this.state.selectedSearchFieldId]);
|
||||
} else {
|
||||
if (this.state.selectedSearchFieldId === -1 && this.searchFieldsList.length) {
|
||||
this.state.selectedSearchFieldId = 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @odoo-module */
|
||||
import { reactive } from "@odoo/owl";
|
||||
// Create global context objects
|
||||
// e.g. component.env.device = new Context({ isMobile: false });
|
||||
// FIXME POSREF singletons exported by modules are not testable, this should probably be a service
|
||||
export const orderManagement = reactive({ searchString: "", selectedOrder: null });
|
||||
|
||||
@@ -32,6 +32,7 @@ export class PartnerListScreen extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.orm = useService("orm");
|
||||
this.notification = useService("pos_notification");
|
||||
this.searchWordInputRef = useRef("search-word-input-partner");
|
||||
|
||||
@@ -15,7 +15,7 @@ import { PaymentScreenNumpad } from "./PaymentScreenNumpad";
|
||||
import { PaymentScreenPaymentLines } from "./PaymentScreenPaymentLines";
|
||||
import { PaymentScreenStatus } from "./PaymentScreenStatus";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
export class PaymentScreen extends Component {
|
||||
@@ -29,6 +29,7 @@ export class PaymentScreen extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.orm = useService("orm");
|
||||
this.popup = useService("popup");
|
||||
this.report = useService("report");
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
/**
|
||||
* @props partner
|
||||
@@ -14,6 +15,7 @@ export class ActionpadWidget extends Component {
|
||||
|
||||
setup() {
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
|
||||
get isLongName() {
|
||||
|
||||
@@ -37,6 +37,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.popup = useService("popup");
|
||||
this.orm = useService("orm");
|
||||
this.notification = useService("pos_notification");
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ export class ProductsWidgetControlPanel extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.notification = useService("pos_notification");
|
||||
this.orm = useService("orm");
|
||||
this.updateSearch = debounce(this.updateSearch, 100);
|
||||
@@ -29,7 +30,7 @@ export class ProductsWidgetControlPanel extends Component {
|
||||
}
|
||||
get displayCategImages() {
|
||||
return (
|
||||
!this.env.isMobile &&
|
||||
!this.ui.isSmall &&
|
||||
Object.values(this.pos.globalState.db.category_by_id).some((categ) => categ.has_image)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AbstractReceiptScreen } from "@point_of_sale/js/Misc/AbstractReceiptScr
|
||||
import { OfflineErrorPopup } from "@point_of_sale/js/Popups/OfflineErrorPopup";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { OrderReceipt } from "./OrderReceipt";
|
||||
import { onMounted, useRef, status } from "@odoo/owl";
|
||||
import { onMounted, useRef, status, useState } from "@odoo/owl";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { BasePrinter } from "@point_of_sale/app/printer/base_printer";
|
||||
@@ -18,6 +18,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
useErrorHandlers();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.orm = useService("orm");
|
||||
this.orderReceipt = useRef("order-receipt");
|
||||
this.buttonMailReceipt = useRef("order-mail-receipt-button");
|
||||
|
||||
@@ -48,6 +48,7 @@ export class TicketScreen extends IndependentToOrderScreen {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.popup = useService("popup");
|
||||
this.orm = useService("orm");
|
||||
this.numberBuffer = useService("number_buffer");
|
||||
@@ -56,7 +57,7 @@ export class TicketScreen extends IndependentToOrderScreen {
|
||||
});
|
||||
this._state = this.pos.globalState.TICKET_SCREEN_STATE;
|
||||
this.state = useState({
|
||||
showSearchBar: !this.env.isMobile,
|
||||
showSearchBar: !this.ui.isSmall,
|
||||
});
|
||||
const defaultUIState = this.props.reuseSavedUIState
|
||||
? this._state.ui
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="CashierName" owl="1">
|
||||
<div t-att-class="cssClass">
|
||||
<span class="cashier-name"><img t-att-src="avatar" t-att-alt="username" class="avatar"/> <span t-if="!env.isMobile" t-esc="username" class="username"/></span>
|
||||
<span class="cashier-name"><img t-att-src="avatar" t-att-alt="username" class="avatar"/> <span t-if="!ui.isSmall" t-esc="username" class="username"/></span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="ProxyStatus" owl="1">
|
||||
<div class="oe_status js_proxy" t-on-click="() => this.pos.connectToProxy()">
|
||||
<span t-if="this.message and !env.isMobile" class="js_msg">
|
||||
<span t-if="this.message and !ui.isSmall" class="js_msg">
|
||||
<t t-esc="this.message" />
|
||||
</span>
|
||||
<span t-if="connectionInfo.status === 'connected' and !this.message" class="js_connected oe_green">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="point_of_sale.SearchBar" owl="1">
|
||||
<div class="pos-search-bar">
|
||||
<div class="search">
|
||||
<span class="search-icon" t-if="!env.isMobile"><i class="fa fa-search"></i></span>
|
||||
<span class="search-icon" t-if="!ui.isSmall"><i class="fa fa-search"></i></span>
|
||||
<input class="radius-left" t-ref="autofocus" t-att-class="{ 'radius-right': !props.config.filter.show }"
|
||||
t-model="state.searchInput" t-on-keydown="onSearchInputKeydown" t-on-keyup="onSearchInputKeyup" type="text" t-att-placeholder="props.placeholder" />
|
||||
<div t-if="state.showSearchFields and state.searchInput" class="fields">
|
||||
|
||||
@@ -6,20 +6,20 @@
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<div class="button highlight" t-if="state.detailIsShown" t-on-click="() => this.partnerEditor.save()">
|
||||
<i t-if="env.isMobile" class="fa fa-floppy-o"/>
|
||||
<t t-if="!env.isMobile">
|
||||
<i t-if="ui.isSmall" class="fa fa-floppy-o"/>
|
||||
<t t-else="">
|
||||
<span> Save</span>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="!state.detailIsShown" class="button new-customer highlight" role="img" aria-label="Add a customer"
|
||||
t-on-click="createPartner"
|
||||
title="Add a customer">
|
||||
<i t-if="env.isMobile" class="fa fa-plus"/>
|
||||
<t t-if="!env.isMobile"> Create</t>
|
||||
<i t-if="ui.isSmall" class="fa fa-plus"/>
|
||||
<t t-else=""> Create</t>
|
||||
</div>
|
||||
<div class="button back" t-on-click="back">
|
||||
<i t-if="env.isMobile" class="fa fa-angle-double-left"/>
|
||||
<t t-if="!env.isMobile"> Discard</t>
|
||||
<i t-if="ui.isSmall" class="fa fa-angle-double-left"/>
|
||||
<t t-else=""> Discard</t>
|
||||
</div>
|
||||
<div class="top-right-buttons">
|
||||
<div t-if="state.detailIsShown && state.editModeProps.partner.id" class="button more-info">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="PaymentScreen" owl="1">
|
||||
<div class="payment-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-content">
|
||||
<t t-if="!env.isMobile">
|
||||
<t t-if="!ui.isSmall">
|
||||
<div class="top-content">
|
||||
<div class="button back"
|
||||
t-on-click="() => pos.showScreen('ProductScreen')">
|
||||
@@ -16,7 +16,7 @@
|
||||
</t>
|
||||
<div class="main-content">
|
||||
<div class="left-content">
|
||||
<t t-if="env.isMobile">
|
||||
<t t-if="ui.isSmall">
|
||||
<section class="paymentlines-container">
|
||||
<PaymentScreenStatus order="currentOrder" />
|
||||
</section>
|
||||
@@ -44,7 +44,7 @@
|
||||
sendPaymentRequest.bind="sendPaymentRequest"
|
||||
selectLine.bind="selectPaymentLine"/>
|
||||
</div>
|
||||
<div t-if="!env.isMobile" class="button next validation" t-att-class="{ highlight: currentOrder.is_paid() and currentOrder._isValidEmptyOrder() }"
|
||||
<div t-if="!ui.isSmall" class="button next validation" t-att-class="{ highlight: currentOrder.is_paid() and currentOrder._isValidEmptyOrder() }"
|
||||
t-on-click="() => this.validateOrder()">
|
||||
<div class="pay-circle">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="center-content">
|
||||
<t t-if="!env.isMobile">
|
||||
<t t-if="!ui.isSmall">
|
||||
<section class="paymentlines-container">
|
||||
<PaymentScreenStatus order="currentOrder" />
|
||||
</section>
|
||||
@@ -108,7 +108,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="env.isMobile">
|
||||
<t t-if="ui.isSmall">
|
||||
<div class="switchpane">
|
||||
<button class="btn-switchpane"
|
||||
t-att-class="{ secondary: !(currentOrder.is_paid() and currentOrder._isValidEmptyOrder()) }"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="actionpad">
|
||||
<button class="button set-partner" t-att-class="{'decentered': isLongName}"
|
||||
t-on-click="() => this.pos.selectPartner()">
|
||||
<t t-if="!env.isMobile"><i class="fa fa-user" role="img" aria-label="Customer" title="Customer" /></t>
|
||||
<t t-if="!ui.isSmall"><i class="fa fa-user" role="img" aria-label="Customer" title="Customer" /></t>
|
||||
<t t-if="props.partner">
|
||||
<t t-esc="props.partner.name" />
|
||||
</t>
|
||||
@@ -19,7 +19,7 @@
|
||||
</div>
|
||||
<t t-esc="props.actionName" />
|
||||
</button>
|
||||
<button t-if="env.isMobile" class="button back-button" t-on-click="props.onSwitchPane">
|
||||
<button t-if="ui.isSmall" class="button back-button" t-on-click="props.onSwitchPane">
|
||||
<i class="fa fa-angle-double-left"/>
|
||||
Back
|
||||
</button>
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
<t t-name="ProductScreen" owl="1">
|
||||
<div class="product-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-full-width">
|
||||
<div class="leftpane pane-border" t-if="!env.isMobile || state.mobile_pane === 'left'">
|
||||
<div class="leftpane pane-border" t-if="!ui.isSmall || state.mobile_pane === 'left'">
|
||||
<OrderWidget/>
|
||||
<div class="pads">
|
||||
<div class="control-buttons">
|
||||
<t t-if="env.isMobile and controlButtons.length > 3">
|
||||
<t t-if="ui.isSmall and controlButtons.length > 3">
|
||||
<div class="control-button" t-on-click="_displayAllControlPopup">More...</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
@@ -29,10 +29,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rightpane" t-if="!env.isMobile || state.mobile_pane === 'right'">
|
||||
<div class="rightpane" t-if="!ui.isSmall || state.mobile_pane === 'right'">
|
||||
<ProductsWidget />
|
||||
<MobileOrderWidget
|
||||
t-if="env.isMobile"
|
||||
t-if="ui.isSmall"
|
||||
pane="state.mobile_pane"
|
||||
onSwitchPane.bind="switchPane"/>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@
|
||||
<div class="products-widget-control">
|
||||
<div class="rightpane-header">
|
||||
<div class="search-bar-container sb-product">
|
||||
<span t-if="env.isMobile" class="oe_status oe_icon icon" t-on-click="toggleMobileSearchBar">
|
||||
<span t-if="ui.isSmall" class="oe_status oe_icon icon" t-on-click="toggleMobileSearchBar">
|
||||
<i t-attf-class="fa oi {{state.mobileSearchBarIsShown ? 'oi-arrow-left' : 'fa-search'}}"/>
|
||||
</span>
|
||||
<t t-if="!env.isMobile || state.mobileSearchBarIsShown">
|
||||
<t t-if="!ui.isSmall || state.mobileSearchBarIsShown">
|
||||
<div class="pos-search-bar">
|
||||
<i class="fa fa-search"/>
|
||||
<input t-model="this.pos.globalState.searchProductWord" placeholder="Search Products..." type="text" autofocus="autofocus" t-on-keyup="updateSearch" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="ReceiptScreen" owl="1">
|
||||
<div class="receipt-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content" t-if="!env.isMobile">
|
||||
<div class="top-content" t-if="!ui.isSmall">
|
||||
<div class="top-content-center">
|
||||
<h1>
|
||||
<t t-esc="orderAmountPlusTip" />
|
||||
|
||||
@@ -6,20 +6,20 @@
|
||||
<div class="screen-full-width">
|
||||
<div class="rightpane pane-border">
|
||||
<div class="controls">
|
||||
<t t-if="!env.isMobile || !state.showSearchBar">
|
||||
<t t-if="!ui.isSmall || !state.showSearchBar">
|
||||
<div class="buttons">
|
||||
<button class="discard" t-on-click="() => this.onCloseScreen()">
|
||||
<span class="search-icon">
|
||||
<i class="fa fa-angle-double-left"/>
|
||||
</span>
|
||||
<t t-if="!env.isMobile">
|
||||
<t t-if="!ui.isSmall">
|
||||
Back
|
||||
</t>
|
||||
</button>
|
||||
<button t-if="allowNewOrders" class="highlight" t-on-click="() => this.onCreateNewOrder()">New Order</button>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="env.isMobile">
|
||||
<t t-if="ui.isSmall">
|
||||
<t t-if="state.showSearchBar">
|
||||
<button class="arrow-left" t-on-click="() => { state.showSearchBar = !state.showSearchBar }">
|
||||
<span class="search-icon">
|
||||
@@ -58,7 +58,7 @@
|
||||
<div class="orders">
|
||||
<t t-set="_filteredOrderList" t-value="getFilteredOrderList()" />
|
||||
<t t-if="_filteredOrderList.length !== 0">
|
||||
<div class="header-row" t-att-class="{ oe_hidden: env.isMobile }">
|
||||
<div class="header-row" t-att-class="{ oe_hidden: ui.isSmall }">
|
||||
<div class="col wide">Date</div>
|
||||
<div class="col wide">Receipt Number</div>
|
||||
<div class="col">Customer</div>
|
||||
@@ -72,30 +72,30 @@
|
||||
<div class="order-row" t-att-class="{ highlight: isHighlighted(order) }" t-on-click="() => this.onClickOrder(order)">
|
||||
<div class="col wide">
|
||||
<div><t t-esc="getDate(order)"></t></div>
|
||||
<div t-if="env.isMobile"><t t-esc="getTotal(order)"></t></div>
|
||||
<div t-if="ui.isSmall"><t t-esc="getTotal(order)"></t></div>
|
||||
</div>
|
||||
<div class="col wide">
|
||||
<div><t t-esc="order.name"></t></div>
|
||||
<div t-if="env.isMobile"><t t-esc="getStatus(order)"></t></div>
|
||||
<div t-if="ui.isSmall"><t t-esc="getStatus(order)"></t></div>
|
||||
</div>
|
||||
<div class="col" t-if="!env.isMobile">
|
||||
<div class="col" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getPartner(order)"></t></div>
|
||||
</div>
|
||||
<div t-if="showCardholderName() && !env.isMobile" class="col">
|
||||
<div t-if="showCardholderName() and !ui.isSmall" class="col">
|
||||
<div><t t-esc="getCardholderName(order)"></t></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div t-if="env.isMobile"><t t-esc="getPartner(order)"></t></div>
|
||||
<div t-att-class = "env.isMobile ? 'cashier':''"><t t-esc="getCashier(order)"></t></div>
|
||||
<div t-if="ui.isSmall"><t t-esc="getPartner(order)"></t></div>
|
||||
<div t-att-class = "ui.isSmall ? 'cashier':''"><t t-esc="getCashier(order)"></t></div>
|
||||
</div>
|
||||
<div class="col end" t-if="!env.isMobile">
|
||||
<div class="col end" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getTotal(order)"></t></div>
|
||||
</div>
|
||||
<div class="col narrow" t-if="!env.isMobile">
|
||||
<div class="col narrow" t-if="!ui.isSmall">
|
||||
<div><t t-esc="getStatus(order)"></t></div>
|
||||
</div>
|
||||
<div t-if="!shouldHideDeleteButton(order)" class="col very-narrow delete-button" name="delete" t-on-click.stop="() => this.onDeleteOrder(order)">
|
||||
<i class="fa fa-trash" aria-hidden="true"/><t t-if="env.isMobile"> Delete</t>
|
||||
<i class="fa fa-trash" aria-hidden="true"/><t t-if="ui.isSmall"> Delete</t>
|
||||
</div>
|
||||
<div t-else="" class="col very-narrow"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component, useExternalListener } from "@odoo/owl";
|
||||
import { Component, useExternalListener, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class EditBar extends Component {
|
||||
static template = "pos_restaurant.EditBar";
|
||||
@@ -24,6 +25,7 @@ export class EditBar extends Component {
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
this.ui = useState(useService("ui"));
|
||||
useExternalListener(window, "click", this.onOutsideClick);
|
||||
}
|
||||
|
||||
@@ -34,12 +36,12 @@ export class EditBar extends Component {
|
||||
}
|
||||
|
||||
getSelectedTablesShape() {
|
||||
let shape = 'round';
|
||||
let shape = "round";
|
||||
this.props.selectedTables.forEach((table) => {
|
||||
if (table.shape == 'square') {
|
||||
shape = 'square';
|
||||
if (table.shape == "square") {
|
||||
shape = "square";
|
||||
}
|
||||
});
|
||||
return shape;
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="pos_restaurant.EditBar" owl="1">
|
||||
<div class="edit-bar-top">
|
||||
<span class="edit-button first-button" t-if="!env.isMobile"></span>
|
||||
<span class="edit-button first-button" t-if="!ui.isSmall"></span>
|
||||
<span class="edit-button" t-on-click.stop="props.createTable">
|
||||
<i class="fa fa-plus icon-button" role="img" aria-label="Add" title="Add"></i>
|
||||
<span class="text-button">ADD</span>
|
||||
|
||||
@@ -36,13 +36,8 @@ export class FloorScreen extends Component {
|
||||
floorMapScrollTop: 0,
|
||||
isColorPicker: false,
|
||||
});
|
||||
if (!this.pos.globalState.floorPlanStyle) {
|
||||
if (this.env.isMobile) {
|
||||
this.pos.globalState.floorPlanStyle = "kanban";
|
||||
} else {
|
||||
this.pos.globalState.floorPlanStyle = "default";
|
||||
}
|
||||
}
|
||||
const ui = useState(useService("ui"));
|
||||
this.pos.globalState.floorPlanStyle ||= ui.isSmall ? "kanban" : "default";
|
||||
this.floorMapRef = useRef("floor-map-ref");
|
||||
this.addFloorRef = useRef("add-floor-ref");
|
||||
this.map = useRef("map");
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class BackToFloorButton extends Component {
|
||||
static template = "BackToFloorButton";
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
get table() {
|
||||
return this.pos.globalState.table;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
t-on-click="backToFloorScreen"
|
||||
>
|
||||
<i class="fa fa-angle-double-left" role="img" aria-label="Back to floor" title="Back to floor" />
|
||||
<t t-if="env.isMobile">
|
||||
<t t-if="ui.isSmall">
|
||||
<span class="table-name" t-esc="table.name"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
<xpath expr="//div[hasclass('order-row')]//div[@name='delete']" position="before">
|
||||
<div t-if="pos.globalState.config.module_pos_restaurant" class="col" name="table">
|
||||
<t t-if="order.tableId">
|
||||
<div t-if="env.isMobile">Table</div>
|
||||
<div t-if="ui.isSmall">Table</div>
|
||||
<div><t t-esc="getTable(order)"></t></div>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="_state.ui.filter == 'TIPPING'" class="col end narrow" name="tip">
|
||||
<div t-if="env.isMobile">Tip</div>
|
||||
<div t-if="ui.isSmall">Tip</div>
|
||||
<div><TipCell order="order" /></div>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { SaleOrderRow } from "./SaleOrderRow";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
/**
|
||||
* @props {models.Order} [initHighlightedOrder] initially highligted order
|
||||
@@ -12,7 +13,7 @@ export class SaleOrderList extends Component {
|
||||
static template = "SaleOrderList";
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.state = useState({ highlightedOrder: this.props.initHighlightedOrder || null });
|
||||
}
|
||||
get highlightedOrder() {
|
||||
|
||||
@@ -25,6 +25,7 @@ export class SaleOrderManagementControlPanel extends Component {
|
||||
|
||||
setup() {
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.saleOrderFetcher = useService("sale_order_fetcher");
|
||||
this.orderManagementContext = useState(orderManagement);
|
||||
useAutofocus();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module */
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
/**
|
||||
* @props {models.Order} order
|
||||
@@ -9,6 +10,9 @@ import { Component } from "@odoo/owl";
|
||||
export class SaleOrderRow extends Component {
|
||||
static template = "SaleOrderRow";
|
||||
|
||||
setup() {
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
get order() {
|
||||
return this.props.order;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
export class SetSaleOrderButton extends Component {
|
||||
static template = "SetSaleOrderButton";
|
||||
@@ -10,13 +10,14 @@ export class SetSaleOrderButton extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.ui = useState(useService("ui"));
|
||||
this.orm = useService("orm");
|
||||
}
|
||||
async click() {
|
||||
// FIXME POSREF why are we calling browse for a ping?
|
||||
// Why don't we let the order management screen deal with the offline error?
|
||||
await this.orm.call("sale.order", "browse", [[]]);
|
||||
const screen = this.env.isMobile
|
||||
const screen = this.ui.isSmall
|
||||
? "MobileSaleOrderManagementScreen"
|
||||
: "SaleOrderManagementScreen";
|
||||
this.pos.showScreen(screen);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="SaleOrderList" owl="1">
|
||||
<div class="orders">
|
||||
<div class="header-row" t-att-class="{ oe_hidden: env.isMobile }">
|
||||
<div class="header-row" t-att-class="{ oe_hidden: ui.isSmall }">
|
||||
<div class="col name">Order</div>
|
||||
<div class="col date">Date</div>
|
||||
<div class="col customer">Customer</div>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<div class="control-panel">
|
||||
<div class="item button back" t-on-click="() => this.props.close()">
|
||||
<i class="fa fa-angle-double-left"></i>
|
||||
<span t-if="!env.isMobile"> Back</span>
|
||||
<span t-if="!ui.isSmall"> Back</span>
|
||||
</div>
|
||||
<div class="item search-box">
|
||||
<span class="icon">
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
t-att-class="{ highlight: highlighted }"
|
||||
t-on-click="() => this.props.onClickSaleOrder(props.order)">
|
||||
<div class="col name">
|
||||
<div t-if="env.isMobile">Order</div>
|
||||
<div t-if="ui.isSmall">Order</div>
|
||||
<div><t t-esc="name"/></div>
|
||||
</div>
|
||||
<div class="col date">
|
||||
<div t-if="env.isMobile">Date</div>
|
||||
<div t-if="ui.isSmall">Date</div>
|
||||
<div><t t-esc="date"/></div>
|
||||
</div>
|
||||
<div class="col partner">
|
||||
<div t-if="env.isMobile">Customer</div>
|
||||
<div t-if="ui.isSmall">Customer</div>
|
||||
<div><t t-esc="partner"/></div>
|
||||
</div>
|
||||
<div class="col salesman">
|
||||
<div t-if="env.isMobile">Salesman</div>
|
||||
<div t-if="ui.isSmall">Salesman</div>
|
||||
<div><t t-esc="salesman"/></div>
|
||||
</div>
|
||||
<div class="col end total">
|
||||
<div t-if="env.isMobile">Total</div>
|
||||
<div t-if="ui.isSmall">Total</div>
|
||||
<div class="flex-container">
|
||||
<div class="self-end">
|
||||
<t t-esc="total"/>
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col state">
|
||||
<div t-if="env.isMobile">State</div>
|
||||
<div t-if="ui.isSmall">State</div>
|
||||
<div><t t-esc="state"/></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { debounce } from "@web/core/utils/timing";
|
||||
import { throttleForAnimation } from "@web/core/utils/timing";
|
||||
import { BlockUI } from "./block_ui";
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { getTabableElements } from "@web/core/utils/ui";
|
||||
import { getActiveHotkey } from "../hotkeys/hotkey_service";
|
||||
|
||||
import { EventBus, useEffect, useRef } from "@odoo/owl";
|
||||
import { EventBus, reactive, useEffect, useRef } from "@odoo/owl";
|
||||
|
||||
export const SIZES = { XS: 0, VSM: 1, SM: 2, MD: 3, LG: 4, XL: 5, XXL: 6 };
|
||||
|
||||
@@ -173,7 +173,7 @@ export const uiService = {
|
||||
}
|
||||
}
|
||||
|
||||
const ui = {
|
||||
const ui = reactive({
|
||||
bus,
|
||||
size: utils.getSize(),
|
||||
get activeElement() {
|
||||
@@ -182,25 +182,24 @@ export const uiService = {
|
||||
get isBlocked() {
|
||||
return blockCount > 0;
|
||||
},
|
||||
get isSmall() {
|
||||
return utils.isSmall(ui);
|
||||
},
|
||||
isSmall: utils.isSmall(),
|
||||
block,
|
||||
unblock,
|
||||
activateElement,
|
||||
deactivateElement,
|
||||
getActiveElementOf,
|
||||
};
|
||||
});
|
||||
|
||||
// listen to media query status changes
|
||||
const updateSize = () => {
|
||||
const prevSize = ui.size;
|
||||
ui.size = utils.getSize();
|
||||
if (ui.size !== prevSize) {
|
||||
ui.isSmall = utils.isSmall(ui);
|
||||
bus.trigger("resize");
|
||||
}
|
||||
};
|
||||
browser.addEventListener("resize", debounce(updateSize, 100));
|
||||
browser.addEventListener("resize", throttleForAnimation(updateSize));
|
||||
|
||||
Object.defineProperty(env, "isSmall", {
|
||||
get() {
|
||||
|
||||
Reference in New Issue
Block a user