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.

184 lines
7.2 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 data = { event_type: 'typing' };
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 wsUrl = `ws://${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 {
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();
});