Plone gives you the possibility of filtering search results using a date range. Normal date range is set up by using only the minimum date so the range is between today and some date on the past.
I need to add the option of setting a date range with starting and ending dates.
I was thinking on adding an extra option that, when selected, will show a couple of date pickers, but I don't know how to set the created.query:record:list:date
variable to use this 2 values.
I have tried passing a list on the query
variable but then I get:
Error Value: Invalid DateTime "[DateTime('2000/07/14 00:00:00 GMT-3'), DateTime('2014/07/14 00:00:00 GMT-3')]"
Has anybody else has found with a requirement like this before? How did you solved it? Should this be ported to the core?
I spent some time investigating this and I have a working solution.
First we need to understand how Zope and ZPT work; when you name a form element with something like created.query:record:list:date
you are telling Zope to do some parameter conversions:
For more information on this you can take a look at Advanced Zope Scripting.
So, the parameter is then automatically converted to a dictionary record like this in Python:
'created': {'query': [DateTime('2014/07/09 00:00:00 GMT-3')], 'range': 'min'}
My mistake was assuming that I had to pass all list elements on one request variable.
The code I added at the end of the form now looks like this:
<input type="radio"
id="query-date-range"
name="created.query:record:list:date:ignore_empty"
tal:attributes="value python:'';
checked python:checked=='' and 'checked' or '';"
/>
<label for="query-date-range" i18n:translate="time_range">Time range</label>
<input type="text"
id="range-start"
name="created.query:record:list:date:ignore_empty">
<input type="text"
id="range-end"
name="created.query:record:list:date:ignore_empty">
<script>
var today = new Date();
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
var start = yesterday.toLocaleDateString().slice(0, 10);
var end = today.toLocaleDateString().slice(0, 10);
$(document).ready(function() {
$("#range-start").datepicker();
$("#range-end").datepicker();
$('#range-start').hide();
$('#range-end').hide();
});
$('input:radio').change(function() {
var option = $('input:radio:checked', '#searchform').val();
if (option === '') {
$('#range-start').val(start);
$('#range-start').show();
$('#range-end').val(end);
$('#range-end').show();
$('#range').val('min:max');
}
else {
$('#range-start').val('');
$('#range-start').hide();
$('#range-end').val('');
$('#range-end').hide();
$('#range').val('min');
};
});
</script>
Take special attention to the following:
the start and end dates are input elements associated with a jQueryUI datepicker widget.
both input elements share the same name (created.query:record:list:date:ignore_empty
) as the other and here is where the Zope magic takes place: the values of all input elements with the same name are converted on a unique list record like this:
'created': {'query': [DateTime('2014/07/15 00:00:00 GMT-3'), DateTime('2014/07/16 00:00:00 GMT-3')], 'range': 'min:max'}
we set an additional parameter converter (ignore_empty
), which just avoid adding to the list the elements that have no value set (I added this converter to the other input elements too).
when we click on the query-date-range
element we have to initialize the date selectors; when we click on any of the other elements we need to clear these values to avoid adding them to the list.
we also change the value of the range
element according to the query type as mentioned before by @sdupton.
The JavaScript part of the code could be enhanced for sure; my skills are really limited.