diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 44581391..1d643167 100644 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -761,7 +761,22 @@ $routes->group('mensajes', ['namespace' => 'App\Controllers\Mensajeria'], functi $routes->post('datatable', 'TarifaAcabados::datatable', ['as' => 'tarifaAcabadoDT']);*/ }); }); +$routes->group('messages', ['namespace' => 'App\Controllers\Chat'], function ($routes) { + $routes->get('datatable', 'ChatController::datatable_messages', ['as' => 'getDatatableMessages']); + $routes->post('direct', 'ChatController::store_new_direct_message', ['as' => 'storeNewDirectMessage']); + +}); $routes->group('chat', ['namespace' => 'App\Controllers\Chat'], function ($routes) { + + $routes->get('direct/(:num)', 'ChatController::get_chat_direct_view/$1', ['as' => 'getChatDirectView']); + $routes->get('direct/conversation/(:num)', 'ChatController::get_chat_direct/$1', ['as' => 'getChatDirect']); + $routes->get('direct/users/select/(:num)', 'ChatController::get_chat_direct_select_users/$1', ['as' => 'getChatDirectSelectUsers']); + $routes->get('direct/users/(:num)', 'ChatController::get_chat_direct_users', ['as' => 'getChatDirectUsers']); + $routes->post('direct/users/(:num)', 'ChatController::store_chat_direct_users/$1', ['as' => 'storeChatDirectUsers']); + $routes->get('direct/messages/(:num)', 'ChatController::get_chat_direct_messages/$1', ['as' => 'getChatDirectMessages']); + $routes->post('direct/messages/(:num)', 'ChatController::store_chat_direct_message/$1', ['as' => 'storeChatDirectMessages']); + + $routes->get('departments', 'ChatController::get_chat_departments', ['as' => 'getChatDepartments']); $routes->get('department/presupuesto/(:num)/(:num)', 'ChatController::get_chat_presupuesto/$1/$2', ['as' => 'getChatPresupuesto']); $routes->get('department/pedido/(:num)/(:num)', 'ChatController::get_chat_pedido/$1/$2', ['as' => 'getChatPedido']); diff --git a/ci4/app/Controllers/Chat/ChatController.php b/ci4/app/Controllers/Chat/ChatController.php index 93c5bb58..969e7713 100644 --- a/ci4/app/Controllers/Chat/ChatController.php +++ b/ci4/app/Controllers/Chat/ChatController.php @@ -11,10 +11,13 @@ use App\Models\ChatNotification; use App\Models\ChatUser; use App\Models\Clientes\ClienteModel; use App\Models\Usuarios\UserModel; +use App\Services\MessageService; use CodeIgniter\HTTP\ResponseInterface; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\Log\Logger; use Psr\Log\LoggerInterface; +use Hermawan\DataTables\DataTable; +use CodeIgniter\I18n\Time; class ChatController extends BaseController { @@ -27,7 +30,7 @@ class ChatController extends BaseController protected ChatUser $chatUserModel; protected ChatNotification $chatNotificationModel; - + protected static $viewPath = 'themes/vuexy/form/mensajes/'; public function initController( @@ -108,6 +111,16 @@ class ChatController extends BaseController $data["chat"] = $chat; return $this->response->setJSON($data); } + public function get_chat_direct_view($chat_id){ + $chat = $this->chatModel->find($chat_id); + $this->viewData['breadcrumb'] = [ + ['title' => lang("Chat.chat"), 'route' => route_to("mensajeriaView"), 'active' => false], + ['title' => $chat->title, 'route' => 'javascript:void(0);', 'active' => true] + ]; + $this->viewData["chatId"] = $chat_id; + + return view(static::$viewPath . 'messageChat', $this->viewData); + } public function get_chat(int $chat_id) { @@ -428,5 +441,75 @@ class ChatController extends BaseController return $this->response->setJSON($data); } + public function datatable_messages() + { + $query = $this->chatModel->getQueryDatatable(); + $auth_user_id = auth()->user()->id; + return DataTable::of($query) + ->edit('created_at',fn($q) => Time::createFromFormat('Y-m-d H:i:s',$q->created_at)->format("d/m/Y H:i")) + ->edit('updated_at',fn($q) => Time::createFromFormat('Y-m-d H:i:s',$q->updated_at)->format("d/m/Y H:i")) + ->add("creator", fn($q) => $this->chatModel->getChatFirstUser($q->id)->userFullName) + ->add("viewed", fn($q) => $this->chatModel->isMessageChatViewed($q->id,$auth_user_id)) + ->add("action", fn($q) => $q->id) + ->toJson(true); + } + public function store_new_direct_message() + { + $bodyData = $this->request->getPost(); + $rules = [ + "title" => "required|string", + "message" => "required|string", + "users" => "required", + ]; + if(!$this->validate($rules)){ + return $this->response->setStatusCode(400)->setJSON([ + 'message' => lang('App.global_alert_save_error'), + 'status' => 'error', + 'errors' => $this->validator->getErrors(), + ]); + } + $this->chatModel->createNewDirectChat(...$bodyData); + return $this->response->setJSON(["message" => lang("Chat.new_message_ok"),"status" => true]); + + } + public function get_chat_direct($chat_id){ + $chatData = $this->chatModel->getChatDirect($chat_id); + return $this->response->setJSON($chatData); + } + public function get_chat_direct_select_users($chat_id){ + $chat_users_id = $this->chatUserModel->getChatUserArrayId($chat_id); + + $query = $this->userModel->builder()->select( + [ + "id", + "CONCAT(first_name,' ',last_name,'(',username,')') as name" + ] + )->where("cliente_id", null) + ->where("deleted_at", null) + ->whereNotIn("id",$chat_users_id); + if ($this->request->getGet("q")) { + $query->groupStart() + ->orLike("users.username", $this->request->getGet("q")) + ->orLike("CONCAT(first_name,' ',last_name)", $this->request->getGet("q")) + ->groupEnd(); + } + + return $this->response->setJSON($query->get()->getResultObject()); + } + public function store_chat_direct_users($chat_id){ + $bodyData = $this->request->getPost(); + $chat_users = array_map(fn($q) => ["chat_id" => $chat_id,"user_id" => $q],$bodyData["users"]); + $this->chatUserModel->insertBatch($chat_users); + return $this->response->setJSON(["message" => "ok","status" => true]); + } + public function store_chat_direct_message(int $chat_id){ + $bodyData = $this->request->getPost(); + $bodyData["sender_id"] = auth()->user()->id; + $chat_message_id = $this->chatMessageModel->insert($bodyData); + $message = $this->chatMessageModel->get_chat_message($chat_message_id); + return $this->response->setJSON($message); + + + } } diff --git a/ci4/app/Database/Seeds/MessageSeeder.php b/ci4/app/Database/Seeds/MessageSeeder.php new file mode 100644 index 00000000..d8d450ca --- /dev/null +++ b/ci4/app/Database/Seeds/MessageSeeder.php @@ -0,0 +1,52 @@ + "Message Test", + "messages" => [ + [ + "sender_id" => 1, + "receiver_id" => 127, + ], + [ + "sender_id" => 127, + "receiver_id" => 1, + ] + ] + ]; + $chatModel = model(ChatModel::class); + $chatMessageModel = model(ChatMessageModel::class); + $chatNotificationModel = model(ChatNotification::class); + $userModel = model(UserModel::class); + foreach (range(1,100) as $key => $value) { + $chat_id = $chatModel->insert(["title" => $data["title"]." ".$value]); + foreach ($data["messages"] as $key => $value) { + $first_name = $userModel->find($value["receiver_id"])?->first_name; + $chat_message_id = $chatMessageModel->insert([ + "chat_id" => $chat_id, + "sender_id" => $value["sender_id"], + "receiver_id" => $value["receiver_id"], + "message" => "Hola"." ".$first_name + ]); + $chatNotificationModel->insert([ + "chat_message_id" => $chat_message_id, + "user_id" => $value["receiver_id"] + ]); + } + } + } +} diff --git a/ci4/app/Language/es/Chat.php b/ci4/app/Language/es/Chat.php index ea5eaac2..1a0efc20 100644 --- a/ci4/app/Language/es/Chat.php +++ b/ci4/app/Language/es/Chat.php @@ -10,5 +10,17 @@ return [ "new_receivers" => "Nuevos participantes", "btn_send" => "Enviar", "btn_send_update" => "Enviar" - ] + ], + "datatable_messages" => [ + "created_at" => "Fecha creación", + "updated_at" => "Fecha actualización", + "title" => "Título", + "creator" => "Creador", + "viewed" => "Leído", + + ], + "new_message_ok" => "Mensaje enviado correctamente", + "participants" => "Participantes", + "write_message_placeholder" => "Escriba aquí su mensaje..." + ]; \ No newline at end of file diff --git a/ci4/app/Models/Chat/ChatMessageModel.php b/ci4/app/Models/Chat/ChatMessageModel.php index ce3b2b0a..e0ee9a20 100644 --- a/ci4/app/Models/Chat/ChatMessageModel.php +++ b/ci4/app/Models/Chat/ChatMessageModel.php @@ -5,14 +5,15 @@ namespace App\Models\Chat; use App\Models\ChatNotification; use App\Models\Usuarios\UserModel; use CodeIgniter\Model; +use CodeIgniter\Database\BaseBuilder; class ChatMessageModel extends Model { protected $table = 'chat_messages'; protected $primaryKey = 'id'; protected $useAutoIncrement = true; - protected $returnType = 'array'; - protected $useSoftDeletes = false; + protected $returnType = 'object'; + protected $useSoftDeletes = true; protected $protectFields = true; protected $allowedFields = [ "message", @@ -29,7 +30,7 @@ class ChatMessageModel extends Model protected array $castHandlers = []; // Dates - protected $useTimestamps = false; + protected $useTimestamps = true; protected $dateFormat = 'datetime'; protected $createdField = 'created_at'; protected $updatedField = 'updated_at'; @@ -72,6 +73,23 @@ class ChatMessageModel extends Model } return $messages; } + public function get_chat_message(int $chat_message_id): object + { + $user = model(UserModel::class); + $auth_user = auth()->user(); + $message = $this->find($chat_message_id); + $message->pos = $auth_user->id == $message->sender_id ? "right" : "left"; + if ($auth_user->id == $message->sender_id) { + $message->sender_first_name = $auth_user->first_name; + $message->sender_last_name = $auth_user->last_name; + + } else { + $sender_user = $user->find($message->sender_id); + $message->sender_first_name = $sender_user->first_name; + $message->sender_last_name = $sender_user->last_name; + } + return $message; + } public function get_chat_contact_messages(int $receiver_id): array { $conversationArray = []; diff --git a/ci4/app/Models/Chat/ChatModel.php b/ci4/app/Models/Chat/ChatModel.php index 59410d2f..d0b3b5bd 100644 --- a/ci4/app/Models/Chat/ChatModel.php +++ b/ci4/app/Models/Chat/ChatModel.php @@ -3,12 +3,13 @@ namespace App\Models\Chat; use App\Models\ChatNotification; +use App\Models\ChatUser; use App\Models\Facturas\FacturaModel; use App\Models\Pedidos\PedidoModel; use App\Models\Presupuestos\PresupuestoModel; use App\Models\Usuarios\UserModel; use CodeIgniter\Model; -use stdClass; +use CodeIgniter\Database\BaseBuilder; class ChatModel extends Model { @@ -623,5 +624,126 @@ class ChatModel extends Model return $q; } + public function getChatFirstUser(int $chat_id) : object + { + $q = $this->builder()->select(["users.id", + "CONCAT(users.first_name,' ',users.last_name) as userFullName", + ]) + ->join("chat_messages","chat_messages.chat_id = chats.id",'left') + ->join("users","users.id = chat_messages.sender_id","left") + ->where("chats.id",$chat_id) + ->where("chat_messages.deleted_at",null) + ->orderBy("chat_messages.created_at",'ASC'); + return $q->get()->getFirstRow(); + } + /** + * Check if all messages of a chat sended to an user have been viewed. + * + * @param integer $chat_id + * @param integer $user_id + * @return boolean True : All messages readed + */ + public function isMessageChatViewed(int $chat_id, int $user_id) : bool + { + $q = $this->builder()->select(["chat_notifications.id"]) + ->join("chat_messages","chat_messages.chat_id = chats.id",'left') + ->join("chat_notifications","chat_notifications.chat_message_id = chat_messages.id",'left') + ->where("chats.id",$chat_id) + ->where("chat_notifications.user_id",$user_id) + ->where("chat_notifications.viewed",false); + $unread_messages_count = $q->countAllResults(); + if($unread_messages_count > 0){ + $result = false; + }else{ + $result = true; + } + return $result; + } + public function getQueryDatatable(): BaseBuilder + { + $query = $this->builder() + ->select([ + "chats.id", + "chats.created_at", + "chats.updated_at", + "chats.title", + ]) + ->where("chat_department_id",null) + ->where("pedido_id",null) + ->where("presupuesto_id",null) + ->where("factura_id",null) + ->where("title is NOT NULL",NULL,FALSE) + ->orderBy("created_at", "DESC"); + return $query; + } + public function createNewDirectChat(string $title,string $message,array $users) + { + $chatMessageModel = model(ChatMessageModel::class); + $chatNotificationModel = model(ChatNotification::class); + $chatUserModel = model(ChatUser::class); + $auth_user_id = auth()->user()->id; + $chat_id = $this->insert(["title" => $title]); + $chat_message_id = $chatMessageModel->insert([ + "chat_id" => $chat_id, + "sender_id" => $auth_user_id, + "receiver_id" => null, + "message" => $message + ]); + $chatUserModel->insert(["chat_id" => $chat_id,"user_id" => $auth_user_id]); + foreach ($users as $key => $user_id) { + $chatUserModel->insert(["chat_id" => $chat_id,"user_id" => $user_id]); + $chatNotificationModel->insert(["chat_message_id" => $chat_message_id,"user_id" => $user_id]); + } + } + /** + * Obtain users and messages from `chat_id` + * + * @param integer $chat_id + * @return array + * [ + * "chat" => object, + * "messages" => array , + * "users" => array + * ] + */ + public function getChatDirect(int $chat_id) : array + { + $auth_user = auth()->user()->id; + $chat = $this->find($chat_id); + $query = $this->builder()->select([ + "users.*", + ]) + ->join("chat_users","chat_users.chat_id = chats.id") + ->join("users","users.id = chat_users.user_id","left") + ->where("chats.id",$chat_id); + $users = $query->get()->getResultObject(); + $query = $this->builder()->select([ + "chat_messages.*", + "users.first_name as sender_first_name", + "users.last_name as sender_last_name", + + ]) + ->join("chat_messages","chat_messages.chat_id = chats.id","left") + ->join("users","chat_messages.sender_id = users.id","left") + ->where("chats.id",$chat_id); + + $messages = $query->get()->getResultObject(); + $validatedMessages = []; + foreach ($messages as $key => $message) { + if($auth_user == $message->sender_id){ + $message->pos = 'right'; + $validatedMessages[] = $message; + }else{ + $message->pos = 'left'; + $validatedMessages[] = $message; + } + } + $data = [ + "chat" => $chat, + "users" => $users, + "messages" => $validatedMessages + ]; + return $data; + } } diff --git a/ci4/app/Models/ChatNotification.php b/ci4/app/Models/ChatNotification.php index fdbc6e2b..85f774d2 100644 --- a/ci4/app/Models/ChatNotification.php +++ b/ci4/app/Models/ChatNotification.php @@ -47,4 +47,5 @@ class ChatNotification extends Model protected $afterFind = []; protected $beforeDelete = []; protected $afterDelete = []; + } diff --git a/ci4/app/Models/ChatUser.php b/ci4/app/Models/ChatUser.php index 9e92163c..4880c6e5 100644 --- a/ci4/app/Models/ChatUser.php +++ b/ci4/app/Models/ChatUser.php @@ -46,4 +46,12 @@ class ChatUser extends Model protected $afterFind = []; protected $beforeDelete = []; protected $afterDelete = []; + public function getChatUserArrayId(int $chat_id) : array + { + $queryResult = $this->builder() + ->select(['chat_users.user_id']) + ->where("chat_users.chat_id",$chat_id) + ->get()->getResultObject(); + return array_map(fn($q) => $q->user_id,$queryResult); + } } diff --git a/ci4/app/Models/UserModel.php b/ci4/app/Models/UserModel.php index 5507d64b..3c2fe960 100644 --- a/ci4/app/Models/UserModel.php +++ b/ci4/app/Models/UserModel.php @@ -91,5 +91,4 @@ class UserModel extends ShieldUserModel return $result === null; } - } diff --git a/ci4/app/Views/themes/vuexy/components/alerts/alert.php b/ci4/app/Views/themes/vuexy/components/alerts/alert.php new file mode 100644 index 00000000..4741e898 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/components/alerts/alert.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/components/chat_direct.php b/ci4/app/Views/themes/vuexy/components/chat_direct.php new file mode 100644 index 00000000..dad29f75 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/components/chat_direct.php @@ -0,0 +1,154 @@ +
+
+ +
+ + + +
+ + + +
+ + + +
+
+
+
+
+ +

+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
    + + +
+
+ + +
+ + +
+
+
+
+ +
+ + +section('css') ?> + + +endSection() ?> + + + +section("additionalExternalJs") ?> + + +endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/components/modals/modalAddNewChatParticipant.php b/ci4/app/Views/themes/vuexy/components/modals/modalAddNewChatParticipant.php new file mode 100644 index 00000000..36e5c762 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/components/modals/modalAddNewChatParticipant.php @@ -0,0 +1,31 @@ + + \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/components/modals/modalNewDirectMessage.php b/ci4/app/Views/themes/vuexy/components/modals/modalNewDirectMessage.php new file mode 100644 index 00000000..b0f416c5 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/components/modals/modalNewDirectMessage.php @@ -0,0 +1,41 @@ + + \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/mensajes/mensajesView.php b/ci4/app/Views/themes/vuexy/form/mensajes/mensajesView.php index 594efa39..db220a0c 100644 --- a/ci4/app/Views/themes/vuexy/form/mensajes/mensajesView.php +++ b/ci4/app/Views/themes/vuexy/form/mensajes/mensajesView.php @@ -1,10 +1,68 @@ -include("themes/_commonPartialsBs/select2bs5") ?> -include("themes/_commonPartialsBs/datatables") ?> +include('themes/_commonPartialsBs/select2bs5') ?> +include('themes/_commonPartialsBs/datatables') ?> +include('themes/_commonPartialsBs/_confirm2delete') ?> extend('themes/vuexy/main/defaultlayout') ?> + section('content'); ?> -
- null]) ?> +
+
+ +
+
+

+
+ +
+ + +
+
+ +
+
+ + + + + + + + + + + + + + +
+
+ + + +
+ +
+
+ + + +endSection() ?> +section('css') ?> + + + + + +endSection() ?> +section("additionalExternalJs") ?> + + + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/mensajes/messageChat.php b/ci4/app/Views/themes/vuexy/form/mensajes/messageChat.php new file mode 100644 index 00000000..44dc5a48 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/mensajes/messageChat.php @@ -0,0 +1,27 @@ +include('themes/_commonPartialsBs/select2bs5') ?> +include('themes/_commonPartialsBs/datatables') ?> +include('themes/_commonPartialsBs/_confirm2delete') ?> +extend('themes/vuexy/main/defaultlayout') ?> + + +section('content'); ?> + +
+ $chatId]) ?> +
+ + +endSection() ?> +section('css') ?> + + + + + +endSection() ?> +section("additionalExternalJs") ?> + + + + +endSection() ?> \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/alerts/alert.js b/httpdocs/assets/js/safekat/components/alerts/alert.js new file mode 100644 index 00000000..ace6fde9 --- /dev/null +++ b/httpdocs/assets/js/safekat/components/alerts/alert.js @@ -0,0 +1,53 @@ + +class Alert { + constructor(domItem) { + this.item = domItem + this.headingTitle = this.item.find(".alert-heading") + this.body = this.item.find(".alert-body") + this.icon = this.item.find(".icon-alert") + this.iconSuccess = "ti-circle-check" + this.iconError = "ti-exclamation-mark" + + + + } + setIcon(iconClass){ + this.icon.removeClass(this.iconSuccess) + this.icon.removeClass(this.iconError) + this.icon.addClass(iconClass) + } + setAsError() { + this.item.removeClass("alert-success") + this.item.addClass("alert-danger") + this.setIcon(this.iconError) + + } + setAsSuccess() { + this.item.removeClass("alert-danger") + this.item.addClass("alert-success") + this.setIcon(this.iconSuccess) + } + setAsWarning() { + this.item.removeClass("alert-success") + this.item.addClass("alert-warning") + } + setAsInfo() { + this.item.removeClass("alert-*") + this.item.addClass("alert-info") + } + show() { + this.item.removeClass("d-none") + } + hide() { + this.item.addClass("d-none") + } + setHeadingTitle(title) { + this.headingTitle.text(title) + } + setContent(content) { + this.body.append(content) + } + setErrors() { } +} + +export default Alert; \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/chat.js b/httpdocs/assets/js/safekat/components/chat.js index 79003692..844112e6 100644 --- a/httpdocs/assets/js/safekat/components/chat.js +++ b/httpdocs/assets/js/safekat/components/chat.js @@ -1,4 +1,6 @@ import Ajax from '../components/ajax.js' +import Modal from './modal.js' +import ClassSelect from './select2.js' @@ -66,12 +68,38 @@ class Chat { }); } } + initDirectMessage() { + this.chatType = "direct" + this.modalNewParticipant = new Modal(this.domItem.find("#modalAddNewChatParticipant")) + this.selectPlaceholder = { + id: '0', + text: "Seleccione un usuario" + } + this.btnDirectMessageSubmit = this.domItem.find("#send-msg-btn-direct") + this.btnDirectMessageSubmit.on("click", this._handleStoreChatDirectMessage.bind(this)) + this.selectParticipants = new ClassSelect(this.modalNewParticipant.item.find("#select-users"), `/chat/direct/users/select/${this.modelId}`, this.selectPlaceholder, true) + + this.btnAddParticipant = this.domItem.find("#btn-chat-add-participant") + this.btnAddParticipantSubmit = this.domItem.find("#btn-chat-add-participant-submit") + this.btnAddParticipantSubmit.on("click", this._handleStoreChatDirectUsers.bind(this)) + this.btnAddParticipant.on("click", () => { + this.selectParticipants.init() + this.modalNewParticipant.toggle() + }) + this.selectParticipants.item.on("change", () => { + console.log(this.selectParticipants.getVal()) + if (this.selectParticipants.getVal().length > 0) { + this.btnAddParticipantSubmit.removeClass("d-none") + } else { + this.btnAddParticipantSubmit.addClass("d-none") + } + }) + this._handleGetChatDirect() + } initGeneral() { this.chatType = "general" this._handleGetChatList() this.sendBtnMessageDepartment.on("click", this._sendMessage.bind(this)) - - } initPresupuesto() { this.chatType = "presupuesto" @@ -236,8 +264,7 @@ class Chat { ); ajax.get(); } - _getChatDepartmentMessageCount() - { + _getChatDepartmentMessageCount() { let ajax = new Ajax( `/chat/department/count/${this.chatType}/${this.chatDeparmentId}/${this.modelId}`, null, @@ -249,10 +276,10 @@ class Chat { ); ajax.get(); } - _getChatDepartmentMessageCountSuccess(data){ + _getChatDepartmentMessageCountSuccess(data) { this.domItem.find(`chat_${data.name}`).find(".messages-unread-contact").text(data.count) } - _getChatDepartmentMessageCountError(){} + _getChatDepartmentMessageCountError() { } _getChatMessage() { let ajax = new Ajax( @@ -293,7 +320,7 @@ class Chat { ${chatMessage?.user?.first_name + " " + chatMessage?.user?.last_name}
- + ${chatMessage.created_at} @@ -309,6 +336,37 @@ class Chat { this.chatHistory.append(chatItem) return chatItem } + _addChatDirectMessages(chatMessage) { + console.log(chatMessage) + let chatItem = ` +
  • +
    +
    + +
    +

    ${chatMessage?.message}

    +
    +
    +
    + + ${chatMessage?.sender_first_name + " " + chatMessage?.sender_last_name} +
    + + ${chatMessage.created_at} +
    + +
    +
    +
    + ${chatMessage?.sender_first_name.charAt(0) + chatMessage?.sender_last_name.charAt(0)} +
    +
    +
    +
  • + ` + this.chatHistory.append(chatItem) + return chatItem + } _sendMessagePressKey(e) { if (e.which == 13) { e.preventDefault(); @@ -500,6 +558,104 @@ class Chat { this.sideBar.find("#contact-list").append(contactItem) } } + _addParticipantToList(contact) { + + let contactItem = + ` +
  • + +
    + + ${contact?.first_name?.charAt(0) ?? "?" + + contact?.last_name?.charAt(0) ?? "?"} + +
    +
    +
    ${contact?.first_name ?? "" + " " + + contact?.last_name ?? ""}
    +

    + ${contact?.cliente_id ? "[CLIENTE]" : ""}${contact.username} +

    +
    +
    +
  • + ` + + if (contact.first_name || contact.last_name) { + this.sideBar.find("#contact-list").append(contactItem) + } + } + _handleGetChatDirect() { + + const ajax = new Ajax( + `/chat/${this.chatType}/conversation/${this.modelId}`, + null, + null, + this._handleGetChatDirectSuccess.bind(this), + this._handleGetChatDirectError.bind(this) + ) + ajax.get() + } + _handleGetChatDirectSuccess(response) { + const { chat, users, messages } = response + if (users.length > 0) { + users.map(c => this._addContactToList(c)) + } + if (messages.length > 0) { + messages.map(m => this._addChatDirectMessages(m)) + } + this.domItem.find("#chat-direct-title").text(chat.title) + this.domItem.find(".chat-loader").addClass("d-none") + } + _handleGetChatDirectError(error) { } + + _handleStoreChatDirectUsers() { + const data = { "users": this.selectParticipants.getVal() } + this.domItem.find(".chat-loader").removeClass("d-none") + + const ajax = new Ajax( + `/chat/${this.chatType}/users/${this.modelId}`, + data, + null, + this._handleStoreChatDirectUsersSuccess.bind(this), + this._handleStoreChatDirectUsersError.bind(this) + ) + ajax.post() + } + _handleStoreChatDirectUsersSuccess(response) { + this.domItem.find(".chat-loader").removeClass("d-none") + this.chatHistory.empty() + this.sideBar.find("#contact-list").empty() + this.modalNewParticipant.toggle() + this._handleGetChatDirect() + this.selectParticipants.reset() + } + _handleStoreChatDirectUsersError() { + this.domItem.find(".chat-loader").removeClass("d-none") + } + _handleStoreChatDirectMessage() { + const data = { "message": this.messageInput.val(), "chat_id": this.modelId } + if (data.message) { + const ajax = new Ajax( + `/chat/${this.chatType}/messages/${this.modelId}`, + data, + null, + this._handleStoreChatDirectMessageSuccess.bind(this), + this._handleStoreChatDirectMessageError.bind(this) + ) + ajax.post() + } + } + _handleStoreChatDirectMessageSuccess(response) { + let message = response + this._addChatDirectMessages(message) + this.messageInput.val("") + } + _handleStoreChatDirectMessageError(error) { } + + + diff --git a/httpdocs/assets/js/safekat/components/datatables/MessagesDatatable.js b/httpdocs/assets/js/safekat/components/datatables/MessagesDatatable.js new file mode 100644 index 00000000..1efc7aa8 --- /dev/null +++ b/httpdocs/assets/js/safekat/components/datatables/MessagesDatatable.js @@ -0,0 +1,52 @@ +import Ajax from "../ajax.js"; + +class MessagesDatatable { + constructor(domItem) { + this.item = domItem + this.datatableItem = this.item.find("#tableMessages") + this.datatableColumns = [ + { data: 'created_at', searchable: true, sortable: true }, + { data: 'updated_at', searchable: true, sortable: true }, + { data: 'title', searchable: true, sortable: true }, + { data: 'creator', searchable: false, sortable: false }, + { data: 'viewed', searchable: false, sortable: false , + render : (d,t) => { + const iconClass = d == true ? "ti ti-sm ti-check" : "ti ti-sm ti-x" + return `` + } + }, + { + data: 'action', sortable: false, searchable: false, + render: (d, t) => { + return ` +
    + +
    + ` + } + } + ] + } + init() { + this.datatable = this.datatableItem.DataTable({ + processing: true, + layout: { + topStart: 'pageLength', + topEnd: 'search', + bottomStart: 'info', + bottomEnd: 'paging' + }, + serverSide: true, + pageLength: 10, + language: { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" + }, + columns: this.datatableColumns, + ajax: '/messages/datatable' + }); + + } + +} + +export default MessagesDatatable; \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/components/select2.js b/httpdocs/assets/js/safekat/components/select2.js index 1670b091..1d987376 100644 --- a/httpdocs/assets/js/safekat/components/select2.js +++ b/httpdocs/assets/js/safekat/components/select2.js @@ -13,6 +13,7 @@ let ClassSelect = function (domItem, url, placeholder, allowClear = false, param placeholder: placeholder, allowClear: allowClear, dropdownParent: domItem.parent(), + language: "es", ajax: { url: () => { return this.url; @@ -47,7 +48,7 @@ let ClassSelect = function (domItem, url, placeholder, allowClear = false, param this.init = function () { if (this.item.length) { this.item = this.item.select2(this.config); - $.fn.modal.Constructor.prototype.enforceFocus = function () {}; + // $.fn.modal.Constructor.prototype.enforceFocus = function () {}; } }; this.setOption = function (id, nombre) { diff --git a/httpdocs/assets/js/safekat/pages/configuracion/messages/index.js b/httpdocs/assets/js/safekat/pages/configuracion/messages/index.js new file mode 100644 index 00000000..1cdbf75e --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/configuracion/messages/index.js @@ -0,0 +1,5 @@ +import MessagePage from "./messagePage.js"; + +const messagePage = new MessagePage() + +messagePage.init() \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/configuracion/messages/messagePage.js b/httpdocs/assets/js/safekat/pages/configuracion/messages/messagePage.js new file mode 100644 index 00000000..5d2dbbdc --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/configuracion/messages/messagePage.js @@ -0,0 +1,82 @@ +import MessagesDatatable from "../../../components/datatables/MessagesDatatable.js"; +import Modal from "../../../components/modal.js"; +import Ajax from "../../../components/ajax.js"; +import ClassSelect from "../../../components/select2.js"; +import Alert from "../../../components/alerts/alert.js"; +class MessagePage { + constructor() { + this.messageDatatable = new MessagesDatatable($("#messagesViewCard")) // mensajesView.php + this.modalNewMessage = new Modal($("#modalNewDirectMessage")) + this.btnNewMessage = $("#btn-new-message") + this.btnSubmitNewDirectMessage = this.modalNewMessage.item.find("#submit-new-direct-message") + this.formNewDirectMessage = this.modalNewMessage.item.find("#formNewDirectMessage") + this.alert = new Alert($("#alertDirectMessage")) + this.selectUsers = $("#select-users") + this.selectPlaceholder = { + id: '0', + text: "Seleccione un usuario" + } + this.selectMessageUsers = new ClassSelect(this.selectUsers, '/chat/users/internal', this.selectPlaceholder, true) + + } + init() { + this.events() + this.messageDatatable.init() + } + events() { + // Open new message when click in btn-new-message + this.btnNewMessage.on("click", this.openNewMessageModal.bind(this)) + this.btnSubmitNewDirectMessage.on("click", this.handleSubmitNewMessage.bind(this)) + + } + openNewMessageModal() { + this.formNewDirectMessage.trigger("reset") + this.selectMessageUsers.init() + this.alert.hide() + this.showForm() + this.modalNewMessage.toggle() + } + + handleSubmitNewMessage() { + this.btnNewMessage.addClass("loading") + const ajax = new Ajax("/messages/direct", + this.getNewMessageDataForm(), + null, + this.handleSubmitNewMessageSuccess.bind(this), + this.handleSubmitNewMessageError.bind(this)) + ajax.post() + } + handleSubmitNewMessageSuccess(response) { + this.btnNewMessage.removeClass("loading") + this.alert.setAsSuccess() + this.alert.setHeadingTitle(response.message) + this.alert.show() + this.hideForm() + } + handleSubmitNewMessageError(response) { + const error = response.responseJSON + this.btnNewMessage.removeClass("loading") + this.alert.show() + this.alert.setAsError() + this.alert.setHeadingTitle(error.message) + } + getNewMessageDataForm() { + return { + "title": this.formNewDirectMessage.find("#new-direct-message-title").val(), + "message": this.formNewDirectMessage.find("#new-direct-message-text").val(), + "users": this.selectMessageUsers.getVal() + } + } + hideForm() { + this.formNewDirectMessage.addClass("d-none") + this.btnSubmitNewDirectMessage.addClass("d-none") + } + showForm() { + this.formNewDirectMessage.removeClass("d-none") + this.btnSubmitNewDirectMessage.removeClass("d-none") + + } +} + + +export default MessagePage; \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/messages/directMessagePage.js b/httpdocs/assets/js/safekat/pages/messages/directMessagePage.js new file mode 100644 index 00000000..ef79560f --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/messages/directMessagePage.js @@ -0,0 +1,9 @@ +import Chat from "../../components/chat.js"; + +$(function(){ + + const chatDirectMessage = new Chat($("#chat-direct-message")) + chatDirectMessage.init() + chatDirectMessage.initDirectMessage() +} +) diff --git a/httpdocs/assets/js/safekat/validation/newDirectMessageValidation.js b/httpdocs/assets/js/safekat/validation/newDirectMessageValidation.js new file mode 100644 index 00000000..42478e6e --- /dev/null +++ b/httpdocs/assets/js/safekat/validation/newDirectMessageValidation.js @@ -0,0 +1,21 @@ + +export const newDirectMessageValidation = +{ + fields:{ + title:{ + notEmpty:{ + message : "Título no puede estar vacío" + }, + }, + message:{ + notEmpty:{ + message : "Mensaje no puede estar vacío" + }, + }, + users:{ + notEmpty:{ + message : "Debe seleccionar al menos a un participante" + }, + } + }, +} \ No newline at end of file