nextjs-cms 0.9.38 → 0.9.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/actions/pages.d.ts +27 -7
- package/dist/api/actions/pages.d.ts.map +1 -1
- package/dist/api/actions/pages.js +111 -27
- package/dist/api/trpc/root.d.ts +27 -6
- package/dist/api/trpc/root.d.ts.map +1 -1
- package/dist/api/trpc/routers/hasItemsSection.d.ts +23 -2
- package/dist/api/trpc/routers/hasItemsSection.d.ts.map +1 -1
- package/dist/api/trpc/routers/hasItemsSection.js +2 -1
- package/dist/api/trpc/routers/navigation.d.ts +3 -3
- package/dist/api/trpc/routers/simpleSection.d.ts +1 -1
- package/dist/api/trpc/server.d.ts +81 -18
- package/dist/api/trpc/server.d.ts.map +1 -1
- package/dist/core/config/config-loader.d.ts +2 -2
- package/dist/core/factories/FieldFactory.d.ts +1 -6
- package/dist/core/factories/FieldFactory.d.ts.map +1 -1
- package/dist/core/factories/FieldFactory.js +3 -68
- package/dist/core/fields/checkbox.d.ts +3 -3
- package/dist/core/fields/color.d.ts +3 -3
- package/dist/core/fields/date-range.d.ts +2 -2
- package/dist/core/fields/date.d.ts +3 -3
- package/dist/core/fields/document.d.ts +3 -3
- package/dist/core/fields/field.d.ts +25 -12
- package/dist/core/fields/field.d.ts.map +1 -1
- package/dist/core/fields/field.js +51 -23
- package/dist/core/fields/index.d.ts +1 -0
- package/dist/core/fields/index.d.ts.map +1 -1
- package/dist/core/fields/index.js +2 -0
- package/dist/core/fields/map.d.ts +3 -3
- package/dist/core/fields/number.d.ts +4 -4
- package/dist/core/fields/password.d.ts +3 -3
- package/dist/core/fields/photo.d.ts +9 -9
- package/dist/core/fields/richText.d.ts +12 -12
- package/dist/core/fields/select.d.ts +7 -7
- package/dist/core/fields/selectMultiple.d.ts +4 -4
- package/dist/core/fields/slug.d.ts +9 -9
- package/dist/core/fields/tags.d.ts +3 -3
- package/dist/core/fields/text.d.ts +2 -2
- package/dist/core/fields/textArea.d.ts +2 -2
- package/dist/core/fields/video.d.ts +3 -3
- package/dist/core/helpers/conditional-rules.d.ts +63 -0
- package/dist/core/helpers/conditional-rules.d.ts.map +1 -0
- package/dist/core/helpers/conditional-rules.js +113 -0
- package/dist/core/helpers/index.d.ts +1 -0
- package/dist/core/helpers/index.d.ts.map +1 -1
- package/dist/core/helpers/index.js +4 -0
- package/dist/core/sections/category.d.ts +50 -50
- package/dist/core/sections/hasItems.d.ts +74 -74
- package/dist/core/sections/section.d.ts +23 -23
- package/dist/core/sections/simple.d.ts +6 -6
- package/dist/core/submit/submit.d.ts +4 -1
- package/dist/core/submit/submit.d.ts.map +1 -1
- package/dist/core/submit/submit.js +9 -19
- package/dist/core/types/index.d.ts +30 -8
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/translations/client.d.ts +4 -4
- package/dist/translations/server.d.ts +4 -4
- package/package.json +3 -3
- package/dist/api/axios/axiosInstance.d.ts +0 -2
- package/dist/api/axios/axiosInstance.d.ts.map +0 -1
- package/dist/api/axios/axiosInstance.js +0 -8
- package/dist/api/index.d.ts +0 -975
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -13
- package/dist/api/lib/serverActions.d.ts +0 -374
- package/dist/api/lib/serverActions.d.ts.map +0 -1
- package/dist/api/lib/serverActions.js +0 -1445
- package/dist/api/root.d.ts +0 -1917
- package/dist/api/root.d.ts.map +0 -1
- package/dist/api/root.js +0 -115
- package/dist/api/routers/accountSettings.d.ts +0 -66
- package/dist/api/routers/accountSettings.d.ts.map +0 -1
- package/dist/api/routers/accountSettings.js +0 -202
- package/dist/api/routers/admins.d.ts +0 -112
- package/dist/api/routers/admins.d.ts.map +0 -1
- package/dist/api/routers/admins.js +0 -323
- package/dist/api/routers/auth.d.ts +0 -54
- package/dist/api/routers/auth.d.ts.map +0 -1
- package/dist/api/routers/auth.js +0 -50
- package/dist/api/routers/categorySection.d.ts +0 -105
- package/dist/api/routers/categorySection.d.ts.map +0 -1
- package/dist/api/routers/categorySection.js +0 -49
- package/dist/api/routers/config.d.ts +0 -48
- package/dist/api/routers/config.d.ts.map +0 -1
- package/dist/api/routers/config.js +0 -18
- package/dist/api/routers/cpanel.d.ts +0 -82
- package/dist/api/routers/cpanel.d.ts.map +0 -1
- package/dist/api/routers/cpanel.js +0 -216
- package/dist/api/routers/fields.d.ts +0 -35
- package/dist/api/routers/fields.d.ts.map +0 -1
- package/dist/api/routers/fields.js +0 -81
- package/dist/api/routers/files.d.ts +0 -34
- package/dist/api/routers/files.d.ts.map +0 -1
- package/dist/api/routers/files.js +0 -14
- package/dist/api/routers/gallery.d.ts +0 -34
- package/dist/api/routers/gallery.d.ts.map +0 -1
- package/dist/api/routers/gallery.js +0 -64
- package/dist/api/routers/hasItemsSection.d.ts +0 -219
- package/dist/api/routers/hasItemsSection.d.ts.map +0 -1
- package/dist/api/routers/hasItemsSection.js +0 -86
- package/dist/api/routers/logs.d.ts +0 -59
- package/dist/api/routers/logs.d.ts.map +0 -1
- package/dist/api/routers/logs.js +0 -76
- package/dist/api/routers/navigation.d.ts +0 -50
- package/dist/api/routers/navigation.d.ts.map +0 -1
- package/dist/api/routers/navigation.js +0 -11
- package/dist/api/routers/simpleSection.d.ts +0 -105
- package/dist/api/routers/simpleSection.d.ts.map +0 -1
- package/dist/api/routers/simpleSection.js +0 -54
- package/dist/api/trpc.d.ts +0 -111
- package/dist/api/trpc.d.ts.map +0 -1
- package/dist/api/trpc.js +0 -99
- package/dist/auth/axios/axiosInstance.d.ts +0 -2
- package/dist/auth/axios/axiosInstance.d.ts.map +0 -1
- package/dist/auth/axios/axiosInstance.js +0 -8
- package/dist/auth/hooks/useAxiosPrivate.d.ts +0 -5
- package/dist/auth/hooks/useAxiosPrivate.d.ts.map +0 -1
- package/dist/auth/hooks/useAxiosPrivate.js +0 -74
- package/dist/auth/trpc.d.ts +0 -6
- package/dist/auth/trpc.d.ts.map +0 -1
- package/dist/auth/trpc.js +0 -82
- package/dist/core/fields/dateRange.d.ts +0 -115
- package/dist/core/fields/dateRange.d.ts.map +0 -1
- package/dist/core/fields/dateRange.js +0 -149
- package/dist/translations/locale-cookie.d.ts +0 -24
- package/dist/translations/locale-cookie.d.ts.map +0 -1
- package/dist/translations/locale-cookie.js +0 -44
- package/dist/translations/locale-utils.d.ts +0 -8
- package/dist/translations/locale-utils.d.ts.map +0 -1
- package/dist/translations/locale-utils.js +0 -11
- package/dist/translations/localization.d.ts +0 -40
- package/dist/translations/localization.d.ts.map +0 -1
- package/dist/translations/localization.js +0 -48
- package/dist/validators/dateRange.d.ts +0 -11
- package/dist/validators/dateRange.d.ts.map +0 -1
- package/dist/validators/dateRange.js +0 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/api/actions/pages.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AASpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAKR,cAAc,EAGjB,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAyE7D,eAAO,MAAM,uBAAuB,GAAU,SAAS,OAAO,EAAE,aAAa,MAAM,EAAE,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBA8DzE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,GAAG,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE;uBAC3C;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,GAAG,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE;8BACpC,MAAM,EAAE;iBACrB;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,GAAG,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,EAAE;+BAC/B,OAAO;8BACR,OAAO;;;EA6HxC,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC1B,SAAS,OAAO,EAChB,aAAa,MAAM,EACnB,eAAe,MAAM,GAAG,MAAM,EAC9B,YAAY,OAAO,EACnB,kBAAkB,eAAe;;;;EAwRpC,CAAA;AAED,eAAO,MAAM,uBAAuB,GAChC,SAAS,OAAO,EAChB,aAAa,MAAM,EACnB,eAAe,MAAM,GAAG,MAAM,EAC9B,QAAQ,MAAM;;;;EAmMjB,CAAA;AAED,eAAO,MAAM,cAAc,GACvB,SAAS,OAAO,EAChB,aAAa,MAAM,EACnB,eAAe,MAAM,GAAG,MAAM,EAC9B,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA2EM,MAAM;eACZ,MAAM;cACP,GAAG;iBACA,MAAM;;;uBAwDA;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE;uBAC9C;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE;8BACvC,MAAM,EAAE;iBACrB;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,CAAC,EAAE,OAAO,CAAA;SAAE,EAAE;+BAClC,OAAO;8BACR,OAAO;;;;;;;;;;;EA4HxC,CAAA;AAED,eAAO,MAAM,aAAa,GAAU,SAAS,OAAO,EAAE,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0FxE,CAAA;AAED,eAAO,MAAM,0BAA0B,GAAU,sCAK9C;IACC,OAAO,EAAE,OAAO,CAAA;IAChB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CAChB;;;;;;;;;;;;;;;;;;;;EA2DA,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAU,SAAS,OAAO,EAAE,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6D/C,MAAM,GAAG,MAAM,GAAG,SAAS;;;;;;;EAgBzD,CAAA;AAED,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../../src/api/actions/pages.ts"],"names":[],"mappings":"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"}
|
|
@@ -1012,7 +1012,7 @@ export const getCategorySection = async (session, sectionName) => {
|
|
|
1012
1012
|
// publisher: privileges.publisher,
|
|
1013
1013
|
};
|
|
1014
1014
|
};
|
|
1015
|
-
export const getBrowsePage = async (session, sectionName, page = 1, q) => {
|
|
1015
|
+
export const getBrowsePage = async (session, sectionName, page = 1, q, locale) => {
|
|
1016
1016
|
// Let's fetch the section items and admin privileges for the section
|
|
1017
1017
|
const _s = (await SectionFactory.getSectionForAdmin({
|
|
1018
1018
|
name: sectionName,
|
|
@@ -1031,40 +1031,69 @@ export const getBrowsePage = async (session, sectionName, page = 1, q) => {
|
|
|
1031
1031
|
const limit = 12;
|
|
1032
1032
|
const offset = (page - 1) * limit;
|
|
1033
1033
|
const tableName = section.db.table;
|
|
1034
|
+
const identifierName = section.db.identifier.name;
|
|
1035
|
+
const localesTable = section.localesTableName;
|
|
1034
1036
|
const orderByFieldName = section.db.orderByField?.name || 'created_at';
|
|
1035
1037
|
const sqlChunks = [];
|
|
1036
1038
|
const totalRowsSqlChunks = [];
|
|
1037
1039
|
const sectionSearch = section.search?.searchFields ? section.search?.searchFields.length > 0 : false;
|
|
1038
|
-
// Check if we need to JOIN _locales for search
|
|
1039
1040
|
const cmsConfig = await getCMSConfig();
|
|
1040
1041
|
const hasLocalization = !!cmsConfig.localization?.enabled;
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1042
|
+
// Resolve the requested browse locale. A non-default, resolvable locale on a section
|
|
1043
|
+
// with localized content switches the browse view to that locale: localized fields are
|
|
1044
|
+
// rendered from the locale row (base value as fallback) and search is scoped to that same
|
|
1045
|
+
// locale. The default locale (or none) keeps the plain base-table behavior.
|
|
1046
|
+
const localeResult = resolveLocale({ localization: cmsConfig.localization, locale });
|
|
1047
|
+
const browseLocale = localeResult.localizationEnabled &&
|
|
1048
|
+
localeResult.resolvedLocale &&
|
|
1049
|
+
localeResult.isDefault === false &&
|
|
1050
|
+
section.hasLocalizedContent
|
|
1051
|
+
? localeResult.resolvedLocale.code
|
|
1052
|
+
: null;
|
|
1053
|
+
// Display fields whose value should come from the locale row when browsing a non-default locale.
|
|
1054
|
+
const localizedDisplayFieldNames = new Set();
|
|
1055
|
+
if (browseLocale) {
|
|
1056
|
+
if (section.headingField?.localized)
|
|
1057
|
+
localizedDisplayFieldNames.add(section.headingField.name);
|
|
1058
|
+
if (section.coverPhotoField?.localized)
|
|
1059
|
+
localizedDisplayFieldNames.add(section.coverPhotoField.name);
|
|
1060
|
+
if (section.browse?.fields) {
|
|
1061
|
+
for (const f of section.browse.fields) {
|
|
1062
|
+
const field = section.fields.find((sf) => sf.name === f.name);
|
|
1063
|
+
if (field?.localized)
|
|
1064
|
+
localizedDisplayFieldNames.add(f.name);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
const trimmedQuery = q && q.trim().length > 0 ? q.trim() : null;
|
|
1069
|
+
if (browseLocale) {
|
|
1070
|
+
// 1:1 LEFT JOIN via the (parent_id, locale) unique key — at most one locale row per
|
|
1071
|
+
// item, so no DISTINCT is needed. Items without a translation still appear (locale
|
|
1072
|
+
// columns NULL → base fallback). Localized display columns are aliased `__loc_<name>`.
|
|
1073
|
+
const localeJoin = sql `from ${sql.raw(`\`${tableName}\``)} left join ${sql.raw(`\`${localesTable}\``)} on ${sql.raw(`\`${localesTable}\``)}.parent_id = ${sql.raw(`\`${tableName}\``)}.${sql.raw(`\`${identifierName}\``)} and ${sql.raw(`\`${localesTable}\``)}.locale = ${browseLocale}`;
|
|
1074
|
+
const selectParts = [sql `${sql.raw(`\`${tableName}\``)}.*`];
|
|
1075
|
+
for (const fieldName of localizedDisplayFieldNames) {
|
|
1076
|
+
selectParts.push(sql `${sql.raw(`\`${localesTable}\``)}.${sql.raw(`\`${fieldName}\``)} AS ${sql.raw(`\`__loc_${fieldName}\``)}`);
|
|
1077
|
+
}
|
|
1078
|
+
sqlChunks.push(sql `select`, sql.join(selectParts, sql `, `), localeJoin);
|
|
1079
|
+
totalRowsSqlChunks.push(sql `select count(*) as total`, localeJoin);
|
|
1047
1080
|
}
|
|
1048
1081
|
else {
|
|
1049
1082
|
sqlChunks.push(sql `select * from ${sql.raw(`\`${tableName}\``)}`);
|
|
1050
1083
|
totalRowsSqlChunks.push(sql `select count(*) as total from ${sql.raw(`\`${tableName}\``)}`);
|
|
1051
1084
|
}
|
|
1052
|
-
if (
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
whereParts.push(sql `${sql.raw(`\`${localesTable}\``)}.${sql.raw(`\`${field.name}\``)} LIKE CONCAT('%',${sql `${q.trim()}`},'%')`);
|
|
1061
|
-
}
|
|
1085
|
+
if (trimmedQuery && section.search?.searchFields.length) {
|
|
1086
|
+
const whereParts = [];
|
|
1087
|
+
for (const field of section.search.searchFields) {
|
|
1088
|
+
// Base-table column (this is also the default-locale content)
|
|
1089
|
+
whereParts.push(sql `${sql.raw(`\`${tableName}\``)}.${sql.raw(`\`${field.name}\``)} LIKE CONCAT('%',${trimmedQuery},'%')`);
|
|
1090
|
+
// Current locale's column — scoped to the browsed locale only, not all locales
|
|
1091
|
+
if (browseLocale && field.localized) {
|
|
1092
|
+
whereParts.push(sql `${sql.raw(`\`${localesTable}\``)}.${sql.raw(`\`${field.name}\``)} LIKE CONCAT('%',${trimmedQuery},'%')`);
|
|
1062
1093
|
}
|
|
1063
|
-
sqlChunks.push(sql `where`);
|
|
1064
|
-
sqlChunks.push(sql.join(whereParts, sql ` or `));
|
|
1065
|
-
totalRowsSqlChunks.push(sql `where`);
|
|
1066
|
-
totalRowsSqlChunks.push(sql.join(whereParts, sql ` or `));
|
|
1067
1094
|
}
|
|
1095
|
+
sqlChunks.push(sql `where`, sql.join(whereParts, sql ` or `));
|
|
1096
|
+
totalRowsSqlChunks.push(sql `where`, sql.join(whereParts, sql ` or `));
|
|
1068
1097
|
}
|
|
1069
1098
|
sqlChunks.push(sql `ORDER BY ${sql.raw(`\`${tableName}\``)}.${sql.raw(`\`${orderByFieldName}\``)} DESC LIMIT ${limit} OFFSET ${offset}`);
|
|
1070
1099
|
const finalSql = sql.join(sqlChunks, sql.raw(' '));
|
|
@@ -1074,9 +1103,61 @@ export const getBrowsePage = async (session, sectionName, page = 1, q) => {
|
|
|
1074
1103
|
const totalCountResult = await db.execute(totalRowsSql);
|
|
1075
1104
|
const totalCountRows = totalCountResult[0];
|
|
1076
1105
|
const rows = sectionItems[0];
|
|
1106
|
+
// Existing translations per item, keyed by parent id.
|
|
1107
|
+
// Only the current page's rows are looked up, and the query is covered by the
|
|
1108
|
+
// `(parent_id, locale)` unique index on the _locales table, so it's an index-only
|
|
1109
|
+
// scan of at most `limit` groups — negligible cost. Skipped entirely for
|
|
1110
|
+
// non-localized sections.
|
|
1111
|
+
const localesByItemId = new Map();
|
|
1112
|
+
if (hasLocalization && section.hasLocalizedContent && rows.length > 0) {
|
|
1113
|
+
const itemIds = rows
|
|
1114
|
+
.map((row) => row[identifierName])
|
|
1115
|
+
.filter((id) => id !== null && id !== undefined);
|
|
1116
|
+
if (itemIds.length > 0) {
|
|
1117
|
+
// Configured order, so badges render consistently regardless of GROUP_CONCAT order.
|
|
1118
|
+
const localeOrder = cmsConfig.localization?.locales?.map((l) => l.code) ?? [];
|
|
1119
|
+
const idList = sql.join(itemIds.map((id) => sql `${id}`), sql `, `);
|
|
1120
|
+
const localesSql = sql `SELECT parent_id, GROUP_CONCAT(locale) AS locales FROM ${sql.raw(`\`${section.localesTableName}\``)} WHERE parent_id IN (${idList}) GROUP BY parent_id`;
|
|
1121
|
+
try {
|
|
1122
|
+
const localesResult = await db.execute(localesSql);
|
|
1123
|
+
const localeRows = localesResult[0];
|
|
1124
|
+
for (const localeRow of localeRows) {
|
|
1125
|
+
const existing = String(localeRow.locales ?? '')
|
|
1126
|
+
.split(',')
|
|
1127
|
+
.filter(Boolean);
|
|
1128
|
+
const ordered = localeOrder.filter((code) => existing.includes(code));
|
|
1129
|
+
localesByItemId.set(String(localeRow.parent_id), ordered);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
catch (e) {
|
|
1133
|
+
console.error('Failed to load existing locales for browse page items:', e);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1077
1137
|
// Resolve localized section title for the browse page header
|
|
1078
1138
|
const language = resolveLanguage(session.user.language, cmsConfig.i18n.supportedLanguages, cmsConfig.i18n.fallbackLanguage);
|
|
1079
1139
|
const resolvedTitle = resolveMultilingualString(section.title.section, language, cmsConfig.i18n.fallbackLanguage);
|
|
1140
|
+
// Returns a field's display value, preferring the localized (`__loc_<name>`) column when
|
|
1141
|
+
// browsing a non-default locale and a translation exists, falling back to the base value.
|
|
1142
|
+
const displayValue = (row, fieldName) => {
|
|
1143
|
+
if (localizedDisplayFieldNames.has(fieldName)) {
|
|
1144
|
+
const localized = row[`__loc_${fieldName}`];
|
|
1145
|
+
if (localized !== null && localized !== undefined)
|
|
1146
|
+
return localized;
|
|
1147
|
+
}
|
|
1148
|
+
return row[fieldName];
|
|
1149
|
+
};
|
|
1150
|
+
// Locale switcher metadata for the browse page. `currentLocale` reflects the resolved
|
|
1151
|
+
// browse locale (defaulting to the base locale when none/invalid was requested).
|
|
1152
|
+
const browseLocalization = localeResult.localizationEnabled
|
|
1153
|
+
? {
|
|
1154
|
+
locales: localeResult.availableLocales,
|
|
1155
|
+
defaultLocale: localeResult.defaultLocale,
|
|
1156
|
+
currentLocale: localeResult.resolvedLocale ?? localeResult.defaultLocale,
|
|
1157
|
+
localeSwitcherEnabled: localeResult.availableLocales.length > 1 &&
|
|
1158
|
+
(section.hasLocalizedContent === true || process.env.NODE_ENV === 'development'),
|
|
1159
|
+
}
|
|
1160
|
+
: null;
|
|
1080
1161
|
return {
|
|
1081
1162
|
section: {
|
|
1082
1163
|
// tableName: tableName,
|
|
@@ -1087,6 +1168,7 @@ export const getBrowsePage = async (session, sectionName, page = 1, q) => {
|
|
|
1087
1168
|
name: section.name,
|
|
1088
1169
|
title: resolvedTitle,
|
|
1089
1170
|
},
|
|
1171
|
+
localization: browseLocalization,
|
|
1090
1172
|
items: rows.map((row) => {
|
|
1091
1173
|
// Custom browse page implementation: if browse.fields is configured,
|
|
1092
1174
|
// return the specified fields plus default fields (id, headingTitle, coverPhoto, createdAt, createdBy, permission).
|
|
@@ -1096,26 +1178,28 @@ export const getBrowsePage = async (session, sectionName, page = 1, q) => {
|
|
|
1096
1178
|
const item = {
|
|
1097
1179
|
// Always include default fields
|
|
1098
1180
|
id: row[section.db.identifier.name],
|
|
1099
|
-
headingTitle: row
|
|
1100
|
-
coverPhoto: section.coverPhotoField ? row
|
|
1181
|
+
headingTitle: displayValue(row, section.headingField.name),
|
|
1182
|
+
coverPhoto: section.coverPhotoField ? displayValue(row, section.coverPhotoField.name) : null,
|
|
1101
1183
|
createdAt: row['created_at'],
|
|
1102
1184
|
createdBy: row['created_by'],
|
|
1103
1185
|
permission: row.permission,
|
|
1186
|
+
locales: localesByItemId.get(String(row[section.db.identifier.name])) ?? [],
|
|
1104
1187
|
};
|
|
1105
1188
|
// Add configured browse fields
|
|
1106
1189
|
for (const field of section.browse.fields) {
|
|
1107
|
-
item[field.name] = row
|
|
1190
|
+
item[field.name] = displayValue(row, field.name) ?? null;
|
|
1108
1191
|
}
|
|
1109
1192
|
return item;
|
|
1110
1193
|
}
|
|
1111
1194
|
// Default browse page fields (used by the standard CMS browse page)
|
|
1112
1195
|
return {
|
|
1113
1196
|
id: row[section.db.identifier.name],
|
|
1114
|
-
headingTitle: row
|
|
1115
|
-
coverPhoto: section.coverPhotoField ? row
|
|
1197
|
+
headingTitle: displayValue(row, section.headingField.name),
|
|
1198
|
+
coverPhoto: section.coverPhotoField ? displayValue(row, section.coverPhotoField.name) : null,
|
|
1116
1199
|
createdAt: row['created_at'],
|
|
1117
1200
|
createdBy: row['created_by'],
|
|
1118
1201
|
permission: row.permission,
|
|
1202
|
+
locales: localesByItemId.get(String(row[section.db.identifier.name])) ?? [],
|
|
1119
1203
|
};
|
|
1120
1204
|
}),
|
|
1121
1205
|
totalCount: totalCountRows[0].total,
|