Created
February 3, 2015 13:39
-
-
Save stimms/bae36ad20470cb65d63a to your computer and use it in GitHub Desktop.
Code review of React.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.Actions = Marty.createActionCreators({ | |
list: Prime.BHAComponents.Events.List(), | |
receiveComponents: Prime.BHAComponents.Events.ReceiveComponents(), | |
fetchCandidates: Prime.BHAComponents.Events.FetchCandidates(), | |
receiveCandidates: Prime.BHAComponents.Events.ReceiveCandidates(), | |
openCopyDialog: Prime.BHAComponents.Events.OpenCopyDialog(), | |
closeCopyDialog: Prime.BHAComponents.Events.CloseCopyDialog(), | |
openAddDialog: Prime.BHAComponents.Events.OpenAddDialog(), | |
closeAddDialog: Prime.BHAComponents.Events.CloseAddDialog(), | |
setCopySource: Prime.BHAComponents.Events.SetCopySource(), | |
copy: Prime.BHAComponents.Events.Copy(), | |
copyFailure: Prime.BHAComponents.Events.CopyFailure(), | |
fetchAvailableComponents: Prime.BHAComponents.Events.FetchAvailableComponents(), | |
receiveAvailableComponents: Prime.BHAComponents.Events.ReceiveAvailableComponents(), | |
selectListedComponent: Prime.BHAComponents.Events.SelectListedComponent(), | |
selectUnlistedComponent: Prime.BHAComponents.Events.SelectUnlistedComponent(), | |
fetchComponentDetails: Prime.BHAComponents.Events.FetchComponentDetails(), | |
receiveComponentDetails: Prime.BHAComponents.Events.ReceiveComponentDetails() | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.Index = class Index{ | |
constructor(container, jobId, bhaId){ | |
React.render( | |
/*jshint ignore:start*/ | |
<div> | |
<Prime.BHAComponents.CurrentComponentsTable bhaId={bhaId} jobId={jobId}/> | |
<Prime.BHAComponents.NewComponentButton/> | |
<Prime.BHAComponents.CopyBHAButton/> | |
<Prime.BHAComponents.CopyBHADialog jobId={jobId} bhaId={bhaId}/> | |
<Prime.BHAComponents.AddDialog jobId={jobId} bhaId={bhaId}/> | |
</div>, | |
/*jshint ignore:end*/ | |
container[0] | |
); | |
} | |
}; | |
Prime.BHAComponents.NewComponentButton = React.createClass({ | |
render: function(){ | |
return( | |
/*jshint ignore:start*/ | |
<span className="butt" onClick={this.add}>Add Components</span> | |
/*jshint ignore:end*/ | |
); | |
}, | |
add: function(){ | |
Prime.BHAComponents.Actions.openAddDialog(); | |
} | |
}); | |
Prime.BHAComponents.CopyBHAButton = React.createClass({ | |
render: function(){ | |
return( | |
/*jshint ignore:start*/ | |
<span className="butt" onClick={this.copy}>Copy BHA Components</span> | |
/*jshint ignore:end*/ | |
); | |
}, | |
copy: function(){ | |
Prime.BHAComponents.Actions.openCopyDialog(); | |
} | |
}); | |
Prime.BHAComponents.CopyBHADialog = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
/*jshint ignore: start*/ | |
if(this.state.copyDialogOpen) | |
{ | |
var copyFailure; | |
if(this.state.copyFailure) | |
{ | |
copyFailure = <div className="error">Unable to copy components as this BHA has hours assigned to it</div>; | |
} | |
return( <div className="copyDialog"> | |
<span>Select a BHA from which to copy components</span> | |
{copyFailure} | |
<Prime.BHAComponents.CopySourceDropDown jobId={this.props.jobId} state={this.state} /> | |
<span className="butt" onClick={this.copy}>Copy BHA Components</span> | |
<span className="butt" onClick={this.closeCopyDialog}>Cancel</span> | |
</div>); | |
} | |
return <div></div>; | |
/*jshint ignore: end*/ | |
}, | |
closeCopyDialog: function(){ | |
Prime.BHAComponents.Actions.closeCopyDialog(); | |
}, | |
copy: function(){ | |
Prime.BHAComponents.Actions.copy(this.props.bhaId); | |
} | |
}); | |
Prime.BHAComponents.CopySourceDropDown = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
var me = this; | |
var body = this.state.copyCandidates.when({ | |
pending: function(){ | |
/*jshint ignore: start*/ | |
return <span>Loading candidate jobs...</span>; | |
/*jshint ignore: end*/ | |
}, | |
failed: function(error){ | |
/*jshint ignore:start*/ | |
return <div>oh snap! {error.message}</div>; | |
/*jshint ignore:end*/ | |
}, | |
done: function(candidates){ | |
var options = candidates.map((candidate) => { | |
/*jshint ignore: start*/ | |
return <option key={candidate.id} value={candidate.id}>{candidate.name}</option>; | |
/*jshint ignore: end*/ | |
}); | |
/*jshint ignore: start*/ | |
return <select onChange={me.updateCopySource} placeholder="Job and BHA">{options}</select>; | |
/*jshint ignore: end*/ | |
}, | |
}, this); | |
/*jshint ignore: start*/ | |
return <div>{body}</div>; | |
/*jshint ignore: end*/ | |
}, | |
updateCopySource: function(e) | |
{ | |
Prime.BHAComponents.Actions.setCopySource(e.currentTarget.value); | |
} | |
}); | |
Prime.BHAComponents.AddDialog = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
/*jshint ignore: start*/ | |
if(this.state.addDialogOpen) | |
return <div className="addDialog"> | |
<Prime.BHAComponents.AddAutoComplete jobId={this.props.jobId}/> | |
<Prime.BHAComponents.AddUnlistedDetails /> | |
<Prime.BHAComponents.AddListedDetails itemId={this.state.addItem.id} type={this.state.addItem.state}/> | |
</div>; | |
return <div></div>; | |
/*jshint ignore: end*/ | |
} | |
}); | |
Prime.BHAComponents.AddAutoComplete = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
var body = this.state.availableComponents.when({ | |
pending:function(){ | |
/*jshint ignore: start*/ | |
return <div>Loading components</div>; | |
/*jshint ignore: end*/ | |
}, | |
failed: function(error){ | |
/*jshint ignore: start*/ | |
return <div>Unable to load components {error}</div>; | |
/*jshint ignore: end*/ | |
}, | |
done: function(){ | |
/*jshint ignore: start*/ | |
return <div>Serial Number: | |
<input type="text" className="autocomplete" name="addSerialNumber"></input> | |
</div>; | |
/*jshint ignore: end*/ | |
}}, this); | |
/*jshint ignore: start*/ | |
return <div>{body}</div>; | |
/*jshint ignore: end*/ | |
}, | |
componentDidMount: function(){ | |
var node = $(this.getDOMNode()).find("[name=addSerialNumber]"); | |
$.widget( "custom.catcomplete", $.ui.autocomplete, { | |
_create: function() { | |
this._super(); | |
this.widget().menu( "option", "items", "> :not(.ui-autocomplete-category)" ); | |
}, | |
_renderMenu: function( ul, items ) { | |
var that = this, | |
currentCategory = ""; | |
$.each( items, function( index, item ) { | |
var li; | |
if ( item.type != currentCategory ) { | |
ul.append( "<li class='ui-autocomplete-category'>" + item.type + "</li>" ); | |
currentCategory = item.type; | |
} | |
li = that._renderItemData( ul, item ); | |
if ( item.category ) { | |
li.attr( "aria-label", item.category + " : " + item.label ); | |
} | |
}); | |
} | |
}); | |
node.catcomplete({source: _.sortBy(_.map(this.state.availableComponents.result, (item) =>({ | |
'label': item.description, | |
'type': item.type, | |
'id': item.id | |
})), (item)=>item.type), | |
select: this.select, | |
change: this.change | |
}); | |
}, | |
select: function(event, ui){ | |
Prime.BHAComponents.Actions.selectListedComponent(ui.item.id, ui.item.type); | |
}, | |
change: function(event, ui){ | |
if(!ui.item) | |
Prime.BHAComponents.Actions.selectUnlistedComponent($(event.target).val()); | |
} | |
}); | |
Prime.BHAComponents.AddListedDetails = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
/*jshint ignore: start*/ | |
var fetchedDetails = this.state.fetchComponentDetails.when({ | |
pending:function(){ | |
return <div>Loading details</div>; | |
}, | |
error: function(error){ | |
return <div>Loading details error {error}</div>; | |
}, | |
done: function(){ | |
return <div>Loading details done</div>; | |
} | |
}); | |
if(this.state.addItem.id) | |
return (<div> | |
<Prime.BHAComponents.ItemNumber/> | |
{fetchedDetails} | |
</div>); | |
return <div></div>; | |
/*jshint ignore: end*/ | |
} | |
}); | |
Prime.BHAComponents.AddUnlistedDetails = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
/*jshint ignore: start*/ | |
if(this.state.addItem.serialNumber) | |
return (<div> | |
<Prime.BHAComponents.ItemNumber/> | |
<label>Type</label> | |
<span>{this.state.addItem.type}</span> | |
</div>); | |
return <div></div>; | |
/*jshint ignore: end*/ | |
} | |
}); | |
Prime.BHAComponents.ItemNumber = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
/*jshint ignore: start*/ | |
var itemNumberOptions = this.state.components.result.map((component) => { | |
return <option key={component.itemNumber} value={component.itemNumber}>{component.itemNumber}</option>; | |
}); | |
var finalPosition = this.state.components.result.length + 1; | |
itemNumberOptions.push( | |
<option key={finalPosition} value={finalPosition}>{finalPosition}</option> | |
); | |
return (<div> | |
<label>Item Number</label> | |
<select>{itemNumberOptions}</select> | |
</div>); | |
/*jshint ignore: end*/ | |
} | |
}); | |
Prime.BHAComponents.CurrentComponentsTable = React.createClass({ | |
mixins: [Prime.BHAComponents.State], | |
render: function(){ | |
var body = this.state.components.when({ | |
pending: function(){ | |
/*jshint ignore:start*/ | |
return <div>Loading...</div>; | |
/*jshint ignore:end*/ | |
}, | |
failed: function(error){ | |
/*jshint ignore:start*/ | |
return <div>oh snap! {error.message}</div>; | |
/*jshint ignore:end*/ | |
}, | |
done: function(components){ | |
return( | |
/*jshint ignore:start*/ | |
<table className="tbl"> | |
<thead> | |
<tr> | |
<th></th> | |
<th>Item No.</th> | |
<th>Type</th> | |
<th>Vendor</th> | |
<th>Description</th> | |
<th>Serial Number</th> | |
<th>OD</th> | |
<th>ID</th> | |
<th>Connection</th> | |
<th>Length</th> | |
<th>Cumulative Length</th> | |
<th></th> | |
</tr> | |
</thead> | |
<tbody> | |
<Prime.BHAComponents.CurrentComponentsTableRows components={components} /> | |
</tbody> | |
</table> | |
/*jshint ignore:end*/ | |
); | |
} | |
}); | |
/*jshint ignore:start*/ | |
return <div>{body}</div>; | |
/*jshint ignore:end*/ | |
} | |
}); | |
Prime.BHAComponents.CurrentComponentsTableRows = React.createClass({ | |
render: function(){ | |
var rows = this.props.components.map((component) => { | |
return( | |
/*jshint ignore:start*/ | |
<tr key={component.id}> | |
<td><span className="pseudolink" onClick={this.editComponent.bind(this, component.id)}>Edit</span></td> | |
<td>{component.itemNumber}</td> | |
<td>{component.type}</td> | |
<td>{component.vendor}</td> | |
<td>{component.description}</td> | |
<td>{component.serialNumber}</td> | |
<td>{component.outerDiameter}</td> | |
<td>{component.innerDiameter}</td> | |
<td>{component.connection}</td> | |
<td>{component.length}</td> | |
<td>{component.cumulativeLength}</td> | |
<td><span className="pseudolink" onClick={this.deleteComponent.bind(this, component.id)}>Delete</span></td> | |
</tr> | |
/*jshint ignore:end*/ | |
); | |
}); | |
return ( | |
/*jshint ignore:start*/ | |
<tbody> | |
{rows} | |
</tbody> | |
/*jshint ignore:end*/ | |
); | |
}, | |
editComponent: function(id){ | |
console.log("edit" + id); | |
}, | |
deleteComponent: function(id){ | |
console.log("delete" + id); | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.Events = Marty.createConstants([ | |
"List", | |
"ReceiveComponents", | |
"FetchCandidates", | |
"ReceiveCandidates", | |
"ComponentAdded", | |
"ComponentMovedUp", | |
"ComponentMovedDown", | |
"ComponentRemoved", | |
"ComponentEdited", | |
"OpenCopyDialog", | |
"CloseCopyDialog", | |
"SetCopySource", | |
"Copy", | |
"CopyFailure", | |
"OpenAddDialog", | |
"CloseAddDialog", | |
"FetchAvailableComponents", | |
"ReceiveAvailableComponents", | |
"SelectListedComponent", | |
"SelectUnlistedComponent", | |
"FetchComponentDetails", | |
"ReceiveComponentDetails" | |
]); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.State = Marty.createStateMixin({ | |
listenTo: [Prime.BHAComponents.Store], | |
getState: function() { | |
return { | |
components: Prime.BHAComponents.Store.list(this.props.bhaId), | |
copyCandidates: Prime.BHAComponents.Store.fetchCandidates(this.props.jobId), | |
copyDialogOpen: Prime.BHAComponents.Store.state.copyDialogOpen, | |
copySource: Prime.BHAComponents.Store.state.copySource, | |
bhaId: Prime.BHAComponents.Store.state.bhaId, | |
copyFailure: Prime.BHAComponents.Store.state.copyFailure, | |
addDialogOpen: Prime.BHAComponents.Store.state.addDialogOpen, | |
availableComponents: Prime.BHAComponents.Store.fetchAvailableComponents(this.props.jobId), | |
addItem: Prime.BHAComponents.Store.state.addItem, | |
fetchComponentDetails: Prime.BHAComponents.Store.fetchComponentDetails(this.props.itemId, this.props.type) | |
}; | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.StateSource = Marty.createStateSource({ | |
type: 'http', | |
baseUrl: '/BHAComponents', | |
list: function(bhaId){ | |
return this.get('/?bhaId=' + bhaId).then(function(res){ | |
return Prime.BHAComponents.Actions.receiveComponents(res.body); | |
}); | |
}, | |
fetchCandidates: function(jobId) | |
{ | |
return this.get("/CopyCandidates/?jobId=" + jobId).then(function(res){ | |
return Prime.BHAComponents.Actions.receiveCandidates(res.body); | |
}, function(result) | |
{ | |
console.log("Failure in fetching candidates"); | |
console.dir(result); | |
}); | |
}, | |
copy: function(sourceBHAId, destinationBHAId) | |
{ | |
return this.post('/copy?sourceBHAId=' + sourceBHAId + '&destinationBHAId=' + destinationBHAId).then(function(){ | |
Prime.BHAComponents.Actions.list(destinationBHAId); | |
}, function(result){ | |
Prime.BHAComponents.Actions.copyFailure(); | |
}); | |
}, | |
fetchAvailableComponents: function(jobId){ | |
return this.get("/AvailableCandidates/?jobId=" + jobId).then(function(res){ | |
return Prime.BHAComponents.Actions.receiveAvailableComponents(res.body); | |
}, | |
function(result){ | |
console.log("Failed to fetch avaialble components"); | |
console.dir(result); | |
}); | |
}, | |
fetchComponentDetails: function(id, type){ | |
return this.get("/ComponentDetails/?id=" + id + "&type=" + type).then(function(res){ | |
return Prime.BHAComponents.Actions.receiveComponentDetails(res.body); | |
}, | |
function(result){ | |
console.log("Failed to fetch component details"); | |
console.dir(result); | |
}); | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Prime = Prime || {}; | |
Prime.BHAComponents = Prime.BHAComponents || {}; | |
Prime.BHAComponents.Store = Marty.createStore({ | |
handlers: { | |
list: Prime.BHAComponents.Events.List, | |
receiveComponents: Prime.BHAComponents.Events.ReceiveComponents, | |
openCopyDialog: Prime.BHAComponents.Events.OpenCopyDialog, | |
closeCopyDialog: Prime.BHAComponents.Events.CloseCopyDialog, | |
fetchCandidates: Prime.BHAComponents.Events.FetchCandidates, | |
receiveCandidates: Prime.BHAComponents.Events.ReceiveCandidates, | |
setCopySource: Prime.BHAComponents.Events.SetCopySource, | |
copy: Prime.BHAComponents.Events.Copy, | |
copyFailure: Prime.BHAComponents.Events.CopyFailure, | |
openAddDialog: Prime.BHAComponents.Events.OpenAddDialog, | |
fetchAvailableComponents: Prime.BHAComponents.Events.FetchAvailableComponents, | |
receiveAvailableComponents: Prime.BHAComponents.Events.ReceiveAvailableComponents, | |
selectListedComponent: Prime.BHAComponents.Events.SelectListedComponent, | |
selectUnlistedComponent: Prime.BHAComponents.Events.SelectUnlistedComponent, | |
fetchComponentDetails: Prime.BHAComponents.Events.FetchComponentDetails, | |
receiveComponentDetails: Prime.BHAComponents.Events.ReceiveComponentDetails | |
/*componentAdded: Prime.BHAComponents.Events.ComponentAdded, | |
componentMovedUp: Prime.BHAComponents.Events.ComponentMovedUp, | |
componentMovedDown: Prime.BHAComponents.Events.ComponentMovedDown, | |
componentRemoved: Prime.BHAComponents.Events.ComponentRemoved, | |
componentEdited: Prime.BHAComponents.Events.ComponentEdited*/ | |
}, | |
getInitialState: function(){ | |
return { | |
components: [], | |
copyDialogOpen: false, | |
copySource: null, | |
bhaId: null, | |
copying: null, | |
copyFailure: false, | |
addDialogOpen: false, | |
addItem: { | |
id: null, | |
type: null, | |
serialNumber: null | |
} | |
}; | |
}, | |
list: function(bhaId){ | |
return this.fetch({ | |
id: 'list-components', | |
locally: function(){ | |
if(this.hasAlreadyFetched('list-components') && !this.state.copying) | |
return this.state.components; | |
}, | |
remotely: function(){ | |
this.state.bhaId = bhaId; | |
this.state.copying = false; | |
return Prime.BHAComponents.StateSource.list(bhaId); | |
} | |
}); | |
}, | |
receiveComponents: function(components){ | |
this.state.components= components; | |
this.hasChanged(); | |
}, | |
openCopyDialog: function(){ | |
this.state.copyDialogOpen= true; | |
this.hasChanged(); | |
}, | |
closeCopyDialog: function(){ | |
this.state.copyDialogOpen= false; | |
this.hasChanged(); | |
}, | |
setCopySource: function(sourceBHAId){ | |
this.state.copySource = sourceBHAId; | |
this.hasChanged(); | |
}, | |
fetchCandidates: function(jobId){ | |
return this.fetch({ | |
id: 'fetch-candidates', | |
locally: function(){ | |
if(this.hasAlreadyFetched('fetch-candidates')) | |
return this.state.candidates; | |
}, | |
remotely: function(){ | |
return Prime.BHAComponents.StateSource.fetchCandidates(jobId); | |
} | |
}); | |
}, | |
receiveCandidates: function(candidates){ | |
this.state.candidates = candidates; | |
if(candidates && candidates.length>0) | |
this.state.copySource = candidates[0].id; | |
this.hasChanged(); | |
}, | |
fetchAvailableComponents: function(jobId){ | |
return this.fetch({ | |
id: 'fetch-available', | |
locally: function(){ | |
if(this.hasAlreadyFetched('fetch-available')) | |
return this.state.availableComponents; | |
}, | |
remotely: function(){ | |
return Prime.BHAComponents.StateSource.fetchAvailableComponents(jobId); | |
} | |
}); | |
}, | |
receiveAvailableComponents: function(components){ | |
this.state.availableComponents = components; | |
this.hasChanged(); | |
}, | |
copy: function(destinationBHAId){ | |
this.state.copying = true; | |
var bhaId = destinationBHAId; | |
return this.fetch({ | |
id: 'copy-bha-' + this.state.copySource + "-" + this.state.bhaId, | |
locally: function(){ | |
if(this.hasAlreadyFetched('copy-bha-' + this.state.copySource + "-" + this.state.bhaId)) | |
return this.state.candidates; | |
}, | |
remotely: function(){ | |
return Prime.BHAComponents.StateSource.copy(this.state.copySource, this.state.bhaId); | |
} | |
}); | |
}, | |
copyFailure: function(){ | |
this.state.copyFailure = true; | |
}, | |
openAddDialog: function(){ | |
this.state.addDialogOpen= true; | |
this.hasChanged(); | |
}, | |
closeAddDialog: function(){ | |
this.state.addDialogOpen= false; | |
this.hasChanged(); | |
}, | |
selectListedComponent: function(id, type){ | |
this.state.addItem = {id: id, type: type, serialNumber: null}; | |
this.hasChanged(); | |
}, | |
selectUnlistedComponent: function(serialNumber){ | |
this.state.addItem = { | |
id: null, | |
type: null, | |
serialNumber: serialNumber | |
}; | |
this.hasChanged(); | |
}, | |
fetchComponentDetails: function(id, type){ | |
return this.fetch({ | |
id: 'component-details-' + this.state.addItem.id + "-" + this.state.addItem.type, | |
locally: function(){ | |
if(!this.state.addItem.id || this.hasAlreadyFetched('component-details-' + this.state.addItem.id + "-" + this.state.addItem.type)) | |
return this.state.addItem; | |
}, | |
remotely: function(){ | |
return Prime.BHAComponents.StateSource.fetchComponentDetails(this.state.addItem.id, this.state.addItem.type); | |
} | |
}); | |
}, | |
receiveComponentDetails: function(details){ | |
this.state.addItem = { id: details.id, type: details.type, serialNumber: details.serialNumber, vendor: details.vendor}; | |
this.hasChanged(); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looks good overall. I'll have to take a closer look at Marty. The State Source idea seems interesting.
How's do you like React now that you've used it?