messages view

This commit is contained in:
amazuecos
2024-11-28 09:14:59 +01:00
parent 3400c5f77c
commit 093aa42e67
23 changed files with 1030 additions and 19 deletions

View File

@ -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;

View File

@ -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 {
<i class="ti me-1"></i>
<small>${chatMessage?.user?.first_name + " " + chatMessage?.user?.last_name}</small>
</div>
<i class="ti ti-checks ti-xs me-1 text-success"></i>
<i class="ti ${chatMessage?.viewed ? "ti-checks" : "ti-check"} ti-xs me-1 text-success"></i>
<small>${chatMessage.created_at}</small>
</div>
@ -309,6 +336,37 @@ class Chat {
this.chatHistory.append(chatItem)
return chatItem
}
_addChatDirectMessages(chatMessage) {
console.log(chatMessage)
let chatItem = `
<li class="chat-message chat-message-${chatMessage.pos}">
<div class="d-flex overflow-hidden">
<div class="chat-message-wrapper flex-grow-1">
<div class="chat-message-text">
<p class="mb-0">${chatMessage?.message}</p>
</div>
<div class="text-end text-muted mt-1">
<div class="text-start text-muted mt-1">
<i class="ti me-1"></i>
<small>${chatMessage?.sender_first_name + " " + chatMessage?.sender_last_name}</small>
</div>
<i class="ti ${chatMessage?.viewed == "1" ? "ti-checks" : "ti-check"} ti-xs me-1 text-success"></i>
<small>${chatMessage.created_at}</small>
</div>
</div>
<div class="user-avatar flex-shrink-0 ms-3">
<div class="avatar avatar-sm">
<span class="avatar-initial rounded-circle bg-label-primary">${chatMessage?.sender_first_name.charAt(0) + chatMessage?.sender_last_name.charAt(0)}</span>
</div>
</div>
</div>
</li>
`
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 =
`
<li class="chat-contact-list-item">
<a class="d-flex align-items-center contact-chat" data-id="${contact.id}"
id="chat-contact-list-item-${contact.id}">
<div class="avatar d-block flex-shrink-0">
<span class="avatar-initial rounded-circle bg-label-primary">
${contact?.first_name?.charAt(0) ?? "?"
+ contact?.last_name?.charAt(0) ?? "?"}</span>
</div>
<div class="chat-contact-info flex-grow-1 ms-2">
<h6 class="chat-contact-name text-truncate m-0">${contact?.first_name ?? "" + " " +
contact?.last_name ?? ""}</h6>
<p class="chat-contact-status text-muted text-truncate mb-0">
${contact?.cliente_id ? "[CLIENTE]" : ""}${contact.username}
</p>
</div>
</a>
</li>
`
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) { }

View File

@ -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 `<span class="${iconClass}"</span>`
}
},
{
data: 'action', sortable: false, searchable: false,
render: (d, t) => {
return `
<div class="btn-group btn-group-sm">
<a href="/chat/direct/${d}" data-id="${d}" class="message-edit"><i class="ti ti-eye ti-sm mx-2"></i></a>
</div>
`
}
}
]
}
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;

View File

@ -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) {

View File

@ -0,0 +1,5 @@
import MessagePage from "./messagePage.js";
const messagePage = new MessagePage()
messagePage.init()

View File

@ -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;

View File

@ -0,0 +1,9 @@
import Chat from "../../components/chat.js";
$(function(){
const chatDirectMessage = new Chat($("#chat-direct-message"))
chatDirectMessage.init()
chatDirectMessage.initDirectMessage()
}
)

View File

@ -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"
},
}
},
}