From 001f23e7066f2efcd047f8da2ccea7b32e63fa3b Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Sat, 1 May 2021 22:25:18 +0700 Subject: [PATCH 01/84] New: add skeleton of admin panel --- resources/js/components/App.vue | 13 ++-- resources/js/components/HeaderBlock.vue | 3 +- .../js/components/admin/AdminSidePanel.vue | 61 +++++++++++++++++++ resources/js/pages/admin/Admin.vue | 28 +++++++++ resources/js/pages/admin/AdminChessRules.vue | 13 ++++ .../pages/admin/AdminChessRulesCategories.vue | 13 ++++ resources/js/pages/admin/AdminGames.vue | 13 ++++ resources/js/pages/admin/AdminUsers.vue | 13 ++++ resources/js/router/index.js | 31 ++++++++++ 9 files changed, 181 insertions(+), 7 deletions(-) create mode 100644 resources/js/components/admin/AdminSidePanel.vue create mode 100644 resources/js/pages/admin/Admin.vue create mode 100644 resources/js/pages/admin/AdminChessRules.vue create mode 100644 resources/js/pages/admin/AdminChessRulesCategories.vue create mode 100644 resources/js/pages/admin/AdminGames.vue create mode 100644 resources/js/pages/admin/AdminUsers.vue diff --git a/resources/js/components/App.vue b/resources/js/components/App.vue index c9317db..230f3c3 100644 --- a/resources/js/components/App.vue +++ b/resources/js/components/App.vue @@ -1,10 +1,8 @@ @@ -48,11 +49,12 @@ export default { const currentPage = ref(1); const totalPages = ref(1); const totalItems = ref(0); + const currentPerPage = ref(props.perPage); const items = reactive([]); const newPageAction = async (newPage) => { - const res = await getFromTableRequest(props.table, props.columns, newPage, props.perPage); + const res = await getFromTableRequest(props.table, props.columns, newPage, currentPerPage.value); if (res.status === false) { console.log(`Cannot get items from ${props.table}`); @@ -81,6 +83,18 @@ export default { console.log(`api delete, index: ${index}`); }; + const newPerPageAction = async (newPerPage) => { + if (newPerPage === currentPage.value) { + return; + } + + const itemsPrinted = ((currentPage.value - 1) * currentPerPage.value) + items.length; + const newCurrentPage = Math.floor(itemsPrinted / newPerPage); + currentPage.value = newCurrentPage > 0 ? newCurrentPage : 1; + currentPerPage.value = Number(newPerPage); + await newPageAction(currentPage.value); + }; + onBeforeMount(async () => { await newPageAction(1); }); @@ -89,10 +103,12 @@ export default { currentPage, totalPages, items, + currentPerPage, newPageAction, viewAction, editAction, deleteAction, + newPerPageAction, }; }, diff --git a/resources/js/components/table/BaseTable.vue b/resources/js/components/table/BaseTable.vue index 04f88d1..4bd0e9b 100644 --- a/resources/js/components/table/BaseTable.vue +++ b/resources/js/components/table/BaseTable.vue @@ -41,16 +41,24 @@ - +
+ + + +
+ + diff --git a/resources/js/components/admin/AdminUserInfoCardInGames.vue b/resources/js/components/admin/AdminUserInfoCardInGames.vue new file mode 100644 index 0000000..9f8e898 --- /dev/null +++ b/resources/js/components/admin/AdminUserInfoCardInGames.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/resources/js/components/chess/ChessBoard.vue b/resources/js/components/chess/ChessBoard.vue index 296acd5..ae62f8f 100644 --- a/resources/js/components/chess/ChessBoard.vue +++ b/resources/js/components/chess/ChessBoard.vue @@ -66,6 +66,29 @@ export default { ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'], ]); + const resetBoard = () => { + let i = 0; + let j = 0; + + [ + ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], + ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'], + ['', '', '', '', '', '', '', ''], + ['', '', '', '', '', '', '', ''], + ['', '', '', '', '', '', '', ''], + ['', '', '', '', '', '', '', ''], + ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'], + ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'], + ].forEach((raw) => { + j = 0; + raw.forEach((chessman) => { + board[i][j] = chessman; + j++; + }); + i++; + }); + }; + const fromMove = reactive({ x: -1, y: -1, @@ -163,6 +186,17 @@ export default { for (printFrom; printFrom < moves.length; printFrom++) { move(moves[printFrom].from, moves[printFrom].to, moves[printFrom].type); } + + // if need back move + if (moves.length < printFrom) { + resetBoard(); + + moves.forEach((el) => { + move(el.from, el.to, el.type); + }); + + printFrom--; + } }); /* Listener */ diff --git a/resources/js/components/chess/ChessGameReplay.vue b/resources/js/components/chess/ChessGameReplay.vue new file mode 100644 index 0000000..dfaf605 --- /dev/null +++ b/resources/js/components/chess/ChessGameReplay.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/resources/js/components/table/ApiTable.vue b/resources/js/components/tables/ApiTable.vue similarity index 93% rename from resources/js/components/table/ApiTable.vue rename to resources/js/components/tables/ApiTable.vue index 9da4970..d45cd8d 100644 --- a/resources/js/components/table/ApiTable.vue +++ b/resources/js/components/tables/ApiTable.vue @@ -16,6 +16,7 @@ + + diff --git a/resources/js/router/index.js b/resources/js/router/index.js index 23a7d1f..19ff08c 100644 --- a/resources/js/router/index.js +++ b/resources/js/router/index.js @@ -13,6 +13,7 @@ import AdminChessRulesCategories from '~/pages/admin/AdminChessRulesCategories.v import AdminUsers from '~/pages/admin/AdminUsers.vue'; import AdminGames from '~/pages/admin/AdminGames.vue'; import AdminWebsocket from '~/pages/admin/AdminWebsocket.vue'; +import AdminGamesView from '../pages/admin/view/AdminGamesView'; const routes = [ { @@ -110,6 +111,10 @@ const routes = [ path: 'websockets', component: AdminWebsocket, }, + { + path: 'view/games/:id', + component: AdminGamesView, + }, ], meta: { auth: true, diff --git a/resources/js/store/modules/gameModule.js b/resources/js/store/modules/gameModule.js index fdcda7b..9ad8fdd 100644 --- a/resources/js/store/modules/gameModule.js +++ b/resources/js/store/modules/gameModule.js @@ -83,6 +83,11 @@ export default { state.moves.push(payload); }, + REMOVE_LAST(state) { + state.currentMoveNum--; + state.moves.pop(); + }, + SET_TIME_ENDED(state, payload) { state.timerStarted = false; state.timeEnded = payload; @@ -108,6 +113,13 @@ export default { state.moveErrorMessage = payload; }, + START_REPLAY(state) { + state.pageLoading = false; + state.gameStarted = true; + state.currentMoveNum = 1; + state.timerStarted = true; + }, + UNSET_GAME(state) { state.pageLoading = true; state.gameToken = ''; diff --git a/routes/web.php b/routes/web.php index e02b5fb..482904b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,17 +1,12 @@ prefix('/api/admin')->group(function () { Route::post('/table-pagination', [TablePaginationController::class, 'tablePagination']); + + Route::post('/game/{game}', [AdminGameInfoController::class, 'getInfo']); }); Route::post('/subscribed/{channel}', [SubscribedOnChannelController::class, 'subscribed']) From f3ddb6323d3b3a5fa3f0c93e416c812bcb4f1275 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Fri, 7 May 2021 23:53:50 +0700 Subject: [PATCH 08/84] New: add admin view user page --- ...Controller.php => AdminGameController.php} | 3 +- .../Controllers/Admin/AdminUserController.php | 61 +++++++ .../PaginateUserGamesController.php | 15 ++ .../Controllers/TablePaginationController.php | 7 +- .../Requests/PaginateGamesForUserRequest.php | 30 ++++ app/Http/Requests/TablePaginationRequest.php | 19 ++- app/Models/User.php | 15 +- app/Services/PaginateGamesForUserService.php | 30 ++++ app/Services/TablePaginationService.php | 35 +++- .../2021_05_06_204743_update_users_table.php | 31 ++++ resources/js/api/adminBlockUserRequest.js | 13 ++ resources/js/api/adminUnblockUserRequest.js | 13 ++ resources/js/api/adminUserInfoRequest.js | 13 ++ resources/js/api/getFromTableRequest.js | 13 -- .../js/api/paginatedTableByAdminRequest.js | 19 +++ resources/js/api/paginatedUserGamesRequest.js | 12 ++ .../js/components/lists/UserGamesList.vue | 159 ++++++++++++++++++ resources/js/components/tables/ApiTable.vue | 2 +- .../js/pages/admin/view/AdminUsersView.vue | 129 ++++++++++++++ resources/js/router/index.js | 5 + routes/web.php | 16 +- 21 files changed, 597 insertions(+), 43 deletions(-) rename app/Http/Controllers/Admin/{AdminGameInfoController.php => AdminGameController.php} (94%) create mode 100644 app/Http/Controllers/Admin/AdminUserController.php create mode 100644 app/Http/Controllers/PaginateUserGamesController.php create mode 100644 app/Http/Requests/PaginateGamesForUserRequest.php create mode 100644 app/Services/PaginateGamesForUserService.php create mode 100644 database/migrations/2021_05_06_204743_update_users_table.php create mode 100644 resources/js/api/adminBlockUserRequest.js create mode 100644 resources/js/api/adminUnblockUserRequest.js create mode 100644 resources/js/api/adminUserInfoRequest.js delete mode 100644 resources/js/api/getFromTableRequest.js create mode 100644 resources/js/api/paginatedTableByAdminRequest.js create mode 100644 resources/js/api/paginatedUserGamesRequest.js create mode 100644 resources/js/components/lists/UserGamesList.vue create mode 100644 resources/js/pages/admin/view/AdminUsersView.vue diff --git a/app/Http/Controllers/Admin/AdminGameInfoController.php b/app/Http/Controllers/Admin/AdminGameController.php similarity index 94% rename from app/Http/Controllers/Admin/AdminGameInfoController.php rename to app/Http/Controllers/Admin/AdminGameController.php index c5acb97..666ed71 100644 --- a/app/Http/Controllers/Admin/AdminGameInfoController.php +++ b/app/Http/Controllers/Admin/AdminGameController.php @@ -6,9 +6,8 @@ use App\Models\Game; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Models\User; -class AdminGameInfoController extends Controller +class AdminGameController extends Controller { public function getInfo(Request $request, Game $game): JsonResponse { diff --git a/app/Http/Controllers/Admin/AdminUserController.php b/app/Http/Controllers/Admin/AdminUserController.php new file mode 100644 index 0000000..ff16f65 --- /dev/null +++ b/app/Http/Controllers/Admin/AdminUserController.php @@ -0,0 +1,61 @@ +only(['id', 'name', 'email', 'blocked', 'created_at', 'updated_at']); + + if ($aboutUser['blocked'] === true) { + $aboutUser['blocked_at'] = $user->blocked_at; + } + + $info = array_merge($aboutUser, [ + 'count_games' => $user->games()->count(), + 'count_won' => $user->countGamesWon(), + 'not_count_games' => $user->games()->where('end_at', null)->count() + ]); + + } catch (\Exception $e) { + return response()->json(['status' => false, 'message' => 'Something went wrong']); + } + + return response()->json($info); + } + + public function block(Request $request, User $user): JsonResponse + { + $status = $user->update([ + 'blocked' => true, + 'blocked_at' => date('Y-m-d H:i:s'), + ]); + + return response()->json([ + 'status' => $status, + 'blocked_at' => $user->blocked_at, + ]); + } + + public function unblock(Request $request, User $user): JsonResponse + { + $status = $user->update([ + 'blocked' => false, + 'blocked_at' => null, + ]); + + return response()->json(['status' => $status]); + } +} diff --git a/app/Http/Controllers/PaginateUserGamesController.php b/app/Http/Controllers/PaginateUserGamesController.php new file mode 100644 index 0000000..a98a14b --- /dev/null +++ b/app/Http/Controllers/PaginateUserGamesController.php @@ -0,0 +1,15 @@ +id, $request->page); + } +} diff --git a/app/Http/Controllers/TablePaginationController.php b/app/Http/Controllers/TablePaginationController.php index 43360b9..e88ffeb 100644 --- a/app/Http/Controllers/TablePaginationController.php +++ b/app/Http/Controllers/TablePaginationController.php @@ -5,7 +5,6 @@ use App\Http\Requests\TablePaginationRequest; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\DB; -use function Symfony\Component\String\s; class TablePaginationController extends Controller { @@ -16,12 +15,16 @@ class TablePaginationController extends Controller public function tablePagination(TablePaginationRequest $request): JsonResponse { $columns = $request->columns; + $orderBy = $request->ordering['by'] ?? 'ASC'; + $orderingColumn = $request->ordering['column'] ?? 'id'; if (in_array('id', $columns, true) === false) { $columns[] = 'id'; } - $paginated = Db::table($request->table)->paginate($request->perPage, $columns, page: $request->page); + $paginated = Db::table($request->table) + ->orderBy($orderingColumn, $orderBy) + ->paginate($request->perPage, $columns, page: $request->page); return response()->json([ 'status' => true, diff --git a/app/Http/Requests/PaginateGamesForUserRequest.php b/app/Http/Requests/PaginateGamesForUserRequest.php new file mode 100644 index 0000000..9730a38 --- /dev/null +++ b/app/Http/Requests/PaginateGamesForUserRequest.php @@ -0,0 +1,30 @@ + 'required|integer', + ]; + } +} diff --git a/app/Http/Requests/TablePaginationRequest.php b/app/Http/Requests/TablePaginationRequest.php index 9117113..3bcbc2b 100644 --- a/app/Http/Requests/TablePaginationRequest.php +++ b/app/Http/Requests/TablePaginationRequest.php @@ -26,14 +26,23 @@ public function authorize() public function withValidator($validator) { $validator->after(function ($validator) { - $validationMethod = preg_match('/\/admin((?![^ ])|\/)/', $this->path()) === 1 - ? 'canPaginateByAdmin' - : 'canPaginateByUser'; + $forAdmin = preg_match('/\/admin((?![^ ])|\/)/', $this->path()) === 1; - if (TablePaginationService::$validationMethod($this->table, $this->columns) === false) { + $this->ordering = is_array($this->ordering) === true ? $this->ordering : false; + + if (TablePaginationService::isCorrectColumns($forAdmin, $this->table, $this->columns) === false) { + $response = new JsonResponse([ + 'status' => false, + 'message' => 'This table or columns are not accessed', + ], 422); + + throw new ValidationException($validator, $response); + } + + if (TablePaginationService::isCorrectOrdering($forAdmin, $this->table, $this->ordering) === false) { $response = new JsonResponse([ 'status' => false, - 'message' => 'This table or columns are not accessed' + 'message' => 'Incorrect ordering', ], 422); throw new ValidationException($validator, $response); diff --git a/app/Models/User.php b/app/Models/User.php index 4b5ea90..7b1161d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Illuminate\Support\Facades\DB; /** * @mixin IdeHelperUser @@ -26,6 +25,8 @@ class User extends Authenticatable 'name', 'email', 'password', + 'blocked', + 'blocked_at', ]; /** @@ -45,6 +46,7 @@ class User extends Authenticatable */ protected $casts = [ 'email_verified_at' => 'datetime', + 'blocked' => 'boolean', ]; /** @@ -91,13 +93,8 @@ public function countEndedGames(): int */ public function countGamesWon(): int { - $sql = 'SELECT COUNT(*) as count FROM - (SELECT gu.`user_id`, gu.`game_id`, gu.`color` - FROM `game_user` gu - WHERE gu.user_id=:id) AS subq - INNER JOIN `games` g ON g.id=subq.game_id - WHERE g.winner_color=subq.color'; - - return DB::select($sql, ['id' => $this->id])[0]->count; + return Game::join('game_user', 'games.id', '=', 'game_user.game_id') + ->where('game_user.user_id', '=', $this->id) + ->whereColumn('games.winner_color', '=', 'game_user.color')->count(); } } diff --git a/app/Services/PaginateGamesForUserService.php b/app/Services/PaginateGamesForUserService.php new file mode 100644 index 0000000..e3f94a0 --- /dev/null +++ b/app/Services/PaginateGamesForUserService.php @@ -0,0 +1,30 @@ +where('game_user.user_id', $userId) + ->latest() + ->paginate(10, $columns, page: $page); + + return [ + 'items' => $paginated->items(), + 'total' => $paginated->total(), + 'last_page' => $paginated->lastPage(), + 'current_page' => $paginated->currentPage(), + ]; + } +} diff --git a/app/Services/TablePaginationService.php b/app/Services/TablePaginationService.php index 0a49604..ae74923 100644 --- a/app/Services/TablePaginationService.php +++ b/app/Services/TablePaginationService.php @@ -14,20 +14,23 @@ class TablePaginationService 'games' => ['id', 'token', 'start_at', 'end_at', 'winner_color'], ]; + private static array $tableForUser = []; + /** - * Check if the admin can get columns from the table and can get data from the table + * Check if someone can get columns from the table and can get data from the table * - * @param string $tableName + * @param bool $isAdmin + * @param string $table * @param array $columns * @return bool */ - public static function canPaginateByAdmin(string $tableName, array $columns): bool + public static function isCorrectColumns(bool $isAdmin, string $table, array $columns): bool { - if (array_key_exists($tableName, static::$tableForAdmin) === false) { + if (array_key_exists($table, static::$tableForAdmin) === false) { return false; } - $tableColumns = static::$tableForAdmin[$tableName]; + $tableColumns = $isAdmin === true ? static::$tableForAdmin[$table] : static::$tableForUser[$table]; foreach ($columns as $column) { if (in_array($column, $tableColumns, true) === false) { @@ -39,12 +42,26 @@ public static function canPaginateByAdmin(string $tableName, array $columns): bo } /** - * @param string $tableName - * @param array $columns + * Check that ordering parameter is correct + * + * @param bool $isAdmin + * @param string $table + * @param array|bool $ordering * @return bool */ - public static function canPaginateByUser(string $tableName, array $columns): bool + public static function isCorrectOrdering(bool $isAdmin, string $table, array|bool $ordering): bool { - return false; + if ($ordering === false) { + return true; + } + + if ($ordering['by'] !== null && strtoupper($ordering['by']) !== 'ASC' + && strtoupper($ordering['by']) !== 'DESC') { + return false; + } + + $tableColumns = $isAdmin === true ? static::$tableForAdmin[$table] : static::$tableForUser[$table]; + + return in_array($ordering['column'], $tableColumns, true); } } diff --git a/database/migrations/2021_05_06_204743_update_users_table.php b/database/migrations/2021_05_06_204743_update_users_table.php new file mode 100644 index 0000000..13adac0 --- /dev/null +++ b/database/migrations/2021_05_06_204743_update_users_table.php @@ -0,0 +1,31 @@ +boolean('blocked')->default(false); + $table->dateTime('blocked_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} diff --git a/resources/js/api/adminBlockUserRequest.js b/resources/js/api/adminBlockUserRequest.js new file mode 100644 index 0000000..ee51c84 --- /dev/null +++ b/resources/js/api/adminBlockUserRequest.js @@ -0,0 +1,13 @@ +export default async (id) => { + const res = await window.axios.post(`/api/admin/block/${id}`) + .catch((e) => e.response); + + if (res.data.status === false || res.status !== 200) { + return { + status: false, + message: res.data.message ?? 'Something went wrong', + }; + } + + return res.data; +}; diff --git a/resources/js/api/adminUnblockUserRequest.js b/resources/js/api/adminUnblockUserRequest.js new file mode 100644 index 0000000..cf6478f --- /dev/null +++ b/resources/js/api/adminUnblockUserRequest.js @@ -0,0 +1,13 @@ +export default async (id) => { + const res = await window.axios.post(`/api/admin/unblock/${id}`) + .catch((e) => e.response); + + if (res.data.status === false || res.status !== 200) { + return { + status: false, + message: res.data.message ?? 'Something went wrong', + }; + } + + return res.data; +}; diff --git a/resources/js/api/adminUserInfoRequest.js b/resources/js/api/adminUserInfoRequest.js new file mode 100644 index 0000000..fa72432 --- /dev/null +++ b/resources/js/api/adminUserInfoRequest.js @@ -0,0 +1,13 @@ +export default async (id) => { + const res = await window.axios.post(`/api/admin/user/${id}`) + .catch((e) => e.response); + + if (res.data.status === false || res.status !== 200) { + return { + status: false, + message: res.data.message ?? 'Something went wrong', + }; + } + + return res.data; +}; diff --git a/resources/js/api/getFromTableRequest.js b/resources/js/api/getFromTableRequest.js deleted file mode 100644 index 54512be..0000000 --- a/resources/js/api/getFromTableRequest.js +++ /dev/null @@ -1,13 +0,0 @@ -export default async (table, columns, page, perPage) => { - const res = await window.axios.post('/api/admin/table-pagination', { - table, columns, page, perPage, - }).catch((e) => e.response); - - if (res.status !== 200 || res.data.status === false) { - return { - status: false, - }; - } - - return res.data; -}; diff --git a/resources/js/api/paginatedTableByAdminRequest.js b/resources/js/api/paginatedTableByAdminRequest.js new file mode 100644 index 0000000..16f4519 --- /dev/null +++ b/resources/js/api/paginatedTableByAdminRequest.js @@ -0,0 +1,19 @@ +export default async (table, columns, page, perPage, ordering = false) => { + const body = { + table, + columns, + page, + perPage, + ordering, + }; + + const res = await window.axios.post('/api/admin/table-pagination', body).catch((e) => e.response); + + if (res.status !== 200 || res.data.status === false) { + return { + status: false, + }; + } + + return res.data; +}; diff --git a/resources/js/api/paginatedUserGamesRequest.js b/resources/js/api/paginatedUserGamesRequest.js new file mode 100644 index 0000000..dcc5080 --- /dev/null +++ b/resources/js/api/paginatedUserGamesRequest.js @@ -0,0 +1,12 @@ +export default async (userId, page) => { + const res = await window.axios.post(`/api/paginated-user-games/${userId}`, { page }) + .catch((e) => e.response); + + if (res.status !== 200 || res.data.status === false) { + return { + status: false, + }; + } + + return res.data; +}; diff --git a/resources/js/components/lists/UserGamesList.vue b/resources/js/components/lists/UserGamesList.vue new file mode 100644 index 0000000..b17b70c --- /dev/null +++ b/resources/js/components/lists/UserGamesList.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/resources/js/components/tables/ApiTable.vue b/resources/js/components/tables/ApiTable.vue index d45cd8d..4c4a24f 100644 --- a/resources/js/components/tables/ApiTable.vue +++ b/resources/js/components/tables/ApiTable.vue @@ -18,7 +18,7 @@ import { onBeforeMount, reactive, ref } from 'vue'; import { useRouter } from 'vue-router'; import BaseTable from './BaseTable.vue'; -import getFromTableRequest from '../../api/getFromTableRequest'; +import getFromTableRequest from '~/api/paginatedTableByAdminRequest'; export default { name: 'ApiTable', diff --git a/resources/js/pages/admin/view/AdminUsersView.vue b/resources/js/pages/admin/view/AdminUsersView.vue new file mode 100644 index 0000000..82b5daa --- /dev/null +++ b/resources/js/pages/admin/view/AdminUsersView.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/resources/js/router/index.js b/resources/js/router/index.js index 19ff08c..5cc29bd 100644 --- a/resources/js/router/index.js +++ b/resources/js/router/index.js @@ -14,6 +14,7 @@ import AdminUsers from '~/pages/admin/AdminUsers.vue'; import AdminGames from '~/pages/admin/AdminGames.vue'; import AdminWebsocket from '~/pages/admin/AdminWebsocket.vue'; import AdminGamesView from '../pages/admin/view/AdminGamesView'; +import AdminUsersView from '../pages/admin/view/AdminUsersView'; const routes = [ { @@ -115,6 +116,10 @@ const routes = [ path: 'view/games/:id', component: AdminGamesView, }, + { + path: 'view/users/:id', + component: AdminUsersView, + }, ], meta: { auth: true, diff --git a/routes/web.php b/routes/web.php index 482904b..cb7f663 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,8 +1,10 @@ group(function () { + Route::middleware('auth')->post('/paginated-user-games/{user}', PaginateUserGamesController::class); +}); + Route::middleware('auth')->prefix('/api/admin')->group(function () { Route::post('/table-pagination', [TablePaginationController::class, 'tablePagination']); - Route::post('/game/{game}', [AdminGameInfoController::class, 'getInfo']); + Route::post('/game/{game}', [AdminGameController::class, 'getInfo']); + + Route::post('/user/{user}', [AdminUserController::class, 'getInfo']); + + Route::post('/block/{user}', [AdminUserController::class, 'block']); + + Route::post('/unblock/{user}', [AdminUserController::class, 'unblock']); }); Route::post('/subscribed/{channel}', [SubscribedOnChannelController::class, 'subscribed']) From bd7ac00cfdffb8b050c8038d60a57752af254f39 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Sat, 8 May 2021 21:47:23 +0700 Subject: [PATCH 09/84] New: add sorting by column in table --- resources/js/bootstrap.js | 4 ++ resources/js/components/tables/ApiTable.vue | 27 ++++++--- resources/js/components/tables/BaseTable.vue | 61 +++++++++++++++++++- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index 16414b3..f452684 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -16,6 +16,10 @@ window.axios = require('axios'); window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; +window.isBoolean = (value) => typeof value === 'boolean'; +window.isNumber = (value) => typeof value === 'number'; +window.isString = (value) => typeof value === 'string'; + window.Pusher = require('pusher-js'); function echoLoad() { diff --git a/resources/js/components/tables/ApiTable.vue b/resources/js/components/tables/ApiTable.vue index 4c4a24f..43539f5 100644 --- a/resources/js/components/tables/ApiTable.vue +++ b/resources/js/components/tables/ApiTable.vue @@ -6,11 +6,12 @@ :per-page="currentPerPage" :current-page="currentPage" :total-pages="totalPages" - @newPageAction="newPageAction" + @newPageAction="loadData" @viewAction="viewAction" @editAction="editAction" @deleteAction="deleteAction" @newPerPageAction="newPerPageAction" + @sortByColumnAction="sortByColumnAction" > @@ -53,11 +54,15 @@ export default { const totalPages = ref(1); const totalItems = ref(0); const currentPerPage = ref(props.perPage); + const ordering = { + column: 'id', + by: 'asc', + }; const items = reactive([]); - const newPageAction = async (newPage) => { - const res = await getFromTableRequest(props.table, props.columns, newPage, currentPerPage.value); + const loadData = async (page) => { + const res = await getFromTableRequest(props.table, props.columns, page, currentPerPage.value, ordering); if (res.status === false) { console.log(`Cannot get items from ${props.table}`); @@ -68,7 +73,7 @@ export default { totalItems.value = res.total_items; items.length = 0; - currentPage.value = newPage; + currentPage.value = page; res.items.forEach((el) => { items.push(el); }); @@ -97,11 +102,18 @@ export default { const newCurrentPage = Math.floor(itemsPrinted / newPerPage); currentPage.value = newCurrentPage > 0 ? newCurrentPage : 1; currentPerPage.value = Number(newPerPage); - await newPageAction(currentPage.value); + await loadData(currentPage.value); + }; + + const sortByColumnAction = (column, type) => { + ordering.by = type === 'firstMore' ? 'desc' : 'asc'; + ordering.column = column.toLowerCase().replace(/\s/g, '_'); + + loadData(currentPage.value); }; onBeforeMount(async () => { - await newPageAction(1); + await loadData(1); }); return { @@ -109,11 +121,12 @@ export default { totalPages, items, currentPerPage, - newPageAction, + loadData, viewAction, editAction, deleteAction, newPerPageAction, + sortByColumnAction, }; }, diff --git a/resources/js/components/tables/BaseTable.vue b/resources/js/components/tables/BaseTable.vue index 4bd0e9b..bba8256 100644 --- a/resources/js/components/tables/BaseTable.vue +++ b/resources/js/components/tables/BaseTable.vue @@ -4,9 +4,19 @@ - № - - {{ upperFirstLetter(column.replace('/admin/', '').replace(/_/g, ' ')) }} + № + + + +
+ {{ upperFirstLetter(column.replace(/_/g, ' ')) }} + +
+ expand_less + expand_more +
+
+ Actions @@ -91,6 +101,13 @@ export default { type: Array, default: () => ['view', 'edit', 'delete'], }, + defaultSortColumn: { + type: Object, + default: () => ({ + column: 'id', + firstLess: true, + }), + }, needAddAction: { type: Boolean, default: () => false, @@ -146,6 +163,40 @@ export default { currentPerPage.value = props.perPage; }; + const firstMoreColumn = ref(''); + + const defaultSortHandler = () => { + let needleType; + const { firstLess } = props.defaultSortColumn; + const column = window.isString(props.defaultSortColumn.column) === true + ? props.defaultSortColumn.column + : 'id'; + + if (window.isBoolean(firstLess) === false || firstLess === true) { + needleType = 'firstLess'; + firstMoreColumn.value = ''; + } else { + needleType = 'firstMore'; + firstMoreColumn.value = props.defaultSortColumn.column; + } + + emit('sortByColumnAction', column, needleType); + }; + + const sortByColumnAction = (column) => { + let needleType = ''; + + if (firstMoreColumn.value !== column) { + needleType = 'firstMore'; + firstMoreColumn.value = column; + } else { + needleType = 'firstLess'; + firstMoreColumn.value = ''; + } + + emit('sortByColumnAction', column, needleType); + }; + watchEffect(() => { currentPerPage.value = props.perPage; }); @@ -168,6 +219,9 @@ export default { maxCellWidth, currentPerPage, selectedPerPage, + firstMoreColumn, + sortByColumnAction, + defaultSortHandler, }; }, @@ -249,6 +303,7 @@ export default { &__select-page { @apply rounded-full border-none outline-none ring-1 focus:ring-2 ring-yellow-500 focus:ring-yellow-500; } + //color: #F80F6CFF; } From 1bc71d9cee202336db872c5301fd95ebcf166d24 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Mon, 10 May 2021 21:59:07 +0700 Subject: [PATCH 10/84] New: add search in table --- .../TablePaginationValidationException.php | 10 + .../Controllers/TablePaginationController.php | 63 +- app/Http/Requests/SearchInTableRequest.php | 66 ++ app/Http/Requests/TablePaginationRequest.php | 17 +- app/Services/TablePaginationService.php | 57 +- composer.lock | 820 ++++++++++-------- .../js/api/paginatedTableByAdminRequest.js | 10 + resources/js/api/paginatedUserGamesRequest.js | 10 + resources/js/api/searchInTableRequest.js | 31 + .../js/components/lists/UserGamesList.vue | 2 +- resources/js/components/tables/ApiTable.vue | 88 +- resources/js/components/tables/BaseTable.vue | 84 +- .../js/components/tables/BaseTableSearch.vue | 112 +++ .../tables/BaseTableSettingsPanel.vue | 17 + .../tables/cards/BaseTableSettingsCard.vue | 29 + .../tables/cards/TableSearchSettingsCard.vue | 78 ++ resources/js/helpers/validationHelper.js | 37 + resources/js/pages/admin/Admin.vue | 2 +- resources/js/store/index.js | 2 + .../js/store/modules/searchInTableModule.js | 15 + .../AfterPaginationRequestValidation.js | 40 + routes/web.php | 2 + 22 files changed, 1160 insertions(+), 432 deletions(-) create mode 100644 app/Exceptions/TablePaginationValidationException.php create mode 100644 app/Http/Requests/SearchInTableRequest.php create mode 100644 resources/js/api/searchInTableRequest.js create mode 100644 resources/js/components/tables/BaseTableSearch.vue create mode 100644 resources/js/components/tables/BaseTableSettingsPanel.vue create mode 100644 resources/js/components/tables/cards/BaseTableSettingsCard.vue create mode 100644 resources/js/components/tables/cards/TableSearchSettingsCard.vue create mode 100644 resources/js/helpers/validationHelper.js create mode 100644 resources/js/store/modules/searchInTableModule.js create mode 100644 resources/js/validators/AfterPaginationRequestValidation.js diff --git a/app/Exceptions/TablePaginationValidationException.php b/app/Exceptions/TablePaginationValidationException.php new file mode 100644 index 0000000..bf5d7ec --- /dev/null +++ b/app/Exceptions/TablePaginationValidationException.php @@ -0,0 +1,10 @@ +orderBy($orderingColumn, $orderBy) ->paginate($request->perPage, $columns, page: $request->page); - return response()->json([ + return $this->getSuccessfulResponse($paginated); + } + + /** + * $table - was validated in SearchInTableRequest + * + * @param SearchInTableRequest $request + * @param string $table + * @return JsonResponse + */ + public function searchInTable(SearchInTableRequest $request, string $table): JsonResponse + { + $whereConditions = []; + $columns = $request->columns; + $orderBy = $request->ordering['by'] ?? 'ASC'; + $orderingColumn = $request->ordering['column'] ?? 'id'; + + if (in_array('id', $columns, true) === false) { + $columns[] = 'id'; + } + + foreach ($request->searchColumns as $searchColumn) { + $whereConditions[] = [$searchColumn, 'LIKE', "%$request->needle%"]; + } + + if (count($whereConditions) === 0) { + return response()->json([ + 'status' => true, + 'items' => [], + ]); + } + + $paginated = DB::table($table) + ->select($columns) + ->where(function ($query) use ($whereConditions) { + foreach ($whereConditions as $searchCondition) { + $query->orWhere(...$searchCondition); + } + }) + ->orderBy($orderingColumn, $orderBy) + ->paginate($request->perPage, $columns, page: $request->page); + + return $this->getSuccessfulResponse($paginated); + } + + /** + * Fields [ + * status, + * total - total items, + * items, + * last_page, + * current_page, + * ] + * + * @param LengthAwarePaginator $paginated + * @return JsonResponse + */ + private function getSuccessfulResponse(LengthAwarePaginator $paginated): JsonResponse + { + return response()->json([ 'status' => true, 'total' => $paginated->total(), 'items' => $paginated->items(), diff --git a/app/Http/Requests/SearchInTableRequest.php b/app/Http/Requests/SearchInTableRequest.php new file mode 100644 index 0000000..450635e --- /dev/null +++ b/app/Http/Requests/SearchInTableRequest.php @@ -0,0 +1,66 @@ +after(function ($validator) { + $forAdmin = preg_match('/\/admin((?![^ ])|\/)/', $this->path()) === 1; + + $this->ordering = is_array($this->ordering) === true ? $this->ordering : false; + + try { + TablePaginationService::isTableAvailable($forAdmin, $this->table); + TablePaginationService::areColumnsAvailable($forAdmin, $this->table, $this->columns); + TablePaginationService::areColumnsAvailable($forAdmin, $this->table, $this->searchColumns); + TablePaginationService::isCorrectOrdering($forAdmin, $this->table, $this->ordering); + + } catch (TablePaginationValidationException $e) { + $response = new JsonResponse([ + 'status' => false, + 'message' => $e->getMessage(), + ], 422); + + throw new ValidationException($validator, $response); + } + }); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'columns' => 'required|array', + 'searchColumns' => 'required|array', + 'page' => 'required|integer', + 'perPage' => 'required|integer', + 'needle' => 'required|string|min:3' + ]; + } +} diff --git a/app/Http/Requests/TablePaginationRequest.php b/app/Http/Requests/TablePaginationRequest.php index 3bcbc2b..d75d7fa 100644 --- a/app/Http/Requests/TablePaginationRequest.php +++ b/app/Http/Requests/TablePaginationRequest.php @@ -2,6 +2,7 @@ namespace App\Http\Requests; +use App\Exceptions\TablePaginationValidationException; use App\Services\TablePaginationService; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\JsonResponse; @@ -30,19 +31,15 @@ public function withValidator($validator) $this->ordering = is_array($this->ordering) === true ? $this->ordering : false; - if (TablePaginationService::isCorrectColumns($forAdmin, $this->table, $this->columns) === false) { - $response = new JsonResponse([ - 'status' => false, - 'message' => 'This table or columns are not accessed', - ], 422); - - throw new ValidationException($validator, $response); - } + try { + TablePaginationService::isTableAvailable($forAdmin, $this->table); + TablePaginationService::areColumnsAvailable($forAdmin, $this->table, $this->columns); + TablePaginationService::isCorrectOrdering($forAdmin, $this->table, $this->ordering); - if (TablePaginationService::isCorrectOrdering($forAdmin, $this->table, $this->ordering) === false) { + } catch (TablePaginationValidationException $e) { $response = new JsonResponse([ 'status' => false, - 'message' => 'Incorrect ordering', + 'message' => $e->getMessage(), ], 422); throw new ValidationException($validator, $response); diff --git a/app/Services/TablePaginationService.php b/app/Services/TablePaginationService.php index ae74923..0016fb2 100644 --- a/app/Services/TablePaginationService.php +++ b/app/Services/TablePaginationService.php @@ -2,6 +2,8 @@ namespace App\Services; +use App\Exceptions\TablePaginationValidationException; + class TablePaginationService { /** @@ -9,36 +11,50 @@ class TablePaginationService * * @var array|\string[][] */ - private static array $tableForAdmin = [ + private static array $tablesForAdmin = [ 'users' => ['id', 'name', 'email'], 'games' => ['id', 'token', 'start_at', 'end_at', 'winner_color'], ]; - private static array $tableForUser = []; + /** + * Key - table, value - columns + * + * @var array|\string[][] + */ + private static array $tablesForUser = []; + + /** + * Check that table available + * + * @throws TablePaginationValidationException + */ + public static function isTableAvailable(bool $isAdmin, string $table): void + { + $needleTables = $isAdmin === true ? static::$tablesForAdmin : static::$tablesForUser; + + if (array_key_exists($table, $needleTables) === false) { + throw (new TablePaginationValidationException("`$table` table not available")); + } + } /** - * Check if someone can get columns from the table and can get data from the table + * Check if someone can get columns from the table * * @param bool $isAdmin * @param string $table * @param array $columns - * @return bool + * @return void + * @throws TablePaginationValidationException */ - public static function isCorrectColumns(bool $isAdmin, string $table, array $columns): bool + public static function areColumnsAvailable(bool $isAdmin, string $table, array $columns): void { - if (array_key_exists($table, static::$tableForAdmin) === false) { - return false; - } - - $tableColumns = $isAdmin === true ? static::$tableForAdmin[$table] : static::$tableForUser[$table]; + $tableColumns = $isAdmin === true ? static::$tablesForAdmin[$table] : static::$tablesForUser[$table]; foreach ($columns as $column) { if (in_array($column, $tableColumns, true) === false) { - return false; + throw (new TablePaginationValidationException("`$column` column not available")); } } - - return true; } /** @@ -47,21 +63,24 @@ public static function isCorrectColumns(bool $isAdmin, string $table, array $col * @param bool $isAdmin * @param string $table * @param array|bool $ordering - * @return bool + * @return void + * @throws TablePaginationValidationException */ - public static function isCorrectOrdering(bool $isAdmin, string $table, array|bool $ordering): bool + public static function isCorrectOrdering(bool $isAdmin, string $table, array|bool $ordering): void { if ($ordering === false) { - return true; + return; } if ($ordering['by'] !== null && strtoupper($ordering['by']) !== 'ASC' && strtoupper($ordering['by']) !== 'DESC') { - return false; + throw (new TablePaginationValidationException('Incorrect ordering')); } - $tableColumns = $isAdmin === true ? static::$tableForAdmin[$table] : static::$tableForUser[$table]; + $tableColumns = $isAdmin === true ? static::$tablesForAdmin[$table] : static::$tablesForUser[$table]; - return in_array($ordering['column'], $tableColumns, true); + if (in_array($ordering['column'], $tableColumns, true) === false) { + throw (new TablePaginationValidationException('You cannot order by this column')); + } } } diff --git a/composer.lock b/composer.lock index 2a6071c..d50ce77 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a52ba7cc7d9f283be7c75daeae4aad17", + "content-hash": "56cb6ee6220cbdf0ddda7af6076aedd3", "packages": [ { "name": "asm89/stack-cors", - "version": "v2.0.2", + "version": "v2.0.3", "source": { "type": "git", "url": "https://github.com/asm89/stack-cors.git", - "reference": "8d8f88b3b3830916be94292c1fbce84433efb1aa" + "reference": "9cb795bf30988e8c96dd3c40623c48a877bc6714" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/8d8f88b3b3830916be94292c1fbce84433efb1aa", - "reference": "8d8f88b3b3830916be94292c1fbce84433efb1aa", + "url": "https://api.github.com/repos/asm89/stack-cors/zipball/9cb795bf30988e8c96dd3c40623c48a877bc6714", + "reference": "9cb795bf30988e8c96dd3c40623c48a877bc6714", "shasum": "" }, "require": { @@ -58,9 +58,9 @@ ], "support": { "issues": "https://github.com/asm89/stack-cors/issues", - "source": "https://github.com/asm89/stack-cors/tree/v2.0.2" + "source": "https://github.com/asm89/stack-cors/tree/v2.0.3" }, - "time": "2020-10-29T16:03:21+00:00" + "time": "2021-03-11T06:42:03+00:00" }, { "name": "brick/math", @@ -118,43 +118,6 @@ ], "time": "2021-01-20T22:51:39+00:00" }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, { "name": "doctrine/inflector", "version": "2.0.3", @@ -519,16 +482,16 @@ }, { "name": "fruitcake/laravel-cors", - "version": "v2.0.3", + "version": "v2.0.4", "source": { "type": "git", "url": "https://github.com/fruitcake/laravel-cors.git", - "reference": "01de0fe5f71c70d1930ee9a80385f9cc28e0f63a" + "reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/01de0fe5f71c70d1930ee9a80385f9cc28e0f63a", - "reference": "01de0fe5f71c70d1930ee9a80385f9cc28e0f63a", + "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/a8ccedc7ca95189ead0e407c43b530dc17791d6a", + "reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a", "shasum": "" }, "require": { @@ -541,8 +504,8 @@ }, "require-dev": { "laravel/framework": "^6|^7|^8", - "orchestra/testbench-dusk": "^4|^5|^6", - "phpunit/phpunit": "^6|^7|^8", + "orchestra/testbench-dusk": "^4|^5|^6|^7", + "phpunit/phpunit": "^6|^7|^8|^9", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -584,7 +547,7 @@ ], "support": { "issues": "https://github.com/fruitcake/laravel-cors/issues", - "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.3" + "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.4" }, "funding": [ { @@ -592,7 +555,7 @@ "type": "github" } ], - "time": "2020-10-22T13:57:20+00:00" + "time": "2021-04-26T11:24:25+00:00" }, { "name": "graham-campbell/result-type", @@ -662,22 +625,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.2.0", + "version": "7.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79" + "reference": "7008573787b430c1c1f650e3722d9bba59967628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79", - "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^1.4", - "guzzlehttp/psr7": "^1.7", + "guzzlehttp/psr7": "^1.7 || ^2.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0" }, @@ -685,6 +648,7 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", "ext-curl": "*", "php-http/client-integration-tests": "^3.0", "phpunit/phpunit": "^8.5.5 || ^9.3.5", @@ -698,7 +662,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.1-dev" + "dev-master": "7.3-dev" } }, "autoload": { @@ -740,7 +704,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.2.0" + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" }, "funding": [ { @@ -760,7 +724,7 @@ "type": "github" } ], - "time": "2020-10-10T11:47:56+00:00" + "time": "2021-03-23T11:33:13+00:00" }, { "name": "guzzlehttp/promises", @@ -819,16 +783,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.7.0", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3" + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", "shasum": "" }, "require": { @@ -888,22 +852,22 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.7.0" + "source": "https://github.com/guzzle/psr7/tree/1.8.2" }, - "time": "2020-09-30T07:37:11+00:00" + "time": "2021-04-26T09:17:50+00:00" }, { "name": "laravel/framework", - "version": "v8.31.0", + "version": "v8.40.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "2aa5c2488d25178ebc097052c7897a0e463ddc35" + "reference": "a654897ad7f97aea9d7ef292803939798c4a02a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/2aa5c2488d25178ebc097052c7897a0e463ddc35", - "reference": "2aa5c2488d25178ebc097052c7897a0e463ddc35", + "url": "https://api.github.com/repos/laravel/framework/zipball/a654897ad7f97aea9d7ef292803939798c4a02a4", + "reference": "a654897ad7f97aea9d7ef292803939798c4a02a4", "shasum": "" }, "require": { @@ -1058,7 +1022,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-03-04T15:22:36+00:00" + "time": "2021-04-28T14:38:56+00:00" }, { "name": "laravel/tinker", @@ -1130,16 +1094,16 @@ }, { "name": "league/commonmark", - "version": "1.5.7", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54" + "reference": "2651c497f005de305c7ba3f232cbd87b8c00ee8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/11df9b36fd4f1d2b727a73bf14931d81373b9a54", - "reference": "11df9b36fd4f1d2b727a73bf14931d81373b9a54", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/2651c497f005de305c7ba3f232cbd87b8c00ee8c", + "reference": "2651c497f005de305c7ba3f232cbd87b8c00ee8c", "shasum": "" }, "require": { @@ -1227,7 +1191,7 @@ "type": "tidelift" } ], - "time": "2020-10-31T13:49:32+00:00" + "time": "2021-05-08T16:08:00+00:00" }, { "name": "league/flysystem", @@ -1478,16 +1442,16 @@ }, { "name": "nesbot/carbon", - "version": "2.46.0", + "version": "2.47.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4" + "reference": "606262fd8888b75317ba9461825a24fc34001e1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4", - "reference": "2fd2c4a77d58a4e95234c8a61c5df1f157a91bf4", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/606262fd8888b75317ba9461825a24fc34001e1e", + "reference": "606262fd8888b75317ba9461825a24fc34001e1e", "shasum": "" }, "require": { @@ -1567,20 +1531,20 @@ "type": "tidelift" } ], - "time": "2021-02-24T17:30:44+00:00" + "time": "2021-04-13T21:54:02+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.4", + "version": "v4.10.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", + "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", "shasum": "" }, "require": { @@ -1621,22 +1585,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" }, - "time": "2020-12-20T10:01:03+00:00" + "time": "2021-05-03T19:11:20+00:00" }, { "name": "opis/closure", - "version": "3.6.1", + "version": "3.6.2", "source": { "type": "git", "url": "https://github.com/opis/closure.git", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5" + "reference": "06e2ebd25f2869e54a306dda991f7db58066f7f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", - "reference": "943b5d70cc5ae7483f6aff6ff43d7e34592ca0f5", + "url": "https://api.github.com/repos/opis/closure/zipball/06e2ebd25f2869e54a306dda991f7db58066f7f6", + "reference": "06e2ebd25f2869e54a306dda991f7db58066f7f6", "shasum": "" }, "require": { @@ -1686,9 +1650,9 @@ ], "support": { "issues": "https://github.com/opis/closure/issues", - "source": "https://github.com/opis/closure/tree/3.6.1" + "source": "https://github.com/opis/closure/tree/3.6.2" }, - "time": "2020-11-07T02:01:34+00:00" + "time": "2021-04-09T13:42:10+00:00" }, { "name": "paragonie/random_compat", @@ -1742,16 +1706,16 @@ }, { "name": "paragonie/sodium_compat", - "version": "v1.14.0", + "version": "v1.15.4", "source": { "type": "git", "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3" + "reference": "8a93bfe047c7f699f819459de8ddda144cd636a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3", - "reference": "a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/8a93bfe047c7f699f819459de8ddda144cd636a4", + "reference": "8a93bfe047c7f699f819459de8ddda144cd636a4", "shasum": "" }, "require": { @@ -1822,9 +1786,9 @@ ], "support": { "issues": "https://github.com/paragonie/sodium_compat/issues", - "source": "https://github.com/paragonie/sodium_compat/tree/v1.14.0" + "source": "https://github.com/paragonie/sodium_compat/tree/v1.15.4" }, - "time": "2020-12-03T16:26:19+00:00" + "time": "2021-04-17T09:00:05+00:00" }, { "name": "phpoption/phpoption", @@ -2100,16 +2064,16 @@ }, { "name": "psr/log", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", - "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", "shasum": "" }, "require": { @@ -2133,7 +2097,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for logging libraries", @@ -2144,9 +2108,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.3" + "source": "https://github.com/php-fig/log/tree/1.1.4" }, - "time": "2020-03-23T09:12:05+00:00" + "time": "2021-05-03T11:20:27+00:00" }, { "name": "psr/simple-cache", @@ -2201,20 +2165,19 @@ }, { "name": "psy/psysh", - "version": "v0.10.6", + "version": "v0.10.8", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3" + "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/6f990c19f91729de8b31e639d6e204ea59f19cf3", - "reference": "6f990c19f91729de8b31e639d6e204ea59f19cf3", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e4573f47750dd6c92dca5aee543fa77513cbd8d3", + "reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3", "shasum": "" }, "require": { - "dnoegel/php-xdg-base-dir": "0.1.*", "ext-json": "*", "ext-tokenizer": "*", "nikic/php-parser": "~4.0|~3.0|~2.0|~1.3", @@ -2271,9 +2234,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.10.6" + "source": "https://github.com/bobthecow/psysh/tree/v0.10.8" }, - "time": "2021-01-18T15:53:43+00:00" + "time": "2021-04-10T16:23:39+00:00" }, { "name": "pusher/pusher-php-server", @@ -2549,20 +2512,20 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v6.2.6", + "version": "v6.2.7", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "d2791ff0b73247cdc2096b14f5580aba40c12bff" + "reference": "15f7faf8508e04471f666633addacf54c0ab5933" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/d2791ff0b73247cdc2096b14f5580aba40c12bff", - "reference": "d2791ff0b73247cdc2096b14f5580aba40c12bff", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/15f7faf8508e04471f666633addacf54c0ab5933", + "reference": "15f7faf8508e04471f666633addacf54c0ab5933", "shasum": "" }, "require": { - "egulias/email-validator": "^2.0", + "egulias/email-validator": "^2.0|^3.1", "php": ">=7.0.0", "symfony/polyfill-iconv": "^1.0", "symfony/polyfill-intl-idn": "^1.10", @@ -2608,7 +2571,7 @@ ], "support": { "issues": "https://github.com/swiftmailer/swiftmailer/issues", - "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.6" + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.7" }, "funding": [ { @@ -2620,20 +2583,20 @@ "type": "tidelift" } ], - "time": "2021-03-05T12:08:49+00:00" + "time": "2021-03-09T12:30:35+00:00" }, { "name": "symfony/console", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "d6d0cc30d8c0fda4e7b213c20509b0159a8f4556" + "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/d6d0cc30d8c0fda4e7b213c20509b0159a8f4556", - "reference": "d6d0cc30d8c0fda4e7b213c20509b0159a8f4556", + "url": "https://api.github.com/repos/symfony/console/zipball/90374b8ed059325b49a29b55b3f8bb4062c87629", + "reference": "90374b8ed059325b49a29b55b3f8bb4062c87629", "shasum": "" }, "require": { @@ -2701,7 +2664,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.4" + "source": "https://github.com/symfony/console/tree/v5.2.7" }, "funding": [ { @@ -2717,20 +2680,20 @@ "type": "tidelift" } ], - "time": "2021-02-23T10:08:49+00:00" + "time": "2021-04-19T14:07:32+00:00" }, { "name": "symfony/css-selector", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f" + "reference": "59a684f5ac454f066ecbe6daecce6719aed283fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f65f217b3314504a1ec99c2d6ef69016bb13490f", - "reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/59a684f5ac454f066ecbe6daecce6719aed283fb", + "reference": "59a684f5ac454f066ecbe6daecce6719aed283fb", "shasum": "" }, "require": { @@ -2766,7 +2729,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.2.4" + "source": "https://github.com/symfony/css-selector/tree/v5.3.0-BETA1" }, "funding": [ { @@ -2782,20 +2745,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:01:46+00:00" + "time": "2021-04-07T16:07:52+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", - "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", "shasum": "" }, "require": { @@ -2804,7 +2767,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -2833,7 +2796,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/master" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" }, "funding": [ { @@ -2849,20 +2812,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/error-handler", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "b547d3babcab5c31e01de59ee33e9d9c1421d7d0" + "reference": "ea3ddbf67615e883ca7c33a4de61213789846782" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/b547d3babcab5c31e01de59ee33e9d9c1421d7d0", - "reference": "b547d3babcab5c31e01de59ee33e9d9c1421d7d0", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/ea3ddbf67615e883ca7c33a4de61213789846782", + "reference": "ea3ddbf67615e883ca7c33a4de61213789846782", "shasum": "" }, "require": { @@ -2902,7 +2865,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.2.4" + "source": "https://github.com/symfony/error-handler/tree/v5.2.7" }, "funding": [ { @@ -2918,7 +2881,7 @@ "type": "tidelift" } ], - "time": "2021-02-11T08:21:20+00:00" + "time": "2021-04-07T15:57:33+00:00" }, { "name": "symfony/event-dispatcher", @@ -3007,16 +2970,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "0ba7d54483095a198fa51781bc608d17e84dffa2" + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ba7d54483095a198fa51781bc608d17e84dffa2", - "reference": "0ba7d54483095a198fa51781bc608d17e84dffa2", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/69fee1ad2332a7cbab3aca13591953da9cdb7a11", + "reference": "69fee1ad2332a7cbab3aca13591953da9cdb7a11", "shasum": "" }, "require": { @@ -3029,7 +2992,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -3066,7 +3029,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.2.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.4.0" }, "funding": [ { @@ -3082,7 +3045,7 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/finder", @@ -3147,16 +3110,16 @@ }, { "name": "symfony/http-client-contracts", - "version": "v2.3.1", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "41db680a15018f9c1d4b23516059633ce280ca33" + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/41db680a15018f9c1d4b23516059633ce280ca33", - "reference": "41db680a15018f9c1d4b23516059633ce280ca33", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/7e82f6084d7cae521a75ef2cb5c9457bbda785f4", + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4", "shasum": "" }, "require": { @@ -3167,9 +3130,8 @@ }, "type": "library", "extra": { - "branch-version": "2.3", "branch-alias": { - "dev-main": "2.3-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -3206,7 +3168,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v2.3.1" + "source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0" }, "funding": [ { @@ -3222,20 +3184,20 @@ "type": "tidelift" } ], - "time": "2020-10-14T17:08:19+00:00" + "time": "2021-04-11T23:07:08+00:00" }, { "name": "symfony/http-foundation", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "54499baea7f7418bce7b5ec92770fd0799e8e9bf" + "reference": "a416487a73bb9c9d120e9ba3a60547f4a3fb7a1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/54499baea7f7418bce7b5ec92770fd0799e8e9bf", - "reference": "54499baea7f7418bce7b5ec92770fd0799e8e9bf", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a416487a73bb9c9d120e9ba3a60547f4a3fb7a1f", + "reference": "a416487a73bb9c9d120e9ba3a60547f4a3fb7a1f", "shasum": "" }, "require": { @@ -3279,7 +3241,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.2.4" + "source": "https://github.com/symfony/http-foundation/tree/v5.2.7" }, "funding": [ { @@ -3295,20 +3257,20 @@ "type": "tidelift" } ], - "time": "2021-02-25T17:16:57+00:00" + "time": "2021-05-01T13:46:24+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "c452dbe4f385f030c3957821bf921b13815d6140" + "reference": "1e9f6879f070f718e0055fbac232a56f67b8b6bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c452dbe4f385f030c3957821bf921b13815d6140", - "reference": "c452dbe4f385f030c3957821bf921b13815d6140", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1e9f6879f070f718e0055fbac232a56f67b8b6bd", + "reference": "1e9f6879f070f718e0055fbac232a56f67b8b6bd", "shasum": "" }, "require": { @@ -3391,7 +3353,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.2.4" + "source": "https://github.com/symfony/http-kernel/tree/v5.2.7" }, "funding": [ { @@ -3407,20 +3369,20 @@ "type": "tidelift" } ], - "time": "2021-03-04T18:05:55+00:00" + "time": "2021-05-01T14:53:15+00:00" }, { "name": "symfony/mime", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "5155d2fe14ef1eb150e3bdbbc1ec1455df95e9cd" + "reference": "7af452bf51c46f18da00feb32e1ad36db9426515" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/5155d2fe14ef1eb150e3bdbbc1ec1455df95e9cd", - "reference": "5155d2fe14ef1eb150e3bdbbc1ec1455df95e9cd", + "url": "https://api.github.com/repos/symfony/mime/zipball/7af452bf51c46f18da00feb32e1ad36db9426515", + "reference": "7af452bf51c46f18da00feb32e1ad36db9426515", "shasum": "" }, "require": { @@ -3431,12 +3393,13 @@ "symfony/polyfill-php80": "^1.15" }, "conflict": { + "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<4.4" }, "require-dev": { - "egulias/email-validator": "^2.1.10", + "egulias/email-validator": "^2.1.10|^3.1", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^4.4|^5.0", "symfony/property-access": "^4.4|^5.1", @@ -3473,7 +3436,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.2.4" + "source": "https://github.com/symfony/mime/tree/v5.2.7" }, "funding": [ { @@ -3489,7 +3452,7 @@ "type": "tidelift" } ], - "time": "2021-02-15T18:55:04+00:00" + "time": "2021-04-29T20:47:09+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4222,16 +4185,16 @@ }, { "name": "symfony/process", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f" + "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f", - "reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f", + "url": "https://api.github.com/repos/symfony/process/zipball/98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", + "reference": "98cb8eeb72e55d4196dd1e36f1f16e7b3a9a088e", "shasum": "" }, "require": { @@ -4264,7 +4227,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.2.4" + "source": "https://github.com/symfony/process/tree/v5.3.0-BETA1" }, "funding": [ { @@ -4280,20 +4243,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T10:15:41+00:00" + "time": "2021-04-08T10:27:02+00:00" }, { "name": "symfony/routing", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "cafa138128dfd6ab6be1abf6279169957b34f662" + "reference": "3f0cab2e95b5e92226f34c2c1aa969d3fc41f48c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/cafa138128dfd6ab6be1abf6279169957b34f662", - "reference": "cafa138128dfd6ab6be1abf6279169957b34f662", + "url": "https://api.github.com/repos/symfony/routing/zipball/3f0cab2e95b5e92226f34c2c1aa969d3fc41f48c", + "reference": "3f0cab2e95b5e92226f34c2c1aa969d3fc41f48c", "shasum": "" }, "require": { @@ -4316,7 +4279,6 @@ "symfony/yaml": "^4.4|^5.0" }, "suggest": { - "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", @@ -4354,7 +4316,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.2.4" + "source": "https://github.com/symfony/routing/tree/v5.2.7" }, "funding": [ { @@ -4370,25 +4332,25 @@ "type": "tidelift" } ], - "time": "2021-02-22T15:48:39+00:00" + "time": "2021-04-11T22:55:21+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.0" + "psr/container": "^1.1" }, "suggest": { "symfony/service-implementation": "" @@ -4396,7 +4358,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4433,7 +4395,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" }, "funding": [ { @@ -4449,20 +4411,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-04-01T10:43:52+00:00" }, { "name": "symfony/string", - "version": "v5.2.4", + "version": "v5.2.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "4e78d7d47061fa183639927ec40d607973699609" + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4e78d7d47061fa183639927ec40d607973699609", - "reference": "4e78d7d47061fa183639927ec40d607973699609", + "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", "shasum": "" }, "require": { @@ -4516,7 +4478,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.4" + "source": "https://github.com/symfony/string/tree/v5.2.6" }, "funding": [ { @@ -4532,20 +4494,20 @@ "type": "tidelift" } ], - "time": "2021-02-16T10:20:28+00:00" + "time": "2021-03-17T17:12:15+00:00" }, { "name": "symfony/translation", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "74b0353ab34ff4cca827a2cf909e325d96815e60" + "reference": "e37ece5242564bceea54d709eafc948377ec9749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/74b0353ab34ff4cca827a2cf909e325d96815e60", - "reference": "74b0353ab34ff4cca827a2cf909e325d96815e60", + "url": "https://api.github.com/repos/symfony/translation/zipball/e37ece5242564bceea54d709eafc948377ec9749", + "reference": "e37ece5242564bceea54d709eafc948377ec9749", "shasum": "" }, "require": { @@ -4609,7 +4571,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.2.4" + "source": "https://github.com/symfony/translation/tree/v5.2.7" }, "funding": [ { @@ -4625,20 +4587,20 @@ "type": "tidelift" } ], - "time": "2021-03-04T15:41:09+00:00" + "time": "2021-04-01T08:15:21+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105" + "reference": "95c812666f3e91db75385749fe219c5e494c7f95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/e2eaa60b558f26a4b0354e1bbb25636efaaad105", - "reference": "e2eaa60b558f26a4b0354e1bbb25636efaaad105", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95", + "reference": "95c812666f3e91db75385749fe219c5e494c7f95", "shasum": "" }, "require": { @@ -4650,7 +4612,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4687,7 +4649,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.3.0" + "source": "https://github.com/symfony/translation-contracts/tree/v2.4.0" }, "funding": [ { @@ -4703,20 +4665,20 @@ "type": "tidelift" } ], - "time": "2020-09-28T13:05:58+00:00" + "time": "2021-03-23T23:28:01+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6a81fec0628c468cf6d5c87a4d003725e040e223" + "reference": "27cb9f7cfa3853c736425c7233a8f68814b19636" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6a81fec0628c468cf6d5c87a4d003725e040e223", - "reference": "6a81fec0628c468cf6d5c87a4d003725e040e223", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/27cb9f7cfa3853c736425c7233a8f68814b19636", + "reference": "27cb9f7cfa3853c736425c7233a8f68814b19636", "shasum": "" }, "require": { @@ -4775,7 +4737,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.2.4" + "source": "https://github.com/symfony/var-dumper/tree/v5.2.7" }, "funding": [ { @@ -4791,7 +4753,7 @@ "type": "tidelift" } ], - "time": "2021-02-18T23:11:19+00:00" + "time": "2021-04-19T14:07:32+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -5002,30 +4964,35 @@ }, { "name": "webmozart/assert", - "version": "1.9.1", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", + "php": "^7.2 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" + "phpunit/phpunit": "^8.5.13" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -5049,24 +5016,24 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.9.1" + "source": "https://github.com/webmozarts/assert/tree/1.10.0" }, - "time": "2020-07-08T17:02:28+00:00" + "time": "2021-03-09T10:59:23+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.5.2", + "version": "v3.5.5", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "cae0a8d1cb89b0f0522f65e60465e16d738e069b" + "reference": "6420113d90bb746423fa70b9940e9e7c26ebc121" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/cae0a8d1cb89b0f0522f65e60465e16d738e069b", - "reference": "cae0a8d1cb89b0f0522f65e60465e16d738e069b", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/6420113d90bb746423fa70b9940e9e7c26ebc121", + "reference": "6420113d90bb746423fa70b9940e9e7c26ebc121", "shasum": "" }, "require": { @@ -5126,7 +5093,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.2" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.5.5" }, "funding": [ { @@ -5134,20 +5101,20 @@ "type": "github" } ], - "time": "2021-01-06T14:21:44+00:00" + "time": "2021-04-07T11:19:20+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.9.0", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "64a6b902583802c162cdccf7e76dc8619368bf1a" + "reference": "73b1012b927633a1b4cd623c2e6b1678e6faef08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/64a6b902583802c162cdccf7e76dc8619368bf1a", - "reference": "64a6b902583802c162cdccf7e76dc8619368bf1a", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/73b1012b927633a1b4cd623c2e6b1678e6faef08", + "reference": "73b1012b927633a1b4cd623c2e6b1678e6faef08", "shasum": "" }, "require": { @@ -5158,6 +5125,7 @@ "illuminate/console": "^8", "illuminate/filesystem": "^8", "illuminate/support": "^8", + "nikic/php-parser": "^4.7", "php": "^7.3 || ^8.0", "phpdocumentor/type-resolver": "^1.1.0" }, @@ -5172,6 +5140,9 @@ "spatie/phpunit-snapshot-assertions": "^3 || ^4", "vimeo/psalm": "^3.12" }, + "suggest": { + "illuminate/events": "Required for automatic helper generation (^6|^7|^8)." + }, "type": "library", "extra": { "branch-alias": { @@ -5212,7 +5183,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.9.0" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.10.0" }, "funding": [ { @@ -5220,7 +5191,7 @@ "type": "github" } ], - "time": "2020-12-29T10:11:05+00:00" + "time": "2021-04-09T06:17:55+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -5352,20 +5323,21 @@ }, { "name": "composer/composer", - "version": "2.0.11", + "version": "2.0.13", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9" + "reference": "986e8b86b7b570632ad0a905c3726c33dd4c0efb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9", - "reference": "a5a5632da0b1c2d6fa9a3b65f1f4e90d1f04abb9", + "url": "https://api.github.com/repos/composer/composer/zipball/986e8b86b7b570632ad0a905c3726c33dd4c0efb", + "reference": "986e8b86b7b570632ad0a905c3726c33dd4c0efb", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", + "composer/metadata-minifier": "^1.0", "composer/semver": "^3.0", "composer/spdx-licenses": "^1.2", "composer/xdebug-handler": "^1.1", @@ -5429,7 +5401,76 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.0.11" + "source": "https://github.com/composer/composer/tree/2.0.13" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-04-27T11:11:08+00:00" + }, + { + "name": "composer/metadata-minifier", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/metadata-minifier.git", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207", + "reference": "c549d23829536f0d0e984aaabbf02af91f443207", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2", + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\MetadataMinifier\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Small utility library that handles metadata minification and expansion.", + "keywords": [ + "composer", + "compression" + ], + "support": { + "issues": "https://github.com/composer/metadata-minifier/issues", + "source": "https://github.com/composer/metadata-minifier/tree/1.0.0" }, "funding": [ { @@ -5445,7 +5486,7 @@ "type": "tidelift" } ], - "time": "2021-02-24T13:57:23+00:00" + "time": "2021-04-07T13:37:33+00:00" }, { "name": "composer/package-versions-deprecated", @@ -5682,16 +5723,16 @@ }, { "name": "composer/xdebug-handler", - "version": "1.4.5", + "version": "1.4.6", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "f28d44c286812c714741478d968104c5e604a1d4" + "reference": "f27e06cd9675801df441b3656569b328e04aa37c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4", - "reference": "f28d44c286812c714741478d968104c5e604a1d4", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f27e06cd9675801df441b3656569b328e04aa37c", + "reference": "f27e06cd9675801df441b3656569b328e04aa37c", "shasum": "" }, "require": { @@ -5699,7 +5740,8 @@ "psr/log": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + "phpstan/phpstan": "^0.12.55", + "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "autoload": { @@ -5725,7 +5767,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/1.4.5" + "source": "https://github.com/composer/xdebug-handler/tree/1.4.6" }, "funding": [ { @@ -5741,44 +5783,43 @@ "type": "tidelift" } ], - "time": "2020-11-13T08:04:11+00:00" + "time": "2021-03-25T17:01:18+00:00" }, { "name": "doctrine/cache", - "version": "1.10.2", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "13e3381b25847283a91948d04640543941309727" + "reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/13e3381b25847283a91948d04640543941309727", - "reference": "13e3381b25847283a91948d04640543941309727", + "url": "https://api.github.com/repos/doctrine/cache/zipball/a9c1b59eba5a08ca2770a76eddb88922f504e8e0", + "reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0", "shasum": "" }, "require": { "php": "~7.1 || ^8.0" }, "conflict": { - "doctrine/common": ">2.2,<2.4" + "doctrine/common": ">2.2,<2.4", + "psr/cache": ">=3" }, "require-dev": { "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^8.0", "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "predis/predis": "~1.0", + "psr/cache": "^1.0 || ^2.0", + "symfony/cache": "^4.4 || ^5.2" }, "suggest": { "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" @@ -5825,7 +5866,7 @@ ], "support": { "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/1.10.x" + "source": "https://github.com/doctrine/cache/tree/1.11.0" }, "funding": [ { @@ -5841,37 +5882,39 @@ "type": "tidelift" } ], - "time": "2020-07-07T18:54:01+00:00" + "time": "2021-04-13T14:46:17+00:00" }, { "name": "doctrine/dbal", - "version": "3.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "ee6d1260d5cc20ec506455a585945d7bdb98662c" + "reference": "5ba62e7e40df119424866064faf2cef66cb5232a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/ee6d1260d5cc20ec506455a585945d7bdb98662c", - "reference": "ee6d1260d5cc20ec506455a585945d7bdb98662c", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/5ba62e7e40df119424866064faf2cef66cb5232a", + "reference": "5ba62e7e40df119424866064faf2cef66cb5232a", "shasum": "" }, "require": { "composer/package-versions-deprecated": "^1.11.99", "doctrine/cache": "^1.0", + "doctrine/deprecations": "^0.5.3", "doctrine/event-manager": "^1.0", "php": "^7.3 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.1", - "jetbrains/phpstorm-stubs": "^2019.1", - "phpstan/phpstan": "^0.12.40", + "doctrine/coding-standard": "8.2.0", + "jetbrains/phpstorm-stubs": "2020.2", + "phpstan/phpstan": "0.12.81", "phpstan/phpstan-strict-rules": "^0.12.2", - "phpunit/phpunit": "^9.4", - "psalm/plugin-phpunit": "^0.10.0", + "phpunit/phpunit": "9.5.0", + "psalm/plugin-phpunit": "0.13.0", + "squizlabs/php_codesniffer": "3.6.0", "symfony/console": "^2.0.5|^3.0|^4.0|^5.0", - "vimeo/psalm": "^3.17.2" + "vimeo/psalm": "4.6.4" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -5880,11 +5923,6 @@ "bin/doctrine-dbal" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\DBAL\\": "src" @@ -5936,7 +5974,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.0.0" + "source": "https://github.com/doctrine/dbal/tree/3.1.0" }, "funding": [ { @@ -5952,7 +5990,50 @@ "type": "tidelift" } ], - "time": "2020-11-15T18:20:41+00:00" + "time": "2021-04-19T17:51:23+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v0.5.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "9504165960a1f83cc1480e2be1dd0a0478561314" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/9504165960a1f83cc1480e2be1dd0a0478561314", + "reference": "9504165960a1f83cc1480e2be1dd0a0478561314", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0|^7.0|^8.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v0.5.3" + }, + "time": "2021-03-21T12:59:47+00:00" }, { "name": "doctrine/event-manager", @@ -6119,16 +6200,16 @@ }, { "name": "facade/flare-client-php", - "version": "1.4.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/facade/flare-client-php.git", - "reference": "ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546" + "reference": "69742118c037f34ee1ef86dc605be4a105d9e984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/flare-client-php/zipball/ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546", - "reference": "ef0f5bce23b30b32d98fd9bb49c6fa37b40eb546", + "url": "https://api.github.com/repos/facade/flare-client-php/zipball/69742118c037f34ee1ef86dc605be4a105d9e984", + "reference": "69742118c037f34ee1ef86dc605be4a105d9e984", "shasum": "" }, "require": { @@ -6172,7 +6253,7 @@ ], "support": { "issues": "https://github.com/facade/flare-client-php/issues", - "source": "https://github.com/facade/flare-client-php/tree/1.4.0" + "source": "https://github.com/facade/flare-client-php/tree/1.8.0" }, "funding": [ { @@ -6180,26 +6261,26 @@ "type": "github" } ], - "time": "2021-02-16T12:42:06+00:00" + "time": "2021-04-30T11:11:50+00:00" }, { "name": "facade/ignition", - "version": "2.5.14", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "17097f7a83e200d90d1cf9f4d1b35c1001513a47" + "reference": "e7db3b601ce742568b92648818ef903904d20164" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/17097f7a83e200d90d1cf9f4d1b35c1001513a47", - "reference": "17097f7a83e200d90d1cf9f4d1b35c1001513a47", + "url": "https://api.github.com/repos/facade/ignition/zipball/e7db3b601ce742568b92648818ef903904d20164", + "reference": "e7db3b601ce742568b92648818ef903904d20164", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "facade/flare-client-php": "^1.3.7", + "facade/flare-client-php": "^1.6", "facade/ignition-contracts": "^1.0.2", "filp/whoops": "^2.4", "illuminate/support": "^7.0|^8.0", @@ -6257,7 +6338,7 @@ "issues": "https://github.com/facade/ignition/issues", "source": "https://github.com/facade/ignition" }, - "time": "2021-03-04T08:48:01+00:00" + "time": "2021-05-05T06:45:12+00:00" }, { "name": "facade/ignition-contracts", @@ -6314,20 +6395,22 @@ }, { "name": "fakerphp/faker", - "version": "v1.13.0", + "version": "v1.14.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913" + "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ab3f5364d01f2c2c16113442fb987d26e4004913", - "reference": "ab3f5364d01f2c2c16113442fb987d26e4004913", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1", + "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.1 || ^8.0", + "psr/container": "^1.0", + "symfony/deprecation-contracts": "^2.2" }, "conflict": { "fzaninotto/faker": "*" @@ -6335,9 +6418,20 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.4.1", "ext-intl": "*", - "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.4.2" + "symfony/phpunit-bridge": "^4.4 || ^5.2" + }, + "suggest": { + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "v1.15-dev" + } + }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -6360,22 +6454,22 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.13.0" + "source": "https://github.com/FakerPHP/Faker/tree/v.1.14.1" }, - "time": "2020-12-18T16:50:48+00:00" + "time": "2021-03-30T06:27:33+00:00" }, { "name": "filp/whoops", - "version": "2.9.2", + "version": "2.12.1", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "df7933820090489623ce0be5e85c7e693638e536" + "reference": "c13c0be93cff50f88bbd70827d993026821914dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/df7933820090489623ce0be5e85c7e693638e536", - "reference": "df7933820090489623ce0be5e85c7e693638e536", + "url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd", + "reference": "c13c0be93cff50f88bbd70827d993026821914dd", "shasum": "" }, "require": { @@ -6425,7 +6519,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.9.2" + "source": "https://github.com/filp/whoops/tree/2.12.1" }, "funding": [ { @@ -6433,7 +6527,7 @@ "type": "github" } ], - "time": "2021-01-24T12:00:00+00:00" + "time": "2021-04-25T12:00:00+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -6558,16 +6652,16 @@ }, { "name": "laravel/breeze", - "version": "v1.1.3", + "version": "v1.1.6", "source": { "type": "git", "url": "https://github.com/laravel/breeze.git", - "reference": "cf91d78e154fd274273926d6773ed6750f7c2c2c" + "reference": "222889eecf49bb02ea91e2122c9ab9f8379c0c45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/breeze/zipball/cf91d78e154fd274273926d6773ed6750f7c2c2c", - "reference": "cf91d78e154fd274273926d6773ed6750f7c2c2c", + "url": "https://api.github.com/repos/laravel/breeze/zipball/222889eecf49bb02ea91e2122c9ab9f8379c0c45", + "reference": "222889eecf49bb02ea91e2122c9ab9f8379c0c45", "shasum": "" }, "require": { @@ -6610,20 +6704,20 @@ "issues": "https://github.com/laravel/breeze/issues", "source": "https://github.com/laravel/breeze" }, - "time": "2021-02-18T15:47:31+00:00" + "time": "2021-04-27T17:35:17+00:00" }, { "name": "laravel/sail", - "version": "v1.4.6", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "59ee7e2b2efeb644eabea719186db91d11666733" + "reference": "7f2d520f8c7d6fc0e5e4949c1363f6ddff0ff116" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/59ee7e2b2efeb644eabea719186db91d11666733", - "reference": "59ee7e2b2efeb644eabea719186db91d11666733", + "url": "https://api.github.com/repos/laravel/sail/zipball/7f2d520f8c7d6fc0e5e4949c1363f6ddff0ff116", + "reference": "7f2d520f8c7d6fc0e5e4949c1363f6ddff0ff116", "shasum": "" }, "require": { @@ -6670,7 +6764,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2021-03-03T15:22:44+00:00" + "time": "2021-04-20T16:17:55+00:00" }, { "name": "maximebf/debugbar", @@ -6869,16 +6963,16 @@ }, { "name": "nunomaduro/collision", - "version": "v5.3.0", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "aca63581f380f63a492b1e3114604e411e39133a" + "reference": "41b7e9999133d5082700d31a1d0977161df8322a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/aca63581f380f63a492b1e3114604e411e39133a", - "reference": "aca63581f380f63a492b1e3114604e411e39133a", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/41b7e9999133d5082700d31a1d0977161df8322a", + "reference": "41b7e9999133d5082700d31a1d0977161df8322a", "shasum": "" }, "require": { @@ -6953,7 +7047,7 @@ "type": "patreon" } ], - "time": "2021-01-25T15:34:13+00:00" + "time": "2021-04-09T13:38:32+00:00" }, { "name": "phar-io/manifest", @@ -7226,16 +7320,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.12.2", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "245710e971a030f42e08f4912863805570f23d39" + "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39", - "reference": "245710e971a030f42e08f4912863805570f23d39", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", + "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", "shasum": "" }, "require": { @@ -7287,22 +7381,22 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.12.2" + "source": "https://github.com/phpspec/prophecy/tree/1.13.0" }, - "time": "2020-12-19T10:15:11+00:00" + "time": "2021-03-17T13:42:18+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.5", + "version": "9.2.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" + "reference": "f6293e1b30a2354e8428e004689671b83871edde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", - "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", + "reference": "f6293e1b30a2354e8428e004689671b83871edde", "shasum": "" }, "require": { @@ -7358,7 +7452,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" }, "funding": [ { @@ -7366,7 +7460,7 @@ "type": "github" } ], - "time": "2020-11-28T06:44:49+00:00" + "time": "2021-03-28T07:26:59+00:00" }, { "name": "phpunit/php-file-iterator", @@ -7611,16 +7705,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.2", + "version": "9.5.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f661659747f2f87f9e72095bb207bceb0f151cb4" + "reference": "c73c6737305e779771147af66c96ca6a7ed8a741" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4", - "reference": "f661659747f2f87f9e72095bb207bceb0f151cb4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", + "reference": "c73c6737305e779771147af66c96ca6a7ed8a741", "shasum": "" }, "require": { @@ -7698,7 +7792,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" }, "funding": [ { @@ -7710,7 +7804,7 @@ "type": "github" } ], - "time": "2021-02-02T14:45:58+00:00" + "time": "2021-03-23T07:16:29+00:00" }, { "name": "react/promise", @@ -8839,16 +8933,16 @@ }, { "name": "symfony/debug", - "version": "v4.4.20", + "version": "v4.4.22", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16" + "reference": "45b2136377cca5f10af858968d6079a482bca473" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/157bbec4fd773bae53c5483c50951a5530a2cc16", - "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16", + "url": "https://api.github.com/repos/symfony/debug/zipball/45b2136377cca5f10af858968d6079a482bca473", + "reference": "45b2136377cca5f10af858968d6079a482bca473", "shasum": "" }, "require": { @@ -8888,7 +8982,7 @@ "description": "Provides tools to ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.20" + "source": "https://github.com/symfony/debug/tree/v4.4.22" }, "funding": [ { @@ -8904,20 +8998,20 @@ "type": "tidelift" } ], - "time": "2021-01-28T16:54:48+00:00" + "time": "2021-04-02T07:50:12+00:00" }, { "name": "symfony/filesystem", - "version": "v5.2.4", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "710d364200997a5afde34d9fe57bd52f3cc1e108" + "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/710d364200997a5afde34d9fe57bd52f3cc1e108", - "reference": "710d364200997a5afde34d9fe57bd52f3cc1e108", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/056e92acc21d977c37e6ea8e97374b2a6c8551b0", + "reference": "056e92acc21d977c37e6ea8e97374b2a6c8551b0", "shasum": "" }, "require": { @@ -8950,7 +9044,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.2.4" + "source": "https://github.com/symfony/filesystem/tree/v5.2.7" }, "funding": [ { @@ -8966,7 +9060,7 @@ "type": "tidelift" } ], - "time": "2021-02-12T10:38:38+00:00" + "time": "2021-04-01T10:42:13+00:00" }, { "name": "theseer/tokenizer", @@ -9025,7 +9119,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^7.3|^8.0" + "php": "^8.0" }, "platform-dev": [], "plugin-api-version": "2.0.0" diff --git a/resources/js/api/paginatedTableByAdminRequest.js b/resources/js/api/paginatedTableByAdminRequest.js index 16f4519..59a68e9 100644 --- a/resources/js/api/paginatedTableByAdminRequest.js +++ b/resources/js/api/paginatedTableByAdminRequest.js @@ -1,3 +1,5 @@ +import AfterPaginationRequestValidation from '../validators/AfterPaginationRequestValidation'; + export default async (table, columns, page, perPage, ordering = false) => { const body = { table, @@ -15,5 +17,13 @@ export default async (table, columns, page, perPage, ordering = false) => { }; } + const validator = new AfterPaginationRequestValidation(res.data); + + if (validator.validate() === false) { + return { + status: false, + }; + } + return res.data; }; diff --git a/resources/js/api/paginatedUserGamesRequest.js b/resources/js/api/paginatedUserGamesRequest.js index dcc5080..5ad239d 100644 --- a/resources/js/api/paginatedUserGamesRequest.js +++ b/resources/js/api/paginatedUserGamesRequest.js @@ -1,3 +1,5 @@ +import AfterPaginationRequestValidation from '../validators/AfterPaginationRequestValidation'; + export default async (userId, page) => { const res = await window.axios.post(`/api/paginated-user-games/${userId}`, { page }) .catch((e) => e.response); @@ -8,5 +10,13 @@ export default async (userId, page) => { }; } + const validator = new AfterPaginationRequestValidation(res.data); + + if (validator.validate() === false) { + return { + status: false, + }; + } + return res.data; }; diff --git a/resources/js/api/searchInTableRequest.js b/resources/js/api/searchInTableRequest.js new file mode 100644 index 0000000..82fefd6 --- /dev/null +++ b/resources/js/api/searchInTableRequest.js @@ -0,0 +1,31 @@ +import AfterPaginationRequestValidation from '../validators/AfterPaginationRequestValidation'; + +export default async (table, columns, page, perPage, needle, searchColumns, ordering = false) => { + const body = { + table, + columns, + page, + perPage, + needle, + searchColumns, + ordering, + }; + + const res = await window.axios.post(`/api/admin/table/${table}/search`, body).catch((e) => e.response); + + if (res.status !== 200 || res.data.status === false) { + return { + status: false, + }; + } + + const validator = new AfterPaginationRequestValidation(res.data); + + if (validator.validate() === false) { + return { + status: false, + }; + } + + return res.data; +}; diff --git a/resources/js/components/lists/UserGamesList.vue b/resources/js/components/lists/UserGamesList.vue index b17b70c..3aa16d3 100644 --- a/resources/js/components/lists/UserGamesList.vue +++ b/resources/js/components/lists/UserGamesList.vue @@ -122,7 +122,7 @@ export default { diff --git a/resources/js/components/tables/BaseTableSettingsPanel.vue b/resources/js/components/tables/BaseTableSettingsPanel.vue new file mode 100644 index 0000000..4f941a4 --- /dev/null +++ b/resources/js/components/tables/BaseTableSettingsPanel.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/resources/js/components/tables/cards/BaseTableSettingsCard.vue b/resources/js/components/tables/cards/BaseTableSettingsCard.vue new file mode 100644 index 0000000..21738c2 --- /dev/null +++ b/resources/js/components/tables/cards/BaseTableSettingsCard.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/resources/js/components/tables/cards/TableSearchSettingsCard.vue b/resources/js/components/tables/cards/TableSearchSettingsCard.vue new file mode 100644 index 0000000..9f3baa4 --- /dev/null +++ b/resources/js/components/tables/cards/TableSearchSettingsCard.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/resources/js/helpers/validationHelper.js b/resources/js/helpers/validationHelper.js new file mode 100644 index 0000000..e576589 --- /dev/null +++ b/resources/js/helpers/validationHelper.js @@ -0,0 +1,37 @@ +export default () => { + const validateColumns = (req, needleColumns) => { + try { + needleColumns.forEach((needleColumn) => { + if (req[needleColumn.name] === undefined) { + throw new Error(`${needleColumn.name} not exits`); + } + + const typesValidators = { + string: window.isString, + number: window.isNumber, + boolean: window.isBoolean, + object: (val) => typeof val === 'object', + array: Array.isArray, + }; + + if (typesValidators[needleColumn.type] === undefined) { + throw new Error(`${needleColumn.type} cannot be checked`); + } + + if (typesValidators[needleColumn.type](req[needleColumn.name]) === false) { + throw new Error(`${needleColumn.name} column got ${typeof req[needleColumn.name]} ` + + `but must be ${needleColumn.type}`); + } + }); + } catch (e) { + return { + status: false, + message: e.message, + }; + } + + return { status: true }; + }; + + return { validateColumns }; +}; diff --git a/resources/js/pages/admin/Admin.vue b/resources/js/pages/admin/Admin.vue index d5af847..c2739d7 100644 --- a/resources/js/pages/admin/Admin.vue +++ b/resources/js/pages/admin/Admin.vue @@ -51,7 +51,7 @@ export default { diff --git a/resources/js/components/tables/cards/BaseTableSettingsCard.vue b/resources/js/components/tables/cards/BaseTableSettingsCard.vue index 21738c2..0e637ac 100644 --- a/resources/js/components/tables/cards/BaseTableSettingsCard.vue +++ b/resources/js/components/tables/cards/BaseTableSettingsCard.vue @@ -1,23 +1,61 @@ From db1b24f3751456ac3b1dff9f815df84ae4eedf8b Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Wed, 12 May 2021 00:15:28 +0700 Subject: [PATCH 12/84] Refactoring: rename some route --- app/Http/Controllers/TablePaginationController.php | 5 +++-- app/Http/Requests/TablePaginationRequest.php | 1 - resources/js/api/paginatedTableByAdminRequest.js | 3 +-- resources/js/api/paginatedUserGamesRequest.js | 2 +- routes/web.php | 4 ++-- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/TablePaginationController.php b/app/Http/Controllers/TablePaginationController.php index 5f3bc0f..f48bd0c 100644 --- a/app/Http/Controllers/TablePaginationController.php +++ b/app/Http/Controllers/TablePaginationController.php @@ -12,9 +12,10 @@ class TablePaginationController extends Controller { /** * @param TablePaginationRequest $request + * @param string $table * @return JsonResponse */ - public function tablePagination(TablePaginationRequest $request): JsonResponse + public function tablePagination(TablePaginationRequest $request, string $table): JsonResponse { $columns = $request->columns; $orderBy = $request->ordering['by'] ?? 'ASC'; @@ -24,7 +25,7 @@ public function tablePagination(TablePaginationRequest $request): JsonResponse $columns[] = 'id'; } - $paginated = Db::table($request->table) + $paginated = Db::table($table) ->orderBy($orderingColumn, $orderBy) ->paginate($request->perPage, $columns, page: $request->page); diff --git a/app/Http/Requests/TablePaginationRequest.php b/app/Http/Requests/TablePaginationRequest.php index d75d7fa..7ec4647 100644 --- a/app/Http/Requests/TablePaginationRequest.php +++ b/app/Http/Requests/TablePaginationRequest.php @@ -55,7 +55,6 @@ public function withValidator($validator) public function rules() { return [ - 'table' => 'required|string', 'columns' => 'required|array', 'page' => 'required|integer', 'perPage' => 'required|integer', diff --git a/resources/js/api/paginatedTableByAdminRequest.js b/resources/js/api/paginatedTableByAdminRequest.js index 59a68e9..893e803 100644 --- a/resources/js/api/paginatedTableByAdminRequest.js +++ b/resources/js/api/paginatedTableByAdminRequest.js @@ -2,14 +2,13 @@ import AfterPaginationRequestValidation from '../validators/AfterPaginationReque export default async (table, columns, page, perPage, ordering = false) => { const body = { - table, columns, page, perPage, ordering, }; - const res = await window.axios.post('/api/admin/table-pagination', body).catch((e) => e.response); + const res = await window.axios.post(`/api/admin/table/${table}/pagination`, body).catch((e) => e.response); if (res.status !== 200 || res.data.status === false) { return { diff --git a/resources/js/api/paginatedUserGamesRequest.js b/resources/js/api/paginatedUserGamesRequest.js index 5ad239d..e8e1d30 100644 --- a/resources/js/api/paginatedUserGamesRequest.js +++ b/resources/js/api/paginatedUserGamesRequest.js @@ -1,7 +1,7 @@ import AfterPaginationRequestValidation from '../validators/AfterPaginationRequestValidation'; export default async (userId, page) => { - const res = await window.axios.post(`/api/paginated-user-games/${userId}`, { page }) + const res = await window.axios.post(`/api/paginate-user-games/${userId}`, { page }) .catch((e) => e.response); if (res.status !== 200 || res.data.status === false) { diff --git a/routes/web.php b/routes/web.php index 525946c..d78ecfc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -23,11 +23,11 @@ */ Route::prefix('/api')->group(function () { - Route::middleware('auth')->post('/paginated-user-games/{user}', PaginateUserGamesController::class); + Route::middleware('auth')->post('/paginate-user-games/{user}', PaginateUserGamesController::class); }); Route::middleware('auth')->prefix('/api/admin')->group(function () { - Route::post('/table-pagination', [TablePaginationController::class, 'tablePagination']); + Route::post('/table/{table}/pagination', [TablePaginationController::class, 'tablePagination']); Route::post('/table/{table}/search', [TablePaginationController::class, 'searchInTable']); From d069543733789aec9308c7d96817a9287f9220c7 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Wed, 12 May 2021 00:45:22 +0700 Subject: [PATCH 13/84] Refactoring: change height computing and rename some var --- .../js/components/admin/AdminBaseInfoCard.vue | 29 ++++++++++++------- .../js/components/chess/ChessGameReplay.vue | 2 +- .../tables/cards/BaseTableSettingsCard.vue | 10 +++---- .../js/pages/admin/view/AdminGamesView.vue | 1 - 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/resources/js/components/admin/AdminBaseInfoCard.vue b/resources/js/components/admin/AdminBaseInfoCard.vue index 1f36a55..036aa9f 100644 --- a/resources/js/components/admin/AdminBaseInfoCard.vue +++ b/resources/js/components/admin/AdminBaseInfoCard.vue @@ -1,15 +1,15 @@ diff --git a/resources/js/pages/Rules.vue b/resources/js/pages/Rules.vue new file mode 100644 index 0000000..7399739 --- /dev/null +++ b/resources/js/pages/Rules.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/resources/js/router/index.js b/resources/js/router/index.js index 52e05d8..c39446f 100644 --- a/resources/js/router/index.js +++ b/resources/js/router/index.js @@ -2,6 +2,7 @@ import { createWebHistory, createRouter } from 'vue-router'; import middlewares from './middleware'; const Home = () => import('~/pages/Home.vue'); +const Rules = () => import('~/pages/Rules.vue'); const Login = () => import('~/pages/Login.vue'); const Registration = () => import('~/pages/Registration.vue'); const Game = () => import('~/pages/Game.vue'); @@ -37,8 +38,8 @@ const routes = [ name: 'rating', }, { - path: '/rules', - component: Home, + path: '/rules/:rule?', + component: Rules, name: 'rules', }, { diff --git a/resources/sass/app.scss b/resources/sass/app.scss index 663be8f..aa26577 100644 --- a/resources/sass/app.scss +++ b/resources/sass/app.scss @@ -5,3 +5,7 @@ .material-icons { @apply select-none; } + +:root { + --header-height: 88px; +} diff --git a/resources/sass/ckeditor.scss b/resources/sass/ckeditor.scss new file mode 100644 index 0000000..f72e5c2 --- /dev/null +++ b/resources/sass/ckeditor.scss @@ -0,0 +1,225 @@ +:root { + --ck-color-mention-background: hsla(341, 100%, 30%, 0.1); + --ck-color-mention-text: hsl(341, 100%, 30%); + --ck-color-table-caption-background: hsl(0, 0%, 97%); + --ck-color-table-caption-text: hsl(0, 0%, 20%); + --ck-highlight-marker-blue: hsl(201, 97%, 72%); + --ck-highlight-marker-green: hsl(120, 93%, 68%); + --ck-highlight-marker-pink: hsl(345, 96%, 73%); + --ck-highlight-marker-yellow: hsl(60, 97%, 73%); + --ck-highlight-pen-green: hsl(112, 100%, 27%); + --ck-highlight-pen-red: hsl(0, 85%, 49%); + --ck-image-style-spacing: 1.5em; + --ck-todo-list-checkmark-size: 16px; +} + +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-yellow { + background-color: var(--ck-highlight-marker-yellow); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-green { + background-color: var(--ck-highlight-marker-green); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-pink { + background-color: var(--ck-highlight-marker-pink); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .marker-blue { + background-color: var(--ck-highlight-marker-blue); +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .pen-red { + color: var(--ck-highlight-pen-red); + background-color: transparent; +} +/* ckeditor5-highlight/theme/highlight.css */ +.ck-content .pen-green { + color: var(--ck-highlight-pen-green); + background-color: transparent; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-tiny { + font-size: .7em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-small { + font-size: .85em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-big { + font-size: 1.4em; +} +/* ckeditor5-font/theme/fontsize.css */ +.ck-content .text-huge { + font-size: 1.8em; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-side { + float: right; + margin-left: var(--ck-image-style-spacing); + max-width: 50%; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-left { + float: left; + margin-right: var(--ck-image-style-spacing); +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-center { + margin-left: auto; + margin-right: auto; +} +/* ckeditor5-image/theme/imagestyle.css */ +.ck-content .image-style-align-right { + float: right; + margin-left: var(--ck-image-style-spacing); +} +/* ckeditor5-image/theme/image.css */ +.ck-content .image { + display: table; + clear: both; + text-align: center; + margin: 1em auto; +} +/* ckeditor5-image/theme/image.css */ +.ck-content .image img { + display: block; + margin: 0 auto; + max-width: 100%; + min-width: 50px; +} +/* ckeditor5-image/theme/imagecaption.css */ +.ck-content .image > figcaption { + display: table-caption; + caption-side: bottom; + word-break: break-word; + color: hsl(0, 0%, 20%); + background-color: hsl(0, 0%, 97%); + padding: .6em; + font-size: .75em; + outline-offset: -1px; +} +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized { + max-width: 100%; + display: block; + box-sizing: border-box; +} +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized img { + width: 100%; +} +/* ckeditor5-image/theme/imageresize.css */ +.ck-content .image.image_resized > figcaption { + display: block; +} +/* ckeditor5-language/theme/language.css */ +.ck-content span[lang] { + font-style: italic; +} +/* ckeditor5-code-block/theme/codeblock.css */ +.ck-content pre { + padding: 1em; + color: hsl(0, 0%, 20.8%); + background: hsla(0, 0%, 78%, 0.3); + border: 1px solid hsl(0, 0%, 77%); + border-radius: 2px; + text-align: left; + direction: ltr; + tab-size: 4; + white-space: pre-wrap; + font-style: normal; + min-width: 200px; +} +/* ckeditor5-code-block/theme/codeblock.css */ +.ck-content pre code { + background: unset; + padding: 0; + border-radius: 0; +} +/* ckeditor5-horizontal-line/theme/horizontalline.css */ +.ck-content hr { + margin: 15px 0; + height: 4px; + background: hsl(0, 0%, 87%); + border: 0; +} +/* ckeditor5-html-embed/theme/htmlembed.css */ +.ck-content .raw-html-embed { + margin: 1em auto; + min-width: 15em; + font-style: normal; +} +/* ckeditor5-block-quote/theme/blockquote.css */ +.ck-content blockquote { + overflow: hidden; + padding-right: 1.5em; + padding-left: 1.5em; + margin-left: 0; + margin-right: 0; + font-style: italic; + border-left: solid 5px hsl(0, 0%, 80%); +} +/* ckeditor5-block-quote/theme/blockquote.css */ +.ck-content[dir="rtl"] blockquote { + border-left: 0; + border-right: solid 5px hsl(0, 0%, 80%); +} +/* ckeditor5-basic-styles/theme/code.css */ +.ck-content code { + background-color: hsla(0, 0%, 78%, 0.3); + padding: .15em; + border-radius: 2px; +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table { + margin: 1em auto; + display: table; +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + height: 100%; + border: 1px double hsl(0, 0%, 70%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table td, +.ck-content .table table th { + min-width: 2em; + padding: .4em; + border: 1px solid hsl(0, 0%, 75%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content .table table th { + font-weight: bold; + background: hsla(0, 0%, 0%, 5%); +} +/* ckeditor5-table/theme/table.css */ +.ck-content[dir="rtl"] .table th { + text-align: right; +} +/* ckeditor5-table/theme/table.css */ +.ck-content[dir="ltr"] .table th { + text-align: left; +} +/* ckeditor5-table/theme/tablecaption.css */ +.ck-content .table > figcaption { + display: table-caption; + caption-side: top; + word-break: break-word; + text-align: center; + color: var(--ck-color-table-caption-text); + background-color: var(--ck-color-table-caption-background); + padding: .6em; + font-size: .75em; + outline-offset: -1px; +} +/* ckeditor5-mention/theme/mention.css */ +.ck-content .mention { + background: var(--ck-color-mention-background); + color: var(--ck-color-mention-text); +} From 1f2128807ebc4df5efd93ce26c7995bab426fce1 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Tue, 29 Jun 2021 23:48:00 +0700 Subject: [PATCH 39/84] New: add games statistics request --- .../Controllers/Admin/AdminUserController.php | 6 +----- app/Http/Controllers/UserController.php | 20 +++++++++++++++++++ app/Models/User.php | 15 +++++++++++++- app/Policies/UserPolicy.php | 11 ++++++++++ routes/web.php | 2 ++ 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Admin/AdminUserController.php b/app/Http/Controllers/Admin/AdminUserController.php index 1fc70dd..d2b5088 100644 --- a/app/Http/Controllers/Admin/AdminUserController.php +++ b/app/Http/Controllers/Admin/AdminUserController.php @@ -23,11 +23,7 @@ public function show(Request $request, User $user): JsonResponse $aboutUser['blocked_at'] = $user->blocked_at; } - $info = array_merge($aboutUser, [ - 'count_games' => $user->games()->count(), - 'count_won' => $user->countGamesWon(), - 'not_count_games' => $user->games()->where('end_at', null)->count() - ]); + $info = array_merge($aboutUser, $user->getGamesStatistics()); } catch (\Exception $e) { return response()->json(['status' => false, 'message' => 'Something went wrong']); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 9f88542..7c3c7c2 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -5,6 +5,8 @@ use App\Http\Requests\Pagination\PaginateGamesForUserRequest; use App\Models\Game; use App\Models\User; +use Gate; +use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -30,4 +32,22 @@ public function paginateGames(PaginateGamesForUserRequest $request, User $user): { return response()->json(Game::paginateForUser($user->id, $request->page)); } + + /** + * Successful [ + * count_games: int + * count_won: int + * not_count_games: int + * ] + * + * @param User $user + * @return JsonResponse + * @throws AuthorizationException + */ + public function getGamesStatistics(User $user): JsonResponse + { + Gate::authorize('isOwner', [User::class, $user]); + + return response()->json(['statistics' => $user->getGamesStatistics()]); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 0c9b236..5270b80 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use JetBrains\PhpStorm\ArrayShape; /** * @mixin IdeHelperUser @@ -47,7 +48,7 @@ class User extends Authenticatable */ protected $casts = [ 'email_verified_at' => 'datetime', - 'blocked' => 'boolean', + 'blocked' => 'boolean', ]; /** @@ -106,4 +107,16 @@ public function getUserInfo(): array { return $this->only(['id', 'name', 'email', 'role', 'blocked']); } + + /** + * @return array ['count_games' => "int", 'count_won' => "int", 'not_count_games' => "int"] + */ + public function getGamesStatistics(): array + { + return [ + 'count_games' => $this->games()->count(), + 'count_won' => $this->countGamesWon(), + 'not_count_games' => $this->games()->where('end_at', null)->count() + ]; + } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 3438b86..dc880d7 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -21,4 +21,15 @@ public function seeGames(User $currentUser, User $gamesOwner): bool return $isRoleAuthorized || ($currentUser->id === $gamesOwner->id); } + + /** + * @param User $currentUser + * @param User $needleUser + * + * @return bool + */ + public function isOwner(User $currentUser, User $needleUser): bool + { + return $currentUser->id === $needleUser->id; + } } diff --git a/routes/web.php b/routes/web.php index 20f27df..e0d9438 100644 --- a/routes/web.php +++ b/routes/web.php @@ -34,6 +34,8 @@ Route::get('/users/{user}/games/paginated', [UserController::class, 'paginateGames']); + Route::get('/users/{user}/games/statistics', [UserController::class, 'getGamesStatistics']); + Route::post('/channels/{channel}/subscribed', [SubscribedOnChannelController::class, 'subscribed']); }); }); From 3d3535f07cc0578d7254305b466a72c4c986d3f4 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Wed, 30 Jun 2021 01:08:04 +0700 Subject: [PATCH 40/84] New: add statistics page --- .../users/getUserGamesStatisticsRequest.js | 41 +++++++ resources/js/components/App.vue | 1 + resources/js/components/ViewProfile.vue | 2 +- .../js/components/lists/UserGamesList.vue | 2 +- resources/js/helpers/gamesStatisticsHelper.js | 14 +++ resources/js/pages/Statistics.vue | 107 ++++++++++++++++++ resources/js/pages/ViewGame.vue | 38 +++++++ resources/js/router/index.js | 14 ++- .../js/validators/UserRequestValidator.js | 39 +++++++ resources/sass/app.scss | 1 + 10 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 resources/js/api/users/getUserGamesStatisticsRequest.js create mode 100644 resources/js/helpers/gamesStatisticsHelper.js create mode 100644 resources/js/pages/Statistics.vue create mode 100644 resources/js/pages/ViewGame.vue create mode 100644 resources/js/validators/UserRequestValidator.js diff --git a/resources/js/api/users/getUserGamesStatisticsRequest.js b/resources/js/api/users/getUserGamesStatisticsRequest.js new file mode 100644 index 0000000..60e6969 --- /dev/null +++ b/resources/js/api/users/getUserGamesStatisticsRequest.js @@ -0,0 +1,41 @@ +import UserRequestValidator from '../../validators/UserRequestValidator'; + +/** + * Data is validated + * + * Successful { + * statistic: [ + * count_games: int + * count_won: int + * not_count_games: int + * ] + * } + * + * Fail { + * status: false, + * message: String, + * } + * + * */ +export default async (userId) => { + const res = await window.axios.get(`/api/users/${userId}/games/statistics`) + .catch((e) => e.response); + + if (res.status !== 200 || res.data.status === false) { + return { + status: false, + message: res.data.message === undefined ? 'Something went wrong' : res.data.message, + }; + } + + const validator = new UserRequestValidator(res.data); + + if (validator.validateGamesStatistics() === false) { + return { + status: false, + message: 'Got invalid data', + }; + } + + return res.data; +}; diff --git a/resources/js/components/App.vue b/resources/js/components/App.vue index 230f3c3..265e2ac 100644 --- a/resources/js/components/App.vue +++ b/resources/js/components/App.vue @@ -22,5 +22,6 @@ export default { main { height: 1px; max-height: fit-content; + background-color: var(--background-color); } diff --git a/resources/js/components/ViewProfile.vue b/resources/js/components/ViewProfile.vue index d77bd79..3889cda 100644 --- a/resources/js/components/ViewProfile.vue +++ b/resources/js/components/ViewProfile.vue @@ -18,7 +18,7 @@ settings
  • - statistic + statistics
  • diff --git a/resources/js/components/lists/UserGamesList.vue b/resources/js/components/lists/UserGamesList.vue index ae70560..9a79b5f 100644 --- a/resources/js/components/lists/UserGamesList.vue +++ b/resources/js/components/lists/UserGamesList.vue @@ -143,7 +143,7 @@ export default { } ul { - @apply space-y-9; + @apply text-xl space-y-9; li { @apply flex pb-1 justify-between border-b; diff --git a/resources/js/helpers/gamesStatisticsHelper.js b/resources/js/helpers/gamesStatisticsHelper.js new file mode 100644 index 0000000..b465620 --- /dev/null +++ b/resources/js/helpers/gamesStatisticsHelper.js @@ -0,0 +1,14 @@ +export default () => { + const getWinRateAndLoseGames = (countGames, countWon, notCountGames) => { + const loseGames = countGames - countWon - notCountGames; + + return { + loseGames, + winRate: (countWon / loseGames).toFixed(2), + }; + }; + + return { + getWinRateAndLoseGames, + }; +}; diff --git a/resources/js/pages/Statistics.vue b/resources/js/pages/Statistics.vue new file mode 100644 index 0000000..887a3d1 --- /dev/null +++ b/resources/js/pages/Statistics.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/resources/js/pages/ViewGame.vue b/resources/js/pages/ViewGame.vue new file mode 100644 index 0000000..bd74bf1 --- /dev/null +++ b/resources/js/pages/ViewGame.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/resources/js/router/index.js b/resources/js/router/index.js index c39446f..cbde879 100644 --- a/resources/js/router/index.js +++ b/resources/js/router/index.js @@ -9,6 +9,8 @@ const Game = () => import('~/pages/Game.vue'); const SearchGame = () => import('~/pages/SearchGame.vue'); const ForgotPassword = () => import('~/pages/ForgotPassword.vue'); const Settings = () => import('~/pages/Settings.vue'); +const Statistics = () => import('~/pages/Statistics.vue'); +const ViewGame = () => import('../pages/ViewGame'); const Admin = () => import('~/pages/admin/Admin.vue'); const AdminChessRules = () => import('~/pages/admin/AdminChessRules.vue'); const AdminChessRuleCategories = () => import('~/pages/admin/AdminChessRuleCategories.vue'); @@ -56,13 +58,21 @@ const routes = [ }, }, { - path: '/statistic', - component: Home, + path: '/statistics', + component: Statistics, name: 'statistic', meta: { auth: true, }, }, + { + path: '/view/games/:gameId', + component: ViewGame, + name: 'gameReplay', + meta: { + auth: true, + }, + }, { path: '/login', component: Login, diff --git a/resources/js/validators/UserRequestValidator.js b/resources/js/validators/UserRequestValidator.js new file mode 100644 index 0000000..64f636d --- /dev/null +++ b/resources/js/validators/UserRequestValidator.js @@ -0,0 +1,39 @@ +import validationHelper from '../helpers/validationHelper'; + +export default class UserRequestValidator { + constructor(data) { + this.data = data; + } + + validateGamesStatistics() { + const { validateColumns } = validationHelper(); + + const { statistics } = this.data; + + try { + if (window.isObject(statistics) === false) { + throw new Error('Statistics field not required or not array'); + } + + validateColumns(statistics, [ + { + name: 'count_games', + type: Number, + }, + { + name: 'count_won', + type: Number, + }, + { + name: 'not_count_games', + type: Number, + }, + ]); + } catch (e) { + console.log(e.message); + return false; + } + + return true; + } +} diff --git a/resources/sass/app.scss b/resources/sass/app.scss index aa26577..dec9d0d 100644 --- a/resources/sass/app.scss +++ b/resources/sass/app.scss @@ -8,4 +8,5 @@ :root { --header-height: 88px; + --background-color: #f5f5f5; } From 2373b283f4ceca2ee95fb438cbccac06b08a43fe Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Wed, 30 Jun 2021 02:46:06 +0700 Subject: [PATCH 41/84] New: add get game info route --- .../Controllers/Admin/AdminGameController.php | 49 -------------- .../Admin/AdminGamesController.php | 65 +++++++++++++++++++ .../Controllers/Admin/AdminUserController.php | 39 +++++------ app/Http/Controllers/GamesController.php | 62 ++++++++++++++++++ app/Http/Controllers/Traits/GameInfo.php | 57 ++++++++++++++++ app/Models/User.php | 5 +- app/Policies/GamePolicy.php | 23 +++++++ app/Services/GameService.php | 16 +++++ routes/admin/admin.php | 4 +- routes/web.php | 4 ++ 10 files changed, 249 insertions(+), 75 deletions(-) delete mode 100644 app/Http/Controllers/Admin/AdminGameController.php create mode 100644 app/Http/Controllers/Admin/AdminGamesController.php create mode 100644 app/Http/Controllers/GamesController.php create mode 100644 app/Http/Controllers/Traits/GameInfo.php create mode 100644 app/Policies/GamePolicy.php diff --git a/app/Http/Controllers/Admin/AdminGameController.php b/app/Http/Controllers/Admin/AdminGameController.php deleted file mode 100644 index 972a85c..0000000 --- a/app/Http/Controllers/Admin/AdminGameController.php +++ /dev/null @@ -1,49 +0,0 @@ -moves()->get(['from', 'to', 'type'])->toArray(); - $gameInfo = $game->only(['id', 'token', 'start_at', 'end_at', 'winner_color']); - $info = [ - 'status' => true, - 'game' => $gameInfo, - 'users' => $this->getUsersInfo($game), - 'moves' => $moves, - ]; - - } catch (\Exception $e) { - return response()->json(['status' => false, 'message' => 'Something went wrong']); - } - - return response()->json($info); - } - - /** - * @param Game $game - * @return array - */ - private function getUsersInfo(Game $game): array - { - $users = $game->users()->withPivot(['color'])->get(); - - /** @var User $user */ - foreach ($users as $user) { - $info[$user->pivot->color] = array_merge($user->getUserInfo(), - ['count_games' => $user->countEndedGames(), 'count_won' => $user->countGamesWon()]); - } - - return $info ?? []; - } -} diff --git a/app/Http/Controllers/Admin/AdminGamesController.php b/app/Http/Controllers/Admin/AdminGamesController.php new file mode 100644 index 0000000..235d3aa --- /dev/null +++ b/app/Http/Controllers/Admin/AdminGamesController.php @@ -0,0 +1,65 @@ + true], + $this->getGameInfo($game), + ); + + return response()->json($info); + } +} diff --git a/app/Http/Controllers/Admin/AdminUserController.php b/app/Http/Controllers/Admin/AdminUserController.php index d2b5088..c90dce8 100644 --- a/app/Http/Controllers/Admin/AdminUserController.php +++ b/app/Http/Controllers/Admin/AdminUserController.php @@ -14,43 +14,38 @@ class AdminUserController extends Controller * @param User $user * @return JsonResponse */ - public function show(Request $request, User $user): JsonResponse + public function show(User $user): JsonResponse { - try { - $aboutUser = $user->only(['id', 'name', 'email', 'blocked', 'created_at', 'updated_at']); + $aboutUser = $user->only(['id', 'name', 'email', 'blocked', 'created_at', 'updated_at']); - if ($aboutUser['blocked'] === true) { - $aboutUser['blocked_at'] = $user->blocked_at; - } - - $info = array_merge($aboutUser, $user->getGamesStatistics()); - - } catch (\Exception $e) { - return response()->json(['status' => false, 'message' => 'Something went wrong']); + if ($aboutUser['blocked'] === true) { + $aboutUser['blocked_at'] = $user->blocked_at; } + $info = array_merge($aboutUser, $user->getGamesStatistics()); + return response()->json($info); } - public function block(Request $request, User $user): JsonResponse + public function block(User $user): JsonResponse { $status = $user->update([ - 'blocked' => true, - 'blocked_at' => date('Y-m-d H:i:s'), - ]); + 'blocked' => true, + 'blocked_at' => date('Y-m-d H:i:s'), + ]); return response()->json([ - 'status' => $status, - 'blocked_at' => $user->blocked_at, - ]); + 'status' => $status, + 'blocked_at' => $user->blocked_at, + ]); } - public function unblock(Request $request, User $user): JsonResponse + public function unblock(User $user): JsonResponse { $status = $user->update([ - 'blocked' => false, - 'blocked_at' => null, - ]); + 'blocked' => false, + 'blocked_at' => null, + ]); return response()->json(['status' => $status]); } diff --git a/app/Http/Controllers/GamesController.php b/app/Http/Controllers/GamesController.php new file mode 100644 index 0000000..22a823d --- /dev/null +++ b/app/Http/Controllers/GamesController.php @@ -0,0 +1,62 @@ +json($this->getGameInfo($game)); + } + + /** + * @return array + */ + protected function getColumnsForUsersInfo(): array + { + return ['name', 'blocked']; + } +} diff --git a/app/Http/Controllers/Traits/GameInfo.php b/app/Http/Controllers/Traits/GameInfo.php new file mode 100644 index 0000000..02e090c --- /dev/null +++ b/app/Http/Controllers/Traits/GameInfo.php @@ -0,0 +1,57 @@ + array, 'moves' => array, 'users' => array] + */ + public function getGameInfo(Game $game): array + { + $gameService = new GameService($game); + $gameInfo = $gameService->getGameInfo(); + + return array_merge( + ['users' => $this->getUsersInfo($game)], + $gameInfo + ); + } + + /** + * @param Game $game + * @return array + */ + protected function getUsersInfo(Game $game): array + { + $columns = $this->getColumnsForUsersInfo(); + $users = $game->users()->withPivot(['color'])->get(); + + /** @var User $user */ + foreach ($users as $user) { + $info[$user->pivot->color] = array_merge( + $user->getUserInfo($columns), + [ + 'count_games' => $user->countEndedGames(), + 'count_won' => $user->countGamesWon() + ] + ); + } + + return $info ?? []; + } + + /** + * @return string[] + */ + protected function getColumnsForUsersInfo(): array + { + return ['id', 'name', 'email', 'role', 'blocked']; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 5270b80..a32219a 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -101,11 +101,12 @@ public function countGamesWon(): int } /** + * @param array $only * @return array */ - public function getUserInfo(): array + public function getUserInfo(array $only = ['id', 'name', 'email', 'role', 'blocked']): array { - return $this->only(['id', 'name', 'email', 'role', 'blocked']); + return $this->only($only); } /** diff --git a/app/Policies/GamePolicy.php b/app/Policies/GamePolicy.php new file mode 100644 index 0000000..7e77cd4 --- /dev/null +++ b/app/Policies/GamePolicy.php @@ -0,0 +1,23 @@ +users->find(['id' => $user->id])?->isNotEmpty() ?? false; + } +} diff --git a/app/Services/GameService.php b/app/Services/GameService.php index edbb903..da4287c 100644 --- a/app/Services/GameService.php +++ b/app/Services/GameService.php @@ -10,9 +10,25 @@ use App\Models\GameMove; use App\Models\User; use App\Websockets\IWebsocketManager; +use JetBrains\PhpStorm\ArrayShape; class GameService { + public function __construct(protected Game $game) + { + } + + /** + * @return array ['moves' => "array", 'game' => "array"] + */ + public function getGameInfo(): array + { + return [ + 'moves' => $this->game->moves()->get(['from', 'to', 'type'])->toArray(), + 'game' => $this->game->only(['id', 'token', 'start_at', 'end_at', 'winner_color']), + ]; + } + /** * @param Game $game * @param User $user diff --git a/routes/admin/admin.php b/routes/admin/admin.php index 258762c..8a85952 100644 --- a/routes/admin/admin.php +++ b/routes/admin/admin.php @@ -1,6 +1,6 @@ prefix('/api/admin')->group(function () { @@ -8,7 +8,7 @@ require __DIR__ . '/manage_users.php'; - Route::get('/games/{game}', [AdminGameController::class, 'show']) + Route::get('/games/{game}', [AdminGamesController::class, 'showGameInfo']) ->middleware('roles:admin,moderator,support'); Route::post('/images/ckeditor', [ImagesController::class, 'uploadFromCkeditor']) diff --git a/routes/web.php b/routes/web.php index e0d9438..a513159 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,7 @@ Date: Thu, 1 Jul 2021 02:21:45 +0700 Subject: [PATCH 42/84] Refactoring: replay pages --- resources/js/api/game/getGameInfoRequest.js | 45 ++++++ resources/js/app.js | 10 ++ .../classes/viewGame/AbstractViewGameInfo.js | 37 +++++ .../js/classes/viewGame/ViewGameGameInfo.js | 45 ++++++ .../js/classes/viewGame/ViewGameUserInfo.js | 48 ++++++ .../admin/AdminUserInfoCardInGames.vue | 80 ---------- .../BaseDropDownInfoCard.vue} | 31 ++-- .../cards/UserInfoCardInViewGames.vue | 58 ++++++++ .../js/components/chess/ChessBaseViewGame.vue | 110 ++++++++++++++ .../js/components/chess/ChessGameReplay.vue | 15 +- resources/js/helpers/viewGameHelper.js | 52 +++++++ resources/js/pages/ViewGame.vue | 67 ++++++++- .../js/pages/admin/view/AdminGamesView.vue | 140 ------------------ .../js/pages/admin/view/AdminViewGame.vue | 73 +++++++++ resources/js/router/index.js | 8 +- 15 files changed, 569 insertions(+), 250 deletions(-) create mode 100644 resources/js/api/game/getGameInfoRequest.js create mode 100644 resources/js/classes/viewGame/AbstractViewGameInfo.js create mode 100644 resources/js/classes/viewGame/ViewGameGameInfo.js create mode 100644 resources/js/classes/viewGame/ViewGameUserInfo.js delete mode 100644 resources/js/components/admin/AdminUserInfoCardInGames.vue rename resources/js/components/{admin/AdminBaseInfoCard.vue => cards/BaseDropDownInfoCard.vue} (71%) create mode 100644 resources/js/components/cards/UserInfoCardInViewGames.vue create mode 100644 resources/js/components/chess/ChessBaseViewGame.vue create mode 100644 resources/js/helpers/viewGameHelper.js delete mode 100644 resources/js/pages/admin/view/AdminGamesView.vue create mode 100644 resources/js/pages/admin/view/AdminViewGame.vue diff --git a/resources/js/api/game/getGameInfoRequest.js b/resources/js/api/game/getGameInfoRequest.js new file mode 100644 index 0000000..8d45df5 --- /dev/null +++ b/resources/js/api/game/getGameInfoRequest.js @@ -0,0 +1,45 @@ +/** + * Successful { + * game: { + * end_at: String + * id: int + * start_at: String + * token: String + * winner_color: String + * }, + * moves: [ + * { + * from: {x: int, y: int} + * to: {} + * } + * ], + * users: { + * black: { + * blocked: bool + * count_games: int + * count_won: int + * name: String + * } + * white: {} + * } + * } + * + * Fail { + * status: false + * message: String + * unauthorized: Boolean + * } + * */ +export default async (gameId) => { + const res = await window.axios.get(`/api/games/${gameId}`).catch((e) => e.response); + + if (res.data.status === false || res.status !== 200) { + return { + status: false, + message: res.data.message ?? 'Something went wrong', + unauthorized: res.status === 403 || res.status === 401, + }; + } + + return res.data; +}; diff --git a/resources/js/app.js b/resources/js/app.js index 29c225f..43ad166 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -8,6 +8,16 @@ require('./bootstrap'); const app = createApp(App); +app.config.errorHandler = (err, vm, info) => { + console.error( + `Message - ${err.message} + \nInfo - ${info} + \n\nStack - ${err.stack}`, + ); + + return true; +}; + store.dispatch('FETCH_USER') .finally(async () => { const serverTime = await window.axios.get('/api/time').then((res) => res.data.time); diff --git a/resources/js/classes/viewGame/AbstractViewGameInfo.js b/resources/js/classes/viewGame/AbstractViewGameInfo.js new file mode 100644 index 0000000..ec7a444 --- /dev/null +++ b/resources/js/classes/viewGame/AbstractViewGameInfo.js @@ -0,0 +1,37 @@ +import stringHelper from '../../helpers/stringHelper'; + +/** + * @constructor + * @param {Object} [info={}] + * + * @property {Object} formattedInfo + * @property {Object} info + * * */ +export default class AbstractViewGameInfo { + constructor(info = {}) { + this.info = info; + this.formattedInfo = {}; + } + + format() { + this.formatInfoFields(); + } + + formatInfoFields() { + const { upperFirstLetter } = stringHelper(); + + Object.getOwnPropertyNames(this.info).forEach((el) => { + const formattedKey = upperFirstLetter(el.replace(/_/g, ' ')); + + this.formattedInfo[formattedKey] = this.info[el]; + }); + } + + getFormattedInfo() { + return this.formattedInfo; + } + + notNullOrUndefined(value) { + return value !== undefined && value !== null; + } +} diff --git a/resources/js/classes/viewGame/ViewGameGameInfo.js b/resources/js/classes/viewGame/ViewGameGameInfo.js new file mode 100644 index 0000000..c8554d4 --- /dev/null +++ b/resources/js/classes/viewGame/ViewGameGameInfo.js @@ -0,0 +1,45 @@ +import AbstractViewGameInfo from './AbstractViewGameInfo'; + +/** + * @see ViewGameGameInfo + * + * @constructor + * @param {Object} [gameInfo={}] + * @param {Object} [usersInfo={}] + * @param {Number} [movesCount=0] + * */ +export default class ViewGameGameInfo extends AbstractViewGameInfo { + constructor(gameInfo = {}, usersInfo = {}, movesCount = 0) { + super(gameInfo); + + this.usersInfo = usersInfo; + this.movesCount = movesCount; + + this.format(); + } + + format() { + super.format(); + + if (this.notNullOrUndefined(this.info.end_at) && this.notNullOrUndefined(this.info.start_at)) { + const startAt = (new Date(this.info.start_at)).getTime() / 1000; + const endAt = (new Date(this.info.end_at)).getTime() / 1000; + + const minAndSec = (endAt - startAt) / 60; + this.formattedInfo.Duration = `${Math.floor(minAndSec)}m : ${(endAt - startAt) % 60}s`; + } + + if (this.winnerExists()) { + const userInfo = this.usersInfo[this.info.winner_color]; + + if (userInfo !== undefined && userInfo.name !== undefined) { + this.formattedInfo['Winner name'] = userInfo.name; + this.formattedInfo['Count move'] = this.movesCount; + } + } + } + + winnerExists() { + return this.notNullOrUndefined(this.info.winner_color); + } +} diff --git a/resources/js/classes/viewGame/ViewGameUserInfo.js b/resources/js/classes/viewGame/ViewGameUserInfo.js new file mode 100644 index 0000000..8d63f4b --- /dev/null +++ b/resources/js/classes/viewGame/ViewGameUserInfo.js @@ -0,0 +1,48 @@ +import AbstractViewGameInfo from './AbstractViewGameInfo'; + +/** + * @see ViewGameUserInfo + * + * @constructor + * @param {Object} [userInfo={}] + * @param {String} [ownColor=''] + * @param {String} [winnerColor=''] + * */ +export default class ViewGameUserInfo extends AbstractViewGameInfo { + constructor(userInfo = {}, ownColor = '', winnerColor = '') { + super(userInfo); + this.winnerColor = winnerColor; + this.ownColor = ownColor; + + this.format(); + } + + format() { + super.format(); + + if (this.info.count_won !== undefined && this.info.count_games !== undefined) { + const countLose = this.info.count_games - this.info.count_won; + this.formattedInfo['Count lose'] = countLose; + this.formattedInfo['Win rate'] = (this.info.count_won / countLose).toFixed(2); + } + + if (this.ownColor !== '') { + this.formattedInfo['Chessman color'] = this.ownColor; + } + } + + /** + * @return Number|String + * */ + getUserId() { + return (window.isNumber(this.info.id) === true || window.isString(this.info.id) === true) ? this.info.id : 0; + } + + getUserName() { + return this.info.name ?? ''; + } + + isWinner() { + return this.ownColor === this.winnerColor; + } +} diff --git a/resources/js/components/admin/AdminUserInfoCardInGames.vue b/resources/js/components/admin/AdminUserInfoCardInGames.vue deleted file mode 100644 index f41fa33..0000000 --- a/resources/js/components/admin/AdminUserInfoCardInGames.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - - - diff --git a/resources/js/components/admin/AdminBaseInfoCard.vue b/resources/js/components/cards/BaseDropDownInfoCard.vue similarity index 71% rename from resources/js/components/admin/AdminBaseInfoCard.vue rename to resources/js/components/cards/BaseDropDownInfoCard.vue index 359181d..b3060b5 100644 --- a/resources/js/components/admin/AdminBaseInfoCard.vue +++ b/resources/js/components/cards/BaseDropDownInfoCard.vue @@ -1,23 +1,23 @@ + + diff --git a/resources/js/pages/Rules.vue b/resources/js/pages/Rules.vue deleted file mode 100644 index d27e3d2..0000000 --- a/resources/js/pages/Rules.vue +++ /dev/null @@ -1,189 +0,0 @@ - - - - - diff --git a/resources/js/pages/admin/AdminChessRuleCategories.vue b/resources/js/pages/admin/AdminChessRuleNames.vue similarity index 56% rename from resources/js/pages/admin/AdminChessRuleCategories.vue rename to resources/js/pages/admin/AdminChessRuleNames.vue index 1c41e92..a315ac1 100644 --- a/resources/js/pages/admin/AdminChessRuleCategories.vue +++ b/resources/js/pages/admin/AdminChessRuleNames.vue @@ -1,19 +1,19 @@ @@ -22,24 +22,21 @@ import { computed, onBeforeMount, ref } from 'vue'; import BaseList from '../../components/lists/BaseList.vue'; import BaseInformerBlock from '../../components/informers/BaseInformerBlock.vue'; -import ruleCategoriesCreateRequest from '../../api/ruleCategories/ruleCategoriesCreateRequest'; -import ruleCategoriesDeleteRequest from '../../api/ruleCategories/ruleCategoriesDeleteRequest'; -import ruleCategoriesUpdateRequest from '../../api/ruleCategories/ruleCategoriesUpdateRequest'; -import ruleCategoriesAllRequest from '../../api/ruleCategories/ruleCategoriesAllRequest'; +import chessRuleNamesCreateRequest from '../../api/chessRuleNames/chessRuleNamesCreateRequest'; +import chessRuleNamesDeleteRequest from '../../api/chessRuleNames/chessRuleNamesDeleteRequest'; +import chessRuleNamesUpdateRequest from '../../api/chessRuleNames/chessRuleNamesUpdateRequest'; +import chessRuleNamesAllRequest from '../../api/chessRuleNames/chessRuleNamesAllRequest'; import baseInformerHelper from '../../helpers/baseInformerHelper'; -/** - * All category names are unique. - * */ export default { - name: 'AdminChessRuleCategories', + name: 'AdminChessRuleNames', setup() { - const categories = ref([]); - const categoryNames = computed(() => categories.value.map((category) => category.name)); + const ruleNamesInfo = ref([]); + const ruleNames = computed(() => ruleNamesInfo.value.map((ruleNameInfo) => ruleNameInfo.name)); let isAwaiting = false; - const findCategoryIndexByName = (name) => categories.value.findIndex((category) => category.name === name); + const findRuleNameInfoIndex = (name) => ruleNamesInfo.value.findIndex((ruleName) => ruleName.name === name); /* ---------- Informer ---------- */ const { @@ -66,16 +63,16 @@ export default { isAwaiting = false; }; - const storeCategoryHandler = async (newItem) => { + const storeRuleNameHandler = async (newItem) => { const handler = async () => { - const res = await ruleCategoriesCreateRequest(newItem); + const res = await chessRuleNamesCreateRequest(newItem); if (res.status === false) { setError(res.message); return; } - categories.value.push({ + ruleNamesInfo.value.push({ id: res.id, name: newItem, }); @@ -84,47 +81,47 @@ export default { await handlerRunner(handler); }; - const editCategoryHandler = async (index, newValue) => { + const editRuleNameHandler = async (index, newValue) => { const handler = async () => { - const categoryIndex = findCategoryIndexByName(categoryNames.value[index]); + const ruleNameIndex = findRuleNameInfoIndex(ruleNames.value[index]); - if (categoryIndex === -1) { + if (ruleNameIndex === -1) { setError('Something went wrong'); return; } - const { id } = categories.value[categoryIndex]; - const res = await ruleCategoriesUpdateRequest(id, newValue); + const { id } = ruleNamesInfo.value[ruleNameIndex]; + const res = await chessRuleNamesUpdateRequest(id, newValue); if (res.status === false) { setError(res.message); return; } - categories.value[categoryIndex].name = newValue; + ruleNamesInfo.value[ruleNameIndex].name = newValue; }; await handlerRunner(handler); }; - const deleteCategoryHandler = async (index) => { + const deleteRuleNameHandler = async (index) => { const handler = async () => { - const categoryIndex = findCategoryIndexByName(categoryNames.value[index]); + const ruleNameIndex = findRuleNameInfoIndex(ruleNames.value[index]); - if (categoryIndex === -1) { + if (ruleNameIndex === -1) { setError('Something went wrong'); return; } - const { id } = categories.value[categoryIndex]; - const res = await ruleCategoriesDeleteRequest(id); + const { id } = ruleNamesInfo.value[ruleNameIndex]; + const res = await chessRuleNamesDeleteRequest(id); if (res.status === false) { setError(res.message); return; } - categories.value.splice(categoryIndex, 1); + ruleNamesInfo.value.splice(ruleNameIndex, 1); }; await handlerRunner(handler); @@ -133,23 +130,23 @@ export default { /* ---------- Hooks ---------- */ onBeforeMount(async () => { - const res = await ruleCategoriesAllRequest(); + const res = await chessRuleNamesAllRequest(); if (res.status === false) { setError(res.message); return; } - categories.value = res.categories; + ruleNamesInfo.value = res.names_info; }); return { information, - categoryNames, + ruleNames, handlerRunner, - deleteCategoryHandler, - storeCategoryHandler, - editCategoryHandler, + deleteRuleNameHandler, + storeRuleNameHandler, + editRuleNameHandler, }; }, @@ -161,8 +158,8 @@ export default { diff --git a/resources/js/components/tables/cards/BaseTableSettingsCard.vue b/resources/js/components/tables/cards/BaseTableSettingsCard.vue index ecc343f..029c697 100644 --- a/resources/js/components/tables/cards/BaseTableSettingsCard.vue +++ b/resources/js/components/tables/cards/BaseTableSettingsCard.vue @@ -42,6 +42,9 @@ export default { min-width: 18rem; max-width: 24rem; + margin-right: 1rem; + margin-bottom: 1rem; + @apply px-5 py-5 bg-white shadow rounded-2xl; &__header { From c3513df1ea51c739846f5ed3edbe79c536552e44 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Thu, 8 Jul 2021 05:16:23 +0700 Subject: [PATCH 69/84] Update: change links to route name --- resources/js/components/HeaderBlock.vue | 33 ++++++++++++++++--------- resources/js/components/ViewProfile.vue | 20 +++++++++++---- resources/js/router/index.js | 8 +++--- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/resources/js/components/HeaderBlock.vue b/resources/js/components/HeaderBlock.vue index 309c86a..7c68bf4 100644 --- a/resources/js/components/HeaderBlock.vue +++ b/resources/js/components/HeaderBlock.vue @@ -14,17 +14,8 @@ @@ -71,6 +62,25 @@ export default { const router = useRouter(); const route = useRoute(); + const links = [ + { + name: 'main', + path: { name: 'home' }, + }, + { + name: 'rating', + path: { name: 'rating' }, + }, + { + name: 'rules', + path: { name: 'chessRules' }, + }, + { + name: 'support', + path: { name: 'support' }, + }, + ]; + // Store const store = useStore(); const user = computed(() => store.state.user); @@ -96,6 +106,7 @@ export default { }; return { + links, headerActive, user, logged, diff --git a/resources/js/components/ViewProfile.vue b/resources/js/components/ViewProfile.vue index 0885643..0ac234d 100644 --- a/resources/js/components/ViewProfile.vue +++ b/resources/js/components/ViewProfile.vue @@ -17,11 +17,8 @@
  • admin panel
  • -
  • - settings -
  • -
  • - statistics +
  • + {{ link.name }}
  • @@ -39,6 +36,7 @@ import { computed, onBeforeUnmount, onMounted, ref, } from 'vue'; import { useStore } from 'vuex'; +import { useRouter } from 'vue-router'; import router from '../router'; export default { @@ -53,6 +51,17 @@ export default { setup() { const store = useStore(); + const links = [ + { + name: 'settings', + path: { name: 'settings' }, + }, + { + name: 'statistics', + path: { name: 'statistics' }, + }, + ]; + const showAdminPanelLink = computed(() => store.state.user.role !== 'user'); const viewProfileStatus = ref(false); @@ -81,6 +90,7 @@ export default { }); return { + links, showAdminPanelLink, viewProfileStatus, switchViewProfileStatus, diff --git a/resources/js/router/index.js b/resources/js/router/index.js index f28c5c3..119e664 100644 --- a/resources/js/router/index.js +++ b/resources/js/router/index.js @@ -37,7 +37,7 @@ const routes = [ { path: '/', component: SearchGame, - name: 'searchGame', + name: 'home', }, { path: '/game/:token', @@ -55,7 +55,7 @@ const routes = [ { path: '/chess-rules/:rule?', component: ChessRules, - name: 'rules', + name: 'chessRules', }, { path: '/support', @@ -73,7 +73,7 @@ const routes = [ { path: '/statistics', component: Statistics, - name: 'statistic', + name: 'statistics', meta: { auth: true, }, @@ -98,7 +98,7 @@ const routes = [ { path: '/registration', component: Registration, - name: 'register', + name: 'registration', meta: { needHeader: false, guest: true, From edff5801aabe2ea247ccc1ad0f6ef2610b476589 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Thu, 8 Jul 2021 05:21:26 +0700 Subject: [PATCH 70/84] Fix: condition --- resources/js/pages/ChessRules.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/pages/ChessRules.vue b/resources/js/pages/ChessRules.vue index c8f56df..cc44a1c 100644 --- a/resources/js/pages/ChessRules.vue +++ b/resources/js/pages/ChessRules.vue @@ -223,7 +223,7 @@ export default { setLinks(ruleNamesInfo); - if (route.params.rule === '') return; + if (route.params.rule === '' || window.isString(route.params.rule) === false) return; const indexInLinks = ruleNamesInfo.findIndex((el) => el.slug === route.params.rule); From 9fec76e395eac5f8c689ed1c10ee364ab60bbea6 Mon Sep 17 00:00:00 2001 From: SadTomCat Date: Thu, 8 Jul 2021 06:51:55 +0700 Subject: [PATCH 71/84] Update: admin page --- .../js/components/admin/AdminSidePanel.vue | 65 ------------------- .../sidePanels/ColoredSidePanel.vue | 55 ++++++++++++++++ resources/js/pages/admin/Admin.vue | 58 +++++++++++++---- resources/js/router/index.js | 13 ++++ resources/js/typesDefinition.js | 34 ++++++++++ 5 files changed, 148 insertions(+), 77 deletions(-) delete mode 100644 resources/js/components/admin/AdminSidePanel.vue create mode 100644 resources/js/components/sidePanels/ColoredSidePanel.vue diff --git a/resources/js/components/admin/AdminSidePanel.vue b/resources/js/components/admin/AdminSidePanel.vue deleted file mode 100644 index 80c0a57..0000000 --- a/resources/js/components/admin/AdminSidePanel.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - - - diff --git a/resources/js/components/sidePanels/ColoredSidePanel.vue b/resources/js/components/sidePanels/ColoredSidePanel.vue new file mode 100644 index 0000000..9f5429d --- /dev/null +++ b/resources/js/components/sidePanels/ColoredSidePanel.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/resources/js/pages/admin/Admin.vue b/resources/js/pages/admin/Admin.vue index 5cf862b..e6e6852 100644 --- a/resources/js/pages/admin/Admin.vue +++ b/resources/js/pages/admin/Admin.vue @@ -1,6 +1,6 @@