mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 08:19:07 +00:00
fix: cm relation bugs (#19842)
* fix: relations * fix: hardcode english locale * fix(cm): don't try and be clever with caching relations * fix: locale when target is not localized --------- Co-authored-by: Josh <37798644+joshuaellis@users.noreply.github.com>
This commit is contained in:
parent
49e84a90ad
commit
66c1011328
@ -61,10 +61,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
||||
}),
|
||||
invalidatesTags: (result, _error, { model }) => [
|
||||
{ type: 'Document', id: `${model}_LIST` },
|
||||
{
|
||||
type: 'Relations',
|
||||
id: `${model}_${result?.data.documentId}`,
|
||||
},
|
||||
'Relations',
|
||||
],
|
||||
}),
|
||||
deleteDocument: builder.mutation<
|
||||
@ -127,10 +124,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
||||
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model,
|
||||
},
|
||||
{ type: 'Document', id: `${model}_LIST` },
|
||||
{
|
||||
type: 'Relations',
|
||||
id: `${model}_${documentId}`,
|
||||
},
|
||||
'Relations',
|
||||
];
|
||||
},
|
||||
}),
|
||||
@ -278,10 +272,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
||||
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model,
|
||||
},
|
||||
{ type: 'Document', id: `${model}_LIST` },
|
||||
{
|
||||
type: 'Relations',
|
||||
id: `${model}_${documentId}`,
|
||||
},
|
||||
'Relations',
|
||||
];
|
||||
},
|
||||
}),
|
||||
@ -321,10 +312,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
||||
type: 'Document',
|
||||
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model,
|
||||
},
|
||||
{
|
||||
type: 'Relations',
|
||||
id: `${model}_${documentId}`,
|
||||
},
|
||||
'Relations',
|
||||
];
|
||||
},
|
||||
}),
|
||||
|
@ -97,9 +97,7 @@ const relationsApi = contentManagerApi.injectEndpoints({
|
||||
return response;
|
||||
}
|
||||
},
|
||||
providesTags: (result, error, args) => [
|
||||
{ type: 'Relations', id: `${args.model}_${args.id}` },
|
||||
],
|
||||
providesTags: ['Relations'],
|
||||
}),
|
||||
searchRelations: build.query<
|
||||
Contracts.Relations.FindAvailable.Response,
|
||||
|
@ -78,42 +78,66 @@ const addStatusToRelations = async (uid: Common.UID.ContentType, relations: Rela
|
||||
});
|
||||
};
|
||||
|
||||
const getPublishedAtClause = (
|
||||
status: Documents.Params.PublicationStatus.Kind,
|
||||
sourceUid: Common.UID.Schema,
|
||||
targetUid: Common.UID.ContentType
|
||||
) => {
|
||||
const sourceModel = strapi.getModel(sourceUid);
|
||||
const targetModel = strapi.getModel(targetUid);
|
||||
const getPublishedAtClause = (status: string, uid: Common.UID.Schema) => {
|
||||
const model = strapi.getModel(uid);
|
||||
|
||||
/**
|
||||
* If target does not have dp, status should be published.
|
||||
* As it only contains entries with publishedAt set.
|
||||
* If dp is disabled, ignore the filter
|
||||
*/
|
||||
if (!contentTypes.hasDraftAndPublish(targetModel)) {
|
||||
if (!model || !contentTypes.hasDraftAndPublish(model)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* If source does not have dp, status should be draft.
|
||||
* Both draft and publish entries are connectable, but we are doing it like
|
||||
* this atm.
|
||||
*/
|
||||
if (!contentTypes.hasDraftAndPublish(sourceModel)) {
|
||||
return { $null: true };
|
||||
}
|
||||
|
||||
// Prioritize the draft status in case it's not provided
|
||||
return status === 'published' ? { $notNull: true } : { $null: true };
|
||||
};
|
||||
|
||||
const validateLocale = (
|
||||
sourceUid: Common.UID.Schema,
|
||||
targetUid: Common.UID.ContentType,
|
||||
locale?: string
|
||||
) => {
|
||||
const sourceModel = strapi.getModel(sourceUid);
|
||||
const targetModel = strapi.getModel(targetUid);
|
||||
|
||||
const isLocalized = strapi.plugin('i18n').service('content-types').isLocalizedContentType;
|
||||
const isSourceLocalized = isLocalized(sourceModel);
|
||||
const isTargetLocalized = isLocalized(targetModel);
|
||||
|
||||
let validatedLocale = locale;
|
||||
|
||||
if (!targetModel || !isTargetLocalized) validatedLocale = undefined;
|
||||
|
||||
return {
|
||||
locale: validatedLocale,
|
||||
isSourceLocalized,
|
||||
isTargetLocalized,
|
||||
};
|
||||
};
|
||||
|
||||
const validateStatus = (
|
||||
sourceUid: Common.UID.Schema,
|
||||
status?: Documents.Params.PublicationStatus.Kind
|
||||
) => {
|
||||
const sourceModel = strapi.getModel(sourceUid);
|
||||
|
||||
const isDP = contentTypes.hasDraftAndPublish;
|
||||
const isSourceDP = isDP(sourceModel);
|
||||
|
||||
// Default to draft if not set
|
||||
if (!isSourceDP) return { status: undefined };
|
||||
|
||||
switch (status) {
|
||||
case 'published':
|
||||
return { status: 'published' };
|
||||
default:
|
||||
// Assign to draft if the status is not valid
|
||||
return { status: 'draft' };
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
async extractAndValidateRequestInfo(
|
||||
ctx: any,
|
||||
id?: Entity.ID,
|
||||
locale?: Documents.Params.Locale,
|
||||
status?: Documents.Params.PublicationStatus.Kind
|
||||
) {
|
||||
async extractAndValidateRequestInfo(ctx: any, id?: Entity.ID) {
|
||||
const { userAbility } = ctx.state;
|
||||
const { model, targetField } = ctx.params;
|
||||
|
||||
@ -129,6 +153,16 @@ export default {
|
||||
);
|
||||
}
|
||||
|
||||
const sourceUid = model;
|
||||
const targetUid = attribute.target;
|
||||
|
||||
const { locale, isSourceLocalized, isTargetLocalized } = validateLocale(
|
||||
sourceUid,
|
||||
targetUid,
|
||||
ctx.request?.query?.locale
|
||||
);
|
||||
const { status } = validateStatus(sourceUid, ctx.request?.query?.status);
|
||||
|
||||
const permissionChecker = getService('permission-checker').create({
|
||||
userAbility,
|
||||
model,
|
||||
@ -150,13 +184,9 @@ export default {
|
||||
where.documentId = id;
|
||||
|
||||
if (status) {
|
||||
where.publishedAt = getPublishedAtClause(status, sourceSchema.uid, attribute.target);
|
||||
where.publishedAt = getPublishedAtClause(status, sourceUid);
|
||||
}
|
||||
|
||||
const isSourceLocalized = strapi
|
||||
.plugin('i18n')
|
||||
.service('content-types')
|
||||
.isLocalizedContentType(sourceSchema);
|
||||
if (locale && isSourceLocalized) {
|
||||
where.locale = locale;
|
||||
}
|
||||
@ -197,7 +227,7 @@ export default {
|
||||
? await getService('components').findConfiguration(sourceSchema)
|
||||
: await getService('content-types').findConfiguration(sourceSchema);
|
||||
|
||||
const targetSchema = strapi.getModel(attribute.target);
|
||||
const targetSchema = strapi.getModel(targetUid);
|
||||
|
||||
const mainField = flow(
|
||||
prop(`metadatas.${targetField}.edit.mainField`),
|
||||
@ -212,18 +242,14 @@ export default {
|
||||
'documentId',
|
||||
]);
|
||||
|
||||
const isTargetLocalized = strapi
|
||||
.plugin('i18n')
|
||||
.service('content-types')
|
||||
.isLocalizedContentType(targetSchema);
|
||||
|
||||
// TODO: Locale is always present, should we set it regardless?
|
||||
if (isTargetLocalized) {
|
||||
fieldsToSelect.push('locale');
|
||||
}
|
||||
|
||||
return {
|
||||
entryId,
|
||||
locale,
|
||||
status,
|
||||
attribute,
|
||||
fieldsToSelect,
|
||||
mainField,
|
||||
@ -242,12 +268,12 @@ export default {
|
||||
*/
|
||||
async findAvailable(ctx: any) {
|
||||
const { id } = ctx.request.query;
|
||||
const locale = ctx.request?.query?.locale || null;
|
||||
const status = ctx.request?.query?.status;
|
||||
|
||||
await validateFindAvailable(ctx.request.query);
|
||||
|
||||
const {
|
||||
locale,
|
||||
status,
|
||||
targetField,
|
||||
fieldsToSelect,
|
||||
mainField,
|
||||
@ -258,7 +284,7 @@ export default {
|
||||
schema: { uid: targetUid },
|
||||
isLocalized: isTargetLocalized,
|
||||
},
|
||||
} = await this.extractAndValidateRequestInfo(ctx, id, locale, status);
|
||||
} = await this.extractAndValidateRequestInfo(ctx, id);
|
||||
|
||||
const { idsToOmit, idsToInclude, _q, ...query } = ctx.request.query;
|
||||
|
||||
@ -278,7 +304,7 @@ export default {
|
||||
// If no status is requested, we find all the draft relations and later update them
|
||||
// with the latest available status
|
||||
addFiltersClause(queryParams, {
|
||||
publishedAt: getPublishedAtClause(status, sourceUid, targetUid),
|
||||
publishedAt: getPublishedAtClause(status, targetUid),
|
||||
});
|
||||
|
||||
// We will only filter by locale if the target content type is localized
|
||||
@ -316,7 +342,7 @@ export default {
|
||||
|
||||
// Add the status and locale filters if they are provided
|
||||
if (status) {
|
||||
where[`${alias}.published_at`] = getPublishedAtClause(status, sourceUid, targetUid);
|
||||
where[`${alias}.published_at`] = getPublishedAtClause(status, targetUid);
|
||||
}
|
||||
if (filterByLocale) {
|
||||
where[`${alias}.locale`] = locale;
|
||||
@ -374,9 +400,6 @@ export default {
|
||||
|
||||
await validateFindExisting(ctx.request.query);
|
||||
|
||||
const locale = ctx.request?.query?.locale || null;
|
||||
const status = ctx.request?.query?.status;
|
||||
|
||||
const {
|
||||
entryId,
|
||||
attribute,
|
||||
@ -388,7 +411,7 @@ export default {
|
||||
target: {
|
||||
schema: { uid: targetUid },
|
||||
},
|
||||
} = await this.extractAndValidateRequestInfo(ctx, id, locale, status);
|
||||
} = await this.extractAndValidateRequestInfo(ctx, id);
|
||||
|
||||
const permissionQuery = await getService('permission-checker')
|
||||
.create({ userAbility, model: targetUid })
|
||||
@ -443,7 +466,12 @@ export default {
|
||||
const relationsUnion = uniqBy('id', concat(sanitizedRes.results, res.results));
|
||||
|
||||
ctx.body = {
|
||||
pagination: res.pagination,
|
||||
pagination: res.pagination || {
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
pageSize: 10,
|
||||
total: relationsUnion.length,
|
||||
},
|
||||
results: await addStatusToRelations(targetUid, relationsUnion),
|
||||
};
|
||||
},
|
||||
|
@ -9,7 +9,8 @@ export const isLocalizedContentType = (uid: Common.UID.Schema) => {
|
||||
|
||||
export const getDefaultLocale = () => {
|
||||
// TODO: V5 make this more performant
|
||||
return strapi.plugin('i18n').service('locales').getDefaultLocale();
|
||||
// return strapi.plugin('i18n').service('locales').getDefaultLocale();
|
||||
return 'en';
|
||||
};
|
||||
|
||||
export const getRelationTargetLocale = (
|
||||
|
Loading…
x
Reference in New Issue
Block a user