Repository: saleor/saleor

Issue:
Error in modal to select the product class is not displayed properly
When creating a new product, users first have to select the product class in the modal. When clicking "Create new" without selecting the product class, the modal closes and user gets back to the product list. After click the FAB button to add new product again, the modal with error inside appears.

### Steps to reproduce the problem

1. Click on the FAB button to add new product.
2. Click on "Create new" button without selecting a product class

### What I expected to happen

Modal should remain on the screen and appropriate error message should be displayed.

### What happened instead/how it failed

Modal was closed.



Discussion:

Resolving patch:
diff --git a/saleor/dashboard/product/forms.py b/saleor/dashboard/product/forms.py
--- a/saleor/dashboard/product/forms.py
+++ b/saleor/dashboard/product/forms.py
@@ -14,14 +14,13 @@
 
 
 class ProductClassSelectorForm(forms.Form):
-
-    def __init__(self, *args, **kwargs):
-        product_classes = kwargs.pop('product_classes', [])
-        super(ProductClassSelectorForm, self).__init__(*args, **kwargs)
-        choices = [(obj.pk, obj.name) for obj in product_classes]
-        self.fields['product_cls'] = forms.ChoiceField(
-            label=pgettext_lazy('Product class form label', 'Product type'),
-            choices=choices, widget=forms.RadioSelect)
+    """
+    Form that allows selecting product class.
+    """
+    product_cls = forms.ModelChoiceField(
+        queryset=ProductClass.objects.all(),
+        label=pgettext_lazy('Product class form label', 'Product type'),
+        widget=forms.RadioSelect, empty_label=None)
 
 
 class StockForm(forms.ModelForm):
diff --git a/saleor/dashboard/product/urls.py b/saleor/dashboard/product/urls.py
--- a/saleor/dashboard/product/urls.py
+++ b/saleor/dashboard/product/urls.py
@@ -18,6 +18,8 @@
         views.product_create, name='product-add'),
     url(r'^bulk-update/$',
         views.product_bulk_update, name='product-bulk-update'),
+    url(r'^product-select-classes/$',
+        views.product_select_classes, name='product-select-classes'),
 
     url(r'^classes/$',
         views.product_class_list, name='product-class-list'),
diff --git a/saleor/dashboard/product/views.py b/saleor/dashboard/product/views.py
--- a/saleor/dashboard/product/views.py
+++ b/saleor/dashboard/product/views.py
@@ -111,24 +111,37 @@ def product_list(request):
     products = Product.objects.prefetch_related('images')
     products = products.order_by('name')
     product_classes = ProductClass.objects.all()
-
-    form = forms.ProductClassSelectorForm(
-        request.POST or None, product_classes=product_classes)
-    if form.is_valid():
-        return redirect(
-            'dashboard:product-add', class_pk=form.cleaned_data['product_cls'])
     product_filter = ProductFilter(request.GET, queryset=products)
     products = get_paginator_items(
         product_filter.qs, settings.DASHBOARD_PAGINATE_BY,
         request.GET.get('page'))
     ctx = {
-        'bulk_action_form': forms.ProductBulkUpdate(), 'form': form,
+        'bulk_action_form': forms.ProductBulkUpdate(),
         'products': products, 'product_classes': product_classes,
         'filter': product_filter,
     }
     return TemplateResponse(request, 'dashboard/product/list.html', ctx)
 
 
+@staff_member_required
+@permission_required('product.edit_product')
+def product_select_classes(request):
+    """
+    View for add product modal embedded in the product list view.
+    """
+    form = forms.ProductClassSelectorForm(request.POST or None)
+    status = 200
+    if form.is_valid():
+        return redirect(
+            'dashboard:product-add',
+            class_pk=form.cleaned_data.get('product_cls').pk)
+    elif form.errors:
+        status = 400
+    ctx = {'form': form}
+    template = 'product/modal/add_product.html'
+    return TemplateResponse(request, template, ctx, status=status)
+
+
 @staff_member_required
 @permission_required('product.edit_product')
 def product_create(request, class_pk):


Test patch:
diff --git a/tests/dashboard/test_product.py b/tests/dashboard/test_product.py
--- a/tests/dashboard/test_product.py
+++ b/tests/dashboard/test_product.py
@@ -613,3 +613,15 @@ def test_product_list_pagination_with_filters(admin_client, product_list):
     response = admin_client.get(url, data)
     assert response.status_code == 200
     assert list(response.context['products'])[0] == product_list[1]
+
+
+def test_product_select_classes(admin_client, product_list):
+    url = reverse('dashboard:product-select-classes')
+    response = admin_client.get(url)
+    assert response.status_code == HTTP_STATUS_OK
+
+    data = {'product_cls': product_list[0].product_class.pk}
+    response = admin_client.post(url, data)
+    assert response.get('location') == reverse(
+        'dashboard:product-add', args=[product_list[0].product_class.pk])
+    assert response.status_code == HTTP_REDIRECTION