This commit is contained in:
James
2022-10-06 13:11:25 -04:00
parent debcb003bb
commit b4becd1493
8 changed files with 322 additions and 9 deletions

View File

@@ -70,7 +70,7 @@ async function find<T extends TypeWithID = any>(incomingArgs: Arguments): Promis
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where} = {
const queryToBuild: { where?: Where } = {
where: {
and: [],
},
@@ -128,7 +128,13 @@ async function find<T extends TypeWithID = any>(incomingArgs: Arguments): Promis
// Find
// /////////////////////////////////////
const [sortProperty, sortOrder] = buildSortParam(args.sort, collectionConfig.timestamps);
const [sortProperty, sortOrder] = buildSortParam({
sort: args.sort,
config: payload.config,
fields: collectionConfig.fields,
timestamps: collectionConfig.timestamps,
locale,
});
const optionsToExecute = {
page: page || 1,

View File

@@ -9,6 +9,7 @@ import { buildSortParam } from '../../mongoose/buildSortParam';
import { PaginatedDocs } from '../../mongoose/types';
import { TypeWithVersion } from '../../versions/types';
import { afterRead } from '../../fields/hooks/afterRead';
import { buildVersionCollectionFields } from '../../versions/buildCollectionFields';
export type Arguments = {
collection: Collection
@@ -46,7 +47,7 @@ async function findVersions<T extends TypeWithVersion<T> = any>(args: Arguments)
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where} = {};
const queryToBuild: { where?: Where } = {};
let useEstimatedCount = false;
if (where) {
@@ -89,7 +90,13 @@ async function findVersions<T extends TypeWithVersion<T> = any>(args: Arguments)
// Find
// /////////////////////////////////////
const [sortProperty, sortOrder] = buildSortParam(args.sort || '-updatedAt', true);
const [sortProperty, sortOrder] = buildSortParam({
sort: args.sort || '-updatedAt',
fields: buildVersionCollectionFields(collectionConfig),
timestamps: true,
config: payload.config,
locale,
});
const optionsToExecute = {
page: page || 1,

View File

@@ -9,6 +9,7 @@ import { buildSortParam } from '../../mongoose/buildSortParam';
import { TypeWithVersion } from '../../versions/types';
import { SanitizedGlobalConfig } from '../config/types';
import { afterRead } from '../../fields/hooks/afterRead';
import { buildVersionGlobalFields } from '../../versions/buildGlobalFields';
export type Arguments = {
globalConfig: SanitizedGlobalConfig
@@ -44,7 +45,7 @@ async function findVersions<T extends TypeWithVersion<T> = any>(args: Arguments)
// Access
// /////////////////////////////////////
const queryToBuild: { where?: Where} = {};
const queryToBuild: { where?: Where } = {};
let useEstimatedCount = false;
if (where) {
@@ -87,7 +88,13 @@ async function findVersions<T extends TypeWithVersion<T> = any>(args: Arguments)
// Find
// /////////////////////////////////////
const [sortProperty, sortOrder] = buildSortParam(args.sort || '-updatedAt', true);
const [sortProperty, sortOrder] = buildSortParam({
sort: args.sort || '-updatedAt',
fields: buildVersionGlobalFields(globalConfig),
timestamps: true,
config: payload.config,
locale,
});
const optionsToExecute = {
page: page || 1,

View File

@@ -1,4 +1,16 @@
export const buildSortParam = (sort: string, timestamps: boolean) => {
import { Config } from '../config/types';
import { getLocalizedSortProperty } from './getLocalizedSortProperty';
import { Field } from '../fields/config/types';
type Args = {
sort: string
config: Config
fields: Field[]
timestamps: boolean
locale: string
}
export const buildSortParam = ({ sort, config, fields, timestamps, locale }: Args): [string, string] => {
let sortProperty: string;
let sortOrder = 'desc';
@@ -15,7 +27,16 @@ export const buildSortParam = (sort: string, timestamps: boolean) => {
sortOrder = 'asc';
}
if (sortProperty === 'id') sortProperty = '_id';
if (sortProperty === 'id') {
sortProperty = '_id';
} else {
sortProperty = getLocalizedSortProperty({
segments: sortProperty.split('.'),
config,
fields,
locale,
});
}
return [sortProperty, sortOrder];
};

View File

@@ -0,0 +1,182 @@
import { Config } from '../config/types';
import { getLocalizedSortProperty } from './getLocalizedSortProperty';
const config = {
localization: {
locales: ['en', 'es'],
},
} as Config;
describe('get localized sort property', () => {
it('passes through a non-localized sort property', () => {
const result = getLocalizedSortProperty({
segments: ['title'],
config,
fields: [
{
name: 'title',
type: 'text',
},
],
locale: 'en',
});
expect(result).toStrictEqual('title');
});
it('properly localizes an un-localized sort property', () => {
const result = getLocalizedSortProperty({
segments: ['title'],
config,
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
locale: 'en',
});
expect(result).toStrictEqual('title.en');
});
it('keeps specifically asked-for localized sort properties', () => {
const result = getLocalizedSortProperty({
segments: ['title', 'es'],
config,
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
locale: 'en',
});
expect(result).toStrictEqual('title.es');
});
it('properly localizes nested sort properties', () => {
const result = getLocalizedSortProperty({
segments: ['group', 'title'],
config,
fields: [
{
name: 'group',
type: 'group',
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
},
],
locale: 'en',
});
expect(result).toStrictEqual('group.title.en');
});
it('keeps requested locale with nested sort properties', () => {
const result = getLocalizedSortProperty({
segments: ['group', 'title', 'es'],
config,
fields: [
{
name: 'group',
type: 'group',
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
},
],
locale: 'en',
});
expect(result).toStrictEqual('group.title.es');
});
it('properly localizes field within row', () => {
const result = getLocalizedSortProperty({
segments: ['title'],
config,
fields: [
{
type: 'row',
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
},
],
locale: 'en',
});
expect(result).toStrictEqual('title.en');
});
it('properly localizes field within named tab', () => {
const result = getLocalizedSortProperty({
segments: ['tab', 'title'],
config,
fields: [
{
type: 'tabs',
tabs: [
{
name: 'tab',
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
},
],
},
],
locale: 'en',
});
expect(result).toStrictEqual('tab.title.en');
});
it('properly localizes field within unnamed tab', () => {
const result = getLocalizedSortProperty({
segments: ['title'],
config,
fields: [
{
type: 'tabs',
tabs: [
{
label: 'Tab',
fields: [
{
name: 'title',
type: 'text',
localized: true,
},
],
},
],
},
],
locale: 'en',
});
expect(result).toStrictEqual('title.en');
});
});

View File

@@ -0,0 +1,89 @@
import { Config } from '../config/types';
import { Field, fieldAffectsData, fieldIsPresentationalOnly } from '../fields/config/types';
import flattenTopLevelFields from '../utilities/flattenTopLevelFields';
type Args = {
segments: string[]
config: Config
fields: Field[]
locale: string
result?: string
}
export const getLocalizedSortProperty = ({
segments: incomingSegments,
config,
fields: incomingFields,
locale,
result: incomingResult,
}: Args): string => {
// If localization is not enabled, accept exactly
// what is sent in
if (!config.localization) {
return incomingSegments.join('.');
}
// Flatten incoming fields (row, etc)
const fields = flattenTopLevelFields(incomingFields);
const segments = [...incomingSegments];
// Retrieve first segment, and remove from segments
const firstSegment = segments.shift();
// Attempt to find a matched field
const matchedField = fields.find((field) => fieldAffectsData(field) && field.name === firstSegment);
if (matchedField && !fieldIsPresentationalOnly(matchedField)) {
let nextFields: Field[];
const remainingSegments = [...segments];
let localizedSegment = matchedField.name;
if (matchedField.localized) {
// Check to see if next segment is a locale
if (segments.length > 0) {
const nextSegmentIsLocale = config.localization.locales.includes(remainingSegments[0]);
// If next segment is locale, remove it from remaining segments
// and use it to localize the current segment
if (nextSegmentIsLocale) {
const nextSegment = remainingSegments.shift();
localizedSegment = `${matchedField.name}.${nextSegment}`;
}
} else {
// If no more segments, but field is localized, use default locale
localizedSegment = `${matchedField.name}.${locale}`;
}
}
// If there are subfields, pass them through
if (matchedField.type === 'tab' || matchedField.type === 'group' || matchedField.type === 'array') {
nextFields = matchedField.fields;
}
if (matchedField.type === 'blocks') {
nextFields = matchedField.blocks.reduce((flattenedBlockFields, block) => {
return [
...flattenedBlockFields,
...block.fields.filter((blockField) => (fieldAffectsData(blockField) && (blockField.name !== 'blockType' && blockField.name !== 'blockName')) || !fieldAffectsData(blockField)),
];
}, []);
}
const result = incomingResult ? `${incomingResult}.${localizedSegment}` : localizedSegment;
if (nextFields) {
return getLocalizedSortProperty({
segments: remainingSegments,
config,
fields: nextFields,
locale,
result,
});
}
return result;
}
return incomingSegments.join('.');
};

View File

@@ -30,7 +30,7 @@ const flattenFields = (fields: Field[], keepPresentationalFields?: boolean): (Fi
...field.tabs.reduce((tabFields, tab) => {
return [
...tabFields,
...(tabHasName(tab) ? [tab] : flattenFields(tab.fields, keepPresentationalFields)),
...(tabHasName(tab) ? [{ ...tab, type: 'tab' }] : flattenFields(tab.fields, keepPresentationalFields)),
];
}, []),
];

View File

@@ -56,6 +56,7 @@ export default buildConfig({
name: 'title',
type: 'text',
localized: true,
index: true,
},
{
name: 'description',