From 80f973ee9e3341e23766b3471d197746b9c6fb6c Mon Sep 17 00:00:00 2001 From: wynn <66362261+wynn-dev@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:33:51 +0100 Subject: [PATCH 01/54] Update create.blade.php --- resources/views/servers/create.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/servers/create.blade.php b/resources/views/servers/create.blade.php index 6ddb44e21..9863e944d 100644 --- a/resources/views/servers/create.blade.php +++ b/resources/views/servers/create.blade.php @@ -350,7 +350,7 @@ function serverApp() { this.fetchedProducts = true; // TODO: Sortable by user chosen property (cpu, ram, disk...) - this.products = response.data.sort((p1, p2) => p1.price > p2.price && 1 || -1) + this.products = response.data.sort((p1, p2) => parseInt(p1.price,10) > parseInt(p2.price,10) && 1 || -1) //divide cpu by 100 for each product this.products.forEach(product => { From 94bbea26901a4bccba38b7c62fa39d71a69da39d Mon Sep 17 00:00:00 2001 From: SahrulGnwn Date: Mon, 1 Aug 2022 23:52:16 +0700 Subject: [PATCH 02/54] Ticket System --- .../Controllers/Mod/TicketsController.php | 62 ++++++++ app/Http/Controllers/TicketsController.php | 84 +++++++++++ app/Http/Kernel.php | 2 + app/Http/Middleware/isMod.php | 27 ++++ app/Models/Ticket.php | 21 +++ app/Models/TicketCategory.php | 13 ++ app/Models/TicketComment.php | 21 +++ .../Ticket/Admin/AdminCreateNotification.php | 71 +++++++++ .../Ticket/Admin/AdminReplyNotification.php | 78 ++++++++++ .../Ticket/User/CreateNotification.php | 68 +++++++++ .../Ticket/User/ReplyNotification.php | 78 ++++++++++ ...2022_08_01_170819_create_tickets_table.php | 39 +++++ ...1_171633_create_ticketcategories_table.php | 59 ++++++++ ..._01_181607_create_ticketcomments_table.php | 34 +++++ resources/views/admin/users/edit.blade.php | 3 + resources/views/admin/users/show.blade.php | 2 +- resources/views/layouts/main.blade.php | 17 +++ .../views/mail/ticket/admin/create.blade.php | 25 ++++ .../views/mail/ticket/admin/reply.blade.php | 25 ++++ .../views/mail/ticket/user/create.blade.php | 13 ++ .../views/mail/ticket/user/reply.blade.php | 18 +++ resources/views/mod/ticket/index.blade.php | 104 +++++++++++++ resources/views/mod/ticket/show.blade.php | 141 ++++++++++++++++++ resources/views/ticket/create.blade.php | 127 ++++++++++++++++ resources/views/ticket/index.blade.php | 100 +++++++++++++ resources/views/ticket/show.blade.php | 141 ++++++++++++++++++ routes/web.php | 20 ++- 27 files changed, 1391 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/Mod/TicketsController.php create mode 100644 app/Http/Controllers/TicketsController.php create mode 100644 app/Http/Middleware/isMod.php create mode 100644 app/Models/Ticket.php create mode 100644 app/Models/TicketCategory.php create mode 100644 app/Models/TicketComment.php create mode 100644 app/Notifications/Ticket/Admin/AdminCreateNotification.php create mode 100644 app/Notifications/Ticket/Admin/AdminReplyNotification.php create mode 100644 app/Notifications/Ticket/User/CreateNotification.php create mode 100644 app/Notifications/Ticket/User/ReplyNotification.php create mode 100644 database/migrations/2022_08_01_170819_create_tickets_table.php create mode 100644 database/migrations/2022_08_01_171633_create_ticketcategories_table.php create mode 100644 database/migrations/2022_08_01_181607_create_ticketcomments_table.php create mode 100644 resources/views/mail/ticket/admin/create.blade.php create mode 100644 resources/views/mail/ticket/admin/reply.blade.php create mode 100644 resources/views/mail/ticket/user/create.blade.php create mode 100644 resources/views/mail/ticket/user/reply.blade.php create mode 100644 resources/views/mod/ticket/index.blade.php create mode 100644 resources/views/mod/ticket/show.blade.php create mode 100644 resources/views/ticket/create.blade.php create mode 100644 resources/views/ticket/index.blade.php create mode 100644 resources/views/ticket/show.blade.php diff --git a/app/Http/Controllers/Mod/TicketsController.php b/app/Http/Controllers/Mod/TicketsController.php new file mode 100644 index 000000000..4445105a1 --- /dev/null +++ b/app/Http/Controllers/Mod/TicketsController.php @@ -0,0 +1,62 @@ +firstOrFail(); + $ticketcomments = $ticket->ticketcomments; + $ticketcategory = $ticket->ticketcategory; + $server = Server::where('id', $ticket->server)->first(); + return view("admin.ticket.show", compact("ticket", "ticketcategory", "ticketcomments", "server")); + } + + public function close($ticket_id) { + $ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail(); + $ticket->status = "Closed"; + $ticket->save(); + $ticketOwner = $ticket->user; + return redirect()->back()->with('success', __('A ticket has been closed, ID: #') . $ticket->ticket_id); + } + + public function delete($ticket_id){ + $ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail(); + TicketComment::where("ticket_id", $ticket->id)->delete(); + $ticket->delete(); + return redirect()->back()->with('success', __('A ticket has been deleted, ID: #') . $ticket_id); + + } + public function reply(Request $request) { + $this->validate($request, array("ticketcomment" => "required")); + $ticket = Ticket::where('id', $request->input("ticket_id"))->firstOrFail(); + $ticket->status = "Answered"; + $ticket->update(); + $ticketcomment = TicketComment::create(array( + "ticket_id" => $request->input("ticket_id"), + "user_id" => Auth::user()->id, + "ticketcomment" => $request->input("ticketcomment"), + )); + $user = User::where('id', $ticket->user_id)->firstOrFail(); + $newmessage = $request->input("ticketcomment"); + $user->notify(new ReplyNotification($ticket, $user, $newmessage)); + return redirect()->back()->with('success', __('Your comment has been submitted')); + } +} diff --git a/app/Http/Controllers/TicketsController.php b/app/Http/Controllers/TicketsController.php new file mode 100644 index 000000000..f845d4c4e --- /dev/null +++ b/app/Http/Controllers/TicketsController.php @@ -0,0 +1,84 @@ +id)->paginate(10); + $ticketcategories = TicketCategory::all(); + + return view("ticket.index", compact("tickets", "ticketcategories")); + } + public function create() { + $ticketcategories = TicketCategory::all(); + $servers = Auth::user()->servers; + return view("ticket.create", compact("ticketcategories", "servers")); + } + public function store(Request $request) { + $this->validate($request, array( + "title" => "required", + "ticketcategory" => "required", + "priority" => "required", + "message" => "required") + ); + $ticket = new Ticket(array( + "title" => $request->input("title"), + "user_id" => Auth::user()->id, + "ticket_id" => strtoupper(Str::random(5)), + "ticketcategory_id" => $request->input("ticketcategory"), + "priority" => $request->input("priority"), + "message" => $request->input("message"), + "status" => "Open", + "server" => $request->input("server")) + ); + $ticket->save(); + $user = Auth::user(); + $admin = User::where('role', 'admin')->orWhere('role', 'mod')->get(); + $user->notify(new CreateNotification($ticket)); + Notification::send($admin, new AdminCreateNotification($ticket, $user)); + + return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id); + } + public function show($ticket_id) { + $ticket = Ticket::where("ticket_id", $ticket_id)->firstOrFail(); + $ticketcomments = $ticket->ticketcomments; + $ticketcategory = $ticket->ticketcategory; + $server = Server::where('id', $ticket->server)->first(); + return view("ticket.show", compact("ticket", "ticketcategory", "ticketcomments", "server")); + } + public function reply(Request $request) { + $this->validate($request, array("ticketcomment" => "required")); + $ticket = Ticket::where('id', $request->input("ticket_id"))->firstOrFail(); + $ticket->status = "Client Reply"; + $ticket->update(); + $ticketcomment = TicketComment::create(array( + "ticket_id" => $request->input("ticket_id"), + "user_id" => Auth::user()->id, + "ticketcomment" => $request->input("ticketcomment"), + "message" => $request->input("message") + )); + $user = Auth::user(); + $admin = User::where('role', 'admin')->orWhere('role', 'mod')->get(); + $newmessage = $request->input("ticketcomment"); + Notification::send($admin, new AdminReplyNotification($ticket, $user, $newmessage)); + return redirect()->back()->with('success', __('Your comment has been submitted')); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 9b2e1fcde..ee5c8d584 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -6,6 +6,7 @@ use App\Http\Middleware\CheckSuspended; use App\Http\Middleware\GlobalNames; use App\Http\Middleware\isAdmin; +use App\Http\Middleware\isMod; use App\Http\Middleware\LastSeen; use Illuminate\Foundation\Http\Kernel as HttpKernel; @@ -72,6 +73,7 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'admin' => isAdmin::class, + 'mod' => isMod::class, 'api.token' => ApiAuthToken::class, 'checkSuspended' => CheckSuspended::class ]; diff --git a/app/Http/Middleware/isMod.php b/app/Http/Middleware/isMod.php new file mode 100644 index 000000000..73e12446d --- /dev/null +++ b/app/Http/Middleware/isMod.php @@ -0,0 +1,27 @@ +role == 'mod' || Auth::user() && Auth::user()->role == 'admin') { + return $next($request); + } + + return redirect(RouteServiceProvider::HOME); + } +} diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php new file mode 100644 index 000000000..16f548a91 --- /dev/null +++ b/app/Models/Ticket.php @@ -0,0 +1,21 @@ +belongsTo(TicketCategory::class);} + + public function ticketcomments(){ + return $this->hasMany(TicketComment::class);} + + public function user(){ + return $this->belongsTo(User::class);} +} + \ No newline at end of file diff --git a/app/Models/TicketCategory.php b/app/Models/TicketCategory.php new file mode 100644 index 000000000..8301a108a --- /dev/null +++ b/app/Models/TicketCategory.php @@ -0,0 +1,13 @@ +hasMany(Ticket::class);} +} + \ No newline at end of file diff --git a/app/Models/TicketComment.php b/app/Models/TicketComment.php new file mode 100644 index 000000000..c44a5bf1d --- /dev/null +++ b/app/Models/TicketComment.php @@ -0,0 +1,21 @@ +belongsTo(TicketCategory::class);} + + public function ticket(){ + return $this->belongsTo(Ticket::class);} + + public function user(){ + return $this->belongsTo(User::class);} +} + \ No newline at end of file diff --git a/app/Notifications/Ticket/Admin/AdminCreateNotification.php b/app/Notifications/Ticket/Admin/AdminCreateNotification.php new file mode 100644 index 000000000..eb832596a --- /dev/null +++ b/app/Notifications/Ticket/Admin/AdminCreateNotification.php @@ -0,0 +1,71 @@ +ticket = $ticket; + $this->user = $user; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + $via = ['mail','database']; + return $via; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title) + ->markdown('mail.ticket.admin.create' , ['ticket' => $this->ticket, 'user' => $this->user]); + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + 'title' => '[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title, + 'content' => "Ticket With ID : {$this->ticket->ticket_id} has been opened by {$this->user->name}", + ]; + } +} diff --git a/app/Notifications/Ticket/Admin/AdminReplyNotification.php b/app/Notifications/Ticket/Admin/AdminReplyNotification.php new file mode 100644 index 000000000..250d06d65 --- /dev/null +++ b/app/Notifications/Ticket/Admin/AdminReplyNotification.php @@ -0,0 +1,78 @@ +ticket = $ticket; + $this->user = $user; + $this->newmessage = $newmessage; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + $via = ['mail','database']; + return $via; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title) + ->markdown('mail.ticket.admin.reply' , ['ticket' => $this->ticket, 'user' => $this->user, 'newmessage' => $this->newmessage]); + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + 'title' => '[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title, + 'content' => " +

Ticket With ID : {$this->ticket->ticket_id} has had a new reply posted by {$this->user->name}

+
+

Message:

+

{$this->newmessage}

+ ", + ]; + } +} diff --git a/app/Notifications/Ticket/User/CreateNotification.php b/app/Notifications/Ticket/User/CreateNotification.php new file mode 100644 index 000000000..3d2580301 --- /dev/null +++ b/app/Notifications/Ticket/User/CreateNotification.php @@ -0,0 +1,68 @@ +ticket = $ticket; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + $via = ['mail','database']; + return $via; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title) + ->markdown('mail.ticket.user.create' , ['ticket' => $this->ticket]); + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + 'title' => '[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title, + 'content' => "Your Ticket has been Created With ID : {$this->ticket->ticket_id}", + ]; + } +} diff --git a/app/Notifications/Ticket/User/ReplyNotification.php b/app/Notifications/Ticket/User/ReplyNotification.php new file mode 100644 index 000000000..1d2b733a5 --- /dev/null +++ b/app/Notifications/Ticket/User/ReplyNotification.php @@ -0,0 +1,78 @@ +ticket = $ticket; + $this->user = $user; + $this->newmessage = $newmessage; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + $via = ['mail','database']; + return $via; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title) + ->markdown('mail.ticket.user.reply' , ['ticket' => $this->ticket, 'user' => $this->user, 'newmessage' => $this->newmessage]); + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + 'title' => '[Ticket ID: ' . $this->ticket->ticket_id . '] ' . $this->ticket->title, + 'content' => " +

Ticket With ID : {$this->ticket->ticket_id} A response has been added to your ticket. Please see below for our response!

+
+

Message:

+

{$this->newmessage}

+ ", + ]; + } +} diff --git a/database/migrations/2022_08_01_170819_create_tickets_table.php b/database/migrations/2022_08_01_170819_create_tickets_table.php new file mode 100644 index 000000000..5ae8cda7d --- /dev/null +++ b/database/migrations/2022_08_01_170819_create_tickets_table.php @@ -0,0 +1,39 @@ +increments('id'); + $table->integer('user_id')->unsigned(); + $table->integer('ticketcategory_id')->unsigned(); + $table->string('ticket_id')->unique(); + $table->string('title'); + $table->string('priority'); + $table->text('message'); + $table->string('status'); + $table->string('server')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('tickets'); + } +} diff --git a/database/migrations/2022_08_01_171633_create_ticketcategories_table.php b/database/migrations/2022_08_01_171633_create_ticketcategories_table.php new file mode 100644 index 000000000..2473b7714 --- /dev/null +++ b/database/migrations/2022_08_01_171633_create_ticketcategories_table.php @@ -0,0 +1,59 @@ +increments('id'); + $table->string('name'); + $table->timestamps(); + }); + + DB::table('ticket_categories')->insert( + array( + 'name' => 'Technical', + ) + ); + DB::table('ticket_categories')->insert( + array( + 'name' => 'Billing', + ) + ); + DB::table('ticket_categories')->insert( + array( + 'name' => 'Issue', + ) + ); + DB::table('ticket_categories')->insert( + array( + 'name' => 'Request', + ) + ); + DB::table('ticket_categories')->insert( + array( + 'name' => 'Other', + ) + ); + } + + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('ticket_categories'); + } +} diff --git a/database/migrations/2022_08_01_181607_create_ticketcomments_table.php b/database/migrations/2022_08_01_181607_create_ticketcomments_table.php new file mode 100644 index 000000000..58886b457 --- /dev/null +++ b/database/migrations/2022_08_01_181607_create_ticketcomments_table.php @@ -0,0 +1,34 @@ +increments('id'); + $table->integer('ticket_id')->unsigned(); + $table->integer('user_id')->unsigned(); + $table->text('ticketcomment'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('ticket_comments'); + } +} diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php index 206a2dda0..35cefa530 100644 --- a/resources/views/admin/users/edit.blade.php +++ b/resources/views/admin/users/edit.blade.php @@ -104,6 +104,9 @@ class="custom-select @error('role') is-invalid @enderror" value="admin"> {{__(' Administrator')}} + -