mirror of
https://github.com/strapi/strapi.git
synced 2026-01-06 04:03:25 +00:00
fix: unidirectional sync for non dp source
This commit is contained in:
parent
7002f0b916
commit
f8a68bc03b
@ -501,8 +501,8 @@ const transformData = (data: Record<string, any>): any => {
|
||||
}
|
||||
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
if ('api_data' in data) {
|
||||
return data.api_data;
|
||||
if ('apiData' in data) {
|
||||
return data.apiData;
|
||||
}
|
||||
|
||||
return mapValues(transformData)(data);
|
||||
|
||||
@ -86,7 +86,7 @@ function useHandleDisconnect(fieldName: string, consumerName: string) {
|
||||
|
||||
addFieldRow(`${fieldName}.disconnect`, {
|
||||
id: relation.id,
|
||||
api_data: {
|
||||
apiData: {
|
||||
documentId: relation.documentId,
|
||||
},
|
||||
});
|
||||
@ -150,10 +150,10 @@ const RelationsField = React.forwardRef<HTMLDivElement, RelationsFieldProps>(
|
||||
const isMorph = props.attribute.relation.toLowerCase().includes('morph');
|
||||
const isDisabled = isMorph || disabled;
|
||||
|
||||
const { id: componentId, uid: componentUID } = useComponent(
|
||||
'RelationsField',
|
||||
({ uid, id }) => ({ id, uid })
|
||||
);
|
||||
const { componentId, componentUID } = useComponent('RelationsField', ({ uid, id }) => ({
|
||||
componentId: id,
|
||||
componentUID: uid,
|
||||
}));
|
||||
|
||||
/**
|
||||
* We'll always have a documentId in a created entry, so we look for a componentId first.
|
||||
@ -267,7 +267,7 @@ const RelationsField = React.forwardRef<HTMLDivElement, RelationsFieldProps>(
|
||||
|
||||
const item = {
|
||||
id: relation.id,
|
||||
api_data: {
|
||||
apiData: {
|
||||
documentId: relation.documentId,
|
||||
locale: relation.locale,
|
||||
},
|
||||
|
||||
@ -458,7 +458,10 @@ export default {
|
||||
ordering: 'desc',
|
||||
});
|
||||
|
||||
const relationsUnion = uniqBy('documentId', concat(sanitizedRes.results, res.results));
|
||||
const relationsUnion = uniqBy(
|
||||
(res: any) => `${res.documentId}-${res.locale}`,
|
||||
concat(sanitizedRes.results, res.results)
|
||||
);
|
||||
|
||||
ctx.body = {
|
||||
pagination: res.pagination || {
|
||||
|
||||
@ -291,7 +291,10 @@ export const createContentTypeRepository: RepositoryFactoryMethod = (uid) => {
|
||||
]);
|
||||
|
||||
// Load any unidirectional relation targetting the old published entries
|
||||
const relationsToSync = await unidirectionalRelations.load(uid, oldPublishedVersions);
|
||||
const relationsToSync = await unidirectionalRelations.load(uid, {
|
||||
draftVersions: draftsToPublish,
|
||||
publishedVersions: oldPublishedVersions,
|
||||
});
|
||||
|
||||
// Delete old published versions
|
||||
await async.map(oldPublishedVersions, (entry: any) => entries.delete(entry.id));
|
||||
@ -302,7 +305,11 @@ export const createContentTypeRepository: RepositoryFactoryMethod = (uid) => {
|
||||
);
|
||||
|
||||
// Sync unidirectional relations with the new published entries
|
||||
await unidirectionalRelations.sync(oldPublishedVersions, publishedEntries, relationsToSync);
|
||||
await unidirectionalRelations.sync(
|
||||
[...oldPublishedVersions, ...draftsToPublish],
|
||||
publishedEntries,
|
||||
relationsToSync
|
||||
);
|
||||
|
||||
publishedEntries.forEach(emitEvent('entry.publish'));
|
||||
|
||||
@ -358,7 +365,10 @@ export const createContentTypeRepository: RepositoryFactoryMethod = (uid) => {
|
||||
]);
|
||||
|
||||
// Load any unidirectional relation targeting the old drafts
|
||||
const relationsToSync = await unidirectionalRelations.load(uid, oldDrafts);
|
||||
const relationsToSync = await unidirectionalRelations.load(uid, {
|
||||
draftVersions: [],
|
||||
publishedVersions: oldDrafts,
|
||||
});
|
||||
|
||||
// Delete old drafts
|
||||
await async.map(oldDrafts, (entry: any) => entries.delete(entry.id));
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
/* eslint-disable no-continue */
|
||||
import { keyBy } from 'lodash/fp';
|
||||
import { keyBy, omit } from 'lodash/fp';
|
||||
|
||||
import { UID, Schema } from '@strapi/types';
|
||||
|
||||
interface LoadContext {
|
||||
publishedVersions: { id: string; locale: string }[];
|
||||
draftVersions: { id: string; locale: string }[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads lingering relations that need to be updated when overriding a published or draft entry.
|
||||
* This is necessary because the relations are uni-directional and the target entry is not aware of the source entry.
|
||||
* This is not the case for bi-directional relations, where the target entry is also linked to the source entry.
|
||||
*
|
||||
* @param uid The content type uid
|
||||
* @param oldEntries The old entries that are being overridden
|
||||
* @returns An array of relations that need to be updated with the join table reference.
|
||||
*/
|
||||
const load = async (uid: UID.ContentType, oldEntries: { id: string; locale: string }[]) => {
|
||||
const load = async (uid: UID.ContentType, { publishedVersions, draftVersions }: LoadContext) => {
|
||||
const updates = [] as any;
|
||||
|
||||
// Iterate all components and content types to find relations that need to be updated
|
||||
@ -27,29 +28,61 @@ const load = async (uid: UID.ContentType, oldEntries: { id: string; locale: stri
|
||||
/**
|
||||
* Only consider unidirectional relations
|
||||
*/
|
||||
if (attribute.type !== 'relation') continue;
|
||||
if (attribute.target !== uid) continue;
|
||||
if (attribute.inversedBy || attribute.mappedBy) continue;
|
||||
const joinTable = attribute.joinTable;
|
||||
if (
|
||||
attribute.type !== 'relation' ||
|
||||
attribute.target !== uid ||
|
||||
attribute.inversedBy ||
|
||||
attribute.mappedBy
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: joinColumn relations
|
||||
if (!joinTable) continue;
|
||||
const joinTable = attribute.joinTable;
|
||||
if (!joinTable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { name } = joinTable.inverseJoinColumn;
|
||||
|
||||
/**
|
||||
* Load all relations that need to be updated
|
||||
*/
|
||||
const oldEntriesIds = oldEntries.map((entry) => entry.id);
|
||||
const relations = await strapi.db
|
||||
|
||||
const oldPublishedByLocale = keyBy('locale', publishedVersions);
|
||||
|
||||
// NOTE: when the model has draft and publish, we can assume relation are only draft to draft & published to published
|
||||
const oldEntriesIds = publishedVersions.map((entry) => entry.id);
|
||||
|
||||
const oldPublishedRelations = await strapi.db
|
||||
.getConnection()
|
||||
.select('*')
|
||||
.from(joinTable.name)
|
||||
.whereIn(name, oldEntriesIds)
|
||||
.transacting(trx);
|
||||
|
||||
if (relations.length === 0) continue;
|
||||
if (oldPublishedRelations.length > 0) {
|
||||
updates.push({ joinTable, relations: oldPublishedRelations });
|
||||
}
|
||||
|
||||
updates.push({ joinTable, relations });
|
||||
if (!model.options?.draftAndPublish) {
|
||||
const oldEntriesIds = draftVersions
|
||||
.filter((entry) => {
|
||||
return !oldPublishedByLocale[entry.locale];
|
||||
})
|
||||
.map((entry) => entry.id);
|
||||
|
||||
const draftRelations = await strapi.db
|
||||
.getConnection()
|
||||
.select('*')
|
||||
.from(joinTable.name)
|
||||
.whereIn(name, oldEntriesIds)
|
||||
.transacting(trx);
|
||||
|
||||
if (draftRelations.length > 0) {
|
||||
updates.push({ joinTable, relations: draftRelations.map(omit('id')) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -67,7 +100,7 @@ const load = async (uid: UID.ContentType, oldEntries: { id: string; locale: stri
|
||||
const sync = async (
|
||||
oldEntries: { id: string; locale: string }[],
|
||||
newEntries: { id: string; locale: string }[],
|
||||
oldRelations: { joinTable: any; relations: any[] }[]
|
||||
oldRelations: { joinTable: any; relations: any[]; replace?: boolean }[]
|
||||
) => {
|
||||
/**
|
||||
* Create a map of old entry ids to new entry ids
|
||||
@ -89,8 +122,9 @@ const sync = async (
|
||||
// Iterate old relations that are deleted and insert the new ones
|
||||
for (const { joinTable, relations } of oldRelations) {
|
||||
// Update old ids with the new ones
|
||||
const column = joinTable.inverseJoinColumn.name;
|
||||
|
||||
const newRelations = relations.map((relation) => {
|
||||
const column = joinTable.inverseJoinColumn.name;
|
||||
const newId = oldEntriesMap[relation[column]];
|
||||
return { ...relation, [column]: newId };
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user