diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fa27b2d..e96e2c60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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). diff --git a/backend/modules/administrator/controllers/MenuFrontendController.php b/backend/modules/administrator/controllers/MenuFrontendController.php new file mode 100644 index 00000000..92cf5474 --- /dev/null +++ b/backend/modules/administrator/controllers/MenuFrontendController.php @@ -0,0 +1,127 @@ + [ + '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.'); + } +} diff --git a/backend/modules/administrator/models/CmsMenuFrontendSearch.php b/backend/modules/administrator/models/CmsMenuFrontendSearch.php new file mode 100644 index 00000000..1c62e1b2 --- /dev/null +++ b/backend/modules/administrator/models/CmsMenuFrontendSearch.php @@ -0,0 +1,76 @@ + $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; + } +} diff --git a/backend/modules/administrator/views/menu-frontend/_form.php b/backend/modules/administrator/views/menu-frontend/_form.php new file mode 100644 index 00000000..352921c8 --- /dev/null +++ b/backend/modules/administrator/views/menu-frontend/_form.php @@ -0,0 +1,60 @@ + + +
+ + + +
+
+ field($model, 'name')->textInput(['maxlength' => true]) ?> +
+
+ field($model, 'link')->textInput(['maxlength' => true]) ?> +
+
+ +
+
+ field($model, 'position')->dropDownList(CmsMenuFrontend::getPositions()) ?> +
+
+ field($model, 'parent_id')->dropDownList( + ArrayHelper::map( + CmsMenuFrontend::find() + ->where(['parent_id' => null]) + ->andFilterWhere(['<>', 'id', $model->id]) + ->all(), + 'id', + 'name' + ), + ['prompt' => '-- เป็นเมนูหลัก --'] + ) ?> +
+
+ +
+
+ field($model, 'sort_order')->textInput(['type' => 'number']) ?> +
+
+ field($model, 'status')->dropDownList([1 => 'ใช้งาน', 0 => 'ไม่ใช้งาน']) ?> +
+
+ +
+ 'btn btn-success']) ?> +
+ + + +
diff --git a/backend/modules/administrator/views/menu-frontend/create.php b/backend/modules/administrator/views/menu-frontend/create.php new file mode 100644 index 00000000..9fcacd18 --- /dev/null +++ b/backend/modules/administrator/views/menu-frontend/create.php @@ -0,0 +1,21 @@ +title = 'เพิ่มเมนู'; +$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
+
+

title ?>

+
+
+ render('_form', [ + 'model' => $model, + ]) ?> +
+
diff --git a/backend/modules/administrator/views/menu-frontend/index.php b/backend/modules/administrator/views/menu-frontend/index.php new file mode 100644 index 00000000..e0602c23 --- /dev/null +++ b/backend/modules/administrator/views/menu-frontend/index.php @@ -0,0 +1,55 @@ +title = 'จัดการเมนูหน้าบ้าน'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+
+

title ?>

+
+
    +
  • เพิ่มเมนู', ['create'], ['class' => 'btn btn-sm btn-success']) ?>
  • +
+
+
+
+ $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'], + ], + ]); ?> +
+
diff --git a/backend/modules/administrator/views/menu-frontend/update.php b/backend/modules/administrator/views/menu-frontend/update.php new file mode 100644 index 00000000..a82b1277 --- /dev/null +++ b/backend/modules/administrator/views/menu-frontend/update.php @@ -0,0 +1,22 @@ +title = 'แก้ไขเมนู: ' . $model->name; +$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->id]]; +$this->params['breadcrumbs'][] = 'แก้ไข'; +?> +
+
+

title ?>

+
+
+ render('_form', [ + 'model' => $model, + ]) ?> +
+
diff --git a/backend/modules/administrator/views/menu-frontend/view.php b/backend/modules/administrator/views/menu-frontend/view.php new file mode 100644 index 00000000..4ac1e2e7 --- /dev/null +++ b/backend/modules/administrator/views/menu-frontend/view.php @@ -0,0 +1,56 @@ +title = $model->name; +$this->params['breadcrumbs'][] = ['label' => 'จัดการเมนูหน้าบ้าน', 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +\yii\web\YiiAsset::register($this); +?> +
+
+

title ?>

+
+
    +
  • $model->id], ['class' => 'btn btn-sm btn-primary']) ?>
  • +
  • $model->id], [ + 'class' => 'btn btn-sm btn-danger', + 'data' => [ + 'confirm' => 'คุณแน่ใจหรือไม่ว่าต้องการลบรายการนี้?', + 'method' => 'post', + ], + ]) ?>
  • +
+
+
+
+ $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', + ], + ]) ?> +
+
diff --git a/backend/themes/nikom/views/layouts/_menu.php b/backend/themes/nikom/views/layouts/_menu.php index 5d39a718..55c7ae4a 100755 --- a/backend/themes/nikom/views/layouts/_menu.php +++ b/backend/themes/nikom/views/layouts/_menu.php @@ -92,6 +92,7 @@ if (Yii::$app->user->can('administrator')) { ['label' => 'เพิ่มผู้ใช้งาน', 'url' => ['/administrator/user/create']], //['label' => 'เมนู', 'url' => ['/administrator/menu/index']], ]]; + $menu[] = ['label' => ' เมนูหน้าบ้าน', 'url' => ['/administrator/menu-frontend/index']]; $menu[] = ['label' => ' ควบคุมสิทธิ์การเข้าถึง', 'url' => ['/admin/assignment/index'], 'items' => [ ['label' => 'การกำหนด', 'url' => ['/admin/assignment/index']], ['label' => 'บทบาท', 'url' => ['/admin/role/index']], diff --git a/common/models/CmsMenuFrontend.php b/common/models/CmsMenuFrontend.php new file mode 100644 index 00000000..23f27f76 --- /dev/null +++ b/common/models/CmsMenuFrontend.php @@ -0,0 +1,103 @@ + 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 (แถบเมนูข้าง)', + ]; + } +} diff --git a/console/migrations/m260227_020845_create_cms_menu_frontend_table.php b/console/migrations/m260227_020845_create_cms_menu_frontend_table.php new file mode 100644 index 00000000..798e2eed --- /dev/null +++ b/console/migrations/m260227_020845_create_cms_menu_frontend_table.php @@ -0,0 +1,45 @@ +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}}'); + } +}