Files
cms.techvanguard.vn/controllers/partnershipsController.js
T
Tống Thành Đạt 5d0fae6d51 feat(cms): enhance content editors and implement automatic ID generation
Improve the CMS administration interface across multiple pages (Accreditation, Admissions, History, Partnerships, and Policies) with a focus on usability and data integrity.
Key changes include:
- Implement `ensureUniqueIds` utility to automatically generate and maintain unique slugs for content items, removing the need for manual ID entry in the UI.
- Refactor the Admissions calculator to support detailed per-option editing via a new dedicated view and routes.
- Replace basic datalists with a custom, searchable icon combobox component for better visual selection.
- Update `_renderSingletonPageView` to handle active tab persistence via query parameters.
- Streamline editor configurations by removing redundant fields and improving help text.
- Enhance the Admissions "Key Dates" editor with a dynamic table interface for managing columns and rows.
- Normalize data payloads in controllers to ensure consistent API responses and internal linking.
2026-04-21 12:37:19 +07:00

117 lines
3.5 KiB
JavaScript

const PartnershipsPage = require("../models/partnerships");
const AUDIT_ACTIONS = require("../constants/auditAction");
const partnershipsConfig = require("../utils/contentEditors/partnershipsConfig");
const createPageContentController = require("./_createPageContentController");
const createRenderSingletonPageView = require("./_renderSingletonPageView");
const { ensureUniqueIds } = require("../utils/contentEditorIds");
function toInquiryField(id, field, type, width) {
return {
id,
label: field?.label || "",
placeholder: field?.placeholder || "",
type,
width,
required: true,
options: Array.isArray(field?.options) ? field.options : [],
};
}
function normalizeInquiryForm(data) {
if (!data?.inquiryForm) {
return data;
}
if (Array.isArray(data.inquiryForm.fields)) {
return data;
}
const legacyFields = data.inquiryForm.fields || {};
return {
...data,
inquiryForm: {
...data.inquiryForm,
fields: [
toInquiryField("firstName", legacyFields.firstName, "text", "half"),
toInquiryField("lastName", legacyFields.lastName, "text", "half"),
toInquiryField("organization", legacyFields.organization, "text", "full"),
toInquiryField(
"partnershipType",
legacyFields.partnershipType,
"select",
"full",
),
toInquiryField("message", legacyFields.message, "textarea", "full"),
].filter((field) => field.label || field.placeholder || field.id),
},
};
}
function prepareInquiryPayload(payload) {
const normalized = normalizeInquiryForm(payload);
const fields = Array.isArray(normalized?.inquiryForm?.fields)
? normalized.inquiryForm.fields
: [];
const partners = Array.isArray(normalized?.directory?.partners)
? normalized.directory.partners
: [];
return {
...normalized,
directory: {
...normalized.directory,
partners: ensureUniqueIds(
partners,
(partner) => partner.id,
(partner, index) => partner.name || partner.category || `partner-${index + 1}`,
"partner",
),
},
inquiryForm: {
...normalized.inquiryForm,
fields: ensureUniqueIds(
fields,
(field) => field.id,
(field, index) => field.label || field.placeholder || `field-${index + 1}`,
"field",
).map((field) => ({
id: field.id,
label: field.label || "",
placeholder: field.placeholder || "",
type: field.type || "text",
width: field.width || "full",
required: Boolean(field.required),
options: Array.isArray(field.options) ? field.options.filter(Boolean) : [],
})),
},
};
}
const controller = createPageContentController({
model: PartnershipsPage,
modelName: "PartnershipsPage",
auditAction: AUDIT_ACTIONS.UPDATE_PARTNERSHIPS,
editorConfig: partnershipsConfig,
normalizeForEditor: normalizeInquiryForm,
normalizeForApi: normalizeInquiryForm,
preparePayload: prepareInquiryPayload,
});
controller.index = async function index(req, res) {
try {
return await createRenderSingletonPageView({
model: PartnershipsPage,
editorConfig: partnershipsConfig,
view: "admin/partnerships/index",
normalizeForEditor: normalizeInquiryForm,
})(req, res);
} catch (error) {
console.error("partnerships index error:", error);
req.flash("error_msg", "Error loading Partnerships Management");
return req.session.save(() => res.redirect("/admin/dashboard"));
}
};
module.exports = controller;