amis/examples/components/SchemaRender.jsx

217 lines
6.5 KiB
React
Raw Normal View History

2019-06-11 17:00:02 +08:00
import React from 'react';
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 {toast} from '../../src/components/Toast';
import {alert, confirm} from '../../src/components/Alert';
2019-11-07 10:41:14 +08:00
import Button from '../../src/components/Button';
import LazyComponent from '../../src/components/LazyComponent';
import {default as DrawerContainer} from '../../src/components/Drawer';
import {Portal} from 'react-overlays';
2019-06-05 09:48:22 +08:00
import {withRouter} from 'react-router';
2019-04-30 11:11:25 +08:00
function loadEditor() {
2019-11-07 10:41:14 +08:00
return new Promise(resolve =>
require(['../../src/components/Editor'], component =>
resolve(component.default))
);
2019-04-30 11:11:25 +08:00
}
2020-05-14 11:23:44 +08:00
export default function (schema) {
2019-11-07 10:41:14 +08:00
if (!schema['$schema']) {
schema = {
$schema: 'https://houtai.baidu.com/v2/schemas/page.json',
...schema
};
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return withRouter(
class extends React.Component {
static displayName = 'SchemaRenderer';
state = {open: false};
toggleCode = () =>
this.setState({
open: !this.state.open
2019-04-30 11:11:25 +08:00
});
2019-11-07 10:41:14 +08:00
close = () =>
this.setState({
open: false
2019-04-30 11:11:25 +08:00
});
2019-11-07 10:41:14 +08:00
constructor(props) {
super(props);
const {router} = props;
const normalizeLink = to => {
to = to || '';
const location = router.getCurrentLocation();
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx
? to.substring(0, idx)
: ~idx2
? to.substring(0, idx2)
: to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : location.hash;
2019-11-07 10:41:14 +08:00
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
2019-04-30 11:11:25 +08:00
}
2019-11-07 10:41:14 +08:00
pathname = paths.concat(pathname).join('/');
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return pathname + search + hash;
};
this.env = {
updateLocation: (location, replace) => {
router[replace ? 'replace' : 'push'](normalizeLink(location));
},
isCurrentUrl: to => {
const link = normalizeLink(to);
return router.isActive(link);
},
jumpTo: to => {
to = normalizeLink(to);
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (/^https?:\/\//.test(to)) {
window.location.replace(to);
} else {
router.push(to);
}
},
2019-11-07 19:03:58 +08:00
fetcher: ({url, method, data, config, headers}) => {
config = config || {};
config.headers = headers || {};
2020-05-14 11:23:44 +08:00
if (config.cancelExecutor) {
config.cancelToken = new axios.CancelToken(config.cancelExecutor);
}
2019-11-07 10:41:14 +08:00
if (data && data instanceof FormData) {
// config.headers = config.headers || {};
// config.headers['Content-Type'] = 'multipart/form-data';
} else if (
data &&
typeof data !== 'string' &&
!(data instanceof Blob) &&
!(data instanceof ArrayBuffer)
) {
data = JSON.stringify(data);
config.headers['Content-Type'] = 'application/json';
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (method !== 'post' && method !== 'put' && method !== 'patch') {
if (data) {
if (method === 'delete') {
config.data = data;
} else {
config.params = data;
}
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return axios[method](url, config);
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return axios[method](url, data, config);
},
isCancel: value => axios.isCancel(value),
notify: (type, msg) =>
toast[type]
? toast[type](msg, type === 'error' ? '系统错误' : '系统消息')
: console.warn('[Notify]', type, msg),
alert,
confirm,
copy: content => console.log('Copy', content)
};
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
this.handleEditorMount = this.handleEditorMount.bind(this);
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
handleEditorMount(editor, monaco) {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
enableSchemaRequest: true,
validate: true
});
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
renderCode() {
return (
<LazyComponent
getComponent={loadEditor}
editorDidMount={this.handleEditorMount}
language="json"
value={schema}
placeholder="加载中,请稍后。。。"
disabled
/>
);
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
renderSchema() {
2020-06-02 20:41:51 +08:00
const {router, location, theme, locale} = this.props;
2019-11-07 10:41:14 +08:00
return render(
schema,
{
location,
2020-06-02 20:41:51 +08:00
theme,
locale
2019-11-07 10:41:14 +08:00
},
this.env
);
}
render() {
const ns = this.props.classPrefix;
const showCode = this.props.showCode;
return (
<div className="schema-wrapper">
{showCode !== false ? (
<DrawerContainer
classPrefix={ns}
size="lg"
onHide={this.close}
show={this.state.open}
position="left"
>
{this.state.open ? this.renderCode() : null}
</DrawerContainer>
) : null}
{this.renderSchema()}
{showCode !== false ? (
<Portal container={() => document.querySelector('.navbar-nav')}>
<Button
classPrefix={ns}
onClick={this.toggleCode}
active={this.state.open}
iconOnly
tooltip="查看源码"
level="link"
placement="bottom"
className="view-code"
>
<i className="fa fa-code" />
</Button>
<span>点击这里查看源码</span>
2019-11-07 10:41:14 +08:00
</Portal>
) : null}
</div>
);
}
}
);
2019-04-30 11:11:25 +08:00
}