import React, { PropTypes } from 'react'; import { History } from 'react-router'; import { contain } from 'thundercats-react'; import debugFactory from 'debug'; import { getDefaults } from '../utils'; import { inHTMLData, uriInSingleQuotedAttr } from 'xss-filters'; import { Button, Col, Input, Row, Well } from 'react-bootstrap'; import { isAscii, isEmail, isMobilePhone, isURL } from 'validator'; const debug = debugFactory('freecc:jobs:newForm'); const checkValidity = [ 'position', 'locale', 'description', 'email', 'phone', 'url', 'logo', 'name', 'highlight' ]; function formatValue(value, validator, type = 'string') { const formated = getDefaults(type); if (validator && type === 'string') { formated.valid = validator(value); } if (value) { formated.value = value; formated.bsStyle = formated.valid ? 'success' : 'error'; } return formated; } function isValidURL(data) { return isURL(data, { 'require_protocol': true }); } function isValidPhone(data) { return isMobilePhone(data, 'en-US'); } export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { const { position, locale, description, email, phone, url, logo, name, highlight } = form; return { position: formatValue(position, isAscii), locale: formatValue(locale, isAscii), description: formatValue(description, isAscii), email: formatValue(email, isEmail), phone: formatValue(phone, isValidPhone), url: formatValue(url, isValidURL), logo: formatValue(logo, isValidURL), name: formatValue(name, isAscii), highlight: formatValue(highlight, null, 'bool') }; }, subscribeOnWillMount() { return typeof window !== 'undefined'; } }, React.createClass({ displayName: 'NewJob', propTypes: { jobActions: PropTypes.object, position: PropTypes.object, locale: PropTypes.object, description: PropTypes.object, email: PropTypes.object, phone: PropTypes.object, url: PropTypes.object, logo: PropTypes.object, name: PropTypes.object, highlight: PropTypes.object }, mixins: [History], handleSubmit(e) { e.preventDefault(); const props = this.props; let valid = true; checkValidity.forEach((prop) => { // if value exist, check if it is valid if (props[prop].value && props[prop].type !== 'boolean') { valid = valid && !!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; }, {}); job.postedOn = new Date(); debug('job sanitized', job); jobActions.saveForm(job); this.history.pushState(null, '/jobs/new/preview'); }, componentDidMount() { const { jobActions } = this.props; jobActions.getSavedForm(); }, handleChange(name, { target: { value } }) { const { jobActions: { handleForm } } = this.props; handleForm({ [name]: value }); }, render() { const { position, locale, description, email, phone, url, logo, name, highlight, jobActions: { handleForm } } = this.props; const { handleChange } = this; const labelClass = 'col-sm-offset-1 col-sm-2'; const inputClass = 'col-sm-6'; return (