forked from UKSOURCE/cms.hailearning.edu.vn
feat(header-menu): add maintenance mode functionality and related UI elements
This commit is contained in:
@@ -1,6 +1,36 @@
|
||||
const HeaderMenu = require("../models/headerMenu");
|
||||
const slugify = require("slugify");
|
||||
|
||||
const parseBooleanFlag = (value) => {
|
||||
if (typeof value === "boolean") {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
return ["true", "1", "on", "yes"].includes(normalized);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const normalizeInternalUrl = (url = "") => {
|
||||
if (typeof url !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const trimmed = url.trim();
|
||||
if (!trimmed || !trimmed.startsWith("/")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (trimmed === "/") {
|
||||
return "/";
|
||||
}
|
||||
|
||||
return trimmed.replace(/\/+$/, "");
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper: Build tree structure from flat array
|
||||
*/
|
||||
@@ -19,8 +49,10 @@ const buildMenuTree = (items, parentId = null, isPublic = false) => {
|
||||
cleanItem = {
|
||||
id: item._id,
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
url: item.is_maintainance ? "/maintenance" : item.url,
|
||||
originalUrl: item.url,
|
||||
type: item.type,
|
||||
is_maintainance: Boolean(item.is_maintainance),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,7 +91,7 @@ exports.store = async (req, res) => {
|
||||
try {
|
||||
console.log("=== BACKEND: store hit ===");
|
||||
console.log("Body:", req.body);
|
||||
const { title, url, parentId, order, status, type } = req.body;
|
||||
const { title, url, parentId, order, status, type, is_maintainance } = req.body;
|
||||
const slug = slugify(title, { lower: true, strict: true });
|
||||
|
||||
const newItem = new HeaderMenu({
|
||||
@@ -70,6 +102,7 @@ exports.store = async (req, res) => {
|
||||
order: order || 0,
|
||||
status: status || "active",
|
||||
type: type || "internal",
|
||||
is_maintainance: parseBooleanFlag(is_maintainance),
|
||||
});
|
||||
|
||||
const savedItem = await newItem.save();
|
||||
@@ -101,7 +134,7 @@ exports.update = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
console.log("=== BACKEND: update hit ===", { id });
|
||||
console.log("Body:", req.body);
|
||||
const { title, url, parentId, order, status, type } = req.body;
|
||||
const { title, url, parentId, order, status, type, is_maintainance } = req.body;
|
||||
|
||||
const updateData = {
|
||||
url,
|
||||
@@ -109,6 +142,7 @@ exports.update = async (req, res) => {
|
||||
order,
|
||||
status,
|
||||
type,
|
||||
is_maintainance: parseBooleanFlag(is_maintainance),
|
||||
};
|
||||
|
||||
if (title) {
|
||||
@@ -203,3 +237,33 @@ exports.api = async (req, res) => {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
exports.maintenanceStatus = async (req, res) => {
|
||||
try {
|
||||
const items = await HeaderMenu.find({
|
||||
status: "active",
|
||||
is_maintainance: true,
|
||||
})
|
||||
.select("title url slug")
|
||||
.sort({ order: 1 })
|
||||
.lean();
|
||||
|
||||
const urls = [...new Set(items.map((item) => normalizeInternalUrl(item.url)).filter(Boolean))];
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
enabled: items.length > 0,
|
||||
urls,
|
||||
items: items.map((item) => ({
|
||||
id: String(item._id),
|
||||
title: item.title,
|
||||
slug: item.slug,
|
||||
url: item.url,
|
||||
})),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user