Files
thrillwiki_django_no_react/static/js/collaboration-system.js

203 lines
6.0 KiB
JavaScript

// Collaboration System
class CollaborationSystem {
constructor(options = {}) {
this.onCommentAdded = options.onCommentAdded || (() => {});
this.onCommentResolved = options.onCommentResolved || (() => {});
this.onThreadCreated = options.onThreadCreated || (() => {});
this.socket = null;
this.currentUser = options.currentUser;
}
initialize(socketUrl) {
this.socket = new WebSocket(socketUrl);
this.setupSocketHandlers();
}
setupSocketHandlers() {
if (!this.socket) return;
this.socket.addEventListener('open', () => {
console.log('Collaboration system connected');
});
this.socket.addEventListener('message', (event) => {
try {
const data = JSON.parse(event.data);
this.handleEvent(data);
} catch (error) {
console.error('Failed to parse collaboration event:', error);
}
});
this.socket.addEventListener('close', () => {
console.log('Collaboration system disconnected');
// Attempt to reconnect after delay
setTimeout(() => this.reconnect(), 5000);
});
this.socket.addEventListener('error', (error) => {
console.error('Collaboration system error:', error);
});
}
handleEvent(event) {
switch (event.type) {
case 'comment_added':
this.onCommentAdded(event.data);
break;
case 'comment_resolved':
this.onCommentResolved(event.data);
break;
case 'thread_created':
this.onThreadCreated(event.data);
break;
default:
console.warn('Unknown collaboration event:', event.type);
}
}
async createCommentThread(changeId, anchor, initialComment) {
try {
const response = await fetch('/vcs/comments/threads/create/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCsrfToken()
},
body: JSON.stringify({
change_id: changeId,
anchor: anchor,
initial_comment: initialComment
})
});
if (!response.ok) {
throw new Error('Failed to create comment thread');
}
const thread = await response.json();
// Notify other users through WebSocket
this.broadcastEvent({
type: 'thread_created',
data: {
thread_id: thread.id,
change_id: changeId,
anchor: anchor,
author: this.currentUser,
timestamp: new Date().toISOString()
}
});
return thread;
} catch (error) {
console.error('Error creating comment thread:', error);
throw error;
}
}
async addComment(threadId, content, parentId = null) {
try {
const response = await fetch('/vcs/comments/create/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCsrfToken()
},
body: JSON.stringify({
thread_id: threadId,
content: content,
parent_id: parentId
})
});
if (!response.ok) {
throw new Error('Failed to add comment');
}
const comment = await response.json();
// Notify other users through WebSocket
this.broadcastEvent({
type: 'comment_added',
data: {
comment_id: comment.id,
thread_id: threadId,
parent_id: parentId,
author: this.currentUser,
content: content,
timestamp: new Date().toISOString()
}
});
return comment;
} catch (error) {
console.error('Error adding comment:', error);
throw error;
}
}
async resolveThread(threadId) {
try {
const response = await fetch(`/vcs/comments/threads/${threadId}/resolve/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCsrfToken()
}
});
if (!response.ok) {
throw new Error('Failed to resolve thread');
}
const result = await response.json();
// Notify other users through WebSocket
this.broadcastEvent({
type: 'comment_resolved',
data: {
thread_id: threadId,
resolver: this.currentUser,
timestamp: new Date().toISOString()
}
});
return result;
} catch (error) {
console.error('Error resolving thread:', error);
throw error;
}
}
broadcastEvent(event) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(JSON.stringify(event));
}
}
reconnect() {
if (this.socket) {
try {
this.socket.close();
} catch (error) {
console.error('Error closing socket:', error);
}
}
this.initialize(this.socketUrl);
}
getCsrfToken() {
return document.querySelector('[name=csrfmiddlewaretoken]').value;
}
disconnect() {
if (this.socket) {
this.socket.close();
this.socket = null;
}
}
}
export default CollaborationSystem;