bsc

Comprehensive codebase and cou...
Log | Files | Refs | README | LICENSE

commit 1ab1964b3bb3c662845a51688bb3328bdd7283e6
parent 021e1becf4aefc07198b8aae777493acb11fa75a
Author: Amit Dutta <amitdutta4255@gmail.com>
Date:   Wed,  3 Sep 2025 20:51:28 +0530

Add files via upload
Diffstat:
Amain.js | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.json | 14++++++++++++++
Aserver.js | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 248 insertions(+), 0 deletions(-)

diff --git a/main.js b/main.js @@ -0,0 +1,166 @@ +const projectCardsContainer = document.getElementById('project-cards'); +const codeModal = document.getElementById('code-modal'); +const closeModalBtn = document.getElementById('close-modal'); +const modalTitle = document.getElementById('modal-title'); +const codeBlock = document.getElementById('code-block'); +const codeContent = document.getElementById('code-content'); +const snapshotImage = document.getElementById('snapshot-image'); +const githubLink = document.getElementById('github-link'); +const loadingMessage = document.getElementById('loading-message'); + +// Point the API request to your new backend server +// IMPORTANT: Replace this with your Render deployment URL after deployment. +const API_URL = 'http://localhost:3000/api/programs'; +const REPO_OWNER = 'notamitgamer'; +const REPO_NAME = 'bsc'; +const GITHUB_RAW_URL = `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/main`; + +// Function to sanitize a filename for display +function sanitizeFilename(filename) { + return filename.replace(/\.c$/, '').replace(/\.(png|jpe?g|gif)$/i, '').replace(/[-_]/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); +} + +// Fetch and display code in the modal +async function fetchAndDisplayCode(filePath, fileName) { + try { + const response = await fetch(`${GITHUB_RAW_URL}/${filePath}`); + if (!response.ok) { + throw new Error(`GitHub raw content API responded with status ${response.status}`); + } + const code = await response.text(); + modalTitle.textContent = sanitizeFilename(fileName); + codeContent.textContent = code; + githubLink.href = `https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/${filePath}`; + + // Toggle display + codeBlock.classList.remove('hidden'); + snapshotImage.classList.add('hidden'); + githubLink.classList.remove('hidden'); + codeModal.style.display = 'flex'; + } catch (error) { + console.error("Failed to fetch code:", error); + codeContent.textContent = "Error loading code. Please try again later."; + githubLink.classList.add('hidden'); + } +} + +// Fetch and display snapshot in the modal +async function fetchAndDisplaySnapshot(filePath, fileName) { + try { + const response = await fetch(`${GITHUB_RAW_URL}/${filePath}`); + if (!response.ok) { + throw new Error(`GitHub raw content API responded with status ${response.status}`); + } + const imageUrl = await response.url; + modalTitle.textContent = sanitizeFilename(fileName); + snapshotImage.src = imageUrl; + githubLink.href = `https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/${filePath}`; + + // Toggle display + codeBlock.classList.add('hidden'); + snapshotImage.classList.remove('hidden'); + githubLink.classList.remove('hidden'); + codeModal.style.display = 'flex'; + } catch (error) { + console.error("Failed to fetch snapshot:", error); + snapshotImage.src = ''; + snapshotImage.alt = 'Error loading image.'; + githubLink.classList.add('hidden'); + } +} + +// Fetch C programs and render project cards from the backend +async function fetchPrograms() { + loadingMessage.style.display = 'block'; + projectCardsContainer.innerHTML = ''; + try { + const response = await fetch(API_URL); + if (!response.ok) { + throw new Error('Failed to fetch from backend server.'); + } + const data = await response.json(); + + const cFiles = data.cFiles; + const snapshotMap = new Map(data.snapshots.map(file => [file.name, file.path])); + const codeAssetsMap = new Map(data.codeAssets.map(asset => [asset.name, asset.url])); + const exeAssetsMap = new Map(data.exeAssets.map(asset => [asset.name, asset.url])); + + loadingMessage.style.display = 'none'; + + if (cFiles.length === 0) { + projectCardsContainer.innerHTML = '<p class="col-span-full text-center text-slate-500">No programs found.</p>'; + return; + } + + cFiles.forEach(file => { + const card = document.createElement('div'); + card.className = 'bg-white rounded-lg p-6 shadow-lg flex flex-col justify-between transition-transform duration-300 hover:scale-105'; + + const exeFileName = file.name.replace('.c', '.exe'); + const codeDownloadUrl = codeAssetsMap.get(file.name); + const exeDownloadUrl = exeAssetsMap.get(exeFileName); + const snapshotPath = snapshotMap.get(file.name.replace('.c', '.png') || file.name.replace('.c', '.jpg') || file.name.replace('.c', '.jpeg')); + + card.innerHTML = ` + <div> + <h3 class="text-xl font-bold text-cyan-600 mb-2">${sanitizeFilename(file.name)}</h3> + <p class="text-sm text-slate-700 mb-4">A practice program from the syllabus.</p> + </div> + <div class="flex flex-col sm:flex-row gap-2 mt-auto"> + <button class="view-code-btn flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md transition-colors shadow-md" data-path="${file.path}" data-name="${file.name}"> + View Code + </button> + ${snapshotPath ? ` + <button class="view-snapshot-btn flex-1 px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white font-medium rounded-md transition-colors shadow-md" data-path="${snapshotPath}" data-name="${file.name}"> + View Snapshot + </button>` : ''} + ${codeDownloadUrl ? ` + <a href="${codeDownloadUrl}" class="flex-1 px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white text-center font-medium rounded-md transition-colors shadow-md" download> + Download Code + </a>` : ''} + ${exeDownloadUrl ? ` + <a href="${exeDownloadUrl}" class="flex-1 px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-center font-medium rounded-md transition-colors shadow-md" download> + Download EXE + </a>` : ''} + </div> + `; + projectCardsContainer.appendChild(card); + }); + + // Attach click listeners to the "View Code" and "View Snapshot" buttons + document.querySelectorAll('.view-code-btn').forEach(button => { + button.addEventListener('click', (e) => { + const filePath = e.currentTarget.getAttribute('data-path'); + const fileName = e.currentTarget.getAttribute('data-name'); + fetchAndDisplayCode(filePath, fileName); + }); + }); + + document.querySelectorAll('.view-snapshot-btn').forEach(button => { + button.addEventListener('click', (e) => { + const filePath = e.currentTarget.getAttribute('data-path'); + const fileName = e.currentTarget.getAttribute('data-name'); + fetchAndDisplaySnapshot(filePath, fileName); + }); + }); + + } catch (error) { + console.error("Error fetching programs:", error); + loadingMessage.textContent = 'Failed to load programs. Please check the repository and your backend server.'; + } +} + +// Event listener for closing the modal +closeModalBtn.addEventListener('click', () => { + codeModal.style.display = 'none'; +}); + +// Close modal when clicking outside of it +window.addEventListener('click', (event) => { + if (event.target === codeModal) { + codeModal.style.display = 'none'; + } +}); + +// Initial calls to fetch data on page load +fetchPrograms(); diff --git a/package.json b/package.json @@ -0,0 +1,13 @@ +{ +"name": "bsc-portfolio-backend", +"version": "1.0.0", +"description": "Backend for fetching GitHub data to avoid rate limits.", +"main": "server.js", +"scripts": { +"start": "node server.js" +}, +"dependencies": { +"express": "^4.19.2", +"cors": "^2.8.5" +} +}+ \ No newline at end of file diff --git a/server.js b/server.js @@ -0,0 +1,68 @@ +const express = require('express'); +const cors = require('cors'); + +const app = express(); +const port = process.env.PORT || 3000; + +// IMPORTANT: This token is placed here for demonstration. +// For production, you should use environment variables. +Github_API = os.getenv("github") +const GITHUB_TOKEN = 'github'; +const REPO_OWNER = 'notamitgamer'; +const REPO_NAME = 'bsc'; +const GITHUB_API_URL = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}`; + +app.use(cors()); + +// A helper function to fetch data from GitHub with authentication +async function fetchGitHub(url) { + const response = await fetch(url, { + headers: { + 'Authorization': `token ${GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github.v3+json' + } + }); + + if (response.status === 403) { + console.warn('GitHub API rate limit exceeded.'); + return { ok: false, status: 403 }; + } + return response; +} + +// Main API endpoint to fetch all program data +app.get('/api/programs', async (req, res) => { + try { + const [ + cFolderResult, + snapshotFolderResult, + codeAssetsResult, + exeAssetsResult + ] = await Promise.allSettled([ + fetchGitHub(`${GITHUB_API_URL}/contents/c`), + fetchGitHub(`${GITHUB_API_URL}/contents/c/snapshot`), + fetchGitHub(`${GITHUB_API_URL}/releases/tags/bsc-c-code`), + fetchGitHub(`${GITHUB_API_URL}/releases/tags/bsc-c-exe`) + ]); + + const allCFolderFiles = cFolderResult.status === 'fulfilled' && cFolderResult.value.ok ? await cFolderResult.value.json() : []; + const snapshotFiles = snapshotFolderResult.status === 'fulfilled' && snapshotFolderResult.value.ok ? await snapshotFolderResult.value.json() : []; + const codeAssets = codeAssetsResult.status === 'fulfilled' && codeAssetsResult.value.ok ? await codeAssetsResult.value.json() : { assets: [] }; + const exeAssets = exeAssetsResult.status === 'fulfilled' && exeAssetsResult.value.ok ? await exeAssetsResult.value.json() : { assets: [] }; + + res.json({ + cFiles: allCFolderFiles.filter(f => f.name.endsWith('.c')), + snapshots: snapshotFiles.filter(f => f.type === 'file' && f.name.match(/\.(png|jpe?g|gif)$/i)), + codeAssets: codeAssets.assets.map(asset => ({ name: asset.name, url: asset.browser_download_url })), + exeAssets: exeAssets.assets.map(asset => ({ name: asset.name, url: asset.browser_download_url })) + }); + + } catch (error) { + console.error('Error in API endpoint:', error); + res.status(500).json({ error: 'Failed to fetch data from GitHub.', details: error.message }); + } +}); + +app.listen(port, () => { + console.log(`Server listening at http://localhost:${port}`); +});
© notamitgamer • Site Built: 2026-07-21 13:58:23 UTC • git-mirror commit: 1037f62 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror