fix: use correct locale when querying relationships for list view (#2438)
* chore: use correct locale when querying relationship for list view * chore: make sure the relationships are re-queried when the locale changes * chore: cleans up localization test ts-types --------- Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import { useConfig } from '../../../../utilities/Config';
|
||||
import { TypeWithID } from '../../../../../../collections/config/types';
|
||||
import { reducer } from './reducer';
|
||||
import useDebounce from '../../../../../hooks/useDebounce';
|
||||
import { useLocale } from '../../../../utilities/Locale';
|
||||
|
||||
// documents are first set to null when requested
|
||||
// set to false when no doc is returned
|
||||
@@ -30,27 +31,31 @@ export const RelationshipProvider: React.FC<{ children?: React.ReactNode }> = ({
|
||||
const debouncedDocuments = useDebounce(documents, 100);
|
||||
const config = useConfig();
|
||||
const { i18n } = useTranslation();
|
||||
const locale = useLocale();
|
||||
const prevLocale = useRef(locale);
|
||||
|
||||
const {
|
||||
serverURL,
|
||||
routes: { api },
|
||||
} = config;
|
||||
|
||||
useEffect(() => {
|
||||
const loadRelationshipDocs = useCallback(async (reloadAll = false) => {
|
||||
Object.entries(debouncedDocuments).forEach(async ([slug, docs]) => {
|
||||
const idsToLoad: (string | number)[] = [];
|
||||
|
||||
Object.entries(docs).forEach(([id, value]) => {
|
||||
if (value === null) {
|
||||
if (value === null || reloadAll) {
|
||||
idsToLoad.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (idsToLoad.length > 0) {
|
||||
const url = `${serverURL}${api}/${slug}`;
|
||||
const params = {
|
||||
depth: 0,
|
||||
'where[id][in]': idsToLoad,
|
||||
locale: i18n.language,
|
||||
locale,
|
||||
limit: 250,
|
||||
};
|
||||
|
||||
@@ -61,6 +66,7 @@ export const RelationshipProvider: React.FC<{ children?: React.ReactNode }> = ({
|
||||
'Accept-Language': i18n.language,
|
||||
},
|
||||
});
|
||||
|
||||
if (result.ok) {
|
||||
const json = await result.json();
|
||||
if (json.docs) {
|
||||
@@ -71,7 +77,12 @@ export const RelationshipProvider: React.FC<{ children?: React.ReactNode }> = ({
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [i18n, serverURL, api, debouncedDocuments]);
|
||||
}, [debouncedDocuments, serverURL, api, i18n, locale]);
|
||||
|
||||
useEffect(() => {
|
||||
loadRelationshipDocs(locale && prevLocale.current !== locale);
|
||||
prevLocale.current = locale;
|
||||
}, [locale, loadRelationshipDocs]);
|
||||
|
||||
const getRelationships = useCallback(async (relationships: { relationTo: string, value: number | string }[]) => {
|
||||
dispatchDocuments({ type: 'REQUEST', docs: relationships });
|
||||
|
||||
@@ -20,7 +20,7 @@ export type LocalizedPostAllLocale = LocalizedPost & {
|
||||
};
|
||||
};
|
||||
|
||||
export const slug = 'localized-posts';
|
||||
export const localizedPostsSlug = 'localized-posts';
|
||||
export const withLocalizedRelSlug = 'with-localized-relationship';
|
||||
export const relationshipLocalizedSlug = 'relationship-localized';
|
||||
export const withRequiredLocalizedFields = 'localized-required';
|
||||
@@ -46,13 +46,16 @@ export default buildConfig({
|
||||
{
|
||||
name: 'relation',
|
||||
type: 'relationship',
|
||||
relationTo: slug,
|
||||
relationTo: localizedPostsSlug,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug,
|
||||
slug: localizedPostsSlug,
|
||||
access: openAccess,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
@@ -112,26 +115,26 @@ export default buildConfig({
|
||||
{
|
||||
name: 'localizedRelationship',
|
||||
type: 'relationship',
|
||||
relationTo: slug,
|
||||
relationTo: localizedPostsSlug,
|
||||
},
|
||||
// Relation hasMany
|
||||
{
|
||||
name: 'localizedRelationHasManyField',
|
||||
type: 'relationship',
|
||||
relationTo: slug,
|
||||
relationTo: localizedPostsSlug,
|
||||
hasMany: true,
|
||||
},
|
||||
// Relation multiple relationTo
|
||||
{
|
||||
name: 'localizedRelationMultiRelationTo',
|
||||
type: 'relationship',
|
||||
relationTo: [slug, 'dummy'],
|
||||
relationTo: [localizedPostsSlug, 'dummy'],
|
||||
},
|
||||
// Relation multiple relationTo hasMany
|
||||
{
|
||||
name: 'localizedRelationMultiRelationToHasMany',
|
||||
type: 'relationship',
|
||||
relationTo: [slug, 'dummy'],
|
||||
relationTo: [localizedPostsSlug, 'dummy'],
|
||||
hasMany: true,
|
||||
},
|
||||
],
|
||||
@@ -142,26 +145,26 @@ export default buildConfig({
|
||||
{
|
||||
name: 'relationship',
|
||||
type: 'relationship',
|
||||
relationTo: slug,
|
||||
relationTo: localizedPostsSlug,
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'relationshipHasMany',
|
||||
type: 'relationship',
|
||||
relationTo: slug,
|
||||
relationTo: localizedPostsSlug,
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'relationMultiRelationTo',
|
||||
type: 'relationship',
|
||||
relationTo: [slug, 'dummy'],
|
||||
relationTo: [localizedPostsSlug, 'dummy'],
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'relationMultiRelationToHasMany',
|
||||
type: 'relationship',
|
||||
relationTo: [slug, 'dummy'],
|
||||
relationTo: [localizedPostsSlug, 'dummy'],
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
@@ -197,7 +200,7 @@ export default buildConfig({
|
||||
},
|
||||
],
|
||||
onInit: async (payload) => {
|
||||
const collection = slug;
|
||||
const collection = localizedPostsSlug;
|
||||
|
||||
await payload.create({
|
||||
collection,
|
||||
@@ -269,8 +272,8 @@ export default buildConfig({
|
||||
localizedRelationHasManyField: [localizedRelation.id, localizedRelation2.id],
|
||||
localizedRelationMultiRelationTo: { relationTo: collection, value: localizedRelation.id },
|
||||
localizedRelationMultiRelationToHasMany: [
|
||||
{ relationTo: slug, value: localizedRelation.id },
|
||||
{ relationTo: slug, value: localizedRelation2.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation2.id },
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -282,8 +285,8 @@ export default buildConfig({
|
||||
relationshipHasMany: [localizedRelation.id, localizedRelation2.id],
|
||||
relationMultiRelationTo: { relationTo: collection, value: localizedRelation.id },
|
||||
relationMultiRelationToHasMany: [
|
||||
{ relationTo: slug, value: localizedRelation.id },
|
||||
{ relationTo: slug, value: localizedRelation2.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation2.id },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import payload from '../../src';
|
||||
import type { TypeWithTimestamps } from '../../src/collections/config/types';
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil';
|
||||
import { initPayloadTest } from '../helpers/configHelpers';
|
||||
import { login, saveDocAndAssert } from '../helpers';
|
||||
import type { LocalizedPost } from './payload-types';
|
||||
import { slug } from './config';
|
||||
import { localizedPostsSlug } from './config';
|
||||
import { englishTitle, spanishLocale } from './shared';
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,7 @@ describe('Localization', () => {
|
||||
},
|
||||
});
|
||||
|
||||
url = new AdminUrlUtil(serverURL, slug);
|
||||
url = new AdminUrlUtil(serverURL, localizedPostsSlug);
|
||||
|
||||
const context = await browser.newContext();
|
||||
page = await context.newPage();
|
||||
@@ -100,15 +99,15 @@ describe('Localization', () => {
|
||||
let id;
|
||||
|
||||
beforeAll(async () => {
|
||||
const localizedPost = await payload.create<LocalizedPost>({
|
||||
collection: slug,
|
||||
const localizedPost = await payload.create({
|
||||
collection: localizedPostsSlug,
|
||||
data: {
|
||||
title: englishTitle,
|
||||
},
|
||||
});
|
||||
id = localizedPost.id;
|
||||
await payload.update<LocalizedPost>({
|
||||
collection: slug,
|
||||
await payload.update({
|
||||
collection: localizedPostsSlug,
|
||||
id,
|
||||
locale: spanishLocale,
|
||||
data: {
|
||||
@@ -131,7 +130,7 @@ describe('Localization', () => {
|
||||
});
|
||||
});
|
||||
|
||||
async function fillValues(data: Partial<Omit<LocalizedPost, keyof TypeWithTimestamps>>) {
|
||||
async function fillValues(data: Partial<LocalizedPost>) {
|
||||
const { title: titleVal, description: descVal } = data;
|
||||
|
||||
if (titleVal) await page.locator('#field-title').fill(titleVal);
|
||||
|
||||
@@ -5,12 +5,8 @@ import payload from '../../src';
|
||||
import type {
|
||||
LocalizedPost,
|
||||
WithLocalizedRelationship,
|
||||
LocalizedRequired,
|
||||
RelationshipLocalized,
|
||||
GlobalArray,
|
||||
} from './payload-types';
|
||||
import type { LocalizedPostAllLocale } from './config';
|
||||
import configPromise, { relationshipLocalizedSlug, slug, withLocalizedRelSlug, withRequiredLocalizedFields } from './config';
|
||||
import configPromise, { relationshipLocalizedSlug, localizedPostsSlug, withLocalizedRelSlug, withRequiredLocalizedFields } from './config';
|
||||
import {
|
||||
defaultLocale,
|
||||
englishTitle,
|
||||
@@ -25,7 +21,7 @@ import type { Where } from '../../src/types';
|
||||
import { arrayCollectionSlug } from './collections/Array';
|
||||
import type { Config } from '../../src/config/types';
|
||||
|
||||
const collection = slug;
|
||||
const collection = localizedPostsSlug;
|
||||
let config: Config;
|
||||
|
||||
let serverURL;
|
||||
@@ -250,10 +246,10 @@ describe('Localization', () => {
|
||||
data: {
|
||||
localizedRelationship: localizedRelation.id,
|
||||
localizedRelationHasManyField: [localizedRelation.id, localizedRelation2.id],
|
||||
localizedRelationMultiRelationTo: { relationTo: slug, value: localizedRelation.id },
|
||||
localizedRelationMultiRelationTo: { relationTo: localizedPostsSlug, value: localizedRelation.id },
|
||||
localizedRelationMultiRelationToHasMany: [
|
||||
{ relationTo: slug, value: localizedRelation.id },
|
||||
{ relationTo: slug, value: localizedRelation2.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation.id },
|
||||
{ relationTo: localizedPostsSlug, value: localizedRelation2.id },
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -666,7 +662,7 @@ describe('Localization', () => {
|
||||
});
|
||||
|
||||
const result = await payload.findByID({
|
||||
collection: slug,
|
||||
collection: localizedPostsSlug,
|
||||
id: createResult.id,
|
||||
locale: 'all',
|
||||
});
|
||||
|
||||
@@ -5,22 +5,20 @@
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
export interface Config {}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global-array".
|
||||
*/
|
||||
export interface GlobalArray {
|
||||
id: string;
|
||||
array: {
|
||||
text?: string;
|
||||
id?: string;
|
||||
}[];
|
||||
export interface Config {
|
||||
collections: {
|
||||
users: User;
|
||||
'localized-posts': LocalizedPost;
|
||||
'array-fields': ArrayField;
|
||||
'localized-required': LocalizedRequired;
|
||||
'with-localized-relationship': WithLocalizedRelationship;
|
||||
'relationship-localized': RelationshipLocalized;
|
||||
dummy: Dummy;
|
||||
};
|
||||
globals: {
|
||||
'global-array': GlobalArray;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
relation?: string | LocalizedPost;
|
||||
@@ -31,11 +29,8 @@ export interface User {
|
||||
lockUntil?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
password?: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "localized-posts".
|
||||
*/
|
||||
export interface LocalizedPost {
|
||||
id: string;
|
||||
title?: string;
|
||||
@@ -43,10 +38,15 @@ export interface LocalizedPost {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "localized-required".
|
||||
*/
|
||||
export interface ArrayField {
|
||||
id: string;
|
||||
items?: {
|
||||
text: string;
|
||||
id?: string;
|
||||
}[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
export interface LocalizedRequired {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -67,10 +67,6 @@ export interface LocalizedRequired {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "with-localized-relationship".
|
||||
*/
|
||||
export interface WithLocalizedRelationship {
|
||||
id: string;
|
||||
localizedRelationship?: string | LocalizedPost;
|
||||
@@ -108,20 +104,12 @@ export interface WithLocalizedRelationship {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "dummy".
|
||||
*/
|
||||
export interface Dummy {
|
||||
id: string;
|
||||
name?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "relationship-localized".
|
||||
*/
|
||||
export interface RelationshipLocalized {
|
||||
id: string;
|
||||
relationship?: string | LocalizedPost;
|
||||
@@ -159,3 +147,10 @@ export interface RelationshipLocalized {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
export interface GlobalArray {
|
||||
id: string;
|
||||
array?: {
|
||||
text?: string;
|
||||
id?: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ const collectionWithName = (collectionSlug: string): CollectionConfig => {
|
||||
return {
|
||||
slug: collectionSlug,
|
||||
access: openAccess,
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
|
||||
Reference in New Issue
Block a user