diff --git a/app/Events/TicketStatusChanged.php b/app/Events/TicketStatusChanged.php new file mode 100644 index 0000000..64a9e3a --- /dev/null +++ b/app/Events/TicketStatusChanged.php @@ -0,0 +1,25 @@ +ticket = $ticket; + $this->status = $status; + } +} diff --git a/app/Http/Controllers/TicketController.php b/app/Http/Controllers/TicketController.php index a83851f..cd19444 100644 --- a/app/Http/Controllers/TicketController.php +++ b/app/Http/Controllers/TicketController.php @@ -2,10 +2,14 @@ namespace App\Http\Controllers; +use App\Events\TicketStatusChanged; +use App\Mail\NewTicket; +use App\Models\Message; use App\Models\Project; use App\Models\Ticket; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Str; class TicketController extends Controller @@ -22,6 +26,15 @@ class TicketController extends Controller } } + public function show($id) { + $ticket = Ticket::find($id); + $status = $this->status; + $messages = $ticket->messages()->orderBy('created_at', 'DESC')->get(); + if (!$ticket) + abort(404); + return view('ticket.show', compact('ticket', 'status', 'messages')); + } + public function create() { $projects = Project::all(); return view('ticket.create', compact('projects')); @@ -36,19 +49,31 @@ class TicketController extends Controller $type = $request->type; $text = $request->text; $fileTicket = $request->file_ticket; + $fileTicket2 = $request->file_ticket2; $request->validate([ 'text' => 'required|string', ]); + $ticketId = Ticket::count() + 1; + if ($fileTicket !== null) { $request->validate([ 'file_ticket' => 'mimes:jpeg,jpg,png,pdf|max:2048', ]); $projectSlug = Str::slug(Project::find($projectId)->name); - $ticketId = Ticket::count() + 1; - $fileName = Str::slug($projectSlug) . "-" . ($type === 0 ? "bug" : "evo") . "-" . $ticketId . "." . $fileTicket->extension(); + $fileName = $projectSlug . "-" . ($type === "0" ? "bug" : "evo") . "-" . $ticketId . "." . $fileTicket->extension(); $fileTicket->move(public_path('fichiers/' . $projectSlug . "/" . $ticketId . "/"), $fileName); + $filePath = 'fichiers/' . $projectSlug . "/" . $ticketId . "/" . $fileName; + } + if ($fileTicket2 !== null) { + $request->validate([ + 'file_ticket' => 'mimes:jpeg,jpg,png,pdf|max:2048', + ]); + $projectSlug = Str::slug(Project::find($projectId)->name); + $fileName2 = $projectSlug . "-" . ($type === "0" ? "bug" : "evo") . "-" . $ticketId . "-2." . $fileTicket2->extension(); + $fileTicket2->move(public_path('fichiers/' . $projectSlug . "/" . $ticketId . "/"), $fileName2); + $filePath2 = 'fichiers/' . $projectSlug . "/" . $ticketId . "/" . $fileName2; } $ticket = new Ticket(); @@ -56,10 +81,14 @@ class TicketController extends Controller $ticket->type = $type; $ticket->text = $text; if ($fileTicket !== null) - $ticket->file = $fileName; + $ticket->file = $filePath; + if ($fileTicket2 !== null) + $ticket->file2 = $filePath2; $ticket->created_by = Auth::user()->id; $ticket->save(); + Mail::to(config('mail.MAIL_ADMIN'))->send(new NewTicket($ticket)); + return redirect()->route('home')->with('success', 'Ticket enregistré !'); } @@ -83,6 +112,7 @@ class TicketController extends Controller $type = $request->type; $text = $request->text; $fileTicket = $request->file_ticket; + $fileTicket2 = $request->file_ticket2; $request->validate([ 'text' => 'required|string', @@ -94,23 +124,88 @@ class TicketController extends Controller $request->validate([ 'file_ticket' => 'mimes:jpeg,jpg,png,pdf|max:2048', ]); - if (file_exists(public_path('fichiers/' . $ticket->project->name . '/' . $ticket->id . '/') . $ticket->file)) - unlink(public_path('fichiers/' . $ticket->project->name . '/' . $ticket->id . '/') . $ticket->file); + if ($ticket->file !== null && file_exists(public_path() . $ticket->file)) + unlink(public_path() . $ticket->file); $projectSlug = Str::slug(Project::find($projectId)->name); - $fileName = Str::slug($projectSlug) . "-" . ($type === 0 ? "bug" : "evo") . "-" . $ticket->id . "." . $fileTicket->extension(); + $fileName = $projectSlug . "-" . ($type === "0" ? "bug" : "evo") . "-" . $ticket->id . "." . $fileTicket->extension(); $fileTicket->move(public_path('fichiers/' . $projectSlug . "/" . $ticket->id . "/"), $fileName); + $filePath = 'fichiers/' . $projectSlug . "/" . $ticket->id . "/" . $fileName; + } + if ($fileTicket2 !== null) { + $request->validate([ + 'file_ticket2' => 'mimes:jpeg,jpg,png,pdf|max:2048', + ]); + if ($ticket->file2 !== null && file_exists(public_path() . $ticket->file2)) + unlink(public_path() . $ticket->file2); + $projectSlug = Str::slug(Project::find($projectId)->name); + $fileName2 = $projectSlug . "-" . ($type === "0" ? "bug" : "evo") . "-" . $ticket->id . "." . $fileTicket2->extension(); + $fileTicket2->move(public_path('fichiers/' . $projectSlug . "/" . $ticket->id . "/"), $fileName2); + $filePath2 = 'fichiers/' . $projectSlug . "/" . $ticket->id . "/" . $fileName2; } $ticket->project_id = $projectId; $ticket->type = $type; $ticket->text = $text; if ($fileTicket !== null) - $ticket->file = $fileName; - if (Auth::user()->role === 1) + $ticket->file = $filePath; + if ($fileTicket2 !== null) + $ticket->file2 = $filePath2; + if (Auth::user()->role === 1) { $ticket->status = $status; + event(new TicketStatusChanged($ticket, $this->status)); + } $ticket->save(); return redirect()->route('edit-ticket', $ticket->id)->with('success', 'Modifications enregistrées !'); } + + public function changeStatus(Request $request, $id) { + $ticket = Ticket::find($id); + if (!$ticket) + abort(404); + $ticket->status = $request->status; + $ticket->save(); + event(new TicketStatusChanged($ticket, $this->status)); + + return back(); + } + + public function createMessage(Request $request) { + $request->validate([ + 'message' => 'required', + ]); + + if ($request->file_message !== null) { + $request->validate([ + 'file_message' => 'mimes:jpeg,jpg,png,pdf|max:2048', + ]); + } + + $ticketId = $request->ticket_id; + $fileMessage = $request->file_message; + + $ticket = Ticket::find($ticketId); + + if (Auth::user()->role !== 1 && (!$ticket || Auth::user()->id !== $ticket->created_by)) + return back()->withErrors("Les données entrées sont incorrects."); + + $message = new Message(); + $message->ticket_id = $ticketId; + $message->user_id = Auth::user()->id; + $message->message = $request->message; + $message->save(); + + if ($request->file_message !== null) { + $projectSlug = Str::slug($ticket->project->name); + $fileMessage = $request->file_message; + $fileName = $projectSlug . '-ticket-' . $ticket->id . '-message-' . $message->id . '.' . $fileMessage->extension(); + $fileMessage->move(public_path('fichiers/' . $projectSlug . '/' . $ticket->id . '/'), $fileName); + $filePath = 'fichiers/' . $projectSlug . '/' . $ticket->id . '/' . $fileName; + $message->file = $filePath; + $message->save(); + } + + return back(); + } } diff --git a/app/Listeners/AddStatusMessages.php b/app/Listeners/AddStatusMessages.php new file mode 100644 index 0000000..1985c35 --- /dev/null +++ b/app/Listeners/AddStatusMessages.php @@ -0,0 +1,33 @@ +ticket_id = $event->ticket->id; + $message->message = "Le status est passé à : " . $event->status[$event->ticket->status]; + $message->save(); + } +} diff --git a/app/Mail/NewTicket.php b/app/Mail/NewTicket.php new file mode 100644 index 0000000..00934ff --- /dev/null +++ b/app/Mail/NewTicket.php @@ -0,0 +1,36 @@ +ticket = $ticket; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + $ticket = $this->ticket; + return $this->subject("[SupportWeb] Nouveau ticket n°" . $ticket->id)->view('mails.new-ticket', compact('ticket')); + } +} diff --git a/app/Models/Message.php b/app/Models/Message.php new file mode 100644 index 0000000..471f7b1 --- /dev/null +++ b/app/Models/Message.php @@ -0,0 +1,19 @@ +belongsTo('App\Models\Ticket', 'ticket_id'); + } + + public function user() { + return $this->belongsTo('App\Models\User', 'user_id'); + } +} diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php index ed3b08f..7d3bd3e 100644 --- a/app/Models/Ticket.php +++ b/app/Models/Ticket.php @@ -16,4 +16,8 @@ class Ticket extends Model public function user() { return $this->belongsTo('App\Models\User', 'created_by'); } + + public function messages() { + return $this->hasMany('App\Models\Message', 'ticket_id'); + } } diff --git a/app/Models/User.php b/app/Models/User.php index a44efaa..55dce5a 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -44,4 +44,8 @@ class User extends Authenticatable public function tickets() { return $this->hasMany("App\Models\Ticket", 'created_by'); } + + public function messages() { + return $this->hasMany('App\Models\Messages', 'user_id'); + } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index a9f10a6..e925966 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -18,6 +18,9 @@ class EventServiceProvider extends ServiceProvider Registered::class => [ SendEmailVerificationNotification::class, ], + 'App\Events\TicketStatusChanged' => [ + 'App\Listeners\AddStatusMessages', + ], ]; /** diff --git a/config/mail.php b/config/mail.php index 54299aa..6649a64 100644 --- a/config/mail.php +++ b/config/mail.php @@ -15,6 +15,9 @@ return [ 'default' => env('MAIL_MAILER', 'smtp'), + // Mail admin + 'MAIL_ADMIN' => env('MAIL_ADMIN'), + /* |-------------------------------------------------------------------------- | Mailer Configurations diff --git a/database/migrations/2020_11_25_104931_create_messages.php b/database/migrations/2020_11_25_104931_create_messages.php new file mode 100644 index 0000000..5756b1f --- /dev/null +++ b/database/migrations/2020_11_25_104931_create_messages.php @@ -0,0 +1,35 @@ +id(); + $table->foreignId('ticket_id')->constrained('tickets'); + $table->foreignId('user_id')->nullable()->constrained('users'); + $table->text('message'); + $table->string('file')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('messages'); + } +} diff --git a/database/migrations/2020_11_25_141438_alter_tickets.php b/database/migrations/2020_11_25_141438_alter_tickets.php new file mode 100644 index 0000000..626456b --- /dev/null +++ b/database/migrations/2020_11_25_141438_alter_tickets.php @@ -0,0 +1,32 @@ +string('file2')->nullable()->after('file'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('tickets', function(Blueprint $table) { + $table->dropColumn('file2'); + }); + } +} diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 06b5fd9..82710b1 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -3,7 +3,7 @@ @section('tickets', 'active') @section('content') -
+
@auth

Gestion des ticketsCréer un ticket

@@ -11,11 +11,12 @@ - + + @@ -23,10 +24,36 @@ @if (Auth::user()->project_id === $ticket->project->id || Auth::user()->role === 1) + + + + + + + + - - - - - -
# Projet TypeDescription FichierFichier 2 Date de création Créer par StatusContenu
+ {{ $ticket->id }} + {{ $ticket->project->name }} + @if ($ticket->type === 0) + Bug + @else + Évolution + @endif + + @if ($ticket->file !== null) + Fichier + @endif + + @if ($ticket->file2 !== null) + Fichier 2 + @endif + {{ Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i') }}{{ $ticket->user->name }}{{ $status[$ticket->status] }} {{-- Modal du ticket --}} @@ -43,12 +70,6 @@ - - {{ $ticket->project->name }} - @if ($ticket->type === 0) - Bug - @else - Évolution - @endif {{ \Illuminate\Support\Str::limit($ticket->text, 40, '...') }} - @if ($ticket->file !== null) - Fichier - @endif - {{ Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i') }}{{ $ticket->user->name }}{{ $status[$ticket->status] }} @if ($ticket->created_by === Auth::user()->id || Auth::user()->role === 1) Modifier diff --git a/resources/views/layout/app.blade.php b/resources/views/layout/app.blade.php index 563d89d..377f529 100644 --- a/resources/views/layout/app.blade.php +++ b/resources/views/layout/app.blade.php @@ -69,7 +69,9 @@ - @yield('content') +
+ @yield('content') +
diff --git a/resources/views/mails/new-ticket.blade.php b/resources/views/mails/new-ticket.blade.php new file mode 100644 index 0000000..574c352 --- /dev/null +++ b/resources/views/mails/new-ticket.blade.php @@ -0,0 +1,12 @@ +

Bonjour,

+

Un nouveau ticket (n°{{ $ticket->id }}) a été créer sur le support web :

+
    +
  • Projet : {{ $ticket->project->name }}
  • +
  • Type : {{ $ticket->type === 0 ? "Bug" : "Évolution" }}
  • +
  • Créer par : {{ $ticket->user->name }}
  • +
+

+ Description :
+ {!! nl2br(e($ticket->text)) !!} +

+

Lien vers le ticket : Ouvrir dans un nouvel onglet

diff --git a/resources/views/ticket/create.blade.php b/resources/views/ticket/create.blade.php index ddd9c94..34cccf7 100644 --- a/resources/views/ticket/create.blade.php +++ b/resources/views/ticket/create.blade.php @@ -52,6 +52,9 @@
+
+ +
diff --git a/resources/views/ticket/edit.blade.php b/resources/views/ticket/edit.blade.php index dff629c..363d823 100644 --- a/resources/views/ticket/edit.blade.php +++ b/resources/views/ticket/edit.blade.php @@ -70,7 +70,17 @@ @if ($ticket->file !== null)
- + +
+ @endif +
+ +
+ + @if ($ticket->file2 !== null) +
+
+
@endif
diff --git a/resources/views/ticket/show.blade.php b/resources/views/ticket/show.blade.php new file mode 100644 index 0000000..6588af7 --- /dev/null +++ b/resources/views/ticket/show.blade.php @@ -0,0 +1,122 @@ +@extends('layout.app') + +@section('content') +
+
+

+ ← + Ticket n°{{ $ticket->id }} : {{ $ticket->project->name }} - {{ $ticket->type === 0 ? "Bug" : "Évolution" }} + @if (Auth::user()->role !== 1) + {{ $status[$ticket->status] }} + @endif +

+ @if (Auth::user()->role === 1) +
+ @csrf + +
+ @endif +
+
+
+ @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif +

+ Suivi + @if (Auth::user()->id === $ticket->created_by || Auth::user()->role === 1) + + + {{-- Modal --}} + + {{-- Fin modal --}} + @endif +

+ @foreach ($messages as $message) + @if ($message->user_id === null) +
+ {!! nl2br(e($message->message)) !!} - Le {{ \Carbon\Carbon::parse($message->created_at)->format('d/m/Y à H:i')}} (Message système) +
+ @elseif ($message->user_id === Auth::user()->id) +
+ {!! nl2br(e($message->message)) !!}
+ @if ($message->file !== null) + Ouvrir la pièce jointe dans un nouvel onglet
+ @endif + Le {{ \Carbon\Carbon::parse($message->created_at)->format('d/m/Y à H:i')}} par {{ $message->user->name }} +
+ @else +
+ {!! nl2br(e($message->message)) !!}
+ @if ($message->file !== null) + Ouvrir la pièce jointe dans un nouvel onglet
+ @endif + Le {{ \Carbon\Carbon::parse($message->created_at)->format('d/m/Y à H:i')}} par {{ $message->user->name }} +
+ @endif + @endforeach +
+
+
+

Description

+

{!! nl2br(e($ticket->text)) !!}

+ Créer le {{ \Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i') }} +
+
+
+

Pièces jointes

+ +
+
+@endsection diff --git a/routes/web.php b/routes/web.php index 1c7bfb0..ac73c44 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,6 +26,9 @@ Route::middleware(['auth'])->group(function () { Route::put('/ticket/create', [TicketController::class, 'store'])->name('store-ticket'); Route::get('/ticket/{id}/edit', [TicketController::class, 'edit'])->name('edit-ticket'); Route::post('/ticket/{id}/edit', [TicketController::class, 'update'])->name('update-ticket'); + Route::get('/ticket/{id}', [TicketController::class, 'show'])->name('show-ticket'); + Route::post('/ticket/change-status/{id}', [TicketController::class, 'changeStatus'])->name('change-status-ticket'); + Route::put('/ticket/message/create', [TicketController::class, 'createMessage'])->name('create-message'); // Projets (admin) Route::middleware(['is-admin'])->group(function () { Route::get('/projects', [ProjectController::class, 'index'])->name('projects');