Merge pull request #63 from g-plane/master

细节优化,感谢 @g-plane!
This commit is contained in:
printempw 2017-04-28 22:12:40 +08:00 committed by GitHub
commit e6030842aa
38 changed files with 1065 additions and 644 deletions

View File

@ -165,25 +165,25 @@ class AdminController extends Controller
return view('admin.users');
}
public function getUserData()
public function getUserData(Request $request)
{
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at']);
$users = collect();
$permissionTextMap = [
User::BANNED => trans('admin.users.status.banned'),
User::NORMAL => trans('admin.users.status.normal'),
User::ADMIN => trans('admin.users.status.admin'),
User::SUPER_ADMIN => trans('admin.users.status.super-admin')
];
if ($request->has('uid')) {
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at'])
->where('uid', intval($request->input('uid')));
} else {
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at']);
}
return Datatables::of($users)->editColumn('email', function ($user) {
return $user->email ?: 'EMPTY';
})->editColumn('permission', function ($user) use ($permissionTextMap) {
return array_get($permissionTextMap, $user->permission);
})
->setRowId('uid')
->editColumn('score', 'vendor.admin-operations.users.score')
->addColumn('operations', 'vendor.admin-operations.users.operations')
->addColumn('operations', app('user.current')->getPermission())
->addColumn('players_count', function ($user) {
return Player::where('uid', $user->uid)->count();
})
->make(true);
}
@ -198,15 +198,17 @@ class AdminController extends Controller
return view('admin.players');
}
public function getPlayerData()
public function getPlayerData(Request $request)
{
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified']);
$players = collect();
if ($request->has('uid')) {
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified'])
->where('uid', intval($request->input('uid')));
} else {
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified']);
}
return Datatables::of($players)->editColumn('preference', 'vendor.admin-operations.players.preference')
->setRowId('pid')
->addColumn('previews', 'vendor.admin-operations.players.previews')
->addColumn('operations', 'vendor.admin-operations.players.operations')
->make(true);
return Datatables::of($players)->setRowId('pid')->make(true);
}
/**
@ -228,6 +230,10 @@ class AdminController extends Controller
'email' => 'required|email'
]);
if ($users->get($request->input('email'), 'email')) {
return json(trans('admin.users.operations.email.existed', ['email' => $request->input('email')]), 1);
}
$user->setEmail($request->input('email'));
return json(trans('admin.users.operations.email.success'), 0);
@ -354,6 +360,28 @@ class AdminController extends Controller
$player->delete();
return json(trans('admin.players.delete.success'), 0);
} elseif ($action == "name") {
$player->rename($request->input('name'));
return json(trans('admin.players.name.success', ['player' => $player->player_name]), 0, ['name' => $player->player_name]);
}
}
/**
* Get one user information
*
* @param string $uid
* @return JsonResponse
*/
public function getOneUser($uid, UserRepository $users)
{
$user = $users->get(intval($uid));
if ($user) {
return json('success', 0, ['user' => $user->makeHidden([
'password', 'ip', 'last_sign_at', 'register_at'
])->toArray()]);
} else {
return json('No such user.', 1);
}
}

View File

@ -25,43 +25,40 @@ class ClosetController extends Controller
$this->closet = new Closet(session('uid'));
}
public function index(Request $request)
public function index()
{
return view('user.closet')->with('user', app('user.current'));
}
public function getClosetData(Request $request)
{
$category = $request->input('category', 'skin');
$page = $request->input('page', 1);
$page = $page <= 0 ? 1 : $page;
$page = abs($request->input('page', 1));
$q = $request->input('q', null);
$items = [];
if ($q) {
foreach (['skin', 'cape'] as $category) {
// do search
foreach ($this->closet->getItems($category) as $item) {
if (strstr($item->name, $q)) {
$items[$category][] = $item;
}
// do search
foreach ($this->closet->getItems($category) as $item) {
if (stristr($item->name, $q)) {
$items[] = $item;
}
}
} else {
$items['skin'] = $this->closet->getItems('skin');
$items['cape'] = $this->closet->getItems('cape');
$items = $this->closet->getItems($category);
}
// pagination
$total_pages = [];
$total_pages = ceil(count($items) / 6);
foreach ($items as $key => $value) {
$total_pages[] = ceil(count($items[$key]) / 6);
$items[$key] = array_slice($value, ($page-1)*6, 6);
}
$items = array_slice($items, ($page - 1) * 6, 6);
return view('user.closet')->with('items', $items)
->with('page', $page)
->with('q', $q)
->with('category', $category)
->with('total_pages', $total_pages ? max($total_pages) : 0)
->with('user', app('user.current'));
return response()->json([
'category' => $category,
'items' => $items,
'total_pages' => $total_pages
]);
}
public function info()

View File

@ -138,9 +138,13 @@ class PlayerController extends Controller
return json(trans('user.player.set.success', ['name' => $this->player->player_name]), 0);
}
public function clearTexture()
public function clearTexture(Request $request)
{
$this->player->clearTexture();
$types = array_filter(['steve', 'alex', 'cape'], function ($type) use ($request) {
return $request->input($type);
});
$this->player->clearTexture($types);
return json(trans('user.player.clear.success', ['name' => $this->player->player_name]), 0);
}

View File

@ -75,13 +75,13 @@ class PluginController extends Controller
return trans($plugin->description);
})
->editColumn('author', function ($plugin) {
return "<a href='{$plugin->url}' target='_blank'>".trans($plugin->author)."</a>";
return ['author' => trans($plugin->author), 'url' => $plugin->url];
})
->addColumn('status', function ($plugin) {
return trans('admin.plugins.status.'.($plugin->isEnabled() ? 'enabled' : 'disabled'));
})
->addColumn('operations', function ($plugin) {
return view('vendor.admin-operations.plugins.operations', compact('plugin'));
return ['enabled' => $plugin->isEnabled(), 'hasConfigView' => $plugin->hasConfigView()];
})
->make(true);
}

View File

@ -32,7 +32,7 @@ class SetupController extends Controller
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required|min:6|max:16|confirmed',
'password' => 'required|min:8|max:16|confirmed',
'site_name' => 'required'
]);

View File

@ -32,41 +32,41 @@ class SkinlibController extends Controller
{
$filter = $request->input('filter', 'skin');
$sort = $request->input('sort', 'time');
$uid = $request->input('uid', session('uid'));
$page = $request->input('page', 1);
$page = $page <= 0 ? 1 : $page;
$uid = intval($request->input('uid', 0));
$page = $request->input('page', 1) <= 0 ? 1 : $request->input('page', 1);
$sort_by = ($sort == "time") ? "upload_at" : $sort;
if ($filter == "skin") {
$textures = Texture::where(function($query) {
$query->where('type', '=', 'steve')
->orWhere('type', '=', 'alex');
})->orderBy($sort_by, 'desc');
} elseif ($filter == "user") {
$textures = Texture::where('uploader', $uid)->orderBy($sort_by, 'desc');
$textures = Texture::where('type', 'steve')->orWhere('type', 'alex');
} else {
$textures = Texture::where('type', $filter)->orderBy($sort_by, 'desc');
$textures = Texture::where('type', $filter);
}
$textures = $textures->orderBy($sort_by, 'desc')->get();
if ($uid != 0) {
$textures = $textures->where('uploader', $uid);
}
if (!is_null($this->user)) {
// show private textures when show uploaded textures of current user
if (!$this->user->isAdmin())
$textures = $textures->where('public', '1')
->orWhere('uploader', $this->user->uid);
if ($uid != $this->user->uid && !$this->user->isAdmin()) {
$textures = $textures->where('public', 1)
->merge($textures->where('uploader', $this->user->uid));
}
} else {
$textures = $textures->where('public', '1');
$textures = $textures->where('public', 1);
}
$total_pages = ceil($textures->count() / 20);
$textures = $textures->skip(($page - 1) * 20)->take(20)->get();
$textures = $textures->slice(($page - 1) * 20);
return view('skinlib.index')->with('user', $this->user)
->with('sort', $sort)
->with('filter', $filter)
->with('uploader', $uid)
->with('textures', $textures)
->with('page', $page)
->with('total_pages', $total_pages);
@ -80,22 +80,36 @@ class SkinlibController extends Controller
$sort_by = ($sort == "time") ? "upload_at" : $sort;
if ($q == '') {
return redirect('skinlib');
}
if ($filter == "skin") {
$textures = Texture::like('name', $q)->where(function($query) use ($q) {
$query->where('public', '=', '1')
->where('type', '=', 'steve')
$query->where('type', '=', 'steve')
->orWhere('type', '=', 'alex');
})->orderBy($sort_by, 'desc')->get();
} else {
$textures = Texture::like('name', $q)
->where('type', $filter)
->where('public', '1')
->where('public', 1)
->orderBy($sort_by, 'desc')->get();
}
if (!is_null($this->user)) {
// show private textures when show uploaded textures of current user
if (!$this->user->isAdmin()) {
$textures = $textures->where('public', 1)
->merge($textures->where('uploader', $this->user->uid));
}
} else {
$textures = $textures->where('public', 1);
}
return view('skinlib.search')->with('user', $this->user)
->with('sort', $sort)
->with('filter', $filter)
->with('uploader', 0)
->with('q', $q)
->with('textures', $textures);
}
@ -153,6 +167,7 @@ class SkinlibController extends Controller
$t->upload_at = Utils::getTimeFormatted();
$cost = $t->size * (($t->public == "1") ? Option::get('score_per_storage') : Option::get('private_score_per_storage'));
$cost += option('score_per_closet_item');
if ($this->user->getScore() < $cost)
return json(trans('skinlib.upload.lack-score'), 7);
@ -182,7 +197,7 @@ class SkinlibController extends Controller
}
}
public function delete(Request $request)
public function delete(Request $request, UserRepository $users)
{
$result = Texture::find($request->tid);
@ -197,17 +212,24 @@ class SkinlibController extends Controller
Storage::delete($result['hash']);
if (option('return_score')) {
if ($result->public == 1)
$this->user->setScore($result->size * Option::get('score_per_storage'), 'plus');
if ($result->public == 1) {
$users->get($result->uploader)->setScore($result->size * Option::get('score_per_storage'), 'plus');
foreach (Closet::all() as $closet) {
if ($closet->has($result->tid)) {
$closet->remove($result->tid);
$users->get($closet->uid)->setScore(option('score_per_closet_item'), 'plus');
}
}
}
else
$this->user->setScore($result->size * Option::get('private_score_per_storage'), 'plus');
$users->get($result->uploader)->setScore($result->size * Option::get('private_score_per_storage'), 'plus');
}
if ($result->delete())
return json(trans('skinlib.delete.success'), 0);
}
public function privacy(Request $request)
public function privacy(Request $request, UserRepository $users)
{
$t = Texture::find($request->input('tid'));
$type = $t->type;
@ -227,12 +249,12 @@ class SkinlibController extends Controller
if ($closet->uid != $uid && $closet->has($t->tid)) {
$closet->remove($t->tid);
if (option('return_score')) {
User::find($closet->uid)->setScore(option('score_per_closet_item'), 'plus');
$users->get($closet->uid)->setScore(option('score_per_closet_item'), 'plus');
}
}
}
app('user.current')->setScore(
$users->get($t->uploader)->setScore(
$t->size * (option('private_score_per_storage') - option('score_per_storage')) * ($t->public == 1 ? -1 : 1),
'plus'
);

View File

@ -90,9 +90,9 @@ class UserController extends Controller
* Handle changing user profile.
*
* @param Request $request
* @return void
* @return mixed
*/
public function handleProfile(Request $request)
public function handleProfile(Request $request, UserRepository $users)
{
$action = $request->input('action', '');
@ -129,6 +129,10 @@ class UserController extends Controller
'password' => 'required|min:8|max:16'
]);
if ($users->get($request->input('new_email'), 'email')) {
return json(trans('user.profile.email.existed'), 1);
}
if (!$this->user->verifyPassword($request->input('password')))
return json(trans('user.profile.email.wrong-password'), 1);

View File

@ -65,6 +65,7 @@ Route::group(['middleware' => 'auth', 'prefix' => 'user'], function ()
// Closet
Route::get ('/closet', 'ClosetController@index');
Route::get ('/closet-data', 'ClosetController@getClosetData');
Route::post('/closet/add', 'ClosetController@add');
Route::post('/closet/remove', 'ClosetController@remove');
Route::post('/closet/rename', 'ClosetController@rename');
@ -107,6 +108,7 @@ Route::group(['middleware' => 'admin', 'prefix' => 'admin'], function ()
Route::get('/players', 'AdminController@players');
Route::get('/player-data', 'AdminController@getPlayerData');
Route::get('/user/{uid}', 'AdminController@getOneUser');
// ajax handlers
Route::post('/users', 'AdminController@userAjaxHandler');

View File

@ -97,17 +97,22 @@ class Player extends Model
/**
* Clear the textures of player.
*
* @return mixed
* @param array|string $types
* @return $this
*/
public function clearTexture()
public function clearTexture($types)
{
$this->setPreference('default');
$types = (array) $types;
return $this->setTexture([
'tid_steve' => 0,
'tid_alex' => 0,
'tid_cape' => 0
]);
$map = [];
foreach ($types as $type) {
$map["tid_$type"] = 0;
}
$this->setTexture($map);
return $this;
}
/**

View File

@ -24,6 +24,10 @@
"font-awesome": "Font-Awesome#^4.6.3",
"bootstrap-fileinput": "^4.3.3",
"bootstrap": "^3.3.6",
"sweetalert2": "^4.1.6"
"sweetalert2": "^4.1.6",
"jqPaginator": "^1.2.0"
},
"resolutions": {
"jquery": "1.9.1 - 3"
}
}

View File

@ -1,8 +1,8 @@
/*
* @Author: printempw
* @Date: 2016-07-21 13:38:26
* @Last Modified by: printempw
* @Last Modified time: 2017-01-22 20:45:06
* @Last Modified by: g-plane
* @Last Modified time: 2017-04-26 15:39:46
*/
'use strict';
@ -35,6 +35,7 @@ var vendorScripts = [
'toastr/toastr.min.js',
'es6-promise/es6-promise.auto.min.js',
'sweetalert2/dist/sweetalert2.min.js',
'jqPaginator/dist/jqPaginator.min.js',
'resources/assets/dist/scripts/general.js',
];

View File

@ -1,16 +1,39 @@
/*
* @Author: printempw
* @Date: 2016-07-22 14:02:44
* @Last Modified by: printempw
* @Last Modified time: 2017-01-21 10:58:50
* @Last Modified by: g-plane
* @Last Modified time: 2017-04-28 19:54:02
*/
'use strict';
let pluginsTable;
$(document).ready(function() {
$('input').iCheck({
checkboxClass: 'icheckbox_square-blue'
});
swal.setDefaults({
confirmButtonText: trans('general.confirm'),
cancelButtonText: trans('general.cancel')
});
$.extend(true, $.fn.dataTable.defaults, {
language: trans('vendor.datatables'),
scrollX: true,
pageLength: 25,
autoWidth: false,
processing: true,
serverSide: true
});
if (window.location.href.indexOf(url('admin/users')) >= 0) {
initUsersTable();
} else if (window.location.href.indexOf(url('admin/players')) >= 0) {
initPlayersTable();
} else if (window.location.href.indexOf(url('admin/plugins/manage')) >= 0) {
pluginsTable = initPluginsTable();
}
});
$('#layout-skins-list [data-skin]').click(function(e) {
@ -37,67 +60,75 @@ $('#color-submit').click(function() {
});
function changeUserEmail(uid) {
var email = prompt(trans('admin.newUserEmail'));
if (!email) return;
$.ajax({
type: "POST",
url: "./users?action=email",
dataType: "json",
data: { 'uid': uid, 'email': email },
success: function(json) {
if (json.errno == 0) {
$($('tr#'+uid+' > td')[1]).html(email);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
let dom = $(`tr#user-${uid} > td:nth-child(2)`);
swal({
text: trans('admin.newUserEmail'),
showCancelButton: true,
input: 'text',
inputValue: dom.text()
}).then(email => {
$.ajax({
type: "POST",
url: "./users?action=email",
dataType: "json",
data: { 'uid': uid, 'email': email },
success: json => {
if (json.errno == 0) {
dom.text(email);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
});
});
}
function changeUserNickName(uid) {
var nickname = prompt(trans('admin.newUserNickname'));
if (!nickname) return;
$.ajax({
type: "POST",
url: "./users?action=nickname",
dataType: "json",
data: { 'uid': uid, 'nickname': nickname },
success: function(json) {
if (json.errno == 0) {
$($('tr#'+uid+' > td')[2]).html(nickname);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
let dom = $(`tr#user-${uid} > td:nth-child(3)`);
swal({
text: trans('admin.newUserNickname'),
showCancelButton: true,
input: 'text',
inputValue: dom.text()
}).then(nickname => {
$.ajax({
type: "POST",
url: "./users?action=nickname",
dataType: "json",
data: { 'uid': uid, 'nickname': nickname },
success: json => {
if (json.errno == 0) {
dom.text(nickname);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
});
});
}
function changeUserPwd(uid) {
var password = prompt(trans('admin.newUserPassword'));
if (!password) return;
$.ajax({
type: "POST",
url: "./users?action=password",
dataType: "json",
data: { 'uid': uid, 'password': password },
success: function(json) {
if (json.errno == 0)
toastr.success(json.msg);
else
toastr.warning(json.msg);
},
error: showAjaxError
});
swal({
text: trans('admin.newUserPassword'),
showCancelButton: true,
input: 'password',
}).then(password => {
return Promise.resolve($.ajax({
type: "POST",
url: "./users?action=password",
dataType: "json",
data: { 'uid': uid, 'password': password }
}));
}).then(json => {
if (json.errno == 0)
toastr.success(json.msg);
else
toastr.warning(json.msg);
}).catch(error => showAjaxError);
}
function changeUserScore(uid, score) {
@ -126,12 +157,16 @@ function changeBanStatus(uid) {
data: { 'uid': uid },
success: function(json) {
if (json.errno == 0) {
var object = $('#'+uid).find('a#ban');
var dom = '<a id="ban" href="javascript:changeBanStatus('+uid+');">' +
(object.text() == trans('admin.ban') ? trans('admin.unban') : trans('admin.ban')) + '</a>';
object.html(dom);
let dom = $(`#ban-${uid}`);
if (dom.attr('data') == 'banned') {
dom.text(trans('admin.ban'));
dom.attr('data', 'normal');
} else {
dom.text(trans('admin.unban'));
dom.attr('data', 'banned');
}
$('#'+uid).find('#permission').text(json.permission == '-1' ? trans('admin.banned') : trans('admin.normal'));
$(`#user-${uid} > td:nth-child(5)`).text(json.permission == -1 ? trans('admin.banned') : trans('admin.normal'));
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
@ -149,12 +184,16 @@ function changeAdminStatus(uid) {
data: { 'uid': uid },
success: function(json) {
if (json.errno == 0) {
var object = $('#'+uid).find('a#admin');
var dom = '<a href="javascript:changeAdminStatus('+uid+');">' +
(object.text() == trans('admin.setAdmin') ? trans('admin.unsetAdmin') : trans('admin.setAdmin')) + '</a>';
object.html(dom);
let dom = $(`#admin-${uid}`);
if (dom.attr('data') == 'admin') {
dom.text(trans('admin.setAdmin'));
dom.attr('data', 'normal');
} else {
dom.text(trans('admin.unsetAdmin'));
dom.attr('data', 'admin');
}
$('#'+uid).find('#permission').text(json.permission == '1' ? trans('admin.admin') : trans('admin.normal'));
$(`#user-${uid} > td:nth-child(5)`).text(json.permission == 1 ? trans('admin.admin') : trans('admin.normal'));
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
@ -165,23 +204,25 @@ function changeAdminStatus(uid) {
}
function deleteUserAccount(uid) {
if (!window.confirm(trans('admin.deleteUserNotice'))) return;
$.ajax({
type: "POST",
url: "./users?action=delete",
dataType: "json",
data: { 'uid': uid },
success: function(json) {
if (json.errno == 0) {
$('tr#'+uid).remove();
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
});
swal({
text: trans('admin.deleteUserNotice'),
type: 'warning',
showCancelButton: true
}).then(() => {
return Promise.resolve($.ajax({
type: "POST",
url: "./users?action=delete",
dataType: "json",
data: { 'uid': uid }
}))
}).then(json => {
if (json.errno == 0) {
$('tr#user-' + uid).remove();
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
}).catch(error => showAjaxError);
}
$('body').on('keypress', '.score', function(event){
@ -191,7 +232,7 @@ $('body').on('keypress', '.score', function(event){
}
});
$('body').on('change', '#preference', function() {
function changePreference() {
$.ajax({
type: "POST",
url: "./players?action=preference",
@ -206,9 +247,9 @@ $('body').on('change', '#preference', function() {
},
error: showAjaxError
});
});
}
function changeTexture(pid) {
function changeTexture(pid, playerName) {
let dom = `
<div class="form-group">
<label for="model">${trans('admin.textureType')}</label>
@ -223,8 +264,6 @@ function changeTexture(pid) {
<input id="tid" class="form-control" type="text" placeholder="${trans('admin.pidNotice')}">
</div>`;
let playerName = $('#'+pid).find('#player-name').text();
showModal(dom, trans('admin.changePlayerTexture', {'player': playerName}), 'default', {
callback: `ajaxChangeTexture(${pid})`
});
@ -259,46 +298,106 @@ function ajaxChangeTexture(pid) {
});
}
function changePlayerName(pid, oldName) {
let dom = $(`tr#${pid} > td:nth-child(3)`);
swal({
text: trans('admin.changePlayerNameNotice'),
input: 'text',
inputValue: oldName,
inputValidator: name => {
return new Promise((resolve, reject) => {
if (name) {
resolve();
} else {
reject(trans('admin.emptyPlayerName'));
}
})
}
}).then(name => {
return Promise.resolve($.ajax({
type: 'POST',
url: './players?action=name',
dataType: 'json',
data: { pid: pid, name: name }
}));
}).then(json => {
if (json.errno == 0) {
dom.text(json.name);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
}).catch(error => showAjaxError);
}
function changeOwner(pid) {
var uid = prompt(trans('admin.changePlayerOwner'));
if (!uid) return;
$.ajax({
type: "POST",
url: "./players?action=owner",
dataType: "json",
data: { 'pid': pid, 'uid': uid },
success: function(json) {
if (json.errno == 0) {
$($('#'+pid).children()[1]).text(uid);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
let dom = $(`#${pid} > td:nth-child(2)`);
swal({
html: `${trans('admin.changePlayerOwner')}<br><small>&nbsp;</small>`,
input: 'number',
inputValue: dom.text(),
showCancelButton: true
}).then(uid => {
$.ajax({
type: "POST",
url: "./players?action=owner",
dataType: "json",
data: { 'pid': pid, 'uid': uid },
success: function (json) {
if (json.errno == 0) {
dom.text(uid);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
});
});
$('.swal2-input').on('input', debounce(() => {
const uid = $('.swal2-input').val();
if (uid > 0) {
Promise.resolve($.ajax({
type: 'GET',
url: `./user/${uid}`,
dataType: 'json'
})).then(result => {
$('#swal2-content').html(
`${trans('admin.changePlayerOwner')}<br>
<small>${trans('admin.targetUser', { nickname: result.user.nickname })}</small>`
);
}).catch(() => {
$('#swal2-content').html(`${trans('admin.changePlayerOwner')}<br><small>${trans('admin.noSuchUser')}</small>`);
});
}
}, 350));
}
function deletePlayer(pid) {
if (!window.confirm(trans('admin.deletePlayerNotice'))) return;
swal({
text: trans('admin.deletePlayerNotice'),
type: 'warning',
showCancelButton: true
}).then(() => {
return Promise.resolve($.ajax({
type: "POST",
url: "./players?action=delete",
dataType: "json",
data: { 'pid': pid },
success: function (json) {
$.ajax({
type: "POST",
url: "./players?action=delete",
dataType: "json",
data: { 'pid': pid },
success: function(json) {
if (json.errno == 0) {
$('tr#'+pid).remove();
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: showAjaxError
});
},
error: showAjaxError
}))
}).then(json => {
if (json.errno == 0) {
$('tr#' + pid).remove();
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
}).catch(error => showAjaxError);
}
function enablePlugin(name) {
@ -310,7 +409,7 @@ function enablePlugin(name) {
if (json.errno == 0) {
toastr.success(json.msg);
table.ajax.reload(null, false);
pluginsTable.ajax.reload(null, false);
} else {
toastr.warning(json.msg);
}
@ -328,7 +427,7 @@ function disablePlugin(name) {
if (json.errno == 0) {
toastr.warning(json.msg);
table.ajax.reload(null, false);
pluginsTable.ajax.reload(null, false);
} else {
toastr.warning(json.msg);
}
@ -351,7 +450,7 @@ function deletePlugin(name) {
if (json.errno == 0) {
toastr.success(json.msg);
$('tr[id=plugin-'+name+']').remove();
pluginsTable.ajax.reload(null, false);
} else {
toastr.warning(json.msg);
}
@ -453,3 +552,273 @@ function downloadUpdates() {
.fail(showAjaxError);
}
function initUsersTable() {
let dataUrl = url('admin/user-data');
if (getQueryString('uid')) {
dataUrl += '?uid=' + getQueryString('uid');
}
$('#user-table').DataTable({
ajax: dataUrl,
scrollY: ($('.content-wrapper').height() - $('.content-header').outerHeight()) * 0.7,
rowCallback: (row, data) => {
$(row).attr('id', `user-${data.uid}`);
},
columnDefs: [
{
targets: 0,
data: 'uid',
width: '1%'
},
{
targets: 1,
data: 'email'
},
{
targets: 2,
data: 'nickname'
},
{
targets: 3,
data: 'score',
render: data => {
return `<input type="number" class="form-control score" value="${data}" title="${trans('admin.scoreTip')}" data-toggle="tooltip" data-placement="right">`;
}
},
{
targets: 4,
data: 'players_count',
render: (data, type, row) => {
return `<span title="${trans('admin.doubleClickToSeePlayers')}"
style="cursor: pointer;"
ondblclick="window.location.href = '${url('admin/players?uid=') + row.uid}'"
data-toggle="tooltip" data-placement="top">${data}</span>`;
}
},
{
targets: 5,
data: 'permission',
render: data => {
switch (data) {
case -1:
return trans('admin.banned');
case 0:
return trans('admin.normal');
case 1:
return trans('admin.admin');
case 2:
return trans('admin.superAdmin');
}
}
},
{
targets: 6,
data: 'register_at'
},
{
targets: 7,
data: 'operations',
searchable: false,
orderable: false,
render: (data, type, row) => {
let operationsHtml, adminOption = '', bannedOption = '', deleteUserButton;
if (row.permission !== 2) {
if (data === 2) {
if (row.permission === 1) {
adminOption = `<li class="divider"></li>
<li><a id="admin-${row.uid}" data="admin" href="javascript:changeAdminStatus(${row.uid});">${trans('admin.unsetAdmin')}</a></li>`;
} else {
adminOption = `<li class="divider"></li>
<li><a id="admin-${row.uid}" data="normal" href="javascript:changeAdminStatus(${row.uid});">${trans('admin.setAdmin')}</a></li>`;
}
}
if (row.permission === -1) {
bannedOption = `<li class="divider"></li>
<li><a id="ban-${row.uid}" data="banned" href="javascript:changeBanStatus(${row.uid});">${trans('admin.unban')}</a></li>`;
} else {
bannedOption = `<li class="divider"></li>
<li><a id="ban-${row.uid}" data="normal" href="javascript:changeBanStatus(${row.uid});">${trans('admin.ban')}</a></li>`;
}
}
if (data === 2) {
if (row.permission === 2) {
deleteUserButton = `
<a class="btn btn-danger btn-sm" disabled="disabled" data-toggle="tooltip" data-placement="bottom" title="${trans('admin.cannotDeleteSuperAdmin')}">${trans('admin.deleteUser')}</a>`;
} else {
deleteUserButton = `
<a class="btn btn-danger btn-sm" href="javascript:deleteUserAccount(${row.uid});">${trans('admin.deleteUser')}</a>`;
}
} else {
if (row.permission === 1 || row.permission === 2) {
deleteUserButton = `
<a class="btn btn-danger btn-sm" disabled="disabled" data-toggle="tooltip" data-placement="bottom" title="${trans('admin.cannotDeleteAdmin')}">${trans('admin.deleteUser')}</a>`;
} else {
deleteUserButton = `
<a class="btn btn-danger btn-sm" href="javascript:deleteUserAccount(${row.uid});">${trans('admin.deleteUser')}</a>`;
}
}
return `
<div class="btn-group">
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${trans('admin.operationsTitle')} <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="javascript:changeUserEmail(${row.uid});">${trans('admin.changeEmail')}</a></li>
<li><a href="javascript:changeUserNickName(${row.uid});">${trans('admin.changeNickName')}</a></li>
<li><a href="javascript:changeUserPwd(${row.uid});">${trans('admin.changePassword')}</a></li>
${adminOption}${bannedOption}
</ul>
</div>
${deleteUserButton}`;
}
}
]
});
}
function initPlayersTable() {
let dataUrl = url('admin/player-data');
if (getQueryString('uid')) {
dataUrl += '?uid=' + getQueryString('uid');
}
$('#player-table').DataTable({
ajax: dataUrl,
scrollY: ($('.content-wrapper').height() - $('.content-header').outerHeight()) * 0.7,
columnDefs: [
{
targets: 0,
data: 'pid',
width: '1%'
},
{
targets: 1,
data: 'uid',
render: (data, type, row) => {
return `<span title="${trans('admin.doubleClickToSeeUser')}"
style="cursor: pointer;"
ondblclick="window.location.href = '${url('admin/users?uid=') + row.uid}'"
data-toggle="tooltip" data-placement="top">${data}</span>`;
}
},
{
targets: 2,
data: 'player_name'
},
{
targets: 3,
data: 'preference',
render: data => {
return `
<select class="form-control" onchange="changePreference.call(this)">
<option ${(data == "default") ? 'selected=selected' : ''} value="default">Default</option>
<option ${(data == "slim") ? 'selected=selected' : ''} value="slim">Slim</option>
</select>`;
}
},
{
targets: 4,
searchable: false,
orderable: false,
render: (data, type, row) => {
let html = { steve: '', alex: '', cape: '' };
['steve', 'alex', 'cape'].forEach(textureType => {
if (row['tid_' + textureType] === 0) {
html[textureType] = `<img id="${row.pid}-${row['tid_' + textureType]}" width="64" />`;
} else {
html[textureType] = `
<a href="${url('/')}skinlib/show/${row['tid_' + textureType]}">
<img id="${row.pid}-${row['tid_' + textureType]}" width="64" src="${url('/')}preview/64/${row['tid_' + textureType]}.png" />
</a>`;
}
});
return html.steve + html.alex + html.cape;
}
},
{
targets: 5,
data: 'last_modified'
},
{
targets: 6,
searchable: false,
orderable: false,
render: (data, type, row) => {
return `
<div class="btn-group">
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${trans('admin.operationsTitle')} <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="javascript:changeTexture(${row.pid}, '${row.player_name}');">${trans('admin.changeTexture')}</a></li>
<li><a href="javascript:changePlayerName(${row.pid}, '${row.player_name}');">${trans('admin.changePlayerName')}</a></li>
<li><a href="javascript:changeOwner(${row.pid});">${trans('admin.changeOwner')}</a></li>
</ul>
</div>
<a class="btn btn-danger btn-sm" href="javascript:deletePlayer(${row.pid});">${trans('admin.deletePlayer')}</a>`;
}
}
]
});
}
function initPluginsTable() {
return $('#plugin-table').DataTable({
ajax: url('admin/plugins/data'),
columnDefs: [
{
targets: 0,
data: 'title'
},
{
targets: 1,
data: 'description',
width: '35%'
},
{
targets: 2,
data: 'author',
render: data => {
if (data.url === '' || data.url === null) {
return data.author;
} else {
return `<a href="${data.url}" target="_blank">${data.author}</a>`;
}
}
},
{
targets: 3,
data: 'version'
},
{
targets: 4,
data: 'status'
},
{
targets: 5,
data: 'operations',
searchable: false,
orderable: false,
render: (data, type, row) => {
let switchEnableButton, configViewButton, deletePluginButton;
if (data.enabled) {
switchEnableButton = `
<a class="btn btn-warning btn-sm" href="javascript:disablePlugin('${row.name}');">${trans('admin.disablePlugin')}</a>`;
} else {
switchEnableButton = `
<a class="btn btn-primary btn-sm" href="javascript:enablePlugin('${row.name}');">${trans('admin.enablePlugin')}</a>`;
}
if (data.enabled && data.hasConfigView) {
configViewButton = `
<a class="btn btn-default btn-sm" href="${url('/')}admin/plugins/config/${row.name}">${trans('admin.configurePlugin')}</a>`;
} else {
configViewButton = `
<a class="btn btn-default btn-sm" disabled="disabled" title="${trans('admin.noPluginConfigNotice')}" data-toggle="tooltip" data-placement="top">${trans('admin.configurePlugin')}</a>`;
}
deletePluginButton = `
<a class="btn btn-danger btn-sm" href="javascript:deletePlugin('${row.name}');">${trans('admin.deletePlugin')}</a>`;
return switchEnableButton + configViewButton + deletePluginButton;
}
}
]
});
}

View File

@ -1,8 +1,8 @@
/*
* @Author: printempw
* @Date: 2016-09-15 10:39:41
* @Last Modified by: printempw
* @Last Modified time: 2017-01-22 18:51:51
* @Last Modified by: g-plane
* @Last Modified time: 2017-04-27 15:33:24
*/
'use strict';
@ -88,7 +88,7 @@ function trans(key, parameters = {}) {
return temp;
}
function showModal(msg, title = 'Messgae', type = 'default', options = {}) {
function showModal(msg, title = 'Message', type = 'default', options = {}) {
let btnType = (type != "default") ? "btn-outline" : "btn-primary";
let onClick = (options.callback === undefined) ? 'data-dismiss="modal"' : `onclick="${options.callback}"`;
@ -157,6 +157,28 @@ function getQueryString(key) {
}
}
/**
* Return a debounced function
*
* @param {Function} func
* @param {number} delay
* @param {Array} args
* @param {Object} context
*/
function debounce(func, delay, args = [], context = undefined) {
if (isNaN(delay) || typeof func !== 'function') {
throw new Error('Arguments type of function "debounce" is incorrent!');
}
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
}
}
// polyfill of String.prototype.endsWith
if (!String.prototype.endsWith) {
String.prototype.endsWith = function (searchString, position) {
@ -200,18 +222,11 @@ function confirmLogout() {
}
function logout() {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: url('auth/logout'),
dataType: "json",
success: (json) => resolve(json),
error: (json) => {
showAjaxError(json);
reject(json);
}
});
});
return Promise.resolve($.ajax({
type: "POST",
url: url('auth/logout'),
dataType: "json"
}));
}
$('#logout-button').click(() => confirmLogout());
@ -237,7 +252,7 @@ var TexturePreview = function (type, tid, preference) {
this.change3dPreview = function () {
if (this.playerPreference == this.preference) {
if (this.playerPreference == this.preference || this.type == 'cape') {
$.ajax({
type: "GET",
url: url(`skinlib/info/${this.tid}`),

View File

@ -1,8 +1,8 @@
/*
* @Author: printempw
* @Date: 2016-07-19 10:46:38
* @Last Modified by: printempw
* @Last Modified time: 2017-01-22 15:57:57
* @Last Modified by: g-plane
* @Last Modified time: 2017-04-25 21:56:19
*/
'use strict';
@ -158,8 +158,9 @@ function handleFiles(files, type) {
(type == "skin") ? MSP.changeSkin(img.src) : MSP.changeCape(img.src);
let domTextureName = $('#name');
if (domTextureName.val() === '' || domTextureName.val() === domTextureName.attr('data-last-file-name')) {
domTextureName.attr('data-last-file-name', file.name);
domTextureName.val(file.name);
const fileName = file.name.replace(/\.[Pp][Nn][Gg]$/, '');
domTextureName.attr('data-last-file-name', fileName);
domTextureName.val(fileName);
}
};
img.onerror = () => toastr.warning(trans('skinlib.fileExtError'));
@ -243,10 +244,11 @@ function upload() {
return false;
}
function changeTextureName(tid) {
function changeTextureName(tid, oldName) {
swal({
text: trans('skinlib.setNewTextureName'),
input: 'text',
inputValue: oldName,
showCancelButton: true,
inputValidator: (value) => {
return new Promise((resolve, reject) => {

View File

@ -1,8 +1,8 @@
/*
* @Author: printempw
* @Date: 2016-07-16 10:02:24
* @Last Modified by: printempw
* @Last Modified time: 2017-01-20 21:19:07
* @Last Modified by: g-plane
* @Last Modified time: 2017-04-27 16:37:05
*/
'use strict';
@ -18,13 +18,13 @@ $('body').on('click', '#preview-switch', () => {
TexturePreview.previewType == '3D' ? TexturePreview.show2dPreview() : TexturePreview.show3dPreview();
});
var selected = [];
let selectedTextures = [];
$('body').on('click', '.item-body', function () {
$('.item-selected').parent().removeClass('item-selected');
$(this).parent().addClass('item-selected');
let tid = $(this).parent().attr('tid');
const tid = parseInt($(this).parent().attr('tid'));
$.ajax({
type: "POST",
@ -33,24 +33,94 @@ $('body').on('click', '.item-body', function () {
success: (json) => {
if (json.type == "cape") {
MSP.changeCape('../textures/' + json.hash);
selected['cape'] = tid;
selectedTextures['cape'] = tid;
} else {
MSP.changeSkin('../textures/' + json.hash);
selected['skin'] = tid;
selectedTextures['skin'] = tid;
}
selected.length = 0;
['skin', 'cape'].forEach((key) => {
if (selected[key] !== undefined) selected.length++;
$('#textures-indicator').html(selected.length);
});
if (selectedTextures['skin'] !== undefined && selectedTextures['cape'] !== undefined)
$('#textures-indicator').text(`${trans('general.skin')} & ${trans('general.cape')}`);
else if (selectedTextures['skin'] != undefined)
$('#textures-indicator').text(trans('general.skin'));
else if (selectedTextures['cape'] != undefined)
$('#textures-indicator').text(trans('general.cape'));
},
error: showAjaxError
});
});
$('body').on('click', '.category-switch', () => {
const category = $('a[href="#skin-category"]').parent().hasClass('active') ? 'cape' : 'skin';
const page = parseInt($('#closet-paginator').attr(`last-${category}-page`));
const search = $('input[name=q]').val();
reloadCloset(category, page, search);
});
function renderClosetItemComponent(item) {
return `
<div class="item" tid="${item.tid}">
<div class="item-body">
<img src="${url('/')}preview/${item.tid}.png">
</div>
<div class="item-footer">
<p class="texture-name">
<span title="${item.name}">${item.name} <small>(${item.type})</small></span>
</p>
<a href="${url('/')}skinlib/show/${item.tid}" title="${trans('user.viewInSkinlib')}" class="more" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-share"></i></a>
<span title="${trans('general.more')}" class="more" data-toggle="dropdown" aria-haspopup="true" id="more-button"><i class="fa fa-cog"></i></span>
<ul class="dropup dropdown-menu" aria-labelledby="more-button">
<li><a href="javascript:renameClosetItem(${item.tid}, '${item.name}');">${trans('user.renameItem')}</a></li>
<li><a href="javascript:removeFromCloset(${item.tid});">${trans('user.removeItem')}</a></li>
<li><a href="javascript:setAsAvatar(${item.tid});">${trans('user.setAsAvatar')}</a></li>
</ul>
</div>
</div>`;
}
function renderCloset(items, category) {
const search = $('input[name=q]').val();
let container = $(`#${category}-category`);
container.html('');
if (items.length === 0) {
$('#closet-paginator').hide();
if (search === '') {
container.html(`<div class="empty-msg">
${trans('user.emptyClosetMsg', { url: url('skinlib?filter=' + category) })}</div>`);
} else {
container.html(`<div class="empty-msg">${trans('general.noResult')}</div>`);
}
} else {
$('#closet-paginator').show();
for (const item of items) {
container.append(renderClosetItemComponent(item));
}
}
}
function reloadCloset(category, page, search) {
Promise.resolve($.ajax({
type: 'GET',
url: url('user/closet-data'),
dataType: 'json',
data: {
category: category,
page: page,
q: search
}
})).then(result => {
renderCloset(result.items, result.category);
let paginator = $('#closet-paginator');
paginator.attr(`last-${result.category}-page`, page);
paginator.jqPaginator('option', {
currentPage: page,
totalPages: result.total_pages
});
}).catch(error => showAjaxError);
}
function showPlayerTexturePreview(pid) {
$.ajax({
type: "POST",
@ -81,10 +151,11 @@ function showPlayerTexturePreview(pid) {
});
}
function renameClosetItem(tid) {
function renameClosetItem(tid, oldName) {
swal({
title: trans('user.renameClosetItem'),
input: 'text',
inputValue: oldName,
showCancelButton: true,
inputValidator: function(value) {
return new Promise(function(resolve, reject) {
@ -133,6 +204,14 @@ function removeFromCloset(tid) {
});
$('div[tid='+tid+']').remove();
['skin', 'cape'].forEach(type => {
let container = $(`#${type}-category`);
if ($.trim(container.html()) == '') {
container.html(`<div class="empty-msg">
${trans('user.emptyClosetMsg', { url: url('skinlib?filter=' + type) })}</div>`);
}
})
} else {
toastr.warning(json.msg);
}
@ -178,6 +257,43 @@ $(document).ready(function() {
confirmButtonText: trans('general.confirm'),
cancelButtonText: trans('general.cancel')
});
if (window.location.pathname.includes('/user/closet')) {
Promise.resolve($.ajax({
type: 'GET',
url: /(^https?.*)\/user\/closet/.exec(window.location.href)[1] + '/user/closet-data',
dataType: 'json'
})).then(result => {
renderCloset(result.items, result.category);
$('#closet-paginator').jqPaginator({
totalPages: result.total_pages,
visiblePages: 5,
currentPage: 1,
first: '<li><a style="cursor: pointer;">«</a></li>',
prev: '<li><a style="cursor: pointer;"></a></li>',
next: '<li><a style="cursor: pointer;"></a></li>',
last: '<li><a style="cursor: pointer;">»</a></li>',
page: '<li><a style="cursor: pointer;">{{page}}</a></li>',
wrapper: '<ul class="pagination pagination-sm no-margin"></ul>',
onPageChange: page => {
reloadCloset(
$('#skin-category').hasClass('active') ? 'skin' : 'cape',
page,
$('input[name=q]').val()
);
}
});
}).catch(error => showAjaxError);
$('input[name=q]').on('input', debounce(() => {
const category = $('#skin-category').hasClass('active') ? 'skin' : 'cape';
reloadCloset(
category,
1,
$('input[name=q]').val()
);
}, 350));
}
});
function setTexture() {
@ -189,7 +305,7 @@ function setTexture() {
if (!pid) {
toastr.info(trans('user.emptySelectedPlayer'));
} else if (selected.length == 0) {
} else if (selectedTextures['skin'] == undefined && selectedTextures['cape'] == undefined) {
toastr.info(trans('user.emptySelectedTexture'));
} else {
$.ajax({
@ -198,8 +314,8 @@ function setTexture() {
dataType: "json",
data: {
'pid': pid,
'tid[skin]': selected['skin'],
'tid[cape]': selected['cape']
'tid[skin]': selectedTextures['skin'],
'tid[cape]': selectedTextures['cape']
},
success: function(json) {
if (json.errno == 0) {
@ -238,7 +354,7 @@ $('body').on('change', '#preference', function() {
function changePlayerName(pid, current_player_name) {
swal({
title: trans('user.changePlayerName'),
text: trans('user.playerNameRule'),
text: $('#player_name').attr('placeholder'),
inputValue: current_player_name,
input: 'text',
showCancelButton: true,
@ -277,32 +393,49 @@ function changePlayerName(pid, current_player_name) {
}
function clearTexture(pid) {
swal({
text: trans('user.clearTexture'),
type: 'warning',
showCancelButton: true
}).then(function() {
$.ajax({
type: "POST",
url: "./player/texture/clear",
dataType: "json",
data: { 'pid' : pid },
success: function(json) {
if (json.errno == 0) {
swal({
type: 'success',
html: json.msg
});
} else {
swal({
type: 'error',
html: json.msg
});
}
},
error: showAjaxError
});
let dom = `
<div class="form-group">
<input type="checkbox" id="clear-steve"> Default (Steve)
</div>
<div class="form-group">
<input type="checkbox" id="clear-alex"> Slim (Alex)
</div>
<div class="form-group">
<input type="checkbox" id="clear-cape"> ${trans('general.cape')}
</div>
<script>
$('input[type=checkbox]').iCheck({ checkboxClass: 'icheckbox_square-blue' });
</script>
`;
showModal(dom, trans('user.chooseClearTexture'), 'default', { callback: `ajaxClearTexture(${pid})` });
return;
}
function ajaxClearTexture(pid) {
$('.modal').each(function () {
if ($(this).css('display') == "none")
$(this).remove();
});
let data = { pid: pid };
['steve', 'alex', 'cape'].forEach(type => {
data[type] = $(`#clear-${type}`).prop('checked') ? 1 : 0;
});
if (data['steve'] == 0 && data['alex'] == 0 && data['cape'] == 0) {
toastr.warning(trans('user.noClearChoice'));
return;
}
Promise.resolve($.ajax({
type: 'POST',
url: './player/texture/clear',
dataType: 'json',
data: data
})).then(json => {
swal({ type: json.errno == 0 ? 'success' : 'error', html: json.msg });
$('.modal').modal('hide');
}).catch(error => showAjaxError);
}
function deletePlayer(pid) {
@ -405,49 +538,46 @@ function changeNickName() {
}
function changePassword() {
let domOldPwd = $('#password');
let domNewPwd = $('#new-passwd');
let domConfirmPwd = $('#confirm-pwd');
var password = $('#password').val();
var new_passwd = $('#new-passwd').val();
let password = domOldPwd.val();
let new_passwd = domNewPwd.val();
if (password == "") {
toastr.info(trans('user.emptyPassword'));
$('#passwd').focus();
domOldPwd.focus();
} else if (new_passwd == "") {
toastr.info(trans('user.emptyNewPassword'));
$('#new-passwd').focus();
} else if ($('#confirm-pwd').val() == "") {
domNewPwd.focus();
} else if (domConfirmPwd.val() == "") {
toastr.info(trans('auth.emptyConfirmPwd'));
$('#confirm-pwd').focus();
} else if (new_passwd != $('#confirm-pwd').val()) {
domConfirmPwd.focus();
} else if (new_passwd != domConfirmPwd.val()) {
toastr.warning(trans('auth.invalidConfirmPwd'));
$('#confirm-pwd').focus();
domConfirmPwd.focus();
} else {
$.ajax({
Promise.resolve($.ajax({
type: "POST",
url: "./profile?action=password",
dataType: "json",
data: { 'current_password': password, 'new_password': new_passwd},
success: function(json) {
if (json.errno == 0) {
swal({
type: 'success',
html: json.msg
}).then(function() {
logout(true, function() {
window.location = "../auth/login";
});
});
} else {
swal({
type: 'warning',
html: json.msg
});
}
},
error: showAjaxError
});
data: { 'current_password': password, 'new_password': new_passwd }
})).then(result => {
if (result.errno == 0) {
return swal({ type: 'success', text: result.msg })
.then(() => {
return logout();
}).then(result => {
if (result.errno == 0) {
window.location = url('auth/login');
}
}).catch(error => showAjaxError);
} else {
return swal({ type: 'warning', text: result.msg });
}
}).catch(error => showAjaxError);
}
return false;
}
$('#new-email').focusin(function() {
@ -481,32 +611,27 @@ function changeEmail() {
text: trans('user.changeEmail', { new_email: new_email }),
type: 'question',
showCancelButton: true
}).then(function() {
$.ajax({
type: "POST",
url: "./profile?action=email",
dataType: "json",
data: { 'new_email' : new_email, 'password' : $('#current-password').val() },
success: function(json) {
if (json.errno == 0) {
swal({
type: 'success',
html: json.msg
}).then(function() {
logout(true, function() {
window.location = "../auth/login";
});
});
} else {
swal({
type: 'warning',
html: json.msg
});
}
},
error: showAjaxError
});
});
}).then(() => {
return Promise.resolve($.ajax({
type: 'POST',
url: './profile?action=email',
dataType: 'json',
data: { 'new_email': new_email, 'password': $('#current-password').val() }
}));
}).then(result => {
if (result.errno == 0) {
return swal({ type: 'success', text: result.msg })
.then(() => {
return logout();
}).then(result => {
if (result.errno == 0) {
window.location = url('auth/login');
}
}).catch(error => showAjaxError);
} else {
return swal({ type: 'warning', text: result.msg });
}
}).catch(error => showAjaxError);
}
function deleteAccount() {

View File

@ -6,19 +6,20 @@ index:
overview: Overview
users:
players-count:
title: Players Count
status:
title: Status
normal: Normal
banned: Banned
admin: Admin
super-admin: Super Admin
score:
tip: Press enter to submit new score
operations:
title: Operations
non-existent: No such user.
email:
change: Edit Email
existed: :email is existed.
success: Email changed successfully.
nickname:
change: Edit Nickname
@ -61,6 +62,8 @@ players:
change: Change Textures
non-existent: No such texture tid.:tid
success: The textures of :player has been updated.
name:
success: Player name has been updated to :player
owner:
change: Change Owner
success: The player :player was transferred to user :user.
@ -100,12 +103,6 @@ plugins:
operations:
title: Operations
disable: Disable
enable: Enable
configure: Configure
no-config-notice: The plugin has been disabled or no configuration is provided.
delete: Delete
enabled: :plugin has been enabled.
disabled: :plugin has been disabled.
deleted: The plugin was deleted successfully.

View File

@ -62,12 +62,17 @@
setAsPublic: 'Set as Public',
setPublicNotice: 'Sure to set this as public texture?',
deleteNotice: 'Are you sure to delete this texture? Scores will be returned.'
deleteNotice: 'Are you sure to delete this texture?'
},
user: {
signInRemainingTime: 'Available after :time hours',
// Closet
emptyClosetMsg: '<p>Nothing in your closet...</p><p>Why not explore the <a href=":url">Skin Library</a> for a while?</p>',
renameItem: 'Rename item',
removeItem: 'Remove from closet',
setAsAvatar: 'Set as avatar',
viewInSkinlib: 'View in skin library',
switch2dPreview: 'Switch to 2D Preview',
switch3dPreview: 'Switch to 3D Preview',
removeFromClosetNotice: 'Sure to remove this texture from your closet?',
@ -77,11 +82,12 @@
// Player
changePlayerName: 'Please enter the player name:',
playerNameRule: 'The player name should only contain letters, numbers, and dashes.',
emptyPlayerName: 'Empty player name.',
clearTexture: 'Sure to clear the skins & cape of this player?',
deletePlayer: 'Sure to delete this player?',
deletePlayerNotice: 'It\'s permanent. No backups.',
chooseClearTexture: 'Choose texture types you want to clear',
noClearChoice: 'You haven\'t choose any types',
// Profile
setAvatar: 'Sure to set this as your avatar?',
@ -95,38 +101,59 @@
emptyDeletePassword: 'Please enter the current password:'
},
admin: {
// Change User Profile
newUserEmail: 'Please enter the new email:',
newUserNickname: 'Please enter the new nickname:',
newUserPassword: 'Please enter the new password:',
deleteUserNotice: 'Are you sure to delete this user? It\' permanent.',
changePlayerOwner: 'Please enter the id of user which this player should be transferred to:',
deletePlayerNotice: 'Are you sure to delete this player? It\' permanent.',
operationsTitle: 'Operations',
// Status
banned: 'Banned',
normal: 'Normal',
admin: 'Admin',
// Operations
// Users
ban: 'Ban',
unban: 'Unban',
setAdmin: 'Set as admin',
unsetAdmin: 'Remove admin',
deleteUser: 'Delete User',
cannotDeleteAdmin: 'You can\'t delete admins.',
cannotDeleteSuperAdmin: 'You can\'t delete super admin in this way',
changeEmail: 'Edit Email',
changeNickName: 'Edit Nickname',
changePassword: 'Edit Password',
newUserEmail: 'Please enter the new email:',
newUserNickname: 'Please enter the new nickname:',
newUserPassword: 'Please enter the new password:',
deleteUserNotice: 'Are you sure to delete this user? It\' permanent.',
scoreTip: 'Press ENTER to submit new score',
doubleClickToSeeUser: 'Double click to see info of this user',
doubleClickToSeePlayers: 'Double click to see his/her players',
// Change Player Texture
// Status
banned: 'Banned',
normal: 'Normal',
admin: 'Admin',
superAdmin: 'Super Admin',
// Players
textureType: 'Texture Type',
skin: 'Skin (:model Model)',
cape: 'Cape',
pid: 'Texture ID',
pidNotice: 'Please enter the tid of texture',
pidNotice: 'Please enter the tid of texture. Inputting 0 can clear texture of this player.',
changePlayerTexture: 'Change textures of :player',
changeTexture: 'Change Textures',
changePlayerName: 'Change Player Name',
changeOwner: 'Change Owner',
deletePlayer: 'Delete',
changePlayerOwner: 'Please enter the id of user which this player should be transferred to:',
deletePlayerNotice: 'Are you sure to delete this player? It\' permanent.',
targetUser: 'Target user is :nickname',
noSuchUser: 'No such user',
changePlayerNameNotice: 'Please input new player name:',
emptyPlayerName: 'Player name cannot be empty.',
// Index
textureUploads: 'Texture Uploads',
userRegistration: 'User Registration',
// Plugins
configurePlugin: 'Configure',
noPluginConfigNotice: 'The plugin has been disabled or no configuration is provided.',
deletePlugin: 'Delete',
statusEnabled: 'Enabled',
statusDisabled: 'Disabled',
enablePlugin: 'Enable',
@ -139,10 +166,14 @@
extracting: 'Extracting update package..'
},
general: {
skin: 'Skin',
cape: 'Cape',
fatalError: 'Fatal Error (Please contact the author)',
confirmLogout: 'Sure to log out?',
confirm: 'OK',
cancel: 'Cancel'
cancel: 'Cancel',
more: 'More',
noResult: 'No result.'
}
};
})(window.jQuery);

View File

@ -16,10 +16,11 @@ score-intro:
title: What is score?
introduction: |
We use score system to prevent the behaviors like uplaoding huge amount of textures and registering players casually.
Both adding players and uplaoding textures will consume your score. The score will be returned if you deleted them.
Adding textures from skin library to your closet will not decline your score.
Both adding players and uplaoding textures will consume your score. :return-score
The inital score of user on this site is :initial_score, you can acquire :score-from ~ :score-to scores by signing in.
will-return-score: The score will be returned if you deleted them.
no-return-score: But the score will NOT be returned if you deleted them.
rates:
storage: :score scores = 1 KB storage
player: :score scores = 1 player
@ -27,13 +28,11 @@ score-intro:
closet:
upload: Upload Texture
search: Search Texture
type-to-search: Type to search
switch-category: Switch Category
view: View in skin library
more: More
set-avatar: Set as avatar
empty-msg: |
<p>Nothing in your closet...</p>
<p>Why not explore the <a href=":url">Skin Library</a> for a while?</p>
use-as:
button: Apply...
@ -128,6 +127,7 @@ profile:
password: Current Password
button: Change Email
wrong-password: Wrong password.
existed: This email address is used.
success: Email address updated successfully, please log in again.
delete:

View File

@ -6,19 +6,20 @@ index:
overview: 概览
users:
players-count:
title: 拥有角色数
status:
title: 状态
normal: 普通用户
banned: 封禁
admin: 管理员
super-admin: 超级管理员
score:
tip: 输入修改后的积分,回车提交
operations:
title: 更多操作
non-existent: 用户不存在
email:
change: 修改邮箱
existed: :email 已被占用
success: 邮箱修改成功
nickname:
change: 修改昵称
@ -61,6 +62,8 @@ players:
change: 更换材质
non-existent: 材质 tid.:tid 不存在
success: 角色 :player 的材质修改成功
name:
success: 角色名成功更改为 :player
owner:
change: 更换角色拥有者
success: 角色 :player 已成功让渡至 :user
@ -100,12 +103,6 @@ plugins:
operations:
title: 操作
disable: 禁用插件
enable: 启用插件
configure: 插件配置
no-config-notice: 插件已被禁用或无配置页
delete: 删除插件
enabled: :plugin 已启用
disabled: :plugin 已禁用
deleted: 插件已被成功删除

View File

@ -62,12 +62,17 @@
setAsPublic: '设为公开',
setPublicNotice: '要将此材质设置为公开吗?',
deleteNotice: '真的要删除此材质吗?积分将会被返还'
deleteNotice: '真的要删除此材质吗?'
},
user: {
signInRemainingTime: ':time 小时后可签到',
// Closet
emptyClosetMsg: '<p>衣柜里啥都没有哦~</p><p>去<a href=":url">皮肤库</a>看看吧~</p>',
renameItem: '重命名物品',
removeItem: '从衣柜中移除',
setAsAvatar: '设为头像',
viewInSkinlib: '在皮肤库中查看',
switch2dPreview: '切换 2D 预览',
switch3dPreview: '切换 3D 预览',
removeFromClosetNotice: '确定要从衣柜中移除此材质吗?',
@ -77,11 +82,12 @@
// Player
changePlayerName: '请输入角色名:',
playerNameRule: '允许数字、字母以及下划线,是否支持中文角色名请参考本站设置',
emptyPlayerName: '你还没有填写名称哦',
clearTexture: '确定要重置该用户的皮肤/披风吗?',
deletePlayer: '真的要删除该玩家吗?',
deletePlayerNotice: '这将是永久性的删除',
chooseClearTexture: '选择要删除的材质类型',
noClearChoice: '您还没选择要删除的材质类型',
// Profile
setAvatar: '确定要将此材质设置为用户头像吗?',
@ -95,38 +101,59 @@
emptyDeletePassword: '请先输入当前用户密码'
},
admin: {
// Change User Profile
newUserEmail: '请输入新邮箱:',
newUserNickname: '请输入新昵称:',
newUserPassword: '请输入新密码:',
deleteUserNotice: '真的要删除此用户吗?此操作不可恢复',
changePlayerOwner: '请输入此角色要让渡至的用户 UID',
deletePlayerNotice: '真的要删除此角色吗?此操作不可恢复',
operationsTitle: '更多操作',
// Status
banned: '封禁',
normal: '正常',
admin: '管理员',
// Operations
// Users
ban: '封禁',
unban: '解封',
setAdmin: '设为管理员',
unsetAdmin: '解除管理员',
deleteUser: '删除用户',
cannotDeleteAdmin: '你不能删除管理员账号哦',
cannotDeleteSuperAdmin: '超级管理员账号不能被这样删除的啦',
changeEmail: '修改邮箱',
changeNickName: '修改昵称',
changePassword: '更改密码',
newUserEmail: '请输入新邮箱:',
newUserNickname: '请输入新昵称:',
newUserPassword: '请输入新密码:',
deleteUserNotice: '真的要删除此用户吗?此操作不可恢复',
scoreTip: '输入修改后的积分,回车提交',
doubleClickToSeeUser: '双击可查看该用户的信息',
doubleClickToSeePlayers: '双击可查看该用户的角色',
// Change Player Texture
// Status
banned: '封禁',
normal: '普通用户',
admin: '管理员',
superAdmin: '超级管理员',
// Players
textureType: '材质类型',
skin: '皮肤(:model 模型)',
cape: '披风',
pid: '材质 ID',
pidNotice: '输入要更换的材质的 TID',
pidNotice: '输入要更换的材质的 TID,输入 0 即可清除该角色的材质',
changePlayerTexture: '更换角色 :player 的材质',
changeTexture: '更换材质',
changePlayerName: '更改角色名',
changeOwner: '更换角色拥有者',
deletePlayer: '删除角色',
changePlayerOwner: '请输入此角色要让渡至的用户 UID',
deletePlayerNotice: '真的要删除此角色吗?此操作不可恢复',
targetUser: '目标用户::nickname',
noSuchUser: '没有这个用户哦~',
changePlayerNameNotice: '请输入新的角色名:',
emptyPlayerName: '您还没填写角色名呢',
// Index
textureUploads: '材质上传',
userRegistration: '用户注册',
// Plugins
configurePlugin: '插件配置',
noPluginConfigNotice: '插件已被禁用或无配置页',
deletePlugin: '删除插件',
statusEnabled: '已启用',
statusDisabled: '已禁用',
enablePlugin: '启用插件',
@ -139,10 +166,14 @@
extracting: '正在解压更新包'
},
general: {
skin: '皮肤',
cape: '披风',
fatalError: '严重错误(请联系作者)',
confirmLogout: '确定要登出吗?',
confirm: '确定',
cancel: '取消'
cancel: '取消',
more: '更多',
noResult: '无结果'
},
vendor: {
datatables: {

View File

@ -22,10 +22,12 @@ score-intro:
「贯彻爱与真实的。。呸!」上面只是卖下萌~
为了不出现用户一个劲上传材质导致存储空间爆满,我们决定启用积分系统。
添加角色以及上传材质都会消耗积分,而删除已经添加的角色和已上传的材质时积分将会被返还
添加角色以及上传材质都会消耗积分,:return-score
本站用户初始积分为 :initial_score每日签到可以随机获得 :score-from ~ :score-to 积分
添加皮肤库里的材质到衣柜不消耗积分。
will-return-score: 而删除已经添加的角色和已上传的材质时积分将会被返还
no-return-score: 但删除已经添加的角色和已上传的材质时积分不会被返还
rates:
storage: :score 积分 = 1 KB 存储空间
player: :score 积分 = 1 个角色
@ -33,13 +35,11 @@ score-intro:
closet:
upload: 上传材质
search: 搜索材质
type-to-search: 输入即搜索
switch-category: 切换分类
view: 在皮肤库中查看
more: 更多
set-avatar: 设为头像
empty-msg: |
<p>衣柜里啥都没有哦~</p>
<p>去<a href=":url">皮肤库</a>看看吧~</p>
use-as:
button: 使用...
@ -134,6 +134,7 @@ profile:
password: 当前密码
button: 修改邮箱
wrong-password: 密码错误
existed: 这个邮箱已经被别人占用啦
success: 邮箱修改成功,请重新登录
delete:

View File

@ -43,26 +43,5 @@
$(document).ready(function() {
$('.box-body').css('min-height', $('.content-wrapper').height() - $('.content-header').outerHeight() - 120);
});
$('#player-table').DataTable({
language: trans('vendor.datatables'),
scrollX: true,
autoWidth: false,
processing: true,
serverSide: true,
ajax: '{{ url("admin/player-data") }}',
createdRow: function (row, data, index) {
$('td', row).eq(2).attr('id', 'player-name');
},
columns: [
{data: 'pid', 'width': '1%'},
{data: 'uid'},
{data: 'player_name'},
{data: 'preference'},
{data: 'previews', searchable: false, orderable: false},
{data: 'last_modified'},
{data: 'operations', searchable: false, orderable: false}
]
});
</script>
@endsection

View File

@ -47,32 +47,3 @@
</div><!-- /.content-wrapper -->
@endsection
@section('script')
<script type="text/javascript">
var table = $('#plugin-table').DataTable({
language: trans('vendor.datatables'),
scrollX: true,
pageLength: 25,
autoWidth: false,
processing: true,
serverSide: true,
ajax: '{{ url("admin/plugins/data") }}',
createdRow: function (row, data, index) {
$('td', row).eq(1).attr('id', 'description');
$('td', row).eq(2).attr('id', 'author');
$('td', row).eq(3).attr('id', 'version');
$('td', row).eq(4).attr('id', 'status');
},
columns: [
{data: 'title'},
{data: 'description', 'width': '35%'},
{data: 'author'},
{data: 'version'},
{data: 'status'},
{data: 'operations', searchable: false, orderable: false}
]
});
</script>
@endsection

View File

@ -24,6 +24,7 @@
<th>{{ trans('general.user.email') }}</th>
<th>{{ trans('general.user.nickname') }}</th>
<th>{{ trans('general.user.score') }}</th>
<th>{{ trans('admin.users.players-count.title') }}</th>
<th>{{ trans('admin.users.status.title') }}</th>
<th>{{ trans('general.user.register-at') }}</th>
<th>{{ trans('general.operations') }}</th>
@ -42,28 +43,5 @@
$(document).ready(function() {
$('.box-body').css('min-height', $('.content-wrapper').height() - $('.content-header').outerHeight() - 120);
});
$('#user-table').DataTable({
language: trans('vendor.datatables'),
scrollX: true,
autoWidth: false,
processing: true,
serverSide: true,
ajax: '{{ url("admin/user-data") }}',
createdRow: function (row, data, index) {
$('td', row).eq(1).attr('id', 'email');
$('td', row).eq(2).attr('id', 'nickname');
$('td', row).eq(4).attr('id', 'permission');
},
columns: [
{data: 'uid', 'width': '1%'},
{data: 'email'},
{data: 'nickname'},
{data: 'score'},
{data: 'permission'},
{data: 'register_at'},
{data: 'operations', searchable: false, orderable: false}
]
});
</script>
@endsection

View File

@ -39,17 +39,17 @@
<i class="fa fa-filter" aria-hidden="true"></i> {{ trans('skinlib.general.filter') }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=skin&sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.any-model') }}</small></a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=steve&sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.steve-model') }}</small></a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=alex&sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.alex-model') }}</small></a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=skin&{{ isset($_GET["uid"]) ? "uid=$uploader&" : "" }}sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.any-model') }}</small></a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=steve&{{ isset($_GET["uid"]) ? "uid=$uploader&" : "" }}sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.steve-model') }}</small></a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=alex&{{ isset($_GET["uid"]) ? "uid=$uploader&" : "" }}sort={{ $sort }}'>{{ trans('general.skin') }} <small>{{ trans('skinlib.filter.alex-model') }}</small></a></li>
<li class="divider"></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=cape&sort={{ $sort }}'>{{ trans('general.cape') }}</a></li>
<li><a href='?{{ isset($_GET["q"]) ? "q=$q&" : "" }}filter=cape&{{ isset($_GET["uid"]) ? "uid=$uploader&" : "" }}sort={{ $sort }}'>{{ trans('general.cape') }}</a></li>
@if (!is_null($user))
<li class="divider"></li>
<li><a href="?filter=user&uid={{ $user->uid }}&sort={{ $sort }}">{{ trans('skinlib.general.my-upload') }}</a></li>
<li><a href="?{{ isset($_GET["filter"]) ? "filter=$filter&" : "" }}uid={{ $user->uid }}&sort={{ $sort }}">{{ trans('skinlib.general.my-upload') }}</a></li>
@endif
<li class="divider"></li>
<li><a href="/skinlib">{{ trans('skinlib.filter.clean-filter') }}</a></li>
<li><a href="{{ url('skinlib') }}">{{ trans('skinlib.filter.clean-filter') }}</a></li>
</ul>
</li>

View File

@ -10,7 +10,6 @@
<section class="content-header">
<h1>
{{ $__env->getSections()['title'] }}
<small>Search Result</small>
</h1>
@include('vendor.breadcrumb')

View File

@ -51,14 +51,20 @@
<td id="name">{{ $texture->name }}
@if (!is_null($user) && ($texture->uploader == $user->uid || $user->isAdmin()))
<small>
<a href="javascript:changeTextureName({{ $texture->tid }});">{{ trans('skinlib.show.edit-name') }}</a>
<a href="javascript:changeTextureName({{ $texture->tid }}, '{{ $texture->name }}');">{{ trans('skinlib.show.edit-name') }}</a>
</small>
@endif
</td>
</tr>
<tr>
<td>{{ trans('skinlib.show.model') }}</td>
<td>{{ $texture->type }}</td>
<td>
@if ($texture->type == 'cape')
{{ trans('general.cape') }}
@else
{{ $texture->type }}
@endif
</td>
</tr>
<tr>
<td>Hash
@ -75,7 +81,7 @@
<tr>
<td>{{ trans('skinlib.show.uploader') }}</td>
@if ($uploader = app('users')->get($texture->uploader))
<td><a href="{{ url('skinlib?filter=user&uid='.$uploader->uid) }}&sort=time">{{ $uploader->getNickName() }}</a></td>
<td><a href="{{ url('skinlib?filter='.($texture->type == 'cape' ? 'cape' : 'skin').'&uid='.$uploader->uid) }}&sort=time">{{ $uploader->getNickName() }}</a></td>
@else
<td><a href="#">{{ trans('general.unexistent-user') }}</a></td>
@endif

View File

@ -26,51 +26,30 @@
<div class="nav-tabs-custom">
<!-- Tabs within a box -->
<ul class="nav nav-tabs">
<li class="active"><a href="#skin-category" data-toggle="tab">{{ trans('general.skin') }}</a></li>
<li><a href="#cape-category" data-toggle="tab">{{ trans('general.cape') }}</a></li>
<li class="active"><a href="#skin-category" class="category-switch" data-toggle="tab">{{ trans('general.skin') }}</a></li>
<li><a href="#cape-category" class="category-switch" data-toggle="tab">{{ trans('general.cape') }}</a></li>
<div style="padding: 7px;">
<li class="pull-right" style="padding: 7px;">
<div class="has-feedback pull-right">
<form method="get" action="" class="user-search-form">
<input type="text" name="q" class="form-control input-sm" placeholder="输入,回车搜索" value="{{ $q }}">
<div class="user-search-form">
<input type="text" name="q" class="form-control input-sm" placeholder="{{ trans('user.closet.type-to-search') }}">
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</form>
</div>
</div>
</div>
</li>
</ul>
<div class="tab-content no-padding">
<div class="tab-pane active box-body" id="skin-category">
@include('vendor.closet-items', ['items' => (array)array_get($items, 'skin')])
</div>
<div class="tab-pane box-body" id="cape-category">
@include('vendor.closet-items', ['items' => (array)array_get($items, 'cape')])
</div>
<div class="tab-pane active box-body" id="skin-category"></div>
<div class="tab-pane box-body" id="cape-category"></div>
</div>
<div class="box-footer">
<ul class="pagination pagination-sm no-margin pull-right">
<?php $base_url = $q ? "?q=$q&" : "?"; ?>
<li><a href="{{ $base_url }}page=1">«</a></li>
@if ($page != 1)
<li><a href="{{ $base_url }}page={{ $page-1 }}">{{ $page - 1 }}</a></li>
@endif
<li><a href="{{ $base_url }}page={{ $page }}" class="active">{{ $page }}</a></li>
@if ($total_pages > $page)
<li><a href="{{ $base_url }}page={{ $page+1 }}">{{ $page+1 }}</a></li>
@endif
<li><a href="{{ $base_url }}page={{ $total_pages }}">»</a></li>
</ul>
<p class="pull-right">{{ trans('general.pagination', ['page' => $page, 'total' => $total_pages]) }}</p>
<div class="pull-right" id="closet-paginator" last-skin-page="1" last-cape-page="1"></div>
</div>
</div><!-- /.nav-tabs-custom -->
</div>
<!-- Left col -->
<!-- Right col -->
<div class="col-md-4">
<div class="box box-default">

View File

@ -110,7 +110,8 @@
{!! nl2br(trans('user.score-intro.introduction', [
'initial_score' => option('user_initial_score'),
'score-from' => $from,
'score-to' => $to
'score-to' => $to,
'return-score' => option('return_score') ? trans('user.score-intro.will-return-score') : trans('user.score-intro.no-return-score')
])) !!}
<hr />

View File

@ -1,11 +0,0 @@
<div class="btn-group">
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ trans('admin.players.operations.title') }} <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="javascript:changeTexture('{{ $pid }}');">{{ trans('admin.players.textures.change') }}</a></li>
<li><a href="javascript:changeOwner('{{ $pid }}');">{{ trans('admin.players.owner.change') }}</a></li>
</ul>
</div>
<a class="btn btn-danger btn-sm" href="javascript:deletePlayer('{{ $pid }}');">{{ trans('admin.players.delete.delete') }}</a>

View File

@ -1,4 +0,0 @@
<select class="form-control" id="preference">
<option {{ ($preference == "default") ? 'selected=selected' : '' }} value="default">Default</option>
<option {{ ($preference == "slim") ? 'selected=selected' : '' }} value="slim">Slim</option>
</select>

View File

@ -1,23 +0,0 @@
@if ($tid_steve == '0')
<img id="{{ $pid }}-steve" width="64" />
@else
<a href="{{ url('skinlib/show/'.$tid_steve) }}">
<img id="{{ $pid }}-steve" width="64" src="{{ url('preview/64/'.$tid_steve) }}.png" />
</a>
@endif
@if ($tid_alex == '0')
<img id="{{ $pid }}-alex" width="64" />
@else
<a href="{{ url('skinlib/show/'.$tid_alex) }}">
<img id="{{ $pid }}-alex" width="64" src="{{ url('preview/64/'.$tid_alex) }}.png" />
</a>
@endif
@if ($tid_cape == '0')
<img id="{{ $pid }}-cape" width="64" />
@else
<a href="{{ url('skinlib/show/'.$tid_cape) }}">
<img id="{{ $pid }}-cape" width="64" src="{{ url('preview/64/'.$tid_cape) }}.png" />
</a>
@endif

View File

@ -1,13 +0,0 @@
@if ($plugin->isEnabled())
<a class="btn btn-warning btn-sm" href="javascript:disablePlugin('{{ $plugin->name }}');">{{ trans('admin.plugins.operations.disable') }}</a>
@else
<a class="btn btn-primary btn-sm" href="javascript:enablePlugin('{{ $plugin->name }}');">{{ trans('admin.plugins.operations.enable') }}</a>
@endif
@if ($plugin->isEnabled() && $plugin->hasConfigView())
<a class="btn btn-default btn-sm" href="{{ url('admin/plugins/config/'.$plugin->name) }}">{{ trans('admin.plugins.operations.configure') }}</a>
@else
<a class="btn btn-default btn-sm" disabled="disabled" title="{{ trans('admin.plugins.operations.no-config-notice') }}" data-toggle="tooltip" data-placement="top">{{ trans('admin.plugins.operations.configure') }}</a>
@endif
<a class="btn btn-danger btn-sm" href="javascript:deletePlugin('{{ $plugin->name }}');">{{ trans('admin.plugins.operations.delete') }}</a>

View File

@ -1,50 +0,0 @@
<?php use App\Models\User; ?>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ trans('admin.users.operations.title') }} <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="javascript:changeUserEmail('{{ $uid }}');">{{ trans('admin.users.operations.email.change') }}</a></li>
<li><a href="javascript:changeUserNickName('{{ $uid }}');">{{ trans('admin.users.operations.nickname.change') }}</a></li>
<li><a href="javascript:changeUserPwd('{{ $uid }}');">{{ trans('admin.users.operations.password.change') }}</a></li>
@unless ($permission == User::SUPER_ADMIN)
<li class="divider"></li>
{{-- If current user is super admin --}}
@if (app('user.current')->getPermission() == User::SUPER_ADMIN)
@if ($permission == User::ADMIN)
<li><a id="admin" href="javascript:changeAdminStatus('{{ $uid }}');">{{ trans('admin.users.operations.admin.unset.text') }}</a></li>
@else
<li><a id="admin" href="javascript:changeAdminStatus('{{ $uid }}');">{{ trans('admin.users.operations.admin.set.text') }}</a></li>
@endif
@endif
<li class="divider"></li>
@if ($permission == User::BANNED)
<li><a id="ban" href="javascript:changeBanStatus('{{ $uid }}');">{{ trans('admin.users.operations.ban.unban.text') }}</a></li>
@else
<li><a id="ban" href="javascript:changeBanStatus('{{ $uid }}');">{{ trans('admin.users.operations.ban.ban.text') }}</a></li>
@endif
@endunless
</ul>
</div>
{{-- If current user is super admin --}}
@if (app('user.current')->getPermission() == User::SUPER_ADMIN)
@if ($permission == "2")
<a class="btn btn-danger btn-sm" disabled="disabled" data-toggle="tooltip" data-placement="bottom" title="{{ trans('admin.users.operations.delete.cant-super-admin') }}">{{ trans('admin.users.operations.delete.delete') }}</a>
@else
<a class="btn btn-danger btn-sm" href="javascript:deleteUserAccount('{{ $uid }}');">{{ trans('admin.users.operations.delete.delete') }}</a>
@endif
@else
@if ($permission == "1" || $permission == "2")
<a class="btn btn-danger btn-sm" disabled="disabled" data-toggle="tooltip" data-placement="bottom" title="{{ trans('admin.users.operations.delete-cant-admin') }}">{{ trans('admin.users.operations.delete.delete') }}</a>
@else
<a class="btn btn-danger btn-sm" href="javascript:deleteUserAccount('{{ $uid }}');">{{ trans('admin.users.operations.delete.delete') }}</a>
@endif
@endif

View File

@ -1 +0,0 @@
<input type="text" class="form-control score" value="{{ $score }}" title="{{ trans('admin.users.score.tip') }}" data-toggle="tooltip" data-placement="right">

View File

@ -5,17 +5,18 @@
{{ trans('skinlib.filter.skin') }}
<small>{{ trans('skinlib.filter.any-model') }}</small>
@elseif ($filter == "steve")
{{ trans('skinlib.filter.any-model') }}
<small>({{ trans('skinlib.filter.steve-model') }})</small>
{{ trans('skinlib.filter.skin') }}
<small>{{ trans('skinlib.filter.steve-model') }}</small>
@elseif ($filter == "alex")
{{ trans('skinlib.filter.skin') }}
<small>{{ trans('skinlib.filter.alex-model') }}</small>
@elseif ($filter == "cape")
{{ trans('skinlib.filter.cape') }}
@elseif ($filter == "user")
{{ trans('skinlib.filter.uploader', ['name' => App::make('users')->get($_GET['uid'])->getNickName()]) }}
@endif
</li>
@unless ($uploader == 0)
<li>{{ trans('skinlib.filter.uploader', ['name' => App::make('users')->get($_GET['uid'])->getNickName()]) }}</li>
@endunless
<li class="active">
@if ($sort == "time")
{{ trans('skinlib.sort.newest-uploaded') }}

View File

@ -1,30 +0,0 @@
@forelse ($items as $item)
<div class="item" tid="{{ $item->tid }}">
<div class="item-body">
<img src="{{ url('preview/'.$item->tid) }}.png">
</div>
<div class="item-footer">
<p class="texture-name">
<span title="{{ $item->name }}">{{ $item->name }} <small>({{ $item->type }})</small></span>
</p>
<a href="{{ url('skinlib/show/'.$item->tid) }}" title="{{ trans('user.closet.view') }}" class="more" data-toggle="tooltip" data-placement="bottom"><i class="fa fa-share"></i></a>
<span title="{{ trans('user.closet.more') }}" class="more" data-toggle="dropdown" aria-haspopup="true" id="more-button"><i class="fa fa-cog"></i></span>
<ul class="dropup dropdown-menu" aria-labelledby="more-button">
<li><a href="javascript:renameClosetItem({{ $item->tid }});">{{ trans('user.closet.rename.title') }}</a></li>
<li><a href="javascript:removeFromCloset({{ $item->tid }});">{{ trans('user.closet.remove.title') }}</a></li>
<li><a href="javascript:setAsAvatar({{ $item->tid }});">{{ trans('user.closet.set-avatar') }}</a></li>
</ul>
</div>
</div>
@empty
<div class="empty-msg">
@if($q)
{{ trans('skinlib.general.no-result') }}
@else
{!! trans('user.closet.empty-msg', ['url' => url('skinlib')]) !!}
@endif
</div>
@endforelse

View File

@ -8,7 +8,11 @@
<ul class="dropdown-menu" role="menu">
@foreach(config('locales') as $code => $langInfo)
@if (!isset($langInfo['alias']))
<li class="locale"><a href="?lang={{ $code }}">{{ $langInfo['name'] }}</a></li>
@if (count($_GET) == 0 || (count($_GET) == 1 && isset($_GET['lang'])))
<li class="locale"><a href="?lang={{ $code }}">{{ $langInfo['name'] }}</a></li>
@else
<li class="locale"><a href="{{ $_SERVER['REQUEST_URI'] }}&lang={{ $code }}">{{ $langInfo['name'] }}</a></li>
@endif
@endif
@endforeach
</ul>