save form to localStorage
parent
d8a6373b1e
commit
8148c1a19c
|
@ -1,5 +1,13 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { contain } from 'thundercats-react';
|
||||
import debugFactory from 'debug';
|
||||
import { getDefaults } from '../utils';
|
||||
|
||||
import {
|
||||
inHTMLData,
|
||||
uriInSingleQuotedAttr
|
||||
} from 'xss-filters';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
|
@ -7,6 +15,7 @@ import {
|
|||
Row,
|
||||
Well
|
||||
} from 'react-bootstrap';
|
||||
|
||||
import {
|
||||
isAscii,
|
||||
isEmail,
|
||||
|
@ -14,31 +23,34 @@ import {
|
|||
isURL
|
||||
} from 'validator';
|
||||
|
||||
const defaults = {
|
||||
'string': {
|
||||
value: '',
|
||||
valid: false,
|
||||
pristine: true
|
||||
},
|
||||
bool: {
|
||||
value: false
|
||||
}
|
||||
};
|
||||
const debug = debugFactory('freecc:jobs:newForm');
|
||||
|
||||
const checkValidity = [
|
||||
'position',
|
||||
'locale',
|
||||
'description',
|
||||
'email',
|
||||
'phone',
|
||||
'url',
|
||||
'logo',
|
||||
'name',
|
||||
'highlight'
|
||||
];
|
||||
|
||||
export default contain({
|
||||
actions: 'jobActions',
|
||||
store: 'jobsStore',
|
||||
map({ form = {} }) {
|
||||
const {
|
||||
position = defaults['string'],
|
||||
locale = defaults['string'],
|
||||
description = defaults['string'],
|
||||
email = defaults['string'],
|
||||
phone = defaults['string'],
|
||||
url = defaults['string'],
|
||||
logo = defaults['string'],
|
||||
name = defaults['string'],
|
||||
highlight = defaults['bool']
|
||||
position = getDefaults('string'),
|
||||
locale = getDefaults('string'),
|
||||
description = getDefaults('string'),
|
||||
email = getDefaults('string'),
|
||||
phone = getDefaults('string'),
|
||||
url = getDefaults('string'),
|
||||
logo = getDefaults('string'),
|
||||
name = getDefaults('string'),
|
||||
highlight = getDefaults('bool')
|
||||
} = form;
|
||||
return {
|
||||
position,
|
||||
|
@ -51,6 +63,9 @@ export default contain({
|
|||
name,
|
||||
highlight
|
||||
};
|
||||
},
|
||||
subscribeOnWillMount() {
|
||||
return typeof window !== 'undefined';
|
||||
}
|
||||
},
|
||||
React.createClass({
|
||||
|
@ -69,6 +84,63 @@ export default contain({
|
|||
highlight: PropTypes.object
|
||||
},
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
let valid = true;
|
||||
checkValidity.forEach((prop) => {
|
||||
// if value exist, check if it is valid
|
||||
if (this.props[prop].value) {
|
||||
valid = valid && !!this.props[prop].valid;
|
||||
}
|
||||
});
|
||||
|
||||
if (!valid) {
|
||||
debug('form not valid');
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
position,
|
||||
locale,
|
||||
description,
|
||||
email,
|
||||
phone,
|
||||
url,
|
||||
logo,
|
||||
name,
|
||||
highlight,
|
||||
jobActions
|
||||
} = this.props;
|
||||
|
||||
// sanitize user output
|
||||
const jobValues = {
|
||||
position: inHTMLData(position.value),
|
||||
location: inHTMLData(locale.value),
|
||||
description: inHTMLData(description.value),
|
||||
email: inHTMLData(email.value),
|
||||
phone: inHTMLData(phone.value),
|
||||
url: uriInSingleQuotedAttr(url.value),
|
||||
logo: uriInSingleQuotedAttr(logo.value),
|
||||
name: inHTMLData(name.value),
|
||||
highlight: !!highlight.value
|
||||
};
|
||||
|
||||
const job = Object.keys(jobValues).reduce((accu, prop) => {
|
||||
if (jobValues[prop]) {
|
||||
accu[prop] = jobValues[prop];
|
||||
}
|
||||
return accu;
|
||||
}, {});
|
||||
|
||||
debug('job sanitized', job);
|
||||
jobActions.saveForm(job);
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
const { jobActions } = this.props;
|
||||
jobActions.getSavedForm();
|
||||
},
|
||||
|
||||
handleChange(name, validator, { target: { value } }) {
|
||||
const { jobActions: { handleForm } } = this.props;
|
||||
handleForm({ name, value, validator });
|
||||
|
@ -95,7 +167,9 @@ export default contain({
|
|||
<Col>
|
||||
<Well className='text-center'>
|
||||
<h1>Create Your Job Post</h1>
|
||||
<form className='form-horizontal'>
|
||||
<form
|
||||
className='form-horizontal'
|
||||
onSubmit={ this.handleSubmit }>
|
||||
|
||||
<div className='spacer'>
|
||||
<h2>Job Information</h2>
|
||||
|
@ -151,7 +225,7 @@ export default contain({
|
|||
<h2>Company Information</h2>
|
||||
</div>
|
||||
<Input
|
||||
bsStyle={ locale.bsStyle }
|
||||
bsStyle={ name.bsStyle }
|
||||
label='Company Name'
|
||||
labelClassName={ labelClass }
|
||||
onChange={ (e) => {
|
||||
|
@ -248,8 +322,9 @@ export default contain({
|
|||
lgOffset={ 3 }>
|
||||
<Button
|
||||
block={ true }
|
||||
bsSize='lg'
|
||||
bsStyle='primary'>
|
||||
bsSize='large'
|
||||
bsStyle='primary'
|
||||
type='submit'>
|
||||
Preview My Ad
|
||||
</Button>
|
||||
</Col>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { Actions } from 'thundercats';
|
||||
import store from 'store';
|
||||
import { getDefaults } from '../utils';
|
||||
import debugFactory from 'debug';
|
||||
|
||||
const debug = debugFactory('freecc:jobs:actions');
|
||||
|
@ -52,12 +54,14 @@ export default Actions({
|
|||
newState.form = assign(
|
||||
{},
|
||||
form,
|
||||
{ [name]: {
|
||||
value,
|
||||
valid: false,
|
||||
pristine: false,
|
||||
bsStyle: value ? 'error' : null
|
||||
}}
|
||||
{
|
||||
[name]: {
|
||||
value,
|
||||
valid: false,
|
||||
pristine: false,
|
||||
bsStyle: value ? 'error' : null
|
||||
}
|
||||
}
|
||||
);
|
||||
return newState;
|
||||
}
|
||||
|
@ -70,16 +74,31 @@ export default Actions({
|
|||
newState.form = assign(
|
||||
{},
|
||||
form,
|
||||
{ [name]: {
|
||||
value,
|
||||
valid: true,
|
||||
pristine: false,
|
||||
bsStyle: value ? 'success' : null
|
||||
}}
|
||||
{
|
||||
[name]: {
|
||||
value,
|
||||
valid: true,
|
||||
pristine: false,
|
||||
bsStyle: value ? 'success' : null
|
||||
}
|
||||
}
|
||||
);
|
||||
return newState;
|
||||
}
|
||||
};
|
||||
},
|
||||
saveForm: null,
|
||||
getSavedForm: null,
|
||||
setForm(job) {
|
||||
const form = Object.keys(job).reduce((accu, prop) => {
|
||||
console.log('form', accu);
|
||||
return Object.assign(
|
||||
accu,
|
||||
{ [prop]: getDefaults(typeof prop, job[prop]) }
|
||||
);
|
||||
}, {});
|
||||
|
||||
return { form };
|
||||
}
|
||||
})
|
||||
.refs({ displayName: 'JobActions' })
|
||||
|
@ -111,5 +130,14 @@ export default Actions({
|
|||
jobActions.setJobs({});
|
||||
});
|
||||
});
|
||||
|
||||
jobActions.saveForm.subscribe((form) => {
|
||||
store.set('newJob', form);
|
||||
});
|
||||
|
||||
jobActions.getSavedForm.subscribe(() => {
|
||||
const job = store.get('newJob');
|
||||
jobActions.setForm(job);
|
||||
});
|
||||
return jobActions;
|
||||
});
|
||||
|
|
|
@ -15,13 +15,15 @@ export default Store({ showModal: false })
|
|||
setError,
|
||||
openModal,
|
||||
closeModal,
|
||||
handleForm
|
||||
handleForm,
|
||||
setForm
|
||||
} = cat.getActions('JobActions');
|
||||
const register = createRegistrar(jobsStore);
|
||||
register(setter(setJobs));
|
||||
register(setter(setError));
|
||||
register(setter(openModal));
|
||||
register(setter(closeModal));
|
||||
register(setter(setForm));
|
||||
|
||||
register(transformer(findJob));
|
||||
register(handleForm);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
const defaults = {
|
||||
'string': {
|
||||
value: '',
|
||||
valid: false,
|
||||
pristine: true,
|
||||
type: 'string'
|
||||
},
|
||||
bool: {
|
||||
value: false,
|
||||
type: 'boolean'
|
||||
}
|
||||
};
|
||||
|
||||
export function getDefaults(type, value) {
|
||||
if (!type) {
|
||||
return defaults['string'];
|
||||
}
|
||||
if (value) {
|
||||
return Object.assign({}, defaults[type], { value });
|
||||
}
|
||||
return defaults[type];
|
||||
}
|
|
@ -30,6 +30,9 @@
|
|||
"state": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"country": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -39,7 +42,7 @@
|
|||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"isApproverd": {
|
||||
"isApproved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isHighlighted": {
|
||||
|
|
|
@ -97,12 +97,14 @@
|
|||
"sanitize-html": "~1.6.1",
|
||||
"sort-keys": "^1.1.1",
|
||||
"source-map-support": "^0.3.2",
|
||||
"store": "https://github.com/berkeleytrue/store.js.git#feature/noop-server",
|
||||
"thundercats": "^2.1.0",
|
||||
"thundercats-react": "^0.1.0",
|
||||
"twit": "~1.1.20",
|
||||
"uglify-js": "~2.4.15",
|
||||
"validator": "^3.22.1",
|
||||
"webpack": "^1.9.12",
|
||||
"xss-filters": "^1.2.6",
|
||||
"yui": "~3.18.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
Loading…
Reference in New Issue