[IMP] web: add new date range picker field widget

Adds a new widget to support start & end date or datetime.

closes odoo/odoo#33266

Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
This commit is contained in:
Jigar Patel
2019-07-18 12:13:34 +00:00
committed by Vincent Schippefilt
parent 125dbf0dfd
commit cda93a5c19
11 changed files with 2406 additions and 2 deletions
+6 -2
View File
@@ -232,8 +232,12 @@
<field name="auto_confirm" groups="base.group_no_one"/>
</group>
<group>
<field name="date_begin"/>
<field name="date_end"/>
<label for="date_begin" string="Date"/>
<div class="o_row">
<field name="date_begin" widget="daterange" nolabel="1" class="oe_inline" options="{'related_end_date': 'date_end'}"/>
<i class="fa fa-long-arrow-right mx-2" aria-label="Arrow icon" title="Arrow"/>
<field name="date_end" widget="daterange" nolabel="1" class="oe_inline" options="{'related_start_date': 'date_begin'}"/>
</div>
<field name="date_tz"/>
</group>
<group>
@@ -0,0 +1,38 @@
# Date Range Picker
![Improvely.com](https://i.imgur.com/UTRlaar.png)
This date range picker component creates a dropdown menu from which a user can
select a range of dates. I created it while building the UI for [Improvely](http://www.improvely.com),
which needed a way to select date ranges for reports.
Features include limiting the selectable date range, localizable strings and date formats,
a single date picker mode, a time picker, and predefined date ranges.
## [Documentation and Live Usage Examples](http://www.daterangepicker.com)
## [See It In a Live Application](https://awio.iljmp.com/5/drpdemogh)
## License
The MIT License (MIT)
Copyright (c) 2012-2019 Dan Grossman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,410 @@
.daterangepicker {
position: absolute;
color: inherit;
background-color: #fff;
border-radius: 4px;
border: 1px solid #ddd;
width: 278px;
max-width: none;
padding: 0;
margin-top: 7px;
top: 100px;
left: 20px;
z-index: 3001;
display: none;
font-family: arial;
font-size: 15px;
line-height: 1em;
}
.daterangepicker:before, .daterangepicker:after {
position: absolute;
display: inline-block;
border-bottom-color: rgba(0, 0, 0, 0.2);
content: '';
}
.daterangepicker:before {
top: -7px;
border-right: 7px solid transparent;
border-left: 7px solid transparent;
border-bottom: 7px solid #ccc;
}
.daterangepicker:after {
top: -6px;
border-right: 6px solid transparent;
border-bottom: 6px solid #fff;
border-left: 6px solid transparent;
}
.daterangepicker.opensleft:before {
right: 9px;
}
.daterangepicker.opensleft:after {
right: 10px;
}
.daterangepicker.openscenter:before {
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
}
.daterangepicker.openscenter:after {
left: 0;
right: 0;
width: 0;
margin-left: auto;
margin-right: auto;
}
.daterangepicker.opensright:before {
left: 9px;
}
.daterangepicker.opensright:after {
left: 10px;
}
.daterangepicker.drop-up {
margin-top: -7px;
}
.daterangepicker.drop-up:before {
top: initial;
bottom: -7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.drop-up:after {
top: initial;
bottom: -6px;
border-bottom: initial;
border-top: 6px solid #fff;
}
.daterangepicker.single .daterangepicker .ranges, .daterangepicker.single .drp-calendar {
float: none;
}
.daterangepicker.single .drp-selected {
display: none;
}
.daterangepicker.show-calendar .drp-calendar {
display: block;
}
.daterangepicker.show-calendar .drp-buttons {
display: block;
}
.daterangepicker.auto-apply .drp-buttons {
display: none;
}
.daterangepicker .drp-calendar {
display: none;
max-width: 270px;
}
.daterangepicker .drp-calendar.left {
padding: 8px 0 8px 8px;
}
.daterangepicker .drp-calendar.right {
padding: 8px;
}
.daterangepicker .drp-calendar.single .calendar-table {
border: none;
}
.daterangepicker .calendar-table .next span, .daterangepicker .calendar-table .prev span {
color: #fff;
border: solid black;
border-width: 0 2px 2px 0;
border-radius: 0;
display: inline-block;
padding: 3px;
}
.daterangepicker .calendar-table .next span {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.daterangepicker .calendar-table .prev span {
transform: rotate(135deg);
-webkit-transform: rotate(135deg);
}
.daterangepicker .calendar-table th, .daterangepicker .calendar-table td {
white-space: nowrap;
text-align: center;
vertical-align: middle;
min-width: 32px;
width: 32px;
height: 24px;
line-height: 24px;
font-size: 12px;
border-radius: 4px;
border: 1px solid transparent;
white-space: nowrap;
cursor: pointer;
}
.daterangepicker .calendar-table {
border: 1px solid #fff;
border-radius: 4px;
background-color: #fff;
}
.daterangepicker .calendar-table table {
width: 100%;
margin: 0;
border-spacing: 0;
border-collapse: collapse;
}
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
background-color: #eee;
border-color: transparent;
color: inherit;
}
.daterangepicker td.week, .daterangepicker th.week {
font-size: 80%;
color: #ccc;
}
.daterangepicker td.off, .daterangepicker td.off.in-range, .daterangepicker td.off.start-date, .daterangepicker td.off.end-date {
background-color: #fff;
border-color: transparent;
color: #999;
}
.daterangepicker td.in-range {
background-color: #ebf4f8;
border-color: transparent;
color: #000;
border-radius: 0;
}
.daterangepicker td.start-date {
border-radius: 4px 0 0 4px;
}
.daterangepicker td.end-date {
border-radius: 0 4px 4px 0;
}
.daterangepicker td.start-date.end-date {
border-radius: 4px;
}
.daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #357ebd;
border-color: transparent;
color: #fff;
}
.daterangepicker th.month {
width: auto;
}
.daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999;
cursor: not-allowed;
text-decoration: line-through;
}
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px;
padding: 1px;
height: auto;
margin: 0;
cursor: default;
}
.daterangepicker select.monthselect {
margin-right: 2%;
width: 56%;
}
.daterangepicker select.yearselect {
width: 40%;
}
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 50px;
margin: 0 auto;
background: #eee;
border: 1px solid #eee;
padding: 2px;
outline: 0;
font-size: 12px;
}
.daterangepicker .calendar-time {
text-align: center;
margin: 4px auto 0 auto;
line-height: 30px;
position: relative;
}
.daterangepicker .calendar-time select.disabled {
color: #ccc;
cursor: not-allowed;
}
.daterangepicker .drp-buttons {
clear: both;
text-align: right;
padding: 8px;
border-top: 1px solid #ddd;
display: none;
line-height: 12px;
vertical-align: middle;
}
.daterangepicker .drp-selected {
display: inline-block;
font-size: 12px;
padding-right: 8px;
}
.daterangepicker .drp-buttons .btn {
margin-left: 8px;
font-size: 12px;
font-weight: bold;
padding: 4px 8px;
}
.daterangepicker.show-ranges.single.rtl .drp-calendar.left {
border-right: 1px solid #ddd;
}
.daterangepicker.show-ranges.single.ltr .drp-calendar.left {
border-left: 1px solid #ddd;
}
.daterangepicker.show-ranges.rtl .drp-calendar.right {
border-right: 1px solid #ddd;
}
.daterangepicker.show-ranges.ltr .drp-calendar.left {
border-left: 1px solid #ddd;
}
.daterangepicker .ranges {
float: none;
text-align: left;
margin: 0;
}
.daterangepicker.show-calendar .ranges {
margin-top: 8px;
}
.daterangepicker .ranges ul {
list-style: none;
margin: 0 auto;
padding: 0;
width: 100%;
}
.daterangepicker .ranges li {
font-size: 12px;
padding: 8px 12px;
cursor: pointer;
}
.daterangepicker .ranges li:hover {
background-color: #eee;
}
.daterangepicker .ranges li.active {
background-color: #08c;
color: #fff;
}
/* Larger Screen Styling */
@media (min-width: 564px) {
.daterangepicker {
width: auto;
}
.daterangepicker .ranges ul {
width: 140px;
}
.daterangepicker.single .ranges ul {
width: 100%;
}
.daterangepicker.single .drp-calendar.left {
clear: none;
}
.daterangepicker.single .ranges, .daterangepicker.single .drp-calendar {
float: left;
}
.daterangepicker {
direction: ltr;
text-align: left;
}
.daterangepicker .drp-calendar.left {
clear: left;
margin-right: 0;
}
.daterangepicker .drp-calendar.left .calendar-table {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.daterangepicker .drp-calendar.right {
margin-left: 0;
}
.daterangepicker .drp-calendar.right .calendar-table {
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.daterangepicker .drp-calendar.left .calendar-table {
padding-right: 8px;
}
.daterangepicker .ranges, .daterangepicker .drp-calendar {
float: left;
}
}
@media (min-width: 730px) {
.daterangepicker .ranges {
width: auto;
}
.daterangepicker .ranges {
float: left;
}
.daterangepicker.rtl .ranges {
float: right;
}
.daterangepicker .drp-calendar.left {
clear: none !important;
}
}
File diff suppressed because it is too large Load Diff
@@ -22,6 +22,7 @@ var session = require('web.session');
var utils = require('web.utils');
var view_dialogs = require('web.view_dialogs');
var field_utils = require('web.field_utils');
var time = require('web.time');
require("web.zoomodoo");
@@ -554,6 +555,121 @@ var LinkButton = AbstractField.extend({
},
});
var FieldDateRange = InputField.extend({
className: 'o_field_date_range',
tagName: 'span',
jsLibs: [
'/web/static/lib/daterangepicker/daterangepicker.js',
'/web/static/src/js/libs/daterangepicker.js',
],
cssLibs: [
'/web/static/lib/daterangepicker/daterangepicker.css',
],
supportedFieldTypes: ['date', 'datetime'],
/**
* @override
*/
init: function () {
this._super.apply(this, arguments);
this.isDateField = this.formatType === 'date';
this.dateRangePickerOptions = _.defaults(
{},
this.nodeOptions.picker_options || {},
{
timePicker: !this.isDateField,
timePicker24Hour: _t.database.parameters.time_format.search('%H') !== -1,
autoUpdateInput: false,
timePickerIncrement: 10,
locale: {
format: this.isDateField ? time.getLangDateFormat() : time.getLangDatetimeFormat(),
},
}
);
this.relatedEndDate = this.nodeOptions.related_end_date;
this.relatedStartDate = this.nodeOptions.related_start_date;
},
/**
* @override
*/
destroy: function () {
if (this.$pickerContainer) {
this.$pickerContainer.remove();
}
this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {Event} ev
* @param {Object} picker
*/
_applyChanges: function (ev, picker) {
var changes = {};
var displayStartDate = field_utils.format[this.formatType](picker.startDate, {}, {timezone: false});
var displayEndDate = field_utils.format[this.formatType](picker.endDate, {}, {timezone: false});
var changedStartDate = picker.startDate;
var changedEndDate = picker.endDate;
if (this.isDateField) {
// In date mode, the library will give moment object of start and end date having
// time at 00:00:00. So, Odoo will consider it as UTC. To fix this added browser
// timezone offset in dates to get a correct selected date.
changedStartDate = picker.startDate.add(session.getTZOffset(picker.startDate), 'minutes');
changedEndDate = picker.endDate.startOf('day').add(session.getTZOffset(picker.endDate), 'minutes');
}
if (this.relatedEndDate) {
this.$el.val(displayStartDate);
changes[this.name] = this._parseValue(changedStartDate);
changes[this.relatedEndDate] = this._parseValue(changedEndDate);
}
if (this.relatedStartDate) {
this.$el.val(displayEndDate);
changes[this.name] = this._parseValue(changedEndDate);
changes[this.relatedStartDate] = this._parseValue(changedStartDate);
}
this.trigger_up('field_changed', {
dataPointID: this.dataPointID,
viewType: this.viewType,
changes: changes,
});
},
/**
* @override
*/
_renderEdit: function () {
this._super.apply(this, arguments);
var self = this;
var startDate;
var endDate;
if (this.relatedEndDate) {
startDate = this._formatValue(this.value);
endDate = this._formatValue(this.recordData[this.relatedEndDate]);
}
if (this.relatedStartDate) {
startDate = this._formatValue(this.recordData[this.relatedStartDate]);
endDate = this._formatValue(this.value);
}
this.dateRangePickerOptions.startDate = startDate || moment();
this.dateRangePickerOptions.endDate = endDate || moment();
this.$el.daterangepicker(this.dateRangePickerOptions);
this.$el.on('apply.daterangepicker', this._applyChanges.bind(this));
this.$el.off('keyup.daterangepicker');
this.$pickerContainer = this.$el.data('daterangepicker').container;
// Prevent from leaving the edition of a row in editable list view
this.$pickerContainer.on('click', function (ev) {
ev.stopPropagation();
if ($(ev.target).hasClass('applyBtn')) {
self.$el.data('daterangepicker').hide();
}
});
},
});
var FieldDate = InputField.extend({
description: _lt("Date"),
className: "o_field_date",
@@ -3101,6 +3217,7 @@ return {
LinkButton: LinkButton,
FieldDate: FieldDate,
FieldDateTime: FieldDateTime,
FieldDateRange: FieldDateRange,
FieldDomain: FieldDomain,
FieldFloat: FieldFloat,
FieldFloatTime: FieldFloatTime,
@@ -24,6 +24,7 @@ registry
.add('boolean', basic_fields.FieldBoolean)
.add('date', basic_fields.FieldDate)
.add('datetime', basic_fields.FieldDateTime)
.add('daterange', basic_fields.FieldDateRange)
.add('domain', basic_fields.FieldDomain)
.add('text', basic_fields.FieldText)
.add('list.text', basic_fields.ListFieldText)
@@ -0,0 +1,14 @@
odoo.define('web.daterangepicker.extensions', function () {
'use strict';
/**
* Don't allow user to select off days(Dates which are out of current calendar).
*/
var clickDateFunction = daterangepicker.prototype.clickDate;
daterangepicker.prototype.clickDate = function (ev) {
if (!$(ev.target).hasClass('off')) {
clickDateFunction.apply(this, arguments);
}
};
});
@@ -0,0 +1,69 @@
// Restore date range picker style
.daterangepicker {
.drp-calendar {
.calendar-table {
thead {
tr:first-child {
color: #FFFFFF;
background-color: $o-brand-odoo;
th {
&.prev, &.next {
span {
color: #FFFFFF;
border-color: #FFFFFF;
}
&:hover {
background-color: darken($o-brand-odoo, 10%);
}
}
}
}
tr:last-child {
color: $o-datepicker-week-color;
background-color: $o-datepicker-week-bg-color;
}
th {
border-radius: 0;
}
}
tbody {
tr {
border-bottom: 1px solid $o-datepicker-week-bg-color;
td {
border-width: 0px;
&:not(.off) {
&.in-range {
background-color: gray('200');
}
&.available:hover {
background-color: gray('200');
}
&.active, &.active:hover {
background-color: $o-brand-primary;
}
}
&.off:hover {
background: #FFFFFF;
color: #999;
}
}
}
}
}
.calendar-time {
select {
&.hourselect, &.minuteselect, &.secondselect, &.ampmselect {
display: initial;
-webkit-appearance: menulist-button;
-moz-appearance: menulist-button;
appearance: menulist-button;
}
}
}
}
.drp-buttons {
.drp-selected {
display: none;
}
}
}
@@ -2578,6 +2578,174 @@ QUnit.module('basic_fields', {
});
QUnit.module('FieldDateRange');
QUnit.test('Datetime field', async function (assert) {
assert.expect(19);
this.data.partner.fields.datetime_end = {string: 'Datetime End', type: 'datetime'};
this.data.partner.records[0].datetime_end = '2017-03-13 00:00:00';
var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<field name="datetime" widget="daterange" options="{\'related_end_date\': \'datetime_end\'}"/>' +
'<field name="datetime_end" widget="daterange" options="{\'related_start_date\': \'datetime\'}"/>' +
'</form>',
res_id: 1,
session: {
getTZOffset: function () {
return 330;
},
},
});
// Check date display correctly in readonly
assert.strictEqual(form.$('.o_field_date_range:first').text(), '02/08/2017 15:30:00',
"the start date should be correctly displayed in readonly");
assert.strictEqual(form.$('.o_field_date_range:last').text(), '03/13/2017 05:30:00',
"the end date should be correctly displayed in readonly");
// Edit
await testUtils.form.clickEdit(form);
// Check date range picker initialization
assert.containsN(document.body, '.daterangepicker', 2,
"should initialize 2 date range picker");
assert.strictEqual($('.daterangepicker:first').css('display'), 'block',
"date range picker should be opened initially");
assert.strictEqual($('.daterangepicker:last').css('display'), 'none',
"date range picker should be closed initially");
assert.strictEqual($('.daterangepicker:first .drp-calendar.left .active.start-date').text(), '8',
"active start date should be '8' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.left .hourselect').val(), '15',
"active start date hour should be '15' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.left .minuteselect').val(), '30',
"active start date minute should be '30' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.right .active.end-date').text(), '13',
"active end date should be '13' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.right .hourselect').val(), '5',
"active end date hour should be '5' in date range picker");
assert.strictEqual($('.daterangepicker:first .drp-calendar.right .minuteselect').val(), '30',
"active end date minute should be '30' in date range picker");
// Close picker
await testUtils.dom.click($('.daterangepicker:first .cancelBtn'));
assert.strictEqual($('.daterangepicker:first').css('display'), 'none',
"date range picker should be closed");
// Try to check with end date
await testUtils.dom.click(form.$('.o_field_date_range:last'));
assert.strictEqual($('.daterangepicker:last').css('display'), 'block',
"date range picker should be opened");
assert.strictEqual($('.daterangepicker:last .drp-calendar.left .active.start-date').text(), '8',
"active start date should be '8' in date range picker");
assert.strictEqual($('.daterangepicker:last .drp-calendar.left .hourselect').val(), '15',
"active start date hour should be '15' in date range picker");
assert.strictEqual($('.daterangepicker:last .drp-calendar.left .minuteselect').val(), '30',
"active start date minute should be '30' in date range picker");
assert.strictEqual($('.daterangepicker:last .drp-calendar.right .active.end-date').text(), '13',
"active end date should be '13' in date range picker");
assert.strictEqual($('.daterangepicker:last .drp-calendar.right .hourselect').val(), '5',
"active end date hour should be '5' in date range picker");
assert.strictEqual($('.daterangepicker:last .drp-calendar.right .minuteselect').val(), '30',
"active end date minute should be '30' in date range picker");
form.destroy();
});
QUnit.test('Date field', async function (assert) {
assert.expect(18);
this.data.partner.fields.date_end = {string: 'Date End', type: 'date'};
this.data.partner.records[0].date_end = '2017-02-08';
var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<field name="date" widget="daterange" options="{\'related_end_date\': \'date_end\'}"/>' +
'<field name="date_end" widget="daterange" options="{\'related_start_date\': \'date\'}"/>' +
'</form>',
res_id: 1,
session: {
getTZOffset: function () {
return 330;
},
},
});
// Check date display correctly in readonly
assert.strictEqual(form.$('.o_field_date_range:first').text(), '02/03/2017',
"the start date should be correctly displayed in readonly");
assert.strictEqual(form.$('.o_field_date_range:last').text(), '02/08/2017',
"the end date should be correctly displayed in readonly");
// Edit
await testUtils.form.clickEdit(form);
// Check date range picker initialization
assert.containsN(document.body, '.daterangepicker', 2,
"should initialize 2 date range picker");
assert.strictEqual($('.daterangepicker:first').css('display'), 'block',
"date range picker should be opened initially");
assert.strictEqual($('.daterangepicker:last').css('display'), 'none',
"date range picker should be closed initially");
assert.strictEqual($('.daterangepicker:first .active.start-date').text(), '3',
"active start date should be '3' in date range picker");
assert.strictEqual($('.daterangepicker:first .active.end-date').text(), '8',
"active end date should be '8' in date range picker");
// Change date
await testUtils.dom.triggerMouseEvent($('.daterangepicker:first .drp-calendar.left .available:contains("16")'), 'mousedown');
await testUtils.dom.triggerMouseEvent($('.daterangepicker:first .drp-calendar.right .available:contains("12")'), 'mousedown');
await testUtils.dom.click($('.daterangepicker:first .applyBtn'));
// Check date after change
assert.strictEqual($('.daterangepicker:first').css('display'), 'none',
"date range picker should be closed");
assert.strictEqual(form.$('.o_field_date_range:first').val(), '02/16/2017',
"the date should be '02/16/2017'");
assert.strictEqual(form.$('.o_field_date_range:last').val(), '03/12/2017',
"'the date should be '03/12/2017'");
// Try to change range with end date
await testUtils.dom.click(form.$('.o_field_date_range:last'));
assert.strictEqual($('.daterangepicker:last').css('display'), 'block',
"date range picker should be opened");
assert.strictEqual($('.daterangepicker:last .active.start-date').text(), '16',
"start date should be a 16 in date range picker");
assert.strictEqual($('.daterangepicker:last .active.end-date').text(), '12',
"end date should be a 12 in date range picker");
// Change date
await testUtils.dom.triggerMouseEvent($('.daterangepicker:last .drp-calendar.left .available:contains("13")'), 'mousedown');
await testUtils.dom.triggerMouseEvent($('.daterangepicker:last .drp-calendar.right .available:contains("18")'), 'mousedown');
await testUtils.dom.click($('.daterangepicker:last .applyBtn'));
// Check date after change
assert.strictEqual($('.daterangepicker:last').css('display'), 'none',
"date range picker should be closed");
assert.strictEqual(form.$('.o_field_date_range:first').val(), '02/13/2017',
"the start date should be '02/13/2017'");
assert.strictEqual(form.$('.o_field_date_range:last').val(), '03/18/2017',
"the end date should be '03/18/2017'");
// Save
await testUtils.form.clickSave(form);
// Check date after save
assert.strictEqual(form.$('.o_field_date_range:first').text(), '02/13/2017',
"the start date should be '02/13/2017' after save");
assert.strictEqual(form.$('.o_field_date_range:last').text(), '03/18/2017',
"the end date should be '03/18/2017' after save");
form.destroy();
});
QUnit.module('FieldDate');
QUnit.test('date field: toggle datepicker [REQUIRE FOCUS]', async function (assert) {
+1
View File
@@ -72,6 +72,7 @@
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/animation.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/rainbow.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/datepicker.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/daterangepicker.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/banner.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/colorpicker.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/keyboard.scss"/>
+17
View File
@@ -1651,6 +1651,23 @@ order.
<field name="datetimefield" options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'/>
- daterange (FieldDateRange)
This widget allow user to select start and end date into single picker.
- Supported field types: *date*, *datetime*
Options:
- related_start_date: apply on end date field to get start date value which
is used to display range in the picker.
- related_end_date: apply on start date field to get end date value which
is used to display range in the picker.
- picker_options: extra settings for picker.
.. code-block:: xml
<field name="start_date" widget="daterange" options='{"related_end_date": "end_date"}'/>
- monetary (FieldMonetary)
This is the default field type for fields of type 'monetary'. It is used to
display a currency. If there is a currency fields given in option, it will