forked from UKSOURCE/cms.lams
feat(cms): enhance content editors with dynamic UI configs and validation
Implement a more flexible, configuration-driven approach for CMS editors across accreditation, admissions, and partnerships modules. - Move UI labels, help texts, and field limits from hardcoded views to `editorUi` configurations in config files. - Add server-side and client-side validation to prevent duplicate category tabs in accreditation and partnerships editors. - Refactor partnership and admission views to dynamically render tabs and fields based on the provided configuration. - Update field length constraints and default values across multiple content editors to better align with frontend requirements. - Improve the admissions calculator editor with dynamic field configurations and default value fallbacks.
This commit is contained in:
@@ -30,7 +30,7 @@ module.exports = {
|
||||
label: "Hero",
|
||||
icon: "fas fa-image",
|
||||
schema: object("hero", "Hero", [
|
||||
text("badge", "Eyebrow label", { maxLength: 40 }),
|
||||
text("badge", "Eyebrow label", { maxLength: 30 }),
|
||||
text("title", "Headline", { maxLength: 60 }),
|
||||
textarea("description", "Supporting text", { maxLength: 420, rows: 5 }),
|
||||
]),
|
||||
|
||||
@@ -20,6 +20,39 @@ module.exports = {
|
||||
previewPath: "/admissions",
|
||||
dataFile: "admissions",
|
||||
imageType: "admissions",
|
||||
editorUi: {
|
||||
keyDates: {
|
||||
tableLabel: "Key dates table",
|
||||
tableHelpText: "Manage the table directly by adding or removing columns and rows.",
|
||||
addColumnLabel: "Add Column",
|
||||
addRowLabel: "Add Row",
|
||||
columnPlaceholder: "Column name",
|
||||
emptyRowsText: "No rows yet.",
|
||||
actionsLabel: "Actions",
|
||||
columnLabelMaxLength: 40,
|
||||
cellMaxLength: 60,
|
||||
},
|
||||
calculator: {
|
||||
ctaLabel: "Primary button",
|
||||
ctaHelpText: "This button appears at the bottom of the calculator card.",
|
||||
optionsLabel: "Calculator options",
|
||||
optionsHelpText: "Each option has its own pricing labels, amount, note, and icon. Open the edit page to update the option details.",
|
||||
optionsEmptyText: "No calculator options yet.",
|
||||
addOptionLabel: "Add calculator option",
|
||||
maxOptions: 3,
|
||||
limitHelpText: "You can add up to 3 calculator options.",
|
||||
defaultOption: {
|
||||
paceLabel: "Target Pace",
|
||||
minPaceLabel: "Relaxed",
|
||||
maxPaceLabel: "Accelerated",
|
||||
resultLabel: "Estimated Monthly Payment",
|
||||
monthlyAmount: "299",
|
||||
monthlySuffix: "/mo",
|
||||
noteIcon: "fa-bolt",
|
||||
note: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
key: "hero",
|
||||
@@ -102,8 +135,8 @@ module.exports = {
|
||||
label: "Tuition",
|
||||
icon: "fas fa-chart-column",
|
||||
schema: object("tuition", "Tuition", [
|
||||
text("title", "Section title", { maxLength: 60 }),
|
||||
text("chartTitle", "Chart title", { maxLength: 60 }),
|
||||
text("title", "Section title", { maxLength: 45 }),
|
||||
text("chartTitle", "Chart title", { maxLength: 40 }),
|
||||
textarea("chartDescription", "Chart description", {
|
||||
maxLength: 140,
|
||||
rows: 3,
|
||||
@@ -112,14 +145,14 @@ module.exports = {
|
||||
"series",
|
||||
"Chart series",
|
||||
[
|
||||
text("label", "Series label", { maxLength: 40 }),
|
||||
text("label", "Series label", { maxLength: 20 }),
|
||||
{ key: "color", label: "Series color", type: "color" },
|
||||
objectList(
|
||||
"points",
|
||||
"Data points",
|
||||
[
|
||||
text("time", "Time label", {
|
||||
maxLength: 30,
|
||||
maxLength: 14,
|
||||
placeholder: "Year 1",
|
||||
}),
|
||||
{
|
||||
@@ -170,18 +203,44 @@ module.exports = {
|
||||
objectList(
|
||||
"options",
|
||||
"Calculator options",
|
||||
[
|
||||
hidden("id"),
|
||||
text("label", "Option label", { maxLength: 12 }),
|
||||
text("paceLabel", "Pace label", { maxLength: 30 }),
|
||||
text("minPaceLabel", "Minimum pace label", { maxLength: 20 }),
|
||||
text("maxPaceLabel", "Maximum pace label", { maxLength: 20 }),
|
||||
text("resultLabel", "Result label", { maxLength: 40 }),
|
||||
text("monthlyAmount", "Monthly amount", { maxLength: 20 }),
|
||||
text("monthlySuffix", "Monthly suffix", { maxLength: 10 }),
|
||||
icon("noteIcon", "Note icon"),
|
||||
text("note", "Note text", { maxLength: 60 }),
|
||||
],
|
||||
[
|
||||
hidden("id"),
|
||||
text("label", "Option label", {
|
||||
maxLength: 12,
|
||||
helpText: "This label appears in the calculator option switcher.",
|
||||
}),
|
||||
text("paceLabel", "Pace label", {
|
||||
maxLength: 20,
|
||||
helpText: "This appears above the pace slider.",
|
||||
}),
|
||||
text("minPaceLabel", "Minimum pace label", {
|
||||
maxLength: 7,
|
||||
helpText: "This appears on the left side of the pace slider.",
|
||||
}),
|
||||
text("maxPaceLabel", "Maximum pace label", {
|
||||
maxLength: 7,
|
||||
helpText: "This appears on the right side of the pace slider.",
|
||||
}),
|
||||
text("resultLabel", "Result label", {
|
||||
maxLength: 40,
|
||||
helpText: "This label appears above the calculated amount.",
|
||||
}),
|
||||
text("monthlyAmount", "Monthly amount", {
|
||||
maxLength: 20,
|
||||
helpText: "Enter digits only. The currency symbol is added on the website automatically.",
|
||||
}),
|
||||
text("monthlySuffix", "Monthly suffix", {
|
||||
maxLength: 10,
|
||||
helpText: "Example: /mo",
|
||||
}),
|
||||
icon("noteIcon", "Note icon", {
|
||||
helpText: "Choose the icon shown beside the note.",
|
||||
}),
|
||||
text("note", "Note text", {
|
||||
maxLength: 60,
|
||||
helpText: "This short note appears under the amount.",
|
||||
}),
|
||||
],
|
||||
{
|
||||
itemLabel: "Option",
|
||||
sortable: true,
|
||||
@@ -210,8 +269,8 @@ module.exports = {
|
||||
"items",
|
||||
"Scholarship items",
|
||||
[
|
||||
text("title", "Title", { maxLength: 50 }),
|
||||
text("amount", "Amount", { maxLength: 24 }),
|
||||
text("title", "Title", { maxLength: 40 }),
|
||||
text("amount", "Amount", { maxLength: 12 }),
|
||||
textarea("description", "Description", {
|
||||
maxLength: 160,
|
||||
rows: 3,
|
||||
|
||||
@@ -73,7 +73,7 @@ module.exports = {
|
||||
"Milestones",
|
||||
[
|
||||
text("year", "Year", {
|
||||
maxLength: 30,
|
||||
maxLength: 4,
|
||||
}),
|
||||
combobox("yearRange", "Year range", {
|
||||
maxLength: 30,
|
||||
@@ -83,7 +83,7 @@ module.exports = {
|
||||
maxLength: 40,
|
||||
optionsPath: "filters.categoryOptions",
|
||||
}),
|
||||
text("categoryLabel", "Category badge label", { maxLength: 30 }),
|
||||
text("categoryLabel", "Category badge label", { maxLength: 25 }),
|
||||
text("title", "Milestone title", { maxLength: 90 }),
|
||||
textarea("description", "Description", {
|
||||
maxLength: 260,
|
||||
|
||||
@@ -30,6 +30,15 @@ module.exports = {
|
||||
previewPath: "/about/partnerships",
|
||||
dataFile: "partnerships",
|
||||
imageType: "partnerships",
|
||||
editorUi: {
|
||||
directory: {
|
||||
tabsFrontendHint: "The frontend shows up to 3 direct tabs. Additional tabs move into a More dropdown.",
|
||||
partnersHelpText: "Each partner card keeps its own open or closed state automatically.",
|
||||
},
|
||||
inquiryForm: {
|
||||
fieldsHelpText: "Manage labels, placeholders, type, width, and dropdown options.",
|
||||
},
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
key: "hero",
|
||||
@@ -115,7 +124,7 @@ module.exports = {
|
||||
label: "Inquiry Form",
|
||||
icon: "fas fa-envelope",
|
||||
schema: object("inquiryForm", "Inquiry form", [
|
||||
text("title", "Modal title", { maxLength: 60 }),
|
||||
text("title", "Modal title", { maxLength: 35 }),
|
||||
objectList(
|
||||
"fields",
|
||||
"Form fields",
|
||||
|
||||
@@ -46,7 +46,7 @@ const baseConfig = {
|
||||
schema: object("sidebar", "Sidebar", [
|
||||
text("heading", "Sidebar heading", { maxLength: 30 }),
|
||||
text("helperText", "Helper text", { maxLength: 60 }),
|
||||
text("contactLabel", "Contact link label", { maxLength: 40 }),
|
||||
text("contactLabel", "Contact link label", { maxLength: 25 }),
|
||||
url("contactHref", "Contact URL", { maxLength: 255 }),
|
||||
]),
|
||||
},
|
||||
|
||||
@@ -169,7 +169,7 @@ const variantList = (key, label, variants, options = {}) => ({
|
||||
});
|
||||
|
||||
const linkFields = (prefix = "Link") => [
|
||||
text("label", `${prefix} label`, { maxLength: 60 }),
|
||||
text("label", `${prefix} label`, { maxLength: 40 }),
|
||||
url("href", `${prefix} URL`, { maxLength: 255 }),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user