Enable analysis and annotation features for literary works on the platform

Implements new API routes in `server/routes.ts` for fetching, creating, and retrieving analysis results and annotations, including user enrichment.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: cbacfb18-842a-4116-a907-18c0105ad8ec
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/39b5c689-6e8a-4d5a-9792-69cc81a56534/15578bf6-749f-46f9-89a4-2849cb59c0ac.jpg
This commit is contained in:
mukimovd 2025-05-08 00:20:04 +00:00
parent 085270ea6f
commit fc3a941647

View File

@ -600,6 +600,151 @@ export async function registerRoutes(app: Express): Promise<Server> {
res.json(works); res.json(works);
}); });
// Analysis results routes
app.get("/api/works/:slug/analysis", async (req: Request, res: Response) => {
try {
const work = await storage.getWorkBySlug(req.params.slug);
if (!work) {
return res.status(404).json({ message: "Work not found" });
}
const results = await storage.getAnalysisResultsByWorkId(work.id);
res.json(results);
} catch (error) {
console.error("Error fetching analysis results:", error);
res.status(500).json({ message: "Failed to fetch analysis results" });
}
});
app.get("/api/works/:slug/analysis/:type", async (req: Request, res: Response) => {
try {
const work = await storage.getWorkBySlug(req.params.slug);
if (!work) {
return res.status(404).json({ message: "Work not found" });
}
const result = await storage.getAnalysisResultByWorkAndType(work.id, req.params.type);
if (!result) {
return res.status(404).json({ message: "Analysis result not found" });
}
res.json(result);
} catch (error) {
console.error("Error fetching analysis result:", error);
res.status(500).json({ message: "Failed to fetch analysis result" });
}
});
app.post("/api/analysis", async (req: Request, res: Response) => {
try {
// Validate request body using zod
const analysisData = z.object({
workId: z.number(),
type: z.string(),
data: z.any()
}).parse(req.body);
const result = await storage.createAnalysisResult(analysisData);
res.status(201).json(result);
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({ message: error.errors });
}
console.error("Error creating analysis result:", error);
res.status(500).json({ message: "Failed to create analysis result" });
}
});
// Annotations routes
app.get("/api/works/:slug/annotations", async (req: Request, res: Response) => {
try {
const work = await storage.getWorkBySlug(req.params.slug);
if (!work) {
return res.status(404).json({ message: "Work not found" });
}
const annotations = await storage.getAnnotationsByWorkId(work.id);
// Enrich annotations with user information
const enrichedAnnotations = await Promise.all(annotations.map(async (annotation) => {
const user = await storage.getUser(annotation.userId);
if (!user) return annotation;
const { password, ...safeUser } = user;
return { ...annotation, user: safeUser };
}));
res.json(enrichedAnnotations);
} catch (error) {
console.error("Error fetching annotations:", error);
res.status(500).json({ message: "Failed to fetch annotations" });
}
});
app.get("/api/works/:slug/line/:lineNumber/annotations", async (req: Request, res: Response) => {
try {
const work = await storage.getWorkBySlug(req.params.slug);
if (!work) {
return res.status(404).json({ message: "Work not found" });
}
const lineNumber = Number(req.params.lineNumber);
const translationId = req.query.translationId ? Number(req.query.translationId) : undefined;
const annotations = await storage.getAnnotationsByLine(
work.id,
lineNumber,
translationId
);
// Enrich annotations with user information
const enrichedAnnotations = await Promise.all(annotations.map(async (annotation) => {
const user = await storage.getUser(annotation.userId);
if (!user) return annotation;
const { password, ...safeUser } = user;
return { ...annotation, user: safeUser };
}));
res.json(enrichedAnnotations);
} catch (error) {
console.error("Error fetching line annotations:", error);
res.status(500).json({ message: "Failed to fetch line annotations" });
}
});
app.post("/api/annotations", async (req: Request, res: Response) => {
try {
// Validate request body using zod
const annotationData = z.object({
workId: z.number(),
translationId: z.number().nullable().optional(),
lineNumber: z.number().nullable().optional(),
content: z.string(),
type: z.string(),
userId: z.number(),
isOfficial: z.boolean()
}).parse(req.body);
const annotation = await storage.createAnnotation(annotationData);
// Get user details
const user = await storage.getUser(annotation.userId);
if (user) {
const { password, ...safeUser } = user;
res.status(201).json({ ...annotation, user: safeUser });
} else {
res.status(201).json(annotation);
}
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({ message: error.errors });
}
console.error("Error creating annotation:", error);
res.status(500).json({ message: "Failed to create annotation" });
}
});
const httpServer = createServer(app); const httpServer = createServer(app);
return httpServer; return httpServer;
} }