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 @@
+
+
+ = view("themes/vuexy/components/modals/modalAddNewChatParticipant") ?>
+
+
+
+= $this->section('css') ?>
+
+
+= $this->endSection() ?>
+
+
+
+= $this->section("additionalExternalJs") ?>
+
+
+= $this->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 @@
+
+
+
+
+
+
+
+ = view("themes/vuexy/components/alerts/alert", ["id" => "alertNewParticipant"]) ?>
+
+
+
+
+
+
+
\ 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 @@
+
+
+
+
+
+
+
+ = view("themes/vuexy/components/alerts/alert", ["id" => "alertDirectMessage"]) ?>
+
+
+
+
+
+
+
\ 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 @@
-= $this->include("themes/_commonPartialsBs/select2bs5") ?>
-= $this->include("themes/_commonPartialsBs/datatables") ?>
+= $this->include('themes/_commonPartialsBs/select2bs5') ?>
+= $this->include('themes/_commonPartialsBs/datatables') ?>
+= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
= $this->extend('themes/vuexy/main/defaultlayout') ?>
+
= $this->section('content'); ?>
-
- = view("themes/vuexy/components/chat_general", data: ["modelId" => null]) ?>
+
+
+
+
+
+
+
+
+ = view('themes/_commonPartialsBs/_alertBoxes'); ?>
+
+
+
+
+ = lang('Chat.datatable_messages.created_at') ?>
+ = lang('Chat.datatable_messages.updated_at') ?>
+ = lang('Chat.datatable_messages.title') ?>
+ = lang('Chat.datatable_messages.creator') ?>
+ = lang('Chat.datatable_messages.viewed') ?>
+ = lang('Basic.global.Action') ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+= view("themes/vuexy/components/modals/modalNewDirectMessage") ?>
+
+= $this->endSection() ?>
+= $this->section('css') ?>
+
+
+
+
+
+= $this->endSection() ?>
+= $this->section("additionalExternalJs") ?>
+
+
+
+
= $this->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 @@
+= $this->include('themes/_commonPartialsBs/select2bs5') ?>
+= $this->include('themes/_commonPartialsBs/datatables') ?>
+= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
+= $this->extend('themes/vuexy/main/defaultlayout') ?>
+
+
+= $this->section('content'); ?>
+
+
+= view("themes/vuexy/components/chat_direct",["modelId" => $chatId]) ?>
+
+
+
+= $this->endSection() ?>
+= $this->section('css') ?>
+
+
+
+
+
+= $this->endSection() ?>
+= $this->section("additionalExternalJs") ?>
+
+
+
+
+= $this->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) ?? "?"}
+
+
+
+
+
+ `
+
+ 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