Home Reference Source Repository

lib/entities/editor-interface.js

import cloneDeep from 'lodash/cloneDeep'
import omit from 'lodash/omit'
import { freezeSys, toPlainObject } from 'contentful-sdk-core'
import enhanceWithMethods from '../enhance-with-methods'
import errorHandler from '../error-handler'
/**
 * @typedef {Control} Control
 * @property {string} widgetId - defines how the field will look like e.g. singleLine
 * @property {string} fieldId - id of the field that this control is affecting
 * @property {Object} settings - settings for the widget
 */
/**
 * @typedef {EditorInterface} EditorInterface
 * @property {Object} sys - System metadata
 * @property {Control[]} controls - List of settings per field
 * @property {function(): Promise<EditorInterface>} update - Sends an update to the server with any changes made to the object's properties
 * @property {function(): Control} getControlForField - Gets a control for a specific field
 * @property {function(): Object} toPlainObject() - Returns this Content Type as a plain JS object
 * @example
 *
 * // require contentful-management
 * var contentfulManagement = require('contentful-management')
 * var client = contentfulManagement.createClient({
 * // This is the access token for this space. Normally you get both ID and the token in the Contentful web app
 * accessToken: 'YOUR_ACCESS_TOKEN'
 * })
 *
 * // request our space from Contentful
 * var space = await client.getSpace('SPACE_ID')
 *
 * //=======================================================================================================
 * // web can get an editor interface in two ways
 * // 1. request our ContentType from Contentful
 * //
 * // var contentType = await space.getContentType('CONTENT_TYPE_ID')
 * //
 * //1.1 Get the editorInterface through the ContentType
 * //
 * // var editorInterface = await contentType.getEditorInterface()
 * //
 * // OR
 * //
 * // 2. get an editor interface from the Space object right away
 * //
 * // var editorInterface = await space.getEditorInterfaceForContentType('CONTENT_TYPE_ID')
 * //=======================================================================================================
 *
 * // we'll use option 2
 *
 * var editorInterface = await space.getEditorInterfaceForContentType('CONTENT_TYPE_ID')
 *
 * // Example Updating  and editor interface
 * editorInterface.controls[0] = { "fieldId": "title", "widgetId": "singleLine"}
 * editorInterface.update()
 * .then(editorInterface => console.log(editorInterface.controls))
 */

function createEditorInterfaceApi (http) {
  return {
    /**
     * Sends an update to the server with any changes made to the object's properties
     * @memberof EditorInterface
     * @func update
     * @return {Promise<EditorInterface>} Object returned from the server with updated changes.
     * @example
     * editorInterface.controls[0] = { "fieldId": "title", "widgetId": "singleLine"}
     * editorInterface.update()
     * .then(editorInterface => console.log(editorInterface.controls))
     */
    update: function () {
      const raw = this.toPlainObject()
      const data = omit(raw, ['sys'])
      return http.put(`content_types/${this.sys.contentType.sys.id}/editor_interface`,
        data,
        {
          headers: {'X-Contentful-Version': this.sys.version}
        }
      )
      .then((response) => wrapEditorInterface(http, response.data), errorHandler)
    },
    /**
     * gets a control for a specific field
     * @memberof EditorInterface
     * @func getControlForField
     * @return {?Object} control object for specific field.
     * @example
     * const control = editorInterface.getControlForField('fieldId')
     * console.log(control)
     */
    getControlForField: function (fieldId) {
      const result = this.controls.filter((control) => {
        return control.fieldId === fieldId
      })
      return (result && result.length > 0) ? result[0] : null
    }
  }
}

/**
* @private
* @param {Object} http - HTTP client instance
* @param {Object} data - Raw editor-interface data
* @return {EditorInterface} Wrapped editor-interface data
*/
export function wrapEditorInterface (http, data) {
  const editorInterface = toPlainObject(cloneDeep(data))
  enhanceWithMethods(editorInterface, createEditorInterfaceApi(http))
  return freezeSys(editorInterface)
}