Commit 2f324895bc56cd4fca30b2028c8f6e53d80c0e67
1 parent
d6077779
test
Showing
21 changed files
with
1228 additions
and
97 deletions
Show diff stats
.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
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 | } | ... | ... |
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 | -} | ... | ... |
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
common/modules/comment/rbac/ArtboxCommentUpdateOwnRule.php
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
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/μ)', | |
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> (λ<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> | ... | ... |
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 | ... | ... |
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->beginContent('@app/views/layouts/main.php'); |
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->beginContent('@app/views/layouts/main.php'); |
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->click('Добавить'); |
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'); | ... | ... |