forked from UKSOURCE/cms.lams
feat(cms): add management for partnerships, history, accreditation, admissions, and policies pages
Implement a singleton page content system to manage static informational pages. This includes: - New controllers, models, and data files for Partnerships, History, Accreditation, Admissions, and Policies. - Admin routes and views for updating page content. - Public API endpoints for fetching page data. - Migration scripts for initializing page data. - Updated admin navigation layout to include a dropdown for "About" sections. - Audit action constants for tracking updates to these pages.
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
const { addBaseUrlToImages } = require("../utils/imageHelper");
|
||||
const jsonHelper = require("../utils/jsonHelper");
|
||||
const writeAuditLog = require("../audit/writeAuditLog");
|
||||
const diffObject = require("../audit/diffObject");
|
||||
|
||||
function createPageContentController({
|
||||
model,
|
||||
modelName,
|
||||
auditAction,
|
||||
editorConfig,
|
||||
}) {
|
||||
return {
|
||||
async index(req, res) {
|
||||
try {
|
||||
const doc = await model.getSingle();
|
||||
const data = doc.toObject();
|
||||
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
|
||||
const backendUrl =
|
||||
process.env.BACKEND_URL ?? `${req.protocol}://${req.get("host")}`;
|
||||
|
||||
res.render("admin/pageContent/index", {
|
||||
layout: "layouts/main",
|
||||
title: editorConfig.title,
|
||||
subtitle: editorConfig.subtitle,
|
||||
data,
|
||||
editorConfig,
|
||||
activeTab: req.query.tab || editorConfig.tabs[0].key,
|
||||
frontendUrl,
|
||||
backendUrl,
|
||||
previewUrl: `${frontendUrl}${editorConfig.previewPath}`,
|
||||
currentPath: req.path,
|
||||
user: req.session.user,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`${editorConfig.key} index error:`, error);
|
||||
req.flash("error_msg", `Error loading ${editorConfig.title}`);
|
||||
return req.session.save(() => res.redirect("/admin/dashboard"));
|
||||
}
|
||||
},
|
||||
|
||||
async update(req, res) {
|
||||
try {
|
||||
const payload =
|
||||
typeof req.body.pageJson === "string"
|
||||
? JSON.parse(req.body.pageJson)
|
||||
: req.body.pageJson || {};
|
||||
|
||||
const activeTab = req.body.activeTab || editorConfig.tabs[0].key;
|
||||
const doc = await model.getSingle();
|
||||
const beforeData = JSON.parse(JSON.stringify(doc.toObject()));
|
||||
|
||||
doc.set(payload);
|
||||
Object.keys(payload).forEach((key) => doc.markModified(key));
|
||||
await doc.save();
|
||||
|
||||
const afterData = JSON.parse(JSON.stringify(doc.toObject()));
|
||||
const changes = diffObject(beforeData, afterData);
|
||||
|
||||
if (changes.length > 0) {
|
||||
await writeAuditLog({
|
||||
model: modelName,
|
||||
documentId: doc._id,
|
||||
action: auditAction,
|
||||
before: beforeData,
|
||||
after: afterData,
|
||||
changes,
|
||||
req,
|
||||
});
|
||||
}
|
||||
|
||||
const finalData = await model
|
||||
.findOne()
|
||||
.select("-_id -__v -createdAt -updatedAt")
|
||||
.lean();
|
||||
jsonHelper.writeJsonFile(editorConfig.dataFile, finalData);
|
||||
|
||||
req.flash("success_msg", `${editorConfig.title} updated successfully`);
|
||||
return req.session.save(() =>
|
||||
res.redirect(`${editorConfig.routeBase}?tab=${activeTab}`),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`${editorConfig.key} update error:`, error);
|
||||
req.flash(
|
||||
"error_msg",
|
||||
`Error updating ${editorConfig.title}: ${error.message}`,
|
||||
);
|
||||
return req.session.save(() =>
|
||||
res.redirect(
|
||||
`${editorConfig.routeBase}?tab=${req.body.activeTab || ""}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
async api(req, res) {
|
||||
try {
|
||||
const doc = await model.getSingle();
|
||||
const rawData = doc.toObject();
|
||||
const backendUrl =
|
||||
process.env.BACKEND_URL ?? `${req.protocol}://${req.get("host")}`;
|
||||
const processed = addBaseUrlToImages(rawData, backendUrl);
|
||||
return res.json(processed);
|
||||
} catch (error) {
|
||||
console.error(`${editorConfig.key} api error:`, error);
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: `Error loading ${editorConfig.key} data` });
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = createPageContentController;
|
||||
@@ -0,0 +1,11 @@
|
||||
const AccreditationPage = require("../models/accreditationPage");
|
||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||
const pageContentConfig = require("../utils/pageContentConfig");
|
||||
const createPageContentController = require("./_createPageContentController");
|
||||
|
||||
module.exports = createPageContentController({
|
||||
model: AccreditationPage,
|
||||
modelName: "AccreditationPage",
|
||||
auditAction: AUDIT_ACTIONS.UPDATE_ACCREDITATION,
|
||||
editorConfig: pageContentConfig.accreditation,
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
const AdmissionsPage = require("../models/admissionsPage");
|
||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||
const pageContentConfig = require("../utils/pageContentConfig");
|
||||
const createPageContentController = require("./_createPageContentController");
|
||||
|
||||
module.exports = createPageContentController({
|
||||
model: AdmissionsPage,
|
||||
modelName: "AdmissionsPage",
|
||||
auditAction: AUDIT_ACTIONS.UPDATE_ADMISSIONS,
|
||||
editorConfig: pageContentConfig.admissions,
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
const HistoryPage = require("../models/historyPage");
|
||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||
const pageContentConfig = require("../utils/pageContentConfig");
|
||||
const createPageContentController = require("./_createPageContentController");
|
||||
|
||||
module.exports = createPageContentController({
|
||||
model: HistoryPage,
|
||||
modelName: "HistoryPage",
|
||||
auditAction: AUDIT_ACTIONS.UPDATE_HISTORY,
|
||||
editorConfig: pageContentConfig.history,
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
const PartnershipsPage = require("../models/partnerships");
|
||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||
const pageContentConfig = require("../utils/pageContentConfig");
|
||||
const createPageContentController = require("./_createPageContentController");
|
||||
|
||||
module.exports = createPageContentController({
|
||||
model: PartnershipsPage,
|
||||
modelName: "PartnershipsPage",
|
||||
auditAction: AUDIT_ACTIONS.UPDATE_PARTNERSHIPS,
|
||||
editorConfig: pageContentConfig.partnerships,
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
const PoliciesPage = require("../models/policiesPage");
|
||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||
const pageContentConfig = require("../utils/pageContentConfig");
|
||||
const createPageContentController = require("./_createPageContentController");
|
||||
|
||||
module.exports = createPageContentController({
|
||||
model: PoliciesPage,
|
||||
modelName: "PoliciesPage",
|
||||
auditAction: AUDIT_ACTIONS.UPDATE_POLICIES,
|
||||
editorConfig: pageContentConfig.policies,
|
||||
});
|
||||
Reference in New Issue
Block a user