-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Message Send with Attachment Successfully
- Loading branch information
Showing
11 changed files
with
1,524 additions
and
308 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,163 +0,0 @@ | ||
|
||
<div id="chat-container"> | ||
<div id="search-container"> | ||
<input type="text" placeholder="Search" /> | ||
</div> | ||
|
||
<div class="new-message-container" onclick="openModal()"> | ||
<a href="#">+</a> | ||
</div> | ||
|
||
<div id="chat-title"> | ||
<span id="conversation-partner"></span> | ||
<img src="./images/trash.png" alt="Delete Conversation" /> | ||
</div> | ||
|
||
<!-- placeholder div if no messages are in messages area --> | ||
<div id="chat-message-list"> | ||
<div class="nothing">select a conversation</div> | ||
</div> | ||
|
||
<!-- send message form --> | ||
<form id="chat-form" method="post" enctype="multipart/form-data"> | ||
<label for="attachment"><img src="./images/attachment.png" alt="Add Attachment" /></label> | ||
<input type="file" multiple name="attachment" class="hide" id="attachment" /> | ||
<input type="text" name="message" placeholder="Type a message" autocomplete="off" /> | ||
</form> | ||
|
||
</div> | ||
<%- include('./partials/add-conversation-modal.ejs'); %> | ||
|
||
<!-- import socket io client from cdn --> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.min.js"></script> | ||
|
||
<script> | ||
const form = document.querySelector('#chat-form'); | ||
const messageContainer = document.querySelector('#chat-message-list'); | ||
const chatTitleContainer = document.querySelector('#conversation-partner'); | ||
const loggedinUserId = '<%= loggedInUser.userid %>'; | ||
const loggedinUserName = '<%= loggedInUser.username %>'; | ||
let participant = null; // selected conversation participant object | ||
let current_conversation_id; // selected conversation id | ||
// socket initialization | ||
const socket = io('<%= process.env.APP_URL %>'); | ||
// handle new/live incoming message from socket | ||
socket.on("new_message", data => { | ||
// only respond if current conversation is open in any client | ||
if(data.message.conversation_id == current_conversation_id) { | ||
// message class | ||
const messageClass = data.message.sender.id === loggedinUserId ? 'you-message' : 'other-message'; | ||
const senderAvatar = data.message.sender.avatar ? `<img src="./uploads/avatars/${data.message.sender.avatar}" alt="${data.message.sender.name}" />` : `<img src="./images/nophoto.png" alt="${data.message.sender.name}" />`; | ||
// message attachments | ||
let attachments = '<div class="attachments">'; | ||
if(data.message.attachment && data.message.attachment.length > 0) { | ||
data.message.attachment.forEach(attachment => { | ||
attachments += `<img src="./uploads/attachments/${attachment}" /> `; | ||
}); | ||
} | ||
attachments += '</div>'; | ||
let messageHTML; | ||
// do not show avatar for loggedin user | ||
if(data.message.sender.id == loggedinUserId) { | ||
messageHTML = `<div class="message-row ${messageClass}"><div class="message-content"> | ||
<div class="message-text">${data.message.message}</div> | ||
${attachments} | ||
<div class="message-time">${moment(data.message.date_time).fromNow()}</div> | ||
</div></div>`; | ||
} else { | ||
messageHTML = `<div class="message-row ${messageClass}"><div class="message-content"> | ||
${senderAvatar} | ||
<div class="message-text">${data.message.message}</div> | ||
${attachments} | ||
<div class="message-time">${moment(data.message.date_time).fromNow()}</div> | ||
</div></div>`; | ||
} | ||
// append the inoming message to message area as last item | ||
document.querySelector('#chat-message-list > .message-row:first-child').insertAdjacentHTML('beforeBegin', messageHTML); | ||
} | ||
}); | ||
// get messages of a conversation | ||
async function getMessages(conversation_id, current_conversation_name){ | ||
// messages failure toast | ||
const messagesFailureToast = Toastify({ | ||
text: "Error loading messages!", | ||
duration: 1000, | ||
}); | ||
let response = await fetch(`/inbox/messages/${conversation_id}`); | ||
const result= await response.json(); | ||
if(!result.errors && result.data) { | ||
form.style.visibility = 'visible'; | ||
const {data, user, conversation_id} = result; | ||
participant = data.participant; | ||
current_conversation_id = conversation_id; | ||
if(data.messages) { | ||
let allMessages = ''; | ||
if(data.messages.length > 0) { | ||
data.messages.forEach((message) => { | ||
let senderAvatar = message.sender.avatar ? `./uploads/avatars/${message.sender.avatar}` : './images/nophoto.png'; | ||
const messageClass = message.sender.id === loggedinUserId ? 'you-message' : 'other-message'; | ||
const showAvatar = message.sender.id === loggedinUserId ? '' : `<img src="${senderAvatar}" alt="${message.sender.name}" />`; | ||
// message attachments | ||
let attachments = '<div class="attachments">'; | ||
if(message.attachment && message.attachment.length > 0) { | ||
message.attachment.forEach(attachment => { | ||
attachments += `<img src="./uploads/attachments/${attachment}" /> `; | ||
}); | ||
} | ||
attachments += '</div>'; | ||
// final message html | ||
let messageHTML = `<div class="message-row ${messageClass}"><div class="message-content"> | ||
${showAvatar} | ||
<div class="message-text">${message.text}</div> | ||
${attachments} | ||
<div class="message-time">${moment(message.date_time).fromNow()}</div> | ||
</div></div>`; | ||
allMessages += messageHTML; | ||
messageContainer.innerHTML = allMessages; | ||
}); | ||
} else if(data.messages.length === 0) { | ||
messageContainer.innerHTML = '<div class="message-row"></div>'; | ||
} | ||
chatTitleContainer.textContent = current_conversation_name; | ||
} | ||
} else { | ||
messagesFailureToast.showToast(); | ||
} | ||
} | ||
// message sending | ||
form.onsubmit = async function (event) { | ||
event.preventDefault(); | ||
const sendMessageFailureToast = Toastify({ | ||
text: "Error sending message", | ||
duration: 1000, | ||
}); | ||
// prepare the form data | ||
const formData = new FormData(form); | ||
formData.append('receiverId', participant.id); | ||
formData.append('receiverName', participant.name); | ||
formData.append('avatar', participant.avatar || ''); | ||
formData.append('conversationId', current_conversation_id); | ||
// send the request to server | ||
let response = await fetch("/inbox/message", { | ||
method: "POST", | ||
body: formData, | ||
}); | ||
// get response | ||
let result = await response.json(); | ||
if (!result.errors) { | ||
form.reset(); // reset the form | ||
} else { | ||
sendMessageFailureToast.showToast(); | ||
} | ||
} | ||
</script> | ||
</body> | ||
</html> | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +0,0 @@ | ||
// external imports | ||
const multer = require("multer"); | ||
const path = require("path"); | ||
const createError = require("http-errors"); | ||
|
||
function uploader( | ||
subfolder_path, | ||
allowed_file_types, | ||
max_file_size, | ||
max_number_of_files, | ||
error_msg | ||
) { | ||
// File upload folder | ||
const UPLOADS_FOLDER = `${__dirname}/../public/uploads/${subfolder_path}/`; | ||
|
||
// define the storage | ||
const storage = multer.diskStorage({ | ||
destination: (req, file, cb) => { | ||
cb(null, UPLOADS_FOLDER); | ||
}, | ||
filename: (req, file, cb) => { | ||
const fileExt = path.extname(file.originalname); | ||
const fileName = | ||
file.originalname | ||
.replace(fileExt, "") | ||
.toLowerCase() | ||
.split(" ") | ||
.join("-") + | ||
"-" + | ||
Date.now(); | ||
|
||
cb(null, fileName + fileExt); | ||
}, | ||
}); | ||
|
||
// preapre the final multer upload object | ||
const upload = multer({ | ||
storage: storage, | ||
limits: { | ||
fileSize: max_file_size, | ||
}, | ||
fileFilter: (req, file, cb) => { | ||
if (req.files.length > max_number_of_files) { | ||
cb( | ||
createError( | ||
`Maximum ${max_number_of_files} files are allowed to upload!` | ||
) | ||
); | ||
} else { | ||
if (allowed_file_types.includes(file.mimetype)) { | ||
cb(null, true); | ||
} else { | ||
cb(createError(error_msg)); | ||
} | ||
} | ||
}, | ||
}); | ||
|
||
return upload; | ||
} | ||
|
||
module.exports = uploader; | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
#Emit Socket Event