diff options
| author | Julien Mougenot <jum@odoo.com> | 2020-03-11 09:38:28 +0000 |
|---|---|---|
| committer | Julien Mougenot <jum@odoo.com> | 2020-03-13 14:08:33 +0000 |
| commit | fbf347498f1cc7b74ef373179b7bcae201715c24 (patch) | |
| tree | b8d1eb29ec93b6c2e43dbade712e636d32fe6716 /addons/web/static/src/js/components/dropdown_menu.js | |
| parent | 0a129284e4856b6485c48a194fd86c3ab5c736e7 (diff) | |
[REF] web: Control panel Owl
Refactoring of the control panel with the Owl framework.
The MVC structure of the control panel has been changed to a 'component <-> model'
relationship. As such:
- Removed the old control panel: view/model/controller/renderer
- Created a new Owl Component (ControlPanel)
- Created a new class: the Model (an Owl Store did not fit here) and a newly
designed ControlPanelModel extending it
Refactored all inner subcomponents, including:
- Pager
- ActionMenus (peviously SideBar)
- Filter menu
> Custom filter item
- Group by menu
> Custom group by item
> Removal of groupby_menu_mixin (and refactored graph controller in sibling commit)
- Time range menu
- Favorite menu
> Custom favorite item
> Moved the favorite menu registry to the favorite_menu file
- Search bar
> Removed and splitted auto-completion dropdown logic between the new SearchBar
Component (descriptions) and to the new ControlPanelModel (domains).
The templates (all in web/base.xml) have been adapted to the new standards. Most
of the DOM structure remains unchanged with some occasional improvements (replace
hiding with not rendering, removed pointless wrapper divs, etc.).
Part of task 2196029
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/components/dropdown_menu.js')
| -rw-r--r-- | addons/web/static/src/js/components/dropdown_menu.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/addons/web/static/src/js/components/dropdown_menu.js b/addons/web/static/src/js/components/dropdown_menu.js new file mode 100644 index 00000000000..df7172ae1d4 --- /dev/null +++ b/addons/web/static/src/js/components/dropdown_menu.js @@ -0,0 +1,133 @@ +odoo.define('web.DropdownMenu', function (require) { + "use strict"; + + const DropdownMenuItem = require('web.DropdownMenuItem'); + + const { Component, hooks } = owl; + const { useExternalListener, useRef, useState } = hooks; + + /** + * Dropdown menu + * + * Generic component used to generate a list of interactive items. It uses some + * bootstrap classes but most interactions are handled in here or in the dropdown + * menu item class definition, including some keyboard navigation and escaping + * system (click outside to close the dropdown). + * + * The layout of a dropdown menu is as following: + * > a Button (always rendered) with a `title` and an optional `icon`; + * > a Dropdown (rendered when open) containing a collection of given items. + * These items must be objects and can have two shapes: + * 1. item.Component & item.props > will instantiate the given Component with + * the given props. Any additional key will be useless. + * 2. any other shape > will instantiate a DropdownMenuItem with the item + * object being its props. There is no props validation as this object + * will be passed as-is when `selected` and can contain additional meta-keys + * that will not affect the displayed item. For more information regarding + * the behaviour of these items, @see DropdownMenuItem. + * @extends Component + */ + class DropdownMenu extends Component { + constructor() { + super(...arguments); + + this.dropdownMenu = useRef('dropdown'); + this.state = useState({ open: false }); + + this.symbol = this.env.device.isMobile ? 'fa fa-chevron-right float-right mt4' : false; + + useExternalListener(window, 'click', this._onWindowClick); + useExternalListener(window, 'keydown', this._onWindowKeydown); + } + + //--------------------------------------------------------------------- + // Getters + //--------------------------------------------------------------------- + + /** + * Overriden in case we want to keep the caret style on the button in mobile. + * @returns {boolean} + */ + get displayCaret() { + return !this.env.device.isMobile; + } + + /** + * Meant to be overriden to provide the list of items to display. + * @returns {Object[]} + */ + get items() { + return this.props.items; + } + + /** + * @returns {string} + */ + get title() { + return this.props.title; + } + + //--------------------------------------------------------------------- + // Handlers + //--------------------------------------------------------------------- + + /** + * @private + * @param {KeyboardEvent} ev + */ + _onButtonKeydown(ev) { + switch (ev.key) { + case 'ArrowLeft': + case 'ArrowRight': + case 'ArrowUp': + case 'ArrowDown': + const firstItem = this.el.querySelector('.dropdown-item'); + if (firstItem) { + ev.preventDefault(); + firstItem.focus(); + } + } + } + + /** + * @private + * @param {OwlEvent} ev + */ + _onItemSelected(ev) { } + + /** + * @private + * @param {MouseEvent} ev + */ + _onWindowClick(ev) { + if (this.state.open && !this.el.contains(ev.target)) { + this.state.open = false; + } + } + + /** + * @private + * @param {KeyboardEvent} ev + */ + _onWindowKeydown(ev) { + if (this.state.open && ev.key === 'Escape') { + this.state.open = false; + } + } + } + + DropdownMenu.components = { DropdownMenuItem }; + DropdownMenu.defaultProps = { items: [] }; + DropdownMenu.props = { + icon: { type: String, optional: 1 }, + items: { + type: Array, + element: Object, + optional: 1, + }, + title: { type: String, optional: 1 }, + }; + DropdownMenu.template = 'web.DropdownMenu'; + + return DropdownMenu; +}); |
