Snippets

You are viewing an old version of this snippet. View the current version.
Revised by Илья Караваев 0ea5029
namespace ...;

use ...;

class Controller extends \yii\web\Controller
{
    public function behaviors()
    {
        $behaviours = [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => [
                            'index',
                            'list',
                            'create',
                            'update',
                            'delete',
                            'upload',
                            'comment'
                        ],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            [
                'class' => 'yii\filters\ContentNegotiator',
                'only' => [
                    'list',
                    'create',
                    'update',
                    'delete',
                    'upload',
                    'comment'
                ],
                'formats' => [
                    'application/json' => Response::FORMAT_JSON,
                ],
            ]
        ];
        return ArrayHelper::merge(parent::behaviors(), $behaviours);
    }

    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionCreate()
    {
        $request = \Yii::$app->request;

        $model = new ActiveRecord();
        $model->files = $request->post('files');
        $model->filesForDelete = $request->post('files_delete');

        if ($model->load(Common::prepareRequestData($model->formName())) && $model->save() && $model->refresh()) {
            return ArrayHelper::toArray($model, [
                ActiveRecord::className() => [
                    'id',
                    'name',
                    'email',
                    'phone',
                    'description',
                    'comment',
                    'date_from',
                    'date_to',
                    'files',
                ],
                File::className() => [
                    'id',
                    'name',
                    'url'
                ]
            ]);
        }

        throw new BadRequestHttpException();
    }

    public function actionUpdate($id)
    {
        $model = ActiveRecord::findOne($id);

        if ($model->hasLimitEditing()) {
            throw new BadRequestHttpException();
        }

        $request = \Yii::$app->request;

        $model->files = $request->post('files');
        $model->filesForDelete = $request->post('files_delete');

        if ($model->load(Common::prepareRequestData($model->formName())) && $model->save() && $model->refresh()) {

            return ArrayHelper::toArray($model, [
                ActiveRecord::className() => [
                    'id',
                    'name',
                    'email',
                    'phone',
                    'description',
                    'comment',
                    'date_from',
                    'date_to',
                    'files'
                ],
                File::className() => [
                    'id',
                    'name',
                    'url'
                ],
            ]);
        }

        throw new BadRequestHttpException();
    }

    public function actionDelete($id)
    {
        ...
    }

    public function actionComment()
    {
        ...
    }

    public function actionUpload()
    {
        ...
    }

    public function actionAdd()
    {
        ...
    }

    public function actionMove()
    {
        ...
    }
    
    ...
}
namespace ...;

use ...;

/**
 * Class ActiveRecord
 *
 * @property integer $id
 * @property string $name
 * @property string $phone
 * @property string $email
 * @property string $description
 * @property string $date_from
 * @property string $date_to
 * @property string $created_at
 * @property string $updated_at
 *
 * @property File[] $files
 */
class ActiveRecord extends CommonActiveRecord
{
    protected $_files = [];
    protected $_filesForDelete = [];
    
    public static function tableName()
    {
        return '{{%active_record}}';
    }

    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::className(),
                'value' => new Expression('NOW()'),
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at']
                ],
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => 'date_from',
                    ActiveRecord::EVENT_BEFORE_UPDATE => 'date_from',
                    ActiveRecord::EVENT_BEFORE_VALIDATE => 'date_from',
                ],
                'value' => function ($event) {
                    return date('Y-m-d', strtotime($this->date_from));
                },
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => 'date_to',
                    ActiveRecord::EVENT_BEFORE_UPDATE => 'date_to',
                    ActiveRecord::EVENT_BEFORE_VALIDATE => 'date_to',
                ],
                'value' => function ($event) {
                    return date('Y-m-d', strtotime($this->date_to));
                },
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_AFTER_FIND => 'name',
                ],
                'value' => function ($event) {
                    return Html::decode($this->name);
                },
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_AFTER_FIND => 'description',
                ],
                'value' => function ($event) {
                    return Html::decode($this->description);
                },
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_AFTER_FIND => 'comment',
                ],
                'value' => function ($event) {
                    return Html::decode($this->comment);
                },
            ],
            [
                'class' => AttributeBehavior::className(),
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => 'phone',
                    ActiveRecord::EVENT_BEFORE_UPDATE => 'phone',
                    ActiveRecord::EVENT_AFTER_FIND    => 'phone',
                ],
                'value' => function (\yii\base\Event $event) {
                    if ($this->phone) {
                        if ($event->name == ActiveRecord::EVENT_BEFORE_INSERT || $event->name == ActiveRecord::EVENT_BEFORE_UPDATE) {
                                return preg_replace('/[^0-9]/u', '', $this->phone);
                        }  else {
                            return '+7 ' . Helper::formatPhone($this->phone,'');
                        }
                    }
                    return "";
                },
            ],
        ];
    }
    
    public function attributeLabels()
    {
        return [
            'name' => 'Название',
            'description' => 'Описание',
            'date_from' => 'Начало срока',
            'date_to' => 'Конец срока',
            'email' => 'Email',
            'phone' => 'Телефон',
        ];
    }


    public function rules()
    {
        retirn [
            [['name', 'description', 'date_from', 'date_to', 'email'], 'required'],
            [['description'], 'string'],
            [['max_price'], 'integer'],
            [['max_price'], 'number', 'min' => 0, 'max' => 2147483647],
            [['date_from', 'date_to', 'created_at', 'updated_at'], 'safe'],
            [['date_from', 'date_to'], 'date', 'format' => 'php:Y-m-d'],
            [['name'], 'string', 'max' => 64],
            [['email'], 'string', 'max' => 255],
            [['email'], 'email'],
            [['phone'], 'string', 'max' => 20],
            [['phone'], function ($attribute, $params) {
                if ($this->$attribute) {
                    $clearPhone = preg_replace('/[^0-9]/u', '', $this->$attribute);
                    if (mb_strlen($clearPhone, 'UTF-8') != 11) {
                        $this->addError($attribute, '...');
                    }
                }
            }],
            [['name', 'description', 'email', 'phone'], 'filter', 'filter' => '\yii\helpers\HtmlPurifier::process'],
            [['name', 'description', 'email', 'phone'], 'filter', 'filter' => '\yii\helpers\Html::encode'],
            [
                ['name'],
                'unique',
                'targetAttribute' => [
                    'name',
                    'description',
                    'email',
                    'date_from',
                    'date_to'
                ],
                'message' => '...',
                'when' => function () {
                    return $this->isNewRecord;
                }
            ],
            'date_to', function ($attribute, $params) {
                if (strtotime($this->$attribute) < strtotime($this->date_from)) {
                    $this->addError('date_to', '...');
                }
            }];
        ];
    }
    
    public function getFiles()
    {
        return $this
            ->hasMany(File::className(), ['id' => 'file_id'])
            ->viaTable('doc', ['doc_id' => 'id']);
    }

    public function setFilesForDelete($files)
    {
        if ($files) {
            $this->_filesForDelete = is_array($files) ? $files : explode(',', preg_replace('/([\d,]+)[,]&?/', '$1', $files));
        } else {
            $this->_filesForDelete = [];
        }
    }

    public function afterSave($insert, $changedAttributes)
    {
        \Yii::$app
            ->db
            ->createCommand()
            ->delete('doc', 'id = ' . $this->id)
            ->execute();

        if (!empty($this->_files)) {
            foreach ($this->_files as $file) {
                \Yii::$app
                    ->db
                    ->createCommand()
                    ->insert('doc', [
                        'id' => $this->id,
                        'file_id' => $file,
                        'attached_at' => new Expression('NOW()'),
                    ])->execute();
            }
        }

        if (!empty($this->_filesForDelete)) {
            foreach ($this->_filesForDelete as $fileId) {
                File::findOne($fileId)->delete();
            }
        }
        parent::afterSave($insert, $changedAttributes);
    }

    public function setFiles($files)
    {
        if ($files) {
            $this->_files = is_array($files) ? $files : explode(',', $files);
        } else {
            $this->_files = [];
        }
    }

    public function beforeDelete()
    {
        if ($this->files) {
            foreach ($this->files as $file) {
                if ($file->delete() === false) {
                    return false;
                }
            }
        }
        return parent::beforeDelete();
    }

    public static function find()
    {
        return \Yii::createObject(ActiceQuery::className(), [get_called_class()]);
    }

    public function hasLimitEditing()
    {
        $limitEditing = \Yii::$app->formatter->asTimestamp($this->created_at) + \Yii::$app->params['editingLimit'];
        
        if (time() >= $limitEditing) {
            return true;
        }
        
        return false;
    }
}
export default function(modelData = false) {
	var modelTemplate = _.template(`
	<div class="model model_status_<%= model.status %>" data-model>
		<% var costFormId = _.uniqueId('cost-form'); %>
		<div class="model__inner" data-model-id="<%= model.id %>" data-model-inner>
			<div class="model__actions">
				<% if(model.status === 3) { %>
					<button class="model__actions__item model__actions__item_cost" type="button"  data-modal="#<%= costFormId %>"></button>
				<% } %>
				<button class="model__actions__item model__actions__item_edit" type="button" data-edit></button>
				<button class="model__actions__item model__actions__item_delete" type="button" data-delete></button>
			</div>
			<div class="model__date" data-model-date>по <%= app.helpers.formatDate(model.date_to) %></div>
			<div class="model__info">
				<div class="model__name"><%= app.helpers.escape(model.name) %></div>
				<div class="model__contacts">
					<a href="mailto:<%= model.email %>" class="model__contact link"><%= model.email %></a>
					<% if (model.phone) { %>
					<span class="model__contact"><%= model.phone %></span>
					<% } %>
				</div>
				<div class="model__text"><%= app.helpers.multiline(app.helpers.escape(model.description)) %></div>
				<% if (model.files && model.files.length) { %>
				<ul class="files">
					<% _.each(model.files, function(item){ %>
						<li class="files__item"><a href="<%= app.helpers.escapeUrl(item.url) %>" target="_blank" class="link"><%= app.helpers.escape(item.name) %></a></li>
					<% }); %>
				</ul>
				<% } %>
			</div>
			<% if (model.costs && model.costs.length > 0) { %>
			<div class="costs">
				<div class="costs__item costs__item_title">
					<span class="costs__comment">Комментарий</span>
					<span class="costs__cost">Сумма</span>
					<span class="costs__commission">Коммисия</span>
				</div>
				<ul class="costs__list">
				<% _.each(model.costs, function(item){ %>
					<li class="costs__item" data-id="<%= item.id %>">
						<span class="costs__comment">
							<%= app.helpers.escape(item.comment) %>
						</span>
						<span class="costs__cost">
							<%= app.helpers.formatNumber(item.cost) %>&nbsp;<span class="rouble">a</span>
						</span>
						<span class="costs__commission">
							<%= app.helpers.formatNumber(item.commission) %>&nbsp;<span class="rouble">a</span>
						</span>
						<span class="costs__delete"></span>
					</li>
				<% }); %>
				</ul>
				<div class="costs__item costs__item_result">
					<span class="costs__comment">
						Итого:
					</span>
					<span class="costs__cost"><%= app.helpers.formatNumber(_.reduce(model.costs, function(memo, item){ return memo + item.cost; }, 0)) %>&nbsp;<span class="rouble">a</span></span>
					<span class="costs__commission"><%= app.helpers.formatNumber(_.reduce(model.costs, function(memo, item){ return memo + item.commission; }, 0)) %>&nbsp;<span class="rouble">a</span></span>
				</div>
			</div>
			<% } %>
			<form class="model__cost-form modal" data-status="<%= model.status %>" action="<%= app.config.urls.costs + model.id %>" id="<%= costFormId %>">
				<div class="model__cost-form__title title title_level_5">&laquo;<%= app.helpers.escape(model.name) %>&raquo; &mdash; добавить платеж</div>
				<input class="model__cost-form__field model__cost-form__field_inline field" placeholder="Сумма" name="cost" />
				<input class="model__cost-form__field model__cost-form__field_inline model__cost-form__field_commission field" placeholder="Комиссия" name="commission" value="20"/>
				<textarea class="model__cost-form__field field" placeholder="Комментарий" name="comment"></textarea>
				<button class="model__cost-form__button button" type="submit">Сохранить</button>
			</form>
		</div>
	</div>
	`);

	var askForDeleteTemplate = _.template(`
		<div class="model__delete-block" data-delete-block>
			<div class="model__name model__name_indent"><%= app.helpers.escape(model.name) %></div>
			<div class="model__text">Вы уверенны, что хотите удалить?</div>
			<button class="model__deleted button" type="button" data-deleted>УДАЛИТЬ</button>
			<button class="model__canceled button" type="button" data-canceled>ОТМЕНА</button>
		</div>
	`);

	var $wrapper = $(this);
	var html = modelTemplate({ model: modelData });
	var $block = $(html).appendTo($wrapper);
	var $modelInner = $wrapper.find('[data-model-inner]');
	var modelId = $wrapper.find('[data-model-id]').data('modelId');
	var $model = $wrapper.find('[data-model]');

	var initCostForm = function(){
		var $form = $model.find('.model__cost-form');
		$form.ajaxForm({
			type: 'post',
			beforeSubmit: function(){
				$form.find('button').attr('disabled', 'disabled');
			},
			success: function(data){
				alertify.success('Данные успешно сохранены');
				$.arcticmodal('close');
				$model.html(modelTemplate({ model: data }));
				modelData = data;

				initPlugins();
				initCostForm();
			},
			error: function(data){
				$form.find('button').removeAttr('disabled');
				alertify.error(data.responseJSON.message);
			}
		});

		$model.find(".costs__item");.each( function (el) {
			var id = $(this).data('id');
			var $removeButton = $(this).find(".costs__delete");
			$removeButton.on('click', function () {
				alertify
				.okBtn("Удалить")
				.cancelBtn("Отменить")
				.confirm("<div class='model__comment-form__title title title_level_5'> Удалить запись?</div>", function() {
					$.ajax({
						url: app.config.urls.costs + modelId,
						data: {cost : id},
						type: 'DELETE',
						contentType: 'application/json',
							dataType: 'json',
						success: function(data){
							alertify.success('Данные успешно сохранены');
							console.log(data);

							$model.html(modelTemplate({ model: data }));
							modelData = data;

							initPlugins();
							initCostForm();
						},
						error: function(data){
							alertify.error(data.responseJSON.message);
						}
					});
				}, function() {
					alertify.error("Отмена");
				});

			})
		})
	};

	var initPlugins = function(){
		$model.find('[data-modal]').plugin('modal-link');
		$model.plugins(['field', 'select']);
	};

	initPlugins();
	initCostForm();

	$wrapper.on('click', '[data-edit]', function () {
		$model.data('plugins', []);
		$model.empty().plugin('application', modelData, function(editTender){
			$model.html(modelTemplate({ model: editTender }));
			modelData = editTender;

			initPlugins();
			initCostForm();
		});
	});

	$wrapper.on('click', '[data-delete]', function () {
		$model.html(askForDeleteTemplate({ model: modelData }));
	});

	$wrapper.on('click', '[data-deleted]', function () {
		$.ajax({
			url: app.config.urls.models + modelId,
			type: 'DELETE',
			contentType: 'application/json',
			dataType: 'json',
			success: function(data) {
				$model.remove();
				alertify.logPosition("bottom right");
				alertify.error("Запись удалена");
			},
			error: function(data){
				alertify.error(data.responseJSON.message);
			}
		});
	});

	$wrapper.on('click', '[data-canceled]', function () {
		$model.html(modelTemplate({ model: modelData }));
	});
}
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.