This commit is contained in:
Omar Najjar 2025-04-13 04:47:32 +10:00
parent c785511f3f
commit 25e2921d74
2 changed files with 161 additions and 26 deletions

View file

@ -2293,37 +2293,85 @@ async function submitComment(proposalId, commentText) {
console.log(`Submitting comment for proposal ${proposalId}: ${commentText.substring(0, 20)}...`);
try {
const response = await fetch(`${API_BASE_URL}/comments`, {
console.log("Making POST request to comments endpoint");
// Log the full API URL and request details
const requestUrl = `${API_BASE_URL}/comments`;
const requestData = {
proposalId: proposalId,
userId: currentUser?.id || 'anonymous',
commentText: commentText
};
console.log("Request URL:", requestUrl);
console.log("Request data:", requestData);
// Ensure we have a user
if (!currentUser || !currentUser.id) {
console.error("No current user - creating anonymous");
showToastMessage('Please wait, initializing user...', '#ff0099');
await loadUserData(); // Reinitialize user
}
// Create a controller to manage request timeouts
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
const response = await fetch(requestUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
proposalId: proposalId,
userId: currentUser.id,
commentText: commentText
})
}),
mode: 'cors',
credentials: 'same-origin',
signal: controller.signal
});
console.log("Comment submission response status:", response.status);
clearTimeout(timeoutId);
if (response.status >= 200 && response.status < 300) {
console.log("Comment submission response status:", response.status);
console.log("Response headers:", Object.fromEntries(response.headers.entries()));
// Process response based on status code
if (response.status === 200 || response.status === 201) {
// Successfully created comment
const data = await response.json();
console.log("Comment created successfully:", data);
loadComments(proposalId);
updateCommentCount(proposalId);
showToastMessage('Comment posted!', '#11cc77');
return data;
try {
const data = await response.json();
console.log("Comment created successfully:", data);
loadComments(proposalId);
updateCommentCount(proposalId);
showToastMessage('Comment posted!', '#11cc77');
return data;
} catch (jsonError) {
console.warn("Could not parse success response as JSON:", jsonError);
// Still consider this a success if status code was good
loadComments(proposalId);
updateCommentCount(proposalId);
showToastMessage('Comment posted!', '#11cc77');
return { success: true };
}
} else {
// Server returned an error
let errorMessage;
try {
const errorData = await response.json();
console.error("Error response data:", errorData);
errorMessage = errorData.error || 'Unknown server error';
} catch (e) {
errorMessage = await response.text() || 'Failed to post comment';
try {
errorMessage = await response.text() || 'Failed to post comment';
console.error("Error response text:", errorMessage);
} catch (textError) {
errorMessage = `HTTP error ${response.status}`;
console.error("Could not read error response:", textError);
}
}
console.error('Error posting comment:', errorMessage);
@ -2331,8 +2379,13 @@ async function submitComment(proposalId, commentText) {
throw new Error(errorMessage);
}
} catch (error) {
console.error('Network or processing error:', error);
showToastMessage('Failed to post comment', '#ff0099');
if (error.name === 'AbortError') {
console.error('Comment request timed out');
showToastMessage('Comment request timed out', '#ff0099');
} else {
console.error('Network or processing error:', error);
showToastMessage('Failed to post comment', '#ff0099');
}
throw error;
}
}

104
worker.js
View file

@ -2,7 +2,7 @@
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, Accept',
'Access-Control-Max-Age': '86400'
};
@ -19,6 +19,13 @@ function handleOptions() {
// Helper to create standardized responses
function createResponse(body, status = 200, cacheDuration = 60*60*24) {
// Don't allow null or undefined body
if (body === null || body === undefined) {
console.error('createResponse called with null or undefined body');
body = { error: 'Empty response body' };
status = 500;
}
const headers = {
'Content-Type': 'application/json',
...corsHeaders // Add CORS headers
@ -31,6 +38,9 @@ function createResponse(body, status = 200, cacheDuration = 60*60*24) {
headers['Cache-Control'] = 'no-store';
}
// Log the response details for debugging
console.log(`Creating response: status=${status}, headers=${JSON.stringify(headers)}, body type=${typeof body}`);
// Create a standard Response object
// This ensures properties like 'ok' are properly set based on status code
return new Response(JSON.stringify(body), {
@ -1028,6 +1038,10 @@ async function healthCheck(env) {
// Get proposals with optional sorting
async function getProposals(request, env) {
try {
// Define pagination constants locally to ensure they're in scope
const DEFAULT_PAGE_SIZE = 20;
const MAX_PAGE_SIZE = 100;
const url = new URL(request.url);
const page = parseInt(url.searchParams.get('page')) || 1;
const limit = Math.min(
@ -1037,7 +1051,7 @@ async function getProposals(request, env) {
const offset = (page - 1) * limit;
const sortBy = url.searchParams.get('sortBy') || 'newest';
console.log(`Getting proposals with sorting: ${sortBy}`);
console.log(`Getting proposals with sorting: ${sortBy}, page: ${page}, limit: ${limit}`);
// Define the base query
let query = `
@ -1698,29 +1712,69 @@ async function getComments(request, env) {
// Function to create a new comment
async function createComment(request, env) {
console.log("========== BEGIN createComment ==========");
try {
const data = await request.json();
// First check if request is properly formed
if (!request || !request.body) {
console.error("Invalid request object or missing body");
return createResponse({
error: 'Invalid request',
details: 'Request missing required properties'
}, 400);
}
// Attempt to parse JSON data
let data;
try {
data = await request.json();
console.log(`Parsed comment request data: ${JSON.stringify(data)}`);
} catch (jsonError) {
console.error("Failed to parse request JSON:", jsonError);
return createResponse({
error: 'Invalid JSON in request',
details: 'Could not parse request body as JSON'
}, 400);
}
const { proposalId, userId, commentText } = data;
console.log(`Creating comment: ${JSON.stringify(data)}`);
console.log(`Creating comment: proposalId=${proposalId}, userId=${userId}, text length=${commentText?.length || 0}`);
if (!proposalId || !userId || !commentText) {
console.error("Missing required fields:", {
hasProposalId: !!proposalId,
hasUserId: !!userId,
hasCommentText: !!commentText
});
return createResponse({
error: 'Missing required fields',
received: { proposalId, userId, commentText: commentText ? '[present]' : '[missing]' }
received: {
proposalId: proposalId || '[missing]',
userId: userId || '[missing]',
commentText: commentText ? '[present]' : '[missing]'
}
}, 400);
}
// Check if proposal exists
try {
console.log(`Checking if proposal exists: ${proposalId}`);
const proposalCheck = await env.DB.prepare(
`SELECT id FROM proposals WHERE id = ?`
).bind(proposalId).first();
if (!proposalCheck) {
return createResponse({ error: 'Proposal does not exist', proposalId }, 404);
console.error(`Proposal not found: ${proposalId}`);
return createResponse({
error: 'Proposal does not exist',
proposalId
}, 404);
}
console.log(`Proposal found: ${proposalCheck.id}`);
} catch (checkError) {
console.error("Error checking proposal existence:", checkError);
return createResponse({
error: 'Error checking proposal existence',
details: logError(checkError, { action: 'check_proposal', proposalId })
@ -1729,24 +1783,37 @@ async function createComment(request, env) {
// Check if user exists
try {
console.log(`Checking if user exists: ${userId}`);
const userCheck = await env.DB.prepare(
`SELECT id FROM users WHERE id = ?`
).bind(userId).first();
if (!userCheck) {
return createResponse({ error: 'User does not exist', userId }, 404);
console.error(`User not found: ${userId}`);
return createResponse({
error: 'User does not exist',
userId
}, 404);
}
console.log(`User found: ${userCheck.id}`);
} catch (userError) {
console.error("Error checking user existence:", userError);
return createResponse({
error: 'Error checking user existence',
details: logError(userError, { action: 'check_user', userId })
}, 500);
}
// Generate a unique comment ID
const id = 'comment_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
const timestamp = Date.now();
console.log(`Generated comment ID: ${id}`);
// Insert the comment into the database
try {
console.log("Inserting comment into database");
await env.DB.prepare(`
INSERT INTO comments (id, proposal_id, user_id, comment_text, timestamp)
VALUES (?, ?, ?, ?, ?)
@ -1755,19 +1822,32 @@ async function createComment(request, env) {
console.log(`Successfully created comment with ID: ${id}`);
// Get user name for response
console.log("Getting user name for response");
const userQuery = await env.DB.prepare(
`SELECT name FROM users WHERE id = ?`
).bind(userId).first();
return createResponse({
if (!userQuery || !userQuery.name) {
console.warn(`Could not find name for user ${userId}, using 'Anonymous'`);
}
const responseData = {
id,
proposalId,
userId,
userName: userQuery.name,
userName: userQuery?.name || 'Anonymous',
commentText,
timestamp
});
timestamp,
upvotes: 0,
downvotes: 0
};
console.log(`Creating successful response: ${JSON.stringify(responseData)}`);
console.log("========== END createComment ==========");
return createResponse(responseData, 201); // Use 201 Created for successful creation
} catch (dbError) {
console.error("Database error creating comment:", dbError);
return createResponse({
error: 'Failed to create comment in database',
details: logError(dbError, {
@ -1777,6 +1857,8 @@ async function createComment(request, env) {
}, 500);
}
} catch (error) {
console.error("Unhandled error in createComment:", error);
console.log("========== END createComment (with error) ==========");
return createResponse({
error: 'Failed to process comment creation',
details: logError(error, { action: 'create_comment_outer' })