Files
cms.techvanguard.vn/utils/contentEditors/historyConfig.js
T
Tống Thành Đạt a39c336dd4 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.
2026-04-22 18:06:03 +07:00

124 lines
3.5 KiB
JavaScript

const {
text,
textarea,
image,
icon,
checkbox,
url,
combobox,
object,
stringList,
objectList,
} = require("./sharedFields");
module.exports = {
key: "history",
title: "History Management",
subtitle: "Manage the content for the history page",
routeBase: "/admin/history",
apiPath: "/api/history",
previewPath: "/about/history",
dataFile: "history",
imageType: "history",
tabs: [
{
key: "highlight",
label: "Highlight Bar",
icon: "fas fa-star",
schema: object("highlight", "Highlight bar", [
icon("icon", "Highlight icon"),
text("text", "Message", { maxLength: 110 }),
text("linkLabel", "Link label", { maxLength: 30 }),
url("href", "Link URL", {
maxLength: 255,
helpText: "Use an anchor or website path only. Examples: #milestones, /about/history, /contact",
}),
]),
},
{
key: "hero",
label: "Hero",
icon: "fas fa-image",
schema: object("hero", "Hero", [
text("badge", "Eyebrow label", { maxLength: 40 }),
text("title", "Headline", { maxLength: 90 }),
textarea("description", "Supporting text", { maxLength: 220, rows: 4 }),
]),
},
{
key: "filters",
label: "Filter Controls",
icon: "fas fa-filter",
schema: object("filters", "Filter controls", [
stringList("yearOptions", "Year options", {
itemLabel: "Year option",
maxLength: 30,
sortable: true,
helpText: "Reorder these options to change the order in the Year range dropdown.",
}),
stringList("categoryOptions", "Category options", {
itemLabel: "Category option",
maxLength: 40,
sortable: true,
}),
]),
},
{
key: "timeline",
label: "Timeline",
icon: "fas fa-clock-rotate-left",
schema: object("timeline", "Timeline", [
objectList(
"items",
"Milestones",
[
text("year", "Year", {
maxLength: 4,
}),
combobox("yearRange", "Year range", {
maxLength: 30,
optionsPath: "filters.yearOptions",
}),
combobox("category", "Category", {
maxLength: 40,
optionsPath: "filters.categoryOptions",
}),
text("categoryLabel", "Category badge label", { maxLength: 25 }),
text("title", "Milestone title", { maxLength: 90 }),
textarea("description", "Description", {
maxLength: 260,
rows: 4,
}),
image("image", "Milestone image", {
imageHint: "Recommended 436x190 px, 16:9 aspect ratio.",
helpText: "Wide image used inside the milestone card.",
}),
text("imageAlt", "Image alt text", { maxLength: 120 }),
objectList(
"stats",
"Stats",
[
text("value", "Value", { maxLength: 24 }),
text("label", "Label", { maxLength: 50 }),
],
{
itemLabel: "Stat",
sortable: true,
emptyText: "No stats yet.",
},
),
checkbox("featured", "Featured milestone"),
],
{
itemLabel: "Milestone",
sortable: true,
itemTitleKey: "title",
itemSubtitleKey: "year",
emptyText: "No milestones yet.",
},
),
]),
},
],
};