-
Notifications
You must be signed in to change notification settings - Fork 145
overview
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.
Now, let's take a example to see what does the schema changes.
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>
)
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'
})
]
)
)
To archeive the goals, we will change the code again:
- customized component
- dynamic import
- predefined type
- 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'));
});
})
})
]
)
)
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}
}