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/datepicker.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/datepicker.js')
| -rw-r--r-- | addons/web/static/src/js/components/datepicker.js | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/addons/web/static/src/js/components/datepicker.js b/addons/web/static/src/js/components/datepicker.js new file mode 100644 index 00000000000..715e594e077 --- /dev/null +++ b/addons/web/static/src/js/components/datepicker.js @@ -0,0 +1,244 @@ +odoo.define('web.DatePickerOwl', function (require) { + "use strict"; + + const field_utils = require('web.field_utils'); + const time = require('web.time'); + const { useAutofocus } = require('web.custom_hooks'); + + const { Component, hooks } = owl; + const { useExternalListener, useRef, useState } = hooks; + + let datePickerId = 0; + + /** + * Date picker + * + * This component exposes the API of the tempusdominus datepicker library. + * As such, its template is a simple input that will open the TD datepicker + * when clicked on. The component will also synchronize any user-input value + * with the library widget and vice-vera. + * + * For further details regarding the implementation of the picker itself, please + * refer to the official tempusdominus documentation (note: all props given + * to this component will be passed as arguments to instantiate the picker widget). + * @extends Component + */ + class DatePicker extends Component { + constructor() { + super(...arguments); + + this.inputRef = useRef('input'); + this.state = useState({ warning: false }); + + this.datePickerId = `o_datepicker_${datePickerId++}`; + this.typeOfDate = 'date'; + + useAutofocus(); + useExternalListener(window, 'scroll', this._onWindowScroll); + } + + mounted() { + $(this.el).on('show.datetimepicker', this._onDateTimePickerShow.bind(this)); + $(this.el).on('hide.datetimepicker', this._onDateTimePickerHide.bind(this)); + $(this.el).on('error.datetimepicker', () => false); + + this._datetimepicker(this.props); + this.inputRef.el.value = this._formatDate(this.props.date); + } + + willUnmount() { + this._datetimepicker('destroy'); + } + + willUpdateProps(nextProps) { + if (nextProps.date) { + this._datetimepicker('date', nextProps.date); + this.inputRef.el.value = this._formatDate(nextProps.date); + } + } + + //--------------------------------------------------------------------- + // Private + //--------------------------------------------------------------------- + + /** + * Handle bootstrap datetimepicker calls. + * @private + * @param {...any} args anything that will be passed to the datetimepicker function. + */ + _datetimepicker(...args) { + $(this.el).datetimepicker(...args); + } + + /** + * @private + * @param {moment} date + * @returns {string} + */ + _formatDate(date) { + try { + return field_utils.format[this.typeOfDate](date, null, { timezone: false }); + } catch (err) { + return false; + } + } + + /** + * @private + * @param {string|false} value + * @returns {moment} + */ + _parseInput(inputValue) { + try { + return field_utils.parse[this.typeOfDate](inputValue, null, { timezone: false }); + } catch (err) { + return false; + } + } + + //--------------------------------------------------------------------- + // Handlers + //--------------------------------------------------------------------- + + /** + * Reacts to the datetimepicker being hidden + * Used to unbind the scroll event from the datetimepicker + * @private + */ + _onDateTimePickerHide() { + const date = this._parseInput(this.inputRef.el.value); + this.state.warning = date.format('YYYY-MM-DD') > moment().format('YYYY-MM-DD'); + this.trigger('datetime-changed', { date }); + } + + /** + * Reacts to the datetimepicker being shown + * Could set/verify our widget value + * And subsequently update the datetimepicker + * @private + */ + _onDateTimePickerShow() { + this.inputRef.el.select(); + } + + /** + * @private + */ + _onInputClick() { + this._datetimepicker('toggle'); + } + + /** + * @private + */ + _onInputChange() { + const date = this._parseInput(this.inputRef.el.value); + if (date) { + this.state.warning = date.format('YYYY-MM-DD') > moment().format('YYYY-MM-DD'); + this.trigger('datetime-changed', { date }); + } else { + this.inputRef.el.value = this._formatDate(this.props.date); + } + } + + /** + * @private + */ + _onWindowScroll(ev) { + if (ev.target !== this.inputRef.el) { + this._datetimepicker('hide'); + } + } + } + + DatePicker.defaultProps = { + calendarWeeks: true, + format: time.getLangDateFormat(), + icons: { + clear: 'fa fa-delete', + close: 'fa fa-check primary', + date: 'fa fa-calendar', + down: 'fa fa-chevron-down', + next: 'fa fa-chevron-right', + previous: 'fa fa-chevron-left', + time: 'fa fa-clock-o', + today: 'fa fa-calendar-check-o', + up: 'fa fa-chevron-up', + }, + locale: moment.locale(), + maxDate: moment({ y: 9999, M: 11, d: 31 }), + minDate: moment({ y: 1900 }), + useCurrent: false, + widgetParent: 'body', + }; + DatePicker.props = { + // Actual date value + date: moment, + // Other props + buttons: { + type: Object, + shape: { + showClear: Boolean, + showClose: Boolean, + showToday: Boolean, + }, + optional: 1, + }, + calendarWeeks: Boolean, + format: String, + icons: { + type: Object, + shape: { + clear: String, + close: String, + date: String, + down: String, + next: String, + previous: String, + time: String, + today: String, + up: String, + }, + }, + keyBinds: { validate: kb => typeof kb === 'object' || kb === null, optional: 1 }, + locale: String, + maxDate: moment, + minDate: moment, + readonly: { type: Boolean, optional: 1 }, + useCurrent: Boolean, + widgetParent: String, + }; + DatePicker.template = 'web.DatePicker'; + + /** + * Date/time picker + * + * Similar to the DatePicker component, adding the handling of more specific + * time values: hour-minute-second. + * + * Once again, refer to the tempusdominus documentation for implementation + * details. + * @extends DatePicker + */ + class DateTimePicker extends DatePicker { + constructor() { + super(...arguments); + + this.typeOfDate = 'datetime'; + } + } + + DateTimePicker.defaultProps = Object.assign({}, DatePicker.defaultProps, { + buttons: { + showClear: false, + showClose: true, + showToday: false, + }, + format: time.getLangDatetimeFormat(), + }); + + return { + DatePicker, + DateTimePicker, + }; +}); |
