amis/examples/components/App.jsx
2020-06-15 14:50:45 +08:00

913 lines
25 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import NotFound from '../../src/components/404';
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';
import {Icon} from '../../src/components/icons';
import '../../src/locale/en';
import {
Router,
Route,
IndexRoute,
browserHistory,
hashHistory,
Link,
Redirect,
withRouter
} from 'react-router';
import makeSchemaRenderer from './SchemaRender';
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 TransferFormSchema from './Form/Transfer';
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';
import Definitions from './Form/Definitions';
import Docs from './Doc';
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';
import HeaderGroupSchema from './CRUD/HeaderGroup';
import LoadOnceTableCrudSchema from './CRUD/LoadOnce';
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';
import AudioSchema from './Audio';
import CarouselSchema from './Carousel';
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';
import DocSearch from './DocSearch';
let PathPrefix = '/examples';
let ContextPath = '';
if (process.env.NODE_ENV === 'production') {
PathPrefix = '';
ContextPath = '/amis';
}
const navigations = [
Docs,
{
prefix: ({classnames: cx}) => <li className={cx('AsideNav-divider')} />,
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/transfer',
component: makeSchemaRenderer(TransferFormSchema)
},
{
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/definitions',
component: makeSchemaRenderer(Definitions)
}
// {
// 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)
},
{
label: '表头分组',
path: 'crud/header-group',
component: makeSchemaRenderer(HeaderGroupSchema)
},
{
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)
}
// {
// 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)
},
{
label: '轮播图',
icon: 'fa fa-pause',
path: 'carousel',
component: makeSchemaRenderer(CarouselSchema)
},
{
label: '音频',
icon: 'fa fa-volume-up',
path: 'audio',
component: makeSchemaRenderer(AudioSchema)
},
{
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
}
]
}
];
function isActive(link, location) {
return !!(link && link === location.pathname);
}
const themes = [
{
label: '默认主题',
ns: 'a-',
value: 'default'
},
{
label: '百度云舍',
ns: 'cxd-',
value: 'cxd'
},
{
label: 'Dark',
ns: 'dark-',
value: 'dark'
}
];
const locales = [
{
label: '默认',
value: 'zh-cn'
},
{
label: 'English',
value: 'en'
}
];
@withRouter
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],
locale: localStorage.getItem('locale') || ''
};
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) {
const props = this.props;
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;
}
if (props.location.pathname !== preProps.location.pathname) {
this.setState(
{
offScreen: false
},
() => window.scrollTo(0, 0)
);
const pageURL = props.location.pathname;
_hmt && _hmt.push(['_trackPageview', pageURL]);
}
}
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')}
onClick={e => toggleExpand(link, e)}
>
<Icon icon="right-arrow-bold" className="icon" />
</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] === '/'
? ContextPath + link.path
: `${ContextPath}${PathPrefix}/${link.path}`
}
>
{children}
</Link>
) : (
<a onClick={link.children ? () => toggleExpand(link) : null}>
{children}
</a>
);
}}
isActive={link =>
isActive(
link.path && link.path[0] === '/'
? ContextPath + link.path
: `${ContextPath}${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" />
</button>
<div className={`${theme.ns}Layout-brand`}>
<i className="fa fa-paw" />
<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">
<div id="headerLeftBtns" className="m-t-sm">
<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>
<Button
theme={this.state.theme.value}
level="link"
className="no-shadow navbar-btn"
href="https://github.com/baidu/amis"
tooltip="前往 Github 仓库地址"
placement="bottom"
iconOnly
>
<i className={'fa fa-github'} />
</Button>
</div>
</div>
<div className="hidden-xs p-t-sm pull-right m-l-sm">
语言
{
<Select
clearable={false}
theme={this.state.theme.value}
value={this.state.locale || 'zh-cn'}
options={locales}
onChange={locale => {
this.setState({locale: locale.value});
localStorage.setItem('locale', locale.value);
}}
/>
}
</div>
<div className="hidden-xs p-t-sm pull-right">
主题
{
<Select
clearable={false}
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>
<DocSearch theme={this.state.theme.value} />
</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} locale={this.state.locale} />
<AlertComponent theme={theme.value} locale={this.state.locale} />
{React.cloneElement(this.props.children, {
...this.props.children.props,
setAsideFolded: this.setAsideFolded,
setHeaderVisible: this.setHeaderVisible,
theme: theme.value,
classPrefix: theme.ns,
locale: this.state.locale
})}
</Layout>
);
}
}
function navigations2route(pathPrefix = PathPrefix) {
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] === '/'
? ContextPath + item.path
: `${ContextPath}${pathPrefix}/${item.path}`
}
component={item.component}
/>
);
} else if (item.path && item.getComponent) {
routes.push(
<Route
key={routes.length + 1}
path={
item.path[0] === '/'
? ContextPath + item.path
: `${ContextPath}${pathPrefix}/${item.path}`
}
getComponent={item.getComponent}
/>
);
}
});
});
return routes;
}
export default function entry({pathPrefix}) {
PathPrefix = pathPrefix || PathPrefix;
let history = browserHistory;
// if (process.env.NODE_ENV === 'production') {
// history = hashHistory;
// }
return (
<Router history={history}>
<Route component={App}>
<Redirect from={`${ContextPath}/`} to={`${ContextPath}/docs/intro`} />
<Redirect from={`${PathPrefix}/`} to={`/docs/intro`} />
{navigations2route(PathPrefix)}
<Route path="*" component={NotFound} />
</Route>
</Router>
);
}