Skip to content

Data source plugin for GrapesJs to let user design with data from databases, CMS, API

Notifications You must be signed in to change notification settings

silexlabs/grapesjs-data-source

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GrapesJs Data Source plugin

This GrapesJS plugin integrates various APIs into the editor.

It makes a new UI available to the user so that she can manage custom states on components, linking them to data from a CMS or a data base or an API.

The plugin also has data management feature needed to manage components states, expressions made of tokens, build a query from the component states.

This code is part of a larger project: about Silex v3

DEMO

Use

The output of this plugin is component states which are stored on the components. This data then needs to be used by other plugins or your application. For example you can implement a "publish" feature to generate pages and data files for a static site generator or CMSs. Or you can make a vue app generator with it, by implementing a "renderer" which takes the states and adds the vue code to the generated website.

Here is how your application can use the data generated by the user with this plugin:

  1. Components states
import { getStateIds, getState } from './state'
// ...
const component = editor.getSelected()

// Get one specific state
console.log('innerHTML state:', getState(component, 'innerHTML'))

// Display all states of the component
const stateIds = getStateIds(component)
console.log('Alls states:', stateIds.map(stateId => getState(component, stateId)))

// Detect state changes
editor.on('component:state:changed', ({state, component}) => {
  console.log('State changed:', {state, component})
})

Here is an example output:

innerHTML state: {"expression":[{"type":"property","propType":"field","fieldId":"post","label":"post","typeIds":["PostEntityResponse"],"dataSourceId":"strapi","kind":"object","options":{"id":"1"}},{"type":"property","propType":"field","fieldId":"data","label":"data","typeIds":["PostEntity"],"dataSourceId":"strapi","kind":"object"},{"type":"property","propType":"field","fieldId":"attributes","label":"attributes","typeIds":["Post"],"dataSourceId":"strapi","kind":"object"},{"type":"property","propType":"field","fieldId":"title","label":"title","typeIds":["String"],"dataSourceId":"strapi","kind":"scalar"}]}
All states: [{"expression":[{"type":"property","propType":"field","fieldId":"post","label":"post","typeIds":["PostEntityResponse"],"dataSourceId":"strapi","kind":"object","options":{"id":"1"}},{"type":"property","propType":"field","fieldId":"data","label":"data","typeIds":["PostEntity"],"dataSourceId":"strapi","kind":"object"},{"type":"property","propType":"field","fieldId":"attributes","label":"attributes","typeIds":["Post"],"dataSourceId":"strapi","kind":"object"},{"type":"property","propType":"field","fieldId":"title","label":"title","typeIds":["String"],"dataSourceId":"strapi","kind":"scalar"}]}]
  1. GraphQL query to get the data needed for the current page in functino of the data used in the states
// Get the current page
var page = editor.Pages.getSelected()

// Get the GraphQL query
const query = editor.DataSourceManager.getPageQuery(page)
console.log(query)

Here is an example output:

{
  "strapi": "posts {\n  data {\n  attributes {\n  title\n  content\n}\n}\n}"
}

Supported APIs

This plugin suports only GraphQL for now, contribution are welcome for support of other REST specific APIs or more generic Open API

Here is a list of GraphQL APIs you can use, it includes fake data and demo public APIs. Also consider these open source self hostable services:

Contributions welcome for documenting the use of these data sources

HTML

<link href="https://unpkg.com/grapesjs/dist/css/grapes.min.css" rel="stylesheet">
<script src="https://unpkg.com/grapesjs"></script>
<script src="https://unpkg.com/@silexlabs/grapesjs-data-source"></script>

<div id="gjs"></div>

JS

const editor = grapesjs.init({
	container: '#gjs',
  height: '100%',
  fromElement: true,
  storageManager: false,
  plugins: ['@silexlabs/grapesjs-data-source'],
  pluginsOpts: {
    '@silexlabs/grapesjs-data-source': {
      dataSources: [{
        id: 'countries',
        type: 'graphql',
        label: 'Countries',
        url: 'https://countries.trevorblades.com/graphql',
        method: 'POST',
        headers: {},
      }],
      properties: {
        el: () => editor.Panels.getPanel('views-container').view.el,
        button: () => editor.Panels.getPanel('views').get('buttons').get('open-tm'),
      },
      filters: 'liquid',
    }
  }
});

CSS

body, html {
  margin: 0;
  height: 100%;
}

Local tests and development

Use a local strapi to test GraphQL data source

$ cd strapi
$ yarn develop

Strapi admin

  • http://localhost:1337/admin/
  • Login: alex@test.com
  • Password: test_TEST1

Strapi GraphQL:

  • http://localhost:1337/graphql
  • Bearer 456fe45a764921a26a81abd857bf987cd1735fbdbe58951ff5fc45a1c0ed2c52ab920cc0498b17411cd03954da7bb3e62e6bae612024360fb89717bd2274493ce190f3be14cdf47fccd33182fd795a67e48624e37f7276d9f84e98b2ec6945926d7a150e8c5deafa272aa9d9d97ee89e227c1edb1d6740ffd37a16b2298b3cc8

Use this as a data source in the plugin options:

grapesjs.init({
  // ...
  // Your config here
  // ...

  plugins: ['@silexlabs/grapesjs-data-source'],
  pluginsOpts: {
    '@silexlabs/grapesjs-data-source': {
      dataSources: [
        {
          id: 'strapi',
          type: 'graphql',
          name: 'Strapi',
          url: 'http://localhost:1337/graphql',
          method: 'POST',
          headers: {
            'Authorization': 'Bearer 79c9e74b3cf4a9f5ce2836b81fd8aaf8a986b5696769456d3646a3213f5d7228634a1a15a8bbad4e87c09ab864c501499c6f8955cf350e49b89311764009aee68589a4b78f22c06b7e09835b48cd6f21fb84311ce873cd5672bd4652fde3f5f0db6afb258dfe7b93371b7632b551ecdd969256ffc076ab8f735b5d8c7d228825',
            'Content-Type': 'application/json',
          },
        },
      ],
      properties: {
        el: () => editor.Panels.getPanel('views-container').view.el,
        button: () => editor.Panels.getPanel('views').get('buttons').get('open-tm'),
      },
      filters: 'liquid',
    }
  }
});

Configuration examples

Here are examples of APIs I tested:

Directus

{
  id: 'directus',
  type: 'graphql',
  name: 'Directus',
  url: `https://localhost:8085/graphql`,
  method: 'POST',
  headers: {
    'Authorization': 'Bearer yjgwcj...0c_0zex',
    'Content-Type': 'application/json',
  },
}

Strapi

{
  id: 'strapi',
  type: 'graphql',
  name: 'Strapi',
  url: 'http://localhost:1337/graphql',
  method: 'POST',
  headers: {
    'Authorization': 'Bearer 456fe45a764921a2...6b2298b3cc8',
    'Content-Type': 'application/json',
  },
}

Supabase (I had a CORS problem, let's discuss this in an issue if you want to give it a try)

{
  id: 'supabase',
  type: 'graphql',
  name: 'Supabase',
  url: `https://api.supabase.io/platform/projects/jpslgeqihfj/api/graphql`,
  method: 'POST',
  headers: {
    'Authorization': 'Bearer eyjhbgcioijiuz...tww8imndplsfm',
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
  },
}

Options

Option Description Default
dataSources List of data sources, see config examples and the plugin code for docs (data source options and GraphQL data source options) []
filters The string 'liquidjs' for LiquidJs filters or a list of filters (JS objects like the ones in src/filters/liquid.ts) []
view Options for the UI []
view.el UI element to attach properties, states, attributes, loop .gjs-pn-panel.gjs-pn-views-container
view.button Optional GrapesJs button or a function which returns a button. This button will show/hide the UI undefined which means no button
view.styles CSS styles which are applied to the UI (inserted in a style tag) See the file src/view/defaultStyles.ts
view.optionsStyles CSS styles which are applied to each "expression selector" UI (inserted in a style tag) See the file src/view/defaultStyles.ts
view.defaultFixed If true, the UI shows fixed by default or if false it shows expression by default false

Download

  • CDN
    • https://unpkg.com/@silexlabs/grapesjs-data-source
  • NPM
    • npm i @silexlabs/grapesjs-data-source
  • GIT
    • git clone https://github.com/silexlabs/grapesjs-data-source.git

Usage

Directly in the browser

<link href="https://unpkg.com/grapesjs/dist/css/grapes.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/grapesjs"></script>
<script src="path/to/grapesjs-data-source.min.js"></script>

<div id="gjs"></div>

<script type="text/javascript">
  var editor = grapesjs.init({
      container: '#gjs',
      // ...
      plugins: ['@silexlabs/grapesjs-data-source'],
      pluginsOpts: {
        '@silexlabs/grapesjs-data-source': { /* options */ }
      }
  });
</script>

Modern javascript

import grapesjs from 'grapesjs';
import plugin from '@silexlabs/grapesjs-data-source';
import 'grapesjs/dist/css/grapes.min.css';

const editor = grapesjs.init({
  container : '#gjs',
  // ...
  plugins: [plugin],
  pluginsOpts: {
    [plugin]: { /* options */ }
  }
  // or
  plugins: [
    editor => plugin(editor, { /* options */ }),
  ],
});

Development

Clone the repository

$ git clone https://github.com/silexlabs/grapesjs-data-source.git
$ cd grapesjs-data-source

Install dependencies

$ npm i

Start the dev server

$ npm start

Build the source

$ npm run build

Developement notes

Here are the key parts of the plugin:

  1. editor.DataSourceManager: A Backbone collection to manage the APIs. This collection holds the different available data sources and their settings (type, url, auth...). This data is provided by the config. The main API of this class is getDataTree() to get the data tree

  2. DataTree: A class to manage component states and generate queries to APIs. Component states are used to build the query needed for the current page, and they can be used to create other states in child components or override a component's attributes or style. This collection is generated from the components attributes, it is not stored with the site data.

  3. DataSource: An interface for classes managing an API, abstracting the calls and queries. It includes methods like getData(query) and getTypes().

The components with "Loop Template" also have a current state, similar to dynamic pages.

The plugin's architecture is designed to provide a flexible and efficient way to manage data and rendering in the editor, supporting dynamic content and static site generation. It abstracts the complexities of working with different APIs and provides a unified way to manage component states, templates, and dynamic content.

License

MIT

About

Data source plugin for GrapesJs to let user design with data from databases, CMS, API

Resources

Stars

Watchers

Forks

Packages

No packages published