From 5df3d85acd9e5975295828fc0ff912e14ba9975b Mon Sep 17 00:00:00 2001 From: Abdelrahman Saeed Elhassan Date: Tue, 19 Jul 2022 13:31:03 +0200 Subject: [PATCH] Adding ticket category crud and access permissions --- config/config.php | 11 +- resources/views/categories/create.blade.php | 33 ++++ resources/views/categories/index.blade.php | 64 +++++++ resources/views/categories/show.blade.php | 40 +++++ src/Controllers/CategoryControllable.php | 187 ++++++++++++++++++++ src/Controllers/TicketControllable.php | 67 ++++--- src/LaravelTicketsServiceProvider.php | 35 +++- 7 files changed, 397 insertions(+), 40 deletions(-) create mode 100644 resources/views/categories/create.blade.php create mode 100644 resources/views/categories/index.blade.php create mode 100644 resources/views/categories/show.blade.php create mode 100644 src/Controllers/CategoryControllable.php diff --git a/config/config.php b/config/config.php index 2369ce5..bf2b61e 100644 --- a/config/config.php +++ b/config/config.php @@ -40,7 +40,7 @@ /* * The default guard for authentication middleware */ - 'guard' => [ 'web', 'auth' ], + 'guard' => ['web', 'auth'], /* * Database tables name @@ -90,6 +90,13 @@ 'show-ticket' => 'can:tickets.show', 'message-ticket' => 'can:tickets.message', 'download-ticket' => 'can:tickets.download', + /** + * Categories + */ + 'create-category' => 'can:categories.create', + 'list-category' => 'can:categories.index', + 'show-category' => 'can:categories.show', + 'edit-category' => 'can:categories.edit', /* * For administrate tickets */ @@ -99,7 +106,7 @@ /* * The priorities */ - 'priorities' => [ 'LOW', 'MID', 'HIGH' ], + 'priorities' => ['LOW', 'MID', 'HIGH'], /* * Layout view */ diff --git a/resources/views/categories/create.blade.php b/resources/views/categories/create.blade.php new file mode 100644 index 0000000..10b2c53 --- /dev/null +++ b/resources/views/categories/create.blade.php @@ -0,0 +1,33 @@ +@extends(config('laravel-tickets.layouts')) + +@section('content') +
+
+ @lang('Add new category') +
+
+ @includeWhen(session()->has('message'), 'laravel-tickets::alert', ['type' => 'info', 'message' => + session()->get('message')]) +
+ @csrf +
+
+
+ + + @error('translation') +
{{ $message }}
+ @enderror +
+
+
+ + @lang('Cancel') +
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/categories/index.blade.php b/resources/views/categories/index.blade.php new file mode 100644 index 0000000..5727e75 --- /dev/null +++ b/resources/views/categories/index.blade.php @@ -0,0 +1,64 @@ +@extends(config('laravel-tickets.layouts')) + +@section('content') +
+
+
+
+ {{__('Categories')}} +
+
+ {{__('Add new')}} +
+
+
+ +
+ @includeWhen(session()->has('message'), 'laravel-tickets::alert', ['message' => session()->get('message'),'type' + => session()->get('type')]) +
+ + + + + + + + + + + + @foreach ($categories as $category) + + + + + + + + @endforeach + +
#{{__('Translation')}}@lang('Last Update')@lang('Created at'){{__('Action')}}
{{ $category->id }}{{ $category->translation }}{{ $category->updated_at ? $category->updated_at->format(config('laravel-tickets.datetime-format')) : trans('Not updated') }} + {{ $category->created_at ? $category->created_at->format(config('laravel-tickets.datetime-format')) : trans('Not created') }} + +
+ {{__('Show')}} + {{__('Edit')}} +
+ @csrf + @method('DELETE') + +
+
+
+
+ {!! $categories->links('pagination::bootstrap-4') !!} +
+
+ +
+
+@endsection \ No newline at end of file diff --git a/resources/views/categories/show.blade.php b/resources/views/categories/show.blade.php new file mode 100644 index 0000000..5eb7bce --- /dev/null +++ b/resources/views/categories/show.blade.php @@ -0,0 +1,40 @@ +@extends(config('laravel-tickets.layouts')) + +@section('content') +
+
+ @includeWhen(session()->has('message'), 'laravel-tickets::alert', ['type' => 'info', 'message' => + session()->get('message')]) +
+
+
+
+ @lang('Category overview') +
+
+
+ + @if ($action=='edit') + + @csrf + @endif +
+ + +
+
+ @if ($action=='edit') + + @endif + @lang('Back') + +
+
+
+
+
+ +@endsection \ No newline at end of file diff --git a/src/Controllers/CategoryControllable.php b/src/Controllers/CategoryControllable.php new file mode 100644 index 0000000..e07519c --- /dev/null +++ b/src/Controllers/CategoryControllable.php @@ -0,0 +1,187 @@ +middleware(config('laravel-tickets.permissions.list-category'))->only('index'); + $this->middleware(config('laravel-tickets.permissions.create-category'))->only('store', 'create'); + $this->middleware(config('laravel-tickets.permissions.show-category'))->only('show'); + $this->middleware(config('laravel-tickets.permissions.edit-category'))->only('edit'); + } + + /** + * Show every @return View|JsonResponse + * + * @link TicketCategory that the user has created + * + * If the accept header is json, the response will be a json response + * + */ + public function index() + { + $categories = TicketCategory::orderBy('id', 'desc')->paginate(10); + + return request()->wantsJson() ? + response()->json(compact('categories')) : + view( + 'laravel-tickets::categories.index', + compact('categories') + ); + } + + /** + * Show the create form + * + * @return View + */ + public function create() + { + return view('laravel-tickets::categories.create'); + } + + /** + * Creates a @param Request $request the request + * + * @return View|JsonResponse|RedirectResponse + * @link TicketCategory + * + */ + public function store(Request $request) + { + $rules = [ + 'translation' => ['required', 'string', 'max:191'], + ]; + $data = $request->validate($rules); + + if ($request->has('action') && $request->action == 'edit') { + $category = TicketCategory::where('id', $request->category_id)->update( + $request->only('translation') + ); + $message = trans('The category was successfully updated'); + } else { + $category = TicketCategory::create( + $request->only('translation') + ); + $message = trans('The category was successfully created'); + } + + return $request->wantsJson() ? + response()->json(compact('category')) : + redirect(route( + 'laravel-tickets.categories.index' + ))->with([ + 'message' => $message, + 'type' => 'success' + ]); + } + + /** + * Show detailed informations about the @param TicketCategory $category + * + * @return View|JsonResponse|RedirectResponse|void + * @link TicketCategory and the informations + * + */ + public function show(TicketCategory $category) + { + if ( + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { + return abort(403); + } + return \request()->wantsJson() ? + response()->json(compact( + 'category', + )) : + view( + 'laravel-tickets::categories.show', + compact( + 'category', + ) + )->with(['action' => 'show']); + } + /** + * edit detailed informations about the @param TicketCategory $category + * + * @return View|JsonResponse|RedirectResponse|void + * @link TicketCategory and the informations + * + */ + public function edit(TicketCategory $category) + { + if ( + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { + return abort(403); + } + return \request()->wantsJson() ? + response()->json(compact( + 'category', + )) : + view( + 'laravel-tickets::categories.show', + compact( + 'category', + ) + )->with(['action' => 'edit']); + } + + + public function destroy(TicketCategory $category) + { + if ( + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { + return abort(403); + } + + $category->delete(); + + $message = trans('The category was successfully deleted'); + + return \request()->wantsJson() ? + response()->json(compact( + 'message', + )) : + redirect()->route('laravel-tickets.categories.index') + ->with([ + 'message' => $message, + 'type' => 'success' + ]); + } +} diff --git a/src/Controllers/TicketControllable.php b/src/Controllers/TicketControllable.php index de4f37f..24da5a1 100644 --- a/src/Controllers/TicketControllable.php +++ b/src/Controllers/TicketControllable.php @@ -33,7 +33,7 @@ trait TicketControllable */ public function __construct() { - if (! config('laravel-tickets.permission')) { + if (!config('laravel-tickets.permission')) { return; } @@ -64,7 +64,8 @@ public function index() return request()->wantsJson() ? response()->json(compact('tickets')) : - view('laravel-tickets::tickets.index', + view( + 'laravel-tickets::tickets.index', compact('tickets') ); } @@ -89,10 +90,10 @@ public function create() public function store(Request $request) { $rules = [ - 'subject' => [ 'required', 'string', 'max:191' ], - 'priority' => [ 'required', Rule::in(config('laravel-tickets.priorities')) ], - 'message' => [ 'required', 'string' ], - 'files' => [ 'max:' . config('laravel-tickets.file.max-files') ], + 'subject' => ['required', 'string', 'max:191'], + 'priority' => ['required', Rule::in(config('laravel-tickets.priorities'))], + 'message' => ['required', 'string'], + 'files' => ['max:' . config('laravel-tickets.file.max-files')], 'files.*' => [ 'sometimes', 'file', @@ -101,13 +102,13 @@ public function store(Request $request) ], ]; if (config('laravel-tickets.category')) { - $rules[ 'category_id' ] = [ + $rules['category_id'] = [ 'required', Rule::exists(config('laravel-tickets.database.ticket-categories-table'), 'id'), ]; } if (config('laravel-tickets.references')) { - $rules[ 'reference' ] = [ + $rules['reference'] = [ config('laravel-tickets.references-nullable') ? 'nullable' : 'required', new TicketReferenceRule(), ]; @@ -127,11 +128,11 @@ public function store(Request $request) ); if (array_key_exists('reference', $data)) { - $reference = explode(',', $data[ 'reference' ]); + $reference = explode(',', $data['reference']); $ticketReference = new TicketReference(); $ticketReference->ticket()->associate($ticket); $ticketReference->referenceable()->associate( - resolve($reference[ 0 ])->find($reference[ 1 ]) + resolve($reference[0])->find($reference[1]) ); $ticketReference->save(); } @@ -141,7 +142,7 @@ public function store(Request $request) $ticketMessage->ticket()->associate($ticket); $ticketMessage->save(); - $this->handleFiles($data[ 'files' ] ?? [], $ticketMessage); + $this->handleFiles($data['files'] ?? [], $ticketMessage); $message = trans('The ticket was successfully created'); return $request->wantsJson() ? @@ -164,19 +165,22 @@ public function store(Request $request) */ public function show(Ticket $ticket) { - if (! $ticket->user()->get()->contains(\request()->user()) && - ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) { + if ( + !$ticket->user()->get()->contains(\request()->user()) && + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { return abort(403); } - $messages = $ticket->messages()->with([ 'user', 'uploads' ])->orderBy('created_at', 'desc'); + $messages = $ticket->messages()->with(['user', 'uploads'])->orderBy('created_at', 'desc'); return \request()->wantsJson() ? response()->json(compact( 'ticket', 'messages' )) : - view('laravel-tickets::tickets.show', + view( + 'laravel-tickets::tickets.show', compact( 'ticket', 'messages' @@ -195,12 +199,14 @@ public function show(Ticket $ticket) */ public function message(Request $request, Ticket $ticket) { - if (! $ticket->user()->get()->contains(\request()->user()) && - ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) { + if ( + !$ticket->user()->get()->contains(\request()->user()) && + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { return abort(403); } - if (! config('laravel-tickets.open-ticket-with-answer') && $ticket->state === 'CLOSED') { + if (!config('laravel-tickets.open-ticket-with-answer') && $ticket->state === 'CLOSED') { $message = trans('You cannot reply to a closed ticket'); return \request()->wantsJson() ? response()->json(compact('message')) : @@ -211,8 +217,8 @@ public function message(Request $request, Ticket $ticket) } $data = $request->validate([ - 'message' => [ 'required', 'string' ], - 'files' => [ 'max:' . config('laravel-tickets.file.max-files') ], + 'message' => ['required', 'string'], + 'files' => ['max:' . config('laravel-tickets.file.max-files')], 'files.*' => [ 'sometimes', 'file', @@ -226,9 +232,9 @@ public function message(Request $request, Ticket $ticket) $ticketMessage->ticket()->associate($ticket); $ticketMessage->save(); - $this->handleFiles($data[ 'files' ] ?? [], $ticketMessage); + $this->handleFiles($data['files'] ?? [], $ticketMessage); - $ticket->update([ 'state' => 'OPEN' ]); + $ticket->update(['state' => 'OPEN']); $message = trans('Your answer was sent successfully'); return $request->wantsJson() ? @@ -248,8 +254,10 @@ public function message(Request $request, Ticket $ticket) */ public function close(Ticket $ticket) { - if (! $ticket->user()->get()->contains(\request()->user()) && - ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) { + if ( + !$ticket->user()->get()->contains(\request()->user()) && + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { return abort(403); } if ($ticket->state === 'CLOSED') { @@ -261,7 +269,7 @@ public function close(Ticket $ticket) $message ); } - $ticket->update([ 'state' => 'CLOSED' ]); + $ticket->update(['state' => 'CLOSED']); $message = trans('The ticket was successfully closed'); return \request()->wantsJson() ? @@ -283,8 +291,10 @@ public function close(Ticket $ticket) */ public function download(Ticket $ticket, TicketUpload $ticketUpload) { - if (! $ticket->user()->get()->contains(\request()->user()) && - ! request()->user()->can(config('laravel-tickets.permissions.all-ticket'))) { + if ( + !$ticket->user()->get()->contains(\request()->user()) && + !request()->user()->can(config('laravel-tickets.permissions.all-ticket')) + ) { return abort(403); } @@ -306,7 +316,7 @@ public function download(Ticket $ticket, TicketUpload $ticketUpload) */ private function handleFiles($files, TicketMessage $ticketMessage) { - if (! config('laravel-tickets.files') || $files == null) { + if (!config('laravel-tickets.files') || $files == null) { return; } foreach ($files as $file) { @@ -319,5 +329,4 @@ private function handleFiles($files, TicketMessage $ticketMessage) ]); } } - } diff --git a/src/LaravelTicketsServiceProvider.php b/src/LaravelTicketsServiceProvider.php index 587c73c..4ec0948 100644 --- a/src/LaravelTicketsServiceProvider.php +++ b/src/LaravelTicketsServiceProvider.php @@ -55,7 +55,7 @@ public function boot() if (config('laravel-tickets.autoclose-days') > 0) { // Registering package commands. - $this->commands([ AutoCloseCommand::class ]); + $this->commands([AutoCloseCommand::class]); } } } @@ -77,25 +77,42 @@ public function register() public function routes() { // Macro routing - foreach ([ 'ticketSystem', 'tickets' ] as $routeMacroName) { + foreach (['ticketSystem', 'tickets'] as $routeMacroName) { Router::macro($routeMacroName, function ($controller) { Route::middleware(config('laravel-tickets.guard'))->name('laravel-tickets.')->group(function () use ($controller) { Route::prefix('/tickets')->group(function () use ($controller) { - Route::get('/', [ $controller, 'index' ])->name('tickets.index'); - Route::post('/', [ $controller, 'store' ])->name('tickets.store'); - Route::get('/create', [ $controller, 'create' ])->name('tickets.create'); + Route::get('/', [$controller, 'index'])->name('tickets.index'); + Route::post('/', [$controller, 'store'])->name('tickets.store'); + Route::get('/create', [$controller, 'create'])->name('tickets.create'); Route::prefix('{ticket}')->group(function () use ($controller) { - Route::get('/', [ $controller, 'show' ])->name('tickets.show'); - Route::post('/', [ $controller, 'close' ])->name('tickets.close'); - Route::post('/message', [ $controller, 'message' ])->name('tickets.message'); + Route::get('/', [$controller, 'show'])->name('tickets.show'); + Route::post('/', [$controller, 'close'])->name('tickets.close'); + Route::post('/message', [$controller, 'message'])->name('tickets.message'); Route::prefix('{ticketUpload}')->group(function () use ($controller) { - Route::get('/download', [ $controller, 'download' ])->name('tickets.download'); + Route::get('/download', [$controller, 'download'])->name('tickets.download'); }); }); }); }); }); } + /** + * Categories + */ + Router::macro('categories', function ($controller) { + Route::middleware(config('laravel-tickets.guard'))->name('laravel-tickets.')->group(function () use ($controller) { + Route::prefix('/categories')->group(function () use ($controller) { + Route::get('/', [$controller, 'index'])->name('categories.index'); + Route::post('/', [$controller, 'store'])->name('categories.store'); + Route::get('/create', [$controller, 'create'])->name('categories.create'); + Route::prefix('{category}')->group(function () use ($controller) { + Route::get('show', [$controller, 'show'])->name('categories.show'); + Route::get('edit', [$controller, 'edit'])->name('categories.edit'); + Route::delete('/', [$controller, 'destroy'])->name('categories.destroy'); + }); + }); + }); + }); } private function observers()