diff --git a/app/Http/Controllers/Admin/Menu/SystemStatus/Children/GateAbilitiesMenuItemController.php b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/GateAbilitiesMenuItemController.php
new file mode 100644
index 0000000..bd88be1
--- /dev/null
+++ b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/GateAbilitiesMenuItemController.php
@@ -0,0 +1,25 @@
+name = 'adminMenu.items.systemStatus.gateAbilities';
+
+ $this->slug = 'gates';
+
+ $this->iconClasses = 'nav-icon icon-wrench';
+ }
+
+ public function handle(Request $request)
+ {
+ $gates = Gate::abilities();
+ return view('admin.menu.systemStatus.gates')->with(compact('gates'));
+ }
+}
diff --git a/app/Http/Controllers/Admin/Menu/SystemStatus/Children/RouteListMenuItemController.php b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/RouteListMenuItemController.php
new file mode 100644
index 0000000..c0db2de
--- /dev/null
+++ b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/RouteListMenuItemController.php
@@ -0,0 +1,39 @@
+name = 'adminMenu.items.systemStatus.routes';
+
+ $this->slug = 'routes';
+
+ $this->iconClasses = 'nav-icon icon-wrench';
+ }
+
+ public function handle(Request $request)
+ {
+ $routes = Route::getRoutes()->getRoutes();
+ $routes = collect($routes)->map(function($route){
+ /** @var \Illuminate\Routing\Route $route */
+ $action = explode('@', $route->getActionName());
+ return [
+ 'methods' => $route->methods(),
+ 'uri' => $route->uri(),
+ 'name' => $route->getName(),
+ 'action' => [
+ 'controller' => isset($action[0]) ? $action[0] : '',
+ 'method' => isset($action[1]) ? $action[1] : '',
+ ],
+ 'middlewares' => $route->middleware(),
+ ];
+ })->all();
+ return view('admin.menu.systemStatus.routes')->with(compact('routes'));
+ }
+}
diff --git a/app/Http/Controllers/Admin/Menu/SystemStatus/Children/SystemMenuItemController.php b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/SystemMenuItemController.php
new file mode 100644
index 0000000..b5d2638
--- /dev/null
+++ b/app/Http/Controllers/Admin/Menu/SystemStatus/Children/SystemMenuItemController.php
@@ -0,0 +1,118 @@
+name = 'adminMenu.items.systemStatus.system';
+
+ $this->slug = 'system';
+
+ $this->iconClasses = 'nav-icon icon-wrench';
+ }
+
+ public function handle(Request $request)
+ {
+ $systemInfo = collect([
+ [
+ 'name' => 'OS',
+ 'value' => php_uname('s') . ' ' . php_uname('r'),
+ ],
+ [
+ 'name' => 'OS Version',
+ 'value' => php_uname('v'),
+ ],
+ [
+ 'name' => 'Server',
+ 'value' => $_SERVER['SERVER_SOFTWARE']
+ ],
+ [
+ 'name' => 'Timezone',
+ 'value' => date_default_timezone_get()
+ ],
+ [
+ 'name' => 'PHP Version',
+ 'value' => phpversion()
+ ],
+ [
+ 'name' => 'PHP Post Max Size',
+ 'value' => ini_get('post_max_size')
+ ],
+ [
+ 'name' => 'PHP Upload Max Filesize',
+ 'value' => ini_get('upload_max_filesize')
+ ],
+ [
+ 'name' => 'PHP Max Execution Time',
+ 'value' => ini_get('max_execution_time')
+ ],
+ [
+ 'name' => 'PHP Max Input Vars',
+ 'value' => ini_get('max_input_vars')
+ ],
+ [
+ 'name' => 'PHP Memory Limit',
+ 'value' => ini_get('memory_limit')
+ ],
+ [
+ 'name' => 'PHP Xdebug Enabled',
+ 'value' => function_exists('xdebug_get_code_coverage')
+ ]
+ ]);
+
+ $systemInfo->push([
+ 'name' => 'DBMS',
+ 'value'=> DB::getDriverName(),
+ ])->push([
+ 'name' => 'DB',
+ 'value'=> DB::getDatabaseName(),
+ ]);
+
+ if(DB::getDriverName() == 'mysql') {
+ $query = DB::raw("SHOW VARIABLES LIKE 'version'");
+ $version = Arr::first(DB::select($query));
+ if($version) {
+ $systemInfo->push([
+ 'name' => 'DB Version',
+ 'value' => $version->Value
+ ]);
+ }
+ }
+
+ $systemInfo->push([
+ 'name' => 'Cache',
+ 'value'=> Cache::getDefaultDriver(),
+ ])->push([
+ 'name' => 'Cache Time',
+ 'value'=> Cache::getDefaultCacheTime(),
+ ]);
+
+
+ if(Cache::getDefaultDriver() == 'redis') {
+ $redisStatus = false;
+
+ try {
+ $redisConfig = config('database.redis.default');
+ $redis = Redis::connect($redisConfig['host'],$redisConfig['port']);
+ $redisStatus = true;
+ } catch(\Exception $e){ }
+
+ $systemInfo->push([
+ 'name' => 'Redis Connected',
+ 'value' => $redisStatus
+ ]);
+ }
+
+
+ return view('admin.menu.systemStatus.system', ['systemInfo' => $systemInfo->all()]);
+ }
+}
diff --git a/app/Http/Controllers/Admin/Menu/SystemStatus/SystemStatusMenuItemController.php b/app/Http/Controllers/Admin/Menu/SystemStatus/SystemStatusMenuItemController.php
new file mode 100644
index 0000000..569921e
--- /dev/null
+++ b/app/Http/Controllers/Admin/Menu/SystemStatus/SystemStatusMenuItemController.php
@@ -0,0 +1,20 @@
+name = 'adminMenu.items.systemStatus.systemStatus';
+
+ $this->slug = 'system-status';
+
+ $this->permissions = ['admin manage system status'];
+
+ $this->iconClasses = 'nav-icon icon-wrench';
+ }
+}
diff --git a/app/Services/AppJsObjectService.php b/app/Services/AppJsObjectService.php
new file mode 100644
index 0000000..60f06fa
--- /dev/null
+++ b/app/Services/AppJsObjectService.php
@@ -0,0 +1,49 @@
+ app()->getLocale(),
+ 'csrfToken' => csrf_token(),
+ 'user' => null,
+ 'options' => [
+ 'googleApiKey' => $option->google_api_key,
+ 'fbAppId' => $option->fb_app_id,
+ ],
+ 'translations' => [
+
+ ],
+ 'methods' => new \stdClass,
+ 'utils' => new \stdClass
+ ];
+ if(Auth::check()) {
+ $user = Auth::user();
+ $obj['user'] = [
+ 'id' => $user->id,
+ 'apiToken' => $user->api_token
+ ];
+ }
+
+ if($siteState->isAdminArea) {
+ $obj['admin']['translations'] = [
+ 'dataTables' => trans('datatables'),
+ ];
+ }
+ return $obj;
+ }
+}
diff --git a/config/admin.php b/config/admin.php
index 187e4b4..af3b5bd 100644
--- a/config/admin.php
+++ b/config/admin.php
@@ -17,6 +17,15 @@ return [
Menu\Options\Children\DevelopmentMenuItemController::class,
]
],
+ [
+ 'type' => 'item',
+ 'controller' => Menu\SystemStatus\SystemStatusMenuItemController::class,
+ 'children' => [
+ Menu\SystemStatus\Children\SystemMenuItemController::class,
+ Menu\SystemStatus\Children\RouteListMenuItemController::class,
+ Menu\SystemStatus\Children\GateAbilitiesMenuItemController::class,
+ ]
+ ],
],
// 設定的項目
'options' => [
diff --git a/config/data-presets.php b/config/data-presets.php
index 86f3c35..ffd2feb 100644
--- a/config/data-presets.php
+++ b/config/data-presets.php
@@ -37,6 +37,12 @@ return [
'displayName' => 'adminManageOptionsDevelopment',
'assignTo' => []
],
+ [
+ //管理系統狀態
+ 'name' => 'admin manage system status',
+ 'displayName' => 'adminManageSystemStatus',
+ 'assignTo' => []
+ ],
],
// 預設的設定值
'options' => [
diff --git a/config/languages.php b/config/languages.php
index 7707530..63ec4ff 100644
--- a/config/languages.php
+++ b/config/languages.php
@@ -2,7 +2,5 @@
return [
'en' => 'English',
'zh-tw' => '繁體中文',
- 'zh-cn' => '简体中文',
- 'ja' => '日本語',
'ko' => '한국어'
];
diff --git a/resources/js/admin/lib.js b/resources/js/admin/lib.js
index 25c35b9..3fd3a45 100644
--- a/resources/js/admin/lib.js
+++ b/resources/js/admin/lib.js
@@ -21,6 +21,8 @@ import 'perfect-scrollbar';
import '@coreui/coreui';
import 'chart.js';
import '@coreui/coreui-plugin-chartjs-custom-tooltips';
+import 'datatables.net-bs4';
+import 'datatables.net-responsive-bs4';
try {
diff --git a/resources/js/admin/page/system-status.js b/resources/js/admin/page/system-status.js
new file mode 100644
index 0000000..2744955
--- /dev/null
+++ b/resources/js/admin/page/system-status.js
@@ -0,0 +1,13 @@
+$(function(){
+ //路由表表格套用datatable
+ app.utils.dataTable('.table.routes', {
+ paginate: false,
+ responsive: true,
+ });
+
+ //Gate Ability表格套用datatable
+ app.utils.dataTable('.table.gate-abilities', {
+ paginate: false,
+ responsive: true,
+ });
+});
diff --git a/resources/js/app-common.js b/resources/js/app-common.js
index a877e83..0245804 100644
--- a/resources/js/app-common.js
+++ b/resources/js/app-common.js
@@ -1,4 +1,14 @@
+import {dataTable} from "./utils/datatable";
+
+
$('.logout-btn').on('click', e => {
e.preventDefault()
$('#logout-form').submit()
})
+
+/**
+ * 第三方工具
+ */
+app.utils = {
+ dataTable: dataTable,
+}
diff --git a/resources/js/utils/datatable.js b/resources/js/utils/datatable.js
new file mode 100644
index 0000000..9a123b2
--- /dev/null
+++ b/resources/js/utils/datatable.js
@@ -0,0 +1,5 @@
+export const dataTable = function(ele, options = {}){
+ return $(ele).dataTable(Object.assign({}, {
+ language: app.admin.translations.dataTables
+ }, options));
+};
diff --git a/resources/lang/en/adminMenu.php b/resources/lang/en/adminMenu.php
index f948090..ceedf30 100644
--- a/resources/lang/en/adminMenu.php
+++ b/resources/lang/en/adminMenu.php
@@ -7,5 +7,11 @@ return array(
'development' => 'Development',
'platform' => 'Platform',
],
+ 'systemStatus' => [
+ 'systemStatus' => 'System Status',
+ 'routes' => 'Route List',
+ 'system' => 'System',
+ 'gateAbilities' => 'Gate Abilities',
+ ]
],
);
diff --git a/resources/lang/en/datatables.php b/resources/lang/en/datatables.php
new file mode 100644
index 0000000..0136ba4
--- /dev/null
+++ b/resources/lang/en/datatables.php
@@ -0,0 +1,26 @@
+ 'Processing...',
+ 'search' => 'Search:',
+ 'lengthMenu' => 'Display _MENU_ items',
+ 'info' => 'Showing _START_ to _END_ on _TOTAL_ items',
+ 'infoEmpty' => 'Showing empty items',
+ 'infoFiltered' => '(filter of _MAX_ total items)',
+ 'infoPostFix' => '',
+ 'loadingRecords' => 'Loading...',
+ 'zeroRecords' => 'No item to display',
+ 'emptyTable' => 'Table is empty',
+ 'paginate' =>
+ array (
+ 'first' => 'First',
+ 'previous' => 'Previous',
+ 'next' => 'Next',
+ 'last' => 'Last',
+ ),
+ 'aria' =>
+ array (
+ 'sortAscending' => ': activate to sort the column in ascending order',
+ 'sortDescending' => ': activate to sort the column in descending order',
+ ),
+);
diff --git a/resources/lang/zh-tw/datatables.php b/resources/lang/zh-tw/datatables.php
new file mode 100644
index 0000000..70321ab
--- /dev/null
+++ b/resources/lang/zh-tw/datatables.php
@@ -0,0 +1,26 @@
+ '處理中...',
+ 'search' => '查詢:',
+ 'lengthMenu' => '顯示 _MENU_ 筆資料',
+ 'info' => '顯示第 _START_ 至 _END_ 筆資料,共 _TOTAL_ 筆',
+ 'infoEmpty' => '顯示 0 筆資料',
+ 'infoFiltered' => '(從 _MAX_ 筆資料中過濾)',
+ 'infoPostFix' => '',
+ 'loadingRecords' => '載入中...',
+ 'zeroRecords' => '查無資料',
+ 'emptyTable' => '無資料',
+ 'paginate' =>
+ array (
+ 'first' => '第一頁',
+ 'previous' => '上一頁',
+ 'next' => '下一頁',
+ 'last' => '最後一頁',
+ ),
+ 'aria' =>
+ array (
+ 'sortAscending' => ': 將資料以正序排序',
+ 'sortDescending' => ': 將資料以倒序排序',
+ ),
+);
diff --git a/resources/sass/admin/page/system-status.scss b/resources/sass/admin/page/system-status.scss
new file mode 100644
index 0000000..1c44ba1
--- /dev/null
+++ b/resources/sass/admin/page/system-status.scss
@@ -0,0 +1,50 @@
+//Boostrap函式庫
+@import "../bootstrap";
+
+body.system-status {
+ &.routes {
+ table.routes {
+ font-size: 1.1em;
+ @include media-breakpoint-down(lg) {
+ font-size: 1em;
+ }
+ @include media-breakpoint-down(md) {
+ font-size: .9em;
+ }
+ &.collapsed {
+ .dtr-data {
+ word-break: break-all;
+ .badge {
+ white-space: unset;
+ }
+ }
+ }
+ td {
+ &.uri {
+ * {
+ color: #baffc6;
+ }
+ }
+ &.action {
+ word-break: break-all;
+ }
+ &.middleware {
+ .badge {
+ margin-right: 2px;
+ font-size: .9em;
+ }
+ }
+ }
+ }
+ }
+ &.system {
+ table.system {
+ font-size: 1.1em;
+ }
+ }
+ &.gates {
+ table {
+ font-size: 1.2em;
+ }
+ }
+}
diff --git a/resources/views/admin/layouts/app.blade.php b/resources/views/admin/layouts/app.blade.php
index 8a8949e..170c0a1 100644
--- a/resources/views/admin/layouts/app.blade.php
+++ b/resources/views/admin/layouts/app.blade.php
@@ -7,6 +7,9 @@
+ @section('admin-app-head-scripts')
+ @include('components.head.appJsObject')
+ @show
@stack('admin-app-head-scripts')
@section('admin-app-styles')
diff --git a/resources/views/admin/menu/systemStatus/gates.blade.php b/resources/views/admin/menu/systemStatus/gates.blade.php
new file mode 100644
index 0000000..da78775
--- /dev/null
+++ b/resources/views/admin/menu/systemStatus/gates.blade.php
@@ -0,0 +1,36 @@
+@extends('admin.layouts.app')
+
+@section('title', 'Gate Abilities')
+
+@push('admin-app-scripts')
+
+@endpush
+
+@push('admin-app-styles')
+
+@endpush
+
+@section('admin-page-content')
+
+
+
+
+
+ | Ability |
+
+
+ @foreach($gates as $ability => $gate)
+
+ | {{ $ability }} |
+
+ @endforeach
+
+
+
+
+
+@endsection
diff --git a/resources/views/admin/menu/systemStatus/routes.blade.php b/resources/views/admin/menu/systemStatus/routes.blade.php
new file mode 100644
index 0000000..3ac626f
--- /dev/null
+++ b/resources/views/admin/menu/systemStatus/routes.blade.php
@@ -0,0 +1,85 @@
+@extends('admin.layouts.app')
+
+@section('title', 'Route List')
+
+@push('admin-app-scripts')
+
+@endpush
+
+@push('admin-app-styles')
+
+@endpush
+
+@section('admin-page-content')
+
+
+
+
+
+
+ | Method |
+ URI |
+ Name |
+ Action |
+ Middleware |
+
+
+
+ @foreach($routes as $route)
+
+
+ {!!
+ collect($route['methods'])
+ ->map(function($method){
+ $badgeType = '';
+ switch(strtolower($method)) {
+ case 'get':
+ $badgeType = 'success';
+ break;
+ case 'post':
+ $badgeType = 'primary';
+ break;
+ case 'put':
+ case 'patch':
+ $badgeType = 'warning';
+ break;
+ case 'delete':
+ $badgeType = 'danger';
+ break;
+ }
+ return app('Html')->bs()->badge($method, $badgeType);
+ })
+ ->join(' ')
+ !!}
+ |
+
+ @if(in_array('GET', $route['methods']))
+ {{ $route['uri'] }}
+ @else
+ {{ $route['uri'] }}
+ @endif
+ |
+ {{ $route['name'] }} |
+
+ {{ $route['action']['controller'] }}@{{ $route['action']['method'] }}
+ |
+
+ {!!
+ collect($route['middlewares'])
+ ->map(function($name){
+ return app('Html')->bs()->badge($name, 'secondary');
+ })
+ ->join('')
+ !!}
+ |
+
+ @endforeach
+
+
+
+
+@endsection
diff --git a/resources/views/admin/menu/systemStatus/system.blade.php b/resources/views/admin/menu/systemStatus/system.blade.php
new file mode 100644
index 0000000..1bb92b1
--- /dev/null
+++ b/resources/views/admin/menu/systemStatus/system.blade.php
@@ -0,0 +1,33 @@
+@extends('admin.layouts.app')
+
+@section('title', 'System Status')
+
+@push('admin-app-scripts')
+
+@endpush
+
+@push('admin-app-styles')
+
+@endpush
+
+@section('admin-page-content')
+
+
+
+
+
+ @foreach($systemInfo as $info)
+
+ | {{ $info['name'] }} |
+ {{ $info['value'] }} |
+
+ @endforeach
+
+
+
+
+@endsection
diff --git a/resources/views/components/head/appJsObject.blade.php b/resources/views/components/head/appJsObject.blade.php
new file mode 100644
index 0000000..d2a3d8a
--- /dev/null
+++ b/resources/views/components/head/appJsObject.blade.php
@@ -0,0 +1,4 @@
+@inject('js', App\Services\AppJsObjectService)
+
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index 50dfc49..c0d30f3 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -12,6 +12,9 @@
@endif
@yield('head-meta')
+ @section('app-head-scripts')
+ @include('components.head.appJsObject')
+ @show
@stack('app-head-scripts')
@section('app-styles')
diff --git a/webpack.mix.js b/webpack.mix.js
index abd5d0a..d8eee85 100644
--- a/webpack.mix.js
+++ b/webpack.mix.js
@@ -21,6 +21,8 @@ mix.js('resources/js/app.js', publicJsDir)
mix.sass('resources/sass/app.scss', publicCssDir);
mix.js('resources/js/admin/app.js', publicAdminJsDir)
+ .js('resources/js/admin/page/system-status.js', publicAdminJsDir + '/page')
mix.sass('resources/sass/admin/lib.scss', publicAdminCssDir)
.sass('resources/sass/admin/app.scss', publicAdminCssDir)
+ .sass('resources/sass/admin/page/system-status.scss', publicAdminCssDir + '/page')