Commit 2b3158498c4a5e029650159473412701eb9eaa15
1 parent
f540c70b
-Product card (without video)
Showing
19 changed files
with
271 additions
and
36 deletions
Show diff stats
controllers/ManageController.php
... | ... | @@ -2,6 +2,7 @@ |
2 | 2 | |
3 | 3 | namespace artweb\artbox\ecommerce\controllers; |
4 | 4 | |
5 | + use artweb\artbox\ecommerce\models\ProductVideo; | |
5 | 6 | use artweb\artbox\language\models\Language; |
6 | 7 | use artweb\artbox\ecommerce\models\Export; |
7 | 8 | use artweb\artbox\ecommerce\models\Import; |
... | ... | @@ -147,6 +148,7 @@ |
147 | 148 | 'model' => $model, |
148 | 149 | 'modelLangs' => $model->modelLangs, |
149 | 150 | 'groups' => $groups, |
151 | + 'videos' => !empty( $model->videos ) ? $model->videos : [ new ProductVideo() ], | |
150 | 152 | ] |
151 | 153 | ); |
152 | 154 | } |
... | ... | @@ -354,7 +356,7 @@ |
354 | 356 | throw new \HttpRequestException('Must be AJAX'); |
355 | 357 | } |
356 | 358 | } |
357 | - | |
359 | + | |
358 | 360 | /** |
359 | 361 | * Perform export |
360 | 362 | * |
... | ... | @@ -397,7 +399,7 @@ |
397 | 399 | if (( $model = Product::find() |
398 | 400 | ->where([ 'id' => $id ]) |
399 | 401 | ->with('lang') |
400 | - ->one() ) !== null | |
402 | + ->one() ) !== NULL | |
401 | 403 | ) { |
402 | 404 | return $model; |
403 | 405 | } else { | ... | ... |
models/Product.php
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | * |
22 | 22 | * @property integer $brand_id |
23 | 23 | * @property integer $id |
24 | + * @property ProductVideo[] $videos | |
24 | 25 | * @property Category $category |
25 | 26 | * @property Category[] $categories |
26 | 27 | * @property ProductVariant $variant |
... | ... | @@ -340,8 +341,12 @@ |
340 | 341 | public function getFullName():string |
341 | 342 | { |
342 | 343 | $name = ''; |
343 | - if (!empty($this->category->lang->category_synonym)) $name = $name . $this->category->lang->category_synonym . ' '; | |
344 | - if (!empty($this->brand)) $name = $name . $this->brand->lang->title . ' '; | |
344 | + if (!empty( $this->category->lang->category_synonym )) { | |
345 | + $name = $name . $this->category->lang->category_synonym . ' '; | |
346 | + } | |
347 | + if (!empty( $this->brand )) { | |
348 | + $name = $name . $this->brand->lang->title . ' '; | |
349 | + } | |
345 | 350 | $name .= $this->lang->title; |
346 | 351 | return $name; |
347 | 352 | } |
... | ... | @@ -455,6 +460,11 @@ |
455 | 460 | return $groups; |
456 | 461 | } |
457 | 462 | |
463 | + public function getVideos() | |
464 | + { | |
465 | + return $this->hasMany(ProductVideo::className(), [ 'product_id' => 'id' ]); | |
466 | + } | |
467 | + | |
458 | 468 | /** |
459 | 469 | * Get Stock query where current Product is in stock |
460 | 470 | * | ... | ... |
models/ProductVariant.php
... | ... | @@ -67,6 +67,10 @@ |
67 | 67 | */ |
68 | 68 | class ProductVariant extends ActiveRecord |
69 | 69 | { |
70 | + | |
71 | + public $customOption = []; | |
72 | + | |
73 | + | |
70 | 74 | /** |
71 | 75 | * @var int[] $options |
72 | 76 | */ |
... | ... | @@ -113,7 +117,7 @@ |
113 | 117 | 'model' => ProductImage::className(), |
114 | 118 | 'config' => [ |
115 | 119 | 'caption' => 'image', |
116 | - 'delete_action' => '/product/variant/delete-image', | |
120 | + 'delete_action' => 'variant/delete-image', | |
117 | 121 | 'id' => 'id', |
118 | 122 | ], |
119 | 123 | ], |
... | ... | @@ -275,6 +279,28 @@ |
275 | 279 | return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ]) |
276 | 280 | ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ]); |
277 | 281 | } |
282 | + | |
283 | + /** | |
284 | + * Get one variant's option whith needed conditions, or random if condition is empty | |
285 | + * | |
286 | + * @param array $conditions | |
287 | + * | |
288 | + * @return ActiveQuery | |
289 | + */ | |
290 | + public function getOption(array $conditions = []) | |
291 | + { | |
292 | + $query = $this->hasOne(TaxOption::className(), [ 'id' => 'option_id' ]) | |
293 | + ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ]); | |
294 | + foreach ($conditions as $condition) | |
295 | + { | |
296 | + if (!empty($condition) && is_array($condition)) | |
297 | + { | |
298 | + $query->andFilterWhere($condition); | |
299 | + } | |
300 | + } | |
301 | + | |
302 | + return $query; | |
303 | + } | |
278 | 304 | |
279 | 305 | /** |
280 | 306 | * Get TaxOptions with preloaded TaxGroups for current ProductVariant |
... | ... | @@ -307,13 +333,15 @@ |
307 | 333 | { |
308 | 334 | $this->options = $values; |
309 | 335 | } |
310 | - | |
336 | + | |
311 | 337 | /** |
312 | 338 | * Get all TaxGroups for current ProductVariant filled with $customOptions that satisfy current ProductVariant |
313 | 339 | * |
314 | - * @return TaxGroup[] | |
340 | + * @param array $conditions | |
341 | + * | |
342 | + * @return \artweb\artbox\ecommerce\models\TaxGroup[] | |
315 | 343 | */ |
316 | - public function getProperties() | |
344 | + public function getProperties(array $conditions = []) | |
317 | 345 | { |
318 | 346 | $groups = $options = []; |
319 | 347 | foreach ($this->getOptions() |
... | ... | @@ -324,11 +352,18 @@ |
324 | 352 | */ |
325 | 353 | $options[ $option->tax_group_id ][] = $option; |
326 | 354 | } |
327 | - foreach (TaxGroup::find() | |
355 | + $query = TaxGroup::find() | |
328 | 356 | ->where([ 'tax_group.id' => array_keys($options) ]) |
329 | 357 | ->orderBy([ 'sort' => SORT_ASC ]) |
330 | - ->with('lang') | |
331 | - ->all() as $group) { | |
358 | + ->with('lang'); | |
359 | + | |
360 | + if (!empty($conditions)) { | |
361 | + foreach ($conditions as $condition) { | |
362 | + $query->andFilterWhere($condition); | |
363 | + } | |
364 | + } | |
365 | + foreach ( | |
366 | + $query->all() as $group) { | |
332 | 367 | /** |
333 | 368 | * @var TaxGroup $group |
334 | 369 | */ | ... | ... |
1 | +<?php | |
2 | + | |
3 | + namespace artweb\artbox\ecommerce\models; | |
4 | + | |
5 | + use yii\db\ActiveRecord; | |
6 | + | |
7 | + /** | |
8 | + * This is the model class for table "product_video". | |
9 | + * | |
10 | + * @property integer $id | |
11 | + * @property integer $product_id | |
12 | + * @property string $url | |
13 | + * @property Product $product | |
14 | + */ | |
15 | + class ProductVideo extends ActiveRecord | |
16 | + { | |
17 | + /** | |
18 | + * @inheritdoc | |
19 | + */ | |
20 | + public static function tableName() | |
21 | + { | |
22 | + return 'product_video'; | |
23 | + } | |
24 | + | |
25 | + /** | |
26 | + * @inheritdoc | |
27 | + */ | |
28 | + public function rules() | |
29 | + { | |
30 | + return [ | |
31 | + [ | |
32 | + [ 'product_id' ], | |
33 | + 'integer', | |
34 | + ], | |
35 | + [ | |
36 | + [ 'url' ], | |
37 | + 'string', | |
38 | + 'max' => 255, | |
39 | + ], | |
40 | + [ | |
41 | + [ 'product_id' ], | |
42 | + 'exist', | |
43 | + 'skipOnError' => true, | |
44 | + 'targetClass' => Product::className(), | |
45 | + 'targetAttribute' => [ 'product_id' => 'id' ], | |
46 | + ], | |
47 | + ]; | |
48 | + } | |
49 | + | |
50 | + /** | |
51 | + * @inheritdoc | |
52 | + */ | |
53 | + public function attributeLabels() | |
54 | + { | |
55 | + return [ | |
56 | + 'id' => \Yii::t('app', 'ID'), | |
57 | + 'product_id' => \Yii::t('app', 'Product ID'), | |
58 | + 'url' => \Yii::t('app', 'Url'), | |
59 | + ]; | |
60 | + } | |
61 | + | |
62 | + /** | |
63 | + * @return \yii\db\ActiveQuery | |
64 | + */ | |
65 | + public function getProduct() | |
66 | + { | |
67 | + return $this->hasOne(Product::className(), [ 'id' => 'product_id' ]); | |
68 | + } | |
69 | + } | ... | ... |
models/TaxGroup.php
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | * @property TaxOption[] $options |
25 | 25 | * @property TaxOption[] $customOptions |
26 | 26 | * @property string $alias |
27 | + * @property integer $position | |
27 | 28 | * * From language behavior * |
28 | 29 | * @property TaxGroupLang $lang |
29 | 30 | * @property TaxGroupLang[] $langs |
... | ... | @@ -94,6 +95,7 @@ |
94 | 95 | [ |
95 | 96 | 'level', |
96 | 97 | 'sort', |
98 | + 'position', | |
97 | 99 | ], |
98 | 100 | 'integer', |
99 | 101 | ], |
... | ... | @@ -116,6 +118,7 @@ |
116 | 118 | 'display' => 'Display', |
117 | 119 | 'is_menu' => 'Отображать в меню', |
118 | 120 | 'level' => 'уровень', |
121 | + 'ppsition' => 'Позиция', | |
119 | 122 | ]; |
120 | 123 | } |
121 | 124 | ... | ... |
views/manage/_form.php
1 | 1 | <?php |
2 | 2 | |
3 | + use artweb\artbox\ecommerce\models\ProductVideo; | |
3 | 4 | use artweb\artbox\language\widgets\LanguageForm; |
4 | 5 | use artweb\artbox\ecommerce\models\Brand; |
5 | 6 | use artweb\artbox\ecommerce\models\ProductLang; |
6 | 7 | use artweb\artbox\ecommerce\models\TaxGroup; |
8 | + use wbraganca\dynamicform\DynamicFormWidget; | |
7 | 9 | use yii\db\ActiveQuery; |
8 | 10 | use yii\helpers\Html; |
9 | 11 | use yii\widgets\ActiveForm; |
... | ... | @@ -11,14 +13,31 @@ |
11 | 13 | use artweb\artbox\components\artboxtree\ArtboxTreeHelper; |
12 | 14 | use artweb\artbox\ecommerce\helpers\ProductHelper; |
13 | 15 | use kartik\select2\Select2; |
16 | + use yii\web\View; | |
14 | 17 | |
15 | 18 | /** |
16 | - * @var yii\web\View $this | |
19 | + * @var yii\web\View $this | |
17 | 20 | * @var artweb\artbox\ecommerce\models\Product $model |
18 | - * @var ProductLang[] $modelLangs | |
19 | - * @var yii\widgets\ActiveForm $form | |
20 | - * @var ActiveQuery $groups | |
21 | + * @var ProductLang[] $modelLangs | |
22 | + * @var yii\widgets\ActiveForm $form | |
23 | + * @var ActiveQuery $groups | |
24 | + * @var ProductVideo[] $videos | |
21 | 25 | */ |
26 | + | |
27 | + $js = ' | |
28 | +$(".dynamicform_wrapper").on("beforeDelete", function(e, item) { | |
29 | + if (! confirm("Are you sure you want to delete this item?")) { | |
30 | + return false; | |
31 | + } | |
32 | + return true; | |
33 | +}); | |
34 | + | |
35 | +$(".dynamicform_wrapper").on("limitReached", function(e, item) { | |
36 | + alert("Limit reached"); | |
37 | +}); | |
38 | +'; | |
39 | + | |
40 | + $this->registerJs($js, View::POS_END); | |
22 | 41 | ?> |
23 | 42 | |
24 | 43 | <div class="product-form"> |
... | ... | @@ -39,6 +58,68 @@ |
39 | 58 | <?= $form->field($model, 'video') |
40 | 59 | ->textarea(); ?> |
41 | 60 | |
61 | + <?php DynamicFormWidget::begin( | |
62 | + [ | |
63 | + 'widgetContainer' => 'dynamicform_wrapper', | |
64 | + // required: only alphanumeric characters plus "_" [A-Za-z0-9_] | |
65 | + 'widgetBody' => '.container-items', | |
66 | + // required: css class selector | |
67 | + 'widgetItem' => '.item', | |
68 | + // required: css class | |
69 | + 'limit' => 10, | |
70 | + // the maximum times, an element can be added (default 999) | |
71 | + 'min' => 1, | |
72 | + // 0 or 1 (default 1) | |
73 | + 'insertButton' => '.add-item', | |
74 | + // css class | |
75 | + 'deleteButton' => '.remove-item', | |
76 | + // css class | |
77 | + 'model' => $videos[ 0 ], | |
78 | + 'formId' => 'dynamic-form', | |
79 | + 'formFields' => [ | |
80 | + 'url', | |
81 | + ], | |
82 | + ] | |
83 | + ); ?> | |
84 | + | |
85 | + <div class="panel panel-default"> | |
86 | + <div class="panel-heading"> | |
87 | + <h4> | |
88 | + <i class="glyphicon glyphicon-envelope"></i> Склады | |
89 | + <button type="button" class="add-item btn btn-success btn-sm pull-right"> | |
90 | + <i class="glyphicon glyphicon-plus"></i> Add | |
91 | + </button> | |
92 | + </h4> | |
93 | + </div> | |
94 | + <div class="panel-body"> | |
95 | + <div class="container-items"><!-- widgetBody --> | |
96 | + <?php foreach ($videos as $i => $video) { ?> | |
97 | + <div class="item panel panel-default"><!-- widgetItem --> | |
98 | + <div class="panel-body"> | |
99 | +<!-- --><?php | |
100 | +// // necessary for update action. | |
101 | +// if (!$stock->isNewRecord) { | |
102 | +// echo Html::activeHiddenInput($stock, "[{$i}]stock_id"); | |
103 | +// } | |
104 | +// ?> | |
105 | + <div class="row"> | |
106 | + <div class="col-sm-5"> | |
107 | + <?= $form->field($video, "[{$i}]url") | |
108 | + ->textInput([ 'maxlength' => true ]) ?> | |
109 | + </div> | |
110 | + <div class="col-sm-2" style="margin-top: 30px"> | |
111 | + <button type="button" class="remove-item btn btn-danger btn-xs"> | |
112 | + <i class="glyphicon glyphicon-minus"></i></button> | |
113 | + </div> | |
114 | + </div><!-- .row --> | |
115 | + </div> | |
116 | + </div> | |
117 | + <?php } ?> | |
118 | + </div> | |
119 | + </div> | |
120 | + </div><!-- .panel --> | |
121 | + <?php DynamicFormWidget::end(); ?> | |
122 | + | |
42 | 123 | <?= $form->field($model, 'brand_id') |
43 | 124 | ->dropDownList( |
44 | 125 | ArrayHelper::map( | ... | ... |
views/manage/update.php
... | ... | @@ -2,20 +2,26 @@ |
2 | 2 | |
3 | 3 | use artweb\artbox\ecommerce\models\Product; |
4 | 4 | use artweb\artbox\ecommerce\models\ProductLang; |
5 | + use artweb\artbox\ecommerce\models\ProductVideo; | |
5 | 6 | use yii\db\ActiveQuery; |
6 | 7 | use yii\helpers\Html; |
7 | 8 | use yii\web\View; |
8 | 9 | |
9 | 10 | /** |
10 | - * @var View $this | |
11 | - * @var Product $model | |
12 | - * @var ProductLang[] $modelLangs | |
13 | - * @var ActiveQuery $groups | |
11 | + * @var View $this | |
12 | + * @var Product $model | |
13 | + * @var ProductLang[] $modelLangs | |
14 | + * @var ActiveQuery $groups | |
15 | + * @var ProductVideo[] $videos | |
14 | 16 | */ |
15 | 17 | |
16 | - $this->title = Yii::t('product', 'Update {modelClass}: ', [ | |
17 | - 'modelClass' => 'Product', | |
18 | - ]) . ' ' . $model->lang->title; | |
18 | + $this->title = Yii::t( | |
19 | + 'product', | |
20 | + 'Update {modelClass}: ', | |
21 | + [ | |
22 | + 'modelClass' => 'Product', | |
23 | + ] | |
24 | + ) . ' ' . $model->lang->title; | |
19 | 25 | $this->params[ 'breadcrumbs' ][] = [ |
20 | 26 | 'label' => Yii::t('product', 'Products'), |
21 | 27 | 'url' => [ 'index' ], |
... | ... | @@ -33,10 +39,14 @@ |
33 | 39 | |
34 | 40 | <h1><?= Html::encode($this->title) ?></h1> |
35 | 41 | |
36 | - <?= $this->render('_form', [ | |
37 | - 'model' => $model, | |
38 | - 'modelLangs' => $modelLangs, | |
39 | - 'groups' => $groups, | |
40 | - ]) ?> | |
42 | + <?= $this->render( | |
43 | + '_form', | |
44 | + [ | |
45 | + 'model' => $model, | |
46 | + 'modelLangs' => $modelLangs, | |
47 | + 'groups' => $groups, | |
48 | + 'videos' => $videos, | |
49 | + ] | |
50 | + ) ?> | |
41 | 51 | |
42 | 52 | </div> | ... | ... |
views/tax-group/_form.php
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | use artweb\artbox\language\widgets\LanguageForm; |
4 | 4 | use artweb\artbox\ecommerce\models\TaxGroup; |
5 | 5 | use artweb\artbox\ecommerce\models\TaxGroupLang; |
6 | + use kartik\select2\Select2; | |
6 | 7 | use yii\helpers\Html; |
7 | 8 | use yii\web\View; |
8 | 9 | use yii\widgets\ActiveForm; |
... | ... | @@ -22,11 +23,30 @@ |
22 | 23 | <?php $form = ActiveForm::begin([ 'options' => [ 'enctype' => 'multipart/form-data' ] ]); ?> |
23 | 24 | |
24 | 25 | <?= $form->field($model, 'categories') |
25 | - ->dropDownList(ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'id', 'lang.title'), [ | |
26 | - 'multiple' => true, | |
27 | - ]) | |
26 | + ->dropDownList( | |
27 | + ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'id', 'lang.title'), | |
28 | + [ | |
29 | + 'multiple' => true, | |
30 | + ] | |
31 | + ) | |
28 | 32 | ->label('Use in the following categories') ?> |
29 | 33 | |
34 | + <?= $form->field($model, 'position') | |
35 | + ->widget( | |
36 | + Select2::className(), | |
37 | + [ | |
38 | + 'data' => [ | |
39 | + 0 => 'Не отображать', | |
40 | + 1 => 'Во вкладках', | |
41 | + 2 => 'В списке', | |
42 | + ], | |
43 | + 'options' => [ 'placeholder' => 'Положение в карточке товара' ], | |
44 | + 'pluginOptions' => [ | |
45 | + 'allowClear' => true, | |
46 | + ], | |
47 | + ] | |
48 | + ) ?> | |
49 | + | |
30 | 50 | <?= $form->field($model, 'is_filter') |
31 | 51 | ->checkbox() ?> |
32 | 52 | |
... | ... | @@ -40,15 +60,20 @@ |
40 | 60 | ->textInput() ?> |
41 | 61 | |
42 | 62 | <?php |
43 | - echo LanguageForm::widget([ | |
44 | - 'modelLangs' => $modelLangs, | |
45 | - 'formView' => '@artweb/artbox/ecommerce/views/tax-group/_form_language', | |
46 | - 'form' => $form, | |
47 | - ]); | |
63 | + echo LanguageForm::widget( | |
64 | + [ | |
65 | + 'modelLangs' => $modelLangs, | |
66 | + 'formView' => '@artweb/artbox/ecommerce/views/tax-group/_form_language', | |
67 | + 'form' => $form, | |
68 | + ] | |
69 | + ); | |
48 | 70 | ?> |
49 | 71 | |
50 | 72 | <div class="form-group"> |
51 | - <?= Html::submitButton($model->isNewRecord ? Yii::t('rubrication', 'Create') : Yii::t('rubrication', 'Update'), [ 'class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary' ]) ?> | |
73 | + <?= Html::submitButton( | |
74 | + $model->isNewRecord ? Yii::t('rubrication', 'Create') : Yii::t('rubrication', 'Update'), | |
75 | + [ 'class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary' ] | |
76 | + ) ?> | |
52 | 77 | </div> |
53 | 78 | |
54 | 79 | <?php ActiveForm::end(); ?> | ... | ... |