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 | 24 | 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field ) |
| 25 | 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 | 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 | 97 | \ No newline at end of file | ... | ... |
common/modules/comment/Permissions.php
| ... | ... | @@ -8,5 +8,5 @@ |
| 8 | 8 | const UPDATE = 'artbox_comment.update'; |
| 9 | 9 | const DELETE = 'artbox_comment.delete'; |
| 10 | 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 | 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 | 22 | \ No newline at end of file | ... | ... |
common/modules/comment/interfaces/CommentInterface.php
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | public function load($data, $formName = null); |
| 6 | 6 | public function formName(); |
| 7 | 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 | 3 | |
| 4 | 4 | /** |
| 5 | 5 | * Class Comment |
| 6 | - * @property bool $guestComment | |
| 6 | + * @property bool $guestComment | |
| 7 | + * @property integer $comment_id | |
| 7 | 8 | * @package common\modules\comment\models |
| 8 | 9 | */ |
| 9 | 10 | class Comment extends \yii\db\ActiveRecord |
| ... | ... | @@ -18,29 +19,87 @@ |
| 18 | 19 | const SCENARIO_USER = 'user'; |
| 19 | 20 | const SCENARIO_GUEST = 'guest'; |
| 20 | 21 | |
| 22 | + /** | |
| 23 | + * @var bool | |
| 24 | + */ | |
| 25 | + public $guestComment = true; | |
| 26 | + | |
| 21 | 27 | public function rules() |
| 22 | 28 | { |
| 23 | 29 | return [ |
| 24 | 30 | [ |
| 25 | - ['text'], | |
| 31 | + [ | |
| 32 | + 'text', | |
| 33 | + 'user_name', | |
| 34 | + 'user_email', | |
| 35 | + ], | |
| 26 | 36 | 'required', |
| 27 | 37 | ], |
| 28 | 38 | [ |
| 29 | - ['user_email'], | |
| 39 | + [ | |
| 40 | + 'rating', | |
| 41 | + ], | |
| 42 | + 'safe', | |
| 43 | + ], | |
| 44 | + [ | |
| 45 | + [ 'user_email' ], | |
| 30 | 46 | 'email', |
| 31 | 47 | ], |
| 32 | 48 | [ |
| 33 | - ['user_name'], | |
| 49 | + [ 'user_name' ], | |
| 34 | 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 | 75 | public function scenarios() |
| 40 | 76 | { |
| 41 | 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 | 114 | public function attributeLabels() |
| 56 | 115 | { |
| 57 | 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 | 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 | 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 | 151 | } else { |
| 152 | + $this->addError('comment_id', 'You can`t post comment here'); | |
| 80 | 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 | 204 | return true; |
| 98 | 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 | 230 | $safe = $this->safeAttributes(); |
| 105 | 231 | $count = count($safe); |
| 106 | 232 | $values = array_fill(0, $count, NULL); |
| ... | ... | @@ -109,4 +235,56 @@ |
| 109 | 235 | $this->setIsNewRecord($setNew); |
| 110 | 236 | } |
| 111 | 237 | |
| 112 | - } | |
| 113 | 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 | 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 | 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 | 39 | \ No newline at end of file | ... | ... |
common/modules/comment/widgets/CommentWidget.php
| ... | ... | @@ -8,9 +8,18 @@ |
| 8 | 8 | { |
| 9 | 9 | |
| 10 | 10 | /** |
| 11 | + * @var null|\yii\web\View | |
| 12 | + */ | |
| 13 | + public $context = NULL; | |
| 14 | + | |
| 15 | + /** | |
| 11 | 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 | 25 | * @var string|\common\modules\comment\models\Comment |
| ... | ... | @@ -20,7 +29,7 @@ |
| 20 | 29 | /** |
| 21 | 30 | * @var array |
| 22 | 31 | */ |
| 23 | - public $class_options = []; | |
| 32 | + public $class_options = [ ]; | |
| 24 | 33 | |
| 25 | 34 | /** |
| 26 | 35 | * @var bool Wheather to display comment list |
| ... | ... | @@ -28,44 +37,72 @@ |
| 28 | 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 | 42 | public $display_comment_form = true; |
| 34 | 43 | |
| 44 | + /** | |
| 45 | + * @var bool Whether to display success text | |
| 46 | + */ | |
| 35 | 47 | public $display_comment_success = true; |
| 36 | 48 | |
| 49 | + /** | |
| 50 | + * @var bool Whether to allow one user post multiple comments | |
| 51 | + */ | |
| 37 | 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 | 57 | public $list_options = [ |
| 42 | - 'tag' => 'div', | |
| 43 | - 'view' => 'list-comment', | |
| 58 | + 'tag' => 'div', | |
| 59 | + 'view' => 'list-comment', | |
| 44 | 60 | 'class' => 'test-class', |
| 45 | 61 | ]; |
| 46 | 62 | |
| 63 | + /** | |
| 64 | + * @var array Options sent to success part | |
| 65 | + */ | |
| 47 | 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 | 75 | public $form_options = [ |
| 54 | - 'tag' => 'div', | |
| 55 | - 'view' => 'form-comment', | |
| 76 | + 'tag' => 'div', | |
| 77 | + 'view' => 'form-comment', | |
| 56 | 78 | 'class' => 'test-class-form', |
| 57 | 79 | ]; |
| 58 | 80 | |
| 81 | + /** | |
| 82 | + * @var bool Indicates whether any successful action happened | |
| 83 | + */ | |
| 59 | 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 | 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 | 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 | 107 | public $dataProvider; |
| 71 | 108 | |
| ... | ... | @@ -75,16 +112,20 @@ |
| 75 | 112 | public function init() |
| 76 | 113 | { |
| 77 | 114 | parent::init(); |
| 115 | + \common\modules\comment\assets\CommentAsset::register($this->view); | |
| 78 | 116 | if(is_string($this->comment_class)) { |
| 79 | 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 | 126 | $this->comment_class->entity = $this->entity; |
| 84 | 127 | $this->createDataProvider(); |
| 85 | - if($this->comment_class->checkCreate($this->entity)) { | |
| 86 | - $this->handleCreate(); | |
| 87 | - } | |
| 128 | + $this->process(); | |
| 88 | 129 | ob_start(); |
| 89 | 130 | } |
| 90 | 131 | |
| ... | ... | @@ -99,62 +140,67 @@ |
| 99 | 140 | return $this->renderWidget(); |
| 100 | 141 | } |
| 101 | 142 | |
| 102 | - public function createParts() { | |
| 143 | + public function createParts() | |
| 144 | + { | |
| 103 | 145 | if($this->display_comment_success && $this->isSuccess) { |
| 104 | 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 | 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 | 150 | $result = Html::encode(ArrayHelper::remove($this->success_options, 'content', $this->success_text)); |
| 109 | 151 | } else { |
| 110 | 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 | 158 | if($this->display_comment_list) { |
| 117 | 159 | $tag = ArrayHelper::remove($this->list_options, 'tag', 'div'); |
| 118 | 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 | 164 | if($this->display_comment_form) { |
| 123 | 165 | $tag = ArrayHelper::remove($this->form_options, 'tag', 'div'); |
| 124 | 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 | 171 | public function createDataProvider() |
| 130 | 172 | { |
| 131 | 173 | $this->dataProvider = new \yii\data\ActiveDataProvider([ |
| 132 | - 'query' => $this->comment_class->getComments($this->entity), | |
| 174 | + 'query' => $this->comment_class->getComments($this->entity), | |
| 133 | 175 | 'pagination' => [ |
| 134 | 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 | 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 | 192 | throw new \yii\base\InvalidConfigException("form_options[view] must be set"); |
| 149 | 193 | } |
| 150 | 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 | 198 | 'dataProvider' => $this->dataProvider, |
| 154 | 199 | ]); |
| 155 | 200 | } |
| 156 | 201 | |
| 157 | - public function renderWidget() { | |
| 202 | + public function renderWidget() | |
| 203 | + { | |
| 158 | 204 | $template = $this->template; |
| 159 | 205 | $parts = $this->parts; |
| 160 | 206 | $options = $this->options; |
| ... | ... | @@ -165,11 +211,13 @@ |
| 165 | 211 | return Html::tag($tag, $template, $options); |
| 166 | 212 | } |
| 167 | 213 | |
| 168 | - public function handleCreate() | |
| 214 | + public function process() | |
| 169 | 215 | { |
| 170 | 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 | 224 | \ No newline at end of file | ... | ... |
common/modules/comment/widgets/views/form-comment.php
| 1 | 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 | 8 | use yii\widgets\ActiveForm; |
| 8 | 9 | use yii\helpers\Html; |
| ... | ... | @@ -11,42 +12,59 @@ |
| 11 | 12 | <div class="new-portf-comm-count">Комментарии: <?= $dataProvider->totalCount ?></div> |
| 12 | 13 | |
| 13 | 14 | <div class="new-portf-add-comm style"> |
| 15 | + | |
| 14 | 16 | <?php |
| 15 | 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 | 29 | if($model->scenario == $model::SCENARIO_GUEST) { |
| 20 | 30 | echo $form->field($model, 'user_name', [ |
| 21 | - 'options' => [ | |
| 31 | + 'options' => [ | |
| 22 | 32 | 'class' => 'input-blocks-comm', |
| 23 | 33 | ], |
| 24 | 34 | 'inputOptions' => [ |
| 25 | 35 | 'class' => 'custom-input-4', |
| 26 | 36 | ], |
| 27 | - ])->textInput(); | |
| 37 | + ]) | |
| 38 | + ->textInput(); | |
| 28 | 39 | echo $form->field($model, 'user_email', [ |
| 29 | - 'options' => [ | |
| 40 | + 'options' => [ | |
| 30 | 41 | 'class' => 'input-blocks-comm', |
| 31 | 42 | ], |
| 32 | 43 | 'inputOptions' => [ |
| 33 | 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 | 54 | echo $form->field($model, 'text', [ |
| 38 | - 'options' => [ | |
| 55 | + 'options' => [ | |
| 39 | 56 | 'class' => 'input-blocks-comm area-comm', |
| 40 | 57 | ], |
| 41 | 58 | 'inputOptions' => [ |
| 42 | 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 | 68 | $form->end(); |
| 51 | 69 | ?> |
| 52 | 70 | </div> |
| 53 | 71 | \ No newline at end of file | ... | ... |
common/modules/comment/widgets/views/project_comment_view.php
| ... | ... | @@ -3,9 +3,9 @@ |
| 3 | 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 | 9 | * current page, starting from 0 |
| 10 | 10 | * @var \yii\widgets\ListView $widget current ListView instance |
| 11 | 11 | * @var User $user |
| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 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 | 22 | <div class="style"> |
| 23 | 23 | <div class="header-cabinet-foto"> |
| 24 | 24 | <?php |
| ... | ... | @@ -32,23 +32,29 @@ |
| 32 | 32 | <div class="new-prof-wrapper-read"> |
| 33 | 33 | <div class="new-portf-comm-read-title"> |
| 34 | 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 | 44 | </div> |
| 45 | 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 | 58 | </div> |
| 53 | 59 | <div class="blog-post-date"> |
| 54 | 60 | <span></span> |
| ... | ... | @@ -56,10 +62,23 @@ |
| 56 | 62 | </div> |
| 57 | 63 | </div> |
| 58 | 64 | |
| 59 | - <div class="new-portf-answer"> | |
| 65 | + <div class="new-portf-answer artbox_comment_text"> | |
| 60 | 66 | <?= Html::encode($model->text) ?> |
| 61 | 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 | 82 | </div> |
| 64 | 83 | <div class="style"></div> |
| 65 | 84 | </div> |
| 66 | 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 | 2 | |
| 3 | 3 | use common\models\Portfolio; |
| 4 | 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 | 10 | * @var ViewAction $this |
| 10 | 11 | * @var User $user |
| 11 | 12 | * @var Portfolio $portfolio |
| 13 | + * @var View $this | |
| 12 | 14 | */ |
| 13 | 15 | $this->params[ 'user' ] = $user; |
| 14 | 16 | |
| ... | ... | @@ -16,7 +18,7 @@ use yii\web\ViewAction; |
| 16 | 18 | ?> |
| 17 | 19 | <div class="portfolio-new-page-wrapper style"> |
| 18 | 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 | 22 | </div> |
| 21 | 23 | <div class="new-portfolio-icons-rating-wr style"> |
| 22 | 24 | <div class="new-portfolio-icons"> |
| ... | ... | @@ -40,7 +42,7 @@ use yii\web\ViewAction; |
| 40 | 42 | <div class="portfolio-project-views-img"> |
| 41 | 43 | <img src="/images/portfolio-project/ico-3.png"></div> |
| 42 | 44 | </div> |
| 43 | - <div class="portfolio-project-views-txt">XX</div> | |
| 45 | + <div class="portfolio-project-views-txt"></div> | |
| 44 | 46 | </div> |
| 45 | 47 | </div> |
| 46 | 48 | </div> |
| ... | ... | @@ -109,209 +111,213 @@ use yii\web\ViewAction; |
| 109 | 111 | } |
| 110 | 112 | ?> |
| 111 | 113 | </div> |
| 112 | - | |
| 113 | 114 | <?php |
| 114 | 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 | 118 | 'comment_class' => \common\modules\comment\models\Comment::className(), |
| 119 | + 'rating_class' => \common\modules\comment\models\Rating::className(), | |
| 117 | 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 | 127 | 'view' => 'list-comment', |
| 123 | 128 | ], |
| 124 | - 'form_options' => [ | |
| 129 | + 'form_options' => [ | |
| 125 | 130 | 'view' => 'form-comment', |
| 126 | - 'tag' => false, | |
| 131 | + 'tag' => 'div', | |
| 132 | + 'class' => 'artbox_comment_form', | |
| 127 | 133 | ], |
| 128 | - 'options' => [ | |
| 134 | + 'options' => [ | |
| 129 | 135 | 'class' => 'new-portf-comments-wr style', |
| 130 | 136 | ], |
| 131 | 137 | ]); |
| 132 | 138 | ?> |
| 133 | 139 | |
| 134 | 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 | 187 | </div> |
| 177 | 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 | 193 | </div> |
| 182 | - </div> | |
| 183 | 194 | |
| 184 | - <div class="new-portf-answer"> | |
| 185 | - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 186 | - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 187 | 195 | </div> |
| 188 | - | |
| 196 | + <div class="style"></div> | |
| 189 | 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 | 217 | </div> |
| 207 | 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 | 223 | </div> |
| 212 | - </div> | |
| 213 | 224 | |
| 214 | - <div class="new-portf-answer"> | |
| 215 | - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 216 | - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 217 | 225 | </div> |
| 218 | - | |
| 226 | + <div class="style"></div> | |
| 219 | 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 | 247 | </div> |
| 237 | 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 | 253 | </div> |
| 242 | - </div> | |
| 243 | 254 | |
| 244 | - <div class="new-portf-answer"> | |
| 245 | - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 246 | - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 247 | 255 | </div> |
| 248 | - | |
| 256 | + <div class="style"></div> | |
| 249 | 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 | 277 | </div> |
| 267 | 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 | 283 | </div> |
| 272 | - </div> | |
| 273 | 284 | |
| 274 | - <div class="new-portf-answer"> | |
| 275 | - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 276 | - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 277 | 285 | </div> |
| 278 | - | |
| 286 | + <div class="style"></div> | |
| 279 | 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 | 306 | </div> |
| 296 | 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 | 312 | </div> |
| 301 | - </div> | |
| 302 | 313 | |
| 303 | - <div class="new-portf-answer"> | |
| 304 | - <p>Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 305 | - <p>Евровагонка — удобная в монтаже фасонная доска, которая позволяет создать обшивку из плотно пригнанных элементов с качественно обработанной поверхностью. Толщина евровагонки составляет 125 мм, общая ширина (с гребнем) 960 мм, рабочая ширина 880 мм.Балкон, обшитый вагонкой, выглядит аккуратно, стильно и уютно. Монтаж обшивки вполне возможно выполнить своими силами — достаточно иметь в распоряжении необходимые инструменты и владеть базовыми навыками строительно-ремонтных работ.</p> | |
| 306 | 314 | </div> |
| 307 | - | |
| 315 | + <div class="style"></div> | |
| 308 | 316 | </div> |
| 309 | - <div class="style"></div> | |
| 310 | - </div> | |
| 311 | 317 | |
| 318 | + </div> | |
| 312 | 319 | </div> |
| 313 | - </div> | |
| 314 | - */ | |
| 320 | + */ | |
| 315 | 321 | ?> |
| 316 | 322 | </div> |
| 317 | 323 | <script> | ... | ... |