From bafe97391f1f84885c595c30c5d92fa464dda51c Mon Sep 17 00:00:00 2001 From: hobsRKM Date: Fri, 3 May 2024 17:55:34 +0000 Subject: [PATCH] Added edit/delete groups --- app/Http/Controllers/AdminController.php | 93 ++++++++++++++++++- app/Models/SaGroupsServers.php | 2 +- package-lock.json | 19 ++++ package.json | 1 + resources/css/app.css | 6 ++ resources/js/admin/admins.ts | 17 +++- resources/js/bans/bans.ts | 14 ++- resources/js/groups/edit.ts | 9 ++ resources/js/groups/list.ts | 5 + resources/js/mutes/mutes.ts | 13 ++- resources/views/admin/admins/create.blade.php | 3 + resources/views/admin/admins/edit.blade.php | 3 + resources/views/admin/groups/delete.blade.php | 37 ++++++++ resources/views/admin/groups/edit.blade.php | 74 +++++++++++++++ resources/views/admin/groups/list.blade.php | 1 + resources/views/partials/scripts.blade.php | 3 - routes/web.php | 6 +- vite.config.js | 3 +- 18 files changed, 296 insertions(+), 13 deletions(-) create mode 100644 resources/js/groups/edit.ts create mode 100644 resources/views/admin/groups/delete.blade.php diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 344d156..ab4fa18 100755 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -482,11 +482,14 @@ public function getGroupsList(Request $request) $formattedData = []; // Format each group record + $siteDir = env('VITE_SITE_DIR'); foreach ($groups as $group) { + $preLoadDefaultServerId = SaGroupsServers::where('group_id', $group->id)->first()->server_id; $formattedData[] = [ "id" => $group->id, - "name" => $group->name, + "name" => "{$group->name}", "flags" => $group->flags ?: "No flags assigned", + 'actions' => " ", ]; } @@ -504,4 +507,92 @@ public function groups() { return view('admin.groups.list'); } + + public function editGroup(Request $request, $group_id, $server_id) { + $groupServer = SaGroupsServers::with('groupsFlags') + ->where('server_id', $server_id) + ->where('group_id', $group_id) + ->get(); + + if ($groupServer->isEmpty()) { + return redirect()->route('groups.list')->with('error', 'Group does not exist for the selected server!. Add Group to the server!'); + } + $groupPermissions = $groupServer->pluck('groupsFlags.*.flag')->flatten()->toArray(); + $groupDetails = SaGroups::where('id', $group_id)->first(); + $permissions = Permission::all(); + $servers = SaServer::all(); + return view('admin.groups.edit', compact('servers', 'permissions', 'groupDetails', 'groupPermissions', 'server_id')); + } + + public function updateGroup(Request $request, $groupId) { + $validated = $request->validate([ + 'permissions' => 'required|array', + 'permissions.*' => 'exists:permissions,permission', + 'server_id' => 'exists:sa_servers,id', + 'immunity' => 'required', + 'name' => 'required', + ]); + + $submittedPermissions = $validated['permissions']; + $groupServer = SaGroupsServers::with('groupsFlags') + ->where('server_id',$validated['server_id']) + ->where('group_id', $groupId) + ->get(); + // Fetch current permissions from the database + $currentPermissions = $groupServer->pluck('groupsFlags.*.flag')->flatten()->toArray(); + // Determine permissions to add and delete + $permissionsToAdd = array_diff($submittedPermissions, $currentPermissions); + $permissionsToDelete = array_diff($currentPermissions, $submittedPermissions); + + $groupDetails = SaGroups::where('id', $groupId)->first(); + SaAdminsFlags::where('flag', $groupDetails->name)->update([ + 'flag' => $validated['name'] + ]); + $groupDetails->name = $validated['name']; + $groupDetails->save(); + foreach($permissionsToAdd as $permission){ + $groupFlags = new SaGroupsFlags(); + $groupFlags->group_id = $groupId; + $groupFlags->flag = $permission; + $groupFlags->save(); + } + SaGroupsFlags::whereIn('flag', $permissionsToDelete) + ->where('group_id',$groupId) + ->delete(); + + return redirect()->route('groups.list')->with('success', 'Group updated successfully.'); + } + + public function showGroupDeleteForm(Request $request, $groupId) { + $groupDetails = SaGroups::where('id', $groupId)->firstOrFail(); + $servers = SaServer::all(); + return view('admin.groups.delete', compact('groupDetails', 'servers')); + } + + public function deleteGroup(Request $request, $groupId) { + $validated = $request->validate([ + 'server_ids.*' => [ + 'required', + function ($attribute, $value, $fail) { + if ($value !== 'all' && !DB::table('sa_servers')->where('id', $value)->exists()) { + $fail($attribute.' is invalid.'); + } + }, + ], + ]); + + if(in_array('all', $validated['server_ids'])) { + SaGroups::where('id', $groupId)->delete(); + }else { + $validated['server_ids'] = SaServer::all()->pluck('id')->toArray(); + SaGroupsServers::where('group_id', $groupId) + ->whereIn('server_id', $validated['server_ids'])->delete(); + + SaAdmin::where('group_id', $groupId) + ->whereIn('server_id', $validated['server_ids'])->delete(); + } + + return redirect()->route('groups.list')->with('success', 'Group deleted successfully.'); + + } } diff --git a/app/Models/SaGroupsServers.php b/app/Models/SaGroupsServers.php index 81c81b0..891e09a 100644 --- a/app/Models/SaGroupsServers.php +++ b/app/Models/SaGroupsServers.php @@ -15,6 +15,6 @@ public function groups() { } public function groupsFlags() { - return $this->belongsTo(SaGroupsFlags::class, 'group_id', 'group_id'); + return $this->hasMany(SaGroupsFlags::class, 'group_id', 'group_id'); } } diff --git a/package-lock.json b/package-lock.json index e9b3193..8592974 100755 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "@types/datatables.net": "^1.10.28", "@types/jquery": "^3.5.29", "datatables.net-dt": "^2.0.2", + "datatables.net-fixedcolumns": "^5.0.0", "dotenv": "^16.4.5", "jquery": "^3.7.1", "ts-node": "^10.9.2" @@ -719,6 +720,15 @@ "jquery": ">=1.7" } }, + "node_modules/datatables.net-fixedcolumns": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-fixedcolumns/-/datatables.net-fixedcolumns-5.0.0.tgz", + "integrity": "sha512-7dTJrVDkZCicx9g//N3ufuEjvwrZpcmpjbkwrtC5LiQFCnuL/hMOiOb4CBcvTg5OiTU7VmtbBuQkeAJGs3QM5g==", + "dependencies": { + "datatables.net": ">=2.0.0", + "jquery": ">=1.7" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1533,6 +1543,15 @@ "jquery": ">=1.7" } }, + "datatables.net-fixedcolumns": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-fixedcolumns/-/datatables.net-fixedcolumns-5.0.0.tgz", + "integrity": "sha512-7dTJrVDkZCicx9g//N3ufuEjvwrZpcmpjbkwrtC5LiQFCnuL/hMOiOb4CBcvTg5OiTU7VmtbBuQkeAJGs3QM5g==", + "requires": { + "datatables.net": ">=2.0.0", + "jquery": ">=1.7" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", diff --git a/package.json b/package.json index d2df521..9a8f48c 100755 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/datatables.net": "^1.10.28", "@types/jquery": "^3.5.29", "datatables.net-dt": "^2.0.2", + "datatables.net-fixedcolumns": "^5.0.0", "dotenv": "^16.4.5", "jquery": "^3.7.1", "ts-node": "^10.9.2" diff --git a/resources/css/app.css b/resources/css/app.css index aa3f9b4..2bd7d76 100755 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -80,3 +80,9 @@ section { .select2 { width: 100% !important; } +.dt-scroll-body .dataTable thead { + display: none; +} +.action-container { + width: 100px; +} diff --git a/resources/js/admin/admins.ts b/resources/js/admin/admins.ts index 20d226e..db95cfa 100755 --- a/resources/js/admin/admins.ts +++ b/resources/js/admin/admins.ts @@ -1,7 +1,14 @@ import DataTable from 'datatables.net-dt'; import {formatDuration, calculateProgress} from '../utility/utility'; +import 'datatables.net-fixedcolumns' const dataTable = new DataTable("#adminsList", { + fixedColumns: { + start: 0, + end: 3, + }, + scrollX: true, + scrollY: "800px", "processing": true, "serverSide": true, "ajax": { @@ -24,12 +31,16 @@ const dataTable = new DataTable("#adminsList", { } }, {"data": "flags"}, - {"data": "hostnames", "width":"300px"}, + {"data": "hostnames", "width":"50px"}, {"data": "created"}, {"data": "ends"}, - {"data": "actions", "width": "200px"}, { - "data": "progress", "render": function (data, type, row, meta) { + "data": "actions", "width": "200px", "render": function (data, type, row, meta) { + return '
' + data + '
'; + } + }, + { + "data": "progress", "width":"100px", "render": function (data, type, row, meta) { const progress = calculateProgress(row.created, row.ends); return `
diff --git a/resources/js/bans/bans.ts b/resources/js/bans/bans.ts index 8fed43b..a16bec9 100755 --- a/resources/js/bans/bans.ts +++ b/resources/js/bans/bans.ts @@ -1,10 +1,16 @@ import DataTable from 'datatables.net-dt'; import {formatDuration, calculateProgress} from '../utility/utility'; - +import 'datatables.net-fixedcolumns' let dataTable = null; function loadBans() { dataTable = new DataTable("#bansList", { + fixedColumns: { + start: 0, + end: 3, + }, "processing": true, + scrollX: true, + scrollY: "800px", "serverSide": true, "ajax": { "url": bansListUrl, @@ -45,7 +51,11 @@ function loadBans() { }, {"data": "server_id"}, {"data": "status"}, - {"data": "action", "width": "200px"}, + { + "data": "action", "width": "200px", "render": function (data, type, row, meta) { + return '
' + data + '
'; + } + }, { "data": "duration", "render": function (data, type, row, meta) { const progress = calculateProgress(row.created, row.ends); diff --git a/resources/js/groups/edit.ts b/resources/js/groups/edit.ts new file mode 100644 index 0000000..ff39945 --- /dev/null +++ b/resources/js/groups/edit.ts @@ -0,0 +1,9 @@ +$('#server_id').on('change', function() { + let selectedOption: any = $(this).val(); + if (selectedOption) { + window.location.href = selectedOption; + } +}); +$(document).ready(function() { + $('#server_id').select2(); +}) diff --git a/resources/js/groups/list.ts b/resources/js/groups/list.ts index 5a546cc..7827b23 100644 --- a/resources/js/groups/list.ts +++ b/resources/js/groups/list.ts @@ -22,6 +22,11 @@ function loadGroups() { {"data": "id"}, {"data": "name"}, {"data": "flags"}, + { + "data": "actions", "width": "200px", "render": function (data, type, row, meta) { + return '
' + data + '
'; + } + }, ] }); } diff --git a/resources/js/mutes/mutes.ts b/resources/js/mutes/mutes.ts index bb2cf90..25cc2cb 100755 --- a/resources/js/mutes/mutes.ts +++ b/resources/js/mutes/mutes.ts @@ -1,11 +1,18 @@ import DataTable from 'datatables.net-dt'; import {formatDuration, calculateProgress} from '../utility/utility'; +import 'datatables.net-fixedcolumns' let dataTable = null; loadMutes(); function loadMutes() { dataTable = new DataTable("#mutesList", { + fixedColumns: { + start: 0, + end: 3, + }, + scrollX: true, + scrollY: "800px", "processing": true, "serverSide": true, "ajax": { @@ -47,7 +54,11 @@ function loadMutes() { }, {"data": "server_id"}, {"data": "status"}, - {"data": "action", "width": "200px"}, + { + "data": "action", "width": "200px", "render": function (data, type, row, meta) { + return '
' + data + '
'; + } + }, { "data": "duration", "render": function (data, type, row, meta) { const progress = calculateProgress(row.created, row.ends); diff --git a/resources/views/admin/admins/create.blade.php b/resources/views/admin/admins/create.blade.php index 493adbb..b1dbec7 100755 --- a/resources/views/admin/admins/create.blade.php +++ b/resources/views/admin/admins/create.blade.php @@ -25,6 +25,9 @@
Add New Admin
@csrf +
+ Note: Newly added admins will not receive their permissions on the server until a map change. Alternatively, you can execute css_reloadadmins for immediate effect. +
diff --git a/resources/views/admin/admins/edit.blade.php b/resources/views/admin/admins/edit.blade.php index a952cf0..15d23dc 100755 --- a/resources/views/admin/admins/edit.blade.php +++ b/resources/views/admin/admins/edit.blade.php @@ -28,6 +28,9 @@ @else @endif +
+ Note: Admins will not receive their permissions on the server until a map change. Alternatively, you can execute css_reloadadmins for immediate effect. +
@csrf
diff --git a/resources/views/admin/groups/delete.blade.php b/resources/views/admin/groups/delete.blade.php new file mode 100644 index 0000000..ee49e23 --- /dev/null +++ b/resources/views/admin/groups/delete.blade.php @@ -0,0 +1,37 @@ +@extends('layouts.app') + +@section('content') +
+
+
+
+
Delete Group
+
+
+ + @csrf +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+@endsection +@vite(['resources/js/admin/delete.ts']) diff --git a/resources/views/admin/groups/edit.blade.php b/resources/views/admin/groups/edit.blade.php index e69de29..e49952f 100644 --- a/resources/views/admin/groups/edit.blade.php +++ b/resources/views/admin/groups/edit.blade.php @@ -0,0 +1,74 @@ +@extends('layouts.app') +@section('content') + @if (session('success')) + + @endif + @if (session('error')) + + @endif + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif +
+
+
+
+
Edit Group
+
+ @csrf + @method('PUT') +
+ Note: Adding permissions to an existing group for new servers will append the new permissions to the existing set, applying for all associated servers. +
+
+ + +
+ +
+ + + +
+
+
+
+ @foreach($permissions as $permission) +
+ permission, $groupPermissions) ? 'checked' : '' }} class="form-check-input" type="checkbox" name="permissions[]" value="{{ $permission->permission }}" id="permission{{ $permission->id }}"> + +
+ @endforeach +
+
+
+ + +
+
+
+
+
+
+
+
+
+@endsection +@vite(['resources/js/groups/edit.ts']) diff --git a/resources/views/admin/groups/list.blade.php b/resources/views/admin/groups/list.blade.php index 2832cc6..66c890a 100644 --- a/resources/views/admin/groups/list.blade.php +++ b/resources/views/admin/groups/list.blade.php @@ -28,6 +28,7 @@ ID Group Flags + Action diff --git a/resources/views/partials/scripts.blade.php b/resources/views/partials/scripts.blade.php index bcd82e2..cdaac27 100755 --- a/resources/views/partials/scripts.blade.php +++ b/resources/views/partials/scripts.blade.php @@ -26,6 +26,3 @@ function getPlayerInfoUrl(serverId) { const playerActionUrl = '{!! env('VITE_SITE_DIR') !!}/players/action'; const groupsListUrl = '{!! env('VITE_SITE_DIR') !!}/list/groups'; - - - diff --git a/routes/web.php b/routes/web.php index 3e90f5d..d53ef34 100755 --- a/routes/web.php +++ b/routes/web.php @@ -39,7 +39,7 @@ Route::get('admins', [AdminController::class, 'admins'])->name('admins.list')->middleware('superadmin'); Route::post('admins', [AdminController::class, 'getAdminsList'])->middleware('superadmin'); Route::get('/groups', [AdminController::class, 'groups'])->name('groups.list')->middleware('superadmin'); - Route::post('/groups', [AdminController::class, 'getGroupsList'])->name('group.list')->middleware('superadmin'); + Route::post('/groups', [AdminController::class, 'getGroupsList'])->middleware('superadmin'); }); Route::prefix('admin')->group(function () { @@ -56,6 +56,10 @@ Route::prefix('group')->group(function () { Route::get('/create', [AdminController::class, 'createGroup'])->name('group.create')->middleware('superadmin'); Route::post('/store', [AdminController::class, 'storeGroup'])->name('group.store')->middleware('superadmin'); + Route::get('/edit/{group_id}/{server_id}', [AdminController::class, 'editGroup'])->name('group.edit')->middleware('superadmin'); + Route::put('/update/{id}', [AdminController::class, 'updateGroup'])->name('group.update')->middleware('superadmin'); + Route::get('/delete/{id}', [AdminController::class, 'showGroupDeleteForm'])->name('group.deleteForm')->middleware('superadmin'); + Route::post('/delete/{id}', [AdminController::class, 'deleteGroup'])->name('group.delete')->middleware('superadmin'); }); Route::prefix('players')->group(function () { Route::post('ban', [BansController::class, 'store'])->name('ban.store')->middleware('permission.ban'); diff --git a/vite.config.js b/vite.config.js index 2e29984..9edfc40 100755 --- a/vite.config.js +++ b/vite.config.js @@ -26,7 +26,8 @@ export default defineConfig({ 'resources/js/mdb.umd.min.js', 'resources/js/app.js', 'resources/js/groups/groups.ts', - 'resources/js/groups/list.ts' + 'resources/js/groups/list.ts', + 'resources/js/groups/edit.ts' ], refresh: true, }),