Ajout abonnement a un ticket pour recevoir un mail en cas de mis à jour du ticket (réponse/status)

This commit is contained in:
Romain Bonhomme 2020-11-26 15:48:35 +01:00
parent 598e8f27c8
commit 2482bf8413
12 changed files with 180 additions and 3 deletions

View file

@ -0,0 +1,25 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NotifySubscriptions
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $ticket, $corpsMaj;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($ticket, $corpsMaj)
{
$this->ticket = $ticket;
$this->corpsMaj = $corpsMaj;
}
}

View file

@ -2,11 +2,13 @@
namespace App\Http\Controllers;
use App\Events\NotifySubscriptions;
use App\Events\TicketStatusChanged;
use App\Mail\NewTicket;
use App\Models\Message;
use App\Models\Project;
use App\Models\Ticket;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
@ -30,9 +32,12 @@ class TicketController extends Controller
$ticket = Ticket::find($id);
$status = $this->status;
$messages = $ticket->messages()->orderBy('created_at', 'DESC')->get();
$isSubscribed = false;
if (!$ticket)
abort(404);
return view('ticket.show', compact('ticket', 'status', 'messages'));
if ($ticket->subscriptions()->where('user_id', Auth::user()->id)->count() !== 0)
$isSubscribed = true;
return view('ticket.show', compact('ticket', 'status', 'messages', 'isSubscribed'));
}
public function create() {
@ -164,6 +169,7 @@ class TicketController extends Controller
$ticket->status = $request->status;
$ticket->save();
event(new TicketStatusChanged($ticket, $this->status));
event(new NotifySubscriptions($ticket, "Le ticket à changé de status : " . $this->status[$ticket->status]));
return back();
}
@ -203,6 +209,13 @@ class TicketController extends Controller
$message->save();
}
event(new NotifySubscriptions($ticket, "Nouvelle réponse de " . $message->user->name . " :<br>" . $message->message));
return back();
}
public function subscribe(Request $request, $id) {
User::find(Auth::user()->id)->subscriptions()->toggle($id);
return back();
}
}

View file

@ -0,0 +1,37 @@
<?php
namespace App\Listeners;
use App\Events\NotifySubscriptions;
use App\Mail\TicketUpdate;
use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
class SendNotificationMail
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param NotifySubscriptions $event
* @return void
*/
public function handle(NotifySubscriptions $event)
{
foreach($event->ticket->subscriptions as $sub)
if ($sub->email !== Auth::user()->email)
Mail::to($sub->email)->send(new TicketUpdate($event->ticket, $event->corpsMaj));
}
}

38
app/Mail/TicketUpdate.php Normal file
View file

@ -0,0 +1,38 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class TicketUpdate extends Mailable
{
use Queueable, SerializesModels;
private $ticket, $corpsMaj;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($ticket, $corpsMaj)
{
$this->ticket = $ticket;
$this->corpsMaj = $corpsMaj;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$ticket = $this->ticket;
$corpsMaj = $this->corpsMaj;
return $this->subject("[SupportWeb] Le ticket n°" . $ticket->id . " à été mis à jour")->view('mails.ticket-update', compact('ticket', 'corpsMaj'));
}
}

View file

@ -20,4 +20,8 @@ class Ticket extends Model
public function messages() {
return $this->hasMany('App\Models\Message', 'ticket_id');
}
public function subscriptions() {
return $this->belongsToMany('App\Models\User', 'subscriptions');
}
}

View file

@ -48,4 +48,8 @@ class User extends Authenticatable
public function messages() {
return $this->hasMany('App\Models\Messages', 'user_id');
}
public function subscriptions() {
return $this->belongsToMany('App\Models\Ticket', 'subscriptions');
}
}

View file

@ -21,6 +21,9 @@ class EventServiceProvider extends ServiceProvider
'App\Events\TicketStatusChanged' => [
'App\Listeners\AddStatusMessages',
],
'App\Events\NotifySubscriptions' => [
'App\Listeners\SendNotificationMail'
],
];
/**

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSubscriptions extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('subscriptions', function (Blueprint $table) {
$table->foreignId('ticket_id')->constrained('tickets');
$table->foreignId('user_id')->constrained('users');
$table->primary(['ticket_id', 'user_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('subscriptions');
}
}

View file

@ -17,7 +17,9 @@
<th scope="col">Créer par</th>
<th scope="col">Status</th>
<th scope="col">Contenu</th>
@if (Auth::user()->role === 1)
<th></th>
@endif
</thead>
<tbody>
@foreach ($tickets as $ticket)
@ -79,7 +81,7 @@
</div>
</td>
<td>
@if ($ticket->created_by === Auth::user()->id || Auth::user()->role === 1)
@if (Auth::user()->role === 1)
<a href="{{ route('edit-ticket', $ticket->id) }}" class="btn btn-sm btn-outline-primary">Modifier</a>
@endif
</td>

View file

@ -0,0 +1,9 @@
<p>Bonjour,</p>
<p>Le ticket n°{{ $ticket->id }} à été mis à jour :</p>
<ul>
<li>Projet : {{ $ticket->project->name }}</li>
<li>Type : {{ $ticket->type === 0 ? "Bug" : "Évolution" }}</li>
<li>Créer par : {{ $ticket->user->name }}</li>
</ul>
<p>{!! $corpsMaj !!}</p>
<p>Lien vers le ticket : <a href="{{ route('show-ticket', $ticket->id) }}" target="_blank">Ouvrir dans un nouvel onglet</a></p>

View file

@ -3,13 +3,20 @@
@section('content')
<div class="container">
<div class="form-row">
<h2 class="col-md-10">
<h2 class="@if (Auth::user()->role === 1)col-md-8 @else col-md-10 @endif">
<a href="{{ route('home') }}" class="text-decoration-none">←</a>
Ticket n°{{ $ticket->id }} : {{ $ticket->project->name }} - {{ $ticket->type === 0 ? "Bug" : "Évolution" }}
@if (Auth::user()->role !== 1)
<span class="badge badge-secondary">{{ $status[$ticket->status] }}</span>
@endif
</h2>
<form action="{{ route('subscribe-ticket', $ticket->id) }}" method="POST" id="form_abonnement" class="col-md-2">
@csrf
<div class="custom-control custom-checkbox text-right p-2">
<input type="checkbox" name="subscription" class="custom-control-input" id="subscription" @if ($isSubscribed)checked @endif onchange="$('#form_abonnement').submit()">
<label class="custom-control-label" for="subscription">Suivre le ticket</label>
</div>
</form>
@if (Auth::user()->role === 1)
<form action="{{ route('change-status-ticket', $ticket->id) }}" method="POST" id="form_status" class="col-md-2">
@csrf
@ -100,6 +107,7 @@
<p>{!! nl2br(e($ticket->text)) !!}</p>
<small class="text-muted">Créer le {{ \Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i') }}</small>
</div>
@if ($ticket->file !== null || $ticket->file2 !== null)
<hr>
<div>
<h4>Pièces jointes</h4>
@ -118,5 +126,6 @@
@endif
</ul>
</div>
@endif
</div>
@endsection

View file

@ -29,6 +29,7 @@ Route::middleware(['auth'])->group(function () {
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');
Route::post('/ticket/subscribe/{id}', [TicketController::class, 'subscribe'])->name('subscribe-ticket');
// Projets (admin)
Route::middleware(['is-admin'])->group(function () {
Route::get('/projects', [ProjectController::class, 'index'])->name('projects');