From 44d75e36b32de1e41657b9077960ced1e6938814 Mon Sep 17 00:00:00 2001 From: srikanth01234 Date: Fri, 14 Aug 2026 11:22:07 +0530 Subject: [PATCH] blog dynamic --- server.js | 312 +++++++++++++++++++++++++++++++++++++++++++++++++--- setup-db.js | 58 ++++++++++ 2 files changed, 353 insertions(+), 17 deletions(-) diff --git a/server.js b/server.js index 425fea5..1a3dfcc 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,4 @@ +// Trigger restart 2 const express = require('express'); const mysql = require('mysql2/promise'); const multer = require('multer'); @@ -71,14 +72,9 @@ const pool = mysql.createPool({ waitForConnections: true, connectionLimit: 10, queueLimit: 0, - acquireTimeout: 60000, - timeout: 60000, enableKeepAlive: true, - keepAliveInitialDelay: 0, - reconnect: true, - idleTimeout: 300000, // 5 minutes - maxIdle: 10, - maxReuse: 1000, + keepAliveInitialDelay: 10000, + idleTimeout: 60000, // Close idle connections after 60s to prevent reuse of dead connections charset: 'utf8mb4' }); @@ -271,6 +267,70 @@ async function ensureUpcomingEventsTable() { } } +async function ensureBlogsTable() { + try { + await pool.execute(` + CREATE TABLE IF NOT EXISTS blogs ( + id INT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255) NOT NULL, + slug VARCHAR(255) UNIQUE NOT NULL, + image TEXT, + description TEXT, + author VARCHAR(255) DEFAULT 'Admin', + profile VARCHAR(255) DEFAULT '/assets/images/profile-1.jpeg', + date VARCHAR(100), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + `); + console.log('✅ Verified blogs table'); + + // Seed initial blogs if empty + const [blogRows] = await pool.execute('SELECT id FROM blogs LIMIT 1'); + if (blogRows.length === 0) { + const initialBlogs = [ + { + title: 'Save soil, save world Projects in 2020', + slug: 'save-soil-save-world', + image: '/assets/img/all-images/blog/blog-img4.png', + description: '

At Eventify 2024, you\'ll join an exclusive gathering of business leaders and innovators shaping the future of their industries. This one-day conference offers dynamic sessions on leadership, technology, and strategy to help you stay ahead in today\'s competitive market. Whether you\'re looking to unlock new opportunities or build lasting eventify partnerships, Eventify is where you need to be.

', + author: 'Beverly', + profile: '/assets/images/profile-1.jpeg', + date: '26 Jan 2025' + }, + { + title: 'Civil Litigation paper’s Of Conference', + slug: 'civil-litigation-papers', + image: '/assets/img/all-images/blog/blog-img5.png', + description: '

Fuel your business growth with actionable insights from world-class experts at Eventify 2024. This premier event brings together forward-thinking professionals to explore the latest trends, technologies, and strategies for success. From keynote speeches to interactive workshops, Eventify provides you with the tools you need.

', + author: 'Gisselle', + profile: '/assets/images/profile-2.jpeg', + date: '26 Jan 2025' + }, + { + title: 'Greetings and Opening Event of health', + slug: 'greetings-and-opening-event', + image: '/assets/img/all-images/blog/blog-img6.png', + description: '

Join us at Eventify 2024, where innovation meets opportunity. This conference is the ultimate destination for business leaders seeking to push the boundaries of what\'s possible. With sessions on disruptive technologies, leadership trends, and market strategies, you\'ll walk away with the knowledge and connections to lead.

', + author: 'Mertie', + profile: '/assets/images/profile-3.jpeg', + date: '26 Jan 2025' + } + ]; + + for (const blog of initialBlogs) { + await pool.execute( + 'INSERT IGNORE INTO blogs (title, slug, image, description, author, profile, date) VALUES (?, ?, ?, ?, ?, ?, ?)', + [blog.title, blog.slug, blog.image, blog.description, blog.author, blog.profile, blog.date] + ); + } + console.log('✅ Seeded initial blogs successfully.'); + } + } catch (error) { + console.error('❌ Failed to ensure blogs table:', error.message); + throw error; + } +} + // Test database connection on startup async function testDatabaseConnection() { try { @@ -281,22 +341,14 @@ async function testDatabaseConnection() { await ensureAdminUsersTable(); await ensureEventImagesSortOrderColumn(); await ensureUpcomingEventsTable(); + await ensureBlogsTable(); } catch (error) { console.error('❌ Database connection failed:', error.message); process.exit(1); } } -// Keep connections alive with periodic ping -setInterval(async () => { - try { - const connection = await pool.getConnection(); - await connection.execute('SELECT 1'); - connection.release(); - } catch (error) { - console.error('Keep-alive ping failed:', error.message); - } -}, 240000); // Every 4 minutes +// (Removed custom keep-alive ping) // Multer configuration for file uploads const storage = multer.diskStorage({ @@ -910,6 +962,232 @@ app.delete('/api/upcoming-events/:id', async (req, res) => { } }); +// =============================== +// BLOGS CRUD ROUTES +// =============================== + +// GET all blogs +app.get('/api/blogs', async (req, res) => { + try { + const [rows] = await pool.execute('SELECT * FROM blogs ORDER BY id DESC'); + res.json({ + success: true, + data: rows + }); + } catch (error) { + console.error('Error fetching blogs:', error); + res.status(500).json({ + success: false, + message: 'Error fetching blogs', + error: error.message + }); + } +}); + +// GET single blog by ID +app.get('/api/blogs/:id', async (req, res) => { + try { + const [rows] = await pool.execute('SELECT * FROM blogs WHERE id = ?', [req.params.id]); + if (rows.length === 0) { + return res.status(404).json({ + success: false, + message: 'Blog not found' + }); + } + res.json({ + success: true, + data: rows[0] + }); + } catch (error) { + console.error('Error fetching blog:', error); + res.status(500).json({ + success: false, + message: 'Error fetching blog', + error: error.message + }); + } +}); + +// GET single blog by slug +app.get('/api/blogs/slug/:slug', async (req, res) => { + try { + const rawSlug = req.params.slug ? req.params.slug.trim() : ''; + const cleanedSlug = slugify(rawSlug); + + let [rows] = await pool.execute( + 'SELECT * FROM blogs WHERE slug = ? OR id = ?', + [rawSlug, rawSlug] + ); + + if (rows.length === 0 && cleanedSlug) { + [rows] = await pool.execute( + 'SELECT * FROM blogs WHERE slug = ? OR LOWER(REPLACE(title, " ", "-")) = ?', + [cleanedSlug, cleanedSlug] + ); + } + + if (rows.length === 0) { + return res.status(404).json({ + success: false, + message: 'Blog not found' + }); + } + res.json({ + success: true, + data: rows[0] + }); + } catch (error) { + console.error('Error fetching blog by slug:', error); + res.status(500).json({ + success: false, + message: 'Error fetching blog', + error: error.message + }); + } +}); + +// POST create new blog +app.post('/api/blogs', async (req, res) => { + try { + const { title, slug, image, description, author, profile, date } = req.body; + + if (!title || String(title).trim() === '') { + return res.status(400).json({ + success: false, + message: 'Blog title is required' + }); + } + + const finalTitle = String(title).trim(); + const generatedSlug = slugify(finalTitle); + const finalSlug = (slug && String(slug).trim()) ? slugify(String(slug).trim()) : generatedSlug; + const finalImage = image || ''; + const finalDesc = description || ''; + const finalAuthor = author || 'Admin'; + const finalProfile = profile || '/assets/images/profile-1.jpeg'; + + // Format current date as "DD MMM YYYY" or similar if no date passed + let finalDate = date; + if (!finalDate) { + const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const now = new Date(); + finalDate = `${now.getDate()} ${months[now.getMonth()]} ${now.getFullYear()}`; + } + + const [result] = await pool.execute( + 'INSERT INTO blogs (title, slug, image, description, author, profile, date) VALUES (?, ?, ?, ?, ?, ?, ?)', + [finalTitle, finalSlug, finalImage, finalDesc, finalAuthor, finalProfile, finalDate] + ); + + res.status(201).json({ + success: true, + message: 'Blog created successfully', + data: { id: result.insertId, slug: finalSlug } + }); + } catch (error) { + console.error('Error creating blog:', error); + if (error && error.code === 'ER_DUP_ENTRY') { + return res.status(409).json({ + success: false, + message: 'A blog with this title or slug already exists' + }); + } + res.status(500).json({ + success: false, + message: 'Error creating blog', + error: error.message + }); + } +}); + +// PUT update blog +app.put('/api/blogs/:id', async (req, res) => { + try { + const blogId = req.params.id; + + // Fetch existing record + const [rows] = await pool.execute('SELECT * FROM blogs WHERE id = ?', [blogId]); + if (rows.length === 0) { + return res.status(404).json({ + success: false, + message: 'Blog not found' + }); + } + + const existing = rows[0]; + const { title, slug, image, description, author, profile, date } = req.body || {}; + + const inputTitle = title || existing.title; + if (!inputTitle || String(inputTitle).trim() === '') { + return res.status(400).json({ + success: false, + message: 'Blog title is required' + }); + } + + const finalTitle = String(inputTitle).trim(); + const generatedSlug = slugify(finalTitle); + + let finalSlug = generatedSlug; + if (slug && String(slug).trim()) { + const userSlug = slugify(String(slug).trim()); + const oldTitleSlug = slugify(existing.title || ''); + if (userSlug !== oldTitleSlug) { + finalSlug = userSlug; + } + } + + const finalImage = image !== undefined ? image : existing.image; + const finalDesc = description !== undefined ? description : existing.description; + const finalAuthor = author !== undefined ? author : existing.author; + const finalProfile = profile !== undefined ? profile : existing.profile; + const finalDate = date !== undefined ? date : existing.date; + + await pool.execute( + 'UPDATE blogs SET title = ?, slug = ?, image = ?, description = ?, author = ?, profile = ?, date = ? WHERE id = ?', + [finalTitle, finalSlug, finalImage, finalDesc, finalAuthor, finalProfile, finalDate, blogId] + ); + + res.json({ + success: true, + message: 'Blog updated successfully' + }); + } catch (error) { + console.error('Error updating blog:', error); + res.status(500).json({ + success: false, + message: 'Error updating blog', + error: error.message + }); + } +}); + +// DELETE blog +app.delete('/api/blogs/:id', async (req, res) => { + try { + const [result] = await pool.execute('DELETE FROM blogs WHERE id = ?', [req.params.id]); + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: 'Blog not found' + }); + } + + res.json({ + success: true, + message: 'Blog deleted successfully' + }); + } catch (error) { + console.error('Error deleting blog:', error); + res.status(500).json({ + success: false, + message: 'Error deleting blog', + error: error.message + }); + } +}); + // =============================== // EVENT_IMAGES CRUD ROUTES // =============================== diff --git a/setup-db.js b/setup-db.js index b924d23..10d6718 100644 --- a/setup-db.js +++ b/setup-db.js @@ -72,6 +72,64 @@ async function setup() { `); console.log('Verified upcoming_events table exists.'); + // Create blogs table + await pool.execute(` + CREATE TABLE IF NOT EXISTS blogs ( + id INT AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(255) NOT NULL, + slug VARCHAR(255) UNIQUE NOT NULL, + image TEXT, + description TEXT, + author VARCHAR(255) DEFAULT 'Admin', + profile VARCHAR(255) DEFAULT '/assets/images/profile-1.jpeg', + date VARCHAR(100), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + `); + console.log('Verified blogs table exists.'); + + // Seed initial blogs if table is empty + const [blogRows] = await pool.execute('SELECT id FROM blogs LIMIT 1'); + if (blogRows.length === 0) { + const initialBlogs = [ + { + title: 'Save soil, save world Projects in 2020', + slug: 'save-soil-save-world', + image: '/assets/img/all-images/blog/blog-img4.png', + description: '

At Eventify 2024, you\'ll join an exclusive gathering of business leaders and innovators shaping the future of their industries. This one-day conference offers dynamic sessions on leadership, technology, and strategy to help you stay ahead in today\'s competitive market. Whether you\'re looking to unlock new opportunities or build lasting eventify partnerships, Eventify is where you need to be.

', + author: 'Beverly', + profile: '/assets/images/profile-1.jpeg', + date: '26 Jan 2025' + }, + { + title: 'Civil Litigation paper’s Of Conference', + slug: 'civil-litigation-papers', + image: '/assets/img/all-images/blog/blog-img5.png', + description: '

Fuel your business growth with actionable insights from world-class experts at Eventify 2024. This premier event brings together forward-thinking professionals to explore the latest trends, technologies, and strategies for success. From keynote speeches to interactive workshops, Eventify provides you with the tools you need.

', + author: 'Gisselle', + profile: '/assets/images/profile-2.jpeg', + date: '26 Jan 2025' + }, + { + title: 'Greetings and Opening Event of health', + slug: 'greetings-and-opening-event', + image: '/assets/img/all-images/blog/blog-img6.png', + description: '

Join us at Eventify 2024, where innovation meets opportunity. This conference is the ultimate destination for business leaders seeking to push the boundaries of what\'s possible. With sessions on disruptive technologies, leadership trends, and market strategies, you\'ll walk away with the knowledge and connections to lead.

', + author: 'Mertie', + profile: '/assets/images/profile-3.jpeg', + date: '26 Jan 2025' + } + ]; + + for (const blog of initialBlogs) { + await pool.execute( + 'INSERT IGNORE INTO blogs (title, slug, image, description, author, profile, date) VALUES (?, ?, ?, ?, ?, ?, ?)', + [blog.title, blog.slug, blog.image, blog.description, blog.author, blog.profile, blog.date] + ); + } + console.log('Seeded initial blogs successfully.'); + } + // Check if admin user exists const [rows] = await pool.execute('SELECT * FROM admin_users WHERE email = ?', ['admin@example.com']);