pricing: categories can be reordered in a pricing model (#64903)

This commit is contained in:
Lauréline Guérin 2022-05-09 10:15:48 +02:00
parent 306ec0e5ce
commit 4976df546a
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 130 additions and 17 deletions

View File

@ -537,18 +537,22 @@ div.paragraph {
}
}
.sortable {
span.handle {
cursor: move;
display: inline-block;
padding: 0.5ex;
text-align: center;
width: 2em;
height: 100%;
box-sizing: border-box;
font-weight: normal;
}
}
ul.objects-list.sortable {
li {
position: relative;
span.handle {
cursor: move;
display: inline-block;
padding: 0.5ex;
text-align: center;
width: 2em;
height: 100%;
box-sizing: border-box;
}
& > a {
display: inline-block;
}

View File

@ -49,12 +49,12 @@ $(function() {
})
}
$('ul.sortable').sortable({
$('.sortable').sortable({
handle: '.handle',
items: 'li.sortable-item',
items: '.sortable-item',
update : function(event, ui) {
var new_order = '';
$(this).find('li.sortable-item').each(function(i, x) {
$(this).find('.sortable-item').each(function(i, x) {
var item_id = $(x).data('item-id');
if (new_order) {
new_order += ',';

View File

@ -23,11 +23,16 @@
{% block content %}
<div class="section">
<h3>{% trans "Criterias" %}</h3>
{% with criterias=object.criterias.all categories=object.categories.all %}
{% if categories %}
<div>
{% with criterias=object.criterias.all %}
{% for category in object.categories.all %}
<div class="paragraph">
<h4>{% trans "Category:" %} {{ category }}</h4>
{% blocktrans %}Use drag and drop with the ⣿ handles to reorder categories.{% endblocktrans %}
</div>
{% endif %}
<div class="sortable" data-order-url="{% url 'chrono-manager-pricing-criteria-category-order' object.pk %}">
{% for category in categories %}
<div class="paragraph sortable-item" data-item-id="{{ category.pk }}">
<h4><span class="handle"></span>{% trans "Category:" %} {{ category }}</h4>
<p>{% trans "Selected criterias:" %}</p>
<ul>
{% for criteria in criterias %}
@ -42,12 +47,12 @@
</p>
</div>
{% endfor %}
{% endwith %}
{% if object.categories.count < 3 %}
<p>
<a rel="popup" class="pk-button" href="{% url 'chrono-manager-pricing-criteria-category-add' pk=object.pk %}">{% trans "Add a category" %} <span class="extra-info">({% trans "max 3 categories" %})</span></a>
</p>
{% endif %}
{% endwith %}
</div>
</div>
{% endblock %}

View File

@ -55,6 +55,11 @@ urlpatterns = [
views.pricing_criteria_category_delete,
name='chrono-manager-pricing-criteria-category-delete',
),
url(
r'^(?P<pk>\d+)/order/$',
views.pricing_criteria_category_order,
name='chrono-manager-pricing-criteria-category-order',
),
url(r'^criterias/$', views.criteria_list, name='chrono-manager-pricing-criteria-list'),
url(
r'^criteria/category/add/$',

View File

@ -234,6 +234,33 @@ class PricingCriteriaCategoryDeleteView(DeleteView):
pricing_criteria_category_delete = PricingCriteriaCategoryDeleteView.as_view()
class PricingCriteriaCategoryOrder(DetailView):
model = Pricing
def dispatch(self, request, *args, **kwargs):
if not request.user.is_staff:
raise PermissionDenied()
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
if 'new-order' not in request.GET:
return HttpResponseBadRequest('missing new-order parameter')
pricing = self.get_object()
try:
new_order = [int(x) for x in request.GET['new-order'].split(',')]
except ValueError:
return HttpResponseBadRequest('incorrect new-order parameter')
categories = pricing.categories.all()
if set(new_order) != {x.pk for x in categories} or len(new_order) != len(categories):
return HttpResponseBadRequest('incorrect new-order parameter')
for i, c_id in enumerate(new_order):
PricingCriteriaCategory.objects.filter(pricing=pricing, category=c_id).update(order=i + 1)
return HttpResponse(status=204)
pricing_criteria_category_order = PricingCriteriaCategoryOrder.as_view()
class CriteriaCategoryAddView(CreateView):
template_name = 'chrono/pricing/manager_criteria_category_form.html'
model = CriteriaCategory

View File

@ -259,6 +259,78 @@ def test_pricing_delete_category_as_manager(app, manager_user):
app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category.pk), status=403)
def test_pricing_reorder_categories(app, admin_user):
category1 = CriteriaCategory.objects.create(label='Cat 1')
category2 = CriteriaCategory.objects.create(label='Cat 2')
category3 = CriteriaCategory.objects.create(label='Cat 3')
category4 = CriteriaCategory.objects.create(label='Cat 4')
pricing = Pricing.objects.create(label='Model')
pricing.categories.add(category1, through_defaults={'order': 1})
pricing.categories.add(category2, through_defaults={'order': 2})
pricing.categories.add(category3, through_defaults={'order': 3})
assert list(
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
) == [category1.pk, category2.pk, category3.pk]
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
1,
2,
3,
]
app = login(app)
# missing get params
app.get('/manage/pricing/%s/order/' % (pricing.pk), status=400)
# bad new-order param
bad_params = [
# missing category3 in order
','.join(str(x) for x in [category1.pk, category2.pk]),
# category1 mentionned twice
','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category1.pk]),
# category4 not in pricing categories
','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category4.pk]),
# not an id
'foo,1,2,3',
' 1 ,2,3',
]
for bad_param in bad_params:
app.get(
'/manage/pricing/%s/order/' % (pricing.pk),
params={'new-order': bad_param},
status=400,
)
# not changed
assert list(
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
) == [category1.pk, category2.pk, category3.pk]
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
1,
2,
3,
]
# change order
app.get(
'/manage/pricing/%s/order/' % (pricing.pk),
params={'new-order': ','.join(str(x) for x in [category3.pk, category1.pk, category2.pk])},
)
assert list(
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
) == [category3.pk, category1.pk, category2.pk]
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
1,
2,
3,
]
def test_pricing_reorder_categories_as_manager(app, manager_user):
pricing = Pricing.objects.create(label='Model')
app = login(app, username='manager', password='manager')
app.get('/manage/pricing/%s/order/' % (pricing.pk), status=403)
def test_list_criterias_as_manager(app, manager_user):
app = login(app, username='manager', password='manager')
app.get('/manage/pricing/criterias/', status=403)