locomotivecms/engine

View on GitHub
app/javascript/src/locomotive/editor/services/api.js

Summary

Maintainability
A
35 mins
Test Coverage
import { toInt } from '../utils/misc';
import { each, replace } from 'lodash';

const requestOptions = (verb, data, headers) => {
  const _headers = Object.assign({
    'Content-Type':   'application/json',
    'X-CSRF-Token':   document.querySelector('meta[name="csrf-token"]').content
  }, headers);

  if (_headers['Content-Type'] === null)
    delete _headers['Content-Type'];

  var options = {
    method:       verb,
    credentials:  'same-origin',
    headers:      _headers
  }

  if (verb !== 'GET')
    options.body = data;

  return options;
}

const post = (url, data, headers) => {
  return fetch(url, requestOptions('POST', data, headers));
}

const put = (url, data, headers) => {
  return fetch(url, requestOptions('PUT', data, headers));
}

const jsonPut = (url, data, headers) => {
  return put(url, JSON.stringify(data), headers)
    .then((response) => { return response.json() })
    .then((data) => {
      if (data.errors) throw(data.errors);
      return data;
    })
}

const get = (url, query, headers) => {
  var url = new URL(url, window.location.origin);
  Object.keys(query || {}).forEach(key => url.searchParams.append(key, query[key]));
  return fetch(url.href, requestOptions('GET', null, headers));
}

const jsonGet = (url, query, headers) => {
  return get(url, query, headers)
    .then((response) => {
      const headers = response.headers;
      return response.json().then(json => { return { headers, json } });
    });
}

// CONTENT

export function saveContent(url, site, page, locale) {
  return jsonPut(url, {
    content_locale: locale,
    site: { sections_content: JSON.stringify(site.sectionsContent) },
    page: {
      title: page.title,
      slug: page.slug,
      listed: page.listed,
      published: page.published,
      seo_title: page.seo_title,
      meta_keywords: page.meta_keywords,
      meta_description: page.meta_description,
      sections_content: JSON.stringify(page.sectionsContent),
      sections_dropzone_content: JSON.stringify(page.sectionsDropzoneContent)
    }
  });
}

export function loadContent(url, pageId, contentEntryId, locale) {
  const _url = replace(url, /\/pages\/[0-9a-z]+\//, `/pages/${pageId}\/`) + '.json';
  return jsonGet(_url, { content_locale: locale, content_entry_id: contentEntryId })
  .then(response => ({ data: response.json.data, urls: response.json.urls }))
}

// SECTION

export function loadSectionHTML(url, section, content) {
  return put(url,
    JSON.stringify({ section_content: content }),
    { 'Locomotive-Section-Type': section.type }
  ).then(response => { return response.text(); })
}

// CONTENT ASSETS

export function uploadAssets(url, assets) {
  var form = new FormData();
  each(assets, asset => {
    if (typeof(asset.name) == 'string')
      form.append('content_assets[][source]', asset)
    else
      form.append('content_assets[][source]', asset.blob, asset.filename)
  })

  return post(url, form, {
    'Content-Type': null
  }).then(response => response.json())
}

export function loadAssets(url, options) {
  return jsonGet(url, {
    query:    options.query || '',
    page:     options.pagination.page || 1,
    per_page: options.pagination.perPage || 10
  })
  .then(response => {
    return {
      list:         response.json,
      pagination:   {
        page:         toInt(response.headers.get('x-current-page')),
        perPage:      toInt(response.headers.get('x-per-page')),
        totalPages:   toInt(response.headers.get('x-total-pages')),
        totalEntries: toInt(response.headers.get('x-total-entries'))
      }
    }
  });
}

export function getThumbnail(url, imageUrl, format) {
  var _imageUrl = new URL(imageUrl, window.location.origin);
  return get(url, { image: _imageUrl, format }).
  then(response => response.text())
}

// RESOURCES

export function searchForResources(url, locale, type, q, scope) {
  return jsonGet(url, { content_locale: locale, q, type, scope })
  .then(response => ({ list: response.json }));
}

export default function ApiFactory(urls, locale) {
  return {
    loadContent:        (pageId, contentEntryId, locale) => loadContent(urls.load, pageId, contentEntryId, locale),
    saveContent:        (site, page, locale) => saveContent(urls.save, site, page, locale),

    loadAssets:         (options) => loadAssets(urls.assets, options),
    uploadAssets:       (assets) => uploadAssets(urls.bulkAssetUpload, assets),
    getThumbnail:       (imageUrl, format) => getThumbnail(urls.thumbnail, imageUrl, format),

    searchForResources: (type, query, scope) => searchForResources(urls.resources, locale, type, query, scope),

    loadSectionHTML:    (sectionType, content) => loadSectionHTML(urls.preview , sectionType, content)
  };
}