Use server side table
This commit is contained in:
parent
f71a9b3dd8
commit
7e4ae5381b
|
|
@ -238,37 +238,72 @@ class AdminController extends Controller
|
||||||
|
|
||||||
public function getUserData(Request $request)
|
public function getUserData(Request $request)
|
||||||
{
|
{
|
||||||
$users = collect();
|
$isSingleUser = $request->has('uid');
|
||||||
|
|
||||||
if ($request->has('uid')) {
|
if ($isSingleUser) {
|
||||||
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at'])
|
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at'])
|
||||||
->where('uid', intval($request->input('uid')));
|
->where('uid', intval($request->input('uid')))
|
||||||
|
->get();
|
||||||
} else {
|
} else {
|
||||||
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at']);
|
$search = $request->input('search', '');
|
||||||
|
$sortField = $request->input('sortField', 'uid');
|
||||||
|
$sortType = $request->input('sortType', 'asc');
|
||||||
|
$page = $request->input('page', 1);
|
||||||
|
$perPage = $request->input('perPage', 10);
|
||||||
|
|
||||||
|
$users = User::select(['uid', 'email', 'nickname', 'score', 'permission', 'register_at'])
|
||||||
|
->where('uid', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('email', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('nickname', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('score', 'like', '%' . $search . '%')
|
||||||
|
->orderBy($sortField, $sortType)
|
||||||
|
->offset(($page - 1) * $perPage)
|
||||||
|
->limit($perPage)
|
||||||
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Datatables::of($users)->editColumn('email', function ($user) {
|
$users->transform(function ($user) {
|
||||||
return $user->email ?: 'EMPTY';
|
$user->operations = auth()->user()->permission;
|
||||||
})
|
$user->players_count = $user->players->count();
|
||||||
->setRowId('uid')
|
return $user;
|
||||||
->addColumn('operations', Auth::user()->permission)
|
});
|
||||||
->addColumn('players_count', function ($user) {
|
|
||||||
return $user->players->count();
|
return [
|
||||||
})
|
'totalRecords' => $isSingleUser ? 1 : User::count(),
|
||||||
->make(true);
|
'data' => $users
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPlayerData(Request $request)
|
public function getPlayerData(Request $request)
|
||||||
{
|
{
|
||||||
$players = collect();
|
$isSpecifiedUser = $request->has('uid');
|
||||||
if ($request->has('uid')) {
|
|
||||||
|
if ($isSpecifiedUser) {
|
||||||
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified'])
|
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified'])
|
||||||
->where('uid', intval($request->input('uid')));
|
->where('uid', intval($request->input('uid')))
|
||||||
|
->get();
|
||||||
} else {
|
} else {
|
||||||
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified']);
|
$search = $request->input('search', '');
|
||||||
|
$sortField = $request->input('sortField', 'pid');
|
||||||
|
$sortType = $request->input('sortType', 'asc');
|
||||||
|
$page = $request->input('page', 1);
|
||||||
|
$perPage = $request->input('perPage', 10);
|
||||||
|
|
||||||
|
$players = Player::select(['pid', 'uid', 'player_name', 'preference', 'tid_steve', 'tid_alex', 'tid_cape', 'last_modified'])
|
||||||
|
->where('pid', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('uid', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('player_name', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('preference', 'like', '%' . $search . '%')
|
||||||
|
->orderBy($sortField, $sortType)
|
||||||
|
->offset(($page - 1) * $perPage)
|
||||||
|
->limit($perPage)
|
||||||
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Datatables::of($players)->setRowId('pid')->make(true);
|
return [
|
||||||
|
'totalRecords' => $isSpecifiedUser ? 1 : Player::count(),
|
||||||
|
'data' => $players
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="content">
|
<section class="content">
|
||||||
<vue-good-table
|
<vue-good-table
|
||||||
|
mode="remote"
|
||||||
:rows="players"
|
:rows="players"
|
||||||
|
:totalRows="totalRecords || players.length"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:search-options="tableOptions.search"
|
:search-options="tableOptions.search"
|
||||||
:pagination-options="tableOptions.pagination"
|
:pagination-options="tableOptions.pagination"
|
||||||
|
@on-page-change="onPageChange"
|
||||||
|
@on-sort-change="onSortChange"
|
||||||
|
@on-search="onSearch"
|
||||||
|
@on-per-page-change="onPerPageChange"
|
||||||
styleClass="vgt-table striped"
|
styleClass="vgt-table striped"
|
||||||
>
|
>
|
||||||
<template slot="table-row" slot-scope="props">
|
<template slot="table-row" slot-scope="props">
|
||||||
|
|
@ -94,6 +100,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
players: [],
|
players: [],
|
||||||
|
totalRecords: 0,
|
||||||
columns: [
|
columns: [
|
||||||
{ field: 'pid', label: 'PID', type: 'number' },
|
{ field: 'pid', label: 'PID', type: 'number' },
|
||||||
{ field: 'player_name', label: this.$t('general.player.player-name') },
|
{ field: 'player_name', label: this.$t('general.player.player-name') },
|
||||||
|
|
@ -103,6 +110,13 @@ export default {
|
||||||
{ field: 'last_modified', label: this.$t('general.player.last-modified') },
|
{ field: 'last_modified', label: this.$t('general.player.last-modified') },
|
||||||
{ field: 'operations', label: this.$t('admin.operationsTitle'), globalSearchDisabled: true, sortable: false },
|
{ field: 'operations', label: this.$t('admin.operationsTitle'), globalSearchDisabled: true, sortable: false },
|
||||||
],
|
],
|
||||||
|
serverParams: {
|
||||||
|
sortField: 'pid',
|
||||||
|
sortType: 'asc',
|
||||||
|
page: 1,
|
||||||
|
perPage: 10,
|
||||||
|
search: '',
|
||||||
|
},
|
||||||
tableOptions: {
|
tableOptions: {
|
||||||
search: {
|
search: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -124,7 +138,29 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
this.players = (await this.$http.get(`/admin/player-data${location.search}`)).data;
|
const { data, totalRecords } = await this.$http.get(
|
||||||
|
`/admin/player-data${location.search}`,
|
||||||
|
!location.search && this.serverParams
|
||||||
|
);
|
||||||
|
this.totalRecords = totalRecords;
|
||||||
|
this.players = data;
|
||||||
|
},
|
||||||
|
onPageChange(params) {
|
||||||
|
this.serverParams.page = params.currentPage;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onPerPageChange(params) {
|
||||||
|
this.serverParams.perPage = params.currentPerPage;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onSortChange(params) {
|
||||||
|
this.serverParams.sortType = params.sortType;
|
||||||
|
this.serverParams.sortField = this.columns[params.columnIndex].field;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onSearch(params) {
|
||||||
|
this.serverParams.search = params.searchTerm;
|
||||||
|
this.fetchData();
|
||||||
},
|
},
|
||||||
async changeTexture(player, model) {
|
async changeTexture(player, model) {
|
||||||
const { dismiss, value } = await swal({
|
const { dismiss, value } = await swal({
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="content">
|
<section class="content">
|
||||||
<vue-good-table
|
<vue-good-table
|
||||||
|
mode="remote"
|
||||||
:rows="users"
|
:rows="users"
|
||||||
|
:totalRows="totalRecords || users.length"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:search-options="tableOptions.search"
|
:search-options="tableOptions.search"
|
||||||
:pagination-options="tableOptions.pagination"
|
:pagination-options="tableOptions.pagination"
|
||||||
|
@on-page-change="onPageChange"
|
||||||
|
@on-sort-change="onSortChange"
|
||||||
|
@on-search="onSearch"
|
||||||
|
@on-per-page-change="onPerPageChange"
|
||||||
styleClass="vgt-table striped"
|
styleClass="vgt-table striped"
|
||||||
>
|
>
|
||||||
<template slot="table-row" slot-scope="props">
|
<template slot="table-row" slot-scope="props">
|
||||||
|
|
@ -96,6 +102,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
users: [],
|
users: [],
|
||||||
|
totalRecords: 0,
|
||||||
columns: [
|
columns: [
|
||||||
{ field: 'uid', label: 'UID', type: 'number' },
|
{ field: 'uid', label: 'UID', type: 'number' },
|
||||||
{ field: 'email', label: this.$t('general.user.email') },
|
{ field: 'email', label: this.$t('general.user.email') },
|
||||||
|
|
@ -106,6 +113,13 @@ export default {
|
||||||
{ field: 'register_at', label: this.$t('general.user.register-at') },
|
{ field: 'register_at', label: this.$t('general.user.register-at') },
|
||||||
{ field: 'operations', label: this.$t('admin.operationsTitle'), sortable: false, globalSearchDisabled: true }
|
{ field: 'operations', label: this.$t('admin.operationsTitle'), sortable: false, globalSearchDisabled: true }
|
||||||
],
|
],
|
||||||
|
serverParams: {
|
||||||
|
sortField: 'uid',
|
||||||
|
sortType: 'asc',
|
||||||
|
page: 1,
|
||||||
|
perPage: 10,
|
||||||
|
search: '',
|
||||||
|
},
|
||||||
tableOptions: {
|
tableOptions: {
|
||||||
search: {
|
search: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -127,9 +141,30 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
const { data } = await this.$http.get(`/admin/user-data${location.search}`);
|
const { data, totalRecords } = await this.$http.get(
|
||||||
|
`/admin/user-data${location.search}`,
|
||||||
|
!location.search && this.serverParams
|
||||||
|
);
|
||||||
|
this.totalRecords = totalRecords;
|
||||||
this.users = data;
|
this.users = data;
|
||||||
},
|
},
|
||||||
|
onPageChange(params) {
|
||||||
|
this.serverParams.page = params.currentPage;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onPerPageChange(params) {
|
||||||
|
this.serverParams.perPage = params.currentPerPage;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onSortChange(params) {
|
||||||
|
this.serverParams.sortType = params.sortType;
|
||||||
|
this.serverParams.sortField = this.columns[params.columnIndex].field;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
|
onSearch(params) {
|
||||||
|
this.serverParams.search = params.searchTerm;
|
||||||
|
this.fetchData();
|
||||||
|
},
|
||||||
async changeEmail(user) {
|
async changeEmail(user) {
|
||||||
const { dismiss, value } = await swal({
|
const { dismiss, value } = await swal({
|
||||||
text: this.$t('admin.newUserEmail'),
|
text: this.$t('admin.newUserEmail'),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,41 @@ jest.mock('@/js/notify');
|
||||||
test('fetch data after initializing', () => {
|
test('fetch data after initializing', () => {
|
||||||
Vue.prototype.$http.get.mockResolvedValue({ data: [] });
|
Vue.prototype.$http.get.mockResolvedValue({ data: [] });
|
||||||
mount(Players);
|
mount(Players);
|
||||||
expect(Vue.prototype.$http.get).toBeCalledWith('/admin/player-data');
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/player-data',
|
||||||
|
{ page: 1, perPage: 10, search: '', sortField: 'pid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update tables', async () => {
|
||||||
|
Vue.prototype.$http.get.mockResolvedValue({
|
||||||
|
data: Array.from({ length: 20 }).map((item, pid) => ({ pid }))
|
||||||
|
});
|
||||||
|
const wrapper = mount(Players);
|
||||||
|
|
||||||
|
wrapper.find('.vgt-input').setValue('abc');
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/player-data',
|
||||||
|
{ page: 1, perPage: 10, search: 'abc', sortField: 'pid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onPageChange({ currentPage: 2 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/player-data',
|
||||||
|
{ page: 2, perPage: 10, search: 'abc', sortField: 'pid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onPerPageChange({ currentPerPage: 5 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/player-data',
|
||||||
|
{ page: 2, perPage: 5, search: 'abc', sortField: 'pid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onSortChange({ sortType: 'desc', columnIndex: 0 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/player-data',
|
||||||
|
{ page: 2, perPage: 5, search: 'abc', sortField: 'pid', sortType: 'desc' }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('change texture', async () => {
|
test('change texture', async () => {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,41 @@ jest.mock('@/js/i18n', () => ({
|
||||||
test('fetch data after initializing', () => {
|
test('fetch data after initializing', () => {
|
||||||
Vue.prototype.$http.get.mockResolvedValue({ data: [] });
|
Vue.prototype.$http.get.mockResolvedValue({ data: [] });
|
||||||
mount(Users);
|
mount(Users);
|
||||||
expect(Vue.prototype.$http.get).toBeCalledWith('/admin/user-data');
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/user-data',
|
||||||
|
{ page: 1, perPage: 10, search: '', sortField: 'uid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update tables', () => {
|
||||||
|
Vue.prototype.$http.get.mockResolvedValue({
|
||||||
|
data: Array.from({ length: 20 }).map((item, uid) => ({ uid }))
|
||||||
|
});
|
||||||
|
const wrapper = mount(Users);
|
||||||
|
|
||||||
|
wrapper.find('.vgt-input').setValue('abc');
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/user-data',
|
||||||
|
{ page: 1, perPage: 10, search: 'abc', sortField: 'uid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onPageChange({ currentPage: 2 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/user-data',
|
||||||
|
{ page: 2, perPage: 10, search: 'abc', sortField: 'uid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onPerPageChange({ currentPerPage: 5 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/user-data',
|
||||||
|
{ page: 2, perPage: 5, search: 'abc', sortField: 'uid', sortType: 'asc' }
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.onSortChange({ sortType: 'desc', columnIndex: 0 });
|
||||||
|
expect(Vue.prototype.$http.get).toBeCalledWith(
|
||||||
|
'/admin/user-data',
|
||||||
|
{ page: 2, perPage: 5, search: 'abc', sortField: 'uid', sortType: 'desc' }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('humanize permission', async () => {
|
test('humanize permission', async () => {
|
||||||
|
|
|
||||||
|
|
@ -105,10 +105,10 @@ Route::group(['middleware' => ['auth', 'admin'], 'prefix' => 'admin'], function
|
||||||
Route::any('/options', 'AdminController@options');
|
Route::any('/options', 'AdminController@options');
|
||||||
|
|
||||||
Route::view('/users', 'admin.users');
|
Route::view('/users', 'admin.users');
|
||||||
Route::get ('/user-data', 'AdminController@getUserData');
|
Route::any ('/user-data', 'AdminController@getUserData');
|
||||||
|
|
||||||
Route::view('/players', 'admin.players');
|
Route::view('/players', 'admin.players');
|
||||||
Route::get ('/player-data', 'AdminController@getPlayerData');
|
Route::any ('/player-data', 'AdminController@getPlayerData');
|
||||||
Route::get ('/user/{uid}', 'AdminController@getOneUser');
|
Route::get ('/user/{uid}', 'AdminController@getOneUser');
|
||||||
|
|
||||||
// ajax handlers
|
// ajax handlers
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ class AdminControllerTest extends BrowserKitTestCase
|
||||||
|
|
||||||
public function testGetUserData()
|
public function testGetUserData()
|
||||||
{
|
{
|
||||||
$this->visit('/admin/user-data')
|
$this->getJson('/admin/user-data')
|
||||||
->seeJsonStructure([
|
->seeJsonStructure([
|
||||||
'data' => [[
|
'data' => [[
|
||||||
'uid',
|
'uid',
|
||||||
|
|
@ -168,7 +168,7 @@ class AdminControllerTest extends BrowserKitTestCase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user = factory(User::class)->create();
|
$user = factory(User::class)->create();
|
||||||
$this->visit('/admin/user-data?uid='.$user->uid)
|
$this->getJson('/admin/user-data?uid='.$user->uid)
|
||||||
->seeJsonSubset([
|
->seeJsonSubset([
|
||||||
'data' => [[
|
'data' => [[
|
||||||
'uid' => $user->uid,
|
'uid' => $user->uid,
|
||||||
|
|
@ -191,7 +191,7 @@ class AdminControllerTest extends BrowserKitTestCase
|
||||||
$player = factory(Player::class)->create();
|
$player = factory(Player::class)->create();
|
||||||
$user = $player->user;
|
$user = $player->user;
|
||||||
|
|
||||||
$this->visit('/admin/player-data')
|
$this->getJson('/admin/player-data')
|
||||||
->seeJsonStructure([
|
->seeJsonStructure([
|
||||||
'data' => [[
|
'data' => [[
|
||||||
'pid',
|
'pid',
|
||||||
|
|
@ -205,7 +205,7 @@ class AdminControllerTest extends BrowserKitTestCase
|
||||||
]]
|
]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->visit('/admin/player-data?uid='.$user->uid)
|
$this->getJson('/admin/player-data?uid='.$user->uid)
|
||||||
->seeJsonSubset([
|
->seeJsonSubset([
|
||||||
'data' => [[
|
'data' => [[
|
||||||
'pid' => $player->pid,
|
'pid' => $player->pid,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user