Commit 2d107e9e171d497711b3129ece88b25676c96a15

Authored by Yarik
1 parent d7d32bb2

test

common/config/main.php
@@ -24,7 +24,10 @@ @@ -24,7 +24,10 @@
24 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field ) 24 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
25 'targetMinPixel' => 200 // Target image minimum pixel size 25 'targetMinPixel' => 200 // Target image minimum pixel size
26 ] 26 ]
27 - ] 27 + ],
  28 + 'artbox-comment' => [
  29 + 'class' => \common\modules\comment\Controller::className(),
  30 + ],
28 ], 31 ],
29 32
30 'modules' => [ 33 'modules' => [
common/models/Blog.php
@@ -87,8 +87,6 @@ @@ -87,8 +87,6 @@
87 return date('Y-m-d',strtotime($this->date_add)); 87 return date('Y-m-d',strtotime($this->date_add));
88 } 88 }
89 89
90 -  
91 -  
92 /** 90 /**
93 * @inheritdoc 91 * @inheritdoc
94 */ 92 */
common/modules/comment/Controller.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\comment;
  3 +
  4 + class Controller extends \yii\web\Controller
  5 + {
  6 + public function behaviors()
  7 + {
  8 + return [
  9 + 'verbs' => [
  10 + 'class' => \yii\filters\VerbFilter::className(),
  11 + 'actions' => [
  12 + '*' => ['post'],
  13 + ],
  14 + ],
  15 + ];
  16 + }
  17 +
  18 + public function actionDelete()
  19 + {
  20 + \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  21 + $post = \Yii::$app->request->post('Comment');
  22 + if(!empty($post['comment_id'])) {
  23 + if($model = \common\modules\comment\models\Comment::findOne($post['comment_id'])) {
  24 + /**
  25 + * @var \common\modules\comment\models\Comment $model
  26 + */
  27 + $model->scenario = is_int(\Yii::$app->user->getId()) ? \common\modules\comment\models\Comment::SCENARIO_USER : \common\modules\comment\models\Comment::SCENARIO_GUEST;
  28 + if($model->deleteComment()) {
  29 + \Yii::$app->response->data = ['text' => 'Comment marked as deleted and will be check by administrators'];
  30 + } else {
  31 + \Yii::$app->response->data = ['error' => $model->hasErrors('comment_id')?$model->getFirstError('comment_id'):'Cannot delete message'];
  32 + }
  33 + }else {
  34 + \Yii::$app->response->data = ['error' => 'Comment not found'];
  35 + };
  36 + } else {
  37 + \Yii::$app->response->data = ['error' => 'Missing comment_id'];
  38 + }
  39 + \Yii::$app->response->send();
  40 + }
  41 +
  42 + public function actionUpdate()
  43 + {
  44 + \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  45 + $post = \Yii::$app->request->post();
  46 + if(!empty($post['Comment']['comment_id'])) {
  47 + if($model = \common\modules\comment\models\Comment::findOne($post['Comment']['comment_id'])) {
  48 + /**
  49 + * @var \common\modules\comment\models\Comment $model
  50 + */
  51 + $model->scenario = is_int(\Yii::$app->user->getId()) ? \common\modules\comment\models\Comment::SCENARIO_USER : \common\modules\comment\models\Comment::SCENARIO_GUEST;
  52 + $model->load($post);
  53 + if(empty($post['Comment']['comment_pid'])) {
  54 + $model->comment_pid = null;
  55 + }
  56 + if($model->updateComment()) {
  57 + \Yii::$app->response->data = ['text' => 'Comment successfully updated'];
  58 + } else {
  59 + \Yii::$app->response->data = ['error' => $model->hasErrors()?$model->getFirstErrors():'Cannot update message'];
  60 + }
  61 + }else {
  62 + \Yii::$app->response->data = ['error' => 'Comment not found'];
  63 + };
  64 + } else {
  65 + \Yii::$app->response->data = ['error' => 'Missing comment_id'];
  66 + }
  67 + \Yii::$app->response->send();
  68 + }
  69 +
  70 + public function actionForm()
  71 + {
  72 + $post = \Yii::$app->request->post('Comment');
  73 + if(!empty($post['comment_id'])) {
  74 + $model = \common\modules\comment\models\Comment::find()->where(['comment_id' => $post['comment_id']])->with('parent', 'author')->one();
  75 + if($model) {
  76 + /**
  77 + * @var \common\modules\comment\models\Comment $model
  78 + */
  79 + $model->scenario = is_int(\Yii::$app->user->getId()) ? \common\modules\comment\models\Comment::SCENARIO_USER : \common\modules\comment\models\Comment::SCENARIO_GUEST;
  80 + if($model->checkUpdate()) {
  81 + return $this->renderAjax('@common/modules/comment/views/comment_form', [
  82 + 'model' => $model,
  83 + ]);
  84 + } else {
  85 + \Yii::$app->response->data = ['error' => 'You are not able to update this comment'];
  86 + }
  87 + }else {
  88 + \Yii::$app->response->data = ['error' => 'Comment not found'];
  89 + };
  90 + } else {
  91 + \Yii::$app->response->data = ['error' => 'Missing comment_id'];
  92 + }
  93 + \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
  94 + \Yii::$app->response->send();
  95 + }
  96 + }
0 \ No newline at end of file 97 \ No newline at end of file
common/modules/comment/Permissions.php
@@ -8,5 +8,5 @@ @@ -8,5 +8,5 @@
8 const UPDATE = 'artbox_comment.update'; 8 const UPDATE = 'artbox_comment.update';
9 const DELETE = 'artbox_comment.delete'; 9 const DELETE = 'artbox_comment.delete';
10 const UPDATE_OWN = 'artbox_comment.update_own'; 10 const UPDATE_OWN = 'artbox_comment.update_own';
11 - const DELETE_OWN = 'artbox_comment.delete.own'; 11 + const DELETE_OWN = 'artbox_comment.delete_own';
12 } 12 }
13 \ No newline at end of file 13 \ No newline at end of file
common/modules/comment/assets/CommentAsset.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\comment\assets;
  3 +
  4 + class CommentAsset extends \yii\web\AssetBundle
  5 + {
  6 + public $sourcePath = '@common/modules/comment/resources';
  7 +
  8 + public $css = [
  9 + 'comment.css',
  10 + ];
  11 +
  12 + public $js = [
  13 + 'comment.js',
  14 + ];
  15 +
  16 + public $depends = [
  17 + '\yii\web\YiiAsset',
  18 + '\yii\web\JqueryAsset',
  19 + ];
  20 +
  21 + }
0 \ No newline at end of file 22 \ No newline at end of file
common/modules/comment/interfaces/CommentInterface.php
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 public function load($data, $formName = null); 5 public function load($data, $formName = null);
6 public function formName(); 6 public function formName();
7 public function getComments($entity); 7 public function getComments($entity);
8 - public function postComment($data);  
9 - public function deleteComment($comment_id);  
10 - public function updateComment($comment_id); 8 + public function postComment();
  9 + public function deleteComment();
  10 + public function updateComment();
11 } 11 }
common/modules/comment/models/Comment.php
@@ -3,7 +3,8 @@ @@ -3,7 +3,8 @@
3 3
4 /** 4 /**
5 * Class Comment 5 * Class Comment
6 - * @property bool $guestComment 6 + * @property bool $guestComment
  7 + * @property integer $comment_id
7 * @package common\modules\comment\models 8 * @package common\modules\comment\models
8 */ 9 */
9 class Comment extends \yii\db\ActiveRecord 10 class Comment extends \yii\db\ActiveRecord
@@ -18,29 +19,87 @@ @@ -18,29 +19,87 @@
18 const SCENARIO_USER = 'user'; 19 const SCENARIO_USER = 'user';
19 const SCENARIO_GUEST = 'guest'; 20 const SCENARIO_GUEST = 'guest';
20 21
  22 + /**
  23 + * @var bool
  24 + */
  25 + public $guestComment = true;
  26 +
21 public function rules() 27 public function rules()
22 { 28 {
23 return [ 29 return [
24 [ 30 [
25 - ['text'], 31 + [
  32 + 'text',
  33 + 'user_name',
  34 + 'user_email',
  35 + ],
26 'required', 36 'required',
27 ], 37 ],
28 [ 38 [
29 - ['user_email'], 39 + [
  40 + 'rating',
  41 + ],
  42 + 'safe',
  43 + ],
  44 + [
  45 + [ 'user_email' ],
30 'email', 46 'email',
31 ], 47 ],
32 [ 48 [
33 - ['user_name'], 49 + [ 'user_name' ],
34 'string', 50 'string',
35 ], 51 ],
  52 + [
  53 + [
  54 + 'comment_id',
  55 + 'comment_pid',
  56 + ],
  57 + 'integer',
  58 + ],
  59 + [
  60 + [ 'status' ],
  61 + 'default',
  62 + 'value' => 1,
  63 + ],
  64 + [
  65 + [ 'comment_pid' ],
  66 + 'exist',
  67 + 'targetAttribute' => 'comment_id',
  68 + 'filter' => [
  69 + 'entity' => $this->entity,
  70 + ],
  71 + ],
36 ]; 72 ];
37 } 73 }
38 74
39 public function scenarios() 75 public function scenarios()
40 { 76 {
41 return [ 77 return [
42 - self::SCENARIO_GUEST => ['user_name', 'user_email', 'text'],  
43 - self::SCENARIO_USER => ['text'], 78 + self::SCENARIO_GUEST => [
  79 + 'user_name',
  80 + 'user_email',
  81 + 'text',
  82 + 'comment_pid',
  83 + ],
  84 + self::SCENARIO_USER => [
  85 + 'text',
  86 + 'comment_pid',
  87 + ],
  88 + ];
  89 + }
  90 +
  91 + /**
  92 + * @inheritdoc
  93 + */
  94 + public function behaviors()
  95 + {
  96 + return [
  97 + [
  98 + 'class' => \yii\behaviors\TimestampBehavior::className(),
  99 + 'createdAtAttribute' => 'date_add',
  100 + 'updatedAtAttribute' => 'date_update',
  101 + 'value' => new \yii\db\Expression('NOW()'),
  102 + ],
44 ]; 103 ];
45 } 104 }
46 105
@@ -55,52 +114,119 @@ @@ -55,52 +114,119 @@
55 public function attributeLabels() 114 public function attributeLabels()
56 { 115 {
57 return [ 116 return [
58 - 'text' => \Yii::t('app', 'Комментарий'),  
59 - 'user_name' => \Yii::t('app', 'Имя'), 117 + 'text' => \Yii::t('app', 'Комментарий'),
  118 + 'user_name' => \Yii::t('app', 'Имя'),
60 'user_email' => \Yii::t('app', 'Email'), 119 'user_email' => \Yii::t('app', 'Email'),
61 ]; 120 ];
62 } 121 }
63 122
64 - public function getGuestComment($entity) 123 + public function getGuestComment()
  124 + {
  125 + return $this->guestComment;
  126 + }
  127 +
  128 + public function setGuestComment($value)
65 { 129 {
66 - return true; 130 + $this->guestComment = $value;
67 } 131 }
68 132
69 public function getComments($entity) 133 public function getComments($entity)
70 { 134 {
71 - return $this->find()->where(['entity' => $this->entity]); 135 + return $this->find()
  136 + ->where([
  137 + 'entity' => $this->entity,
  138 + 'status' => 1,
  139 + ]);
72 } 140 }
73 141
74 - public function postComment($data) 142 + public function postComment()
75 { 143 {
76 - if($this->load($data) && $this->insert($data)) {  
77 - $this->clearSafe();  
78 - return true; 144 + if($this->checkCreate()) {
  145 + if($this->insert()) {
  146 + $this->clearSafe();
  147 + return true;
  148 + } else {
  149 + return false;
  150 + }
79 } else { 151 } else {
  152 + $this->addError('comment_id', 'You can`t post comment here');
80 return false; 153 return false;
81 } 154 }
82 } 155 }
83 156
84 - public function updateComment($comment_id) 157 + public function updateComment()
85 { 158 {
86 - // TODO: Implement updateComment() method. 159 + if($this->checkUpdate()) {
  160 + if(empty( $this->comment_id )) {
  161 + $this->addError('comment_id', 'Comment ID not found');
  162 + return false;
  163 + } else {
  164 + if($this->update()) {
  165 + $this->clearSafe();
  166 + return true;
  167 + } else {
  168 + return false;
  169 + }
  170 + }
  171 + } else {
  172 + $this->addError('comment_id', 'You can`t update this post');
  173 + return false;
  174 + }
87 } 175 }
88 176
89 - public function deleteComment($comment_id) 177 + public function deleteComment()
90 { 178 {
91 - // TODO: Implement deleteComment() method. 179 + if($this->checkDelete()) {
  180 + if(empty( $this->comment_id )) {
  181 + $this->addError('comment_id', 'Comment ID not found');
  182 + return false;
  183 + } else {
  184 + if($this->status == self::STATUS_DELETED) {
  185 + return false;
  186 + }
  187 + $this->status = self::STATUS_DELETED;
  188 + if($this->update()) {
  189 + $this->clearSafe();
  190 + return true;
  191 + } else {
  192 + return false;
  193 + }
  194 + }
  195 + } else {
  196 + $this->addError('comment_id', 'You can`t delete this post');
  197 + return false;
  198 + }
92 } 199 }
93 200
94 - public function checkCreate($entity) 201 + public function checkCreate()
95 { 202 {
96 - if($this->getGuestComment($entity)) { 203 + if($this->getGuestComment()) {
97 return true; 204 return true;
98 } else { 205 } else {
99 - return \Yii::$app->user->can(\common\modules\comment\Permissions::CREATE, ['entity' => $entity]); 206 + return \Yii::$app->user->can(\common\modules\comment\Permissions::CREATE, [ 'entity' => $this->entity ]);
100 } 207 }
101 } 208 }
102 209
103 - protected function clearSafe($setNew = true) { 210 + public function checkUpdate()
  211 + {
  212 + if($this->scenario == self::SCENARIO_GUEST) {
  213 + return false;
  214 + } else {
  215 + return \Yii::$app->user->can(\common\modules\comment\Permissions::UPDATE, [ 'entity' => $this->entity ]) || \Yii::$app->user->can(\common\modules\comment\Permissions::UPDATE_OWN, [ 'entity' => $this->entity ]);
  216 + }
  217 + }
  218 +
  219 + public function checkDelete()
  220 + {
  221 + if($this->scenario == self::SCENARIO_GUEST) {
  222 + return false;
  223 + } else {
  224 + return \Yii::$app->user->can(\common\modules\comment\Permissions::DELETE, [ 'entity' => $this->entity ]) || \Yii::$app->user->can(\common\modules\comment\Permissions::DELETE_OWN, [ 'entity' => $this->entity ]);
  225 + }
  226 + }
  227 +
  228 + protected function clearSafe($setNew = true)
  229 + {
104 $safe = $this->safeAttributes(); 230 $safe = $this->safeAttributes();
105 $count = count($safe); 231 $count = count($safe);
106 $values = array_fill(0, $count, NULL); 232 $values = array_fill(0, $count, NULL);
@@ -109,4 +235,56 @@ @@ -109,4 +235,56 @@
109 $this->setIsNewRecord($setNew); 235 $this->setIsNewRecord($setNew);
110 } 236 }
111 237
112 - }  
113 \ No newline at end of file 238 \ No newline at end of file
  239 + public function getParent()
  240 + {
  241 + return $this->hasOne(self::className(), [ 'comment_id' => 'comment_pid' ]);
  242 + }
  243 +
  244 + public function getAuthor()
  245 + {
  246 + // if($this->user_id != NULL) {
  247 + return $this->hasOne(\common\models\User::className(), [ 'id' => 'user_id' ]);
  248 + // } else {
  249 + // return ['firstname' => $this->user_name, 'email' => $this->user_email];
  250 + // }
  251 + }
  252 +
  253 + public function checkRating()
  254 + {
  255 + $rating = $this->hasOne(\common\modules\comment\models\Rating::className(), [ 'entity' => 'entityId' ])
  256 + ->one();
  257 + if(!$rating instanceof \common\modules\comment\models\Rating) {
  258 + $rating = new \common\modules\comment\models\Rating([
  259 + 'entity' => $this->entityId,
  260 + 'user_id' => $this->user_id,
  261 + ]);
  262 + $rating->save();
  263 + }
  264 + }
  265 +
  266 + public function getRating()
  267 + {
  268 + $this->checkRating();
  269 + return $this->hasOne(\common\modules\comment\models\Rating::className(), [ 'entity' => 'entityId' ]);
  270 + }
  271 +
  272 + public function hasRating($return = true)
  273 + {
  274 + $rating = $this->hasOne(\common\modules\comment\models\Rating::className(), [ 'entity' => 'entityId' ])
  275 + ->andWhere([
  276 + 'not',
  277 + [ 'value' => NULL ],
  278 + ])
  279 + ->one();
  280 + if($return) {
  281 + return $rating;
  282 + } else {
  283 + return $rating ? true : false;
  284 + }
  285 + }
  286 +
  287 + public function getEntityId()
  288 + {
  289 + return $this->formName() . '-' . $this->getPrimaryKey();
  290 + }
  291 + }
common/modules/comment/models/Rating.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace common\modules\comment\models;
  4 +
  5 +use Yii;
  6 +
  7 +/**
  8 + * This is the model class for table "rating".
  9 + *
  10 + * @property integer $rating_id
  11 + * @property string $date_add
  12 + * @property string $date_update
  13 + * @property integer $user_id
  14 + * @property string $entity
  15 + * @property integer $value
  16 + *
  17 + * @property \common\models\User $user
  18 + */
  19 +class Rating extends \yii\db\ActiveRecord
  20 +{
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public static function tableName()
  25 + {
  26 + return 'rating';
  27 + }
  28 +
  29 + /**
  30 + * @inheritdoc
  31 + */
  32 + public function rules()
  33 + {
  34 + return [
  35 + [['value'], 'integer'],
  36 + ];
  37 + }
  38 +
  39 + /**
  40 + * @inheritdoc
  41 + */
  42 + public function attributeLabels()
  43 + {
  44 + return [
  45 + 'rating_id' => Yii::t('app', 'Rating ID'),
  46 + 'date_add' => Yii::t('app', 'Date Add'),
  47 + 'date_update' => Yii::t('app', 'Date Update'),
  48 + 'user_id' => Yii::t('app', 'User ID'),
  49 + 'entity' => Yii::t('app', 'Entity'),
  50 + 'value' => Yii::t('app', 'Value'),
  51 + ];
  52 + }
  53 +
  54 + /**
  55 + * @return \yii\db\ActiveQuery
  56 + */
  57 + public function getUser()
  58 + {
  59 + return $this->hasOne(\common\models\User::className(), ['id' => 'user_id']);
  60 + }
  61 +}
common/modules/comment/resources/comment.css 0 → 100644
  1 +.artbox_comment_reply_author, .artbox_comment_update_reply {
  2 + position: relative;
  3 + width: 25%;
  4 +}
  5 +.artbox_comment_update_reply {
  6 + width: 25%;
  7 + float: none;
  8 +}
  9 +.artbox_comment_reply_author:after, .artbox_comment_update_reply:after {
  10 + content: '';
  11 + background-image: url('delete-ico.png');
  12 + display: block;
  13 + position: absolute;
  14 + right: -13px;
  15 + width: 13px;
  16 + height: 13px;
  17 + top: 0;
  18 + cursor: pointer;
  19 +}
0 \ No newline at end of file 20 \ No newline at end of file
common/modules/comment/resources/comment.js 0 → 100644
  1 +$(function() {
  2 +
  3 + $(document).on('click', '.artbox_comment_delete', function() {
  4 + var container = $(this).parents('.artbox_comment_container');
  5 + var comment_id = $(container).data('comment_id');
  6 + var form_name = $(container).data('form_name');
  7 + if(confirm("Уверены, что хотите удалить комментарий?")) {
  8 + $.post(
  9 + '/artbox-comment/delete',
  10 + {
  11 + Comment: {
  12 + comment_id: comment_id
  13 + }
  14 + },
  15 + function(data, textStatus, jqXHR) {
  16 + if(!data.error) {
  17 + $(container).after('<p class="removeable">'+data.text+'</p>');
  18 + $(container).remove();
  19 + } else {
  20 + $(container).prepend('<p class="removeable error_message">'+data.error+'</p>')
  21 + }
  22 + }
  23 + );
  24 + }
  25 + });
  26 +
  27 + $(document).on('click', '.artbox_comment_reply', function() {
  28 + var container = $(this).parents('.artbox_comment_container').first();
  29 + var comment_id = $(container).data('comment_id');
  30 + var form_name = $(container).data('form_name');
  31 + var author = $(container).find('.artbox_comment_author').first().text();
  32 + var comment_form = $('.artbox_comment_form').first();
  33 + var offset = $(comment_form).offset();
  34 + var reply_block = $(comment_form).find('.artbox_comment_reply_block').first();
  35 + $(reply_block).empty();
  36 + $(reply_block).append('<input type="hidden" name="'+form_name+'[comment_pid]" value="'+comment_id+'">');
  37 + $(reply_block).append('<p class="artbox_comment_reply_author">'+author+'</p>');
  38 + $('html, body').animate({
  39 + scrollTop: offset.top - 50,
  40 + });
  41 + });
  42 +
  43 + $(document).on('click', '.artbox_comment_reply_author', function() {
  44 + $(this).parents('.artbox_comment_reply_block').first().empty();
  45 + });
  46 +
  47 + $(document).on('click', '.artbox_comment_update', function() {
  48 + $(this).removeClass('artbox_comment_update');
  49 + $(this).text('Сохранить');
  50 + $(this).addClass('artbox_comment_update_submit');
  51 + var container = $(this).parents('.artbox_comment_container').first();
  52 + var comment_id = $(container).data('comment_id');
  53 + var form_name = $(container).data('form_name');
  54 + var text = $(container).find('.artbox_comment_text');
  55 + var object = {};
  56 + object[form_name] = {comment_id: comment_id};
  57 + $.post(
  58 + '/artbox-comment/form',
  59 + object,
  60 + function(data, textStatus, jqXHR) {
  61 + $(text).hide();
  62 + $(text).after(
  63 + '<div class="artbox_comment_text_edit new-portf-answer">'
  64 + + data
  65 + + '</div>'
  66 + );
  67 + }
  68 + );
  69 + });
  70 +
  71 + $(document).on('click', '.artbox_comment_update_reply', function() {
  72 + $(this).remove();
  73 + });
  74 +
  75 + $(document).on('click', '.artbox_comment_update_submit', function(e) {
  76 + e.preventDefault();
  77 + var container = $(this).parents('.artbox_comment_container').first();
  78 + var edit = $(container).find('.artbox_comment_text_edit').first();
  79 + $.post(
  80 + '/artbox-comment/update',
  81 + $(edit).find('form').serialize(),
  82 + function(data) {
  83 + if(!data.error) {
  84 + location.reload(true);
  85 + }
  86 + }
  87 + )
  88 + });
  89 +});
0 \ No newline at end of file 90 \ No newline at end of file
common/modules/comment/resources/delete-ico.png 0 → 100644

368 Bytes

common/modules/comment/views/comment_form.php 0 → 100644
  1 +<?php
  2 + /**
  3 + * @var \common\modules\comment\models\Comment $model
  4 + */
  5 + use yii\widgets\ActiveForm;
  6 +
  7 + $form = ActiveForm::begin();
  8 +
  9 +?>
  10 +<?php
  11 + echo $form->field($model, 'comment_id')
  12 + ->label(false)
  13 + ->hiddenInput();
  14 + if(!empty( $model->parent )) {
  15 + ?>
  16 + <div class="artbox_comment_update_reply">
  17 + <?php
  18 + echo "<span>";
  19 + if(!empty( $model->parent->author )) {
  20 + echo $model->parent->author->firstname . ' ' . $model->parent->author->lastname;
  21 + } else {
  22 + echo $model->parent->user_name;
  23 + }
  24 + echo "</span>";
  25 + echo $form->field($model, 'comment_pid')
  26 + ->label(false)
  27 + ->hiddenInput();
  28 + ?>
  29 + </div>
  30 + <?php
  31 + }
  32 + echo $form->field($model, 'text')
  33 + ->label(false)
  34 + ->textarea();
  35 +?>
  36 +<?php
  37 + $form->end();
  38 +?>
0 \ No newline at end of file 39 \ No newline at end of file
common/modules/comment/widgets/CommentWidget.php
@@ -8,9 +8,18 @@ @@ -8,9 +8,18 @@
8 { 8 {
9 9
10 /** 10 /**
  11 + * @var null|\yii\web\View
  12 + */
  13 + public $context = NULL;
  14 +
  15 + /**
11 * @var array Parts of widgets that can be rendered 16 * @var array Parts of widgets that can be rendered
12 */ 17 */
13 - public $parts = []; 18 + public $parts = [ ];
  19 +
  20 + public $rating_class = NULL;
  21 +
  22 + public $rating_options = [ ];
14 23
15 /** 24 /**
16 * @var string|\common\modules\comment\models\Comment 25 * @var string|\common\modules\comment\models\Comment
@@ -20,7 +29,7 @@ @@ -20,7 +29,7 @@
20 /** 29 /**
21 * @var array 30 * @var array
22 */ 31 */
23 - public $class_options = []; 32 + public $class_options = [ ];
24 33
25 /** 34 /**
26 * @var bool Wheather to display comment list 35 * @var bool Wheather to display comment list
@@ -28,44 +37,72 @@ @@ -28,44 +37,72 @@
28 public $display_comment_list = true; 37 public $display_comment_list = true;
29 38
30 /** 39 /**
31 - * @var bool Wheather to display comment form 40 + * @var bool Whether to display comment form
32 */ 41 */
33 public $display_comment_form = true; 42 public $display_comment_form = true;
34 43
  44 + /**
  45 + * @var bool Whether to display success text
  46 + */
35 public $display_comment_success = true; 47 public $display_comment_success = true;
36 48
  49 + /**
  50 + * @var bool Whether to allow one user post multiple comments
  51 + */
37 public $allow_multiple = true; 52 public $allow_multiple = true;
38 53
39 - public $success_text = "Comment posted successfully";  
40 - 54 + /**
  55 + * @var array Options sent to list part
  56 + */
41 public $list_options = [ 57 public $list_options = [
42 - 'tag' => 'div',  
43 - 'view' => 'list-comment', 58 + 'tag' => 'div',
  59 + 'view' => 'list-comment',
44 'class' => 'test-class', 60 'class' => 'test-class',
45 ]; 61 ];
46 62
  63 + /**
  64 + * @var array Options sent to success part
  65 + */
47 public $success_options = [ 66 public $success_options = [
48 - 'tag' => 'div',  
49 - 'content' => null,  
50 - 'class' => 'test-class-success', 67 + 'tag' => 'div',
  68 + 'content' => NULL,
  69 + 'class' => 'test-class-success',
51 ]; 70 ];
52 71
  72 + /**
  73 + * @var array Options sent to form part
  74 + */
53 public $form_options = [ 75 public $form_options = [
54 - 'tag' => 'div',  
55 - 'view' => 'form-comment', 76 + 'tag' => 'div',
  77 + 'view' => 'form-comment',
56 'class' => 'test-class-form', 78 'class' => 'test-class-form',
57 ]; 79 ];
58 80
  81 + /**
  82 + * @var bool Indicates whether any successful action happened
  83 + */
59 protected $isSuccess = false; 84 protected $isSuccess = false;
60 85
  86 + public $success_text = 'Comment successfully added';
  87 +
  88 + /**
  89 + * @var string Entity, to which comments attached
  90 + */
61 public $entity; 91 public $entity;
62 92
  93 + /**
  94 + * @var string Template of the widget. You may use <code>{success}, {form}, {list}</code>
  95 + * to render particular parts. You are also able to use common HTML here.
  96 + */
63 public $template = "{success}\n{form}\n{list}"; 97 public $template = "{success}\n{form}\n{list}";
64 98
65 - public $options = []; 99 + /**
  100 + * @var array Widget options
  101 + */
  102 + public $options = [ ];
66 103
67 /** 104 /**
68 - * @var \yii\data\DataProviderInterface 105 + * @var \yii\data\DataProviderInterface Data provider of comments
69 */ 106 */
70 public $dataProvider; 107 public $dataProvider;
71 108
@@ -75,16 +112,20 @@ @@ -75,16 +112,20 @@
75 public function init() 112 public function init()
76 { 113 {
77 parent::init(); 114 parent::init();
  115 + \common\modules\comment\assets\CommentAsset::register($this->view);
78 if(is_string($this->comment_class)) { 116 if(is_string($this->comment_class)) {
79 $this->comment_class = new $this->comment_class($this->class_options); 117 $this->comment_class = new $this->comment_class($this->class_options);
80 - } elseif(!is_object($this->comment_class)) {  
81 - throw new \yii\base\InvalidConfigException(__CLASS__.'->comment_class must be defined as string or object.'); 118 + } else {
  119 + throw new \yii\base\InvalidConfigException(__CLASS__ . '->comment_class must be defined as object full class name string.');
  120 + }
  121 + if(!empty( $this->rating_class ) && is_string($this->rating_class)) {
  122 + $this->rating_class = new $this->rating_class($this->rating_options);
  123 + } elseif(!empty( $this->rating_class )) {
  124 + throw new \yii\base\InvalidConfigException(__CLASS__ . '->rating_class must be defined as object full class name string.');
82 } 125 }
83 $this->comment_class->entity = $this->entity; 126 $this->comment_class->entity = $this->entity;
84 $this->createDataProvider(); 127 $this->createDataProvider();
85 - if($this->comment_class->checkCreate($this->entity)) {  
86 - $this->handleCreate();  
87 - } 128 + $this->process();
88 ob_start(); 129 ob_start();
89 } 130 }
90 131
@@ -99,62 +140,67 @@ @@ -99,62 +140,67 @@
99 return $this->renderWidget(); 140 return $this->renderWidget();
100 } 141 }
101 142
102 - public function createParts() { 143 + public function createParts()
  144 + {
103 if($this->display_comment_success && $this->isSuccess) { 145 if($this->display_comment_success && $this->isSuccess) {
104 $tag = ArrayHelper::remove($this->success_options, 'tag', 'div'); 146 $tag = ArrayHelper::remove($this->success_options, 'tag', 'div');
105 - if(is_callable($this->success_options['content'])) { 147 + if(is_callable($this->success_options[ 'content' ])) {
106 $result = call_user_func(ArrayHelper::remove($this->success_options, 'content'), $this->success_text); 148 $result = call_user_func(ArrayHelper::remove($this->success_options, 'content'), $this->success_text);
107 - } elseif($this->success_options['content'] != NULL) { 149 + } elseif($this->success_options[ 'content' ] != NULL) {
108 $result = Html::encode(ArrayHelper::remove($this->success_options, 'content', $this->success_text)); 150 $result = Html::encode(ArrayHelper::remove($this->success_options, 'content', $this->success_text));
109 } else { 151 } else {
110 $result = Html::encode($this->success_text); 152 $result = Html::encode($this->success_text);
111 } 153 }
112 - $this->parts['success'] = Html::tag($tag, $result, $this->success_options);  
113 - unset($tag, $result); 154 + $this->parts[ 'success' ] = Html::tag($tag, $result, $this->success_options);
  155 + unset( $tag, $result );
114 } 156 }
115 157
116 if($this->display_comment_list) { 158 if($this->display_comment_list) {
117 $tag = ArrayHelper::remove($this->list_options, 'tag', 'div'); 159 $tag = ArrayHelper::remove($this->list_options, 'tag', 'div');
118 $view = ArrayHelper::remove($this->list_options, 'view'); 160 $view = ArrayHelper::remove($this->list_options, 'view');
119 - $this->parts['list'] = Html::tag($tag, $this->renderItems($view), $this->list_options); 161 + $this->parts[ 'list' ] = Html::tag($tag, $this->renderItems($view), $this->list_options);
120 } 162 }
121 163
122 if($this->display_comment_form) { 164 if($this->display_comment_form) {
123 $tag = ArrayHelper::remove($this->form_options, 'tag', 'div'); 165 $tag = ArrayHelper::remove($this->form_options, 'tag', 'div');
124 $view = ArrayHelper::remove($this->form_options, 'view'); 166 $view = ArrayHelper::remove($this->form_options, 'view');
125 - $this->parts['form'] = Html::tag($tag, $this->renderForm($view), $this->list_options); 167 + $this->parts[ 'form' ] = Html::tag($tag, $this->renderForm($view), $this->form_options);
126 } 168 }
127 } 169 }
128 170
129 public function createDataProvider() 171 public function createDataProvider()
130 { 172 {
131 $this->dataProvider = new \yii\data\ActiveDataProvider([ 173 $this->dataProvider = new \yii\data\ActiveDataProvider([
132 - 'query' => $this->comment_class->getComments($this->entity), 174 + 'query' => $this->comment_class->getComments($this->entity),
133 'pagination' => [ 175 'pagination' => [
134 'pageSize' => 10, 176 'pageSize' => 10,
135 ], 177 ],
136 ]); 178 ]);
137 } 179 }
138 180
139 - public function renderItems($view) {  
140 - if(empty($view)) { 181 + public function renderItems($view)
  182 + {
  183 + if(empty( $view )) {
141 throw new \yii\base\InvalidConfigException("list_options[view] must be set"); 184 throw new \yii\base\InvalidConfigException("list_options[view] must be set");
142 } 185 }
143 - return $this->render($view, ['dataProvider' => $this->dataProvider]); 186 + return $this->render($view, [ 'dataProvider' => $this->dataProvider ]);
144 } 187 }
145 188
146 - public function renderForm($view) {  
147 - if(empty($view)) { 189 + public function renderForm($view)
  190 + {
  191 + if(empty( $view )) {
148 throw new \yii\base\InvalidConfigException("form_options[view] must be set"); 192 throw new \yii\base\InvalidConfigException("form_options[view] must be set");
149 } 193 }
150 return $this->render($view, [ 194 return $this->render($view, [
151 - 'model' => $this->comment_class,  
152 - 'user' => \Yii::$app->user->identity, 195 + 'model' => $this->comment_class,
  196 + 'rating' => $this->rating_class,
  197 + 'user' => \Yii::$app->user->identity,
153 'dataProvider' => $this->dataProvider, 198 'dataProvider' => $this->dataProvider,
154 ]); 199 ]);
155 } 200 }
156 201
157 - public function renderWidget() { 202 + public function renderWidget()
  203 + {
158 $template = $this->template; 204 $template = $this->template;
159 $parts = $this->parts; 205 $parts = $this->parts;
160 $options = $this->options; 206 $options = $this->options;
@@ -165,11 +211,13 @@ @@ -165,11 +211,13 @@
165 return Html::tag($tag, $template, $options); 211 return Html::tag($tag, $template, $options);
166 } 212 }
167 213
168 - public function handleCreate() 214 + public function process()
169 { 215 {
170 $data = \Yii::$app->request->post(); 216 $data = \Yii::$app->request->post();
171 - if($this->comment_class->postComment($data)) {  
172 - $this->isSuccess = true;  
173 - }; 217 + if($this->comment_class->load($data) && $this->comment_class->postComment()) {
  218 + if(is_object($this->rating_class) && $this->comment_class->rating->load($data) && $this->comment_class->rating->save()) {
  219 + $this->isSuccess = true;
  220 + }
  221 + }
174 } 222 }
175 } 223 }
176 \ No newline at end of file 224 \ No newline at end of file
common/modules/comment/widgets/views/form-comment.php
1 <?php 1 <?php
2 /** 2 /**
3 - * @var \common\modules\comment\models\Comment $model  
4 - * @var \common\models\User $user  
5 - * @var \yii\data\ActiveDataProvider $dataProvider 3 + * @var \common\modules\comment\models\Comment $model
  4 + * @var \common\models\User $user
  5 + * @var \yii\data\ActiveDataProvider $dataProvider
  6 + * @var null|\common\modules\comment\models\Rating $rating
6 */ 7 */
7 use yii\widgets\ActiveForm; 8 use yii\widgets\ActiveForm;
8 use yii\helpers\Html; 9 use yii\helpers\Html;
@@ -11,42 +12,59 @@ @@ -11,42 +12,59 @@
11 <div class="new-portf-comm-count">Комментарии: <?= $dataProvider->totalCount ?></div> 12 <div class="new-portf-comm-count">Комментарии: <?= $dataProvider->totalCount ?></div>
12 13
13 <div class="new-portf-add-comm style"> 14 <div class="new-portf-add-comm style">
  15 +
14 <?php 16 <?php
15 $form = ActiveForm::begin(); 17 $form = ActiveForm::begin();
16 - ?>  
17 18
18 - <?php 19 + echo $form->field($rating, 'value')
  20 + ->label(false)
  21 + ->radioList([
  22 + 1 => 1,
  23 + 2 => 2,
  24 + 3 => 3,
  25 + 4 => 4,
  26 + 5 => 5,
  27 + ]);
  28 +
19 if($model->scenario == $model::SCENARIO_GUEST) { 29 if($model->scenario == $model::SCENARIO_GUEST) {
20 echo $form->field($model, 'user_name', [ 30 echo $form->field($model, 'user_name', [
21 - 'options' => [ 31 + 'options' => [
22 'class' => 'input-blocks-comm', 32 'class' => 'input-blocks-comm',
23 ], 33 ],
24 'inputOptions' => [ 34 'inputOptions' => [
25 'class' => 'custom-input-4', 35 'class' => 'custom-input-4',
26 ], 36 ],
27 - ])->textInput(); 37 + ])
  38 + ->textInput();
28 echo $form->field($model, 'user_email', [ 39 echo $form->field($model, 'user_email', [
29 - 'options' => [ 40 + 'options' => [
30 'class' => 'input-blocks-comm', 41 'class' => 'input-blocks-comm',
31 ], 42 ],
32 'inputOptions' => [ 43 'inputOptions' => [
33 'class' => 'custom-input-4', 44 'class' => 'custom-input-4',
34 ], 45 ],
35 - ])->textInput(); 46 + ])
  47 + ->textInput();
36 } 48 }
  49 +
  50 + ?>
  51 + <div class="artbox_comment_reply_block"></div>
  52 + <?php
  53 +
37 echo $form->field($model, 'text', [ 54 echo $form->field($model, 'text', [
38 - 'options' => [ 55 + 'options' => [
39 'class' => 'input-blocks-comm area-comm', 56 'class' => 'input-blocks-comm area-comm',
40 ], 57 ],
41 'inputOptions' => [ 58 'inputOptions' => [
42 'class' => 'custom-area-4', 59 'class' => 'custom-area-4',
43 ], 60 ],
44 - ])->textarea(); 61 + ])
  62 + ->textarea();
45 ?> 63 ?>
46 - <div class="input-blocks-comm-button style">  
47 - <?= Html::submitButton('Добавить комментарий') ?>  
48 - </div>  
49 - <?php 64 + <div class="input-blocks-comm-button style">
  65 + <?= Html::submitButton('Добавить комментарий') ?>
  66 + </div>
  67 + <?php
50 $form->end(); 68 $form->end();
51 ?> 69 ?>
52 </div> 70 </div>
53 \ No newline at end of file 71 \ No newline at end of file
common/modules/comment/widgets/views/project_comment_view.php
@@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
3 use yii\helpers\Html; 3 use yii\helpers\Html;
4 4
5 /** 5 /**
6 - * @var \common\modules\comment\models\Comment $model Current comment model  
7 - * @var integer $key ID of current comment  
8 - * @var integer $index index of current element according to 6 + * @var \common\modules\comment\models\Comment $model Current comment model
  7 + * @var integer $key ID of current comment
  8 + * @var integer $index index of current element according to
9 * current page, starting from 0 9 * current page, starting from 0
10 * @var \yii\widgets\ListView $widget current ListView instance 10 * @var \yii\widgets\ListView $widget current ListView instance
11 * @var User $user 11 * @var User $user
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 ->one(); 18 ->one();
19 } 19 }
20 ?> 20 ?>
21 -<div class="new-portf-comm-read"> 21 +<div class="new-portf-comm-read artbox_comment_container" data-comment_id="<?= $model->comment_id ?>" data-form_name="<?= $model->formName() ?>">
22 <div class="style"> 22 <div class="style">
23 <div class="header-cabinet-foto"> 23 <div class="header-cabinet-foto">
24 <?php 24 <?php
@@ -32,23 +32,29 @@ @@ -32,23 +32,29 @@
32 <div class="new-prof-wrapper-read"> 32 <div class="new-prof-wrapper-read">
33 <div class="new-portf-comm-read-title"> 33 <div class="new-portf-comm-read-title">
34 <?php 34 <?php
35 - if(!empty($user)) {  
36 - echo Html::a($user->firstname . ' ' . $user->lastname, [  
37 - 'performer/common',  
38 - 'performer_id' => $user->id,  
39 - ]);  
40 - } else {  
41 - echo $model->user_name . '(Гость)';  
42 - } 35 + if(!empty( $user )) {
  36 + echo Html::a('<span class="artbox_comment_author">' . $user->firstname . ' ' . $user->lastname . '</span>', [
  37 + 'performer/common',
  38 + 'performer_id' => $user->id,
  39 + ]);
  40 + } else {
  41 + echo '<span class="artbox_comment_author">' . $model->user_name . '</span>' . '(Гость)';
  42 + }
43 ?> 43 ?>
44 </div> 44 </div>
45 <div class="new-portf-comm-read-rating"> 45 <div class="new-portf-comm-read-rating">
46 - <div class="rating">  
47 - <!--оценка-->  
48 - <input type="hidden" class="val" value="3"/>  
49 - <!--количество голосов-->  
50 - <input type="hidden" class="votes" value="12"/>  
51 - </div> 46 + <?php
  47 + if($rating = $model->hasRating()) {
  48 + ?>
  49 + <div class="rating">
  50 + <!--оценка-->
  51 + <input type="hidden" class="val" value="<?= $rating->value ?>"/>
  52 + <!--количество голосов-->
  53 + <input type="hidden" class="votes" value="1"/>
  54 + </div>
  55 + <?php
  56 + }
  57 + ?>
52 </div> 58 </div>
53 <div class="blog-post-date"> 59 <div class="blog-post-date">
54 <span></span> 60 <span></span>
@@ -56,10 +62,23 @@ @@ -56,10 +62,23 @@
56 </div> 62 </div>
57 </div> 63 </div>
58 64
59 - <div class="new-portf-answer"> 65 + <div class="new-portf-answer artbox_comment_text">
60 <?= Html::encode($model->text) ?> 66 <?= Html::encode($model->text) ?>
61 </div> 67 </div>
62 - 68 + <div style="clear:both"></div>
  69 + <?php
  70 + /*
  71 + ?>
  72 + <div class="action_panel">
  73 + <ul>
  74 + <li style="display:inline-block" class="artbox_comment_reply">Ответить</li>
  75 + <li style="display:inline-block" class="artbox_comment_update">Редактировать</li>
  76 + <li style="display:inline-block" class="artbox_comment_delete">Удалить</li>
  77 + </ul>
  78 + </div>
  79 + <?php
  80 + */
  81 + ?>
63 </div> 82 </div>
64 <div class="style"></div> 83 <div class="style"></div>
65 </div> 84 </div>
66 \ No newline at end of file 85 \ No newline at end of file
console/migrations/m160304_081817_rating_table.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m160304_081817_rating_table extends Migration
  6 +{
  7 + public function up()
  8 + {
  9 + $this->createTable('{{%rating}}', [
  10 + 'rating_id' => $this->primaryKey(),
  11 + 'date_add' => $this->timestamp()->notNull()->defaultExpression('NOW()'),
  12 + 'date_update' => $this->timestamp()->notNull()->defaultExpression('NOW()'),
  13 + 'user_id' => $this->integer(),
  14 + 'entity' => $this->string(),
  15 + 'value' => $this->integer(),
  16 + ]);
  17 +
  18 + $this->addForeignKey('rating_user', '{{%rating}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
  19 + }
  20 +
  21 + public function down()
  22 + {
  23 + $this->dropForeignKey('rating_user', '{{%rating}}');
  24 + $this->dropTable('{{%rating}}');
  25 + }
  26 +
  27 +}
frontend/views/performer/portfolio-view.php
@@ -2,13 +2,15 @@ @@ -2,13 +2,15 @@
2 2
3 use common\models\Portfolio; 3 use common\models\Portfolio;
4 use common\models\User; 4 use common\models\User;
5 -use yii\helpers\Html;  
6 -use yii\web\ViewAction; 5 + use yii\helpers\Html;
  6 + use yii\web\ViewAction;
  7 + use yii\web\View;
7 8
8 /** 9 /**
9 * @var ViewAction $this 10 * @var ViewAction $this
10 * @var User $user 11 * @var User $user
11 * @var Portfolio $portfolio 12 * @var Portfolio $portfolio
  13 + * @var View $this
12 */ 14 */
13 $this->params[ 'user' ] = $user; 15 $this->params[ 'user' ] = $user;
14 16
@@ -16,7 +18,7 @@ use yii\web\ViewAction; @@ -16,7 +18,7 @@ use yii\web\ViewAction;
16 ?> 18 ?>
17 <div class="portfolio-new-page-wrapper style"> 19 <div class="portfolio-new-page-wrapper style">
18 <div class="new-portfolio-bg style "> 20 <div class="new-portfolio-bg style ">
19 - <?= Html::img($portfolio->minImg($portfolio->cover,'720', '280')) ?> 21 + <?= Html::img($portfolio->minImg($portfolio->cover, '720', '280')) ?>
20 </div> 22 </div>
21 <div class="new-portfolio-icons-rating-wr style"> 23 <div class="new-portfolio-icons-rating-wr style">
22 <div class="new-portfolio-icons"> 24 <div class="new-portfolio-icons">
@@ -40,7 +42,7 @@ use yii\web\ViewAction; @@ -40,7 +42,7 @@ use yii\web\ViewAction;
40 <div class="portfolio-project-views-img"> 42 <div class="portfolio-project-views-img">
41 <img src="/images/portfolio-project/ico-3.png"></div> 43 <img src="/images/portfolio-project/ico-3.png"></div>
42 </div> 44 </div>
43 - <div class="portfolio-project-views-txt">XX</div> 45 + <div class="portfolio-project-views-txt"></div>
44 </div> 46 </div>
45 </div> 47 </div>
46 </div> 48 </div>
@@ -109,209 +111,213 @@ use yii\web\ViewAction; @@ -109,209 +111,213 @@ use yii\web\ViewAction;
109 } 111 }
110 ?> 112 ?>
111 </div> 113 </div>
112 -  
113 <?php 114 <?php
114 echo \common\modules\comment\widgets\CommentWidget::widget([ 115 echo \common\modules\comment\widgets\CommentWidget::widget([
115 - 'entity' => $portfolio::tableName().'-'.$portfolio->portfolio_id, 116 + 'context' => $this,
  117 + 'entity' => $portfolio::tableName() . '-' . $portfolio->portfolio_id,
116 'comment_class' => \common\modules\comment\models\Comment::className(), 118 'comment_class' => \common\modules\comment\models\Comment::className(),
  119 + 'rating_class' => \common\modules\comment\models\Rating::className(),
117 'class_options' => [ 120 'class_options' => [
118 - 'scenario' => is_int(\Yii::$app->user->getId())?\common\modules\comment\models\Comment::SCENARIO_USER:\common\modules\comment\models\Comment::SCENARIO_GUEST,  
119 - 'user_id' => \Yii::$app->user->getId(), 121 + 'scenario' => is_int(\Yii::$app->user->getId()) ? \common\modules\comment\models\Comment::SCENARIO_USER : \common\modules\comment\models\Comment::SCENARIO_GUEST,
  122 + 'user_id' => \Yii::$app->user->getId(),
  123 + 'guestComment' => true,
  124 + 'status' => \common\modules\comment\models\Comment::STATUS_ACTIVE,
120 ], 125 ],
121 - 'list_options' => [ 126 + 'list_options' => [
122 'view' => 'list-comment', 127 'view' => 'list-comment',
123 ], 128 ],
124 - 'form_options' => [ 129 + 'form_options' => [
125 'view' => 'form-comment', 130 'view' => 'form-comment',
126 - 'tag' => false, 131 + 'tag' => 'div',
  132 + 'class' => 'artbox_comment_form',
127 ], 133 ],
128 - 'options' => [ 134 + 'options' => [
129 'class' => 'new-portf-comments-wr style', 135 'class' => 'new-portf-comments-wr style',
130 ], 136 ],
131 ]); 137 ]);
132 ?> 138 ?>
133 139
134 <?php 140 <?php
135 - /*  
136 - ?>  
137 - <div class="new-portf-comments-wr style">  
138 - <div class="new-portf-comm-count">Комментарии: 3</div>  
139 - <div class="new-portf-add-comm style"> 141 + /*
  142 + ?>
  143 + <div class="new-portf-comments-wr style">
  144 + <div class="new-portf-comm-count">Комментарии: 3</div>
  145 + <div class="new-portf-add-comm style">
140 146
141 - <form action="">  
142 - <div class="input-blocks-comm">  
143 - <label for="input-txt-5">Имя</label>  
144 - <input class="custom-input-4" id="input-txt-5" type="text">  
145 - </div>  
146 - <div class="input-blocks-comm"> 147 + <form action="">
  148 + <div class="input-blocks-comm">
  149 + <label for="input-txt-5">Имя</label>
  150 + <input class="custom-input-4" id="input-txt-5" type="text">
  151 + </div>
  152 + <div class="input-blocks-comm">
147 153
148 - <label for="input-txt-6">e-mail</label>  
149 - <input class="custom-input-4" id="input-txt-6" type="text">  
150 - </div>  
151 - <div class="input-blocks-comm area-comm">  
152 - <label for="input-txt-7">Комментарий</label>  
153 - <textarea class="custom-area-4" id="input-txt-7"></textarea>  
154 - </div>  
155 - <div class="input-blocks-comm-button style">  
156 - <button type="submit" class="">Добавить комментраий</button>  
157 - </div>  
158 - </form> 154 + <label for="input-txt-6">e-mail</label>
  155 + <input class="custom-input-4" id="input-txt-6" type="text">
  156 + </div>
  157 + <div class="input-blocks-comm area-comm">
  158 + <label for="input-txt-7">Комментарий</label>
  159 + <textarea class="custom-area-4" id="input-txt-7"></textarea>
  160 + </div>
  161 + <div class="input-blocks-comm-button style">
  162 + <button type="submit" class="">Добавить комментраий</button>
  163 + </div>
  164 + </form>
159 165
160 - </div> 166 + </div>
161 167
162 - <div class="new-portf-comm-read-wr style">  
163 - <div class="new-portf-comm-read">  
164 - <div class="style">  
165 - <div class="header-cabinet-foto">  
166 - <img src="/images/ded-ico.png" alt="">  
167 - </div>  
168 - <div class="new-prof-wrapper-read">  
169 - <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>  
170 - <div class="new-portf-comm-read-rating">  
171 - <div class="rating">  
172 - <!--оценка-->  
173 - <input type="hidden" class="val" value="3"/>  
174 - <!--количество голосов-->  
175 - <input type="hidden" class="votes" value="12"/> 168 + <div class="new-portf-comm-read-wr style">
  169 + <div class="new-portf-comm-read">
  170 + <div class="style">
  171 + <div class="header-cabinet-foto">
  172 + <img src="/images/ded-ico.png" alt="">
  173 + </div>
  174 + <div class="new-prof-wrapper-read">
  175 + <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>
  176 + <div class="new-portf-comm-read-rating">
  177 + <div class="rating">
  178 + <!--оценка-->
  179 + <input type="hidden" class="val" value="3"/>
  180 + <!--количество голосов-->
  181 + <input type="hidden" class="votes" value="12"/>
  182 + </div>
  183 + </div>
  184 + <div class="blog-post-date">
  185 + <span></span>
  186 + <p>22.09.2015</p>
176 </div> 187 </div>
177 </div> 188 </div>
178 - <div class="blog-post-date">  
179 - <span></span>  
180 - <p>22.09.2015</p> 189 +
  190 + <div class="new-portf-answer">
  191 + <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
  192 + <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
181 </div> 193 </div>
182 - </div>  
183 194
184 - <div class="new-portf-answer">  
185 - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
186 - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
187 </div> 195 </div>
188 - 196 + <div class="style"></div>
189 </div> 197 </div>
190 - <div class="style"></div>  
191 - </div>  
192 198
193 - <div class="new-portf-comm-read">  
194 - <div class="style">  
195 - <div class="header-cabinet-foto">  
196 - <img src="/images/ded-ico.png" alt="">  
197 - </div>  
198 - <div class="new-prof-wrapper-read">  
199 - <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>  
200 - <div class="new-portf-comm-read-rating">  
201 - <div class="rating">  
202 - <!--оценка-->  
203 - <input type="hidden" class="val" value="4"/>  
204 - <!--количество голосов-->  
205 - <input type="hidden" class="votes" value="12"/> 199 + <div class="new-portf-comm-read">
  200 + <div class="style">
  201 + <div class="header-cabinet-foto">
  202 + <img src="/images/ded-ico.png" alt="">
  203 + </div>
  204 + <div class="new-prof-wrapper-read">
  205 + <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>
  206 + <div class="new-portf-comm-read-rating">
  207 + <div class="rating">
  208 + <!--оценка-->
  209 + <input type="hidden" class="val" value="4"/>
  210 + <!--количество голосов-->
  211 + <input type="hidden" class="votes" value="12"/>
  212 + </div>
  213 + </div>
  214 + <div class="blog-post-date">
  215 + <span></span>
  216 + <p>22.09.2015</p>
206 </div> 217 </div>
207 </div> 218 </div>
208 - <div class="blog-post-date">  
209 - <span></span>  
210 - <p>22.09.2015</p> 219 +
  220 + <div class="new-portf-answer">
  221 + <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
  222 + <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
211 </div> 223 </div>
212 - </div>  
213 224
214 - <div class="new-portf-answer">  
215 - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
216 - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
217 </div> 225 </div>
218 - 226 + <div class="style"></div>
219 </div> 227 </div>
220 - <div class="style"></div>  
221 - </div>  
222 228
223 - <div class="new-portf-comm-read">  
224 - <div class="style">  
225 - <div class="header-cabinet-foto">  
226 - <img src="/images/ded-ico.png" alt="">  
227 - </div>  
228 - <div class="new-prof-wrapper-read">  
229 - <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>  
230 - <div class="new-portf-comm-read-rating">  
231 - <div class="rating">  
232 - <!--оценка-->  
233 - <input type="hidden" class="val" value="5"/>  
234 - <!--количество голосов-->  
235 - <input type="hidden" class="votes" value="12"/> 229 + <div class="new-portf-comm-read">
  230 + <div class="style">
  231 + <div class="header-cabinet-foto">
  232 + <img src="/images/ded-ico.png" alt="">
  233 + </div>
  234 + <div class="new-prof-wrapper-read">
  235 + <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>
  236 + <div class="new-portf-comm-read-rating">
  237 + <div class="rating">
  238 + <!--оценка-->
  239 + <input type="hidden" class="val" value="5"/>
  240 + <!--количество голосов-->
  241 + <input type="hidden" class="votes" value="12"/>
  242 + </div>
  243 + </div>
  244 + <div class="blog-post-date">
  245 + <span></span>
  246 + <p>22.09.2015</p>
236 </div> 247 </div>
237 </div> 248 </div>
238 - <div class="blog-post-date">  
239 - <span></span>  
240 - <p>22.09.2015</p> 249 +
  250 + <div class="new-portf-answer">
  251 + <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
  252 + <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
241 </div> 253 </div>
242 - </div>  
243 254
244 - <div class="new-portf-answer">  
245 - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
246 - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
247 </div> 255 </div>
248 - 256 + <div class="style"></div>
249 </div> 257 </div>
250 - <div class="style"></div>  
251 - </div>  
252 258
253 - <div class="new-portf-comm-read">  
254 - <div class="style">  
255 - <div class="header-cabinet-foto">  
256 - <img src="/images/ded-ico.png" alt="">  
257 - </div>  
258 - <div class="new-prof-wrapper-read">  
259 - <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>  
260 - <div class="new-portf-comm-read-rating">  
261 - <div class="rating">  
262 - <!--оценка-->  
263 - <input type="hidden" class="val" value="1"/>  
264 - <!--количество голосов-->  
265 - <input type="hidden" class="votes" value="12"/> 259 + <div class="new-portf-comm-read">
  260 + <div class="style">
  261 + <div class="header-cabinet-foto">
  262 + <img src="/images/ded-ico.png" alt="">
  263 + </div>
  264 + <div class="new-prof-wrapper-read">
  265 + <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>
  266 + <div class="new-portf-comm-read-rating">
  267 + <div class="rating">
  268 + <!--оценка-->
  269 + <input type="hidden" class="val" value="1"/>
  270 + <!--количество голосов-->
  271 + <input type="hidden" class="votes" value="12"/>
  272 + </div>
  273 + </div>
  274 + <div class="blog-post-date">
  275 + <span></span>
  276 + <p>22.09.2015</p>
266 </div> 277 </div>
267 </div> 278 </div>
268 - <div class="blog-post-date">  
269 - <span></span>  
270 - <p>22.09.2015</p> 279 +
  280 + <div class="new-portf-answer">
  281 + <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
  282 + <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
271 </div> 283 </div>
272 - </div>  
273 284
274 - <div class="new-portf-answer">  
275 - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
276 - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
277 </div> 285 </div>
278 - 286 + <div class="style"></div>
279 </div> 287 </div>
280 - <div class="style"></div>  
281 - </div>  
282 - <div class="new-portf-comm-read">  
283 - <div class="style">  
284 - <div class="header-cabinet-foto">  
285 - <img src="/images/ded-ico.png" alt="">  
286 - </div>  
287 - <div class="new-prof-wrapper-read">  
288 - <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>  
289 - <div class="new-portf-comm-read-rating">  
290 - <div class="rating">  
291 - <!--оценка-->  
292 - <input type="hidden" class="val" value="2"/>  
293 - <!--количество голосов-->  
294 - <input type="hidden" class="votes" value="12"/> 288 + <div class="new-portf-comm-read">
  289 + <div class="style">
  290 + <div class="header-cabinet-foto">
  291 + <img src="/images/ded-ico.png" alt="">
  292 + </div>
  293 + <div class="new-prof-wrapper-read">
  294 + <div class="new-portf-comm-read-title"><a href="#">Петер Цумтор</a></div>
  295 + <div class="new-portf-comm-read-rating">
  296 + <div class="rating">
  297 + <!--оценка-->
  298 + <input type="hidden" class="val" value="2"/>
  299 + <!--количество голосов-->
  300 + <input type="hidden" class="votes" value="12"/>
  301 + </div>
  302 + </div>
  303 + <div class="blog-post-date">
  304 + <span></span>
  305 + <p>22.09.2015</p>
295 </div> 306 </div>
296 </div> 307 </div>
297 - <div class="blog-post-date">  
298 - <span></span>  
299 - <p>22.09.2015</p> 308 +
  309 + <div class="new-portf-answer">
  310 + <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
  311 + <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>
300 </div> 312 </div>
301 - </div>  
302 313
303 - <div class="new-portf-answer">  
304 - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
305 - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p>  
306 </div> 314 </div>
307 - 315 + <div class="style"></div>
308 </div> 316 </div>
309 - <div class="style"></div>  
310 - </div>  
311 317
  318 + </div>
312 </div> 319 </div>
313 - </div>  
314 - */ 320 + */
315 ?> 321 ?>
316 </div> 322 </div>
317 <script> 323 <script>
frontend/web/css/art_box.css
@@ -4,4 +4,4 @@ @@ -4,4 +4,4 @@
4 } 4 }
5 .form_for_company .company_info { 5 .form_for_company .company_info {
6 display: none; 6 display: none;
7 -}  
8 \ No newline at end of file 7 \ No newline at end of file
  8 +}