forked from UKSOURCE/cms.lams
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.
186 lines
3.3 KiB
JavaScript
186 lines
3.3 KiB
JavaScript
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,
|
|
min: options.min,
|
|
max: options.max,
|
|
step: options.step,
|
|
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,
|
|
};
|