forked from UKSOURCE/cms.hailearning.edu.vn
feat: Add blog category, blog, and tag controllers with CRUD operations
This commit is contained in:
239
controllers/blogTagController.js
Normal file
239
controllers/blogTagController.js
Normal file
@@ -0,0 +1,239 @@
|
||||
const BlogTag = require('../models/blogTag');
|
||||
|
||||
// -------------------- Admin Controllers --------------------
|
||||
|
||||
// Display tag management page
|
||||
exports.index = async (req, res) => {
|
||||
try {
|
||||
const tags = await BlogTag.find()
|
||||
.sort({ name: 1 })
|
||||
.lean();
|
||||
|
||||
res.render('admin/blog/tags/index', {
|
||||
layout: 'layouts/main',
|
||||
title: 'Blog Tags',
|
||||
tags,
|
||||
currentPath: req.path,
|
||||
user: req.session.user
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Tag index error:', err);
|
||||
req.flash('error_msg', 'Error loading tags');
|
||||
res.redirect('/admin/dashboard');
|
||||
}
|
||||
};
|
||||
|
||||
// Show create tag form
|
||||
exports.create = async (req, res) => {
|
||||
try {
|
||||
res.render('admin/blog/tags/create', {
|
||||
layout: 'layouts/main',
|
||||
title: 'Create New Tag',
|
||||
currentPath: req.path,
|
||||
user: req.session.user
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Tag create form error:', err);
|
||||
req.flash('error_msg', 'Error loading create form');
|
||||
res.redirect('/admin/blog/tags');
|
||||
}
|
||||
};
|
||||
|
||||
// Store new tag
|
||||
exports.store = async (req, res) => {
|
||||
try {
|
||||
const {
|
||||
name,
|
||||
isActive
|
||||
} = req.body;
|
||||
|
||||
// Generate slug
|
||||
const slug = name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '')
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.trim('-');
|
||||
|
||||
// Check if slug exists
|
||||
const existingTag = await BlogTag.findOne({ slug });
|
||||
if (existingTag) {
|
||||
req.flash('error_msg', 'A tag with this name already exists');
|
||||
return res.redirect('/admin/blog/tags/create');
|
||||
}
|
||||
|
||||
// Create tag data
|
||||
const tagData = {
|
||||
name,
|
||||
slug,
|
||||
isActive: isActive === 'on'
|
||||
};
|
||||
|
||||
// Create tag
|
||||
const tag = new BlogTag(tagData);
|
||||
await tag.save();
|
||||
|
||||
req.flash('success_msg', 'Tag created successfully');
|
||||
res.redirect('/admin/blog/tags');
|
||||
} catch (err) {
|
||||
console.error('Tag store error:', err);
|
||||
req.flash('error_msg', 'Error creating tag');
|
||||
res.redirect('/admin/blog/tags/create');
|
||||
}
|
||||
};
|
||||
|
||||
// Show edit tag form
|
||||
exports.edit = async (req, res) => {
|
||||
try {
|
||||
const tag = await BlogTag.findById(req.params.id);
|
||||
|
||||
if (!tag) {
|
||||
req.flash('error_msg', 'Tag not found');
|
||||
return res.redirect('/admin/blog/tags');
|
||||
}
|
||||
|
||||
res.render('admin/blog/tags/edit', {
|
||||
layout: 'layouts/main',
|
||||
title: 'Edit Tag',
|
||||
tag,
|
||||
currentPath: req.path,
|
||||
user: req.session.user
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Tag edit form error:', err);
|
||||
req.flash('error_msg', 'Error loading tag');
|
||||
res.redirect('/admin/blog/tags');
|
||||
}
|
||||
};
|
||||
|
||||
// Update tag
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const tag = await BlogTag.findById(req.params.id);
|
||||
|
||||
if (!tag) {
|
||||
req.flash('error_msg', 'Tag not found');
|
||||
return res.redirect('/admin/blog/tags');
|
||||
}
|
||||
|
||||
const {
|
||||
name,
|
||||
isActive
|
||||
} = req.body;
|
||||
|
||||
// Update tag data
|
||||
tag.name = name;
|
||||
tag.isActive = isActive === 'on';
|
||||
|
||||
// Generate new slug if name changed
|
||||
const newSlug = name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '')
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.trim('-');
|
||||
|
||||
if (newSlug !== tag.slug) {
|
||||
const existingTag = await BlogTag.findOne({
|
||||
slug: newSlug,
|
||||
_id: { $ne: tag._id }
|
||||
});
|
||||
if (existingTag) {
|
||||
req.flash('error_msg', 'A tag with this name already exists');
|
||||
return res.redirect(`/admin/blog/tags/${tag._id}/edit`);
|
||||
}
|
||||
tag.slug = newSlug;
|
||||
}
|
||||
|
||||
await tag.save();
|
||||
|
||||
req.flash('success_msg', 'Tag updated successfully');
|
||||
res.redirect('/admin/blog/tags');
|
||||
} catch (err) {
|
||||
console.error('Tag update error:', err);
|
||||
req.flash('error_msg', 'Error updating tag');
|
||||
res.redirect(`/admin/blog/tags/${req.params.id}/edit`);
|
||||
}
|
||||
};
|
||||
|
||||
// Delete tag
|
||||
exports.destroy = async (req, res) => {
|
||||
try {
|
||||
const tag = await BlogTag.findById(req.params.id);
|
||||
|
||||
if (!tag) {
|
||||
req.flash('error_msg', 'Tag not found');
|
||||
return res.redirect('/admin/blog/tags');
|
||||
}
|
||||
|
||||
// Check if tag has posts
|
||||
const Blog = require('../models/blog');
|
||||
const postCount = await Blog.countDocuments({ tags: { $in: [tag.name] } });
|
||||
|
||||
if (postCount > 0) {
|
||||
req.flash('error_msg', 'Cannot delete tag that is used in blog posts');
|
||||
return res.redirect('/admin/blog/tags');
|
||||
}
|
||||
|
||||
await BlogTag.findByIdAndDelete(req.params.id);
|
||||
|
||||
req.flash('success_msg', 'Tag deleted successfully');
|
||||
res.redirect('/admin/blog/tags');
|
||||
} catch (err) {
|
||||
console.error('Tag delete error:', err);
|
||||
req.flash('error_msg', 'Error deleting tag');
|
||||
res.redirect('/admin/blog/tags');
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------- Public API Controllers --------------------
|
||||
|
||||
// Get all active tags
|
||||
exports.api = async (req, res) => {
|
||||
try {
|
||||
const tags = await BlogTag.getActive();
|
||||
|
||||
// Update post counts
|
||||
for (const tag of tags) {
|
||||
await tag.updatePostCount();
|
||||
}
|
||||
|
||||
res.json(tags);
|
||||
} catch (err) {
|
||||
console.error('Tags API error:', err);
|
||||
res.status(500).json({ error: 'Error loading tags' });
|
||||
}
|
||||
};
|
||||
|
||||
// Get popular tags
|
||||
exports.apiPopular = async (req, res) => {
|
||||
try {
|
||||
const limit = parseInt(req.query.limit) || 10;
|
||||
const tags = await BlogTag.getPopular(limit);
|
||||
res.json(tags);
|
||||
} catch (err) {
|
||||
console.error('Popular tags API error:', err);
|
||||
res.status(500).json({ error: 'Error loading popular tags' });
|
||||
}
|
||||
};
|
||||
|
||||
// Get tag by slug
|
||||
exports.apiShow = async (req, res) => {
|
||||
try {
|
||||
const tag = await BlogTag.findOne({
|
||||
slug: req.params.slug,
|
||||
isActive: true
|
||||
}).lean();
|
||||
|
||||
if (!tag) {
|
||||
return res.status(404).json({ error: 'Tag not found' });
|
||||
}
|
||||
|
||||
res.json(tag);
|
||||
} catch (err) {
|
||||
console.error('Tag show API error:', err);
|
||||
res.status(500).json({ error: 'Error loading tag' });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = exports;
|
||||
Reference in New Issue
Block a user