forked from UKSOURCE/cms.hailearning.edu.vn
first commit
This commit is contained in:
347
controllers/headerController.js
Normal file
347
controllers/headerController.js
Normal file
@@ -0,0 +1,347 @@
|
||||
const { addBaseUrlToImages } = require('../utils/imageHelper');
|
||||
const Header = require('../models/header');
|
||||
const Menu = require('../models/menuHeader');
|
||||
|
||||
// Helper function để thêm title và url cho programmes
|
||||
const addProgrammeDetails = (programmes, menuUrl) => {
|
||||
return programmes.map(prog => ({
|
||||
...prog,
|
||||
title: prog.name,
|
||||
url: `${menuUrl}${prog.code}/`
|
||||
}));
|
||||
};
|
||||
|
||||
// Helper function để xử lý menu tree cho API (đơn giản hóa, map menuid thành id)
|
||||
const processMenuTreeForAPI = (menuTree) => {
|
||||
return menuTree.map(item => {
|
||||
const processedItem = {
|
||||
id: item.menuid, // Map menuid to id for frontend
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
order: item.order,
|
||||
parent: item.parent || null,
|
||||
type: item.type,
|
||||
children: []
|
||||
};
|
||||
|
||||
// Đệ quy cho children
|
||||
if (item.children && item.children.length > 0) {
|
||||
processedItem.children = processMenuTreeForAPI(item.children);
|
||||
}
|
||||
|
||||
return processedItem;
|
||||
});
|
||||
};
|
||||
|
||||
// Helper function để xử lý menu tree và thêm programme details (cho admin)
|
||||
const processMenuTree = (menuTree) => {
|
||||
return menuTree.map(item => {
|
||||
const processedItem = { ...item };
|
||||
|
||||
// Nếu có programmes, thêm title và url
|
||||
if (item.programmes && item.programmes.length > 0) {
|
||||
processedItem.programmes = addProgrammeDetails(item.programmes, item.url);
|
||||
}
|
||||
|
||||
// Đệ quy cho children
|
||||
if (item.children && item.children.length > 0) {
|
||||
processedItem.children = processMenuTree(item.children);
|
||||
}
|
||||
|
||||
return processedItem;
|
||||
});
|
||||
};
|
||||
|
||||
// Get header data from MongoDB
|
||||
const getHeaderData = async () => {
|
||||
const header = await Header.findOne({ name: 'default' });
|
||||
|
||||
if (!header) {
|
||||
return {
|
||||
topbar: {
|
||||
contactInfo: {
|
||||
phone: '',
|
||||
email: ''
|
||||
},
|
||||
links: []
|
||||
},
|
||||
mainMenu: [],
|
||||
logo: ''
|
||||
};
|
||||
}
|
||||
|
||||
// Convert to plain object to allow modifications
|
||||
const headerData = header.toObject();
|
||||
|
||||
// Lấy menu tree từ collection menuHeader (đơn giản, không có programmes)
|
||||
try {
|
||||
const menuTree = await Menu.getMenuTree();
|
||||
// Xử lý menu tree để map menuid thành id cho frontend
|
||||
headerData.mainMenu = processMenuTreeForAPI(menuTree);
|
||||
} catch (error) {
|
||||
console.error('Error getting menu tree:', error);
|
||||
headerData.mainMenu = [];
|
||||
}
|
||||
|
||||
return headerData;
|
||||
};
|
||||
|
||||
// API to get header data
|
||||
exports.api = async (req, res) => {
|
||||
try {
|
||||
// Lấy header data
|
||||
const header = await getHeaderData();
|
||||
|
||||
// Xử lý URL cho logo và các hình ảnh khác
|
||||
const processedData = addBaseUrlToImages(header);
|
||||
|
||||
res.json(processedData);
|
||||
} catch (err) {
|
||||
console.error('API Error:', err);
|
||||
res.status(500).json({ error: 'Error loading header data' });
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy menu tree cho frontend (public API)
|
||||
exports.getMenuTreeAPI = async (req, res) => {
|
||||
try {
|
||||
const menuTree = await Menu.getMenuTree();
|
||||
// Xử lý menu tree để map menuid thành id cho frontend
|
||||
const processedMenuTree = processMenuTreeForAPI(menuTree);
|
||||
res.json(processedMenuTree);
|
||||
} catch (error) {
|
||||
console.error('Error getting menu tree:', error);
|
||||
res.status(500).json({ error: 'Error loading menu tree' });
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy menu tree (cho admin)
|
||||
exports.getMenuTree = async (req, res) => {
|
||||
try {
|
||||
const menuTree = await Menu.getMenuTree();
|
||||
res.json(menuTree);
|
||||
} catch (error) {
|
||||
console.error('Error getting menu tree:', error);
|
||||
res.status(500).json({ error: 'Error loading menu tree' });
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy programmes theo menu ID
|
||||
exports.getProgrammesByMenuId = async (req, res) => {
|
||||
try {
|
||||
const { menuId } = req.params;
|
||||
const programmes = await Header.getProgrammesByMenuId(menuId);
|
||||
|
||||
// Lấy menu item để có URL
|
||||
const menuItem = await Menu.findOne({ menuid: menuId });
|
||||
if (menuItem) {
|
||||
const programmesWithDetails = addProgrammeDetails(programmes, menuItem.url);
|
||||
res.json(programmesWithDetails);
|
||||
} else {
|
||||
res.json(programmes);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error getting programmes by menu ID:', error);
|
||||
res.status(500).json({ error: 'Error loading programmes' });
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy toàn bộ header data
|
||||
exports.getHeaderData = async (req, res) => {
|
||||
try {
|
||||
const headerData = await getHeaderData();
|
||||
res.json(headerData);
|
||||
} catch (error) {
|
||||
console.error('Error getting header data:', error);
|
||||
res.status(500).json({ error: 'Error loading header data' });
|
||||
}
|
||||
};
|
||||
|
||||
// API để lấy menu item theo ID
|
||||
exports.getMenuItem = async (req, res) => {
|
||||
try {
|
||||
const { menuId } = req.params;
|
||||
const Menu = require('../models/menuHeader');
|
||||
const menuItem = await Menu.findOne({ menuid: menuId });
|
||||
|
||||
if (!menuItem) {
|
||||
return res.status(404).json({ error: 'Menu item not found' });
|
||||
}
|
||||
|
||||
// Nếu là level type và có fetch = true, lấy programmes
|
||||
if (menuItem.type === 'level' && menuItem.fetch) {
|
||||
const programmes = await Menu.getProgrammesByMenuId(menuItem.menuid);
|
||||
menuItem.programmes = addProgrammeDetails(programmes, menuItem.url);
|
||||
}
|
||||
|
||||
res.json(menuItem);
|
||||
} catch (error) {
|
||||
console.error('Error getting menu item:', error);
|
||||
res.status(500).json({ error: 'Error loading menu item' });
|
||||
}
|
||||
};
|
||||
|
||||
// Render admin view
|
||||
exports.index = async (req, res) => {
|
||||
try {
|
||||
const data = await getHeaderData();
|
||||
|
||||
res.render('admin/header/index', {
|
||||
title: 'Header Management',
|
||||
data
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in header index:', error);
|
||||
req.flash('error_msg', 'An error occurred while loading the page');
|
||||
res.redirect('/admin/dashboard');
|
||||
}
|
||||
};
|
||||
|
||||
// Update header (chỉ cập nhật topbar và logo)
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const headerData = req.body;
|
||||
|
||||
// Tìm và cập nhật header
|
||||
const header = await Header.findOne({ name: 'default' });
|
||||
if (!header) {
|
||||
req.flash('error_msg', 'Header not found');
|
||||
return res.redirect('/admin/header');
|
||||
}
|
||||
|
||||
// Cập nhật từng phần
|
||||
if (headerData.topbarJson) {
|
||||
header.topbar = JSON.parse(headerData.topbarJson);
|
||||
}
|
||||
|
||||
if (headerData.logo) {
|
||||
header.logo = headerData.logo;
|
||||
}
|
||||
header.updatedAt = new Date();
|
||||
await header.save();
|
||||
|
||||
// Process menu updates if any
|
||||
let menuUpdateCount = 0;
|
||||
let menuErrorCount = 0;
|
||||
|
||||
if (headerData.menuUpdates) {
|
||||
try {
|
||||
const updates = JSON.parse(headerData.menuUpdates);
|
||||
|
||||
if (Array.isArray(updates) && updates.length > 0) {
|
||||
const Menu = require('../models/menuHeader');
|
||||
|
||||
for (const update of updates) {
|
||||
try {
|
||||
const { menuid, title, order, type, parent, fetch, isActive } = update;
|
||||
|
||||
const updateData = {
|
||||
title: title,
|
||||
order: order,
|
||||
type: type,
|
||||
parent: parent
|
||||
};
|
||||
|
||||
// Add fetch field if provided
|
||||
if (fetch !== undefined) {
|
||||
updateData.fetch = fetch;
|
||||
}
|
||||
|
||||
// Add isActive field if provided
|
||||
if (isActive !== undefined) {
|
||||
updateData.isActive = isActive;
|
||||
}
|
||||
|
||||
const result = await Menu.findOneAndUpdate(
|
||||
{ menuid: menuid },
|
||||
updateData,
|
||||
{ new: true }
|
||||
);
|
||||
|
||||
if (result) {
|
||||
menuUpdateCount++;
|
||||
} else {
|
||||
console.warn(`Menu item not found for update: ${menuid}`);
|
||||
menuErrorCount++;
|
||||
}
|
||||
} catch (innerErr) {
|
||||
console.error(`Error updating menu item ${update.menuid}:`, innerErr);
|
||||
menuErrorCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error processing menu updates:', err);
|
||||
}
|
||||
}
|
||||
|
||||
let flashMsg = 'Header updated successfully.';
|
||||
if (menuUpdateCount > 0) {
|
||||
flashMsg += ` Updated ${menuUpdateCount} menu items.`;
|
||||
}
|
||||
if (menuErrorCount > 0) {
|
||||
req.flash('error_msg', `Updated ${menuUpdateCount} items, but failed to update ${menuErrorCount} items. Check logs.`);
|
||||
} else {
|
||||
req.flash('success_msg', flashMsg);
|
||||
}
|
||||
|
||||
// Redirect back to the active tab
|
||||
const activeTab = req.body.activeTab || 'topbar';
|
||||
res.redirect(`/admin/header?activeTab=${activeTab}`);
|
||||
} catch (error) {
|
||||
console.error('Error updating header:', error);
|
||||
req.flash('error_msg', 'Error updating header: ' + error.message);
|
||||
res.redirect('/admin/header');
|
||||
}
|
||||
};
|
||||
|
||||
// Update menu structure (order and parent)
|
||||
exports.updateMenu = async (req, res) => {
|
||||
try {
|
||||
const { updates } = req.body;
|
||||
|
||||
if (!updates || !Array.isArray(updates)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Invalid updates data'
|
||||
});
|
||||
}
|
||||
|
||||
const Menu = require('../models/menuHeader');
|
||||
|
||||
// Update each menu item
|
||||
for (const update of updates) {
|
||||
const { menuid, title, order, type, parent, fetch, isActive } = update;
|
||||
|
||||
console.log(menuid, title, order, type, parent, fetch, isActive);
|
||||
|
||||
const updateData = {
|
||||
title: title,
|
||||
order: order,
|
||||
type: type,
|
||||
parent: parent
|
||||
};
|
||||
|
||||
// Add fetch field if provided (for level type menus)
|
||||
if (fetch !== undefined) {
|
||||
updateData.fetch = fetch;
|
||||
}
|
||||
|
||||
// Add isActive field if provided
|
||||
if (isActive !== undefined) {
|
||||
updateData.isActive = isActive;
|
||||
}
|
||||
|
||||
await Menu.findOneAndUpdate(
|
||||
{ menuid: menuid },
|
||||
updateData,
|
||||
{ new: true }
|
||||
);
|
||||
}
|
||||
res.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Error updating menu structure:', error);
|
||||
req.flash('error_msg', 'Error updating menu structure: ' + error.message);
|
||||
res.redirect('/admin/header');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user