Blade -> Twig (wip)
This commit is contained in:
parent
19efd013f6
commit
9403ae356d
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
|
|
@ -10,6 +10,8 @@ jobs:
|
|||
- uses: actions/checkout@v1
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
- name: Validate Twig templates
|
||||
run: php artisan twig:lint -v
|
||||
frontend:
|
||||
name: JavaScript Check
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -21,6 +21,18 @@ use Illuminate\Support\Facades\Redis;
|
|||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('admin.index', [
|
||||
'sum' => [
|
||||
'users' => User::count(),
|
||||
'players' => Player::count(),
|
||||
'textures' => Texture::count(),
|
||||
'storage' => Texture::select('size')->sum('size'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function chartData()
|
||||
{
|
||||
$today = Carbon::today()->timestamp;
|
||||
|
|
@ -105,7 +117,7 @@ class AdminController extends Controller
|
|||
return redirect('/admin');
|
||||
}
|
||||
|
||||
public function customize(Request $request)
|
||||
public function customize(Request $request, \App\Services\Webpack $webpack)
|
||||
{
|
||||
$homepage = Option::form('homepage', OptionForm::AUTO_DETECT, function ($form) {
|
||||
$form->text('home_pic_url')->hint();
|
||||
|
|
@ -142,7 +154,14 @@ class AdminController extends Controller
|
|||
option(['color_scheme' => $color]);
|
||||
}
|
||||
|
||||
return view('admin.customize', ['forms' => compact('homepage', 'customJsCss')]);
|
||||
return view('admin.customize', [
|
||||
'colors' => ['blue', 'yellow', 'green', 'purple', 'red', 'black'],
|
||||
'skins_css' => $webpack->url('skins/_all-skins.min.css'),
|
||||
'forms' => [
|
||||
'homepage' => $homepage,
|
||||
'custom_js_css' => $customJsCss,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function score()
|
||||
|
|
|
|||
|
|
@ -41,21 +41,26 @@ class UserController extends Controller
|
|||
$user = Auth::user();
|
||||
|
||||
[$from, $to] = explode(',', option('sign_score'));
|
||||
$scoreIntro = nl2br(trans('user.score-intro.introduction', [
|
||||
$scoreIntro = trans('user.score-intro.introduction', [
|
||||
'initial_score' => option('user_initial_score'),
|
||||
'score-from' => $from,
|
||||
'score-to' => $to,
|
||||
'return-score' => option('return_score')
|
||||
? trans('user.score-intro.will-return-score')
|
||||
: trans('user.score-intro.no-return-score'),
|
||||
]));
|
||||
]);
|
||||
|
||||
return view('user.index')->with([
|
||||
'statistics' => [
|
||||
'players' => $this->calculatePercentageUsed($user->players->count(), option('score_per_player')),
|
||||
'storage' => $this->calculatePercentageUsed($this->getStorageUsed($user), option('score_per_storage')),
|
||||
],
|
||||
'scoreIntro' => $scoreIntro,
|
||||
'score_intro' => $scoreIntro,
|
||||
'rates' => [
|
||||
'storage' => option('score_per_storage'),
|
||||
'player' => option('score_per_player'),
|
||||
'closet' => option('score_per_closet_item'),
|
||||
],
|
||||
'announcement' => app('parsedown')->text(option_localized('announcement')),
|
||||
'extra' => ['unverified' => option('require_verification') && ! $user->verified],
|
||||
]);
|
||||
|
|
|
|||
70
app/Http/View/Composers/FootComposer.php
Normal file
70
app/Http/View/Composers/FootComposer.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Services\Webpack;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\Translations\JavaScript;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class FootComposer
|
||||
{
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
/** @var Webpack */
|
||||
protected $webpack;
|
||||
|
||||
/** @var JavaScript */
|
||||
protected $javascript;
|
||||
|
||||
/** @var Dispatcher */
|
||||
protected $dispatcher;
|
||||
|
||||
public function __construct(
|
||||
Request $request,
|
||||
Webpack $webpack,
|
||||
JavaScript $javascript,
|
||||
Dispatcher $dispatcher
|
||||
) {
|
||||
$this->request = $request;
|
||||
$this->webpack = $webpack;
|
||||
$this->javascript = $javascript;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$this->injectJavaScript($view);
|
||||
$this->addExtra($view);
|
||||
}
|
||||
|
||||
public function injectJavaScript(View $view)
|
||||
{
|
||||
$scripts = [];
|
||||
|
||||
$locale = app()->getLocale();
|
||||
$scripts[] = $this->javascript->generate($locale);
|
||||
if ($pluginI18n = $this->javascript->plugin($locale)) {
|
||||
$scripts[] = $pluginI18n;
|
||||
}
|
||||
if ($this->request->is('admin*') && auth()->user()->permission >= User::SUPER_ADMIN) {
|
||||
$scripts[] = $this->webpack->url('check-updates.js');
|
||||
}
|
||||
$scripts[] = $this->webpack->url('index.js');
|
||||
|
||||
$view->with([
|
||||
'scripts' => $scripts,
|
||||
'inline_js' => option('custom_js'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function addExtra(View $view)
|
||||
{
|
||||
$content = [];
|
||||
$this->dispatcher->dispatch(new \App\Events\RenderingFooter($content));
|
||||
$view->with('extra_foot', $content);
|
||||
}
|
||||
}
|
||||
79
app/Http/View/Composers/HeadComposer.php
Normal file
79
app/Http/View/Composers/HeadComposer.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use App\Services\Webpack;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class HeadComposer
|
||||
{
|
||||
/** @var Webpack */
|
||||
protected $webpack;
|
||||
|
||||
/** @var Dispatcher */
|
||||
protected $dispatcher;
|
||||
|
||||
public function __construct(Webpack $webpack, Dispatcher $dispatcher)
|
||||
{
|
||||
$this->webpack = $webpack;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$this->addFavicon($view);
|
||||
$this->applyThemeColor($view);
|
||||
$this->seo($view);
|
||||
$this->injectStyles($view);
|
||||
$this->addExtra($view);
|
||||
}
|
||||
|
||||
public function addFavicon(View $view)
|
||||
{
|
||||
$url = option('favicon_url', config('options.favicon_url'));
|
||||
$url = Str::startsWith($url, 'http') ? $url : url($url);
|
||||
$view->with('favicon', $url);
|
||||
}
|
||||
|
||||
public function applyThemeColor(View $view)
|
||||
{
|
||||
$colors = [
|
||||
'blue' => '#3c8dbc',
|
||||
'yellow' => '#f39c12',
|
||||
'green' => '#00a65a',
|
||||
'purple' => '#605ca8',
|
||||
'red' => '#dd4b39',
|
||||
'black' => '#ffffff',
|
||||
];
|
||||
preg_match('/skin-(\w+)?(?:-light)?/', option('color_scheme'), $matches);
|
||||
$view->with('theme_color', Arr::get($colors, $matches[1]));
|
||||
}
|
||||
|
||||
public function seo(View $view)
|
||||
{
|
||||
$view->with('seo', [
|
||||
'keywords' => option('meta_keywords'),
|
||||
'description' => option('meta_description'),
|
||||
'extra' => option('meta_extras'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function injectStyles(View $view)
|
||||
{
|
||||
$view->with('styles', [
|
||||
$this->webpack->url('style.css'),
|
||||
$this->webpack->url('skins/'.option('color_scheme').'.min.css'),
|
||||
]);
|
||||
$view->with('inline_css', option('custom_css'));
|
||||
}
|
||||
|
||||
public function addExtra(View $view)
|
||||
{
|
||||
$content = [];
|
||||
$this->dispatcher->dispatch(new \App\Events\RenderingHeader($content));
|
||||
$view->with('extra_head', $content);
|
||||
}
|
||||
}
|
||||
40
app/Http/View/Composers/LanguagesMenuComposer.php
Normal file
40
app/Http/View/Composers/LanguagesMenuComposer.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class LanguagesMenuComposer
|
||||
{
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$query = $this->request->query();
|
||||
$url = $this->request->url();
|
||||
|
||||
$langs = collect(config('locales'))
|
||||
->reject(function ($locale) {
|
||||
return Arr::has($locale, 'alias');
|
||||
})
|
||||
->map(function ($locale, $id) use ($query, $url) {
|
||||
$query = array_merge($query, ['lang' => $id]);
|
||||
$locale['url'] = $url.'?'.http_build_query($query);
|
||||
|
||||
return $locale;
|
||||
});
|
||||
|
||||
$view->with([
|
||||
'current' => config('locales.'.app()->getLocale().'.short_name'),
|
||||
'langs' => $langs,
|
||||
]);
|
||||
}
|
||||
}
|
||||
101
app/Http/View/Composers/SideMenuComposer.php
Normal file
101
app/Http/View/Composers/SideMenuComposer.php
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use App\Events;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\PluginManager;
|
||||
|
||||
class SideMenuComposer
|
||||
{
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$type = $view->gatherData()['type'];
|
||||
|
||||
$menu = config('menu');
|
||||
switch ($type) {
|
||||
case 'user':
|
||||
event(new Events\ConfigureUserMenu($menu));
|
||||
break;
|
||||
case 'explore':
|
||||
event(new Events\ConfigureExploreMenu($menu));
|
||||
break;
|
||||
case 'admin':
|
||||
event(new Events\ConfigureAdminMenu($menu));
|
||||
$menu['admin'] = $this->collectPluginConfigs($menu['admin']);
|
||||
break;
|
||||
}
|
||||
|
||||
$view->with('items', array_map(function ($item) {
|
||||
return $this->transform($item);
|
||||
}, $menu[$type]));
|
||||
}
|
||||
|
||||
public function transform(array $item): array
|
||||
{
|
||||
$isActive = $this->request->is(Arr::get($item, 'link'));
|
||||
foreach (Arr::get($item, 'children', []) as $k => $v) {
|
||||
if ($this->request->is(Arr::get($v, 'link'))) {
|
||||
$isActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
if ($isActive) {
|
||||
$classes[] = 'active menu-open';
|
||||
}
|
||||
|
||||
if (Arr::has($item, 'children')) {
|
||||
$classes[] = 'treeview';
|
||||
$item['children'] = array_map(function ($item) {
|
||||
return $this->transform($item);
|
||||
}, $item['children']);
|
||||
}
|
||||
|
||||
$item['classes'] = $classes;
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function collectPluginConfigs(array &$menu)
|
||||
{
|
||||
$menu = array_map(function ($item) {
|
||||
if (Arr::get($item, 'id') === 'plugin-configs') {
|
||||
$pluginConfigs = resolve(PluginManager::class)
|
||||
->getEnabledPlugins()
|
||||
->filter(function ($plugin) {
|
||||
return $plugin->hasConfigView();
|
||||
})
|
||||
->map(function ($plugin) {
|
||||
return [
|
||||
'title' => trans($plugin->title),
|
||||
'link' => 'admin/plugins/config/'.$plugin->name,
|
||||
'icon' => 'fa-circle',
|
||||
];
|
||||
});
|
||||
|
||||
// Don't display this menu item when no plugin config is available
|
||||
if ($pluginConfigs->isNotEmpty()) {
|
||||
$item['children'] = array_merge($item['children'], $pluginConfigs->values()->all());
|
||||
|
||||
return $item;
|
||||
}
|
||||
} else {
|
||||
return $item;
|
||||
}
|
||||
}, $menu);
|
||||
|
||||
return array_filter($menu); // Remove empty items
|
||||
}
|
||||
}
|
||||
35
app/Http/View/Composers/UserMenuComposer.php
Normal file
35
app/Http/View/Composers/UserMenuComposer.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class UserMenuComposer
|
||||
{
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$view->with('user', $user);
|
||||
|
||||
if ($this->request->is('skinlib*') || $this->request->is('/')) {
|
||||
$view->with(
|
||||
'tiny_avatar',
|
||||
url('avatar/25/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
}
|
||||
|
||||
$view->with(
|
||||
'avatar',
|
||||
url('avatar/128/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
}
|
||||
}
|
||||
41
app/Http/View/Composers/UserPanelComposer.php
Normal file
41
app/Http/View/Composers/UserPanelComposer.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\View\Composers;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class UserPanelComposer
|
||||
{
|
||||
/** @var Dispatcher */
|
||||
protected $dispatcher;
|
||||
|
||||
public function __construct(Dispatcher $dispatcher)
|
||||
{
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
public function compose(View $view)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$roles = [
|
||||
User::BANNED => 'banned',
|
||||
User::NORMAL => 'normal',
|
||||
User::ADMIN => 'admin',
|
||||
User::SUPER_ADMIN => 'super-admin',
|
||||
];
|
||||
$role = $roles[$user->permission];
|
||||
$avatar = url('avatar/45/'.base64_encode($user->email).'.png?tid='.$user->avatar);
|
||||
|
||||
$badges = [];
|
||||
$this->dispatcher->dispatch(new \App\Events\RenderingBadges($badges));
|
||||
|
||||
$view->with([
|
||||
'user' => $user,
|
||||
'role' => trans("admin.users.status.$role"),
|
||||
'avatar' => $avatar,
|
||||
'badges' => $badges,
|
||||
]);
|
||||
}
|
||||
}
|
||||
54
app/Providers/ViewServiceProvider.php
Normal file
54
app/Providers/ViewServiceProvider.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use View;
|
||||
use App\Http\View\Composers;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ViewServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
View::composer(['*.base', 'shared.header'], function ($view) {
|
||||
$view->with([
|
||||
'site_name' => option_localized('site_name'),
|
||||
'color_scheme' => option('color_scheme'),
|
||||
]);
|
||||
});
|
||||
|
||||
View::composer('shared.head', Composers\HeadComposer::class);
|
||||
|
||||
View::composer('shared.notifications', function ($view) {
|
||||
$notifications = auth()->user()->unreadNotifications;
|
||||
$view->with([
|
||||
'notifications' => $notifications,
|
||||
'amount' => count($notifications),
|
||||
]);
|
||||
});
|
||||
|
||||
View::composer('shared.languages', Composers\LanguagesMenuComposer::class);
|
||||
|
||||
View::composer('shared.user-menu', Composers\UserMenuComposer::class);
|
||||
|
||||
View::composer('shared.side-menu', Composers\SideMenuComposer::class);
|
||||
|
||||
View::composer('shared.user-panel', Composers\UserPanelComposer::class);
|
||||
|
||||
View::composer('shared.footer', function ($view) {
|
||||
$customCopyright = get_string_replaced(
|
||||
option_localized('copyright_text'),
|
||||
[
|
||||
'{site_name}' => option_localized('site_name'),
|
||||
'{site_url}' => option('site_url'),
|
||||
]
|
||||
);
|
||||
$view->with([
|
||||
'copyright' => option_localized('copyright_prefer', 0),
|
||||
'custom_copyright' => $customCopyright,
|
||||
]);
|
||||
});
|
||||
|
||||
View::composer('shared.foot', Composers\FootComposer::class);
|
||||
}
|
||||
}
|
||||
112
app/helpers.php
112
app/helpers.php
|
|
@ -77,102 +77,6 @@ if (! function_exists('bs_header_extra')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (! function_exists('bs_menu')) {
|
||||
function bs_menu(string $type): string
|
||||
{
|
||||
$menu = config('menu');
|
||||
|
||||
switch ($type) {
|
||||
case 'user':
|
||||
event(new App\Events\ConfigureUserMenu($menu));
|
||||
break;
|
||||
case 'explore':
|
||||
event(new App\Events\ConfigureExploreMenu($menu));
|
||||
break;
|
||||
case 'admin':
|
||||
event(new App\Events\ConfigureAdminMenu($menu));
|
||||
break;
|
||||
}
|
||||
|
||||
if (! isset($menu[$type])) {
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
$menu[$type] = array_map(function ($item) {
|
||||
if (Arr::get($item, 'id') === 'plugin-configs') {
|
||||
$pluginConfigs = app('plugins')->getEnabledPlugins()
|
||||
->filter(function ($plugin) {
|
||||
return $plugin->hasConfigView();
|
||||
})
|
||||
->map(function ($plugin) {
|
||||
return [
|
||||
'title' => trans($plugin->title),
|
||||
'link' => 'admin/plugins/config/'.$plugin->name,
|
||||
'icon' => 'fa-circle',
|
||||
];
|
||||
});
|
||||
|
||||
// Don't display this menu item when no plugin config is available
|
||||
if ($pluginConfigs->isNotEmpty()) {
|
||||
$item['children'] = array_merge($item['children'], $pluginConfigs->values()->all());
|
||||
|
||||
return $item;
|
||||
}
|
||||
} else {
|
||||
return $item;
|
||||
}
|
||||
}, $menu[$type]);
|
||||
|
||||
return bs_menu_render($menu[$type]);
|
||||
}
|
||||
|
||||
function bs_menu_render(array $data): string
|
||||
{
|
||||
$content = '';
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$active = app('request')->is(@$value['link']);
|
||||
|
||||
// also set parent as active if any child is active
|
||||
foreach ((array) @$value['children'] as $childKey => $childValue) {
|
||||
if (app('request')->is(@$childValue['link'])) {
|
||||
$active = true;
|
||||
}
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
$active ? ($classes[] = 'active menu-open') : null;
|
||||
isset($value['children']) ? ($classes[] = 'treeview') : null;
|
||||
|
||||
$attr = count($classes) ? sprintf(' class="%s"', implode(' ', $classes)) : '';
|
||||
|
||||
$content .= "<li{$attr}>";
|
||||
|
||||
if (isset($value['children'])) {
|
||||
$content .= sprintf('<a href="#"><i class="fas %s"></i> <span>%s</span><span class="pull-right-container"><i class="fas fa-angle-left pull-right"></i></span></a>', $value['icon'], trans($value['title']));
|
||||
|
||||
// recurse
|
||||
$content .= '<ul class="treeview-menu">'.bs_menu_render($value['children']).'</ul>';
|
||||
} else {
|
||||
if ($value) {
|
||||
$content .= sprintf(
|
||||
'<a href="%s" %s><i class="%s %s"></i> <span>%s</span></a>',
|
||||
url((string) $value['link']),
|
||||
Arr::get($value, 'new-tab') ? 'target="_blank"' : '',
|
||||
$value['icon'] == 'fa-circle' ? 'far' : 'fas',
|
||||
(string) $value['icon'],
|
||||
trans((string) $value['title'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$content .= '</li>';
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('bs_copyright')) {
|
||||
function bs_copyright(): string
|
||||
{
|
||||
|
|
@ -323,22 +227,6 @@ if (! function_exists('is_request_secure')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (! function_exists('nl2p')) {
|
||||
/**
|
||||
* Wrap blocks of text (delimited by \n) in p tags (similar to nl2br).
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
function nl2p(string $text): string
|
||||
{
|
||||
$parts = explode("\n", $text);
|
||||
$result = '<p>'.implode('</p><p>', $parts).'</p>';
|
||||
// Remove empty paragraphs
|
||||
return str_replace('<p></p>', '', $result);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('png')) {
|
||||
function png($resource)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
"composer/ca-bundle": "^1.2",
|
||||
"facade/ignition": "^1.4",
|
||||
"spatie/laravel-translation-loader": "^2.4",
|
||||
"symfony/yaml": "^4.3"
|
||||
"symfony/yaml": "^4.3",
|
||||
"twig/twig": "^2.11",
|
||||
"rcrowe/twigbridge": "^0.11.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "~1.8",
|
||||
|
|
|
|||
141
composer.lock
generated
141
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e0bda645aa2fc04fc9dc1d6e0d711c50",
|
||||
"content-hash": "5ac658b15e8a3bf5b2f92d73193abf8a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
|
|
@ -2577,6 +2577,78 @@
|
|||
],
|
||||
"time": "2018-07-19T23:38:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rcrowe/twigbridge",
|
||||
"version": "v0.11.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rcrowe/TwigBridge.git",
|
||||
"reference": "2054abdbd8dcde573cd86d8d3856873e2388d47b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/2054abdbd8dcde573cd86d8d3856873e2388d47b",
|
||||
"reference": "2054abdbd8dcde573cd86d8d3856873e2388d47b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "5.5.*|5.6.*|5.7.*|5.8.x|6.0.*",
|
||||
"illuminate/view": "5.5.*|5.6.*|5.7.*|5.8.x|6.0.*",
|
||||
"php": ">=7.1",
|
||||
"twig/twig": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/framework": "5.5.*",
|
||||
"mockery/mockery": "0.9.*",
|
||||
"phpunit/phpunit": "~6.0",
|
||||
"satooshi/php-coveralls": "~0.6",
|
||||
"squizlabs/php_codesniffer": "~1.5"
|
||||
},
|
||||
"suggest": {
|
||||
"laravelcollective/html": "For bringing back html/form in Laravel 5.x",
|
||||
"twig/extensions": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.11-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"TwigBridge\\ServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Twig": "TwigBridge\\Facade\\Twig"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TwigBridge\\": "src",
|
||||
"TwigBridge\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Crowe",
|
||||
"email": "hello@vivalacrowe.com"
|
||||
},
|
||||
{
|
||||
"name": "Barry vd. Heuvel",
|
||||
"email": "barryvdh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Adds the power of Twig to Laravel",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"twig"
|
||||
],
|
||||
"time": "2019-09-05T11:59:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "scrivo/highlight.php",
|
||||
"version": "v9.15.10.0",
|
||||
|
|
@ -4356,6 +4428,73 @@
|
|||
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
|
||||
"time": "2017-11-27T11:13:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v2.11.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "699ed2342557c88789a15402de5eb834dedd6792"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/699ed2342557c88789a15402de5eb834dedd6792",
|
||||
"reference": "699ed2342557c88789a15402de5eb834dedd6792",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/container": "^1.0",
|
||||
"symfony/debug": "^2.7",
|
||||
"symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.11-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Twig_": "lib/"
|
||||
},
|
||||
"psr-4": {
|
||||
"Twig\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com",
|
||||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Armin Ronacher",
|
||||
"email": "armin.ronacher@active-4.com",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Twig Team",
|
||||
"homepage": "https://twig.symfony.com/contributors",
|
||||
"role": "Contributors"
|
||||
}
|
||||
],
|
||||
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
||||
"homepage": "https://twig.symfony.com",
|
||||
"keywords": [
|
||||
"templating"
|
||||
],
|
||||
"time": "2019-06-18T15:37:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tymon/jwt-auth",
|
||||
"version": "dev-develop",
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ return [
|
|||
App\Providers\PluginServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
App\Providers\ValidatorExtendServiceProvider::class,
|
||||
|
||||
App\Providers\ViewServiceProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|
|
|
|||
214
config/twigbridge.php
Normal file
214
config/twigbridge.php
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the TwigBridge package.
|
||||
*
|
||||
* @copyright Robert Crowe <hello@vivalacrowe.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration options for Twig.
|
||||
*/
|
||||
return [
|
||||
|
||||
'twig' => [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| File extension for Twig view files.
|
||||
|
|
||||
*/
|
||||
'extension' => 'twig',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Accepts all Twig environment configuration options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
||||
|
|
||||
*/
|
||||
'environment' => [
|
||||
|
||||
// When set to true, the generated templates have a __toString() method
|
||||
// that you can use to display the generated nodes.
|
||||
// default: false
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
|
||||
// The charset used by the templates.
|
||||
// default: utf-8
|
||||
'charset' => 'utf-8',
|
||||
|
||||
// The base template class to use for generated templates.
|
||||
// default: TwigBridge\Twig\Template
|
||||
'base_template_class' => 'TwigBridge\Twig\Template',
|
||||
|
||||
// An absolute path where to store the compiled templates, or false to disable caching. If null
|
||||
// then the cache file path is used.
|
||||
// default: cache file storage path
|
||||
'cache' => null,
|
||||
|
||||
// When developing with Twig, it's useful to recompile the template
|
||||
// whenever the source code changes. If you don't provide a value
|
||||
// for the auto_reload option, it will be determined automatically based on the debug value.
|
||||
'auto_reload' => true,
|
||||
|
||||
// If set to false, Twig will silently ignore invalid variables
|
||||
// (variables and or attributes/methods that do not exist) and
|
||||
// replace them with a null value. When set to true, Twig throws an exception instead.
|
||||
// default: false
|
||||
'strict_variables' => false,
|
||||
|
||||
// If set to true, auto-escaping will be enabled by default for all templates.
|
||||
// default: 'html'
|
||||
'autoescape' => 'html',
|
||||
|
||||
// A flag that indicates which optimizations to apply
|
||||
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
|
||||
'optimizations' => -1,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These will always be passed in and can be accessed as Twig variables.
|
||||
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
||||
|
|
||||
*/
|
||||
'globals' => [],
|
||||
],
|
||||
|
||||
'extensions' => [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enabled extensions.
|
||||
|
|
||||
| `Twig\Extension\DebugExtension` is enabled automatically if twig.debug is TRUE.
|
||||
|
|
||||
*/
|
||||
'enabled' => [
|
||||
'Twig\Extension\StringLoaderExtension',
|
||||
|
||||
'TwigBridge\Extension\Loader\Facades',
|
||||
'TwigBridge\Extension\Loader\Filters',
|
||||
'TwigBridge\Extension\Loader\Functions',
|
||||
|
||||
'TwigBridge\Extension\Laravel\Auth',
|
||||
'TwigBridge\Extension\Laravel\Config',
|
||||
'TwigBridge\Extension\Laravel\Dump',
|
||||
// 'TwigBridge\Extension\Laravel\Input',
|
||||
'TwigBridge\Extension\Laravel\Session',
|
||||
// 'TwigBridge\Extension\Laravel\Str',
|
||||
'TwigBridge\Extension\Laravel\Translator',
|
||||
'TwigBridge\Extension\Laravel\Url',
|
||||
// 'TwigBridge\Extension\Laravel\Model',
|
||||
// 'TwigBridge\Extension\Laravel\Gate',
|
||||
|
||||
// 'TwigBridge\Extension\Laravel\Form',
|
||||
// 'TwigBridge\Extension\Laravel\Html',
|
||||
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Facades
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
||||
|
|
||||
| Each facade can take an optional array of options. To mark the whole facade
|
||||
| as safe you can set the option `'is_safe' => true`. Setting the facade as
|
||||
| safe means that any HTML returned will not be escaped.
|
||||
|
|
||||
| It is advisable to not set the whole facade as safe and instead mark the
|
||||
| each appropriate method as safe for security reasons. You can do that with
|
||||
| the following syntax:
|
||||
|
|
||||
| <code>
|
||||
| 'Form' => [
|
||||
| 'is_safe' => [
|
||||
| 'open'
|
||||
| ]
|
||||
| ]
|
||||
| </code>
|
||||
|
|
||||
| The values of the `is_safe` array must match the called method on the facade
|
||||
| in order to be marked as safe.
|
||||
|
|
||||
*/
|
||||
'facades' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Available functions. Access like `{{ secure_url(...) }}`.
|
||||
|
|
||||
| Each function can take an optional array of options. These options are
|
||||
| passed directly to `Twig\TwigFunction`.
|
||||
|
|
||||
| So for example, to mark a function as safe you can do the following:
|
||||
|
|
||||
| <code>
|
||||
| 'link_to' => [
|
||||
| 'is_safe' => ['html']
|
||||
| ]
|
||||
| </code>
|
||||
|
|
||||
| The options array also takes a `callback` that allows you to name the
|
||||
| function differently in your Twig templates than what it's actually called.
|
||||
|
|
||||
| <code>
|
||||
| 'link' => [
|
||||
| 'callback' => 'link_to'
|
||||
| ]
|
||||
| </code>
|
||||
|
|
||||
*/
|
||||
'functions' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filters
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Available filters. Access like `{{ variable|filter }}`.
|
||||
|
|
||||
| Each filter can take an optional array of options. These options are
|
||||
| passed directly to `Twig\TwigFilter`.
|
||||
|
|
||||
| So for example, to mark a filter as safe you can do the following:
|
||||
|
|
||||
| <code>
|
||||
| 'studly_case' => [
|
||||
| 'is_safe' => ['html']
|
||||
| ]
|
||||
| </code>
|
||||
|
|
||||
| The options array also takes a `callback` that allows you to name the
|
||||
| filter differently in your Twig templates than what is actually called.
|
||||
|
|
||||
| <code>
|
||||
| 'snake' => [
|
||||
| 'callback' => 'snake_case'
|
||||
| ]
|
||||
| </code>
|
||||
|
|
||||
*/
|
||||
'filters' => [
|
||||
'get' => 'data_get',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
@ -57,6 +57,9 @@ body, h1, h2, h3, h4, h5, h6
|
|||
.main-header .navbar .user-menu .user-image
|
||||
border-radius 10%
|
||||
|
||||
.navbar-nav > .user-menu > .dropdown-menu > li.user-header
|
||||
height unset
|
||||
|
||||
#language-menu li
|
||||
a
|
||||
color #777
|
||||
|
|
|
|||
|
|
@ -159,15 +159,16 @@ update:
|
|||
latest: "Latest Version:"
|
||||
current: "Current Version:"
|
||||
|
||||
check-github: <a href=":url" target="_blank" class="el-button pull-right">Check GitHub Releases</a>
|
||||
check-github: Check GitHub Releases
|
||||
button: Update Now
|
||||
|
||||
cautions:
|
||||
title: Cautions
|
||||
link: check out this.
|
||||
text: |
|
||||
Please choose update source according to your host's network environment.
|
||||
Low-speed connection between update source and your host will cause long-time loading at checking and downloading page.
|
||||
To change the default update source, please refer to <a target="_blank" href="https://blessing.netlify.com/update-sources.html">this article</a>.
|
||||
To change the default update source,
|
||||
|
||||
download:
|
||||
downloading: Downloading update package...
|
||||
|
|
|
|||
|
|
@ -164,15 +164,16 @@ update:
|
|||
latest: 最新版本:
|
||||
current: 当前版本:
|
||||
|
||||
check-github: <a href=":url" target="_blank" class="el-button pull-right">查看 GitHub Releases</a>
|
||||
check-github: 查看 GitHub Releases
|
||||
button: 马上升级
|
||||
|
||||
cautions:
|
||||
title: 注意事项
|
||||
link: 点击了解详情
|
||||
text: |
|
||||
请根据你的主机所在位置(国内/国外)选择更新源。
|
||||
如错选至相对于你的主机速度较慢的源,可能会造成检查与下载更新页面长时间无响应。
|
||||
如何更换更新源?<a target="_blank" href="https://blessing.netlify.com/update-sources.html">点击了解详情</a>。
|
||||
如何更换更新源?
|
||||
|
||||
download:
|
||||
downloading: 正在下载更新包
|
||||
|
|
|
|||
25
resources/views/admin/base.twig
Normal file
25
resources/views/admin/base.twig
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{ include('shared.head') }}
|
||||
<title>{% block title %}{% endblock %} - {{ site_name }}</title>
|
||||
</head>
|
||||
|
||||
<body class="hold-transition {{ color_scheme }} sidebar-mini">
|
||||
<div class="wrapper">
|
||||
{{ include('shared.header') }}
|
||||
{{ include('shared.sidebar', {scope: 'admin'}) }}
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>{{ block('title') }}</h1>
|
||||
</section>
|
||||
<section class="content">
|
||||
{% block content %}{% endblock %}
|
||||
</section>
|
||||
</div>
|
||||
{{ include('shared.footer') }}
|
||||
</div>
|
||||
{% block before_foot %}{% endblock %}
|
||||
{{ include('shared.foot') }}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.customize'))
|
||||
|
||||
@section('style')
|
||||
<link rel="stylesheet" href="{{ webpack_assets('skins/_all-skins.min.css') }}">
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.customize')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<form class="box box-primary" method="post" action="{{ url('/admin/customize?action=color') }}">
|
||||
@csrf
|
||||
<div class="box-header with-border">
|
||||
<h3 v-t="'admin.change-color.title'" class="box-title">
|
||||
@lang('admin.customize.change-color.title')
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-striped bring-up nth-2-center" id="change-color">
|
||||
@php
|
||||
$colors = ['blue', 'yellow', 'green', 'purple', 'red', 'black'];
|
||||
@endphp
|
||||
<tbody>
|
||||
@foreach ($colors as $color)
|
||||
<tr>
|
||||
<td>@lang('admin.customize.colors.'.$color)</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="radio" name="color" value="skin-{{ $color }}" style="display: none;">
|
||||
<span class="btn bg-{{ $color }} btn-xs">
|
||||
<i class="far fa-eye"></i>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@lang('admin.customize.colors.'.$color.'-light')</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="radio" name="color" value="skin-{{ $color }}-light" style="display: none;">
|
||||
<span class="btn bg-{{ $color }} btn-xs">
|
||||
<i class="far fa-eye"></i>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="submit" class="el-button el-button--primary" value="@lang('general.submit')" name="submit_color">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
{!! $forms['homepage']->render() !!}
|
||||
|
||||
{!! $forms['customJsCss']->render() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
@endsection
|
||||
74
resources/views/admin/customize.twig
Normal file
74
resources/views/admin/customize.twig
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.customize') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<form class="box box-primary" method="post" action="{{ url('/admin/customize?action=color') }}">
|
||||
{{ csrf_field() }}
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
{{ trans('admin.customize.change-color.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body no-padding">
|
||||
<table class="table table-striped bring-up nth-2-center" id="change-color">
|
||||
<tbody>
|
||||
{% for color in colors %}
|
||||
<tr>
|
||||
<td>{{ trans("admin.customize.colors.#{color}") }}</td>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="color"
|
||||
value="skin-{{ color }}"
|
||||
style="display: none;"
|
||||
>
|
||||
<span class="btn bg-{{ color }} btn-xs">
|
||||
<i class="far fa-eye"></i>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans("admin.customize.colors.#{color}-light") }}</td>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name="color"
|
||||
value="skin-{{ color }}-light"
|
||||
style="display: none;"
|
||||
>
|
||||
<span class="btn bg-{{ color }} btn-xs">
|
||||
<i class="far fa-eye"></i>
|
||||
</span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input
|
||||
type="submit"
|
||||
class="el-button el-button--primary"
|
||||
value="{{ trans('general.submit') }}"
|
||||
name="submit_color"
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ forms.homepage|raw }}
|
||||
{{ forms.custom_js_css|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<link rel="stylesheet" href="{{ skins_css }}">
|
||||
{% endblock %}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.i18n'))
|
||||
|
||||
@section('content')
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>@lang('general.i18n')</h1>
|
||||
</section>
|
||||
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div id="table"></div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<form action="{{ url('/admin/i18n') }}" method="post">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">@lang('admin.i18n.add')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
@if (session()->pull('success'))
|
||||
<div class="callout callout-success">@lang('admin.i18n.added')</div>
|
||||
@endif
|
||||
@if ($errors->any())
|
||||
<div class="callout callout-danger">{{ $errors->first() }}</div>
|
||||
@endif
|
||||
@csrf
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>@lang('admin.i18n.group')</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="group" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@lang('admin.i18n.key')</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="key" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@lang('admin.i18n.text')</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="text" required>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="submit" value="@lang('general.submit')" class="el-button el-button--primary">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="callout callout-info">
|
||||
<a href="https://blessing.netlify.com/ui-text.html" target="_blank">
|
||||
@lang('admin.i18n.tip')
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@endsection
|
||||
60
resources/views/admin/i18n.twig
Normal file
60
resources/views/admin/i18n.twig
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.i18n') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-lg-8"><div id="table"></div></div>
|
||||
<div class="col-lg-4">
|
||||
<form action="{{ url('/admin/i18n') }}" method="post">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">{{ trans('admin.i18n.add') }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if errors.any %}
|
||||
<div class="callout callout-danger">{{ errors.first }}</div>
|
||||
{% elseif session_pull('success') %}
|
||||
<div class="callout callout-success">{{ trans('admin.i18n.added') }}</div>
|
||||
{% endif %}
|
||||
{{ csrf_field() }}
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ trans('admin.i18n.group') }}</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="group" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('admin.i18n.key') }}</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="key" required>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('admin.i18n.text') }}</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" name="text" required>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input
|
||||
type="submit"
|
||||
value="{{ trans('general.submit') }}"
|
||||
class="el-button el-button--primary"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="callout callout-info">
|
||||
<a href="https://blessing.netlify.com/ui-text.html" target="_blank">
|
||||
{{ trans('admin.i18n.tip') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.dashboard'))
|
||||
|
||||
@section('content')
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.dashboard')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-aqua">
|
||||
<div class="inner">
|
||||
<h3>{{ resolve(\App\Models\User::class)->count() }}</h3>
|
||||
<p>@lang('admin.index.total-users')</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-users"></i></div>
|
||||
<a href="{{ url('admin/users') }}" class="small-box-footer">
|
||||
@lang('general.user-manage') <i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner">
|
||||
<h3>{{ App\Models\Player::count() }}</h3>
|
||||
<p>@lang('admin.index.total-players')</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-gamepad"></i></div>
|
||||
<a href="{{ url('admin/players') }}" class="small-box-footer">
|
||||
@lang('general.player-manage') <i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-purple">
|
||||
<div class="inner">
|
||||
<h3>{{ App\Models\Texture::count() }}</h3>
|
||||
<p>@lang('admin.index.total-textures')</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-file"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner">
|
||||
@php
|
||||
$size = DB::table('textures')->sum('size') ?: 0;
|
||||
@endphp
|
||||
<h3>{{ $size > 1024 ? round($size / 1024, 1).'MB' : $size.'KB' }}</h3>
|
||||
<p>@lang('admin.index.disk-usage')</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-hdd"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('admin.notifications.send.title')</h3>
|
||||
</div>
|
||||
<form method="post" action="{{ url('/admin/notifications/send') }}">
|
||||
@csrf
|
||||
<div class="box-body">
|
||||
@if ($errors->any())
|
||||
<div class="callout callout-danger">{{ $errors->first() }}</div>
|
||||
@endif
|
||||
@if ($sentResult = Session::pull('sentResult'))
|
||||
<div class="callout callout-success">{{ $sentResult }}</div>
|
||||
@endif
|
||||
<div class="form-group">
|
||||
<label>@lang('admin.notifications.receiver.title')</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="all" required>
|
||||
@lang('admin.notifications.receiver.all')
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="normal" required>
|
||||
@lang('admin.notifications.receiver.normal')
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="uid" required>
|
||||
@lang('admin.notifications.receiver.uid')
|
||||
<input type="number" name="uid" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="email" required>
|
||||
@lang('admin.notifications.receiver.email')
|
||||
<input type="email" name="email" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>@lang('admin.notifications.title')</label>
|
||||
<input type="text" name="title" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>@lang('admin.notifications.content')</label>
|
||||
<textarea name="content" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="submit" value="@lang('general.submit')" class="el-button el-button--primary">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('admin.index.overview')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div id="chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
@endsection
|
||||
136
resources/views/admin/index.twig
Normal file
136
resources/views/admin/index.twig
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.dashboard') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-aqua">
|
||||
<div class="inner">
|
||||
<h3>{{ sum.users }}</h3>
|
||||
<p>{{ trans('admin.index.total-users') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-users"></i></div>
|
||||
<a href="{{ url('admin/users') }}" class="small-box-footer">
|
||||
{{ trans('general.user-manage') }}
|
||||
<i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner">
|
||||
<h3>{{ sum.players }}</h3>
|
||||
<p>{{ trans('admin.index.total-players') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-gamepad"></i></div>
|
||||
<a href="{{ url('admin/players') }}" class="small-box-footer">
|
||||
{{ trans('general.player-manage') }}
|
||||
<i class="fa fa-arrow-circle-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-purple">
|
||||
<div class="inner">
|
||||
<h3>{{ sum.textures }}</h3>
|
||||
<p>{{ trans('admin.index.total-textures') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-file"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner">
|
||||
{% if sum.storage > 1024 %}
|
||||
<h3>{{ (sum.storage / 1024)|round(1) }}MB</h3>
|
||||
{% else %}
|
||||
<h3>{{ sum.storage }}KB</h3>
|
||||
{% endif %}
|
||||
<p>{{ trans('admin.index.disk-usage') }}</p>
|
||||
</div>
|
||||
<div class="icon"><i class="fas fa-hdd"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('admin.notifications.send.title') }}</h3>
|
||||
</div>
|
||||
<form method="post" action="{{ url('/admin/notifications/send') }}">
|
||||
{{ csrf_field() }}
|
||||
<div class="box-body">
|
||||
{% if errors.any %}
|
||||
<div class="callout callout-danger">{{ errors.first }}</div>
|
||||
{% endif %}
|
||||
{% set sent_result = session_pull('sentResult') %}
|
||||
{% if sent_result %}
|
||||
<div class="callout callout-success">{{ sent_result }}</div>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label>{{ trans('admin.notifications.receiver.title') }}</label>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="all" required>
|
||||
{{ trans('admin.notifications.receiver.all') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="normal" required>
|
||||
{{ trans('admin.notifications.receiver.normal') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="uid" required>
|
||||
{{ trans('admin.notifications.receiver.uid') }}
|
||||
<input type="number" name="uid" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="receiver" value="email" required>
|
||||
{{ trans('admin.notifications.receiver.email') }}
|
||||
<input type="email" name="email" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ trans('admin.notifications.title') }}</label>
|
||||
<input type="text" name="title" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ trans('admin.notifications.content') }}</label>
|
||||
<textarea name="content" class="form-control" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input
|
||||
type="submit"
|
||||
value="{{ trans('general.submit') }}"
|
||||
class="el-button el-button--primary"
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('admin.index.overview') }}</h3>
|
||||
</div>
|
||||
<div class="box-body"><div id="chart"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'admin', 'title' => trans('general.plugin-market')])
|
||||
@endcomponent
|
||||
3
resources/views/admin/market.twig
Normal file
3
resources/views/admin/market.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.plugin-market') }}{% endblock %}
|
||||
|
|
@ -1,94 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@include('shared.head')
|
||||
<title>@yield('title') - {{ option_localized('site_name') }}</title>
|
||||
@include('common.favicon')
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@include('common.theme-color')
|
||||
<!-- App Styles -->
|
||||
@include('common.dependencies.style')
|
||||
|
||||
@yield('style')
|
||||
</head>
|
||||
|
||||
@php
|
||||
$user = auth()->user();
|
||||
@endphp
|
||||
|
||||
<body class="hold-transition {{ option('color_scheme') }} sidebar-mini">
|
||||
<div class="wrapper">
|
||||
|
||||
<!-- Main Header -->
|
||||
<header class="main-header">
|
||||
|
||||
<!-- Logo -->
|
||||
<a href="{{ option('site_url') }}" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini"> <i class="fas fa-bookmark"></i> </span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg">{{ option_localized('site_name') }}</span>
|
||||
</a>
|
||||
|
||||
<!-- Header Navbar -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<!-- Navbar Right Menu -->
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
@include('common.notifications-menu')
|
||||
|
||||
@include('common.language')
|
||||
|
||||
@include('common.user-menu')
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- Left side column. contains the logo and sidebar -->
|
||||
<aside class="main-sidebar">
|
||||
|
||||
<!-- sidebar: style can be found in sidebar.less -->
|
||||
<section class="sidebar">
|
||||
@include('common.user-panel')
|
||||
<!-- Sidebar Menu -->
|
||||
<ul class="sidebar-menu tree" data-widget="tree">
|
||||
<li class="header">@lang('general.admin-panel')</li>
|
||||
{!! bs_menu('admin') !!}
|
||||
|
||||
<li class="header">@lang('general.back')</li>
|
||||
<li><a href="{{ url('user') }}"><i class="fas fa-user"></i> <span>@lang('general.user-center')</span></a></li>
|
||||
</ul><!-- /.sidebar-menu -->
|
||||
</section>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
|
||||
@include('shared.header')
|
||||
@include('shared.sidebar', ['scope' => 'admin'])
|
||||
@yield('content')
|
||||
@include('shared.footer')
|
||||
</div>
|
||||
|
||||
<!-- Main Footer -->
|
||||
<footer class="main-footer">
|
||||
<!-- YOU CAN NOT MODIFIY THE COPYRIGHT TEXT W/O PERMISSION -->
|
||||
<div id="copyright-text" class="pull-right hidden-xs">
|
||||
@include('common.copyright')
|
||||
</div>
|
||||
<!-- Default to the left -->
|
||||
@include('common.custom-copyright')
|
||||
</footer>
|
||||
|
||||
</div><!-- ./wrapper -->
|
||||
|
||||
<!-- App Scripts -->
|
||||
@include('common.dependencies.script')
|
||||
@if ($user->permission >= \App\Models\User::SUPER_ADMIN)
|
||||
<script defer src="{{ webpack_assets('check-updates.js') }}"></script>
|
||||
@endif
|
||||
@include('shared.foot')
|
||||
@yield('script')
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.options'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.options')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{!! $forms['general']->render() !!}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{!! $forms['announ']->render() !!}
|
||||
|
||||
{!! $forms['meta']->render() !!}
|
||||
|
||||
{!! $forms['recaptcha']->render() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
@endsection
|
||||
16
resources/views/admin/options.twig
Normal file
16
resources/views/admin/options.twig
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.options') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ forms.general.render()|raw }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ forms.announ.render()|raw }}
|
||||
{{ forms.meta.render()|raw }}
|
||||
{{ forms.recaptcha.render()|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'admin', 'title' => trans('general.player-manage')])
|
||||
@endcomponent
|
||||
3
resources/views/admin/players.twig
Normal file
3
resources/views/admin/players.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.player-manage') }}{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'admin', 'title' => trans('general.plugin-manage')])
|
||||
@endcomponent
|
||||
3
resources/views/admin/plugins.twig
Normal file
3
resources/views/admin/plugins.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.plugin-manage') }}{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'admin', 'title' => trans('general.report-manage')])
|
||||
@endcomponent
|
||||
3
resources/views/admin/reports.twig
Normal file
3
resources/views/admin/reports.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.report-manage') }}{% endblock %}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.res-options'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.res-options')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="callout callout-warning">@lang('options.res-warning')</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{!! $forms['resources']->render() !!}
|
||||
|
||||
{!! $forms['redis']->render() !!}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{!! $forms['cache']->render() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
@endsection
|
||||
23
resources/views/admin/resource.twig
Normal file
23
resources/views/admin/resource.twig
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.res-options') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="callout callout-warning">
|
||||
{{ trans('options.res-warning') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ forms.resources.render()|raw }}
|
||||
{{ forms.redis.render()|raw }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ forms.cache.render()|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.score-options'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.score-options')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{!! $forms['rate']->render() !!}
|
||||
|
||||
{!! $forms['report']->render() !!}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{!! $forms['sign']->render() !!}
|
||||
|
||||
{!! $forms['sharing']->render() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
@endsection
|
||||
16
resources/views/admin/score.twig
Normal file
16
resources/views/admin/score.twig
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.score-options') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ forms.rate.render()|raw }}
|
||||
{{ forms.report.render()|raw }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ forms.sign.render()|raw }}
|
||||
{{ forms.sharing.render()|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.status'))
|
||||
|
||||
@section('content')
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>@lang('general.status')</h1>
|
||||
</section>
|
||||
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">@lang('admin.status.info')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<tbody>
|
||||
@foreach ($detail as $category => $info)
|
||||
<tr>
|
||||
<th colspan="2">@lang("admin.status.$category.name")</th>
|
||||
</tr>
|
||||
@foreach ($info as $key => $value)
|
||||
<tr>
|
||||
<td>@lang("admin.status.$category.$key")</td>
|
||||
<td>{{ $value }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
<tr>
|
||||
<th colspan="2">@lang('admin.status.plugins', ['amount' => $plugins->count()])</th>
|
||||
</tr>
|
||||
@foreach ($plugins as $plugin)
|
||||
<tr>
|
||||
<td>{{ $plugin['title'] }}</td>
|
||||
<td>{{ $plugin['version'] }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6"></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@endsection
|
||||
44
resources/views/admin/status.twig
Normal file
44
resources/views/admin/status.twig
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.status') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">{{ trans('admin.status.info') }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table class="table table-bordered table-striped">
|
||||
<tbody>
|
||||
{% for category, info in detail %}
|
||||
<tr>
|
||||
<th colspan="2">{{ trans("admin.status.#{category}.name") }}</th>
|
||||
</tr>
|
||||
{% for key, value in info %}
|
||||
<tr>
|
||||
<td>{{ trans("admin.status.#{category}.#{key}") }}</td>
|
||||
<td>{{ value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
{{ trans('admin.status.plugins', {amount: plugins|length}) }}
|
||||
</th>
|
||||
</tr>
|
||||
{% for plugin in plugins %}
|
||||
<tr>
|
||||
<td>{{ plugin.title }}</td>
|
||||
<td>{{ plugin.version }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
@extends('admin.master')
|
||||
|
||||
@section('title', trans('general.check-update'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.check-update')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('admin.update.info.title')</h3>
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
@if ($extra['canUpdate'])
|
||||
<div class="callout callout-info">@lang('admin.update.info.available')</div>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="key">@lang('admin.update.info.versions.latest')</td>
|
||||
<td class="value">
|
||||
v{{ $info['latest'] }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="key">@lang('admin.update.info.versions.current')</td>
|
||||
<td class="value">
|
||||
v{{ $info['current'] }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
|
||||
@if (is_string($error))
|
||||
<div class="callout callout-danger">{{ trans('admin.update.errors.connection', ['error' => $error]) }}</div>
|
||||
@else
|
||||
<div class="callout callout-success">{{ trans('admin.update.info.up-to-date') }}</div>
|
||||
@endif
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="key">@lang('admin.update.info.versions.current')</td>
|
||||
<td class="value">
|
||||
v{{ $info['current'] }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
</div><!-- /.box-body -->
|
||||
<div class="box-footer">
|
||||
<span id="update-button"></span>
|
||||
{!! trans('admin.update.info.check-github', ['url' => 'https://github.com/bs-community/blessing-skin-server/releases']) !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('admin.update.cautions.title')</h3>
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
{!! nl2p(trans('admin.update.cautions.text')) !!}
|
||||
</div><!-- /.box-body -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
<script>
|
||||
blessing.extra = @json($extra)
|
||||
</script>
|
||||
@endsection
|
||||
91
resources/views/admin/update.twig
Normal file
91
resources/views/admin/update.twig
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.check-update') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('admin.update.info.title') }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if extra.canUpdate %}
|
||||
<div class="callout callout-info">
|
||||
{{ trans('admin.update.info.available') }}
|
||||
</div>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="key">{{ trans('admin.update.info.versions.latest') }}</td>
|
||||
<td class="value">
|
||||
v{{ info.latest }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="key">{{ trans('admin.update.info.versions.current') }}</td>
|
||||
<td class="value">
|
||||
v{{ info.current }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
{% if error is not empty %}
|
||||
<div class="callout callout-danger">
|
||||
{{ trans('admin.update.errors.connection', {error: error}) }}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="callout callout-success">
|
||||
{{ trans('admin.update.info.up-to-date') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="key">
|
||||
{{ trans('admin.update.info.versions.current') }}</td>
|
||||
<td class="value">
|
||||
v{{ info.current }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<span id="update-button"></span>
|
||||
<a
|
||||
target="_blank"
|
||||
class="el-button pull-right"
|
||||
href="https://github.com/bs-community/blessing-skin-server/releases"
|
||||
>
|
||||
{{ trans('admin.update.info.check-github') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
{{ trans('admin.update.cautions.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% for text in trans('admin.update.cautions.text')|split('\n') %}
|
||||
<p>{{ text }}</p>
|
||||
{% endfor %}
|
||||
<a target="_blank" href="https://blessing.netlify.com/update-sources.html">
|
||||
{{ trans('admin.update.cautions.link') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<script>
|
||||
blessing.extra = {{ extra|json_encode|raw }}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'admin', 'title' => trans('general.user-manage')])
|
||||
@endcomponent
|
||||
3
resources/views/admin/users.twig
Normal file
3
resources/views/admin/users.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'admin.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.user-manage') }}{% endblock %}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
@extends("$parent.master")
|
||||
|
||||
@section('title', $title)
|
||||
|
||||
@section('content')
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>{{ $title }}</h1>
|
||||
</section>
|
||||
<section class="content"></section>
|
||||
</div>
|
||||
|
||||
{{ $bottom ?? '' }}
|
||||
@endsection
|
||||
|
|
@ -1,16 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@include('shared.head')
|
||||
<title>{{ option_localized('site_name') }}</title>
|
||||
@include('common.favicon')
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@include('common.seo-meta-tags')
|
||||
<!-- App Styles -->
|
||||
@include('common.dependencies.style')
|
||||
<style>
|
||||
.hp-wrapper {
|
||||
@if (option('fixed_bg'))
|
||||
|
|
@ -63,10 +55,10 @@
|
|||
<!-- Navbar Right Menu -->
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
@include('common.language')
|
||||
@include('shared.languages')
|
||||
|
||||
@auth
|
||||
@include('common.user-menu')
|
||||
@include('shared.user-menu')
|
||||
@else {{-- Anonymous User --}}
|
||||
<!-- User Account Menu -->
|
||||
<li class="dropdown user user-menu">
|
||||
|
|
|
|||
8
resources/views/shared/foot.twig
Normal file
8
resources/views/shared/foot.twig
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{% for script in scripts %}
|
||||
<script src="{{ script }}"></script>
|
||||
{% endfor %}
|
||||
|
||||
<script>
|
||||
{{ inline_js|striptags('<div><span><ul><li><p><a><img><i>')|raw }}
|
||||
</script>
|
||||
{{ extra_foot|join('\n')|raw }}
|
||||
20
resources/views/shared/footer.twig
Normal file
20
resources/views/shared/footer.twig
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{% set repo = 'https://github.com/bs-community/blessing-skin-server' %}
|
||||
<footer class="main-footer">
|
||||
<!-- YOU CAN NOT MODIFIY THE COPYRIGHT TEXT W/O PERMISSION -->
|
||||
<div id="copyright-text" class="pull-right hidden-xs">
|
||||
{% if copyright == 0 %}
|
||||
Powered with ❤ by <a href="{{ repo }}">Blessing Skin Server</a>.
|
||||
{% elseif copyright == 1 %}
|
||||
Powered by <a href="{{ repo }}">Blessing Skin Server</a>.
|
||||
{% elseif copyright == 2 %}
|
||||
Proudly powered by <a href="{{ repo }}">Blessing Skin Server</a>.
|
||||
{% elseif copyright == 3 %}
|
||||
由 <a href="{{ repo }}">Blessing Skin Server</a> 强力驱动。
|
||||
{% else %}
|
||||
自豪地采用 <a href="{{ repo }}">Blessing Skin Server</a>。
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Default to the left -->
|
||||
{{ custom_copyright|raw }}
|
||||
</footer>
|
||||
18
resources/views/shared/head.twig
Normal file
18
resources/views/shared/head.twig
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<meta name="theme-color" content="{{ theme_color }}">
|
||||
<meta name="keywords" content="{{ seo.keywords }}">
|
||||
<meta name="description" content="{{ seo.description }}">
|
||||
{{ seo.extra|striptags('<meta>')|raw }}
|
||||
|
||||
<link rel="shortcut icon" href="{{ favicon }}">
|
||||
<link rel="icon" type="image/png" href="{{ favicon }}" sizes="192x192">
|
||||
<link rel="apple-touch-icon" href="{{ favicon }}" sizes="180x180">
|
||||
|
||||
{% for style in styles %}
|
||||
<link rel="stylesheet" href="{{ style }}">
|
||||
{% endfor %}
|
||||
<style>{{ inline_css|striptags }}</style>
|
||||
{{ extra_head|join('\n')|raw }}
|
||||
26
resources/views/shared/header.twig
Normal file
26
resources/views/shared/header.twig
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<header class="main-header">
|
||||
<!-- Logo -->
|
||||
<a href="{{ url('/') }}" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini"> <i class="fas fa-bookmark"></i> </span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg">{{ site_name }}</span>
|
||||
</a>
|
||||
|
||||
<!-- Header Navbar -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<!-- Navbar Right Menu -->
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
{{ include('shared.notifications') }}
|
||||
{{ include('shared.languages') }}
|
||||
{{ include('shared.user-menu') }}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
14
resources/views/shared/languages.twig
Normal file
14
resources/views/shared/languages.twig
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fas fa-language" aria-hidden="true"></i>
|
||||
<span class="description-text">{{ current }}</span>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu" id="language-menu">
|
||||
{% for lang in langs %}
|
||||
<li class="locale">
|
||||
<a href="{{ lang.url }}">{{ lang.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
25
resources/views/shared/notifications.twig
Normal file
25
resources/views/shared/notifications.twig
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<li class="dropdown notifications-menu">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fas fa-bell"></i>
|
||||
{% if amount > 0 %}
|
||||
<span class="label label-warning notifications-counter">{{ amount }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if amount == 0 %}
|
||||
<li class="header text-center">{{ trans('user.no-unread') }}</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<ul class="menu notifications-list">
|
||||
{% for notification in notifications %}
|
||||
<li>
|
||||
<a href="#" data-nid="{{ notification.id }}">
|
||||
<i class="far fa-circle text-aqua"></i> {{ notification.data.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
27
resources/views/shared/side-menu-item.twig
Normal file
27
resources/views/shared/side-menu-item.twig
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<li class="{{ item.classes|join(' ') }}">
|
||||
{% if item.children %}
|
||||
<a href="#">
|
||||
<i class="fas {{ item.icon }}"></i>
|
||||
<span>{{ trans(item.title) }}</span>
|
||||
<span class="pull-right-container">
|
||||
<i class="fas fa-angle-left pull-right"></i>
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
{% for child in item.children %}
|
||||
{{ include('shared.side-menu-item', {item: child}) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<a
|
||||
href="{{ url(item.link) }}"
|
||||
{% if attribute(item, 'new-tab') %}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
{% endif %}
|
||||
>
|
||||
<i class="{{ item.icon == 'fa-circle' ? 'far' : 'fas' }} {{ item.icon }}"></i>
|
||||
<span>{{ trans(item.title) }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
3
resources/views/shared/side-menu.twig
Normal file
3
resources/views/shared/side-menu.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% for item in items %}
|
||||
{{ include('shared.side-menu-item', {item: item}) }}
|
||||
{% endfor %}
|
||||
44
resources/views/shared/sidebar.twig
Normal file
44
resources/views/shared/sidebar.twig
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<aside class="main-sidebar">
|
||||
<section class="sidebar">
|
||||
{{ include('shared.user-panel') }}
|
||||
<ul class="sidebar-menu tree" data-widget="tree">
|
||||
|
||||
{% if scope == 'user' %}
|
||||
|
||||
<li class="header">{{ trans('general.user-center') }}</li>
|
||||
{{ include('shared.side-menu', {type: 'user'}) }}
|
||||
<li class="header">{{ trans('general.explore') }}</li>
|
||||
{{ include('shared.side-menu', {type: 'explore'}) }}
|
||||
{% if auth_user().admin %}
|
||||
<li class="header">{{ trans('general.manage') }}</li>
|
||||
<li>
|
||||
<a href="{{ url('admin') }}">
|
||||
<i class="fas fa-cog"></i>
|
||||
<span>{{ trans('general.admin-panel') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% elseif scope == 'admin' %}
|
||||
|
||||
<li class="header">{{ trans('general.admin-panel') }}</li>
|
||||
{{ include('shared.side-menu', {type: 'admin'}) }}
|
||||
<li class="header">{{ trans('general.back') }}</li>
|
||||
<li>
|
||||
<a href="{{ url('user') }}">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>{{ trans('general.user-center') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ url('skinlib') }}">
|
||||
<i class="fas fa-archive"></i>
|
||||
<span>{{ trans('general.skinlib') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
</section>
|
||||
</aside>
|
||||
47
resources/views/shared/user-menu.twig
Normal file
47
resources/views/shared/user-menu.twig
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<li class="dropdown user user-menu">
|
||||
<!-- Menu Toggle Button -->
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
{% if tiny_avatar %}
|
||||
<img src="{{ tiny_avatar }}" class="user-image" alt="User Image">
|
||||
{% else %}
|
||||
<i class="fas fa-user"></i>
|
||||
{% endif %}
|
||||
<!-- hidden-xs hides the username on small devices so only the image appears. -->
|
||||
<span class="hidden-xs nickname">{{ user.nickname ?? user.email }}</span>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu">
|
||||
<li class="user-header">
|
||||
<img src="{{ avatar }}" alt="User Image">
|
||||
<p>{{ user.email }}</p>
|
||||
</li>
|
||||
{% if user.admin %}
|
||||
<li class="user-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 text-center">
|
||||
<a href="{{ url('admin') }}">{{ trans('general.admin-panel') }}</a>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
<a href="{{ url('admin/users') }}">{{ trans('general.user-manage') }}</a>
|
||||
</div>
|
||||
<div class="col-xs-4 text-center">
|
||||
<a href="{{ url('admin/options') }}">{{ trans('general.options') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
<!-- Menu Footer-->
|
||||
<li class="user-footer">
|
||||
<div class="pull-left">
|
||||
<a href="{{ url('user') }}" class="btn btn-default btn-flat">
|
||||
{{ trans('general.user-center') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<button id="logout-button" class="btn btn-default btn-flat">
|
||||
{{ trans('general.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
20
resources/views/shared/user-panel.twig
Normal file
20
resources/views/shared/user-panel.twig
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<div class="user-panel">
|
||||
<div class="pull-left image">
|
||||
<img src="{{ avatar }}" alt="User Image">
|
||||
</div>
|
||||
<div class="pull-left info">
|
||||
<p class="nickname">{{ user.nickname ?? user.email }}</p>
|
||||
<i class="fas fa-circle text-success"></i> {{ role }}
|
||||
{% if badges|length == 1 %}
|
||||
<small class="label bg-{{ badges[0][1] }}">{{ badges[0][0] }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if badges|length > 1 %}
|
||||
<div class="user-panel" style="padding-top: 0">
|
||||
{% for badge in badges %}
|
||||
<small class="label bg-{{ badge[1] }}">{{ badge[0] }}</small>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -1,18 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@include('shared.head')
|
||||
<title>@yield('title') - {{ option_localized('site_name') }}</title>
|
||||
@include('common.favicon')
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@include('common.theme-color')
|
||||
@include('common.seo-meta-tags')
|
||||
<!-- App Styles -->
|
||||
@include('common.dependencies.style')
|
||||
|
||||
@yield('style')
|
||||
</head>
|
||||
|
||||
|
|
|
|||
25
resources/views/user/base.twig
Normal file
25
resources/views/user/base.twig
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{ include('shared.head') }}
|
||||
<title>{% block title %}{% endblock %} - {{ site_name }}</title>
|
||||
</head>
|
||||
|
||||
<body class="hold-transition {{ color_scheme }} sidebar-mini">
|
||||
<div class="wrapper">
|
||||
{{ include('shared.header') }}
|
||||
{{ include('shared.sidebar', {scope: 'user'}) }}
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>{{ block('title') }}</h1>
|
||||
</section>
|
||||
<section class="content">
|
||||
{% block content %}{% endblock %}
|
||||
</section>
|
||||
</div>
|
||||
{{ include('shared.footer') }}
|
||||
</div>
|
||||
{% block before_foot %}{% endblock %}
|
||||
{{ include('shared.foot') }}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
@extends('user.master')
|
||||
|
||||
@section('title', trans('general.my-closet'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
@lang('general.my-closet')
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content"></section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
get: () => Object.freeze(@json($extra))
|
||||
})
|
||||
</script>
|
||||
@endsection
|
||||
11
resources/views/user/closet.twig
Normal file
11
resources/views/user/closet.twig
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.my-closet') }}{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
get: () => Object.freeze({{ extra|json_encode|raw }})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
@extends('user.master')
|
||||
|
||||
@section('title', trans('general.dashboard'))
|
||||
|
||||
@section('content')
|
||||
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
<div class="content-wrapper">
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>@lang('general.dashboard')</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="box" id="usage-box"></div><!-- /.box -->
|
||||
</div><!-- /.col -->
|
||||
|
||||
<div class="col-md-5">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('user.announcement')</h3>
|
||||
@if (auth()->user()->isAdmin())
|
||||
<a href="{{ url('/admin/options') }}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
@endif
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
{!! $announcement !!}
|
||||
</div><!-- /.box-body -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section><!-- /.content -->
|
||||
</div><!-- /.content-wrapper -->
|
||||
|
||||
<div id="modal-score-instruction" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">@lang('user.score-intro.title')</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{!! $scoreIntro !!}
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<p class="text-center">@lang('user.score-intro.rates.storage', ['score' => option('score_per_storage')])</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-center">@lang('user.score-intro.rates.player', ['score' => option('score_per_player')])</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-center">@lang('user.score-intro.rates.closet', ['score' => option('score_per_closet_item')])</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="el-button" data-dismiss="modal">@lang('general.close')</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
get: () => Object.freeze(@json($extra))
|
||||
})
|
||||
</script>
|
||||
@endsection
|
||||
68
resources/views/user/index.twig
Normal file
68
resources/views/user/index.twig
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.dashboard') }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="box" id="usage-box">
|
||||
<div class="box-header with-border"></div>
|
||||
<div class="box-body"></div>
|
||||
<div class="box-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-5">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ trans('user.announcement') }}</h3>
|
||||
{% if auth_user().admin %}
|
||||
<a href="{{ url('/admin/options') }}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{{ announcement|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<div id="modal-score-instruction" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">{{ trans('user.score-intro.title') }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ score_intro|nl2br }}
|
||||
<hr />
|
||||
<div class="row">
|
||||
{% for key, value in rates %}
|
||||
<div class="col-md-4">
|
||||
<p class="text-center">
|
||||
{{ trans("user.score-intro.rates.#{key}", {score: value}) }}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="el-button" data-dismiss="modal">{{ trans('general.close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
get: () => Object.freeze({{ extra|json_encode|raw }})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -1,97 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@include('shared.head')
|
||||
<title>@yield('title') - {{ option_localized('site_name') }}</title>
|
||||
@include('common.favicon')
|
||||
<!-- Tell the browser to be responsive to screen width -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@include('common.theme-color')
|
||||
<!-- App Styles -->
|
||||
@include('common.dependencies.style')
|
||||
|
||||
@yield('style')
|
||||
</head>
|
||||
|
||||
@php
|
||||
$user = auth()->user();
|
||||
@endphp
|
||||
|
||||
<body class="hold-transition {{ option('color_scheme') }} sidebar-mini">
|
||||
<div class="wrapper">
|
||||
|
||||
<!-- Main Header -->
|
||||
<header class="main-header">
|
||||
|
||||
<!-- Logo -->
|
||||
<a href="{{ option('site_url') }}" class="logo">
|
||||
<!-- mini logo for sidebar mini 50x50 pixels -->
|
||||
<span class="logo-mini"> <i class="fas fa-bookmark"></i> </span>
|
||||
<!-- logo for regular state and mobile devices -->
|
||||
<span class="logo-lg">{{ option_localized('site_name') }}</span>
|
||||
</a>
|
||||
|
||||
<!-- Header Navbar -->
|
||||
<nav class="navbar navbar-static-top" role="navigation">
|
||||
<!-- Sidebar toggle button-->
|
||||
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
|
||||
<i class="fas fa-bars"></i>
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
</a>
|
||||
<!-- Navbar Right Menu -->
|
||||
<div class="navbar-custom-menu">
|
||||
<ul class="nav navbar-nav">
|
||||
@include('common.notifications-menu')
|
||||
|
||||
@include('common.language')
|
||||
|
||||
@include('common.user-menu')
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<!-- Left side column. contains the logo and sidebar -->
|
||||
<aside class="main-sidebar">
|
||||
|
||||
<!-- sidebar: style can be found in sidebar.less -->
|
||||
<section class="sidebar">
|
||||
@include('common.user-panel')
|
||||
<!-- Sidebar Menu -->
|
||||
<ul class="sidebar-menu tree" data-widget="tree">
|
||||
<li class="header">@lang('general.user-center')</li>
|
||||
{!! bs_menu('user') !!}
|
||||
|
||||
<li class="header">@lang('general.explore')</li>
|
||||
{!! bs_menu('explore') !!}
|
||||
|
||||
@admin($user)
|
||||
<li class="header">@lang('general.manage')</li>
|
||||
<li><a href="{{ url('admin') }}"><i class="fas fa-cog"></i> <span>@lang('general.admin-panel')</span></a></li>
|
||||
@endadmin
|
||||
</ul><!-- /.sidebar-menu -->
|
||||
</section>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
|
||||
@include('shared.header')
|
||||
@include('shared.sidebar', ['scope' => 'user'])
|
||||
@yield('content')
|
||||
@include('shared.footer')
|
||||
</div>
|
||||
|
||||
<!-- Main Footer -->
|
||||
<footer class="main-footer">
|
||||
<!-- YOU CAN NOT MODIFIY THE COPYRIGHT TEXT W/O PERMISSION -->
|
||||
<div id="copyright-text" class="pull-right hidden-xs">
|
||||
@include('common.copyright')
|
||||
</div>
|
||||
<!-- Default to the left -->
|
||||
@include('common.custom-copyright')
|
||||
</footer>
|
||||
|
||||
</div><!-- ./wrapper -->
|
||||
|
||||
<!-- App Scripts -->
|
||||
@include('common.dependencies.script')
|
||||
|
||||
@include('shared.foot')
|
||||
@yield('script')
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'user', 'title' => trans('general.oauth-manage')])
|
||||
@endcomponent
|
||||
3
resources/views/user/oauth.twig
Normal file
3
resources/views/user/oauth.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.oauth-manage') }}{% endblock %}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'user', 'title' => trans('general.player-manage')])
|
||||
@slot('bottom')
|
||||
<script>blessing.extra = @json($extra)</script>
|
||||
@endslot
|
||||
@endcomponent
|
||||
7
resources/views/user/player.twig
Normal file
7
resources/views/user/player.twig
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.player-manage') }}{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<script>blessing.extra = {{ extra|json_encode|raw }}</script>
|
||||
{% endblock %}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'user', 'title' => trans('general.profile')])
|
||||
@slot('bottom')
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
configurable: false,
|
||||
get: () => Object.freeze(@json($extra)),
|
||||
})
|
||||
</script>
|
||||
@endslot
|
||||
@endcomponent
|
||||
12
resources/views/user/profile.twig
Normal file
12
resources/views/user/profile.twig
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.profile') }}{% endblock %}
|
||||
|
||||
{% block before_foot %}
|
||||
<script>
|
||||
Object.defineProperty(blessing, 'extra', {
|
||||
configurable: false,
|
||||
get: () => Object.freeze({{ extra|json_encode|raw }}),
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
@component('common.skeleton', ['parent' => 'user', 'title' => trans('general.my-reports')])
|
||||
@endcomponent
|
||||
3
resources/views/user/report.twig
Normal file
3
resources/views/user/report.twig
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{% extends 'user.base' %}
|
||||
|
||||
{% block title %}{{ trans('general.my-reports') }}{% endblock %}
|
||||
|
|
@ -114,7 +114,7 @@ Route::group(['prefix' => 'skinlib'], function () {
|
|||
* Admin Panel
|
||||
*/
|
||||
Route::group(['middleware' => ['authorize', 'admin'], 'prefix' => 'admin'], function () {
|
||||
Route::view('/', 'admin.index');
|
||||
Route::get('/', 'AdminController@index');
|
||||
Route::get('/chart', 'AdminController@chartData');
|
||||
Route::post('/notifications/send', 'AdminController@sendNotification');
|
||||
|
||||
|
|
|
|||
|
|
@ -154,12 +154,12 @@ class AdminConfigurationsTest extends BrowserKitTestCase
|
|||
$this->visit('/admin/options')
|
||||
->type('kw', 'meta_keywords')
|
||||
->type('desc', 'meta_description')
|
||||
->type('<!-- nothing -->', 'meta_extras')
|
||||
->type('<meta>', 'meta_extras')
|
||||
->press('submit_meta');
|
||||
$this->visit('/')
|
||||
->see('<meta name="keywords" content="kw">')
|
||||
->see('<meta name="description" content="desc">')
|
||||
->see('<!-- nothing -->');
|
||||
->see('<meta>');
|
||||
|
||||
$this->visit('/admin/options')
|
||||
->type('key', 'recaptcha_sitekey')
|
||||
|
|
|
|||
72
tests/HttpTest/ViewTest/ComposersTest/FootComposerTest.php
Normal file
72
tests/HttpTest/ViewTest/ComposersTest/FootComposerTest.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Event;
|
||||
use App\Models\User;
|
||||
use App\Services\Webpack;
|
||||
use App\Services\Translations\JavaScript;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class FootComposerTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
public function testInjectJavaScript()
|
||||
{
|
||||
option([
|
||||
'custom_js' => '"<div></div>"</script><h1 id=disallowed></h1><script>',
|
||||
]);
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user);
|
||||
$this->get('/user')->assertSee('"<div></div>"');
|
||||
$crawler = new Crawler($this->get('/user')->getContent());
|
||||
$this->assertCount(0, $crawler->filter('#disallowed'));
|
||||
|
||||
$this->mock(JavaScript::class, function ($mock) {
|
||||
$mock->shouldReceive('generate')
|
||||
->with('en')
|
||||
->twice()
|
||||
->andReturn('en.js');
|
||||
$mock->shouldReceive('plugin')
|
||||
->with('en')
|
||||
->twice()
|
||||
->andReturn('en_plugin.js');
|
||||
});
|
||||
$this->mock(Webpack::class, function ($mock) {
|
||||
$mock->shouldReceive('url')->with('style.css');
|
||||
$mock->shouldReceive('url')->with('skins/skin-blue.min.css');
|
||||
$mock->shouldReceive('url')
|
||||
->with('check-updates.js')
|
||||
->once()
|
||||
->andReturn('check-updates.js');
|
||||
$mock->shouldReceive('url')
|
||||
->with('index.js')
|
||||
->twice()
|
||||
->andReturn('index.js');
|
||||
});
|
||||
|
||||
$this->get('/user')
|
||||
->assertSee('en.js')
|
||||
->assertSee('en_plugin.js')
|
||||
->assertSee('index.js')
|
||||
->assertDontSee('check-updates.js');
|
||||
|
||||
$superAdmin = factory(User::class, 'superAdmin')->make();
|
||||
$this->actingAs($superAdmin);
|
||||
$this->get('/admin')->assertSee('check-updates.js');
|
||||
}
|
||||
|
||||
public function testAddExtra()
|
||||
{
|
||||
Event::listen(\App\Events\RenderingFooter::class, function ($event) {
|
||||
$event->contents[] = '<div id=appended></div>';
|
||||
});
|
||||
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user);
|
||||
$this->get('/user')->assertSee('<div id=appended></div>');
|
||||
}
|
||||
}
|
||||
68
tests/HttpTest/ViewTest/ComposersTest/HeadComposerTest.php
Normal file
68
tests/HttpTest/ViewTest/ComposersTest/HeadComposerTest.php
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Event;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class HeadComposerTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
public function testAddFavicon()
|
||||
{
|
||||
$this->get('/')->assertSee(config('options.favicon_url'));
|
||||
|
||||
option(['favicon_url' => '/a']);
|
||||
$this->get('/')->assertSee(url('/a'));
|
||||
|
||||
option(['favicon_url' => 'http://example.com/icon']);
|
||||
$this->get('/')->assertSee('http://example.com/icon');
|
||||
}
|
||||
|
||||
public function testApplyThemeColor()
|
||||
{
|
||||
$crawler = new Crawler($this->get('/')->getContent());
|
||||
$this->assertCount(1, $crawler->filter('meta[name="theme-color"]'));
|
||||
}
|
||||
|
||||
public function testSeo()
|
||||
{
|
||||
option([
|
||||
'meta_keywords' => 'kw',
|
||||
'meta_description' => 'desc',
|
||||
'meta_extras' => '<meta name=fake><div id=disallowed></div>'
|
||||
]);
|
||||
$crawler = new Crawler($this->get('/')->getContent());
|
||||
$this->assertEquals(
|
||||
'kw',
|
||||
$crawler->filter('meta[name=keywords]')->attr('content')
|
||||
);
|
||||
$this->assertEquals(
|
||||
'desc',
|
||||
$crawler->filter('meta[name=description]')->attr('content')
|
||||
);
|
||||
$this->assertCount(1, $crawler->filter('meta[name=fake]'));
|
||||
$this->assertCount(0, $crawler->filter('div#disallowed'));
|
||||
}
|
||||
|
||||
public function testInjectStyles()
|
||||
{
|
||||
option(['custom_css' => 'div {} <style><div id=disallowed></div></style>']);
|
||||
|
||||
$this->get('/')->assertSee('div {}');
|
||||
|
||||
$crawler = new Crawler($this->get('/')->getContent());
|
||||
$this->assertCount(0, $crawler->filter('div#disallowed'));
|
||||
}
|
||||
|
||||
public function testAddExtra()
|
||||
{
|
||||
Event::listen(\App\Events\RenderingHeader::class, function ($event) {
|
||||
$event->contents[] = '<meta name=appended>';
|
||||
});
|
||||
|
||||
$this->get('/')->assertSee('<meta name=appended>');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
class LanguagesMenuComposerTest extends TestCase
|
||||
{
|
||||
public function testCompose()
|
||||
{
|
||||
$this->get('/')->assertSee('?lang=en')->assertDontSee('en_US');
|
||||
$this->get('/?key=value')->assertSee('?key=value&lang=en');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Event;
|
||||
use App\Events;
|
||||
use App\Models\User;
|
||||
use App\Services\Plugin;
|
||||
use App\Services\PluginManager;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class SideMenuComposerTest extends TestCase
|
||||
{
|
||||
public function testEvents()
|
||||
{
|
||||
Event::fake();
|
||||
|
||||
$admin = factory(User::class, 'admin')->make();
|
||||
$this->actingAs($admin)->get('/user');
|
||||
Event::assertDispatched(Events\ConfigureUserMenu::class);
|
||||
Event::assertDispatched(Events\ConfigureExploreMenu::class);
|
||||
|
||||
$this->get('/admin');
|
||||
Event::assertDispatched(Events\ConfigureAdminMenu::class);
|
||||
}
|
||||
|
||||
public function testTransform()
|
||||
{
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user);
|
||||
|
||||
$crawler = new Crawler($this->get('/user/oauth/manage')->getContent());
|
||||
$this->assertCount(1, $crawler->filter('aside .treeview'));
|
||||
$this->assertCount(2, $crawler->filter('aside .active'));
|
||||
}
|
||||
|
||||
public function testCollectPluginConfigs()
|
||||
{
|
||||
$this->mock(PluginManager::class, function ($mock) {
|
||||
$mock->shouldReceive('getEnabledPlugins')
|
||||
->with()
|
||||
->twice()
|
||||
->andReturn(
|
||||
collect(),
|
||||
collect([
|
||||
new Plugin(resource_path(''), [
|
||||
'config' => 'user/master.blade.php',
|
||||
'title' => 'Fake',
|
||||
'name' => 'fake',
|
||||
])
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
$admin = factory(User::class, 'admin')->make();
|
||||
$this->actingAs($admin)
|
||||
->get('/admin')
|
||||
->assertDontSee(trans('general.plugin-configs'));
|
||||
|
||||
$this->actingAs($admin)
|
||||
->get('/admin')
|
||||
->assertSee(trans('general.plugin-configs'))
|
||||
->assertSee('fa-circle')
|
||||
->assertSee('Fake')
|
||||
->assertSee('admin/plugins/config/fake');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class UserMenuComposerTest extends TestCase
|
||||
{
|
||||
public function testAvatar()
|
||||
{
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user)
|
||||
->get('/user')
|
||||
->assertSee(
|
||||
url('avatar/128/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
}
|
||||
|
||||
public function testTinyAvatar()
|
||||
{
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user)
|
||||
->get('/')
|
||||
->assertSee(
|
||||
url('avatar/25/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
$this->actingAs($user)
|
||||
->get('/skinlib')
|
||||
->assertSee(
|
||||
url('avatar/25/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
$this->actingAs($user)
|
||||
->get('/user')
|
||||
->assertDontSee(
|
||||
url('avatar/25/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Event;
|
||||
use App\Models\User;
|
||||
|
||||
class UserPanelComposerTest extends TestCase
|
||||
{
|
||||
public function testRenderUser()
|
||||
{
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user);
|
||||
|
||||
$this->get('/user')
|
||||
->assertSee(trans('admin.users.status.normal'))
|
||||
->assertSee(
|
||||
url('avatar/45/'.base64_encode($user->email).'.png?tid='.$user->avatar)
|
||||
);
|
||||
}
|
||||
|
||||
public function testBadges()
|
||||
{
|
||||
$user = factory(User::class)->make();
|
||||
$this->actingAs($user);
|
||||
|
||||
Event::listen(\App\Events\RenderingBadges::class, function ($event) {
|
||||
$event->badges[] = ['Pro', 'purple'];
|
||||
});
|
||||
|
||||
$this->get('/user')->assertSee('<small class="label bg-purple">Pro</small>');
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,8 @@ class HookTest extends TestCase
|
|||
$this->actAs('normal')
|
||||
->get('/user')
|
||||
->assertSee('Link A')
|
||||
->assertSee('/to/a" target="_blank"')
|
||||
->assertSee('/to/a')
|
||||
->assertSee('target="_blank"')
|
||||
->assertSee('fa-book');
|
||||
|
||||
// Out of bound
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user