Skip to content

Commit 8da6f86

Browse files
Merge pull request #87 from tutorcruncher/fix-contractor-details
fix contractor details view
2 parents 352254c + 70e6f75 commit 8da6f86

File tree

6 files changed

+79
-183
lines changed

6 files changed

+79
-183
lines changed

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
"lintfix": "eslint src --fix"
2424
},
2525
"engines": {
26-
"node": "8.x",
27-
"npm": "5.x",
28-
"yarn": "1.10.x"
26+
"node": ">=8",
27+
"npm": ">=5",
28+
"yarn": ">=1.10"
2929
},
3030
"jest": {
3131
"verbose": true,

src/components/contractors/ConDetails.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ const filter_qual_levels = skills => {
99
}
1010
}
1111

12-
const ConDetails = ({contractor, contractor_extra, get_text}) => (
12+
const ConDetails = ({contractor, get_text}) => (
1313
<div className="con-details">
1414
<Markdown content={contractor.primary_description}/>
1515

16-
<DisplayExtraAttrs extra_attributes={contractor_extra && contractor_extra.extra_attributes}/>
17-
<If v={contractor_extra && contractor_extra.skills}>
16+
<DisplayExtraAttrs extra_attributes={contractor.extra_attributes}/>
17+
<If v={contractor.skills}>
1818
<table className="tcs-skills">
1919
<caption>
2020
<h3>{get_text('skills_label')}</h3>
2121
</caption>
2222
<tbody>
23-
{contractor_extra && contractor_extra.skills.map((skill, i) => (
23+
{contractor.skills && contractor.skills.map((skill, i) => (
2424
<tr key={i}>
2525
<th scope="row">{skill.subject}</th>
2626
<td>

src/components/contractors/ConModal.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,47 +11,44 @@ const TRANSITION_TIME = 500
1111
class ConModal extends Component {
1212
constructor (props) {
1313
super(props)
14-
this.con_id = parseInt(this.props.id, 10)
1514
this.state = {
1615
show_enquiry: false,
1716
transition_class: '',
17+
loaded: false,
1818
}
19-
this.get_contractor = this.get_contractor.bind(this)
20-
this.switch_view = this.switch_view.bind(this)
2119
}
2220

23-
get_contractor () {
24-
for (let contractor of this.props.contractors) {
25-
if (contractor.id === this.con_id) {
26-
return {contractor, contractor_extra: this.props.get_contractor_details(contractor)}
27-
}
28-
}
21+
componentDidMount () {
22+
this.props.get_contractor(
23+
parseInt(this.props.id, 10),
24+
c => this.setState({contractor: c, loaded: true})
25+
)
2926
}
3027

31-
switch_view () {
28+
switch_view = () => {
3229
this.setState({transition_class: ' in-trans'})
3330
setTimeout(() => {
3431
this.setState({show_enquiry: !this.state.show_enquiry, transition_class: ''})
3532
}, TRANSITION_TIME)
3633
}
3734

3835
render () {
39-
if (!this.props.got_contractors) {
36+
if (!this.state.loaded) {
4037
return (
4138
<Modal history={this.props.history} title='' config={this.props.config}>
4239
<p>Loading...</p>
4340
</Modal>
4441
)
4542
}
46-
const _con = this.get_contractor()
47-
if (!_con) {
43+
const contractor = this.state.contractor
44+
if (!contractor) {
4845
return (
4946
<Modal history={this.props.history} config={this.props.config} title='Contractor not Found'>
5047
<p>No Contractor found with id {this.props.id}.</p>
5148
</Modal>
5249
)
5350
}
54-
const {contractor, contractor_extra} = _con
51+
5552
return (
5653
<Modal history={this.props.history} title={contractor.name} last_url={this.props.last_url} config={this.props.config}>
5754
<div className="tcs-extra">
@@ -83,9 +80,7 @@ class ConModal extends Component {
8380
config={this.props.config}
8481
mode='con-modal'/>
8582
{/*else:*/}
86-
<ConDetails contractor={contractor}
87-
contractor_extra={contractor_extra}
88-
get_text={this.props.config.get_text}/>
83+
<ConDetails get_text={this.props.config.get_text} contractor={contractor}/>
8984
</IfElse>
9085

9186
</div>

src/components/contractors/Contractors.js

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, { Component } from 'react'
22
import {Link, Route} from 'react-router-dom'
3-
import {slugify} from '../../utils'
3+
import {slugify, sleep} from '../../utils'
44
import {If} from '../shared/Tools'
55
import {Grid, List} from './List'
66
import ConModal from './ConModal'
77
import {SubjectSelect, LocationInput} from './Filters'
88

9-
class Contractors extends Component {
9+
export default class Contractors extends Component {
1010
constructor (props) {
1111
super(props)
1212
this.state = {
@@ -18,14 +18,6 @@ class Contractors extends Component {
1818
last_url: null,
1919
location_str: null,
2020
}
21-
this.update_contractors = this.update_contractors.bind(this)
22-
this.get_contractor_details = this.get_contractor_details.bind(this)
23-
this.set_contractor_details = this.set_contractor_details.bind(this)
24-
this.subject_url = this.subject_url.bind(this)
25-
this.page_url = this.page_url.bind(this)
26-
this.subject_change = this.subject_change.bind(this)
27-
this.location_change = this.location_change.bind(this)
28-
this.submit_location = this.submit_location.bind(this)
2921
}
3022

3123
async componentDidMount () {
@@ -38,38 +30,38 @@ class Contractors extends Component {
3830
await this.update_contractors()
3931
}
4032

41-
subject_url (selected_subject) {
33+
subject_url = selected_subject => {
4234
if (selected_subject) {
4335
return this.props.root.url(`subject/${selected_subject.id}-${slugify(selected_subject.name)}`)
4436
} else {
4537
return this.props.root.url('')
4638
}
4739
}
4840

49-
page_url (new_page) {
41+
page_url = new_page => {
5042
let url = this.subject_url(this.state.selected_subject)
5143
if (new_page > 1) {
5244
url += `${url.substr(-1) === '/' ? '' : '/'}page/${new_page}`
5345
}
5446
return url
5547
}
5648

57-
subject_change (selected_subject) {
49+
subject_change = selected_subject => {
5850
const url = this.subject_url(selected_subject)
5951
this.props.history.push(url)
6052
this.setState({last_url: url})
6153
this.update_contractors(selected_subject)
6254
}
6355

64-
location_change (loc) {
56+
location_change = loc => {
6557
this.setState({location_str: loc})
6658
}
6759

68-
submit_location (location_str) {
60+
submit_location = location_str => {
6961
this.update_contractors(this.state.selected_subject, location_str)
7062
}
7163

72-
async update_contractors (selected_subject, location_str) {
64+
update_contractors = async (selected_subject, location_str) => {
7365
if (!selected_subject) {
7466
const m = this.props.history.location.pathname.match(/subject\/(\d+)/)
7567
const subject_id = m ? parseInt(m[1], 10) : null
@@ -101,20 +93,39 @@ class Contractors extends Component {
10193
}), 0)
10294
}
10395

104-
get_contractor_details (con) {
105-
const state_ref = 'con_extra_' + con.id
106-
const con_extra = this.state[state_ref]
107-
if (con_extra === undefined) {
108-
this.set_contractor_details(con.url, state_ref)
96+
get_contractor = async (contractor_id, set_contractor) => {
97+
98+
const state_ref = `con_extra_${contractor_id}`
99+
let contractor = this.state[state_ref]
100+
if (contractor) {
101+
set_contractor(contractor)
102+
return
103+
}
104+
105+
// make sure update_contractors has finished before getting the contractor to avoid unnecessary requests
106+
while (!this.state.contractor_response) {
107+
await sleep(50)
109108
}
110-
return con_extra
111-
}
112109

113-
async set_contractor_details (url, state_ref) {
114-
this.setState({[state_ref]: null})
115-
const con_details = await this.props.root.requests.get(url)
116-
this.props.config.event_callback('get_contractor_details', con_details)
117-
this.setState({[state_ref]: con_details})
110+
const contractor_summary = this.state.contractor_response.results.find(c => c.id === contractor_id)
111+
let url
112+
if (contractor_summary) {
113+
set_contractor(contractor_summary)
114+
url = contractor_summary.url
115+
} else {
116+
url = `contractors/${contractor_id}`
117+
}
118+
119+
let r = await this.props.root.requests.get(url, null, {expected_statuses: [200, 404]})
120+
if (r.status === 404) {
121+
set_contractor(null)
122+
} else {
123+
contractor = r.data
124+
this.props.config.event_callback('get_contractor_details', contractor)
125+
126+
this.setState({[state_ref]: contractor})
127+
set_contractor(contractor)
128+
}
118129
}
119130

120131
render () {
@@ -194,18 +205,16 @@ class Contractors extends Component {
194205
</div>
195206
</If>
196207
<Route path={this.props.root.url(':id(\\d+):_extra')} render={props => (
197-
<ConModal id={props.match.params.id}
198-
last_url={this.state.last_url}
199-
contractors={this.state.contractor_response && this.state.contractor_response.results}
200-
got_contractors={Boolean(this.state.contractor_response)}
201-
get_contractor_details={this.get_contractor_details}
202-
root={this.props.root}
203-
config={this.props.config}
204-
history={props.history}/>
208+
<ConModal
209+
id={props.match.params.id}
210+
last_url={this.state.last_url}
211+
get_contractor={this.get_contractor}
212+
root={this.props.root}
213+
config={this.props.config}
214+
history={props.history}
215+
/>
205216
)}/>
206217
</div>
207218
)
208219
}
209220
}
210-
211-
export default Contractors

src/utils.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import marked from 'marked'
22

33
marked.setOptions({
44
gfm: true,
5-
sanitize: true,
5+
sanitize: true, // SWITCH to https://github.com/cure53/DOMPurify
66
smartLists: true,
77
})
88

@@ -14,6 +14,10 @@ export const to_markdown = t => {
1414
}
1515
}
1616

17+
export function sleep (ms) {
18+
return new Promise(resolve => setTimeout(resolve, ms))
19+
}
20+
1721
export const auto_url_root = path => {
1822
// remove :
1923
// * /subject/.*

0 commit comments

Comments
 (0)