save form to localStorage

pull/3525/head
Berkeley Martinez 2015-09-24 20:28:04 -07:00
parent d8a6373b1e
commit 8148c1a19c
6 changed files with 169 additions and 37 deletions

View File

@ -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>

View File

@ -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;
});

View File

@ -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);

View File

@ -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];
}

View File

@ -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": {

View File

@ -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": {