amis/examples/components/App.jsx

782 lines
28 KiB
React
Raw Normal View History

2019-04-30 11:11:25 +08:00
import * as React from 'react';
import NotFound from '../../src/components/404';
import Layout from '../../src/components/Layout';
import AsideNav from '../../src/components/AsideNav';
import {AlertComponent, ToastComponent} from '../../src/components/index';
import {
mapTree
} from '../../src/utils/helper';
2019-05-20 12:03:25 +08:00
import { Router, Route, IndexRoute, browserHistory, hashHistory, Link, Redirect, withRouter } from 'react-router';
2019-04-30 11:11:25 +08:00
import makeSchemaRenderer from './SchemaRender';
2019-05-09 18:25:12 +08:00
2019-04-30 11:11:25 +08:00
import SimplePageSchema from './Page/Simple';
import ErrorPageSchema from './Page/Error';
import FormPageSchema from './Page/Form';
import ModeFormSchema from './Form/Mode';
import FieldSetFormSchema from './Form/FieldSet';
import TabsFormSchema from './Form/Tabs';
import RemoteFormSchema from './Form/Remote';
import ReactionFormSchema from './Form/Reaction';
import ValidationFormSchema from './Form/Validation';
import FullFormSchema from './Form/Full';
import StaticFormSchema from './Form/Static';
import HintFormSchema from './Form/Hint';
import FieldSetInTabsFormSchema from './Form/FieldSetInTabs';
import ComboFormSchema from './Form/Combo';
import SubFormSchema from './Form/SubForm';
import RichTextSchema from './Form/RichText';
import EditorSchema from './Form/Editor';
import TestFormSchema from './Form/Test';
import TableFormSchema from './Form/Table';
import PickerFormSchema from './Form/Picker';
import FormulaFormSchema from './Form/Formula';
import CustomFormSchema from './Form/Custom';
import FormLayoutTestSchema from './Form/layoutTest';
2019-05-09 18:25:12 +08:00
import Docs from './Doc';
2019-04-30 11:11:25 +08:00
import TableCrudSchema from './CRUD/Table';
import ItemActionsSchema from './CRUD/ItemActions';
import GridCrudSchema from './CRUD/Grid';
import ListCrudSchema from './CRUD/List';
import LoadMoreSchema from './CRUD/LoadMore';
import TestCrudSchema from './CRUD/test';
import FixedCrudSchema from './CRUD/Fix';
import AsideCrudSchema from './CRUD/Aside';
import FieldsCrudSchema from './CRUD/Fields';
import JumpNextCrudSchema from './CRUD/JumpNext';
import KeyboardsCrudSchema from './CRUD/Keyboards';
import FootableCrudSchema from './CRUD/Footable';
import NestedCrudSchema from './CRUD/Nested';
import MergeCellSchema from './CRUD/MergeCell';
2019-05-27 17:27:17 +08:00
import HeaderGroupSchema from './CRUD/HeaderGroup';
import LoadOnceTableCrudSchema from './CRUD/LoadOnce';
2019-04-30 11:11:25 +08:00
import SdkTest from './Sdk/Test';
import JSONSchemaForm from './Form/Schem';
import SimpleDialogSchema from './Dialog/Simple';
import DrwaerSchema from './Dialog/Drawer';
import PageLinkPageSchema from './Linkage/Page';
import FormLinkPageSchema from './Linkage/Form';
import Form2LinkPageSchema from './Linkage/Form2';
import CRUDLinkPageSchema from './Linkage/CRUD';
import OptionsPageSchema from './Linkage/Options';
import OptionsLocalPageSchema from './Linkage/OptionsLocal';
import WizardSchema from './Wizard';
import ChartSchema from './Chart';
import HorizontalSchema from './Horizontal';
import VideoSchema from './Video';
2019-05-06 14:08:33 +08:00
import AudioSchema from './Audio';
2019-05-16 16:31:20 +08:00
import CarouselSchema from './Carousel';
2019-04-30 11:11:25 +08:00
import TasksSchema from './Tasks';
import ServicesDataSchema from './Services/Data';
import ServicesSchemaSchema from './Services/Schema';
import ServicesFormSchema from './Services/Form';
import IFrameSchema from './IFrame';
import NormalTabSchema from './Tabs/Normal';
import FormTabSchema from './Tabs/Form';
import Tab1Schema from './Tabs/Tab1';
import Tab2Schema from './Tabs/Tab2';
import Tab3Schema from './Tabs/Tab3';
import TestComponent from './Test';
import Select from '../../src/components/Select';
import Button from '../../src/components/Button';
2019-06-04 16:24:09 +08:00
import DocSearch from './DocSearch';
2019-04-30 11:11:25 +08:00
let PathPrefix = '/examples';
2019-05-09 19:40:59 +08:00
if (process.env.NODE_ENV === 'production') {
PathPrefix = ''
}
2019-04-30 11:11:25 +08:00
const navigations = [
{
label: '示例',
children: [
{
label: '页面',
icon: 'glyphicon glyphicon-th',
badge: 3,
badgeClassName: 'bg-info',
children: [
{
label: '简单页面',
path: 'pages/simple',
component: makeSchemaRenderer(SimplePageSchema)
},
{
label: '初始化出错',
path: 'pages/error',
component: makeSchemaRenderer(ErrorPageSchema)
},
{
label: '表单页面',
path: 'pages/form',
component: makeSchemaRenderer(FormPageSchema)
}
]
},
{
label: '表单',
icon: 'fa fa-list-alt',
children: [
{
label: '表单展示模式',
path: 'form/mode',
component: makeSchemaRenderer(ModeFormSchema)
},
{
label: '所有类型汇总',
path: 'form/full',
component: makeSchemaRenderer(FullFormSchema)
},
{
label: '静态展示',
path: 'form/static',
component: makeSchemaRenderer(StaticFormSchema)
},
{
label: '输入提示',
path: 'form/hint',
component: makeSchemaRenderer(HintFormSchema)
},
{
label: 'FieldSet',
path: 'form/fieldset',
component: makeSchemaRenderer(FieldSetFormSchema)
},
{
label: 'Tabs',
path: 'form/tabs',
component: makeSchemaRenderer(TabsFormSchema)
},
{
label: 'FieldSet Tabs 组合',
path: 'form/fields-tabs',
component: makeSchemaRenderer(FieldSetInTabsFormSchema)
},
{
label: '动态数据',
path: 'form/remote',
component: makeSchemaRenderer(RemoteFormSchema)
},
{
label: '显隐状态联动',
path: 'form/reaction',
component: makeSchemaRenderer(ReactionFormSchema)
},
{
label: '表单验证',
path: 'form/validation',
component: makeSchemaRenderer(ValidationFormSchema)
},
{
label: '组合类型',
path: 'form/combo',
component: makeSchemaRenderer(ComboFormSchema)
},
{
label: '多功能选择器',
path: 'form/picker',
component: makeSchemaRenderer(PickerFormSchema)
},
{
label: '子表单',
path: 'form/sub-form',
component: makeSchemaRenderer(SubFormSchema)
},
{
label: 'JSon Schema表单',
path: 'form/json-schema',
component: JSONSchemaForm
},
{
label: '富文本',
path: 'form/rich-text',
component: makeSchemaRenderer(RichTextSchema)
},
{
label: '代码编辑器',
path: 'form/ide',
component: makeSchemaRenderer(EditorSchema)
},
{
label: '自定义组件',
path: 'form/custom',
component: makeSchemaRenderer(CustomFormSchema)
},
{
label: '表格编辑',
path: 'form/table',
component: makeSchemaRenderer(TableFormSchema)
},
{
label: '公式示例',
path: 'form/formula',
component: makeSchemaRenderer(FormulaFormSchema)
},
{
label: '布局测试',
path: 'form/layout-test',
component: makeSchemaRenderer(FormLayoutTestSchema)
},
{
label: '测试',
path: 'form/test',
component: makeSchemaRenderer(TestFormSchema)
},
]
},
{
label: '增删改查',
icon: 'fa fa-table',
children: [
{
label: '表格模式',
path: 'crud/table',
component: makeSchemaRenderer(TableCrudSchema)
},
{
label: '卡片模式',
path: 'crud/grid',
component: makeSchemaRenderer(GridCrudSchema)
},
{
label: '列表模式',
path: 'crud/list',
component: makeSchemaRenderer(ListCrudSchema)
},
{
label: '加载更多模式',
path: 'crud/load-more',
component: makeSchemaRenderer(LoadMoreSchema)
},
{
label: '操作交互显示',
path: 'crud/item-actions',
component: makeSchemaRenderer(ItemActionsSchema)
},
{
label: '列类型汇总',
path: 'crud/columns',
component: makeSchemaRenderer(FieldsCrudSchema)
},
{
label: '可折叠',
path: 'crud/footable',
component: makeSchemaRenderer(FootableCrudSchema)
},
{
label: '嵌套',
path: 'crud/nested',
component: makeSchemaRenderer(NestedCrudSchema)
},
{
label: '合并单元格',
path: 'crud/merge-cell',
component: makeSchemaRenderer(MergeCellSchema)
},
2019-05-27 17:27:17 +08:00
{
label: '表头分组',
path: 'crud/header-group',
component: makeSchemaRenderer(HeaderGroupSchema)
},
2019-04-30 11:11:25 +08:00
{
label: '带边栏',
path: 'crud/aside',
component: makeSchemaRenderer(AsideCrudSchema)
},
{
label: '固定表头/列',
path: 'crud/fixed',
component: makeSchemaRenderer(FixedCrudSchema)
},
{
label: '键盘操作编辑',
path: 'crud/keyboards',
component: makeSchemaRenderer(KeyboardsCrudSchema)
},
{
label: '操作并下一个',
path: 'crud/jump-next',
component: makeSchemaRenderer(JumpNextCrudSchema)
},
{
label: '一次性加载',
path: 'crud/load-once',
component: makeSchemaRenderer(LoadOnceTableCrudSchema)
},
2019-04-30 11:11:25 +08:00
{
label: '测试',
path: 'crud/test',
component: makeSchemaRenderer(TestCrudSchema)
}
]
},
{
label: '弹框',
icon: 'fa fa-bomb',
children: [
{
label: '对话框',
path: 'dialog/simple',
component: makeSchemaRenderer(SimpleDialogSchema)
},
{
label: '侧边弹出',
path: 'dialog/drawer',
component: makeSchemaRenderer(DrwaerSchema)
}
]
},
{
label: '选项卡',
icon: 'fa fa-clone',
children: [
{
label: '常规选项卡',
path: 'tabs/normal',
component: makeSchemaRenderer(NormalTabSchema)
},
{
label: '表单中选项卡分组',
path: 'tabs/form',
component: makeSchemaRenderer(FormTabSchema)
},
{
label: '选项卡页面1',
path: 'tabs/tab1',
component: makeSchemaRenderer(Tab1Schema)
},
{
label: '选项卡页面2',
path: 'tabs/tab2',
component: makeSchemaRenderer(Tab2Schema)
},
{
label: '选项卡页面3',
path: 'tabs/tab3',
component: makeSchemaRenderer(Tab3Schema)
},
]
},
{
label: '联动',
icon: 'fa fa-bolt',
children: [
{
label: '地址栏变化自动更新',
path: 'linkpage/page',
component: makeSchemaRenderer(PageLinkPageSchema)
},
{
label: '选项联动',
path: 'linkpage/options-local',
component: makeSchemaRenderer(OptionsLocalPageSchema)
},
{
label: '选项远程联动',
path: 'linkpage/options',
component: makeSchemaRenderer(OptionsPageSchema)
},
{
label: '表单和表单联动',
path: 'linkpage/form',
component: makeSchemaRenderer(FormLinkPageSchema)
},
{
label: '表单自动更新',
path: 'linkpage/form2',
component: makeSchemaRenderer(Form2LinkPageSchema)
},
{
label: '表单和列表联动',
path: 'linkpage/crud',
component: makeSchemaRenderer(CRUDLinkPageSchema)
}
]
},
{
label: '动态加载',
icon: 'fa fa-magic',
children: [
{
label: '动态加载数据',
path: 'services/data',
component: makeSchemaRenderer(ServicesDataSchema)
},
{
label: '动态加载页面',
path: 'services/schema',
component: makeSchemaRenderer(ServicesSchemaSchema)
},
{
label: '动态加载部分表单',
path: 'services/form',
component: makeSchemaRenderer(ServicesFormSchema)
}
]
},
{
label: '向导',
icon: 'fa fa-desktop',
path: 'wizard',
component: makeSchemaRenderer(WizardSchema)
},
{
label: '排版',
icon: 'fa fa-columns',
path: 'horizontal',
component: makeSchemaRenderer(HorizontalSchema)
},
{
label: '图表',
icon: 'fa fa-bar-chart',
path: 'chart',
component: makeSchemaRenderer(ChartSchema)
},
2019-05-16 16:31:20 +08:00
{
label: '轮播图',
icon: 'fa fa-pause',
path: 'carousel',
component: makeSchemaRenderer(CarouselSchema)
},
2019-05-06 14:08:33 +08:00
{
label: '音频',
icon: 'fa fa-volume-up',
path: 'audio',
component: makeSchemaRenderer(AudioSchema)
},
2019-04-30 11:11:25 +08:00
{
label: '视频',
icon: 'fa fa-video-camera',
path: 'video',
component: makeSchemaRenderer(VideoSchema)
},
{
label: '异步任务',
icon: 'fa fa-tasks',
path: 'task',
component: makeSchemaRenderer(TasksSchema)
},
{
label: 'IFrame',
icon: 'fa fa-cloud',
path: 'iframe',
component: makeSchemaRenderer(IFrameSchema)
},
{
label: 'SDK',
icon: 'fa fa-rocket',
path: 'sdk',
component: SdkTest
},
{
label: 'Test',
icon: 'fa fa-code',
path: 'test',
component: TestComponent
}
]
},
2019-05-09 18:25:12 +08:00
Docs
2019-04-30 11:11:25 +08:00
];
function isActive(link, location) {
return !!(link && link === location.pathname);
}
const themes = [
{
label: '默认主题',
ns: 'a-',
value: 'default'
},
{
label: '百度云舍',
ns: 'cxd-',
value: 'cxd'
}
];
2019-05-20 12:03:25 +08:00
@withRouter
2019-04-30 11:11:25 +08:00
export class App extends React.PureComponent {
state = {
asideFolded: localStorage.getItem('asideFolded') === 'true',
offScreen: false,
headerVisible: true,
themeIndex: 0,
themes: themes,
theme: themes[localStorage.getItem('themeIndex') || 0]
};
constructor(props) {
super(props);
this.toggleAside = this.toggleAside.bind(this);
this.setAsideFolded = this.setAsideFolded.bind(this);
this.setHeaderVisible = this.setHeaderVisible.bind(this);
}
componentDidMount() {
if (this.state.theme.value !== "default") {
document.querySelectorAll('link[title]').forEach(item => {
item.disabled = true
});
document.querySelector(`link[title=${this.state.theme.value}]`).disabled = false;
}
}
componentDidUpdate(preProps, preState) {
2019-05-20 12:03:25 +08:00
const props = this.props;
2019-04-30 11:11:25 +08:00
if (preState.theme.value !== this.state.theme.value) {
document.querySelector(`link[title=${preState.theme.value}]`).disabled = true;
document.querySelector(`link[title=${this.state.theme.value}]`).disabled = false;
}
2019-05-20 12:03:25 +08:00
2019-05-20 12:12:32 +08:00
if (props.location.pathname !== preProps.location.pathname) {
2019-05-20 12:03:25 +08:00
const pageURL = props.location.pathname;
_hmt && _hmt.push(['_trackPageview', pageURL]);
2019-05-28 11:56:51 +08:00
// 页面切换跳转到顶部。
window.scrollTo(0, 0);
2019-05-20 12:03:25 +08:00
}
2019-04-30 11:11:25 +08:00
}
toggleAside() {
this.setAsideFolded(!this.state.asideFolded);
}
setAsideFolded(folded = false) {
localStorage.setItem('asideFolded', JSON.stringify(folded));
this.setState({
asideFolded: folded
});
}
setHeaderVisible(visible = false) {
this.setState({
headerVisible: visible
});
}
renderAside() {
const location = this.props.location;
if (location.pathname === '/edit') {
return null;
}
const theme = this.state.theme;
return (
<AsideNav
theme={theme.value}
navigations={navigations}
renderLink={({link, active, toggleExpand, classnames: cx}) => {
let children = [];
if (link.children) {
children.push(
<span
key="expand-toggle"
className={cx('AsideNav-itemArrow')}
2019-05-28 11:56:51 +08:00
onClick={(e) => toggleExpand(link, e)}
2019-04-30 11:11:25 +08:00
></span>
);
}
link.badge && children.push(
<b key="badge" className={cx(`AsideNav-itemBadge`, link.badgeClassName || 'bg-info')}>{link.badge}</b>
);
link.icon && children.push(
<i key="icon" className={cx(`AsideNav-itemIcon`, link.icon)} />
);
children.push(
<span className={cx(`AsideNav-itemLabel`)} key="label">{link.label}</span>
);
return link.path ? (<Link to={link.path[0] === '/' ? link.path : `${PathPrefix}/${link.path}`}>{children}</Link>) : (<a onClick={link.children ? () => toggleExpand(link) : null}>{children}</a>);
}}
isActive={link => isActive(link.path && link.path[0] === '/' ? link.path : `${PathPrefix}/${link.path}`, location)}
/>
);
}
renderHeader() {
const location = this.props.location;
const theme = this.state.theme;
if (location.pathname === '/edit') {
return (
<div id="headerBar" className="box-shadow bg-dark">
<div className={`${theme.ns}Layout-brand`}>AMis 可视化编辑器</div>
</div>
);
}
return (
<div>
<div className={`${theme.ns}Layout-brandBar`}>
<button
onClick={() => this.setState({offScreen: !this.state.offScreen})}
className="pull-right visible-xs"
>
<i className="glyphicon glyphicon-align-justify"></i>
</button>
<div className={`${theme.ns}Layout-brand`}>
<i className="fa fa-paw"></i>
<span className="hidden-folded m-l-sm">AMis Renderer</span>
</div>
</div>
<div className={`${theme.ns}Layout-headerBar`}>
<div className="nav navbar-nav hidden-xs">
<Button
theme={this.state.theme.value}
level="link"
className="no-shadow navbar-btn"
onClick={this.toggleAside}
tooltip="展开或收起侧边栏"
placement="bottom"
iconOnly
>
<i className={this.state.asideFolded ? 'fa fa-indent' : 'fa fa-dedent'} />
</Button>
2019-05-23 16:44:16 +08:00
<Button
theme={this.state.theme.value}
level="link"
className="no-shadow navbar-btn"
2019-05-23 16:48:05 +08:00
href="https://github.com/baidu/amis"
2019-05-23 16:44:16 +08:00
tooltip="前往 Github 仓库地址"
placement="bottom"
iconOnly
>
<i className={'fa fa-github'} />
</Button>
2019-04-30 11:11:25 +08:00
</div>
<div className="hidden-xs p-t-sm pull-right">
主题{(
<Select
theme={this.state.theme.value}
value={this.state.theme}
options={this.state.themes}
onChange={(theme) => {
this.setState({theme});
localStorage.setItem('themeIndex', this.state.themes.indexOf(theme));
}}
/>
)}
</div>
2019-06-04 16:24:09 +08:00
<DocSearch />
2019-04-30 11:11:25 +08:00
</div>
</div>
);
}
render() {
// const pathname = this.props.location.pathname;
const theme = this.state.theme;
return (
<Layout
theme={theme.value}
offScreen={this.state.offScreen}
header={this.state.headerVisible ? this.renderHeader() : null}
folded={this.state.asideFolded}
aside={this.renderAside()}
>
<ToastComponent theme={theme.value} />
<AlertComponent theme={theme.value} />
{React.cloneElement(this.props.children, {
...this.props.children.props,
setAsideFolded: this.setAsideFolded,
setHeaderVisible: this.setHeaderVisible,
theme: theme.value,
classPrefix: theme.ns
})}
</Layout>
);
}
}
2019-05-09 19:40:59 +08:00
function navigations2route(pathPrefix = PathPrefix) {
2019-04-30 11:11:25 +08:00
let routes = [];
navigations.forEach(root => {
root.children && mapTree(root.children, item => {
if (item.path && item.component) {
routes.push(
<Route key={routes.length + 1} path={item.path[0] === '/' ? item.path : `${pathPrefix}/${item.path}`} component={item.component} />
)
} else if (item.path && item.getComponent) {
routes.push(
<Route key={routes.length + 1} path={item.path[0] === '/' ? item.path : `${pathPrefix}/${item.path}`} getComponent={item.getComponent} />
)
}
});
});
return routes;
}
export default function entry({pathPrefix}) {
2019-05-09 19:40:59 +08:00
PathPrefix = pathPrefix || PathPrefix;
2019-05-09 19:30:08 +08:00
let history = browserHistory;
if (process.env.NODE_ENV === 'production') {
history = hashHistory;
}
2019-04-30 11:11:25 +08:00
return (
2019-05-09 19:30:08 +08:00
<Router history={ history }>
2019-04-30 11:11:25 +08:00
<Route component={App}>
2019-05-09 19:40:59 +08:00
<Redirect from={`/`} to={`${PathPrefix}/pages/simple`} />
2019-04-30 11:11:25 +08:00
<Redirect from={`${PathPrefix}/`} to={`${PathPrefix}/pages/simple`} />
{navigations2route(PathPrefix)}
<Route path="*" component={NotFound} />
</Route>
</Router>
);
}