Snippets

Created by Илья Караваев last modified
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 }));
    });
}

Comments (0)

HTTPS SSH

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