From bcf85917194ef9eb168b8f87a9ea45c511ec9c4a Mon Sep 17 00:00:00 2001 From: Tomas Mirchev Date: Mon, 30 Jun 2025 17:55:41 +0000 Subject: [PATCH] update --- reader/src/ResourcePage.jsx | 1 - resource-provider/server.js | 109 ++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/reader/src/ResourcePage.jsx b/reader/src/ResourcePage.jsx index b223aef..4b3407f 100644 --- a/reader/src/ResourcePage.jsx +++ b/reader/src/ResourcePage.jsx @@ -143,7 +143,6 @@ const ResourcePage = ({ topics }) => { const htmlContent = useMemo(() => { let fileContent = content || "**No Data!**"; fileContent = marked.parse(fileContent); - console.log({ content, fileContent }); fileContent = ` diff --git a/resource-provider/server.js b/resource-provider/server.js index f740f05..5ddd556 100644 --- a/resource-provider/server.js +++ b/resource-provider/server.js @@ -161,6 +161,115 @@ app.post( }), ); +app.post( + "/resources/duplicate", + verifyToken, + asyncHandler(async (req, res) => { + try { + const { sourceResourceSeq, targetResourceSeq } = req.body; + + if (!sourceResourceSeq || !targetResourceSeq) { + res + .status(400) + .json({ message: "Missing sourceResourceSeq or targetResourceSeq" }); + return; + } + + if ( + typeof sourceResourceSeq !== "number" || + typeof targetResourceSeq !== "number" + ) { + res + .status(400) + .json({ message: "Invalid body - sequences must be numbers" }); + return; + } + + if (sourceResourceSeq === targetResourceSeq) { + res + .status(400) + .json({ + message: "Source and target resource sequences cannot be the same", + }); + return; + } + + const sourceResourceIdx = sourceResourceSeq - 1; + const targetResourceIdx = targetResourceSeq - 1; + + const topics = await getStructure(); + + // Validate resource sequences exist (check against first topic to get max resources) + if ( + sourceResourceIdx < 0 || + targetResourceIdx < 0 || + sourceResourceIdx >= topics[0].resources.length || + targetResourceIdx >= topics[0].resources.length + ) { + res + .status(400) + .json({ message: "Invalid resource sequence - out of bounds" }); + return; + } + + let duplicatedCount = 0; + let skippedCount = 0; + const timestamp = Date.now(); + + // Process all topics with Promise.all to handle async operations properly + await Promise.all( + topics.map(async (topic) => { + const sourceResource = topic.resources[sourceResourceIdx]; + const targetResource = topic.resources[targetResourceIdx]; + + // Skip if source resource has no content + if (!sourceResource || !sourceResource.filename) { + skippedCount++; + return; + } + + try { + // Read content from source file + const sourceFilePath = path.join( + STATIC_DIR, + sourceResource.filename, + ); + const content = await fs.readFile(sourceFilePath, "utf8"); + + // Create new filename for target resource + const newFilename = `F_${targetResource.id}_${timestamp}.md`; + const targetFilePath = path.join(STATIC_DIR, newFilename); + + // Write content to new file + await fs.writeFile(targetFilePath, content, "utf8"); + + // Update target resource filename + targetResource.filename = newFilename; + duplicatedCount++; + } catch (fileError) { + console.error( + `Failed to duplicate resource for topic ${topic.id}:`, + fileError, + ); + skippedCount++; + } + }), + ); + + res.json({ + success: true, + duplicatedCount, + skippedCount, + message: `Successfully duplicated ${duplicatedCount} resources from sequence ${sourceResourceSeq} to ${targetResourceSeq}. Skipped ${skippedCount} resources.`, + structure: topics, + }); + } catch (error) { + console.error("Duplicate resources error:", error); + res.status(500).json({ error: "Failed to duplicate resources" }); + } + }), +); + app.use(errorRequestHandler); const PORT = process.env.PORT || 3000;