Skip to content
Browse files

changing dates to use ranges and sparkline

  • Loading branch information...
1 parent bca7c3e commit d79d6419e9ced01984eb4fdcd5e33a35e16016fc @yourcelf committed Sep 13, 2010
Showing with 126 additions and 94 deletions.
  1. +8 −0 afg/templates/afg/entry.html
  2. +28 −17 afg/templates/afg/search.html
  3. +90 −77 afg/views.py
View
8 afg/templates/afg/entry.html
@@ -196,6 +196,14 @@
// Load data
var summary = "{{ entry.summary|escapejs }}";
var phrases = {{ entry.phrase_links|safe }};
+ var pk = "{{ entry.pk }}";
+ // Remove ourselves from link lists.
+ for (var phrase in phrases) {
+ var idx = phrases[phrase].indexOf(pk);
+ if (idx != -1) {
+ phrases[phrase].splice(idx, 1);
+ }
+ }
var linkPhrases = {};
for (var phrase in phrases) {
for (var i = 0; i < phrases[phrase].length; i++) {
View
45 afg/templates/afg/search.html
@@ -10,7 +10,7 @@
inputs.each(function() {
var el = $(this);
var val = $(this).val();
- if (val === '' || (val === '0' && /.*gte/.test(el.name))) {
+ if (val === '' || (val === '0' && /.*gte/.test(el.attr('name')))) {
$(this).remove();
}
});
@@ -23,7 +23,7 @@
<input type='submit' value='search' />
{% for param, choice_opts in choices.items %}
- {% if choice_opts.type == 'min_max' %}
+ {% if choice_opts.type == 'min_max' or choice_opts.type == 'date' %}
<h2>{{ choice_opts.title }}</h2>
{% if choice_opts.max_value == choice_opts.min_value %}
{{ choice_opts.max_value }}
@@ -32,46 +32,50 @@
<div id='sparkline_{{param}}'></div>
<div id='slider_{{param}}'></div>
<div>
- <div style='width: 20%; text-align: left; float: left;'>
- <input name='{{param}}__gte' id='{{param}}__gte' value='{{ choice_opts.chosen_min }}' size=3 title='{{ choice_opts.min_value }}' />
+ <div>
+ Between
+ <input name='{{param}}__gte' id='{{param}}__gte' value='{{ choice_opts.chosen_min }}' title='{{ choice_opts.min_value }}' style='width: 70px;' />
+ and
+ <input name='{{param}}__lte' id='{{param}}__lte' value='{{ choice_opts.chosen_max }}' style='width: 70px;' title='{{ choice_opts.max_value }}'/>
</div>
- <div style='width: 59%; text-align: center; float: left;'>
+ <div style='text-align: center'>
(<span id='count_{{param}}' style='text-align: center;'>{{ page.paginator.count }}</span> documents)
</div>
- <div style='width: 20%; text-align: right; float: left;'>
- <input name='{{param}}__lte' id='{{param}}__lte' value='{{ choice_opts.chosen_max }}' size=3 title='{{ choice_opts.max_value }}'/>
- </div>
- <div style='clear: both;'></div>
</div>
</div>
<script type='text/javascript'>
(function() {
var counts = [{{ choice_opts.counts|join:", " }}];
- var vals = [{{ choice_opts.vals|join:", " }}];
+ var vals = ["{{ choice_opts.vals|join:"\", \"" }}"];
+ for (var i = 0; i < vals.length; i++) {
+ if ("" + parseInt(vals[i]) == vals[i]) {
+ vals[i] = parseInt(vals[i]);
+ }
+ }
// remove '0' for sparkline display; it out-ranges all other values
var sparkline_counts = [{{ choice_opts.counts|join:", " }}];
sparkline_counts.splice(0, 1);
$('#sparkline_{{param}}').sparkline(sparkline_counts, {width: '100%'});
var update = function(event, ui) {
+ var actualValues = [vals[ui.values[0]], vals[ui.values[1]]];
if (ui.value == ui.values[0]) {
- $("#{{param}}__gte").val(ui.value).trigger('change');
+ $("#{{param}}__gte").val(actualValues[0]).trigger('change');
} else if (ui.value == ui.values[1]) {
- $("#{{param}}__lte").val(ui.value).trigger('change');
+ $("#{{param}}__lte").val(actualValues[1]).trigger('change');
}
var count = 0;
for (var i = 0; i < vals.length; i++) {
- if (vals[i] >= ui.values[0] && vals[i] <= ui.values[1]) {
+ if (vals[i] >= actualValues[0] && vals[i] <= actualValues[1]) {
count += counts[i];
}
}
$("#count_{{param}}").html(count);
}
$('#slider_{{param}}').slider({
range: true,
- values: [{% if choice_opts.chosen_min %} {{ choice_opts.chosen_min }}{% else %}{{ choice_opts.min_value }}{% endif %},
- {% if choice_opts.chosen_max %} {{ choice_opts.chosen_max }}{% else %}{{ choice_opts.max_value }}{% endif %}],
- max: {{ choice_opts.max_value }},
- min: {{ choice_opts.min_value }},
+ values: [0, vals.length - 1],
+ max: vals.length - 1,
+ min: 0,
change: update,
slide: update
});
@@ -156,6 +160,13 @@
$(promptSpan).hide();
}
$(this).before(promptSpan);
+ $(promptSpan).each(function(i){
+ var pos = $(this).position();
+ $(this).css({
+ left: pos.left + 'px',
+ top: pos.top + 'px'
+ });
+ });
$(this).change(function(){
if ($(this).val() == '') {
$('#input-prompt-' + i).show();
View
167 afg/views.py
@@ -196,41 +196,53 @@ def search(request, about=False, api=False):
# Narrow query set by given date facets
for key, field in date_fields.iteritems():
- date = request.GET.get(key, '')
- if date:
+ start_str = request.GET.get(key + '__gte', '')
+ end_str = request.GET.get(key + '__lte', '')
+ start = None
+ end = None
+ if start_str:
try:
- year, month, day = [int(d) for d in (date + "-0-0").split("-")[0:3]]
- if year > 3000 or month > 12 or day > 31:
- raise ValueError
+ start = datetime.datetime(*[int(a) for a in (start_str + '-1-1').split('-')[0:3]])
except ValueError:
- year, month, day = 0, 0, 0
- else:
+ start = None
+ if end_str:
+ try:
+ end = datetime.datetime(*[int(a) for a in ((end_str + '-1-1').split('-')[0:3])]) - \
+ datetime.timedelta(seconds=1)
+ except ValueError:
+ end = None
+ if not start and not end:
# Legacy date format
day = int(request.GET.get(key + '__day', 0))
month = int(request.GET.get(key + '__month', 0))
year = int(request.GET.get(key + '__year', 0))
- if year:
- if not month:
- start = datetime.datetime(year, 1, 1)
- end = datetime.datetime(year + 1, 1, 1) - datetime.timedelta(seconds=1)
- params[key] = start.strftime("%Y")
- sqs = sqs.date_facet(key, start, end, 'month')
- elif not day:
- start = datetime.datetime(year, month, 1)
- next_month = datetime.datetime(year, month, 1) + datetime.timedelta(days=31)
- end = datetime.datetime(next_month.year, next_month.month, 1) - datetime.timedelta(seconds=1)
- params[key] = start.strftime("%Y-%m")
- sqs = sqs.date_facet(key, start, end, 'day')
- else:
- start = datetime.datetime(year, month, day)
- end = datetime.datetime(year, month, day + 1) - datetime.timedelta(seconds=1)
- params[key] = start.strftime("%Y-%m-%d")
- sqs = sqs.date_facet('date', start, end, 'day')
- sqs = sqs.narrow("%s:[%s TO %s]" % (key, start.isoformat() + "Z", end.isoformat() + "Z"))
+ if year:
+ if month:
+ if day:
+ start = datetime.datetime(year, month, day)
+ end = start + datetime.timedelta(days=1) - datetime.timedelta(seconds=1)
+ else:
+ start = datetime.datetime(year, month, 1)
+ next_month = start + datetime.timedelta(days=31)
+ end = datetime.datetime(next_month.year, next_month.month, 1) - datetime.timedelta(seconds=1)
+ else:
+ start = datetime.datetime(year, 1, 1)
+ end = datetime.datetime(year + 1, 1, 1) - datetime.timedelta(seconds=1)
+ if start:
+ sqs = sqs.narrow("%s:[%s TO *]" % (key, start.isoformat() + 'Z'))
+ params[key + '__gte'] = start.strftime("%Y-%m-%d")
else:
start = DiaryEntryIndex.min_date
+ if end:
+ sqs = sqs.narrow("%s:[* TO %s]" % (key, end.isoformat() + 'Z'))
+ params[key + '__lte'] = end.strftime("%Y-%m-%d")
+ else:
end = DiaryEntryIndex.max_date
- sqs = sqs.date_facet(key, start, end, 'year')
+
+ if (end - start).days > 365:
+ sqs = sqs.date_facet(key, start, end, 'month')
+ else:
+ sqs = sqs.date_facet(key, start, end, 'day')
# sorting
sort = request.GET.get('sort', '')
@@ -264,71 +276,72 @@ def search(request, about=False, api=False):
entries.append((entry, excerpt))
# Choices
- total_count = sqs.count()
counts = sqs.facet_counts()
choices = utils.OrderedDict()
for key in DiaryEntryIndex.search_facet_display:
field = DiaryEntryIndex.fields[key]
- choice = {
- 'title': fix_constraint_name(key),
- 'value': params.get(key, '')
- }
+ choice = None
if isinstance(field, haystack.fields.CharField):
- choice['choices'] = sorted((k, k, c) for k, c in counts['fields'][key] if c > 0)
- choice['type'] = 'text'
- elif isinstance(field, haystack.fields.DateTimeField):
- choice['type'] = 'date'
- date_facets = []
- for d,c in sorted(counts['dates'][key].iteritems()):
- try:
- # magic method to parse ISO date format.
- dt = datetime.datetime(*map(int, re.split('[^\d]', d)[:-1]))
- if c > 0:
- date_facets.append((dt, c))
- except (TypeError, ValueError):
- pass
-
- year, month, day = (params.get(key, '') + "--").split("-")[0:3]
- if year:
- if month:
- if day:
- d = datetime.date(int(year), int(month), int(day))
- choice['choices'] = [(d.strftime("%Y %B %e"), d.strftime("%Y-%m-%d"), total_count)]
- else:
- choice['choices'] = [(d.strftime("%B %e"), d.strftime("%Y-%m-%d"), c) for d, c in date_facets]
- else:
- choice['choices'] = [(d.strftime("%B"), d.strftime("%Y-%m"), c) for d, c in date_facets]
- else:
- choice['choices'] = [(d.year, d.year, c) for d, c in date_facets]
+ choice = {
+ 'choices': sorted((k, k, c) for k, c in counts['fields'][key] if c > 0),
+ 'type': 'text',
+ 'value': params.get(key, ''),
+ }
elif isinstance(field, haystack.fields.IntegerField):
# Integer choices
- facets = sorted([(int(k), v) for k,v in counts['fields'][key] if v > 0])
+ facets = sorted([(int(k), c) for k,c in counts['fields'][key] if c > 0])
if facets:
- choice.update({
+ choice = {
'type': 'min_max',
- 'counts': [v for k,v in facets],
- 'vals': [k for k,v in facets],
+ 'counts': [c for k,c in facets],
+ 'vals': [k for k,c in facets],
'min_value': facets[0][0],
'max_value': facets[-1][0],
'chosen_min': params.get(key + '__gte', ''),
'chosen_max': params.get(key + '__lte', ''),
- })
- choices[key] = choice
+ }
+ elif isinstance(field, haystack.fields.DateTimeField):
+ facets = sorted(counts['dates'][key].iteritems())
+ if facets:
+ val_counts = []
+ vals = []
+ for d,c in facets:
+ if c > 0:
+ try:
+ # magic method to parse ISO date format.
+ dt = datetime.datetime(*map(int, re.split('[^\d]', d)[:-1]))
+ val_counts.append(c)
+ vals.append(dt.strftime('%Y-%m-%d'))
+ except (TypeError, ValueError):
+ pass
+ choice = {
+ 'type': 'date',
+ 'counts': val_counts,
+ 'vals': vals,
+ 'min_value': vals[0],
+ 'max_value': vals[-1],
+ 'chosen_min': params.get(key + '__gte', ''),
+ 'chosen_max': params.get(key + '__lte', ''),
+ }
+ if choice:
+ choice['title'] = fix_constraint_name(key)
+ choices[key] = choice
search_url = reverse('afg.search')
# Links to remove constraints
constraints = {}
exclude = set(('sort',))
- for field in params.keys():
- if field not in exclude:
- value = params.pop(field)
- constraints[field] = {
+ for key in params.keys():
+ if key not in exclude:
+ value = params.pop(key)
+ constraints[key] = {
'value': value,
'removelink': "%s?%s" % (search_url, urllib.urlencode(params)),
- 'title': fix_constraint_name(field)
+ 'title': fix_constraint_name(key)
}
- params[field] = value
+ params[key] = value
+ print constraints
# Links to change sorting
sort_links = []
@@ -393,11 +406,11 @@ def search(request, about=False, api=False):
'sort_links': sort_links,
})
-def fix_constraint_name(field):
- field = field.replace('_', ' ')
- field = field.replace('wia', 'wounded')
- field = field.replace('kia', 'killed')
- field = field.replace('gte', ' - more than')
- field = field.replace('lte', ' - less than')
- field = field.replace('icontains', 'contains')
- return field[0].upper() + field[1:]
+def fix_constraint_name(name):
+ name = name.replace('_', ' ')
+ name = name.replace('wia', 'wounded')
+ name = name.replace('kia', 'killed')
+ name = name.replace('gte', ' - more than')
+ name = name.replace('lte', ' - less than')
+ name = name.replace('icontains', 'contains')
+ return name[0].upper() + name[1:]

0 comments on commit d79d641

Please sign in to comment.
Something went wrong with that request. Please try again.