Translation user and post page.

This commit is contained in:
zuiidea
2018-10-24 18:52:56 +08:00
parent f654b277fa
commit 0499b70218
15 changed files with 495 additions and 381 deletions
+8 -1
View File
@@ -17,17 +17,24 @@ export function randomNumber(min, max) {
}
export function randomAvatar() {
// https://uifaces.co
const avatarList = [
'https://randomuser.me/api/portraits/men/32.jpg',
'https://images.pexels.com/photos/415829/pexels-photo-415829.jpeg?h=350&auto=compress&cs=tinysrgb',
'https://d3iw72m71ie81c.cloudfront.net/female-17.jpg',
'https://randomuser.me/api/portraits/men/35.jpg',
'https://pbs.twimg.com/profile_images/835224725815246848/jdMBCxHS.jpg',
'https://pbs.twimg.com/profile_images/1010888664732200962/OmFg5TO0.jpg',
'https://pbs.twimg.com/profile_images/584098247641300992/N25WgvW_.png',
'https://d3iw72m71ie81c.cloudfront.net/male-5.jpg',
'https://images.pexels.com/photos/413723/pexels-photo-413723.jpeg?h=350&auto=compress&cs=tinysrgb',
'https://images.pexels.com/photos/61100/pexels-photo-61100.jpeg?h=350&auto=compress&cs=tinysrgb',
'https://randomuser.me/api/portraits/women/44.jpg',
'https://randomuser.me/api/portraits/women/68.jpg',
'https://randomuser.me/api/portraits/women/65.jpg',
'https://randomuser.me/api/portraits/men/43.jpg',
'https://tinyfac.es/data/avatars/475605E3-69C5-4D2B-8727-61B7BB8C4699-500w.jpeg',
'https://pbs.twimg.com/profile_images/943227488292962306/teiNNAiy.jpg',
'https://randomuser.me/api/portraits/men/46.jpg'
]
return avatarList[randomNumber(0, avatarList.length - 1)]
}
+1 -7
View File
@@ -15,13 +15,7 @@ let usersListData = Mock.mock({
email: '@email',
createTime: '@datetime',
avatar() {
return Mock.Random.image(
'100x100',
Mock.Random.color(),
'#757575',
'png',
this.nickName.substr(0, 1)
)
return randomAvatar()
},
},
],
+41 -1
View File
@@ -1,14 +1,54 @@
{
"/dashboard": "/dashboard",
"Add Param": "Add Param",
"Address": "Address",
"Age": "Age",
"Are you sure delete this record?": "Are you sure delete this record?",
"Author": "Author",
"Avatar": "Avatar",
"Categories": "Categories",
"Clear notifications": "Clear notifications",
"Comments": "Comments",
"Create": "Create",
"Create User": "Create User",
"CreateTime": "CreateTime",
"Dark": "Dark",
"Delete": "Delete",
"Email": "Email",
"Female": "Female",
"Gender": "Gender",
"Hi,": "Hi,",
"Image": "Image",
"Light": "Light",
"Male": "Male",
"Name": "Name",
"NickName": "NickName",
"Not Found": "Not Found",
"Operation": "Operation",
"Params": "Params",
"Password": "Password",
"Phone": "Phone",
"Pick an address": "Pick an address",
"Please pick an address": "Please pick an address",
"Publised": "Publised",
"Publish Date": "Publish Date",
"Reset": "Reset",
"Search": "Search",
"Search Name": "Search Name",
"Send": "Send",
"Sign in": "Sign in",
"Sign out": "Sign out",
"Switch Theme": "Switch Theme",
"Tags": "Tags",
"The input is not valid E-mail!": "The input is not valid E-mail!",
"The input is not valid phone!": "The input is not valid phone!",
"Title": "Title",
"Total {total} Items": "Total {total} Items",
"Unpublished": "Unpublished",
"Update": "Update",
"Update User": "Update User",
"Username": "Username",
"Views": "Views",
"Visibility": "Visibility",
"You have viewed all notifications.": "You have viewed all notifications."
}
}
+41 -1
View File
@@ -1,14 +1,54 @@
{
"/dashboard": "/zh/dashboard",
"Add Param": "添加参数",
"Address": "地址",
"Age": "年龄",
"Are you sure delete this record?": "您确定要删除这条记录吗?",
"Author": "作者",
"Avatar": "头像",
"Categories": "类别",
"Clear notifications": "清空消息",
"Comments": "评论数",
"Create": "创建",
"Create User": "创建用户",
"CreateTime": "创建时间",
"Dark": "暗",
"Delete": "删除",
"Email": "电子邮件",
"Female": "女",
"Gender": "性别",
"Hi,": "你好,",
"Image": "图像",
"Light": "明",
"Male": "男性",
"Name": "名字",
"NickName": "昵称",
"Not Found": "未找到",
"Operation": "操作",
"Params": "参数",
"Password": "密码",
"Phone": "电话",
"Pick an address": "选择地址",
"Please pick an address": "选择地址",
"Publised": "已发布",
"Publish Date": "发布日期",
"Reset": "重置",
"Search": "搜索",
"Search Name": "搜索名字",
"Send": "发送",
"Sign in": "登录",
"Sign out": "退出登录",
"Switch Theme": "切换主题",
"Tags": "标签",
"The input is not valid E-mail!": "输入的电子邮件无效!",
"The input is not valid phone!": "输入无效的手机!",
"Title": "标题",
"Total {total} Items": "总共 {total} 条记录",
"Unpublished": "未发布",
"Update": "更新",
"Update User": "更新用户",
"Username": "用户名",
"Views": "浏览数",
"Visibility": "可见性",
"You have viewed all notifications.": "您已查看所有通知"
}
}
+64 -58
View File
@@ -1,63 +1,69 @@
import React from 'react'
import { Table } from 'antd'
import styles from './List.less'
import React, { PureComponent } from 'react'
import { Table, Avatar } from 'antd'
import { withI18n } from '@lingui/react'
const List = ({ ...tableProps }) => {
const columns = [
{
title: 'Image',
dataIndex: 'image',
className: styles.image,
width: 64,
render: text => <img alt="Feture" width={26} src={text} />,
},
{
title: 'Title',
dataIndex: 'title',
},
{
title: 'Author',
dataIndex: 'author',
},
{
title: 'Categories',
dataIndex: 'categories',
},
{
title: 'Tags',
dataIndex: 'tags',
},
{
title: 'Visibility',
dataIndex: 'visibility',
},
{
title: 'Comments',
dataIndex: 'comments',
},
{
title: 'Views',
dataIndex: 'views',
},
{
title: 'Date',
dataIndex: 'date',
},
]
@withI18n()
class List extends PureComponent {
render() {
const { i18n, ...tableProps } = this.props
const columns = [
{
title: i18n.t`Image`,
dataIndex: 'image',
width: 100,
render: text => <Avatar shape="square" src={text} />,
},
{
title: i18n.t`Title`,
dataIndex: 'title',
},
{
title: i18n.t`Author`,
dataIndex: 'author',
},
{
title: i18n.t`Categories`,
dataIndex: 'categories',
},
{
title: i18n.t`Tags`,
dataIndex: 'tags',
},
{
title: i18n.t`Visibility`,
dataIndex: 'visibility',
},
{
title: i18n.t`Comments`,
dataIndex: 'comments',
},
{
title: i18n.t`Views`,
dataIndex: 'views',
},
{
title: i18n.t`Publish Date`,
dataIndex: 'date',
},
]
return (
<div>
<Table
{...tableProps}
bordered
scroll={{ x: 1200 }}
columns={columns}
simple
className={styles.table}
rowKey={record => record.id}
/>
</div>
)
return (
<div>
<Table
{...tableProps}
pagination={{
...tableProps.pagination,
showTotal: total => i18n.t`Total ${total} Items`,
}}
bordered
scroll={{ x: 1200 }}
columns={columns}
simple
rowKey={record => record.id}
/>
</div>
)
}
}
export default List
-16
View File
@@ -1,16 +0,0 @@
.table {
td.image {
line-height: 1;
img {
border-radius: 2px;
}
}
:global {
.ant-table-tbody > tr > td,
.ant-table-thead > tr > th {
height: 60px;
}
}
}
+11 -3
View File
@@ -4,6 +4,7 @@ import { connect } from 'dva'
import { Tabs } from 'antd'
import { router } from 'utils'
import { stringify } from 'qs'
import { withI18n } from '@lingui/react'
import { Page } from 'components'
import List from './components/List'
@@ -14,10 +15,11 @@ const EnumPostStatus = {
PUBLISHED: 2,
}
@withI18n()
@connect(({ post, loading }) => ({ post, loading }))
class Post extends PureComponent {
render() {
const { post, loading, location } = this.props
const { post, loading, location, i18n } = this.props
const { list, pagination } = post
const { query, pathname } = location
@@ -56,10 +58,16 @@ class Post extends PureComponent {
}
onTabClick={handleTabClick}
>
<TabPane tab="Publised" key={String(EnumPostStatus.PUBLISHED)}>
<TabPane
tab={i18n.t`Publised`}
key={String(EnumPostStatus.PUBLISHED)}
>
<List {...listProps} />
</TabPane>
<TabPane tab="Unpublish" key={String(EnumPostStatus.UNPUBLISH)}>
<TabPane
tab={i18n.t`Unpublished`}
key={String(EnumPostStatus.UNPUBLISH)}
>
<List {...listProps} />
</TabPane>
</Tabs>
+3 -1
View File
@@ -237,7 +237,9 @@ class RequestPage extends React.Component {
))}
<Row style={{ marginTop: 8 }}>
<Button onClick={this.handleAddField}>Add Param</Button>
<Button onClick={this.handleAddField}>
<Trans>Add Param</Trans>
</Button>
</Row>
</div>
+3 -2
View File
@@ -1,6 +1,7 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'dva'
import { Page } from 'components'
import styles from './index.less'
@connect(({ userDetail }) => ({ userDetail }))
@@ -20,9 +21,9 @@ class UserDetail extends PureComponent {
}
}
return (
<div className="content-inner">
<Page inner>
<div className={styles.content}>{content}</div>
</div>
</Page>
)
}
}
+106 -81
View File
@@ -1,8 +1,9 @@
/* global document */
import React from 'react'
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import moment from 'moment'
import { FilterItem } from 'components'
import { Trans, withI18n } from '@lingui/react'
import { Form, Button, Row, Col, DatePicker, Input, Cascader } from 'antd'
import city from 'utils/city'
@@ -22,13 +23,10 @@ const TwoColProps = {
xl: 96,
}
const Filter = ({
onAdd,
onFilterChange,
filter,
form: { getFieldDecorator, getFieldsValue, setFieldsValue },
}) => {
const handleFields = fields => {
@withI18n()
@Form.create()
class Filter extends PureComponent {
handleFields = fields => {
const { createTime } = fields
if (createTime.length) {
fields.createTime = [
@@ -39,13 +37,19 @@ const Filter = ({
return fields
}
const handleSubmit = () => {
handleSubmit = () => {
const { onFilterChange, form } = this.props
const { getFieldsValue } = form
let fields = getFieldsValue()
fields = handleFields(fields)
fields = this.handleFields(fields)
onFilterChange(fields)
}
const handleReset = () => {
handleReset = () => {
const { form } = this.props
const { getFieldsValue, setFieldsValue } = form
const fields = getFieldsValue()
for (let item in fields) {
if ({}.hasOwnProperty.call(fields, item)) {
@@ -57,86 +61,107 @@ const Filter = ({
}
}
setFieldsValue(fields)
handleSubmit()
this.handleSubmit()
}
handleChange = (key, values) => {
const { form, onFilterChange } = this.props
const { getFieldsValue } = form
const handleChange = (key, values) => {
let fields = getFieldsValue()
fields[key] = values
fields = handleFields(fields)
fields = this.handleFields(fields)
onFilterChange(fields)
}
const { name, address } = filter
let initialCreateTime = []
if (filter.createTime && filter.createTime[0]) {
initialCreateTime[0] = moment(filter.createTime[0])
}
if (filter.createTime && filter.createTime[1]) {
initialCreateTime[1] = moment(filter.createTime[1])
}
render() {
const { onAdd, filter, form, i18n } = this.props
const { getFieldDecorator } = form
const { name, address } = filter
return (
<Row gutter={24}>
<Col {...ColProps} xl={{ span: 4 }} md={{ span: 8 }}>
{getFieldDecorator('name', { initialValue: name })(
<Search placeholder="Search Name" onSearch={handleSubmit} />
)}
</Col>
<Col {...ColProps} xl={{ span: 4 }} md={{ span: 8 }} id="addressCascader">
{getFieldDecorator('address', { initialValue: address })(
<Cascader
style={{ width: '100%' }}
options={city}
placeholder="Please pick an address"
onChange={handleChange.bind(null, 'address')}
getPopupContainer={() => document.getElementById('addressCascader')}
/>
)}
</Col>
<Col
{...ColProps}
xl={{ span: 6 }}
md={{ span: 8 }}
sm={{ span: 12 }}
id="createTimeRangePicker"
>
<FilterItem label="Createtime">
{getFieldDecorator('createTime', { initialValue: initialCreateTime })(
<RangePicker
style={{ width: '100%' }}
onChange={handleChange.bind(null, 'createTime')}
getCalendarContainer={() => {
return document.getElementById('createTimeRangePicker')
}}
let initialCreateTime = []
if (filter.createTime && filter.createTime[0]) {
initialCreateTime[0] = moment(filter.createTime[0])
}
if (filter.createTime && filter.createTime[1]) {
initialCreateTime[1] = moment(filter.createTime[1])
}
return (
<Row gutter={24}>
<Col {...ColProps} xl={{ span: 4 }} md={{ span: 8 }}>
{getFieldDecorator('name', { initialValue: name })(
<Search
placeholder={i18n.t`Search Name`}
onSearch={this.handleSubmit}
/>
)}
</FilterItem>
</Col>
<Col
{...TwoColProps}
xl={{ span: 10 }}
md={{ span: 24 }}
sm={{ span: 24 }}
>
<Row type="flex" align="middle" justify="space-between">
<div>
<Button
type="primary"
className="margin-right"
onClick={handleSubmit}
>
Search
</Col>
<Col
{...ColProps}
xl={{ span: 4 }}
md={{ span: 8 }}
id="addressCascader"
>
{getFieldDecorator('address', { initialValue: address })(
<Cascader
style={{ width: '100%' }}
options={city}
placeholder={i18n.t`Please pick an address`}
onChange={this.handleChange.bind(this, 'address')}
getPopupContainer={() =>
document.getElementById('addressCascader')
}
/>
)}
</Col>
<Col
{...ColProps}
xl={{ span: 6 }}
md={{ span: 8 }}
sm={{ span: 12 }}
id="createTimeRangePicker"
>
<FilterItem label={i18n.t`CreateTime`}>
{getFieldDecorator('createTime', {
initialValue: initialCreateTime,
})(
<RangePicker
style={{ width: '100%' }}
onChange={this.handleChange.bind(this, 'createTime')}
getCalendarContainer={() => {
return document.getElementById('createTimeRangePicker')
}}
/>
)}
</FilterItem>
</Col>
<Col
{...TwoColProps}
xl={{ span: 10 }}
md={{ span: 24 }}
sm={{ span: 24 }}
>
<Row type="flex" align="middle" justify="space-between">
<div>
<Button
type="primary"
className="margin-right"
onClick={this.handleSubmit}
>
<Trans>Search</Trans>
</Button>
<Button onClick={this.handleReset}>
<Trans>Reset</Trans>
</Button>
</div>
<Button type="ghost" onClick={onAdd}>
<Trans>Create</Trans>
</Button>
<Button onClick={handleReset}>Reset</Button>
</div>
<Button type="ghost" onClick={onAdd}>
Create
</Button>
</Row>
</Col>
</Row>
)
</Row>
</Col>
</Row>
)
}
}
Filter.propTypes = {
@@ -146,4 +171,4 @@ Filter.propTypes = {
onFilterChange: PropTypes.func,
}
export default Form.create()(Filter)
export default Filter
+100 -85
View File
@@ -1,19 +1,22 @@
import React from 'react'
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { Table, Modal } from 'antd'
import { Table, Modal, Avatar } from 'antd'
import { DropOption } from 'components'
import { Trans, withI18n } from '@lingui/react'
import Link from 'umi/link'
import styles from './List.less'
const { confirm } = Modal
const List = ({ onDeleteItem, onEditItem, location, ...tableProps }) => {
const handleMenuClick = (record, e) => {
@withI18n()
class List extends PureComponent {
handleMenuClick = (record, e) => {
const { onDeleteItem, onEditItem, i18n } = this.props
if (e.key === '1') {
onEditItem(record)
} else if (e.key === '2') {
confirm({
title: 'Are you sure delete this record?',
title: i18n.t`Are you sure delete this record?`,
onOk() {
onDeleteItem(record.id)
},
@@ -21,86 +24,98 @@ const List = ({ onDeleteItem, onEditItem, location, ...tableProps }) => {
}
}
const columns = [
{
title: 'Avatar',
dataIndex: 'avatar',
key: 'avatar',
width: 64,
className: styles.avatar,
render: text => <img alt="avatar" width={24} src={text} />,
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (text, record) => <Link to={`user/${record.id}`}>{text}</Link>,
},
{
title: 'NickName',
dataIndex: 'nickName',
key: 'nickName',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Gender',
dataIndex: 'isMale',
key: 'isMale',
render: text => <span>{text ? 'Male' : 'Female'}</span>,
},
{
title: 'Phone',
dataIndex: 'phone',
key: 'phone',
},
{
title: 'Email',
dataIndex: 'email',
key: 'email',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'CreateTime',
dataIndex: 'createTime',
key: 'createTime',
},
{
title: 'Operation',
key: 'operation',
width: 100,
render: (text, record) => {
return (
<DropOption
onMenuClick={e => handleMenuClick(record, e)}
menuOptions={[
{ key: '1', name: 'Update' },
{ key: '2', name: 'Delete' },
]}
/>
)
},
},
]
render() {
const {
handleMenuClick,
onDeleteItem,
onEditItem,
i18n,
...tableProps
} = this.props
return (
<Table
{...tableProps}
className={styles.table}
bordered
scroll={{ x: 1250 }}
columns={columns}
simple
rowKey={record => record.id}
/>
)
const columns = [
{
title: <Trans>Avatar</Trans>,
dataIndex: 'avatar',
key: 'avatar',
width: 100,
render: text => <Avatar style={{ marginLeft: 8 }} src={text} />,
},
{
title: <Trans>Name</Trans>,
dataIndex: 'name',
key: 'name',
render: (text, record) => <Link to={`user/${record.id}`}>{text}</Link>,
},
{
title: <Trans>NickName</Trans>,
dataIndex: 'nickName',
key: 'nickName',
},
{
title: <Trans>Age</Trans>,
dataIndex: 'age',
key: 'age',
},
{
title: <Trans>Gender</Trans>,
dataIndex: 'isMale',
key: 'isMale',
render: text => <span>{text ? 'Male' : 'Female'}</span>,
},
{
title: <Trans>Phone</Trans>,
dataIndex: 'phone',
key: 'phone',
},
{
title: <Trans>Email</Trans>,
dataIndex: 'email',
key: 'email',
},
{
title: <Trans>Address</Trans>,
dataIndex: 'address',
key: 'address',
},
{
title: <Trans>CreateTime</Trans>,
dataIndex: 'createTime',
key: 'createTime',
},
{
title: <Trans>Operation</Trans>,
key: 'operation',
width: 100,
render: (text, record) => {
return (
<DropOption
onMenuClick={e => handleMenuClick(record, e)}
menuOptions={[
{ key: '1', name: i18n.t`Update` },
{ key: '2', name: i18n.t`Delete` },
]}
/>
)
},
},
]
return (
<Table
{...tableProps}
pagination={{
...tableProps.pagination,
showTotal: total => i18n.t`Total ${total} Items`,
}}
bordered
scroll={{ x: 1250 }}
columns={columns}
simple
rowKey={record => record.id}
/>
)
}
}
List.propTypes = {
-14
View File
@@ -1,14 +0,0 @@
.table {
td.avatar {
img {
border-radius: 50%;
}
}
:global {
.ant-table-tbody > tr > td,
.ant-table-thead > tr > th {
height: 62px;
}
}
}
+111 -107
View File
@@ -1,6 +1,7 @@
import React from 'react'
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { Form, Input, InputNumber, Radio, Modal, Cascader } from 'antd'
import { Trans, withI18n } from '@lingui/react'
import city from 'utils/city'
const FormItem = Form.Item
@@ -13,14 +14,13 @@ const formItemLayout = {
span: 14,
},
}
@withI18n()
@Form.create()
class UserModal extends PureComponent {
handleOk = () => {
const { item = {}, onOk, form } = this.props
const { validateFields, getFieldsValue } = form
const modal = ({
item = {},
onOk,
form: { getFieldDecorator, validateFields, getFieldsValue },
...modalProps
}) => {
const handleOk = () => {
validateFields(errors => {
if (errors) {
return
@@ -34,111 +34,115 @@ const modal = ({
})
}
const modalOpts = {
...modalProps,
onOk: handleOk,
}
render() {
const { item = {}, onOk, form, i18n, ...modalProps } = this.props
const { getFieldDecorator } = form
return (
<Modal {...modalOpts}>
<Form layout="horizontal">
<FormItem label="Name" hasFeedback {...formItemLayout}>
{getFieldDecorator('name', {
initialValue: item.name,
rules: [
{
required: true,
},
],
})(<Input />)}
</FormItem>
<FormItem label="NickName" hasFeedback {...formItemLayout}>
{getFieldDecorator('nickName', {
initialValue: item.nickName,
rules: [
{
required: true,
},
],
})(<Input />)}
</FormItem>
<FormItem label="Gender" hasFeedback {...formItemLayout}>
{getFieldDecorator('isMale', {
initialValue: item.isMale,
rules: [
{
required: true,
type: 'boolean',
},
],
})(
<Radio.Group>
<Radio value>Male</Radio>
<Radio value={false}>Female</Radio>
</Radio.Group>
)}
</FormItem>
<FormItem label="Age" hasFeedback {...formItemLayout}>
{getFieldDecorator('age', {
initialValue: item.age,
rules: [
{
required: true,
type: 'number',
},
],
})(<InputNumber min={18} max={100} />)}
</FormItem>
<FormItem label="Phone" hasFeedback {...formItemLayout}>
{getFieldDecorator('phone', {
initialValue: item.phone,
rules: [
{
required: true,
pattern: /^1[34578]\d{9}$/,
message: 'The input is not valid phone!',
},
],
})(<Input />)}
</FormItem>
<FormItem label="E-mail" hasFeedback {...formItemLayout}>
{getFieldDecorator('email', {
initialValue: item.email,
rules: [
{
required: true,
pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,
message: 'The input is not valid E-mail!',
},
],
})(<Input />)}
</FormItem>
<FormItem label="Address" hasFeedback {...formItemLayout}>
{getFieldDecorator('address', {
initialValue: item.address && item.address.split(' '),
rules: [
{
required: true,
},
],
})(
<Cascader
style={{ width: '100%' }}
options={city}
placeholder="Pick an address"
/>
)}
</FormItem>
</Form>
</Modal>
)
return (
<Modal {...modalProps} onOk={this.handleOk}>
<Form layout="horizontal">
<FormItem label={i18n.t`Name`} hasFeedback {...formItemLayout}>
{getFieldDecorator('name', {
initialValue: item.name,
rules: [
{
required: true,
},
],
})(<Input />)}
</FormItem>
<FormItem label={i18n.t`NickName`} hasFeedback {...formItemLayout}>
{getFieldDecorator('nickName', {
initialValue: item.nickName,
rules: [
{
required: true,
},
],
})(<Input />)}
</FormItem>
<FormItem label={i18n.t`Gender`} hasFeedback {...formItemLayout}>
{getFieldDecorator('isMale', {
initialValue: item.isMale,
rules: [
{
required: true,
type: 'boolean',
},
],
})(
<Radio.Group>
<Radio value>
<Trans>Male</Trans>
</Radio>
<Radio value={false}>
<Trans>Female</Trans>
</Radio>
</Radio.Group>
)}
</FormItem>
<FormItem label={i18n.t`Age`} hasFeedback {...formItemLayout}>
{getFieldDecorator('age', {
initialValue: item.age,
rules: [
{
required: true,
type: 'number',
},
],
})(<InputNumber min={18} max={100} />)}
</FormItem>
<FormItem label={i18n.t`Phone`} hasFeedback {...formItemLayout}>
{getFieldDecorator('phone', {
initialValue: item.phone,
rules: [
{
required: true,
pattern: /^1[34578]\d{9}$/,
message: i18n.t`The input is not valid phone!`,
},
],
})(<Input />)}
</FormItem>
<FormItem label={i18n.t`Email`} hasFeedback {...formItemLayout}>
{getFieldDecorator('email', {
initialValue: item.email,
rules: [
{
required: true,
pattern: /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/,
message: i18n.t`The input is not valid E-mail!`,
},
],
})(<Input />)}
</FormItem>
<FormItem label={i18n.t`Address`} hasFeedback {...formItemLayout}>
{getFieldDecorator('address', {
initialValue: item.address && item.address.split(' '),
rules: [
{
required: true,
},
],
})(
<Cascader
style={{ width: '100%' }}
options={city}
placeholder={i18n.t`Pick an address`}
/>
)}
</FormItem>
</Form>
</Modal>
)
}
}
modal.propTypes = {
UserModal.propTypes = {
form: PropTypes.object.isRequired,
type: PropTypes.string,
item: PropTypes.object,
onOk: PropTypes.func,
}
export default Form.create()(modal)
export default UserModal
+6 -3
View File
@@ -3,16 +3,18 @@ import PropTypes from 'prop-types'
import { router } from 'utils'
import { connect } from 'dva'
import { Row, Col, Button, Popconfirm } from 'antd'
import { withI18n } from '@lingui/react'
import { Page } from 'components'
import { stringify } from 'qs'
import List from './components/List'
import Filter from './components/Filter'
import Modal from './components/Modal'
@withI18n()
@connect(({ user, loading }) => ({ user, loading }))
class User extends PureComponent {
render() {
const { location, dispatch, user, loading } = this.props
const { location, dispatch, user, loading, i18n } = this.props
const { query, pathname } = location
const {
list,
@@ -41,7 +43,9 @@ class User extends PureComponent {
visible: modalVisible,
maskClosable: false,
confirmLoading: loading.effects[`user/${modalType}`],
title: `${modalType === 'create' ? 'Create User' : 'Update User'}`,
title: `${
modalType === 'create' ? i18n.t`Create User` : i18n.t`Update User`
}`,
wrapClassName: 'vertical-center-modal',
onOk(data) {
dispatch({
@@ -62,7 +66,6 @@ class User extends PureComponent {
dataSource: list,
loading: loading.effects['user/query'],
pagination,
location,
onChange(page) {
handleRefresh({
page: page.current,
-1
View File
@@ -17,7 +17,6 @@ export const pageModel = modelExtend(model, {
pagination: {
showSizeChanger: true,
showQuickJumper: true,
showTotal: total => `Total ${total} Items`,
current: 1,
total: 0,
pageSize: 10,