Removed Semantic UI React
This commit is contained in:
@@ -3,16 +3,18 @@ import { Login, Logout, ResetPassword, ForgotPassword, ConfirmEmail, ProtectedRo
|
||||
import { Home } from './Home'
|
||||
import { Profile } from './Profile'
|
||||
import { Users } from './Users'
|
||||
import { HolyGrail } from './ui'
|
||||
import { HolyGrail, Image, Text, Icon } from './ui'
|
||||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
|
||||
import logoImage from 'images/logo.png'
|
||||
import { versionInfo } from './version'
|
||||
|
||||
export class App extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<HolyGrail>
|
||||
<HolyGrail.Header>
|
||||
<img src={logoImage} style={{ width: '50px', height: '50px', margin: '5px' }} />
|
||||
<Image source={logoImage} width={50} height={50} margin={5} />
|
||||
<Icon name='logout' />
|
||||
</HolyGrail.Header>
|
||||
<HolyGrail.Body>
|
||||
<Router basename='/'>
|
||||
@@ -30,7 +32,7 @@ export class App extends React.Component {
|
||||
</Router>
|
||||
</HolyGrail.Body>
|
||||
<HolyGrail.Footer>
|
||||
<div style={{ margin: '10px' }}>v1.0.0. Copyright © 2018, Deighton.</div>
|
||||
<Text margin={10}>{versionInfo.fullVersion} © 2018, Kingston Software Solutions.</Text>
|
||||
</HolyGrail.Footer>
|
||||
</HolyGrail>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import React from 'react'
|
||||
import { api } from '../helpers'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Container } from 'semantic-ui-react'
|
||||
import { MessageDialog, WaitDialog } from '../Dialog'
|
||||
import './ConfirmEmail.scss'
|
||||
|
||||
export class ConfirmEmail extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -56,7 +54,7 @@ export class ConfirmEmail extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container className='email-confirm-container'>
|
||||
<div>
|
||||
<WaitDialog active={!!this.state.waitDialog}
|
||||
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
|
||||
|
||||
@@ -64,7 +62,7 @@ export class ConfirmEmail extends React.Component {
|
||||
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
|
||||
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
|
||||
onDismiss={this.handleMessageDialogDismiss} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
.ui.container.email-confirm-container {
|
||||
display: flex;
|
||||
height: 80vh;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui.container.email-confirm-container button {
|
||||
margin-top: 1em;
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import { Container, Header, Form, Message } from 'semantic-ui-react'
|
||||
import './ForgotPassword.scss'
|
||||
import { Text, StackLayout } from '../ui'
|
||||
import { MessageDialog, WaitDialog } from '../Dialog'
|
||||
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
|
||||
import { api } from '../helpers'
|
||||
@@ -67,16 +66,26 @@ export class ForgotPassword extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container className='forgot-password-container'>
|
||||
<Header content='Forgotten Password' size='large' />
|
||||
<Form size='large' onSubmit={this.handleSubmit}>
|
||||
<ValidatedInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' validator={this.state.validator}
|
||||
message='A valid email address' />
|
||||
<Message info content='The email address of an existing user to send the password reset link to.' />
|
||||
<ValidatedButton className='submit' name='submit' content='Submit'
|
||||
primary submit validator={this.state.validator}>Submit</ValidatedButton>
|
||||
</Form>
|
||||
<div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<Text size='large'>Forgotten Password</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' validator={this.state.validator}
|
||||
message='A valid email address' />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Text>The email address of an existing user to send the password reset link to.</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton className='submit' name='submit' content='Submit'
|
||||
primary submit validator={this.state.validator}>Submit</ValidatedButton>
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
|
||||
<WaitDialog active={!!this.state.waitDialog}
|
||||
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
|
||||
@@ -87,7 +96,7 @@ export class ForgotPassword extends React.Component {
|
||||
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
|
||||
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
|
||||
onDismiss={this.handleMessageDialogDismiss} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
.ui.container.forgot-password-container {
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui.container.forgot-password-container .header {
|
||||
border-bottom: 1px solid #d4d4d5;
|
||||
width: 40%;
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.ui.container.forgot-password-container form {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.ui.container.forgot-password-container .message {
|
||||
margin: 2em 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Container, Header, Form, Message } from 'semantic-ui-react'
|
||||
import './Login.scss'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import { api } from '../helpers'
|
||||
import { Validator, ValidatedInput, ValidatedCheckbox } from '../Validated'
|
||||
import { Validator, ValidatedInput, ValidatedCheckbox, ValidatedButton } from '../Validated'
|
||||
import { WaitDialog, MessageDialog } from '../Dialog'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Button } from '../ui'
|
||||
import { Image, Link, Text, StackLayout } from '../ui'
|
||||
import headerLogo from 'images/deighton.png'
|
||||
|
||||
export class Login extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -90,30 +88,40 @@ export class Login extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container id='login' className='password-reset-container'>
|
||||
<Header size='large'>Login Portal</Header>
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
{/* Add in 'Username' field pass */}
|
||||
<ValidatedInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' validator={this.state.validator}
|
||||
message='Enter the email address associated with your account.' width={16} />
|
||||
<ValidatedInput password label='Password' name='password'
|
||||
validator={this.state.validator} message='Enter your password.' width={16} />
|
||||
<Form.Group widths='equal' className='login-options'>
|
||||
<Form.Field className='login-password'>
|
||||
<div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<Image source={headerLogo} width={279} height={73} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Email' name='email'
|
||||
placeholder='example@xyz.com' validator={this.state.validator}
|
||||
message='Enter the email address associated with your account.' width={16} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput password label='Password' name='password'
|
||||
validator={this.state.validator} message='Enter your password.' width={16} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Link to='/forgot-password'>Forgot your password?</Link>
|
||||
</Form.Field>
|
||||
<ValidatedCheckbox label='Remember Me'
|
||||
name='rememberMe' onChange={this.handleChange} validator={this.state.validator}
|
||||
message='Should we keep you logged in on this computer?' className='login-checkbox' />
|
||||
</Form.Group>
|
||||
{ /* <ValidatedButton className='submit' name='submit' content='Submit'
|
||||
primary submit validator={this.state.validator} /> */ }
|
||||
<Button>Login</Button>
|
||||
<Message info>
|
||||
Please contact <a href='mailto:support@jamoki.com'>support@jamoki.com</a> to request login credentials.
|
||||
</Message>
|
||||
</Form>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedCheckbox label='Remember Me'
|
||||
name='rememberMe' onChange={this.handleChange} validator={this.state.validator}
|
||||
message='Should we keep you logged in on this computer?' className='login-checkbox' />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton className='submit' name='submit' content='Login'
|
||||
submit validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Text>
|
||||
Please contact <Link to='mailto:support@jamoki.com'>support@jamoki.com</Link> to request login credentials.
|
||||
</Text>
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
|
||||
<WaitDialog active={this.state.waitDialog} message='Logging In' />
|
||||
|
||||
@@ -121,7 +129,7 @@ export class Login extends React.Component {
|
||||
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
|
||||
message={this.state.messageDialog ? this.state.messageDialog.message : ''}
|
||||
onDismiss={this.handleMessageDialogDismiss} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#login .login-options { margin: 1.5em 0 3em 0; }
|
||||
#login .login-password { text-align: left; }
|
||||
#login .login-checkbox { text-align: right; }
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Container, Header, Form, Message } from 'semantic-ui-react'
|
||||
import './ResetPassword.scss'
|
||||
import { Text, StackLayout } from '../ui'
|
||||
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
|
||||
import { MessageDialog, WaitDialog } from '../Dialog'
|
||||
import { api } from '../helpers'
|
||||
@@ -62,23 +61,35 @@ export class ResetPassword extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container className='password-reset-container'>
|
||||
<Header content='Reset Password' size='large' />
|
||||
<Form size='large' onSubmit={this.handleSubmit}>
|
||||
<ValidatedInput label='New Password' password name='newPassword'
|
||||
message='A new password, cannot be blank or the same as your old password'
|
||||
width={16} validator={this.state.validator} />
|
||||
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
|
||||
message='The new password again, must match and cannot be blank'
|
||||
width={16} validator={this.state.validator} />
|
||||
<Message info>
|
||||
Passwords can contain special characters and are discouraged from being simple or reused from other sites or applications.
|
||||
<br /><br />
|
||||
Passwords must be at least 6 characters long.
|
||||
</Message>
|
||||
<ValidatedButton className='submit' name='submit' content='Submit'
|
||||
primary submit validator={this.state.validator} />
|
||||
</Form>
|
||||
<div>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<Text size='large'>Reset Password</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='New Password' password name='newPassword'
|
||||
message='A new password, cannot be blank or the same as your old password'
|
||||
width={16} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
|
||||
message='The new password again, must match and cannot be blank'
|
||||
width={16} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Text>
|
||||
Passwords can contain special characters and should be unique to this application.
|
||||
<br /><br />
|
||||
Passwords must be at least 6 characters long.
|
||||
</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton className='submit' name='submit' content='Submit'
|
||||
submit validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
|
||||
<MessageDialog error open={!!this.state.messageDialog}
|
||||
title={this.state.messageDialog ? this.state.messageDialog.title : ''}
|
||||
@@ -87,7 +98,7 @@ export class ResetPassword extends React.Component {
|
||||
|
||||
<WaitDialog active={!!this.state.waitDialog}
|
||||
message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
.ui.container.password-reset-container {
|
||||
height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui.container.password-reset-container .header {
|
||||
border-bottom: 1px solid #d4d4d5;
|
||||
width: 40%;
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.ui.container.password-reset-container form {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.ui.container.password-reset-container .message {
|
||||
margin: 2em 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import { Modal, Button, Icon, Header, Grid, Form } from 'semantic-ui-react'
|
||||
import { ValidatedInput, ValidatedActionsButton, Validator } from '../Validated'
|
||||
import { Modal, Button, Icon, StackLayout, Text } from '../ui'
|
||||
import { ValidatedInput, ValidatedButton, Validator } from '../Validated'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
|
||||
export class ChangeEmailDialog extends React.Component {
|
||||
@@ -57,28 +57,26 @@ export class ChangeEmailDialog extends React.Component {
|
||||
return (
|
||||
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose}
|
||||
closeOnDimmerClick={false}>
|
||||
<Header color='black' icon='edit' content='Change Email' />
|
||||
<Modal.Content>
|
||||
<Form className='user-form' id='emailForm' onSubmit={this.handleSubmit}>
|
||||
<Grid>
|
||||
<Grid.Column width={16}>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='New Email' name='newEmail' width={16}
|
||||
message='Your new email address, e.g. xyz@abc.com, cannot be blank'
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Form>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<ValidatedActionsButton primary submit form='emailForm' name='submit' validator={this.state.validator}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</ValidatedActionsButton>
|
||||
<Button color='red' onClick={this.handleClick}>
|
||||
<Icon name='close' /> Cancel
|
||||
</Button>
|
||||
</Modal.Actions>
|
||||
<form className='user-form' id='emailForm' onSubmit={this.handleSubmit}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<Text>Change Email</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='New Email' name='newEmail' width={16}
|
||||
message='Your new email address, e.g. xyz@abc.com, cannot be blank'
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton primary submit form='emailForm' name='submit' validator={this.state.validator}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</ValidatedButton>
|
||||
<Button color='red' onClick={this.handleClick}>
|
||||
<Icon name='close' /> Cancel
|
||||
</Button>
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import { Modal, Button, Icon, Header, Grid, Form } from 'semantic-ui-react'
|
||||
import { Modal, Button, Icon, StackLayout, RowLayout, Text } from '../ui'
|
||||
import { ValidatedInput, ValidatedActionsButton, Validator } from '../Validated'
|
||||
|
||||
export class ChangePasswordDialog extends React.Component {
|
||||
@@ -64,38 +64,41 @@ export class ChangePasswordDialog extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose}
|
||||
closeOnDimmerClick={false}>
|
||||
<Header color='black' icon='edit' content='Change Password' />
|
||||
<Modal.Content>
|
||||
<Form className='user-form' id='passwordForm' onSubmit={this.handleSubmit}>
|
||||
<Grid stackable>
|
||||
<Grid.Column width={16}>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Current Password' password name='oldPassword'
|
||||
message='Your existing password, cannot be blank'
|
||||
width={8} validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='New Password' password name='newPassword'
|
||||
message='A new password, cannot be blank or the same as your old password'
|
||||
width={8} validator={this.state.validator} />
|
||||
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
|
||||
message='The new password again, must match and cannot be blank'
|
||||
width={8} validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Form>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<ValidatedActionsButton primary submit form='passwordForm' name='submit' validator={this.state.validator}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</ValidatedActionsButton>
|
||||
<Button color='red' onClick={this.handleClick}>
|
||||
<Icon name='close' /> Cancel
|
||||
</Button>
|
||||
</Modal.Actions>
|
||||
<Modal dimmer='inverted' open={this.props.open} onClose={this.handleClose} closeOnDimmerClick={false}>
|
||||
<form id='passwordForm' onSubmit={this.handleSubmit}>
|
||||
<StackLayout.Item color='black' icon='edit'>
|
||||
<Text size='large'>Change Password</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Current Password' password name='oldPassword'
|
||||
message='Your existing password, cannot be blank'
|
||||
width={8} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='New Password' password name='newPassword'
|
||||
message='A new password, cannot be blank or the same as your old password'
|
||||
width={8} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Re-entered New Password' password name='reenteredNewPassword'
|
||||
message='The new password again, must match and cannot be blank'
|
||||
width={8} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<RowLayout>
|
||||
<ValidatedActionsButton primary submit form='passwordForm' name='submit' validator={this.state.validator}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</ValidatedActionsButton>
|
||||
<Button color='red' onClick={this.handleClick}>
|
||||
<Icon name='close' /> Cancel
|
||||
</Button>
|
||||
</RowLayout>
|
||||
</StackLayout.Item>
|
||||
</form>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Modal, Button, Icon, Header } from 'semantic-ui-react'
|
||||
import { Modal, Button, Icon, StackLayout, Text } from '../ui'
|
||||
|
||||
export class MessageDialog extends React.Component {
|
||||
static propTypes = {
|
||||
open: PropTypes.bool,
|
||||
error: PropTypes.bool,
|
||||
title: PropTypes.string.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
onDismiss: PropTypes.func
|
||||
@@ -13,20 +12,20 @@ export class MessageDialog extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal dimmer='inverted' open={this.props.open} onClose={this.props.onDismiss}
|
||||
closeOnDimmerClick={false}>
|
||||
<Header
|
||||
color={this.props.error ? 'red' : 'blue'}
|
||||
icon={this.props.error ? 'warning circle' : 'info circle'}
|
||||
content={this.props.title} />
|
||||
<Modal.Content>
|
||||
<h3>{this.props.message}</h3>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<Button onClick={this.props.onDismiss}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</Button>
|
||||
</Modal.Actions>
|
||||
<Modal open={this.props.open} onClose={this.props.onDismiss} closeOnDimmerClick={false}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<Text>{this.props.title}</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Text>{this.props.message}</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Button onClick={this.props.onDismiss}>
|
||||
<Icon name='checkmark' /> OK
|
||||
</Button>
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dimmer, Button, Progress } from 'semantic-ui-react'
|
||||
import './ProgressDialog.scss'
|
||||
import { Dimmer, Button, Progress } from '../ui'
|
||||
|
||||
export class ProgressDialog extends React.Component {
|
||||
static propTypes = {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
.progress-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#progress {
|
||||
width: 60%;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dimmer, Loader } from 'semantic-ui-react'
|
||||
import { Dimmer, Loader } from '../ui'
|
||||
|
||||
export class WaitDialog extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -10,9 +10,61 @@ export class WaitDialog extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Dimmer inverted page active={this.props.active}>
|
||||
<div style={style.dimmer}>
|
||||
<Loader inverted size='massive'>{this.props.message}...</Loader>
|
||||
</Dimmer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { keyframes, css } from 'emotion';
|
||||
import { onlyUpdateForKeys } from 'recompose';
|
||||
|
||||
// This returns an animation
|
||||
const pulse = keyframes`
|
||||
0% {transform: scale(1);opacity: 1}
|
||||
45% {transform: scale(0.1);opacity: 0.7}
|
||||
80% {transform: scale(1);opacity: 1}
|
||||
`;
|
||||
|
||||
class Loader extends React.Component {
|
||||
style = i => css`{
|
||||
background-color: ${this.props.color};
|
||||
width: ${this.props.size}px;
|
||||
height: ${this.props.size}px;
|
||||
margin: ${this.props.margin};
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
animation: ${pulse} 0.75s ${i * 0.12}s infinite cubic-bezier(.2,.68,.18,1.08);
|
||||
animation-fill-mode: both;
|
||||
}`;
|
||||
|
||||
render() {
|
||||
return this.props.loading ?
|
||||
<div>
|
||||
<div className={this.style(1)} />
|
||||
<div className={this.style(2)} />
|
||||
<div className={this.style(3)} />
|
||||
</div> : null;
|
||||
}
|
||||
}
|
||||
|
||||
Loader.propTypes = {
|
||||
loading: PropTypes.bool,
|
||||
color: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
margin: PropTypes.string
|
||||
};
|
||||
|
||||
Loader.defaultProps = {
|
||||
loading: true,
|
||||
color: '#000000',
|
||||
size: 15,
|
||||
margin: '2px'
|
||||
};
|
||||
|
||||
const Component = onlyUpdateForKeys(['loading', 'color', 'size', 'margin'])(Loader);
|
||||
Component.defaultProps = Loader.defaultProps;
|
||||
export default Component;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import './YesNoMessageDialog.scss'
|
||||
import { Modal, Button, Icon, Header } from 'semantic-ui-react'
|
||||
import { Modal, Button, StackLayout, Text, Icon } from '../ui'
|
||||
|
||||
export class YesNoMessageDialog extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -17,20 +16,24 @@ export class YesNoMessageDialog extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal dimmer='inverted' open={this.props.open} onClose={this.onDismiss(false)}
|
||||
<Modal open={this.props.open} onClose={this.onDismiss(false)}
|
||||
closeOnDimmerClick={false} className='yes-no-modal'>
|
||||
<Header color='orange' size='large' icon='warning circle' content={this.props.title} />
|
||||
<Modal.Content>
|
||||
<p>{this.props.message}</p>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
<Button negative onClick={this.onDismiss(false)}>
|
||||
<Icon name='remove' /> No
|
||||
</Button>
|
||||
<Button positive onClick={this.onDismiss(true)}>
|
||||
<Icon name='checkmark' /> Yes
|
||||
</Button>
|
||||
</Modal.Actions>
|
||||
<StackLayout>
|
||||
<StackLayout.Item color='orange'>
|
||||
<Text>{this.props.title}</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Text>{this.props.message}</Text>
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Button negative onClick={this.onDismiss(false)}>
|
||||
<Icon name='remove' /> No
|
||||
</Button>
|
||||
<Button positive onClick={this.onDismiss(true)}>
|
||||
<Icon name='checkmark' /> Yes
|
||||
</Button>
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.yes-no-modal p {
|
||||
font-size: 1.125em;
|
||||
line-height: 1.6em;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Button, Header, Icon } from 'semantic-ui-react'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import './FilePicker.scss'
|
||||
|
||||
export class FilePicker extends React.Component {
|
||||
static propTypes = {
|
||||
validExtensions: PropTypes.arrayOf(PropTypes.string).isRequired, // Make sure these are lowercase
|
||||
onFileSelect: PropTypes.func,
|
||||
content: PropTypes.string,
|
||||
horizontal: PropTypes.bool
|
||||
}
|
||||
constructor(props) {
|
||||
super(props)
|
||||
autoBind(this, (name) => (name.startsWith('handle')))
|
||||
|
||||
this.state = {
|
||||
icon: 'none',
|
||||
value: ''
|
||||
}
|
||||
this.counter = 0
|
||||
}
|
||||
|
||||
handleDragEnter(e) {
|
||||
this.counter++
|
||||
this.setState({ icon: 'pending' })
|
||||
}
|
||||
|
||||
handleDragLeave(e) {
|
||||
this.counter--
|
||||
|
||||
if (this.counter === 0) {
|
||||
this.setState({ icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
handleDragOver(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
handleDragDrop(e) {
|
||||
e.preventDefault()
|
||||
|
||||
const files = e.dataTransfer.files
|
||||
|
||||
if (files.length > 0) {
|
||||
const file = files[0]
|
||||
|
||||
if (file) {
|
||||
const fileName = file.name.toLowerCase()
|
||||
const isValidFile = this.props.validExtensions.some((ext) => (fileName.endsWith(ext)))
|
||||
|
||||
this.setState({ icon: isValidFile ? 'valid' : 'invalid' })
|
||||
this.counter = 0
|
||||
if (isValidFile && this.props.onFileSelect) {
|
||||
this.props.onFileSelect(file)
|
||||
window.setTimeout(function() {
|
||||
this.setState({ icon: 'none' })
|
||||
}.bind(this), 1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleOnFileChange(e) {
|
||||
let file = e.currentTarget.files[0]
|
||||
|
||||
this.setState({ value: '' })
|
||||
if (this.props.onFileSelect) {
|
||||
this.props.onFileSelect(file)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div draggable id={this.props.horizontal ? 'holderHorizontal' : 'holderVertical'}
|
||||
onDragOver={this.handleDragOver}
|
||||
onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave}
|
||||
onDrop={this.handleDragDrop}>
|
||||
<input id='fileInput' type='file' onChange={this.handleOnFileChange} value={this.state.value} />
|
||||
<Button as='label' htmlFor='fileInput' size={'medium'} type='browse' name='selectFile'
|
||||
id='selectFile' content={this.props.content} icon='upload' primary />
|
||||
{ this.props.horizontal
|
||||
? (<Icon id='fileIconHorizontal'
|
||||
name={'file' + ((this.state.icon === 'none' || this.state.icon === 'pending') ? ' outline' : '')}
|
||||
size='huge'
|
||||
color={this.state.icon === 'valid' ? 'green' : this.state.icon === 'invalid' ? 'red' : 'grey'}
|
||||
style={this.state.icon === 'pending' ? { transform: 'scale(1.5)' } : {}} />)
|
||||
: (<Header as='h3' color='grey' icon>
|
||||
OR
|
||||
<Header.Subheader>
|
||||
Drag-and-drop the file here
|
||||
</Header.Subheader>
|
||||
<Icon id='fileIconVertical' className=''
|
||||
name={'file' + ((this.state.icon === 'none' || this.state.icon === 'pending') ? ' outline' : '')}
|
||||
size='huge'
|
||||
color={this.state.icon === 'valid' ? 'green' : this.state.icon === 'invalid' ? 'red' : 'grey'}
|
||||
style={this.state.icon === 'pending' ? { transform: 'scale(1.5)' } : {}} />
|
||||
</Header>)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#holderVertical {
|
||||
border: 3px dashed lightgray;
|
||||
text-align: center;
|
||||
border-radius: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.25em 1.25em;
|
||||
width: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#holderHorizontal {
|
||||
border: 3px dashed lightgray;
|
||||
text-align: center;
|
||||
border-radius: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.25em 1.25em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#helpText {
|
||||
height: 2em;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 2em;
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
#fileIconVertical {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#fileIconHorizontal {
|
||||
margin-left: 0.3em;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#selectFile {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#fileInput {
|
||||
display: none;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { FilePicker } from './FilePicker'
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import { Container } from 'semantic-ui-react'
|
||||
import { ProfileForm } from './ProfileForm'
|
||||
import { Constants, api } from '../helpers'
|
||||
import { WaitDialog, MessageDialog, ChangePasswordDialog, ProgressDialog, ChangeEmailDialog } from '../Dialog'
|
||||
@@ -147,7 +146,7 @@ export class Profile extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<div>
|
||||
<ProfileForm
|
||||
user={this.state.user}
|
||||
onSaved={this.handleSaved}
|
||||
@@ -171,7 +170,7 @@ export class Profile extends React.Component {
|
||||
message={this.state.progressDialog ? this.state.progressDialog.message : ''}
|
||||
percent={this.state.uploadPercent}
|
||||
onCancel={this.handleUploadCancel} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Grid, Form, Image } from 'semantic-ui-react'
|
||||
import { StackLayout, Button } from '../ui'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import './ProfileForm.scss'
|
||||
import { Constants } from '../helpers'
|
||||
import { FilePicker } from '../FilePicker'
|
||||
import { Validator, ValidatedInput, ValidatedDropdown, ValidatedButton, ValidatedDatePicker } from '../Validated'
|
||||
import { Validator, ValidatedInput, ValidatedButton } from '../Validated'
|
||||
|
||||
export class ProfileForm extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -13,9 +10,7 @@ export class ProfileForm extends React.Component {
|
||||
onSaved: PropTypes.func.isRequired,
|
||||
onModifiedChanged: PropTypes.func,
|
||||
onChangePassword: PropTypes.func,
|
||||
onChangeEmail: PropTypes.func,
|
||||
onSelectImage: PropTypes.func,
|
||||
userImageUrl: PropTypes.string
|
||||
onChangeEmail: PropTypes.func
|
||||
}
|
||||
|
||||
static validations = {
|
||||
@@ -99,72 +94,32 @@ export class ProfileForm extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form className='profile-form' onSubmit={this.handleSubmit}>
|
||||
<Grid stackable>
|
||||
<Grid.Column width={3}>
|
||||
<Image id='userImage' shape='circular' size='medium' src={this.props.userImageUrl} centered />
|
||||
<FilePicker validExtensions={['.jpg', '.jpeg', '.png']} content='Select Image' onFileSelect={this.props.onSelectImage} />
|
||||
</Grid.Column>
|
||||
|
||||
<Grid.Column width={13}>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='First Name' name='firstName' width={8}
|
||||
validator={this.state.validator} />
|
||||
<ValidatedInput label='Last Name' name='lastName' width={8}
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Email' name='email' width={8} message='Required. Must be a valid email address.'
|
||||
validator={this.state.validator} />
|
||||
<Form.Button fluid content={'Change Email'} label=' '
|
||||
width={4} onClick={this.props.onChangeEmail} />
|
||||
<Form.Button fluid content={'Change Password'} label=' '
|
||||
width={4} onClick={this.props.onChangePassword} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Zip' name='zip' width={4}
|
||||
validator={this.state.validator} message='5 Character U.S. Zip Code. Optional.' />
|
||||
<ValidatedDropdown label='State' name='state' width={6} message='Type or select a U.S. State or Province.'
|
||||
placeholder='Select State' options={Constants.stateOptions}
|
||||
validator={this.state.validator} searchable />
|
||||
<ValidatedInput label='City' name='city' width={6}
|
||||
validator={this.state.validator} message='U.S. City. Optional.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Address' name='address1' width={12}
|
||||
validator={this.state.validator} message='Primary Street Address. Optional.' />
|
||||
<ValidatedInput label='Apt. #' name='address2' width={4}
|
||||
validator={this.state.validator} message='Apartment/Unit number. Optional.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Home Phone' name='homePhone' width={8}
|
||||
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
|
||||
<ValidatedInput label='Cell Phone' name='cellPhone' width={8}
|
||||
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedDatePicker label='Date of Birth' name='dateOfBirth' width={5}
|
||||
validator={this.state.validator} message='Select a date.' />
|
||||
<ValidatedInput label='SSN' name='ssn' width={6}
|
||||
validator={this.state.validator} message='U.S. Social Security Number. IE: 123-45-6789' />
|
||||
<ValidatedDatePicker label='Hire Date' name='dateOfHire' width={5}
|
||||
validator={this.state.validator} message='Select a date.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<Form.Field width={12} />
|
||||
<ValidatedButton submit primary width={4} size='medium' content='Save' label=' ' name='save'
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Form>
|
||||
<form className='profile-form' onSubmit={this.handleSubmit}>
|
||||
<StackLayout stackable>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='First Name' name='firstName' width={8}
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Last Name' name='lastName' width={8}
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Email' name='email' width={8} message='Required. Must be a valid email address.'
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<Button fluid content={'Change Email'} label=' '
|
||||
width={4} onClick={this.props.onChangeEmail} />
|
||||
<Button fluid content={'Change Password'} label=' '
|
||||
width={4} onClick={this.props.onChangePassword} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton submit primary width={4} size='medium' content='Save' label=' ' name='save'
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
.profile-form {
|
||||
text-align: left;
|
||||
margin: 3em auto 4em auto;
|
||||
}
|
||||
|
||||
.profile-form > .fields {
|
||||
margin-bottom: 1.5em !important;
|
||||
}
|
||||
|
||||
#userImage {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
@@ -2,11 +2,10 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import { regExpPattern } from 'regexp-pattern'
|
||||
import { Grid, Form } from 'semantic-ui-react'
|
||||
import './UserForm.scss'
|
||||
import { ValidatedEmailIcon } from './ValidatedEmailIcon'
|
||||
import { Constants, api } from '../helpers'
|
||||
import { Validator, ValidatedInput, ValidatedButton, ValidatedDropdown, ValidatedDatePicker, ValidatedContainer } from '../Validated'
|
||||
import { Validator, ValidatedInput, ValidatedButton, ValidatedCheckbox } from '../Validated'
|
||||
import { StackLayout } from '../ui'
|
||||
|
||||
export class UserForm extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -144,87 +143,43 @@ export class UserForm extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form className='user-form' onSubmit={this.handleSubmit}>
|
||||
<Grid stackable>
|
||||
<Grid.Column width={16}>
|
||||
<Form.Group>
|
||||
<ValidatedDropdown label={'Deighton Access & Security Level'} width={6} selection
|
||||
options={Constants.accessLevels} name='role' message='The user role and security level'
|
||||
placeholder='' validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='First Name' name='firstName'
|
||||
width={8} validator={this.state.validator} />
|
||||
<ValidatedInput label='Last Name' name='lastName'
|
||||
width={8} validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
|
||||
validator={this.state.validator} />
|
||||
<ValidatedEmailIcon name='emailValidated' validator={this.state.validator} width={4}
|
||||
onClick={this.handleResendEmail} />
|
||||
<ValidatedButton width={4} size='medium' content='Change Email' label=' ' name='changeEmail'
|
||||
validator={this.state.validator} onClick={this.handleChangeEmail} />
|
||||
</Form.Group>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<StackLayout>
|
||||
<StackLayout.Item>
|
||||
<ValidatedCheckbox label={'Deighton Access & Security Level'} width={6} selection
|
||||
options={Constants.accessLevels} name='role' message='The user role and security level'
|
||||
placeholder='' validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='First Name' name='firstName'
|
||||
width={8} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Last Name' name='lastName'
|
||||
width={8} validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedInput label='Email' name='email' width={8} message='Must be a valid email address. Required.'
|
||||
validator={this.state.validator} />
|
||||
<ValidatedEmailIcon name='emailValidated' validator={this.state.validator} width={4}
|
||||
onClick={this.handleResendEmail} />
|
||||
</StackLayout.Item>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton width={4} size='medium' content='Change Email' label=' ' name='changeEmail'
|
||||
validator={this.state.validator} onClick={this.handleChangeEmail} />
|
||||
</StackLayout.Item>
|
||||
|
||||
<ValidatedContainer name='standard-fields' validator={this.state.validator}>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Zip' width={4} name='zip' message='5 Character U.S. Zip Code. Optional.'
|
||||
position='bottom center' validator={this.state.validator} />
|
||||
<ValidatedDropdown label='State' name='state' width={4}
|
||||
placeholder='Select State' options={Constants.stateOptions} validator={this.state.validator} searchable />
|
||||
<ValidatedInput label='City' width={8} type='text' name='city' message='U.S. City. Optional.'
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Address' width={12} name='address1'
|
||||
validator={this.state.validator} message='Primary Street Address. Optional.' />
|
||||
<ValidatedInput label='Apt. #' width={4} name='address2'
|
||||
validator={this.state.validator} message='Apartment/Unit number. Optional.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedInput label='Home Phone' width={8} name='homePhone'
|
||||
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
|
||||
<ValidatedInput label='Cell Phone' width={8} name='cellPhone'
|
||||
validator={this.state.validator} message='A valid U.S. phone number. IE: (555)123-4567. Optional.' />
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedDatePicker label='Date of Birth' width={5} name='dateOfBirth'
|
||||
validator={this.state.validator} />
|
||||
<ValidatedInput label='SSN' width={6} name='ssn'
|
||||
validator={this.state.validator} message='U.S. Social Security Number. IE: 123-45-6789' />
|
||||
<ValidatedDatePicker label='Hire Date' width={5} name='dateOfHire'
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
</ValidatedContainer>
|
||||
|
||||
<ValidatedContainer name='broker-fields' validator={this.state.validator}>
|
||||
<Form.Group>
|
||||
<ValidatedInput label='# Households' width={5} name='numHouseholds'
|
||||
message='Number of households in this brokers account' validator={this.state.validator} />
|
||||
<ValidatedInput label='T-12' width={6} name='t12' message='This brokers T-12 info.'
|
||||
validator={this.state.validator} />
|
||||
<ValidatedInput label='AUM' width={5} name='aum'
|
||||
message='This brokers AUM information.' validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
</ValidatedContainer>
|
||||
|
||||
<Form.Group>
|
||||
<ValidatedButton color='red' width={4} size='medium' content='Remove' label=' ' name='remove'
|
||||
validator={this.state.validator} onClick={this.props.onRemove} />
|
||||
<ValidatedButton width={4} size='medium' content='Reset' label=' ' name='reset'
|
||||
validator={this.state.validator} onClick={this.handleReset} />
|
||||
<Form.Field width={this.state.validator._id ? 8 : 12} />
|
||||
<ValidatedButton primary submit width={4} size='medium'
|
||||
content={this.state.validator._id ? 'Save' : 'Add'} label=' ' name='submit'
|
||||
validator={this.state.validator} />
|
||||
</Form.Group>
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</Form>
|
||||
<StackLayout.Item>
|
||||
<ValidatedButton color='red' width={4} size='medium' content='Remove' label=' ' name='remove'
|
||||
validator={this.state.validator} onClick={this.props.onRemove} />
|
||||
<ValidatedButton width={4} size='medium' content='Reset' label=' ' name='reset'
|
||||
validator={this.state.validator} onClick={this.handleReset} />
|
||||
<ValidatedButton primary submit width={4} size='medium'
|
||||
content={this.state.validator._id ? 'Save' : 'Add'} label=' ' name='submit'
|
||||
validator={this.state.validator} />
|
||||
</StackLayout.Item>
|
||||
</StackLayout>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dropdown, List, Icon, Button, Image } from 'semantic-ui-react'
|
||||
import { Dropdown, List, Icon, Button, Image } from '../ui'
|
||||
import { Constants, api } from '../helpers'
|
||||
import './UserList.scss'
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import { Container, Grid } from 'semantic-ui-react'
|
||||
import { autoBind } from 'auto-bind2'
|
||||
import { UserList } from './UserList'
|
||||
import { UserForm } from './UserForm'
|
||||
import { UserFormPlaceholder } from './UserFormPlaceholder'
|
||||
import { api } from '../helpers'
|
||||
import { RowLayout } from '../ui'
|
||||
import { YesNoMessageDialog, MessageDialog, ChangeEmailDialog, WaitDialog } from '../Dialog'
|
||||
|
||||
export class Users extends React.Component {
|
||||
@@ -237,19 +237,19 @@ export class Users extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<div>
|
||||
<div>Users</div>
|
||||
|
||||
<Grid stackable>
|
||||
<RowLayout>
|
||||
{/* User List - Displayed on left hand side. */}
|
||||
<Grid.Column width={5}>
|
||||
<RowLayout.Item width={5}>
|
||||
<UserList users={this.state.users} selectedUser={this.state.selectedUser}
|
||||
selectionModified={this.state.modified} onUserListClick={this.handleUserListClick}
|
||||
onAddNewUser={this.handleAddNewUser} />
|
||||
</Grid.Column>
|
||||
</RowLayout.Item>
|
||||
|
||||
{/* User Info - Displayed on right hand side. */}
|
||||
<Grid.Column width={11}>
|
||||
<RowLayout.Item>
|
||||
{
|
||||
this.state.selectedUser
|
||||
? <UserForm user={this.state.selectedUser} onSave={this.handleSave}
|
||||
@@ -257,8 +257,8 @@ export class Users extends React.Component {
|
||||
onChangeEmail={this.handleChangeEmail} onResendEmail={this.handleResendEmail} />
|
||||
: <UserFormPlaceholder />
|
||||
}
|
||||
</Grid.Column>
|
||||
</Grid>
|
||||
</RowLayout.Item>
|
||||
</RowLayout>
|
||||
|
||||
<ChangeEmailDialog open={!!this.state.changeEmailDialog} onDismiss={this.handleChangeEmailDismiss} />
|
||||
|
||||
@@ -275,7 +275,7 @@ export class Users extends React.Component {
|
||||
onDismiss={this.handleMessageDialogDismiss} />
|
||||
|
||||
<WaitDialog active={!!this.state.waitDialog} message={this.state.waitDialog ? this.state.waitDialog.message : ''} />
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form, Icon, Popup, Button } from 'semantic-ui-react'
|
||||
import { Label, Button, Icon } from '../ui'
|
||||
import './ValidatedEmailIcon.scss'
|
||||
|
||||
// This is a validated component with a value that cannot change itself and is specialized
|
||||
@@ -27,20 +27,19 @@ export class ValidatedEmailIcon extends React.Component {
|
||||
render() {
|
||||
if (this.state.value) {
|
||||
return (
|
||||
<Form.Field width={this.props.width}>
|
||||
<label> </label>
|
||||
<Popup content='Email Validated' position='bottom center' hoverable trigger={
|
||||
<div width={this.props.width}>
|
||||
<Label>
|
||||
<Icon name='mail' color='green' size='big' className='mail-validated-icon' />
|
||||
} />
|
||||
</Form.Field>
|
||||
</Label>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Form.Field width={this.props.width}>
|
||||
<label> </label>
|
||||
<div width={this.props.width}>
|
||||
<Label> </Label>
|
||||
<Button fluid icon='mail outline' color='red' labelPosition='left'
|
||||
content='Resend Email' onClick={this.props.onClick} disabled={this.state.disabled} />
|
||||
</Form.Field>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Button } from 'semantic-ui-react'
|
||||
import { Button } from '../ui'
|
||||
|
||||
export class ValidatedActionsButton extends React.Component {
|
||||
static propTypes = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form, Button } from 'semantic-ui-react'
|
||||
import { Button } from '../ui'
|
||||
|
||||
export class ValidatedButton extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -46,13 +46,15 @@ export class ValidatedButton extends React.Component {
|
||||
render() {
|
||||
if (this.state.visible) {
|
||||
return (
|
||||
<Form.Field width={this.props.width} disabled={this.state.disabled}>
|
||||
<div width={this.props.width} disabled={this.state.disabled}>
|
||||
<label>{this.props.label}</label>
|
||||
<Button fluid color={this.props.color} primary={this.props.primary}
|
||||
<Button color={this.props.color} primary={this.props.primary}
|
||||
type={this.props.submit ? 'submit' : 'button'} onClick={this.props.onClick}
|
||||
content={this.props.content} size={this.props.size} name={this.props.name}
|
||||
floated={this.props.floated} />
|
||||
</Form.Field>
|
||||
size={this.props.size} name={this.props.name}
|
||||
floated={this.props.floated}>
|
||||
{this.props.content}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form } from 'semantic-ui-react'
|
||||
import { Checkbox } from '../ui'
|
||||
import { Checkbox, Label } from '../ui'
|
||||
|
||||
// This is an example of a validated component with a value that can change itself, that cannot ever be invalid.
|
||||
|
||||
@@ -38,9 +37,10 @@ export class ValidatedCheckbox extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form.Field width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
|
||||
<Checkbox value={!!this.state.value} name={this.props.name} label={this.props.label} />
|
||||
</Form.Field>
|
||||
<Label width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
|
||||
<Checkbox value={!!this.state.value} name={this.props.name} />
|
||||
{this.props.label}
|
||||
</Label>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Container } from 'semantic-ui-react'
|
||||
|
||||
export class ValidatedContainer extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -41,9 +40,9 @@ export class ValidatedContainer extends React.Component {
|
||||
render() {
|
||||
if (this.state.visible) {
|
||||
return (
|
||||
<Container>
|
||||
<div>
|
||||
{this.props.children}
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form, Popup } from 'semantic-ui-react'
|
||||
import 'moment'
|
||||
import { DatePickerInput } from 'rc-datepicker'
|
||||
import 'rc-datepicker/lib/style.css'
|
||||
|
||||
export class ValidatedDatePicker extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
label: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
validator: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = props.validator.getField(props.name)
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleClear = this.handleClear.bind(this)
|
||||
}
|
||||
|
||||
handleChange(e, data) {
|
||||
const { validator, name } = this.props
|
||||
const state = validator.getField(name)
|
||||
|
||||
if (!state.readOnly && !state.disabled) {
|
||||
// NOTE: data is a little different for this control - no value property
|
||||
this.setState(validator.updateValue(name, data))
|
||||
}
|
||||
}
|
||||
|
||||
handleClear(e) {
|
||||
this.props.validator.updateValue(this.props.name, '')
|
||||
this.setState(this.props.validator.getField(this.props.name))
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.validator !== this.props.validator) {
|
||||
this.setState(nextProps.validator.getField(nextProps.name))
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form.Field error={!this.state.valid} width={this.props.width} disabled={this.state.disabled}>
|
||||
<label>{this.props.label}</label>
|
||||
<Popup content={this.props.message} position='right center' hoverable trigger={
|
||||
<DatePickerInput value={this.state.value} name={this.props.name} onChange={this.handleChange}
|
||||
showOnInputClick onClear={this.handleClear} />} />
|
||||
</Form.Field>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form, Dropdown, Popup } from 'semantic-ui-react'
|
||||
import { Dropdown, Text } from '../ui'
|
||||
|
||||
export class ValidatedDropdown extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -35,13 +35,13 @@ export class ValidatedDropdown extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form.Field error={!this.state.valid} width={this.props.width}>
|
||||
<div error={!this.state.valid} width={this.props.width}>
|
||||
<label>{this.props.label}</label>
|
||||
<Popup content={this.props.message} position='right center' hoverable trigger={
|
||||
<Dropdown selection fluid disabled={this.state.disabled} readOnly={this.state.readOnly}
|
||||
placeholder={this.props.placeholder} options={this.props.options}
|
||||
value={this.state.value} onChange={this.handleChange} search={this.props.searchable} />} />
|
||||
</Form.Field>
|
||||
<Dropdown selection disabled={this.state.disabled} readOnly={this.state.readOnly}
|
||||
placeholder={this.props.placeholder} options={this.props.options}
|
||||
value={this.state.value} onChange={this.handleChange} search={this.props.searchable} />
|
||||
<Text>{this.props.message}</Text>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Form } from 'semantic-ui-react'
|
||||
import { Input } from '../ui'
|
||||
import { Input, Label, Text } from '../ui'
|
||||
|
||||
// This is an example of a validated component with a value that changes itself
|
||||
|
||||
@@ -13,10 +12,7 @@ export class ValidatedInput extends React.Component {
|
||||
width: PropTypes.number,
|
||||
validator: PropTypes.object.isRequired,
|
||||
password: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
icon: PropTypes.string,
|
||||
iconPosition: PropTypes.string
|
||||
placeholder: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@@ -43,17 +39,17 @@ export class ValidatedInput extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Form.Field error={!this.state.valid} width={this.props.width} disabled={this.state.disabled} className={this.props.className}>
|
||||
<label>{this.props.label}</label>
|
||||
<Input value={this.state.value}
|
||||
hidden={this.props.password}
|
||||
name={this.props.name}
|
||||
onChange={this.handleChange}
|
||||
placeholder={this.props.placeholder}
|
||||
className={this.props.className} icon={this.props.icon}
|
||||
iconPosition={this.props.iconPosition} />
|
||||
<label>{this.props.message}</label>
|
||||
</Form.Field>
|
||||
<div width={this.props.width} disabled={this.state.disabled}>
|
||||
<Label>{this.props.label}<br />
|
||||
<Input value={this.state.value}
|
||||
password={this.props.password}
|
||||
name={this.props.name}
|
||||
onChange={this.handleChange}
|
||||
placeholder={this.props.placeholder} />
|
||||
</Label>
|
||||
<br />
|
||||
<Text size='small'>{this.props.message}</Text>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,5 @@ export { ValidatedInput } from './ValidatedInput'
|
||||
export { ValidatedButton } from './ValidatedButton'
|
||||
export { ValidatedActionsButton } from './ValidatedActionsButton'
|
||||
export { ValidatedDropdown } from './ValidatedDropdown'
|
||||
export { ValidatedDatePicker } from './ValidatedDatePicker'
|
||||
export { ValidatedCheckbox } from './ValidatedCheckbox'
|
||||
export { ValidatedContainer } from './ValidatedContainer'
|
||||
|
||||
54
website/src/assets/icons/logout.svg
Normal file
54
website/src/assets/icons/logout.svg
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 320.002 320.002" style="enable-background:new 0 0 320.002 320.002;" xml:space="preserve">
|
||||
<g id="XMLID_6_">
|
||||
<path id="XMLID_7_" d="M51.213,175.001h173.785c8.284,0,15-6.716,15-15c0-8.284-6.716-15-15-15H51.213l19.394-19.394
|
||||
c5.858-5.858,5.858-15.355,0-21.213c-5.857-5.858-15.355-5.858-21.213,0L4.396,149.393c-0.351,0.351-0.683,0.719-0.997,1.103
|
||||
c-0.137,0.167-0.256,0.344-0.385,0.515c-0.165,0.22-0.335,0.435-0.488,0.664c-0.14,0.209-0.261,0.426-0.389,0.64
|
||||
c-0.123,0.206-0.252,0.407-0.365,0.619c-0.118,0.22-0.217,0.446-0.323,0.67c-0.104,0.219-0.213,0.435-0.306,0.659
|
||||
c-0.09,0.219-0.164,0.442-0.243,0.664c-0.087,0.24-0.179,0.477-0.253,0.722c-0.067,0.222-0.116,0.447-0.172,0.672
|
||||
c-0.063,0.249-0.133,0.497-0.183,0.751c-0.051,0.259-0.082,0.521-0.119,0.782c-0.032,0.223-0.075,0.443-0.097,0.669
|
||||
c-0.048,0.484-0.073,0.971-0.074,1.457c0,0.007-0.001,0.015-0.001,0.022c0,0.007,0.001,0.015,0.001,0.022
|
||||
c0.001,0.487,0.026,0.973,0.074,1.458c0.022,0.223,0.064,0.44,0.095,0.661c0.038,0.264,0.069,0.528,0.121,0.79
|
||||
c0.05,0.252,0.119,0.496,0.182,0.743c0.057,0.227,0.107,0.456,0.175,0.681c0.073,0.241,0.164,0.474,0.248,0.71
|
||||
c0.081,0.226,0.155,0.453,0.247,0.675c0.091,0.22,0.198,0.431,0.3,0.646c0.108,0.229,0.21,0.46,0.33,0.685
|
||||
c0.11,0.205,0.235,0.4,0.354,0.599c0.131,0.221,0.256,0.444,0.4,0.659c0.146,0.219,0.309,0.424,0.466,0.635
|
||||
c0.136,0.181,0.262,0.368,0.407,0.544c0.299,0.364,0.616,0.713,0.947,1.048c0.016,0.016,0.029,0.034,0.045,0.05l45,45.001
|
||||
c2.93,2.929,6.768,4.394,10.607,4.394c3.838-0.001,7.678-1.465,10.606-4.393c5.858-5.858,5.858-15.355,0.001-21.213L51.213,175.001
|
||||
z"/>
|
||||
<path id="XMLID_8_" d="M305.002,25h-190c-8.284,0-15,6.716-15,15v60c0,8.284,6.716,15,15,15s15-6.716,15-15V55h160v210.001h-160
|
||||
v-45.001c0-8.284-6.716-15-15-15s-15,6.716-15,15v60.001c0,8.284,6.716,15,15,15h190c8.284,0,15-6.716,15-15V40
|
||||
C320.002,31.716,313.286,25,305.002,25z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
55
website/src/assets/icons/shapes.svg
Normal file
55
website/src/assets/icons/shapes.svg
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 210 210" style="enable-background:new 0 0 210 210;" xml:space="preserve">
|
||||
<g id="XMLID_12_">
|
||||
<path id="XMLID_13_" d="M195,0h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
|
||||
C210,6.716,203.284,0,195,0z"/>
|
||||
<path id="XMLID_14_" d="M115,0H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
|
||||
C130,6.716,123.284,0,115,0z"/>
|
||||
<path id="XMLID_15_" d="M35,0H15C6.716,0,0,6.716,0,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V15
|
||||
C50,6.716,43.284,0,35,0z"/>
|
||||
<path id="XMLID_16_" d="M195,160h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
|
||||
C210,166.716,203.284,160,195,160z"/>
|
||||
<path id="XMLID_17_" d="M115,160H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
|
||||
C130,166.716,123.284,160,115,160z"/>
|
||||
<path id="XMLID_18_" d="M35,160H15c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15v-20
|
||||
C50,166.716,43.284,160,35,160z"/>
|
||||
<path id="XMLID_19_" d="M195,80h-20c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
|
||||
C210,86.716,203.284,80,195,80z"/>
|
||||
<path id="XMLID_20_" d="M115,80H95c-8.284,0-15,6.716-15,15v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
|
||||
C130,86.716,123.284,80,115,80z"/>
|
||||
<path id="XMLID_21_" d="M35,80H15C6.716,80,0,86.716,0,95v20c0,8.284,6.716,15,15,15h20c8.284,0,15-6.716,15-15V95
|
||||
C50,86.716,43.284,80,35,80z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1,9 +1,8 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { App } from './App'
|
||||
import './index.scss'
|
||||
|
||||
ReactDOM.render(
|
||||
<App />,
|
||||
<App style={{ minHeight: '100vh', position: 'relative' }} />,
|
||||
document.getElementById('root')
|
||||
)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@import '~semantic-ui-css/semantic.min.css';
|
||||
|
||||
body #root {
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
@@ -1,16 +1,18 @@
|
||||
import { colorInfo, fontInfo } from './style'
|
||||
|
||||
export default {
|
||||
base: {
|
||||
borderRadius: '10px',
|
||||
fontFamily: 'Arial',
|
||||
color: '#ffffff',
|
||||
fontFamily: fontInfo.family,
|
||||
color: '#FFFFFF',
|
||||
fontSize: '20px',
|
||||
background: '#3498db',
|
||||
background: colorInfo.buttonBackgroundHover,
|
||||
padding: '10px 20px 10px 20px',
|
||||
textDecoration: 'none',
|
||||
outline: 'none',
|
||||
|
||||
':hover': {
|
||||
background: '#3cb0fd',
|
||||
background: colorInfo.buttonBackground,
|
||||
textDecoration: 'none'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { colorInfo } from './style'
|
||||
|
||||
export default {
|
||||
checkbox: {
|
||||
cursor: 'pointer',
|
||||
position: 'relative',
|
||||
backgroundColor: '#2196F3',
|
||||
backgroundColor: colorInfo.buttonBackground,
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: 25,
|
||||
|
||||
19
website/src/ui/Dropdown.js
Normal file
19
website/src/ui/Dropdown.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import style from './Input.style'
|
||||
|
||||
class Dropdown extends Component {
|
||||
static propTypes = {
|
||||
password: PropTypes.bool,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input type={this.props.password ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(Dropdown)
|
||||
2
website/src/ui/Dropdown.style.js
Normal file
2
website/src/ui/Dropdown.style.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export default {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
// See https://www.flaticon.com/packs/web-button-compilation for more icons
|
||||
|
||||
export default class Icon extends Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
size: PropTypes.number,
|
||||
margin: PropTypes.number
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 50,
|
||||
margin: 5,
|
||||
name: 'shapes'
|
||||
}
|
||||
|
||||
static svgs = {
|
||||
logout: require('icons/logout.svg'),
|
||||
shapes: require('icons/shapes.svg')
|
||||
}
|
||||
|
||||
render() {
|
||||
return <img style={{ width: this.props.size, height: this.props.size, margin: this.props.margin }}
|
||||
src={Icon.svgs[this.props.name]} />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
|
||||
class Image extends Component {
|
||||
static propTypes = {
|
||||
source: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
margin: PropTypes.number
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<img src={this.props.source} style={{ width: this.props.width, height: this.props.height, margin: this.props.margin }} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(Image)
|
||||
|
||||
@@ -5,13 +5,13 @@ import style from './Input.style'
|
||||
|
||||
class Input extends Component {
|
||||
static propTypes = {
|
||||
hidden: PropTypes.bool,
|
||||
password: PropTypes.bool,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input type={this.props.hidden ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
|
||||
<input type={this.props.password ? 'password' : 'text'} style={style.base}>{this.props.children}</input>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
33
website/src/ui/Label.js
Normal file
33
website/src/ui/Label.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { fontInfo } from './style'
|
||||
|
||||
class Label extends Component {
|
||||
static propTypes = {
|
||||
size: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 'medium',
|
||||
color: 'normal',
|
||||
margin: 0
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<label style={{
|
||||
display: 'inline-block',
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
color: fontInfo.color[this.props.color],
|
||||
fontFamily: fontInfo.family,
|
||||
margin: this.props.margin
|
||||
}}>{this.props.children}</label>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(Label)
|
||||
30
website/src/ui/Link.js
Normal file
30
website/src/ui/Link.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { fontInfo } from './style'
|
||||
|
||||
class Link extends Component {
|
||||
static propTypes = {
|
||||
to: PropTypes.string,
|
||||
size: PropTypes.string,
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 'medium',
|
||||
margin: 0
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a href={this.props.to} style={{
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
fontFamily: fontInfo.family,
|
||||
margin: this.props.margin
|
||||
}}>{this.props.children}</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(Link)
|
||||
30
website/src/ui/List.js
Normal file
30
website/src/ui/List.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { 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() {
|
||||
return (
|
||||
<span style={{
|
||||
display: 'inline-block',
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
fontFamily: fontInfo.family,
|
||||
margin: this.props.margin
|
||||
}}>{this.props.children}</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(List)
|
||||
51
website/src/ui/Loader.js
Normal file
51
website/src/ui/Loader.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { keyframes, css } from 'emotion';
|
||||
import { onlyUpdateForKeys } from 'recompose';
|
||||
|
||||
// This returns an animation
|
||||
const pulse = keyframes`
|
||||
0% {transform: scale(1);opacity: 1}
|
||||
45% {transform: scale(0.1);opacity: 0.7}
|
||||
80% {transform: scale(1);opacity: 1}
|
||||
`;
|
||||
|
||||
class Loader extends React.Component {
|
||||
style = i => css`{
|
||||
background-color: ${this.props.color};
|
||||
width: ${this.props.size}px;
|
||||
height: ${this.props.size}px;
|
||||
margin: ${this.props.margin};
|
||||
border-radius: 100%;
|
||||
display: inline-block;
|
||||
animation: ${pulse} 0.75s ${i * 0.12}s infinite cubic-bezier(.2,.68,.18,1.08);
|
||||
animation-fill-mode: both;
|
||||
}`;
|
||||
|
||||
render() {
|
||||
return this.props.loading ?
|
||||
<div>
|
||||
<div className={this.style(1)} />
|
||||
<div className={this.style(2)} />
|
||||
<div className={this.style(3)} />
|
||||
</div> : null;
|
||||
}
|
||||
}
|
||||
|
||||
Loader.propTypes = {
|
||||
loading: PropTypes.bool,
|
||||
color: PropTypes.string,
|
||||
size: PropTypes.number,
|
||||
margin: PropTypes.string
|
||||
};
|
||||
|
||||
Loader.defaultProps = {
|
||||
loading: true,
|
||||
color: '#000000',
|
||||
size: 15,
|
||||
margin: '2px'
|
||||
};
|
||||
|
||||
const Component = onlyUpdateForKeys(['loading', 'color', 'size', 'margin'])(Loader);
|
||||
Component.defaultProps = Loader.defaultProps;
|
||||
export default Component;
|
||||
29
website/src/ui/Modal.js
Normal file
29
website/src/ui/Modal.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import style from './Modal.style'
|
||||
import { reactAutoBind } from 'auto-bind2'
|
||||
|
||||
export class Modal extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
reactAutoBind(this)
|
||||
}
|
||||
|
||||
preventPropagation(e) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={style.dimmer} onClick={this.preventPropagation}>
|
||||
<div style={style.modal}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
28
website/src/ui/Modal.style.js
Normal file
28
website/src/ui/Modal.style.js
Normal file
@@ -0,0 +1,28 @@
|
||||
export default {
|
||||
dimmer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: 100,
|
||||
background: 'rgba(25, 25, 30, 0.75)'
|
||||
},
|
||||
|
||||
modal: {
|
||||
zIndex: 101,
|
||||
background: '#FFFFFF',
|
||||
margin: 0,
|
||||
padding: '18px 24px',
|
||||
width: '80%',
|
||||
border: '1px solid $border-primary',
|
||||
borderRadius: 4,
|
||||
boxShadow: '0 0 25px #000000'
|
||||
}
|
||||
}
|
||||
31
website/src/ui/RowLayout.js
Normal file
31
website/src/ui/RowLayout.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import Radium from 'radium'
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class RowLayout extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]).isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ display: 'flex', minWidth: this.props.width, flexDirection: 'row' }}>{this.props.children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout.Item = Radium(class RowLayoutItem extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={[ this.props.width ? { minWidth: this.props.width } : { flexGrow: 1 } ]}>{this.props.children}</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Radium(RowLayout)
|
||||
31
website/src/ui/StackLayout.js
Normal file
31
website/src/ui/StackLayout.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import Radium from 'radium'
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class StackLayout extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]).isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{ display: 'flex', minHeight: this.props.height, flexDirection: 'column' }}>{this.props.children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
StackLayout.Item = Radium(class StackLayoutItem extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={[ this.props.height ? { minHeight: this.props.height } : { flexGrow: 1 } ]}>{this.props.children}</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Radium(StackLayout)
|
||||
@@ -0,0 +1,30 @@
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { Component } from 'react'
|
||||
import { fontInfo } from './style'
|
||||
|
||||
class Text extends Component {
|
||||
static propTypes = {
|
||||
size: PropTypes.string,
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
size: 'medium',
|
||||
margin: 0
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<span style={{
|
||||
display: 'inline-block',
|
||||
fontSize: fontInfo.size[this.props.size],
|
||||
fontFamily: fontInfo.family,
|
||||
margin: this.props.margin
|
||||
}}>{this.props.children}</span>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Radium(Text)
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
export { default as Button } from './Button'
|
||||
export { default as Checkbox } from './Checkbox'
|
||||
export { default as Input } from './Input'
|
||||
export { default as Image } from './Image'
|
||||
export { default as Text } from './Text'
|
||||
export { default as Link } from './Link'
|
||||
export { default as Label } from './Label'
|
||||
export { default as Icon } from './Icon'
|
||||
export { default as List } from './List'
|
||||
export { default as Dropdown } from './Dropdown'
|
||||
export { default as Modal } from './Modal'
|
||||
export { default as Dimmer } from './Dimmer'
|
||||
export { default as Loader } from './Loader'
|
||||
export { default as HolyGrail } from './HolyGrail'
|
||||
export { default as RowLayout } from './RowLayout'
|
||||
export { default as StackLayout } from './StackLayout'
|
||||
|
||||
19
website/src/ui/style.js
Normal file
19
website/src/ui/style.js
Normal file
@@ -0,0 +1,19 @@
|
||||
export const colorInfo = {
|
||||
text: '#000000',
|
||||
alertText: '#FF0000',
|
||||
buttonBackground: '#3498DB',
|
||||
buttonBackgroundHover: '#3CB0FD'
|
||||
}
|
||||
|
||||
export const fontInfo = {
|
||||
family: 'Hind, sans-serif', // https://fonts.google.com/specimen/Hind?selection.family=Hind
|
||||
size: {
|
||||
small: '10pt',
|
||||
medium: '12pt',
|
||||
large: '14pt'
|
||||
},
|
||||
color: {
|
||||
'normal': colorInfo.text,
|
||||
'alert': colorInfo.alertText
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
export class VersionInfo {
|
||||
static version = '0.0.4'
|
||||
static fullVersion = '0.0.4-20171018.0'
|
||||
static startYear = '2017'
|
||||
export const versionInfo = {
|
||||
version: '0.1.0',
|
||||
fullVersion: '0.1.0-20180225.0',
|
||||
startYear: '2017'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user