Commit 2f324895bc56cd4fca30b2028c8f6e53d80c0e67

Authored by Yarik
1 parent d6077779

test

.gitignore
  1 +/node_modules
1 2 # yii console command
2 3 /yii
3 4  
... ... @@ -22,6 +23,10 @@ Thumbs.db
22 23 composer.phar
23 24  
24 25 # Mac DS_Store Files
  26 +/server.js
  27 +/frontend/controllers/ModellingController.php
  28 +/frontend/views/modelling
  29 +/frontend/models/SMOClosed.php
25 30 .DS_Store
26 31  
27 32 # phpunit itself is not needed
... ...
common/components/rules/DeleteRule.php
... ... @@ -11,6 +11,7 @@
11 11  
12 12 public function execute ($user, $item, $params)
13 13 {
  14 + return true;
14 15 $auth = \Yii::$app->authManager;
15 16 $access = false;
16 17 if($params['record']) {
... ...
common/models/Portfolio.php
... ... @@ -25,6 +25,7 @@
25 25 * @property string $preview
26 26 * @property PortfolioSpecialization[] $portfolioSpecializations
27 27 * @property Specialization[] $specializations
  28 + * @property User $user
28 29 */
29 30 class Portfolio extends \yii\db\ActiveRecord
30 31 {
... ... @@ -55,7 +56,7 @@
55 56 'value' => new Expression('NOW()'),
56 57 ],
57 58 [
58   - 'class' => 'common\behaviors\ShowImage',
  59 + 'class' => 'common\behaviors\ShowImage',
59 60 ],
60 61 ];
61 62 }
... ... @@ -71,7 +72,7 @@
71 72 'name',
72 73 'preview',
73 74 'city',
74   - 'cover'
  75 + 'cover',
75 76 ],
76 77 'required',
77 78 ],
... ... @@ -190,6 +191,12 @@
190 191  
191 192 public function getPortfolioUsers()
192 193 {
193   - return $this->hasMany(PortfolioUser::className(), ['portfolio_id' => 'portfolio_id'])->with('user');
  194 + return $this->hasMany(PortfolioUser::className(), [ 'portfolio_id' => 'portfolio_id' ])
  195 + ->with('user');
  196 + }
  197 +
  198 + public function getUser()
  199 + {
  200 + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]);
194 201 }
195 202 }
... ...
common/models/PortfolioGallery.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace common\models;
  4 +
  5 +use Yii;
  6 +
  7 +/**
  8 + * This is the model class for table "portfolio_gallery".
  9 + *
  10 + * @property integer $portfolio_gallery_id
  11 + * @property integer $gallery_id
  12 + * @property integer $portfolio_id
  13 + * @property string $caption
  14 + * @property integer $visible
  15 + *
  16 + * @property Gallery $gallery
  17 + * @property Portfolio $portfolio
  18 + */
  19 +class PortfolioGallery extends \yii\db\ActiveRecord
  20 +{
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public static function tableName()
  25 + {
  26 + return 'portfolio_gallery';
  27 + }
  28 +
  29 + /**
  30 + * @inheritdoc
  31 + */
  32 + public function rules()
  33 + {
  34 + return [
  35 + [['gallery_id', 'portfolio_id'], 'required'],
  36 + [['gallery_id', 'portfolio_id', 'visible'], 'integer'],
  37 + [['caption'], 'string', 'max' => 255],
  38 + [['gallery_id'], 'exist', 'skipOnError' => true, 'targetClass' => Gallery::className(), 'targetAttribute' => ['gallery_id' => 'gallery_id']],
  39 + [['portfolio_id'], 'exist', 'skipOnError' => true, 'targetClass' => Portfolio::className(), 'targetAttribute' => ['portfolio_id' => 'portfolio_id']],
  40 + ];
  41 + }
  42 +
  43 + /**
  44 + * @inheritdoc
  45 + */
  46 + public function attributeLabels()
  47 + {
  48 + return [
  49 + 'portfolio_gallery_id' => Yii::t('app', 'Portfolio Gallery ID'),
  50 + 'gallery_id' => Yii::t('app', 'Gallery ID'),
  51 + 'portfolio_id' => Yii::t('app', 'Portfolio ID'),
  52 + 'caption' => Yii::t('app', 'Описание'),
  53 + 'visible' => Yii::t('app', 'Visible'),
  54 + ];
  55 + }
  56 +
  57 + /**
  58 + * @return \yii\db\ActiveQuery
  59 + */
  60 + public function getGallery()
  61 + {
  62 + return $this->hasOne(Gallery::className(), ['gallery_id' => 'gallery_id']);
  63 + }
  64 +
  65 + /**
  66 + * @return \yii\db\ActiveQuery
  67 + */
  68 + public function getPortfolio()
  69 + {
  70 + return $this->hasOne(Portfolio::className(), ['portfolio_id' => 'portfolio_id']);
  71 + }
  72 +}
... ...
common/models/PortfolioUser.php
1 1 <?php
2 2  
3   -namespace common\models;
  3 + namespace common\models;
4 4  
5   -use Yii;
  5 + use Yii;
6 6  
7   -/**
8   - * This is the model class for table "portfolio_user".
9   - *
10   - * @property integer $portfolio_user_id
11   - * @property integer $portfolio_id
12   - * @property integer $user_id
13   - * @property string $position
14   - * @property integer $time
15   - * @property integer $status
16   - *
17   - * @property Portfolio $portfolio
18   - * @property User $user
19   - */
20   -class PortfolioUser extends \yii\db\ActiveRecord
21   -{
22 7 /**
23   - * @inheritdoc
  8 + * This is the model class for table "portfolio_user".
  9 + * @property integer $portfolio_user_id
  10 + * @property integer $portfolio_id
  11 + * @property integer $user_id
  12 + * @property string $position
  13 + * @property integer $time
  14 + * @property integer $status
  15 + * @property Portfolio $portfolio
  16 + * @property User $user
24 17 */
25   - public static function tableName()
  18 + class PortfolioUser extends \yii\db\ActiveRecord
26 19 {
27   - return 'portfolio_user';
28   - }
29 20  
30   - /**
31   - * @inheritdoc
32   - */
33   - public function rules()
34   - {
35   - return [
36   - [['portfolio_id', 'user_id'], 'required'],
37   - [['portfolio_id', 'user_id', 'time'], 'integer'],
38   - [['position'], 'string', 'max' => 255],
39   - [['portfolio_id', 'user_id'], 'unique', 'targetAttribute' => ['portfolio_id', 'user_id'], 'message' => 'The combination of Portfolio ID and User ID has already been taken.'],
40   - [['portfolio_id'], 'exist', 'skipOnError' => true, 'targetClass' => Portfolio::className(), 'targetAttribute' => ['portfolio_id' => 'portfolio_id']],
41   - [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
42   - ];
43   - }
  21 + public $project;
44 22  
45   - /**
46   - * @inheritdoc
47   - */
48   - public function attributeLabels()
49   - {
50   - return [
51   - 'portfolio_user_id' => Yii::t('app', 'Portfolio User ID'),
52   - 'portfolio_id' => Yii::t('app', 'Portfolio ID'),
53   - 'user_id' => Yii::t('app', 'User ID'),
54   - 'position' => Yii::t('app', 'Position'),
55   - 'time' => Yii::t('app', 'Time'),
56   - 'status' => Yii::t('app', 'Status'),
57   - ];
58   - }
  23 + public $time_from;
59 24  
60   - /**
61   - * @return \yii\db\ActiveQuery
62   - */
63   - public function getPortfolio()
64   - {
65   - return $this->hasOne(Portfolio::className(), ['portfolio_id' => 'portfolio_id']);
66   - }
  25 + public $time_to;
  26 +
  27 + /**
  28 + * @inheritdoc
  29 + */
  30 + public static function tableName()
  31 + {
  32 + return 'portfolio_user';
  33 + }
  34 +
  35 + /**
  36 + * @inheritdoc
  37 + */
  38 + public function rules()
  39 + {
  40 + return [
  41 + [
  42 + [
  43 + 'portfolio_id',
  44 + 'user_id',
  45 + ],
  46 + 'required',
  47 + ],
  48 + [
  49 + [
  50 + 'portfolio_id',
  51 + 'user_id',
  52 + 'time',
  53 + 'status',
  54 + ],
  55 + 'integer',
  56 + ],
  57 + [
  58 + [ 'position' ],
  59 + 'string',
  60 + 'max' => 255,
  61 + ],
  62 + [
  63 + [
  64 + 'portfolio_id',
  65 + 'user_id',
  66 + ],
  67 + 'unique',
  68 + 'targetAttribute' => [
  69 + 'portfolio_id',
  70 + 'user_id',
  71 + ],
  72 + 'message' => 'The combination of Portfolio ID and User ID has already been taken.',
  73 + ],
  74 + [
  75 + [ 'portfolio_id' ],
  76 + 'exist',
  77 + 'skipOnError' => true,
  78 + 'targetClass' => Portfolio::className(),
  79 + 'targetAttribute' => [ 'portfolio_id' => 'portfolio_id' ],
  80 + ],
  81 + [
  82 + [ 'user_id' ],
  83 + 'exist',
  84 + 'skipOnError' => true,
  85 + 'targetClass' => User::className(),
  86 + 'targetAttribute' => [ 'user_id' => 'id' ],
  87 + ],
  88 + ];
  89 + }
  90 +
  91 + /**
  92 + * @inheritdoc
  93 + */
  94 + public function attributeLabels()
  95 + {
  96 + return [
  97 + 'portfolio_user_id' => Yii::t('app', 'Portfolio User ID'),
  98 + 'portfolio_id' => Yii::t('app', 'Portfolio ID'),
  99 + 'user_id' => Yii::t('app', 'User ID'),
  100 + 'position' => Yii::t('app', 'Должность'),
  101 + 'time' => Yii::t('app', 'Рабочих часов'),
  102 + 'status' => Yii::t('app', 'Статус'),
  103 + 'project' => Yii::t('app', 'Проект'),
  104 + 'time_from' => Yii::t('app', 'часы от'),
  105 + 'time_to' => Yii::t('app', 'часы до'),
  106 + ];
  107 + }
  108 +
  109 + /**
  110 + * @return \yii\db\ActiveQuery
  111 + */
  112 + public function getPortfolio()
  113 + {
  114 + return $this->hasOne(Portfolio::className(), [ 'portfolio_id' => 'portfolio_id' ])
  115 + ->inverseOf('portfolioUsers');
  116 + }
  117 +
  118 + /**
  119 + * @return \yii\db\ActiveQuery
  120 + */
  121 + public function getUser()
  122 + {
  123 + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]);
  124 + }
  125 +
  126 + public function afterSave($insert, $changedAttributes)
  127 + {
  128 + if(!$insert && array_key_exists('status', $changedAttributes)) {
  129 + $portfolioGallery = PortfolioGallery::find()
  130 + ->where([
  131 + 'portfolio_id' => $this->portfolio_id,
  132 + 'user_id' => $this->user_id,
  133 + ])
  134 + ->one();
  135 + if(empty( $portfolioGallery )) {
  136 + $gallery = new Gallery([
  137 + 'user_id' => $this->user_id,
  138 + 'name' => $this->portfolio->name,
  139 + ]);
  140 + if($gallery->save()) {
  141 + $portfolioGallery = new PortfolioGallery([
  142 + 'gallery_id' => $gallery->gallery_id,
  143 + 'portfolio_id' => $this->portfolio_id,
  144 + 'user_id' => $this->user_id,
  145 + ]);
  146 + $portfolioGallery->save();
  147 + } else {
  148 + throw new \Exception('Невозможно создать галерею пользователя ' . $this->user_id . ' для проекта ' . $this->portfolio_id);
  149 + }
  150 + }
  151 + }
  152 + parent::afterSave($insert, $changedAttributes);
  153 + }
  154 +
  155 + public function getPortfolioGallery()
  156 + {
  157 + return $this->hasOne(PortfolioGallery::className(), [
  158 + 'portfolio_id' => 'portfolio_id',
  159 + 'user_id' => 'user_id',
  160 + ]);
  161 + }
  162 +
  163 + public function getGallery()
  164 + {
  165 + return $this->hasOne(Gallery::className(), [
  166 + 'gallery_id' => 'gallery_id',
  167 + 'user_id' => 'user_id',
  168 + ])
  169 + ->via('portfolioGallery');
  170 + }
67 171  
68   - /**
69   - * @return \yii\db\ActiveQuery
70   - */
71   - public function getUser()
72   - {
73   - return $this->hasOne(User::className(), ['id' => 'user_id']);
74 172 }
75   -}
... ...
common/models/PortfolioUserSearch.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace common\models;
  4 +
  5 + use Yii;
  6 + use yii\data\ActiveDataProvider;
  7 +
  8 + class PortfolioUserSearch extends PortfolioUser
  9 + {
  10 +
  11 + /**
  12 + * @inheritdoc
  13 + */
  14 + public function rules()
  15 + {
  16 + return [
  17 + [
  18 + [
  19 + 'project',
  20 + 'position',
  21 + ],
  22 + 'safe',
  23 + ],
  24 + [
  25 + [
  26 + 'time_from',
  27 + 'time_to',
  28 + ],
  29 + 'integer',
  30 + 'min' => 0,
  31 + ],
  32 + [
  33 + [
  34 + 'time_to',
  35 + ],
  36 + 'compare',
  37 + 'compareAttribute' => 'time_from',
  38 + 'operator' => '>=',
  39 + ],
  40 + [
  41 + [
  42 + 'status',
  43 + ],
  44 + 'integer',
  45 + 'min' => 1,
  46 + 'max' => 2,
  47 + ],
  48 + ];
  49 + }
  50 +
  51 + public function search($params)
  52 + {
  53 + $query = PortfolioUser::find()
  54 + ->where([ 'portfolio_user.user_id' => \Yii::$app->user->id ]);
  55 +
  56 + $dataProvider = new ActiveDataProvider([
  57 + 'query' => $query,
  58 + ]);
  59 +
  60 + $this->load($params);
  61 +
  62 + if(!$this->validate()) {
  63 + // uncomment the following line if you do not want to return any records when validation fails
  64 + // $query->where('0=1');
  65 + return $dataProvider;
  66 + }
  67 +
  68 + if(!empty( $this->time_from ) && !empty( $this->time_to )) {
  69 + $query->andWhere([
  70 + 'between',
  71 + 'time',
  72 + $this->time_from,
  73 + $this->time_to,
  74 + ]);
  75 + } elseif(!empty( $this->time_from )) {
  76 + $query->andWhere([
  77 + '>=',
  78 + 'time',
  79 + $this->time_from,
  80 + ]);
  81 + } elseif(!empty( $this->time_to )) {
  82 + $query->andWhere([
  83 + '<=',
  84 + 'time',
  85 + $this->time_to,
  86 + ]);
  87 + }
  88 +
  89 + $query->andFilterWhere(['status' => $this->status]);
  90 +
  91 + $query->andFilterWhere([
  92 + 'like',
  93 + 'LOWER(position)',
  94 + mb_strtolower($this->position),
  95 + ]);
  96 +
  97 + $query->andFilterWhere([
  98 + 'like',
  99 + 'LOWER(portfolio.name)',
  100 + mb_strtolower($this->project),
  101 + ]);
  102 +
  103 + return $dataProvider;
  104 + }
  105 + }
... ...
common/models/TenderSearch.php
... ... @@ -117,8 +117,7 @@
117 117 {
118 118 $query = Project::find()
119 119 ->joinWith('projectSpecializations')
120   - ->joinWith('projectPayments')
121   - ->andWhere([ 'hidden' => 0 ]);
  120 + ->joinWith('projectPayments');
122 121  
123 122 $dataProvider = new ActiveDataProvider([
124 123 'query' => $query,
... ...
common/models/UserSearch.php
... ... @@ -65,7 +65,7 @@
65 65 $dataProvider = new ActiveDataProvider([
66 66 'query' => $query,
67 67 'pagination' => new Pagination([
68   - 'pageSize' => 10,
  68 + 'pageSize' => 5,
69 69 ]),
70 70 'sort' => new Sort([
71 71 'defaultOrder' => [
... ...
common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php
... ... @@ -11,7 +11,7 @@
11 11  
12 12 public function execute($user, $item, $params)
13 13 {
14   - return true;
  14 + return false;
15 15 }
16 16  
17 17 }
18 18 \ No newline at end of file
... ...
console/migrations/m160411_143038_create_portfolio_gallery.php 0 → 100644
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + /**
  6 + * Handles the creation for table `portfolio_gallery`.
  7 + */
  8 + class m160411_143038_create_portfolio_gallery extends Migration
  9 + {
  10 +
  11 + /**
  12 + * @inheritdoc
  13 + */
  14 + public function up()
  15 + {
  16 + $this->createTable('portfolio_gallery', [
  17 + 'portfolio_gallery_id' => $this->primaryKey(),
  18 + 'gallery_id' => $this->integer()
  19 + ->notNull(),
  20 + 'portfolio_id' => $this->integer()
  21 + ->notNull(),
  22 + 'user_id' => $this->integer()
  23 + ->notNull(),
  24 + 'caption' => $this->string(),
  25 + 'visible' => $this->smallInteger()
  26 + ->defaultValue(1),
  27 + ]);
  28 + $this->addForeignKey('portfolio_gallery_gallery', '{{%portfolio_gallery}}', 'gallery_id', '{{%gallery}}', 'gallery_id', 'CASCADE', 'CASCADE');
  29 + $this->addForeignKey('portfolio_gallery_portfolio', '{{%portfolio_gallery}}', 'portfolio_id', '{{%portfolio}}', 'portfolio_id', 'CASCADE', 'CASCADE');
  30 + $this->addForeignKey('portfolio_gallery_user', '{{%portfolio_gallery}}', 'user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
  31 + }
  32 +
  33 + /**
  34 + * @inheritdoc
  35 + */
  36 + public function down()
  37 + {
  38 + $this->dropForeignKey('portfolio_gallery_user', '{{%portfolio_gallery}}');
  39 + $this->dropForeignKey('portfolio_gallery_gallery', '{{%portfolio_gallery}}');
  40 + $this->dropForeignKey('portfolio_gallery_portfolio', '{{%portfolio_gallery}}');
  41 + $this->dropTable('portfolio_gallery');
  42 + }
  43 + }
... ...
frontend/controllers/AccountsController.php
... ... @@ -19,6 +19,7 @@
19 19 use common\models\PortfolioSearch;
20 20 use common\models\PortfolioSpecialization;
21 21 use common\models\PortfolioUser;
  22 + use common\models\PortfolioUserSearch;
22 23 use common\models\Project;
23 24 use common\models\ProjectSearch;
24 25 use common\models\Specialization;
... ... @@ -33,6 +34,7 @@
33 34 use common\models\UserInfo;
34 35  
35 36 use yii\base\ErrorException;
  37 + use yii\data\Sort;
36 38 use yii\db\ActiveRecord;
37 39 use yii\filters\AccessControl;
38 40 use yii\filters\VerbFilter;
... ... @@ -77,6 +79,18 @@
77 79 ];
78 80 }
79 81  
  82 + public function beforeAction($action)
  83 + {
  84 + $portfolio_user_count = PortfolioUser::find()
  85 + ->where([
  86 + 'user_id' => \Yii::$app->user->id,
  87 + 'status' => 2,
  88 + ])
  89 + ->count();
  90 + $this->view->params[ 'portfolio_user_count' ] = $portfolio_user_count;
  91 + return parent::beforeAction($action); // TODO: Change the autogenerated stub
  92 + }
  93 +
80 94 /**
81 95 * Page of additional skills, consist:
82 96 * * working with programs;
... ... @@ -456,6 +470,107 @@
456 470 return $this->renderAjax('_job_form', [ 'index' => $lastindex + 1 ]);
457 471 }
458 472  
  473 + public function actionParticipant()
  474 + {
  475 + $searchModel = new PortfolioUserSearch();
  476 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  477 + $dataProvider->query->joinWith('portfolio');
  478 + $dataProvider->sort = new Sort([
  479 + 'defaultOrder' => [
  480 + 'portfolio_user_id' => SORT_ASC,
  481 + ],
  482 + 'attributes' => [
  483 + 'project' => [
  484 + 'asc' => [
  485 + 'portfolio.name' => SORT_ASC,
  486 + ],
  487 + 'desc' => [
  488 + 'portfolio.name' => SORT_DESC,
  489 + ],
  490 + ],
  491 + 'portfolio_user_id',
  492 + 'position',
  493 + 'time',
  494 + 'status',
  495 + ],
  496 + ]);
  497 + $dataProvider->pagination->pageSize = 5;
  498 + return $this->render('participant', [
  499 + 'searchModel' => $searchModel,
  500 + 'dataProvider' => $dataProvider,
  501 + ]);
  502 + }
  503 +
  504 + public function actionParticipantConfirm($id)
  505 + {
  506 + $portfolioUser = PortfolioUser::find()
  507 + ->where([
  508 + 'portfolio_user_id' => $id,
  509 + 'user_id' => \Yii::$app->user->id,
  510 + 'status' => 2,
  511 + ])
  512 + ->one();
  513 + if(empty( $portfolioUser )) {
  514 + throw new NotFoundHttpException('Приглашение не найдено');
  515 + }
  516 + $portfolioUser->status = 1;
  517 + if($portfolioUser->save(false)) {
  518 + return $this->redirect([ 'accounts/participant' ]);
  519 + } else {
  520 + throw new \Exception('Неизвестная ошибка');
  521 + }
  522 + }
  523 +
  524 + public function actionParticipantDelete($id)
  525 + {
  526 + $portfolioUser = PortfolioUser::find()
  527 + ->where([
  528 + 'portfolio_user_id' => $id,
  529 + 'user_id' => \Yii::$app->user->id,
  530 + ])
  531 + ->one();
  532 + if(empty( $portfolioUser )) {
  533 + throw new NotFoundHttpException('Приглашение не найдено');
  534 + }
  535 + if($portfolioUser->delete()) {
  536 + return $this->redirect([ 'accounts/participant' ]);
  537 + } else {
  538 + throw new \Exception('Неизвестная ошибка');
  539 + }
  540 + }
  541 +
  542 + public function actionParticipantEdit($id)
  543 + {
  544 + $portfolioUser = PortfolioUser::find()
  545 + ->where([
  546 + 'portfolio_user_id' => $id,
  547 + 'user_id' => \Yii::$app->user->id,
  548 + ])
  549 + ->with('gallery')
  550 + ->one();
  551 + if(empty( $portfolioUser )) {
  552 + throw new NotFoundHttpException('Приглашение не найдено');
  553 + }
  554 + $post = \Yii::$app->request->post();
  555 + if(!empty( $post )) {
  556 + if($portfolioUser->load($post)) {
  557 + $portfolioUser->status = 1;
  558 + if($portfolioUser->save()) {
  559 + if(!empty($portfolioUser->gallery)) {
  560 + $portfolioUser->gallery->load($post);
  561 + $portfolioUser->portfolioGallery->load($post);
  562 + if($portfolioUser->gallery->save() && $portfolioUser->portfolioGallery->save()) {
  563 + return $this->redirect(['accounts/participant']);
  564 + }
  565 + } else {
  566 + return $this->redirect(['accounts/participant-edit', 'id' => $portfolioUser->portfolio_user_id]);
  567 + }
  568 + }
  569 + }
  570 + }
  571 + return $this->render('participant-edit', [ 'model' => $portfolioUser ]);
  572 + }
  573 +
459 574 /**
460 575 * Page of User's portfolio
461 576 * @return string
... ... @@ -510,7 +625,7 @@
510 625 foreach($post[ 'PortfolioUser' ] as $index => $item) {
511 626 $portfolioUsers[ $index ] = new PortfolioUser([ 'portfolio_id' => $portfolio->portfolio_id ]);
512 627 }
513   - $success = (PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers));
  628 + $success = ( PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers) );
514 629 if($success) {
515 630 foreach($portfolioUsers as $index => $portfolioUser) {
516 631 $portfolioUser->save(false);
... ... @@ -562,7 +677,13 @@
562 677 ->all();
563 678  
564 679 $post = \Yii::$app->request->post();
565   - $portfolioUsers = $portfolio->portfolioUsers;
  680 + $portfolioUsers = $portfolio->getPortfolioUsers()
  681 + ->where([ 'status' => 2 ])
  682 + ->all();
  683 + $portfolioUsersConfirmed = $portfolio->getPortfolioUsers()
  684 + ->where([ 'status' => 1 ])
  685 + ->indexBy('user_id')
  686 + ->all();
566 687  
567 688 if(!empty( $post )) {
568 689 $portfolio->load($post);
... ... @@ -573,18 +694,33 @@
573 694 foreach($portfolio->specializationInput as $one_specialization) {
574 695 $portfolio->link('specializations', Specialization::findOne($one_specialization));
575 696 }
576   - $portfolio->unlinkAll('portfolioUsers', true);
  697 + PortfolioUser::deleteAll([
  698 + 'portfolio_id' => $portfolio->portfolio_id,
  699 + 'status' => 2,
  700 + ]);
577 701 $success = true;
578 702 if(!empty( $post[ 'PortfolioUser' ] )) {
579 703 $portfolioUsers = [ ];
580 704 foreach($post[ 'PortfolioUser' ] as $index => $item) {
581 705 $portfolioUsers[ $index ] = new PortfolioUser([ 'portfolio_id' => $portfolio->portfolio_id ]);
582 706 }
583   - $success = (PortfolioUser::loadMultiple($portfolioUsers, $post) && PortfolioUser::validateMultiple($portfolioUsers));
  707 + $success = PortfolioUser::loadMultiple($portfolioUsers, $post);
  708 + foreach($portfolioUsers as $index => $portfolioUser) {
  709 + if($portfolioUser->status == 1) {
  710 + $portfolioUsersConfirmed[ $portfolioUser->user_id ]->position = $portfolioUser->position;
  711 + $portfolioUsersConfirmed[ $portfolioUser->user_id ]->time = $portfolioUser->time;
  712 + unset( $portfolioUsers[ $index ] );
  713 + }
  714 + }
  715 + $success = ( $success && PortfolioUser::validateMultiple($portfolioUsers) && PortfolioUser::validateMultiple($portfolioUsersConfirmed) );
584 716 if($success) {
585 717 foreach($portfolioUsers as $index => $portfolioUser) {
  718 + $portfolioUser->status = 2;
586 719 $portfolioUser->save(false);
587 720 }
  721 + foreach($portfolioUsersConfirmed as $index => $portfolioUserConfirmed) {
  722 + $portfolioUserConfirmed->save(false);
  723 + }
588 724 }
589 725 }
590 726 if($success) {
... ... @@ -594,10 +730,11 @@
594 730 }
595 731  
596 732 return $this->render('_portfolio_form', [
597   - 'portfolio' => $portfolio,
598   - 'specializations' => $specializations,
599   - 'galleries' => $galleries,
600   - 'portfolioUsers' => $portfolioUsers,
  733 + 'portfolio' => $portfolio,
  734 + 'specializations' => $specializations,
  735 + 'galleries' => $galleries,
  736 + 'portfolioUsers' => $portfolioUsers,
  737 + 'portfolioUsersConfirmed' => $portfolioUsersConfirmed,
601 738 ]);
602 739 }
603 740  
... ...
frontend/controllers/AjaxController.php
1 1 <?php
2 2 namespace frontend\controllers;
3 3  
  4 + use common\models\Portfolio;
  5 + use common\models\PortfolioUser;
4 6 use common\models\User;
5 7 use common\models\UserSearch;
6 8 use yii\db\ActiveRecord;
... ... @@ -26,7 +28,11 @@
26 28 $ids = json_decode(\Yii::$app->request->get('ids'));
27 29 $model = new UserSearch();
28 30 $dataProvider = $model->search(\Yii::$app->request->queryParams);
29   - $dataProvider->query->andFilterWhere(['not in', 'id', $ids]);
  31 + $dataProvider->query->andFilterWhere([
  32 + 'not in',
  33 + 'id',
  34 + $ids,
  35 + ]);
30 36 $dataProvider->query->andWhere([
31 37 'user_info.is_freelancer' => 1,
32 38 'type' => 1,
... ... @@ -90,4 +96,53 @@
90 96 ];
91 97 }
92 98  
  99 + public function actionPortfolioUserRemove()
  100 + {
  101 + $request = \Yii::$app->request;
  102 + $response = \Yii::$app->response;
  103 + $response->format = $response::FORMAT_JSON;
  104 + $post = $request->post();
  105 + if(empty( $post[ 'user_id' ] ) || empty( $post[ 'portfolio_id' ] )) {
  106 + return [ 'error' => 'user_id и portfolio_id должны быть заполнены.' ];
  107 + }
  108 + $user_id = $post[ 'user_id' ];
  109 + $portfolio_id = $post[ 'portfolio_id' ];
  110 + $portfolio = Portfolio::find()
  111 + ->where([
  112 + 'portfolio_id' => $portfolio_id,
  113 + 'user_id' => \Yii::$app->user->id,
  114 + ])
  115 + ->one();
  116 + if(empty( $portfolio )) {
  117 + return [ 'error' => 'Запись не найдена' ];
  118 + }
  119 + $user = User::find()
  120 + ->where([ 'id' => $user_id ])
  121 + ->one();
  122 + if(empty( $user )) {
  123 + return [ 'error' => 'Пользователь не найден' ];
  124 + }
  125 + $portfolio_user = PortfolioUser::find()
  126 + ->where([
  127 + 'portfolio_id' => $portfolio->portfolio_id,
  128 + 'user_id' => $user->id,
  129 + 'status' => 1,
  130 + ])
  131 + ->one();
  132 + if(empty( $portfolio_user )) {
  133 + return [ 'error' => 'Пользователь не относится к данной записи' ];
  134 + }
  135 + if($portfolio_user->delete()) {
  136 + return [
  137 + 'result' => [
  138 + 'message' => 'Пользователь удален',
  139 + 'user_id' => $user->id,
  140 + 'portfolio_id' => $portfolio->portfolio_id,
  141 + ],
  142 + ];
  143 + } else {
  144 + return [ 'error' => 'Ошибка удаления' ];
  145 + }
  146 + }
  147 +
93 148 }
... ...
frontend/controllers/SearchController.php
... ... @@ -63,6 +63,7 @@ use common\models\Social;
63 63 {
64 64 $model = new TenderSearch();
65 65 $dataProvider = $model->search(Yii::$app->request->queryParams);
  66 + $dataProvider->query->andWhere(['hidden' => 0]);
66 67 $dataProvider->setPagination([
67 68 'pageSize' => 10,
68 69 ]);
... ...
frontend/models/SMOClosed.php 0 → 100644
  1 +<?php
  2 + namespace frontend\models;
  3 +
  4 + use yii\base\Exception;
  5 + use yii\base\InvalidParamException;
  6 + use yii\base\Model;
  7 +
  8 + class SMOClosed extends Model
  9 + {
  10 +
  11 + public $n;
  12 +
  13 + public $N;
  14 +
  15 + public $p;
  16 +
  17 + public $K;
  18 +
  19 + public $r;
  20 +
  21 + public $mu;
  22 +
  23 + public $e;
  24 +
  25 + public $b;
  26 +
  27 + public $k;
  28 +
  29 + public $probs;
  30 +
  31 + public $SMO;
  32 +
  33 + public $C;
  34 +
  35 + public $L;
  36 +
  37 + public $R;
  38 +
  39 + public $M;
  40 +
  41 + public $La;
  42 +
  43 + public $T;
  44 +
  45 + public $Q;
  46 +
  47 + function __construct(array $config)
  48 + {
  49 + parent::__construct($config);
  50 + if(!intval($this->n)) {
  51 + throw new InvalidParamException('Кількість СМО має бути цілим невід\'ємним числом');
  52 + } else {
  53 + $this->k[ 0 ] = 0;
  54 + for($i = 1; $i <= $this->n; $i++) {
  55 + for($j = 1; $j <= $this->n; $j++) {
  56 + $this->p[ $i ][ $j ] = 0;
  57 + $this->r[ $i ] = 1;
  58 + $this->mu[ $i ] = 0;
  59 + }
  60 + }
  61 + }
  62 + }
  63 +
  64 + public function attributeLabels()
  65 + {
  66 + return [
  67 + 'n' => 'Кількість систем масового обслуговування (n)',
  68 + 'N' => 'Кількість вимог в мережі масового обслуговування (N)',
  69 + 'p' => 'Матриця ймовірностей (p<sub>i,j</sub>)',
  70 + 'K' => 'Показники системи масового обслуговування (K)',
  71 + 'r' => 'Кількість каналів обслуговування (r)',
  72 + 'mu' => 'Інтенсивність обслуговування каналом (1/&mu;)',
  73 + 'e' => 'Коефіцієнт передачі (e)',
  74 + 'b' => 'Початкова СМО (e = 1)',
  75 + 'k' => 'Масив вимог',
  76 + 'probs' => 'Допоміжні функції p<sub>i</sub>(k)',
  77 + 'SMO' => 'Ймовірність перебування j вимоги в i-тій СМО P<sub>СМО<sub>i</sub></sub>(j)',
  78 + 'C' => 'Нормуючий множник (C(N))',
  79 + 'L' => 'Середня кількість вимог у черзі СМО<sub>i</sub> (L<sub>i</sub>)',
  80 + 'R' => 'Середня кількість зайнятих пристроїв у СМО<sub>i</sub> (R<sub>i</sub>)',
  81 + 'M' => 'Середня кількість вимог у СМО<sub>i</sub> (M<sub>i</sub>)',
  82 + 'La' => 'Інтенсивність вихідного потоку вимог у СМО<sub>i</sub> (&lambda;<sub>i</sub>)',
  83 + 'T' => 'Середній час перебування вимоги у СМО<sub>i</sub> (T<sub>i</sub>)',
  84 + 'Q' => 'Середній час очікування у черзі СМО<sub>i</sub> (Q<sub>i</sub>)',
  85 + ];
  86 + }
  87 +
  88 + public function rules()
  89 + {
  90 + return [
  91 + [
  92 + [ 'b' ],
  93 + 'required',
  94 + ],
  95 + [
  96 + [
  97 + 'N',
  98 + ],
  99 + 'integer',
  100 + 'min' => 1,
  101 + ],
  102 + [
  103 + [ 'n' ],
  104 + 'integer',
  105 + 'min' => 2,
  106 + 'max' => 3,
  107 + 'message' => 'На даний момент допустимі значення кількості СМО лише 2 або 3',
  108 + ],
  109 + [
  110 + [
  111 + 'p',
  112 + 'mu',
  113 + ],
  114 + 'safe',
  115 + ],
  116 + [
  117 + [ 'r' ],
  118 + 'each',
  119 + 'rule' => [
  120 + 'integer',
  121 + 'min' => 1,
  122 + ],
  123 + ],
  124 + [
  125 + [ 'mu' ],
  126 + 'each',
  127 + 'rule' => [
  128 + 'number',
  129 + 'min' => 0,
  130 + ],
  131 + ],
  132 + [
  133 + [ 'b' ],
  134 + 'integer',
  135 + 'min' => 1,
  136 + ],
  137 + [
  138 + [ 'b' ],
  139 + 'compare',
  140 + 'compareAttribute' => 'n',
  141 + 'operator' => '<=',
  142 + ],
  143 + [
  144 + [ 'b' ],
  145 + 'default',
  146 + 'value' => 1,
  147 + ],
  148 + ];
  149 + }
  150 +
  151 + public function buildk()
  152 + {
  153 + if(!empty($this->N)) {
  154 + for($i = 1; $i <= $this->N; $i++) {
  155 + $this->k[$i] = $i;
  156 + }
  157 + }
  158 + }
  159 +
  160 + public function buildE($antiloop = true)
  161 + {
  162 + $this->e[ $this->b ] = 1;
  163 + for($k = 1; $k <= $this->n; $k++) {
  164 + if($k == $this->b) {
  165 + continue;
  166 + } else {
  167 + $this->e[ $k ] = '';
  168 + }
  169 + }
  170 + foreach($this->p as $i => $vals) {
  171 + foreach($vals as $j => $val) {
  172 + if($j == $this->b) {
  173 + continue;
  174 + }
  175 + if($val != 0) {
  176 + $this->e[ $j ] .= '{' . $i . '};';
  177 + }
  178 + }
  179 + }
  180 + do {
  181 + $iteration = 0;
  182 + $found = 0;
  183 + foreach($this->e as $i => $val) {
  184 + if(!preg_match('/\{\d\}/', $val)) {
  185 + foreach($this->e as $j => $value) {
  186 + if(preg_match('/\{' . $i . '\}/', $this->e[ $j ])) {
  187 + $this->e[ $j ] = preg_replace('/\{' . $i . '\}/', ( $this->p[ $i ][ $j ] * $val ), $this->e[ $j ]);
  188 + $found = 1;
  189 + }
  190 + }
  191 + }
  192 + }
  193 + if($antiloop) {
  194 + $iteration++;
  195 + }
  196 + } while($found && $iteration < 100);
  197 + foreach($this->e as $i => $val) {
  198 + if(strpos($val, ';') !== false) {
  199 + $this->e[ $i ] = array_sum(explode(';', $val));
  200 + }
  201 + }
  202 + }
  203 +
  204 + public function buildProbs()
  205 + {
  206 + for($q = 1; $q <= $this->n; $q++) {
  207 + foreach($this->k as $k) {
  208 + $prob = pow($this->e[ $q ] * $this->mu[ $q ], $k);
  209 + if($k <= $this->r[ $q ]) {
  210 + $prob = $prob * 1 / $this->factorial($k);
  211 + } else {
  212 + $prob = $prob * 1 / $this->factorial($this->r[ $q ]) * pow($this->r[ $q ], ( $k - $this->r[ $q ] ));
  213 + }
  214 + $this->probs[ $q ][ $k ] = $prob;
  215 + unset( $prob );
  216 + }
  217 + }
  218 + }
  219 +
  220 + public function factorial($x)
  221 + {
  222 + $x = intval($x);
  223 + if(!is_int($x) || $x < 0) {
  224 + throw new Exception('Factorial must be greater than 0');
  225 + }
  226 + $res = 1;
  227 + for($i = 1; $i <= $x; $i++) {
  228 + $res *= $i;
  229 + }
  230 + return $res;
  231 + }
  232 +
  233 + public function buildC()
  234 + {
  235 + $result = 0;
  236 + if($this->n == 2) {
  237 + for($a = 0; $a <= $this->N; $a++) {
  238 + $result += $this->probs[1][$a] * $this->probs[2][$this->N - $a];
  239 + }
  240 + } elseif($this->n == 3) {
  241 + for($a = 0; $a <= $this->N; $a++) {
  242 + $sum = 0;
  243 + for($b = 0; $b <= ( $this->N - $a ); $b++) {
  244 + $sum += $this->findSum($b, $a);
  245 + }
  246 + $result += $sum * $this->probs[ 1 ][ $a ];
  247 + unset( $sum );
  248 + }
  249 + }
  250 + $this->C = pow($result, ( -1 ));
  251 + }
  252 +
  253 + public function findSum($b, $a)
  254 + {
  255 + return $this->probs[ 2 ][ $b ] * $this->probs[ 3 ][ $this->N - $a - $b ];
  256 + }
  257 +
  258 + public function buildSMO()
  259 + {
  260 + for($q = 1; $q <= $this->n; $q++) {
  261 + foreach($this->k as $k) {
  262 + $sum = 0;
  263 + if($this->n == 2) {
  264 + if($q == 1) {
  265 + $sum += $this->probs[1][$k]*$this->probs[2][$this->N - $k];
  266 + } elseif($q == 2) {
  267 + $sum += $this->probs[1][$this->N - $k]*$this->probs[2][$k];
  268 + }
  269 + } elseif($this->n == 3) {
  270 + for($a = 0; $a <= ($this->N - $k); $a++) {
  271 + if($q == 1) {
  272 + $sum += $this->probs[1][$k]*$this->probs[2][$a]*$this->probs[3][($this->N - $k - $a)];
  273 + } elseif($q == 2) {
  274 + $sum += $this->probs[1][$a]*$this->probs[2][$k]*$this->probs[3][($this->N - $k - $a)];
  275 + } elseif($q ===3) {
  276 + $sum += $this->probs[1][$a]*$this->probs[2][($this->N - $k - $a)]*$this->probs[3][$k];
  277 + }
  278 + }
  279 + }
  280 + $this->SMO[$q][$k] = $sum*$this->C;
  281 + unset($sum);
  282 + }
  283 + }
  284 + }
  285 +
  286 + public function testSMO()
  287 + {
  288 + $message = '';
  289 + foreach($this->SMO as $K => $vals) {
  290 + $message .= 'SUM of SMO'.$K.': ';
  291 + $sum = 0;
  292 + foreach($vals as $val) {
  293 + $sum += $val;
  294 + }
  295 + $message .= $sum.'; <br>';
  296 + unset($sum);
  297 + }
  298 + return $message;
  299 + }
  300 +
  301 + public function buildL()
  302 + {
  303 + for($i = 1; $i <= $this->n; $i++) {
  304 + $sum = 0;
  305 + for($j = ($this->r[$i] + 1); $j <= $this->N; $j++) { // Maybe error
  306 + $sum += ($j - $this->r[$i]) * $this->SMO[$i][$j];
  307 + }
  308 + $this->L[$i] = $sum;
  309 + unset($sum);
  310 + }
  311 + }
  312 +
  313 + public function buildR()
  314 + {
  315 + for($i = 1; $i <= $this->n; $i++) {
  316 + $sum = 0;
  317 + for($j = 0; $j <= ($this->r[$i] - 1); $j++) {
  318 + $sum += ($this->r[$i] - $j) * $this->SMO[$i][$j];
  319 + }
  320 + $sum = $this->r[$i] - $sum;
  321 + $this->R[$i] = $sum;
  322 + unset($sum);
  323 + }
  324 + }
  325 +
  326 + public function buildM()
  327 + {
  328 + for($i = 1; $i <= $this->n; $i++) {
  329 + $this->M[$i] = $this->L[$i] + $this->R[$i];
  330 + }
  331 + }
  332 +
  333 + public function buildLa()
  334 + {
  335 + for($i = 1; $i <= $this->n; $i++) {
  336 + $this->La[$i] = $this->R[$i] * pow($this->mu[$i], (-1));
  337 + }
  338 + }
  339 +
  340 + public function buildT()
  341 + {
  342 + for($i = 1; $i <= $this->n; $i++) {
  343 + $this->T[$i] = $this->M[$i] / $this->La[$i];
  344 + }
  345 + }
  346 +
  347 + public function buildQ()
  348 + {
  349 + for($i = 1; $i <= $this->n; $i++) {
  350 + $this->Q[$i] = $this->L[$i] / $this->La[$i];
  351 + }
  352 + }
  353 + }
0 354 \ No newline at end of file
... ...
frontend/views/accounts/_portfolio_form.php
1 1 <?php
2 2 /**
3   - * @var View $this
4   - * @var Portfolio $portfolio
5   - * @var integer[] $specializations
6   - * @var string[] $galleries
  3 + * @var View $this
  4 + * @var Portfolio $portfolio
  5 + * @var integer[] $specializations
  6 + * @var string[] $galleries
  7 + * @var PortfolioUser[] $portfolioUsers
  8 + * @var PortfolioUser[] $portfolioUsersConfirmed
7 9 */
8 10 use common\components\Request;
9 11 use common\models\Option;
10 12 use common\models\Portfolio;
  13 + use common\models\PortfolioUser;
11 14 use common\models\Specialization;
12 15 use common\modules\file\widgets\ImageUploader;
13 16 use common\modules\file\widgets\ImageUploaderInput;
... ... @@ -185,21 +188,42 @@
185 188 <div class="clearfix"></div>
186 189  
187 190 <?php
188   - /* == Project add user block == */
  191 + /* == Project add user block == */
189 192 ?>
190 193 <div class="add_project_user_wrapper" id="<?= $form->id ?>_project_user">
191 194 <p>Добавить пользователя</p>
192 195 <p><?= Html::a('Добавить', false, [ 'class' => 'add_project_user_link' ]) ?></p>
  196 + <p>Отправлено предложение:</p>
193 197 <div class="add_project_user_list">
194 198 <?php
195 199 foreach($portfolioUsers as $portfolioUser) {
196   - echo $this->render('@frontend/views/ajax/project_user', ['model' => $portfolioUser, 'user' => $portfolioUser->user]);
197   - }
  200 + echo $this->render('@frontend/views/ajax/project_user', [
  201 + 'model' => $portfolioUser,
  202 + 'user' => $portfolioUser->user,
  203 + ]);
  204 + }
198 205 ?>
199 206 </div>
  207 + <?php
  208 + if(!empty( $portfolioUsersConfirmed )) {
  209 + ?>
  210 + <p class="added_project_user_header">Подтвержденные:</p>
  211 + <div class="added_project_user_list">
  212 + <?php
  213 + foreach($portfolioUsersConfirmed as $portfolioUserConfirmed) {
  214 + echo $this->render('@frontend/views/ajax/project_user', [
  215 + 'model' => $portfolioUserConfirmed,
  216 + 'user' => $portfolioUserConfirmed->user,
  217 + ]);
  218 + }
  219 + ?>
  220 + </div>
  221 + <?php
  222 + }
  223 + ?>
200 224 </div>
201 225 <?php
202   - /* == End of project add user block == */
  226 + /* == End of project add user block == */
203 227 ?>
204 228  
205 229 </div>
... ...
frontend/views/accounts/participant-edit.php 0 → 100644
  1 +<?php
  2 + use common\models\PortfolioUser;
  3 + use common\modules\file\widgets\ImageUploader;
  4 + use yii\helpers\Html;
  5 + use yii\web\View;
  6 + use yii\widgets\ActiveForm;
  7 +
  8 + /**
  9 + * @var View $this
  10 + * @var PortfolioUser $model
  11 + */
  12 + $this->title = 'Редактирование участия в проекте';
  13 + $this->params[ 'breadcrumbs' ][] = $this->title;
  14 +?>
  15 +<div class="login-left-column-title"><?= $this->title ?></div>
  16 +<div>
  17 + <p>Редактировать информацию о себе:</p>
  18 + <?php
  19 + if($model->status != 1) {
  20 + ?>
  21 + <div class="alert alert-info" role="alert">
  22 + <strong>Внимание:</strong> данным действием Вы подтверждаете свое участие в проекте.
  23 + </div>
  24 + <?php
  25 + }
  26 + ?>
  27 + <div>
  28 + <?php
  29 + $form = ActiveForm::begin();
  30 + echo $form->field($model, 'position')
  31 + ->textInput();
  32 + echo $form->field($model, 'time')
  33 + ->input('number');
  34 + ?>
  35 + </div>
  36 + <p>Добавить фотографию в личный альбом данного проекта:</p>
  37 + <?php
  38 + if($model->status == 1 && !empty($model->gallery)) {
  39 + echo $form->field($model->portfolioGallery, 'caption')->textInput();
  40 + echo Html::tag('div', ImageUploader::widget([
  41 + 'model' => $model->gallery,
  42 + 'field' => 'photo',
  43 + 'size' => [
  44 + [
  45 + 'width' => 152,
  46 + 'height' => 108,
  47 + ],
  48 + ],
  49 + 'multi' => true,
  50 + 'gallery' => $model->gallery->photo,
  51 + 'name' => 'Загрузить фото галереи',
  52 + ]), [ 'class' => 'admin-gallery-photos-load-wr style' ]);
  53 + } else {
  54 + echo Html::tag('p', 'Для добавления фотографий Вы должны подтвердить свое участие');
  55 + }
  56 + ?>
  57 + <p class="text-right">
  58 + <?php
  59 + echo Html::a('Вернуться', [ 'accounts/participant' ]);
  60 + echo Html::submitButton('Обновить');
  61 + $form->end();
  62 + ?>
  63 + </p>
  64 +</div>
0 65 \ No newline at end of file
... ...
frontend/views/accounts/participant.php 0 → 100644
  1 +<?php
  2 + /**
  3 + * @var View $this
  4 + * @var PortfolioUserSearch $searchModel
  5 + * @var ActiveDataProvider $dataProvider
  6 + */
  7 + use common\models\PortfolioUser;
  8 + use common\models\PortfolioUserSearch;
  9 + use yii\data\ActiveDataProvider;
  10 + use yii\grid\ActionColumn;
  11 + use yii\grid\DataColumn;
  12 + use yii\grid\GridView;
  13 + use yii\helpers\Html;
  14 + use yii\web\View;
  15 +
  16 + $this->title = 'Портфолио участник';
  17 + $this->params[ 'breadcrumbs' ][] = $this->title;
  18 +?>
  19 +<div class="login-left-column-title"><?= $this->title ?></div>
  20 +<div class="admin-table-portfolio">
  21 + <?= GridView::widget([
  22 + 'options' => [ 'class' => 'style admin-all-pages-wr' ],
  23 + 'dataProvider' => $dataProvider,
  24 + 'filterModel' => $searchModel,
  25 + 'columns' => [
  26 + [
  27 + 'attribute' => 'project',
  28 + 'content' => function($model, $key, $index, $column) {
  29 + /**
  30 + * @var PortfolioUser $model
  31 + */
  32 + $type = $model->portfolio->user->type;
  33 + $type_string = ( $type == 2 ) ? 'company' : 'performer';
  34 + return Html::a($model->portfolio->name, [
  35 + $type_string . '/portfolio-view',
  36 + $type_string . '_id' => $model->portfolio->user_id,
  37 + 'portfolio_id' => $model->portfolio->portfolio_id,
  38 + ], [
  39 + 'target' => '_blank',
  40 + ]);
  41 + },
  42 + ],
  43 + [
  44 + 'attribute' => 'position',
  45 + 'value' => function($model, $key, $index, $column) {
  46 + /**
  47 + * @var PortfolioUser $model
  48 + * @var DataColumn $column
  49 + * @var int $key
  50 + * @var int $index
  51 + */
  52 + if(empty( $model[ $column->attribute ] )) {
  53 + return NULL;
  54 + } else {
  55 + return $model[ $column->attribute ];
  56 + }
  57 + },
  58 + ],
  59 + [
  60 + 'attribute' => 'time',
  61 + 'filter' => Html::tag('div', Html::activeInput('text', $searchModel, 'time_from', [ 'class' => 'form-control' ]), [ 'style' => 'width:70px;display:inline-block' ]) . Html::tag('div', Html::tag('i', '', [
  62 + 'class' => 'glyphicon glyphicon-resize-horizontal',
  63 + 'style' => 'left:3px',
  64 + ]), [ 'style' => 'width:20px;display:inline-block;' ]) . Html::tag('div', Html::activeInput('text', $searchModel, 'time_to', [ 'class' => 'form-control' ]), [ 'style' => 'width:70px;display:inline-block' ]) . ( ( $searchModel->hasErrors('time_from') ) ? Html::error($searchModel, 'time_from', [ 'class' => 'help-block' ]) : '' ) . ( ( $searchModel->hasErrors('time_to') ) ? Html::error($searchModel, 'time_to', [ 'class' => 'help-block' ]) : '' ),
  65 + 'filterOptions' => [
  66 + 'class' => ( $searchModel->hasErrors('time_from') || $searchModel->hasErrors('time_to') ) ? 'has-error' : '',
  67 + 'style' => 'width: 200px',
  68 + ],
  69 + ],
  70 + [
  71 + 'attribute' => 'status',
  72 + 'filter' => [
  73 + 1 => 'Подтверждено',
  74 + 2 => 'Ожидание',
  75 + ],
  76 + 'value' => function($model) {
  77 + if($model->status == 1) {
  78 + return 'Подтвержден';
  79 + } elseif($model->status == 2) {
  80 + return 'В ожидании';
  81 + } else {
  82 + return 'Неизвестный';
  83 + }
  84 + },
  85 + ],
  86 + [
  87 + 'class' => ActionColumn::className(),
  88 + 'buttons' => [
  89 + 'confirm' => function($url, $model, $key) {
  90 + return ( $model->status == 2 ) ? Html::a(Html::img('/images/tick.png', [
  91 + 'width' => '15px',
  92 + 'height' => '15px',
  93 + ]), [
  94 + 'accounts/participant-confirm',
  95 + 'id' => $model->portfolio_user_id,
  96 + ], [
  97 + 'title' => 'Подтвердить',
  98 + 'aria-label' => 'Подтвердить',
  99 + 'data-confirm' => 'Вы уверены, что хотите подтвердить участие в данном проекте?',
  100 + 'data-method' => 'post',
  101 + 'data-pjax' => 0,
  102 + ]) : '';
  103 + },
  104 + 'edit' => function($url, $model, $key) {
  105 + return Html::a(Html::img('/images/ico_pencil.png'), [
  106 + 'accounts/participant-edit',
  107 + 'id' => $model->portfolio_user_id,
  108 + ], [
  109 + 'title' => 'Редактировать',
  110 + 'aria-label' => 'Редактировать',
  111 + 'data-pjax' => 0,
  112 + ]);
  113 + },
  114 + 'deny' => function($url, $model, $key) {
  115 + return Html::a(Html::img('/images/delete-ico.png'), [
  116 + 'accounts/participant-delete',
  117 + 'id' => $model->portfolio_user_id,
  118 + ], [
  119 + 'title' => 'Удалить',
  120 + 'aria-label' => 'Удалить',
  121 + 'data-confirm' => 'Вы уверены, что хотите отказаться от участия в данном проекте?',
  122 + 'data-method' => 'post',
  123 + 'data-pjax' => 0,
  124 + ]);
  125 + },
  126 + ],
  127 + 'template' => '{confirm}{edit}{deny}',
  128 + ],
  129 + ],
  130 + ]); ?>
  131 +</div>
... ...
frontend/views/ajax/project_user.php
... ... @@ -10,7 +10,7 @@
10 10 use yii\web\View;
11 11  
12 12 ?>
13   -<div class="form-inline project_user_wrapper" data-id="<?=$user->id?>">
  13 +<div class="form-inline project_user_wrapper" data-id="<?=$user->id?>" <?php if($model->status == 1) { echo 'data-portfolio="'.$model->portfolio_id.'"'; } ?>>
14 14 <div class="error-summary">
15 15 <?=Html::errorSummary($model)?>
16 16 </div>
... ... @@ -18,6 +18,12 @@
18 18 <label class="sr-only">User name</label>
19 19 <p class="form-control-static"><?=Html::a($user->name, ['performer/common', 'performer_id' => $user->id], ['target' => '_blank'])?></p>
20 20 <?=Html::activeHiddenInput($model, "[{$user->id}]user_id", ['value' => $user->id])?>
  21 + <?php
  22 + if($model->status == 1) {
  23 + echo Html::activeHiddenInput($model, "[{$user->id}]status", ['value' => $model->status]);
  24 + }
  25 + ?>
  26 + <?=Html::activeHiddenInput($model, "[{$user->id}]user_id", ['value' => $user->id])?>
21 27 </div>
22 28 <div class="form-group" style="display: inline-block">
23 29 <?=Html::activeLabel($model, 'position', ['label' => Yii::t('app', 'Должность: ')])?>
... ...
frontend/views/layouts/admin.php
... ... @@ -17,7 +17,6 @@ $this-&gt;beginContent(&#39;@app/views/layouts/main.php&#39;);
17 17 <div class="login-right-column">
18 18 <div class="admin-my-page">Моя страница</div>
19 19 <?php
20   -
21 20 $item = [
22 21 [
23 22 'label' => 'Учетные данные',
... ... @@ -55,7 +54,12 @@ $this-&gt;beginContent(&#39;@app/views/layouts/main.php&#39;);
55 54 'url' => ['accounts/portfolio'],
56 55 'active' => preg_match('/^portfolio.*$/', $this->context->action->id)?true:false,
57 56 ],
58   -
  57 + [
  58 + 'label' => "Портфолио участник <span class='badge'>{$this->params['portfolio_user_count']}</span>",
  59 + 'encode' => false,
  60 + 'url' => ['accounts/participant'],
  61 + 'active' => preg_match('/^participant.*$/', $this->context->action->id)?true:false,
  62 + ],
59 63 [
60 64 'label' => 'Блог',
61 65 'url' => ['accounts/blog'],
... ...
frontend/web/js/script.js
... ... @@ -1159,10 +1159,7 @@ $(document).ready(
1159 1159 );
1160 1160 $.fancybox.open(
1161 1161 {href : '/ajax/project-user'}, {
1162   - type : 'ajax',
1163   - margin: [70, 20, 30, 20],
1164   - maxWidth : 800,
1165   - ajax : {dataType : 'html', data : {ids : JSON.stringify(ids)}},
  1162 + type : 'ajax', margin : [70, 20, 30, 20], maxWidth : 800, ajax : {dataType : 'html', data : {ids : JSON.stringify(ids)}},
1166 1163 tpl : {wrap : '<div class="fancybox-wrap" tabIndex="-1" data-model="common\\models\\PortfolioUser" data-component="' + component + '"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>'}
1167 1164 }
1168 1165 );
... ... @@ -1197,11 +1194,41 @@ $(document).ready(
1197 1194 }
1198 1195 );
1199 1196 $(document).on(
1200   - 'click', '.project_user_remove', function()
  1197 + 'click', '.add_project_user_list .project_user_remove', function()
1201 1198 {
1202 1199 $(this).parents('.project_user_wrapper').remove();
1203 1200 }
1204 1201 );
  1202 + $(document).on(
  1203 + 'click', '.added_project_user_list .project_user_remove', function()
  1204 + {
  1205 + var wrapper = $(this).parents('.project_user_wrapper');
  1206 + var user_id = $(wrapper).data('id');
  1207 + var portfolio_id = $(wrapper).data('portfolio');
  1208 + $.post(
  1209 + '/ajax/portfolio-user-remove', {user_id : user_id, portfolio_id : portfolio_id}, function(data)
  1210 + {
  1211 + if(data.error) {
  1212 + alert(data.error);
  1213 + } else {
  1214 + var element = $('.added_project_user_list .project_user_wrapper[data-id='+data.result.user_id+'][data-portfolio='+data.result.portfolio_id+']');
  1215 + var widget_wrapper = $(element).parents('.add_project_user_wrapper');
  1216 + $(element).remove();
  1217 + var widget_id = $(widget_wrapper).attr('id');
  1218 + checkAddedHeader(widget_id);
  1219 + }
  1220 + }
  1221 + );
  1222 + }
  1223 + );
1205 1224  
  1225 + function checkAddedHeader(id) {
  1226 + var count = $('#'+id).find('.added_project_user_list').find('.project_user_wrapper').length;
  1227 + if(count <= 0) {
  1228 + $('#'+id).find('.added_project_user_header').hide();
  1229 + } else {
  1230 + $('#'+id).find('.added_project_user_header').show();
  1231 + }
  1232 + }
1206 1233 }
1207 1234 );
1208 1235 \ No newline at end of file
... ...
tests/acceptance/FirstTestCept.php
... ... @@ -18,5 +18,5 @@ $I-&gt;click(&#39;Добавить&#39;);
18 18 $I->wait(1);
19 19 $I->attachFile('input[type="file"]', 'ViewIllustrator_2001.jpg');
20 20 $I->fillField('#portfolio-name','');
21   -$I->click('Добавить');
22   -$I->see('Необходимо заполнить «Название».','div');
  21 +$I->click('Добавить', '.input-blocks-wrapper');
  22 +$I->see('Необходимо заполнить «name».','div');
... ...