render individual job on request and window transition
This commit is contained in:
@ -1,23 +1,39 @@
|
|||||||
import React, { cloneElement, PropTypes } from 'react';
|
import React, { cloneElement, PropTypes } from 'react';
|
||||||
import { contain } from 'thundercats-react';
|
import { contain } from 'thundercats-react';
|
||||||
|
import { Navigation } from 'react-router';
|
||||||
import { Button, Jumbotron, Row } from 'react-bootstrap';
|
import { Button, Jumbotron, Row } from 'react-bootstrap';
|
||||||
import ListJobs from './List.jsx';
|
import ListJobs from './List.jsx';
|
||||||
|
|
||||||
export default contain(
|
export default contain(
|
||||||
{
|
{
|
||||||
store: 'jobsStore',
|
store: 'jobsStore',
|
||||||
fetchAction: 'jobActions.getJobs'
|
fetchAction: 'jobActions.getJobs',
|
||||||
|
actions: 'jobActions'
|
||||||
},
|
},
|
||||||
React.createClass({
|
React.createClass({
|
||||||
displayName: 'Jobs',
|
displayName: 'Jobs',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
children: PropTypes.element,
|
children: PropTypes.element,
|
||||||
|
jobActions: PropTypes.object,
|
||||||
jobs: PropTypes.array
|
jobs: PropTypes.array
|
||||||
},
|
},
|
||||||
|
mixins: [Navigation],
|
||||||
|
|
||||||
renderList(jobs) {
|
handleJobClick(id) {
|
||||||
|
const { jobActions } = this.props;
|
||||||
|
if (!id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
jobActions.findJob(id);
|
||||||
|
this.transitionTo(`/jobs/${id}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderList(handleJobClick, jobs) {
|
||||||
return (
|
return (
|
||||||
<ListJobs jobs={ jobs }/>
|
<ListJobs
|
||||||
|
handleClick={ handleJobClick }
|
||||||
|
jobs={ jobs }/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -53,7 +69,7 @@ export default contain(
|
|||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
{ this.renderChild(children, jobs) ||
|
{ this.renderChild(children, jobs) ||
|
||||||
this.renderList(jobs) }
|
this.renderList(this.handleJobClick, jobs) }
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import { Link } from 'react-router';
|
|
||||||
import { PanelGroup, Thumbnail, Panel, Well } from 'react-bootstrap';
|
import { PanelGroup, Thumbnail, Panel, Well } from 'react-bootstrap';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
@ -7,15 +6,17 @@ export default React.createClass({
|
|||||||
displayName: 'ListJobs',
|
displayName: 'ListJobs',
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
handleClick: PropTypes.func,
|
||||||
jobs: PropTypes.array
|
jobs: PropTypes.array
|
||||||
},
|
},
|
||||||
|
|
||||||
renderJobs(jobs =[]) {
|
renderJobs(handleClick, jobs =[]) {
|
||||||
const thumbnailStyle = {
|
const thumbnailStyle = {
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
maxHeight: '100px',
|
maxHeight: '100px',
|
||||||
maxWidth: '100px'
|
maxWidth: '100px'
|
||||||
};
|
};
|
||||||
|
|
||||||
return jobs.map((
|
return jobs.map((
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@ -47,7 +48,6 @@ export default React.createClass({
|
|||||||
eventKey={ index }
|
eventKey={ index }
|
||||||
header={ header }
|
header={ header }
|
||||||
key={ id }>
|
key={ id }>
|
||||||
<Link to={ `/jobs/${id}` }>
|
|
||||||
<Well>
|
<Well>
|
||||||
<Thumbnail
|
<Thumbnail
|
||||||
alt={ company + 'company logo' }
|
alt={ company + 'company logo' }
|
||||||
@ -61,19 +61,22 @@ export default React.createClass({
|
|||||||
<br />
|
<br />
|
||||||
Posted On: { moment(postedOn).format('MMMM Do, YYYY') }
|
Posted On: { moment(postedOn).format('MMMM Do, YYYY') }
|
||||||
</Panel>
|
</Panel>
|
||||||
<p>{ description }</p>
|
<p onClick={ () => handleClick(id) }>{ description }</p>
|
||||||
</Well>
|
</Well>
|
||||||
</Link>
|
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { jobs } = this.props;
|
const {
|
||||||
|
handleClick,
|
||||||
|
jobs
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelGroup>
|
<PanelGroup>
|
||||||
{ this.renderJobs(jobs) }
|
{ this.renderJobs(handleClick, jobs) }
|
||||||
</PanelGroup>
|
</PanelGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,18 @@ export default contain(
|
|||||||
store: 'jobsStore',
|
store: 'jobsStore',
|
||||||
fetchAction: 'jobActions.getJob',
|
fetchAction: 'jobActions.getJob',
|
||||||
map({ currentJob }) {
|
map({ currentJob }) {
|
||||||
|
return { job: currentJob };
|
||||||
|
},
|
||||||
|
getPayload({ params: { id }, job = {} }) {
|
||||||
return {
|
return {
|
||||||
job: currentJob
|
id,
|
||||||
|
isPrimed: job.id === id
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getPayload({ params }) {
|
// using es6 destructuring
|
||||||
return { id: params.id };
|
shouldContainerFetch({ job = {} }, { params: { id } }
|
||||||
},
|
) {
|
||||||
shouldContainerFetch({ currentJob = {} }, { currentJob: nextJob = {}}) {
|
return job.id !== id;
|
||||||
return currentJob.id !== nextJob.id;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
React.createClass({
|
React.createClass({
|
||||||
@ -46,7 +49,7 @@ export default contain(
|
|||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { job } = this.props;
|
const { job = {} } = this.props;
|
||||||
const {
|
const {
|
||||||
logo,
|
logo,
|
||||||
position,
|
position,
|
||||||
|
@ -5,6 +5,29 @@ const debug = debugFactory('freecc:jobs:actions');
|
|||||||
|
|
||||||
export default Actions({
|
export default Actions({
|
||||||
setJobs: null,
|
setJobs: null,
|
||||||
|
// findJob assumes that the job is already in the list of jobs
|
||||||
|
findJob(id) {
|
||||||
|
return oldState => {
|
||||||
|
const { currentJob = {}, jobs = [] } = oldState;
|
||||||
|
// currentJob already set
|
||||||
|
// do nothing
|
||||||
|
if (currentJob.id === id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const foundJob = jobs.reduce((newJob, job) => {
|
||||||
|
if (job.id === id) {
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
return newJob;
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
// if no job found this will be null which is a op noop
|
||||||
|
return foundJob ?
|
||||||
|
Object.assign({}, oldState, { currentJob: foundJob }) :
|
||||||
|
null;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
setError: null,
|
||||||
getJob: null,
|
getJob: null,
|
||||||
getJobs(params) {
|
getJobs(params) {
|
||||||
return { params };
|
return { params };
|
||||||
@ -13,13 +36,28 @@ export default Actions({
|
|||||||
.refs({ displayName: 'JobActions' })
|
.refs({ displayName: 'JobActions' })
|
||||||
.init(({ instance: jobActions, args: [services] }) => {
|
.init(({ instance: jobActions, args: [services] }) => {
|
||||||
jobActions.getJobs.subscribe(() => {
|
jobActions.getJobs.subscribe(() => {
|
||||||
services.read('job', null, null, (err, jobs) => {
|
services.read('jobs', null, null, (err, jobs) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
debug('job services experienced an issue', err);
|
debug('job services experienced an issue', err);
|
||||||
jobActions.setJobs({ jobs: [] });
|
return jobActions.setError({ err });
|
||||||
}
|
}
|
||||||
jobActions.setJobs({ jobs });
|
jobActions.setJobs({ jobs });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jobActions.getJob.subscribe(({ id, isPrimed }) => {
|
||||||
|
// job is already set, do nothing.
|
||||||
|
if (isPrimed) {
|
||||||
|
debug('job is primed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
services.read('jobs', { id }, null, (err, job) => {
|
||||||
|
if (err) {
|
||||||
|
debug('job services experienced an issue', err);
|
||||||
|
return jobActions.setError({ err });
|
||||||
|
}
|
||||||
|
jobActions.setJobs({ currentJob: job });
|
||||||
|
});
|
||||||
|
});
|
||||||
return jobActions;
|
return jobActions;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import { Store } from 'thundercats';
|
import { Store } from 'thundercats';
|
||||||
|
|
||||||
const { setter } = Store;
|
const {
|
||||||
|
createRegistrar,
|
||||||
|
setter,
|
||||||
|
transformer
|
||||||
|
} = Store;
|
||||||
|
|
||||||
export default Store()
|
export default Store()
|
||||||
.refs({ displayName: 'JobsStore' })
|
.refs({ displayName: 'JobsStore' })
|
||||||
.init(({ instance: jobsStore, args: [cat] }) => {
|
.init(({ instance: jobsStore, args: [cat] }) => {
|
||||||
let jobActions = cat.getActions('JobActions');
|
const { setJobs, findJob, setError } = cat.getActions('JobActions');
|
||||||
jobsStore.register(setter(jobActions.setJobs));
|
const register = createRegistrar(jobsStore);
|
||||||
|
register(setter(setJobs));
|
||||||
|
register(transformer(findJob));
|
||||||
|
register(setter(setError));
|
||||||
});
|
});
|
||||||
|
@ -2,8 +2,12 @@ export default function getJobServices(app) {
|
|||||||
const { Job } = app.models;
|
const { Job } = app.models;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'job',
|
name: 'jobs',
|
||||||
read: (req, resource, params, config, cb) => {
|
read: (req, resource, params, config, cb) => {
|
||||||
|
const id = params ? params.id : null;
|
||||||
|
if (id) {
|
||||||
|
return Job.findById(id, cb);
|
||||||
|
}
|
||||||
Job.find({}, (err, jobs) => {
|
Job.find({}, (err, jobs) => {
|
||||||
cb(err, jobs);
|
cb(err, jobs);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user