admin themes

This commit is contained in:
2024-09-03 16:29:44 +03:00
parent c325b156bd
commit 2ae5c4ac73
235 changed files with 33397 additions and 57 deletions

View File

@ -0,0 +1,22 @@
<?php
namespace kernel;
use kernel\Controller;
use kernel\services\AdminThemeService;
class AdminController extends Controller
{
protected AdminThemeService $adminThemeService;
protected function init()
{
$this->adminThemeService = new AdminThemeService();
$active_theme = $this->adminThemeService->getActiveAdminThemeInfo();
$this->cgView->layoutPath = getConst($active_theme['layout_path']);
$this->cgView->layout = "/" . $active_theme['layout'];
$this->cgView->addVarToLayout("resources", $active_theme['resource']);
}
}

View File

@ -38,6 +38,7 @@ class App
public function setRouting(): void
{
include KERNEL_DIR . "/routs/admin.php";
include ROOT_DIR . "/rout.php";
}

View File

@ -2,9 +2,14 @@
namespace kernel;
use app\helpers\Debug;
class CgView
{
public string $viewPath = '';
public string $layoutPath = '';
public array $varToLayout = [];
public bool|string $layout = false;
public function __construct()
@ -26,29 +31,47 @@ class CgView
return $content;
}
public function addVarToLayout($key, $value): void
{
$this->varToLayout[$key] = $value;
}
private function createContent(string $view, array $data = []): false|string
{
ob_start();
foreach ($data as $key => $datum){
foreach ($data as $key => $datum) {
${"$key"} = $datum;
}
include ($this->viewPath . $view);
include($this->viewPath . $view);
$content = ob_get_contents();
ob_end_clean ();
ob_end_clean();
ob_start();
$file_content = $content;
if ($this->layout){
if (file_exists($this->viewPath . $this->layout)){
include ($this->viewPath . $this->layout);
$layoutPath = $this->viewPath;
if ($this->layout) {
if ($this->layoutPath !== '') {
$layoutPath = $this->layoutPath;
}
if (file_exists($layoutPath . $this->layout)) {
if ($this->varToLayout){
foreach ($this->varToLayout as $key => $datum) {
${"$key"} = $datum;
}
}
include($layoutPath . $this->layout);
$file_content = ob_get_contents();
}
}
ob_end_clean ();
ob_end_clean();
return $file_content;
}

225
kernel/Request.php Normal file
View File

@ -0,0 +1,225 @@
<?php
namespace kernel;
use Rakit\Validation\Validator;
#[\AllowDynamicProperties]
class Request
{
/**
* @var string $host Абсолютный адрес сервера
*/
public string $host;
/**
* @var array $headers Заголовки запроса
*/
public array $headers;
/**
* @var array
*/
public array $data = [];
/**
* @var array
*/
public array $errors = [];
public function __construct()
{
$this->headers = $this->getRequestHeaders();
$this->load();
}
/**
* @return array
*/
public function rules(): array
{
return [];
}
/**
* @return array
*/
public function messages(): array
{
return [];
}
/**
* Возвращает абсолютный адрес сервера.
* @return string
*/
public function getHost(): string
{
if ($this->host !== null) {
return $this->host;
}
$http = $this->getIsSecure() ? 'https' : 'http';
if ($this->headerExist('Host')) {
$this->host = $http . '://' . $this->getHeader('Host');
} elseif (isset($_SERVER['SERVER_NAME'])) {
$this->host = $http . '://' . $_SERVER['SERVER_NAME'];
}
return $this->host;
}
/**
* Возвращает true если шифрование https, иначе false.
* @return bool
*/
public function getIsSecure(): bool
{
if (isset($_SERVER['HTTPS']) && (strcasecmp($_SERVER['HTTPS'], 'on') === 0 || $_SERVER['HTTPS'] == 1)) {
return true;
}
return false;
}
/**
* Проверяет был ли передан заголовок запроса.
* @return bool
*/
public function headerExist($header): bool
{
return isset($this->headers[$header]);
}
/**
* Возвращает заголовок запроса
* @param string $header Заголовок.
* @param mixed $defaultValue Значение если, параметр не передан.
* @return mixed|null
*/
public function getHeader($header, $defaultValue = null): mixed
{
return $this->headers[$header] ?? $defaultValue;
}
/**
* Возвращает GET - параметр.
* @param string $param Параметр.
* @param mixed $defaultValue Значение если, параметр не передан.
* @return mixed
*/
public function get($param = null, $defaultValue = null): mixed
{
if (is_null($param)) {
return $_GET;
}
return $_GET[$param] ?? $defaultValue;
}
/**
* Возвращает POST - параметр.
* @param string $param Параметр.
* @param mixed $defaultValue Значение если, параметр не передан.
* @return mixed
*/
public function post($param = null, $defaultValue = null): mixed
{
if (is_null($param)) {
return $_POST;
}
return $_POST[$param] ?? $defaultValue;
}
/**
* Был ли POST - запрос.
* @return bool
*/
public function isPost(): bool
{
return ($_SERVER['REQUEST_METHOD'] === 'POST');
}
/**
* Был ли GET - запрос.
* @return bool
*/
public function isGet(): bool
{
return ($_SERVER['REQUEST_METHOD'] === 'GET');
}
/**
* Загружаем свойсва
*/
public function load(): void
{
if (!empty($_REQUEST)) {
foreach ($_REQUEST as $key => $item) {
$this->{$key} = $item;
$this->data[$key] = $item;
}
}
}
/**
* @return bool
*/
public function validate(): bool
{
if (!empty($this->data)) {
$valid = new Validator();
$validation = $valid->make($this->data, $this->rules());
$validation->setMessages($this->messages());
$validation->validate();
if ($validation->fails()) {
$this->errors = $validation->errors();
return false;
}
}
return true;
}
/**
* @return array
*/
public function getMessagesArray(): array
{
$msgs = [];
if($this->errors){
foreach ($this->errors->toArray() as $item){
$msgs[] = array_values($item)[0];
}
}
return $msgs;
}
/**
* @return array
*/
protected function getRequestHeaders(): array
{
$headers = array();
foreach ($_SERVER as $key => $value) {
if (substr($key, 0, 5) <> 'HTTP_') {
continue;
}
$header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
$headers[$header] = $value;
}
return $headers;
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* @var $content
* @var string $resources
*/
?>
<!doctype html>
<html lang="en">
<head>
<title>Sidebar 01</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700,800,900" rel="stylesheet">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="<?=$resources?>/css/style.css">
</head>
<body>
<div class="wrapper d-flex align-items-stretch">
<nav id="sidebar">
<div class="p-4 pt-5">
<a href="#" class="img logo rounded-circle mb-5" style="background-image: url(/resources/admin_theme/images/logo.jpg);"></a>
<?php \kernel\widgets\MenuWidget::create()->run(); ?>
<div class="footer">
</div>
</div>
</nav>
<!-- Page Content -->
<div id="content" class="p-4 p-md-5">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="btn btn-primary">
<i class="fa fa-bars"></i>
<span class="sr-only">Toggle Menu</span>
</button>
<button class="btn btn-dark d-inline-block d-lg-none ml-auto" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<i class="fa fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Portfolio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<?= $content ?>
</div>
</div>
<script src="<?=$resources?>/js/jquery.min.js"></script>
<script src="<?=$resources?>/js/popper.js"></script>
<script src="<?=$resources?>/js/bootstrap.min.js"></script>
<script src="<?=$resources?>/js/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,10 @@
{
"name": "Default",
"version": "0.1",
"description": "Default admin theme",
"preview": "preview.png",
"resource": "/resources/default",
"resource_path": "{RESOURCES}/default",
"layout": "main.php",
"layout_path": "{KERNEL_ADMIN_THEMES}/default/layout"
}

View File

@ -0,0 +1,72 @@
<?php
/**
* @var $content
* @var string $resources
*/
?>
<!doctype html>
<html lang="en">
<head>
<title>Sidebar 01</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700,800,900" rel="stylesheet">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="<?=$resources?>/css/style.css">
</head>
<body>
<div class="wrapper d-flex align-items-stretch">
<nav id="sidebar">
<div class="p-4 pt-5">
<a href="#" class="img logo rounded-circle mb-5" style="background-image: url(<?=$resources?>/images/33.png);"></a>
<?php \kernel\widgets\MenuWidget::create()->run(); ?>
<div class="footer">
</div>
</div>
</nav>
<!-- Page Content -->
<div id="content" class="p-4 p-md-5">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="btn btn-primary">
<i class="fa fa-bars"></i>
<span class="sr-only">Toggle Menu</span>
</button>
<button class="btn btn-dark d-inline-block d-lg-none ml-auto" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<i class="fa fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Portfolio</a>
</li>
</ul>
</div>
</div>
</nav>
<?= $content ?>
</div>
</div>
<script src="<?=$resources?>/js/jquery.min.js"></script>
<script src="<?=$resources?>/js/popper.js"></script>
<script src="<?=$resources?>/js/bootstrap.min.js"></script>
<script src="<?=$resources?>/js/main.js"></script>
</body>
</html>

View File

@ -0,0 +1,10 @@
{
"name": "Simple",
"version": "0.1",
"description": "Simple admin theme",
"preview": "preview.png",
"resource": "/resources/simple",
"resource_path": "{RESOURCES}/simple",
"layout": "main.php",
"layout_path": "{KERNEL_ADMIN_THEMES}/simple/layout"
}

View File

@ -78,12 +78,14 @@ class MigrationController extends ConsoleController
public function actionRollback(): void
{
try {
$step = $this->argv['step'] ?? 1;
$dmr = new DatabaseMigrationRepository(App::$db->capsule->getDatabaseManager(), 'migration');
$m = new Migrator($dmr, App::$db->capsule->getDatabaseManager(), new Filesystem());
//$migrationPaths = array_merge(App::$migrationsPaths, [WORKSPACE_DIR . '/console/migrations']);
$migrationPaths = [ROOT_DIR . '/console/migrations'];
$res = $m->rollback($migrationPaths);
$migrationPaths = [ROOT_DIR . '/migrations'];
$res = $m->rollback($migrationPaths, ['step' => $step]);
print_r($step);
foreach ($res as $re){
$this->out->r(basename($re), 'green');
}

View File

@ -18,6 +18,9 @@ use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
const DISABLE_STATUS = 0;
const ACTIVE_STATUS = 1;
protected $table = 'menu';
protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status'];
protected array $dates = ['deleted_at'];
@ -43,4 +46,15 @@ class Menu extends Model
return false;
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::DISABLE_STATUS => "Не активный",
self::ACTIVE_STATUS => "Активный",
];
}
}

40
kernel/models/Option.php Normal file
View File

@ -0,0 +1,40 @@
<?php
namespace kernel\models;
use Illuminate\Database\Eloquent\Model;
class Option extends Model
{
const DISABLE_STATUS = 0;
const ACTIVE_STATUS = 1;
protected $table = 'option';
protected $fillable = ['key', 'value', 'label', 'status', 'created_at', 'updated_at'];
protected array $dates = ['deleted_at'];
public static function labels(): array
{
return [
'key' => 'Ключ',
'value' => 'Значение',
'label' => 'Заголовок',
'status' => 'Статус',
'created_at' => 'Дата создания',
'updated_at' => 'Дата редактирования',
];
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::DISABLE_STATUS => "Не активный",
self::ACTIVE_STATUS => "Активный",
];
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace kernel\modules\admin_themes\controllers;
use app\helpers\Debug;
use DirectoryIterator;
use JetBrains\PhpStorm\NoReturn;
use kernel\AdminController;
use kernel\Controller;
use kernel\models\Option;
use kernel\Request;
use kernel\services\AdminThemeService;
class AdminThemeController extends AdminController
{
protected function init(): void
{
parent::init();
$this->cgView->viewPath = KERNEL_MODULES_DIR . "/admin_themes/views/";
}
public function actionIndex(): void
{
$admin_theme_paths = Option::where("key", "admin_theme_paths")->first();
$dirs = [];
if ($admin_theme_paths){
$path = json_decode($admin_theme_paths->value);
foreach ($path->paths as $p){
$dirs[] = getConst($p);
}
}
$info_to_table = [];
$meta = [];
$meta['columns'] = ["preview" => "Превью", "name" => "Название", "version" => "Версия", "description" => "Описание"];
$meta['params'] = ["class" => "table table-bordered"];
$meta['perPage'] = 10;
$meta['baseUrl'] = "/admin/settings/admin-themes";
$meta['currentPage'] = 1;
$info_to_table['meta'] = $meta;
$themes_info = [];
foreach ($dirs as $dir){
$i = 1;
foreach (new DirectoryIterator($dir) as $fileInfo) {
$info = [];
if($fileInfo->isDot()) continue;
$info['id'] = $i;
$themes_info[] = array_merge($info, $this->adminThemeService->getAdminThemeInfo($fileInfo->getPathname()));
$i++;
}
}
$info_to_table['meta']['total'] = count($themes_info);
$info_to_table['data'] = $themes_info;
$this->cgView->render("index.php", ['json' => json_encode($info_to_table, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)]);
}
#[NoReturn] public function actionActivate(): void
{
$request = new Request();
$this->adminThemeService->setActiveAdminTheme($request->get("p"));
$this->cgView->render("view.php", ['data' => $this->adminThemeService->getAdminThemeInfo($request->get("p"))]);
}
}

View File

@ -0,0 +1,29 @@
<?php
/**
* @var $json string
*/
use app\helpers\Debug;
use Itguild\EloquentTable\EloquentDataProvider;
use Itguild\EloquentTable\ListEloquentTable;
use kernel\models\Option;
$table = new \Itguild\Tables\ListJsonTable($json);
$table->columns([
'preview' => function ($data) {
return "<img src='$data' width='200px'>";
}
]);
$table->addAction(function ($row, $url){
$path = $row['path'];
$active_admin_theme = Option::where("key", "active_admin_theme")->first();
$btn = "<a class='btn btn-primary' href='$url/activate/?p=$path' style='margin: 3px; width: 150px;' >Активировать</a>";;
if ($path === $active_admin_theme->value){
$btn = "Активна";
}
return $btn;
});
$table->create();
$table->render();

View File

@ -0,0 +1,30 @@
<?php
/**
* @var array $data
*/
use kernel\IGTabel\btn\DangerBtn;
use kernel\IGTabel\btn\PrimaryBtn;
use kernel\IGTabel\btn\SuccessBtn;
$table_info = [
"meta" => [
"rows" => ["preview" => "Превью", "name" => "Название", "version" => "Версия", "description" => "Описание"],
"params" => ["class" => "table table-bordered"],
"baseUrl" => "/admin/settings/admin-themes",
],
"data" => $data
];
$table = new \Itguild\Tables\ViewJsonTable(json_encode($table_info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
$table->rows([
'preview' => function ($data) {
return "<img src='$data' width='500px'>";
}
]);
$table->beforePrint(function () {
$btn = PrimaryBtn::create("Список", "/admin/settings/admin-themes")->fetch();
return $btn;
});
$table->create();
$table->render();

View File

@ -0,0 +1,107 @@
<?php
namespace kernel\modules\menu\controllers;
use app\helpers\Debug;
use app\models\forms\CreateMenuForm;
use app\services\MenuService;
use Exception;
use JetBrains\PhpStorm\NoReturn;
use kernel\Controller;
use kernel\models\Menu;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
class MenuController extends Controller
{
protected function init(): void
{
$this->cgView->viewPath = KERNEL_MODULES_DIR . "/menu/views/";
$this->cgView->layoutPath = ROOT_DIR . "/views/admin/";
$this->cgView->layout = "layouts/main.php";
}
public function actionCreate(): void
{
$this->cgView->render("form.php");
}
#[NoReturn] public function actionAdd(): void
{
$menuForm = new CreateMenuForm();
$menuService = new MenuService();
$menuForm->load($_REQUEST);
if ($menuForm->validate()){
$menuItem = $menuService->create($menuForm);
if ($menuItem){
$this->redirect("/admin/settings/menu/" . $menuItem->id);
}
}
$this->redirect("/admin/settings/menu/create");
}
/**
* @throws Exception
*/
public function actionIndex($page_number = 1): void
{
$this->cgView->render("index.php", ['page_number' => $page_number]);
}
/**
* @throws Exception
*/
public function actionView($id): void
{
$menuItem = Menu::find($id);
if (!$menuItem){
throw new Exception(message: "The menu item not found");
}
$this->cgView->render("view.php", ['menu' => $menuItem]);
}
/**
* @throws RuntimeError
* @throws SyntaxError
* @throws LoaderError|Exception
*/
public function actionUpdate($id): void
{
$model = Menu::find($id);
if (!$model){
throw new Exception(message: "The menu item not found");
}
$this->cgView->render("form.php", ['model' => $model]);
}
/**
* @throws Exception
*/
public function actionEdit($id): void
{
$menuItem = Menu::find($id);
if (!$menuItem){
throw new Exception(message: "The menu item not found");
}
$menuForm = new CreateMenuForm();
$menuService = new MenuService();
$menuForm->load($_REQUEST);
if ($menuForm->validate()){
$menuItem = $menuService->update($menuForm, $menuItem);
if ($menuItem){
$this->redirect("/admin/settings/menu/" . $menuItem->id);
}
}
$this->redirect("/admin/settings/menu/update/" . $id);
}
#[NoReturn] public function actionDelete($id): void
{
Menu::find($id)->delete();
$this->redirect("/admin/settings/menu/");
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace kernel\modules\menu\models;
use app\helpers\Debug;
use Illuminate\Database\Eloquent\Model;
/**
* @property int $id
* @property int parent_id
* @property string icon_file
* @property string icon_font
* @property string label
* @property string url
* @property int status
* @method static find($id)
*/
class Menu extends Model
{
const DISABLE_STATUS = 0;
const ACTIVE_STATUS = 1;
protected $table = 'menu';
protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status'];
protected array $dates = ['deleted_at'];
public static function labels(): array
{
return [
'parent_id' => 'Родительский пункт меню',
'icon_file' => 'Путь к иконке',
'icon_font' => 'Иконка',
'label' => 'Заголовок',
'url' => 'URL',
'status' => 'Статус',
];
}
public static function getChild(int $id)
{
$collection = Menu::where("parent_id", $id)->get();
if (!$collection->isEmpty()){
return $collection;
}
return false;
}
/**
* @return string[]
*/
public static function getStatus(): array
{
return [
self::DISABLE_STATUS => "Не активный",
self::ACTIVE_STATUS => "Активный",
];
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* @var Menu $model
*/
use kernel\models\Menu;
$form = new \itguild\forms\ActiveForm();
$form->beginForm(isset($model) ? "/admin/settings/menu/edit/" . $model->id : "/admin/menu");
$form->field(class: \itguild\forms\inputs\Select::class, name: "parent_id", params: [
'class' => "form-control",
'value' => $model->parent_id ?? ''
])
->setLabel("Родительский пункт меню")
->setOptions(\app\services\MenuService::createLabelArr())
->render();
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "icon_file", params: [
'class' => "form-control",
'value' => $model->icon_file ?? ''
])
->setLabel("Путь к иконке")
->render();
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "icon_font", params: [
'class' => "form-control",
'value' => $model->icon_font ?? ''
])
->setLabel("Иконка")
->render();
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "label", params: [
'class' => "form-control",
'value' => $model->label ?? ''
])
->setLabel("Заголовок")
->render();
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "url", params: [
'class' => "form-control",
'value' => $model->url ?? ''
])
->setLabel("URL")
->render();
$form->field(class: \itguild\forms\inputs\Select::class, name: "status", params: [
'class' => "form-control",
'value' => $model->status ?? '1'
])
->setLabel("Статус")
->setOptions(Menu::getStatus())
->render();
?>
<div class="row">
<div class="col-sm-2">
<?php
$form->field(\itguild\forms\inputs\Button::class, name: "btn-submit", params: [
'class' => "btn btn-primary ",
'value' => 'Отправить',
'typeInput' => 'submit'
])
->render();
?>
</div>
<div class="col-sm-2">
<?php
$form->field(\itguild\forms\inputs\Button::class, name: "btn-reset", params: [
'class' => "btn btn-warning",
'value' => 'Сбросить',
'typeInput' => 'reset'
])
->render();
?>
</div>
</div>
<?php
$form->endForm();

View File

@ -0,0 +1,49 @@
<?php
/**
* @var \Illuminate\Database\Eloquent\Collection $menuItem
* @var int $page_number
*/
use app\tables\columns\menu\MenuDeleteActionColumn;
use app\tables\columns\menu\MenuEditActionColumn;
use app\tables\columns\menu\MenuViewActionColumn;
use Itguild\EloquentTable\EloquentDataProvider;
use Itguild\EloquentTable\ListEloquentTable;
use kernel\IGTabel\btn\PrimaryBtn;
use kernel\models\Menu;
$table = new ListEloquentTable(new EloquentDataProvider(Menu::class, [
'currentPage' => $page_number,
'perPage' => 8,
'params' => ["class" => "table table-bordered", "border" => "2"],
'baseUrl' => "/admin/settings/menu",
]));
$table->columns([
'parent_id' => (function ($data) {
if ($data == 0) return null;
return Menu::find($data)->label;
}),
'created_at' => function ($data) {
if (!$data){
return null;
}
return (new DateTimeImmutable($data))->format("d-m-Y");
},
'updated_at' => function ($data) {
if (!$data){
return null;
}
return (new DateTimeImmutable($data))->format("d-m-Y");
}
]);
$table->beforePrint(function () {
return PrimaryBtn::create("Создать", "/admin/menu/create")->fetch();
//return (new PrimaryBtn("Создать", "/admin/user/create"))->fetch();
});
$table->addAction(MenuViewActionColumn::class);
$table->addAction(MenuEditActionColumn::class);
$table->addAction(MenuDeleteActionColumn::class);
$table->create();
$table->render();

View File

@ -0,0 +1,51 @@
<?php
/**
* @var \Illuminate\Database\Eloquent\Collection $menu
*/
use app\models\User;
use Itguild\EloquentTable\ViewEloquentTable;
use Itguild\EloquentTable\ViewJsonTableEloquentModel;
use kernel\IGTabel\btn\DangerBtn;
use kernel\IGTabel\btn\PrimaryBtn;
use kernel\IGTabel\btn\SuccessBtn;
use kernel\models\Menu;
$table = new ViewEloquentTable(new ViewJsonTableEloquentModel($menu, [
'params' => ["class" => "table table-bordered", "border" => "2"],
'baseUrl' => "/admin/menu",
]));
$r = new ViewJsonTableEloquentModel($menu, [
'params' => ["class" => "table table-bordered", "border" => "2"],
'baseUrl' => "/admin/menu",
]);
\app\helpers\Debug::dd($r->getJson());
$table->beforePrint(function () use ($menu) {
$btn = PrimaryBtn::create("Список", "/admin/settings/menu")->fetch();
$btn .= SuccessBtn::create("Редактировать", "/admin/settings/menu/update/" . $menu->id)->fetch();
$btn .= DangerBtn::create("Удалить", "/admin/settings/menu/delete/" . $menu->id)->fetch();
return $btn;
});
$table->rows([
'parent_id' => (function ($data) {
if ($data == 0) return null;
return Menu::find($data)->label;
}),
'created_at' => function ($data) {
if (!$data){
return null;
}
return (new DateTimeImmutable($data))->format("d-m-Y");
},
'updated_at' => function ($data) {
if (!$data){
return null;
}
return (new DateTimeImmutable($data))->format("d-m-Y");
}
]);
$table->create();
$table->render();

52
kernel/routs/admin.php Normal file
View File

@ -0,0 +1,52 @@
<?php
use app\controllers\MainController;
use kernel\App;
use kernel\modules\admin_themes\controllers\AdminThemeController;
use Phroute\Phroute\RouteCollector;
App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){
App::$collector->group(["prefix" => "user"], callback: function (RouteCollector $router){
App::$collector->get('/', [\app\controllers\UserController::class, 'actionIndex']);
App::$collector->get('/page/{page_number}', [\app\controllers\UserController::class, 'actionIndex']);
App::$collector->get('/create', [\app\controllers\UserController::class, 'actionCreate']);
App::$collector->post("/", [\app\controllers\UserController::class, 'actionAdd']);
App::$collector->get('/{id}', [\app\controllers\UserController::class, 'actionView']);
App::$collector->any('/update/{id}', [\app\controllers\UserController::class, 'actionUpdate']);
App::$collector->any("/edit/{id}", [\app\controllers\UserController::class, 'actionEdit']);
App::$collector->get('/delete/{id}', [\app\controllers\UserController::class, 'actionDelete']);
});
App::$collector->group(["prefix" => "post"], function (RouteCollector $router){
App::$collector->get('/', [\app\controllers\PostController::class, 'actionIndex']);
App::$collector->get('/page/{page_number}', [\app\controllers\PostController::class, 'actionIndex']);
App::$collector->get('/create', [\app\controllers\PostController::class, 'actionCreate']);
App::$collector->post("/", [\app\controllers\PostController::class, 'actionAdd']);
App::$collector->get('/{id}', [\app\controllers\PostController::class, 'actionView']);
App::$collector->any('/update/{id}', [\app\controllers\PostController::class, 'actionUpdate']);
App::$collector->any("/edit/{id}", [\app\controllers\PostController::class, 'actionEdit']);
App::$collector->get('/delete/{id}', [\app\controllers\PostController::class, 'actionDelete']);
});
App::$collector->group(["prefix" => "settings"], function (RouteCollector $router){
App::$collector->group(["prefix" => "menu"], function (RouteCollector $router){
App::$collector->get('/', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']);
App::$collector->get('/page/{page_number}', [\kernel\modules\menu\controllers\MenuController::class, 'actionIndex']);
App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']);
App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']);
App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']);
App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']);
App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']);
App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']);
});
App::$collector->group(["prefix" => "admin-themes"], function (RouteCollector $router){
App::$collector->get('/', [AdminThemeController::class, 'actionIndex']);
App::$collector->get('/activate', [AdminThemeController::class, 'actionActivate']);
// App::$collector->get('/create', [\kernel\modules\menu\controllers\MenuController::class, 'actionCreate']);
// App::$collector->post("/", [\kernel\modules\menu\controllers\MenuController::class, 'actionAdd']);
// App::$collector->get('/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionView']);
// App::$collector->any('/update/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionUpdate']);
// App::$collector->any("/edit/{id}", [\kernel\modules\menu\controllers\MenuController::class, 'actionEdit']);
// App::$collector->get('/delete/{id}', [\kernel\modules\menu\controllers\MenuController::class, 'actionDelete']);
});
});
});

View File

@ -0,0 +1,56 @@
<?php
namespace kernel\services;
use kernel\models\Option;
class AdminThemeService
{
protected Option $option;
protected string $active_theme;
public function __construct()
{
$this->option = new Option();
$this->findActiveAdminTheme();
}
public function findActiveAdminTheme(): void
{
$model = Option::where("key", "active_admin_theme")->first();
$this->active_theme = $model->value;
}
public function getActiveAdminTheme(): string
{
return $this->active_theme;
}
public function setActiveAdminTheme(string $theme): void
{
$active_admin_theme = Option::where("key", "active_admin_theme")->first();
$active_admin_theme->value = $theme;
$active_admin_theme->save();
}
public function getActiveAdminThemeInfo(): false|array|string
{
return $this->getAdminThemeInfo($this->active_theme);
}
public function getAdminThemeInfo(string $theme): false|array|string
{
$info = [];
$info['path'] = $theme;
if (file_exists($theme . "/manifest.json")){
$manifest = file_get_contents($theme . "/manifest.json");
$manifest = json_decode($manifest, true);
$manifest['preview'] = $manifest['resource'] . "/" . $manifest['preview'];
$info = array_merge($info, $manifest);
}
return $info;
}
}