Selectable List in place
This commit is contained in:
@@ -7,7 +7,7 @@ import { HeaderButton, Column, Row, Text, Box } from 'ui'
|
||||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
|
||||
import logoImage from 'images/logo.png'
|
||||
import { versionInfo } from './version'
|
||||
import { sizeInfo } from 'ui/style'
|
||||
import { sizeInfo, colorInfo } from 'ui/style'
|
||||
import { api } from 'src/API'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
|
||||
@@ -59,7 +59,7 @@ export class App extends Component {
|
||||
<Router basename='/'>
|
||||
<Column minHeight='100vh'>
|
||||
<Column.Item height={sizeInfo.headerHeight - sizeInfo.headerBorderWidth}>
|
||||
<Box color='#FAFAFA' borderBottom={`${sizeInfo.headerBorderWidth}px solid #B2B2B2`}>
|
||||
<Box color={colorInfo.headerButtonBackground} borderBottom={`${sizeInfo.headerBorderWidth}px solid ${colorInfo.headerBorder}`}>
|
||||
<Row minWidth='100vw'>
|
||||
<Row.Item>{headerButtonsLeft}</Row.Item>
|
||||
<Row.Item grow />
|
||||
@@ -67,24 +67,20 @@ export class App extends Component {
|
||||
</Row>
|
||||
</Box>
|
||||
</Column.Item>
|
||||
<Column.Item grow />
|
||||
<Switch>
|
||||
<Route path='/login' component={Login} />
|
||||
<Route path='/confirm-email' component={ConfirmEmail} />
|
||||
<Route path='/reset-password' component={ResetPassword} />
|
||||
<Route path='/forgot-password' component={ForgotPassword} />
|
||||
<ProtectedRoute path='/profile' component={Profile} />
|
||||
<ProtectedRoute path='/users' component={Users} />
|
||||
<ProtectedRoute path='/teams' component={Users} />
|
||||
<ProtectedRoute path='/system' component={Users} />
|
||||
<ProtectedRoute path='/logout' component={Logout} />
|
||||
<ProtectedRoute path='/' component={Home} />
|
||||
</Switch>
|
||||
<Column.Item>
|
||||
<Switch>
|
||||
<Route path='/login' component={Login} />
|
||||
<Route path='/confirm-email' component={ConfirmEmail} />
|
||||
<Route path='/reset-password' component={ResetPassword} />
|
||||
<Route path='/forgot-password' component={ForgotPassword} />
|
||||
<ProtectedRoute path='/profile' component={Profile} />
|
||||
<ProtectedRoute path='/users' component={Users} />
|
||||
<ProtectedRoute path='/teams' component={Users} />
|
||||
<ProtectedRoute path='/system' component={Users} />
|
||||
<ProtectedRoute path='/logout' component={Logout} />
|
||||
<ProtectedRoute path='/' component={Home} />
|
||||
</Switch>
|
||||
</Column.Item>
|
||||
<Column.Item grow />
|
||||
<Column.Item>
|
||||
<Box color='#FAFAFA' borderTop={`${sizeInfo.headerBorderWidth}px solid #B2B2B2`}>
|
||||
<Box color={colorInfo.headerButtonBackground} borderTop={`${sizeInfo.headerBorderWidth}px solid ${colorInfo.headerBorder}`}>
|
||||
<Text color='dimmed' margin={10}>{'v' + versionInfo.version} {versionInfo.copyright}</Text>
|
||||
</Box>
|
||||
</Column.Item>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import { api } from 'src/API'
|
||||
@@ -10,7 +10,7 @@ import { FormBinder } from 'react-form-binder'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
import { sizeInfo } from 'ui/style'
|
||||
|
||||
export class Login extends React.Component {
|
||||
export class Login extends Component {
|
||||
static propTypes = {
|
||||
history: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
|
||||
}
|
||||
@@ -96,68 +96,74 @@ export class Login extends React.Component {
|
||||
const { messageModal, waitModal } = this.state
|
||||
|
||||
return (
|
||||
<Row minHeight='100%'>
|
||||
<Row.Item grow />
|
||||
<Row.Item width='450px'>
|
||||
<form onSubmit={this.handleSubmit} id='loginForm'>
|
||||
<Column minHeight='100%'>
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<Image source={headerLogo} width={250} />
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<BoundInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' binder={this.state.binder}
|
||||
message='Enter the email address associated with your account.' />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<BoundInput password label='Password' name='password'
|
||||
binder={this.state.binder} message='Enter your password.' />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
<Link to='/forgot-password'>Forgot your password?</Link>
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<BoundCheckbox label='Remember Me' name='rememberMe' binder={this.state.binder} />
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item height={sizeInfo.buttonHeight}>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<BoundButton name='submit' content='Login' submit='loginForm' binder={this.state.binder} />
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item>
|
||||
<Text>
|
||||
Please contact <Link to={`mailto:${versionInfo.supportEmail}`}>{versionInfo.supportEmail}</Link> to request login credentials.
|
||||
</Text>
|
||||
</Column.Item>
|
||||
</Column>
|
||||
</form>
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
<Fragment>
|
||||
<Column.Item grow />
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item width='450px'>
|
||||
<form onSubmit={this.handleSubmit} id='loginForm'>
|
||||
<Column minHeight='100%'>
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<Image source={headerLogo} width={250} />
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<BoundInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' binder={this.state.binder}
|
||||
message='Enter the email address associated with your account.' />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<BoundInput password label='Password' name='password'
|
||||
binder={this.state.binder} message='Enter your password.' />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item>
|
||||
<Link to='/forgot-password'>Forgot your password?</Link>
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<BoundCheckbox label='Remember Me' name='rememberMe' binder={this.state.binder} />
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item height={sizeInfo.buttonHeight}>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<BoundButton name='submit' text='Login' submit='loginForm' binder={this.state.binder} />
|
||||
</Row.Item>
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item>
|
||||
<Text>
|
||||
Please contact <Link to={`mailto:${versionInfo.supportEmail}`}>{versionInfo.supportEmail}</Link> to request login credentials.
|
||||
</Text>
|
||||
</Column.Item>
|
||||
</Column>
|
||||
</form>
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item grow>
|
||||
<WaitModal active={waitModal} message='Logging in...' />
|
||||
|
||||
<WaitModal active={waitModal} message='Logging in...' />
|
||||
|
||||
<MessageModal error open={!!messageModal}
|
||||
icon={messageModal ? messageModal.icon : ''}
|
||||
message={messageModal ? messageModal.message : ''}
|
||||
detail={messageModal ? messageModal.detail : ''}
|
||||
onDismiss={this.handleMessageModalDismiss} />
|
||||
</Row>
|
||||
<MessageModal error open={!!messageModal}
|
||||
icon={messageModal ? messageModal.icon : ''}
|
||||
message={messageModal ? messageModal.message : ''}
|
||||
detail={messageModal ? messageModal.detail : ''}
|
||||
onDismiss={this.handleMessageModalDismiss} />
|
||||
</Column.Item>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import React from 'react'
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Row, Column, PanelButton } from 'ui'
|
||||
|
||||
export class Home extends React.Component {
|
||||
export class Home extends Component {
|
||||
static propTypes = {
|
||||
history: PropTypes.object
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Column>
|
||||
<Fragment>
|
||||
<Column.Item grow />
|
||||
<Column.Item>
|
||||
<Row>
|
||||
<Row.Item grow />
|
||||
<Row.Item>
|
||||
<PanelButton icon='users' text='Users' onClick={() => (this.props.history.replace('/users'))} />
|
||||
<PanelButton icon='users' text='Users' onClick={() => (this.props.history.push('/users'))} />
|
||||
</Row.Item>
|
||||
<Row.Item width={30} />
|
||||
<Row.Item>
|
||||
@@ -29,7 +29,7 @@ export class Home extends React.Component {
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item grow />
|
||||
</Column>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ export class ChangeEmailModal extends React.Component {
|
||||
binder={this.state.binder} />
|
||||
</Column.Item>
|
||||
<Column.Item>
|
||||
<BoundButton primary submit form='emailForm' name='submit' binder={this.state.binder}>
|
||||
<BoundButton primary submit='emailForm' name='submit' binder={this.state.binder}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</BoundButton>
|
||||
<Button color='red' onClick={this.handleClick}>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import React from 'react'
|
||||
import { Column, Text } from 'ui'
|
||||
|
||||
export const UserFormPlaceholder = () => (
|
||||
<div className='user-form-placeholder'>
|
||||
<h3>Select a registered user to view details here</h3>
|
||||
<h5>Or 'Add New User'</h5>
|
||||
</div>
|
||||
<Column fillParent>
|
||||
<Column.Item grow />
|
||||
<Column.Item>
|
||||
<Text size='large' align='center' width='100%'>Select a registered user to view details here</Text>
|
||||
<br />
|
||||
<Text size='small' align='center' width='100%'>Or 'Add New User'</Text>
|
||||
</Column.Item>
|
||||
<Column.Item grow />
|
||||
</Column>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { List, Icon, Button } from 'ui'
|
||||
import { Column, List, Button } from 'ui'
|
||||
import { sizeInfo } from 'ui/style'
|
||||
|
||||
export class UserList extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -20,8 +21,6 @@ export class UserList extends React.Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// This ensures that the original list is populated with 'all' by default,
|
||||
// due to the component mounting before users are returned (by api)
|
||||
if (nextProps.users !== this.props.users) {
|
||||
this.setState({ users: nextProps.users })
|
||||
}
|
||||
@@ -38,26 +37,30 @@ export class UserList extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<List className='user-list' selection>
|
||||
{
|
||||
this.state.users
|
||||
? this.state.users.map((user, index) =>
|
||||
(<List.Item className='user-list-item' key={user._id || '0'} onClick={this.props.onUserListClick}
|
||||
active={user === this.props.selectedUser} data-index={index}>
|
||||
<Icon name='profile' size={20} />
|
||||
<List.Content>
|
||||
{ user._id ? user.firstName + ' ' + user.lastName : '[New User]' }
|
||||
{ user === this.props.selectedUser && this.props.selectionModified ? <Icon className='user-update'
|
||||
name='edit' /> : null }
|
||||
</List.Content>
|
||||
</List.Item>)
|
||||
)
|
||||
: null
|
||||
}
|
||||
</List>
|
||||
<Button className='add-new-user' content='Add New User' primary onClick={this.props.onAddNewUser} />
|
||||
</div>
|
||||
<Column fillParent>
|
||||
<Column.Item grow>
|
||||
<List>
|
||||
{
|
||||
this.state.users
|
||||
? this.state.users.map((user, index) =>
|
||||
(<List.Item className='user-list-item' key={user._id || '0'} onClick={this.props.onUserListClick}
|
||||
active={true || user === this.props.selectedUser} data-index={index}>
|
||||
<List.Icon name='profile' size={30} />
|
||||
<List.Text>
|
||||
{ user._id ? user.firstName + ' ' + user.lastName : '[New User]' }
|
||||
</List.Text>
|
||||
{ user === this.props.selectedUser && this.props.selectionModified ? <List.Icon className='user-update' name='edit' /> : null }
|
||||
</List.Item>)
|
||||
)
|
||||
: null
|
||||
}
|
||||
</List>
|
||||
</Column.Item>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item height={sizeInfo.buttonHeight}>
|
||||
<Button className='add-new-user' width='100%' color='inverse' onClick={this.props.onAddNewUser} text='Add New User' />
|
||||
</Column.Item>
|
||||
</Column>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react'
|
||||
import React, { Component, Fragment } from 'react'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
import { UserList } from './UserList'
|
||||
import { UserForm } from './UserForm'
|
||||
import { UserFormPlaceholder } from './UserFormPlaceholder'
|
||||
import { api } from 'src/API'
|
||||
import { Row } from 'ui'
|
||||
import { Row, Column, Box } from 'ui'
|
||||
import { YesNoMessageModal, MessageModal, ChangeEmailModal, WaitModal } from '../Modal'
|
||||
import { sizeInfo, colorInfo } from 'ui/style'
|
||||
|
||||
export class Users extends React.Component {
|
||||
export class Users extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
reactAutoBind(this)
|
||||
@@ -236,42 +237,53 @@ export class Users extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { messageModal } = this.state
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Users</div>
|
||||
<Row>
|
||||
<Row.Item width={5}>
|
||||
<UserList users={this.state.users} selectedUser={this.state.selectedUser}
|
||||
selectionModified={this.state.modified} onUserListClick={this.handleUserListClick}
|
||||
onAddNewUser={this.handleAddNewUser} />
|
||||
</Row.Item>
|
||||
<Row.Item>
|
||||
{
|
||||
this.state.selectedUser
|
||||
? <UserForm user={this.state.selectedUser} onSave={this.handleSave}
|
||||
onRemove={this.handleRemove} onModifiedChanged={this.handleModifiedChanged}
|
||||
onChangeEmail={this.handleChangeEmail} onResendEmail={this.handleResendEmail} />
|
||||
: <UserFormPlaceholder />
|
||||
}
|
||||
</Row.Item>
|
||||
</Row>
|
||||
<Fragment>
|
||||
<Column.Item height={20} />
|
||||
<Column.Item grow>
|
||||
<Row fillParent>
|
||||
<Row.Item width={20} />
|
||||
<Row.Item width='25vw'>
|
||||
<UserList users={this.state.users} selectedUser={this.state.selectedUser}
|
||||
selectionModified={this.state.modified} onUserListClick={this.handleUserListClick}
|
||||
onAddNewUser={this.handleAddNewUser} />
|
||||
</Row.Item>
|
||||
<Row.Item width={20} />
|
||||
<Row.Item grow>
|
||||
<Box border={`${sizeInfo.headerBorderWidth}px solid ${colorInfo.headerBorder}`} radius={sizeInfo.formBoxRadius}>
|
||||
{
|
||||
this.state.selectedUser
|
||||
? <UserForm user={this.state.selectedUser} onSave={this.handleSave}
|
||||
onRemove={this.handleRemove} onModifiedChanged={this.handleModifiedChanged}
|
||||
onChangeEmail={this.handleChangeEmail} onResendEmail={this.handleResendEmail} />
|
||||
: <UserFormPlaceholder />
|
||||
}
|
||||
</Box>
|
||||
</Row.Item>
|
||||
<Row.Item width={20} />
|
||||
</Row>
|
||||
</Column.Item>
|
||||
<Column.Item height={20}>
|
||||
<ChangeEmailModal open={!!this.state.changeEmailModal} onDismiss={this.handleChangeEmailDismiss} />
|
||||
|
||||
<ChangeEmailModal open={!!this.state.changeEmailModal} onDismiss={this.handleChangeEmailDismiss} />
|
||||
<YesNoMessageModal open={!!this.state.yesNoModal}
|
||||
title={this.state.yesNoModal ? this.state.yesNoModal.title : ''}
|
||||
message={this.state.yesNoModal ? this.state.yesNoModal.message : ''}
|
||||
onDismiss={this.state.yesNoModal ? this.state.yesNoModal.onDismiss : null} />
|
||||
|
||||
<YesNoMessageModal open={!!this.state.yesNoModal}
|
||||
title={this.state.yesNoModal ? this.state.yesNoModal.title : ''}
|
||||
message={this.state.yesNoModal ? this.state.yesNoModal.message : ''}
|
||||
onDismiss={this.state.yesNoModal ? this.state.yesNoModal.onDismiss : null} />
|
||||
<MessageModal
|
||||
open={!!messageModal}
|
||||
icon={messageModal ? messageModal.icon : ''}
|
||||
error={messageModal ? messageModal.error : false}
|
||||
title={messageModal ? messageModal.title : ''}
|
||||
message={messageModal ? messageModal.message : ''}
|
||||
onDismiss={this.handleMessageModalDismiss} />
|
||||
|
||||
<MessageModal
|
||||
open={!!this.state.messageModal}
|
||||
error={this.state.messageModal ? this.state.messageModal.error : false}
|
||||
title={this.state.messageModal ? this.state.messageModal.title : ''}
|
||||
message={this.state.messageModal ? this.state.messageModal.message : ''}
|
||||
onDismiss={this.handleMessageModalDismiss} />
|
||||
|
||||
<WaitModal active={!!this.state.waitModal} message={this.state.waitModal ? this.state.waitModal.message : ''} />
|
||||
</div>
|
||||
<WaitModal active={!!this.state.waitModal} message={this.state.waitModal ? this.state.waitModal.message : ''} />
|
||||
</Column.Item>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { reactAutoBind } from 'auto-bind2'
|
||||
export default class BoundButton extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
content: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
binder: PropTypes.object.isRequired,
|
||||
submit: PropTypes.string,
|
||||
onClick: PropTypes.func
|
||||
@@ -39,14 +39,11 @@ export default class BoundButton extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { name, content, submit, onClick } = this.props
|
||||
const { name, text, submit, onClick } = this.props
|
||||
const { visible, disabled } = this.state
|
||||
|
||||
return (
|
||||
<Button disabled={disabled} submit={submit}
|
||||
onClick={onClick} name={name} visible={visible}>
|
||||
{content}
|
||||
</Button>
|
||||
<Button disabled={disabled} submit={submit} onClick={onClick} name={name} visible={visible} text={text} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export default class BoundInput extends React.Component {
|
||||
onChange={this.handleChange}
|
||||
placeholder={placeholder} />
|
||||
<br />
|
||||
<Text size='small' color='alert'>{valid ? ' ' : message}</Text>
|
||||
<Text size='small' color='alert' hidden={valid}>{message}</Text>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
|
||||
// TODO: Refactor this to allow setting each border property separately
|
||||
|
||||
class Box extends Component {
|
||||
static propTypes = {
|
||||
borderTop: PropTypes.string,
|
||||
@@ -9,17 +11,19 @@ class Box extends Component {
|
||||
borderRight: PropTypes.string,
|
||||
borderLeft: PropTypes.string,
|
||||
border: PropTypes.string,
|
||||
radius: PropTypes.number,
|
||||
color: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, color, borderTop, borderBottom, borderLeft, borderRight, border } = this.props
|
||||
const { children, color, borderTop, borderBottom, borderLeft, borderRight, border, radius } = this.props
|
||||
|
||||
return (
|
||||
<div style={[
|
||||
{ height: '100%', width: '100%' },
|
||||
color && { backgroundColor: color },
|
||||
radius && { borderRadius: radius },
|
||||
border ? { border } : { borderTop, borderBottom, borderLeft, borderRight }]}>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -3,15 +3,17 @@ import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import style from './Button.style'
|
||||
import { sizeInfo } from './style'
|
||||
import { Text } from '.'
|
||||
|
||||
class Button extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
text: PropTypes.node,
|
||||
visible: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
name: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
submit: PropTypes.string,
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
@@ -20,13 +22,14 @@ class Button extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { name, children, submit, visible, disabled, onClick } = this.props
|
||||
const { name, submit, visible, disabled, width, text, onClick } = this.props
|
||||
|
||||
return (
|
||||
<button name={name} type={!visible ? 'hidden' : submit ? 'submit' : 'button'}
|
||||
disabled={disabled} form={submit}
|
||||
style={[style.base, { minWidth: sizeInfo.minButtonWidth }]} onClick={onClick}>
|
||||
{children}
|
||||
style={[style.base, { width, minWidth: sizeInfo.minButtonWidth }]}
|
||||
onClick={onClick}>
|
||||
<Text color='inverse'>{text}</Text>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { colorInfo, fontInfo } from './style'
|
||||
import { colorInfo } from './style'
|
||||
|
||||
export default {
|
||||
base: {
|
||||
height: '100%',
|
||||
borderRadius: '10px',
|
||||
fontFamily: fontInfo.family,
|
||||
color: '#FFFFFF',
|
||||
fontSize: fontInfo.size.large,
|
||||
borderRadius: 10,
|
||||
background: colorInfo.buttonBackgroundHover,
|
||||
verticalAlign: 'middle',
|
||||
padding: '0 15px 0 15px',
|
||||
@@ -16,6 +13,10 @@ export default {
|
||||
},
|
||||
':disabled': {
|
||||
background: colorInfo.disabledButtonBackground,
|
||||
},
|
||||
':active': {
|
||||
borderWidth: 0,
|
||||
background: colorInfo.buttonBackgroundActive,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@ class Column extends Component {
|
||||
children: PropTypes.node,
|
||||
minHeight: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
fillParent: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, minHeight, height } = this.props
|
||||
const { children, minHeight, height, fillParent } = this.props
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%', display: 'flex', height, minHeight, flexDirection: 'column' }}>{children}</div>
|
||||
<div style={[
|
||||
{ display: 'flex', height, minHeight, flexDirection: 'column' },
|
||||
fillParent && { position: 'absolute', width: '100%', height: '100%' },
|
||||
]}>{children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +35,7 @@ Column.Item = Radium(class StackLayoutItem extends Component {
|
||||
const flexGrow = grow ? 1 : null
|
||||
|
||||
return (
|
||||
<div style={{ height, minHeight, flexGrow }}>
|
||||
<div style={{ position: 'relative', height, minHeight, flexGrow }}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -8,10 +8,12 @@ export default class Icon extends Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
size: PropTypes.number,
|
||||
margin: PropTypes.number,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 50
|
||||
size: 50,
|
||||
margin: sizeInfo.iconMargin,
|
||||
}
|
||||
|
||||
static svgs = {
|
||||
@@ -25,9 +27,8 @@ export default class Icon extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let { size, name } = this.props
|
||||
let { size, name, margin } = this.props
|
||||
let source = Icon.svgs[name] || Icon.svgs['placeholder']
|
||||
const margin = sizeInfo.iconMargin
|
||||
|
||||
size -= margin * 2
|
||||
|
||||
|
||||
@@ -1,30 +1,99 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { fontInfo } from './style'
|
||||
import { Box, Icon } from '.'
|
||||
import { sizeInfo, colorInfo, fontInfo } from './style'
|
||||
|
||||
class List extends Component {
|
||||
static propTypes = {
|
||||
size: PropTypes.string,
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 'medium',
|
||||
margin: 0
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props
|
||||
const listGapItem = (<div style={{ background: 'transparent', height: sizeInfo.listTopBottomGap }} />)
|
||||
|
||||
return (
|
||||
<span style={{
|
||||
display: 'inline-block',
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
fontSize: fontInfo.size.medium,
|
||||
fontFamily: fontInfo.family,
|
||||
margin: this.props.margin
|
||||
}}>{this.props.children}</span>
|
||||
}}>
|
||||
<Box border={`${sizeInfo.listBorderWidth}px solid ${colorInfo.listBorder}`} radius={sizeInfo.formBoxRadius}>
|
||||
{listGapItem}
|
||||
<div style={{ overflow: scroll }}>
|
||||
{children}
|
||||
</div>
|
||||
{listGapItem}
|
||||
</Box>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
List.Item = Radium(class ListItem extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
active: PropTypes.bool,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, active, onClick } = this.props
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
display: 'table-row',
|
||||
background: active ? colorInfo.listBackgroundActive : colorInfo.listBackground,
|
||||
}} onClick={onClick}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
List.Icon = Radium(class ListIcon extends Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { size, name } = this.props
|
||||
let source = Icon.svgs[name] || Icon.svgs['placeholder']
|
||||
|
||||
return (
|
||||
<img src={source} style={{
|
||||
display: 'table-cell',
|
||||
verticalAlign: 'middle',
|
||||
width: size,
|
||||
height: size,
|
||||
margin: '5px 10px 5px 10px', // TODO: Put in style.js
|
||||
}} />
|
||||
)
|
||||
}
|
||||
})
|
||||
List.Text = Radium(class ListText extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props
|
||||
|
||||
return (
|
||||
<span style={{
|
||||
display: 'table-cell',
|
||||
width: '100%',
|
||||
color: fontInfo.color.normal,
|
||||
align: 'left',
|
||||
verticalAlign: 'middle',
|
||||
textAlign: 'left'
|
||||
}}>{children}</span>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Radium(List)
|
||||
|
||||
@@ -22,7 +22,7 @@ class PanelButton extends Component {
|
||||
]}
|
||||
onClick={onClick}>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<Icon name={icon} size={sizeInfo.panelIconSize} />
|
||||
<Icon name={icon} size={sizeInfo.panelIconSize} margin={0} />
|
||||
<span style={{
|
||||
position: 'absolute',
|
||||
top: sizeInfo.panelTextOffset,
|
||||
|
||||
@@ -7,13 +7,17 @@ class Row extends Component {
|
||||
children: PropTypes.node,
|
||||
minWidth: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
fillParent: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, width, minWidth } = this.props
|
||||
const { children, width, minWidth, fillParent } = this.props
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', display: 'flex', width, minWidth, flexDirection: 'row' }}>{children}</div>
|
||||
<div style={[
|
||||
{ display: 'flex', minWidth, width, flexDirection: 'row' },
|
||||
fillParent && { position: 'absolute', width: '100%', height: '100%' },
|
||||
]}>{children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +35,9 @@ Row.Item = Radium(class RowLayoutItem extends Component {
|
||||
const flexGrow = grow ? 1 : null
|
||||
|
||||
return (
|
||||
<div style={{ width, minWidth, flexGrow }}>{children}</div>
|
||||
<div style={{ position: 'relative', width, minWidth, flexGrow }}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ class Text extends Component {
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node,
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
hidden: PropTypes.bool,
|
||||
align: PropTypes.string,
|
||||
}
|
||||
|
||||
@@ -21,10 +22,10 @@ class Text extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { margin, width, align, children } = this.props
|
||||
const { margin, width, align, hidden, children } = this.props
|
||||
|
||||
return (
|
||||
<span style={{
|
||||
<span style={[{
|
||||
display: 'inline-block',
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
fontFamily: fontInfo.family,
|
||||
@@ -32,7 +33,7 @@ class Text extends Component {
|
||||
textAlign: align,
|
||||
margin,
|
||||
width,
|
||||
}}>{children}</span>
|
||||
}, hidden && { visibility: 'hidden' }]}>{children}</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ let colorInfo = {
|
||||
grayText: '#B0B0B0',
|
||||
buttonBackground: '#3498DB',
|
||||
buttonBackgroundHover: '#3CB0FD',
|
||||
buttonBackgroundActive: '#1A72AC',
|
||||
headerButtonBackground: '#FAFAFA',
|
||||
headerButtonBackgroundHover: '#DADADA',
|
||||
headerButtonBackgroundActive: '#AAAAAA',
|
||||
headerBorder: '#B2B2B2',
|
||||
disabledButtonBackground: '#E0E0E0',
|
||||
modalBackground: '#FFFFFF',
|
||||
uncheckedCheckbox: '#A0A0A0',
|
||||
@@ -20,6 +22,10 @@ Object.assign(colorInfo, {
|
||||
panelButtonBackgroundHover: colorInfo.headerButtonBackgroundHover,
|
||||
panelButtonBackgroundActive: colorInfo.headerButtonBackgroundActive,
|
||||
disabledPanelButtonBackground: colorInfo.disabledButtonBackground,
|
||||
listBackground: '#FFFFFF',
|
||||
listBackgroundHover: colorInfo.headerButtonBackgroundHover,
|
||||
listBackgroundActive: '#E7E5E5',
|
||||
listBorder: colorInfo.headerBorder,
|
||||
})
|
||||
|
||||
const sizeInfo = {
|
||||
@@ -27,12 +33,15 @@ const sizeInfo = {
|
||||
imageMargin: 5, // The margin around images
|
||||
iconMargin: 10, // The margin around icons
|
||||
headerBorderWidth: 1,
|
||||
listBorderWidth: 1,
|
||||
buttonHeight: 40,
|
||||
minButtonWidth: 100,
|
||||
checkboxSize: 25,
|
||||
panelButtonSize: 200,
|
||||
panelIconSize: 170,
|
||||
panelTextOffset: 130,
|
||||
panelTextOffset: 120,
|
||||
formBoxRadius: 5,
|
||||
listTopBottomGap: 10,
|
||||
}
|
||||
|
||||
const fontInfo = {
|
||||
|
||||
Reference in New Issue
Block a user