Commit 3735dff7ee125b66a7cacbcc27a8343e1125c292

Authored by Yarik
1 parent e75f77a6

test

common/config/bootstrap.php
1 <?php 1 <?php
2 -Yii::setAlias('common', dirname(__DIR__));  
3 -Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend');  
4 -Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend');  
5 -Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');  
6 -Yii::setAlias('saveImageDir', '@frontend/web/images/upload/');  
7 -Yii::setAlias('storage', dirname(dirname(__DIR__)) . '/storage'); 2 + Yii::setAlias('common', dirname(__DIR__));
  3 + Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend');
  4 + Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend');
  5 + Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');
  6 + Yii::setAlias('saveImageDir', '@frontend/web/images/upload/');
  7 + Yii::setAlias('storage', dirname(dirname(__DIR__)) . '/storage');
  8 + Yii::setAlias('documentRoot', dirname(dirname(__DIR__)));
common/config/main.php
1 <?php 1 <?php
2 2
  3 + use common\modules\fileloader\controllers\FileloaderController;
  4 +
3 return [ 5 return [
4 'timeZone' => 'Europe/Kiev', 6 'timeZone' => 'Europe/Kiev',
5 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor', 7 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
@@ -28,6 +30,9 @@ @@ -28,6 +30,9 @@
28 'artbox-comment' => [ 30 'artbox-comment' => [
29 'class' => \common\modules\comment\Controller::className(), 31 'class' => \common\modules\comment\Controller::className(),
30 ], 32 ],
  33 + 'fileloader' => [
  34 + 'class' => FileloaderController::className(),
  35 + ],
31 ], 36 ],
32 37
33 'modules' => [ 38 'modules' => [
common/models/Project.php
@@ -3,9 +3,12 @@ @@ -3,9 +3,12 @@
3 namespace common\models; 3 namespace common\models;
4 4
5 use common\modules\comment\models\CommentProject; 5 use common\modules\comment\models\CommentProject;
  6 + use common\modules\fileloader\behaviors\FileloaderBehavior;
  7 + use common\modules\fileloader\models\Fileloader;
6 use Yii; 8 use Yii;
7 use yii\behaviors\BlameableBehavior; 9 use yii\behaviors\BlameableBehavior;
8 use yii\behaviors\TimestampBehavior; 10 use yii\behaviors\TimestampBehavior;
  11 + use yii\db\ActiveQuery;
9 use yii\db\Expression; 12 use yii\db\Expression;
10 13
11 /** 14 /**
@@ -33,6 +36,8 @@ @@ -33,6 +36,8 @@
33 * @property Currency $budgetCurrency 36 * @property Currency $budgetCurrency
34 * @property Project $parent 37 * @property Project $parent
35 * @property int $hidden 38 * @property int $hidden
  39 + * @property int[] $fileloader
  40 + * @method File[] getFileloaderFiles()
36 */ 41 */
37 class Project extends \yii\db\ActiveRecord 42 class Project extends \yii\db\ActiveRecord
38 { 43 {
@@ -64,12 +69,15 @@ @@ -64,12 +69,15 @@
64 'updatedAtAttribute' => false, 69 'updatedAtAttribute' => false,
65 'value' => new Expression('NOW()'), 70 'value' => new Expression('NOW()'),
66 ], 71 ],
67 - 'slug' => [ 72 + 'slug' => [
68 'class' => 'common\behaviors\Slug', 73 'class' => 'common\behaviors\Slug',
69 'in_attribute' => 'name', 74 'in_attribute' => 'name',
70 'out_attribute' => 'link', 75 'out_attribute' => 'link',
71 'translit' => true, 76 'translit' => true,
72 ], 77 ],
  78 + 'fileloader' => [
  79 + 'class' => FileloaderBehavior::className(),
  80 + ],
73 ]; 81 ];
74 } 82 }
75 83
@@ -154,21 +162,21 @@ @@ -154,21 +162,21 @@
154 'boolean', 162 'boolean',
155 ], 163 ],
156 [ 164 [
157 - ['hidden'], 165 + [ 'hidden' ],
158 'default', 166 'default',
159 'value' => 0, 167 'value' => 0,
160 ], 168 ],
161 [ 169 [
162 - ['date_end'], 170 + [ 'date_end' ],
163 'filter', 171 'filter',
164 'filter' => function($value) { 172 'filter' => function($value) {
165 $unix = strtotime($value); 173 $unix = strtotime($value);
166 if($unix <= time()) { 174 if($unix <= time()) {
167 - $unix = time() + (3600 * 24 * 7); 175 + $unix = time() + ( 3600 * 24 * 7 );
168 } 176 }
169 return date('Y-m-d', $unix); 177 return date('Y-m-d', $unix);
170 - }  
171 - ] 178 + },
  179 + ],
172 ]; 180 ];
173 } 181 }
174 182
@@ -332,4 +340,5 @@ @@ -332,4 +340,5 @@
332 return $this->hasMany(CommentProject::className(), [ 'model_id' => 'project_id' ]) 340 return $this->hasMany(CommentProject::className(), [ 'model_id' => 'project_id' ])
333 ->andWhere([ 'model' => $this->className() ]); 341 ->andWhere([ 'model' => $this->className() ]);
334 } 342 }
  343 +
335 } 344 }
common/modules/fileloader/Module.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\fileloader;
  3 +
  4 + /**
  5 + * Class Module
  6 + * @package common\modules\comment
  7 + */
  8 + class Module extends \yii\base\Module
  9 + {
  10 +
  11 + /**
  12 + * @var string Module name
  13 + */
  14 + public static $moduleName = 'artbox_fileloader';
  15 +
  16 + /**
  17 + * @inheritdoc
  18 + */
  19 + public function init()
  20 + {
  21 + parent::init();
  22 + }
  23 + }
0 \ No newline at end of file 24 \ No newline at end of file
common/modules/fileloader/assets/FileloaderAsset.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\fileloader\assets;
  3 +
  4 + use yii\web\View;
  5 +
  6 + class FileloaderAsset extends \yii\web\AssetBundle
  7 + {
  8 +
  9 + public $sourcePath = '@common/modules/fileloader/resources';
  10 +
  11 + public $css = [
  12 + 'fileloader.css',
  13 + ];
  14 +
  15 + public $js = [
  16 + 'jquery.ui.widget.js',
  17 + 'jquery.fileupload.js',
  18 + 'jquery.iframe-transport.js',
  19 + 'handler.js',
  20 + ];
  21 +
  22 + public $depends = [
  23 + '\yii\web\YiiAsset',
  24 + '\yii\web\JqueryAsset',
  25 + '\yii\bootstrap\BootstrapAsset',
  26 + ];
  27 +
  28 + public $jsOptions = [
  29 + 'position' => View::POS_HEAD,
  30 + ];
  31 +
  32 + }
0 \ No newline at end of file 33 \ No newline at end of file
common/modules/fileloader/behaviors/FileloaderBehavior.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\fileloader\behaviors;
  3 +
  4 + use yii\base\Behavior;
  5 + use yii\base\Event;
  6 + use yii\db\ActiveQuery;
  7 + use yii\db\ActiveRecord;
  8 + use yii\validators\Validator;
  9 +
  10 + /**
  11 + * Class FileloaderBehavior
  12 + * @package common\modules\fileloader\behaviors
  13 + */
  14 + class FileloaderBehavior extends Behavior
  15 + {
  16 +
  17 + /**
  18 + * @var string $fileclass Classname that hande files
  19 + */
  20 + public $fileclass = 'common\models\File';
  21 +
  22 + /**
  23 + * @var string $relationtable Table name that keeps relation between model and file
  24 + */
  25 + public $relationclass = 'common\modules\fileloader\models\FileRelation';
  26 +
  27 + /**
  28 + * @var int[] Files ids to insert
  29 + */
  30 + public $fileloader = [ ];
  31 +
  32 + /**
  33 + * @inheritdoc
  34 + */
  35 + public function events()
  36 + {
  37 + return [
  38 + ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
  39 + ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
  40 + ActiveRecord::EVENT_INIT => 'attachValidator',
  41 + ];
  42 + }
  43 +
  44 + public function attachValidator($event)
  45 + {
  46 + $validator = Validator::createValidator('safe', $this->owner, 'fileloader');
  47 + $this->owner->validators->append($validator);
  48 + }
  49 +
  50 + /**
  51 + * After saving model delete all relative files and insert new file connections from
  52 + * fileloader variable
  53 + *
  54 + * @param Event $event
  55 + */
  56 + public function afterSave($event)
  57 + {
  58 + /**
  59 + * @var ActiveRecord $owner
  60 + * @var string $relation
  61 + */
  62 + $owner = $this->owner;
  63 + $relation = $this->relationclass;
  64 + call_user_func([
  65 + $relation,
  66 + 'deleteAll',
  67 + ], [
  68 + 'model' => $owner->className(),
  69 + 'model_id' => $owner->primaryKey,
  70 + ]);
  71 + if(!empty( $owner->fileloader )) {
  72 + foreach($owner->fileloader as $file) {
  73 + /**
  74 + * @var ActiveRecord $model
  75 + */
  76 + $model = new $relation([
  77 + 'file_id' => $file,
  78 + 'model' => $owner->className(),
  79 + 'model_id' => $owner->primaryKey,
  80 + 'user_id' => \Yii::$app->user->getId(),
  81 + 'status' => 1,
  82 + ]);
  83 + if($model->validate()) {
  84 + $model->save(false);
  85 + }
  86 + unset( $model );
  87 + }
  88 + }
  89 + }
  90 +
  91 + /**
  92 + * Bind owner class tp specified $fileclass via $relationclass table.
  93 + * @return ActiveQuery
  94 + */
  95 + public function getFileloaderFiles()
  96 + {
  97 + /**
  98 + * @var ActiveRecord $owner
  99 + */
  100 + $owner = $this->owner;
  101 + $relationtable = call_user_func([
  102 + $this->relationclass,
  103 + 'tableName',
  104 + ]);
  105 + return $owner->hasMany($this->fileclass, [ 'file_id' => 'file_id' ])
  106 + ->viaTable($relationtable, [ 'model_id' => $owner->primaryKey()[ 0 ] ], function($query) use ($owner) {
  107 + /**
  108 + * @var ActiveQuery $query
  109 + */
  110 + $query->andWhere([
  111 + 'model' => $owner->className(),
  112 + 'status' => 1,
  113 + ]);
  114 + });
  115 + }
  116 + }
0 \ No newline at end of file 117 \ No newline at end of file
common/modules/fileloader/controllers/FileloaderController.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\fileloader\controllers;
  3 +
  4 + use common\modules\fileloader\models\Fileloader;
  5 + use yii\filters\AccessControl;
  6 + use yii\helpers\Html;
  7 + use yii\web\UploadedFile;
  8 +
  9 + class FileloaderController extends \yii\web\Controller
  10 + {
  11 +
  12 + /**
  13 + * @inheritdoc
  14 + */
  15 + public function behaviors()
  16 + {
  17 + return [
  18 + 'access' => [
  19 + 'class' => AccessControl::className(),
  20 + 'rules' => [
  21 + [
  22 + 'allow' => true,
  23 + 'roles' => [ '@' ],
  24 + ],
  25 + ],
  26 + ],
  27 + 'verbs' => [
  28 + 'class' => \yii\filters\VerbFilter::className(),
  29 + 'actions' => [
  30 + '*' => [ 'post' ],
  31 + ],
  32 + ],
  33 + ];
  34 + }
  35 +
  36 + /**
  37 + * Handle ajax file uploading
  38 + *
  39 + * @return array
  40 + */
  41 + public function actionUpload()
  42 + {
  43 + $request = \Yii::$app->request;
  44 + $response = \Yii::$app->response;
  45 + $response->format = $response::FORMAT_JSON;
  46 + $model = new Fileloader();
  47 + $model->files = UploadedFile::getInstance($model, 'files');
  48 + if(!empty( $model->files )) {
  49 + $file_id = $model->saveFile($model->files);
  50 + if(!empty( $file_id )) {
  51 + $child_model = $request->post('model', $model->className());
  52 + $child_model = new $child_model([ 'file' => $file_id ]);
  53 + $input = Html::activeHiddenInput($child_model, 'fileloader[]', [
  54 + 'value' => $file_id,
  55 + 'class' => 'fileloader-item-input',
  56 + ]);
  57 + return [
  58 + 'result' => [
  59 + 'file_id' => $file_id,
  60 + 'file_name' => $model->name,
  61 + 'file_href' => $model->dir,
  62 + 'input' => $input,
  63 + 'id' => $request->post('id'),
  64 + ],
  65 + ];
  66 + } else {
  67 + return [ 'error' => 'Ошибка сохранения файла' ];
  68 + }
  69 + }
  70 + return [ 'error' => 'Ошибка загрузки' ];
  71 + }
  72 +
  73 + /**
  74 + * Handle ajax file deleting
  75 + *
  76 + * @return array
  77 + */
  78 + public function actionDelete()
  79 + {
  80 + /**
  81 + * @var Fileloader $model
  82 + */
  83 + $request = \Yii::$app->request;
  84 + $response = \Yii::$app->response;
  85 + $response->format = $response::FORMAT_JSON;
  86 + if(empty( $request->post('id') )) {
  87 + return [ 'error' => 'Не указан id файла' ];
  88 + }
  89 + $model = Fileloader::find()
  90 + ->where([
  91 + 'file_id' => $request->post('id'),
  92 + 'user_id' => \Yii::$app->user->getId(),
  93 + ])
  94 + ->one();
  95 + if(empty( $model )) {
  96 + return [ 'error' => 'Файл не найден' ];
  97 + }
  98 + if($model->delete()) {
  99 + return [ 'result' => [ 'message' => 'Файл успешно удален' ] ];
  100 + } else {
  101 + return [ 'error' => 'Ошибка удаления файла' ];
  102 + }
  103 + }
  104 +
  105 + }
0 \ No newline at end of file 106 \ No newline at end of file
common/modules/fileloader/models/FileRelation.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace common\modules\fileloader\models;
  4 +
  5 +use common\models\File;
  6 +use common\models\User;
  7 +use Yii;
  8 +
  9 +/**
  10 + * This is the model class for table "file_relation".
  11 + *
  12 + * @property integer $file_relation_id
  13 + * @property integer $file_id
  14 + * @property string $model
  15 + * @property integer $model_id
  16 + * @property integer $user_id
  17 + * @property string $date_add
  18 + * @property integer $status
  19 + *
  20 + * @property File $file
  21 + * @property User $user
  22 + */
  23 +class FileRelation extends \yii\db\ActiveRecord
  24 +{
  25 + /**
  26 + * @inheritdoc
  27 + */
  28 + public static function tableName()
  29 + {
  30 + return 'file_relation';
  31 + }
  32 +
  33 + /**
  34 + * @inheritdoc
  35 + */
  36 + public function rules()
  37 + {
  38 + return [
  39 + [['file_id', 'model', 'model_id'], 'required'],
  40 + [['file_id', 'model_id', 'user_id', 'status'], 'integer'],
  41 + [['date_add'], 'safe'],
  42 + [['model'], 'string', 'max' => 255],
  43 + [['file_id'], 'exist', 'skipOnError' => true, 'targetClass' => File::className(), 'targetAttribute' => ['file_id' => 'file_id']],
  44 + [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
  45 + ];
  46 + }
  47 +
  48 + /**
  49 + * @inheritdoc
  50 + */
  51 + public function attributeLabels()
  52 + {
  53 + return [
  54 + 'file_relation_id' => Yii::t('app', 'File Relation ID'),
  55 + 'file_id' => Yii::t('app', 'File ID'),
  56 + 'model' => Yii::t('app', 'Model'),
  57 + 'model_id' => Yii::t('app', 'Model ID'),
  58 + 'user_id' => Yii::t('app', 'User ID'),
  59 + 'date_add' => Yii::t('app', 'Date Add'),
  60 + 'status' => Yii::t('app', 'Status'),
  61 + ];
  62 + }
  63 +
  64 + /**
  65 + * @return \yii\db\ActiveQuery
  66 + */
  67 + public function getFile()
  68 + {
  69 + return $this->hasOne(File::className(), ['file_id' => 'file_id']);
  70 + }
  71 +
  72 + /**
  73 + * @return \yii\db\ActiveQuery
  74 + */
  75 + public function getUser()
  76 + {
  77 + return $this->hasOne(User::className(), ['id' => 'user_id']);
  78 + }
  79 +}
common/modules/fileloader/models/Fileloader.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace common\modules\fileloader\models;
  4 +
  5 +use common\models\Tools;
  6 +use Yii;
  7 +use yii\behaviors\BlameableBehavior;
  8 +use yii\web\UploadedFile;
  9 +
  10 +/**
  11 + * This is the model class for table "file".
  12 + *
  13 + * @property integer $file_id
  14 + * @property integer $status
  15 + * @property string $name
  16 + * @property string $dir
  17 + */
  18 +class Fileloader extends \yii\db\ActiveRecord
  19 +{
  20 + public $files;
  21 + /**
  22 + * @inheritdoc
  23 + */
  24 + public static function tableName()
  25 + {
  26 + return 'file';
  27 + }
  28 +
  29 + /**
  30 + * @inheritdoc
  31 + */
  32 + public function behaviors()
  33 + {
  34 + return [
  35 + [
  36 + 'class' => BlameableBehavior::className(),
  37 + 'createdByAttribute' => 'user_id',
  38 + 'updatedByAttribute' => false,
  39 + ],
  40 + ];
  41 + }
  42 +
  43 + /**
  44 + * @inheritdoc
  45 + */
  46 + public function rules()
  47 + {
  48 + return [
  49 + [['status'], 'integer'],
  50 + [['name'], 'string', 'max' => 50],
  51 + [['dir'], 'string', 'max' => 255],
  52 + ];
  53 + }
  54 +
  55 + /**
  56 + * @inheritdoc
  57 + */
  58 + public function attributeLabels()
  59 + {
  60 + return [
  61 + 'file_id' => 'File ID',
  62 + 'status' => 'Status',
  63 + 'name' => 'Name',
  64 + 'dir' => 'Dir',
  65 + ];
  66 + }
  67 +
  68 + /**
  69 + * @param UploadedFile $file
  70 + * @return int file id in model File
  71 + */
  72 + public function saveFile(UploadedFile $file){
  73 + $imgDir = Yii::getAlias('@storage/'.'user_'.\Yii::$app->user->id.'/files/');
  74 + $uploadName = preg_replace('/\s/', '_', $file->baseName).'_'. time().'.'.$file->extension;
  75 + $uploadName = Tools::translit($uploadName, 'letter');
  76 + if(!is_dir($imgDir)) {
  77 + mkdir($imgDir, 0755, true);
  78 + }
  79 + if($file->saveAs($imgDir.$uploadName)){
  80 + $this->dir = '/storage/user_'.\Yii::$app->user->id.'/files/'.$uploadName;
  81 + $this->name = preg_replace('/\s/', '_', $file->baseName).'.'.$file->extension;
  82 + $this->save();
  83 + return $this->file_id;
  84 + }
  85 + }
  86 +
  87 + /**
  88 + * Extends ActiveRecord::delete() method, also deletes file from file system
  89 + *
  90 + * @see ActiveRecord::delete()
  91 + * @return false|int
  92 + * @throws \Exception
  93 + */
  94 + public function delete()
  95 + {
  96 + if(!empty($this->dir)) {
  97 + if(file_exists(Yii::getAlias('@documentRoot').$this->dir)) {
  98 + unlink(Yii::getAlias('@documentRoot').$this->dir);
  99 + }
  100 + }
  101 + return parent::delete();
  102 + }
  103 +}
common/modules/fileloader/resources/fileloader.css 0 → 100644
  1 +.fileloader-item-name {
  2 + display: inline-block;
  3 +}
  4 +.fileloader-item-name a {
  5 + text-decoration: none;
  6 + border-bottom: dotted 1px;
  7 +}
  8 +.fileloader-item-name a:hover, .fileloader-item-name a:focus {
  9 + text-decoration: none;
  10 +}
  11 +.fileloader-item-remove {
  12 + padding-left: 10px;
  13 + cursor: pointer;
  14 +}
  15 +.fileloader-file {
  16 + position: relative;
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
common/modules/fileloader/resources/handler.js 0 → 100644
  1 +$(function() {
  2 + if(fileloader !== undefined) {
  3 + $.each(fileloader, function(index, value) {
  4 + var id = value.id;
  5 + var model = value.model;
  6 + var formData = {};
  7 + if(typeof model == 'string' && model !== '') {
  8 + formData.model = model;
  9 + }
  10 + if(typeof id == 'string' && id !== '') {
  11 + formData.id = id;
  12 + $('#'+id).fileupload({
  13 + dataType: 'json',
  14 + url: '/fileloader/upload',
  15 + formData: formData,
  16 + done: function(e, data) {
  17 + if(!data.result.error) {
  18 + var id = data.result.result.id;
  19 + var input = $('#'+id);
  20 + var wrapper = $(input).parents('.fileloader-wrapper').first();
  21 + var html = '<div class="fileloader-item-wrapper" data-id="'+data.result.result.file_id+'">'+
  22 + data.result.result.input + '<p class="fileloader-item-name">'+
  23 + '<a href="'+data.result.result.file_href+'" target="_blank">'+data.result.result.file_name+'</a></p>'+'<span class="fileloader-item-remove glyphicon glyphicon-remove"></span>'+
  24 + '</div>';
  25 + $(html).appendTo($(wrapper).find('.fileloader-list'));
  26 + }
  27 + }
  28 + });
  29 + }
  30 + });
  31 + }
  32 +
  33 + $(document).on('click', '.fileloader-item-remove', function(e) {
  34 + var wrapper = $(this).parents('.fileloader-item-wrapper').first();
  35 + var id = $(wrapper).data('id');
  36 + $.post(
  37 + '/fileloader/delete',
  38 + {
  39 + id: id
  40 + },
  41 + function(data) {}
  42 + );
  43 + $(wrapper).remove();
  44 + });
  45 +});
common/modules/fileloader/widgets/FileloaderWidget.php 0 → 100644
  1 +<?php
  2 + namespace common\modules\fileloader\widgets;
  3 +
  4 + use common\modules\fileloader\assets\FileloaderAsset;
  5 + use common\modules\fileloader\behaviors\FileloaderBehavior;
  6 + use common\modules\fileloader\models\Fileloader;
  7 + use yii\db\ActiveRecord;
  8 + use yii\helpers\ArrayHelper;
  9 + use \yii\helpers\Html;
  10 + use yii\web\View;
  11 +
  12 + /**
  13 + * Class FileloaderWidget
  14 + * @package common\modules\fileloader\widgets
  15 + */
  16 + class FileloaderWidget extends \yii\base\Widget
  17 + {
  18 +
  19 + /**
  20 + * @var array $labelOptions Label options.
  21 + * <i>Special: 1. You cannot modify 'for' attribute</i>
  22 + */
  23 + public $labelOptions = [ ];
  24 +
  25 + /**
  26 + * @var array $inputOptions Input options.
  27 + * <i>
  28 + * Special:
  29 + * 1. You cannot modify 'id' attribute.
  30 + * 2. Class will be appended by base input class
  31 + * <i>
  32 + */
  33 + public $inputOptions = [ ];
  34 +
  35 + /**
  36 + * @var array $hintOptions Hint options.
  37 + * <i>
  38 + * 1. tag will be used to generate container tag. Default to 'div'
  39 + * 2. value will be used to generate content. If missing, component won't be rendered
  40 + * </i>
  41 + */
  42 + public $hintOptions = [ ];
  43 +
  44 + /**
  45 + * @var array $errorOptions Error options
  46 + * <i>
  47 + * 1. tag will be used to generate container tag. Default to 'div'
  48 + * 2. class will be appended by base error class
  49 + * </i>
  50 + */
  51 + public $errorOptions = [ ];
  52 +
  53 + /**
  54 + * @var array $listOptions Items list options
  55 + * <i>
  56 + * 1. tag will be used to generate container tag. Default to 'div'
  57 + * 2. class will be appended by base list class
  58 + * </i>
  59 + */
  60 + public $listOptions = [ ];
  61 +
  62 + /**
  63 + * @var array $options Container options
  64 + * <i>
  65 + * 1. tag will be used to generate container tag. Default to 'div'
  66 + * 2. class will be appended by base wrapper class
  67 + * </i>
  68 + */
  69 + public $options = [ ];
  70 +
  71 + /**
  72 + * @var ActiveRecord $model Model where to insert files
  73 + */
  74 + public $model;
  75 +
  76 + /**
  77 + * @var string $attribute Model attribute
  78 + */
  79 + public $attribute;
  80 +
  81 + /**
  82 + * @var View $view Current view object
  83 + */
  84 + public $view;
  85 +
  86 + /**
  87 + * @var string $template Widget template. Recognised components: {label}, {input}, {hint},
  88 + * {error}, {list}
  89 + */
  90 + public $template = '{label}{input}{hint}{error}{list}';
  91 +
  92 + /**
  93 + * @var bool $displayLabel Whether to display label component or not
  94 + */
  95 + public $displayLabel = true;
  96 +
  97 + /**
  98 + * @var bool $displayInput Whether to display input component or not
  99 + */
  100 + public $displayInput = true;
  101 +
  102 + /**
  103 + * @var bool $displayHint Whether to display hint component or not
  104 + */
  105 + public $displayHint = true;
  106 +
  107 + /**
  108 + * @var bool $displayError Whether to display error component or not
  109 + */
  110 + public $displayError = true;
  111 +
  112 + /**
  113 + * @var bool $displayList Whether to display list component or not
  114 + */
  115 + public $displayList = true;
  116 +
  117 + protected $label = '';
  118 +
  119 + protected $input = '';
  120 +
  121 + protected $hint = '';
  122 +
  123 + protected $error = '';
  124 +
  125 + protected $list = '';
  126 +
  127 + /**
  128 + * @var string Unique widget ID
  129 + */
  130 + protected $inputID;
  131 +
  132 + /**
  133 + * @var Fileloader $fileloader Fileloader model
  134 + */
  135 + protected $fileloader;
  136 +
  137 + protected $output = '';
  138 +
  139 + /**
  140 + * @var string $baseClass Will be added to input component
  141 + */
  142 + protected $baseClass = ' fileloader-input';
  143 +
  144 + /**
  145 + * @var string $baseErrorClass Will be added to error container
  146 + */
  147 + protected $baseErrorClass = ' fileloader-error';
  148 +
  149 + /**
  150 + * @var string $baseListClass Will be added to list container
  151 + */
  152 + protected $baseListClass = ' fileloader-list';
  153 +
  154 + /**
  155 + * @var string $baseWrapperClass Will be added to Container
  156 + */
  157 + protected $baseWrapperClass = ' fileloader-wrapper';
  158 +
  159 + /**
  160 + * @inheritdoc
  161 + */
  162 + public function init()
  163 + {
  164 + parent::init();
  165 + FileloaderAsset::register($this->view);
  166 + }
  167 +
  168 + /**
  169 + * @inheritdoc
  170 + * @return string
  171 + */
  172 + public function run()
  173 + {
  174 + $this->fileloader = new Fileloader();
  175 + $this->inputID = 'fileloader-' . $this->getId();
  176 + $this->createParts();
  177 + $this->output = $this->renderLoader();
  178 + $this->renderJS();
  179 + return $this->output;
  180 + }
  181 +
  182 + /**
  183 + * Fills widget components with data
  184 + */
  185 + public function createParts()
  186 + {
  187 + if(!empty( $this->displayLabel ) && preg_match('/^.*\{label\}.*$/i', $this->template)) {
  188 + $this->labelOptions[ 'for' ] = $this->inputID;
  189 + $this->label = Html::activeLabel($this->fileloader, 'files', $this->labelOptions);
  190 + }
  191 + if(!empty( $this->displayInput ) && preg_match('/^.*\{input\}.*$/i', $this->template)) {
  192 + if(empty( $this->inputOptions[ 'class' ] )) {
  193 + $this->inputOptions[ 'class' ] = $this->baseClass;
  194 + } else {
  195 + $this->inputOptions[ 'class' ] .= $this->baseClass;
  196 + }
  197 + $this->inputOptions[ 'id' ] = $this->inputID;
  198 + $this->input = Html::activeFileInput($this->fileloader, 'files', $this->inputOptions);
  199 + }
  200 + if(!empty( $this->displayHint ) && preg_match('/^.*\{hint\}.*$/i', $this->template) && !empty( $this->hintOptions[ 'value' ] )) {
  201 + $this->hint = Html::tag(ArrayHelper::remove($this->hintOptions, 'tag', 'div'), ArrayHelper::remove($this->hintOptions, 'value'), $this->hintOptions);
  202 + }
  203 + if(!empty( $this->displayError ) && preg_match('/^.*\{error\}.*$/i', $this->template)) {
  204 + if(empty( $this->errorOptions[ 'class' ] )) {
  205 + $this->errorOptions[ 'class' ] = $this->baseErrorClass;
  206 + } else {
  207 + $this->errorOptions[ 'class' ] .= $this->baseErrorClass;
  208 + }
  209 + $this->error = Html::tag(ArrayHelper::remove($this->errorOptions, 'tag', 'div'), '', $this->errorOptions);
  210 + }
  211 + if(!empty( $this->displayList ) && preg_match('/^.*\{list\}.*$/i', $this->template)) {
  212 + if(empty( $this->listOptions[ 'class' ] )) {
  213 + $this->listOptions[ 'class' ] = $this->baseListClass;
  214 + } else {
  215 + $this->listOptions[ 'class' ] .= $this->baseListClass;
  216 + }
  217 + $list = '';
  218 + $items = $this->getItems();
  219 + if(!empty( $items )) {
  220 + foreach($items as $item) {
  221 + $list .= '<div class="fileloader-item-wrapper" data-id="' . $item->file_id . '">' . Html::activeHiddenInput($this->model, 'fileloader[]', [
  222 + 'value' => $item->file_id,
  223 + 'class' => 'fileloader-item-input',
  224 + ]) . Html::tag('p', Html::a($item->name, $item->dir, [ 'target' => '_blank' ]), [
  225 + 'class' => 'fileloader-item-name',
  226 + ]) . Html::tag('span', '', [
  227 + 'class' => 'fileloader-item-remove glyphicon glyphicon-remove',
  228 + ]) . '</div>';
  229 + }
  230 + }
  231 + $this->list = Html::tag(ArrayHelper::remove($this->listOptions, 'tag', 'div'), $list, $this->listOptions);
  232 + }
  233 + }
  234 +
  235 + /**
  236 + * Fills template with components
  237 + * @return string
  238 + */
  239 + public function renderLoader()
  240 + {
  241 + $template = $this->template;
  242 + $template = preg_replace('/{label}/', $this->label, $template);
  243 + $template = preg_replace('/{input}/', $this->input, $template);
  244 + $template = preg_replace('/{hint}/', $this->hint, $template);
  245 + $template = preg_replace('/{error}/', $this->error, $template);
  246 + $template = preg_replace('/{list}/', $this->list, $template);
  247 + if(empty( $this->options[ 'class' ] )) {
  248 + $this->options[ 'class' ] = $this->baseWrapperClass;
  249 + } else {
  250 + $this->options[ 'class' ] .= $this->baseWrapperClass;
  251 + }
  252 + return Html::tag(ArrayHelper::remove($this->options, 'tag', 'div'), $template, $this->options);
  253 + }
  254 +
  255 + /**
  256 + * Get already set items
  257 + * @return ActiveRecord[]
  258 + */
  259 + public function getItems()
  260 + {
  261 + /**
  262 + * @var ActiveRecord $model
  263 + */
  264 + $model = $this->model;
  265 + if($behavior = $model->getBehavior('fileloader')) {
  266 + if($behavior instanceof FileloaderBehavior) {
  267 + return $model->getFileloaderFiles()
  268 + ->all();
  269 + } else {
  270 + return [ ];
  271 + }
  272 + } else {
  273 + return [ ];
  274 + }
  275 + }
  276 +
  277 + /**
  278 + * Render JS for widget
  279 + */
  280 + public function renderJS()
  281 + {
  282 + /**
  283 + * @var View $view
  284 + */
  285 + $view = $this->view;
  286 + $vars = json_encode([
  287 + 'id' => $this->inputID,
  288 + 'model' => $this->model->className(),
  289 + ]);
  290 + $js = "if(fileloader === undefined) {
  291 + var fileloader = [];
  292 + fileloader[0] = " . $vars . ";
  293 + } else {
  294 + fileloader[fileloader.length] = " . $vars . ";
  295 + }
  296 + ";
  297 + $view->registerJs($js, $view::POS_BEGIN);
  298 + }
  299 +
  300 + }
0 \ No newline at end of file 301 \ No newline at end of file
console/migrations/m160325_153328_file_relation_table.php 0 → 100644
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m160325_153328_file_relation_table extends Migration
  6 + {
  7 +
  8 + public function up()
  9 + {
  10 + $this->createTable('{{%file_relation}}', [
  11 + 'file_relation_id' => $this->primaryKey(),
  12 + 'file_id' => $this->integer()
  13 + ->notNull(),
  14 + 'model' => $this->string()
  15 + ->notNull(),
  16 + 'model_id' => $this->integer()
  17 + ->notNull(),
  18 + 'user_id' => $this->integer(),
  19 + 'date_add' => $this->timestamp()
  20 + ->notNull()
  21 + ->defaultExpression('NOW()'),
  22 + 'status' => $this->smallInteger()
  23 + ->defaultValue(1),
  24 + ]);
  25 + $this->addForeignKey('file_relation_file', '{{%file_relation}}', 'file_id', '{{%file}}', 'file_id', 'CASCADE', 'CASCADE');
  26 + $this->addForeignKey('file_relation_user', '{{%file_relation}}', 'user_id', '{{%user}}', 'id', 'SET NULL', 'CASCADE');
  27 + }
  28 +
  29 + public function down()
  30 + {
  31 + $this->dropForeignKey('file_relation_file', '{{%file_relation}}');
  32 + $this->dropForeignKey('file_relation_user', '{{%file_relation}}');
  33 + $this->dropTable('{{%file_relation}}');
  34 + }
  35 + }
console/migrations/m160329_085324_file_add_user.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Migration;
  4 +
  5 +class m160329_085324_file_add_user extends Migration
  6 +{
  7 + public function up()
  8 + {
  9 + $this->addColumn('{{%file}}', 'user_id', $this->integer());
  10 + $this->addForeignKey('file_user', '{{%file}}', 'user_id', '{{%user}}', 'id', 'SET DEFAULT', 'CASCADE');
  11 + }
  12 +
  13 + public function down()
  14 + {
  15 + $this->dropForeignKey('file_user', '{{%file}}');
  16 + $this->dropColumn('{{%file}}', 'user_id');
  17 + }
  18 +}
frontend/controllers/SiteController.php
@@ -4,6 +4,7 @@ namespace frontend\controllers; @@ -4,6 +4,7 @@ namespace frontend\controllers;
4 use common\models\Cities; 4 use common\models\Cities;
5 use common\models\CompanyInfo; 5 use common\models\CompanyInfo;
6 use common\models\Country; 6 use common\models\Country;
  7 +use common\models\Project;
7 use common\models\Specialization; 8 use common\models\Specialization;
8 use common\models\UserInfo; 9 use common\models\UserInfo;
9 use Faker\Provider\is_IS\Company; 10 use Faker\Provider\is_IS\Company;
frontend/views/accounts/_projects_form.php
@@ -7,10 +7,12 @@ @@ -7,10 +7,12 @@
7 */ 7 */
8 use common\components\Request; 8 use common\components\Request;
9 use common\models\Currency; 9 use common\models\Currency;
  10 + use common\models\File;
10 use common\models\Payment; 11 use common\models\Payment;
11 use common\models\Project; 12 use common\models\Project;
12 use common\models\Specialization; 13 use common\models\Specialization;
13 use common\modules\file\widgets\ImageUploader; 14 use common\modules\file\widgets\ImageUploader;
  15 + use common\modules\fileloader\widgets\FileloaderWidget;
14 use kartik\select2\Select2; 16 use kartik\select2\Select2;
15 use mihaildev\ckeditor\CKEditor; 17 use mihaildev\ckeditor\CKEditor;
16 use yii\helpers\Html; 18 use yii\helpers\Html;
@@ -24,7 +26,7 @@ @@ -24,7 +26,7 @@
24 <div class="login-left-column-title"><?= $this->title ?></div> 26 <div class="login-left-column-title"><?= $this->title ?></div>
25 27
26 <?php 28 <?php
27 - $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); 29 + $form = ActiveForm::begin([ 'options' => [ 'enctype' => 'multipart/form-data' ] ]);
28 ?> 30 ?>
29 31
30 32
@@ -212,43 +214,55 @@ @@ -212,43 +214,55 @@
212 </div> 214 </div>
213 215
214 <?php 216 <?php
215 -/* == Здесь епты == */  
216 -?>  
217 -<div class="tender-file-wr">  
218 - <?= $form->field($project, 'files[]')  
219 - ->fileInput([ 'class' => 'multi', 'multiple' => 'multiple' ])  
220 - ->label(false) ?>  
221 - <a href="#" class="addfilemulti">Прикрепить файл</a>  
222 - <div class="max-size">Максимальный размер<br/>файла 5 МБ</div>  
223 -</div>  
224 -<?php  
225 -/* == .i. Конец епты .i. == */  
226 -?>  
227 -  
228 -<div class="input-blocks-wrapper admin-project-file">  
229 - <div class="input-blocks">  
230 - <div style="position: absolute; float: left;top: 0; left: 0; z-index: 1; width: 100%; overflow: hidden">  
231 - <div class="gen-admin-title">Присоединить файл</div>  
232 - <div class="admin-project-file-btn">Загрузить</div>  
233 - <div class="not-file-mb-adm">До 3 Мб файл</div>  
234 - </div>  
235 - <div style="opacity: 0; height: 54px; width: 100%; float: left;position: absolute; top: 0;left: 0; z-index: 2;-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)'">  
236 - <?= $form->field($project, 'files[]')  
237 - ->fileInput([ 'multiple' => 'multiple' ]) ?> 217 + /* == Old file upload ==
  218 + ?>
  219 + <div class="input-blocks-wrapper admin-project-file">
  220 + <div class="input-blocks">
  221 + <div style="position: absolute; float: left;top: 0; left: 0; z-index: 1; width: 100%; overflow: hidden">
  222 + <div class="gen-admin-title">Присоединить файл</div>
  223 + <div class="admin-project-file-btn">Загрузить</div>
  224 + <div class="not-file-mb-adm">До 3 Мб файл</div>
  225 + </div>
  226 + <div style="opacity: 0; height: 54px; width: 100%; float: left;position: absolute; top: 0;left: 0; z-index: 2;-ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=0)'">
  227 + <?= $form->field($project, 'files[]')
  228 + ->fileInput([ 'multiple' => 'multiple' ]) ?>
  229 + </div>
238 </div> 230 </div>
239 -  
240 </div> 231 </div>
  232 + <?php
  233 + == End of old file upload == */
  234 +?>
  235 +
  236 +<div class="input-blocks-wrapper">
  237 + <?php
  238 + echo $form->field($project, 'fileloader')
  239 + ->label(false)
  240 + ->widget(FileloaderWidget::className(), [
  241 + 'labelOptions' => [ 'label' => '<div class="gen-admin-title">Присоединить файлы</div><div class="admin-project-file-btn">Загрузить</div><div class="not-file-mb-adm">До 3 Мб файл</div>' ],
  242 + 'inputOptions' => [
  243 + 'multiple' => 'multiple',
  244 + 'class' => 'hidden',
  245 + ],
  246 + 'options' => [ 'class' => 'fileloader-file' ],
  247 + ]);
  248 + ?>
241 </div> 249 </div>
242 250
243 <div class="input-blocks-wrapper"> 251 <div class="input-blocks-wrapper">
244 <div class="input-blocks admin-project-list admin-currency-second"> 252 <div class="input-blocks admin-project-list admin-currency-second">
245 - <?= $form->field($project, 'date_end')->widget(DatePicker::className(), ['dateFormat' => 'yyyy-MM-dd', 'clientOptions' => ['minDate' => 1]]) ?> 253 + <?= $form->field($project, 'date_end')
  254 + ->widget(DatePicker::className(), [
  255 + 'dateFormat' => 'yyyy-MM-dd',
  256 + 'clientOptions' => [ 'minDate' => 1 ],
  257 + ]) ?>
246 </div> 258 </div>
247 </div> 259 </div>
248 260
249 <div class="input-blocks-wrapper"> 261 <div class="input-blocks-wrapper">
250 <div class="input-blocks admin-project-list admin-currency-second"> 262 <div class="input-blocks admin-project-list admin-currency-second">
251 - <?= $form->field($project, 'hidden')->checkbox()->hint('Проект, снятый с тендера, будет добавлен в Архив (не доступен в поиске, но доступен по ссылке)') ?> 263 + <?= $form->field($project, 'hidden')
  264 + ->checkbox()
  265 + ->hint('Проект, снятый с тендера, будет добавлен в Архив (не доступен в поиске, но доступен по ссылке)') ?>
252 </div> 266 </div>
253 </div> 267 </div>
254 268
frontend/views/layouts/performer.php
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <?php 22 <?php
23 if($this->params[ 'user' ]->id != \Yii::$app->user->getId()) { 23 if($this->params[ 'user' ]->id != \Yii::$app->user->getId()) {
24 // Offer project button 24 // Offer project button
25 - if(!empty( $this->params[ 'type' ] ) && $this->params[ 'type' ] == 'customer') { 25 + if(empty( $this->params[ 'type' ] ) || $this->params[ 'type' ] != 'customer') {
26 echo Html::a('Предложить проект', [ '#' ], [ 26 echo Html::a('Предложить проект', [ '#' ], [
27 'class' => 'blog-buttons-offer', 27 'class' => 'blog-buttons-offer',
28 'data-performer-id' => $this->params[ 'user' ]->id, 28 'data-performer-id' => $this->params[ 'user' ]->id,
frontend/views/site/index.php
1 <?php 1 <?php
2 2
3 -use \yii\helpers\Html;  
4 -use \common\models\Specialization;  
5 -/**  
6 - * @var $this yii\web\View  
7 - * @var $specializations common\models\Specialization  
8 - */ 3 + use common\models\Project;
  4 + use common\modules\fileloader\widgets\FileloaderWidget;
  5 + use \yii\helpers\Html;
  6 + use \common\models\Specialization;
  7 + use yii\widgets\ActiveForm;
9 8
10 -$this->title = 'My Yii Application';  
11 -?> 9 + /**
  10 + * @var $this yii\web\View
  11 + * @var $specializations common\models\Specialization
  12 + */
12 13
13 - <div class="section-box-1">  
14 - <div class="box-wr">  
15 - <div class="box-all">  
16 - <div class="section-box-base">  
17 - Самая полная база текущих и реализованных  
18 - строительных проектов с исполнителями  
19 - </div>  
20 - <div class="section-box-base-block">  
21 - <div class="base-blocks">  
22 - <?= Html::a('Хочу заказать проект',['landing/landing-order-project'],['class'=>'base-blocks-button first_butt']) ?>  
23 - <div class="base-blocks-text">  
24 - <p>Лучшие компании и исполнители готовы помочь вам</p>  
25 - </div> 14 + $this->title = 'My Yii Application';
  15 +?>
  16 +<div class="section-box-1">
  17 + <div class="box-wr">
  18 + <div class="box-all">
  19 + <div class="section-box-base">
  20 + Самая полная база текущих и реализованных
  21 + строительных проектов с исполнителями
  22 + </div>
  23 + <div class="section-box-base-block">
  24 + <div class="base-blocks">
  25 + <?= Html::a('Хочу заказать проект', [ 'landing/landing-order-project' ], [ 'class' => 'base-blocks-button first_butt' ]) ?>
  26 + <div class="base-blocks-text">
  27 + <p>Лучшие компании и исполнители готовы помочь вам</p>
26 </div> 28 </div>
27 - <div class="base-blocks">  
28 - <?= Html::a('Проектант/Фрилансер',['landing/landing-freelance'],['class'=>'base-blocks-button second_butt']) ?>  
29 - <div class="base-blocks-text">  
30 - <p>  
31 - Частные проекты и субподряды от лучших компаний и заказчиков для вас  
32 - </p>  
33 - <p>  
34 - <?= Html::a('Ищу работу',['landing/landing-work']) ?>  
35 - Вакансии компаний и заказчиков на полную занятость и резюме свободных проектантов  
36 - </p>  
37 - </div> 29 + </div>
  30 + <div class="base-blocks">
  31 + <?= Html::a('Проектант/Фрилансер', [ 'landing/landing-freelance' ], [ 'class' => 'base-blocks-button second_butt' ]) ?>
  32 + <div class="base-blocks-text">
  33 + <p>
  34 + Частные проекты и субподряды от лучших компаний и заказчиков для вас
  35 + </p>
  36 + <p>
  37 + <?= Html::a('Ищу работу', [ 'landing/landing-work' ]) ?>
  38 + Вакансии компаний и заказчиков на полную занятость и резюме свободных проектантов
  39 + </p>
38 </div> 40 </div>
39 - <div class="base-blocks">  
40 - <?= Html::a('Представляю компанию',['landing/landing-company'], ['class'=>'base-blocks-button third_butt']) ?>  
41 - <div class="base-blocks-text">  
42 - <p>Презентуйте лучшую команду профессиональных проектантов и получите актуальные тендеры на проектирование.</p>  
43 - </div> 41 + </div>
  42 + <div class="base-blocks">
  43 + <?= Html::a('Представляю компанию', [ 'landing/landing-company' ], [ 'class' => 'base-blocks-button third_butt' ]) ?>
  44 + <div class="base-blocks-text">
  45 + <p>Презентуйте лучшую команду профессиональных проектантов и получите актуальные тендеры на проектирование.</p>
44 </div> 46 </div>
45 </div> 47 </div>
46 </div> 48 </div>
47 </div> 49 </div>
48 </div> 50 </div>
49 - <div class="section-box-2">  
50 - <div class="box-wr">  
51 - <div class="box-all">  
52 - <div class="menu-two-wrapp-title">Специализация работ по исполнителям</div>  
53 - <div class="menu-two-wrapp" style="background: url('/images/menu-pic-1.jpg') 100% 100% no-repeat">  
54 - <ul class="content-menu-first">  
55 - <?php foreach($specializations as $specialization):?>  
56 - <li data-img="<?= $specialization->image?>">  
57 - <span data-menu-bg="<?= $specialization->background ?>" style="background: <?= $specialization->background ?>"></span><a href="#"><?= $specialization->specialization_name?></a>  
58 - <ul>  
59 - <?php foreach($specialization->children as $child_first):?> 51 +</div>
  52 +<div class="section-box-2">
  53 + <div class="box-wr">
  54 + <div class="box-all">
  55 + <div class="menu-two-wrapp-title">Специализация работ по исполнителям</div>
  56 + <div class="menu-two-wrapp" style="background: url('/images/menu-pic-1.jpg') 100% 100% no-repeat">
  57 + <ul class="content-menu-first">
  58 + <?php foreach($specializations as $specialization): ?>
  59 + <li data-img="<?= $specialization->image ?>">
  60 + <span data-menu-bg="<?= $specialization->background ?>" style="background: <?= $specialization->background ?>"></span><a href="#"><?= $specialization->specialization_name ?></a>
  61 + <ul>
  62 + <?php foreach($specialization->children as $child_first): ?>
60 63
61 - <?php if($child_first instanceof Specialization):?>  
62 - <li>  
63 - <a href="#"><?= $child_first->specialization_name?></a>  
64 - <ul>  
65 - <?php foreach($child_first->children as $child_second):?>  
66 - <?php if($child_first instanceof Specialization): ?>  
67 - <li><a href="#"><?= $child_second->specialization_name?></a></li>  
68 - <?php endif;?>  
69 - <?php endforeach; ?>  
70 - </ul>  
71 - </li>  
72 - <?php endif; ?>  
73 - <?php endforeach; ?> 64 + <?php if($child_first instanceof Specialization): ?>
  65 + <li>
  66 + <a href="#"><?= $child_first->specialization_name ?></a>
  67 + <ul>
  68 + <?php foreach($child_first->children as $child_second): ?>
  69 + <?php if($child_first instanceof Specialization): ?>
  70 + <li>
  71 + <a href="#"><?= $child_second->specialization_name ?></a>
  72 + </li>
  73 + <?php endif; ?>
  74 + <?php endforeach; ?>
  75 + </ul>
  76 + </li>
  77 + <?php endif; ?>
  78 + <?php endforeach; ?>
74 79
75 - </ul>  
76 - </li>  
77 - <?php endforeach; ?>  
78 - </ul>  
79 - </div> 80 + </ul>
  81 + </li>
  82 + <?php endforeach; ?>
  83 + </ul>
80 </div> 84 </div>
81 </div> 85 </div>
82 </div> 86 </div>
83 - <div class="section-box-3">  
84 - <div class="box-wr">  
85 - <div class="box-all">  
86 - <div class="all-project-home-title_menu">  
87 - <p>Проекты на нашем сайте</p>  
88 - <ul>  
89 - <li class="project-home-active"><span>Текущие</span></li>  
90 - <li><span>Завершенные</span></li>  
91 - </ul>  
92 - </div> 87 +</div>
  88 +<div class="section-box-3">
  89 + <div class="box-wr">
  90 + <div class="box-all">
  91 + <div class="all-project-home-title_menu">
  92 + <p>Проекты на нашем сайте</p>
  93 + <ul>
  94 + <li class="project-home-active"><span>Текущие</span></li>
  95 + <li><span>Завершенные</span></li>
  96 + </ul>
93 </div> 97 </div>
94 </div> 98 </div>
95 - <div class="section-box-map">  
96 - <div class="shadow-map"></div>  
97 - <div id="map_cloud" style="display: none;">  
98 - <script type="text/javascript">  
99 - function initialize() {  
100 - var start_position = new google.maps.LatLng('56', '30');  
101 - var settings = {  
102 - zoom: 7,  
103 - scrollwheel: false,  
104 - center: start_position,  
105 - mapTypeControl: false,  
106 - mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},  
107 - navigationControl: false,  
108 - navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL},  
109 - scaleControl: false,  
110 - streetViewControl: false,  
111 - rotateControl: false,  
112 - zoomControl:true,  
113 - mapTypeId: google.maps.MapTypeId.ROADMAP};  
114 - var map = new google.maps.Map(document.getElementById("map_canvas"), settings);  
115 -  
116 -  
117 - var image1 = new google.maps.MarkerImage('/images/markers/marker-we-1.png',  
118 - new google.maps.Size(21, 32),  
119 - new google.maps.Point(0,0),  
120 - new google.maps.Point(16, 35)  
121 - );  
122 - var image2 = new google.maps.MarkerImage('/images/markers/marker-we-2.png',  
123 - new google.maps.Size(21, 32),  
124 - new google.maps.Point(0,0),  
125 - new google.maps.Point(16, 35)  
126 - );  
127 - var image3 = new google.maps.MarkerImage('/images/markers/marker-we-3.png',  
128 - new google.maps.Size(21, 32),  
129 - new google.maps.Point(0,0),  
130 - new google.maps.Point(16, 35)  
131 - );  
132 - var image4 = new google.maps.MarkerImage('/images/markers/marker-we-4.png',  
133 - new google.maps.Size(21, 32),  
134 - new google.maps.Point(0,0),  
135 - new google.maps.Point(16, 35)  
136 - );  
137 - var image5 = new google.maps.MarkerImage('/images/markers/marker-we-5.png',  
138 - new google.maps.Size(21, 32),  
139 - new google.maps.Point(0,0),  
140 - new google.maps.Point(16, 35)  
141 - );  
142 - var image6 = new google.maps.MarkerImage('/images/markers/marker-we-6.png',  
143 - new google.maps.Size(21, 32),  
144 - new google.maps.Point(0,0),  
145 - new google.maps.Point(16, 35)  
146 - );  
147 - var image7 = new google.maps.MarkerImage('/images/markers/marker-we-7.png',  
148 - new google.maps.Size(21, 32),  
149 - new google.maps.Point(0,0),  
150 - new google.maps.Point(16, 35)  
151 - );  
152 - var image8 = new google.maps.MarkerImage('/images/markers/marker-we-8.png',  
153 - new google.maps.Size(21, 32),  
154 - new google.maps.Point(0,0),  
155 - new google.maps.Point(16, 35)  
156 - );  
157 - var image9 = new google.maps.MarkerImage('/images/markers/marker-we-9.png',  
158 - new google.maps.Size(21, 32),  
159 - new google.maps.Point(0,0),  
160 - new google.maps.Point(16, 35)  
161 - );  
162 - var image10 = new google.maps.MarkerImage('/images/markers/marker-empl-1.png',  
163 - new google.maps.Size(21, 32),  
164 - new google.maps.Point(0,0),  
165 - new google.maps.Point(16, 35)  
166 - );  
167 - var image11 = new google.maps.MarkerImage('/images/markers/marker-empl-2.png',  
168 - new google.maps.Size(21, 32),  
169 - new google.maps.Point(0,0),  
170 - new google.maps.Point(16, 35)  
171 - );  
172 - var image12 = new google.maps.MarkerImage('/images/markers/marker-empl-3.png',  
173 - new google.maps.Size(21, 32),  
174 - new google.maps.Point(0,0),  
175 - new google.maps.Point(16, 35)  
176 - );  
177 - var image13 = new google.maps.MarkerImage('/images/markers/marker-empl-4.png',  
178 - new google.maps.Size(21, 32),  
179 - new google.maps.Point(0,0),  
180 - new google.maps.Point(16, 35)  
181 - );  
182 - var image14 = new google.maps.MarkerImage('/images/markers/marker-empl-5.png',  
183 - new google.maps.Size(21, 32),  
184 - new google.maps.Point(0,0),  
185 - new google.maps.Point(16, 35)  
186 - );  
187 - var image15 = new google.maps.MarkerImage('/images/markers/marker-empl-6.png',  
188 - new google.maps.Size(21, 32),  
189 - new google.maps.Point(0,0),  
190 - new google.maps.Point(16, 35)  
191 - );  
192 - var image16 = new google.maps.MarkerImage('/images/markers/marker-empl-7.png',  
193 - new google.maps.Size(21, 32),  
194 - new google.maps.Point(0,0),  
195 - new google.maps.Point(16, 35)  
196 - );  
197 - var image17 = new google.maps.MarkerImage('/images/markers/marker-empl-8.png',  
198 - new google.maps.Size(21, 32),  
199 - new google.maps.Point(0,0),  
200 - new google.maps.Point(16, 35)  
201 - );  
202 - var image18 = new google.maps.MarkerImage('/images/markers/marker-empl-9.png',  
203 - new google.maps.Size(21, 32),  
204 - new google.maps.Point(0,0),  
205 - new google.maps.Point(16, 35)  
206 - ); 99 + </div>
  100 + <div class="section-box-map">
  101 + <div class="shadow-map"></div>
  102 + <div id="map_cloud" style="display: none;">
  103 + <script type="text/javascript">
  104 + function initialize()
  105 + {
  106 + var start_position = new google.maps.LatLng('56', '30');
  107 + var settings = {
  108 + zoom : 7, scrollwheel : false, center : start_position,
  109 + mapTypeControl : false,
  110 + mapTypeControlOptions : {style : google.maps.MapTypeControlStyle.DROPDOWN_MENU},
  111 + navigationControl : false,
  112 + navigationControlOptions : {style : google.maps.NavigationControlStyle.SMALL},
  113 + scaleControl : false, streetViewControl : false, rotateControl : false,
  114 + zoomControl : true, mapTypeId : google.maps.MapTypeId.ROADMAP
  115 + };
  116 + var map = new google.maps.Map(document.getElementById("map_canvas"), settings);
207 117
208 - var markers = []; 118 + var image1 = new google.maps.MarkerImage(
  119 + '/images/markers/marker-we-1.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  120 + );
  121 + var image2 = new google.maps.MarkerImage(
  122 + '/images/markers/marker-we-2.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  123 + );
  124 + var image3 = new google.maps.MarkerImage(
  125 + '/images/markers/marker-we-3.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  126 + );
  127 + var image4 = new google.maps.MarkerImage(
  128 + '/images/markers/marker-we-4.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  129 + );
  130 + var image5 = new google.maps.MarkerImage(
  131 + '/images/markers/marker-we-5.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  132 + );
  133 + var image6 = new google.maps.MarkerImage(
  134 + '/images/markers/marker-we-6.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  135 + );
  136 + var image7 = new google.maps.MarkerImage(
  137 + '/images/markers/marker-we-7.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  138 + );
  139 + var image8 = new google.maps.MarkerImage(
  140 + '/images/markers/marker-we-8.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  141 + );
  142 + var image9 = new google.maps.MarkerImage(
  143 + '/images/markers/marker-we-9.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  144 + );
  145 + var image10 = new google.maps.MarkerImage(
  146 + '/images/markers/marker-empl-1.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  147 + );
  148 + var image11 = new google.maps.MarkerImage(
  149 + '/images/markers/marker-empl-2.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  150 + );
  151 + var image12 = new google.maps.MarkerImage(
  152 + '/images/markers/marker-empl-3.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  153 + );
  154 + var image13 = new google.maps.MarkerImage(
  155 + '/images/markers/marker-empl-4.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  156 + );
  157 + var image14 = new google.maps.MarkerImage(
  158 + '/images/markers/marker-empl-5.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  159 + );
  160 + var image15 = new google.maps.MarkerImage(
  161 + '/images/markers/marker-empl-6.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  162 + );
  163 + var image16 = new google.maps.MarkerImage(
  164 + '/images/markers/marker-empl-7.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  165 + );
  166 + var image17 = new google.maps.MarkerImage(
  167 + '/images/markers/marker-empl-8.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  168 + );
  169 + var image18 = new google.maps.MarkerImage(
  170 + '/images/markers/marker-empl-9.png', new google.maps.Size(21, 32), new google.maps.Point(0, 0), new google.maps.Point(16, 35)
  171 + );
209 172
210 - var marker = new google.maps.Marker({  
211 - position: new google.maps.LatLng('56', '35.3'),  
212 - map: map,  
213 - title: 'Marker Title2',  
214 - icon: image1  
215 - });  
216 - markers.push(marker); 173 + var markers = [];
217 174
218 - var marker = new google.maps.Marker({  
219 - position: new google.maps.LatLng('56', '36'),  
220 - map: map,  
221 - title: 'Marker Title2',  
222 - icon: image2  
223 - });  
224 - markers.push(marker); 175 + var marker = new google.maps.Marker(
  176 + {
  177 + position : new google.maps.LatLng('56', '35.3'), map : map,
  178 + title : 'Marker Title2', icon : image1
  179 + }
  180 + );
  181 + markers.push(marker);
225 182
226 - var marker = new google.maps.Marker({  
227 - position: new google.maps.LatLng('56', '34.5'),  
228 - map: map,  
229 - title: 'Marker Title3',  
230 - icon: image18  
231 - });  
232 - markers.push(marker); 183 + var marker = new google.maps.Marker(
  184 + {
  185 + position : new google.maps.LatLng('56', '36'), map : map,
  186 + title : 'Marker Title2', icon : image2
  187 + }
  188 + );
  189 + markers.push(marker);
233 190
234 - var marker = new google.maps.Marker({  
235 - position: new google.maps.LatLng('56', '35'),  
236 - map: map,  
237 - title: 'Marker Title4',  
238 - icon: image13  
239 - });  
240 - markers.push(marker); 191 + var marker = new google.maps.Marker(
  192 + {
  193 + position : new google.maps.LatLng('56', '34.5'), map : map,
  194 + title : 'Marker Title3', icon : image18
  195 + }
  196 + );
  197 + markers.push(marker);
241 198
  199 + var marker = new google.maps.Marker(
  200 + {
  201 + position : new google.maps.LatLng('56', '35'), map : map,
  202 + title : 'Marker Title4', icon : image13
  203 + }
  204 + );
  205 + markers.push(marker);
242 206
243 - var clusterStyles = [  
244 - {  
245 - url: '/images/markers/clasters.png',  
246 - height: 36,  
247 - width: 36  
248 - } 207 + var clusterStyles = [
  208 + {
  209 + url : '/images/markers/clasters.png', height : 36, width : 36
  210 + }
249 211
250 - ];  
251 - markerClusterer = new MarkerClusterer(map, markers,  
252 - {  
253 - maxZoom: 10,  
254 - gridSize: 100,  
255 - styles: clusterStyles  
256 - });  
257 - }  
258 - </script>  
259 - </div>  
260 - <div id="map_canvas" style="width: 100%; height:100%;"></div> 212 + ];
  213 + markerClusterer = new MarkerClusterer(
  214 + map, markers, {
  215 + maxZoom : 10, gridSize : 100, styles : clusterStyles
  216 + }
  217 + );
  218 + }
  219 + </script>
261 </div> 220 </div>
  221 + <div id="map_canvas" style="width: 100%; height:100%;"></div>
262 </div> 222 </div>
  223 +</div>
263 224
264 - <div class="section-box-4">  
265 - <div class="box-wr">  
266 - <div class="box-all">  
267 - <div class="federation-home-title">Зачем нужна Международная федерация проектантов</div>  
268 - <div class="federation-home-list-wr">  
269 - <ul class="federation-home-list">  
270 - <li class="federation-home-list-active"><span>Заказчикам</span></li>  
271 - <li><span>Компаниям</span></li>  
272 - <li><span>Проектантам</span></li>  
273 - <li><span>Наша миссия</span></li>  
274 - </ul>  
275 - </div>  
276 - <div class="federation-home-blocks-wr">  
277 - <div class="federation-home-blocks-wr-blocks">  
278 - <div class="federation-home-blocks">  
279 - <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/></div>  
280 - <div class="federation-home-text">Описания рейтингов</div> 225 +<div class="section-box-4">
  226 + <div class="box-wr">
  227 + <div class="box-all">
  228 + <div class="federation-home-title">Зачем нужна Международная федерация проектантов</div>
  229 + <div class="federation-home-list-wr">
  230 + <ul class="federation-home-list">
  231 + <li class="federation-home-list-active"><span>Заказчикам</span></li>
  232 + <li><span>Компаниям</span></li>
  233 + <li><span>Проектантам</span></li>
  234 + <li><span>Наша миссия</span></li>
  235 + </ul>
  236 + </div>
  237 + <div class="federation-home-blocks-wr">
  238 + <div class="federation-home-blocks-wr-blocks">
  239 + <div class="federation-home-blocks">
  240 + <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/>
281 </div> 241 </div>
282 - <div class="federation-home-blocks">  
283 - <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/></div>  
284 - <div class="federation-home-text">Вы получаете лучшую цену</div> 242 + <div class="federation-home-text">Описания рейтингов</div>
  243 + </div>
  244 + <div class="federation-home-blocks">
  245 + <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/>
285 </div> 246 </div>
286 - <div class="federation-home-blocks">  
287 - <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/></div>  
288 - <div class="federation-home-text">Гарантии получения проекта в срок</div> 247 + <div class="federation-home-text">Вы получаете лучшую цену</div>
  248 + </div>
  249 + <div class="federation-home-blocks">
  250 + <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/>
289 </div> 251 </div>
  252 + <div class="federation-home-text">Гарантии получения проекта в срок</div>
290 </div> 253 </div>
  254 + </div>
291 255
292 - <div class="federation-home-blocks-wr-blocks">  
293 - <div class="federation-home-blocks">  
294 - <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/></div>  
295 - <div class="federation-home-text">2Описания рейтингов</div> 256 + <div class="federation-home-blocks-wr-blocks">
  257 + <div class="federation-home-blocks">
  258 + <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/>
296 </div> 259 </div>
297 - <div class="federation-home-blocks">  
298 - <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/></div>  
299 - <div class="federation-home-text">2Вы получаете лучшую цену</div> 260 + <div class="federation-home-text">2Описания рейтингов</div>
  261 + </div>
  262 + <div class="federation-home-blocks">
  263 + <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/>
300 </div> 264 </div>
301 - <div class="federation-home-blocks">  
302 - <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/></div>  
303 - <div class="federation-home-text">2Гарантии получения проекта в срок</div> 265 + <div class="federation-home-text">2Вы получаете лучшую цену</div>
  266 + </div>
  267 + <div class="federation-home-blocks">
  268 + <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/>
304 </div> 269 </div>
  270 + <div class="federation-home-text">2Гарантии получения проекта в срок</div>
305 </div> 271 </div>
  272 + </div>
306 273
307 - <div class="federation-home-blocks-wr-blocks">  
308 - <div class="federation-home-blocks">  
309 - <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/></div>  
310 - <div class="federation-home-text">3Описания рейтингов</div> 274 + <div class="federation-home-blocks-wr-blocks">
  275 + <div class="federation-home-blocks">
  276 + <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/>
311 </div> 277 </div>
312 - <div class="federation-home-blocks">  
313 - <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/></div>  
314 - <div class="federation-home-text">3Вы получаете лучшую цену</div> 278 + <div class="federation-home-text">3Описания рейтингов</div>
  279 + </div>
  280 + <div class="federation-home-blocks">
  281 + <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/>
315 </div> 282 </div>
316 - <div class="federation-home-blocks">  
317 - <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/></div>  
318 - <div class="federation-home-text">3Гарантии получения проекта в срок</div> 283 + <div class="federation-home-text">3Вы получаете лучшую цену</div>
  284 + </div>
  285 + <div class="federation-home-blocks">
  286 + <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/>
319 </div> 287 </div>
  288 + <div class="federation-home-text">3Гарантии получения проекта в срок</div>
320 </div> 289 </div>
  290 + </div>
321 291
322 - <div class="federation-home-blocks-wr-blocks">  
323 - <div class="federation-home-blocks">  
324 - <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/></div>  
325 - <div class="federation-home-text">4Описания рейтингов</div> 292 + <div class="federation-home-blocks-wr-blocks">
  293 + <div class="federation-home-blocks">
  294 + <div class="federation-home-ico"><img src="/images/ico-fed-1.png" alt=""/>
326 </div> 295 </div>
327 - <div class="federation-home-blocks">  
328 - <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/></div>  
329 - <div class="federation-home-text">4Вы получаете лучшую цену</div> 296 + <div class="federation-home-text">4Описания рейтингов</div>
  297 + </div>
  298 + <div class="federation-home-blocks">
  299 + <div class="federation-home-ico"><img src="/images/ico-fed-2.png" alt=""/>
330 </div> 300 </div>
331 - <div class="federation-home-blocks">  
332 - <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/></div>  
333 - <div class="federation-home-text">4Гарантии получения проекта в срок</div> 301 + <div class="federation-home-text">4Вы получаете лучшую цену</div>
  302 + </div>
  303 + <div class="federation-home-blocks">
  304 + <div class="federation-home-ico"><img src="/images/ico-fed-3.png" alt=""/>
334 </div> 305 </div>
  306 + <div class="federation-home-text">4Гарантии получения проекта в срок</div>
335 </div> 307 </div>
336 </div> 308 </div>
337 </div> 309 </div>
338 </div> 310 </div>
339 - </div>  
340 \ No newline at end of file 311 \ No newline at end of file
  312 + </div>
  313 +</div>
341 \ No newline at end of file 314 \ No newline at end of file
frontend/views/site/registration.php
@@ -117,7 +117,10 @@ @@ -117,7 +117,10 @@
117 </div> 117 </div>
118 <div class="input-blocks-wrapper"> 118 <div class="input-blocks-wrapper">
119 <div class="input-blocks"> 119 <div class="input-blocks">
120 - <?= $form->field($model, 'city', ['enableClientValidation' => false, 'options' => ['class' => 'required-no-star']]) 120 + <?= $form->field($model, 'city', [
  121 + 'enableClientValidation' => false,
  122 + 'options' => [ 'class' => 'required-no-star' ],
  123 + ])
121 ->widget(Select2::classname(), [ 124 ->widget(Select2::classname(), [
122 'options' => [ 'placeholder' => 'Выбор города ...' ], 125 'options' => [ 'placeholder' => 'Выбор города ...' ],
123 'pluginOptions' => [ 126 'pluginOptions' => [
@@ -199,9 +202,6 @@ @@ -199,9 +202,6 @@
199 $('.field-signupform-lastname label').html(labelLastName) 202 $('.field-signupform-lastname label').html(labelLastName)
200 $('.register-company-block').css('display', 'none'); 203 $('.register-company-block').css('display', 'none');
201 $('#w0').yiiActiveForm('remove','signupform-name'); 204 $('#w0').yiiActiveForm('remove','signupform-name');
202 -  
203 -  
204 -  
205 } else { 205 } else {
206 //company 206 //company
207 $('.field-signupform-firstname label').html(labelName+' '+newLabelName) 207 $('.field-signupform-firstname label').html(labelName+' '+newLabelName)
frontend/web/css/style.css
@@ -6414,7 +6414,7 @@ input[disabled], select[disabled] { @@ -6414,7 +6414,7 @@ input[disabled], select[disabled] {
6414 position: relative; 6414 position: relative;
6415 height: 54px; 6415 height: 54px;
6416 } 6416 }
6417 -.admin-project-file .admin-project-file-btn{ 6417 +.admin-project-file .admin-project-file-btn, .fileloader-file .admin-project-file-btn {
6418 background: #fff; 6418 background: #fff;
6419 color: #0072bc; 6419 color: #0072bc;
6420 height: 29px; 6420 height: 29px;
@@ -6428,12 +6428,12 @@ input[disabled], select[disabled] { @@ -6428,12 +6428,12 @@ input[disabled], select[disabled] {
6428 border-radius: 4px; 6428 border-radius: 4px;
6429 cursor: pointer; 6429 cursor: pointer;
6430 } 6430 }
6431 -.admin-project-file .admin-project-file-btn:hover{ 6431 +.admin-project-file .admin-project-file-btn:hover, .fileloader-file .admin-project-file-btn:hover{
6432 transition: 0.2s; 6432 transition: 0.2s;
6433 background: #0072bc; 6433 background: #0072bc;
6434 color: #fff; 6434 color: #fff;
6435 } 6435 }
6436 -.admin-project-file .gen-admin-title{ 6436 +.admin-project-file .gen-admin-title, .fileloader-file .gen-admin-title{
6437 font-size: 13px; 6437 font-size: 13px;
6438 font-weight: 700; 6438 font-weight: 700;
6439 margin-bottom: 10px; 6439 margin-bottom: 10px;
@@ -6444,7 +6444,7 @@ input[disabled], select[disabled] { @@ -6444,7 +6444,7 @@ input[disabled], select[disabled] {
6444 cursor: pointer; 6444 cursor: pointer;
6445 margin-top: 8px; 6445 margin-top: 8px;
6446 } 6446 }
6447 -.admin-project-file .not-file-mb-adm{ 6447 +.admin-project-file .not-file-mb-adm, .fileloader-file .not-file-mb-adm {
6448 position: static; 6448 position: static;
6449 margin-left: 10px; 6449 margin-left: 10px;
6450 width: 540px; 6450 width: 540px;