diff --git a/app/pages/project/finished-banner.jsx b/app/pages/project/finished-banner.jsx index 1f6aba8f28..275f14554f 100644 --- a/app/pages/project/finished-banner.jsx +++ b/app/pages/project/finished-banner.jsx @@ -11,10 +11,8 @@ export default class FinishedBanner extends React.Component { this.state = { hasResultsPage: false, hide: false, - projectIsComplete: false, }; - this.getCompleteness = this.getCompleteness.bind(this); this.getResultsPageExistence = this.getResultsPageExistence.bind(this); this.hide = this.hide.bind(this); this.refresh = this.refresh.bind(this); @@ -31,25 +29,6 @@ export default class FinishedBanner extends React.Component { } } - getCompleteness(project) { - if (project.redirect) { - return Promise.resolve(false); - } - - return getWorkflowsInOrder(project, { active: true, fields: 'finished_at' }) - .then((activeWorkflows) => { - if (activeWorkflows.length === 0) { - // No active workflows? This is probably a custom project. - return false; - } else { - const activeUnfinishedWorkflows = activeWorkflows.filter((workflow) => { - return !workflow.finished_at ? workflow : null; - }); - return activeUnfinishedWorkflows.length === 0; - } - }); - } - getResultsPageExistence(project) { return project.get('pages').then((pages) => { const resultsPages = pages.filter((page) => { @@ -71,15 +50,12 @@ export default class FinishedBanner extends React.Component { this.setState({ hasResultsPage: false, hide: false, - projectIsComplete: false, }); - Promise.all([ - this.getCompleteness(project), - this.getResultsPageExistence(project), - ]).then(([projectIsComplete, hasResultsPage]) => { - this.setState({ projectIsComplete, hasResultsPage }); - }); + this.getResultsPageExistence(project) + .then((hasResultsPage) => { + this.setState({ hasResultsPage }); + }); } renderResultsPage() { @@ -103,7 +79,7 @@ export default class FinishedBanner extends React.Component { const dismissals = finishedProjectDismissals ? JSON.parse(finishedProjectDismissals) : {}; const recentlyDismissed = Date.now() - dismissals[this.props.project.id] < this.props.dismissFor; - if (recentlyDismissed || !this.state.projectIsComplete || this.state.hide) { + if (recentlyDismissed || this.state.hide) { return null; } @@ -130,4 +106,5 @@ FinishedBanner.propTypes = { id: React.PropTypes.string, slug: React.PropTypes.string, }), + projectIsComplete: React.PropTypes.bool }; diff --git a/app/pages/project/home.jsx b/app/pages/project/home.jsx index ecc7068571..75c878a724 100644 --- a/app/pages/project/home.jsx +++ b/app/pages/project/home.jsx @@ -94,9 +94,10 @@ export default class ProjectHomePage extends React.Component { return (
-
- -
+ {this.props.projectIsComplete && + (
+ +
)}
{this.props.project.description}
@@ -142,6 +143,7 @@ ProjectHomePage.defaultProps = { onChangePreferences: () => {}, preferences: {}, project: {}, + projectIsComplete: false, splits: {} }; @@ -158,5 +160,6 @@ ProjectHomePage.propTypes = { introduction: React.PropTypes.string, researcher_quote: React.PropTypes.string }).isRequired, + projectIsComplete: React.PropTypes.bool, splits: React.PropTypes.object }; diff --git a/app/pages/project/index.cjsx b/app/pages/project/index.cjsx index f7ef63bfc2..b60a440fb3 100644 --- a/app/pages/project/index.cjsx +++ b/app/pages/project/index.cjsx @@ -169,7 +169,7 @@ ProjectPage = React.createClass @isWorkflowInactive(project, selectedWorkflowID) checkIfProjectIsComplete: (project) -> - projectIsComplete = (true for workflow in @state.activeWorkflows when not workflow.finished_at?).length is 0 + projectIsComplete = project.completeness > 0.99 @setState { projectIsComplete } selectRandomWorkflow: (project) -> diff --git a/app/pages/project/metadata.jsx b/app/pages/project/metadata.jsx index 1e16aceaec..ff47efa29d 100644 --- a/app/pages/project/metadata.jsx +++ b/app/pages/project/metadata.jsx @@ -45,15 +45,7 @@ export default class ProjectMetadata extends React.Component { } renderStatus() { - let percentComplete = 0; - this.props.activeWorkflows.map((workflow) => { - percentComplete += workflow.completeness; - return percentComplete; - }); - - if (this.props.activeWorkflows.length > 0) { - percentComplete /= this.props.activeWorkflows.length; - } + const percentComplete = this.props.project.completeness; return (
@@ -107,9 +99,9 @@ ProjectMetadata.contextTypes = { }; ProjectMetadata.propTypes = { - activeWorkflows: React.PropTypes.arrayOf(React.PropTypes.object), project: React.PropTypes.shape({ classifications_count: React.PropTypes.number, + completeness: React.PropTypes.number, display_name: React.PropTypes.string, id: React.PropTypes.id, slug: React.PropTypes.string, @@ -118,7 +110,6 @@ ProjectMetadata.propTypes = { }; ProjectMetadata.defaultProps = { - activeWorkflows: [], project: {}, showTalkStatus: false, }; diff --git a/app/pages/project/metadata.spec.js b/app/pages/project/metadata.spec.js index d534f76c2e..78233d9aa7 100644 --- a/app/pages/project/metadata.spec.js +++ b/app/pages/project/metadata.spec.js @@ -1,42 +1,54 @@ -import React from 'react' -import assert from 'assert' -import sinon from 'sinon' -import ProjectMetadata from './metadata' -import {shallow, render, mount} from 'enzyme' +import React from 'react'; +import assert from 'assert'; +import sinon from 'sinon'; +import { render, mount } from 'enzyme'; + +import ProjectMetadata from './metadata'; describe('ProjectMetadata', function(){ - var project; - var pusher; + let project; + let pusher; before(function() { - project = {classifiers_count: 0, classifications_count: 0, subjects_count: 0, retired_subjects_count: 0}; + project = { classifiers_count: 0, classifications_count: 0, completeness: 0.56, subjects_count: 0, retired_subjects_count: 0 }; - const subscribe = function(channel) { return {bind: function(event, callback) { }}} - pusher = {subscribe: subscribe}; + const subscribe = function(channel) { return { bind: function(event, callback) { } }}; + pusher = { subscribe }; }); - it('renders stats', function(){ - const context = {pusher: pusher}; - const page = render(, {context}); - assert(page.find('.project-metadata-stat').length, 4); - }); + describe('render', function() { + let wrapper; + before(function() { + const context = { pusher }; + wrapper = render(, { context }); + }); - it('subscribes to pusher', function() { - const context = {pusher: pusher}; - pusher.subscribe = sinon.spy(pusher.subscribe); - const wrapper = mount(, {context}); - wrapper.setContext(context); - assert(pusher.subscribe.called, true); - }); + it('renders stats', function() { + assert(wrapper.find('.project-metadata-stat').length, 4); + }); - it('subscribes to pusher', function() { - const context = {pusher: pusher}; - pusher.unsubscribe = sinon.spy(); - - const wrapper = mount(, {context}); - wrapper.setContext(context); - wrapper.unmount(); + it('renders 56% completeness', function() { + assert(wrapper.find('rect').first().prop('width'), 0.56); + }); + }); - assert(pusher.unsubscribe.called, true); + describe('pusher', function() { + it('subscribes to pusher', function() { + const context = { pusher }; + pusher.subscribe = sinon.spy(pusher.subscribe); + const wrapper = mount(, { context }); + + wrapper.setContext(context); + assert(pusher.subscribe.called, true); + }); + + it('unsubscribes to pusher', function() { + pusher.unsubscribe = sinon.spy(); + const context = { pusher }; + const wrapper = mount(, { context }); + wrapper.setContext(context); + wrapper.unmount(); + assert(pusher.unsubscribe.called, true); + }); }); });