Compare commits
10 Commits
804e880331
...
e2285db816
| Author | SHA1 | Date |
|---|---|---|
|
|
e2285db816 | |
|
|
98b34a2959 | |
|
|
203d845825 | |
|
|
412ffc0e87 | |
|
|
6b51f6a402 | |
|
|
f13e2a1945 | |
|
|
f0e7e09ef8 | |
|
|
521e3b084c | |
|
|
fe3a69e9f7 | |
|
|
1760c7e0aa |
|
|
@ -6,6 +6,9 @@
|
|||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.zip
|
||||
/chat.kundesone.no
|
||||
/mailgun.kundesone.no
|
||||
.env.backup
|
||||
.env.production
|
||||
.phpunit.result.cache
|
||||
|
|
@ -17,3 +20,4 @@ yarn-error.log
|
|||
/.fleet
|
||||
/.idea
|
||||
/.vscode
|
||||
/chat.kundesone.no
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ RewriteRule ^(/)?$ public/index.php [L]
|
|||
php_flag zlib.output_compression Off
|
||||
</IfModule>
|
||||
# END cPanel-generated php ini directives, do not edit
|
||||
# Deny access to .env files
|
||||
<Files .env>
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# php -- BEGIN cPanel-generated handler, do not edit
|
||||
# Set the “ea-php81” package as the default “PHP” programming language.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\ChatGroup;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Response;
|
||||
use App\Models\Message; // Assuming Message is the model for your messages table
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CheckChatGroupStatus extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'chatgroup:check-status';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Check ChatGroup status and create tickets if status is closed';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Fetch all closed chat groups
|
||||
$closedChatGroups = ChatGroup::where('status', 'closed')->get();
|
||||
|
||||
foreach ($closedChatGroups as $chatGroup) {
|
||||
DB::transaction(function () use ($chatGroup) {
|
||||
|
||||
$company = get_company('id',$chatGroup->company_id);
|
||||
|
||||
$ticket = insertTicket($chatGroup->email, $company->email, $chatGroup->subject, '','chat',$chatGroup->name,$chatGroup->user_id,'done',true );
|
||||
|
||||
|
||||
// Fetch all messages from the chat group
|
||||
$messages = $chatGroup->messages;
|
||||
|
||||
// Insert each message as a response to the ticket
|
||||
foreach ($messages as $message) {
|
||||
|
||||
// Create a new Response instance
|
||||
$response = new Response;
|
||||
|
||||
$html = $message->message;
|
||||
|
||||
if($message->type == 'image'){
|
||||
$html = "<img src='{$message->message}' />";
|
||||
}
|
||||
|
||||
if($message->type == 'file'){
|
||||
$html = "<a target='_blank' href='{$message->message}'>View File</a>";
|
||||
}
|
||||
|
||||
|
||||
// Set the properties of the Response
|
||||
$response->message = $html;
|
||||
$response->ticket_id = $ticket->id;
|
||||
$response->user_id = $message->from == 'user'?0:1; // You may want to dynamically set the user_id based on the authenticated user
|
||||
$response->created_at = $message->created_at;
|
||||
$response->updated_at = $message->updated_at;
|
||||
// Save the response to the database
|
||||
$response->save();
|
||||
|
||||
}
|
||||
|
||||
// Optionally update the chat group status to indicate a ticket has been created
|
||||
$chatGroup->update(['status' => 'ticket_created']);
|
||||
});
|
||||
}
|
||||
|
||||
$this->info('Chat groups checked and tickets created for closed statuses.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use \Carbon\Carbon;
|
||||
use App\Models\User;
|
||||
|
||||
class UpdateLastOnline extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'users:update-last-online';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Update last online user if he/she is not active with the period of three minutes';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$now = Carbon::now()->format('Y-m-d H:i:s');
|
||||
$users = User::whereNotNull('last_online')->where('last_online', '!=', '')->get();
|
||||
foreach($users as $user)
|
||||
{
|
||||
$lastOnline = Carbon::parse($user->last_online);
|
||||
|
||||
if ($lastOnline->diffInMinutes($now) > 3) {
|
||||
//update user
|
||||
$user->is_available = 0;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->info('Users last online updated successfully.');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,8 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$schedule->command('chatgroup:check-status')->everyMinute();
|
||||
$schedule->command('users:update-last-online')->everyMinute();
|
||||
// $schedule->command('inspire')->hourly();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,73 @@
|
|||
use App\Models\CompanyMeta;
|
||||
use App\Models\Settings;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketMeta;
|
||||
use App\Models\Response;
|
||||
use App\Models\TicketNote;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Mailgun\Mailgun;
|
||||
use App\Models\Company;
|
||||
use App\Models\ChatGroup;
|
||||
use App\Models\Message;
|
||||
use App\Models\Tag;
|
||||
use App\Models\Rule;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Models\Notification;
|
||||
|
||||
function get_company_users($company_id){
|
||||
|
||||
return CompanyUser::where('company_id', $company_id)->with('user')->get();
|
||||
|
||||
}
|
||||
|
||||
function getCompanyTags($companyId) {
|
||||
$tags = Tag::where('company_id', $companyId)->get();
|
||||
return $tags;
|
||||
}
|
||||
|
||||
|
||||
function get_company($key,$value){
|
||||
return Company::where($key,$value)->first();
|
||||
}
|
||||
|
||||
function get_current_company_tickets($args = []){
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
if(!$companyId){
|
||||
return false;
|
||||
}
|
||||
|
||||
$company = get_company('id',$companyId);
|
||||
|
||||
if(!$company){
|
||||
return false;
|
||||
}
|
||||
|
||||
$tickets = Ticket::where('to_email', $company->email);
|
||||
|
||||
$tickets->orderBy('created_at','desc');
|
||||
|
||||
if(isset($args['type'])){
|
||||
$tickets->where('type',$args['type']);
|
||||
}
|
||||
|
||||
if(isset($args['status'])){
|
||||
$tickets->where('status',$args['status']);
|
||||
}
|
||||
|
||||
if(isset($args['orderby'])){
|
||||
$tickets->orderBy($args['orderby'],$args['order']??'asc');
|
||||
}
|
||||
|
||||
if(isset($args['with'])){
|
||||
$tickets->with($args['with']);
|
||||
}
|
||||
|
||||
$tickets = $tickets->get();
|
||||
|
||||
return $tickets;
|
||||
}
|
||||
|
||||
function getResponse($company_id, $key, $type) {
|
||||
$meta = CompanyMeta::where('company_id', $company_id)->where('key', $key)->where('type', $type)->first();
|
||||
|
|
@ -37,13 +101,24 @@ function verifyMailgunSignature($token, $timestamp, $signature)
|
|||
}
|
||||
//Insert Ticket
|
||||
if (!function_exists('insertTicket')) {
|
||||
function insertTicket($from_email, $to_email, $subject, $content, $type, $sender_name) {
|
||||
function insertTicket($from_email, $to_email, $subject, $content, $type, $sender_name,$user_assigned = 0,$status = 'waiting',$force = false) {
|
||||
|
||||
$check = Ticket::where('subject', $subject)
|
||||
->where('from_email',$from_email)
|
||||
->where('to_email',$to_email)->first();
|
||||
$check = Ticket::where(function ($query) use ($from_email, $to_email) {
|
||||
$query->where('from_email', $from_email)
|
||||
->where('to_email', $to_email);
|
||||
})
|
||||
->where(function ($query) use ($subject) {
|
||||
$cleanSubject = trim(str_ireplace('Re:', '', $subject)); // Remove 'Re:' prefix and trim whitespace
|
||||
$query->where('subject', $cleanSubject)
|
||||
->orWhere('subject', 'Re: ' . $cleanSubject)
|
||||
->orWhere('subject2', 'Re: ' . $cleanSubject)
|
||||
->orWhere('subject2', $cleanSubject); // Consider both with and without 'Re:'
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
if(!$check){
|
||||
|
||||
if(!$check || $force){
|
||||
|
||||
$ticket = new Ticket;
|
||||
$ticket->from_email = $from_email;
|
||||
|
|
@ -53,9 +128,9 @@ function insertTicket($from_email, $to_email, $subject, $content, $type, $sender
|
|||
$ticket->subject = $subject;
|
||||
$ticket->content = $content;
|
||||
$ticket->priority = 'low';
|
||||
$ticket->status = 'waiting';
|
||||
$ticket->status = $status;
|
||||
$ticket->parent_id = 0;
|
||||
$ticket->user_assigned = 0;
|
||||
$ticket->user_assigned = $user_assigned;
|
||||
$ticket->save();
|
||||
|
||||
}else{
|
||||
|
|
@ -70,7 +145,7 @@ function insertTicket($from_email, $to_email, $subject, $content, $type, $sender
|
|||
function getSelectedCompany() {
|
||||
$company = Session::get('selected_company');
|
||||
if (!$company) {
|
||||
return response()->json(['message' => 'Company not found'], 404);
|
||||
return false;
|
||||
}
|
||||
return $company;
|
||||
}
|
||||
|
|
@ -110,3 +185,194 @@ function containsHtml($string) {
|
|||
return $string != strip_tags($string);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('sendEmailViaMailgun')) {
|
||||
function sendEmailViaMailgun( $domain, $from, $to, $subject, $html) {
|
||||
|
||||
$apiKey = env('MAILGUN_SECRET');
|
||||
|
||||
// Create a new Mailgun instance with API credentials
|
||||
$mg = Mailgun::create($apiKey);
|
||||
|
||||
// Prepare the message parameters
|
||||
$params = [
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
'subject' => $subject,
|
||||
'html' => $html
|
||||
];
|
||||
|
||||
// Send the email
|
||||
$response = $mg->messages()->send($domain, $params);
|
||||
|
||||
// Return the response from Mailgun
|
||||
return $response;
|
||||
}
|
||||
|
||||
function createResponse($ticket_id, $message, $user_id = 0)
|
||||
{
|
||||
// Create a new Response instance
|
||||
$response = new Response;
|
||||
|
||||
// Set the properties of the Response
|
||||
$response->message = $message;
|
||||
$response->ticket_id = $ticket_id;
|
||||
$response->user_id = $user_id; // You may want to dynamically set the user_id based on the authenticated user
|
||||
|
||||
// Save the response to the database
|
||||
$response->save();
|
||||
|
||||
// Return the created response
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new chat group.
|
||||
*
|
||||
* @param int $companyId The ID of the company associated with the chat.
|
||||
* @param int $userId The ID of the user creating the chat group.
|
||||
* @param string $customerId Identifier for the customer involved in the chat.
|
||||
* @param string $name Name or title of the chat group.
|
||||
* @param string $email Email address associated with the chat group.
|
||||
* @param string $subject Subject or initial topic of the chat group.
|
||||
* @param string $status Current status of the chat group (e.g., 'active', 'closed').
|
||||
* @return ChatGroup The newly created chat group object.
|
||||
*/
|
||||
function createChatGroup($companyId, $userId, $customerId, $name, $email, $subject, $status)
|
||||
{
|
||||
return ChatGroup::create([
|
||||
'company_id' => $companyId,
|
||||
'user_id' => $userId,
|
||||
'customer_id' => $customerId,
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'subject' => $subject,
|
||||
'status' => $status
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a new message in a specified chat group.
|
||||
*
|
||||
* @param int $chatId The ID of the chat group.
|
||||
* @param string $from Sender identifier.
|
||||
* @param string $to Receiver identifier.
|
||||
* @param string $message Content of the message.
|
||||
* @param string $type Type of the message.
|
||||
* @return Message The newly created message object.
|
||||
*/
|
||||
function storeMessage($chatId, $from, $to, $message, $type)
|
||||
{
|
||||
return Message::create([
|
||||
'chat_id' => $chatId,
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
'message' => $message,
|
||||
'type' => $type
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve all messages from a specified chat group.
|
||||
*
|
||||
* @param int $chatId The ID of the chat group.
|
||||
* @return \Illuminate\Database\Eloquent\Collection A collection of messages.
|
||||
*/
|
||||
function getMessagesByChatId($chatId)
|
||||
{
|
||||
return Message::where('chat_id', $chatId)->orderBy('created_at', 'asc')->get();
|
||||
}
|
||||
|
||||
|
||||
function setTicketMeta(int $ticketId, string $key, $value, string $type = 'string')
|
||||
{
|
||||
$ticket_metas = [];
|
||||
return TicketMeta::updateOrCreate(
|
||||
['ticket_id' => $ticketId, 'key' => $key],
|
||||
['value' => json_encode($value), 'type' => $type]
|
||||
);
|
||||
|
||||
// foreach($value as $tag)
|
||||
// {
|
||||
// $ticket_meta = TicketMeta::updateOrCreate([
|
||||
// 'ticket_id' => $ticketId,
|
||||
// 'key' => $key
|
||||
// ],[
|
||||
// 'value' => $tag,
|
||||
// 'type' => $type
|
||||
// ]);
|
||||
|
||||
// $ticket_metas[] = $ticket_meta;
|
||||
// }
|
||||
|
||||
// return $ticket_metas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a meta value for a ticket.
|
||||
*
|
||||
* @param int $ticketId
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
function getTicketMeta(int $ticketId, string $key)
|
||||
{
|
||||
$meta = TicketMeta::where('ticket_id', $ticketId)->where('key', $key)->first();
|
||||
return $meta ? json_decode($meta->value) : null;
|
||||
}
|
||||
|
||||
function getCompanyMeta(int $companyId, string $key)
|
||||
{
|
||||
$meta = CompanyMeta::where('company_id', $companyId)->where('key', $key)->first();
|
||||
return $meta ? $meta->value : null;
|
||||
}
|
||||
|
||||
function getChatSetting($key, $company_id = null)
|
||||
{
|
||||
$companyId = $company_id??getSelectedCompany();
|
||||
$get_chat_setting = CompanyMeta::where('company_id', $companyId)->where('key', $key)->where('type', 'Chat Setting')->first();
|
||||
return $get_chat_setting;
|
||||
}
|
||||
|
||||
function getChatSettings($key, $company_id = null)
|
||||
{
|
||||
$companyId = $company_id??getSelectedCompany();
|
||||
$get_chat_setting = CompanyMeta::where('company_id', $companyId)->where('key', $key)->where('type', 'Chat Setting')->get();
|
||||
return $get_chat_setting;
|
||||
}
|
||||
|
||||
function getCompanyRules()
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
$rules = Rule::where('company_id', $companyId)->get();
|
||||
return $rules;
|
||||
}
|
||||
|
||||
|
||||
function extractEmail($fromField) {
|
||||
// Regular expression to extract email address within angle brackets or standalone
|
||||
if (preg_match('/<?([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})>?/', $fromField, $matches)) {
|
||||
return $matches[1]; // Return the email address
|
||||
}
|
||||
return null; // Return null if no email is found
|
||||
}
|
||||
|
||||
function send_notification($user_id,$text,$type,$status='default')
|
||||
{
|
||||
$notify = new Notification;
|
||||
$notify->user_id = $user_id;
|
||||
$notify->text = $text;
|
||||
$notify->status = $status;
|
||||
$notify->type = $type;
|
||||
$notify->save();
|
||||
|
||||
return $notify;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use App\Services\MailgunService;
|
||||
use App\Http\Controllers\Mailgun\MailgunController;
|
||||
use App\Models\CompanyUser;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
|
|
@ -37,9 +40,13 @@ class LoginController extends Controller
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
protected $mailgunService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest')->except('logout');
|
||||
$this->mailgunService = app(MailgunService::class);
|
||||
}
|
||||
|
||||
public function login()
|
||||
|
|
@ -55,13 +62,52 @@ public function storeLogin(Request $request)
|
|||
]);
|
||||
|
||||
if (Auth::attempt($credentials)) {
|
||||
// dd(Auth::user());
|
||||
if(Auth::user()->role_id == 3){
|
||||
$company = CompanyUser::where('user_id',Auth::id())->first();
|
||||
|
||||
if($company){
|
||||
|
||||
Session::put('selected_company', $company->company_id);
|
||||
return redirect('/dashboard');
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
if(!Auth::user()->Company) {
|
||||
return redirect('/company-info');
|
||||
} else {
|
||||
$company = Company::where('user_id', Auth::id())->first();
|
||||
Session::put('selected_company', $company->id);
|
||||
return redirect('/dashboard');
|
||||
$domain = $company->domain;
|
||||
|
||||
$mailgunDomain = $this->mailgunService->getDomain($domain);
|
||||
|
||||
if($mailgunDomain){
|
||||
|
||||
$state = $mailgunDomain->getDomain()->getState();
|
||||
|
||||
if($state == 'unverified'){
|
||||
return redirect()->route('showDomain',$domain);
|
||||
}elseif($state == 'active'){
|
||||
|
||||
if(empty($company->internal_email)){
|
||||
|
||||
$mailgun = new MailgunController();
|
||||
$mailgun->createEmail($domain);
|
||||
}
|
||||
|
||||
Session::put('selected_company', $company->id);
|
||||
return redirect('/dashboard');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'Invalid Credentials');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,262 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Chat;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyMeta;
|
||||
use App\Models\ChatGroup;
|
||||
use App\Models\Message;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ChatController extends Controller
|
||||
{
|
||||
|
||||
public function chatDemo(Request $request){
|
||||
return view('chat.demo');
|
||||
}
|
||||
|
||||
public function CloseChat(Request $request){
|
||||
$chat_id = $request->chat_id;
|
||||
|
||||
$chat = ChatGroup::find($chat_id);
|
||||
|
||||
if($chat){
|
||||
$chat->status = 'closed';
|
||||
$chat->save();
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getChat(Request $request){
|
||||
$chat_id = $request->chat_id;
|
||||
|
||||
return ChatGroup::find($chat_id);
|
||||
}
|
||||
|
||||
|
||||
public function getMessages(Request $request){
|
||||
$chat_id = $request->chat_id;
|
||||
|
||||
return Message::where('chat_id',$chat_id)->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start a new chat by creating a chat group.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function startChat(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'company_id' => 'required|integer|exists:companies,id',
|
||||
//'user_id' => 'required|integer|exists:users,id',
|
||||
'customer_id' => 'required|string|max:255',
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|max:255',
|
||||
'subject' => 'required|string|max:1000',
|
||||
//'status' => 'required|string|max:255'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(['errors' => $validator->errors()], 422);
|
||||
}
|
||||
|
||||
$company_id = $request->company_id;
|
||||
|
||||
$user = $this->select_user($company_id);
|
||||
|
||||
if($user){
|
||||
|
||||
$data = [
|
||||
'company_id' => $company_id,
|
||||
'user_id' => $user->user_id,
|
||||
'customer_id' => $request->customer_id,
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'subject' => $request->subject,
|
||||
'status' => 'open',
|
||||
|
||||
];
|
||||
|
||||
$chatGroup = ChatGroup::create($data);
|
||||
|
||||
return response()->json(['chat' => $chatGroup], 200);
|
||||
|
||||
}else{
|
||||
return response()->json(['message' => 'user not found'], 400);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function sendMessage(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'chat_id' => 'required|integer|exists:chat_group,id',
|
||||
'from' => 'required|string|max:255',
|
||||
//'to' => 'required|string|max:255',
|
||||
//'message' => 'required|string',
|
||||
'type' => 'required|string|max:255'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(['errors' => $validator->errors()], 422);
|
||||
}
|
||||
$fileUrl = '';
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
$file = $request->file('file');
|
||||
$filePath = $file->store('chat', 'public'); // Store in the 'public/uploads' directory
|
||||
$fileUrl = url(Storage::url($filePath)); // Generate the file URL
|
||||
}
|
||||
|
||||
$data = [
|
||||
'chat_id' => $request->chat_id,
|
||||
|
||||
'from' => $request->from,
|
||||
'to' => $request->from == 'user'?'company':'user',
|
||||
'message' => $request->hasFile('file')? $fileUrl: $request->message,
|
||||
'type' => $request->type,
|
||||
|
||||
|
||||
];
|
||||
|
||||
|
||||
$message = Message::create($data);
|
||||
|
||||
return response()->json(['message' => 'Message sent successfully', 'data' => $message], 200);
|
||||
}
|
||||
|
||||
public function select_user($company_id){
|
||||
$companyUsers = get_company_users($company_id);
|
||||
//Get Max Number f Chats
|
||||
$get_max_number_of_chats = CompanyMeta::where('company_id', $company_id)->where('key', 'max_number_of_chats_per_editor')->first();
|
||||
|
||||
if(!is_null($get_max_number_of_chats)){
|
||||
$get_max_number_of_chats = $get_max_number_of_chats->value;
|
||||
}else{
|
||||
$get_max_number_of_chats = 5;
|
||||
}
|
||||
|
||||
$selected = false;
|
||||
|
||||
foreach($companyUsers as $user){
|
||||
$access = json_decode($user->access);
|
||||
//Get Chat Groups
|
||||
$chat_groups = ChatGroup::where('user_id', $user->user_id)->where('status', 'open')->count();
|
||||
|
||||
|
||||
if(in_array('chat',$access) && $user->user->is_available == 1 && $chat_groups <= $get_max_number_of_chats){
|
||||
$selected = $user;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $selected;
|
||||
|
||||
}
|
||||
|
||||
public function getChatGroupsByCompany(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
$chatGroups = ChatGroup::where('company_id', $companyId)
|
||||
->where(function($query) {
|
||||
$query->where('status', '!=', 'ticket_created')
|
||||
->where('status', '!=', 'closed');
|
||||
})
|
||||
->get();
|
||||
|
||||
return response()->json($chatGroups);
|
||||
}
|
||||
|
||||
public function getIpAdresses($companyId)
|
||||
{
|
||||
return CompanyMeta::where('company_id', $companyId)
|
||||
->where('type', 'Chat Setting')
|
||||
->where('key', 'ip_addresses')
|
||||
->pluck('value')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function checkChat(Request $request){
|
||||
$company_id = $request->company_id;
|
||||
$domain = $request->domain;
|
||||
|
||||
$company = get_company('id',$company_id);
|
||||
$ip_addresses = $this->getIpAdresses($company_id);
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
if(in_array($ip, $ip_addresses)) {
|
||||
return response()->json(['status' => 'error', 'message' => 'this IP Address ' . $ip . ' has been blocked.']);
|
||||
}
|
||||
|
||||
if($company){
|
||||
// Str::contains('This is my name', 'my')
|
||||
if( $company->domain == $domain ){
|
||||
|
||||
$start_message = getChatSetting('start_message',$company_id)?getChatSetting('start_message',$company_id)->value:"What can we help you with?"; //welcome message
|
||||
$message_when_chat_is_closed = getChatSetting('message_when_chat_is_closed',$company_id)?getChatSetting('message_when_chat_is_closed',$company_id)->value:"No user is availble right now! Try later.";
|
||||
$wellcome_text = getChatSetting('wellcome_text',$company_id)?getChatSetting('wellcome_text',$company_id)->value:"Hi, welcome how i can help you today?";
|
||||
|
||||
//Get Style
|
||||
$styles = [
|
||||
'text_theme_color' => getChatSetting('text_theme_color', $company_id) ? getChatSetting('text_theme_color', $company_id)->value : null,
|
||||
'background_theme_color' => getChatSetting('background_theme_color', $company_id) ? getChatSetting('background_theme_color', $company_id)->value : null,
|
||||
'text_color_for_sent_message' => getChatSetting('text_color_for_sent_message', $company_id) ? getChatSetting('text_color_for_sent_message', $company_id)->value : null,
|
||||
'background_color_of_sent_message' => getChatSetting('background_color_of_sent_message', $company_id) ? getChatSetting('background_color_of_sent_message', $company_id)->value : null,
|
||||
'background_color_of_received_message' => getChatSetting('background_color_of_received_message', $company_id) ? getChatSetting('background_color_of_received_message', $company_id)->value : null,
|
||||
'text_color_of_received_message' => getChatSetting('text_color_of_received_message', $company_id) ? getChatSetting('text_color_of_received_message', $company_id)->value : null,
|
||||
'text_color_of_notification' => getChatSetting('text_color_of_notification', $company_id) ? getChatSetting('text_color_of_notification', $company_id)->value : null,
|
||||
'text_color_of_error_message' => getChatSetting('text_color_of_error_message', $company_id) ? getChatSetting('text_color_of_error_message', $company_id)->value : null,
|
||||
'background_color_of_error_message' => getChatSetting('background_color_of_error_message', $company_id) ? getChatSetting('background_color_of_error_message', $company_id)->value : null,
|
||||
'link_color' => getChatSetting('link_color', $company_id) ? getChatSetting('link_color', $company_id)->value : null,
|
||||
];
|
||||
|
||||
//Get Display
|
||||
$settings = getChatSettings('Display Chat', $company_id);
|
||||
$display_chats = $settings ? $settings->pluck('value')->map(function($value) {
|
||||
return json_decode($value);
|
||||
}) : null;
|
||||
$hide_chats = getChatSetting('Hide Chat', $company_id) ? getChatSetting('Hide Chat', $company_id)->value : null;
|
||||
$displays = [
|
||||
'display_chats' => $display_chats,
|
||||
'hide_chat' => $hide_chats,
|
||||
];
|
||||
|
||||
//Get Canned Responses
|
||||
$canned_responses = getChatSettings('Chat Canned Responses', $company_id);
|
||||
$canned_responses = $canned_responses ? $canned_responses->pluck('value')->map(function($value) {
|
||||
return json_decode($value);
|
||||
}) : null;
|
||||
|
||||
//Terms And Conditions
|
||||
$link_text = "https://kundesone.no/terms-and-conditions/$company_id";//getChatSetting('link_text', $company_id) ? getChatSetting('link_text', $company_id)->value : null;
|
||||
|
||||
|
||||
$user = $this->select_user($company_id);
|
||||
|
||||
if($user){
|
||||
return response()->json(['status' => 'success','data' => ['welcome' => $wellcome_text, 'start_message' => $start_message, 'user' => $user->user->name, 'styles' => $styles,
|
||||
'displays' => $displays, 'canned_responses' => $canned_responses, 'link_text' => $link_text] ]);
|
||||
}else{
|
||||
return response()->json(['status' => 'error', 'message' => $message_when_chat_is_closed]);
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
return response()->json(['status' => 'error', 'message' => "You are not authorized!"]);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['status' => 'error', 'message' => "You are not authorized!"]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\CompanyMeta;
|
||||
|
||||
class ChatSettingController extends Controller
|
||||
{
|
||||
public function chatSetting()
|
||||
{
|
||||
$display_chats = CompanyMeta::where('key', 'Display Chat')->where('type', 'Chat Setting')->get();
|
||||
$hide_chats = CompanyMeta::where('key', 'Hide Chat')->where('type', 'Chat Setting')->first();
|
||||
$canned_responses = CompanyMeta::where('key', 'Chat Canned Responses')->where('type', 'Chat Setting')->get();
|
||||
$abuses = CompanyMeta::where('key', 'ip_addresses')->where('type', 'Chat Setting')->get();
|
||||
return view('chat-setting', ['display_chats' => $display_chats, 'hide_chats' => $hide_chats, 'canned_responses' => $canned_responses, 'abuses' => $abuses]);
|
||||
}
|
||||
|
||||
public function storeFlowSetting(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
//Update Company Meta
|
||||
$flow_setting = [
|
||||
'show_profile_image_of_editors' => $request->show_profile_image_of_editors,
|
||||
'allow_visitor_to_send_messages' => $request->allow_visitor_to_send_messages,
|
||||
'max_number_of_chats_per_editor' => $request->max_number_of_chats_per_editor,
|
||||
'save_email_address_for_anonymous_chat' => $request->save_email_address_for_anonymous_chat,
|
||||
'delete_chat_data_automatically' => $request->delete_chat_data_automatically,
|
||||
'delay_for_automatic_deletion' => $request->delay_for_automatic_deletion,
|
||||
'allow_users_to_join_queue' => $request->allow_users_to_join_queue,
|
||||
'show_chat_button' => $request->show_chat_button,
|
||||
'visitor_can_send_images' => $request->visitor_can_send_images,
|
||||
'guest_must_write_name_and_email_to_chat' => $request->guest_must_write_name_and_email_to_chat,
|
||||
'logout_editor_who_missed_chat' => $request->logout_editor_who_missed_chat,
|
||||
'logout_everyone_automatically' => $request->logout_everyone_automatically,
|
||||
'chat_assistant_show_suggestion_form' => $request->chat_assistant_show_suggestion_form,
|
||||
'message_sent_to' => $request->message_sent_to,
|
||||
];
|
||||
|
||||
foreach($flow_setting as $key => $value) {
|
||||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
} else {
|
||||
CompanyMeta::where('key', $key)->where('company_id', $companyId)->where('type', 'Chat Setting')->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'Flow Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function storeDisplayChat(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'path' => 'required',
|
||||
'start_chat_after' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Collect data into an array
|
||||
$display_data = [
|
||||
'path' => $request->path,
|
||||
'start_chat_after' => $request->start_chat_after,
|
||||
];
|
||||
|
||||
CompanyMeta::create([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'Display Chat',
|
||||
'value' =>json_encode($display_data),
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Chat Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function deleteDisplayChat($id)
|
||||
{
|
||||
$display_chat = CompanyMeta::find($id);
|
||||
$display_chat->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Chat Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function storeHideChat(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'hide_chat_path' => 'required',
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
CompanyMeta::updateOrCreate([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'Hide Chat',
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => 'Hide Chat',
|
||||
'value' => $request->hide_chat_path,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Chat Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function storeText(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
//Update Company Meta
|
||||
$text_data = [
|
||||
'public_name' => $request->public_name,
|
||||
'internal_name' => $request->internal_name,
|
||||
'wellcome_text' => $request->wellcome_text,
|
||||
'wellcome_text_at_queue' => $request->wellcome_text_at_queue,
|
||||
'start_message' => $request->start_message,
|
||||
'text_in_message_box' => $request->text_in_message_box,
|
||||
'message_when_chat_is_closed' => $request->message_when_chat_is_closed
|
||||
];
|
||||
|
||||
foreach($text_data as $key => $value) {
|
||||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
} else {
|
||||
CompanyMeta::where('key', $key)->where('company_id', $companyId)->where('type', 'Chat Setting')->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['success' => 'Text Setting Updated Successfully']);
|
||||
}
|
||||
|
||||
public function storeStyle(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
//Update Company Meta
|
||||
$style_data = [
|
||||
'text_theme_color' => $request->text_theme_color,
|
||||
'background_theme_color' => $request->background_theme_color,
|
||||
'text_color_for_sent_message' => $request->text_color_for_sent_message,
|
||||
'background_color_of_sent_message' => $request->background_color_of_sent_message,
|
||||
'background_color_of_received_message' => $request->background_color_of_received_message,
|
||||
'text_color_of_received_message' => $request->text_color_of_received_message,
|
||||
'text_color_of_notification' => $request->text_color_of_notification,
|
||||
'text_color_of_error_message' => $request->text_color_of_error_message,
|
||||
'background_color_of_error_message' => $request->background_color_of_error_message,
|
||||
'link_color' => $request->link_color
|
||||
];
|
||||
|
||||
foreach($style_data as $key => $value) {
|
||||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
} else {
|
||||
CompanyMeta::where('key', $key)->where('company_id', $companyId)->where('type', 'Chat Setting')->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'Style Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function storeChatCannedResponses(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required',
|
||||
'text' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Collect data into an array
|
||||
$canned_data = [
|
||||
'name' => $request->name,
|
||||
'text' => $request->text,
|
||||
];
|
||||
|
||||
// Encode the data array as JSON
|
||||
$jsonData = json_encode($canned_data);
|
||||
|
||||
CompanyMeta::create([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'Chat Canned Responses',
|
||||
'value' => $jsonData,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Canned Response Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function deleteChatCannedResponses($id)
|
||||
{
|
||||
$get_chat_canned_response = CompanyMeta::find($id);
|
||||
$get_chat_canned_response->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Canned Response Deleted Successfully.');
|
||||
}
|
||||
|
||||
public function storePersonalData(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
//Update Company Meta
|
||||
$personal_data = [
|
||||
'name' => $request->name,
|
||||
'link_text' => $request->link_text,
|
||||
'active_approval' => $request->active_approval,
|
||||
];
|
||||
|
||||
foreach($personal_data as $key => $value) {
|
||||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
} else {
|
||||
CompanyMeta::where('key', $key)->where('company_id', $companyId)->where('type', 'Chat Setting')->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'Personal Data Updated Successfully');
|
||||
}
|
||||
|
||||
public function storeTags(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
//Update Company Meta
|
||||
$tags_data = [
|
||||
'new_tags_to_be_created_when_tagging' => $request->new_tags_to_be_created_when_tagging,
|
||||
];
|
||||
|
||||
foreach($tags_data as $key => $value) {
|
||||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
} else {
|
||||
CompanyMeta::where('key', $key)->where('company_id', $companyId)->where('type', 'Chat Setting')->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'Tags Updated Successfully');
|
||||
}
|
||||
|
||||
public function settingAllChat(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'heading_for_chat_flow' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => 'heading_for_chat_flow',
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => 'heading_for_chat_flow',
|
||||
'value' => $request->heading_for_chat_flow,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
return redirect()->back()->with('success', 'Chat Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function blockIpAdresses(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'ip_addresses' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
CompanyMeta::create([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'ip_addresses',
|
||||
'value' => $request->ip_addresses,
|
||||
'type' => 'Chat Setting'
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Chat Setting Updated Successfully');
|
||||
}
|
||||
|
||||
public function deleteBlockIpAdresses($id)
|
||||
{
|
||||
$get_ip_address = CompanyMeta::find($id);
|
||||
$get_ip_address->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'IP Address Deleted Successfully.');
|
||||
}
|
||||
|
||||
public function companyTermsAndConditions($companyId)
|
||||
{
|
||||
$link_text = getChatSetting('link_text', $companyId)->value;
|
||||
return view('terms-conditions', ['link_text' => $link_text]);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,9 +22,9 @@ public function storeCompany(Request $request)
|
|||
|
||||
if(Session::has('user_id') || Auth::id()) {
|
||||
|
||||
$messages = [
|
||||
$messages = [
|
||||
'company_domain.unique' => 'The domain has already been registered.',
|
||||
'company_domain.regex' => 'Please enter a valid domain format. e.g (example.com) wihtout https and /'
|
||||
'company_domain.regex' => 'Please enter a valid domain format, e.g., example.com (without https and /)'
|
||||
];
|
||||
|
||||
$this->validate($request, [
|
||||
|
|
@ -32,11 +32,12 @@ public function storeCompany(Request $request)
|
|||
'company_email' => 'required|email',
|
||||
'company_domain' => [
|
||||
'required',
|
||||
'regex:/^([a-zA-Z0-9]+(\.[a-zA-Z0-9]+)+.*)$/',
|
||||
'regex:/^([a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+)$/', // Updated regex
|
||||
'unique:companies,domain'
|
||||
],
|
||||
], $messages);
|
||||
|
||||
|
||||
$company = Company::updateOrCreate([
|
||||
'user_id' => Session::has('user_id') ? Session::get('user_id') : Auth::id(),
|
||||
],[
|
||||
|
|
|
|||
|
|
@ -8,30 +8,70 @@
|
|||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\CompanyMeta;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function dashboard()
|
||||
{
|
||||
$companyId = Session::get('selected_company');
|
||||
$company = Company::find($companyId);
|
||||
$tickets = Ticket::where('type', 'inbox')
|
||||
->where('to_email', 'LIKE', '%' . $company->domain)
|
||||
->get();
|
||||
return view('index', ['tickets' => $tickets]);
|
||||
$tickets = get_current_company_tickets(['type' => 'inbox']);
|
||||
$companyId = getSelectedCompany();
|
||||
$tags = getCompanyTags($companyId);
|
||||
$canned_response = $this->get_canned_responses();
|
||||
return view('index', ['tickets' => $tickets, 'tags' => $tags, 'canned_response' => $canned_response]);
|
||||
}
|
||||
|
||||
public function waiting()
|
||||
{
|
||||
$companyId = Session::get('selected_company');
|
||||
$company = Company::find($companyId);
|
||||
$tickets = Ticket::where('status', 'waiting')->where('type', 'chat')->where('to_email', 'LIKE', '%' . $company->domain)->get();
|
||||
return view('waiting', ['tickets' => $tickets]);
|
||||
public function get_canned_responses(){
|
||||
$companyId = getSelectedCompany();
|
||||
return CompanyMeta::where('company_id', $companyId)->where('key', 'canned_responses')->get();
|
||||
}
|
||||
|
||||
public function profile()
|
||||
{
|
||||
$users = User::where('role_id', '!=', 1)->where('id', '!=', Auth::id())->get();
|
||||
return view('profile', ['users' => $users]);
|
||||
$company = getSelectedCompany();
|
||||
$user = Auth::user();
|
||||
$users = $users = User::where('role_id', '!=', 1)
|
||||
//->where('id', '!=', Auth::id())
|
||||
->join('company_users', 'users.id', '=', 'company_users.user_id')
|
||||
->where('company_users.company_id', $company)
|
||||
->select('users.*')
|
||||
->get();
|
||||
return view('profile', ['users' => $users, 'user' => $user]);
|
||||
}
|
||||
|
||||
public function updateProfile(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'required|string',
|
||||
'profile_image' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if($request->hasFile('profile_image')) {
|
||||
|
||||
//Remove Old Image
|
||||
if ($user->profile_image) {
|
||||
$oldImagePath = str_replace('/storage/', '', $user->profile_image);
|
||||
Storage::disk('public')->delete($oldImagePath);
|
||||
}
|
||||
|
||||
//Store New Image
|
||||
$file = $request->file('profile_image');
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = time() . '_' . Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)) . '.' . $extension;
|
||||
$path = $file->storeAs('profile_images', $filename, 'public');
|
||||
|
||||
$user->profile_image = Storage::url($path);
|
||||
}
|
||||
|
||||
//update user
|
||||
$user->name = $request->name;
|
||||
$user->save();
|
||||
|
||||
return back()->with('success', 'Profile Updated Successfully');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,23 +6,43 @@
|
|||
use App\Models\Timezone;
|
||||
use App\Models\User;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Response;
|
||||
use App\Models\Language;
|
||||
use App\Models\Tag;
|
||||
use App\Models\Rule;
|
||||
use App\Models\CompanyMeta;
|
||||
use App\Models\CompanyUser;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class InboxController extends Controller
|
||||
|
||||
{
|
||||
public function get_canned_responses(){
|
||||
$companyId = getSelectedCompany();
|
||||
return CompanyMeta::where('company_id', $companyId)->where('key', 'canned_responses')->get();
|
||||
}
|
||||
|
||||
|
||||
public function inboxSetting()
|
||||
{
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
$timezones = Timezone::all();
|
||||
$languages = Language::all();
|
||||
$languages = Language::where('title', 'English (US)')->get();
|
||||
$basic_setting = CompanyMeta::where('company_id', $companyId)->where('type', 'Basic Setting')->get();
|
||||
$canned_response = CompanyMeta::where('company_id', $companyId)->where('type', 'Canned Response')->first();
|
||||
$canned_response = $this->get_canned_responses();
|
||||
$spam_handling = CompanyMeta::where('company_id', $companyId)->where('type', 'Spam Handling')->first();
|
||||
$email_signature = CompanyMeta::where('company_id', $companyId)->where('type', 'Email Signature')->first();
|
||||
$company_users = get_company_users($companyId);
|
||||
$tags = Tag::where('company_id', $companyId)->get();
|
||||
$rule = Rule::where('company_id', $companyId)->first();
|
||||
|
||||
|
||||
return view('inbox-setting', ['timezones' => $timezones, 'basic_setting' => $basic_setting, 'spam_handling' => $spam_handling,
|
||||
'email_signature' => $email_signature, 'canned_response' => $canned_response, 'languages' => $languages]);
|
||||
'email_signature' => $email_signature, 'canned_response' => $canned_response, 'languages' => $languages, 'company' => get_company('id',$companyId),
|
||||
'company_users' => $company_users, 'tags' => $tags, 'rule' => $rule]);
|
||||
}
|
||||
|
||||
public function basicSetting(Request $request)
|
||||
|
|
@ -36,7 +56,7 @@ public function basicSetting(Request $request)
|
|||
'timezone' => ['required'],
|
||||
]);
|
||||
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
//Update Company Meta
|
||||
$basic_data = [
|
||||
|
|
@ -50,9 +70,9 @@ public function basicSetting(Request $request)
|
|||
foreach($basic_data as $key => $value) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'value' => $value
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Basic Setting'
|
||||
|
|
@ -68,13 +88,11 @@ public function emailSignature(Request $request)
|
|||
'email_signature' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => 'email_signature',
|
||||
'value' => $request->email_signature
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => 'email_signature',
|
||||
'value' => $request->email_signature,
|
||||
'type' => 'Email Signature'
|
||||
]);
|
||||
|
|
@ -84,7 +102,7 @@ public function emailSignature(Request $request)
|
|||
|
||||
public function responseTime(Request $request)
|
||||
{
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
//Update Company Meta
|
||||
$response_data = [
|
||||
'monday_start_time' => $request->monday_start_time,
|
||||
|
|
@ -115,9 +133,9 @@ public function responseTime(Request $request)
|
|||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'value' => $value
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'type' => 'Response Time'
|
||||
|
|
@ -137,36 +155,34 @@ public function cannedResponse(Request $request)
|
|||
'text' => 'required'
|
||||
]);
|
||||
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Collect data into an array
|
||||
$canned_data = [
|
||||
$canned_data =
|
||||
[
|
||||
'name' => $request->name,
|
||||
'text' => $request->text,
|
||||
]
|
||||
];
|
||||
];
|
||||
|
||||
// Retrieve existing canned responses
|
||||
$existingMeta = CompanyMeta::where('company_id', $companyId)
|
||||
->where('key', 'canned_responses')
|
||||
->where('type', 'Canned Response')
|
||||
->first();
|
||||
// $existingMeta = CompanyMeta::where('company_id', $companyId)
|
||||
// ->where('key', 'canned_responses')
|
||||
// ->where('type', 'Canned Response')
|
||||
// ->first();
|
||||
|
||||
// Decode existing JSON data if it exists
|
||||
if ($existingMeta) {
|
||||
$existingData = json_decode($existingMeta->value, true);
|
||||
$canned_data = array_merge($existingData, $canned_data);
|
||||
}
|
||||
// // Decode existing JSON data if it exists
|
||||
// if ($existingMeta) {
|
||||
// $existingData = json_decode($existingMeta->value, true);
|
||||
// $canned_data = array_merge($existingData, $canned_data);
|
||||
// }
|
||||
|
||||
// Encode the data array as JSON
|
||||
// // Encode the data array as JSON
|
||||
$jsonData = json_encode($canned_data);
|
||||
|
||||
// Update or create the CompanyMeta entry
|
||||
CompanyMeta::updateOrCreate([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'canned_responses',
|
||||
], [
|
||||
|
||||
|
||||
CompanyMeta::create([
|
||||
'company_id' => $companyId,
|
||||
'key' => 'canned_responses',
|
||||
'value' => $jsonData,
|
||||
|
|
@ -178,27 +194,26 @@ public function cannedResponse(Request $request)
|
|||
|
||||
public function deleteCannedResponse($index)
|
||||
{
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Retrieve the existing canned responses
|
||||
$cannedMeta = CompanyMeta::where('company_id', $companyId)
|
||||
CompanyMeta::where('company_id', $companyId)
|
||||
->where('key', 'canned_responses')
|
||||
->where('type', 'Canned Response')
|
||||
->first();
|
||||
->where('id', $index)
|
||||
->delete();
|
||||
|
||||
if ($cannedMeta) {
|
||||
$canned_data = json_decode($cannedMeta->value, true);
|
||||
// if ($cannedMeta) {
|
||||
// $canned_data = json_decode($cannedMeta->value, true);
|
||||
|
||||
if (isset($canned_data[$index])) {
|
||||
unset($canned_data[$index]);
|
||||
// if (isset($canned_data[$index])) {
|
||||
// unset($canned_data[$index]);
|
||||
|
||||
$canned_data = array_values($canned_data);
|
||||
$jsonData = json_encode($canned_data);
|
||||
// $canned_data = array_values($canned_data);
|
||||
// $jsonData = json_encode($canned_data);
|
||||
|
||||
$cannedMeta->value = $jsonData;
|
||||
$cannedMeta->save();
|
||||
}
|
||||
}
|
||||
// $cannedMeta->value = $jsonData;
|
||||
// $cannedMeta->save();
|
||||
// }
|
||||
// }
|
||||
|
||||
return redirect()->back()->with('success', 'Canned response deleted successfully.');
|
||||
|
||||
|
|
@ -206,7 +221,7 @@ public function deleteCannedResponse($index)
|
|||
|
||||
public function acknowledgementReceipt(Request $request)
|
||||
{
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
//Update Company Meta
|
||||
$acknowledgement_data = [
|
||||
'automatic_reply_subject' => $request->automatic_reply_subject,
|
||||
|
|
@ -220,10 +235,10 @@ public function acknowledgementReceipt(Request $request)
|
|||
if(!is_null($value)) {
|
||||
CompanyMeta::updateOrCreate([
|
||||
'key' => $key,
|
||||
'value' => $value
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'key' => $key,
|
||||
],[
|
||||
|
||||
|
||||
'value' => $value,
|
||||
'type' => 'Acknowledgement of Receipt'
|
||||
]);
|
||||
|
|
@ -241,7 +256,7 @@ public function spamHandling(Request $request)
|
|||
'spam_email' => 'required|email'
|
||||
]);
|
||||
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Collect data into an array
|
||||
$canned_data = [
|
||||
|
|
@ -282,7 +297,7 @@ public function spamHandling(Request $request)
|
|||
|
||||
public function deleteSpamHandling($index)
|
||||
{
|
||||
$companyId = Auth::user()->company->id;
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
// Retrieve the existing canned responses
|
||||
$spamMeta = CompanyMeta::where('company_id', $companyId)
|
||||
|
|
@ -309,9 +324,20 @@ public function deleteSpamHandling($index)
|
|||
|
||||
public function inbox()
|
||||
{
|
||||
$tickets = Ticket::orderBy('id', 'desc')->with('lastResponse')->get();
|
||||
$tickets = get_current_company_tickets([
|
||||
|
||||
'type' => 'inbox',
|
||||
'orderby' => 'id',
|
||||
'order' => 'desc',
|
||||
'with' => 'lastResponse'
|
||||
|
||||
]);
|
||||
|
||||
|
||||
$messages = [];
|
||||
return view('inbox', ['tickets' => $tickets, 'messages' => $messages]);
|
||||
$canned_response = $this->get_canned_responses();
|
||||
|
||||
return view('inbox', ['tickets' => $tickets, 'messages' => $messages, 'canned_response' => $canned_response]);
|
||||
}
|
||||
|
||||
public function fetchChatMessages($ticketId)
|
||||
|
|
@ -324,8 +350,104 @@ public function fetchChatMessages($ticketId)
|
|||
|
||||
public function fetchActionBox($ticketId)
|
||||
{
|
||||
$selectedCompany = getSelectedCompany();
|
||||
$ticket = Ticket::where('id', $ticketId)->with('comments')->first();
|
||||
$companyUsers = get_company_users($selectedCompany);//CompanyUser::where('company_id', $selectedCompany)->with('user')->get();
|
||||
|
||||
return view('partials.action-box', compact('ticket'))->render();
|
||||
return view('partials.action-box', compact('ticket','companyUsers'))->render();
|
||||
}
|
||||
|
||||
public function storeResponse(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'message' => 'required',
|
||||
'ticket_id' => 'required',
|
||||
]);
|
||||
|
||||
// Handle both single and multiple ticket IDs
|
||||
$ticket_ids = explode(',', $request->ticket_id);
|
||||
|
||||
$messageWithClasses = $request->message;
|
||||
|
||||
foreach ($ticket_ids as $ticket_id) {
|
||||
$response = createResponse($ticket_id, $messageWithClasses, 1);
|
||||
|
||||
$ticket = Ticket::find($ticket_id);
|
||||
|
||||
if (!$ticket) continue;
|
||||
|
||||
$companyId = Session::get('selected_company');
|
||||
$company = get_company('id', $companyId);
|
||||
|
||||
// Send mail to mailgun
|
||||
$domain = $company->domain;
|
||||
$company_name = $company->getMeta('sender_name') ?? $company->name;
|
||||
$from = "$company_name <$company->email>";
|
||||
$to = $ticket->from_email;
|
||||
$subject = $ticket->subject;
|
||||
$html = $request->message;
|
||||
|
||||
// Call the function to send the email
|
||||
sendEmailViaMailgun($domain, $from, $to, $subject, $html);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => strip_tags($response->message),
|
||||
'created_at' => $response->created_at->format('h:i A')
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function storeComment(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'ticket_id' => 'required|exists:tickets,id',
|
||||
'comment' => 'required|string',
|
||||
]);
|
||||
|
||||
// Assuming authenticated user
|
||||
$user_id = auth()->id();
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->author = $user_id;
|
||||
$comment->ticket_id = $request->ticket_id;
|
||||
$comment->comment = $request->comment;
|
||||
$comment->save();
|
||||
|
||||
return $comment;
|
||||
}
|
||||
|
||||
public function deleteComment($commentId)
|
||||
{
|
||||
$comment = Comment::findOrFail($commentId);
|
||||
$comment->delete();
|
||||
|
||||
return response()->json(['message' => 'Comment Deleted Successfully']);
|
||||
}
|
||||
|
||||
public function updateRule(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
//Update Rule
|
||||
Rule::updateOrCreate([
|
||||
'company_id' => $companyId,
|
||||
],[
|
||||
'company_id' => $companyId,
|
||||
'from' => $request->from,
|
||||
'to' => $request->to,
|
||||
'subject_contains' => $request->subject_contains,
|
||||
'text_contains' => $request->text_contains,
|
||||
'subject1_contains' => $request->subject1_contains,
|
||||
'tag_id' => $request->tag_id,
|
||||
'name' => $request->name,
|
||||
'assign_to' => $request->assign_to,
|
||||
'status' => isset($request->status) ? $request->status : 'set as done',
|
||||
'priority' => isset($request->priority) ? $request->priority : 'Set highest priority',
|
||||
'message_to_assigned_editor' => $request->message_to_assigned_editor,
|
||||
'all_emails_automatically_mark_as_spam' => $request->all_emails_automatically_mark_as_spam,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Setting Updated successfully.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,39 +4,139 @@
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Response;
|
||||
|
||||
class EmailController extends Controller
|
||||
{
|
||||
public function saveEmail(Request $request){
|
||||
|
||||
$token = $request->input('token');
|
||||
$timestamp = $request->input('timestamp');
|
||||
$signature = $request->input('signature');
|
||||
|
||||
// DB::beginTransaction();
|
||||
|
||||
// if (!verifyMailgunSignature($token, $timestamp, $signature)) {
|
||||
// abort(403, 'Invalid signature.');
|
||||
// }
|
||||
// try {
|
||||
|
||||
$file_urls = [];
|
||||
$token = $request->input('token');
|
||||
$timestamp = $request->input('timestamp');
|
||||
$signature = $request->input('signature');
|
||||
|
||||
$data = $this->extractMailgunData($request->all());
|
||||
|
||||
insertTicket($data['from_email'], $data['to_email'], $data['subject'], $data['message'] );
|
||||
|
||||
update_setting('aw_test',json_encode($request->all()));
|
||||
if (!verifyMailgunSignature($token, $timestamp, $signature)) {
|
||||
update_setting('aw_test','Invalid signature.');
|
||||
abort(403, 'Invalid signature.');
|
||||
}
|
||||
update_setting('aw_test',json_encode($request->all()));
|
||||
|
||||
$data = $this->extractMailgunData($request->all());
|
||||
|
||||
|
||||
|
||||
$to_email = $data['to_email'];
|
||||
$message = $data['message'];
|
||||
|
||||
//update_setting('aw_test',$to_email);
|
||||
|
||||
$company = get_company('email',$to_email);
|
||||
|
||||
if($company){
|
||||
$ticket = insertTicket($data['from_email'], $company->email, $data['subject'], $message,'inbox',$data['from_name'] );
|
||||
if($ticket){
|
||||
|
||||
//Check Email if it is spam
|
||||
$get_spam_handlings = getResponse($company->id,'spam_handling', 'Spam Handling');
|
||||
if(!is_null($get_spam_handlings)) {
|
||||
//pluck spam emails
|
||||
$values = json_decode($get_spam_handlings->value, true);
|
||||
$spam_emails = array_map(function ($item) {
|
||||
return $item['spam_email'];
|
||||
}, $values);
|
||||
if(in_array($data['from_email'], $spam_emails)) {
|
||||
//update status
|
||||
$ticket->status = 'spam';
|
||||
$ticket->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->sendEmail($company,$ticket->id);
|
||||
|
||||
$response = createResponse($ticket->id,$message);
|
||||
|
||||
$attachmentCount = $request->input('attachment-count', 0);
|
||||
|
||||
|
||||
for ($i = 1; $i <= $attachmentCount; $i++) {
|
||||
$attachment = $request->file("attachment-$i");
|
||||
// update_setting('aw_test',$attachment->getClientOriginalName());
|
||||
if ($attachment && $attachment->isValid()) {
|
||||
// Define a unique filename, possibly using the original filename and appending a timestamp or a unique id
|
||||
$filename = time() . '_' . $attachment->getClientOriginalName();
|
||||
|
||||
// Save the attachment to the local or specific disk
|
||||
$filePath = $attachment->storeAs('tickets/' . $ticket->id, $filename, 'public');
|
||||
$fileUrl = Storage::url($filePath);
|
||||
$file_urls[] = $fileUrl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Update Responses Table with Attachments
|
||||
if(count($file_urls) > 0) {
|
||||
$response->attachments = json_encode($file_urls);
|
||||
$response->save();
|
||||
}
|
||||
|
||||
}
|
||||
}else{}
|
||||
|
||||
//update_setting('aw_test',json_encode($request->all()));
|
||||
|
||||
// DB::commit();
|
||||
// } catch (\Exception $e) {
|
||||
|
||||
// DB::rollBack();
|
||||
// update_setting('aw_test',json_encode($e->getMessage()));
|
||||
// sendEmailViaMailgun( 'ai.rapidev.tech', 'support@ai.rapidev.tech', '16bsse18212@gmail.com', 'error', json_encode($e->getMessage()));
|
||||
// // Handle the exception
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
private function sendEmail($company,$ticketId)
|
||||
{
|
||||
$ticket = Ticket::find($ticketId);
|
||||
$responses = Response::where('ticket_id', $ticket->id)->get();
|
||||
$activate_delivery_confirmation = getCompanyMeta($company->id,'activate_delivery_confirmation');
|
||||
$subject = getCompanyMeta($company->id,'automatic_reply_subject');
|
||||
$subject = str_replace(['{title}', '{ticket}'], [$ticket->subject, $ticket->id], $subject);
|
||||
$message = getCompanyMeta($company->id,'automatic_reply_text');
|
||||
$message = str_replace(['{title}', '{text}', '{ticket}', '{name}'], [$ticket->subject, $ticket->content, $ticket->id, $ticket->sender_name], $message);
|
||||
if ($ticket && count($responses) == 0 && !is_null($subject) && !is_null($message) && $activate_delivery_confirmation == 'on') {
|
||||
|
||||
$company_name = $company->getMeta('sender_name')??$company->name;
|
||||
$from = "$company_name <$company->email>";
|
||||
|
||||
sendEmailViaMailgun($company->domain, $from, $ticket->from_email, $subject, $message);
|
||||
}
|
||||
//Update Ticket With Subject2
|
||||
$ticket->subject2 = $subject;
|
||||
$ticket->save();
|
||||
}
|
||||
|
||||
|
||||
public function extractMailgunData($data) {
|
||||
// Decode the JSON payload into an associative array
|
||||
// $data = json_decode($jsonPayload, true);
|
||||
|
||||
|
||||
// Prepare an array to hold the extracted data
|
||||
|
||||
$from = extractEmail($data['from']);
|
||||
$to = extractEmail($data['To']);
|
||||
|
||||
$extractedData = [
|
||||
'from_email' => $data['from'],
|
||||
'to_email' => $data['To'],
|
||||
'from_email' => $from,
|
||||
'to_email' => $to,
|
||||
'from_name' => '', // This will be extracted from the 'from' field
|
||||
'subject' => $data['subject'],
|
||||
'message' => $data['body-plain'],
|
||||
'message' => isset($data['body-html'])?$data['body-html']:$data['body-plain'],
|
||||
'mime_version' => $data['Mime-Version'],
|
||||
'dkim_signature' => $data['Dkim-Signature']
|
||||
];
|
||||
|
|
@ -46,7 +146,7 @@ public function extractMailgunData($data) {
|
|||
$extractedData['from_name'] = $matches[1];
|
||||
$extractedData['from_email'] = $matches[2];
|
||||
}
|
||||
|
||||
|
||||
return $extractedData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,14 +5,35 @@
|
|||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\MailgunService;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Services\CPanelApiService;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
||||
class MailgunController extends Controller
|
||||
{
|
||||
protected $mailgunService;
|
||||
protected $cpanelApiService;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->mailgunService = app(MailgunService::class); // Resolving through the service container
|
||||
$this->cpanelApiService = app(CPanelApiService::class);
|
||||
}
|
||||
|
||||
public function test(){
|
||||
$domain = 'test.com';
|
||||
$email = "kundesone.$domain@mailgun.kundesone.no";
|
||||
|
||||
$company = get_company('id',14);
|
||||
|
||||
// $folderPath = 'tickets/51'; // Adjust the path according to your structure
|
||||
|
||||
// if (Storage::disk('public')->exists($folderPath)) {
|
||||
// Storage::disk('public')->deleteDirectory($folderPath);
|
||||
// }
|
||||
|
||||
dd($company->getMeta('sender_name'));
|
||||
}
|
||||
|
||||
public function addDomain($domain)
|
||||
|
|
@ -33,7 +54,7 @@ public function addDomain($domain)
|
|||
|
||||
$response = $this->mailgunService->addDomain($domain);
|
||||
|
||||
return route('showDomain',$domain)->redirect();
|
||||
return redirect()->route('showDomain',$domain);
|
||||
|
||||
}else{
|
||||
return redirect()->route('showDomain',$domain);
|
||||
|
|
@ -60,16 +81,33 @@ public function showDomain($domain){
|
|||
public function verifyDomain(Request $request)
|
||||
{
|
||||
$domain = $request->input('domain');
|
||||
$response = $this->mailgunService->verifyDomain($domain);
|
||||
|
||||
$result = $this->is_domain_verified($domain);
|
||||
|
||||
if($result){
|
||||
$email = "kundesone.$domain@mailgun.kundesone.no";
|
||||
$this->createEmail($domain);
|
||||
|
||||
|
||||
return redirect('/dashboard');
|
||||
}else{
|
||||
return redirect()->route('showDomain',$domain);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function is_domain_verified($domain){
|
||||
|
||||
$response = $this->mailgunService->verifyDomain($domain);
|
||||
|
||||
$state = $response->getDomain()->getState();
|
||||
|
||||
if($state == 'unverified'){
|
||||
return redirect()->route('showDomain',$domain);
|
||||
return false;
|
||||
}elseif($state == 'active'){
|
||||
$this->createRoute($request);
|
||||
|
||||
return redirect('/dashboard');
|
||||
//$this->createRoute($request);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -81,6 +119,30 @@ public function createRoute(Request $request)
|
|||
$response = $this->mailgunService->createRoute($domain, $forwardUrl);
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function createEmail($domain){
|
||||
|
||||
$email = "kundesone.$domain@mailgun.kundesone.no";
|
||||
$password = Str::random(12);
|
||||
$quota = 0;
|
||||
|
||||
$response = $this->cpanelApiService->createEmailAccount($domain, $email, $password, $quota);
|
||||
|
||||
if (isset($response['error'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$company = get_company('domain',$domain);
|
||||
|
||||
if($company){
|
||||
$company->internal_email = $email;
|
||||
$company->save();
|
||||
}
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,52 +4,65 @@
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketMeta;
|
||||
use App\Models\TicketNote;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Response;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyMeta;
|
||||
use App\Models\Tag;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class TicketController extends Controller
|
||||
{
|
||||
public function allTickets()
|
||||
{
|
||||
$tickets = Ticket::all();
|
||||
return view('all-tickets', ['tickets' => $tickets]);
|
||||
public function get_canned_responses(){
|
||||
$companyId = getSelectedCompany();
|
||||
return CompanyMeta::where('company_id', $companyId)->where('key', 'canned_responses')->get();
|
||||
}
|
||||
|
||||
public function storeResponse(Request $request)
|
||||
public function allTickets()
|
||||
{
|
||||
$this->validate($request, [
|
||||
'message' => 'required'
|
||||
]);
|
||||
|
||||
// Load the HTML content into DOMDocument
|
||||
$dom = new \DOMDocument();
|
||||
libxml_use_internal_errors(true); // Prevents HTML errors from being thrown as exceptions
|
||||
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $request->message);
|
||||
libxml_clear_errors();
|
||||
$companyId = getSelectedCompany();
|
||||
$tickets = get_current_company_tickets(['type' => 'chat']);
|
||||
$tags = Tag::where('company_id', $companyId)->get();
|
||||
return view('all-tickets', ['tickets' => $tickets, 'tags' => $tags]);
|
||||
}
|
||||
|
||||
// Get all <p> tags
|
||||
$paragraphs = $dom->getElementsByTagName('p');
|
||||
public function waiting()
|
||||
{
|
||||
|
||||
$tickets = get_current_company_tickets(['status' => 'waiting']);
|
||||
return view('waiting', ['tickets' => $tickets]);
|
||||
}
|
||||
|
||||
// Add classes to each <p> tag
|
||||
foreach ($paragraphs as $paragraph) {
|
||||
$existingClasses = $paragraph->getAttribute('class');
|
||||
$paragraph->setAttribute('class', trim($existingClasses . ' user-message bg-light-green-color color-light'));
|
||||
}
|
||||
|
||||
// Save the modified HTML
|
||||
$messageWithClasses = $dom->saveHTML($dom->documentElement);
|
||||
public function showTicket($id)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
$tickets = get_current_company_tickets([
|
||||
|
||||
'type' => 'inbox',
|
||||
'orderby' => 'id',
|
||||
'order' => 'desc',
|
||||
'with' => 'lastResponse'
|
||||
|
||||
]);
|
||||
|
||||
$single_ticket = Ticket::find($id);
|
||||
|
||||
|
||||
$messages = [];
|
||||
$canned_response = $this->get_canned_responses();
|
||||
$email_signature = CompanyMeta::where('company_id', $companyId)->where('type', 'Email Signature')->first();
|
||||
|
||||
$response = new Response;
|
||||
$response->message = $messageWithClasses;
|
||||
$response->ticket_id = $request->ticket_id;
|
||||
$response->user_id = 1;
|
||||
$response->save();
|
||||
|
||||
// Return the updated response and time
|
||||
return response()->json([
|
||||
'message' => strip_tags($response->message), // Stripping HTML tags
|
||||
'created_at' => $response->created_at->format('h:i A') // Formatting time
|
||||
return view('show-ticket', [
|
||||
'tickets' => $tickets,
|
||||
'single_ticket' => $single_ticket,
|
||||
'messages' => $messages,
|
||||
'canned_response' => $canned_response,
|
||||
'email_signature' => $email_signature?$email_signature->value:''
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -67,22 +80,257 @@ public function updateStatus(Request $request, $ticketId)
|
|||
return response()->json(['message' => 'Ticket status updated successfully']);
|
||||
}
|
||||
|
||||
public function storeComment(Request $request)
|
||||
public function updateTicket(Request $request, $ticketId)
|
||||
{
|
||||
$request->validate([
|
||||
'ticket_id' => 'required|exists:tickets,id',
|
||||
'comment' => 'required|string',
|
||||
]);
|
||||
|
||||
// Assuming authenticated user
|
||||
$user_id = auth()->id();
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->author = $user_id;
|
||||
$comment->ticket_id = $request->ticket_id;
|
||||
$comment->comment = $request->comment;
|
||||
$comment->save();
|
||||
$ticket = Ticket::find($ticketId);
|
||||
//Update Ticket
|
||||
if(isset($request->priority)) {
|
||||
$ticket->priority = $request->priority;
|
||||
}
|
||||
if(isset($request->user_assigned)) {
|
||||
$ticket->user_assigned = $request->user_assigned;
|
||||
}
|
||||
$ticket->save();
|
||||
|
||||
return $comment;
|
||||
return response()->json(['success' => true, 'message' => 'Ticket Updated successfully!']);
|
||||
}
|
||||
|
||||
public function storeTags(Request $request)
|
||||
{
|
||||
$company = getSelectedCompany();
|
||||
$ticket_id = $request->ticket_id;
|
||||
|
||||
$tags = json_decode($request->tags);
|
||||
|
||||
TicketMeta::where('key','tags')->where('ticket_id',$ticket_id)->delete();
|
||||
|
||||
foreach($tags as $tag)
|
||||
{
|
||||
|
||||
TicketMeta::create(
|
||||
['ticket_id' => $ticket_id, 'key' => 'tags',
|
||||
'value' => $tag->value, 'type' => 'string']
|
||||
);
|
||||
|
||||
//Update Tags Table
|
||||
Tag::updateOrCreate([
|
||||
'company_id' => $company,
|
||||
'name' => $tag->value
|
||||
],[
|
||||
'company_id' => $company,
|
||||
'name' => $tag->value,
|
||||
'type' => 'inbox'
|
||||
]);
|
||||
|
||||
|
||||
|
||||
//Update Company Meta Table
|
||||
|
||||
|
||||
|
||||
// CompanyMeta::updateOrCreate([
|
||||
// 'company_id' => $company,
|
||||
// 'value' => $tag->value
|
||||
// ],[
|
||||
// 'company_id' => $company,
|
||||
// 'value' => $tag->value,
|
||||
// 'key' => 'tag',
|
||||
// 'type' => 'tags'
|
||||
// ]);
|
||||
}
|
||||
|
||||
return response()->json(['success' => true, 'message' => 'Tags Added Successfully']);
|
||||
}
|
||||
|
||||
public function AssignTicket(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'user_assigned' => 'required|integer',
|
||||
'message' => 'required|string',
|
||||
'ticket_ids' => 'required|string',
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
$ticketIds = explode(',', $request->ticket_ids);
|
||||
foreach ($ticketIds as $ticket_id) {
|
||||
$ticket = Ticket::find($ticket_id);
|
||||
|
||||
if ($ticket) {
|
||||
// Update Ticket
|
||||
$ticket->user_assigned = $request->user_assigned;
|
||||
$ticket->save();
|
||||
|
||||
//Send Mail
|
||||
$company = Company::find($companyId);
|
||||
sendEmailViaMailgun($company->domain, $company->email, $ticket->from_email, $ticket->subject, $request->message);
|
||||
//Create Response
|
||||
$formattedMessage = '<p>' . $request->message . '</p>';
|
||||
createResponse($ticket_id,$formattedMessage,auth()->id());
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['success' => true, 'message' => 'Post Assigned Successfully']);
|
||||
}
|
||||
|
||||
public function deleteTickets(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'ticket_ids' => 'required|string',
|
||||
]);
|
||||
|
||||
$ticketIds = explode(',', $request->ticket_ids);
|
||||
foreach ($ticketIds as $ticket_id) {
|
||||
$ticket = Ticket::find($ticket_id);
|
||||
|
||||
if ($ticket) {
|
||||
// Delete Ticket
|
||||
Comment::where('ticket_id', $ticket_id)->delete();
|
||||
TicketMeta::where('ticket_id', $ticket_id)->delete();
|
||||
Response::where('ticket_id', $ticket_id)->delete();
|
||||
TicketNote::where('ticket_id', $ticket_id)->delete();
|
||||
//Delete Attachments
|
||||
$folderPath = "tickets/$ticket_id"; // Adjust the path according to your structure
|
||||
|
||||
if (Storage::disk('public')->exists($folderPath)) {
|
||||
Storage::disk('public')->deleteDirectory($folderPath);
|
||||
}
|
||||
$ticket->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['success' => true, 'message' => 'Tickets Deleted Successfully']);
|
||||
}
|
||||
|
||||
public function updateTicketStatus(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'ticket_ids' => 'required|string',
|
||||
'status' => 'required|string'
|
||||
]);
|
||||
|
||||
$ticketIds = explode(',', $request->ticket_ids);
|
||||
foreach ($ticketIds as $ticket_id) {
|
||||
$ticket = Ticket::find($ticket_id);
|
||||
|
||||
if ($ticket) {
|
||||
// Delete Ticket
|
||||
$ticket->status = $request->status;
|
||||
$ticket->save();
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['success' => true, 'message' => 'Tickets Status Updated Successfully']);
|
||||
}
|
||||
|
||||
public function filter(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'filter' => 'required|string',
|
||||
'status' => 'required|string',
|
||||
]);
|
||||
|
||||
$companyId = getSelectedCompany();
|
||||
$company = get_company('id',$companyId);
|
||||
$now = \Carbon\Carbon::now();
|
||||
|
||||
if(isset($request->type)) {
|
||||
$tickets = Ticket::where('to_email', $company->email)->where('type', $request->type)->where('status', '!=', 'done')->orderBy('created_at','desc');
|
||||
} else {
|
||||
$tickets = Ticket::where('to_email', $company->email)->where('status', '!=', 'done')->orderBy('created_at','desc');
|
||||
}
|
||||
|
||||
if($request->filter == 'Assigned to') {
|
||||
$all_tickets = $tickets->where('user_assigned', $request->status)->get();
|
||||
return response()->json(['tickets' => $all_tickets]);
|
||||
} elseif($request->filter == 'With activity') {
|
||||
|
||||
if ($request->status === 'last 24 hours') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subDay());
|
||||
} elseif ($request->status === 'last 3 days') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subDays(3));
|
||||
} elseif ($request->status === 'last week') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subWeek());
|
||||
} elseif ($request->status === 'last month') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subMonth());
|
||||
} elseif ($request->status === 'last 3 months') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subMonths(3));
|
||||
} elseif ($request->status === 'last 6 months') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subMonths(6));
|
||||
} elseif ($request->status === 'last year') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subYear());
|
||||
} elseif ($request->status === 'the past 2 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subYears(2));
|
||||
} elseif ($request->status === 'the past 3 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subYears(3));
|
||||
} elseif ($request->status === 'the past 4 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subYears(4));
|
||||
} elseif ($request->status === 'the past 5 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '>=', $now->subYears(5));
|
||||
}
|
||||
|
||||
$activity_tickets = $all_tickets->get();
|
||||
return response()->json(['tickets' => $activity_tickets]);
|
||||
} elseif($request->filter == 'No activity') {
|
||||
|
||||
if ($request->status === 'last 24 hours') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subDay());
|
||||
} elseif ($request->status === 'last 3 days') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subDays(3));
|
||||
} elseif ($request->status === 'last week') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subWeek());
|
||||
} elseif ($request->status === 'last month') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subMonth());
|
||||
} elseif ($request->status === 'last 3 months') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subMonths(3));
|
||||
} elseif ($request->status === 'last 6 months') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subMonths(6));
|
||||
} elseif ($request->status === 'last year') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subYear());
|
||||
} elseif ($request->status === 'the past 2 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subYears(2));
|
||||
} elseif ($request->status === 'the past 3 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subYears(3));
|
||||
} elseif ($request->status === 'the past 4 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subYears(4));
|
||||
} elseif ($request->status === 'the past 5 years') {
|
||||
$all_tickets = $tickets->where('updated_at', '<=', $now->subYears(5));
|
||||
}
|
||||
|
||||
|
||||
$no_activity_tickets = $all_tickets->get();
|
||||
return response()->json(['tickets' => $no_activity_tickets]);
|
||||
} elseif($request->filter == 'Spam') {
|
||||
if($request->status == 'marked as spam') {
|
||||
$all_tickets = $tickets->where('status', 'spam')->get();
|
||||
return response()->json(['tickets' => $all_tickets]);
|
||||
} else {
|
||||
$all_tickets = $tickets->where('status', '!=', 'spam')->get();
|
||||
return response()->json(['tickets' => $all_tickets]);
|
||||
}
|
||||
} elseif($request->filter == 'Status') {
|
||||
$all_tickets = $tickets->where('status', $request->status)->get();
|
||||
return response()->json(['tickets' => $all_tickets]);
|
||||
} elseif($request->filter == 'Tags') {
|
||||
$ticket_meta = TicketMeta::where('value', $request->status)->pluck('ticket_id')->toArray();
|
||||
if(isset($request->type)) {
|
||||
$all_tickets = Ticket::where('to_email', $company->email)->where('type', $request->type)->where('status', '!=', 'done')->orderBy('created_at','desc')->whereIn('id', $ticket_meta)->get();
|
||||
} else {
|
||||
$all_tickets = Ticket::where('to_email', $company->email)->orderBy('created_at','desc')->where('status', '!=', 'done')->whereIn('id', $ticket_meta)->get();
|
||||
}
|
||||
return response()->json(['tickets' => $all_tickets]);
|
||||
}
|
||||
}
|
||||
|
||||
public function defaultAllTickets(Request $request)
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
$company = get_company('id',$companyId);
|
||||
if(isset($request->type)) {
|
||||
$tickets = get_current_company_tickets(['type' => $request->type]);
|
||||
} else {
|
||||
$tickets = get_current_company_tickets();
|
||||
}
|
||||
return response()->json(['tickets' => $tickets]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Models\CompanyUser;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
|
@ -15,6 +18,8 @@ public function addUser(Request $request)
|
|||
'email' => ['required', 'email', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:8'],
|
||||
]);
|
||||
|
||||
$company = getSelectedCompany();
|
||||
|
||||
$user = new User;
|
||||
$user->role_id = 3;
|
||||
|
|
@ -22,6 +27,15 @@ public function addUser(Request $request)
|
|||
$user->email = $request->email;
|
||||
$user->password = Hash::make($request->password);
|
||||
$user->save();
|
||||
|
||||
//Update Company User
|
||||
CompanyUser::updateOrCreate([
|
||||
'user_id' => $user->id
|
||||
],[
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company,
|
||||
'access' => json_encode($request->access)
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'User Added Successfully');
|
||||
}
|
||||
|
|
@ -32,4 +46,31 @@ public function deleteUser($id)
|
|||
$user->delete();
|
||||
return redirect()->back()->with('success', 'User Deleted Successfully');
|
||||
}
|
||||
|
||||
public function updateChatAvailability(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
//update user
|
||||
if($request->status == "on") {
|
||||
$user->is_available = 1;
|
||||
$user->save();
|
||||
} else {
|
||||
$user->is_available = 0;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
return response()->json(['success' => 'Updated Successfully']);
|
||||
}
|
||||
|
||||
public function updateLastOnline()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
//update last online
|
||||
$user->last_online = Carbon::now();
|
||||
$user->save();
|
||||
|
||||
return response()->json(['success' => true]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class Kernel extends HttpKernel
|
|||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
// \App\Http\Middleware\VerifyDomain::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -36,6 +37,7 @@ class Kernel extends HttpKernel
|
|||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
//\App\Http\Middleware\VerifyDomain::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
|
@ -64,5 +66,6 @@ class Kernel extends HttpKernel
|
|||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'verifyDomain' => \App\Http\Middleware\VerifyDomain::class,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Http\Controllers\Mailgun\MailgunController;
|
||||
|
||||
class VerifyDomain
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$companyId = getSelectedCompany();
|
||||
|
||||
if(!$companyId){
|
||||
return false;
|
||||
}
|
||||
|
||||
$company = get_company('id',$companyId);
|
||||
|
||||
if(!$company){
|
||||
return false;
|
||||
}
|
||||
|
||||
$domain = $company->domain;
|
||||
|
||||
$controller = new MailgunController();
|
||||
|
||||
$result = $controller->is_domain_verified($domain);
|
||||
if($result){
|
||||
return $next($request);
|
||||
}else{
|
||||
return redirect()->route('showDomain',$domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ChatGroup extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
protected $table = 'chat_group';
|
||||
|
||||
protected $fillable = ['company_id', 'user_id', 'customer_id', 'name', 'email', 'subject', 'status'];
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return $this->hasMany(Message::class, 'chat_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -10,4 +10,9 @@ class Company extends Model
|
|||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function getMeta($key){
|
||||
return getCompanyMeta($this->id,$key);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CompanyUser extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Message extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'message';
|
||||
|
||||
protected $fillable = ['chat_id', 'from', 'to', 'message', 'type'];
|
||||
|
||||
public function chat()
|
||||
{
|
||||
return $this->belongsTo(ChatGroup::class, 'chat_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Notification extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Rule extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Tag extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $guarded = [];
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ class User extends Authenticatable
|
|||
'email',
|
||||
'password',
|
||||
'role_id',
|
||||
'profile_image'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
public const HOME = '/dashboard';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
// app/Services/CPanelApiService.php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
class CPanelApiService
|
||||
{
|
||||
protected $client;
|
||||
protected $cpanelUrl;
|
||||
protected $cpanelUsername;
|
||||
protected $cpanelToken;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->cpanelUrl = env('CPANEL_URL');
|
||||
$this->cpanelUsername = env('CPANEL_USERNAME');
|
||||
$this->cpanelToken = env('CPANEL_TOKEN');
|
||||
|
||||
$this->client = new Client([
|
||||
'base_uri' => $this->cpanelUrl,
|
||||
'headers' => [
|
||||
'Authorization' => 'cpanel ' . $this->cpanelUsername . ':' . $this->cpanelToken
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function createEmailAccount($domain, $email, $password, $quota)
|
||||
{
|
||||
$query = [
|
||||
'cpanel_jsonapi_user' => $this->cpanelUsername,
|
||||
'cpanel_jsonapi_apiversion' => '2',
|
||||
'cpanel_jsonapi_module' => 'Email',
|
||||
'cpanel_jsonapi_func' => 'addpop',
|
||||
'domain' => $domain,
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'quota' => $quota
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->client->request('GET', '/json-api/cpanel', ['query' => $query]);
|
||||
return json_decode($response->getBody(), true);
|
||||
} catch (GuzzleException $e) {
|
||||
return ['error' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"guzzlehttp/guzzle": "^7.8",
|
||||
"laravel/framework": "^10.10",
|
||||
"laravel/sanctum": "^3.3",
|
||||
"laravel/tinker": "^2.8",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e3f9f69a248021a08a4b420d64573db7",
|
||||
"content-hash": "3427d1f055fffcf2c0867d5d8137c3f3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('companies', function (Blueprint $table) {
|
||||
$table->string('internal_email')->default('');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('companies', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('company_users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->foreignId('company_id')->constrained('companies')->onDelete('cascade');
|
||||
$table->text('access')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('company_users');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tags', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('company_id')->constrained('companies')->onDelete('cascade');
|
||||
$table->string('name');
|
||||
$table->string('type');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tags');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('chat_group', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('company_id')->constrained('companies')->onDelete('cascade');
|
||||
$table->foreignId('user_id')->constrained('users');
|
||||
$table->string('customer_id');
|
||||
$table->string('name');
|
||||
$table->string('email');
|
||||
$table->text('subject');
|
||||
$table->string('status');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('chat_group');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('message', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('chat_id')->constrained('chat_group')->onDelete('cascade');
|
||||
$table->string('from');
|
||||
$table->string('to');
|
||||
$table->text('message');
|
||||
$table->string('type');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('message');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('last_online')->nullable();
|
||||
$table->boolean('is_available')->default(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('rules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('company_id')->constrained('companies')->onDelete('cascade');
|
||||
$table->integer('tag_id')->nullable();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('from')->nullable();
|
||||
$table->string('to')->nullable();
|
||||
$table->string('subject_contains')->nullable();
|
||||
$table->string('text_contains')->nullable();
|
||||
$table->string('subject1_contains')->nullable();
|
||||
$table->string('assign_to')->nullable();
|
||||
$table->string('message_to_assigned_editor')->nullable();
|
||||
$table->string('all_emails_automatically_mark_as_spam')->nullable();
|
||||
$table->string('status');
|
||||
$table->string('priority');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('rules');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('tickets', function (Blueprint $table) {
|
||||
$table->string('subject2')->nullable()->after('subject');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('tickets', function (Blueprint $table) {
|
||||
$table->dropColumn('subject2');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('responses', function (Blueprint $table) {
|
||||
$table->longText('attachments')->nullable()->after('message');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('responses', function (Blueprint $table) {
|
||||
$table->dropColumn('attachments');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('notifications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->text('text')->nullable();
|
||||
$table->string('status')->nullable();
|
||||
$table->string('type')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('notifications');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('profile_image')->nullable()->after('remember_token');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('profile_image');
|
||||
});
|
||||
}
|
||||
};
|
||||
BIN
kundesone.zip
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
# php -- BEGIN cPanel-generated handler, do not edit
|
||||
# Set the “ea-php81” package as the default “PHP” programming language.
|
||||
<IfModule mime_module>
|
||||
AddHandler application/x-httpd-ea-php81 .php .php8 .phtml
|
||||
</IfModule>
|
||||
# php -- END cPanel-generated handler, do not edit
|
||||
|
|
@ -9,11 +9,13 @@ $(document).ready(function () {
|
|||
});
|
||||
initFomanticDropdown(".user-select-dropdown", { action: "activate" });
|
||||
|
||||
|
||||
|
||||
//Handle opening / closing of inbox
|
||||
$(".open-inbox").on("click", function () {
|
||||
slideTransition("#chat-feature-widget", "left", true);
|
||||
slideTransition("#inbox", "right", false);
|
||||
});
|
||||
// $(".open-inbox").on("click", function () {
|
||||
// slideTransition("#chat-feature-widget", "left", true);
|
||||
// slideTransition("#inbox", "right", false);
|
||||
// });
|
||||
|
||||
$("#back-to-users").on("click", function () {
|
||||
slideTransition("#inbox", "left", true);
|
||||
|
|
@ -38,7 +40,7 @@ function initFomanticDropdown(selector, config, callback = null) {
|
|||
}
|
||||
|
||||
function slideTransition(selector, direction, shouldHide) {
|
||||
$(selector).transition(`slide ${direction}`);
|
||||
//$(selector).transition(`slide ${direction}`);
|
||||
if (shouldHide) {
|
||||
$(selector).addClass("hidden");
|
||||
} else {
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 273 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
|
@ -4,6 +4,422 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.side-bar-links a').removeClass('bg-light-color');
|
||||
$('.aw-a-inbox').addClass('bg-light-color');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Toastr CSS -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet">
|
||||
<!-- Toastr JS -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
||||
<!-- SweetAlert2 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet">
|
||||
<!-- SweetAlert2 JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>
|
||||
|
||||
@php
|
||||
$companyId = getSelectedCompany();
|
||||
$company_users = get_company_users($companyId);
|
||||
@endphp
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Toggle filter dropdown on button click
|
||||
$('.list-filter-btn').click(function() {
|
||||
$('.filter-options').toggle();
|
||||
});
|
||||
|
||||
// Initial hide for handle_multiple__options
|
||||
$('.filter-options').hide();
|
||||
$('.handle_multiple__options').hide();
|
||||
|
||||
// Toggle visibility of handle_multiple__options on button click
|
||||
$('.handle-multiple-btn').click(function() {
|
||||
$('.handle_multiple__options').toggle();
|
||||
});
|
||||
|
||||
// Initially disable all the buttons
|
||||
$('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
|
||||
// Enable/disable buttons based on the select all checkbox
|
||||
// $('#select-all').change(function() {
|
||||
// if ($(this).is(':checked')) {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', false);
|
||||
// } else {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Show the modal when "Assign post" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Assign post")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Move" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Move")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal2').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Reply to multiple" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Reply to multiple")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal3').show();
|
||||
});
|
||||
|
||||
// Close the modal when the close button or outside the modal is clicked
|
||||
$('.modal-close, .modal').click(function() {
|
||||
$('.modal').hide();
|
||||
});
|
||||
|
||||
// Prevent modal content from closing the modal when clicked
|
||||
$('.modal-content').click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Update Select status options based on Select filter selection
|
||||
$('#filter-select').change(function() {
|
||||
var selectedFilter = $(this).val();
|
||||
console.log("Selected filter:", selectedFilter); // Debugging log
|
||||
updateStatusOptions(selectedFilter);
|
||||
});
|
||||
|
||||
// Initially hide filter based data section
|
||||
$('.filter_based__data').hide();
|
||||
|
||||
// Function to update status options based on selectedFilter
|
||||
function updateStatusOptions(selectedFilter) {
|
||||
console.log("Updating status options for:", selectedFilter); // Debugging log
|
||||
switch (selectedFilter) {
|
||||
case 'Assigned to':
|
||||
// $('#status-select').html(`
|
||||
// <option disabled value="">Select assigned to</option>
|
||||
// <option value="Assigned">Assigned</option>
|
||||
// <option value="Unassigned">Unassigned</option>
|
||||
// <option value="Margin">Margin</option>
|
||||
// `);
|
||||
var options = '<option value="">Select assigned to</option>';
|
||||
// Loop through the company_users array
|
||||
@foreach($company_users as $company_user)
|
||||
options += '<option value="{{ $company_user->user->id }}">{{ $company_user->user->name }}</option>';
|
||||
@endforeach
|
||||
|
||||
$('#status-select').html(options);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'With activity':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select No activity</option>
|
||||
<option value="last 24 hours">Last 24 hours</option>
|
||||
<option value="last 3 days">Last 3 days</option>
|
||||
<option value="last week">Last week</option>
|
||||
<option value="last month">Last month</option>
|
||||
<option value="last 3 months">Last 3 months</option>
|
||||
<option value="last 6 months">Last 6 months</option>
|
||||
<option value="last year">Last year</option>
|
||||
<option value="the past 2 years">The past 2 years</option>
|
||||
<option value="the past 3 years">The past 3 years</option>
|
||||
<option value="the past 4 years">The past 4 years</option>
|
||||
<option value="the past 5 years">The past 5 years</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'No activity':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select No activity</option>
|
||||
<option value="last 24 hours">Last 24 hours</option>
|
||||
<option value="last 3 days">Last 3 days</option>
|
||||
<option value="last week">Last week</option>
|
||||
<option value="last month">Last month</option>
|
||||
<option value="last 3 months">Last 3 months</option>
|
||||
<option value="last 6 months">Last 6 months</option>
|
||||
<option value="last year">Last year</option>
|
||||
<option value="the past 2 years">The past 2 years</option>
|
||||
<option value="the past 3 years">The past 3 years</option>
|
||||
<option value="the past 4 years">The past 4 years</option>
|
||||
<option value="the past 5 years">The past 5 years</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Editor':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select Editor</option>
|
||||
<option value="Computer tool">Computer tool</option>
|
||||
<option value="Direct editor">Direct editor</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Spam':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select Spam</option>
|
||||
<option value="marked as spam">Marked as spam</option>
|
||||
<option value="marked as not spam">Marked as not spam</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Status':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select status</option>
|
||||
<option value="open">Open</option>
|
||||
<option value="waiting">Waiting</option>
|
||||
<option value="done">Done</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Tags':
|
||||
|
||||
var options = '<option value="">Select Tags</option>';
|
||||
@foreach($tags as $tag)
|
||||
options += '<option value="{{$tag->name}}">{{$tag->name}}</option>';
|
||||
@endforeach
|
||||
|
||||
$('#status-select').html(options);
|
||||
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Users':
|
||||
|
||||
var options = '<option value="">Select Users</option>';
|
||||
// Loop through the company_users array
|
||||
@foreach($company_users as $company_user)
|
||||
options += '<option value="{{ $company_user->user->id }}">{{ $company_user->user->name }}</option>';
|
||||
@endforeach
|
||||
|
||||
// Update the select element with the generated options
|
||||
$('#status-select').html(options);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
default:
|
||||
$('#status-select').html(`
|
||||
<option disabled value="">Select status</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.handle_multiple__options {
|
||||
display: none;
|
||||
background-color: #f8f9fa;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button {
|
||||
background-color: #748C62;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button:hover {
|
||||
background-color: #383F33;
|
||||
}
|
||||
.handle_multiple__options .tags button:disabled {
|
||||
background-color: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.handle_multiple__options input{
|
||||
width: 32px;
|
||||
height: 19px;
|
||||
}
|
||||
.handle_multiple__options .common_shre{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* Custom Modal CSS */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 13%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
#customModal3 .modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 40%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.modal-content .btn-primary{
|
||||
background-color: #748C62 !important;
|
||||
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.modal-close:focus {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter select {
|
||||
margin-right: 10px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
/* Hide checkboxes initially */
|
||||
.checkbox-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show checkboxes when 'Handle Multiple' is active */
|
||||
.handle-multiple-active .checkbox-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Show checkboxes when 'Handle Multiple' is active */
|
||||
.handle-multiple-active .checkbox-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
padding: 12px 11px !important;
|
||||
}
|
||||
|
||||
.chat-user-img{
|
||||
margin-left:12px !important;
|
||||
}
|
||||
|
||||
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* When checkbox is checked, set background to green */
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: #748C62;
|
||||
border-color: #748C62;
|
||||
}
|
||||
|
||||
/* Optional: Add checkmark icon or any visual effect */
|
||||
input[type="checkbox"]:checked::before {
|
||||
transform: translate(0px, -1px);
|
||||
content: '✔';
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
/* margin-top: 12px; */
|
||||
transform: translate(2px, 6px);
|
||||
}
|
||||
#cannedResponseModal ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex !important;
|
||||
gap: 8px !important;
|
||||
flex-wrap: wrap !important;
|
||||
}
|
||||
.canned-response {
|
||||
background-color: #748C62 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="ui card chat-card">
|
||||
<div class="content chat-card-header d-flex align-items-center justify-content-between">
|
||||
|
|
@ -20,15 +436,56 @@
|
|||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="filter-options">
|
||||
<div class="filter">
|
||||
<span> <b>Filter on:</b> </span>
|
||||
<select id="filter-select" name="">
|
||||
<option value="select_filter_default">Select filter</option>
|
||||
<option value="Assigned to">Assigned to</option>
|
||||
<option value="With activity">With activity</option>
|
||||
<option value="No activity">No activity</option>
|
||||
<!--<option value="Editor">Editor</option>-->
|
||||
<option value="Spam">Spam</option>
|
||||
<option value="Status">Status</option>
|
||||
<option value="Tags">Tags</option>
|
||||
<!--<option value="Users">Users</option>-->
|
||||
</select>
|
||||
<div class="filter_based__data">
|
||||
<select id="status-select" name="">
|
||||
<option disabled>Select status</option>
|
||||
<!-- Options will be dynamically updated based on selected filter -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="handle_multiple__options">
|
||||
<div class="common_shre">
|
||||
<label for="select-all"> <input type="checkbox" name="" id="select-all"> Select all</label>
|
||||
<div class="tags">
|
||||
<button>Assign post</button>
|
||||
<button id="delete-posts">Delete</button>
|
||||
<!--<button>Move</button>-->
|
||||
<button data-status="open" class="update-posts-status">Open</button>
|
||||
<button data-status="waiting" class="update-posts-status">Waiting</button>
|
||||
<button data-status="done" class="update-posts-status">Done</button>
|
||||
<!--<button>Tag</button>-->
|
||||
<!--<button>Not spam</button>-->
|
||||
<button>Reply to multiple</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content chat-content">
|
||||
<ul class="chat-details">
|
||||
@foreach($tickets as $ticket)
|
||||
<li>
|
||||
<a href="{{ route('inbox') }}" class="chat-detail-item d-flex align-items-center">
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-{{$ticket->id}}">
|
||||
</div>
|
||||
<div class="chat-user-img all-tickets position-relative">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
<img style="height: 42px; width: 42px; border-radius: 50%;" src="{{ asset('dummy-image.jpg') }}" alt="User">
|
||||
<div
|
||||
class="chat-status-icon rounded-circle text-center align-content-center position-absolute">
|
||||
<img src="{{ asset('images/icons/chat-round.svg') }}" alt="Chat Round">
|
||||
|
|
@ -46,8 +503,8 @@ class="chat-status-icon rounded-circle text-center align-content-center position
|
|||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">{{ $ticket->subject }}</p>
|
||||
<p class="receiver-message"> - {{ $ticket->content }}</p>
|
||||
<p class="color-dark-green receiver-name">{{ $ticket->sender_name }}</p>
|
||||
<p class="receiver-message"> - {{\Illuminate\Support\Str::limit($ticket->subject, 90)}}</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">{{\Carbon\Carbon::parse($ticket->created_at)->format('h:i A')}}</p>
|
||||
</div>
|
||||
|
|
@ -62,4 +519,132 @@ class="chat-status-icon rounded-circle text-center align-content-center position
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
<!--Filter Status Code-->
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const filterSelect = $('#filter-select');
|
||||
const statusSelect = $('#status-select');
|
||||
const statusOptions = $('#status-options');
|
||||
const chatDetails = $('.chat-details');
|
||||
|
||||
// Handle status change
|
||||
$('#status-select').change(function() {
|
||||
fetchTickets();
|
||||
});
|
||||
|
||||
// Fetch tickets based on filter
|
||||
function fetchTickets() {
|
||||
const filter = filterSelect.val();
|
||||
const status = $('#status-select').val();
|
||||
|
||||
$.ajax({
|
||||
url: '/filter',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
filter: filter,
|
||||
status: status,
|
||||
},
|
||||
success: function(data) {
|
||||
chatDetails.empty();
|
||||
$.each(data.tickets, function(index, ticket) {
|
||||
chatDetails.append(`
|
||||
<li>
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-${ticket.id}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="/images/Avatar.png" alt="User">
|
||||
</div>
|
||||
<div class="chat-message-info d-flex align-self-baseline">
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-light-green">#${ticket.id}</p>
|
||||
<div class="ui tiny label bg-dark-green-color color-light">
|
||||
${ticket.status}
|
||||
</div>
|
||||
</div>
|
||||
<p class="color-dark-green">${new Date(ticket.created_at).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">${ticket.sender_name}</p>
|
||||
<p class="receiver-message"> - ${ticket.subject}</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">${new Date(ticket.created_at).toLocaleTimeString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
const chatDetails = $('.chat-details');
|
||||
const filterSelect = $('#filter-select');
|
||||
filterSelect.change(function() {
|
||||
const selectedFilter = $(this).val();
|
||||
|
||||
if (selectedFilter === 'select_filter_default') {
|
||||
$.ajax({
|
||||
url: 'default/all-tickets',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
success: function(data) {
|
||||
chatDetails.empty();
|
||||
$.each(data.tickets, function(index, ticket) {
|
||||
chatDetails.append(`
|
||||
<li>
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-${ticket.id}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="/images/Avatar.png" alt="User">
|
||||
</div>
|
||||
<div class="chat-message-info d-flex align-self-baseline">
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-light-green">#${ticket.id}</p>
|
||||
<div class="ui tiny label bg-dark-green-color color-light">
|
||||
${ticket.status}
|
||||
</div>
|
||||
</div>
|
||||
<p class="color-dark-green">${new Date(ticket.created_at).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">${ticket.sender_name}</p>
|
||||
<p class="receiver-message"> - ${ticket.subject}</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">${new Date(ticket.created_at).toLocaleTimeString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<x-custom-modals />
|
||||
|
||||
@endsection
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
<meta content="" name="keywords">
|
||||
|
||||
<!-- Favicons -->
|
||||
<link href="" rel="icon">
|
||||
<link href="assets/img/apple-touch-icon.png" rel="apple-touch-icon">
|
||||
<link rel="icon" href="{{asset('images/favicon.ico')}}" type="image/png">
|
||||
<!--<link href="assets/img/apple-touch-icon.png" rel="apple-touch-icon">-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<link rel="stylesheet" href="https://chat.rapidev.tech/chat/chat.css">
|
||||
<div id="aw-root-chat" data-company="{{getSelectedCompany()}}"></div>
|
||||
<script src="https://chat.rapidev.tech/chat/chat.js"></script>
|
||||
|
|
@ -0,0 +1,629 @@
|
|||
<style>
|
||||
|
||||
.aw-chat-head img{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.scrollhint .item .single-user-content img,.scrollhint .item .sender-message-box img{
|
||||
width:100%;
|
||||
}
|
||||
@media screen and (max-width: 767px) {
|
||||
.chat-message-box {
|
||||
left: 20px !important;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 525px) {
|
||||
div.chat-inbox>.chat-content-wrapper>.chat-message>.single-message-chat>.user-message {
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Support and Chat Fixed Buttons -->
|
||||
<div class="chat-message-box position-fixed">
|
||||
|
||||
|
||||
<!-- Chat Drop Down -->
|
||||
<div class="ui floating bg-dark-green-color chat-widget-wrapper icon dropdown button">
|
||||
<img src="{{ asset('images/icons/Vector 386.png') }}" alt="Chat Icon">
|
||||
|
||||
<div class="menu chat-menu">
|
||||
<div id="chat-feature-widget" class="ui transition chat-feature-widget">
|
||||
<div class="header d-flex justify-content-between align-items-center text-white">
|
||||
<p class="chat-popup-label text-light">Chats</p>
|
||||
<img class="remove-chat" src="{{ asset('images/icons/Vector (3).svg') }}" alt="Cross Chat Icon">
|
||||
</div>
|
||||
|
||||
<div class="aw-chats">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- User Inbox menu -->
|
||||
<div id="inbox" class="ui transition hidden chat-feature-widget inbox-wrapper">
|
||||
<div class="header aw-chat-head d-flex align-items-center" style="justify-content: space-between;">
|
||||
<img id="back-to-users" src="{{ asset('images/icons/Vector 387.png') }}" alt="Back To Chat">
|
||||
<p class="chat-popup-label text-light">James</p>
|
||||
<img id="close-chat" src="{{ asset('images/icons/Vector (3).svg') }}" alt="Close Chat">
|
||||
</div>
|
||||
<div class="scrollhint">
|
||||
|
||||
|
||||
<!--<div class="item">-->
|
||||
<!-- <div class="single-user-content d-flex">-->
|
||||
<!-- <div class="chat-user-img-box receiver-message-box d-flex">-->
|
||||
<!-- <img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">-->
|
||||
<!-- <p>Typing...</p>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
|
||||
</div>
|
||||
<div class="outer-message-input-box">
|
||||
<div class="inner-message-input d-flex align-items-center justify-content-between">
|
||||
<input id="aw-sms" type="text" class="border-0" placeholder="Type a reply">
|
||||
<p class="input-action d-flex align-items-center">
|
||||
<!--<img src="{{ asset('images/icons/gif.png') }}" alt="Gif">-->
|
||||
<!--<img src="{{ asset('images/icons/emoji.png') }}" alt="Emoji">-->
|
||||
<img src="{{ asset('images/icons/attachment.png') }}" alt="Attachment">
|
||||
<input type="file" id="file-picker" class="file-picker">
|
||||
<i class="fa fa-paper-plane-o send-icon" aria-hidden="true"></i>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
|
||||
|
||||
<!-- Support Drop down -->
|
||||
<div class="ui floating bg-dark-green-color support-widget-wrapper icon dropdown button ">
|
||||
<img src="{{asset('images/icons/support.svg')}}" alt="Support Icon">
|
||||
<div class="menu support-widget">
|
||||
<div class="header support-header mt-0 text-center">
|
||||
<h2 class="color-dark-green">Help & Support</h2>
|
||||
</div>
|
||||
<div class="support-facilities-box d-flex justify-content-between flex-wrap">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/faq-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">FAQ</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/laptop-minimalistic-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">Using Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/launch-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Launching Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/setting-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Settings</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/data-mapping-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Integration</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/open-door-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Privacy & Policy</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/news-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">News & Updates</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/graduate-cap-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Training</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header contact-us-header text-center">
|
||||
<h2 class="color-dark-green">Contact Us</h2>
|
||||
</div>
|
||||
|
||||
<div class="contact-us-box d-flex justify-content-center">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/email-14-svgrepo-com (1) 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Questions</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{asset('images/icons/about-filled-svgrepo-com 1.svg')}}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">About Kundo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- End -->
|
||||
|
||||
<audio style="display:none;" id="messageSound" src="{{asset('assets/noti.wav')}}" preload="auto"></audio>
|
||||
|
||||
|
||||
<script src="https://chat.rapidev.tech/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
|
||||
var customer_id = false;
|
||||
var startData = false;
|
||||
var localId = false;
|
||||
|
||||
var customers = [];
|
||||
|
||||
const socket = io('https://chat.rapidev.tech/', {
|
||||
withCredentials: false,
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Event listener for successful connection
|
||||
socket.on('connect', () => {
|
||||
console.log('Connected to the server with socket ID:', socket.id);
|
||||
customer_id = socket.id;
|
||||
|
||||
localId = "{{auth()->user()->id}}";
|
||||
|
||||
socket.emit('register', localId);
|
||||
console.log(localId);
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Optionally, handle the disconnect event
|
||||
socket.on('disconnect', (reason) => {
|
||||
console.log('Disconnected from the server:', reason);
|
||||
customer_id = false;
|
||||
if (reason === 'io server disconnect') {
|
||||
// The server disconnected the client, try to reconnect
|
||||
socket.connect();
|
||||
}
|
||||
});
|
||||
|
||||
function loadChats(){
|
||||
$.ajax({
|
||||
url: "{{route('chatgroups.get')}}",
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
|
||||
var html = '';
|
||||
|
||||
for(var i=0;i<response.length;i++){
|
||||
|
||||
var chat = response[i];
|
||||
|
||||
chat['isFirst'] = true;
|
||||
|
||||
customers[chat.id] = chat;
|
||||
|
||||
html += ` <div class="item open-inbox" data-chat="${chat.id}" data-customer="${chat.customer_id}" data-subject="${chat.subject}" data-user="${chat.user_id}">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" class="aw-avatar" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">${chat.name} <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">${chat.subject}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
}
|
||||
|
||||
$('.aw-chats').html(html);
|
||||
|
||||
// Update action box with fetched content
|
||||
// $('.action-box').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error fetching action box content:', error);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
console.log(socket);
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
|
||||
loadChats()
|
||||
|
||||
var activeChat = false;
|
||||
var inbox = $('#inbox .scrollhint');
|
||||
|
||||
$('#close-chat').click(function(){
|
||||
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "Do you want to close this chat?",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed && activeChat) {
|
||||
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route("CloseChat") }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{csrf_token()}}',
|
||||
chat_id: activeChat.id
|
||||
},
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
|
||||
socket.emit('chat_closed',
|
||||
{ customer_id:activeChat.customer_id, chat_id: activeChat.id }
|
||||
);
|
||||
|
||||
Swal.fire({
|
||||
title: 'Success',
|
||||
text: "Chat is closed.",
|
||||
icon: 'success',
|
||||
showCancelButton: false,
|
||||
confirmButtonColor: '#3085d6',
|
||||
//cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'OK'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
loadChats();
|
||||
$('#back-to-users').click();
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.log(xhr.responseText);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('chat closed');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$(document).on('click', '.open-inbox', async function() {
|
||||
inbox.html(null);
|
||||
|
||||
var chat = customers[$(this).data('chat')];
|
||||
|
||||
var messages = await getMessage(chat.id);
|
||||
console.log(messages);
|
||||
|
||||
if(messages){
|
||||
|
||||
for(var i=0;i<messages.length;i++){
|
||||
var sms = messages[i];
|
||||
|
||||
var content = sms.message;
|
||||
|
||||
if(sms.type == 'image'){
|
||||
content = '<img src="'+sms.message+'"/>';
|
||||
}
|
||||
|
||||
if(sms.type == 'file'){
|
||||
content = '<a target="_blank" href="'+sms.message+'"> View File </a>';
|
||||
}
|
||||
|
||||
if(sms.from == "user"){
|
||||
|
||||
|
||||
//<img src="{{ asset('images/Avatar.png') }}" class="aw-avatar" alt="Dummy User">
|
||||
inbox.append(` <div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
|
||||
<p>${content}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
}else{
|
||||
inbox.append(` <div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>${content}</p>
|
||||
</div>
|
||||
</div>`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$('.chat-popup-label').text(chat.name);
|
||||
|
||||
activeChat = chat;
|
||||
|
||||
if(chat.isFirst){
|
||||
|
||||
}
|
||||
|
||||
console.log(activeChat);
|
||||
|
||||
slideTransition('#chat-feature-widget', 'left', true);
|
||||
slideTransition('#inbox', 'right', false);
|
||||
});
|
||||
|
||||
$('.send-icon').click(async function(){
|
||||
|
||||
var sms = $('#aw-sms').val();
|
||||
|
||||
const fileInput = document.getElementById("file-picker");
|
||||
const file = fileInput.files[0];
|
||||
var type = "text";
|
||||
|
||||
if(sms != "" || file){
|
||||
|
||||
console.log(activeChat.id);
|
||||
const formData = new FormData();
|
||||
|
||||
if (file) {
|
||||
formData.append("file", file); // Append the selected file
|
||||
|
||||
// Check the file type
|
||||
const fileType = file.type;
|
||||
if (fileType.startsWith("image/")) {
|
||||
console.log("This is an image file.");
|
||||
type = "image";
|
||||
} else {
|
||||
type = "file";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
formData.append('chat_id', activeChat.id); // Static value as per your example
|
||||
formData.append('from', 'company'); // Assuming a static value for simplicity
|
||||
formData.append('message', sms);
|
||||
formData.append('type', type);
|
||||
|
||||
|
||||
// API endpoint
|
||||
const apiUrl = 'https://kundesone.no/api/chat/send-message';
|
||||
|
||||
// Fetch API to send the FormData
|
||||
fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
||||
var sms = data.data;
|
||||
var content = sms.message;
|
||||
|
||||
console.log('Success:', data,'chat message',{
|
||||
sms:content,
|
||||
id:activeChat.id,
|
||||
type:sms.type
|
||||
|
||||
},
|
||||
activeChat.customer_id);
|
||||
|
||||
socket.emit('chat message',
|
||||
{
|
||||
sms:content,
|
||||
id:activeChat.id,
|
||||
type:sms.type
|
||||
|
||||
},
|
||||
activeChat.customer_id
|
||||
);
|
||||
|
||||
|
||||
|
||||
if(sms.type == 'image'){
|
||||
content = '<img src="'+content+'"/>';
|
||||
}
|
||||
|
||||
if(sms.type == 'file'){
|
||||
content = '<a target="_blank" href="'+content+'"> View File </a>';
|
||||
}
|
||||
|
||||
inbox.append(` <div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>${content}</p>
|
||||
</div>
|
||||
</div>`);
|
||||
|
||||
$('#aw-sms').val("");
|
||||
|
||||
scrollToBottom();
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
async function getMessage(chat_id) {
|
||||
const apiUrl = 'https://kundesone.no/api/chat/getMessages';
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json' // Assuming the server expects JSON
|
||||
},
|
||||
body: JSON.stringify({ chat_id: chat_id })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
|
||||
const messages = await response.json();
|
||||
return messages;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
socket.on('chat_created',function(data){
|
||||
loadChats();
|
||||
console.log(data);
|
||||
playMessageSound();
|
||||
});
|
||||
|
||||
|
||||
socket.on('chat message', function(msg) {
|
||||
playMessageSound();
|
||||
|
||||
if(msg.id == activeChat.id){
|
||||
|
||||
var sms = msg;
|
||||
|
||||
var content = sms.sms;
|
||||
|
||||
if(sms.type == 'image'){
|
||||
content = '<img src="'+content+'"/>';
|
||||
}
|
||||
|
||||
if(sms.type == 'file'){
|
||||
content = '<a target="_blank" href="'+content+'"> View File </a>';
|
||||
}
|
||||
|
||||
|
||||
//<img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
inbox.append(` <div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
|
||||
<p>${content}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>`);
|
||||
|
||||
}
|
||||
|
||||
console.log(msg);
|
||||
// var item = document.createElement('li');
|
||||
// item.textContent = msg;
|
||||
// document.getElementById('messages').appendChild(item);
|
||||
// window.scrollTo(0, document.body.scrollHeight);
|
||||
|
||||
scrollToBottom();
|
||||
});
|
||||
|
||||
|
||||
socket.on('start_chat', function(msg) {
|
||||
console.log(msg);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
function scrollToBottom() {
|
||||
var $div = $('.scrollhint');
|
||||
$div.scrollTop($div.prop("scrollHeight"));
|
||||
}
|
||||
|
||||
function playMessageSound() {
|
||||
var sound = document.getElementById('messageSound');
|
||||
|
||||
sound.play();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script>document.querySelector('.input-action img[alt="Attachment"]').addEventListener('click', function() {
|
||||
document.getElementById('file-picker').click();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.outer-message-input-box {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.inner-message-input {
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.inner-message-input input {
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.input-action img {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input-action .file-picker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fa-paper-plane-o {
|
||||
font-size: 17px !important;
|
||||
background: #748C62 !important;
|
||||
padding: 3px 7px !important;
|
||||
color: white !important;
|
||||
border-radius: 3px !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,570 @@
|
|||
<style>
|
||||
#cke_editor1{
|
||||
width:100%!important;
|
||||
}
|
||||
|
||||
div.chat-inbox.chat-box{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
background:;#748c62 !important
|
||||
}
|
||||
|
||||
.close-button:hover,
|
||||
.close-button:focus {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
#cannedResponseModal ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#cannedResponseModal li {
|
||||
padding: 8px 0; /* Spacing between buttons */
|
||||
}
|
||||
|
||||
.canned-response {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.canned-response:hover {
|
||||
background-color: #45a049;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.24);
|
||||
}
|
||||
.close-button {
|
||||
color: #aaa;
|
||||
/* float: right; */
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
background: ;
|
||||
display: flex !important;
|
||||
justify-content: flex-end !important;
|
||||
margin-top: -14px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<!-- Custom Modal post -->
|
||||
<div id="customModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="modal-close">×</span>
|
||||
<h5>Assign Post</h5>
|
||||
<form id="assignForm">
|
||||
<input type="hidden" id="ticket-ids" name="ticket_ids">
|
||||
<div class="mb-3">
|
||||
<label for="recipient-name" class="col-form-label">Recipient:</label>
|
||||
@php
|
||||
$companyId = getSelectedCompany();
|
||||
$company_users = get_company_users($companyId);
|
||||
@endphp
|
||||
<select name="user_assigned" class="form-control" required>
|
||||
<option>Select User</option>
|
||||
@foreach($company_users as $company_user)
|
||||
<option value="{{$company_user->user->id}}">{{$company_user->user->name}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="message-text" class="col-form-label">Message:</label>
|
||||
<textarea class="form-control" id="message-text" name="message" required></textarea>
|
||||
</div>
|
||||
</form>
|
||||
<button type="button" class="btn btn-primary assign-post">Send</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Custom Modal move-->
|
||||
<div id="customModal2" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="modal-close">×</span>
|
||||
<h5>Move</h5>
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="recipient-name" class="col-form-label">Conversation moved:</label>
|
||||
<input type="text" class="form-control" id="recipient-name" placeholder="Inbox">
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<button type="button" class="btn btn-primary">Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Custom Modal Replay to multiple-->
|
||||
<div id="customModal3" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="modal-close">×</span>
|
||||
<h5>Reply to multiple</h5>
|
||||
<form>
|
||||
<div class="content d-flex align-items-end flex-column message-writing-content-area">
|
||||
<textarea name="email_signature" id="editor1" rows="10" placeholder="Your Message"
|
||||
class="form-control input-reply-textarea" required></textarea>
|
||||
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row-reverse;">
|
||||
<button type="button" class="btn btn-primary reply-to-multiple">Reply</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Canned Response Modal -->
|
||||
<div id="cannedResponseModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-button">×</span>
|
||||
<h2>Canned Responses</h2>
|
||||
<ul>
|
||||
@php
|
||||
$companyId = getSelectedCompany();
|
||||
$canned_response = \App\Models\CompanyMeta::where('company_id', $companyId)->where('key', 'canned_responses')->get();
|
||||
$email_signature = \App\Models\CompanyMeta::where('company_id', $companyId)->where('type', 'Email Signature')->first()?->value;
|
||||
@endphp
|
||||
@if(count($canned_response) > 0)
|
||||
@foreach($canned_response as $index => $value)
|
||||
|
||||
@php
|
||||
|
||||
$result = json_decode($value->value);
|
||||
|
||||
@endphp
|
||||
|
||||
<li><button class="canned-response" data-response="{{$result->text}}">{{$result->name}}</button></li>
|
||||
@endforeach
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
//CKEDITOR.replace('editor1');
|
||||
|
||||
CKEDITOR.plugins.add('addcannedresponse', {
|
||||
init: function(editor) {
|
||||
// Command for inserting canned response
|
||||
editor.addCommand('addCannedResponseCmd', {
|
||||
exec: function(editor) {
|
||||
// Show your modal or handle canned response insertion
|
||||
document.getElementById('cannedResponseModal').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
// Command for inserting signature
|
||||
editor.addCommand('addSignatureCmd', {
|
||||
exec: function(editor) {
|
||||
var signatureHtml = `<br>{!! $email_signature !!}`; // Signature content
|
||||
CKEDITOR.instances.editor1.insertHtml(signatureHtml);
|
||||
}
|
||||
});
|
||||
|
||||
// Add "Insert Canned Response" button
|
||||
editor.ui.addButton('AddCannedResponse', {
|
||||
label: 'Insert Canned Response',
|
||||
command: 'addCannedResponseCmd',
|
||||
icon: 'https://kundesone.no/images/canned.png', // Use an accessible icon URL or local path
|
||||
toolbar: 'insert,0'
|
||||
});
|
||||
|
||||
// Add "Insert Signature" button
|
||||
editor.ui.addButton('AddSignature', {
|
||||
label: 'Insert Signature',
|
||||
command: 'addSignatureCmd',
|
||||
icon: 'https://kundesone.no/images/signature-icon.png', // Placeholder icon URL, replace with a valid one
|
||||
toolbar: 'insert,1'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
CKEDITOR.replace('editor1', {
|
||||
extraPlugins: 'addcannedresponse', // Ensure your plugin is added to extraPlugins
|
||||
// Optionally customize your toolbar further, or use the default configuration
|
||||
toolbarGroups: [
|
||||
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
|
||||
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'forms' },
|
||||
{ name: 'tools' },
|
||||
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
|
||||
{ name: 'others' },
|
||||
'/',
|
||||
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
|
||||
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
|
||||
{ name: 'styles' },
|
||||
{ name: 'colors' },
|
||||
{ name: 'about' }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
// Get the modal
|
||||
var modal = document.getElementById("cannedResponseModal");
|
||||
|
||||
// Get the button that opens the modal
|
||||
var btn = document.getElementsByClassName("canned-response");
|
||||
|
||||
// Get the <span> element that closes the modal
|
||||
var span = document.getElementsByClassName("close-button")[0];
|
||||
|
||||
// When the user clicks on <span> (x), close the modal
|
||||
span.onclick = function() {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
|
||||
// When the user clicks anywhere outside of the modal, close it
|
||||
window.onclick = function(event) {
|
||||
if (event.target == modal) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners to canned response buttons
|
||||
Array.from(btn).forEach(function(element) {
|
||||
element.addEventListener('click', function() {
|
||||
var response = this.getAttribute('data-response');
|
||||
CKEDITOR.instances.editor1.insertHtml(response);
|
||||
modal.style.display = "none";
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var $handleMultipleButton = $('.handle-multiple-btn');
|
||||
var $selectAllCheckbox = $('#select-all');
|
||||
var $ticketCheckboxes = $('.ticket-checkbox');
|
||||
var $actionButtons = $('.handle_multiple__options .tags button');
|
||||
|
||||
// Function to toggle button states
|
||||
function updateButtonStates() {
|
||||
var selectedCount = $ticketCheckboxes.filter(':checked').length;
|
||||
$actionButtons.prop('disabled', selectedCount === 0);
|
||||
}
|
||||
|
||||
// Toggle checkboxes visibility
|
||||
$handleMultipleButton.on('click', function() {
|
||||
$('.content').toggleClass('handle-multiple-active');
|
||||
});
|
||||
|
||||
// Toggle all checkboxes based on 'Select all'
|
||||
$selectAllCheckbox.on('change', function() {
|
||||
$ticketCheckboxes.prop('checked', $selectAllCheckbox.prop('checked'));
|
||||
updateButtonStates();
|
||||
});
|
||||
|
||||
// Toggle button states when individual checkboxes change
|
||||
$ticketCheckboxes.on('change', function() {
|
||||
updateButtonStates();
|
||||
});
|
||||
|
||||
// Initialize button states
|
||||
updateButtonStates();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!--Assigned Post Start-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.assign-post').on('click', function() {
|
||||
|
||||
var selectedTickets = [];
|
||||
$('.ticket-checkbox:checked').each(function() {
|
||||
selectedTickets.push($(this).attr('id').replace('ticket-', ''));
|
||||
});
|
||||
$('#ticket-ids').val(selectedTickets.join(','));
|
||||
|
||||
// SweetAlert2 confirmation dialog
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'You are about to send this message.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, send it!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// Get form data
|
||||
var formData = $('#assignForm').serialize();
|
||||
|
||||
// AJAX request to submit the form
|
||||
$.ajax({
|
||||
url: 'assign/ticket',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
// Show success notification
|
||||
Swal.fire(
|
||||
'Assigned!',
|
||||
'Post Assigned Successfully!',
|
||||
'success'
|
||||
);
|
||||
|
||||
location.reload();
|
||||
// Hide the modal
|
||||
$('#customModal').modal('hide');
|
||||
},
|
||||
error: function(xhr) {
|
||||
// Show error notification
|
||||
Swal.fire(
|
||||
'Error!',
|
||||
'An error occurred. Please try again.',
|
||||
'error'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--Assigned Post End-->
|
||||
|
||||
<!--Delete Post Start-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#delete-posts').on('click', function() {
|
||||
|
||||
var selectedTickets = [];
|
||||
$('.ticket-checkbox:checked').each(function() {
|
||||
selectedTickets.push($(this).attr('id').replace('ticket-', ''));
|
||||
});
|
||||
|
||||
var ticket_ids = selectedTickets.join(',');
|
||||
|
||||
// SweetAlert2 confirmation dialog
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'You are about to delete selected tickets.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete them!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// AJAX request to delete the tickets
|
||||
$.ajax({
|
||||
url: 'delete/tickets',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
ticket_ids: ticket_ids
|
||||
},
|
||||
success: function(response) {
|
||||
// Show success notification
|
||||
Swal.fire(
|
||||
'Deleted!',
|
||||
'Tickets have been deleted successfully.',
|
||||
'success'
|
||||
);
|
||||
// Reload the page or update the UI as needed
|
||||
location.reload();
|
||||
},
|
||||
error: function(xhr) {
|
||||
// Show error notification
|
||||
Swal.fire(
|
||||
'Error!',
|
||||
'An error occurred. Please try again.',
|
||||
'error'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--Delete Post End-->
|
||||
|
||||
<!--Update Status Start-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.update-posts-status').on('click', function() {
|
||||
|
||||
var status = $(this).data('status');
|
||||
|
||||
var selectedTickets = [];
|
||||
$('.ticket-checkbox:checked').each(function() {
|
||||
selectedTickets.push($(this).attr('id').replace('ticket-', ''));
|
||||
});
|
||||
|
||||
var ticket_ids = selectedTickets.join(',');
|
||||
|
||||
// SweetAlert2 confirmation dialog
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'You are about to update the status of selected tickets.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, update it!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// AJAX request to submit the form
|
||||
$.ajax({
|
||||
url: 'update/ticket/status',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
ticket_ids: ticket_ids,
|
||||
status: status
|
||||
},
|
||||
success: function(response) {
|
||||
// Show success notification
|
||||
Swal.fire(
|
||||
'Updated!',
|
||||
'Tickets status has been updated successfully.',
|
||||
'success'
|
||||
);
|
||||
// Optionally reload or update the page
|
||||
location.reload();
|
||||
},
|
||||
error: function(xhr) {
|
||||
// Show error notification
|
||||
Swal.fire(
|
||||
'Error!',
|
||||
'An error occurred. Please try again.',
|
||||
'error'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--Update Status End-->
|
||||
|
||||
<!-- Reply to Multiple Start -->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.reply-to-multiple').on('click', function(){
|
||||
var message = CKEDITOR.instances.editor1.getData();
|
||||
if(message.trim() === '') {
|
||||
toastr.error('Message cannot be empty');
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedTickets = [];
|
||||
$('.ticket-checkbox:checked').each(function() {
|
||||
selectedTickets.push($(this).attr('id').replace('ticket-', ''));
|
||||
});
|
||||
|
||||
var ticket_ids = selectedTickets.join(',');
|
||||
console.log(ticket_ids);
|
||||
|
||||
// SweetAlert2 confirmation dialog
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: 'are you sure to send reply?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, send it!',
|
||||
cancelButtonText: 'Cancel'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.ajax({
|
||||
url: '/store/response',
|
||||
method: 'POST',
|
||||
data: {
|
||||
ticket_id: ticket_ids,
|
||||
message: message,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
|
||||
// Show success notification
|
||||
Swal.fire(
|
||||
'Updated!',
|
||||
'Reply has been sent successfully.',
|
||||
'success'
|
||||
);
|
||||
// Optionally reload or update the page
|
||||
location.reload();
|
||||
},
|
||||
error: function(xhr) {
|
||||
// Show error notification
|
||||
Swal.fire(
|
||||
'Error!',
|
||||
'An error occurred. Please try again.',
|
||||
'error'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Reply to Multiple End -->
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<script>
|
||||
$(document).ready(function() {
|
||||
// Toggle filter dropdown on button click
|
||||
$('.list-filter-btn').click(function() {
|
||||
$('.filter-options').toggle();
|
||||
});
|
||||
|
||||
// Initial hide for handle_multiple__options
|
||||
$('.filter-options').hide();
|
||||
$('.handle_multiple__options').hide();
|
||||
|
||||
// Toggle visibility of handle_multiple__options on button click
|
||||
$('.handle-multiple-btn').click(function() {
|
||||
$('.handle_multiple__options').toggle();
|
||||
});
|
||||
|
||||
// Initially disable all the buttons
|
||||
$('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
|
||||
// Enable/disable buttons based on the select all checkbox
|
||||
// $('#select-all').change(function() {
|
||||
// if ($(this).is(':checked')) {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', false);
|
||||
// } else {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Show the modal when "Assign post" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Assign post")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Move" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Move")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal2').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Reply to multiple" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Reply to multiple")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal3').show();
|
||||
});
|
||||
|
||||
// Close the modal when the close button or outside the modal is clicked
|
||||
$('.modal-close, .modal').click(function() {
|
||||
$('.modal').hide();
|
||||
});
|
||||
|
||||
// Prevent modal content from closing the modal when clicked
|
||||
$('.modal-content').click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="content chat-card-header d-flex align-items-center justify-content-between">
|
||||
<div class="header">Chats</div>
|
||||
<div class="data-actions d-flex justify-content-end">
|
||||
|
||||
<button class="action-button bg-dark-green-color color-light handle-multiple-btn">
|
||||
<img src="{{ asset('images/icons/Add_Plus.png') }}" alt="Plus Icon">
|
||||
<span>Handle Multiple</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="handle_multiple__options">
|
||||
<div class="common_shre">
|
||||
<label for="select-all"> <input type="checkbox" name="" id="select-all"> Select all</label>
|
||||
<div class="tags">
|
||||
<button>Assign post</button>
|
||||
<button id="delete-posts">Delete</button>
|
||||
<!--<button>Move</button>-->
|
||||
<button data-status="open" class="update-posts-status">Open</button>
|
||||
<button data-status="waiting" class="update-posts-status">Waiting</button>
|
||||
<button data-status="done" class="update-posts-status">Done</button>
|
||||
<!--<button>Tag</button>-->
|
||||
<!--<button>Not spam</button>-->
|
||||
<button>Reply to multiple</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,10 +1,157 @@
|
|||
<style>
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 34px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.chat{
|
||||
transform: translate(15px, 1px);
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.in_setting{
|
||||
display: none !important;
|
||||
|
||||
}
|
||||
@media screen and (max-width: 767px) {
|
||||
div.inbox-content-wrapper>.inbox-inner-wrapper>.user-box {
|
||||
width: 90px;
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 420px) {
|
||||
.logout {
|
||||
display: none !important;
|
||||
}
|
||||
.in_setting{
|
||||
display: block !important;
|
||||
margin-left:12px;
|
||||
}
|
||||
@media only screen and (max-width: 348px) {
|
||||
header .nav-links {
|
||||
gap: 17px;
|
||||
}
|
||||
.chat {
|
||||
transform: translate(7px, 1px) !important;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 525px) {
|
||||
div.chat-inbox>.chat-content-wrapper>.chat-message>.single-message-chat>.user-message {
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 315px) {
|
||||
header .nav-links {
|
||||
gap: 15px;
|
||||
}
|
||||
.chat {
|
||||
transform: translate(7px, 1px) !important;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.logout_form {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.logout_form .nav-btn {
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 6.26px;
|
||||
height: 38px;
|
||||
width: 126.89px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.content-area header .row .col-sm-8 {
|
||||
flex-direction: column;
|
||||
align-items: center !important;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
.single-message-chat {
|
||||
width: 100%;
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
|
||||
<header>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 user-name-nav-area d-flex align-content-center">
|
||||
<div class="dev-toggle-sidebar">
|
||||
<img src="{{ asset('images/icons/blocks-icon.svg') }}">
|
||||
<img src="https://kundesone.no/images/logo_cropped.png">
|
||||
</div>
|
||||
<h2 class="d-flex align-items-center">Hello Maxwell <span>👋🏼</span>,</h2>
|
||||
<h2 class="d-flex align-items-center">Hello {{auth()->user()->name}} <span>👋🏼</span>,</h2>
|
||||
</div>
|
||||
<div class="col-sm-8 d-flex justify-content-end align-items-center">
|
||||
<div class="search-box d-flex align-items-center">
|
||||
|
|
@ -12,7 +159,12 @@
|
|||
<input type="text" class="color-dark-green" placeholder="Search...">
|
||||
</div>
|
||||
<div class="nav-links d-flex align-items-center">
|
||||
<form method="POST" action="{{route('logout')}}">
|
||||
<span class="chat">Chat </span>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="toggleSwitch" @if(auth()->user()->is_available == 1) checked @endif>
|
||||
<span class="slider round">
|
||||
</label>
|
||||
<form class="logout" method="POST" action="{{route('logout')}}">
|
||||
@csrf
|
||||
<button class="nav-btn bg-dark-green-color">
|
||||
<img height="25" width="50" src="{{ asset('images/logout.png') }}" alt="">
|
||||
|
|
@ -77,6 +229,7 @@ class="chat-settings-btn-row text-center d-flex justify-content-center align-ite
|
|||
<a
|
||||
class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="item">
|
||||
<p class="action-heading-paragraph text-center align-content-center">
|
||||
|
|
@ -89,7 +242,15 @@ class="chat-settings-btn-row text-center d-flex justify-content-center align-ite
|
|||
<!--<a class="ui secondary basic button tag-btn shadow-none">Tags</a>-->
|
||||
<a href="{{ route('profile') }}"
|
||||
class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
</div> <hr >
|
||||
|
||||
<div class="logout_form">
|
||||
<form class="in_setting" method="POST" action="https://kundesone.no/logout">
|
||||
<input type="hidden" name="_token" value="18hlNz76CXQJdP55j8LVsnhIf8KpaEi5MXKu9EFV" autocomplete="off"> <button class="nav-btn bg-dark-green-color">
|
||||
<img height="25" width="50" src="https://kundesone.no/images/logout.png" alt="">
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -97,4 +258,75 @@ class="ui secondary basic button shadow-none setting-btn text-white align-conten
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
<script src="https://cdn.ckeditor.com/4.16.0/standard/ckeditor.js"></script>
|
||||
<!-- Toastr JS -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
||||
|
||||
<style>
|
||||
|
||||
.cke_notification.cke_notification_warning{
|
||||
display:none!important;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.getElementById('toggleButton').addEventListener('click', function() {
|
||||
this.classList.toggle('btn-success');
|
||||
this.classList.toggle('btn-primary');
|
||||
this.textContent = this.classList.contains('btn-success') ? 'On' : 'Off';
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--chat avialability ajax-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#toggleSwitch').off('change').on('change', function(e) {
|
||||
// Prevent default form submission if the toggle is inside a form
|
||||
e.preventDefault();
|
||||
|
||||
const isChecked = $(this).is(':checked');
|
||||
let status = isChecked ? 'on' : 'off';
|
||||
|
||||
// Disable the checkbox to avoid multiple clicks during the AJAX call
|
||||
$(this).prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: 'update/chat-availability',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
status: status
|
||||
},
|
||||
success: function(response) {
|
||||
if(response.success) {
|
||||
toastr.success('Chat Availability Updated Successfully');
|
||||
}
|
||||
// Enable the checkbox again after the AJAX call completes
|
||||
$('#toggleSwitch').prop('disabled', false);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error:', error);
|
||||
$('#toggleSwitch').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.content-area header .row .col-sm-8 {
|
||||
flex-direction: column;
|
||||
align-items: center !important;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,37 @@
|
|||
<div class="sidebar-area">
|
||||
<aside class="bg-dark-green-color">
|
||||
<div class="image-box d-flex justify-content-between">
|
||||
<div class="image-box d-flex justify-content-between frame">
|
||||
<img src="{{ asset('images/logo-white.png') }}" alt="Site Logo">
|
||||
<div class="dev-toggle-sidebar dev-close"><img src="{{ asset('images/icons/close-icon.svg') }}" alt=""></div>
|
||||
<div class="dev-toggle-sidebar dev-close"><img src="https://kundesone.no/images/icons/Frame.png" alt=""></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.side-bar-links ul li .bg-light-color .color-light{
|
||||
color: #383f33 !important;
|
||||
}
|
||||
.sidebar_icon{
|
||||
font-size: 20px !important;
|
||||
color: white !important;
|
||||
}
|
||||
.bg-light-color .sidebar_icon{
|
||||
color: #383F33 !important;
|
||||
}
|
||||
.frame .dev-toggle-sidebar img {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
vertical-align: top !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="side-bar-links">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{ route('index') }}"
|
||||
class="side-bar-link bg-light-color d-flex align-items-center justify-content-between">
|
||||
class="side-bar-link bg-light-color d-flex align-items-center justify-content-between aw-a-inbox">
|
||||
<div class="link-left-content align-items-center d-flex">
|
||||
<img src="{{ asset('images/icons/Message.png') }}" alt="Message">
|
||||
<h6 class="color-dark-green">Inbox</h6>
|
||||
<i class="fa fa-envelope-o sidebar_icon" aria-hidden="true"></i>
|
||||
<h6 class="color-light">Inbox</h6>
|
||||
</div>
|
||||
<div class="link-right-content">
|
||||
<img src="{{ asset('images/icons/chevron-right-dark.png') }}" alt="chevron right">
|
||||
|
|
@ -20,9 +40,9 @@ class="side-bar-link bg-light-color d-flex align-items-center justify-content-be
|
|||
</li>
|
||||
<li>
|
||||
<a href="{{ route('waiting') }}"
|
||||
class="side-bar-link d-flex align-items-center justify-content-between">
|
||||
class="side-bar-link d-flex align-items-center justify-content-between aw-a-waiting">
|
||||
<div class="link-left-content align-items-center d-flex">
|
||||
<img src="{{ asset('images/icons/Time_light.png') }}" alt="Message">
|
||||
<i class="fa fa-clock-o sidebar_icon" aria-hidden="true"></i>
|
||||
<h6 class="color-light">Waiting</h6>
|
||||
</div>
|
||||
<div class="link-right-content">
|
||||
|
|
@ -32,10 +52,10 @@ class="side-bar-link d-flex align-items-center justify-content-between">
|
|||
</li>
|
||||
<li>
|
||||
<a href="{{ route('all.tickets') }}"
|
||||
class="side-bar-link d-flex align-items-center justify-content-between">
|
||||
class="side-bar-link d-flex align-items-center justify-content-between aw-a-all">
|
||||
<div class="link-left-content align-items-center d-flex">
|
||||
<img src="{{ asset('images/Ticket_use.svg') }}" alt="Message">
|
||||
<h6 class="color-light">All Tickets</h6>
|
||||
<i class="fa fa-ticket sidebar_icon" aria-hidden="true"></i>
|
||||
<h6 class="color-light">Chats</h6>
|
||||
</div>
|
||||
<div class="link-right-content">
|
||||
<img src="{{ asset('images/icons/chevron-right-light.png') }}" alt="chevron right">
|
||||
|
|
@ -43,9 +63,9 @@ class="side-bar-link d-flex align-items-center justify-content-between">
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="side-bar-link d-flex align-items-center justify-content-between">
|
||||
<a href="#" class="side-bar-link d-flex align-items-center justify-content-between aw-a-stats">
|
||||
<div class="link-left-content align-items-center d-flex">
|
||||
<img src="{{ asset('images/chart-square.svg') }}" alt="Message">
|
||||
<i class="fa fa-bar-chart sidebar_icon" aria-hidden="true"></i>
|
||||
<h6 class="color-light">Statistics</h6>
|
||||
</div>
|
||||
<div class="link-right-content">
|
||||
|
|
@ -62,7 +82,7 @@ class="side-bar-link d-flex align-items-center justify-content-between">
|
|||
<li class="channels-widgets-wrapper side-bar-link bg-light-color d-flex align-items-center justify-content-between">
|
||||
|
||||
<div class="link-left-content align-items-center d-flex">
|
||||
<img src="{{ asset('images/icons/Message.png') }}" alt="Message">
|
||||
<i class="fa fa-envelope-o sidebar_icon" aria-hidden="true"></i>
|
||||
<h6 class="color-dark-green">Channels</h6>
|
||||
</div>
|
||||
<div class="link-right-content">
|
||||
|
|
@ -100,12 +120,15 @@ class="dropdown-item-label color-light">FORUM</span></p>
|
|||
<div class="profile-nav-row d-flex side-bar-link">
|
||||
|
||||
<div class="profile-nav-box">
|
||||
<div class="img-box"><img src="{{ asset('images/user.png') }}" alt="User Image"></div>
|
||||
@if(!is_null(Auth::user()->profile_image))
|
||||
<div class="img-box"><a href="{{route('profile')}}"><img style="height: 42px; width: 42px; border-radius: 50%" src="{{ url('' . Auth::user()->profile_image) }}" alt="User Image"></a></div>
|
||||
@else
|
||||
<div class="img-box"><img style="height: 42px; width: 42px; border-radius: 50%" src="{{ asset('dummy-image.jpg') }}" alt="User Image"></div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="user-info-box d-flex justify-content-between">
|
||||
<div class="info">
|
||||
<p class="color-light side-bar-user-name">Maxwell</p>
|
||||
<p class="color-offset-white">Project Manager</p>
|
||||
<a style="text-decoration: none; color: white;" href="{{route('profile')}}"><p class="color-light side-bar-user-name">{{Auth::user()->name}}</p></a>
|
||||
</div>
|
||||
<div class="icon align-self-center">
|
||||
<img src="{{ asset('images/icons/chevron-down 3.png') }}" alt="Chevron Down Icon">
|
||||
|
|
|
|||
|
|
@ -10,56 +10,134 @@
|
|||
<meta content="" name="description">
|
||||
<meta content="" name="keywords">
|
||||
|
||||
<!-- Favicons -->
|
||||
<link href="" rel="icon">
|
||||
<link href="assets/img/apple-touch-icon.png" rel="apple-touch-icon">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>
|
||||
<!-- Bootstrap Styles -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link href="https://api.fontshare.com/v2/css?f[]=satoshi@300,301,400,401,500,501,700,701,900,901&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<!-- font-awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" />
|
||||
<link rel="stylesheet" href="{{ asset('assets/auth.css') }}">
|
||||
<!-- Toastr CSS -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Satoshi', sans-serif;
|
||||
background-color: #f4f7f9;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 90%;
|
||||
margin: 40px auto;
|
||||
padding: 30px;
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
margin-bottom: 15px;
|
||||
color: #4A4A4A;
|
||||
}
|
||||
|
||||
.alert {
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.domain-details, .dns-records {
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.record {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
margin-bottom: 10px;
|
||||
transition: background-color 0.3s, transform 0.2s;
|
||||
}
|
||||
|
||||
.record:hover {
|
||||
background-color: #f1f1f1;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn.signup {
|
||||
background: #748C62;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 12px 25px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background 0.3s, transform 0.2s;
|
||||
}
|
||||
|
||||
.btn.signup:hover {
|
||||
background: #45a049;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.btn.signup {
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.verify{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Domain Verification Response</h1>
|
||||
<h1>Instructions to Verify Domain</h1>
|
||||
|
||||
<div class="domain-details">
|
||||
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
|
||||
<li>Domain is {{$domain->getDomain()->getState()}}</li>
|
||||
|
||||
</ul>
|
||||
<div class="alert alert-{{$domain->getDomain()->getState() == 'active'?'success':'danger'}}">
|
||||
<ul>
|
||||
<li>Domain is {{$domain->getDomain()->getState()}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2>Domain Information</h2>
|
||||
<p><strong>Name:</strong> {{ $domain->getDomain()->getName() }}</p>
|
||||
|
||||
<p><strong>State:</strong> {{ $domain->getDomain()->getState() }}</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="dns-records">
|
||||
<h2>Inbound DNS Records</h2>
|
||||
@foreach($domain->getInboundDnsRecords() as $record)
|
||||
<div class="record">
|
||||
<p><strong>Type:</strong> {{ $record->getType() }}</p>
|
||||
<p><strong>Value:</strong> {{ $record->getValue() }}</p>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<h2>Outbound DNS Records</h2>
|
||||
<h2>Step 1: Add Forwarder</h2>
|
||||
<div class="record">
|
||||
<p>Forward your email to internal email: <span class="alert-success"><b>kundesone.{{ $domain->getDomain()->getName() }}@mailgun.kundesone.no</b></span>. Make sure to forward only your company email that you registered.</p>
|
||||
</div>
|
||||
|
||||
<h2>Step 2: Add Outbound DNS Records</h2>
|
||||
@foreach($domain->getOutboundDnsRecords() as $record)
|
||||
<div class="record">
|
||||
<p><strong>Type:</strong> {{ $record->getType() }}</p>
|
||||
|
|
@ -67,69 +145,31 @@
|
|||
<p><strong>Value:</strong> {{ $record->getValue() }}</p>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<h2>Step 3: Add Inbound DNS Records</h2>
|
||||
@foreach($domain->getInboundDnsRecords() as $record)
|
||||
<div class="record">
|
||||
<p><strong>Type:</strong> {{ $record->getType() }}</p>
|
||||
<p><strong>Name:</strong> {{ $domain->getDomain()->getName() }}</p>
|
||||
<p><strong>Value:</strong> {{ $record->getValue() }}</p>
|
||||
<p><strong>Priority:</strong> 10</p>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<h2>Note: DNS Propagation Time</h2>
|
||||
<div class="record">
|
||||
<p>DNS propagation can take up to 48 hours. During this time, your domain may not be active.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="verify-form" action="{{route('verifyDomain')}}" method="post">
|
||||
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="domain" value="{{$domain->getDomain()->getName()}}"/>
|
||||
|
||||
<button type="submit" class="btn signup">Verify Domain
|
||||
</button>
|
||||
<form id="verify-form" action="{{route('verifyDomain')}}" method="post">
|
||||
@csrf
|
||||
<input type="hidden" name="domain" value="{{$domain->getDomain()->getName()}}"/>
|
||||
<div class="verify">
|
||||
<button type="submit" class="btn signup">Verify Domain</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
#verify-form{
|
||||
display:flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn.signup{
|
||||
background:#748c62;
|
||||
color:white;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.message {
|
||||
background-color: #f0f0f0;
|
||||
padding: 10px;
|
||||
border-left: 5px solid green;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.domain-details, .dns-records {
|
||||
background-color: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.record {
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #eee;
|
||||
padding: 8px;
|
||||
margin-bottom: 10px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<button type="button">Response</button>
|
||||
<button type="button">Canned Responses</button>
|
||||
<button type="button">Acknowledge</button>
|
||||
<button type="button">Rules</button>
|
||||
<!--<button type="button">Rules</button>-->
|
||||
<button type="button">Spam handling</button>
|
||||
<!--<button type="button">Tags</button>-->
|
||||
<!--<button type="button">Others</button>-->
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<div class="col col-left">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Receiving email address </label>
|
||||
<input name="company_email" type="email" value="{{ Auth::user()->company->email }}" placeholder="kundo@limonmedia.no" readonly required>
|
||||
<input name="company_email" type="email" value="{{ $company->email }}" placeholder="support@kundesone.no" readonly required>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. support@yourcompany.com</span>
|
||||
|
|
@ -38,23 +38,23 @@
|
|||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Email address on Kundo</label>
|
||||
<input name="kundo_email" type="email" value="{{ $basic_setting[0]['value'] ?? '' }}" placeholder="kundo.limonmedia.no@mail.kundo.se" required>
|
||||
<input name="kundo_email" readonly type="email" value="{{ $company->internal_email }}" placeholder="kundo.limonmedia.no@mailgun.kundesone.no" required>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>Updates when you change the email address above</span>
|
||||
<span>Your kundesone internal email address.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Inbox name</label>
|
||||
<input name="inbox_name" type="text" placeholder="Type here.." value="{{ $basic_setting[1]['value'] ?? '' }}" required>
|
||||
<input name="inbox_name" type="text" placeholder="Type here.." value="{{ $company->getMeta('inbox_name') ?? '' }}" required>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>Your internal name. I.e. the email address</span>
|
||||
<span>Your internal name. I.e. the Inbox</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Sender name</label>
|
||||
<input name="sender_name" type="text" placeholder="Type here.." value="{{ $basic_setting[2]['value'] ?? '' }}" required>
|
||||
<input name="sender_name" type="text" placeholder="Type here.." value="{{ $company->getMeta('sender_name') ?? '' }}" required>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. company name or department</span>
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
<select name="language" required>
|
||||
<option value="">Select Language</option>
|
||||
@foreach($languages as $language)
|
||||
<option value="{{$language->value}}" @if(count($basic_setting) > 0 && $basic_setting[3]['value'] == $language->value) selected @endif>{{$language->title}}</option>
|
||||
<option value="{{$language->value}}" @if(count($basic_setting) > 0 && $company->getMeta('language') == $language->value) selected @endif>{{$language->title}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
<select name="timezone" required>
|
||||
<option value="">Select your Timezone</option>
|
||||
@foreach($timezones as $timezone)
|
||||
<option value="{{$timezone->label}}" @if(count($basic_setting) > 0 && $basic_setting[4]['value'] == $timezone->label) selected @endif>{{$timezone->label}}</option>
|
||||
<option value="{{$timezone->label}}" @if(count($basic_setting) > 0 && $company->getMeta('timezone') == $timezone->label) selected @endif>{{$timezone->label}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -165,7 +165,7 @@
|
|||
<h2>Common email signature</h2>
|
||||
</div>
|
||||
<div class="dev-content-inner">
|
||||
<form method="POST" action="{{ route('inbox.email.signature') }}">
|
||||
<form method="POST" action="{{ route('inbox.email.signature') }}" onsubmit="return validateSignatureForm()">
|
||||
@csrf
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<div class="input-box-row">
|
||||
|
|
@ -186,13 +186,21 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
title.</span>
|
||||
</div>
|
||||
</div>
|
||||
@if(Auth::user()->role_id == 2)
|
||||
<button type="submit" class="dev-form-submit-btn">Save</button>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function validateSignatureForm() {
|
||||
var textarea = document.getElementById('editor1');
|
||||
if (textarea.value === '') {
|
||||
toastr.error('Please enter a message in the textarea.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
<script src="https://cdn.ckeditor.com/4.16.0/standard/ckeditor.js"></script>
|
||||
<script>
|
||||
CKEDITOR.replace('editor1');
|
||||
|
|
@ -218,7 +226,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<h3>Monday</h3>
|
||||
<div class="schedule-box">
|
||||
@php
|
||||
$monday_start_time = getResponse(Auth::user()->company->id, 'monday_start_time', 'Response Time');
|
||||
$monday_start_time = getResponse($company->id, 'monday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<input id="monday_start_time" name="monday_start_time" type="time" @if(isset($monday_start_time) && !is_null($monday_start_time)) value="{{$monday_start_time->value}}" @endif placeholder="08:00">
|
||||
<!-- <img src="{{ asset('images/downn.svg') }}" alt=""> -->
|
||||
|
|
@ -226,14 +234,14 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<span class="line"></span>
|
||||
<div class="schedule-box">
|
||||
@php
|
||||
$monday_end_time = getResponse(Auth::user()->company->id, 'monday_end_time', 'Response Time');
|
||||
$monday_end_time = getResponse($company->id, 'monday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<input id="monday_end_time" name="monday_end_time" type="time" @if(isset($monday_end_time) && !is_null($monday_end_time)) value="{{$monday_end_time->value}}" @endif placeholder="16:00">
|
||||
<!-- <img src="{{ asset('images/downn.svg') }}" alt=""> -->
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$monday_closed = getResponse(Auth::user()->company->id, 'monday_closed', 'Response Time');
|
||||
$monday_closed = getResponse($company->id, 'monday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="monday_closed" name="monday_closed" @if(isset($monday_closed) && !is_null($monday_closed)) checked @endif type="checkbox" onclick="toggleClosed('monday')">
|
||||
|
|
@ -244,7 +252,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Tuesday</h3>
|
||||
@php
|
||||
$tuesday_start_time = getResponse(Auth::user()->company->id, 'tuesday_start_time', 'Response Time');
|
||||
$tuesday_start_time = getResponse($company->id, 'tuesday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="tuesday_start_time" name="tuesday_start_time" type="time" @if(isset($tuesday_start_time) && !is_null($tuesday_start_time)) value="{{$tuesday_start_time->value}}" @endif placeholder="08:00">
|
||||
|
|
@ -252,7 +260,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$tuesday_end_time = getResponse(Auth::user()->company->id, 'tuesday_end_time', 'Response Time');
|
||||
$tuesday_end_time = getResponse($company->id, 'tuesday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="tuesday_end_time" name="tuesday_end_time" type="time" @if(isset($tuesday_end_time) && !is_null($tuesday_end_time)) value="{{$tuesday_end_time->value}}" @endif placeholder="16:00">
|
||||
|
|
@ -260,7 +268,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$tuesday_closed = getResponse(Auth::user()->company->id, 'tuesday_closed', 'Response Time');
|
||||
$tuesday_closed = getResponse($company->id, 'tuesday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="tuesday_closed" name="tuesday_closed" @if(isset($tuesday_closed) && !is_null($tuesday_closed)) checked @endif type="checkbox" onclick="toggleClosed('tuesday')">
|
||||
|
|
@ -271,7 +279,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Wednesday</h3>
|
||||
@php
|
||||
$wednesday_start_time = getResponse(Auth::user()->company->id, 'wednesday_start_time', 'Response Time');
|
||||
$wednesday_start_time = getResponse($company->id, 'wednesday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="wednesday_start_time" name="wednesday_start_time" @if(isset($wednesday_start_time) && !is_null($wednesday_start_time)) value="{{$wednesday_start_time->value}}" @endif type="time" placeholder="08:00">
|
||||
|
|
@ -279,7 +287,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$wednesday_end_time = getResponse(Auth::user()->company->id, 'wednesday_end_time', 'Response Time');
|
||||
$wednesday_end_time = getResponse($company->id, 'wednesday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="wednesday_end_time" name="wednesday_end_time" @if(isset($wednesday_end_time) && !is_null($wednesday_end_time)) value="{{$wednesday_end_time->value}}" @endif type="time" placeholder="16:00">
|
||||
|
|
@ -287,7 +295,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$wednesday_closed = getResponse(Auth::user()->company->id, 'wednesday_closed', 'Response Time');
|
||||
$wednesday_closed = getResponse($company->id, 'wednesday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="wednesday_closed" name="wednesday_closed" @if(isset($wednesday_closed) && !is_null($wednesday_closed)) checked @endif type="checkbox" onclick="toggleClosed('wednesday')">
|
||||
|
|
@ -298,7 +306,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Thursday</h3>
|
||||
@php
|
||||
$thursday_start_time = getResponse(Auth::user()->company->id, 'thursday_start_time', 'Response Time');
|
||||
$thursday_start_time = getResponse($company->id, 'thursday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="thursday_start_time" name="thursday_start_time" @if(isset($thursday_start_time) && !is_null($thursday_start_time)) value="{{$thursday_start_time->value}}" @endif type="time" placeholder="08:00">
|
||||
|
|
@ -306,7 +314,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$thursday_end_time = getResponse(Auth::user()->company->id, 'thursday_end_time', 'Response Time');
|
||||
$thursday_end_time = getResponse($company->id, 'thursday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="thursday_end_time" name="thursday_end_time" @if(isset($thursday_end_time) && !is_null($thursday_end_time)) value="{{$thursday_end_time->value}}" @endif type="time" placeholder="16:00">
|
||||
|
|
@ -314,7 +322,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$thursday_closed = getResponse(Auth::user()->company->id, 'thursday_closed', 'Response Time');
|
||||
$thursday_closed = getResponse($company->id, 'thursday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="thursday_closed" name="thursday_closed" @if(isset($thursday_closed) && !is_null($thursday_closed)) checked @endif type="checkbox" onclick="toggleClosed('thursday')">
|
||||
|
|
@ -325,7 +333,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Friday</h3>
|
||||
@php
|
||||
$friday_start_time = getResponse(Auth::user()->company->id, 'friday_start_time', 'Response Time');
|
||||
$friday_start_time = getResponse($company->id, 'friday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="friday_start_time" name="friday_start_time" @if(isset($friday_start_time) && !is_null($friday_start_time)) value="{{$friday_start_time->value}}" @endif type="time" placeholder="08:00">
|
||||
|
|
@ -333,7 +341,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$friday_end_time = getResponse(Auth::user()->company->id, 'friday_end_time', 'Response Time');
|
||||
$friday_end_time = getResponse($company->id, 'friday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="friday_end_time" name="friday_end_time" @if(isset($friday_end_time) && !is_null($friday_end_time)) value="{{$friday_end_time->value}}" @endif type="time" placeholder="16:00">
|
||||
|
|
@ -341,7 +349,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$friday_closed = getResponse(Auth::user()->company->id, 'friday_closed', 'Response Time');
|
||||
$friday_closed = getResponse($company->id, 'friday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="friday_closed" name="friday_closed" @if(isset($friday_closed) && !is_null($friday_closed)) checked @endif type="checkbox" onclick="toggleClosed('friday')">
|
||||
|
|
@ -352,7 +360,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Saturday</h3>
|
||||
@php
|
||||
$saturday_start_time = getResponse(Auth::user()->company->id, 'saturday_start_time', 'Response Time');
|
||||
$saturday_start_time = getResponse($company->id, 'saturday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="saturday_start_time" name="saturday_start_time" @if(isset($saturday_start_time) && !is_null($saturday_start_time)) value="{{$saturday_start_time->value}}" @endif type="time" placeholder="08:00">
|
||||
|
|
@ -360,7 +368,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$saturday_end_time = getResponse(Auth::user()->company->id, 'saturday_end_time', 'Response Time');
|
||||
$saturday_end_time = getResponse($company->id, 'saturday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="saturday_end_time" name="saturday_end_time" @if(isset($saturday_end_time) && !is_null($saturday_end_time)) value="{{$saturday_end_time->value}}" @endif type="time" placeholder="16:00">
|
||||
|
|
@ -368,7 +376,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$satureday_closed = getResponse(Auth::user()->company->id, 'satureday_closed', 'Response Time');
|
||||
$satureday_closed = getResponse($company->id, 'satureday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="saturday_closed" name="saturday_closed" @if(isset($saturday_closed) && !is_null($saturday_closed)) checked @endif type="checkbox" onclick="toggleClosed('saturday')">
|
||||
|
|
@ -379,7 +387,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-content-schedule">
|
||||
<h3>Sunday</h3>
|
||||
@php
|
||||
$sunday_start_time = getResponse(Auth::user()->company->id, 'sunday_start_time', 'Response Time');
|
||||
$sunday_start_time = getResponse($company->id, 'sunday_start_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="sunday_start_time" name="sunday_start_time" @if(isset($sunday_start_time) && !is_null($sunday_start_time)) value="{{$sunday_start_time->value}}" @endif type="time" placeholder="08:00">
|
||||
|
|
@ -387,7 +395,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<span class="line"></span>
|
||||
@php
|
||||
$sunday_end_time = getResponse(Auth::user()->company->id, 'sunday_end_time', 'Response Time');
|
||||
$sunday_end_time = getResponse($company->id, 'sunday_end_time', 'Response Time');
|
||||
@endphp
|
||||
<div class="schedule-box">
|
||||
<input id="sunday_end_time" name="sunday_end_time" @if(isset($sunday_end_time) && !is_null($sunday_end_time)) value="{{$sunday_end_time->value}}" @endif type="time" placeholder="16:00">
|
||||
|
|
@ -395,7 +403,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$sunday_closed = getResponse(Auth::user()->company->id, 'sunday_closed', 'Response Time');
|
||||
$sunday_closed = getResponse($company->id, 'sunday_closed', 'Response Time');
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Closed
|
||||
<input id="sunday_closed" name="sunday_closed" @if(isset($sunday_closed) && !is_null($sunday_closed)) checked @endif type="checkbox" onclick="toggleClosed('sunday')">
|
||||
|
|
@ -409,7 +417,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Expected response time, in hours</label>
|
||||
@php
|
||||
$expected_response = getResponse(Auth::user()->company->id, 'expected_response', 'Response Time');
|
||||
$expected_response = getResponse($company->id, 'expected_response', 'Response Time');
|
||||
@endphp
|
||||
<input name="expected_response" type="text" @if(isset($expected_response) && !is_null($expected_response)) value="{{ $expected_response->value }}" @endif placeholder="8">
|
||||
<div class="dev-input-info">
|
||||
|
|
@ -420,9 +428,7 @@ class="form-control input-reply-textarea" required>{!! $email_signature->value ?
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@if(Auth::user()->role_id == 2)
|
||||
<button type="submit" class="dev-form-submit-btn">Save</button>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -471,15 +477,13 @@ function toggleClosed(day) {
|
|||
@csrf
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Name</label>
|
||||
<input name="name" type="text" placeholder="Type here" value="{{ $canned_response[0]['value'] ?? '' }}" required>
|
||||
<input name="name" type="text" placeholder="Type here" required>
|
||||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Text</label>
|
||||
<textarea name="text" required rows="6">{{ $canned_response[1]['value'] ?? '' }}</textarea>
|
||||
<textarea name="text" required rows="6"></textarea>
|
||||
</div>
|
||||
@if(Auth::user()->role_id == 2)
|
||||
<button type="submit" class="dev-form-submit-btn">Save</button>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -487,20 +491,29 @@ function toggleClosed(day) {
|
|||
<div class="dev-title-row">
|
||||
<h2>Canned responses</h2>
|
||||
<div class="dev-users-boxs">
|
||||
@foreach(json_decode($canned_response->value) as $index => $values)
|
||||
@if(count($canned_response) > 0)
|
||||
@foreach($canned_response as $index => $value)
|
||||
|
||||
@php
|
||||
|
||||
$result = json_decode($value->value);
|
||||
|
||||
@endphp
|
||||
|
||||
<div class="dev-users-box">
|
||||
<div class="dev-box">
|
||||
<h3>{{ $values->name }}</h3>
|
||||
<span>{{ $values->text }}</span>
|
||||
<h3>{{ $result->name }}</h3>
|
||||
<span>{{ $result->text }}</span>
|
||||
</div>
|
||||
<!--<div class="dev-icon">-->
|
||||
<!-- <img src="{{ asset('images/settingss.svg') }}" alt="">-->
|
||||
<!--</div>-->
|
||||
<div class="dev-icon">
|
||||
<img src="{{ asset('images/settingss.svg') }}" alt="">
|
||||
</div>
|
||||
<div class="dev-icon">
|
||||
<a href="{{ route('delete.canned.response', $index) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
|
||||
<a style="cursor:pointer;" href="{{ route('delete.canned.response', $value->id) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -520,7 +533,7 @@ function toggleClosed(day) {
|
|||
@csrf
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$activate_delivery_confirmation = getResponse(Auth::user()->company->id, 'activate_delivery_confirmation', 'Acknowledgement of Receipt')
|
||||
$activate_delivery_confirmation = getResponse($company->id, 'activate_delivery_confirmation', 'Acknowledgement of Receipt')
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Activate delivery confirmation
|
||||
<input name="activate_delivery_confirmation" @if(isset($activate_delivery_confirmation) && !is_null($activate_delivery_confirmation)) checked @endif type="checkbox">
|
||||
|
|
@ -530,7 +543,7 @@ function toggleClosed(day) {
|
|||
<div class="dev-form-inner">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
@php
|
||||
$automatic_reply_subject = getResponse(Auth::user()->company->id, 'automatic_reply_subject', 'Acknowledgement of Receipt')
|
||||
$automatic_reply_subject = getResponse($company->id, 'automatic_reply_subject', 'Acknowledgement of Receipt')
|
||||
@endphp
|
||||
<label>Subject of the automatic reply</label>
|
||||
<input name="automatic_reply_subject" type="text" @if(isset($automatic_reply_subject) && !is_null($automatic_reply_subject)) value="{{ $automatic_reply_subject->value }}" @endif placeholder="Type here">
|
||||
|
|
@ -558,7 +571,7 @@ function toggleClosed(day) {
|
|||
<h3>Text in the automatic reply</h3>
|
||||
<div class="input-box-row">
|
||||
@php
|
||||
$automatic_reply_text = getResponse(Auth::user()->company->id, 'automatic_reply_text', 'Acknowledgement of Receipt')
|
||||
$automatic_reply_text = getResponse($company->id, 'automatic_reply_text', 'Acknowledgement of Receipt')
|
||||
@endphp
|
||||
<div class="ui card inbox-send-message-card w-100">
|
||||
<div class="content input-options bg-dark-green-color">
|
||||
|
|
@ -596,7 +609,7 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
|
|||
</div>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$confirmation_receipt = getResponse(Auth::user()->company->id, 'confirmation_receipt', 'Acknowledgement of Receipt')
|
||||
$confirmation_receipt = getResponse($company->id, 'confirmation_receipt', 'Acknowledgement of Receipt')
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Only send confirmation of receipt outside
|
||||
of business hours
|
||||
|
|
@ -612,7 +625,7 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
|
|||
</p>
|
||||
<div class="dev-input-group">
|
||||
@php
|
||||
$activate_ticket_number = getResponse(Auth::user()->company->id, 'activate_ticket_number', 'Acknowledgement of Receipt')
|
||||
$activate_ticket_number = getResponse($company->id, 'activate_ticket_number', 'Acknowledgement of Receipt')
|
||||
@endphp
|
||||
<label class="dev-checkbox-wrapper">Activate ticket numbers
|
||||
<input name="activate_ticket_number" @if(isset($activate_ticket_number) && !is_null($activate_ticket_number)) checked @endif type="checkbox">
|
||||
|
|
@ -645,185 +658,178 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
|
|||
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="dev-tabcontent dev-tabcontent-rules">
|
||||
<div class="dev-tabcontent-outers">
|
||||
<div class="dev-title-row">
|
||||
<h2>Automatic rules</h2>
|
||||
<p>
|
||||
With automatic rules you can perform common tasks automatically, e.g. assign an
|
||||
e-mail to a specific person if the subject contains a certain word. Automatic
|
||||
rules consist of a filter and an effect.
|
||||
</p>
|
||||
</div>
|
||||
<h2>Create a new rule</h2>
|
||||
<form>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Name</label>
|
||||
<input type="text" placeholder="Type here..">
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>Tag everything from the sales department</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<h3>Filter</h3>
|
||||
<p>If you complete the From, To, and Subject fields, they must all match an email for
|
||||
the rule to be activated. Leave any field empty to avoid having to match that part.
|
||||
If you specify multiple email addresses in the same field, it's enough for one of
|
||||
them to match.
|
||||
If, for example, you fill in <a href="#">support@kundo.se</a> and <a
|
||||
href="#">info@kundo.se</a> in the From field,
|
||||
and "hello" in the subject field, all e-mails from <a href="#">support@kundo.se</a>
|
||||
OR <a href="#">info@kundo.se</a>
|
||||
that ALSO contains "hello" in the subject field will match.
|
||||
If you want to activate a rule for all emails that come from a group of email
|
||||
addresses, you can write *@kundo.se in the "from" field.
|
||||
</p>
|
||||
<form>
|
||||
<div class="dev-form-inner">
|
||||
<div class="col-left">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>From</label>
|
||||
<input type="text" placeholder="Type here..">
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. example@example.com or *@example.com</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>To</label>
|
||||
<input type="text" placeholder="Type here..">
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. test@example.com</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-right">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Subject Contains</label>
|
||||
<input type="text" placeholder="Type here..">
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. Great deals!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Text Contains</label>
|
||||
<input type="text" placeholder="Type here..">
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>E.g. Great deals!</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">All e-mails automatically marked as spam
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<h3>Exceptions</h3>
|
||||
<p>Email that matches the filter above but for which the rule should not be activated.
|
||||
</p>
|
||||
<form>
|
||||
<div class="dev-form-inner">
|
||||
<div class="col-left">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Subject Contains</label>
|
||||
<textarea rows="6">Type here..</textarea>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>Order Confirmation</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-right">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Text Contains</label>
|
||||
<textarea rows="6">Type here..</textarea>
|
||||
<div class="dev-input-info">
|
||||
<img src="{{ asset('images/info.svg') }}" alt="info">
|
||||
<span>Your Order</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<h3>Effect</h3>
|
||||
<p>The effect describes what should happen when the filter above matches. It happens
|
||||
automatically, before the e-mail shows up in
|
||||
the dashboard.</p>
|
||||
<form>
|
||||
<div class="dev-content-schedule">
|
||||
<label>Monday</label>
|
||||
<div class="schedule-box">
|
||||
<input type="text" placeholder="08:00">
|
||||
<img src="{{ asset('images/downn.svg') }}" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="dev-form-inner">
|
||||
<div class="col-left">
|
||||
<div class="dev-input-group dev-input-group-input-info">
|
||||
<label>Message to assigned editor</label>
|
||||
<textarea rows="6">Hi! Feel free to contact us via chat if you are wondering about anything.
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">Remove and hide from the statistics
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-right">
|
||||
<div class="dev-content-schedule">
|
||||
<label>Add tags</label>
|
||||
<div class="schedule-box">
|
||||
<input type="text" placeholder="Add tags">
|
||||
<img src="{{ asset('images/downn.svg') }}" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="checkbox-box">
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">Set as done
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">Set highest priority
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">Mark as spam
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label class="dev-checkbox-wrapper">Set lowest priority
|
||||
<input type="checkbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!--<div class="dev-tabcontent dev-tabcontent-rules">-->
|
||||
<!-- <div class="dev-tabcontent-outers">-->
|
||||
<!-- <div class="dev-title-row">-->
|
||||
<!-- <h2>Automatic rules</h2>-->
|
||||
<!-- <p>-->
|
||||
<!-- With automatic rules you can perform common tasks automatically, e.g. assign an-->
|
||||
<!-- e-mail to a specific person if the subject contains a certain word. Automatic-->
|
||||
<!-- rules consist of a filter and an effect.-->
|
||||
<!-- </p>-->
|
||||
<!-- </div>-->
|
||||
<!-- <h2>Create a new rule</h2>-->
|
||||
<!-- <form method="POST" action="{{ route('update.rule') }}">-->
|
||||
<!-- @csrf-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Name</label>-->
|
||||
<!-- <input name="name" type="text" placeholder="Type here.." value="{{$rule->name ?? ''}}">-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>Tag everything from the sales department</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <h3>Filter</h3>-->
|
||||
<!-- <p>If you complete the From, To, and Subject fields, they must all match an email for-->
|
||||
<!-- the rule to be activated. Leave any field empty to avoid having to match that part.-->
|
||||
<!-- If you specify multiple email addresses in the same field, it's enough for one of-->
|
||||
<!-- them to match.-->
|
||||
<!-- If, for example, you fill in <a href="#">support@kundo.se</a> and <a-->
|
||||
<!-- href="#">info@kundo.se</a> in the From field,-->
|
||||
<!-- and "hello" in the subject field, all e-mails from <a href="#">support@kundo.se</a>-->
|
||||
<!-- OR <a href="#">info@kundo.se</a>-->
|
||||
<!-- that ALSO contains "hello" in the subject field will match.-->
|
||||
<!-- If you want to activate a rule for all emails that come from a group of email-->
|
||||
<!-- addresses, you can write *@kundo.se in the "from" field.-->
|
||||
<!-- </p>-->
|
||||
<!-- <div class="dev-form-inner">-->
|
||||
<!-- <div class="col-left">-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>From</label>-->
|
||||
<!-- <input type="email" name="from" placeholder="Type here.." value="{{$rule->from ?? ''}}">-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>E.g. example@example.com or *@example.com</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>To</label>-->
|
||||
<!-- <input type="email" name="to" placeholder="Type here.." value="{{$rule->to ?? ''}}">-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>E.g. test@example.com</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col-right">-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Subject Contains</label>-->
|
||||
<!-- <input type="text" name="subject_contains" placeholder="Type here.." value="{{$rule->subject_contains ?? ''}}">-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>E.g. Great deals!</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Text Contains</label>-->
|
||||
<!-- <input type="text" name="text_contains" placeholder="Type here.." value="{{$rule->text_contains ?? ''}}">-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>E.g. Great deals!</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group">-->
|
||||
<!-- <label class="dev-checkbox-wrapper">All e-mails automatically marked as spam-->
|
||||
<!-- <input name="all_emails_automatically_mark_as_spam" type="checkbox" @if($rule && !is_null($rule->all_emails_automatically_mark_as_spam)) checked @endif>-->
|
||||
<!-- <span class="checkmark"></span>-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
<!-- <h3>Exceptions</h3>-->
|
||||
<!-- <p>Email that matches the filter above but for which the rule should not be activated.-->
|
||||
<!-- </p>-->
|
||||
<!-- <div class="dev-form-inner">-->
|
||||
<!-- <div class="col-left">-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Subject Contains</label>-->
|
||||
<!-- <textarea rows="6" name="subject1_contains">{{$rule->subject1_contains ?? ''}}</textarea>-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>Order Confirmation</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--<div class="col-right">-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Text Contains</label>-->
|
||||
<!-- <textarea rows="6">Type here..</textarea>-->
|
||||
<!-- <div class="dev-input-info">-->
|
||||
<!-- <img src="{{ asset('images/info.svg') }}" alt="info">-->
|
||||
<!-- <span>Your Order</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <h3>Effect</h3>-->
|
||||
<!-- <p>The effect describes what should happen when the filter above matches. It happens-->
|
||||
<!-- automatically, before the e-mail shows up in-->
|
||||
<!-- the dashboard.</p>-->
|
||||
<!-- <div class="dev-content-schedule">-->
|
||||
<!-- <label>Assign To</label>-->
|
||||
<!-- <div class="schedule-box">-->
|
||||
<!-- <select name="assign_to">-->
|
||||
<!-- @foreach($company_users as $company_user)-->
|
||||
<!-- <option value="{{$company_user->user->id}}" @if($rule && !is_null($rule->assign_to) && $rule->assign_to == $company_user->user->id) selected @endif>{{$company_user->user->name}}</option>-->
|
||||
<!-- @endforeach-->
|
||||
<!-- </select>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-form-inner">-->
|
||||
<!-- <div class="col-left">-->
|
||||
<!-- <div class="dev-input-group dev-input-group-input-info">-->
|
||||
<!-- <label>Message to assigned editor</label>-->
|
||||
<!-- <textarea rows="6" name="message_to_assigned_editor">{{$rule->message_to_assigned_editor ?? ''}}</textarea>-->
|
||||
<!-- </div>-->
|
||||
<!--<div class="dev-input-group">-->
|
||||
<!-- <label class="dev-checkbox-wrapper">Remove and hide from the statistics -->
|
||||
<!-- <input type="checkbox">-->
|
||||
<!-- <span class="checkmark"></span>-->
|
||||
<!-- </label>-->
|
||||
<!--</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="col-right">-->
|
||||
<!-- <div class="dev-content-schedule">-->
|
||||
<!-- <label>Add tags</label>-->
|
||||
<!-- <div class="schedule-box">-->
|
||||
<!-- <select name="tag_id">-->
|
||||
<!-- @foreach($tags as $tag)-->
|
||||
<!-- <option value="{{$tag->id}}" @if($rule && !is_null($rule->tag_id) && $rule->tag_id == $tag->id) selected @endif>{{$tag->name}}</option>-->
|
||||
<!-- @endforeach-->
|
||||
<!-- </select>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="checkbox-box">-->
|
||||
<!-- <div class="dev-input-group">-->
|
||||
<!-- <input type="radio" value="set as done" name="status" @if($rule && !is_null($rule->status) && $rule->status == 'set as done') checked @endif>-->
|
||||
<!-- <label class="dev-checkbox-wrapper">Set as done</label>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group">-->
|
||||
<!-- <label class="dev-checkbox-wrapper">Set highest priority</label>-->
|
||||
<!-- <input type="radio" value="Set highest priority" name="priority" @if($rule && !is_null($rule->priority) && $rule->priority == 'Set highest priority') checked @endif>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group">-->
|
||||
<!-- <label class="dev-checkbox-wrapper">Mark as spam</label>-->
|
||||
<!-- <input type="radio" value="mask as spam" name="status" @if($rule && !is_null($rule->status) && $rule->status == 'mask as spam') checked @endif>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="dev-input-group">-->
|
||||
<!-- <label class="dev-checkbox-wrapper">Set lowest priority</label>-->
|
||||
<!-- <input type="radio" value="Set lowest priority" name="priority" @if($rule && !is_null($rule->priority) && $rule->priority == 'Set lowest priority') checked @endif>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button type="button" class="dev-form-submit-btn">Save</button>
|
||||
</div>
|
||||
<!-- <button type="submit" class="dev-form-submit-btn">Save</button>-->
|
||||
<!-- </form>-->
|
||||
<!-- </div>-->
|
||||
|
||||
</div>
|
||||
<!--</div>-->
|
||||
<!-- -->
|
||||
<div class="dev-tabcontent dev-tabcontent-canned">
|
||||
<div class="dev-tabcontent-outers">
|
||||
|
|
@ -865,24 +871,57 @@ class="form-control input-reply-textarea">{!! $automatic_reply_text->value ?? ''
|
|||
<h2>Email addresses that never should be marked as spam<br>
|
||||
Blocked email addresses</h2>
|
||||
<div class="dev-users-boxs">
|
||||
@if(!is_null($spam_handling))
|
||||
@foreach(json_decode($spam_handling->value) as $index => $values)
|
||||
<div class="dev-users-box">
|
||||
<div class="dev-box">
|
||||
<h3>{{ $values->spam_email }}</h3>
|
||||
<span>{{ $values->marking_radio }}</span>
|
||||
</div>
|
||||
<!--<div class="dev-icon">-->
|
||||
<!-- <img src="{{ asset('images/settingss.svg') }}" alt="">-->
|
||||
<!--</div>-->
|
||||
<div class="dev-icon">
|
||||
<img src="{{ asset('images/settingss.svg') }}" alt="">
|
||||
</div>
|
||||
<div class="dev-icon">
|
||||
<a href="{{ route('delete.spam.handling', $index) }}" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
|
||||
<a href="{{ route('delete.spam.handling', $index) }}" style="cursor:pointer;" class="delete-user"><img src="{{ asset('images/binn.svg') }}" alt=""></a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script defer>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const deleteLinks = document.querySelectorAll('.delete-user');
|
||||
|
||||
deleteLinks.forEach(function (link) {
|
||||
link.addEventListener('click', function (event) {
|
||||
event.preventDefault(); // Prevent the default link click behavior
|
||||
|
||||
const url = this.href;
|
||||
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "You won't be able to revert this!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete it!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// If the user confirms, redirect to the delete URL
|
||||
window.location.href = url;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- -->
|
||||
<div class="dev-tabcontent dev-tabcontent-tags">
|
||||
<div class="dev-tabcontent-outers">
|
||||
|
|
|
|||
|
|
@ -74,9 +74,112 @@ class="form-control input-reply-textarea" id="editor1" required></textarea>
|
|||
</div>
|
||||
</div>
|
||||
<!--wysywyg editor-->
|
||||
<script src="https://cdn.ckeditor.com/4.16.0/standard/ckeditor.js"></script>
|
||||
<!--<script src="https://cdn.ckeditor.com/4.24.0/standard/ckeditor.js"></script>-->
|
||||
|
||||
|
||||
<!-- Canned Response Modal -->
|
||||
<!-- Canned Response Modal -->
|
||||
<div id="cannedResponseModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-button">×</span>
|
||||
<h2>Canned Responses</h2>
|
||||
<ul>
|
||||
|
||||
@if(count($canned_response) > 0)
|
||||
@foreach($canned_response as $index => $value)
|
||||
|
||||
@php
|
||||
|
||||
$result = json_decode($value->value);
|
||||
|
||||
@endphp
|
||||
|
||||
<li><button class="canned-response" data-response="{{$result->text}}">{{$result->name}}</button></li>
|
||||
@endforeach
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
CKEDITOR.replace('editor1');
|
||||
//CKEDITOR.replace('editor1');
|
||||
|
||||
CKEDITOR.plugins.add('addcannedresponse', {
|
||||
init: function(editor) {
|
||||
editor.addCommand('addCannedResponseCmd', {
|
||||
exec: function(editor) {
|
||||
document.getElementById('cannedResponseModal').style.display = 'block';
|
||||
}
|
||||
});
|
||||
editor.ui.addButton('AddCannedResponse', {
|
||||
label: 'Insert Canned Response',
|
||||
command: 'addCannedResponseCmd',
|
||||
icon: 'https://kundesone.no/images/canned.png', // Use an accessible icon URL or local path
|
||||
toolbar: 'insert,0'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
CKEDITOR.replace('editor1', {
|
||||
extraPlugins: 'addcannedresponse', // Ensure your plugin is added to extraPlugins
|
||||
// Optionally customize your toolbar further, or use the default configuration
|
||||
toolbarGroups: [
|
||||
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
|
||||
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'forms' },
|
||||
{ name: 'tools' },
|
||||
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
|
||||
{ name: 'others' },
|
||||
'/',
|
||||
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
|
||||
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
|
||||
{ name: 'styles' },
|
||||
{ name: 'colors' },
|
||||
{ name: 'about' }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
// Get the modal
|
||||
var modal = document.getElementById("cannedResponseModal");
|
||||
|
||||
// Get the button that opens the modal
|
||||
var btn = document.getElementsByClassName("canned-response");
|
||||
|
||||
// Get the <span> element that closes the modal
|
||||
var span = document.getElementsByClassName("close-button")[0];
|
||||
|
||||
// When the user clicks on <span> (x), close the modal
|
||||
span.onclick = function() {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
|
||||
// When the user clicks anywhere outside of the modal, close it
|
||||
window.onclick = function(event) {
|
||||
if (event.target == modal) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners to canned response buttons
|
||||
Array.from(btn).forEach(function(element) {
|
||||
element.addEventListener('click', function() {
|
||||
var response = this.getAttribute('data-response');
|
||||
CKEDITOR.instances.editor1.insertHtml(response);
|
||||
modal.style.display = "none";
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Action Box -->
|
||||
|
|
@ -86,9 +189,105 @@ class="form-control input-reply-textarea" id="editor1" required></textarea>
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tagify CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet">
|
||||
|
||||
<!-- Tagify JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
#cke_editor1{
|
||||
width:100%!important;
|
||||
}
|
||||
|
||||
div.chat-inbox.chat-box{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
background:;#748c62 !important
|
||||
}
|
||||
|
||||
.close-button:hover,
|
||||
.close-button:focus {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
#cannedResponseModal ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#cannedResponseModal li {
|
||||
padding: 8px 0; /* Spacing between buttons */
|
||||
}
|
||||
|
||||
.canned-response {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.canned-response:hover {
|
||||
background-color: #45a049;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.24);
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--Script Tag-->
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var activeTicketId = $('.chat-detail-item.active').data('ticket-id');
|
||||
|
||||
// Load chat messages for the active ticket on page load
|
||||
|
|
@ -137,7 +336,7 @@ function loadActionBox(ticketId) {
|
|||
$('.saveReply').on('click', function(){
|
||||
var message = CKEDITOR.instances.editor1.getData();
|
||||
if(message.trim() === '') {
|
||||
alert('Message cannot be empty');
|
||||
toastr.error('Message cannot be empty');
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
|
|
|
|||
|
|
@ -4,18 +4,475 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.side-bar-links a').removeClass('bg-light-color');
|
||||
$('.aw-a-inbox').addClass('bg-light-color');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Toastr CSS -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet">
|
||||
<!-- Toastr JS -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
||||
<!-- SweetAlert2 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet">
|
||||
<!-- SweetAlert2 JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>
|
||||
|
||||
@php
|
||||
$companyId = getSelectedCompany();
|
||||
$company_users = get_company_users($companyId);
|
||||
@endphp
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Toggle filter dropdown on button click
|
||||
$('.list-filter-btn').click(function() {
|
||||
$('.filter-options').toggle();
|
||||
});
|
||||
|
||||
// Initial hide for handle_multiple__options
|
||||
$('.filter-options').hide();
|
||||
$('.handle_multiple__options').hide();
|
||||
|
||||
// Toggle visibility of handle_multiple__options on button click
|
||||
$('.handle-multiple-btn').click(function() {
|
||||
$('.handle_multiple__options').toggle();
|
||||
});
|
||||
|
||||
// Initially disable all the buttons
|
||||
$('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
|
||||
// Enable/disable buttons based on the select all checkbox
|
||||
// $('#select-all').change(function() {
|
||||
// if ($(this).is(':checked')) {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', false);
|
||||
// } else {
|
||||
// $('.handle_multiple__options .tags button').prop('disabled', true);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Show the modal when "Assign post" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Assign post")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Move" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Move")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal2').show();
|
||||
});
|
||||
|
||||
// Show the modal when "Reply to multiple" button is clicked
|
||||
$('.handle_multiple__options .tags button:contains("Reply to multiple")').click(function(e) {
|
||||
e.preventDefault();
|
||||
$('#customModal3').show();
|
||||
});
|
||||
|
||||
// Close the modal when the close button or outside the modal is clicked
|
||||
$('.modal-close, .modal').click(function() {
|
||||
$('.modal').hide();
|
||||
});
|
||||
|
||||
// Prevent modal content from closing the modal when clicked
|
||||
$('.modal-content').click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Update Select status options based on Select filter selection
|
||||
$('#filter-select').change(function() {
|
||||
var selectedFilter = $(this).val();
|
||||
console.log("Selected filter:", selectedFilter); // Debugging log
|
||||
updateStatusOptions(selectedFilter);
|
||||
});
|
||||
|
||||
// Initially hide filter based data section
|
||||
$('.filter_based__data').hide();
|
||||
|
||||
// Function to update status options based on selectedFilter
|
||||
function updateStatusOptions(selectedFilter) {
|
||||
console.log("Updating status options for:", selectedFilter); // Debugging log
|
||||
switch (selectedFilter) {
|
||||
case 'Assigned to':
|
||||
// $('#status-select').html(`
|
||||
// <option disabled value="">Select assigned to</option>
|
||||
// <option value="Assigned">Assigned</option>
|
||||
// <option value="Unassigned">Unassigned</option>
|
||||
// <option value="Margin">Margin</option>
|
||||
// `);
|
||||
var options = '<option value="">Select assigned to</option>';
|
||||
// Loop through the company_users array
|
||||
@foreach($company_users as $company_user)
|
||||
options += '<option value="{{ $company_user->user->id }}">{{ $company_user->user->name }}</option>';
|
||||
@endforeach
|
||||
|
||||
$('#status-select').html(options);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'With activity':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select No activity</option>
|
||||
<option value="last 24 hours">Last 24 hours</option>
|
||||
<option value="last 3 days">Last 3 days</option>
|
||||
<option value="last week">Last week</option>
|
||||
<option value="last month">Last month</option>
|
||||
<option value="last 3 months">Last 3 months</option>
|
||||
<option value="last 6 months">Last 6 months</option>
|
||||
<option value="last year">Last year</option>
|
||||
<option value="the past 2 years">The past 2 years</option>
|
||||
<option value="the past 3 years">The past 3 years</option>
|
||||
<option value="the past 4 years">The past 4 years</option>
|
||||
<option value="the past 5 years">The past 5 years</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'No activity':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select No activity</option>
|
||||
<option value="last 24 hours">Last 24 hours</option>
|
||||
<option value="last 3 days">Last 3 days</option>
|
||||
<option value="last week">Last week</option>
|
||||
<option value="last month">Last month</option>
|
||||
<option value="last 3 months">Last 3 months</option>
|
||||
<option value="last 6 months">Last 6 months</option>
|
||||
<option value="last year">Last year</option>
|
||||
<option value="the past 2 years">The past 2 years</option>
|
||||
<option value="the past 3 years">The past 3 years</option>
|
||||
<option value="the past 4 years">The past 4 years</option>
|
||||
<option value="the past 5 years">The past 5 years</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Editor':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select Editor</option>
|
||||
<option value="Computer tool">Computer tool</option>
|
||||
<option value="Direct editor">Direct editor</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Spam':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select Spam</option>
|
||||
<option value="marked as spam">Marked as spam</option>
|
||||
<option value="marked as not spam">Marked as not spam</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Status':
|
||||
$('#status-select').html(`
|
||||
<option value="">Select status</option>
|
||||
<option value="open">Open</option>
|
||||
<option value="waiting">Waiting</option>
|
||||
<option value="done">Done</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Tags':
|
||||
|
||||
var options = '<option value="">Select Tags</option>';
|
||||
@foreach($tags as $tag)
|
||||
options += '<option value="{{$tag->name}}">{{$tag->name}}</option>';
|
||||
@endforeach
|
||||
|
||||
$('#status-select').html(options);
|
||||
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
case 'Users':
|
||||
|
||||
var options = '<option value="">Select Users</option>';
|
||||
// Loop through the company_users array
|
||||
@foreach($company_users as $company_user)
|
||||
options += '<option value="{{ $company_user->user->id }}">{{ $company_user->user->name }}</option>';
|
||||
@endforeach
|
||||
|
||||
$('#status-select').html(options);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
default:
|
||||
$('#status-select').html(`
|
||||
<option disabled value="">Select status</option>
|
||||
`);
|
||||
$('.filter_based__data').show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<!--chat avialability ajax-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// $('#toggleSwitch').on('change', function() {
|
||||
// const isChecked = $(this).is(':checked');
|
||||
|
||||
// if (isChecked) {
|
||||
// // Call route when toggle is ON
|
||||
// $.ajax({
|
||||
// url: 'update/chat-availability',
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
// },
|
||||
// data: {
|
||||
// status: 'on'
|
||||
// },
|
||||
// success: function(response) {
|
||||
// console.log('Success:', response);
|
||||
// if(response.success) {
|
||||
// toastr.success('Chat Availability Updated Successfully');
|
||||
// }
|
||||
// },
|
||||
// error: function(xhr, status, error) {
|
||||
// console.error('Error:', error);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// // Call route when toggle is OFF
|
||||
// $.ajax({
|
||||
// url: 'update/chat-availability',
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
// },
|
||||
// data: {
|
||||
// status: 'off'
|
||||
// },
|
||||
// success: function(response) {
|
||||
// console.log('Success:', response);
|
||||
// if(response.success) {
|
||||
// toastr.success('Chat Availability Updated Successfully');
|
||||
// }
|
||||
// },
|
||||
// error: function(xhr, status, error) {
|
||||
// console.error('Error:', error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.handle_multiple__options {
|
||||
display: none;
|
||||
background-color: #f8f9fa;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button {
|
||||
background-color: #748C62;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button:hover {
|
||||
background-color: #383F33;
|
||||
}
|
||||
.handle_multiple__options .tags button:disabled {
|
||||
background-color: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.handle_multiple__options input{
|
||||
width: 32px;
|
||||
height: 19px;
|
||||
}
|
||||
.handle_multiple__options .common_shre{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* Custom Modal CSS */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 13%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
#customModal3 .modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 40%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.modal-content .btn-primary{
|
||||
background-color: #748C62 !important;
|
||||
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.modal-close:focus {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter select {
|
||||
margin-right: 10px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
/* Hide checkboxes initially */
|
||||
.checkbox-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show checkboxes when 'Handle Multiple' is active */
|
||||
.handle-multiple-active .checkbox-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Show checkboxes when 'Handle Multiple' is active */
|
||||
.handle-multiple-active .checkbox-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
padding: 12px 11px !important;
|
||||
}
|
||||
|
||||
.chat-user-img{
|
||||
margin-left:12px !important;
|
||||
}
|
||||
|
||||
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* When checkbox is checked, set background to green */
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: #748C62;
|
||||
border-color: #748C62;
|
||||
}
|
||||
|
||||
/* Optional: Add checkmark icon or any visual effect */
|
||||
input[type="checkbox"]:checked::before {
|
||||
transform: translate(0px, -1px);
|
||||
content: '✔';
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
/* margin-top: 12px; */
|
||||
transform: translate(2px, 6px);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="ui card chat-card">
|
||||
<div class="content chat-card-header d-flex align-items-center justify-content-between">
|
||||
<div class="header">Chats</div>
|
||||
<div class="data-actions d-flex justify-content-end">
|
||||
<div class="date-filter d-flex align-items-center">
|
||||
<img src="{{ asset('images/icons/calendar.png') }}" alt="Calendar">
|
||||
<!--<div class="date-filter d-flex align-items-center">-->
|
||||
<!-- <img src="{{ asset('images/icons/calendar.png') }}" alt="Calendar">-->
|
||||
|
||||
<select class="date-filter-selectbox" name="">
|
||||
<option value="">Last 7 Days</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- <select class="date-filter-selectbox" name="">-->
|
||||
<!-- <option value="">Last 7 Days</option>-->
|
||||
<!-- </select>-->
|
||||
<!--</div>-->
|
||||
<button class="action-button d-flex align-items-center list-filter-btn">
|
||||
<img src="{{ asset('images/icons/list-filter.png') }}" alt="">
|
||||
</button>
|
||||
|
|
@ -27,12 +484,53 @@
|
|||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="filter-options">
|
||||
<div class="filter">
|
||||
<span> <b>Filter on:</b> </span>
|
||||
<select id="filter-select" name="">
|
||||
<option value="select_filter_default">Select filter</option>
|
||||
<option value="Assigned to">Assigned to</option>
|
||||
<option value="With activity">With activity</option>
|
||||
<option value="No activity">No activity</option>
|
||||
<!--<option value="Editor">Editor</option>-->
|
||||
<option value="Spam">Spam</option>
|
||||
<option value="Status">Status</option>
|
||||
<option value="Tags">Tags</option>
|
||||
<!--<option value="Users">Users</option>-->
|
||||
</select>
|
||||
<div class="filter_based__data">
|
||||
<select id="status-select" name="">
|
||||
<option disabled>Select status</option>
|
||||
<!-- Options will be dynamically updated based on selected filter -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="handle_multiple__options">
|
||||
<div class="common_shre">
|
||||
<label for="select-all"> <input type="checkbox" name="" id="select-all"> Select all</label>
|
||||
<div class="tags">
|
||||
<button>Assign post</button>
|
||||
<button id="delete-posts">Delete</button>
|
||||
<!--<button>Move</button>-->
|
||||
<button data-status="open" class="update-posts-status">Open</button>
|
||||
<button data-status="waiting" class="update-posts-status">Waiting</button>
|
||||
<button data-status="done" class="update-posts-status">Done</button>
|
||||
<!--<button>Tag</button>-->
|
||||
<!--<button>Not spam</button>-->
|
||||
<button>Reply to multiple</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content chat-content">
|
||||
<ul class="chat-details">
|
||||
@foreach($tickets as $ticket)
|
||||
<li>
|
||||
<a href="{{ route('inbox') }}" class="chat-detail-item d-flex align-items-center">
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-{{$ticket->id}}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
</div>
|
||||
|
|
@ -48,8 +546,8 @@
|
|||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">{{$ticket->subject}}</p>
|
||||
<p class="receiver-message"> - {{$ticket->content}}.</p>
|
||||
<p class="color-dark-green receiver-name">{{$ticket->sender_name}}</p>
|
||||
<p class="receiver-message"> - {{\Illuminate\Support\Str::limit($ticket->subject, 90)}}.</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">{{ \Carbon\Carbon::parse($ticket->created_at)->format('h:i A')}}</p>
|
||||
</div>
|
||||
|
|
@ -63,4 +561,136 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!--Filter Status Code-->
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
const filterSelect = $('#filter-select');
|
||||
const statusSelect = $('#status-select');
|
||||
const statusOptions = $('#status-options');
|
||||
const chatDetails = $('.chat-details');
|
||||
|
||||
// Handle status change
|
||||
$('#status-select').change(function() {
|
||||
fetchTickets();
|
||||
});
|
||||
|
||||
// Fetch tickets based on filter
|
||||
function fetchTickets() {
|
||||
const filter = filterSelect.val();
|
||||
const status = $('#status-select').val();
|
||||
|
||||
$.ajax({
|
||||
url: '/filter',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
filter: filter,
|
||||
status: status,
|
||||
type: 'inbox',
|
||||
},
|
||||
success: function(data) {
|
||||
chatDetails.empty();
|
||||
$.each(data.tickets, function(index, ticket) {
|
||||
chatDetails.append(`
|
||||
<li>
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-${ticket.id}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="/images/Avatar.png" alt="User">
|
||||
</div>
|
||||
<div class="chat-message-info d-flex align-self-baseline">
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-light-green">#${ticket.id}</p>
|
||||
<div class="ui tiny label bg-dark-green-color color-light">
|
||||
${ticket.status}
|
||||
</div>
|
||||
</div>
|
||||
<p class="color-dark-green">${new Date(ticket.created_at).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">${ticket.sender_name}</p>
|
||||
<p class="receiver-message"> - ${ticket.subject}</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">${new Date(ticket.created_at).toLocaleTimeString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
const chatDetails = $('.chat-details');
|
||||
const filterSelect = $('#filter-select');
|
||||
filterSelect.change(function() {
|
||||
const selectedFilter = $(this).val();
|
||||
|
||||
if (selectedFilter === 'select_filter_default') {
|
||||
$.ajax({
|
||||
url: 'default/all-tickets',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': "{{ csrf_token() }}"
|
||||
},
|
||||
data: {
|
||||
type: 'inbox'
|
||||
},
|
||||
success: function(data) {
|
||||
chatDetails.empty();
|
||||
$.each(data.tickets, function(index, ticket) {
|
||||
chatDetails.append(`
|
||||
<li>
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-${ticket.id}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="/images/Avatar.png" alt="User">
|
||||
</div>
|
||||
<div class="chat-message-info d-flex align-self-baseline">
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-light-green">#${ticket.id}</p>
|
||||
<div class="ui tiny label bg-dark-green-color color-light">
|
||||
${ticket.status}
|
||||
</div>
|
||||
</div>
|
||||
<p class="color-dark-green">${new Date(ticket.created_at).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">${ticket.sender_name}</p>
|
||||
<p class="receiver-message"> - ${ticket.subject}</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">${new Date(ticket.created_at).toLocaleTimeString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<x-custom-modals />
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="icon" href="./assets/images/favicon.ico" type="image/png">
|
||||
<link rel="icon" href="{{asset('images/favicon.ico')}}" type="image/png">
|
||||
|
||||
<!-- Google fonts -->
|
||||
|
||||
|
|
@ -30,4 +30,29 @@
|
|||
crossorigin="anonymous"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function updateLastOnline() {
|
||||
$.ajax({
|
||||
url: '/update-last-online',
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
console.log('Last online updated successfully.');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error('An error occurred:', xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update last online every minute (60000 milliseconds)
|
||||
setInterval(updateLastOnline, 60000);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,17 +4,20 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- CSRF Token Meta Tag -->
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Inbox</title>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>
|
||||
<!--<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>-->
|
||||
<!-- Bootstrap Styles -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<!-- Main Styles -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/style.css') }}">
|
||||
|
||||
<link rel="icon" href="{{asset('images/favicon.ico')}}" type="image/png">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" />
|
||||
</head>
|
||||
</head>
|
||||
|
||||
|
|
@ -38,231 +41,53 @@
|
|||
@yield('content')
|
||||
<!-- End -->
|
||||
|
||||
<!-- Support and Chat Fixed Buttons -->
|
||||
<div class="chat-message-box position-fixed">
|
||||
|
||||
|
||||
<!-- Chat Drop Down -->
|
||||
<div class="ui floating bg-dark-green-color chat-widget-wrapper icon dropdown button">
|
||||
<img src="{{ asset('images/icons/Vector 386.png') }}" alt="Chat Icon">
|
||||
|
||||
<div class="menu chat-menu">
|
||||
<div id="chat-feature-widget" class="ui transition chat-feature-widget">
|
||||
<div class="header d-flex justify-content-between align-items-center text-white">
|
||||
<p class="chat-popup-label text-light">Chats</p>
|
||||
<img class="remove-chat" src="{{ asset('images/icons/Vector (3).svg') }}" alt="Cross Chat Icon">
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- User Inbox menu -->
|
||||
<div id="inbox" class="ui transition hidden chat-feature-widget inbox-wrapper">
|
||||
<div class="header d-flex align-items-center">
|
||||
<img id="back-to-users" src="{{ asset('images/icons/Vector 387.png') }}" alt="Back To Chat">
|
||||
<p class="chat-popup-label text-light">James</p>
|
||||
</div>
|
||||
<div class="scrollhint">
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>👋 Hi there! How can I help?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lorem
|
||||
est,
|
||||
tincidunt at placerat ultricies, vehicula in erat. Donec vitae ante
|
||||
mollis, pretium augue vel, feugiat risus.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>Typing...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="outer-message-input-box">
|
||||
<div class="inner-message-input d-flex align-items-center justify-content-between ">
|
||||
<input type="text" class="border-0" placeholder="Type a reply">
|
||||
<p class="input-action d-flex align-items-center ">
|
||||
<img src="{{ asset('images/icons/gif.png') }}" alt="Gif">
|
||||
<img src="{{ asset('images/icons/emoji.png') }}" alt="Gif">
|
||||
<img src="{{ asset('images/icons/attachment.png') }}" alt="Gif">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
|
||||
|
||||
<!-- Support Drop down -->
|
||||
<div class="ui floating bg-dark-green-color support-widget-wrapper icon dropdown button ">
|
||||
<img src="images/icons/support.svg" alt="Support Icon">
|
||||
<div class="menu support-widget">
|
||||
<div class="header support-header mt-0 text-center">
|
||||
<h2 class="color-dark-green">Help & Support</h2>
|
||||
</div>
|
||||
<div class="support-facilities-box d-flex justify-content-between flex-wrap">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/faq-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">FAQ</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/laptop-minimalistic-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">Using Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/launch-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Launching Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/setting-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Settings</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/data-mapping-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Integration</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/open-door-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Privacy & Policy</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/news-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">News & Updates</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/graduate-cap-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Training</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header contact-us-header text-center">
|
||||
<h2 class="color-dark-green">Contact Us</h2>
|
||||
</div>
|
||||
|
||||
<div class="contact-us-box d-flex justify-content-center">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/email-14-svgrepo-com (1) 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Questions</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/about-filled-svgrepo-com 1.svg" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">About Kundo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
</div>
|
||||
<!-- End -->
|
||||
<x-chat-box />
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Jquery -->
|
||||
<!-- <script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
||||
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> -->
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
||||
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Bootstrap scripts -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
|
||||
crossorigin="anonymous"></script> -->
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Fomantic Ui Scripts -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script> -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.3/dist/semantic.min.js"></script>
|
||||
|
||||
<!-- Main Custom Js -->
|
||||
<script src="{{ asset('assets/script.js') }}"></script>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function updateLastOnline() {
|
||||
$.ajax({
|
||||
url: '/update-last-online',
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
console.log('Last online updated successfully.');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error('An error occurred:', xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update last online every minute (60000 milliseconds)
|
||||
setInterval(updateLastOnline, 60000);
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- CSRF Token Meta Tag -->
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Inbox</title>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
||||
|
|
@ -21,7 +23,16 @@
|
|||
|
||||
<!-- Main Styles -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/style.css') }}">
|
||||
<link rel="icon" href="{{asset('images/favicon.ico')}}" type="image/png">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" />
|
||||
|
||||
<style>
|
||||
.logo_be .img{
|
||||
transform: translate(7px, -5px) !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
</head>
|
||||
|
||||
|
|
@ -32,9 +43,9 @@
|
|||
|
||||
<!-- Sidebar -->
|
||||
<div class=" sidebar-area short-sidebar">
|
||||
<aside class="bg-dark-green-color align-items-center">
|
||||
<div class="image-box d-flex justify-content-between">
|
||||
<img src="{{ asset('images/logo-white.png') }}" alt="Site Logo">
|
||||
<aside class="bg-dark-green-color align-items-center ">
|
||||
<div class="image-box d-flex justify-content-between logo_be">
|
||||
<img src="{{ asset('images/logo_cropped.png') }}" class="img" alt="Site Logo">
|
||||
<div class="dev-toggle-sidebar dev-close"><img src="{{ asset('images/icons/close-icon.svg') }}" alt=""></div>
|
||||
</div>
|
||||
<div class="side-bar-links d-flex justify-content-center">
|
||||
|
|
@ -84,7 +95,11 @@ class="side-bar-link bg-light-color d-flex align-items-center justify-content-be
|
|||
<div class="profile-nav-row d-flex side-bar-link">
|
||||
|
||||
<div class="profile-nav-box">
|
||||
<div class="img-box"><img src="{{ asset('images/user.png') }}" alt="User Image"></div>
|
||||
@if(!is_null(Auth::user()->profile_image))
|
||||
<div class="img-box"><a href="{{route('profile')}}"><img style="height: 42px; width: 42px; border-radius: 50%" src="{{ url('' . Auth::user()->profile_image) }}" alt="User Image"></a></div>
|
||||
@else
|
||||
<div class="img-box"><img style="height: 42px; width: 42px; border-radius: 50%" src="{{ asset('dummy-image.jpg') }}" alt="User Image"></div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -97,304 +112,15 @@ class="side-bar-link bg-light-color d-flex align-items-center justify-content-be
|
|||
<div class="content-area position-relative bg-light-color">
|
||||
|
||||
<!-- Header -->
|
||||
<header class="position-relative">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 user-name-nav-area d-flex align-content-center">
|
||||
<div class="dev-toggle-sidebar">
|
||||
<img src="{{ asset('images/icons/blocks-icon.svg') }}">
|
||||
</div>
|
||||
<h2 class="d-flex align-items-center">Hello Maxwell <span>👋🏼</span>,</h2>
|
||||
</div>
|
||||
<div class="col-sm-8 d-flex justify-content-end align-items-center">
|
||||
<div class="search-box d-flex align-items-center">
|
||||
<img src="{{ asset('images/icons/search 1.png') }}" alt="">
|
||||
<input type="text" class="color-dark-green" placeholder="Search...">
|
||||
</div>
|
||||
<div class="nav-links d-flex align-items-center">
|
||||
<form method="POST" action="{{route('logout')}}">
|
||||
@csrf
|
||||
<button class="nav-btn bg-dark-green-color">
|
||||
<img height="25" width="50" src="{{ asset('images/logout.png') }}" alt="">
|
||||
</button>
|
||||
</form>
|
||||
<a href="{{ route('chat.setting') }}" class="nav-btn bg-dark-green-color">
|
||||
<img src="{{ asset('images/icons/Message_alt_fill.png') }}" alt="">
|
||||
</a>
|
||||
<a href="{{ route('inbox.setting') }}" class="nav-btn bell-btn bg-dark-green-color">
|
||||
<img src="{{ asset('images/icons/notification.svg') }}" alt="">
|
||||
</a>
|
||||
<div class="ui dropdown custom-dropdown options-widget-wrapper">
|
||||
<div class="text">
|
||||
<button class="nav-btn bg-dark-green-color">
|
||||
<img src="{{ asset('images/icons/Group 32.png') }}" alt="">
|
||||
</button>
|
||||
</div>
|
||||
<div class="menu nav-bar-menu mt-2">
|
||||
<div class="item">
|
||||
<p class="action-heading-paragraph text-center align-content-center">
|
||||
<img src="{{ asset('images/icons/Vector (3).png') }}" alt="">
|
||||
<span class="action-label text-white">Inbox</span>
|
||||
</p>
|
||||
<div class="chat-settings-btn-row text-center">
|
||||
<a class="ui secondary basic button tag-btn shadow-none">Tags</a>
|
||||
<a
|
||||
href="{{ route('inbox.setting') }}" class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<p class="action-heading-paragraph text-center align-content-center">
|
||||
<img src="{{ asset('images/icons/chat-round-white.svg') }}" alt="">
|
||||
<span class="action-label text-white">Chats</span>
|
||||
</p>
|
||||
<div class="chat-settings-btn-row text-center">
|
||||
<a class="ui secondary basic button tag-btn shadow-none">Tags</a>
|
||||
<a
|
||||
href="{{ route('chat.setting') }}" class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<p class="action-heading-paragraph text-center align-content-center">
|
||||
<img src="{{ asset('images/icons/Group 133630.svg') }}" alt="">
|
||||
<span class="action-label text-white">Help Center</span>
|
||||
</p>
|
||||
<div class="chat-settings-btn-row text-center">
|
||||
<i class="external link square alternate icon color-dark-green"></i>
|
||||
<a class="ui secondary basic button tag-btn shadow-none">Tags</a>
|
||||
<a
|
||||
class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<p class="action-heading-paragraph text-center align-content-center">
|
||||
<img src="{{ asset('images/icons/question-square-svgrepo-com 2.svg') }}" alt="">
|
||||
<span class="action-label text-white">Forum</span>
|
||||
</p>
|
||||
<div class="chat-settings-btn-row text-center d-flex justify-content-center align-items-center">
|
||||
<i class="external link square alternate icon color-dark-green"></i>
|
||||
<a class="ui secondary basic button tag-btn shadow-none">Tags</a>
|
||||
<a
|
||||
class="ui secondary basic button shadow-none setting-btn text-white align-content-center">Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<!-- End -->
|
||||
<x-header />
|
||||
<!-- End -->
|
||||
|
||||
<!-- Main Content Area -->
|
||||
@yield('content')
|
||||
<!-- End -->
|
||||
|
||||
<!-- Support and Chat Fixed Buttons -->
|
||||
<div class="chat-message-box position-fixed">
|
||||
|
||||
|
||||
<!-- Chat Drop Down -->
|
||||
<div class="chat-widget-wrapper ui floating bg-dark-green-color icon dropdown button">
|
||||
<img src="{{ asset('images/icons/Vector 386.png') }}" alt="Chat Icon">
|
||||
|
||||
<div class="menu chat-menu">
|
||||
<div id="chat-feature-widget" class="ui transition chat-feature-widget">
|
||||
<div class="header d-flex justify-content-between align-items-center text-white">
|
||||
<p class="chat-popup-label text-light">Chats</p>
|
||||
<img class="remove-chat" src="{{ asset('images/icons/Vector (3).svg') }}" alt="Cross Chat Icon">
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item open-inbox">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
</div>
|
||||
<div class="user-message-detail">
|
||||
<p class="recepient-message-detail">James <span>Sep 27</span></p>
|
||||
<p class="text-wrap descriptive-message">Lorem ipsum dolor sit amet,
|
||||
adipiscing
|
||||
elit. In lorem est... </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- User Inbox menu -->
|
||||
<div id="inbox" class="ui transition hidden chat-feature-widget inbox-wrapper">
|
||||
<div class="header d-flex align-items-center">
|
||||
<img id="back-to-users" src="{{ asset('images/icons/Vector 387.png') }}" alt="Back To Chat">
|
||||
<p class="chat-popup-label text-light">James</p>
|
||||
</div>
|
||||
<div class="scrollhint">
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>👋 Hi there! How can I help?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lorem
|
||||
est,
|
||||
tincidunt at placerat ultricies, vehicula in erat. Donec vitae ante
|
||||
mollis, pretium augue vel, feugiat risus.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item d-flex justify-content-end">
|
||||
<div class="sender-message-box text-white">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="single-user-content d-flex">
|
||||
<div class="chat-user-img-box receiver-message-box d-flex">
|
||||
<img class="align-self-end" src="{{ asset('images/Avatar.png') }}" alt="Dummy User">
|
||||
<p>Typing...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="outer-message-input-box">
|
||||
<div class="inner-message-input d-flex align-items-center justify-content-between ">
|
||||
<input type="text" class="border-0" placeholder="Type a reply">
|
||||
<p class="input-action d-flex align-items-center ">
|
||||
<img src="{{ asset('images/icons/gif.png') }}" alt="Gif">
|
||||
<img src="{{ asset('images/icons/emoji.png') }}" alt="Gif">
|
||||
<img src="{{ asset('images/icons/attachment.png') }}" alt="Gif">
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
|
||||
|
||||
<!-- Support Drop down -->
|
||||
<div class="ui floating bg-dark-green-color support-widget-wrapper icon dropdown button ">
|
||||
<img src="{{ asset('images/icons/support.svg') }}" alt="Support Icon">
|
||||
<div class="menu support-widget">
|
||||
<div class="header support-header mt-0 text-center">
|
||||
<h2 class="color-dark-green">Help & Support</h2>
|
||||
</div>
|
||||
<div class="support-facilities-box d-flex justify-content-between flex-wrap">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/faq-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">FAQ</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/laptop-minimalistic-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">Using Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/launch-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Launching Kundo</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/setting-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Settings</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/data-mapping-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Integration</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/open-door-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Privacy & Policy</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/news-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">News & Updates</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="{{ asset('images/icons/graduate-cap-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green ">Training</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="header contact-us-header text-center">
|
||||
<h2 class="color-dark-green">Contact Us</h2>
|
||||
</div>
|
||||
|
||||
<div class="contact-us-box d-flex justify-content-center">
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/email-14-svgrepo-com (1) 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green text-wrap">Technical Questions</p>
|
||||
</div>
|
||||
<div class="item text-center">
|
||||
<div class="support-img-box align-content-center">
|
||||
<img src="images/icons/about-filled-svgrepo-com 1.svg') }}" alt="">
|
||||
</div>
|
||||
<p class="color-dark-green">About Kundo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- End -->
|
||||
|
||||
</div>
|
||||
<x-chat-box />
|
||||
<!-- End -->
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -416,6 +142,27 @@ class="ui secondary basic button shadow-none setting-btn text-white align-conten
|
|||
@endif
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
function updateLastOnline() {
|
||||
$.ajax({
|
||||
url: '/update-last-online',
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
console.log('Last online updated successfully.');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error('An error occurred:', xhr.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update last online every minute (60000 milliseconds)
|
||||
setInterval(updateLastOnline, 60000);
|
||||
});
|
||||
</script>
|
||||
<!-- Main Custom Js -->
|
||||
<script src="{{ asset('assets/script.js') }}"></script>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<div class="box-top-area">
|
||||
<div class="box-heading-row d-flex justify-content-between align-items-center">
|
||||
<p class="heading color-dark-green">Administrate</p>
|
||||
|
|
@ -10,20 +13,187 @@
|
|||
<button class="action-btn status-btn @if($ticket->status == 'done') active @endif" data-status="done">Done</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-body-area">
|
||||
<ul class="inbox-chat-options">
|
||||
<li class="single-option d-flex justify-content-between">
|
||||
<p>Assign <span>(Assign to me)</span></p>
|
||||
<p><img src="{{ asset('images/icons/Frame (1).png') }}" alt="Chevron Right"></p>
|
||||
<p><b>Assign:</b></p>
|
||||
<p class="dev-custom-select">
|
||||
<select class="aw-select" name="user_assigned">
|
||||
<option>(Assign)</option>
|
||||
@foreach($companyUsers as $companyUser)
|
||||
<option value="{{$companyUser->user_id}}" @if($ticket->user_assigned == $companyUser->user_id) selected @endif>{{$companyUser->user->name}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</p>
|
||||
<p class="aw-done bg-light-green-color" id="save-ticket" data-ticket_id="{{$ticket->id}}"><i class="fas fa-check"></i></p>
|
||||
</li>
|
||||
<li class="single-option d-flex justify-content-between">
|
||||
<p>Priority <span>(Choose Priority)</span></p>
|
||||
<p><img src="{{ asset('images/icons/Frame (1).png') }}" alt="Chevron Right"></p>
|
||||
<p><b>Priority:</b></span></p>
|
||||
|
||||
<p class="dev-custom-select">
|
||||
<select class="aw-select" name="priority">
|
||||
<option>(Choose Priority)</option>
|
||||
<option value="low" @if($ticket->priority == 'low') selected @endif>Low</option>
|
||||
<option value="medium" @if($ticket->priority == 'medium') selected @endif>Medium</option>
|
||||
<option value="high" @if($ticket->priority == 'high') selected @endif>High</option>
|
||||
</select>
|
||||
</p>
|
||||
<p class="aw-done bg-light-green-color" id="save-priority" data-ticket_id="{{$ticket->id}}"><i class="fas fa-check"></i></p>
|
||||
<!--<p><img src="{{ asset('images/icons/Frame (1).png') }}" alt="Chevron Right"></p>-->
|
||||
</li>
|
||||
<li class="single-option d-flex justify-content-between">
|
||||
<li class="single-option">
|
||||
<p>Tags <span>(Choose Tags)</span></p>
|
||||
<p><img src="{{ asset('images/icons/+.png') }}" alt="Chevron Right"></p>
|
||||
|
||||
<!--save user assigned-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#save-ticket').on('click', function() {
|
||||
var userAssigned = $('select[name="user_assigned"]').val();
|
||||
var ticketId = $(this).data('ticket_id');
|
||||
|
||||
// Check if a user is selected
|
||||
if (userAssigned === '(Assign)') {
|
||||
toastr.error("Please select a user to assign.");
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX request to save the ticket assignment
|
||||
$.ajax({
|
||||
url: '/update-ticket/' + ticketId,
|
||||
type: 'POST',
|
||||
data: {
|
||||
user_assigned: userAssigned,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
// Handle the response from the server
|
||||
if (response.success) {
|
||||
toastr.success('Ticket Assigned Successfully');
|
||||
} else {
|
||||
alert('Error: ' + response.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// Handle any errors that occurred during the request
|
||||
console.error('AJAX Error:', status, error);
|
||||
toastr.error("An error occurred while assigning the ticket.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!--save priority-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#save-priority').on('click', function() {
|
||||
var priority = $('select[name="priority"]').val();
|
||||
var ticketId = $(this).data('ticket_id');
|
||||
|
||||
// Check if a user is selected
|
||||
if (priority === '(Choose Priority)') {
|
||||
toastr.error("Please select a priority.");
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX request to save the ticket assignment
|
||||
$.ajax({
|
||||
url: '/update-ticket/' + ticketId,
|
||||
type: 'POST',
|
||||
data: {
|
||||
priority: priority,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
// Handle the response from the server
|
||||
if (response.success) {
|
||||
toastr.success('Priority Updated Successfully');
|
||||
} else {
|
||||
toastr.error('Error: ' + response.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// Handle any errors that occurred during the request
|
||||
console.error('AJAX Error:', status, error);
|
||||
toastr.error('An error occurred while updating the priority.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// Assuming you have a DOM element with the ID 'tags'
|
||||
var input = document.getElementById('tags');
|
||||
new Tagify(input);
|
||||
</script>
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
$tags = [];
|
||||
$db_tags = getTicketMeta($ticket->id,'tags',false);
|
||||
|
||||
// if($db_tags){
|
||||
|
||||
// foreach($db_tags as $tag){
|
||||
// $tags[] = $tag->value;
|
||||
// }
|
||||
|
||||
// }
|
||||
?>
|
||||
|
||||
<input type="text" name="tags" id="tags" value="{{implode(',',$tags)}}" placeholder="Type and press Enter"
|
||||
class="form-control input-reply-textarea input-comment-textarea" required/>
|
||||
|
||||
|
||||
<button data-ticket_id="{{$ticket->id}}" class="ui button bg-light-green-color mt-4 color-light" id="save-tags">
|
||||
Save
|
||||
</button>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#save-tags').on('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var tags = $('#tags').val();
|
||||
var ticketId = $(this).data('ticket_id');
|
||||
|
||||
// Check if the input field is not empty
|
||||
if (tags === '') {
|
||||
toastr.error('Please enter some tags.');
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX request to save the tags
|
||||
$.ajax({
|
||||
url: '/store-tags',
|
||||
type: 'POST',
|
||||
data: {
|
||||
tags: tags,
|
||||
ticket_id:ticketId,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
// Handle the response from the server
|
||||
if (response.success) {
|
||||
toastr.success('Tags Added successfully!');
|
||||
} else {
|
||||
toastr.error('Error: ' + response.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
// Handle any errors that occurred during the request
|
||||
console.error('AJAX Error:', status, error);
|
||||
toastr.error('An error occurred while saving the tags.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
<!--<p><img src="{{ asset('images/icons/+.png') }}" alt="Chevron Right"></p>-->
|
||||
</li>
|
||||
</form>
|
||||
<li class="single-option d-flex justify-content-between">
|
||||
<div class="accordion w-100 border-0" id="accordionExample">
|
||||
<div class="accordion-item custom-accordion">
|
||||
|
|
@ -39,7 +209,7 @@
|
|||
<div class="accordion-body accordion-body--custom">
|
||||
<div class="body-content">
|
||||
<textarea rows="7" placeholder="Your Message"
|
||||
class="form-control input-reply-textarea input-comment-textarea"></textarea>
|
||||
class="form-control input-reply-textarea input-comment-textarea" id="add-comment"></textarea>
|
||||
<button class="ui button bg-light-green-color mt-4 add-comment-btn color-light">
|
||||
Add Your Comment
|
||||
</button>
|
||||
|
|
@ -56,12 +226,12 @@ class="form-control input-reply-textarea input-comment-textarea"></textarea>
|
|||
<p class="response-comment-user-name">{{ $comment->user->name }}</p>
|
||||
</div>
|
||||
<div class="right-area d-flex">
|
||||
<!--<button-->
|
||||
<!-- class="ui button comment--btn bg-dark-green-color color-light comment-edit-btn ">-->
|
||||
<!-- <i class="edit outline icon"></i>-->
|
||||
<!--</button>-->
|
||||
<button
|
||||
class="ui button comment--btn bg-dark-green-color color-light comment-edit-btn ">
|
||||
<i class="edit outline icon"></i>
|
||||
</button>
|
||||
<button
|
||||
class="ui button comment--btn bg-light-green-color color-light comment-delete-btn">
|
||||
class="ui button comment--btn bg-light-green-color color-light comment-delete-btn" data-comment-id="{{ $comment->id }}">
|
||||
<i class="trash alternate outline icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -80,16 +250,85 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
.aw-done{
|
||||
padding:10px;
|
||||
color:white;
|
||||
font-size:20px!important;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.aw-select{
|
||||
color: #8d98aa;
|
||||
font-family: Poppins;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
padding: 13px;
|
||||
background: linear-gradient(0deg, #edf2f6 0%, #edf2f6 100%), #fff;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 6px;
|
||||
width: 100%;
|
||||
resize: unset;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!--delete Comment-->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.comment-delete-btn').on('click', function() {
|
||||
var commentId = $(this).data('comment-id');
|
||||
var commentElement = $(this).closest('.response-comment');
|
||||
|
||||
// SweetAlert confirmation dialog
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "You won't be able to revert this!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete it!'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.ajax({
|
||||
url: '/delete-comment/' + commentId,
|
||||
method: 'GET',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
toastr.success("Comment Deleted Successfully");
|
||||
commentElement.remove();
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error deleting comment:', error);
|
||||
Swal.fire(
|
||||
'Error!',
|
||||
'An error occurred while deleting the comment.',
|
||||
'error'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--store comment-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.add-comment-btn').on('click', function() {
|
||||
var ticketId = $('.chat-detail-item.active').data('ticket-id');
|
||||
var comment = $('.input-comment-textarea').val();
|
||||
var comment = $('#add-comment').val();
|
||||
|
||||
if (comment === '') {
|
||||
alert('Comment cannot be empty');
|
||||
return;
|
||||
toastr.error('Comment cannot be empty');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
|
|
@ -101,9 +340,18 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
|
|||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
$('.accordion-body--custom').prepend(response);
|
||||
toastr.success("Comment Added Successfully");
|
||||
$('.input-comment-textarea').val('');
|
||||
$('#add-comment').val('');
|
||||
$.ajax({
|
||||
url: '/fetch-action-box/' + ticketId,
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
$('.action-box').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error fetching action box content:', error);
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error adding comment:', error);
|
||||
|
|
@ -116,35 +364,27 @@ class="ui button comment--btn bg-light-green-color color-light comment-delete-bt
|
|||
<!--change ticket status-->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Click event for status buttons
|
||||
$('.status-btn').on('click', function() {
|
||||
var newStatus = $(this).data('status');
|
||||
|
||||
// Update UI immediately
|
||||
$('.status-btn').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
// Optionally, update backend via AJAX
|
||||
updateTicketStatus(newStatus);
|
||||
});
|
||||
|
||||
// Function to update ticket status via AJAX
|
||||
function updateTicketStatus(newStatus) {
|
||||
// Example AJAX request
|
||||
$.ajax({
|
||||
url: 'update-ticket-status/{{ $ticket->id }}', // Replace with your route
|
||||
url: '/update-ticket-status/{{ $ticket->id }}',
|
||||
method: 'POST',
|
||||
data: {
|
||||
status: newStatus,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
// Handle success response if needed
|
||||
toastr.success(response.message);
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error updating ticket status:', error);
|
||||
// Optionally handle error response
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,65 @@
|
|||
<style>
|
||||
.attachment {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chat-sender .single-message-chat{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.chat-sender .single-message-chat{
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.chat_style p{
|
||||
text-align:left !important;
|
||||
}
|
||||
.single-message-chat img {
|
||||
width: 83% !important;
|
||||
height: auto !important;
|
||||
max-height:200px;
|
||||
}
|
||||
.left_box img {
|
||||
width: 62% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.left_box p{
|
||||
|
||||
|
||||
|
||||
color: rgba(117, 138, 137, 1);
|
||||
font-family: "Satoshi", sans-serif;
|
||||
font-size: 10px;
|
||||
|
||||
transform: translate(8px, 2px);
|
||||
}
|
||||
#cannedResponseModal ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex !important;
|
||||
gap: 8px !important;
|
||||
flex-wrap: wrap !important;
|
||||
}
|
||||
|
||||
.canned-response {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background-color: #748C62 !important;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
.single-message-chat {
|
||||
width: 100%;
|
||||
height: -webkit-fill-available !important;
|
||||
}
|
||||
</style>
|
||||
@foreach($messages as $message)
|
||||
<!-- Recepient Message -->
|
||||
@if($message->user_id == 0)
|
||||
|
|
@ -6,7 +68,19 @@
|
|||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
</div>
|
||||
<div class="single-message-chat">
|
||||
<p class="user-message">{!!$message->message!!}</p>
|
||||
<div class="user-message">
|
||||
{!!$message->message!!}
|
||||
@if(!is_null($message->attachments) && count(json_decode($message->attachments)) > 0)
|
||||
@foreach(json_decode($message->attachments) as $attachment)
|
||||
<div class="attachment">
|
||||
@php
|
||||
$fileName = basename($attachment);
|
||||
@endphp
|
||||
<a download href="{{ url('' . $attachment) }}">{{$fileName}}</a>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
<p class="message-time">{{ \Carbon\Carbon::parse($message->created_at)->format('h:i A') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -14,16 +88,15 @@
|
|||
@elseif($message->user_id == 1)
|
||||
<div class="chat-message chat-sender d-flex justify-content-end">
|
||||
<div class="single-message-chat">
|
||||
@if(!containsHtml($message->message))
|
||||
<p class="user-message bg-light-green-color color-light">{!!$message->message!!}</p>
|
||||
@else
|
||||
{!! $message->message !!}
|
||||
@endif
|
||||
<p class="message-time">{{ \Carbon\Carbon::parse($message->created_at)->format('h:i A') }}</p>
|
||||
</div>
|
||||
<div class="chat-user-img-box align-self-end">
|
||||
|
||||
<div class="user-message bg-light-green-color color-light chat_style">{!!$message->message!!}</div>
|
||||
<div class="chat-user-img-box align-self-end left_box">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
<p class="message-time">{{ \Carbon\Carbon::parse($message->created_at)->format('h:i A') }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
|
@ -4,6 +4,38 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<!-- Update Profile --->
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="dev-chat-tabs">
|
||||
<div class="dev-tabcontent dev-tabcontent-users">
|
||||
<div class="dev-tabcontent-outers">
|
||||
<div class="dev-title-row">
|
||||
<h2>Update Profile</h2>
|
||||
</div>
|
||||
<form method="POST" action="{{ route('update.profile') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="dev-input-group">
|
||||
<label for="name">Name</label>
|
||||
<input name="name" value="{{$user->name}}" type="text" placeholder="Enter your name" required>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label for="email">Email</label>
|
||||
<input name="email" type="email" readonly value="{{$user->email}}" placeholder="Enter your email" required>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label for="email">Profile Image</label>
|
||||
<input name="profile_image" type="file">
|
||||
</div>
|
||||
<button type="submit">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- End Update Profile -->
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="dev-chat-tabs">
|
||||
<div class="dev-tabcontent dev-tabcontent-users">
|
||||
|
|
@ -11,7 +43,7 @@
|
|||
<div class="dev-title-row">
|
||||
<h2>Add a new user</h2>
|
||||
</div>
|
||||
<form method="POST" action="{{ route('inbox.add.user') }}">
|
||||
<form method="POST" action="{{ route('inbox.add.user') }}" id="accessForm" onsubmit="return validateCheckboxes()">
|
||||
@csrf
|
||||
<div class="dev-input-group">
|
||||
<label for="name">Name</label>
|
||||
|
|
@ -25,6 +57,17 @@
|
|||
<label for="email">Email</label>
|
||||
<input name="email" type="email" placeholder="Enter your email" required>
|
||||
</div>
|
||||
<div class="dev-input-group">
|
||||
<label for="email">Access</label>
|
||||
<label class="dev-checkbox-wrapper">Inbox Module
|
||||
<input name="access[]" type="checkbox" value="inbox">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label class="dev-checkbox-wrapper">Chat Module
|
||||
<input name="access[]" type="checkbox" value="chat">
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit">Send Activation Email</button>
|
||||
</form>
|
||||
<div class="dev-title-row">
|
||||
|
|
@ -50,7 +93,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
|
||||
|
||||
<script defer>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const deleteLinks = document.querySelectorAll('.delete-user');
|
||||
|
|
@ -79,6 +122,23 @@
|
|||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
function validateCheckboxes() {
|
||||
const checkboxes = document.querySelectorAll('input[name="access[]"]');
|
||||
let checked = false;
|
||||
checkboxes.forEach((checkbox) => {
|
||||
if (checkbox.checked) {
|
||||
checked = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!checked) {
|
||||
alert('Please select at least one checkbox.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,468 @@
|
|||
@extends('layouts.setting')
|
||||
|
||||
<title>Inbox</title>
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
div.chat-inbox>.chat-content-wrapper>.chat-message>.single-message-chat>.user-message{
|
||||
max-width:90%!important;
|
||||
width: 70%;
|
||||
|
||||
}
|
||||
.single-message-chat{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.receiver-message{
|
||||
word-break: break-all;
|
||||
}
|
||||
.single-message-chat img{
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
color: #aaa;
|
||||
/* float: right; */
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
background: ;
|
||||
display: flex !important;
|
||||
justify-content: flex-end !important;
|
||||
margin-top: -14px;
|
||||
font-size: 32px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<input type="hidden" value="{{$single_ticket->id}}" id="aw-ticket_id"/>
|
||||
|
||||
<div class="inbox-content-wrapper w-100 ">
|
||||
<div class="inbox-inner-wrapper w-100 d-flex">
|
||||
|
||||
<!-- User Box -->
|
||||
<div class="box user-box">
|
||||
<ul>
|
||||
@foreach($tickets as $key => $ticket)
|
||||
<li style="cursor:pointer;" class="chat-detail-item @if($single_ticket->id == $ticket->id) active @endif inbox-user-box d-flex" data-ticket-id="{{ $ticket->id }}">
|
||||
<div class="chat-user-img inbox position-relative">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
<div class="chat-status-icon rounded-circle text-center align-content-center position-absolute">
|
||||
<img src="{{ asset('images/icons/chat-round.svg') }}" alt="Chat Round">
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-message-info d-flex align-self-baseline">
|
||||
|
||||
<div class="chat-ticket-row align-items-center d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex flex-column">
|
||||
<p class="color-dark-green receiver-name">{{$ticket->sender_name}}</p>
|
||||
<p class="receiver-message">{!! \Illuminate\Support\Str::limit(strip_tags($ticket?->lastResponse?->message) ?? '', 90) !!}</p>
|
||||
</div>
|
||||
<p class=" bold message-time">{{\Carbon\Carbon::parse($ticket?->lastResponse?->created_at)->format('h:i A') ?? ''}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Chat Box -->
|
||||
<div class="chat-inbox chat-box">
|
||||
<div class="chat-content-wrapper">
|
||||
</div>
|
||||
<!-- Send Message Input -->
|
||||
<div class="message-input-box">
|
||||
<!--<div class="select-user-row mt-2">-->
|
||||
<!-- <p>To:</p>-->
|
||||
|
||||
<!-- <select name="skills" multiple="" class="ui fluid dropdown user-select-dropdown">-->
|
||||
<!-- <option value="">Select User</option>-->
|
||||
<!-- <option value="angular">Angular</option>-->
|
||||
<!-- <option value="css">CSS</option>-->
|
||||
<!-- </select>-->
|
||||
<!--</div>-->
|
||||
<div class="input-box-row">
|
||||
<div class="ui card inbox-send-message-card w-100">
|
||||
<!--<div class="content input-options bg-dark-green-color">-->
|
||||
<!-- <div class="input-option-row ">-->
|
||||
<!-- <img src="{{ asset('images/icons/B.png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/I.png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/Vector (5).png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/Vector (6).png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/Vector (8).png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/drive.png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/Vector (5).png') }}" alt="">-->
|
||||
<!-- <img src="{{ asset('images/icons/Vector (6).png') }}" alt="">-->
|
||||
<!-- </div>-->
|
||||
<!--</div>-->
|
||||
|
||||
@if($single_ticket->type != 'chat')
|
||||
|
||||
<div class="content d-flex align-items-end flex-column message-writing-content-area">
|
||||
<textarea rows="7" placeholder="Your Message"
|
||||
class="form-control input-reply-textarea" id="editor1" required></textarea>
|
||||
<button class="ui button bg-light-green-color mt-4 color-light saveReply">
|
||||
Reply
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--wysywyg editor-->
|
||||
<!--<script src="https://cdn.ckeditor.com/4.16.0/standard/ckeditor.js"></script>-->
|
||||
|
||||
|
||||
<!-- Canned Response Modal -->
|
||||
<!-- Canned Response Modal -->
|
||||
<div id="cannedResponseModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-button">×</span>
|
||||
<h2>Canned Responses</h2>
|
||||
<ul>
|
||||
|
||||
@if(count($canned_response) > 0)
|
||||
@foreach($canned_response as $index => $value)
|
||||
|
||||
@php
|
||||
|
||||
$result = json_decode($value->value);
|
||||
|
||||
@endphp
|
||||
|
||||
<li><button class="canned-response" data-response="{{$result->text}}">{{$result->name}}</button></li>
|
||||
@endforeach
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
//CKEDITOR.replace('editor1');
|
||||
|
||||
CKEDITOR.plugins.add('addcannedresponse', {
|
||||
init: function(editor) {
|
||||
// Command for inserting canned response
|
||||
editor.addCommand('addCannedResponseCmd', {
|
||||
exec: function(editor) {
|
||||
// Show your modal or handle canned response insertion
|
||||
document.getElementById('cannedResponseModal').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
// Command for inserting signature
|
||||
editor.addCommand('addSignatureCmd', {
|
||||
exec: function(editor) {
|
||||
var signatureHtml = `<br>{!! $email_signature !!}`; // Signature content
|
||||
CKEDITOR.instances.editor1.insertHtml(signatureHtml);
|
||||
}
|
||||
});
|
||||
|
||||
// Add "Insert Canned Response" button
|
||||
editor.ui.addButton('AddCannedResponse', {
|
||||
label: 'Insert Canned Response',
|
||||
command: 'addCannedResponseCmd',
|
||||
icon: 'https://kundesone.no/images/canned.png', // Use an accessible icon URL or local path
|
||||
toolbar: 'insert,0'
|
||||
});
|
||||
|
||||
// Add "Insert Signature" button
|
||||
editor.ui.addButton('AddSignature', {
|
||||
label: 'Insert Signature',
|
||||
command: 'addSignatureCmd',
|
||||
icon: 'https://kundesone.no/images/signature-icon.png', // Placeholder icon URL, replace with a valid one
|
||||
toolbar: 'insert,1'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
CKEDITOR.replace('editor1', {
|
||||
extraPlugins: 'addcannedresponse', // Ensure your plugin is added to extraPlugins
|
||||
// Optionally customize your toolbar further, or use the default configuration
|
||||
toolbarGroups: [
|
||||
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
|
||||
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] },
|
||||
{ name: 'links' },
|
||||
{ name: 'insert' },
|
||||
{ name: 'forms' },
|
||||
{ name: 'tools' },
|
||||
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
|
||||
{ name: 'others' },
|
||||
'/',
|
||||
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
|
||||
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] },
|
||||
{ name: 'styles' },
|
||||
{ name: 'colors' },
|
||||
{ name: 'about' }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
// Get the modal
|
||||
var modal = document.getElementById("cannedResponseModal");
|
||||
|
||||
// Get the button that opens the modal
|
||||
var btn = document.getElementsByClassName("canned-response");
|
||||
|
||||
// Get the <span> element that closes the modal
|
||||
var span = document.getElementsByClassName("close-button")[0];
|
||||
|
||||
// When the user clicks on <span> (x), close the modal
|
||||
span.onclick = function() {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
|
||||
// When the user clicks anywhere outside of the modal, close it
|
||||
window.onclick = function(event) {
|
||||
if (event.target == modal) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners to canned response buttons
|
||||
Array.from(btn).forEach(function(element) {
|
||||
element.addEventListener('click', function() {
|
||||
var response = this.getAttribute('data-response');
|
||||
CKEDITOR.instances.editor1.insertHtml(response);
|
||||
modal.style.display = "none";
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Action Box -->
|
||||
<div class="action-box">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tagify CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet">
|
||||
|
||||
<!-- Tagify JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
#cke_editor1{
|
||||
width:100%!important;
|
||||
}
|
||||
|
||||
div.chat-inbox.chat-box{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 100%;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
background:;#748c62 !important
|
||||
}
|
||||
|
||||
.close-button:hover,
|
||||
.close-button:focus {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
#cannedResponseModal ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#cannedResponseModal li {
|
||||
padding: 8px 0; /* Spacing between buttons */
|
||||
}
|
||||
|
||||
.canned-response {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background-color 0.3s, box-shadow 0.3s;
|
||||
}
|
||||
|
||||
.canned-response:hover {
|
||||
background-color: #45a049;
|
||||
box-shadow: 0 2px 4px 0 rgba(0,0,0,0.24);
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--Script Tag-->
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
// var activeTicketId = $('.chat-detail-item.active').data('ticket-id');
|
||||
var activeTicketId = $('#aw-ticket_id').val();
|
||||
|
||||
// Load chat messages for the active ticket on page load
|
||||
loadChatMessages(activeTicketId);
|
||||
loadActionBox(activeTicketId);
|
||||
|
||||
// Click event to switch between tickets
|
||||
$('.chat-detail-item').on('click', function() {
|
||||
$('.chat-detail-item').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
activeTicketId = $(this).data('ticket-id');
|
||||
loadChatMessages(activeTicketId);
|
||||
loadActionBox(activeTicketId);
|
||||
});
|
||||
|
||||
// Function to load chat messages for a specific ticket
|
||||
function loadChatMessages(ticketId) {
|
||||
$.ajax({
|
||||
url: '/fetch-chat-messages/' + ticketId,
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
// Update chat box with fetched messages
|
||||
$('.chat-content-wrapper').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error loading messages:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Function to load action box for a specific ticket
|
||||
function loadActionBox(ticketId) {
|
||||
$.ajax({
|
||||
url: '/fetch-action-box/' + ticketId,
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
// Update action box with fetched content
|
||||
$('.action-box').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error fetching action box content:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save reply
|
||||
$('.saveReply').on('click', function(){
|
||||
var message = CKEDITOR.instances.editor1.getData();
|
||||
if(message.trim() === '') {
|
||||
toastr.error('Message cannot be empty');
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: '/store/response',
|
||||
method: 'POST',
|
||||
data: {
|
||||
ticket_id: activeTicketId,
|
||||
message: message,
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
// Reload chat messages for the active ticket
|
||||
loadChatMessages(activeTicketId);
|
||||
loadActionBox(activeTicketId);
|
||||
// Update the last response in the ticket list
|
||||
var ticketElement = $('.chat-detail-item[data-ticket-id="' + activeTicketId + '"]');
|
||||
ticketElement.find('.receiver-message').text(response.message);
|
||||
ticketElement.find('.message-time').text(response.created_at);
|
||||
// Clear the editor
|
||||
CKEDITOR.instances.editor1.setData('');
|
||||
|
||||
// window.location.reload();
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error creating a response:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.chat-detail-item').on('click', function(){
|
||||
$('.chat-detail-item').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
var ticketId = $(this).data('ticket-id');
|
||||
fetchChatMessages(ticketId);
|
||||
updateActionBox(ticketId);
|
||||
});
|
||||
|
||||
// Function to fetch and display chat messages for a ticket
|
||||
function fetchChatMessages(ticketId) {
|
||||
$.ajax({
|
||||
url: '/fetch-chat-messages/' + ticketId,
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
// Update chat box with fetched messages
|
||||
$('.chat-content-wrapper').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error fetching chat messages:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to update the action box for a ticket
|
||||
function updateActionBox(ticketId) {
|
||||
$.ajax({
|
||||
url: '/fetch-action-box/' + ticketId,
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
// Update action box with fetched content
|
||||
$('.action-box').html(response);
|
||||
},
|
||||
error: function(error) {
|
||||
console.log('Error fetching action box content:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>Terms And Conditions</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
{!! $link_text !!}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -4,29 +4,232 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<script>
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.side-bar-links a').removeClass('bg-light-color');
|
||||
$('.aw-a-waiting').addClass('bg-light-color');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Toastr CSS -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" rel="stylesheet">
|
||||
<!-- Toastr JS -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
||||
<!-- SweetAlert2 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css" rel="stylesheet">
|
||||
<!-- SweetAlert2 JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.handle_multiple__options {
|
||||
display: none;
|
||||
background-color: #f8f9fa;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button {
|
||||
background-color: #748C62;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.handle_multiple__options .tags button:hover {
|
||||
background-color: #383F33;
|
||||
}
|
||||
.handle_multiple__options .tags button:disabled {
|
||||
background-color: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.handle_multiple__options input{
|
||||
width: 32px;
|
||||
height: 19px;
|
||||
}
|
||||
.handle_multiple__options .common_shre{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* Custom Modal CSS */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 13%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
#customModal3 .modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: 15% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 40%;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.modal-content .btn-primary{
|
||||
background-color: #748C62 !important;
|
||||
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-close:hover,
|
||||
.modal-close:focus {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.filter-options {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter select {
|
||||
margin-right: 10px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
/* Hide checkboxes initially */
|
||||
.checkbox-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Show checkboxes when 'Handle Multiple' is active */
|
||||
.handle-multiple-active .checkbox-wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
padding: 12px 11px !important;
|
||||
}
|
||||
|
||||
.chat-user-img{
|
||||
margin-left:12px !important;
|
||||
}
|
||||
|
||||
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* When checkbox is checked, set background to green */
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: #748C62;
|
||||
border-color: #748C62;
|
||||
}
|
||||
|
||||
/* Optional: Add checkmark icon or any visual effect */
|
||||
input[type="checkbox"]:checked::before {
|
||||
transform: translate(0px, -1px);
|
||||
content: '✔';
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 4px;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.handle_multiple__options label {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: flex-start;
|
||||
/* margin-top: 12px; */
|
||||
transform: translate(2px, 6px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content-wrapper">
|
||||
<div class="ui card chat-card waiting-chat-card">
|
||||
<div class="content chat-card-header d-flex align-items-center justify-content-between">
|
||||
<div class="header">Waiting</div>
|
||||
<div class="data-actions d-flex justify-content-end">
|
||||
<button class="action-button d-flex align-items-center list-filter-btn">
|
||||
<img src="{{ asset('images/icons/list-filter.png') }}" alt="">
|
||||
</button>
|
||||
|
||||
<button class="action-button bg-dark-green-color color-light handle-multiple-btn">
|
||||
<img src="{{ asset('images/icons/Add_Plus.png') }}" alt="Plus Icon">
|
||||
<span>Handle Multiple</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--handle multiple-->
|
||||
<x-handle-filter />
|
||||
|
||||
@if(count($tickets) > 0)
|
||||
<div class="content chat-content">
|
||||
<ul class="chat-details">
|
||||
@foreach($tickets as $ticket)
|
||||
<li>
|
||||
<a href="{{ route('inbox') }}" class="chat-detail-item d-flex align-items-center">
|
||||
<a href="{{ route('show.ticket', $ticket->id) }}" class="chat-detail-item d-flex align-items-center">
|
||||
<div class="checkbox-wrapper">
|
||||
<input type="checkbox" class="ticket-checkbox" id="ticket-{{$ticket->id}}">
|
||||
</div>
|
||||
<div class="chat-user-img">
|
||||
<img src="{{ asset('images/Avatar.png') }}" alt="User">
|
||||
</div>
|
||||
|
|
@ -42,8 +245,8 @@
|
|||
</div>
|
||||
<div class="chat-ticket-row d-flex justify-content-between">
|
||||
<div class="ticket-status d-flex">
|
||||
<p class="color-dark-green receiver-name">{{$ticket->subject}}</p>
|
||||
<p class="receiver-message"> - {{$ticket->content}}.</p>
|
||||
<p class="color-dark-green receiver-name">{{$ticket->sender_name}}</p>
|
||||
<p class="receiver-message"> - {{\Illuminate\Support\Str::limit($ticket->subject, 90)}}.</p>
|
||||
</div>
|
||||
<p class="color-dark-green bold message-time">{{ \Carbon\Carbon::parse($ticket->created_at)->format('h:i A')}}</p>
|
||||
</div>
|
||||
|
|
@ -62,4 +265,5 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<x-custom-modals />
|
||||
@endsection
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\Mailgun\EmailController;
|
||||
use App\Http\Controllers\Chat\ChatController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -18,6 +19,17 @@
|
|||
|
||||
Route::post('/save-email', [EmailController::class, 'saveEmail']);
|
||||
|
||||
Route::post('/chat/start', [ChatController::class, 'startChat']);
|
||||
Route::post('/chat/send-message', [ChatController::class, 'sendMessage']);
|
||||
|
||||
Route::post('/chat/get', [ChatController::class, 'getChat']);
|
||||
Route::post('/chat/getMessages', [ChatController::class, 'getMessages']);
|
||||
|
||||
Route::post('/chat/check', [ChatController::class, 'checkChat']);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,12 @@
|
|||
use App\Http\Controllers\UserController;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Http\Controllers\TicketController;
|
||||
use App\Http\Controllers\ChatSettingController;
|
||||
|
||||
use App\Http\Controllers\Mailgun\MailgunController;
|
||||
use App\Http\Controllers\Chat\ChatController;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
@ -21,7 +25,6 @@
|
|||
|
|
||||
*/
|
||||
|
||||
|
||||
Route::get('/', [LoginController::class, 'login'])->name('login.create');
|
||||
Route::post('store/login', [LoginController::class, 'storeLogin'])->name('store.login');
|
||||
Route::post('store/register', [RegisterController::class, 'storeRegister'])->name('store.register');
|
||||
|
|
@ -31,24 +34,47 @@
|
|||
|
||||
Route::middleware(['auth'])->group(function(){
|
||||
|
||||
Route::get('/test', [MailgunController::class, 'addDomain'])->name('addDomain');
|
||||
// In routes/web.php
|
||||
Route::get('/chatgroups', [ChatController::class, 'getChatGroupsByCompany'])->name('chatgroups.get');
|
||||
|
||||
Route::get('/chat-demo', [ChatController::class, 'chatDemo'])->name('chat.demo');
|
||||
|
||||
Route::post('/close-chat', [ChatController::class, 'CloseChat'])->name('CloseChat');
|
||||
|
||||
|
||||
Route::get('/test', [MailgunController::class, 'test'])->name('test');
|
||||
|
||||
Route::get('/show-domain/{domain}', [MailgunController::class, 'showDomain'])->name('showDomain');
|
||||
|
||||
Route::post('/verify-domain', [MailgunController::class, 'verifyDomain'])->name('verifyDomain');
|
||||
|
||||
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('index');
|
||||
//Filter Route
|
||||
Route::post('filter', [TicketController::class, 'filter']);
|
||||
Route::post('default/all-tickets', [TicketController::class, 'defaultAllTickets']);
|
||||
Route::get('update-last-online', [UserController::class, 'updateLastOnline']);
|
||||
|
||||
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('index')->middleware('verifyDomain');;
|
||||
Route::get('/profile', [DashboardController::class, 'profile'])->name('profile');
|
||||
Route::post('update/profile', [DashboardController::class, 'updateProfile'])->name('update.profile');
|
||||
Route::get('company-info', [CompanyController::class, 'getCompanyInfo'])->name('get.company.info');
|
||||
Route::get('/waiting', [DashboardController::class, 'waiting'])->name('waiting');
|
||||
Route::get('/waiting', [TicketController::class, 'waiting'])->name('waiting');
|
||||
Route::get('/all-tickets', [TicketController::class, 'allTickets'])->name('all.tickets');
|
||||
Route::get('/show-ticket/{ticketId}', [TicketController::class, 'showTicket'])->name('show.ticket');
|
||||
Route::post('update-ticket-status/{ticketId}', [TicketController::class, 'updateStatus']);
|
||||
Route::post('update-ticket/{ticketId}', [TicketController::class, 'updateTicket'])->name('update.ticket');
|
||||
Route::post('store-tags', [TicketController::class, 'storeTags'])->name('store.tags');
|
||||
Route::get('inbox', [InboxController::class, 'inbox'])->name('inbox');
|
||||
Route::get('fetch-chat-messages/{ticketId}', [InboxController::class, 'fetchChatMessages']);
|
||||
Route::get('fetch-action-box/{ticketId}', [InboxController::class, 'fetchActionBox']);
|
||||
Route::get('/inbox-setting', [InboxController::class, 'inboxSetting'])->name('inbox.setting');
|
||||
Route::post('update-ticket-status/{ticketId}', [TicketController::class, 'updateStatus']);
|
||||
Route::post('store-comment', [TicketController::class, 'storeComment']);
|
||||
Route::post('store/response', [TicketController::class, 'storeResponse'])->name('store.response');
|
||||
Route::post('store-comment', [InboxController::class, 'storeComment']);
|
||||
Route::get('delete-comment/{commentId}', [InboxController::class, 'deleteComment']);
|
||||
Route::post('store/response', [InboxController::class, 'storeResponse'])->name('store.response');
|
||||
Route::post('update/chat-availability', [UserController::class, 'updateChatAvailability']);
|
||||
Route::post('assign/ticket', [TicketController::class, 'AssignTicket']);
|
||||
Route::post('delete/tickets', [TicketController::class, 'deleteTickets']);
|
||||
Route::post('update/ticket/status', [TicketController::class, 'updateTicketStatus']);
|
||||
Route::post('update/rule', [InboxController::class, 'updateRule'])->name('update.rule');
|
||||
//Basic Setting Route
|
||||
Route::post('inbox/basic-setting', [InboxController::class, 'basicSetting'])->name('inbox.basic.setting');
|
||||
//User Routes
|
||||
|
|
@ -66,9 +92,23 @@
|
|||
//Spam Handling
|
||||
Route::post('inbox/spam-handling', [InboxController::class, 'spamHandling'])->name('inbox.spam.handling');
|
||||
Route::get('spam-handling/{index}', [InboxController::class, 'deleteSpamHandling'])->name('delete.spam.handling');
|
||||
Route::get('/chat-setting', function(){
|
||||
return view('chat-setting');
|
||||
})->name('chat.setting');
|
||||
//Chat Setting Routes
|
||||
Route::get('/chat-setting', [ChatSettingController::class, 'chatSetting'])->name('chat.setting');
|
||||
Route::post('store/flow-setting', [ChatSettingController::class, 'storeFlowSetting'])->name('store.flow.setting');
|
||||
Route::post('store/display-chat', [ChatSettingController::class, 'storeDisplayChat'])->name('store.display.chat');
|
||||
Route::get('delete/display-chat/{id}', [ChatSettingController::class, 'deleteDisplayChat'])->name('delete.display.chat');
|
||||
Route::post('store/hide-chat', [ChatSettingController::class, 'storeHideChat'])->name('store.hide.chat');
|
||||
Route::post('store/text', [ChatSettingController::class, 'storeText'])->name('store.text');
|
||||
Route::post('store/style', [ChatSettingController::class, 'storeStyle'])->name('store.style');
|
||||
Route::post('store/chat-canned-responses', [ChatSettingController::class, 'storeChatCannedResponses'])->name('store.chat.canned.responses');
|
||||
Route::get('delete/chat-canned-responses/{id}', [ChatSettingController::class, 'deleteChatCannedResponses'])->name('delete.chat.canned.responses');
|
||||
Route::post('store/personal-data', [ChatSettingController::class, 'storePersonalData'])->name('store.personal.data');
|
||||
Route::get('terms-and-conditions/{companyId}', [ChatSettingController::class, 'companyTermsAndConditions'])->name('company.terms.conditions');
|
||||
Route::post('store/tags', [ChatSettingController::class, 'storeTags'])->name('store.tags');
|
||||
Route::post('setting/all-chat', [ChatSettingController::class, 'settingAllChat'])->name('setting.all.chat');
|
||||
Route::post('block/ip-addresses', [ChatSettingController::class, 'blockIpAdresses'])->name('block.ip.addresses');
|
||||
Route::get('delete/block/ip-addresses/{id}', [ChatSettingController::class, 'deleteBlockIpAdresses'])->name('delete.block.ip.addresses');
|
||||
|
||||
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
|
||||
Route::post('logout', [LoginController::class, 'logout'])->name('logout');
|
||||
});
|
||||
|
|
|
|||