Commit 2d107e9e171d497711b3129ece88b25676c96a15
1 parent
d7d32bb2
test
Showing
18 changed files
with
880 additions
and
259 deletions
Show diff stats
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
| 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 |
| 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 | + } |
| 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 | +} |
| 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 |
| 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 |
368 Bytes
| 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 |
| 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> |