Skip to content

Commit 244ff0b

Browse files
authored
Merge pull request #16 from MetalBlazer/all_questions_sorter
Sortable Header added in place of page sorter
2 parents b8d8364 + 6c8ebd3 commit 244ff0b

6 files changed

Lines changed: 262 additions & 42 deletions

File tree

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Django==1.5.12
2-
2+
future==0.17.1
33
MySQL-python==1.2.5
44
argparse==1.2.1
55
django-appconf==0.6

static/website/templates/questions.html

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,25 @@
11
{% extends 'website/templates/base.html' %}
22
{% load static %}
33
{% load count_tags %}
4-
4+
{% load forumdata %}
55
{% block content %}
6-
<script>
7-
$(document).ready(function(){
8-
$("#listTable").tablesorter({
9-
headers:{ 3:{sorter:false }
10-
},
11-
12-
});
136

14-
});
15-
</script>
167
<h4>
178
<h5>
189
Showing {{ questions.start_index }} - {{ questions.end_index }} of {{ questions.paginator.count }} questions.
1910
</h5>
2011
</h4>
21-
<table id = "listTable" class="tablesorter-blue">
12+
<div class="col-lg-16">
13+
<table id = "listTable" class="paleblue table table-striped table-hover table-bordered">
14+
2215
<thead>
23-
<tr>
24-
<th> FOSS </th>
25-
<th> Tutorial</th>
26-
<th> Min </th>
27-
<th> Sec </th>
28-
<th> Question <span class="glyphicon glyphicon-link"></span></th>
29-
<th> Date</th>
30-
<th> Views</th>
31-
<th> Answers</th>
32-
<th> User</th>
33-
</tr>
34-
</thead>
16+
{% get_sortable_header header ordering request.GET %}
17+
</thead>
3518
<tbody>
3619
{% for question in questions %}
3720

3821
<tr>
39-
<td>
22+
<td class="col-md-1">
4023
<span href="#" class="category" data-toggle="tooltip" data-placement="top" title="{{ question.category}}">
4124
{{ question.category|truncatechars:12 }}
4225
</span>
@@ -45,7 +28,7 @@ <h5>
4528
</a>
4629
</td>
4730

48-
<td>
31+
<td class="col-md-1">
4932
<span class="tutorial" data-toggle="tooltip" data-placement="top" title="{{ question.tutorial}}">
5033
{{ question.tutorial|truncatechars:12 }}
5134
</span>
@@ -54,54 +37,54 @@ <h5>
5437
</a>
5538
</td>
5639

57-
<td>
40+
<td class="col-md-1">
5841
<span>
5942
<a href="{% url 'website:filter' question.category question.tutorial question.minute_range %}?qid={{ question.id }}">
6043
{{ question.minute_range }}
6144
</a>
6245
</span>
6346
</td>
6447

65-
<td>
48+
<td class="col-md-1">
6649
<span>
6750
<a href="{% url 'website:filter' question.category question.tutorial question.minute_range question.second_range%}?qid={{ question.id }}">
6851
{{ question.second_range }}
6952
</a>
7053
</span>
7154
</td>
7255

73-
<td>
56+
<td class="col-md-3">
7457
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.title }}">
7558
<a href="{% url 'website:get_question' question.id %}">{{ question.title|truncatechars:40 }}</a>
7659
</span>
7760
</td>
7861

79-
<td>
62+
<td class="col-md-1">
8063
<span>
8164
<i>
8265
{{ question.date_created|date:"d-m-y" }}
8366
</i>
8467
</span>
8568
</td>
8669

87-
<td>
70+
<td class="col-md-1">
8871
{{ question.views}}
8972
</td>
9073

91-
<td>
74+
<td class="col-md-1">
9275
{{ question.answer_set.count }}
9376
</td>
9477

95-
<td>
78+
<td class="col-md-1">
9679
<span class="title" data-toggle="tooltip" data-placement="top" title="{{ question.user }}">
9780
{{ question.user|truncatechars:10 }}
9881
</span>
9982
</td>
10083
</tr>
10184
{% endfor %}
102-
<tbody>
85+
</tbody>
10386
</table>
104-
87+
</div>
10588
<ul class="pagination pull-right">
10689
{% if questions.has_previous %}
10790
<li><a href="?page={{ questions.previous_page_number }}">&laquo; <small>Prev</small></a></li>
@@ -113,7 +96,7 @@ <h5>
11396
{% ifequal num questions.number %}
11497
<li class="active"><a href="#">{{ num }}<span class="sr-only">(current)</span></a></li>
11598
{% else %}
116-
<li><a href="?page={{ num }}">{{ num }}</a></li>
99+
<li><a href="?{{ request.GET|combine_get_values }}page={{ num }}">{{ num }}</a></li>
117100
{% endifequal %}
118101
{% endfor %}
119102

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{% load forumdata %}
2+
<tr class="active">
3+
{% for header in headers %}
4+
<th scope="col" class="{{ header.class_name }}" {{ header.attribs }}>
5+
{% if header.sortable %}
6+
<div class="sortoptions"{{' data="123"'}}>
7+
{% if not header.removable == None %}<a class="sortremove" href="?o={{ header.removable }}{% with other_get_vals=getValue|reset_get_value:'o' %}{% if other_get_vals %}&{{other_get_vals}}{% endif %}{% endwith %}" title="Remove from sorting"></a>{% endif %}
8+
{% if header.order %}
9+
<span class="glyphicon glyphicon-sort" title="Sorting priority: {{ header.order }}"></span>
10+
{% endif %}
11+
<a href="?o={{ header.ordering }}{% with other_get_vals=getValue|reset_get_value:'o' %}{% if other_get_vals %}&{{other_get_vals}}{% endif %}{% endwith %}" class="toggle {{ header.sort_type }}" title="Toggle sorting"></a>
12+
</div>
13+
{% endif %}
14+
<div class="text">
15+
{% if header.sortable %}
16+
<a href="?o={{ header.ordering }}{% with other_get_vals=getValue|reset_get_value:'o' %}{% if other_get_vals %}&{{other_get_vals}}{% endif %}{% endwith %}">
17+
{% endif %}
18+
19+
{% if header.verbose_name %}
20+
{{ header.verbose_name|safe }}
21+
{% else %}
22+
{{ header.name|safe }}
23+
{% endif %}
24+
{% if header.sortable %}
25+
</a>
26+
{% endif %}
27+
</div>
28+
<div class="clear"></div>
29+
</th>
30+
{% endfor %}
31+
</tr>

website/sortable.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Third Party Stuff
2+
from builtins import str
3+
from builtins import range
4+
from builtins import object
5+
from django.contrib import messages
6+
7+
8+
class SortableHeader(object):
9+
def __init__(self, name, sortable, verbose_name='', class_name='', attribs=''):
10+
self.name = name
11+
self.sortable = sortable
12+
self.verbose_name = verbose_name
13+
self.ordering = ''
14+
self.removable = ''
15+
self.class_name = class_name
16+
self.sort_type = ''
17+
self.order = 0
18+
self.attribs = attribs
19+
20+
21+
def get_field_index(raw_get_data):
22+
if raw_get_data:
23+
field_index = []
24+
tmp_index = raw_get_data.split('.')
25+
for index in tmp_index:
26+
field_index.append(int(index))
27+
if field_index:
28+
return field_index
29+
return None
30+
31+
32+
def get_sorted_list(request, obj, fields_list, raw_get_data):
33+
field_index = get_field_index(raw_get_data)
34+
sort_order = []
35+
if field_index:
36+
for index in field_index:
37+
try:
38+
fixed_index = index
39+
if index < 0:
40+
fixed_index = index * -1
41+
field = fields_list[fixed_index]
42+
if field.sortable:
43+
if index < 0:
44+
sort_order.append('-' + field.name)
45+
else:
46+
sort_order.append(field.name)
47+
except Exception as e:
48+
print(e)
49+
messages.error(request, 'Invalid ordering key has passed!')
50+
return obj
51+
if len(sort_order):
52+
try:
53+
print(sort_order)
54+
return obj.order_by(*sort_order)
55+
except Exception as e:
56+
print(e)
57+
messages.error(request, 'Invalid field name passed for sorting!')
58+
return obj
59+
60+
61+
def get_ordering(ordering, unsigned_index, signed_index, sign_to_add):
62+
order_string = ''
63+
flag = 1
64+
removable = ''
65+
if ordering:
66+
for order in ordering:
67+
if order == signed_index:
68+
if order_string:
69+
order_string = str(order * -1) + '.' + order_string
70+
else:
71+
order_string = str(order * -1)
72+
flag = 0
73+
else:
74+
if order_string:
75+
order_string = order_string + '.'
76+
order_string = order_string + str(order)
77+
if removable:
78+
removable = removable + '.'
79+
removable = removable + str(order)
80+
if flag:
81+
if order_string:
82+
order_string = '.' + order_string
83+
order_string = sign_to_add + str(unsigned_index) + order_string
84+
removable = None
85+
return order_string, removable
86+
87+
88+
def get_sortable_header(header, ordering, getValue):
89+
descending_list = []
90+
ascending_list = []
91+
if ordering:
92+
counter = 1
93+
for order in ordering:
94+
if order < 0:
95+
header[order * -1].order = counter
96+
descending_list.append(header[order * -1].name)
97+
else:
98+
header[order].order = counter
99+
ascending_list.append(header[order].name)
100+
counter = counter + 1
101+
header_len = len(header) + 1
102+
headers = []
103+
for row in range(header_len):
104+
if row == 0:
105+
continue
106+
class_name = 'col-' + header[row].name
107+
signed_index = row
108+
if header[row].sortable:
109+
class_name = class_name + ' sortable'
110+
sign_str = ''
111+
if header[row].name in ascending_list:
112+
sign_str = '-'
113+
class_name = 'sorted ascending ' + class_name
114+
header[row].sort_type = 'ascending'
115+
elif header[row].name in descending_list:
116+
class_name = 'sorted descending ' + class_name
117+
header[row].sort_type = 'descending'
118+
signed_index = signed_index * -1
119+
header[row].ordering, header[row].removable = get_ordering(ordering, row, signed_index, sign_str)
120+
header[row].class_name = header[row].class_name + ' ' + class_name
121+
headers.append(header[row])
122+
context = {
123+
'headers': headers,
124+
'getValue': getValue
125+
}
126+
return context
127+
128+
129+
def format_raw_data(raw_data):
130+
str_rows = raw_data.split('\n')
131+
formatted_data = ''
132+
for str_row in str_rows:
133+
if str_row:
134+
formatted_data += '<p>' + str_row + '</p>'
135+
return formatted_data

website/templatetags/forumdata.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from django import template
2+
from forums.sortable import get_sortable_header
3+
register = template.Library()
4+
5+
6+
@register.filter
7+
def sort_by(queryset, order):
8+
return queryset.filter(visible__exact=1).order_by('position')
9+
10+
11+
''' includes: will include include's values '''
12+
13+
14+
def reset_get_values(getValue, includes=['page']):
15+
values = ''
16+
for k, v in list(getValue.items()):
17+
if k in includes:
18+
values += k+'='+v+'&'
19+
return values
20+
21+
22+
''' includes: will include include's values '''
23+
24+
25+
def reset_get_value(getValue, exclude_key=None):
26+
values = ''
27+
for k, v in list(getValue.items()):
28+
if k != exclude_key:
29+
if values:
30+
values += '&'
31+
values += k + '=' + v
32+
return values
33+
34+
35+
''' excludes: will exclude excludes's values '''
36+
def combine_get_values(getValue, excludes = ['page']):
37+
values = ''
38+
for k,v in list(getValue.items()):
39+
if k not in excludes:
40+
values += k+'='+v+'&'
41+
return values
42+
43+
44+
register.filter('reset_get_values', reset_get_values)
45+
register.filter('reset_get_value', reset_get_value)
46+
register.inclusion_tag('website/templates/sortable_header.html')(get_sortable_header)
47+
register.filter('combine_get_values', combine_get_values)

0 commit comments

Comments
 (0)