forked from UKSOURCE/cms.lams
feat(cms): refactor page content management and implement detailed editors
Refactor the CMS page content system to use a more modular configuration-driven approach. This replaces the monolithic `pageContentConfig.js` with individual configuration files for each page and introduces a shared field utility to standardize editor components. Key changes: - Implement a generic `_renderSingletonPageView` helper to reduce duplication across controllers. - Enhance `_createPageContentController` with `normalizeForEditor`, `normalizeForApi`, and `preparePayload` hooks for custom data transformation. - Create dedicated configuration and view structures for Partnerships, History, Accreditation, Admissions, and Policies pages. - Add a specialized section editor for Policies to manage complex nested content. - Improve the frontend `page-content-editor.js` with support for visibility logic, auto-sequencing for arrays, and URL synchronization for active tabs. - Update data JSON files to align with the new schema.
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
const ICON_OPTIONS = [
|
||||
"fa-scale-balanced",
|
||||
"fa-shield-check",
|
||||
"fa-magnifying-glass",
|
||||
"fa-graduation-cap",
|
||||
"fa-check-double",
|
||||
"fa-building-columns",
|
||||
"fa-award",
|
||||
"fa-trophy",
|
||||
"fa-arrow-down",
|
||||
"fa-arrow-right",
|
||||
"fa-check-circle",
|
||||
"fa-exchange-alt",
|
||||
"fa-bolt",
|
||||
"fa-book-open",
|
||||
"fa-credit-card",
|
||||
"fa-calendar-days",
|
||||
"fa-envelope",
|
||||
"fa-file-lines",
|
||||
"fa-globe",
|
||||
"fa-briefcase",
|
||||
"fa-handshake",
|
||||
"fa-circle-info",
|
||||
"fa-star",
|
||||
"fa-list-check",
|
||||
];
|
||||
|
||||
const text = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "text",
|
||||
...options,
|
||||
});
|
||||
|
||||
const hidden = (key, options = {}) => ({
|
||||
key,
|
||||
type: "hidden",
|
||||
...options,
|
||||
});
|
||||
|
||||
const textarea = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "textarea",
|
||||
rows: options.rows || 4,
|
||||
...options,
|
||||
});
|
||||
|
||||
const image = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "image",
|
||||
...options,
|
||||
});
|
||||
|
||||
const icon = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "icon",
|
||||
options: options.options || ICON_OPTIONS,
|
||||
...options,
|
||||
});
|
||||
|
||||
const checkbox = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "checkbox",
|
||||
...options,
|
||||
});
|
||||
|
||||
const url = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "url",
|
||||
...options,
|
||||
});
|
||||
|
||||
const select = (key, label, options = [], extra = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "select",
|
||||
options,
|
||||
...extra,
|
||||
});
|
||||
|
||||
const combobox = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "combobox",
|
||||
...options,
|
||||
});
|
||||
|
||||
const object = (key, label, fields, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "object",
|
||||
fields,
|
||||
...options,
|
||||
});
|
||||
|
||||
const stringList = (key, label, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "array",
|
||||
itemLabel: options.itemLabel || "Item",
|
||||
sortable: options.sortable,
|
||||
addLabel: options.addLabel,
|
||||
helpText: options.helpText,
|
||||
emptyText: options.emptyText,
|
||||
itemSchema: {
|
||||
type: "primitive",
|
||||
fieldType: options.fieldType || "text",
|
||||
label: options.itemLabel || "Item",
|
||||
maxLength: options.maxLength,
|
||||
placeholder: options.placeholder,
|
||||
helpText: options.itemHelpText,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
||||
const objectList = (key, label, fields, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "array",
|
||||
itemLabel: options.itemLabel || "Item",
|
||||
sortable: options.sortable,
|
||||
addLabel: options.addLabel,
|
||||
helpText: options.helpText,
|
||||
emptyText: options.emptyText,
|
||||
itemTitleKey: options.itemTitleKey,
|
||||
itemSubtitleKey: options.itemSubtitleKey,
|
||||
itemActions: options.itemActions,
|
||||
itemSchema: {
|
||||
type: "object",
|
||||
fields,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
||||
const variantList = (key, label, variants, options = {}) => ({
|
||||
key,
|
||||
label,
|
||||
type: "array",
|
||||
itemLabel: options.itemLabel || "Item",
|
||||
sortable: options.sortable,
|
||||
addLabel: options.addLabel,
|
||||
helpText: options.helpText,
|
||||
emptyText: options.emptyText,
|
||||
itemSchema: {
|
||||
type: "variant",
|
||||
discriminator: "type",
|
||||
options: Object.keys(variants).map((value) => ({
|
||||
value,
|
||||
label: variants[value].label,
|
||||
})),
|
||||
variants,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
||||
const linkFields = (prefix = "Link") => [
|
||||
text("label", `${prefix} label`, { maxLength: 60 }),
|
||||
url("href", `${prefix} URL`, { maxLength: 255 }),
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
ICON_OPTIONS,
|
||||
text,
|
||||
hidden,
|
||||
textarea,
|
||||
image,
|
||||
icon,
|
||||
checkbox,
|
||||
url,
|
||||
select,
|
||||
combobox,
|
||||
object,
|
||||
stringList,
|
||||
objectList,
|
||||
variantList,
|
||||
linkFields,
|
||||
};
|
||||
Reference in New Issue
Block a user