feat: add frontend menu management system
parent
8c83876074
commit
8ef18d6d30
|
|
@ -2,3 +2,4 @@
|
|||
- Refactored visitor statistics calculation logic for better accuracy and performance.
|
||||
- Fixed incorrect aggregation in monthly and yearly statistics.
|
||||
- Adjusted footer contact information font style for better readability.
|
||||
- Added frontend menu management system in administrator module (navbar and left menu positions).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace backend\modules\administrator\controllers;
|
||||
|
||||
use Yii;
|
||||
use common\models\CmsMenuFrontend;
|
||||
use backend\modules\administrator\models\CmsMenuFrontendSearch;
|
||||
use yii\web\Controller;
|
||||
use yii\web\NotFoundHttpException;
|
||||
use yii\filters\VerbFilter;
|
||||
|
||||
/**
|
||||
* MenuFrontendController implements the CRUD actions for CmsMenuFrontend model.
|
||||
*/
|
||||
class MenuFrontendController extends Controller
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::class,
|
||||
'actions' => [
|
||||
'delete' => ['POST'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all CmsMenuFrontend models.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionIndex()
|
||||
{
|
||||
$searchModel = new CmsMenuFrontendSearch();
|
||||
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
||||
|
||||
return $this->render('index', [
|
||||
'searchModel' => $searchModel,
|
||||
'dataProvider' => $dataProvider,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a single CmsMenuFrontend model.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionView($id)
|
||||
{
|
||||
return $this->render('view', [
|
||||
'model' => $this->findModel($id),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CmsMenuFrontend model.
|
||||
* If creation is successful, the browser will be redirected to the 'view' page.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionCreate()
|
||||
{
|
||||
$model = new CmsMenuFrontend();
|
||||
|
||||
if ($model->load(Yii::$app->request->post()) && $model->save()) {
|
||||
return $this->redirect(['view', 'id' => $model->id]);
|
||||
}
|
||||
|
||||
return $this->render('create', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing CmsMenuFrontend model.
|
||||
* If update is successful, the browser will be redirected to the 'view' page.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionUpdate($id)
|
||||
{
|
||||
$model = $this->findModel($id);
|
||||
|
||||
if ($model->load(Yii::$app->request->post()) && $model->save()) {
|
||||
return $this->redirect(['view', 'id' => $model->id]);
|
||||
}
|
||||
|
||||
return $this->render('update', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing CmsMenuFrontend model.
|
||||
* If deletion is successful, the browser will be redirected to the 'index' page.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionDelete($id)
|
||||
{
|
||||
$this->findModel($id)->delete();
|
||||
|
||||
return $this->redirect(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the CmsMenuFrontend model based on its primary key value.
|
||||
* If the model is not found, a 404 HTTP exception will be thrown.
|
||||
* @param integer $id
|
||||
* @return CmsMenuFrontend the loaded model
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
protected function findModel($id)
|
||||
{
|
||||
if (($model = CmsMenuFrontend::findOne($id)) !== null) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException('The requested page does not exist.');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace backend\modules\administrator\models;
|
||||
|
||||
use yii\base\Model;
|
||||
use yii\data\ActiveDataProvider;
|
||||
use common\models\CmsMenuFrontend;
|
||||
|
||||
/**
|
||||
* CmsMenuFrontendSearch represents the model behind the search form of `common\models\CmsMenuFrontend`.
|
||||
*/
|
||||
class CmsMenuFrontendSearch extends CmsMenuFrontend
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id', 'parent_id', 'sort_order', 'status', 'created_at', 'updated_at'], 'integer'],
|
||||
[['name', 'link', 'position'], 'safe'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function scenarios()
|
||||
{
|
||||
// bypass scenarios() implementation in the parent class
|
||||
return Model::scenarios();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates data provider instance with search query applied
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return ActiveDataProvider
|
||||
*/
|
||||
public function search($params)
|
||||
{
|
||||
$query = CmsMenuFrontend::find();
|
||||
|
||||
// add conditions that should always apply here
|
||||
|
||||
$dataProvider = new ActiveDataProvider([
|
||||
'query' => $query,
|
||||
'sort' => ['defaultOrder' => ['position' => SORT_ASC, 'sort_order' => SORT_ASC]]
|
||||
]);
|
||||
|
||||
$this->load($params);
|
||||
|
||||
if (!$this->validate()) {
|
||||
// uncomment the following line if you do not want to return any records when validation fails
|
||||
// $query->where('0=1');
|
||||
return $dataProvider;
|
||||
}
|
||||
|
||||
// grid filtering conditions
|
||||
$query->andFilterWhere([
|
||||
'id' => $this->id,
|
||||
'parent_id' => $this->parent_id,
|
||||
'sort_order' => $this->sort_order,
|
||||
'status' => $this->status,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
]);
|
||||
|
||||
$query->andFilterWhere(['like', 'name', $this->name])
|
||||
->andFilterWhere(['like', 'link', $this->link])
|
||||
->andFilterWhere(['like', 'position', $this->position]);
|
||||
|
||||
return $dataProvider;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
use common\models\CmsMenuFrontend;
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap4\ActiveForm;
|
||||
use yii\helpers\ArrayHelper;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $model common\models\CmsMenuFrontend */
|
||||
/* @var $form yii\widgets\ActiveForm */
|
||||
?>
|
||||
|
||||
<div class="cms-menu-frontend-form">
|
||||
|
||||
<?php $form = ActiveForm::begin(); ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'link')->textInput(['maxlength' => true]) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'position')->dropDownList(CmsMenuFrontend::getPositions()) ?>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'parent_id')->dropDownList(
|
||||
ArrayHelper::map(
|
||||
CmsMenuFrontend::find()
|
||||
->where(['parent_id' => null])
|
||||
->andFilterWhere(['<>', 'id', $model->id])
|
||||
->all(),
|
||||
'id',
|
||||
'name'
|
||||
),
|
||||
['prompt' => '-- เป็นเมนูหลัก --']
|
||||
) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'sort_order')->textInput(['type' => 'number']) ?>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<?= $form->field($model, 'status')->dropDownList([1 => 'ใช้งาน', 0 => 'ไม่ใช้งาน']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<?= Html::submitButton('บันทึก', ['class' => 'btn btn-success']) ?>
|
||||
</div>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
|
||||
</div>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $model common\models\CmsMenuFrontend */
|
||||
|
||||
$this->title = 'เพิ่มเมนู';
|
||||
$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']];
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><?= $this->title ?></h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= $this->render('_form', [
|
||||
'model' => $model,
|
||||
]) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
use common\models\CmsMenuFrontend;
|
||||
use yii\helpers\Html;
|
||||
use yii\grid\GridView;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $searchModel backend\modules\administrator\models\CmsMenuFrontendSearch */
|
||||
/* @var $dataProvider yii\data\ActiveDataProvider */
|
||||
|
||||
$this->title = 'จัดการเมนูหน้าบ้าน';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><?= $this->title ?></h4>
|
||||
<div class="heading-elements">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><?= Html::a('<i class="fa fa-plus"></i> เพิ่มเมนู', ['create'], ['class' => 'btn btn-sm btn-success']) ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= GridView::widget([
|
||||
'dataProvider' => $dataProvider,
|
||||
'filterModel' => $searchModel,
|
||||
'columns' => [
|
||||
['class' => 'yii\grid\SerialColumn'],
|
||||
[
|
||||
'attribute' => 'name',
|
||||
'value' => function ($model) {
|
||||
return ($model->parent_id ? '— ' : '') . $model->name;
|
||||
}
|
||||
],
|
||||
'link',
|
||||
[
|
||||
'attribute' => 'position',
|
||||
'filter' => CmsMenuFrontend::getPositions(),
|
||||
'value' => function ($model) {
|
||||
return CmsMenuFrontend::getPositions()[$model->position] ?? $model->position;
|
||||
}
|
||||
],
|
||||
'sort_order',
|
||||
[
|
||||
'attribute' => 'status',
|
||||
'filter' => [0 => 'ไม่ใช้งาน', 1 => 'ใช้งาน'],
|
||||
'value' => function ($model) {
|
||||
return $model->status ? 'ใช้งาน' : 'ไม่ใช้งาน';
|
||||
}
|
||||
],
|
||||
['class' => 'yii\grid\ActionColumn'],
|
||||
],
|
||||
]); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $model common\models\CmsMenuFrontend */
|
||||
|
||||
$this->title = 'แก้ไขเมนู: ' . $model->name;
|
||||
$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']];
|
||||
$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]];
|
||||
$this->params['breadcrumbs'][] = 'แก้ไข';
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><?= $this->title ?></h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= $this->render('_form', [
|
||||
'model' => $model,
|
||||
]) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
use common\models\CmsMenuFrontend;
|
||||
use yii\helpers\Html;
|
||||
use yii\widgets\DetailView;
|
||||
|
||||
/* @var $this yii\web\View */
|
||||
/* @var $model common\models\CmsMenuFrontend */
|
||||
|
||||
$this->title = $model->name;
|
||||
$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']];
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
\yii\web\YiiAsset::register($this);
|
||||
?>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title"><?= $this->title ?></h4>
|
||||
<div class="heading-elements">
|
||||
<ul class="list-inline mb-0">
|
||||
<li><?= Html::a('แก้ไข', ['update', 'id' => $model->id], ['class' => 'btn btn-sm btn-primary']) ?></li>
|
||||
<li><?= Html::a('ลบ', ['delete', 'id' => $model->id], [
|
||||
'class' => 'btn btn-sm btn-danger',
|
||||
'data' => [
|
||||
'confirm' => 'คุณแน่ใจหรือไม่ว่าต้องการลบรายการนี้?',
|
||||
'method' => 'post',
|
||||
],
|
||||
]) ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= DetailView::widget([
|
||||
'model' => $model,
|
||||
'attributes' => [
|
||||
'id',
|
||||
[
|
||||
'attribute' => 'parent_id',
|
||||
'value' => $model->parent ? $model->parent->name : '-- เป็นเมนูหลัก --',
|
||||
],
|
||||
'name',
|
||||
'link',
|
||||
[
|
||||
'attribute' => 'position',
|
||||
'value' => CmsMenuFrontend::getPositions()[$model->position] ?? $model->position,
|
||||
],
|
||||
'sort_order',
|
||||
[
|
||||
'attribute' => 'status',
|
||||
'value' => $model->status ? 'ใช้งาน' : 'ไม่ใช้งาน',
|
||||
],
|
||||
'created_at:datetime',
|
||||
'updated_at:datetime',
|
||||
],
|
||||
]) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -92,6 +92,7 @@ if (Yii::$app->user->can('administrator')) {
|
|||
['label' => '<span>เพิ่มผู้ใช้งาน</span>', 'url' => ['/administrator/user/create']],
|
||||
//['label' => '<span>เมนู</span>', 'url' => ['/administrator/menu/index']],
|
||||
]];
|
||||
$menu[] = ['label' => '<i class="fa fa-list"></i> <span>เมนูหน้าบ้าน</span>', 'url' => ['/administrator/menu-frontend/index']];
|
||||
$menu[] = ['label' => '<i class="fa fa-lock"></i> <span>ควบคุมสิทธิ์การเข้าถึง</span>', 'url' => ['/admin/assignment/index'], 'items' => [
|
||||
['label' => '<span>การกำหนด</span>', 'url' => ['/admin/assignment/index']],
|
||||
['label' => '<span>บทบาท</span>', 'url' => ['/admin/role/index']],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace common\models;
|
||||
|
||||
use Yii;
|
||||
use yii\behaviors\TimestampBehavior;
|
||||
|
||||
/**
|
||||
* This is the model class for table "cms_menu_frontend".
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $parent_id
|
||||
* @property string $name
|
||||
* @property string|null $link
|
||||
* @property string $position navbar, left_menu
|
||||
* @property int|null $sort_order
|
||||
* @property int|null $status
|
||||
* @property int|null $created_at
|
||||
* @property int|null $updated_at
|
||||
*
|
||||
* @property CmsMenuFrontend $parent
|
||||
* @property CmsMenuFrontend[] $cmsMenuFrontends
|
||||
*/
|
||||
class CmsMenuFrontend extends \yii\db\ActiveRecord
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function tableName()
|
||||
{
|
||||
return 'cms_menu_frontend';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
TimestampBehavior::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['parent_id', 'sort_order', 'status', 'created_at', 'updated_at'], 'integer'],
|
||||
[['name', 'position'], 'required'],
|
||||
[['name', 'link'], 'string', 'max' => 255],
|
||||
[['position'], 'string', 'max' => 50],
|
||||
[['parent_id'], 'exist', 'skipOnError' => true, 'targetClass' => CmsMenuFrontend::class, 'targetAttribute' => ['parent_id' => 'id']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'id' => 'ID',
|
||||
'parent_id' => 'เมนูหลัก',
|
||||
'name' => 'ชื่อเมนู',
|
||||
'link' => 'ลิงก์',
|
||||
'position' => 'ตำแหน่ง',
|
||||
'sort_order' => 'ลำดับ',
|
||||
'status' => 'สถานะ',
|
||||
'created_at' => 'สร้างเมื่อ',
|
||||
'updated_at' => 'แก้ไขเมื่อ',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets query for [[Parent]].
|
||||
*
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->hasOne(CmsMenuFrontend::class, ['id' => 'parent_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets query for [[CmsMenuFrontends]].
|
||||
*
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getCmsMenuFrontends()
|
||||
{
|
||||
return $this->hasMany(CmsMenuFrontend::class, ['parent_id' => 'id']);
|
||||
}
|
||||
|
||||
public static function getPositions()
|
||||
{
|
||||
return [
|
||||
'navbar' => 'Navbar (แถบเมนูบน)',
|
||||
'left_menu' => 'Left Menu (แถบเมนูข้าง)',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Handles the creation of table `{{%cms_menu_frontend}}`.
|
||||
*/
|
||||
class m260227_020845_create_cms_menu_frontend_table extends Migration
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function safeUp()
|
||||
{
|
||||
$this->createTable('{{%cms_menu_frontend}}', [
|
||||
'id' => $this->primaryKey(),
|
||||
'parent_id' => $this->integer()->defaultValue(null),
|
||||
'name' => $this->string(255)->notNull(),
|
||||
'link' => $this->string(255)->defaultValue(null),
|
||||
'position' => $this->string(50)->notNull()->comment('navbar, left_menu'),
|
||||
'sort_order' => $this->integer()->defaultValue(0),
|
||||
'status' => $this->smallInteger(1)->defaultValue(1),
|
||||
'created_at' => $this->integer(),
|
||||
'updated_at' => $this->integer(),
|
||||
]);
|
||||
|
||||
$this->addForeignKey(
|
||||
'fk-cms_menu_frontend-parent_id',
|
||||
'{{%cms_menu_frontend}}',
|
||||
'parent_id',
|
||||
'{{%cms_menu_frontend}}',
|
||||
'id',
|
||||
'CASCADE'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function safeDown()
|
||||
{
|
||||
$this->dropForeignKey('fk-cms_menu_frontend-parent_id', '{{%cms_menu_frontend}}');
|
||||
$this->dropTable('{{%cms_menu_frontend}}');
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue