Fix date pickers in metering modal
The metering forms were using the date picker functionality from the d3 line chart library, this used to work when it was loaded as a whole page as the d3 libary would run intending to setup any d3 graphs however now it is being loaded as a modal the elements that would be affected by the d3 code do not exist at page load time. In order to get the date picker events to be added to the elements on the form when the modal loads, the JS in the forms template has been extended in this patch to support adding those events. This patch also changes the data attributes on the form elements so that they do not conflict with any d3 line chart elements. Alongside the javascript this patch fixes bug to do with parsing the dates in metering utils and adds UTs to prevent regression. Change-Id: I4e239daa03b2f54e434254bac48ba0cceb037b5d Closes-Bug: 1427756
This commit is contained in:
parent
11fa3ed6bd
commit
0d010f601c
@ -757,13 +757,8 @@ horizon.d3_line_chart = {
|
||||
* connected to charts.
|
||||
*/
|
||||
var bind_datepicker_change = function(settings) {
|
||||
|
||||
$(datepicker_selector).each(function() {
|
||||
var el = $(this);
|
||||
el.datepicker({format: 'yyyy-mm-dd',
|
||||
setDate: new Date(),
|
||||
showButtonPanel: true});
|
||||
});
|
||||
var now = new Date();
|
||||
horizon.datepickers.add(datepicker_selector);
|
||||
delegate_event_and_refresh_charts(datepicker_selector, 'changeDate', settings);
|
||||
};
|
||||
|
||||
|
13
horizon/static/horizon/js/horizon.datepickers.js
Normal file
13
horizon/static/horizon/js/horizon.datepickers.js
Normal file
@ -0,0 +1,13 @@
|
||||
horizon.datepickers = {
|
||||
add: function(selector) {
|
||||
$(selector).each(function () {
|
||||
var el = $(this);
|
||||
el.datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
setDate: new Date(),
|
||||
showButtonPanel: true,
|
||||
language: horizon.datepickerLocale
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
32
horizon/static/horizon/js/horizon.metering.js
Normal file
32
horizon/static/horizon/js/horizon.metering.js
Normal file
@ -0,0 +1,32 @@
|
||||
horizon.metering = {
|
||||
init_create_usage_report_form: function() {
|
||||
horizon.datepickers.add('input[data-date-picker="True"]');
|
||||
horizon.metering.add_change_event_to_period_dropdown();
|
||||
horizon.metering.show_or_hide_date_fields();
|
||||
},
|
||||
init_stats_page: function() {
|
||||
if (typeof horizon.d3_line_chart !== 'undefined') {
|
||||
horizon.d3_line_chart.init("div[data-chart-type='line_chart']",
|
||||
{'auto_resize': true});
|
||||
}
|
||||
horizon.metering.add_change_event_to_period_dropdown();
|
||||
horizon.metering.show_or_hide_date_fields();
|
||||
},
|
||||
show_or_hide_date_fields: function() {
|
||||
$("#date_from .controls input, #date_to .controls input").val('');
|
||||
if ($("#id_period").find("option:selected").val() === "other"){
|
||||
$("#id_date_from, #id_date_to").parent().parent().show();
|
||||
return true;
|
||||
} else {
|
||||
$("#id_date_from, #id_date_to").parent().parent().hide();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
add_change_event_to_period_dropdown: function() {
|
||||
$("#id_period").change(function(evt) {
|
||||
if (horizon.metering.show_or_hide_date_fields()) {
|
||||
evt.stopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@ -76,6 +76,7 @@
|
||||
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.accordion_nav.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.communication.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.datepickers.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.forms.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.formset_table.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.instances.js'></script>
|
||||
@ -92,6 +93,7 @@
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.templates.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.users.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.membership.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.metering.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.networktopology.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.d3piechart.js'></script>
|
||||
<script src='{{ STATIC_URL }}horizon/js/horizon.heattop.js'></script>
|
||||
|
@ -34,12 +34,10 @@ class UsageReportForm(forms.SelfHandlingForm):
|
||||
choices=PERIOD_CHOICES)
|
||||
date_from = forms.DateField(label=_("From"), required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={'data-line-chart-command':
|
||||
'date_picker_change'}))
|
||||
attrs={'data-date-picker': True}))
|
||||
date_to = forms.DateField(label=_("To"), required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={'data-line-chart-command':
|
||||
'date_picker_change'}))
|
||||
attrs={'data-date-picker': True}))
|
||||
|
||||
def clean_date_from(self):
|
||||
period = self.cleaned_data['period']
|
||||
|
@ -27,31 +27,12 @@
|
||||
|
||||
{% block modal-js %}
|
||||
<script type="text/javascript">
|
||||
if (typeof $ !== 'undefined') {
|
||||
show_hide_datepickers();
|
||||
if (typeof horizon.metering !== 'undefined') {
|
||||
horizon.metering.init_create_usage_report_form();
|
||||
} else {
|
||||
addHorizonLoadEvent(function() {
|
||||
show_hide_datepickers();
|
||||
horizon.metering.init_create_usage_report_form();
|
||||
});
|
||||
}
|
||||
|
||||
function show_hide_datepickers() {
|
||||
$("#id_period").change(function(evt) {
|
||||
// Enhancing behaviour of selectbox, on 'other' value selected, I don't
|
||||
// want to refresh, but show hide the date fields
|
||||
if ($(this).find("option:selected").val() === "other"){
|
||||
evt.stopPropagation();
|
||||
$("#date_from .controls input, #date_to .controls input").val('');
|
||||
$("#id_date_from, #id_date_to").parent().parent().show();
|
||||
} else {
|
||||
$("#id_date_from, #id_date_to").parent().parent().hide();
|
||||
}
|
||||
});
|
||||
if ($("#id_period").find("option:selected").val() === "other"){
|
||||
$("#id_date_from, #id_date_to").parent().parent().show();
|
||||
} else {
|
||||
$("#id_date_from, #id_date_to").parent().parent().hide();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -166,35 +166,11 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
if (typeof horizon.d3_line_chart !== 'undefined') {
|
||||
horizon.d3_line_chart.init("div[data-chart-type='line_chart']",
|
||||
{'auto_resize': true});
|
||||
}
|
||||
|
||||
if (typeof $ !== 'undefined') {
|
||||
show_hide_datepickers();
|
||||
horizon.metering.init_stats_page();
|
||||
} else {
|
||||
addHorizonLoadEvent(function() {
|
||||
show_hide_datepickers();
|
||||
horizon.metering.init_stats_page();
|
||||
});
|
||||
}
|
||||
|
||||
function show_hide_datepickers() {
|
||||
$("#date_options").change(function(evt) {
|
||||
// Enhancing behaviour of selectbox, on 'other' value selected, I don't
|
||||
// want to refresh, but show hide the date fields
|
||||
if ($(this).find("option:selected").val() == "other"){
|
||||
evt.stopPropagation();
|
||||
$("#date_from input, #date_to input").val('');
|
||||
$("#date_from, #date_to").show();
|
||||
} else {
|
||||
$("#date_from, #date_to").hide();
|
||||
}
|
||||
});
|
||||
if ($("#date_options").find("option:selected").val() == "other"){
|
||||
$("#date_from, #date_to").show();
|
||||
} else {
|
||||
$("#date_from, #date_to").hide();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -618,6 +618,11 @@ td.loading {
|
||||
|
||||
|
||||
/* Forms */
|
||||
|
||||
.datepicker {
|
||||
z-index: $zindex-popover !important;
|
||||
}
|
||||
|
||||
.datepicker input{
|
||||
@extend .form-control;
|
||||
}
|
||||
|
@ -13,10 +13,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from openstack_dashboard.test import helpers as test
|
||||
from openstack_dashboard.utils import filters
|
||||
from openstack_dashboard.utils import metering
|
||||
|
||||
|
||||
class UtilsFilterTests(test.TestCase):
|
||||
@ -38,3 +40,26 @@ class UtilsFilterTests(test.TestCase):
|
||||
def test_reject_random_string(self):
|
||||
val = '55WbJTpJDf'
|
||||
self.assertRaises(ValueError, filters.get_int_or_uuid, val)
|
||||
|
||||
|
||||
class UtilsMeteringTests(test.TestCase):
|
||||
|
||||
def test_calc_date_args_strings(self):
|
||||
date_from, date_to = metering.calc_date_args(
|
||||
"2012-04-11", "2012-04-12", "other")
|
||||
self.assertTrue(type(date_from) is datetime.datetime)
|
||||
self.assertTrue(type(date_to) is datetime.datetime)
|
||||
self.assertEqual(str(date_from.tzinfo), "UTC")
|
||||
self.assertEqual(str(date_to.tzinfo), "UTC")
|
||||
|
||||
def test_calc_date_args_datetime_dates(self):
|
||||
date_from, date_to = metering.calc_date_args(
|
||||
datetime.date(2012, 4, 11), datetime.date(2012, 4, 12), "other")
|
||||
self.assertTrue(type(date_from) is datetime.datetime)
|
||||
self.assertTrue(type(date_to) is datetime.datetime)
|
||||
self.assertEqual(str(date_from.tzinfo), "UTC")
|
||||
self.assertEqual(str(date_to.tzinfo), "UTC")
|
||||
|
||||
def test_calc_date_args_invalid(self):
|
||||
self.assertRaises(
|
||||
ValueError, metering.calc_date_args, object, object, "other")
|
||||
|
@ -61,7 +61,7 @@ def calc_date_args(date_from, date_to, date_options):
|
||||
try:
|
||||
if date_from:
|
||||
date_from = pytz.utc.localize(
|
||||
datetime.datetime.strptime(date_from, "%Y-%m-%d"))
|
||||
datetime.datetime.strptime(str(date_from), "%Y-%m-%d"))
|
||||
else:
|
||||
# TODO(lsmola) there should be probably the date
|
||||
# of the first sample as default, so it correctly
|
||||
@ -70,7 +70,7 @@ def calc_date_args(date_from, date_to, date_options):
|
||||
pass
|
||||
if date_to:
|
||||
date_to = pytz.utc.localize(
|
||||
datetime.datetime.strptime(date_to, "%Y-%m-%d"))
|
||||
datetime.datetime.strptime(str(date_to), "%Y-%m-%d"))
|
||||
# It returns the beginning of the day, I want the end of
|
||||
# the day, so I add one day without a second.
|
||||
date_to = (date_to + datetime.timedelta(days=1) -
|
||||
|
Loading…
Reference in New Issue
Block a user