From 1cec4e0888e9ce5697f529d45dc2f95cf706e344 Mon Sep 17 00:00:00 2001 From: Bruno Boi Date: Thu, 3 Jun 2021 08:19:24 +0000 Subject: [PATCH] [IMP] web: allow user to select multiple company Before this commit: when user selects company from company switcher, page is reloaded, what if user wants to select multiple companies from dropdown, he have to wait for page reload and need to do same process again. After this commit: when user selects company from company switcher, page will not reloaded as soon as user toggles checkbox, user will given time to select another item or unselect other item from dropdown, so user can select multiple companies or unselect multiple companies. task-2467747 closes odoo-dev/odoo#875 Related: odoo-dev/enterprise#148 Signed-off-by: Aaron Bohy (aab) --- addons/web/static/src/core/utils/arrays.js | 15 + .../static/src/webclient/company_service.js | 28 +- .../switch_company_menu.js | 25 +- .../switch_company_menu.xml | 6 +- .../web/static/tests/helpers/mock_services.js | 13 +- addons/web/static/tests/helpers/utils.js | 8 +- .../webclient/switch_company_menu_tests.js | 293 +++++++++++++----- 7 files changed, 271 insertions(+), 117 deletions(-) diff --git a/addons/web/static/src/core/utils/arrays.js b/addons/web/static/src/core/utils/arrays.js index 2937135c632..79d1d8a9fed 100644 --- a/addons/web/static/src/core/utils/arrays.js +++ b/addons/web/static/src/core/utils/arrays.js @@ -77,3 +77,18 @@ export function sortBy(array, criterion, order = "asc") { return order === "asc" ? result : -result; }); } + +/** + * Returns an array containing all the elements of arrayA + * that are not in arrayB and vice-versa. + * + * @param {any[]} arrayA + * @param {any[]} arrayB + * @returns an array containing all the elements of arrayA + * that are not in arrayB and vice-versa. + */ +export function symmetricalDifference(arrayA, arrayB) { + return arrayA + .filter((id) => !arrayB.includes(id)) + .concat(arrayB.filter((id) => !arrayA.includes(id))); +} diff --git a/addons/web/static/src/webclient/company_service.js b/addons/web/static/src/webclient/company_service.js index ff940bc4326..5167c65e85f 100644 --- a/addons/web/static/src/webclient/company_service.js +++ b/addons/web/static/src/webclient/company_service.js @@ -2,6 +2,7 @@ import { browser } from "@web/core/browser/browser"; import { registry } from "@web/core/registry"; +import { symmetricalDifference } from "../core/utils/arrays"; function parseCompanyIds(cidsFromHash) { const cids = []; @@ -53,32 +54,29 @@ export const companyService = { get currentCompany() { return availableCompanies[allowedCompanyIds[0]]; }, - setCompanies(mode, companyId) { + setCompanies(mode, ...companyIds) { // compute next company ids - let nextCompanyIds = allowedCompanyIds.slice(); + let nextCompanyIds; if (mode === "toggle") { - if (nextCompanyIds.includes(companyId)) { - nextCompanyIds = nextCompanyIds.filter((id) => id !== companyId); - } else { - nextCompanyIds.push(companyId); - } + nextCompanyIds = symmetricalDifference(allowedCompanyIds, companyIds); } else if (mode === "loginto") { - if (nextCompanyIds.length === 1) { + const companyId = companyIds[0]; + if (allowedCompanyIds.length === 1) { // 1 enabled company: stay in single company mode nextCompanyIds = [companyId]; } else { // multi company mode - if (nextCompanyIds.includes(companyId)) { - nextCompanyIds = nextCompanyIds.filter((id) => id !== companyId); - } - nextCompanyIds.unshift(companyId); + nextCompanyIds = [ + companyId, + ...allowedCompanyIds.filter((id) => id !== companyId), + ]; } } - allowedCompanyIds = nextCompanyIds.length ? nextCompanyIds : [companyId]; + nextCompanyIds = nextCompanyIds.length ? nextCompanyIds : [companyIds[0]]; // apply them - router.pushState({ cids: allowedCompanyIds }, { lock: true }); - cookie.setCookie("cids", allowedCompanyIds); + router.pushState({ cids: nextCompanyIds }, { lock: true }); + cookie.setCookie("cids", nextCompanyIds); browser.setTimeout(() => browser.location.reload()); // history.pushState is a little async }, }; diff --git a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js index 62a4f097f2d..4a8ebc5d1f0 100644 --- a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js +++ b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js @@ -2,8 +2,13 @@ import { useService } from "../../core/service_hook"; import { registry } from "../../core/registry"; +import { browser } from "../../core/browser/browser"; +import { symmetricalDifference } from "../../core/utils/arrays"; -export class SwitchCompanyMenu extends owl.Component { +const { Component, hooks } = owl; +const { useState } = hooks; + +export class SwitchCompanyMenu extends Component { static isDisplayed(env) { const { availableCompanies } = env.services.company; return Object.keys(availableCompanies).length > 1 && !env.isSmall; @@ -12,16 +17,32 @@ export class SwitchCompanyMenu extends owl.Component { setup() { this.companyService = useService("company"); this.currentCompany = this.companyService.currentCompany; + this.state = useState({ companiesToToggle: [] }); } toggleCompany(companyId) { - this.companyService.setCompanies("toggle", companyId); + this.state.companiesToToggle = symmetricalDifference(this.state.companiesToToggle, [ + companyId, + ]); + browser.clearTimeout(this.toggleTimer); + this.toggleTimer = browser.setTimeout(() => { + this.companyService.setCompanies("toggle", ...this.state.companiesToToggle); + }, this.constructor.toggleDelay); } logIntoCompany(companyId) { + browser.clearTimeout(this.toggleTimer); this.companyService.setCompanies("loginto", companyId); } + + get selectedCompanies() { + return symmetricalDifference( + this.companyService.allowedCompanyIds, + this.state.companiesToToggle + ); + } } SwitchCompanyMenu.template = "web.SwitchCompanyMenu"; +SwitchCompanyMenu.toggleDelay = 1000; registry.category("systray").add("SwitchCompanyMenu", SwitchCompanyMenu, { sequence: 1 }); diff --git a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.xml b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.xml index 2a5b08afd1e..d64a8bcf07a 100644 --- a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.xml +++ b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.xml @@ -19,7 +19,7 @@
- +