amis/examples/components/Play.jsx

298 lines
7.0 KiB
React
Raw Normal View History

2019-06-11 17:00:02 +08:00
import React from 'react';
2019-11-07 10:41:14 +08:00
import {toast} from '../../src/components/Toast';
2019-04-30 11:11:25 +08:00
import {render} from '../../src/index';
2019-06-11 17:00:02 +08:00
import axios from 'axios';
2019-04-30 11:11:25 +08:00
import Frame from 'react-frame-component';
2019-06-11 17:00:02 +08:00
import stripJsonComments from 'strip-json-comments';
2019-04-30 11:11:25 +08:00
import CodeEditor from '../../src/components/Editor';
const DEFAULT_CONTENT = `{
2019-05-09 18:25:12 +08:00
"$schema": "https://houtai.baidu.com/v2/schemas/page.json#",
2019-04-30 11:11:25 +08:00
"type": "page",
"title": "Title",
"body": "Body",
"aside": "Aside",
"toolbar": "Toolbar"
}`;
const scopes = {
2019-12-06 09:58:08 +08:00
'none': ``,
2019-04-30 11:11:25 +08:00
2019-12-06 09:58:08 +08:00
'body': `{
2019-04-30 11:11:25 +08:00
"type": "page",
"body": SCHEMA_PLACEHOLDER
}`,
2019-12-06 09:58:08 +08:00
'form': `{
2019-04-30 11:11:25 +08:00
"type": "page",
"body": {
"title": "",
"type": "form",
"autoFocus": false,
"api": "/api/mock/saveForm?waitSeconds=1",
"mode": "horizontal",
"controls": SCHEMA_PLACEHOLDER,
"submitText": null,
"actions": []
}
}`,
2019-11-07 10:41:14 +08:00
'form-item': `{
2019-04-30 11:11:25 +08:00
"type": "page",
"body": {
"title": "",
"type": "form",
"mode": "horizontal",
"autoFocus": false,
"controls": [
SCHEMA_PLACEHOLDER
],
"submitText": null,
"actions": []
}
}`
};
export default class PlayGround extends React.Component {
2019-11-07 10:41:14 +08:00
state = null;
startX = 0;
oldContents = '';
frameTemplate;
static defaultProps = {
useIFrame: false,
vertical: false
};
constructor(props) {
super(props);
const schema = this.buildSchema(props.code || DEFAULT_CONTENT, props);
this.state = {
asideWidth: props.asideWidth || Math.max(300, window.innerWidth * 0.3),
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
2019-04-30 11:11:25 +08:00
};
2019-11-07 10:41:14 +08:00
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this.removeWindowEvents = this.removeWindowEvents.bind(this);
this.handleChange = this.handleChange.bind(this);
this.schemaProps = {
style: {
height: '100%'
}
};
this.env = {
updateLocation: () => {},
fetcher: config => {
config = {
dataType: 'json',
...config
2019-04-30 11:11:25 +08:00
};
2019-11-07 10:41:14 +08:00
if (config.dataType === 'json' && config.data) {
config.data = JSON.stringify(config.data);
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
return axios[config.method](config.url, config.data, config);
},
notify: (type, msg) =>
toast[type]
? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
: console.warn('[Notify]', type, msg)
};
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
const links = [].slice
.call(document.head.querySelectorAll('link,style'))
.map(item => item.outerHTML);
this.frameTemplate = `<!DOCTYPE html><html><head>${links.join(
''
)}</head><body><div></div></body></html>`;
}
componentWillReceiveProps(nextprops) {
const props = this.props;
if (props.code !== nextprops.code) {
const schema = this.buildSchema(
nextprops.code || DEFAULT_CONTENT,
nextprops
);
this.setState({
schema: schema,
schemaCode: JSON.stringify(schema, null, 2)
});
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
componentDidMount() {
this.props.setAsideFolded && this.props.setAsideFolded(true);
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
componentWillUnmount() {
this.props.setAsideFolded && this.props.setAsideFolded(false);
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
buildSchema(schemaContent, props = this.props) {
const query = props.location.query;
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
try {
const scope = query.scope || props.scope;
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (scope && scopes[scope]) {
schemaContent = scopes[scope].replace(
'SCHEMA_PLACEHOLDER',
schemaContent
2019-04-30 11:11:25 +08:00
);
2019-11-07 10:41:14 +08:00
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
schemaContent = stripJsonComments(schemaContent).replace(
/('|")raw:/g,
'$1'
); // 去掉注释
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return JSON.parse(schemaContent);
} catch (e) {
console.error(this.formatMessage(e.message, schemaContent));
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
return {};
}
formatMessage(message, input) {
if (/position\s?(\d+)$/.test(message)) {
const lines = input
.substring(0, parseInt(RegExp.$1, 10))
.split(/\n|\r\n|\r/);
message = `Json 语法错误,请检测。出错位置:${lines.length},列:${
lines[lines.length - 1].length
}`;
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
return message;
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
renderPreview() {
const schema = this.state.schema;
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (!this.props.useIFrame) {
return render(schema, this.schemaProps, this.env);
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
return (
<Frame
width="100%"
height="100%"
frameBorder={0}
initialContent={this.frameTemplate}
>
{render(schema, this.schemaProps, this.env)}
</Frame>
);
}
handleChange(value) {
this.setState({
schemaCode: value
});
try {
const schema = JSON.parse(value);
this.setState({
schema
});
} catch (e) {
//ignore
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
}
handleMouseDown(e) {
this.startX = e.clientX;
this.startWidth = this.state.asideWidth;
// this.startPosition.y = e.clientY;
window.addEventListener('mouseup', this.handleMouseUp);
window.addEventListener('mousemove', this.handleMouseMove);
return false;
}
handleMouseMove(e) {
const diff = this.startX - e.clientX;
e.preventDefault();
this.setState({
asideWidth: Math.min(800, Math.max(200, this.startWidth + diff))
});
}
handleMouseUp() {
this.removeWindowEvents();
}
removeWindowEvents() {
window.removeEventListener('mouseup', this.handleMouseUp);
window.removeEventListener('mousemove', this.handleMouseMove);
}
renderEditor() {
return (
<CodeEditor
value={this.state.schemaCode}
onChange={this.handleChange}
language="json"
/>
);
}
render() {
const {vertical} = this.props;
if (vertical) {
return (
<div className="vbox">
<div className="row-row">
<div className="cell pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
</div>
</div>
</div>
2020-07-23 20:31:51 +08:00
<div className="row-row b-t" style={{height: 200}}>
2019-11-07 10:41:14 +08:00
<div className="cell">{this.renderEditor()}</div>
</div>
</div>
);
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
return (
<div
style={{
position: 'absolute',
top: 50,
bottom: 0
}}
>
<div className="hbox">
<div className="col pos-rlt">
<div className="scroll-y h-full pos-abt w-full">
{this.renderPreview()}
2019-04-30 11:11:25 +08:00
</div>
2019-11-07 10:41:14 +08:00
</div>
<div
className="col bg-light lter b-l bg-auto pos-rlt"
style={{width: this.state.asideWidth}}
>
<div className="resizer" onMouseDown={this.handleMouseDown} />
{this.renderEditor()}
</div>
</div>
</div>
);
}
2019-04-30 11:11:25 +08:00
}