Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ gem 'jbuilder', '~> 1.2'
gem 'jquery-rails'
gem 'rack-timeout'
gem 'rails', '~> 4.2.0'
gem 'react-rails', '~> 1.0.0.pre', github: 'reactjs/react-rails'
gem 'sass-rails'
gem 'sprockets-es6'
gem 'thin'
gem 'turbolinks'
gem 'uglifier', '>= 1.3.0'
Expand Down
40 changes: 29 additions & 11 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
GIT
remote: git://github.com/reactjs/react-rails.git
revision: b6538ae1b11f7da82a7186929cedc0dcbba10ae3
specs:
react-rails (1.0.0.pre)
coffee-script-source (~> 1.9)
connection_pool
execjs
rails (>= 3.1)
react-source (~> 0.12)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -38,6 +49,10 @@ GEM
tzinfo (~> 1.1)
addressable (2.3.7)
arel (6.0.0)
babel-source (5.1.9)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
bcrypt (3.1.10)
builder (3.2.2)
coderay (1.1.0)
Expand All @@ -47,7 +62,8 @@ GEM
coffee-script (2.3.0)
coffee-script-source
execjs
coffee-script-source (1.9.0)
coffee-script-source (1.9.1)
connection_pool (2.1.3)
daemons (1.1.9)
decent_exposure (2.3.2)
decent_generators (0.0.3)
Expand All @@ -72,7 +88,7 @@ GEM
dotenv (1.0.2)
erubis (2.7.0)
eventmachine (1.0.7)
execjs (2.3.0)
execjs (2.4.0)
factory_girl (4.5.0)
activesupport (>= 3.0.0)
faraday (0.9.1)
Expand All @@ -81,7 +97,7 @@ GEM
foreman (0.77.0)
dotenv (~> 1.0.2)
thor (~> 0.19.1)
globalid (0.3.0)
globalid (0.3.3)
activesupport (>= 4.1.0)
haml (4.0.6)
tilt
Expand All @@ -92,7 +108,6 @@ GEM
html2haml (>= 1.0.1)
railties (>= 4.0.1)
hashie (3.4.0)
hike (1.2.3)
html2haml (2.0.0)
erubis (~> 2.7.0)
haml (~> 4.0.0)
Expand All @@ -117,7 +132,7 @@ GEM
mime-types (2.4.3)
mini_portile (0.6.2)
minitest (5.5.1)
multi_json (1.10.1)
multi_json (1.11.0)
multi_xml (0.5.5)
multipart-post (2.0.0)
newrelic_rpm (3.10.0.279)
Expand Down Expand Up @@ -173,7 +188,7 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
railties (4.2.0)
actionpack (= 4.2.0)
Expand All @@ -182,6 +197,7 @@ GEM
thor (>= 0.18.1, < 2.0)
raindrops (0.13.0)
rake (10.4.2)
react-source (0.13.0)
responders (2.1.0)
railties (>= 4.2.0, < 5)
rspec (3.2.0)
Expand Down Expand Up @@ -225,11 +241,11 @@ GEM
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
slop (3.6.0)
sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
sprockets (3.0.1)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-es6 (0.6.0)
babel-transpiler
sprockets (~> 3.0.0.beta)
sprockets-rails (2.2.4)
actionpack (>= 3.0)
activesupport (>= 3.0)
Expand All @@ -239,7 +255,7 @@ GEM
eventmachine (~> 1.0)
rack (~> 1.0)
thor (0.19.1)
thread_safe (0.3.4)
thread_safe (0.3.5)
tilt (1.4.1)
turbolinks (2.5.3)
coffee-rails
Expand Down Expand Up @@ -288,10 +304,12 @@ DEPENDENCIES
pry-rails
rack-timeout
rails (~> 4.2.0)
react-rails (~> 1.0.0.pre)!
rspec
rspec-rails
sass-rails
shoulda-matchers
sprockets-es6
thin
turbolinks
twitter-bootstrap-rails
Expand Down
3 changes: 3 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@
//= require turbolinks
//= require mousetrap-1.4.6
//= require fastclick-1.0.6
//= require react
//= require components
//= require react_ujs
//= require_tree .
27 changes: 0 additions & 27 deletions app/assets/javascripts/checklists.js

This file was deleted.

1 change: 1 addition & 0 deletions app/assets/javascripts/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//= require_tree ./components
Empty file.
18 changes: 18 additions & 0 deletions app/assets/javascripts/components/checklist.js.es6.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var Checklist = React.createClass({
render() {
return (
<div>
<h3><a href={this.props.repository_path}>{this.props.github_repository_full_name}</a></h3>
<h3>{this.props.name}</h3>
<div className="row">
<div className="col-xs-10">
<a href={this.props.edit_path}>Edit</a> | <a href={this.props.index_path}>Back</a>
</div>
</div>
<ChecklistItems items={this.props.items} checklist={this.props} />
</div>
);
}
})

window.Checklist = Checklist
66 changes: 66 additions & 0 deletions app/assets/javascripts/components/checklist_item.js.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
window.ChecklistItem = React.createClass({
removeLink: function() { return React.findDOMNode(this.refs.removeLink); },
row: function() { return React.findDOMNode(this.refs.row); },

componentDidMount: function() {
var self = this;

$(this.removeLink()).on('ajax:success.ChecklistItem', function() {
$(self.row()).slideUp('slow', function() { self.removeItem(this.state.item.id) })
});
},

componentWillUnmount: function() {
$(this.removeLink()).off('ajax:success.ChecklistItem')
},

formAjaxSuccess: function(newItem) {
this.toggleEditMode();
this.setState({item: newItem});
},

getInitialState: function() {
return { item: this.props.item };
},

currentlyInEditMode: function() {
return this.props.editModeIdx === this.props.idx;
},

handleRowClick: function(e) {
if(!$(e.target).is('input, a')) {
this.toggleEditMode();
}
},

toggleEditMode: function() {
this.props.updateEditModeIdx(this.currentlyInEditMode() ? -1 : this.props.idx);
},

render: function() {
var name = (
<div>
<div className="col-xs-6 col-md-4">
<div className="checklist-item-name" data-edit-prompt="Edit">
<span className="name">{this.state.item.name}</span>
</div>
</div>
<div className="col-xs-2 col-md-1">
</div>
</div>
);

var form = (
<ChecklistItemForm ref="form" method="patch" item={this.state.item} formClass="edit_checklist_item" formAjaxSuccess={this.formAjaxSuccess} focus={this.currentlyInEditMode()} />
)

return (
<div className="row" onClick={this.handleRowClick} ref="row">
{this.currentlyInEditMode() ? form : name}
<div className="col-xs-2 col-md-5">
<a ref="removeLink" href={this.state.item.path} className="destroy-checklist-item btn btn-danger btn-sm" data-method="delete" data-remote="true" data-disable="true" data-comfortable-text="Remove" data-abbreviated-text="X"></a>
</div>
</div>
);
}
})
50 changes: 50 additions & 0 deletions app/assets/javascripts/components/checklist_item_form.js.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
window.ChecklistItemForm = React.createClass({
formElement: function() { return React.findDOMNode(this.refs.form); },

componentDidMount: function() {
var self = this;

$(this.formElement()).on('ajax:success.ChecklistItem', function(e, newItem) {
self.props.formAjaxSuccess(newItem)
}).on('ajax:error.ChecklistItem', function(e, xhr) {
alert(xhr.responseText)
});
},

componentWillUnmount: function() {
$(this.formElement()).off('ajax:success.ChecklistItem').off('ajax:error.ChecklistItem')
},

getInitialState: function() {
return { formName: this.props.item.name }
},

componentWillReceiveProps: function(newProps) {
this.setState({ formName: newProps.item.name })
},

handleFormChange: function(e) {
this.setState({ formName: e.target.value });
},

componentDidUpdate: function() {
if (this.props.focus) {
React.findDOMNode(this.refs.focusField).focus();
}
},

render: function() {
return (
<form method="POST" data-remote="true" action={this.props.item.path} className={this.props.formClass} acceptCharset="UTF-8" ref="form">
<div className="col-xs-6 col-md-4">
<input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="_method" value={this.props.method} />
<input className='form-control' type="text" name="checklist_item[name]" id="checklist_item_name" placeholder={this.props.placeholder} value={this.state.formName} onChange={this.handleFormChange} ref="focusField" />
</div>
<div className="col-xs-2 col-md-1">
<input type="submit" value="Save" data-disable-with="Saving.." className="btn btn-primary btn-sm" />
</div>
</form>
);
}
})
40 changes: 40 additions & 0 deletions app/assets/javascripts/components/checklist_items.js.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
window.ChecklistItems = React.createClass({
getInitialState: function() {
return { editModeIdx: -1, items: this.props.items };
},

updateEditModeIdx: function(newIdx) {
this.setState({ editModeIdx: newIdx })
},

addChecklistItem: function(newItem) {
var newItems = this.state.items.slice(0);
newItems.push(newItem);
this.setState({ items: newItems, newItemFormName: '' });
},

removeItem: function(itemId) {
this.setState({items: items.filter(function(i) { return i.id !== itemId }) });
},

render: function() {
var self = this;
return (
<div className="checklist-items">
<div className="row">
<div className="col-xs-10">
<h4>Item</h4>
</div>
</div>
{
this.state.items.map(function(item, idx) {
return <ChecklistItem key={item.id} idx={idx} item={item} updateEditModeIdx={self.updateEditModeIdx} editModeIdx={self.state.editModeIdx} addChecklistItem={self.addChecklistItem} removeItem={self.removeItem} />;
})
}
<div className="row">
<ChecklistItemForm placeholder="New Item" method="post" item={{name: this.state.newItemFormName, path: this.props.checklist.create_item_path}} editMode={true} formClass="new_checklist_item" formAjaxSuccess={this.addChecklistItem} />
</div>
</div>
);
}
})
7 changes: 7 additions & 0 deletions app/assets/javascripts/components/react_test.js.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});

window.HelloMessage = HelloMessage
29 changes: 9 additions & 20 deletions app/assets/stylesheets/checklists.sass
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,17 @@
.btn
vertical-align: middle

.edit_checklist_item
[data-edit-control]
display: none
.checklist-item-name
&:after
content: attr(data-edit-prompt)
margin-left: 5px
color: grey

&[data-edit-mode]
[data-edit-control]
display: block
.name
@media (min-width: 768px)
&:after
display: none

&:not([data-edit-mode])
.checklist-item-name
&:after
content: attr(data-edit-prompt)
margin-left: 5px
color: grey

@media (min-width: 768px)
&:after
display: none
&:hover:after
display: inline
&:hover:after
display: inline

[data-comfortable-text]
@media (max-width: 767px)
Expand Down
Loading