You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
7.9 KiB
JavaScript
199 lines
7.9 KiB
JavaScript
function app(socket) {
|
|
return {
|
|
wysiwyg: null,
|
|
socket: socket,
|
|
typingTimeout: null,
|
|
init: function (el) {
|
|
this.wysiwyg = el;
|
|
this.setupWysiwyg();
|
|
},
|
|
setupWysiwyg: function () {
|
|
this.updateTextarea();
|
|
this.wysiwyg.contentDocument.body.addEventListener('input', this.onInput.bind(this));
|
|
this.wysiwyg.contentDocument.querySelector('head').innerHTML += `<style>
|
|
*, ::after, ::before {box-sizing: border-box;}
|
|
:root {tab-size: 4;}
|
|
html {line-height: 1.15;text-size-adjust: 100%;}
|
|
body {margin: 0px; padding: 1rem 0.5rem;}
|
|
body {font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";}
|
|
</style>`;
|
|
this.wysiwyg.contentDocument.body.innerHTML = '';
|
|
this.wysiwyg.contentDocument.designMode = "on";
|
|
},
|
|
onInput: function () {
|
|
this.updateTextarea();
|
|
this.sendTypingEvent();
|
|
},
|
|
updateTextarea: function () {
|
|
var wrapperDiv = document.createElement('div');
|
|
wrapperDiv.className = this.wysiwyg.classList.contains('rtl') ? 'rtl' : 'ltr';
|
|
wrapperDiv.innerHTML = this.wysiwyg.contentDocument.body.innerHTML;
|
|
document.getElementById('textEditor').value = wrapperDiv.outerHTML;
|
|
},
|
|
sendTypingEvent: function () {
|
|
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
clearTimeout(this.typingTimeout);
|
|
const userId = document.getElementById('userId').textContent.trim();
|
|
const data = { event_type: 'typing', user_id: userId};
|
|
this.socket.send(JSON.stringify(data));
|
|
|
|
this.typingTimeout = setTimeout(() => {
|
|
const stopTypingData = { event_type: 'stop_typing' };
|
|
this.socket.send(JSON.stringify(stopTypingData));
|
|
}, 1500);
|
|
}
|
|
},
|
|
format: function (cmd, param) {
|
|
this.wysiwyg.contentDocument.execCommand(cmd, false, param || null);
|
|
this.updateTextarea();
|
|
},
|
|
setDirection: function (direction) {
|
|
this.wysiwyg.classList.remove('rtl', 'ltr');
|
|
this.wysiwyg.contentDocument.body.classList.remove('rtl', 'ltr');
|
|
document.getElementById('textEditor').classList.remove('rtl', 'ltr');
|
|
|
|
this.wysiwyg.classList.add(direction);
|
|
this.wysiwyg.contentDocument.body.classList.add(direction);
|
|
document.getElementById('textEditor').classList.add(direction);
|
|
|
|
this.wysiwyg.contentDocument.body.style.direction = direction;
|
|
this.updateTextarea();
|
|
}
|
|
}
|
|
}
|
|
|
|
function initializeWebSocket() {
|
|
const ticketId = document.getElementById('ticketId').textContent.trim();
|
|
const wsScheme = window.location.protocol === "https:" ? "wss" : "ws";
|
|
const wsUrl = `${wsScheme}://${window.location.host}/ws/ticketroom/${ticketId}/`;;
|
|
const socket = new WebSocket(wsUrl);
|
|
|
|
socket.onopen = () => {
|
|
console.log('WebSocket connection established');
|
|
const appInstance = app(socket);
|
|
const wysiwygElement = document.querySelector('iframe');
|
|
appInstance.init(wysiwygElement);
|
|
};
|
|
|
|
let typingTimeout;
|
|
|
|
socket.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
const typingDiv = document.getElementById('typing-notification');
|
|
const messagesDiv = document.getElementById('messages');
|
|
|
|
if (data.event_type === 'typing') {
|
|
clearTimeout(typingTimeout);
|
|
|
|
|
|
if (!typingDiv.classList.contains('fade-in-up')) {
|
|
typingDiv.innerHTML = data.html;
|
|
typingDiv.classList.remove('fade-out');
|
|
typingDiv.classList.add('fade-in-up');
|
|
}
|
|
|
|
} else if (data.event_type === 'stop_typing') {
|
|
if (!typingDiv.classList.contains('fade-out')) {
|
|
typingDiv.classList.remove('fade-in-up');
|
|
typingDiv.classList.add('fade-out');
|
|
|
|
typingTimeout = setTimeout(() => {
|
|
typingDiv.innerHTML = '';
|
|
typingDiv.classList.remove('fade-out');
|
|
}, 600);
|
|
}
|
|
|
|
} else if (data.event_type === 'reaction') {
|
|
const updateElement = document.getElementById(`update-${data.update_id}`);
|
|
updateElement.querySelectorAll('.reaction-button').forEach(button => {
|
|
button.classList.remove('border-2', 'border-secondosiblue');
|
|
if (button.dataset.reaction === data.reaction) {
|
|
button.classList.add('border-2', 'border-secondosiblue');
|
|
}
|
|
});
|
|
const submittedReactions = updateElement.querySelector('#submitted-reactions');
|
|
submittedReactions.classList.remove('w-full', 'border-t', 'border-gray-200', 'pt-5', 'flex', 'justify-start', 'items-center', 'gap-3', 'p-5');
|
|
updateElement.querySelectorAll('.submittedreaction-button').forEach(button => {
|
|
button.classList.add('hidden');
|
|
if (button.dataset.reaction === data.reaction) {
|
|
submittedReactions.classList.add('w-full', 'border-t', 'border-gray-200', 'pt-5', 'flex', 'justify-start', 'items-center', 'gap-3', 'p-5');
|
|
button.classList.remove('hidden');
|
|
}
|
|
});
|
|
|
|
} else if (data.event_type === 'user_status') {
|
|
const toponlineUsersDiv = document.getElementById('top-online-users');
|
|
const fixedonlineUsersDiv = document.getElementById('fixed-online-users');
|
|
toponlineUsersDiv.innerHTML = data.html;
|
|
fixedonlineUsersDiv.innerHTML = data.html;
|
|
|
|
} else if (data.event_type === 'ticket_status') {
|
|
const ticketStatusDivs = document.querySelectorAll('.ticket-status');
|
|
ticketStatusDivs.forEach(div => {
|
|
div.innerHTML = data.html;
|
|
});
|
|
|
|
} else if (data.event_type === 'ticket_department') {
|
|
const ticketStatusDivs = document.querySelectorAll('.ticket-department');
|
|
ticketStatusDivs.forEach(div => {
|
|
div.innerHTML = data.html;
|
|
});
|
|
|
|
} else {
|
|
messagesDiv.insertAdjacentHTML('beforeend', data.html);
|
|
typingDiv.innerHTML = '';
|
|
typingDiv.classList.remove('fade-in-up', 'fade-out');
|
|
}
|
|
};
|
|
|
|
|
|
socket.onclose = () => {
|
|
console.log('WebSocket connection closed');
|
|
};
|
|
|
|
socket.onerror = (error) => {
|
|
console.log('WebSocket error:', error);
|
|
};
|
|
|
|
const form = document.getElementById('ticketForm');
|
|
const textEditor = document.getElementById('textEditor');
|
|
const wysiwygElement = document.querySelector('iframe');
|
|
|
|
form.addEventListener('submit', (event) => {
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(form);
|
|
const description = formData.get('description');
|
|
const filePath = formData.getAll('filePath');
|
|
|
|
const data = {
|
|
event_type: 'update',
|
|
description: description,
|
|
filePath: filePath
|
|
};
|
|
|
|
socket.send(JSON.stringify(data));
|
|
form.reset();
|
|
textEditor.value = '';
|
|
wysiwygElement.contentDocument.body.innerHTML = ''; // Clear the WYSIWYG content
|
|
});
|
|
|
|
document.addEventListener('click', (event) => {
|
|
if (event.target.classList.contains('reaction-button')) {
|
|
const updateId = event.target.dataset.updateId;
|
|
const reaction = event.target.dataset.reaction;
|
|
|
|
const data = {
|
|
event_type: 'update_reaction',
|
|
update_id: updateId,
|
|
reaction: reaction
|
|
};
|
|
|
|
socket.send(JSON.stringify(data));
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initializeWebSocket();
|
|
}); |