hunk.code_window:         this.el = document.createElement('div');
           this.el.className = 'oe-commandbar-wrapper';
           this.el.style.display = 'none';
           this.el.style.width = `${this.options.width}px`;
           document.body.append(this.el);
           this.addHotKey('/', { commands: this.options.commands });
  
hunk.labels: keep keep keep keep replace keep keep keep keep
hunk.after_edit:         if (this.options.width !== undefined) {
               this.el.style.width = `${this.options.width}px`;
           }
  
hunk.file_path: addons/web_editor/static/lib/odoo-editor/src/powerbox/Powerbox.js
hunk.type: replace
file: /** @odoo-module **/
  
  import { dialogService } from "@web/core/dialog/dialog_service";
  import { notificationService } from "@web/core/notifications/notification_service";
  import { ormService } from "@web/core/orm_service";
  import { popoverService } from "@web/core/popover/popover_service";
  import { registry } from "@web/core/registry";
  import { legacyServiceProvider } from "@web/legacy/legacy_service_provider";
  import {
      makeLegacyNotificationService,
      mapLegacyEnvToWowlEnv,
      makeLegacySessionService,
  } from "@web/legacy/utils";
  import { makeLegacyActionManagerService } from "@web/legacy/backend_utils";
  import { viewService } from "@web/views/view_service";
  import { actionService } from "@web/webclient/actions/action_service";
  import { effectService } from "@web/core/effects/effect_service";
  import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
  import { menuService } from "@web/webclient/menus/menu_service";
  import { WebClient } from "@web/webclient/webclient";
  // This import is needed because of it's sideeffects, for exemple :
  // web.test_utils easyload xml templates at line : 124:130.
  // Also it set the autocomplete delay time for the field Many2One at 0 for the tests at line : 132:137
  import "web.test_legacy";
  import AbstractService from "web.AbstractService";
  import ActionMenus from "web.ActionMenus";
  import basicFields from "web.basic_fields";
  import Registry from "web.Registry";
  import core from "web.core";
  import makeTestEnvironment from "web.test_env";
  import { registerCleanup } from "../helpers/cleanup";
  import { makeTestEnv } from "../helpers/mock_env";
  import {
      fakeTitleService,
      makeFakeLocalizationService,
      makeFakeRouterService,
      makeFakeHTTPService,
  } from "../helpers/mock_services";
  import {
      getFixture,
      legacyExtraNextTick,
      mount,
      nextTick,
      patchWithCleanup,
  } from "../helpers/utils";
  import session from "web.session";
  import LegacyMockServer from "web.MockServer";
  import Widget from "web.Widget";
  import { userService } from "@web/core/user_service";
  import { uiService } from "@web/core/ui/ui_service";
  import { ClientActionAdapter, ViewAdapter } from "@web/legacy/action_adapters";
  import { commandService } from "@web/core/commands/command_service";
  import { CustomFavoriteItem } from "@web/search/favorite_menu/custom_favorite_item";
  import { standaloneAdapter } from "web.OwlCompatibility";
  
  const { Component, onMounted, xml } = owl;
  
  const actionRegistry = registry.category("actions");
  const serviceRegistry = registry.category("services");
  const favoriteMenuRegistry = registry.category("favoriteMenu");
  
  /**
   * Builds the required registries for tests using a WebClient.
   * We use a default version of each required registry item.
   * If the registry already contains one of those items,
   * the existing one is kept (it means it has been added in the test
   * directly, e.g. to have a custom version of the item).
   */
  export function setupWebClientRegistries() {
      const favoriveMenuItems = {
          "custom-favorite-item": {
              value: { Component: CustomFavoriteItem, groupNumber: 3 },
              options: { sequence: 0 },
          },
      };
      for (let [key, { value, options }] of Object.entries(favoriveMenuItems)) {
          if (!favoriteMenuRegistry.contains(key)) {
              favoriteMenuRegistry.add(key, value, options);
          }
      }
      const services = {
          action: () => actionService,
          command: () => commandService,
          dialog: () => dialogService,
          effect: () => effectService,
          hotkey: () => hotkeyService,
          http: () => makeFakeHTTPService(),
          legacy_service_provider: () => legacyServiceProvider,
          localization: () => makeFakeLocalizationService(),
          menu: () => menuService,
          notification: () => notificationService,
          orm: () => ormService,
          popover: () => popoverService,
          router: () => makeFakeRouterService(),
          title: () => fakeTitleService,
          ui: () => uiService,
          user: () => userService,
          view: () => viewService,
      };
      for (let serviceName in services) {
          if (!serviceRegistry.contains(serviceName)) {
              serviceRegistry.add(serviceName, services[serviceName]());
          }
      }
  }
  
  /**
   * Remove this as soon as we drop the legacy support
   */
  export function addLegacyMockEnvironment(env, legacyParams = {}) {
      // setup a legacy env
      const dataManager = Object.assign(
          {
              load_action: (actionID, context) => {
                  return env.services.rpc("/web/action/load", {
                      action_id: actionID,
                      additional_context: context,
                  });
              },
              load_views: async (params, options) => {
                  const result = await env.services.rpc(`/web/dataset/call_kw/${params.model}`, {
                      args: [],
                      kwargs: {
                          context: params.context,
                          options: options,
                          views: params.views_descr,
                      },
                      method: "load_views",
                      model: params.model,
                  });
                  const views = result.fields_views;
                  for (const [, viewType] of params.views_descr) {
                      const fvg = views[viewType];
                      fvg.viewFields = fvg.fields;
                      fvg.fields = result.fields;
                  }
                  if (params.favoriteFilters && "search" in views) {
                      views.search.favoriteFilters = params.favoriteFilters;
                  }
                  return views;
              },
              load_filters: (params) => {
                  if (QUnit.config.debug) {
                      console.log("[mock] load_filters", params);
                  }
                  return Promise.resolve([]);
              },
          },
          legacyParams.dataManager
      );
  
      // clear the ActionMenus registry to prevent external code from doing unknown rpcs
      const actionMenusRegistry = ActionMenus.registry;
      ActionMenus.registry = new Registry();
      registerCleanup(() => (ActionMenus.registry = actionMenusRegistry));
  
      let localSession;
      if (legacyParams && legacyParams.getTZOffset) {
          patchWithCleanup(session, {
              getTZOffset: legacyParams.getTZOffset,
          });
          localSession = { getTZOffset: legacyParams.getTZOffset };
      }
  
      const baseEnv = { dataManager, bus: core.bus, session: localSession };
      const legacyEnv = makeTestEnvironment(Object.assign(baseEnv, legacyParams.env));
  
      if (legacyParams.serviceRegistry) {
          const legacyServiceMap = core.serviceRegistry.map;
          core.serviceRegistry.map = legacyParams.serviceRegistry.map;
          // notification isn't a deployed service, but it is added by `makeTestEnvironment`.
          // Here, we want full control on the deployed services, so we simply remove it.
          delete legacyEnv.services.notification;
          AbstractService.prototype.deployServices(legacyEnv);
          registerCleanup(() => {
              core.serviceRegistry.map = legacyServiceMap;
          });
      }
  
      Component.env = legacyEnv;
      mapLegacyEnvToWowlEnv(legacyEnv, env);
      function patchLegacySession() {
          const userContext = Object.getOwnPropertyDescriptor(session, "user_context");
          registerCleanup(() => {
              Object.defineProperty(session, "user_context", userContext);
          });
      }
      patchLegacySession();
      serviceRegistry.add("legacy_session", makeLegacySessionService(legacyEnv, session));
      // deploy the legacyActionManagerService (in Wowl env)
      const legacyActionManagerService = makeLegacyActionManagerService(legacyEnv);
      serviceRegistry.add("legacy_action_manager", legacyActionManagerService);
      serviceRegistry.add("legacy_notification", makeLegacyNotificationService(legacyEnv));
      // patch DebouncedField delay
      const debouncedField = basicFields.DebouncedField;
      const initialDebouncedVal = debouncedField.prototype.DEBOUNCE;
      debouncedField.prototype.DEBOUNCE = 0;
      registerCleanup(() => (debouncedField.prototype.DEBOUNCE = initialDebouncedVal));
  
      if (legacyParams.withLegacyMockServer) {
          const adapter = standaloneAdapter({ Component });
          adapter.env = legacyEnv;
          const W = Widget.extend({ do_push_state() {} });
          const widget = new W(adapter);
          const legacyMockServer = new LegacyMockServer(legacyParams.models, { widget });
          const originalRPC = env.services.rpc;
          env.services.rpc = async (...args) => {
              try {
                  return await originalRPC(...args);
              } catch (e) {
                  if (e.message.includes("Unimplemented")) {
                      return legacyMockServer._performRpc(...args);
                  } else {
                      throw e;
                  }
              }
          };
      }
  }
  
  /**
   * This method create a web client instance properly configured.
   *
   * Note that the returned web client will be automatically cleaned up after the
   * end of the test.
   *
   * @param {*} params
   */
  export async function createWebClient(params) {
      setupWebClientRegistries();
  
      // With the compatibility layer, the action manager keeps legacy alive if they
      // are still acessible from the breacrumbs. They are manually destroyed as soon
      // as they are no longer referenced in the stack. This works fine in production,
      // because the webclient is never destroyed. However, at the end of each test,
      // we destroy the webclient and expect every legacy that has been instantiated
      // to be destroyed. We thus need to manually destroy them here.
      const controllers = [];
      patchWithCleanup(ClientActionAdapter.prototype, {
          setup() {
              this._super();
              onMounted(() => {
                  controllers.push(this.widget);
              });
          },
      });
      patchWithCleanup(ViewAdapter.prototype, {
          setup() {
              this._super();
              onMounted(() => {
                  controllers.push(this.widget);
              });
          },
      });
  
      const legacyParams = params.legacyParams;
      params.serverData = params.serverData || {};
      const models = params.serverData.models;
      if (legacyParams && legacyParams.withLegacyMockServer && models) {
          legacyParams.models = Object.assign({}, models);
          // In lagacy, data may not be sole models, but can contain some other variables
          // So we filter them out for our WOWL mockServer
          Object.entries(legacyParams.models).forEach(([k, v]) => {
              if (!(v instanceof Object) || !("fields" in v)) {
                  delete models[k];
              }
          });
      }
  
      const mockRPC = params.mockRPC || undefined;
      const env = await makeTestEnv({
          serverData: params.serverData,
          mockRPC,
      });
      addLegacyMockEnvironment(env, legacyParams);
  
      const WebClientClass = params.WebClientClass || WebClient;
      const target = params && params.target ? params.target : getFixture();
      const wc = await mount(WebClientClass, target, { env });
      registerCleanup(() => {
          for (const controller of controllers) {
              if (!controller.isDestroyed()) {
                  controller.destroy();
              }
          }
      });
      // Wait for visual changes caused by a potential loadState
      await nextTick();
      return wc;
  }
  
  export async function doAction(env, ...args) {
      if (env instanceof Component) {
          env = env.env;
      }
      try {
          await env.services.action.doAction(...args);
      } finally {
          await legacyExtraNextTick();
      }
  }
  
  export async function loadState(env, state) {
      if (env instanceof Component) {
          env = env.env;
      }
      env.bus.trigger("test:hashchange", state);
      // wait the asynchronous hashchange
      // (the event hashchange must be triggered in a nonBlocking stack)
      await nextTick();
      // wait for the regular rendering
      await nextTick();
      // wait for the legacy rendering below owl layer
      await legacyExtraNextTick();
  }
  
  export function getActionManagerServerData() {
      // additional basic client action
      class TestClientAction extends Component {}
      TestClientAction.template = xml`
        <div class="test_client_action">
          ClientAction_<t t-esc="props.action.params?.description"/>
        </div>`;
      actionRegistry.add("__test__client__action__", TestClientAction);
  
      const menus = {
          root: { id: "root", children: [0, 1, 2], name: "root", appID: "root" },
          // id:0 is a hack to not load anything at webClient mount
          0: { id: 0, children: [], name: "UglyHack", appID: 0, xmlid: "menu_0" },
          1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1001, xmlid: "menu_1" },
          2: { id: 2, children: [], name: "App2", appID: 2, actionID: 1002, xmlid: "menu_2" },
      };
      const actionsArray = [
          {
              id: 1,
              xml_id: "action_1",
              name: "Partners Action 1",
              res_model: "partner",
              type: "ir.actions.act_window",
              views: [[1, "kanban"]],
          },
          {
              id: 2,
              xml_id: "action_2",
              type: "ir.actions.server",
          },
          {
              id: 3,
              xml_id: "action_3",
              name: "Partners",
              res_model: "partner",
              type: "ir.actions.act_window",
              views: [
                  [false, "list"],
                  [1, "kanban"],
                  [false, "form"],
              ],
          },
          {
              id: 4,
              xml_id: "action_4",
              name: "Partners Action 4",
              res_model: "partner",
              type: "ir.actions.act_window",
              views: [
                  [1, "kanban"],
                  [2, "list"],
                  [false, "form"],
              ],
          },
          {
              id: 5,
              xml_id: "action_5",
              name: "Create a Partner",
              res_model: "partner",
              target: "new",
              type: "ir.actions.act_window",
              views: [[false, "form"]],
          },
          {
              id: 6,
              xml_id: "action_6",
              name: "Partner",
              res_id: 2,
              res_model: "partner",
              target: "inline",
              type: "ir.actions.act_window",
              views: [[false, "form"]],
          },
          {
              id: 7,
              xml_id: "action_7",
              name: "Some Report",
              report_name: "some_report",
              report_type: "qweb-pdf",
              type: "ir.actions.report",
          },
          {
              id: 8,
              xml_id: "action_8",
              name: "Favorite Ponies",
              res_model: "pony",
              type: "ir.actions.act_window",
              views: [
                  [false, "list"],
                  [false, "form"],
              ],
          },
          {
              id: 9,
              xml_id: "action_9",
              name: "A Client Action",
              tag: "ClientAction",
              type: "ir.actions.client",
          },
          {
              id: 10,
              type: "ir.actions.act_window_close",
          },
          {
              id: 11,
              xml_id: "action_11",
              name: "Another Report",
              report_name: "another_report",
              report_type: "qweb-pdf",
              type: "ir.actions.report",
              close_on_report_download: true,
          },
          {
              id: 12,
              xml_id: "action_12",
              name: "Some HTML Report",
              report_name: "some_report",
              report_type: "qweb-html",
              type: "ir.actions.report",
          },
          {
              id: 24,
              name: "Partner",
              res_id: 2,
              res_model: "partner",
              type: "ir.actions.act_window",
              views: [[666, "form"]],
          },
          {
              id: 25,
              name: "Create a Partner",
              res_model: "partner",
              target: "new",
              type: "ir.actions.act_window",
              views: [[3, "form"]],
          },
          {
              id: 1001,
              tag: "__test__client__action__",
              target: "main",
              type: "ir.actions.client",
              params: { description: "Id 1" },
          },
          {
              id: 1002,
              tag: "__test__client__action__",
              target: "main",
              type: "ir.actions.client",
              params: { description: "Id 2" },
          },
          {
              xmlId: "wowl.client_action",
              id: 1099,
              tag: "__test__client__action__",
              target: "main",
              type: "ir.actions.client",
              params: { description: "xmlId" },
          },
      ];
      const actions = {};
      actionsArray.forEach((act) => {
          actions[act.xmlId || act.id] = act;
      });
      const archs = {
          // kanban views
          "partner,1,kanban":
              '<kanban><templates><t t-name="kanban-box">' +
              '<div class="oe_kanban_global_click"><field name="foo"/></div>' +
              "</t></templates></kanban>",
          // list views
          "partner,false,list": '<tree><field name="foo"/></tree>',
          "partner,2,list": '<tree limit="3"><field name="foo"/></tree>',
          "pony,false,list": '<tree><field name="name"/></tree>',
          // form views
          "partner,false,form":
              "<form>" +
              "<header>" +
              '<button name="object" string="Call method" type="object"/>' +
              '<button name="4" string="Execute action" type="action"/>' +
              "</header>" +
              "<group>" +
              '<field name="display_name"/>' +
              '<field name="foo"/>' +
              "</group>" +
              "</form>",
          "partner,3,form": `
        <form>
        <footer>
        <button class="btn-primary" string="Save" special="save"/>
        </footer>
        </form>`,
          "partner,666,form": `<form>
        <header></header>
        <sheet>
        <div class="oe_button_box" name="button_box" modifiers="{}">
        <button class="oe_stat_button" type="action" name="1" icon="fa-star" context="{'default_partner': active_id}">
        <field string="Partners" name="o2m" widget="statinfo"/>
        </button>
        </div>
        <field name="display_name"/>
        </sheet>
        </form>`,
          "pony,false,form": "<form>" + '<field name="name"/>' + "</form>",
          // search views
          "partner,false,search": '<search><field name="foo" string="Foo"/></search>',
          "partner,4,search":
              "<search>" +
              '<filter name="bar" help="Bar" domain="[(\'bar\', \'=\', 1)]"/>' +
              "</search>",
          "pony,false,search": "<search></search>",
      };
      const models = {
          partner: {
              fields: {
                  id: { string: "Id", type: "integer" },
                  foo: { string: "Foo", type: "char" },
                  bar: { string: "Bar", type: "many2one", relation: "partner" },
                  o2m: {
                      string: "One2Many",
                      type: "one2many",
                      relation: "partner",
                      relation_field: "bar",
                  },
                  m2o: { string: "Many2one", type: "many2one", relation: "partner" },
              },
              records: [
                  { id: 1, display_name: "First record", foo: "yop", bar: 2, o2m: [2, 3], m2o: 3 },
                  {
                      id: 2,
                      display_name: "Second record",
                      foo: "blip",
                      bar: 1,
                      o2m: [1, 4, 5],
                      m2o: 3,
                  },
                  { id: 3, display_name: "Third record", foo: "gnap", bar: 1, o2m: [], m2o: 1 },
                  { id: 4, display_name: "Fourth record", foo: "plop", bar: 2, o2m: [], m2o: 1 },
                  { id: 5, display_name: "Fifth record", foo: "zoup", bar: 2, o2m: [], m2o: 1 },
              ],
          },
          pony: {
              fields: {
                  id: { string: "Id", type: "integer" },
                  name: { string: "Name", type: "char" },
              },
              records: [
                  { id: 4, name: "Twilight Sparkle" },
                  { id: 6, name: "Applejack" },
                  { id: 9, name: "Fluttershy" },
              ],
          },
      };
      return {
          models,
          views: archs,
          actions,
          menus,
      };
  }
  