-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add filters to lists in dasboards #1299
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1299 +/- ##
==========================================
+ Coverage 81.97% 81.98% +0.01%
==========================================
Files 115 123 +8
Lines 5598 5746 +148
Branches 644 667 +23
==========================================
+ Hits 4589 4711 +122
- Misses 850 878 +28
+ Partials 159 157 -2
Continue to review full report at Codecov.
|
3a0ecd6
to
aad9523
Compare
saleor/core/utils/filters.py
Outdated
|
||
def get_sort_by_choices(filter): | ||
return [(choice[0], choice[1].lower()) for choice in | ||
filter.filters['sort_by'].field.choices[1::2]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not name your variables after built-in functions, please rename filter
to something else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any suggestions? I wanted to change it but...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could name it filter_set
after the class from django-filters
.
saleor/core/utils/filters.py
Outdated
|
||
|
||
def get_now_sorted_by(filter, fields, default_sort='name'): | ||
sort_by = filter.form.cleaned_data.get('sort_by') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
saleor/dashboard/order/views.py
Outdated
else: | ||
orders = orders_all.all() | ||
orders = (Order.objects.prefetch_related( | ||
'groups', 'payments', 'groups__items', 'user').order_by('-pk')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you prefetch some_field__somefields_field
then some_field
will be automatically prefetched.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, this is not my code but i will change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, I only added order_by and delete if :)
But this is exactly same code from invoice ;)
<div class="card-content"> | ||
<div class="col s12"> | ||
<span class="card-title">{% trans 'Filters' context 'Dashboard card title' %}</span> | ||
<span>{% trans 'Total records found' context 'Dashboard filter' %}: {{ filter.qs|length }}</span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use count
here? I think passing it from the backend would be better, as usually, we are trying to avoid templates firing up additional queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will check if this triggers query.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does. In case of a large dataset this would be really slow. Actually we don't display the number of items in queryset in the list views. Maybe it would be better to add it consistently to all lists in a different PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm i don't think that another PR is required. I already have to do this so why not now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we add it to every list then it's fine in this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is knowing the precise number of results useful? When is it useful? When is it not? It would be nice to have some use cases before we add something to all list views.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reason @patrys just mentioned I would split it out to another issue/PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the other hand we need a visual feedback that there's some filtering being applied and number of records found would partially serve that purpose.
<div class="row"> | ||
{% for field in filter.form %} | ||
<div class="col s12"> | ||
{% if field.name == 'sort_by' %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of, I think rendering those fields separately would be a more error-proof option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those fields are taken from many filters, adding every possible field would create enormous if statement.
@@ -1,6 +1,7 @@ | |||
{% extends "dashboard/base.html" %} | |||
{% load i18n %} | |||
{% load prices_i18n %} | |||
{% load shop %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're using only one function, it would be more convenient to use {% load function from shop %}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do. But I think we need PR which will make those changes for every template for every templatetag library
saleor/settings.py
Outdated
@@ -289,7 +289,7 @@ def get_host(): | |||
|
|||
TEST_RUNNER = '' | |||
|
|||
ALLOWED_HOSTS = get_list(os.environ.get('ALLOWED_HOSTS', 'localhost')) | |||
ALLOWED_HOSTS = ['*'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like local settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooops
4bbee55
to
48b1b8a
Compare
@dominik-zeglen RangeWidget and DateRangeWidget have some issues with 'clicking aea'. Could you investigate it? |
5ce3b88
to
4597cbd
Compare
@dominik-zeglen @koradon I've reviewed the UI and have a few remarks:
|
def handle_nullboolean(field): | ||
value = yesno( | ||
field.value(), | ||
pgettext_lazy('Possible values of boolean filter', 'yes,no,all')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
descriptive 👍
from django.template.defaultfilters import yesno | ||
from django.utils.translation import pgettext_lazy | ||
|
||
PATTERN = '%s: %s' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATTERN
of ..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Chip formatting
@@ -0,0 +1,65 @@ | |||
from django.template.defaultfilters import yesno |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing unicode_literals import
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
label=pgettext_lazy('Staff list filter label', 'Groups'), | ||
name='groups', | ||
queryset=Group.objects.all()) | ||
is_active = ChoiceFilter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use BooleanField
here? I think it's more obvious than returning '1' or '0' as str
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately BooleanFilter does not have 'empty_label' and 'choices' params. Sience we want a custom string 'All' if no option was chosen and a custom choices like 'Published'/'Not published' I had to use ChoiceFilter. And this is a recommended approach for this kind of customization.
choices=PUBLISHED_CHOICES, | ||
empty_label=pgettext_lazy('Filter empty choice label', 'All'), | ||
widget=forms.Select) | ||
is_featured = ChoiceFilter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as with is_active
saleor/core/templatetags/shop.py
Outdated
request_get = request.GET.copy() | ||
sort_by = request_get.get('sort_by') | ||
arrow_src = '' | ||
active = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather expect a boolean variable is_active
. If I'm correct below a CSS class is set as value of this variable which is not a good practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, i wanted less logic in template
saleor/core/templatetags/shop.py
Outdated
if field == sort_by[1:]: | ||
arrow_src = static('/images/arrow_down_icon.svg') | ||
active = 'active' | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this case happens? Isn't setting of these values already covered in lines 41 and 42?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, some old code i guess. Deleted
from django.db.models import Q | ||
|
||
|
||
def get_sort_by_choices(filter_set): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add docstrings to all of these functions.
saleor/core/templatetags/shop.py
Outdated
request = context['request'] | ||
request_get = request.GET.copy() | ||
sort_by = request_get.get('sort_by') | ||
arrow_src = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename it to sorting_icon
. If we changed from arrows to something else we won't have to update the variable names :)
4be9cad
to
21b67a1
Compare
Add filters.py to dashboard/product. Update product_list view. Update dashboard/product/list.html.
Add template dashboard/_filters.html. Add include tag.
Move get_sort_by_choices and get_now_sorted_by to core.utils.filters.py.
Add filters to order list. Change include path from relative to absolute. Move _filters.html from dashboard to dashboard/includes. Delete _status_filters.html.
Add sort_by links to order and customer lists.
Move include _filters before check if QuerySet exists.
Change PATTERN to CHIPS_PATTERN.
e0ea595
to
1291754
Compare
Return just sort_by GET value instead of whole request.
"""Build a list of chips for NullBooleanField field.""" | ||
value = yesno( | ||
field.value(), | ||
pgettext_lazy('Possible values of boolean filter', 'yes,no,all')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't do this. If that's the only way to pass data do yesno
then please don't use yesno
as well.
Add filter capability for lists in dashboard.
Fixes #256
Fixes #1387