Commit 4921cad4d331a811e8369f6b79dd266c21578ef8

Authored by Yarik
1 parent bb1ff629

Добален блог v 0.5 dev

backend/controllers/BlogController.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace backend\controllers;
  4 +
  5 +use common\modules\blog\models\Article;
  6 +use yii\base\Controller;
  7 +use yii\data\ActiveDataProvider;
  8 +
  9 +class BlogController extends Controller
  10 +{
  11 + public $defaultAction = 'articles';
  12 +
  13 + public function actionIndex()
  14 + {
  15 + echo 123;
  16 + }
  17 +
  18 + public function actionArticles($category_id = NULL)
  19 + {
  20 + $dataProvider = new ActiveDataProvider([
  21 + 'query' => Article::find(),
  22 + 'pagination' => [
  23 + 'pageSize' => 10
  24 + ]
  25 + ]);
  26 + return $this->render('articles', ['dataProvider' => $dataProvider]);
  27 + }
  28 +
  29 +}
0 \ No newline at end of file 30 \ No newline at end of file
backend/views/blog/articles.php 0 → 100644
  1 +<?php
  2 +use yii\grid\ActionColumn;
  3 +use yii\grid\Column;
  4 +use yii\grid\GridView;
  5 +use common\modules\blog\models\Article;
  6 +use common\models\Language;
  7 +
  8 +echo GridView::widget([
  9 + 'dataProvider' => $dataProvider,
  10 + 'columns' => [
  11 + 'id',
  12 + 'code',
  13 + 'create_at',
  14 + [
  15 + 'value' => function($data) {
  16 + return $data->author0->firstname.' '.$data->author0->lastname;
  17 + },
  18 + 'header' => Yii::t('app', 'Author')
  19 + ],
  20 + [
  21 + 'class' => Column::className(),
  22 + 'header' => Yii::t('app', 'Name'),
  23 + 'content' => function($model, $key, $index, $column) {
  24 + return $model->getArticleLangs()->where(['lang_id' => Language::getDefaultLang()->language_id])->one()->name;
  25 + }
  26 + ],
  27 + [
  28 + 'class' => ActionColumn::className(),
  29 + 'template' => '{update} {delete}'
  30 + ]
  31 + ]
  32 +]);
0 \ No newline at end of file 33 \ No newline at end of file
backend/views/layouts/left.php
@@ -40,6 +40,16 @@ @@ -40,6 +40,16 @@
40 ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest], 40 ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
41 ['label' => 'Пользователи', 'icon' => 'fa fa-file-code-o', 'url' => ['/user/']], 41 ['label' => 'Пользователи', 'icon' => 'fa fa-file-code-o', 'url' => ['/user/']],
42 [ 42 [
  43 + 'label' => Yii::t('app', 'Blog'),
  44 + 'icon' => 'fa fa-share',
  45 + 'url' => '#',
  46 + 'items' => [
  47 + ['label' => Yii::t('app', 'Static pages'), 'icon' => 'fa fa-file-code-o', 'url' => ['blog/articles', 'category_id' => '63'],],
  48 + ['label' => Yii::t('app', 'Categories'), 'icon' => 'fa fa-dashboard', 'url' => ['blog/categories'],],
  49 + ['label' => Yii::t('app', 'Articles'), 'icon' => 'fa fa-dashboard', 'url' => ['blog/articles'],],
  50 + ],
  51 + ],
  52 + [
43 'label' => 'Роли', 53 'label' => 'Роли',
44 'icon' => 'fa fa-share', 54 'icon' => 'fa fa-share',
45 'url' => '#', 55 'url' => '#',
backend/web/js/option.js
  1 +function readURL(input) {
  2 + $(input).parents('.tab-pane').find('.image_inputs_prev').remove();
  3 + var urls = [];
  4 + if (input.files) {
  5 + $.each(input.files, function(key, value) {
  6 + var reader = new FileReader();
  7 + reader.onload = function(e) {
  8 + $(input).parent().append('<img src="'+ e.target.result +'" width="100" class="image_inputs_prev" />');
  9 + }
  10 + reader.readAsDataURL(value);
  11 + });
  12 + }
  13 + return urls;
  14 +}
1 $(function() { 15 $(function() {
2 - var counter = 0;  
3 - $(document).on('click', '.add_row', function() {  
4 - counter++;  
5 - var clone = $('#main_row').clone().html().replace(new RegExp("Option\\[0\\]", 'g'), "Option["+counter+"]");  
6 - console.log(form);  
7 - $(clone).appendTo('#'+form);  
8 - $('#'+form+' button[type=submit]').parent().appendTo('#'+form);  
9 - });  
10 - $(document).on('click', '.add_lang', function() {  
11 - var field_block = $(this).parent().parent();  
12 - if($(this).hasClass('active')) {  
13 - $(field_block).find('.main_input').attr('required', '').show();  
14 - $(field_block).find('.lang_inputs').hide();  
15 - $(this).removeClass('active');  
16 - } else {  
17 - $(field_block).find('.main_input').removeAttr('required').hide();  
18 - $(field_block).find('.lang_inputs').show();  
19 - $(this).addClass('active');  
20 - }  
21 - });  
22 - $(document).on('click', '.remove_lang', function() {  
23 - $(this).parents('.form-wrapper').remove();  
24 - });  
25 - });  
26 \ No newline at end of file 16 \ No newline at end of file
  17 + var counter = 0;
  18 + $(document).on('click', '.add_row', function() {
  19 + counter++;
  20 + var clone = $('#main_row').clone().html().replace(new RegExp("Option\\[0\\]", 'g'), "Option["+counter+"]");
  21 + console.log(form);
  22 + $(clone).appendTo('#'+form);
  23 + $('#'+form+' button[type=submit]').parent().appendTo('#'+form);
  24 + });
  25 + $(document).on('click', '.add_lang', function() {
  26 + var field_block = $(this).parent().parent();
  27 + if($(this).hasClass('active')) {
  28 + $(field_block).find('.main_input').attr('required', '').show();
  29 + $(field_block).find('.lang_inputs').hide();
  30 + $(this).removeClass('active');
  31 + } else {
  32 + $(field_block).find('.main_input').removeAttr('required').hide();
  33 + $(field_block).find('.lang_inputs').show();
  34 + $(this).addClass('active');
  35 + }
  36 + });
  37 + $(document).on('click', '.remove_lang', function() {
  38 + $(this).parents('.form-wrapper').remove();
  39 + });
  40 + if($('#lang-tabs li').length > 1) {
  41 + $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')
  42 + }
  43 + $(document).on('click', '#lang-dropdown li a[data-lang]', function() {
  44 + var lang = $(this).data('lang');
  45 + var flag = $(this).find('span').first().clone();
  46 + var el = $(this);
  47 + $.get('/blog/ajax/category-form', { lang_id: lang }, function(data) {
  48 + $('#lang-tabs li').removeClass('active');
  49 + $('#lang-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#lang-'+lang+'" aria-controls="lang-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>');
  50 + $('.lang-tab-content .tab-pane.active').removeClass('active');
  51 + $('.lang-tab-content').append($(data).find('.ajax-loaded').first());
  52 + $('body').append($(data).filter('script'));
  53 + $(el).parent().remove();
  54 + if(!$('#lang-dropdown li').length) {
  55 + $('#dropdownLang').addClass('disabled');
  56 + }
  57 + if($('#lang-tabs li').length > 1) {
  58 + $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')
  59 + }
  60 + });
  61 + });
  62 + $(document).on('click', '.remove-lang', function() {
  63 + var lang = $(this).parent().data('lang');
  64 + var flag = $(this).parent().find('span.flag').first().clone();
  65 + $('#lang-'+lang).remove();
  66 + $('#lang-dropdown').append('<li><a href="#lang-tabs" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>');
  67 + $('#dropdownLang').removeClass('disabled');
  68 + $(this).parent().remove();
  69 + if($('#lang-tabs li').length <= 1) {
  70 + $('#lang-tabs li').find('.remove-lang').remove();
  71 + }
  72 + if(!$('#lang-tabs>li.active').length) {
  73 + $('#lang-tabs>li').first().find('a').tab('show');
  74 + }
  75 + });
  76 + $(document).on('change', '.image_inputs_field', function() {
  77 + readURL(this);
  78 + });
  79 + $('a.remove_image').on('click', function(e) {
  80 + var el = $(this);
  81 + e.preventDefault();
  82 + if(confirm(confirm_message)) {
  83 + $.ajax({
  84 + type: 'post',
  85 + url: $(this).attr('href'),
  86 + data: $(this).data('params')
  87 + }).done(function() {
  88 + $(el).parents('.additional_image_container').remove();
  89 + });
  90 + }
  91 + return false;
  92 + });
  93 +});
27 \ No newline at end of file 94 \ No newline at end of file
common/config/bootstrap.php
@@ -3,3 +3,4 @@ Yii::setAlias(&#39;common&#39;, dirname(__DIR__)); @@ -3,3 +3,4 @@ Yii::setAlias(&#39;common&#39;, dirname(__DIR__));
3 Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend'); 3 Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend');
4 Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend'); 4 Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend');
5 Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console'); 5 Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');
  6 +Yii::setAlias('saveImageDir', '@frontend/web/images/upload/');
common/config/main.php
@@ -8,9 +8,6 @@ return [ @@ -8,9 +8,6 @@ return [
8 'userClass' => 'common\models\User' 8 'userClass' => 'common\models\User'
9 ] 9 ]
10 ], 10 ],
11 - 'blog' => [  
12 - 'class' => 'common\modules\blog\Module',  
13 - ],  
14 ], 11 ],
15 'components' => [ 12 'components' => [
16 'cache' => [ 13 'cache' => [
common/modules/blog/behaviors/Autocomplete.php 0 → 100644
  1 +<?php
  2 +namespace common\modules\blog\behaviors;
  3 +
  4 +use common\models\Tools;
  5 +use yii\db\ActiveRecord;
  6 +use yii\base\Behavior;
  7 +use yii\helpers\StringHelper;
  8 +
  9 +/**
  10 + * Класс для автозаполнения полей некими данными или их форматирования
  11 + *
  12 + * Клас предназначен для заполнения полей данными или форматирования данных
  13 + *
  14 + */
  15 +
  16 +class Autocomplete extends Behavior
  17 +{
  18 + /**
  19 + * Атрибуты для обработки
  20 + *
  21 + * Атрибуты считываются автоматически с настроек поведения в конкретном обьекте.
  22 + * Имеет вид ассоциативного массива, где ключ - метод автозаполнения, а значение - массив, каждій єлемент
  23 + * которого - свойство обьекта для обработки, может включать массив - первый єлемент которого свойство,
  24 + * а дальнейшие конфигурации.
  25 + *
  26 + * @var array Ассоциативны массив [key(метод заполнения) => [[0 => property(свойство обьекта), ... дополнительные
  27 + * настройки]], ...[]]
  28 + *
  29 + */
  30 + public $attributes;
  31 +
  32 + /**
  33 + * События
  34 + *
  35 + * События на которые должно срабатывать поведение. Задается ассоциативный массив, в котором ключ - событие
  36 + * связанного обьекта, а значение - метод, который вызывается при этом событии
  37 + *
  38 + * @return array [key(event) => val(method)]
  39 + *
  40 + */
  41 + public function events()
  42 + {
  43 + return [
  44 + ActiveRecord::EVENT_BEFORE_INSERT => 'autocomplete',
  45 + ActiveRecord::EVENT_BEFORE_UPDATE => 'autocomplete',
  46 + ];
  47 + }
  48 +
  49 + /**
  50 + * События
  51 + *
  52 + * События на которые должно срабатывать поведение. Задается ассоциативный массив, в котором ключ - событие
  53 + * связанного обьекта, а значение - метод, который вызывается при этом событии
  54 + * Доступные автозаполнения:
  55 + * ['translit' => ['prop1', ... 'prop2']],
  56 + * где prop - свойство подлежащее транслитерации
  57 + * ['repeat' => [[string 'prop1', string 'target1', boolean 'skipFilled', int 'count', boolean 'truncate', string 'suffix'], ...[]],
  58 + * где prop - свойство для преобразования,
  59 + * target - свойство с которого взять данные,
  60 + * count - число для преобразования,
  61 + * skipFilled - пропустить непустые,
  62 + * truncate - true - обрезать по словам, false - по символам,
  63 + * suffix - суффикс, который добавить после обрезки
  64 + *
  65 + * @param mixed $event Yii обьект свойста https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/concept-events.md
  66 + *
  67 + */
  68 + public function autocomplete($event)
  69 + {
  70 + if(!empty($this->attributes['translit'])) {
  71 + foreach($this->attributes['translit'] as $translit) {
  72 + if($this->owner->hasAttribute($translit)) {
  73 + $this->owner->$translit = Tools::translit($this->owner->$translit);
  74 + }
  75 + }
  76 + }
  77 + if(!empty($this->attributes['repeat'])) {
  78 + foreach($this->attributes['repeat'] as $repeat) {
  79 + if(is_array($repeat) && $this->owner->hasAttribute($repeat[0]) && $this->owner->hasAttribute($repeat[1]) && is_int($repeat[3]) && (empty($this->owner->$repeat[0]) || $repeat[2])) {
  80 + $suffix = $repeat[5]?:'';
  81 + $truncate = $repeat[4]?'truncateWords':'truncate';
  82 + $this->owner->$repeat[0] = StringHelper::$truncate($this->owner->$repeat[1], $repeat[3], $suffix);
  83 + }
  84 + }
  85 + }
  86 + }
  87 +}
0 \ No newline at end of file 88 \ No newline at end of file
common/modules/blog/controllers/AjaxController.php
@@ -2,19 +2,81 @@ @@ -2,19 +2,81 @@
2 namespace common\modules\blog\controllers; 2 namespace common\modules\blog\controllers;
3 3
4 use common\models\Language; 4 use common\models\Language;
  5 +use common\modules\blog\models\ArticleCategory;
5 use common\modules\blog\models\ArticleCategoryLang; 6 use common\modules\blog\models\ArticleCategoryLang;
  7 +use common\modules\blog\models\ArticleCategoryMedia;
  8 +use common\modules\blog\models\ArticleLang;
  9 +use common\modules\blog\models\ArticleMedia;
6 use yii\web\Controller; 10 use yii\web\Controller;
  11 +use yii\web\ForbiddenHttpException;
7 use yii\web\NotFoundHttpException; 12 use yii\web\NotFoundHttpException;
8 13
9 class AjaxController extends Controller 14 class AjaxController extends Controller
10 { 15 {
  16 + public function beforeAction($action)
  17 + {
  18 + if(!\Yii::$app->request->getIsAjax()) {
  19 + //throw new ForbiddenHttpException('Permission denied');
  20 + }
  21 +
  22 + if(!parent::beforeAction($action)) {
  23 + return false;
  24 + }
  25 +
  26 + return true;
  27 + }
  28 +
11 public function actionCategoryForm($lang_id) 29 public function actionCategoryForm($lang_id)
12 { 30 {
13 - $model = Language::findOne($lang_id); 31 + $model = Language::find()->where(['>=', 'language_id', 1])->andWhere(['active' => 1, 'language_id' => $lang_id])->one();
14 if(!$model) { 32 if(!$model) {
15 throw new NotFoundHttpException('Language not found'); 33 throw new NotFoundHttpException('Language not found');
16 } 34 }
17 $category_lang = new ArticleCategoryLang(); 35 $category_lang = new ArticleCategoryLang();
18 - return $this->renderPartial('_category_form', ['model' => $model, 'category_lang' => $category_lang]); 36 + return $this->renderAjax('_category_form', ['model' => $model, 'category_lang' => $category_lang]);
  37 + }
  38 +
  39 + public function actionArticleForm($lang_id)
  40 + {
  41 + $model = Language::find()->where(['>=', 'language_id', 1])->andWhere(['active' => 1, 'language_id' => $lang_id])->one();
  42 + if(!$model) {
  43 + throw new NotFoundHttpException('Language not found');
  44 + }
  45 + $article_lang = new ArticleLang();
  46 + return $this->renderAjax('_article_form', ['model' => $model, 'article_lang' => $article_lang]);
  47 + }
  48 +
  49 + public function actionRemoveImage()
  50 + {
  51 + $post = \Yii::$app->request->post();
  52 + if(!empty($post['article_media_id'])) {
  53 + $article_media = ArticleMedia::findOne($post['article_media_id']);
  54 + if($post['remove_media']) {
  55 + $media = $article_media->media->delete();
  56 + }
  57 + if(!empty($article_media)) {
  58 + $article_media->delete();
  59 + }
  60 + return true;
  61 + } else {
  62 + return false;
  63 + }
  64 + }
  65 +
  66 + public function actionRemoveImageCategory()
  67 + {
  68 + $post = \Yii::$app->request->post();
  69 + if(!empty($post['category_media_id'])) {
  70 + $category_media = ArticleCategoryMedia::findOne($post['category_media_id']);
  71 + if($post['remove_media']) {
  72 + $media = $category_media->media->delete();
  73 + }
  74 + if(!empty($category_media)) {
  75 + $category_media->delete();
  76 + }
  77 + return true;
  78 + } else {
  79 + return false;
  80 + }
19 } 81 }
20 } 82 }
common/modules/blog/controllers/ArticleController.php
1 <?php 1 <?php
2 namespace common\modules\blog\controllers; 2 namespace common\modules\blog\controllers;
3 3
  4 +use common\models\Language;
4 use common\modules\blog\models\Article; 5 use common\modules\blog\models\Article;
  6 +use common\modules\blog\models\ArticleLang;
  7 +use common\modules\blog\models\ArticleMedia;
  8 +use common\modules\blog\models\ArticleToCategory;
5 use yii\data\ActiveDataProvider; 9 use yii\data\ActiveDataProvider;
6 use yii\web\Controller; 10 use yii\web\Controller;
  11 +use yii\web\UploadedFile;
7 12
8 class ArticleController extends Controller 13 class ArticleController extends Controller
9 { 14 {
  15 +
10 public function actionIndex() 16 public function actionIndex()
11 { 17 {
12 $dataProvider = new ActiveDataProvider([ 18 $dataProvider = new ActiveDataProvider([
@@ -20,6 +26,178 @@ class ArticleController extends Controller @@ -20,6 +26,178 @@ class ArticleController extends Controller
20 26
21 public function actionCreate() 27 public function actionCreate()
22 { 28 {
23 - return $this->render('create'); 29 + $article_langs = array();
  30 + $article = new Article();
  31 + $images = array();
  32 + $images['full'] = new ArticleMedia(['scenario' => ArticleMedia::SCENARIO_FULL]);
  33 + $images['preview'] = new ArticleMedia(['scenario' => ArticleMedia::SCENARIO_PREVIEW]);
  34 + $images['additional'] = new ArticleMedia(['scenario' => ArticleMedia::SCENARIO_ADDITIONAL]);
  35 + $article->loadDefaultValues();
  36 + $langs = Language::getActiveLanguages();
  37 + $default_lang = Language::getDefaultLang();
  38 + $isValid = false;
  39 + if(!empty(\Yii::$app->request->post())) {
  40 + $isValid = true;
  41 + $article->load(\Yii::$app->request->post());
  42 + $article->author = \Yii::$app->user->getId();
  43 + $isValid = $article->validate();
  44 + foreach($images as $index => $value) {
  45 + $images[$index]->type = $index;
  46 + if($index == 'additional') {
  47 + $images[$index]->imageFile = UploadedFile::getInstances($images[$index], "[{$index}]imageFile");
  48 + } else {
  49 + $images[$index]->imageFile = UploadedFile::getInstance($images[$index], "[{$index}]imageFile");
  50 + }
  51 + $isValid = $images[$index]->validate(['imageFile']) && $isValid;
  52 + }
  53 + if(empty(\Yii::$app->request->post()['ArticleLang'])) {
  54 + $article_langs[$default_lang->language_id] = new ArticleLang();
  55 + $isValid = ArticleLang::validateMultiple($article_langs) && $isValid;
  56 + } else {
  57 + foreach(\Yii::$app->request->post()['ArticleLang'] as $index => $article_lang) {
  58 + $article_langs[$index] = new ArticleLang();
  59 + }
  60 + ArticleLang::loadMultiple($article_langs, \Yii::$app->request->post());
  61 + $isValid = ArticleLang::validateMultiple($article_langs) && $isValid;
  62 + }
  63 + } else {
  64 + $article_langs[$default_lang->language_id] = new ArticleLang();
  65 + }
  66 + if($isValid) {
  67 + $article->save(false);
  68 + $article_categories = \Yii::$app->request->post('Article')['articleCategoriesArray'];
  69 + if(!empty($article_categories)) {
  70 + foreach($article_categories as $article_category) {
  71 + $articletocategory[$article_category] = new ArticleToCategory();
  72 + $articletocategory[$article_category]->category_id = $article_category;
  73 + $articletocategory[$article_category]->link('article', $article);
  74 + }
  75 + }
  76 + $first = 1;
  77 + foreach($images as $index => $image) {
  78 + $images[$index]->upload($article->id);
  79 + }
  80 + foreach($article_langs as $article_lang) {
  81 + if($first) {
  82 + $article_lang_clone = clone $article_lang;
  83 + $article_lang_clone->lang_id = 0;
  84 + $article_lang_clone->link('article', $article);
  85 + unset($article_lang_clone);
  86 + }
  87 + $article_lang->link('article', $article);
  88 + $first = 0;
  89 + }
  90 + echo "ok";
  91 + //$this->redirect('index');
  92 + } else {
  93 + return $this->render('create', [
  94 + 'article_langs' => $article_langs,
  95 + 'article' => $article,
  96 + 'langs' => $langs,
  97 + 'images' => $images
  98 + ]);
  99 + }
  100 + }
  101 +
  102 + public function actionUpdate($id)
  103 + {
  104 + $article = Article::findOne($id);
  105 + $images = $article->getArticleMedia()->indexBy('type')->all();
  106 + if(!array_key_exists('full', $images)) {
  107 + $images['full'] = new ArticleMedia();
  108 + }
  109 + if(!array_key_exists('preview', $images)) {
  110 + $images['preview'] = new ArticleMedia();
  111 + }
  112 + foreach($images as $index => $image) {
  113 + $images[$index]->scenario = $index;
  114 + }
  115 + $images['additional'] = array(
  116 + 0 => new ArticleMedia(['scenario' => ArticleMedia::SCENARIO_ADDITIONAL])
  117 + );
  118 + $images['additional'] = array_merge($images['additional'], $article->getArticleMedia()->andWhere(['type' => 'additional'])->indexBy('id')->all());
  119 + foreach($images['additional'] as $index => $image) {
  120 + $images['additional'][$index]->scenario = 'additional';
  121 + }
  122 + $article_langs = $article->getArticleLangs()->where(['>=', 'lang_id', '1'])->indexBy('lang_id')->all();
  123 + $langs = Language::getActiveLanguages();
  124 + $default_lang = Language::getDefaultLang();
  125 + $isValid = false;
  126 + if(!empty(\Yii::$app->request->post())) {
  127 + $isValid = true;
  128 + $article->load(\Yii::$app->request->post());
  129 + ArticleToCategory::deleteAll(['article_id' => $article->id]);
  130 + $article_categories = \Yii::$app->request->post('Article')['articleCategoriesArray'];
  131 + if(!empty($article_categories)) {
  132 + foreach($article_categories as $article_category) {
  133 + $articletocategory[$article_category] = new ArticleToCategory();
  134 + $articletocategory[$article_category]->category_id = $article_category;
  135 + $articletocategory[$article_category]->link('article', $article);
  136 + }
  137 + }
  138 + $isValid = $article->validate();
  139 + foreach($images as $index => $value) {
  140 + if($index == 'additional') {
  141 + $images[$index][0]->type = $index;
  142 + $images[$index][0]->imageFile = UploadedFile::getInstances($images[$index][0], "[{$index}]imageFile");
  143 + $isValid = $images[$index][0]->validate(['imageFile']) && $isValid;
  144 + } else {
  145 + $images[$index]->type = $index;
  146 + $images[$index]->imageFile = UploadedFile::getInstance($images[$index], "[{$index}]imageFile");
  147 + $isValid = $images[$index]->validate(['imageFile']) && $isValid;
  148 + }
  149 + }
  150 + if(empty(\Yii::$app->request->post()['ArticleLang'])) {
  151 + $isValid = ArticleLang::validateMultiple($article_langs) && $isValid;
  152 + } else {
  153 + foreach(\Yii::$app->request->post()['ArticleLang'] as $index => $article_lang) {
  154 + if (!array_key_exists($index, $article_langs)) {
  155 + $article_langs[$index] = new ArticleLang();
  156 + $article_langs[$index]->article_id = $article->id;
  157 + }
  158 + }
  159 + ArticleLang::loadMultiple($article_langs, \Yii::$app->request->post());
  160 + $isValid = ArticleLang::validateMultiple($article_langs) && $isValid;
  161 + }
  162 + }
  163 + if($isValid) {
  164 + $article->save(false);
  165 + foreach($images as $index => $image) {
  166 + if($index == 'additional') {
  167 + $images[$index][0]->upload($article->id);
  168 + } else {
  169 + if(!empty($images[$index]->imageFile)) {
  170 + $images[$index]->replace($article->id, true);
  171 + }
  172 + }
  173 + }
  174 + foreach($article_langs as $article_lang) {
  175 + $article_lang->save(false);
  176 + }
  177 + echo "ok";
  178 + //$this->redirect('index');
  179 + } else {
  180 + return $this->render('update', [
  181 + 'article_langs' => $article_langs,
  182 + 'article' => $article,
  183 + 'langs' => $langs,
  184 + 'images' => $images
  185 + ]);
  186 + }
  187 + }
  188 +
  189 + public function actionDelete($id)
  190 + {
  191 + $this->findModel($id)->delete();
  192 + return $this->redirect(['index']);
  193 + }
  194 +
  195 + protected function findModel($id)
  196 + {
  197 + if (($model = Article::findOne($id)) !== null) {
  198 + return $model;
  199 + } else {
  200 + throw new NotFoundHttpException('The requested page does not exist.');
  201 + }
24 } 202 }
25 } 203 }
common/modules/blog/controllers/CategoryController.php
@@ -5,12 +5,28 @@ use common\models\Language; @@ -5,12 +5,28 @@ use common\models\Language;
5 use common\modules\blog\models\Article; 5 use common\modules\blog\models\Article;
6 use common\modules\blog\models\ArticleCategory; 6 use common\modules\blog\models\ArticleCategory;
7 use common\modules\blog\models\ArticleCategoryLang; 7 use common\modules\blog\models\ArticleCategoryLang;
  8 +use common\modules\blog\models\ArticleCategoryMedia;
8 use common\modules\blog\models\ArticleLang; 9 use common\modules\blog\models\ArticleLang;
9 use yii\data\ActiveDataProvider; 10 use yii\data\ActiveDataProvider;
  11 +use yii\filters\VerbFilter;
10 use yii\web\Controller; 12 use yii\web\Controller;
  13 +use yii\web\NotFoundHttpException;
  14 +use yii\web\UploadedFile;
11 15
12 class CategoryController extends Controller 16 class CategoryController extends Controller
13 { 17 {
  18 + public function behaviors()
  19 + {
  20 + return [
  21 + 'verbs' => [
  22 + 'class' => VerbFilter::className(),
  23 + 'actions' => [
  24 + 'delete' => ['post']
  25 + ]
  26 + ]
  27 + ];
  28 + }
  29 +
14 public function actionIndex() 30 public function actionIndex()
15 { 31 {
16 $dataProvider = new ActiveDataProvider([ 32 $dataProvider = new ActiveDataProvider([
@@ -26,9 +42,23 @@ class CategoryController extends Controller @@ -26,9 +42,23 @@ class CategoryController extends Controller
26 { 42 {
27 $category_langs = array(); 43 $category_langs = array();
28 $category = new ArticleCategory(); 44 $category = new ArticleCategory();
  45 + $images = array();
  46 + $images['full'] = new ArticleCategoryMedia(['scenario' => ArticleCategoryMedia::SCENARIO_FULL]);
  47 + $images['preview'] = new ArticleCategoryMedia(['scenario' => ArticleCategoryMedia::SCENARIO_PREVIEW]);
  48 + $images['additional'] = new ArticleCategoryMedia(['scenario' => ArticleCategoryMedia::SCENARIO_ADDITIONAL]);
  49 + $category->loadDefaultValues();
29 $langs = Language::getActiveLanguages(); 50 $langs = Language::getActiveLanguages();
30 $default_lang = Language::getDefaultLang(); 51 $default_lang = Language::getDefaultLang();
31 $isValid = false; 52 $isValid = false;
  53 + foreach($images as $index => $value) {
  54 + $images[$index]->type = $index;
  55 + if($index == 'additional') {
  56 + $images[$index]->imageFile = UploadedFile::getInstances($images[$index], "[{$index}]imageFile");
  57 + } else {
  58 + $images[$index]->imageFile = UploadedFile::getInstance($images[$index], "[{$index}]imageFile");
  59 + }
  60 + $isValid = $images[$index]->validate(['imageFile']) && $isValid;
  61 + }
32 if(!empty(\Yii::$app->request->post())) { 62 if(!empty(\Yii::$app->request->post())) {
33 $isValid = true; 63 $isValid = true;
34 $category->load(\Yii::$app->request->post()); 64 $category->load(\Yii::$app->request->post());
@@ -48,16 +78,122 @@ class CategoryController extends Controller @@ -48,16 +78,122 @@ class CategoryController extends Controller
48 } 78 }
49 if($isValid) { 79 if($isValid) {
50 $category->save(false); 80 $category->save(false);
  81 + $first = 1;
  82 + foreach($images as $index => $image) {
  83 + $images[$index]->upload($category->id);
  84 + }
51 foreach($category_langs as $category_lang) { 85 foreach($category_langs as $category_lang) {
  86 + if($first) {
  87 + $category_lang_clone = clone $category_lang;
  88 + $category_lang_clone->lang_id = 0;
  89 + $category_lang_clone->link('category', $category);
  90 + unset($category_lang_clone);
  91 + }
52 $category_lang->link('category', $category); 92 $category_lang->link('category', $category);
  93 + $first = 0;
53 } 94 }
54 echo "ok"; 95 echo "ok";
  96 + //$this->redirect('index');
55 } else { 97 } else {
56 return $this->render('create', [ 98 return $this->render('create', [
57 'category_langs' => $category_langs, 99 'category_langs' => $category_langs,
58 'category' => $category, 100 'category' => $category,
59 - 'langs' => $langs 101 + 'langs' => $langs,
  102 + 'images' => $images
60 ]); 103 ]);
61 } 104 }
62 } 105 }
  106 +
  107 + public function actionUpdate($id)
  108 + {
  109 + $category = ArticleCategory::findOne($id);
  110 + $images = $category->getArticleCategoryMedia()->indexBy('type')->all();
  111 + if(!array_key_exists('full', $images)) {
  112 + $images['full'] = new ArticleCategoryMedia();
  113 + }
  114 + if(!array_key_exists('preview', $images)) {
  115 + $images['preview'] = new ArticleCategoryMedia();
  116 + }
  117 + foreach($images as $index => $image) {
  118 + $images[$index]->scenario = $index;
  119 + }
  120 + $images['additional'] = array(
  121 + 0 => new ArticleCategoryMedia(['scenario' => ArticleCategoryMedia::SCENARIO_ADDITIONAL])
  122 + );
  123 + $images['additional'] = array_merge($images['additional'], $category->getArticleCategoryMedia()->andWhere(['type' => 'additional'])->indexBy('id')->all());
  124 + foreach($images['additional'] as $index => $image) {
  125 + $images['additional'][$index]->scenario = 'additional';
  126 + }
  127 + $category_langs = $category->getArticleCategoryLangs()->where(['>=', 'lang_id', '1'])->indexBy('lang_id')->all();
  128 + $langs = Language::getActiveLanguages();
  129 + $default_lang = Language::getDefaultLang();
  130 + $isValid = false;
  131 + if(!empty(\Yii::$app->request->post())) {
  132 + $isValid = true;
  133 + $category->load(\Yii::$app->request->post());
  134 + $isValid = $category->validate();
  135 + foreach($images as $index => $value) {
  136 + if($index == 'additional') {
  137 + $images[$index][0]->type = $index;
  138 + $images[$index][0]->imageFile = UploadedFile::getInstances($images[$index][0], "[{$index}]imageFile");
  139 + $isValid = $images[$index][0]->validate(['imageFile']) && $isValid;
  140 + } else {
  141 + $images[$index]->type = $index;
  142 + $images[$index]->imageFile = UploadedFile::getInstance($images[$index], "[{$index}]imageFile");
  143 + $isValid = $images[$index]->validate(['imageFile']) && $isValid;
  144 + }
  145 + }
  146 + if(empty(\Yii::$app->request->post()['ArticleCategoryLang'])) {
  147 + $isValid = ArticleCategoryLang::validateMultiple($category_langs) && $isValid;
  148 + } else {
  149 + foreach(\Yii::$app->request->post()['ArticleCategoryLang'] as $index => $category_lang) {
  150 + if(!array_key_exists($index, $category_langs)) {
  151 + $category_langs[$index] = new ArticleCategoryLang();
  152 + $category_langs[$index]->category_id = $category->id;
  153 + }
  154 + }
  155 + ArticleCategoryLang::loadMultiple($category_langs, \Yii::$app->request->post());
  156 + $isValid = ArticleCategoryLang::validateMultiple($category_langs) && $isValid;
  157 + }
  158 + }
  159 + if($isValid) {
  160 + $category->save(false);
  161 + foreach($images as $index => $image) {
  162 + if($index == 'additional') {
  163 + $images[$index][0]->upload($category->id);
  164 + } else {
  165 + if(!empty($images[$index]->imageFile)) {
  166 + $images[$index]->replace($category->id, true);
  167 + }
  168 + }
  169 + }
  170 + foreach($category_langs as $category_lang) {
  171 + $category_lang->save(false);
  172 + }
  173 + echo "ok";
  174 + //$this->redirect('index');
  175 + } else {
  176 + return $this->render('update', [
  177 + 'category_langs' => $category_langs,
  178 + 'category' => $category,
  179 + 'langs' => $langs,
  180 + 'images' => $images
  181 + ]);
  182 + }
  183 + }
  184 +
  185 + public function actionDelete($id)
  186 + {
  187 + $this->findModel($id)->delete();
  188 + return $this->redirect(['index']);
  189 + }
  190 +
  191 + protected function findModel($id)
  192 + {
  193 + if (($model = ArticleCategory::findOne($id)) !== null) {
  194 + return $model;
  195 + } else {
  196 + throw new NotFoundHttpException('The requested page does not exist.');
  197 + }
  198 + }
63 } 199 }
common/modules/blog/controllers/MediaController.php 0 → 100644
  1 +<?php
  2 +namespace common\modules\blog\controllers;
  3 +
  4 +use common\models\Media;
  5 +use common\modules\blog\models\Article;
  6 +use yii\web\Controller;
  7 +use yii\web\UploadedFile;
  8 +
  9 +class MediaController extends Controller
  10 +{
  11 + public function actionIndex()
  12 + {
  13 + $model = new Media();
  14 + if(\Yii::$app->request->isPost) {
  15 + $model->imageFile = UploadedFile::getInstance($model, 'imageFile');
  16 + if($model->upload()) {
  17 + return true;
  18 + } else {
  19 + return false;
  20 + }
  21 + }
  22 + return $this->render('index', ['model' => $model]);
  23 + }
  24 +
  25 + public function actionCreate()
  26 + {
  27 +
  28 + }
  29 +
  30 + public function actionUpdate($id)
  31 + {
  32 +
  33 + }
  34 +
  35 + public function actionDelete($id)
  36 + {
  37 + $model = Media::findOne($id);
  38 + return $model->delete();
  39 + }
  40 +
  41 + protected function findModel($id)
  42 + {
  43 +
  44 + }
  45 +}
common/modules/blog/views/ajax/_article_form.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\bootstrap\ActiveField;
  4 +use mihaildev\ckeditor\CKEditor;
  5 +
  6 +$form = \yii\bootstrap\ActiveForm::begin();
  7 +?>
  8 +<div role="" class="tab-pane active ajax-loaded" id="lang-<?=$model->language_id?>">
  9 +
  10 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]lang_id"]))->label(false)->hiddenInput(['value' => $model->language_id]) ?>
  11 +
  12 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]text", 'form' => $form]))->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ]]); ?>
  13 +
  14 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]preview", 'form' => $form]))->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ]]); ?>
  15 +
  16 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]seo_url"]))->textInput() ?>
  17 +
  18 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]name"]))->textInput() ?>
  19 +
  20 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]meta_title"]))->textInput() ?>
  21 +
  22 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]meta_descr"]))->textarea() ?>
  23 +
  24 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]meta_keywords"]))->textInput() ?>
  25 +
  26 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]h1_tag"]))->textInput() ?>
  27 +
  28 + <?= (new ActiveField(['model' => $article_lang, 'attribute' => "[$model->language_id]tags"]))->textInput() ?>
  29 +
  30 +</div>
  31 +<?php
  32 +$form->end();
  33 +?>
common/modules/blog/views/ajax/_category_form.php
1 <?php 1 <?php
2 2
3 -use yii\bootstrap; 3 +use yii\bootstrap\ActiveField;
  4 +use mihaildev\ckeditor\CKEditor;
4 5
  6 +$form = \yii\bootstrap\ActiveForm::begin();
5 ?> 7 ?>
6 -<div role="" class="tab-pane active" id="lang-<?=$model->language_id?>"> 8 +<div role="" class="tab-pane active ajax-loaded" id="lang-<?=$model->language_id?>">
7 9
8 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]lang_id"]))->label(false)->hiddenInput(['value' => $model->language_id]) ?> 10 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]lang_id"]))->label(false)->hiddenInput(['value' => $model->language_id]) ?>
9 11
10 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]text"]))->textarea() ?> 12 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]text", 'form' => $form]))->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ]]); ?>
11 13
12 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]preview"]))->textarea() ?> 14 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]preview", 'form' => $form]))->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ]]); ?>
13 15
14 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]seo_url"]))->textInput() ?> 16 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]seo_url"]))->textInput() ?>
15 17
16 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]name"]))->textInput() ?> 18 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]name"]))->textInput() ?>
17 19
18 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_title"]))->textInput() ?> 20 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_title"]))->textInput() ?>
19 21
20 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_descr"]))->textarea() ?> 22 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_descr"]))->textarea() ?>
21 23
22 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_keywords"]))->textInput() ?> 24 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]meta_keywords"]))->textInput() ?>
23 25
24 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]h1_tag"]))->textInput() ?> 26 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]h1_tag"]))->textInput() ?>
25 27
26 - <?= (new bootstrap\ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]tags"]))->textInput() ?> 28 + <?= (new ActiveField(['model' => $category_lang, 'attribute' => "[$model->language_id]tags"]))->textInput() ?>
27 29
28 </div> 30 </div>
  31 +<?php
  32 +$form->end();
  33 +?>
common/modules/blog/views/article/_form.php 0 → 100644
  1 +<?php
  2 +use common\modules\blog\models\ArticleCategory;
  3 +use yii\bootstrap\ActiveForm;
  4 +use common\modules\blog\models\Article;
  5 +use yii\bootstrap\Html;
  6 +use mihaildev\ckeditor\CKEditor;
  7 +use yii\helpers\Json;
  8 +use yii\helpers\Url;
  9 +use yii\widgets\Pjax;
  10 +
  11 +$def_lang = array_keys($langs)[0];
  12 +$uploaddir = \Yii::getAlias('@saveImageDir');
  13 +?>
  14 +<div class="article-form">
  15 +
  16 + <?php $form = \yii\bootstrap\ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
  17 +
  18 + <?= $form->field($article, 'code')->hint(Yii::t('app', 'Insensitive latin non-space'))->textInput() ?>
  19 +
  20 + <?= $form->field($article, 'tags')->hint(Yii::t('app', 'Comma-separated'))->textInput() ?>
  21 +
  22 + <?= $form->field($article, 'sort')->input('number') ?>
  23 +
  24 + <?= $form->field($article, 'parent_id')
  25 + ->dropDownList(Article::findArticleDropdown($article->id), ['prompt' => Yii::t('app', 'Select parent')]) ?>
  26 +
  27 + <?= $form->field($article, 'articleCategoriesArray')
  28 + ->dropDownList(ArticleCategory::findArticleCategoryDropdown(NULL), ['multiple' => 'multiple'])->label(\Yii::t('app', 'Article Categories Array')); ?>
  29 +
  30 + <?= $form->field($article, 'active')->checkbox() ?>
  31 +
  32 + <ul class="nav nav-tabs" id="image-tabs" role="tablist">
  33 + <?php
  34 + $first = 1;
  35 + foreach($images as $index => $image) {
  36 + ?>
  37 + <li role="image_inputs" class="<?php if($first) { echo 'active'; }?>" data-type="<?=$index?>"><a href="#image-<?=$index?>" aria-controls="image-<?=$index?>" role="tab" data-toggle="tab"><span><?= \Yii::t('app', $index)?></span></a></li>
  38 + <?php
  39 + $first = 0;
  40 + }
  41 + ?>
  42 + </ul>
  43 + <div class="tab-content image-tab-content">
  44 + <?php
  45 + $first = 1;
  46 + foreach($images as $index => $image) {
  47 + ?>
  48 + <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="image-<?=$index?>">
  49 + <?php if($index == 'additional') {
  50 + echo $form->field(is_array($image)?$images[$index][0]:$images[$index], "[{$index}]imageFile[]")->fileInput(['multiple' => 'multiple', 'class' => 'image_inputs_field']);
  51 + if(is_array($image) && count($image) > 1) {
  52 + foreach($image as $oneindex => $oneimage) {
  53 + if($oneindex) {
  54 + ?>
  55 + <div class="additional_image_container">
  56 + <img src='/images/upload/<?= $oneimage->media->hash ?>/original.<?= $oneimage->media->extension ?>' width='100'>
  57 + <a
  58 + href="<?= Url::to(['ajax/remove-image']) ?>"
  59 + class="remove_image glyphicon glyphicon-remove-circle"
  60 + data-params='<?= Json::encode(['article_media_id' => $oneimage->id, 'remove_media' => true]) ?>',
  61 + ></a>
  62 + </div>
  63 + <?php
  64 + }
  65 + }
  66 + }
  67 + } else {
  68 + echo $form->field($images[$index], "[{$index}]imageFile")->fileInput(['class' => 'image_inputs_field']);
  69 + if(!empty($image->id)) {
  70 + echo "<img src='/images/upload/{$image->media->hash}/original.{$image->media->extension}' width='100' class='image_inputs_prev'>";
  71 + }
  72 + }
  73 + ?>
  74 + </div>
  75 + <?php
  76 + $first = 0;
  77 + }
  78 + ?>
  79 + </div>
  80 +
  81 + <hr>
  82 +
  83 + <div class="dropdown pull-right">
  84 + <button class="btn btn-default dropdown-toggle" type="button" id="dropdownLang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
  85 + <?= Yii::t('app', 'Add language') ?>
  86 + <span class="caret"></span>
  87 + </button>
  88 + <ul class="dropdown-menu f32" id="lang-dropdown" aria-labelledby="dropdownMenu1">
  89 + <?php foreach($langs as $index => $lang) {
  90 + if(in_array($index, array_keys($article_langs))) continue;
  91 + ?>
  92 + <li><a href="#lang-tabs" data-lang="<?=$lang->language_id?>"><span class="flag <?=$lang->country_code?>"></span></a></li>
  93 + <?php } ?>
  94 + </ul>
  95 + </div>
  96 + <ul class="nav nav-tabs f32" id="lang-tabs" role="tablist">
  97 + <?php
  98 + $first = 1;
  99 + foreach($article_langs as $index => $article_lang) {
  100 + ?>
  101 + <li role="lang_inputs" class="<?php if($first) { echo 'active'; }?>" data-lang="<?=$index?>"><a href="#lang-<?=$index?>" aria-controls="lang-<?=$index?>" role="tab" data-toggle="tab"><span class="flag <?=$langs[$index]->country_code?>"></span></a></li>
  102 + <?php
  103 + $first = 0;
  104 + }
  105 + ?>
  106 + </ul>
  107 + <div class="tab-content lang-tab-content">
  108 + <?php
  109 + $first = 1;
  110 + foreach($article_langs as $index => $article_lang) {
  111 + ?>
  112 + <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="lang-<?=$index?>">
  113 + <?= $form->field($article_langs[$index], "[$index]lang_id")->label(false)->hiddenInput(['value' => $index]) ?>
  114 +
  115 + <?= $form->field($article_langs[$index], "[$index]text")->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?>
  116 +
  117 + <?= $form->field($article_langs[$index], "[$index]preview")->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?>
  118 +
  119 + <?= $form->field($article_langs[$index], "[$index]seo_url")->textInput() ?>
  120 +
  121 + <?= $form->field($article_langs[$index], "[$index]name")->textInput() ?>
  122 +
  123 + <?= $form->field($article_langs[$index], "[$index]meta_title")->textInput() ?>
  124 +
  125 + <?= $form->field($article_langs[$index], "[$index]meta_descr")->textarea(); ?>
  126 +
  127 + <?= $form->field($article_langs[$index], "[$index]meta_keywords")->textInput() ?>
  128 +
  129 + <?= $form->field($article_langs[$index], "[$index]h1_tag")->textInput() ?>
  130 +
  131 + <?= $form->field($article_langs[$index], "[$index]tags")->textInput() ?>
  132 +
  133 + </div>
  134 + <?php
  135 + $first = 0;
  136 + }
  137 + ?>
  138 + </div>
  139 +
  140 + <div class="form-group">
  141 + <?= Html::submitButton($article->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $article->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
  142 + </div>
  143 +
  144 + <?php ActiveForm::end(); ?>
  145 +
  146 +</div>
  147 +<script>
  148 + var confirm_message = '<?= \Yii::t('app', 'Remove image?') ?>';
  149 +</script>
0 \ No newline at end of file 150 \ No newline at end of file
common/modules/blog/views/article/create.php
1 <?php 1 <?php
  2 +use yii\helpers\Html;
  3 +
  4 +$this->title = Yii::t('app', 'Article create');
  5 +$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Articles'), 'url' => ['index']];
  6 +$this->params['breadcrumbs'][] = $this->title;
  7 +?>
  8 +<div class="article-create">
  9 +
  10 + <h1><?= Html::encode($this->title) ?></h1>
  11 +
  12 + <?= $this->render('_form', [
  13 + 'article_langs' => $article_langs,
  14 + 'article' => $article,
  15 + 'langs' => $langs,
  16 + 'images' => $images
  17 + ]) ?>
  18 +
  19 +</div>
common/modules/blog/views/article/index.php
1 <?php 1 <?php
  2 +use yii\grid\ActionColumn;
  3 +use yii\grid\Column;
2 use yii\grid\GridView; 4 use yii\grid\GridView;
3 use common\modules\blog\models\Article; 5 use common\modules\blog\models\Article;
4 use common\models\Language; 6 use common\models\Language;
  7 +
5 echo GridView::widget([ 8 echo GridView::widget([
6 'dataProvider' => $dataProvider, 9 'dataProvider' => $dataProvider,
  10 + 'columns' => [
  11 + 'id',
  12 + 'code',
  13 + 'create_at',
  14 + [
  15 + 'value' => function($data) {
  16 + return $data->author0->firstname.' '.$data->author0->lastname;
  17 + },
  18 + 'header' => Yii::t('app', 'Author')
  19 + ],
  20 + [
  21 + 'class' => Column::className(),
  22 + 'header' => Yii::t('app', 'Name'),
  23 + 'content' => function($model, $key, $index, $column) {
  24 + return $model->getArticleLangs()->where(['lang_id' => Language::getDefaultLang()->language_id])->one()->name;
  25 + }
  26 + ],
  27 + [
  28 + 'class' => ActionColumn::className(),
  29 + 'template' => '{update} {delete}'
  30 + ]
  31 + ]
7 ]); 32 ]);
8 \ No newline at end of file 33 \ No newline at end of file
common/modules/blog/views/article/update.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +
  4 +$this->title = Yii::t('app', 'Article update');
  5 +$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Articles'), 'url' => ['index']];
  6 +$this->params['breadcrumbs'][] = $this->title;
  7 +?>
  8 +<div class="article-create">
  9 +
  10 + <h1><?= Html::encode($this->title) ?></h1>
  11 + <?= $this->render('_form', [
  12 + 'article_langs' => $article_langs,
  13 + 'article' => $article,
  14 + 'langs' => $langs,
  15 + 'images' => $images
  16 + ]) ?>
  17 +
  18 +</div>
common/modules/blog/views/category/_form.php
@@ -2,23 +2,79 @@ @@ -2,23 +2,79 @@
2 use yii\bootstrap\ActiveForm; 2 use yii\bootstrap\ActiveForm;
3 use common\modules\blog\models\ArticleCategory; 3 use common\modules\blog\models\ArticleCategory;
4 use yii\bootstrap\Html; 4 use yii\bootstrap\Html;
  5 +use mihaildev\ckeditor\CKEditor;
  6 +use yii\helpers\Json;
  7 +use yii\helpers\Url;
5 8
6 $def_lang = array_keys($langs)[0]; 9 $def_lang = array_keys($langs)[0];
7 - 10 +$uploaddir = \Yii::getAlias('@saveImageDir');
8 ?> 11 ?>
9 <div class="category-form"> 12 <div class="category-form">
10 13
11 - <?php $form = \yii\bootstrap\ActiveForm::begin(); ?> 14 + <?php $form = \yii\bootstrap\ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
12 15
13 <?= $form->field($category, 'code')->hint(Yii::t('app', 'Insensitive latin non-space'))->textInput() ?> 16 <?= $form->field($category, 'code')->hint(Yii::t('app', 'Insensitive latin non-space'))->textInput() ?>
14 17
15 <?= $form->field($category, 'tags')->hint(Yii::t('app', 'Comma-separated'))->textInput() ?> 18 <?= $form->field($category, 'tags')->hint(Yii::t('app', 'Comma-separated'))->textInput() ?>
16 19
  20 + <?= $form->field($category, 'sort')->input('number') ?>
  21 +
17 <?= $form->field($category, 'parent_id') 22 <?= $form->field($category, 'parent_id')
18 - ->dropDownList(ArticleCategory::findArticleCategoryDropdown(), ['prompt' => Yii::t('app', 'Select parent')]) ?> 23 + ->dropDownList(ArticleCategory::findArticleCategoryDropdown($category->id), ['prompt' => Yii::t('app', 'Select parent')]) ?>
19 24
20 <?= $form->field($category, 'active')->checkbox() ?> 25 <?= $form->field($category, 'active')->checkbox() ?>
21 26
  27 + <ul class="nav nav-tabs" id="image-tabs" role="tablist">
  28 + <?php
  29 + $first = 1;
  30 + foreach($images as $index => $image) {
  31 + ?>
  32 + <li role="image_inputs" class="<?php if($first) { echo 'active'; }?>" data-type="<?=$index?>"><a href="#image-<?=$index?>" aria-controls="image-<?=$index?>" role="tab" data-toggle="tab"><span><?= \Yii::t('app', $index)?></span></a></li>
  33 + <?php
  34 + $first = 0;
  35 + }
  36 + ?>
  37 + </ul>
  38 + <div class="tab-content image-tab-content">
  39 + <?php
  40 + $first = 1;
  41 + foreach($images as $index => $image) {
  42 + ?>
  43 + <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="image-<?=$index?>">
  44 + <?php if($index == 'additional') {
  45 + echo $form->field(is_array($image)?$images[$index][0]:$images[$index], "[{$index}]imageFile[]")->fileInput(['multiple' => 'multiple', 'class' => 'image_inputs_field']);
  46 + if(is_array($image) && count($image) > 1) {
  47 + foreach($image as $oneindex => $oneimage) {
  48 + if($oneindex) {
  49 + ?>
  50 + <div class="additional_image_container">
  51 + <img src='/images/upload/<?= $oneimage->media->hash ?>/original.<?= $oneimage->media->extension ?>' width='100'>
  52 + <a
  53 + href="<?= Url::to(['ajax/remove-image-category']) ?>"
  54 + class="remove_image glyphicon glyphicon-remove-circle"
  55 + data-params='<?= Json::encode(['category_media_id' => $oneimage->id, 'remove_media' => true]) ?>',
  56 + ></a>
  57 + </div>
  58 + <?php
  59 + }
  60 + }
  61 + }
  62 + } else {
  63 + echo $form->field($images[$index], "[{$index}]imageFile")->fileInput(['class' => 'image_inputs_field']);
  64 + if(!empty($image->id)) {
  65 + echo "<img src='/images/upload/{$image->media->hash}/original.{$image->media->extension}' width='100' class='image_inputs_prev'>";
  66 + }
  67 + }
  68 + ?>
  69 + </div>
  70 + <?php
  71 + $first = 0;
  72 + }
  73 + ?>
  74 + </div>
  75 +
  76 + <hr>
  77 +
22 <div class="dropdown pull-right"> 78 <div class="dropdown pull-right">
23 <button class="btn btn-default dropdown-toggle" type="button" id="dropdownLang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> 79 <button class="btn btn-default dropdown-toggle" type="button" id="dropdownLang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
24 <?= Yii::t('app', 'Add language') ?> 80 <?= Yii::t('app', 'Add language') ?>
@@ -43,7 +99,7 @@ $def_lang = array_keys($langs)[0]; @@ -43,7 +99,7 @@ $def_lang = array_keys($langs)[0];
43 } 99 }
44 ?> 100 ?>
45 </ul> 101 </ul>
46 - <div class="tab-content"> 102 + <div class="tab-content lang-tab-content">
47 <?php 103 <?php
48 $first = 1; 104 $first = 1;
49 foreach($category_langs as $index => $category_lang) { 105 foreach($category_langs as $index => $category_lang) {
@@ -51,9 +107,9 @@ $def_lang = array_keys($langs)[0]; @@ -51,9 +107,9 @@ $def_lang = array_keys($langs)[0];
51 <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="lang-<?=$index?>"> 107 <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="lang-<?=$index?>">
52 <?= $form->field($category_langs[$index], "[$index]lang_id")->label(false)->hiddenInput(['value' => $index]) ?> 108 <?= $form->field($category_langs[$index], "[$index]lang_id")->label(false)->hiddenInput(['value' => $index]) ?>
53 109
54 - <?= $form->field($category_langs[$index], "[$index]text")->textarea() ?> 110 + <?= $form->field($category_langs[$index], "[$index]text")->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?>
55 111
56 - <?= $form->field($category_langs[$index], "[$index]preview")->textarea() ?> 112 + <?= $form->field($category_langs[$index], "[$index]preview")->widget(CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?>
57 113
58 <?= $form->field($category_langs[$index], "[$index]seo_url")->textInput() ?> 114 <?= $form->field($category_langs[$index], "[$index]seo_url")->textInput() ?>
59 115
@@ -61,7 +117,7 @@ $def_lang = array_keys($langs)[0]; @@ -61,7 +117,7 @@ $def_lang = array_keys($langs)[0];
61 117
62 <?= $form->field($category_langs[$index], "[$index]meta_title")->textInput() ?> 118 <?= $form->field($category_langs[$index], "[$index]meta_title")->textInput() ?>
63 119
64 - <?= $form->field($category_langs[$index], "[$index]meta_descr")->textarea() ?> 120 + <?= $form->field($category_langs[$index], "[$index]meta_descr")->textarea(); ?>
65 121
66 <?= $form->field($category_langs[$index], "[$index]meta_keywords")->textInput() ?> 122 <?= $form->field($category_langs[$index], "[$index]meta_keywords")->textInput() ?>
67 123
@@ -84,42 +140,5 @@ $def_lang = array_keys($langs)[0]; @@ -84,42 +140,5 @@ $def_lang = array_keys($langs)[0];
84 140
85 </div> 141 </div>
86 <script> 142 <script>
87 - $(function() {  
88 - if($('#lang-tabs li').length > 1) {  
89 - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')  
90 - }  
91 - $(document).on('click', '#lang-dropdown li a[data-lang]', function() {  
92 - var lang = $(this).data('lang');  
93 - var flag = $(this).find('span').first().clone();  
94 - $('#lang-tabs li').removeClass('active');  
95 - console.log(flag);  
96 - $('#lang-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#lang-'+lang+'" aria-controls="lang-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>');  
97 - $('.tab-pane.active').removeClass('active');  
98 - $.get('/blog/ajax/category-form?', { lang_id: lang }, function(data) {  
99 - $('.tab-content').append(data);  
100 - });  
101 - $(this).parent().remove();  
102 - if(!$('#lang-dropdown li').length) {  
103 - $('#dropdownLang').addClass('disabled');  
104 - }  
105 - if($('#lang-tabs li').length > 1) {  
106 - $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')  
107 - }  
108 - });  
109 - $(document).on('click', '.remove-lang', function() {  
110 - var lang = $(this).parent().data('lang');  
111 - var flag = $(this).parent().find('span.flag').first().clone();  
112 - $('#lang-'+lang).remove();  
113 - $('#lang-dropdown').append('<li><a href="#lang-tabs" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>');  
114 - $('#dropdownLang').removeClass('disabled');  
115 - $(this).parent().remove();  
116 - if($('#lang-tabs li').length <= 1) {  
117 - $('#lang-tabs li').find('.remove-lang').remove();  
118 - }  
119 - if(!$('#lang-tabs>li.active').length) {  
120 - $('#lang-tabs>li').first().find('a').tab('show');  
121 - }  
122 - });  
123 -  
124 - }); 143 + var confirm_message = '<?= \Yii::t('app', 'Remove image?') ?>';
125 </script> 144 </script>
126 \ No newline at end of file 145 \ No newline at end of file
common/modules/blog/views/category/create.php
1 <?php 1 <?php
2 use yii\helpers\Html; 2 use yii\helpers\Html;
3 3
4 -$this->title = Yii::t('app', 'Create category'); 4 +$this->title = Yii::t('app', 'Category create');
5 $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Categories'), 'url' => ['index']]; 5 $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Categories'), 'url' => ['index']];
6 $this->params['breadcrumbs'][] = $this->title; 6 $this->params['breadcrumbs'][] = $this->title;
7 ?> 7 ?>
@@ -12,12 +12,8 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $this-&gt;title; @@ -12,12 +12,8 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $this-&gt;title;
12 <?= $this->render('_form', [ 12 <?= $this->render('_form', [
13 'category_langs' => $category_langs, 13 'category_langs' => $category_langs,
14 'category' => $category, 14 'category' => $category,
15 - 'langs' => $langs 15 + 'langs' => $langs,
  16 + 'images' => $images
16 ]) ?> 17 ]) ?>
17 18
18 </div> 19 </div>
19 -<script>  
20 - $(function() {  
21 -  
22 - });  
23 -</script>  
common/modules/blog/views/category/index.php
1 <?php 1 <?php
  2 +use yii\grid\ActionColumn;
  3 +use yii\grid\Column;
2 use yii\grid\GridView; 4 use yii\grid\GridView;
3 use common\modules\blog\models\Article; 5 use common\modules\blog\models\Article;
4 use common\models\Language; 6 use common\models\Language;
5 echo GridView::widget([ 7 echo GridView::widget([
6 'dataProvider' => $dataProvider, 8 'dataProvider' => $dataProvider,
  9 + 'columns' => [
  10 + 'id',
  11 + 'code',
  12 + 'created_at',
  13 + 'updated_at',
  14 + [
  15 + 'class' => Column::className(),
  16 + 'header' => Yii::t('app', 'Name'),
  17 + 'content' => function($model, $key, $index, $column) {
  18 + return $model->getArticleCategoryLangs()->where(['lang_id' => Language::getDefaultLang()->language_id])->one()->name;
  19 + }
  20 + ],
  21 + [
  22 + 'class' => ActionColumn::className(),
  23 + 'template' => '{update} {delete}'
  24 + ]
  25 + ]
7 ]); 26 ]);
8 \ No newline at end of file 27 \ No newline at end of file
common/modules/blog/views/category/update.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +
  4 +$this->title = Yii::t('app', 'Update category');
  5 +$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Categories'), 'url' => ['index']];
  6 +$this->params['breadcrumbs'][] = $this->title;
  7 +?>
  8 +<div class="category-create">
  9 +
  10 + <h1><?= Html::encode($this->title) ?></h1>
  11 + <?= $this->render('_form', [
  12 + 'category_langs' => $category_langs,
  13 + 'category' => $category,
  14 + 'langs' => $langs,
  15 + 'images' => $images
  16 + ]) ?>
  17 +
  18 +</div>
common/modules/blog/views/media/index.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\bootstrap\ActiveForm;
  4 +use yii\bootstrap\Html;
  5 +
  6 +$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
  7 +
  8 +echo $form->field($model, 'imageFile')->fileInput(['multiple' => 'multiple']);
  9 +
  10 +?>
  11 + <img id="blah" src="#" alt="your image">
  12 +<div class="form-group">
  13 + <?= Html::submitButton(Yii::t('app', 'Create'), ['class' => 'btn btn-success']) ?>
  14 +</div>
  15 +<?php
  16 +ActiveForm::end();
  17 +?>
  18 +<script>
  19 + function readURL(input) {
  20 + if (input.files && input.files[1]) {
  21 + var reader = new FileReader();
  22 +
  23 + reader.onload = function (e) {
  24 + $('#blah')
  25 + .attr('src', e.target.result)
  26 + .width(150);
  27 + };
  28 +
  29 + reader.readAsDataURL(input.files[1]);
  30 + }
  31 + }
  32 + $(function() {
  33 + $(document).on('change', 'input[type=file]', function() {
  34 + readURL(this);
  35 + });
  36 + });
  37 +</script>
common/translation/ru/app.php
@@ -24,4 +24,38 @@ return [ @@ -24,4 +24,38 @@ return [
24 'message' => 'Сообщение', 24 'message' => 'Сообщение',
25 'Feedback' => 'Обратная связь', 25 'Feedback' => 'Обратная связь',
26 'Pages' => 'Страницы', 26 'Pages' => 'Страницы',
  27 + 'Articles' => 'Статьи',
  28 + 'Article update' => 'Редактирование статьи',
  29 + 'Code' => 'Идентификатор',
  30 + 'Tags' => 'Тэги',
  31 + 'Sort' => 'Сортировка',
  32 + 'Parent ID' => 'Родительская запись',
  33 + 'Article Categories Array' => 'Родительские категории',
  34 + 'Active' => 'Активность',
  35 + 'full' => 'Детальное изображение',
  36 + 'preview' => 'Миниатюрное изображение',
  37 + 'additional' => 'Дополнительные изображения',
  38 + 'Image File' => 'Изображение',
  39 + 'Text' => 'Текст записи детально',
  40 + 'Preview' => 'Текст записи кратко',
  41 + 'Seo Url' => 'Seo Url',
  42 + 'Name' => 'Название',
  43 + 'Meta Title' => 'Meta Title',
  44 + 'Meta Descr' => 'Meta Description',
  45 + 'Meta Keywords' => 'Meta Keywords',
  46 + 'H1 Tag' => 'H1 тэг',
  47 + 'Create At' => 'Дата создания',
  48 + 'Update At' => 'Дата изменения',
  49 + 'Author' => 'Автор',
  50 + 'Created At' => 'Дата создания',
  51 + 'Updated At' => 'Дата изменения',
  52 + 'Add language' => 'Добавить язык',
  53 + 'Categories' => 'Категории',
  54 + 'Category create' => 'Создание категории',
  55 + 'Category update' => 'Редактирование категории',
  56 + 'Article create' => 'Создание статьи',
  57 + 'Update category' => 'Редактирование категории',
  58 + 'Select parent' => 'Выберать родителя',
  59 + 'Blog' => 'Блог',
  60 + 'Static pages' => 'Статические страницы',
27 ]; 61 ];
28 \ No newline at end of file 62 \ No newline at end of file
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 "dmstr/yii2-adminlte-asset": "2.*", 21 "dmstr/yii2-adminlte-asset": "2.*",
22 "yiisoft/yii2-jui": "^2.0", 22 "yiisoft/yii2-jui": "^2.0",
23 "kartik-v/yii2-widget-select2": "@dev", 23 "kartik-v/yii2-widget-select2": "@dev",
  24 + "mihaildev/yii2-ckeditor": "*",
24 "developeruz/yii2-db-rbac": "*", 25 "developeruz/yii2-db-rbac": "*",
25 "nodge/yii2-eauth": "*" 26 "nodge/yii2-eauth": "*"
26 }, 27 },
@@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 "This file is @generated automatically" 5 "This file is @generated automatically"
6 ], 6 ],
7 - "hash": "6b310fccece1d1eddc11db43624c06ab", 7 + "hash": "0a46956b2ac16c603963c69e1b1f078c",
  8 + "content-hash": "1827ea8c78463126c172696034e7e2aa",
8 "packages": [ 9 "packages": [
9 { 10 {
10 "name": "almasaeed2010/adminlte", 11 "name": "almasaeed2010/adminlte",
@@ -97,16 +98,16 @@ @@ -97,16 +98,16 @@
97 }, 98 },
98 { 99 {
99 "name": "bower-asset/fontawesome", 100 "name": "bower-asset/fontawesome",
100 - "version": "v4.4.0", 101 + "version": "v4.5.0",
101 "source": { 102 "source": {
102 "type": "git", 103 "type": "git",
103 "url": "https://github.com/FortAwesome/Font-Awesome.git", 104 "url": "https://github.com/FortAwesome/Font-Awesome.git",
104 - "reference": "e554555d73a44e0a7d11b0361ad7a5325a5f551c" 105 + "reference": "fddd2c240452e6c8990c4ef75e0265b455aa7968"
105 }, 106 },
106 "dist": { 107 "dist": {
107 "type": "zip", 108 "type": "zip",
108 - "url": "https://api.github.com/repos/FortAwesome/Font-Awesome/zipball/e554555d73a44e0a7d11b0361ad7a5325a5f551c",  
109 - "reference": "e554555d73a44e0a7d11b0361ad7a5325a5f551c", 109 + "url": "https://api.github.com/repos/FortAwesome/Font-Awesome/zipball/fddd2c240452e6c8990c4ef75e0265b455aa7968",
  110 + "reference": "fddd2c240452e6c8990c4ef75e0265b455aa7968",
110 "shasum": "" 111 "shasum": ""
111 }, 112 },
112 "type": "bower-asset-library", 113 "type": "bower-asset-library",
@@ -713,6 +714,57 @@ @@ -713,6 +714,57 @@
713 "time": "2015-09-09 06:43:02" 714 "time": "2015-09-09 06:43:02"
714 }, 715 },
715 { 716 {
  717 + "name": "mihaildev/yii2-ckeditor",
  718 + "version": "1.0.1",
  719 + "source": {
  720 + "type": "git",
  721 + "url": "https://github.com/MihailDev/yii2-ckeditor.git",
  722 + "reference": "d20aa7f6bcf610fee226d6eb15212a279875bf87"
  723 + },
  724 + "dist": {
  725 + "type": "zip",
  726 + "url": "https://api.github.com/repos/MihailDev/yii2-ckeditor/zipball/d20aa7f6bcf610fee226d6eb15212a279875bf87",
  727 + "reference": "d20aa7f6bcf610fee226d6eb15212a279875bf87",
  728 + "shasum": ""
  729 + },
  730 + "require": {
  731 + "yiisoft/yii2": "*"
  732 + },
  733 + "type": "yii2-extension",
  734 + "extra": {
  735 + "asset-installer-paths": {
  736 + "npm-asset-library": "vendor/npm",
  737 + "bower-asset-library": "vendor/bower"
  738 + }
  739 + },
  740 + "autoload": {
  741 + "psr-4": {
  742 + "mihaildev\\ckeditor\\": ""
  743 + }
  744 + },
  745 + "notification-url": "https://packagist.org/downloads/",
  746 + "license": [
  747 + "BSD-3-Clause"
  748 + ],
  749 + "authors": [
  750 + {
  751 + "name": "Mihail",
  752 + "email": "mihail.kucher@gmail.com",
  753 + "homepage": "https://github.com/MihailDev",
  754 + "role": "Developer"
  755 + }
  756 + ],
  757 + "description": "Yii2 CKEditor",
  758 + "homepage": "https://github.com/MihailDev/yii2-ckeditor",
  759 + "keywords": [
  760 + "CKEditor",
  761 + "editor",
  762 + "wysiwyg",
  763 + "yii"
  764 + ],
  765 + "time": "2014-11-19 22:04:08"
  766 + },
  767 + {
716 "name": "nodge/lightopenid", 768 "name": "nodge/lightopenid",
717 "version": "1.1.2", 769 "version": "1.1.2",
718 "source": { 770 "source": {
@@ -813,20 +865,20 @@ @@ -813,20 +865,20 @@
813 }, 865 },
814 { 866 {
815 "name": "rmrevin/yii2-fontawesome", 867 "name": "rmrevin/yii2-fontawesome",
816 - "version": "2.12.2", 868 + "version": "2.13.0",
817 "source": { 869 "source": {
818 "type": "git", 870 "type": "git",
819 "url": "https://github.com/rmrevin/yii2-fontawesome.git", 871 "url": "https://github.com/rmrevin/yii2-fontawesome.git",
820 - "reference": "62308687477734c166753de0ad9e2333dc7dce32" 872 + "reference": "2efbfacb22be59f373d11a7e3dfa9213e2ba18a9"
821 }, 873 },
822 "dist": { 874 "dist": {
823 "type": "zip", 875 "type": "zip",
824 - "url": "https://api.github.com/repos/rmrevin/yii2-fontawesome/zipball/62308687477734c166753de0ad9e2333dc7dce32",  
825 - "reference": "62308687477734c166753de0ad9e2333dc7dce32", 876 + "url": "https://api.github.com/repos/rmrevin/yii2-fontawesome/zipball/2efbfacb22be59f373d11a7e3dfa9213e2ba18a9",
  877 + "reference": "2efbfacb22be59f373d11a7e3dfa9213e2ba18a9",
826 "shasum": "" 878 "shasum": ""
827 }, 879 },
828 "require": { 880 "require": {
829 - "bower-asset/fontawesome": "4.4.*", 881 + "bower-asset/fontawesome": "4.5.*",
830 "php": ">=5.4.0", 882 "php": ">=5.4.0",
831 "yiisoft/yii2": "2.0.*" 883 "yiisoft/yii2": "2.0.*"
832 }, 884 },
@@ -861,7 +913,7 @@ @@ -861,7 +913,7 @@
861 "font", 913 "font",
862 "yii" 914 "yii"
863 ], 915 ],
864 - "time": "2015-11-20 09:17:45" 916 + "time": "2015-11-26 15:24:53"
865 }, 917 },
866 { 918 {
867 "name": "swiftmailer/swiftmailer", 919 "name": "swiftmailer/swiftmailer",
frontend/assets/AppAsset.php
@@ -22,6 +22,7 @@ class AppAsset extends AssetBundle @@ -22,6 +22,7 @@ class AppAsset extends AssetBundle
22 'css/flags32.css' 22 'css/flags32.css'
23 ]; 23 ];
24 public $js = [ 24 public $js = [
  25 + 'js/option.js'
25 ]; 26 ];
26 public $depends = [ 27 public $depends = [
27 'yii\web\YiiAsset', 28 'yii\web\YiiAsset',
frontend/config/main.php
@@ -15,6 +15,11 @@ return [ @@ -15,6 +15,11 @@ return [
15 //'bootstrap' => ['log', 'PageController'], 15 //'bootstrap' => ['log', 'PageController'],
16 'bootstrap' => ['log'], 16 'bootstrap' => ['log'],
17 'controllerNamespace' => 'frontend\controllers', 17 'controllerNamespace' => 'frontend\controllers',
  18 + 'modules' => [
  19 + 'blog' => [
  20 + 'class' => 'common\modules\blog\Module',
  21 + ],
  22 + ],
18 'components' => [ 23 'components' => [
19 //'PageController'=>[ 24 //'PageController'=>[
20 // 'class' => 'frontend\controllers\PageController' 25 // 'class' => 'frontend\controllers\PageController'
frontend/web/js/option.js 0 → 100644
  1 +function readURL(input) {
  2 + $(input).parents('.tab-pane').find('.image_inputs_prev').remove();
  3 + var urls = [];
  4 + if (input.files) {
  5 + $.each(input.files, function(key, value) {
  6 + var reader = new FileReader();
  7 + reader.onload = function(e) {
  8 + $(input).parent().append('<img src="'+ e.target.result +'" width="100" class="image_inputs_prev" />');
  9 + }
  10 + reader.readAsDataURL(value);
  11 + });
  12 + }
  13 + return urls;
  14 +}
  15 +$(function() {
  16 + var counter = 0;
  17 + $(document).on('click', '.add_row', function() {
  18 + counter++;
  19 + var clone = $('#main_row').clone().html().replace(new RegExp("Option\\[0\\]", 'g'), "Option["+counter+"]");
  20 + console.log(form);
  21 + $(clone).appendTo('#'+form);
  22 + $('#'+form+' button[type=submit]').parent().appendTo('#'+form);
  23 + });
  24 + $(document).on('click', '.add_lang', function() {
  25 + var field_block = $(this).parent().parent();
  26 + if($(this).hasClass('active')) {
  27 + $(field_block).find('.main_input').attr('required', '').show();
  28 + $(field_block).find('.lang_inputs').hide();
  29 + $(this).removeClass('active');
  30 + } else {
  31 + $(field_block).find('.main_input').removeAttr('required').hide();
  32 + $(field_block).find('.lang_inputs').show();
  33 + $(this).addClass('active');
  34 + }
  35 + });
  36 + $(document).on('click', '.remove_lang', function() {
  37 + $(this).parents('.form-wrapper').remove();
  38 + });
  39 + if($('#lang-tabs li').length > 1) {
  40 + $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')
  41 + }
  42 + $(document).on('click', '#lang-dropdown li a[data-lang]', function() {
  43 + var lang = $(this).data('lang');
  44 + var flag = $(this).find('span').first().clone();
  45 + var el = $(this);
  46 + $.get('/blog/ajax/category-form', { lang_id: lang }, function(data) {
  47 + $('#lang-tabs li').removeClass('active');
  48 + $('#lang-tabs').append('<li role="lang_inputs" class="active" data-lang="'+lang+'"><a href="#lang-'+lang+'" aria-controls="lang-'+lang+'" role="tab" data-toggle="tab">'+$('<p>').append($(flag)).html()+'</a></li>');
  49 + $('.lang-tab-content .tab-pane.active').removeClass('active');
  50 + $('.lang-tab-content').append($(data).find('.ajax-loaded').first());
  51 + $('body').append($(data).filter('script'));
  52 + $(el).parent().remove();
  53 + if(!$('#lang-dropdown li').length) {
  54 + $('#dropdownLang').addClass('disabled');
  55 + }
  56 + if($('#lang-tabs li').length > 1) {
  57 + $('#lang-tabs li').append('<span class="glyphicon glyphicon-remove-circle remove-lang"></span>')
  58 + }
  59 + });
  60 + });
  61 + $(document).on('click', '.remove-lang', function() {
  62 + var lang = $(this).parent().data('lang');
  63 + var flag = $(this).parent().find('span.flag').first().clone();
  64 + $('#lang-'+lang).remove();
  65 + $('#lang-dropdown').append('<li><a href="#lang-tabs" data-lang="'+lang+'">'+$('<p>').append($(flag)).html()+'</a></li>');
  66 + $('#dropdownLang').removeClass('disabled');
  67 + $(this).parent().remove();
  68 + if($('#lang-tabs li').length <= 1) {
  69 + $('#lang-tabs li').find('.remove-lang').remove();
  70 + }
  71 + if(!$('#lang-tabs>li.active').length) {
  72 + $('#lang-tabs>li').first().find('a').tab('show');
  73 + }
  74 + });
  75 + $(document).on('change', '.image_inputs_field', function() {
  76 + readURL(this);
  77 + });
  78 + $('a.remove_image').on('click', function(e) {
  79 + var el = $(this);
  80 + e.preventDefault();
  81 + if(confirm(confirm_message)) {
  82 + $.ajax({
  83 + type: 'post',
  84 + url: $(this).attr('href'),
  85 + data: $(this).data('params')
  86 + }).done(function() {
  87 + $(el).parents('.additional_image_container').remove();
  88 + });
  89 + }
  90 + return false;
  91 + });
  92 +});
0 \ No newline at end of file 93 \ No newline at end of file