Skip to content

Commit

Permalink
fix(live-preview): compounds merge results (#4306)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobsfletch committed Nov 29, 2023
1 parent 3514bfb commit 381c158
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 87 deletions.
8 changes: 7 additions & 1 deletion packages/live-preview/src/handleMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { mergeData } from '.'
// Send this cached value to `mergeData`, instead of `eventData.fieldSchemaJSON` directly
let payloadLivePreviewFieldSchema = undefined // TODO: type this from `fieldSchemaToJSON` return type

// Each time the data is merged, cache the result as a `previousData` variable
// This will ensure changes compound overtop of each other
let payloadLivePreviewPreviousData = undefined

export const handleMessage = async <T>(args: {
apiRoute?: string
depth?: number
Expand Down Expand Up @@ -37,10 +41,12 @@ export const handleMessage = async <T>(args: {
depth,
fieldSchema: payloadLivePreviewFieldSchema,
incomingData: eventData.data,
initialData,
initialData: payloadLivePreviewPreviousData || initialData,
serverURL,
})

payloadLivePreviewPreviousData = mergedData

return mergedData
}
}
Expand Down
72 changes: 45 additions & 27 deletions packages/live-preview/src/traverseRichText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,50 +11,68 @@ export const traverseRichText = ({
apiRoute: string
depth: number
incomingData: any
populationPromises: Promise<void>[]
populationPromises: Promise<any>[]
result: any
serverURL: string
}): any => {
if (Array.isArray(incomingData)) {
result = incomingData.map((incomingRow) =>
traverseRichText({
if (!result) {
result = []
}

result = incomingData.map((item, index) => {
if (!result[index]) {
result[index] = item
}

return traverseRichText({
apiRoute,
depth,
incomingData: incomingRow,
incomingData: item,
populationPromises,
result,
result: result[index],
serverURL,
}),
)
} else if (typeof incomingData === 'object' && incomingData !== null) {
result = incomingData

if ('relationTo' in incomingData && 'value' in incomingData && incomingData.value) {
populationPromises.push(
promise({
id: typeof incomingData.value === 'object' ? incomingData.value.id : incomingData.value,
accessor: 'value',
apiRoute,
collection: String(incomingData.relationTo),
depth,
ref: result,
serverURL,
}),
)
} else {
})
})
} else if (incomingData && typeof incomingData === 'object') {
if (!result) {
result = {}
}

Object.keys(incomingData).forEach((key) => {
if (!result[key]) {
result[key] = incomingData[key]
}

const isRelationship = key === 'value' && 'relationTo' in incomingData

Object.keys(incomingData).forEach((key) => {
if (isRelationship) {
const needsPopulation = !result.value || typeof result.value !== 'object'

if (needsPopulation) {
populationPromises.push(
promise({
id: incomingData[key],
accessor: 'value',
apiRoute,
collection: incomingData.relationTo,
depth,
ref: result,
serverURL,
}),
)
}
} else {
result[key] = traverseRichText({
apiRoute,
depth,
incomingData: incomingData[key],
populationPromises,
result,
result: result[key],
serverURL,
})
})
}
}
})
} else {
result = incomingData
}
Expand Down
203 changes: 153 additions & 50 deletions test/live-preview/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,7 @@ describe('Collections - Live Preview', () => {

expect(mergedDataWithoutUpload.hero.media).toBeFalsy()
})

it('— relationships - populates all types', async () => {
it('— relationships - populates monomorphic has one relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
}
Expand All @@ -199,28 +198,84 @@ describe('Collections - Live Preview', () => {
incomingData: {
...initialData,
relationshipMonoHasOne: testPost.id,
relationshipMonoHasMany: [testPost.id],
relationshipPolyHasOne: { value: testPost.id, relationTo: postsSlug },
relationshipPolyHasMany: [{ value: testPost.id, relationTo: postsSlug }],
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(4)
expect(merge1._numberOfRequests).toEqual(1)
expect(merge1.relationshipMonoHasOne).toMatchObject(testPost)
})

it('— relationships - populates monomorphic has many relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
}

const merge1 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...initialData,
relationshipMonoHasMany: [testPost.id],
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(1)
expect(merge1.relationshipMonoHasMany).toMatchObject([testPost])
})

it('— relationships - populates polymorphic has one relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
}

const merge1 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...initialData,
relationshipPolyHasOne: { value: testPost.id, relationTo: postsSlug },
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(1)
expect(merge1.relationshipPolyHasOne).toMatchObject({
value: testPost,
relationTo: postsSlug,
})
})

it('— relationships - populates polymorphic has many relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
}

const merge1 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...initialData,
relationshipPolyHasMany: [{ value: testPost.id, relationTo: postsSlug }],
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(1)
expect(merge1.relationshipPolyHasMany).toMatchObject([
{ value: testPost, relationTo: postsSlug },
])
})

it('— relationships - can clear relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
Expand Down Expand Up @@ -421,9 +476,22 @@ describe('Collections - Live Preview', () => {
expect(merge2.relationshipInRichText[0].type).toEqual('paragraph')
})

it('— rich text - merges rich text', async () => {
it('— relationships - does not re-populate existing rich text relationships', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
relationshipInRichText: [
{
type: 'paragraph',
text: 'Paragraph 1',
},
{
type: 'reference',
reference: {
relationTo: 'posts',
value: testPost,
},
},
],
}

// Add a relationship
Expand All @@ -432,57 +500,28 @@ describe('Collections - Live Preview', () => {
fieldSchema: schemaJSON,
incomingData: {
...initialData,
hero: {
type: 'lowImpact',
richText: [
{
type: 'paragraph',
children: [
{
text: 'Paragraph 1',
},
],
relationshipInRichText: [
{
type: 'paragraph',
text: 'Paragraph 1',
},
{
type: 'reference',
reference: {
relationTo: 'posts',
value: testPost.id,
},
],
},
},
],
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(0)
expect(merge1.hero.richText).toHaveLength(1)
expect(merge1.hero.richText[0].children[0].text).toEqual('Paragraph 1')

// Update the rich text
const merge2 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...merge1,
hero: {
type: 'lowImpact',
richText: [
{
type: 'paragraph',
children: [
{
text: 'Paragraph 1 (Updated)',
},
],
},
],
},
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge2._numberOfRequests).toEqual(0)
expect(merge2.hero.richText).toHaveLength(1)
expect(merge2.hero.richText[0].children[0].text).toEqual('Paragraph 1 (Updated)')
expect(merge1.relationshipInRichText).toHaveLength(2)
expect(merge1.relationshipInRichText[1].reference.value).toMatchObject(testPost)
})

it('— relationships - populates within blocks', async () => {
Expand Down Expand Up @@ -545,6 +584,70 @@ describe('Collections - Live Preview', () => {
expect(merge2._numberOfRequests).toEqual(1)
})

it('— rich text - merges rich text', async () => {
const initialData: Partial<Page> = {
title: 'Test Page',
}

// Add a relationship
const merge1 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...initialData,
hero: {
type: 'lowImpact',
richText: [
{
type: 'paragraph',
children: [
{
text: 'Paragraph 1',
},
],
},
],
},
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge1._numberOfRequests).toEqual(0)
expect(merge1.hero.richText).toHaveLength(1)
expect(merge1.hero.richText[0].children[0].text).toEqual('Paragraph 1')

// Update the rich text
const merge2 = await mergeData({
depth: 1,
fieldSchema: schemaJSON,
incomingData: {
...merge1,
hero: {
type: 'lowImpact',
richText: [
{
type: 'paragraph',
children: [
{
text: 'Paragraph 1 (Updated)',
},
],
},
],
},
},
initialData,
serverURL,
returnNumberOfRequests: true,
})

expect(merge2._numberOfRequests).toEqual(0)
expect(merge2.hero.richText).toHaveLength(1)
expect(merge2.hero.richText[0].children[0].text).toEqual('Paragraph 1 (Updated)')
})

it('— blocks - adds, reorders, and removes blocks', async () => {
const block1ID = '123'
const block2ID = '456'
Expand Down

0 comments on commit 381c158

Please sign in to comment.