From a8928739ddb17d6d669454c9ecb2170eb87b3366 Mon Sep 17 00:00:00 2001 From: Tom <20648924+moT01@users.noreply.github.com> Date: Tue, 26 Nov 2019 09:15:59 -0600 Subject: [PATCH] feat(client): completion modal progress bar (#37775) * feat: add progress bar to completion modal * feat: add stuff * feat: finalize-layout-and-make-responsive * feat: add feature to all challenge templates * git test * fix: remove challenge title + enlarge top message * fix: move graphql query to completion modal * fix: remove some previous additions * fix: optimize functions * fix: removed isRequired flag * feat: add animation * feat: add interval to state + clear on unmount * fix: change around interval function * feat: make bar fill non-linearly * Update client/src/templates/Challenges/components/CompletionModal.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModal.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModal.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/redux/index.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/redux/index.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/redux/index.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/redux/index.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModalBody.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModalBody.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModalBody.js Co-Authored-By: Oliver Eyton-Williams * fix: remove bracket * fix: tweak animation + change to pure component * fix: remove comment * Update client/src/templates/Challenges/components/CompletionModalBody.js Co-Authored-By: Oliver Eyton-Williams * Update client/src/templates/Challenges/components/CompletionModalBody.js Co-Authored-By: Oliver Eyton-Williams * fix: remove animateProgress * feat: add tests for progress bar * feat: add working tests Co-authored-by: ojeytonwilliams * fix: add formatting * fix: use content selectors where possible * fix: make progress bar show 0 for unauthed users --- client/package-lock.json | 5 + client/package.json | 1 + .../src/templates/Challenges/classic/Show.js | 8 +- .../Challenges/components/CompletionModal.js | 91 ++++++++++++-- .../components/CompletionModal.test.js | 47 ++++++++ .../components/CompletionModalBody.js | 97 +++++++++++++++ .../components/CompletionModalBody.test.js | 68 +++++++++++ .../CompletionModalBody.test.js.snap | 92 ++++++++++++++ .../components/completion-modal.css | 114 +++++++++++++++++- .../Challenges/projects/backend/Show.js | 2 +- .../Challenges/projects/frontend/Show.js | 2 +- .../src/templates/Challenges/redux/index.js | 2 + 12 files changed, 512 insertions(+), 17 deletions(-) create mode 100644 client/src/templates/Challenges/components/CompletionModal.test.js create mode 100644 client/src/templates/Challenges/components/CompletionModalBody.js create mode 100644 client/src/templates/Challenges/components/CompletionModalBody.test.js create mode 100644 client/src/templates/Challenges/components/__snapshots__/CompletionModalBody.test.js.snap diff --git a/client/package-lock.json b/client/package-lock.json index 15bfc69d26..c0f90f22c0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4074,6 +4074,11 @@ "resolved": "https://registry.npmjs.org/better-queue-memory/-/better-queue-memory-1.0.4.tgz", "integrity": "sha512-SWg5wFIShYffEmJpI6LgbL8/3Dqhku7xI1oEiy6FroP9DbcZlG0ZDjxvPdP9t7hTGW40IpIcC6zVoGT1oxjOuA==" }, + "bezier-easing": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", + "integrity": "sha1-wE3+i5JtbsrKGBPWn/F5t8ICXYY=" + }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", diff --git a/client/package.json b/client/package.json index da0041e8f4..e08641d2e9 100644 --- a/client/package.json +++ b/client/package.json @@ -18,6 +18,7 @@ "@reach/router": "^1.2.1", "algoliasearch": "^3.35.1", "axios": "^0.19.0", + "bezier-easing": "^2.1.0", "browser-cookies": "^1.2.0", "chai": "^4.2.0", "date-fns": "^1.30.1", diff --git a/client/src/templates/Challenges/classic/Show.js b/client/src/templates/Challenges/classic/Show.js index 6c8886ff8a..18620dd494 100644 --- a/client/src/templates/Challenges/classic/Show.js +++ b/client/src/templates/Challenges/classic/Show.js @@ -252,7 +252,11 @@ class ShowClassic extends Component { } render() { - const { forumTopicId, title } = this.getChallenge(); + const { + fields: { blockName }, + forumTopicId, + title + } = this.getChallenge(); const { executeChallenge, pageContext: { @@ -298,7 +302,7 @@ class ShowClassic extends Component { testOutput={this.renderTestOutput()} /> - + diff --git a/client/src/templates/Challenges/components/CompletionModal.js b/client/src/templates/Challenges/components/CompletionModal.js index c5794dcf10..91d77ff5f4 100644 --- a/client/src/templates/Challenges/components/CompletionModal.js +++ b/client/src/templates/Challenges/components/CompletionModal.js @@ -4,10 +4,11 @@ import noop from 'lodash/noop'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { Button, Modal } from '@freecodecamp/react-bootstrap'; +import { useStaticQuery, graphql } from 'gatsby'; import ga from '../../../analytics'; import Login from '../../../components/Header/components/Login'; -import GreenPass from '../../../assets/icons/GreenPass'; +import CompletionModalBody from './CompletionModalBody'; import { dasherize } from '../../../../../utils/slugs'; @@ -16,6 +17,7 @@ import './completion-modal.css'; import { closeModal, submitChallenge, + completedChallengesIds, isCompletionModalOpenSelector, successMessageSelector, challengeFilesSelector, @@ -27,12 +29,22 @@ import { isSignedInSelector } from '../../../redux'; const mapStateToProps = createSelector( challengeFilesSelector, challengeMetaSelector, + completedChallengesIds, isCompletionModalOpenSelector, isSignedInSelector, successMessageSelector, - (files, { title }, isOpen, isSignedIn, message) => ({ + ( + files, + { title, id }, + completedChallengesIds, + isOpen, + isSignedIn, + message + ) => ({ files, title, + id, + completedChallengesIds, isOpen, isSignedIn, message @@ -59,9 +71,13 @@ const mapDispatchToProps = function(dispatch) { }; const propTypes = { + blockName: PropTypes.string, close: PropTypes.func.isRequired, + completedChallengesIds: PropTypes.array, + currentBlockIds: PropTypes.array, files: PropTypes.object.isRequired, handleKeypress: PropTypes.func.isRequired, + id: PropTypes.string, isOpen: PropTypes.bool, isSignedIn: PropTypes.bool.isRequired, message: PropTypes.string, @@ -69,7 +85,27 @@ const propTypes = { title: PropTypes.string }; -export class CompletionModal extends Component { +export function getCompletedPercent( + completedChallengesIds, + currentBlockIds, + currentChallengeId +) { + completedChallengesIds = completedChallengesIds.includes(currentChallengeId) + ? completedChallengesIds + : [...completedChallengesIds, currentChallengeId]; + + const completedChallengesInBlock = completedChallengesIds.filter(id => { + return currentBlockIds.includes(id); + }); + + const completedPercent = Math.round( + (completedChallengesInBlock.length / currentBlockIds.length) * 100 + ); + + return completedPercent > 100 ? 100 : completedPercent; +} + +export class CompletionModalInner extends Component { state = { downloadURL: null }; @@ -111,7 +147,11 @@ export class CompletionModal extends Component { render() { const { + blockName = '', close, + completedChallengesIds = [], + currentBlockIds = [], + id = '', isOpen, isSignedIn, submitChallenge, @@ -119,6 +159,11 @@ export class CompletionModal extends Component { message, title } = this.props; + + const completedPercent = !isSignedIn + ? 0 + : getCompletedPercent(completedChallengesIds, currentBlockIds, id); + if (isOpen) { ga.modalview('/completion-modal'); } @@ -137,12 +182,13 @@ export class CompletionModal extends Component { className='challenge-list-header fcc-modal' closeButton={true} > - {message} + {message} -
- -
+