Skip to content
This repository has been archived by the owner on Apr 24, 2023. It is now read-only.

overview

Siou edited this page Apr 12, 2019 · 6 revisions

Canner is a React component which is used to build the CMS with a JSX file which we call schema and an Apollo client which represents the data sources. Using Canner you don't have to manually connect the APIs yourself, just define the data structure in the schemas, and ensure the Apollo client follows OpenCRUD.

The structure of the Canner packages is below, the right side is the process of a schema passing to the Canner component, it's compiled to the runnable es5 code by babel-loader and canner-schema-loader in the build time and transformed to JSON by canner-script in the runtime. Inside the Canner component, JSON schema is transformed to the component tree by canner-compiler which is the left side shows. Figure1

Now, let's take a example to see what does the schema changes.

schema

A schema is a JSX file whose pragma is canner-script. The entry schema is often called canner.schema.js which finally exports an object with several properties, such as schema, pageSchema, visitors, imageStorages. These properties are used in Canner component. You can check out the document to know how a schema looks like.

schema

import CannerScript from 'canner-script';
export default (
  <root>
    <array keyName="posts" title="Posts">
      <string keyName="title" title="Title"/>
      <string keyName="content" title="Content" ui="textarea" />
    </array>
  </root>
)

schema after babel loader

The JSX is just a syntax extension of Javascript, it's not runnable, we have to compile it to a runnable es5 JS file with Babal and @babel/plugin-transform-rect-jsx.

schema after babel

var CannerScript = require('canner-script');
module.exports = CannerScript('root', null,
  CannerScript('array', {
    keyName: 'posts',
    title: 'Posts',
  },
    [
      CannerScript('string', {
        keyName: 'title',
        title: 'Title'
      }),
      CannerScript('string', {
        keyName: 'content',
        title: 'Content',
        ui: 'textarea'
      })
    ]
  )
)

schema after canner-schema-loader

To archeive the goals, we will change the code again:

  1. customized component
  2. dynamic import
  3. predefined type
  4. canner attributes

schema after canner-schema-loader

var CannerScript = require('canner-script');
module.exports = CannerScript('root', null,
  CannerScript('array', {
    keyName: 'posts',
    title: 'Posts',
    packageName: '<PROJECT_DIR>/node_modules/@canner/antd-array-tabs',
    loader: new Promise((resolve) => {
      require.ensure([], (require) => {
        resolve(require('<PROJECT_DIR>/node_modules/@canner/antd-array-tabs'));
      });
    })
  },
    [
      CannerScript('string', {
        keyName: 'title',
        title: 'Title',
        packageName: '<PROJECT_DIR>/node_modules/@canner/antd-string-input',
        loader: new Promise((resolve) => {
          require.ensure([], (require) => {
            resolve(require('<PROJECT_DIR>/node_modules/@canner/antd-string-input'));
          });
        })
      }),
      CannerScript('string', {
        keyName: 'content',
        title: 'Content',
        ui: 'textarea',
        packageName: '<PROJECT_DIR>/node_modules/@canner/antd-string-textarea',
        loader: new Promise((resolve) => {
          require.ensure([], (require) => {
            resolve(require('<PROJECT_DIR>/node_modules/@canner/antd-string-textarea'));
          });
        })
      })
    ]
  )
)

schema in the runtime

In the runtime, schema is a object which contains lots of information we will use in Canner component

You can take a look by console.log(schema).

{
  dict: {}, // the dictionary of i18n texts
  schema: { // the data schema
    posts: {
      type: 'array',
      keyName: 'posts',
      title: 'Posts',
      packageName: '<PROJECT_DIR>/node_modules/@canner/antd-array-tabs`,
      loader: Promise,
      items: {
        type: 'object',
        items: {
          title: {
            type: 'string',
            keyName: 'title',
            title: 'Title',
            packageName: '<PROJECT_DIR>/node_modules/@canner/antd-string-input`,
            loader: Promise,
          },
          content: {
            type: 'string',
            keyName: 'content',
            title: 'Content',
            packageName: '<PROJECT_DIR>/node_modules/@canner/antd-string-textarea`,
            loader: Promise,
          }
        }
      }
    }
  },
  pageSchema: {}, // the schemas of <page>
  visitors: [], // will use in canner-compiler to generate the component tree
  imageStorages: {posts: null},
  fileStorages: {posts: null}
}