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 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 33 \ No newline at end of file
... ...
backend/views/layouts/left.php
... ... @@ -40,6 +40,16 @@
40 40 ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
41 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 53 'label' => 'Роли',
44 54 'icon' => 'fa fa-share',
45 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 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 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 94 \ No newline at end of file
... ...
common/config/bootstrap.php
... ... @@ -3,3 +3,4 @@ Yii::setAlias(&#39;common&#39;, dirname(__DIR__));
3 3 Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend');
4 4 Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend');
5 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 8 'userClass' => 'common\models\User'
9 9 ]
10 10 ],
11   - 'blog' => [
12   - 'class' => 'common\modules\blog\Module',
13   - ],
14 11 ],
15 12 'components' => [
16 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 88 \ No newline at end of file
... ...
common/modules/blog/controllers/AjaxController.php
... ... @@ -2,19 +2,81 @@
2 2 namespace common\modules\blog\controllers;
3 3  
4 4 use common\models\Language;
  5 +use common\modules\blog\models\ArticleCategory;
5 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 10 use yii\web\Controller;
  11 +use yii\web\ForbiddenHttpException;
7 12 use yii\web\NotFoundHttpException;
8 13  
9 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 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 32 if(!$model) {
15 33 throw new NotFoundHttpException('Language not found');
16 34 }
17 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 1 <?php
2 2 namespace common\modules\blog\controllers;
3 3  
  4 +use common\models\Language;
4 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 9 use yii\data\ActiveDataProvider;
6 10 use yii\web\Controller;
  11 +use yii\web\UploadedFile;
7 12  
8 13 class ArticleController extends Controller
9 14 {
  15 +
10 16 public function actionIndex()
11 17 {
12 18 $dataProvider = new ActiveDataProvider([
... ... @@ -20,6 +26,178 @@ class ArticleController extends Controller
20 26  
21 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 5 use common\modules\blog\models\Article;
6 6 use common\modules\blog\models\ArticleCategory;
7 7 use common\modules\blog\models\ArticleCategoryLang;
  8 +use common\modules\blog\models\ArticleCategoryMedia;
8 9 use common\modules\blog\models\ArticleLang;
9 10 use yii\data\ActiveDataProvider;
  11 +use yii\filters\VerbFilter;
10 12 use yii\web\Controller;
  13 +use yii\web\NotFoundHttpException;
  14 +use yii\web\UploadedFile;
11 15  
12 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 30 public function actionIndex()
15 31 {
16 32 $dataProvider = new ActiveDataProvider([
... ... @@ -26,9 +42,23 @@ class CategoryController extends Controller
26 42 {
27 43 $category_langs = array();
28 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 50 $langs = Language::getActiveLanguages();
30 51 $default_lang = Language::getDefaultLang();
31 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 62 if(!empty(\Yii::$app->request->post())) {
33 63 $isValid = true;
34 64 $category->load(\Yii::$app->request->post());
... ... @@ -48,16 +78,122 @@ class CategoryController extends Controller
48 78 }
49 79 if($isValid) {
50 80 $category->save(false);
  81 + $first = 1;
  82 + foreach($images as $index => $image) {
  83 + $images[$index]->upload($category->id);
  84 + }
51 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 92 $category_lang->link('category', $category);
  93 + $first = 0;
53 94 }
54 95 echo "ok";
  96 + //$this->redirect('index');
55 97 } else {
56 98 return $this->render('create', [
57 99 'category_langs' => $category_langs,
58 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 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 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 150 \ No newline at end of file
... ...
common/modules/blog/views/article/create.php
1 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 1 <?php
  2 +use yii\grid\ActionColumn;
  3 +use yii\grid\Column;
2 4 use yii\grid\GridView;
3 5 use common\modules\blog\models\Article;
4 6 use common\models\Language;
  7 +
5 8 echo GridView::widget([
6 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 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 2 use yii\bootstrap\ActiveForm;
3 3 use common\modules\blog\models\ArticleCategory;
4 4 use yii\bootstrap\Html;
  5 +use mihaildev\ckeditor\CKEditor;
  6 +use yii\helpers\Json;
  7 +use yii\helpers\Url;
5 8  
6 9 $def_lang = array_keys($langs)[0];
7   -
  10 +$uploaddir = \Yii::getAlias('@saveImageDir');
8 11 ?>
9 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 16 <?= $form->field($category, 'code')->hint(Yii::t('app', 'Insensitive latin non-space'))->textInput() ?>
14 17  
15 18 <?= $form->field($category, 'tags')->hint(Yii::t('app', 'Comma-separated'))->textInput() ?>
16 19  
  20 + <?= $form->field($category, 'sort')->input('number') ?>
  21 +
17 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 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 78 <div class="dropdown pull-right">
23 79 <button class="btn btn-default dropdown-toggle" type="button" id="dropdownLang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
24 80 <?= Yii::t('app', 'Add language') ?>
... ... @@ -43,7 +99,7 @@ $def_lang = array_keys($langs)[0];
43 99 }
44 100 ?>
45 101 </ul>
46   - <div class="tab-content">
  102 + <div class="tab-content lang-tab-content">
47 103 <?php
48 104 $first = 1;
49 105 foreach($category_langs as $index => $category_lang) {
... ... @@ -51,9 +107,9 @@ $def_lang = array_keys($langs)[0];
51 107 <div role="" class="tab-pane <?php if($first) { echo 'active main-tab'; } ?>" id="lang-<?=$index?>">
52 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 114 <?= $form->field($category_langs[$index], "[$index]seo_url")->textInput() ?>
59 115  
... ... @@ -61,7 +117,7 @@ $def_lang = array_keys($langs)[0];
61 117  
62 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 122 <?= $form->field($category_langs[$index], "[$index]meta_keywords")->textInput() ?>
67 123  
... ... @@ -84,42 +140,5 @@ $def_lang = array_keys($langs)[0];
84 140  
85 141 </div>
86 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 144 </script>
126 145 \ No newline at end of file
... ...
common/modules/blog/views/category/create.php
1 1 <?php
2 2 use yii\helpers\Html;
3 3  
4   -$this->title = Yii::t('app', 'Create category');
  4 +$this->title = Yii::t('app', 'Category create');
5 5 $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Categories'), 'url' => ['index']];
6 6 $this->params['breadcrumbs'][] = $this->title;
7 7 ?>
... ... @@ -12,12 +12,8 @@ $this-&gt;params[&#39;breadcrumbs&#39;][] = $this-&gt;title;
12 12 <?= $this->render('_form', [
13 13 'category_langs' => $category_langs,
14 14 'category' => $category,
15   - 'langs' => $langs
  15 + 'langs' => $langs,
  16 + 'images' => $images
16 17 ]) ?>
17 18  
18 19 </div>
19   -<script>
20   - $(function() {
21   -
22   - });
23   -</script>
... ...
common/modules/blog/views/category/index.php
1 1 <?php
  2 +use yii\grid\ActionColumn;
  3 +use yii\grid\Column;
2 4 use yii\grid\GridView;
3 5 use common\modules\blog\models\Article;
4 6 use common\models\Language;
5 7 echo GridView::widget([
6 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 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 24 'message' => 'Сообщение',
25 25 'Feedback' => 'Обратная связь',
26 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 62 \ No newline at end of file
... ...
composer.json
... ... @@ -21,6 +21,7 @@
21 21 "dmstr/yii2-adminlte-asset": "2.*",
22 22 "yiisoft/yii2-jui": "^2.0",
23 23 "kartik-v/yii2-widget-select2": "@dev",
  24 + "mihaildev/yii2-ckeditor": "*",
24 25 "developeruz/yii2-db-rbac": "*",
25 26 "nodge/yii2-eauth": "*"
26 27 },
... ...
composer.lock
... ... @@ -4,7 +4,8 @@
4 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 5 "This file is @generated automatically"
6 6 ],
7   - "hash": "6b310fccece1d1eddc11db43624c06ab",
  7 + "hash": "0a46956b2ac16c603963c69e1b1f078c",
  8 + "content-hash": "1827ea8c78463126c172696034e7e2aa",
8 9 "packages": [
9 10 {
10 11 "name": "almasaeed2010/adminlte",
... ... @@ -97,16 +98,16 @@
97 98 },
98 99 {
99 100 "name": "bower-asset/fontawesome",
100   - "version": "v4.4.0",
  101 + "version": "v4.5.0",
101 102 "source": {
102 103 "type": "git",
103 104 "url": "https://github.com/FortAwesome/Font-Awesome.git",
104   - "reference": "e554555d73a44e0a7d11b0361ad7a5325a5f551c"
  105 + "reference": "fddd2c240452e6c8990c4ef75e0265b455aa7968"
105 106 },
106 107 "dist": {
107 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 111 "shasum": ""
111 112 },
112 113 "type": "bower-asset-library",
... ... @@ -713,6 +714,57 @@
713 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 768 "name": "nodge/lightopenid",
717 769 "version": "1.1.2",
718 770 "source": {
... ... @@ -813,20 +865,20 @@
813 865 },
814 866 {
815 867 "name": "rmrevin/yii2-fontawesome",
816   - "version": "2.12.2",
  868 + "version": "2.13.0",
817 869 "source": {
818 870 "type": "git",
819 871 "url": "https://github.com/rmrevin/yii2-fontawesome.git",
820   - "reference": "62308687477734c166753de0ad9e2333dc7dce32"
  872 + "reference": "2efbfacb22be59f373d11a7e3dfa9213e2ba18a9"
821 873 },
822 874 "dist": {
823 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 878 "shasum": ""
827 879 },
828 880 "require": {
829   - "bower-asset/fontawesome": "4.4.*",
  881 + "bower-asset/fontawesome": "4.5.*",
830 882 "php": ">=5.4.0",
831 883 "yiisoft/yii2": "2.0.*"
832 884 },
... ... @@ -861,7 +913,7 @@
861 913 "font",
862 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 919 "name": "swiftmailer/swiftmailer",
... ...
frontend/assets/AppAsset.php
... ... @@ -22,6 +22,7 @@ class AppAsset extends AssetBundle
22 22 'css/flags32.css'
23 23 ];
24 24 public $js = [
  25 + 'js/option.js'
25 26 ];
26 27 public $depends = [
27 28 'yii\web\YiiAsset',
... ...
frontend/config/main.php
... ... @@ -15,6 +15,11 @@ return [
15 15 //'bootstrap' => ['log', 'PageController'],
16 16 'bootstrap' => ['log'],
17 17 'controllerNamespace' => 'frontend\controllers',
  18 + 'modules' => [
  19 + 'blog' => [
  20 + 'class' => 'common\modules\blog\Module',
  21 + ],
  22 + ],
18 23 'components' => [
19 24 //'PageController'=>[
20 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 93 \ No newline at end of file
... ...