Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use deriveLinkedEntries with many references field needs documentation. #127

Closed
lucasvanlierop opened this issue Aug 1, 2018 · 7 comments · Fixed by #138
Closed

Use deriveLinkedEntries with many references field needs documentation. #127

lucasvanlierop opened this issue Aug 1, 2018 · 7 comments · Fixed by #138

Comments

@lucasvanlierop
Copy link

lucasvanlierop commented Aug 1, 2018

Expected Behavior

When converting a single field to a many references field, one entry should be created and linked

Actual Behavior

Migration plan looks successful:

The following migration has been planned

Derive entries from articleContactBlock
  - from: emailAddress
  - to: address
  - via: emailAddresses
Update Content Type articleContactBlock

  Update field emailAddresses
    - disabled: false

Publish Content Type articleContactBlock
? Do you want to apply the migration Yes

Migration then fails:

 ❯ Derive entries from articleContactBlock
   ✖ Making requests (28/28)
   
   Update Content Type articleContactBlock
🚨  Migration unsuccessful
Batch failed

Error: {"status":"Unprocessable Entity","message":"Validation error","details":{"errors":[{"name":"type","value":{"sys":{"type":"Link","linkType":"Entry","id":"63dbf7d9-d48f-4aa0-98f9-bacaf6934a80"}},"type":"Array","details":"The type of \"value\" is incorrect, expected type: Array","path":["fields","emailAddresses","nl-NL"]}]},"url":"https://api.contentful.com:443/spaces/ea7q533w75xs/environments/migrate-test/entries/N7JP7I1Qwm8EAmesSQ8We"}

Error: {"status":"Conflict","message":"","details":{},"url":"https://api.contentful.com:443/spaces/ea7q533w75xs/environments/migrate-test/entries/N7JP7I1Qwm8EAmesSQ8We/published"}

....

Possible Solution

Create a variant of the derive entry example which shows how to use it with a many references field

Steps to Reproduce

run a migration similar to this:

module.exports = function (migration) {
    const emailAddress = migration.createContentType('emailAddress').name('Email adres');
    emailAddress.displayField('address');
    emailAddress.createField('address').type('Symbol').name('Adres').validations([{ unique: true }]);
    emailAddress.createField('label').type('Symbol').name('Label').validations([{ unique: true }]);
    emailAddress.createField('description').type('Symbol').name('Titel').validations([{ unique: true }]);
    emailAddress.createField('internal').type('Boolean').name('Voor intern gebruik');

    const articleContactBlock = migration.editContentType('articleContactBlock');

    articleContactBlock.editField('emailAddress').disabled(true);

    articleContactBlock.createField('emailAddresses')
        .name('Email adressen')
        .type('Array')
        .disabled(true)
        .items({
            type: 'Link',
            linkType: 'Entry',
            validations: [
                {
                    'linkContentType': [
                        'emailAddress'
                    ]
                }
            ]
        });

    articleContactBlock.moveField('emailAddresses').afterField('emailAddress');

    const sha1 = require('sha1');

    const articleContactBlock = migration.editContentType('articleContactBlock');
    migration.deriveLinkedEntries({
        contentType: 'articleContactBlock',
        derivedContentType: 'emailAddress',
        from: ['emailAddress'],
        toReferenceField: 'emailAddresses',
        derivedFields: [
            'address',
            'label',
            'description',
            'internal'
        ],
        identityKey: async (fromFields) => {
            if (typeof fromFields.emailAddress === 'undefined') {
                return 'empty';
            }

            return 'sha1' + sha1(fromFields.emailAddress);
        },
        shouldPublish: false,
        deriveEntryForLocale: async (inputFields, locale) => {
            if (typeof inputFields.emailAddress === 'undefined') {
                return {
                    'address': '[email protected]',
                    'label': '',
                    'description': '',
                    'internal': false
                }
            }

            return {
                'address': inputFields.emailAddress[locale],
                'label': '',
                'description': '',
                'internal': false
            };
        }
    });

    articleContactBlock.editField('emailAddresses').disabled(false);

    articleContactBlock.deleteField('emailAddress');
};

Context

We want to allow multiple entries instead of just one and are therefore trying to convert an existing field to many references.

Environment

  • Node Version: v9.11.2
  • Package Manager Version: yarn 1.5.1
  • Operating System: Linux 10a2d3449700 4.9.93-linuxkit-aufs
  • Package Version: Contentful CLI 0.16.1
@lucasvanlierop lucasvanlierop changed the title Document how to use deriveLinkedEntries with many references field. Use deriveLinkedEntries with many references field needs documentation. Aug 2, 2018
@lucasvanlierop
Copy link
Author

Just noticed the PUT request to the content type containing the many references field contains a single value

"emailAddresses": {
      "nl-NL": {
        "sys": {
          "type": "Link",
          "linkType": "Entry",
          "id": "the-derived-id"
        }
      }
    }

whereas I would expect:

"emailAddresses": {
      "nl-NL": [
        {
          "sys": {
            "type": "Link",
            "linkType": "Entry",
            "id": "the-derived-id"
          }
        }
      ]
    }

@Khaledgarbaya
Copy link
Contributor

Hi @lucasvanlierop,
Here is an example on how to convert a signle ref field to a multiRef field

module.exports = (migration) => {
  const article = migration.editContentType('MyContentType')  
  migration.transformEntries({
    contentType: 'article',
    from: ['singleRef'],
    to: ['multiRef'],
    transformEntryForLocale: (fromFields, currentLocale) => {
      if (!fromFields.singleRef) {
        return
      }
      return {multiRef:[fromFields.singleRef[currentLocale]]}
    }
  })

}

@Khaledgarbaya
Copy link
Contributor

we'll improve the tool in the future to detect field type and prevent this from happening.

@lucasvanlierop
Copy link
Author

Thanks @Khaledgarbaya! I worked on it yesterday, and fixed some other small bugs as well. I now understand it's a multi step process.

What I've done is:

  • Create a content type where values can be derived to
  • Disable the field to be derived for editing
  • Add a temporary disabled single reference field
  • Derive values to the new content type and link them to the single reference field
  • Transform links from the temporary single reference field to the many references field
  • Enable many references field
  • Remove old field
  • Remove temporary single reference field

This approach seems to work

phoebeschmidt pushed a commit that referenced this issue Sep 21, 2018
Fixes #127.

Link derived entry based on the type of the reference field (either as first item in Array or single entry)
@phoebeschmidt
Copy link
Contributor

🎉 This issue has been resolved in version 0.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@gkulasik-livongo
Copy link

Thanks for working on this update!

I noticed this same issue when working with the Contentful CLI. Will this update be applied to that repo as well?

@Khaledgarbaya
Copy link
Contributor

Hey @gkulasik-livongo we are working on some more improvement and we'll update the cli soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants