From e7974a21a7fbed4276f464e340a4a01b516d0a38 Mon Sep 17 00:00:00 2001 From: franck Date: Mon, 23 Sep 2013 11:41:14 +0200 Subject: [PATCH] Finished combination creation GUI --- .../Thelia/Config/Resources/routing/admin.xml | 13 + .../Controller/Admin/ProductController.php | 70 +++ .../default/ajax/product-attributes-tab.html | 255 ++++----- .../default/ajax/product-related-tab.html | 516 +++++++++--------- .../default/includes/inner-form-toolbar.html | 4 +- .../default/includes/product-details-tab.html | 262 +++++---- templates/admin/default/product-edit.html | 87 +++ templates/admin/default/template-edit.html | 20 +- 8 files changed, 740 insertions(+), 487 deletions(-) diff --git a/core/lib/Thelia/Config/Resources/routing/admin.xml b/core/lib/Thelia/Config/Resources/routing/admin.xml index 5b40ff65a..d2b9e4ffb 100755 --- a/core/lib/Thelia/Config/Resources/routing/admin.xml +++ b/core/lib/Thelia/Config/Resources/routing/admin.xml @@ -223,6 +223,19 @@ Thelia\Controller\Admin\ProductController::updateAttributesAndFeaturesAction + + + + Thelia\Controller\Admin\ProductController::getAttributeValuesAction + xml|json + + + + + Thelia\Controller\Admin\ProductController::addAttributeValueToCombinationAction + xml|json + + diff --git a/core/lib/Thelia/Controller/Admin/ProductController.php b/core/lib/Thelia/Controller/Admin/ProductController.php index f3b1b088e..adc3da942 100644 --- a/core/lib/Thelia/Controller/Admin/ProductController.php +++ b/core/lib/Thelia/Controller/Admin/ProductController.php @@ -51,6 +51,8 @@ use Thelia\Core\Event\ProductSetTemplateEvent; use Thelia\Model\Base\ProductSaleElementsQuery; use Thelia\Core\Event\ProductAddCategoryEvent; use Thelia\Core\Event\ProductDeleteCategoryEvent; +use Thelia\Model\AttributeQuery; +use Thelia\Model\AttributeAvQuery; /** * Manages products @@ -668,4 +670,72 @@ class ProductController extends AbstractCrudController $this->redirectToEditionTemplate(); } + + // -- Product combination management --------------------------------------- + + public function getAttributeValuesAction($productId, $attributeId) { + + $result = array(); + + // Get attribute for this product + $attribute = AttributeQuery::create()->findPk($attributeId); + + if ($attribute !== null) { + + $values = AttributeAvQuery::create() + ->joinWithI18n($this->getCurrentEditionLocale()) + ->filterByAttribute($attribute) + ->find(); + ; + + if ($values !== null) { + foreach($values as $value) { + $result[] = array('id' => $value->getId(), 'title' => $value->getTitle()); + } + } + } + + return $this->jsonResponse(json_encode($result)); + } + + public function addAttributeValueToCombinationAction($productId, $attributeAvId, $combination) { + $result = array(); + + // Get attribute for this product + $attributeAv = AttributeAvQuery::create()->joinWithI18n($this->getCurrentEditionLocale())->findPk($attributeAvId); + + if ($attributeAv !== null) { + + $addIt = true; + + // Check if this attribute is not already present + $combinationArray = explode(',', $combination); + + foreach ($combinationArray as $id) { + + $attrAv = AttributeAvQuery::create()->joinWithI18n($this->getCurrentEditionLocale())->findPk($id); + + if ($attrAv !== null) { + + if ($attrAv->getAttributeId() == $attributeAv->getAttributeId()) { + + $attribute = AttributeQuery::create()->joinWithI18n($this->getCurrentEditionLocale())->findPk($attributeAv->getAttributeId()); + + $result['error'] = $this->getTranslator()->trans( + 'A value for attribute "%name" is already present in the combination', + array('%name' => $attribute->getTitle()) + ); + + $addIt = false; + } + + $result[] = array('id' => $attrAv->getId(), 'title' => $attrAv->getTitle()); + } + } + + if ($addIt) $result[] = array('id' => $attributeAv->getId(), 'title' => $attributeAv->getTitle()); + } + + return $this->jsonResponse(json_encode($result)); + } } diff --git a/templates/admin/default/ajax/product-attributes-tab.html b/templates/admin/default/ajax/product-attributes-tab.html index 2c05217ab..2a62da2e3 100644 --- a/templates/admin/default/ajax/product-attributes-tab.html +++ b/templates/admin/default/ajax/product-attributes-tab.html @@ -11,7 +11,7 @@
-
+

{intl l="To use features or attributes on this product, please select a product template. You can define product templates in the configuration section of the administration." tpl_mgmt_url={url path='/admin/configuration/templates'} @@ -45,7 +45,6 @@

-

{intl l='Product Attributes and Features'}

@@ -64,165 +63,169 @@
-
-

{intl l='Product Attributes'}

+
+
+

{intl l='Product Attributes'}

-

- {if $TEMPLATE} - {intl - l="You can change template attributes and their positions in the template configuration page." - tpl_mgmt_url={url path='/admin/configuration/templates/update' template_id=$TEMPLATE} - } - {else} - {intl - l="You can change attributes and their positions in the attributes configuration page." - tpl_mgmt_url={url path='/admin/configuration/attributes'} - } - {/if} -

+

+ {if $TEMPLATE} + {intl + l="You can change template attributes and their positions in the template configuration page." + tpl_mgmt_url={url path='/admin/configuration/templates/update' template_id=$TEMPLATE} + } + {else} + {intl + l="You can change attributes and their positions in the attributes configuration page." + tpl_mgmt_url={url path='/admin/configuration/attributes'} + } + {/if} +

-
- - - - - +
+
{intl l='ID'}{intl l='Attribute Name'}
+ + + + - {module_include location='product_attributes_table_header'} - - + {module_include location='product_attributes_table_header'} + + - - {loop name="product-attributes" type="attribute" order="manual" product=$product_id backend_context="1" lang="$edit_language_id"} - - + + {loop name="product-attributes" type="attribute" order="manual" product=$product_id backend_context="1" lang="$edit_language_id"} + + - + - {module_include location='product_features_table_row'} - - {/loop} + {module_include location='product_features_table_row'} + + {/loop} - {elseloop rel="product-attributes"} - - - - {/elseloop} - -
{intl l='ID'}{intl l='Attribute Name'}
{$ID}
{$ID}{$TITLE}{$TITLE}
-
- {intl l="This product template does not contains any features"} -
-
-
-
-
+ {elseloop rel="product-attributes"} + + +
+ {intl l="This product template does not contains any features"} +
+ + + {/elseloop} + + +
+
+
+
{* -- Begin features management ---------------------------------- *}
-
-

{intl l='Product Features'}

+
+
+

{intl l='Product Features'}

-

- {if $TEMPLATE} - {intl - l="You can change templates features and their positions in the template configuration page." - tpl_mgmt_url={url path='/admin/configuration/templates/update' template_id=$TEMPLATE} - } - {else} - {intl - l="You can change feature and their positions in the features configuration page." - tpl_mgmt_url={url path='/admin/configuration/features'} - } - {/if} -

+

+ {if $TEMPLATE} + {intl + l="You can change templates features and their positions in the template configuration page." + tpl_mgmt_url={url path='/admin/configuration/templates/update' template_id=$TEMPLATE} + } + {else} + {intl + l="You can change feature and their positions in the features configuration page." + tpl_mgmt_url={url path='/admin/configuration/features'} + } + {/if} +

-
- - - - - - +
+
{intl l='ID'}{intl l='Feature Name'}{intl l='Feature value for this product'}
+ + + + + - {module_include location='product_features_table_header'} + {module_include location='product_features_table_header'} - - + + - - {loop name="product-features" type="feature" order="manual" product=$product_id backend_context="1" lang="$edit_language_id"} - - + + {loop name="product-features" type="feature" order="manual" product=$product_id backend_context="1" lang="$edit_language_id"} + + - + - + + {/elseloop} + - {module_include location='product_features_table_row'} + {module_include location='product_features_table_row'} - - {/loop} + + {/loop} - {elseloop rel="product-features"} - - - - {/elseloop} - -
{intl l='ID'}{intl l='Feature Name'}{intl l='Feature value for this product'}
{$ID}
{$ID}{$TITLE}{$TITLE} - {* Multiple values *} + + {* Multiple values *} - {ifloop rel="product-features-av"} + {ifloop rel="product-features-av"} - {* load all selected values in an array to speed up things a little *} + {* load all selected values in an array to speed up things a little *} - {$selected = array()} + {$selected = array()} - {loop name="free-text-value" exclude_free_text="true" type="feature_value" product=$product_id feature=$ID backend_context="1" lang="$edit_language_id"} - {$selected[] = $FEATURE_AV_ID} - {/loop} + {loop name="free-text-value" exclude_free_text="true" type="feature_value" product=$product_id feature=$ID backend_context="1" lang="$edit_language_id"} + {$selected[] = $FEATURE_AV_ID} + {/loop} - {capture "select_options"} - {loop name="product-features-av" type="feature-availability" feature=$ID order="manual" backend_context="1" lang="$edit_language_id"} - + {capture "select_options"} + {loop name="product-features-av" type="feature-availability" feature=$ID order="manual" backend_context="1" lang="$edit_language_id"} + - {$options_count = $LOOP_COUNT} {* LOOP_COUNT is only available inside the loop ! *} - {/loop} - {/capture} + {$options_count = $LOOP_COUNT} {* LOOP_COUNT is only available inside the loop ! *} + {/loop} + {/capture} -
- -
+
+ +
- - {intl l='Use Ctrl+click to select more than one value. You can also clear selected values.' id=$ID} - - {/ifloop} + + {intl l='Use Ctrl+click to select more than one value. You can also clear selected values.' id=$ID} + + {/ifloop} - {* Free text *} + {* Free text *} - {elseloop rel="product-features-av"} - {* Get the free text value *} + {elseloop rel="product-features-av"} + {* Get the free text value *} - {loop name="free-text-value" exclude_feature_availability="1" type="feature_value" product=$product_id feature=$ID backend_context="1" lang="$edit_language_id"} - {$feature_value=$FREE_TEXT_VALUE} - {/loop} + {loop name="free-text-value" exclude_feature_availability="1" type="feature_value" product=$product_id feature=$ID backend_context="1" lang="$edit_language_id"} + {$feature_value=$FREE_TEXT_VALUE} + {/loop} - - {/elseloop} -
-
- {intl l="This product template does not contains any features"} -
-
-
-
+ {elseloop rel="product-features"} + + +
+ {intl l="This product template does not contains any features"} +
+ + + {/elseloop} + + +
+
+
diff --git a/templates/admin/default/ajax/product-related-tab.html b/templates/admin/default/ajax/product-related-tab.html index 977ecf83c..3c909b390 100644 --- a/templates/admin/default/ajax/product-related-tab.html +++ b/templates/admin/default/ajax/product-related-tab.html @@ -14,115 +14,117 @@ {* -- Begin related content management ------------------------------ *}
-
- -
- - - - +
+
{intl l='ID'}
+ + + - + - + - {module_include location='product_contents_table_header'} + {module_include location='product_contents_table_header'} - - - + + + - - {loop name="assigned_contents" type="associated_content" product="$product_id" backend_context="1" lang="$edit_language_id"} - - + + {loop name="assigned_contents" type="associated_content" product="$product_id" backend_context="1" lang="$edit_language_id"} + + - + - + - {module_include location='product_contents_table_row'} + {module_include location='product_contents_table_row'} - - - {/loop} + + + {/loop} - {elseloop rel="assigned_contents"} - - - - {/elseloop} - -
{intl l='ID'}{intl l='Content title'}{intl l='Content title'}{intl l='Position'}{intl l='Position'}{intl l="Actions"}
{intl l="Actions"}
{$ID}
{$ID} - {$TITLE} - + {$TITLE} + - {admin_position_block - permission="admin.products.edit" - path={url path='/admin/product/update-content-position' product_id=$product_id current_tab="related"} - url_parameter="content_id" - in_place_edit_class="contentPositionChange" - position=$POSITION - id=$ID - } - + {admin_position_block + permission="admin.products.edit" + path={url path='/admin/product/update-content-position' product_id=$product_id current_tab="related"} + url_parameter="content_id" + in_place_edit_class="contentPositionChange" + position=$POSITION + id=$ID + } + -
- {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.product.content.delete"} - - - - {/loop} -
-
+
+ {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.product.content.delete"} + + + + {/loop} +
+
-
- {intl l="This product contains no contents"} -
-
+ {elseloop rel="assigned_contents"} + + +
+ {intl l="This product contains no contents"} +
+ + + {/elseloop} + + +
@@ -131,117 +133,119 @@ {* -- Begin accessories management ---------------------------------- *}
-
-
+
+
+ -

{intl l='Product accessories'}

-

{intl l='Define here this product\'s accessories'}

+

{intl l='Product accessories'}

+

{intl l='Define here this product\'s accessories'}

- - + + - {ifloop rel="categories"} -
- + {ifloop rel="categories"} +
+ - {intl l='Select a category to get its products'} -
+ {intl l='Select a category to get its products'} +
-
-
- - - - -
+
+
+ + + + +
- {intl l='Select a product and click (+) to add it as an accessory'} -
+ {intl l='Select a product and click (+) to add it as an accessory'} +
-
-
- {intl l="No available product in this category"} -
-
+
+
+ {intl l="No available product in this category"} +
+
- {/ifloop} + {/ifloop} - {elseloop rel="categories"} -
{intl l="No categories found"}
- {/elseloop} + {elseloop rel="categories"} +
{intl l="No categories found"}
+ {/elseloop} - -
+ +
-
- - - - +
+
{intl l='ID'}
+ + + - + - + - {module_include location='product_accessories_table_header'} + {module_include location='product_accessories_table_header'} - - - + + + - - {loop name="assigned_accessories" order="accessory" type="accessory" product="$product_id" backend_context="1" lang="$edit_language_id"} - - + + {loop name="assigned_accessories" order="accessory" type="accessory" product="$product_id" backend_context="1" lang="$edit_language_id"} + + - + - + - {module_include location='product_accessories_table_row'} + {module_include location='product_accessories_table_row'} - - - {/loop} + + + {/loop} - {elseloop rel="assigned_accessories"} - - - - {/elseloop} - -
{intl l='ID'}{intl l='Accessory title'}{intl l='Accessory title'}{intl l='Position'}{intl l='Position'}{intl l="Actions"}
{intl l="Actions"}
{$ID}
{$ID} - {$TITLE} - + {$TITLE} + - {admin_position_block - permission="admin.products.edit" - path={url path='/admin/product/update-accessory-position' product_id=$product_id current_tab="related"} - url_parameter="accessory_id" - in_place_edit_class="accessoryPositionChange" - position=$POSITION - id=$ID - } - + {admin_position_block + permission="admin.products.edit" + path={url path='/admin/product/update-accessory-position' product_id=$product_id current_tab="related"} + url_parameter="accessory_id" + in_place_edit_class="accessoryPositionChange" + position=$POSITION + id=$ID + } + -
- {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.product.accessory.delete"} - - - - {/loop} -
-
+
+ {loop type="auth" name="can_create" roles="ADMIN" permissions="admin.product.accessory.delete"} + + + + {/loop} +
+
-
- {intl l="This product contains no accessories"} -
-
-
+ {elseloop rel="assigned_accessories"} + + +
+ {intl l="This product contains no accessories"} +
+ + + {/elseloop} + + +
+
{* -- End accessories management ------------------------------------ *} @@ -253,99 +257,101 @@ {* -- Begin categories management ----------------------------------- *}
-
- -
- - - - +
+
{intl l='ID'}
+ + + - + - {module_include location='product_categories_table_header'} + {module_include location='product_categories_table_header'} - - - + + + - - {loop name="additional_categories" type="category" product=$product_id exclude=$DEFAULT_CATEGORY backend_context="1" lang="$edit_language_id"} - - + + {loop name="additional_categories" type="category" product=$product_id exclude=$DEFAULT_CATEGORY backend_context="1" lang="$edit_language_id"} + + - + - {module_include location='product_categories_table_row'} + {module_include location='product_categories_table_row'} - - - {/loop} + + + {/loop} - {elseloop rel="additional_categories"} - - - - {/elseloop} - -
{intl l='ID'}{intl l='Category title'}{intl l='Category title'}{intl l="Actions"}
{intl l="Actions"}
{$ID}
{$ID} - {$TITLE} - + {$TITLE} + -
- {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.product.category.delete"} - - - - {/loop} -
-
+
+ {loop type="auth" name="can_delete" roles="ADMIN" permissions="admin.product.category.delete"} + + + + {/loop} +
+
-
- {intl l="This product doesn't belong to any additional category."} -
-
-
+ {elseloop rel="additional_categories"} + + +
+ {intl l="This product doesn't belong to any additional category."} +
+ + + {/elseloop} + + +
+
{* -- End categories management ------------------------------------- *}
@@ -473,7 +479,7 @@ $(function() { } }); - // Load content on folder selection + // Load accessory on category selection $('#accessory_category_id').change(function(event) { var val = $(this).val(); diff --git a/templates/admin/default/includes/inner-form-toolbar.html b/templates/admin/default/includes/inner-form-toolbar.html index 80cf4c092..96e0e65ab 100755 --- a/templates/admin/default/includes/inner-form-toolbar.html +++ b/templates/admin/default/includes/inner-form-toolbar.html @@ -22,8 +22,8 @@ Parameters: - {if $show_currencies == true}
+ {if $show_currencies == true}
@@ -35,8 +35,8 @@ Parameters:
-
{/if} +
{if $hide_submit_buttons != true} diff --git a/templates/admin/default/includes/product-details-tab.html b/templates/admin/default/includes/product-details-tab.html index a8224a824..46ddfed86 100644 --- a/templates/admin/default/includes/product-details-tab.html +++ b/templates/admin/default/includes/product-details-tab.html @@ -42,125 +42,132 @@ {* -- Pricing ------------------------------------------------------- *}
+
+

{intl l='Pricing'}

-

{intl l='Pricing'}

+

-

+ {form_field form=$form field='price'} +
+ - {form_field form=$form field='price'} -
- +
+ + {$currency_symbol} +
+
+ {/form_field} -
- - {$currency_symbol} -
-
- {/form_field} + {form_field form=$form field='tax_rule'} +
+ +
+ +
- {form_field form=$form field='tax_rule'} -
- -
- -
+
+ {/form_field} -
- {/form_field} + {form_field form=$form field='price_with_tax'} +
+ +
+ + {$currency_symbol} +
+
+ {/form_field} - {form_field form=$form field='price_with_tax'} -
- -
- - {$currency_symbol} -
-
- {/form_field} - - {module_include location='product_details_pricing_form'} + {module_include location='product_details_pricing_form'} +
{* -- Promotion ------------------------------------------------- *}
+
+

{intl l='Promotion'}

-

{intl l='Promotion'}

+ {form_field form=$form field='sale_price'} +
+ - {form_field form=$form field='sale_price'} -
- +
+ + {$currency_symbol} +
+
+ {/form_field} -
- - {$currency_symbol} -
-
- {/form_field} + {form_field form=$form field='onsale'} +
+
+ +
+
+ {/form_field} - {form_field form=$form field='onsale'} -
-
- -
-
- {/form_field} + {form_field form=$form field='isnew'} +
+
+ +
+
+ {/form_field} - {form_field form=$form field='isnew'} -
-
- -
-
- {/form_field} - - {module_include location='product_details_promotion_form'} + {module_include location='product_details_promotion_form'} +
{* -- Shipping -------------------------------------------------- *}
-

{intl l='Shipping'}

+
+

{intl l='Shipping'}

- {form_field form=$form field='weight'} -
- + {form_field form=$form field='weight'} +
+ -
- - {intl l="Kg"} +
+ + {intl l="Kg"} +
+
+ {/form_field} + + {module_include location='product_details_shipping_form'} + +

{intl l='Quantity'}

+ + {form_field form=$form field='quantity'} +
+ + +
+ +
-
- {/form_field} + {/form_field} -

{intl l='Quantity'}

- - {form_field form=$form field='quantity'} -
- - -
- -
-
- {/form_field} - - {module_include location='product_details_shipping_form'} -
+ {module_include location='product_details_quantity_form'} +
+
+ {/form} @@ -171,11 +178,76 @@

{intl l='Attribute Combinations'}

-
- {intl l="This product has no attribute combination"} -
+ {module_include location='product_before_combinations'} - {* com *} - {* row *} + {ifloop rel="product-attributes"} +
+
+

{intl l='Create a new combination'}

+
+ + + {intl l='Select an attribute and click (+) to view available values'} +
+ + +
+
+ {* *} + + + + + + +
+ + {intl l='Select a value click (+) to add it to the combination'} +
+ +
+
+ {intl l="No available value for this attribute"} +
+
+ +
+
+ + + +
+ {intl l='To remove a value from the combination, select it and click "remove"'} + +
+ +
+
+
+ +
+
+ {/ifloop} + + {elseloop rel="product-attributes"} +
+ {intl l="No attributes are attached to this product."} +
+ {/elseloop} + + {module_include location='product_after_combinations'} + + {* com *} + {* row *} \ No newline at end of file diff --git a/templates/admin/default/product-edit.html b/templates/admin/default/product-edit.html index 826b5746d..d9cda2f8d 100644 --- a/templates/admin/default/product-edit.html +++ b/templates/admin/default/product-edit.html @@ -144,6 +144,93 @@ $(function() { // Load active tab $('.nav-tabs a[href="#{$current_tab}"]').trigger("click"); + + // -- Product details management tab --------------------------------------- + + // Load value on attribute selection + $('#attribute_id').change(function(event) { + var val = $(this).val(); + + if (val != "") { + $.ajax({ + url : '{url path="/admin/product/$product_id/attribute-values/"}' + $(this).val() + '.xml', + type : 'get', + dataType : 'json', + success : function(json) { + $('#attribute_value_id :not(:first-child)').remove(); + + var have_content = false; + + $.each(json, function(idx, value) { + $('#attribute_value_id').append($('