TransHub_backend / routes /sourceTexts.js
linguabot's picture
Upload folder using huggingface_hub
da819ac verified
Raw
History Blame Contribute Delete
9.98 kB
const express = require('express');
const jwt = require('jsonwebtoken');
const SourceText = require('../models/SourceText');
const router = express.Router();
// Middleware to verify token (simplified - matches auth.js)
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Access token required' });
}
// For our simplified system, just check if token exists and has the right format
if (token.startsWith('user_') || token.startsWith('visitor_')) {
req.user = { token }; // We'll get user details from localStorage on frontend
next();
} else {
return res.status(403).json({ error: 'Invalid token' });
}
};
// Get all source texts with filters
router.get('/', authenticateToken, async (req, res) => {
try {
const {
sourceLanguage,
sourceCulture,
targetCulture,
difficulty,
sourceType,
tags,
page = 1,
limit = 10
} = req.query;
const filter = { isActive: true };
if (sourceLanguage) filter.sourceLanguage = sourceLanguage;
if (sourceCulture) filter.sourceCulture = sourceCulture;
if (targetCulture) filter.targetCultures = targetCulture;
if (difficulty) filter.difficulty = difficulty;
if (sourceType) filter.sourceType = sourceType;
if (tags) filter.tags = { $in: tags.split(',') };
const skip = (page - 1) * limit;
const texts = await SourceText.find(filter)
.sort({ createdAt: -1 })
.skip(skip)
.limit(parseInt(limit))
.populate('createdBy', 'username');
const total = await SourceText.countDocuments(filter);
res.json({
texts,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
});
} catch (error) {
console.error('Get source texts error:', error);
res.status(500).json({ error: 'Failed to get source texts' });
}
});
// Get a specific source text by ID
router.get('/:id', authenticateToken, async (req, res) => {
try {
const text = await SourceText.findById(req.params.id)
.populate('createdBy', 'username');
if (!text) {
return res.status(404).json({ error: 'Source text not found' });
}
// Increment usage count
text.usageCount += 1;
await text.save();
res.json(text);
} catch (error) {
console.error('Get source text error:', error);
res.status(500).json({ error: 'Failed to get source text' });
}
});
// Create a new source text
router.post('/', authenticateToken, async (req, res) => {
try {
const {
title,
content,
sourceLanguage,
sourceCulture,
sourceUrl,
sourceType,
culturalElements,
difficulty,
tags,
context,
targetCultures,
imageUrl,
imageAlt,
translationBrief,
weekNumber,
category
} = req.body;
// Validate required fields
if (!title || !content || !sourceLanguage || !sourceCulture) {
return res.status(400).json({
error: 'Title, content, source language, and source culture are required'
});
}
const sourceText = new SourceText({
title,
content,
sourceLanguage,
sourceCulture,
sourceUrl,
sourceType,
culturalElements: culturalElements || [],
difficulty: difficulty || 'intermediate',
tags: tags || [],
context,
targetCultures: targetCultures || [],
imageUrl,
imageAlt,
translationBrief,
weekNumber,
category,
createdBy: req.user.userId
});
await sourceText.save();
res.status(201).json({
message: 'Source text created successfully',
sourceText
});
} catch (error) {
console.error('Create source text error:', error);
res.status(500).json({ error: 'Failed to create source text' });
}
});
// Update a source text
router.put('/:id', authenticateToken, async (req, res) => {
try {
const sourceText = await SourceText.findById(req.params.id);
if (!sourceText) {
return res.status(404).json({ error: 'Source text not found' });
}
// Only allow creators or admins to update
if (sourceText.createdBy.toString() !== req.user.userId && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Not authorized to update this source text' });
}
const updatedText = await SourceText.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);
res.json({
message: 'Source text updated successfully',
sourceText: updatedText
});
} catch (error) {
console.error('Update source text error:', error);
res.status(500).json({ error: 'Failed to update source text' });
}
});
// Delete a source text (soft delete)
router.delete('/:id', authenticateToken, async (req, res) => {
try {
const sourceText = await SourceText.findById(req.params.id);
if (!sourceText) {
return res.status(404).json({ error: 'Source text not found' });
}
// Only allow creators or admins to delete
if (sourceText.createdBy.toString() !== req.user.userId && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Not authorized to delete this source text' });
}
sourceText.isActive = false;
await sourceText.save();
res.json({ message: 'Source text deleted successfully' });
} catch (error) {
console.error('Delete source text error:', error);
res.status(500).json({ error: 'Failed to delete source text' });
}
});
// Rate a source text
router.post('/:id/rate', authenticateToken, async (req, res) => {
try {
const { rating } = req.body;
if (!rating || rating < 1 || rating > 5) {
return res.status(400).json({ error: 'Rating must be between 1 and 5' });
}
const sourceText = await SourceText.findById(req.params.id);
if (!sourceText) {
return res.status(404).json({ error: 'Source text not found' });
}
// Update average rating
const newTotal = (sourceText.averageRating * sourceText.ratingCount) + rating;
sourceText.ratingCount += 1;
sourceText.averageRating = newTotal / sourceText.ratingCount;
await sourceText.save();
res.json({
message: 'Rating submitted successfully',
averageRating: sourceText.averageRating,
ratingCount: sourceText.ratingCount
});
} catch (error) {
console.error('Rate source text error:', error);
res.status(500).json({ error: 'Failed to submit rating' });
}
});
// Get weekly practice data by week number (temporarily public for testing)
router.get('/weekly-practice/week/:weekNumber', async (req, res) => {
try {
const weekNumber = parseInt(req.params.weekNumber);
if (isNaN(weekNumber) || weekNumber < 1 || weekNumber > 6) {
return res.status(400).json({ error: 'Invalid week number. Must be between 1 and 6.' });
}
// Debug: Log what we're searching for
console.log(`Searching for weekly practice week ${weekNumber}`);
const practices = await SourceText.find({
category: 'weekly-practice',
weekNumber: weekNumber,
isActive: true
}).sort({ createdAt: 1 });
console.log(`Found ${practices.length} practices for week ${weekNumber}`);
if (practices.length === 0) {
// Debug: Check what's actually in the database
const allTexts = await SourceText.find({});
console.log(`Total texts in database: ${allTexts.length}`);
console.log('Sample texts:', allTexts.slice(0, 3).map(t => ({ title: t.title, category: t.category, weekNumber: t.weekNumber })));
return res.status(404).json({
error: `No weekly practice found for week ${weekNumber}`,
practices: [],
weekNumber: weekNumber,
debug: {
totalTexts: allTexts.length,
sampleTexts: allTexts.slice(0, 3).map(t => ({ title: t.title, category: t.category, weekNumber: t.weekNumber }))
}
});
}
res.json({
weekNumber: weekNumber,
practices: practices,
total: practices.length
});
} catch (error) {
console.error('Get weekly practice error:', error);
res.status(500).json({ error: 'Failed to get weekly practice data' });
}
});
// Get cultural elements for a source text
router.get('/:id/cultural-elements', authenticateToken, async (req, res) => {
try {
const sourceText = await SourceText.findById(req.params.id);
if (!sourceText) {
return res.status(404).json({ error: 'Source text not found' });
}
res.json({
culturalElements: sourceText.culturalElements,
content: sourceText.content
});
} catch (error) {
console.error('Get cultural elements error:', error);
res.status(500).json({ error: 'Failed to get cultural elements' });
}
});
// Highlight cultural elements in text
router.post('/:id/highlight', authenticateToken, async (req, res) => {
try {
const { culturalElements } = req.body;
const sourceText = await SourceText.findById(req.params.id);
if (!sourceText) {
return res.status(404).json({ error: 'Source text not found' });
}
// Only allow creators or admins to update cultural elements
if (sourceText.createdBy.toString() !== req.user.userId && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Not authorized to update this source text' });
}
sourceText.culturalElements = culturalElements;
await sourceText.save();
res.json({
message: 'Cultural elements updated successfully',
culturalElements: sourceText.culturalElements
});
} catch (error) {
console.error('Highlight cultural elements error:', error);
res.status(500).json({ error: 'Failed to update cultural elements' });
}
});
module.exports = router;