Document Transform Flows

Added in: release-2024-09

See the Declarative Document Copy (Legacy) guide for details about the legacy feature used prior to release-2024-09.

Introduction

Document Transform Flows provide a flexible way to modify a document while keeping the same documentId. It is possible to modify the content type, title, content, metadata and translations of a document. However, once a document has been published it is no longer possible to transform it.

Register a server function

Most of the logic for a transform flow will be defined within the transform function. You can register transform functions using the liServer.registerTransformFunctions method, which accepts an array of objects containing a unique handle and a transform function.

When the function is executed it is provided with the document being transformed, the projectConfig which the document belongs to, the userId of the user which triggered the transform process, the params of the optional paramsSchema form completed by the user, and a context object which is defined within the project config later.

The function can return the following values: contentType, title, content, metadata, translations. These values will be used to modify the existing document.

liServer.registerTransformFunctions([
  {
    handle: 'simpleContentTypeTransform',
    transform ({document, projectConfig, userId, params, context}) {
      if (!context?.targetContentType) {
        throw new Error(`A 'targetContentType' was not provided`)
      }

      const data = {
        contentType: context.targetContentType
        // title
        // content
        // metadata
        // translations
      }

      // An example of merging values from the paramsSchema form into the document metadata
      if (Object.keys(params).length) {
        data.metadata = {
          ...document.systemMetadata.toJSON(),
          ...document.metadata.toJSON()
        }
        for (const key in params) {
          const value = params[key]
          data.metadata[key] = value
        }
      }

      return data
    }
  }
])

Add document transform flow to projectConfig

Minimal

Registering a transform flow for a project can be very simple. Only a unique handle property and a reference to the handle of the transform function are required.

{
  // ...
  editorSettings: {
    // ...
    documentTransformFlows: [
      {
        handle: 'externalArticleToArticle',
        transformFunction: 'simpleContentTypeTransform'
        // transformButtonLabel will be generated using handle: "External Article To Article"
        // transformIcon will default to 'swap-horizontal'
      }
    ]
  }
}

Full

In order to customise the transform function further you can also customise the label, description and icon that appear in the UI. The label and description properties are translatable. It is also possible to define a paramsSchema using metadata plugins to prompt the user to input some additional data. The fields will be presented to the user in a form after they select the transform flow, and provided to the transform function in the params object. You can also set default values for the form using the defaultParams property. An additional property, context, can be used to pass data directly to the transform function. This can be useful in situations where you want to reuse the transform function for different scenarios.

{
  // ...
  editorSettings: {
    // ...
    documentTransformFlows: [
      {
        handle: 'externalArticleToArticle',
        transformFunction: 'simpleContentTypeTransform',
        transformButtonLabel: 'Transform into Article',
        transformDescription: 'All data will be kept',
        transformIcon: 'file-outline',
        paramsSchema: [
          {
            handle: 'category',
            type: 'li-category',
            ui: {
              label: 'Category',
              config: {
                placeholder: 'Select a category...'
              }
            }
          },
          {
            handle: 'dataProviderEnum',
            type: 'li-enum',
            ui: {
              label: 'Data Provider Enum'
            },
            config: {
              dataProvider: {
                items: [
                  {label: {en: 'Item A', de: 'Einheit A'}, value: 'a'},
                  {label: {en: 'Item B', de: 'Einheit B'}, value: 'b'},
                  {label: {en: 'Item C', de: 'Einheit C'}, value: 'c'},
                  {
                    label: {en: 'Item D (default)', de: 'Einheit D (default)'},
                    value: 'd',
                    isDefault: true
                  }
                ]
              }
            }
          }
        ],
        defaultParams: {
          dataProviderEnum: 'd'
        },
        context: {
          targetContentType: 'regular'
        }
      }
    ]
  }
}

Enable transform flow in contentTypeConfig

Finally, you need to enable the transform flow for each content type that should be able to use it. To do this you provide a reference to the transform flow you defined in the project config by using the handle as the value for the useDocumentTransformFlow property.

{
  handle: 'external',
  // ...
  documentTransformFlows: [
    {
      useDocumentTransformFlow: 'externalArticleToArticle'
    }
  ]
}