diff --git a/app/assets/javascripts/components/add_domain.js.jsx b/app/assets/javascripts/components/add_domain.js.jsx index 0fff314ee..7de890077 100644 --- a/app/assets/javascripts/components/add_domain.js.jsx +++ b/app/assets/javascripts/components/add_domain.js.jsx @@ -80,7 +80,7 @@ var NewDomainTransfer = React.createClass({ -
+
@@ -122,7 +122,7 @@ var DomainPurchaseApplication = React.createClass({
-
+
diff --git a/app/assets/javascripts/components/admin/admin_withholding.js.jsx b/app/assets/javascripts/components/admin/admin_withholding.js.jsx new file mode 100644 index 000000000..3ecfaaaf0 --- /dev/null +++ b/app/assets/javascripts/components/admin/admin_withholding.js.jsx @@ -0,0 +1,31 @@ +var AdminWithholding = React.createClass({ + render() { + return ( + + Adjust withholding + + ) + }, + + handleClick() { + var amount = prompt('New withholding amount', this.props.amount_withheld / 100) + if (amount) { + $.ajax({ + type: "PATCH", + url: `/admin/withdrawals/${this.props.id}`, + dataType: 'json', + data: { + amount_withheld: amount + }, + success: this.amountUpdated + }) + } + }, + + amountUpdated() { + window.location.reload() + return true + } +}) + +module.exports = window.AdminWithholding = AdminWithholding diff --git a/app/assets/javascripts/components/bounty.js.jsx b/app/assets/javascripts/components/bounty.js.jsx index cd9956984..778b3120f 100644 --- a/app/assets/javascripts/components/bounty.js.jsx +++ b/app/assets/javascripts/components/bounty.js.jsx @@ -107,6 +107,9 @@ let Bounty = React.createClass({ }, getBounty() { + if (!this.isMounted()) { + return + } let bounty = BountyStore.getBounty(); this.setState({ diff --git a/app/assets/javascripts/components/bounty_breakdown.js.jsx b/app/assets/javascripts/components/bounty_breakdown.js.jsx index ead52b88d..5a56de918 100644 --- a/app/assets/javascripts/components/bounty_breakdown.js.jsx +++ b/app/assets/javascripts/components/bounty_breakdown.js.jsx @@ -1,106 +1,100 @@ -(function() { - var Lightbox = require('./lightbox.js.jsx') - var SimpleBountyOffer = require('./simple_bounty_offer.js.jsx') - var UserStore = require('../stores/user_store') - - var BountyBreakdown = React.createClass({ - mixins: [React.addons.LinkedStateMixin], - - getInitialState: function() { - return { - offers: this.props.offers, - offer: this.props.steps[2], - currentUser: UserStore.getUser() - }; - }, - - render: function() { - return ( - -
- - - Close - - -
- How many coins is this bounty worth? -
+'use strict'; + +var Lightbox = require('./lightbox.js.jsx') +var SimpleBountyOffer = require('./simple_bounty_offer.js.jsx') +var UserStore = require('../stores/user_store') + +var BountyBreakdown = React.createClass({ + mixins: [React.addons.LinkedStateMixin], + + getInitialState: function() { + return { + offers: this.props.offers, + offer: this.props.steps[2], + currentUser: UserStore.getUser() + }; + }, + + render: function() { + return ( + +
+ + + Close + + +
+ How many coins is this bounty worth?
+
-
- {this.state.currentUser ? this.renderNewOffer() : null} -
+
+ {this.state.currentUser ? this.renderNewOffer() : null} +
- {this.state.currentUser ? this.renderActions() : null} -
- ) - }, + {this.state.currentUser ? this.renderActions() : null} + + ) + }, - componentDidMount: function() { - var modal = $(this.getDOMNode()).modal({ show: true }) - modal.on('hidden.bs.modal', this.props.onHidden) + componentDidMount: function() { + var modal = $(this.getDOMNode()).modal({ show: true }) + modal.on('hidden.bs.modal', this.props.onHidden) - var product = app.currentAnalyticsProduct(); + var product = app.currentAnalyticsProduct(); + + if (product) { + analytics.track('bounty.valuation.view', { product: app.currentAnalyticsProduct().get('product_slug') }); + } else { + analytics.track('bounty.valuation.view'); + } + }, + + renderNewOffer: function() { + return ; + }, + + renderActions: function() { + return
+
+ + {' '} + {numeral(this.state.offer).format('0,0')} +
- if (product) { - analytics.track('bounty.valuation.view', { product: app.currentAnalyticsProduct().get('product_slug') }); - } else { - analytics.track('bounty.valuation.view'); + +
+ }, + + handleOfferChanged: function(event) { + this.setState({ + offer: event.target.value + }) + }, + + handleOfferClicked: function() { + window.xhr.post( + this.props.offers_url, + { earnable: this.state.offer }, + function(data) { + window.location.reload() } - }, - - renderNewOffer: function() { - return VoteBountyOffer( - _.extend({}, this.props, { - onChange: this.handleOfferChanged, - user: this.state.currentUser - }) - ); - }, - - renderActions: function() { - return
-
- - {' '} - {numeral(this.state.offer).format('0,0')} -
+ ) - -
- }, - - handleOfferChanged: function(event) { - this.setState({ - offer: event.target.value - }) - }, - - handleOfferClicked: function() { - window.xhr.post( - this.props.offers_url, - { earnable: this.state.offer }, - function(data) { - window.location.reload() - } - ) - - return false - }, - - handleShowDetailsClicked: function() { - this.setState({ - showingDetails: !this.state.showingDetails - }) - - return false - } - }); + return false + }, + + handleShowDetailsClicked: function() { + this.setState({ + showingDetails: !this.state.showingDetails + }) - if (typeof module !== 'undefined') { - module.exports = BountyBreakdown; + return false } +}); - window.BountyBreakdown = BountyBreakdown; -})(); +module.exports = window.BountyBreakdown = BountyBreakdown; diff --git a/app/assets/javascripts/components/bounty_list_item.js.jsx b/app/assets/javascripts/components/bounty_list_item.js.jsx index a3be69f90..53a2dbd7d 100644 --- a/app/assets/javascripts/components/bounty_list_item.js.jsx +++ b/app/assets/javascripts/components/bounty_list_item.js.jsx @@ -113,8 +113,8 @@ var BountyListItem = React.createClass({
-
-
+
+
{this.renderTitle()}
@@ -206,9 +206,9 @@ var BountyListItem = React.createClass({ return ( {bounty.title} {' '} - + #{bounty.number} - posted {moment(bounty.created_at).fromNow()} + posted {moment(bounty.created_at).fromNow()} ) diff --git a/app/assets/javascripts/components/bounty_valuation.js.jsx b/app/assets/javascripts/components/bounty_valuation.js.jsx index 3ff4a141b..b67f598ba 100644 --- a/app/assets/javascripts/components/bounty_valuation.js.jsx +++ b/app/assets/javascripts/components/bounty_valuation.js.jsx @@ -24,7 +24,9 @@ var BountyValuation = React.createClass({ renderLightbox: function() { if (this.state.shown) { - return + return } }, diff --git a/app/assets/javascripts/components/chat_entry.js.jsx b/app/assets/javascripts/components/chat_entry.js.jsx index 0a5a5a78d..9419b6d75 100644 --- a/app/assets/javascripts/components/chat_entry.js.jsx +++ b/app/assets/javascripts/components/chat_entry.js.jsx @@ -21,7 +21,7 @@
-
    +
    • @@ -30,13 +30,13 @@
      • - + Permalink
      • - + Create bounty
      • diff --git a/app/assets/javascripts/components/custom_bounty_offer.js.jsx b/app/assets/javascripts/components/custom_bounty_offer.js.jsx index 76e120b4d..424cfaad1 100644 --- a/app/assets/javascripts/components/custom_bounty_offer.js.jsx +++ b/app/assets/javascripts/components/custom_bounty_offer.js.jsx @@ -1,164 +1,166 @@ -(function() { - var CustomBountyOffer = React.createClass({ - getInitialState: function() { - var value = this.props.steps[2] - - if(this.props.onChange) { - this.props.onChange({ target: { value: value }}) - } - - return { - value: value - } - }, - - renderOwnership: function() { - var value = this.state.value - var ownership = value / (value + this.props.coinsMinted) * 100; - - if(ownership < 0.001) { - return "< 0.001%" - } else if(ownership < 1) { - var roundedOwnership = Math.floor(ownership * 1000) / 1000 - return roundedOwnership + "%" - } else if(ownership < 10) { - var roundedOwnership = Math.floor(ownership * 100) / 100 - return roundedOwnership + "%" - } else { - var roundedOwnership = Math.floor(ownership) - return roundedOwnership + "%" - } - }, - - renderSellingPrice: function() { - var value = this.state.value - var ownership = value / (value + this.props.coinsMinted); - - var sellingPrice = Math.round(ownership * 1000000); - - return "$" + sellingPrice - }, - - renderPayout: function() { - var value = this.state.value - var ownership = value / (value + this.props.coinsMinted); - - var profitLastMonth = Math.round(this.props.profitLastMonth / 100) - var payout = Math.round(ownership * (profitLastMonth || 20000)); - - return "$" + payout - }, - - renderProfitLastMonth: function() { - var profitLastMonth = Math.round(this.props.profitLastMonth / 100) - - if(profitLastMonth) { - return "each month out
        of $" + profitLastMonth + "/mo" - } else { - return "each month if you
        made $20,000/mo" - } - }, - - renderAverage: function() { - var average = this.state.value / this.props.averageBounty - - if(average < 0.001) { - return "< 0.001x" - } else if(average < 1) { - var roundedAverage = Math.floor(average * 1000) / 1000 - return roundedAverage + 'x' - } else if(average < 10) { - var roundedAverage = Math.floor(average * 100) / 100 - return roundedAverage + 'x' - } else { - var roundedAverage = Math.floor(average) - return roundedAverage + 'x' - } - }, - - renderStats: function() { - if(this.props.profitLastMonth) { - return( -
        -
        -
        - {this.renderOwnership()} -
        -
        - ownership
        - in {this.props.product.name} -
        + +var CustomBountyOffer = React.createClass({ + propTypes: { + product: React.PropTypes.shape({ + average_bounty: React.PropTypes.number.isRequired, + coins_minted: React.PropTypes.number.isRequired + }) + }, + + getInitialState: function() { + var value = this.props.steps[2] + + if (this.props.onChange) { + this.props.onChange({ target: { value: value }}) + } + + return { + value: value + } + }, + + renderOwnership: function() { + var value = this.state.value + var ownership = value / (value + this.props.product.coins_minted) * 100; + + if (ownership < 0.001) { + return "< 0.001%" + } else if(ownership < 1) { + var roundedOwnership = Math.floor(ownership * 1000) / 1000 + return roundedOwnership + "%" + } else if(ownership < 10) { + var roundedOwnership = Math.floor(ownership * 100) / 100 + return roundedOwnership + "%" + } else { + var roundedOwnership = Math.floor(ownership) + return roundedOwnership + "%" + } + }, + + renderSellingPrice: function() { + var value = this.state.value + var ownership = value / (value + this.props.coinsMinted); + + var sellingPrice = Math.round(ownership * 1000000); + + return "$" + sellingPrice + }, + + renderPayout: function() { + var value = this.state.value + var ownership = value / (value + this.props.coinsMinted); + + var profitLastMonth = Math.round(this.props.profitLastMonth / 100) + var payout = Math.round(ownership * (profitLastMonth || 20000)); + + return "$" + payout + }, + + renderProfitLastMonth: function() { + var profitLastMonth = Math.round(this.props.profitLastMonth / 100) + + if(profitLastMonth) { + return "each month out
        of $" + profitLastMonth + "/mo" + } else { + return "each month if you
        made $20,000/mo" + } + }, + + renderAverage: function() { + var average = this.state.value / this.props.product.average_bounty + + if(average < 0.001) { + return "< 0.001x" + } else if(average < 1) { + var roundedAverage = Math.floor(average * 1000) / 1000 + return roundedAverage + 'x' + } else if(average < 10) { + var roundedAverage = Math.floor(average * 100) / 100 + return roundedAverage + 'x' + } else { + var roundedAverage = Math.floor(average) + return roundedAverage + 'x' + } + }, + + renderStats: function() { + if(this.props.profitLastMonth) { + return( +
        +
        +
        + {this.renderOwnership()}
        -
        -
        - {this.renderPayout()} -
        -
        +
        + ownership
        + in {this.props.product.name}
        -
        -
        - {this.renderSellingPrice()} -
        -
        - if {this.props.product.name} was
        sold for $1 million -
        +
        +
        +
        + {this.renderPayout()}
        +
        - ) - } else { - return( -
        -
        -
        - {this.renderOwnership()} -
        -
        - ownership in {this.props.product.name} -
        +
        +
        + {this.renderSellingPrice()}
        -
        -
        - {this.renderAverage()} -
        -
        - the average {this.props.product.name} bounty -
        +
        + if {this.props.product.name} was
        sold for $1 million
        - ) - } - }, - - render: function() { - return ( -
        -
        -
        - - +
        + ) + } else { + return( +
        +
        +
        + {this.renderOwnership()} +
        +
        + ownership in {this.props.product.name}
        -
        - {this.renderStats()} +
        +
        + {this.renderAverage()} +
        +
        + the average {this.props.product.name} bounty +
        ) - }, + } + }, + + render: function() { + return ( +
        +
        +
        + + +
        +
        +
        + {this.renderStats()} +
        +
        + ) + }, - handleOfferChange: function(e) { - this.setState({ - value: parseInt(e.target.value.replace(/[^\d]/g, '')) || 0 - }) + handleOfferChange: function(e) { + this.setState({ + value: parseInt(e.target.value.replace(/[^\d]/g, '')) || 0 + }) - if(this.props.onChange) { - this.props.onChange(e); - } + if(this.props.onChange) { + this.props.onChange(e); } - }); - - if (typeof module !== 'undefined') { - module.exports = CustomBountyOffer; } +}); - window.CustomBountyOffer = CustomBountyOffer; -})(); +module.exports = window.CustomBountyOffer = CustomBountyOffer; diff --git a/app/assets/javascripts/components/dashboard/dashboard_index.js.jsx b/app/assets/javascripts/components/dashboard/dashboard_index.js.jsx index 3f5fd52bf..36754a1d3 100644 --- a/app/assets/javascripts/components/dashboard/dashboard_index.js.jsx +++ b/app/assets/javascripts/components/dashboard/dashboard_index.js.jsx @@ -474,6 +474,9 @@ let DashboardIndex = React.createClass({ }, getStateFromStore: function() { + if (!this.isMounted()) { + return + } let dashboard = DashboardStore.getDashboard() this.setState({ diff --git a/app/assets/javascripts/components/drag_and_drop_view.js.jsx b/app/assets/javascripts/components/drag_and_drop_view.js.jsx index c3743b253..5f6d91a48 100644 --- a/app/assets/javascripts/components/drag_and_drop_view.js.jsx +++ b/app/assets/javascripts/components/drag_and_drop_view.js.jsx @@ -16,7 +16,7 @@ var DragAndDrop = React.createClass({ {this.props.alt} -
          +
          • Payout diff --git a/app/assets/javascripts/components/form_group.js.jsx b/app/assets/javascripts/components/form_group.js.jsx index ec2b26051..7aec1c383 100644 --- a/app/assets/javascripts/components/form_group.js.jsx +++ b/app/assets/javascripts/components/form_group.js.jsx @@ -29,7 +29,7 @@ var FormGroup = React.createClass({ }, errorMessage: function() { - return {this.props.error} + return {this.props.error} } }); diff --git a/app/assets/javascripts/components/heart.js.jsx b/app/assets/javascripts/components/heart.js.jsx index c977114ae..1bff47ace 100644 --- a/app/assets/javascripts/components/heart.js.jsx +++ b/app/assets/javascripts/components/heart.js.jsx @@ -80,7 +80,7 @@ var Heart = React.createClass({
        return ( - + {heartWithCount} ); @@ -147,7 +147,7 @@ var Heart = React.createClass({ return (
        -
        +
        {heartWithCount}
        diff --git a/app/assets/javascripts/components/idea_progress_widget.js.jsx b/app/assets/javascripts/components/idea_progress_widget.js.jsx index 2e9e66c53..855628938 100644 --- a/app/assets/javascripts/components/idea_progress_widget.js.jsx +++ b/app/assets/javascripts/components/idea_progress_widget.js.jsx @@ -66,11 +66,11 @@ const IdeaProgressWidget = React.createClass({ return (
        -
        +
        {this.state.stages[this.state.activeStage]['cta'] || this.state.stages[this.state.activeStage]['name']}
        -
        +
          {stages}
        diff --git a/app/assets/javascripts/components/ideas/idea_form.js.jsx b/app/assets/javascripts/components/ideas/idea_form.js.jsx index 89c9192eb..f95c8c185 100644 --- a/app/assets/javascripts/components/ideas/idea_form.js.jsx +++ b/app/assets/javascripts/components/ideas/idea_form.js.jsx @@ -43,7 +43,8 @@ let NewIdeaForm = React.createClass({ ideaBody: idea.raw_body || '', ideaName: idea.name || '', isFounder: true, - showWarning: false + showWarning: false, + buttonValid: true }; }, @@ -70,8 +71,13 @@ let NewIdeaForm = React.createClass({ }); }, + buttonValid() { + return this.state.buttonValid || !_.isEmpty(this.props.initialIdea); + }, + onNextClick(e) { e.preventDefault(); + this.setState({buttonValid: false}); if (_.isEmpty(this.props.initialIdea)) { let idea = { @@ -81,6 +87,7 @@ let NewIdeaForm = React.createClass({ }; IdeaActionCreators.submitIdeaClicked(idea); + } else { let slug = this.props.initialIdea.slug; @@ -130,7 +137,7 @@ let NewIdeaForm = React.createClass({
        -
        diff --git a/app/assets/javascripts/components/info_modal.js.jsx b/app/assets/javascripts/components/info_modal.js.jsx index 34aecf873..0dfcc0604 100644 --- a/app/assets/javascripts/components/info_modal.js.jsx +++ b/app/assets/javascripts/components/info_modal.js.jsx @@ -48,7 +48,7 @@ }, logo: function() { - return ; + return ; }, render: function() { @@ -88,7 +88,7 @@ var product = this.props.product; return ( -
        +

        {product.name}

        {this.logo()}

        diff --git a/app/assets/javascripts/components/invite_bounty_form.js.jsx b/app/assets/javascripts/components/invite_bounty_form.js.jsx index 81b4e3005..31a5190f1 100644 --- a/app/assets/javascripts/components/invite_bounty_form.js.jsx +++ b/app/assets/javascripts/components/invite_bounty_form.js.jsx @@ -25,7 +25,7 @@ var FormGroup = require('./form_group.js.jsx'); return (

        -

        Ask a friend

        +

        Ask a friend

        Know somebody who could help with this? Anybody can help out, all you need to do is ask.

        @@ -48,7 +48,7 @@ var FormGroup = require('./form_group.js.jsx'); -

        Start off on the right foot; generosity always pays off.

        +

        Start off on the right foot; generosity always pays off.