diff --git a/backend/actions/Create.php b/backend/actions/Create.php
new file mode 100755
index 0000000..f59738c
--- /dev/null
+++ b/backend/actions/Create.php
@@ -0,0 +1,97 @@
+controller,
+ 'newModel',
+ ]
+ );
+ $languages = Language::getActive();
+ if ($this->hasAlias) {
+ /**
+ * @var \artbox\core\models\Alias[] $aliases
+ */
+ $aliases = $model->loadAliases();
+ }
+
+ $post = \Yii::$app->request->post();
+
+ if (!empty($this->languageFields)) {
+ Model::loadMultiple($model->getVariationModels(), $post);
+ }
+
+ if ($model->load($post) && $model->save()) {
+ if ($this->hasAlias) {
+ /**
+ * @var \artbox\core\models\Alias[] $aliases
+ */
+ Model::loadMultiple($aliases, $post);
+ foreach ($aliases as $alias) {
+ $alias->route = $model->getRoute();
+ if ($this->overwriteEntity === null) {
+ $alias->entity = $model::className();
+ } else {
+ $alias->entity = $this->overwriteEntity;
+ }
+ $alias->save();
+
+ /**
+ * @var \yii\db\ActiveRecord $modelLang
+ */
+ $modelLang = $model->getVariationModel($alias->language_id);
+ $modelLang->alias_id = $alias->id;
+ $modelLang->save();
+ }
+ }
+
+ if ($this->hasGallery) {
+ $model->saveImages($post);
+ }
+
+ return $this->controller->redirect([ 'index' ]);
+ }
+
+ return $this->controller->render(
+ $this->viewPath,
+ [
+ 'action' => $this,
+ 'model' => $model,
+ 'languages' => $languages,
+ ]
+ );
+ }
+ }
\ No newline at end of file
diff --git a/backend/actions/Update.php b/backend/actions/Update.php
new file mode 100755
index 0000000..da7d0e7
--- /dev/null
+++ b/backend/actions/Update.php
@@ -0,0 +1,68 @@
+controller,
+ 'findModel',
+ ],
+ [ $id ]
+ );
+ $languages = Language::getActive();
+ $post = \Yii::$app->request->post();
+
+ if (!empty($this->languageFields)) {
+ Model::loadMultiple($model->getVariationModels(), $post);
+ }
+
+ if ($model->load($post) && $model->save()) {
+ if ($this->hasAlias) {
+ /**
+ * @var \artbox\core\models\Alias[] $aliases
+ */
+ $aliases = $model->loadAliases();
+ Model::loadMultiple($aliases, $post);
+ foreach ($aliases as $alias) {
+ $alias->save();
+ }
+ }
+
+ if ($this->hasGallery) {
+ $model->saveImages($post);
+ }
+
+ return $this->controller->redirect([ 'index' ]);
+ }
+
+ return $this->controller->render(
+ $this->viewPath,
+ [
+ 'action' => $this,
+ 'model' => $model,
+ 'languages' => $languages,
+ ]
+ );
+ }
+ }
\ No newline at end of file
diff --git a/backend/actions/views/create.php b/backend/actions/views/create.php
new file mode 100755
index 0000000..f5443cb
--- /dev/null
+++ b/backend/actions/views/create.php
@@ -0,0 +1,72 @@
+getShortName();
+
+ $this->params[ 'breadcrumbs' ][] = [
+ 'label' => \Yii::t('core', Inflector::pluralize($modelName)),
+ 'url' => [ $action->controller->id . '/index' ],
+ ];
+
+ $this->title = \Yii::t('core', 'Create ' . lcfirst($modelName));
+
+ $this->params[ 'breadcrumbs' ][] = $this->title;
+
+?>
+
+
+
+
+
+
+ languageFields)) {?>
+
+
+ =$language['url']?>
+
+
+
+
+
+
+
+
+
+ languageFields)) {?>
+ Языковой блок
+
+ Основной блок
+ hasAlias){?>
+ Seo
+
+ hasGallery){?>
+ Галерея
+
+
+
+
+
+ $action,
+ 'model' => $model,
+ ]
+ );
+
+
+ ?>
+
+
diff --git a/backend/actions/views/update.php b/backend/actions/views/update.php
new file mode 100755
index 0000000..ab9175a
--- /dev/null
+++ b/backend/actions/views/update.php
@@ -0,0 +1,72 @@
+getShortName();
+
+ $this->params[ 'breadcrumbs' ][] = [
+ 'label' => \Yii::t('core', Inflector::pluralize($modelName)),
+ 'url' => [ $action->controller->id . '/index' ],
+ ];
+
+ $this->title = \Yii::t('core', 'Update ' . lcfirst($modelName));
+
+ $this->params[ 'breadcrumbs' ][] = $this->title;
+?>
+
+
+
+
+
+
+
+ languageFields)) {?>
+
+
+ =$language['url']?>
+
+
+
+
+
+
+
+
+ languageFields)) {?>
+ Языковой блок
+
+ Основной блок
+ hasAlias){?>
+ Seo
+
+ hasGallery){?>
+ Галерея
+
+
+
+
+
+ $action,
+ 'model' => $model,
+ ]
+ );
+
+
+ ?>
+
+
diff --git a/backend/controllers/PageController.php b/backend/controllers/PageController.php
index e3b2153..4d109a0 100755
--- a/backend/controllers/PageController.php
+++ b/backend/controllers/PageController.php
@@ -3,10 +3,10 @@
namespace backend\controllers;
use function array_merge;
- use artbox\core\admin\actions\Create;
+ use backend\actions\Create;
use artbox\core\admin\actions\Delete;
use backend\actions\Index;
- use artbox\core\admin\actions\Update;
+ use backend\actions\Update;
use artbox\core\admin\actions\View;
use artbox\core\admin\interfaces\ControllerInterface;
use artbox\core\admin\widgets\Form;
@@ -159,6 +159,7 @@
[
'name' => 'title',
'type' => Form::STRING,
+ 'decorate' => true
],
[
'name' => 'body',
diff --git a/backend/widgets/Form.php b/backend/widgets/Form.php
new file mode 100755
index 0000000..5b41564
--- /dev/null
+++ b/backend/widgets/Form.php
@@ -0,0 +1,699 @@
+{title}
{tab}';
+
+ /**
+ * Template for block of all languages tabs
+ *
+ * @var string
+ */
+ public $langBlockTemplate = '{tabs}
';
+ /**
+ * @var array fields for seo value
+ */
+ public $decorateField = [];
+ /**
+ * @inheritdoc
+ * @todo Remove H1 stabs
+ * @return string|void
+ * @throws \Exception
+ * @throws \yii\base\InvalidConfigException
+ */
+ public function run()
+ {
+ Switchery::register($this->view);
+
+ $js = <<< JS
+$('.switchery').each(function(idx, elem) {
+ new Switchery(elem, {
+ color:'#46b749',
+ secondaryColor:'#e2e2e2'
+ });
+});
+JS;
+
+
+ $this->languages = new Languages();
+
+ $this->view->registerJs($js, \yii\web\View::POS_READY);
+ $notify = << 0){
+ new PNotify({
+ title: 'Info',
+ text: 'Проверьте заполнение полей',
+ type: 'info',
+ styling: "bootstrap3"
+ });
+ }
+ });
+JS;
+
+ $this->view->registerJs($notify, \yii\web\View::POS_READY);
+
+ $form = ActiveForm::begin();
+ if (!empty($this->action->languageFields)) {
+ echo str_replace(
+ [
+ '{tabs}',
+ '{title}',
+ ],
+ [
+ $this->generateLangBlock($form),
+ 'Языковой блок',
+ ],
+ $this->langBlockTemplate
+ );
+ }
+
+ echo '';
+
+ if ($this->action->hasAlias) {
+ echo str_replace(
+ [
+ '{tabs}',
+ '{title}',
+ ],
+ [
+ $this->generateAliasBlock($form),
+ 'Seo блок',
+ ],
+ $this->langBlockTemplate
+ );
+ }
+
+ if ($this->action->hasGallery) {
+ echo '';
+ }
+
+ echo '';
+ echo Html::submitButton(
+ \Yii::t('core', 'Save'),
+ [
+ 'class' => 'btn btn-success',
+ ]
+ );
+ echo '
';
+
+ $form::end();
+
+ $this->registerClientScripts();
+ }
+
+ protected function registerClientScripts()
+ {
+ $js = << 0) {
+ input.val(newVal);
+ }
+ });
+ $(document)
+ .on('click', '.pos-pluse-adm', function(e) {
+ e.preventDefault();
+ var input = $(this)
+ .parent()
+ .find('input');
+ var newVal = parseInt((input.val() === '' ? 0 : input.val())) + 1;
+ input.val(newVal);
+ });
+
+ $('#page-sort').keypress(function(e) {
+ var symbol = (e.which) ? e.which : e.keyCode;
+ if (symbol < 48 || symbol > 57) {
+ return false;
+ }
+ })
+JS;
+
+ $this->view->registerJs($js, \yii\web\View::POS_READY);
+ }
+
+ /**
+ * If model has languages
+ *
+ * @param \yii\widgets\ActiveForm $form
+ *
+ * @return string
+ * @throws \yii\base\InvalidConfigException
+ */
+ protected function generateLangBlock(ActiveForm $form): string
+ {
+ $tabs = '';
+ $i = 1;
+ foreach ($this->getVariationModels() as $index => $variationModel) {
+ $tab = '';
+ foreach ($this->action->languageFields as $languageField) {
+ switch ($languageField[ 'type' ]) {
+ case self::STRING:
+ if (isset($languageField[ 'decorate' ]) and $languageField[ 'decorate' ]) {
+ $this->decorateField[ $index ] = $form->field(
+ $variationModel,
+ '[' . $index . ']' . $languageField[ 'name' ]
+ )
+ ->label(
+ self::getLanguageLabel(
+ $variationModel,
+ $languageField[ 'name' ],
+ $variationModel->language_id
+ )
+ );
+ $tab .= $this->decorateField[ $index ];
+ } else {
+ $tab .= $form->field($variationModel, '[' . $index . ']' . $languageField[ 'name' ])
+ ->label(
+ self::getLanguageLabel(
+ $variationModel,
+ $languageField[ 'name' ],
+ $variationModel->language_id
+ )
+ );
+ }
+ break;
+ case self::TEXTAREA:
+ $tab .= $form->field($variationModel, '[' . $index . ']' . $languageField[ 'name' ])
+ ->textarea(
+ [
+ 'rows' => 6,
+ ]
+ )
+ ->label(
+ self::getLanguageLabel(
+ $variationModel,
+ $languageField[ 'name' ],
+ $variationModel->language_id
+ )
+ );
+ break;
+ case self::IMAGE:
+ $tab .= $form->field(
+ $variationModel,
+ '[' . $index . ']' . $languageField[ 'name' ],
+ [ 'options' => [ 'class' => 'form-group filed-upload-imgs' ] ]
+ )
+ ->widget(
+ ImageInput::className(),
+ [
+ 'showPreview' => true,
+ ]
+ )
+ ->label(
+ self::getLanguageLabel(
+ $variationModel,
+ $languageField[ 'name' ],
+ $variationModel->language_id
+ )
+ );
+ break;
+ case self::WYSIWYG:
+ $tab .= $form->field($variationModel, '[' . $index . ']' . $languageField[ 'name' ])
+ ->widget(
+ TinyMce::className(),
+ $this->action->getTinyMceConfig()
+ )
+ ->label(
+ self::getLanguageLabel(
+ $variationModel,
+ $languageField[ 'name' ],
+ $variationModel->language_id
+ )
+ );
+ break;
+ default:
+ throw new InvalidConfigException(
+ \Yii::t(
+ 'core',
+ 'Unavailable or unknown type: {type}',
+ [
+ 'type' => $languageField[ 'type' ],
+ ]
+ )
+ );
+ }
+ }
+
+ if ($variationModel->language_id === $this->languages->getDefault()->id) {
+ $tabs .= str_replace(
+ [
+ '{tab}',
+ '{display}',
+ ],
+ [
+ $tab,
+ 'block',
+ ],
+ $this->langTabTemplate
+ );
+ } else {
+ $tabs .= str_replace(
+ [
+ '{tab}',
+ '{display}',
+ ],
+ [
+ $tab,
+ 'none',
+ ],
+ $this->langTabTemplate
+ );
+ }
+
+ $i++;
+ }
+
+ return $tabs;
+ }
+
+ /**
+ * Common block
+ *
+ * @param \yii\widgets\ActiveForm $form
+ *
+ * @throws \yii\base\InvalidConfigException
+ */
+ protected function generateCommonBlock(ActiveForm $form)
+ {
+ foreach ($this->action->fields as $field) {
+ switch ($field[ 'type' ]) {
+ case self::STRING:
+ echo $form->field($this->model, $field[ 'name' ]);
+ break;
+ case self::TEXTAREA:
+ echo $form->field($this->model, $field[ 'name' ])
+ ->textarea(
+ [
+ 'rows' => 6,
+ ]
+ );
+ break;
+ case self::WYSIWYG:
+ echo $form->field($this->model, $field[ 'name' ])
+ ->widget(
+ TinyMce::className(),
+ $this->action->getTinyMceConfig()
+ );
+ break;
+ case self::BOOL:
+ echo $form->field(
+ $this->model,
+ $field[ 'name' ],
+ [
+ 'template' => "{label}
\n{input}\n{error}",
+ ]
+ )
+ ->checkbox(
+ [
+ 'class' => 'switchery',
+ ],
+ false
+ );
+ break;
+ case self::NUMBER:
+ echo $form->field(
+ $this->model,
+ $field[ 'name' ],
+ [
+ 'template' => '{label}{input}
+ {error}{hint}',
+ 'options' => [ 'class' => 'form-group filed-sort' ],
+ ]
+ );
+ break;
+ case self::RELATION:
+ $isMultiple = $field[ 'multiple' ] ?? false;
+ echo $form->field($this->model, $field[ 'name' ])
+ ->widget(
+ Select2::classname(),
+ [
+ 'data' => $this->action->relationalData[ $field[ 'name' ] ],
+ 'options' => [
+ 'placeholder' => \Yii::t('core', 'Select ...'),
+ 'multiple' => $isMultiple,
+ ],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ ]
+ );
+ break;
+ case self::SELECT:
+ $isMultiple = $field[ 'multiple' ] ?? false;
+ echo $form->field($this->model, $field[ 'name' ])
+ ->widget(
+ Select2::classname(),
+ [
+ 'data' => $field['data'],
+ 'options' => [
+ 'placeholder' => \Yii::t('core', 'Select ...'),
+ 'multiple' => $isMultiple,
+ ],
+ 'pluginOptions' => [
+ 'allowClear' => true,
+ ],
+ ]
+ );
+
+ break;
+ case self::IMAGE:
+ echo $form->field(
+ $this->model,
+ $field[ 'name' ],
+ [ 'options' => [ 'class' => 'form-group filed-upload-imgs' ] ]
+ )
+ ->widget(
+ ImageInput::className(),
+ [
+ 'showPreview' => true,
+ ]
+ );
+ break;
+ case self::DATE:
+ DateRangePicker::register($this->view);
+ $mindate = date("d-m-Y H:i");
+ $value = $this->model->{$field['name']};
+ $js = <<< JS
+var dateRangeInputFrom = $('#date_field');
+var dateFormat = '{$this->model->clientDateFormat}';
+dateRangeInputFrom.daterangepicker({
+ singleDatePicker: true,
+ autoUpdateInput: true,
+ showDropdowns: true,
+ minDate: '{$mindate}',
+ timePicker: true,
+ timePicker24Hour: true,
+ locale: {
+ cancelLabel: 'Clear',
+ format: dateFormat
+ }
+}, function(){
+
+ });
+dateRangeInputFrom.on('cancel.daterangepicker', function(ev, picker) {
+ //do something, like clearing an input
+ dateRangeInputFrom.val('');
+});
+if ("{$value}" == ""){
+ dateRangeInputFrom.val('');
+}
+JS;
+ $this->view->registerJs($js, \yii\web\View::POS_READY);
+ echo $form->field(
+ $this->model,
+ $field[ 'name' ],
+ [ 'options' => [ 'class' => 'form-group date-search' ] ]
+ )->textInput(['id' => "date_field"]);
+ break;
+
+ default:
+ throw new InvalidConfigException(
+ \Yii::t(
+ 'core',
+ 'Unavailable or unknown type: {type}',
+ [
+ 'type' => $field[ 'type' ],
+ ]
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * Generate seo block
+ *
+ * @param \yii\widgets\ActiveForm $form
+ *
+ * @return string
+ */
+ protected function generateAliasBlock(ActiveForm $form)
+ {
+ $tabs = '';
+ $i = 1;
+ foreach ($this->getAliases() as $index => $alias) {
+ $tab = '';
+ if (isset($this->decorateField[ $index ])) {
+ $tab .= '' . SlugifyDecorator::decorate(
+ $form->field($alias, "[$index]value"),
+ [ '/seo/alias/slugify' ],
+ $this->decorateField[ $index ],
+ false,
+ $alias->language_id
+ )
+ ->textInput(
+ [ 'maxlength' => true ]
+ ) . "
";
+ } else {
+ $tab .= $form->field($alias, '[' . $index . ']value')
+ ->label(
+ self::getLanguageLabel($alias, 'value', $alias->language_id)
+ );
+ }
+
+ $tab .= $form->field($alias, '[' . $index . ']title')
+ ->label(
+ self::getLanguageLabel($alias, 'title', $alias->language_id)
+ );
+
+ $tab .= $form->field($alias, '[' . $index . ']description')
+ ->textarea(
+ [
+ 'rows' => 6,
+ ]
+ )
+ ->label(
+ self::getLanguageLabel($alias, 'description', $alias->language_id)
+ );
+
+ $tab .= $form->field($alias, '[' . $index . ']h1')
+ ->label(
+ self::getLanguageLabel($alias, 'h1', $alias->language_id)
+ );
+
+ $tab .= $form->field($alias, '[' . $index . ']seo_text')
+ ->widget(
+ TinyMce::className(),
+ $this->action->getTinyMceConfig()
+ )
+ ->label(
+ self::getLanguageLabel($alias, 'seo_text', $alias->language_id)
+ );
+
+ $tab .= $form->field($alias, '[' . $index . ']robots')
+ ->widget(
+ Select2::class,
+ [
+ 'data' => [
+ 'index, follow' => 'index, follow',
+ 'index, nofollow' => 'index, nofollow',
+ 'noindex, follow' => 'noindex, follow',
+ 'noindex, nofollow' => 'noindex, nofollow',
+ ],
+ ]
+ )
+ ->label(
+ self::getLanguageLabel($alias, 'robots', $alias->language_id)
+ );
+
+ if ($alias->language_id === $this->languages->getDefault()->id) {
+ $tabs .= str_replace(
+ [
+ '{tab}',
+ '{display}',
+ ],
+ [
+ $tab,
+ 'block',
+ ],
+ $this->langTabTemplate
+ );
+ } else {
+ $tabs .= str_replace(
+ [
+ '{tab}',
+ '{display}',
+ ],
+ [
+ $tab,
+ 'none',
+ ],
+ $this->langTabTemplate
+ );
+ }
+
+ $i++;
+ }
+
+ return $tabs;
+ }
+
+ /**
+ * Appends language short name to label
+ *
+ * @param \yii\db\ActiveRecord $model
+ * @param string $field
+ * @param $language_id
+ *
+ * @return string
+ */
+ protected static function getLanguageLabel(ActiveRecord $model, string $field, $language_id): string
+ {
+ $languages = Language::getActive();
+ return $model->getAttributeLabel(
+ $field
+ ) . ' (' . $languages[ $language_id ]->url . ')';
+
+ }
+
+ /**
+ * @return ActiveRecord[]
+ */
+ protected function getVariationModels(): array
+ {
+ return call_user_func(
+ [
+ $this->model,
+ 'getVariationModels',
+ ]
+ );
+ }
+
+ /**
+ * @return \artbox\core\models\Alias[]
+ */
+ protected function getAliases(): array
+ {
+ return call_user_func(
+ [
+ $this->model,
+ 'loadAliases',
+ ]
+ );
+ }
+ }
+
+?>
+
+
+
diff --git a/console/migrations/m180831_083021_alter_page_columns.php b/console/migrations/m180831_083021_alter_page_columns.php
new file mode 100644
index 0000000..2245d44
--- /dev/null
+++ b/console/migrations/m180831_083021_alter_page_columns.php
@@ -0,0 +1,48 @@
+dropColumn('page', 'created_at');
+ $this->dropColumn('page', 'updated_at');
+
+ $this->addColumn('page', 'created_at', $this->integer());
+ $this->addColumn('page', 'updated_at', $this->integer());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function safeDown()
+ {
+ $this->dropColumn('page', 'created_at');
+ $this->dropColumn('page', 'updated_at');
+
+ $this->addColumn('page', 'created_at', $this->timestamp());
+ $this->addColumn('page', 'updated_at', $this->timestamp());
+ }
+
+ /*
+ // Use up()/down() to run migration code without a transaction.
+ public function up()
+ {
+
+ }
+
+ public function down()
+ {
+ echo "m180831_083021_alter_page_columns cannot be reverted.\n";
+
+ return false;
+ }
+ */
+}
diff --git a/frontend/views/layouts/main.php b/frontend/views/layouts/main.php
index 61da3a1..50e0d9f 100755
--- a/frontend/views/layouts/main.php
+++ b/frontend/views/layouts/main.php
@@ -139,17 +139,16 @@ JS;