From 28f618c9245ee15b8250bc801f1edf3a69e152bb Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Fri, 17 Jul 2020 14:21:19 -0400 Subject: [PATCH 1/7] Adding new file for test push --- frontend/src/quiz/api/quizQuestions.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 frontend/src/quiz/api/quizQuestions.js diff --git a/frontend/src/quiz/api/quizQuestions.js b/frontend/src/quiz/api/quizQuestions.js new file mode 100644 index 0000000..e69de29 From edb77fb72f9bcc87d0a4e35f35de7d66e2dbbf12 Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Tue, 21 Jul 2020 13:52:52 -0400 Subject: [PATCH 2/7] Entered quiz questions --- frontend/src/quiz/api/quizQuestions.js | 115 +++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/frontend/src/quiz/api/quizQuestions.js b/frontend/src/quiz/api/quizQuestions.js index e69de29..49dd6a1 100644 --- a/frontend/src/quiz/api/quizQuestions.js +++ b/frontend/src/quiz/api/quizQuestions.js @@ -0,0 +1,115 @@ +var quizQuestions = [ + { + question: "Which of the following best describes color contrast?", + answers: [ + { + val: 1, + content: "A measurement of the difference between two colors when they are layered on top of each other" + }, + { + val: 0, + content: "A measurement of a color’s brightness" + }, + { + val: 0, + content: "A condition resulting in reduced sensitivity to green light" + }, + { + val: 0, + content: "None of the above" + } + + ], + multiChoice: false + }, + { + question: "What is the minimum contrast allowed by the WCAG AAA Color Standards?", + answers: [ + { + val: 0, + content: "4" + }, + { + val: 1, + content: "7" + }, + { + val: 0, + content: "9" + }, + { + val: 0, + content: "11" + } + ], + multiChoice: false + }, + { + question: "Which of the following is the best way to correct an improper ratio in color contrast?", + answers: [ + { + val: 0, + content: "Do nothing, it’s impossible to fix" + }, + { + val: 0, + content: "Make everything black and white" + }, + { + val: 1, + content: "Use a color contrast calculator" + }, + { + val: 0, + content: "None of the above" + } + ], + multiChoice: false + }, + { + question: "Which of the following is NOT a form of color vision deficiency?\n", + answers: [ + { + val: 0, + content: "Protanopia" + }, + { + val: 0, + content: "Deuteranopia" + }, + { + val: 0, + content: "Tritanopia" + }, + { + val: 1, + content: "Dichrompia" + } + ], + multiChoice: false + }, + { + question: "If placed in a color contrast calculator, which of the following would result in a proper color contrast ratio?", + answers: [ + { + val: 0, + content: "Dark red placed on another shade of dark red" + }, + { + val: 0, + content: "White placed on light pink" + }, + { + val: 1, + content: "Light pink placed on black" + }, + { + val: 0, + content: "Black placed on black" + } + ], + multiChoice: false + } +]; + +export default quizQuestions; From 884a86fc522a7235b5851c0f13a04c05987d50de Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Wed, 22 Jul 2020 11:13:25 -0400 Subject: [PATCH 3/7] Copying over files for "components" folder --- frontend/src/quiz/components/AnswerOption.js | 49 +++++++ frontend/src/quiz/components/Certificate.js | 83 ++++++++++++ frontend/src/quiz/components/Question.js | 12 ++ frontend/src/quiz/components/QuestionCount.js | 17 +++ frontend/src/quiz/components/Quiz.js | 50 +++++++ frontend/src/quiz/components/Result.js | 124 ++++++++++++++++++ 6 files changed, 335 insertions(+) create mode 100644 frontend/src/quiz/components/AnswerOption.js create mode 100644 frontend/src/quiz/components/Certificate.js create mode 100644 frontend/src/quiz/components/Question.js create mode 100644 frontend/src/quiz/components/QuestionCount.js create mode 100644 frontend/src/quiz/components/Quiz.js create mode 100644 frontend/src/quiz/components/Result.js diff --git a/frontend/src/quiz/components/AnswerOption.js b/frontend/src/quiz/components/AnswerOption.js new file mode 100644 index 0000000..57b4d7d --- /dev/null +++ b/frontend/src/quiz/components/AnswerOption.js @@ -0,0 +1,49 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function AnswerOption(props) { + if(props.multiChoice == true){ + return ( +
  • + + +
  • + ); + } + else { + return ( +
  • + + +
  • + ); + } +} + +AnswerOption.propTypes = { + answerType: PropTypes.string.isRequired, + answerContent: PropTypes.string.isRequired, + onAnswerSelected: PropTypes.func.isRequired, + multiChoice: PropTypes.func.isRequired +}; + +export default AnswerOption; \ No newline at end of file diff --git a/frontend/src/quiz/components/Certificate.js b/frontend/src/quiz/components/Certificate.js new file mode 100644 index 0000000..db9e7c4 --- /dev/null +++ b/frontend/src/quiz/components/Certificate.js @@ -0,0 +1,83 @@ +import React, {Component} from "react"; +import "./../../vendor/bootstrap/css/bootstrap.min.css"; +import "./../../css/agency.min.css"; +import "./../../css/style.css"; +import {connect} from "react-redux"; +import {actions as appActions} from '../../reducers/AppReducer'; +import {bindActionCreators} from 'redux'; +import logo from "./../../img/accessCycle.png"; + +const mapStateToProps = (state) => { + return { + // General + state: state + }; +}; +const mapDispatchToProps = (dispatch) => ({ + actions: bindActionCreators(appActions, dispatch) +}); + + + +class Certificate extends Component { + + constructor(props) { + super(props); + + this.state = { + + }; + + + } + getColor=()=>{ + let score = this.props.quizResult; + score = parseFloat(score); + switch (true) { + case score<=40: + return "red"; + case score<=70: + return "orange"; + default: + return "green"; + } + }; + + render() { + console.log(this.props); + const {state, actions} = this.props; + var today = new Date(); + var date = (today.getMonth()+1)+'/'+today.getDate() +'/'+ today.getFullYear(); + return ( +
    +
    + + Certificate of Completion + +

    + This is to certify that you have completed the course: +

    + {/*Sakshi

    */} + {/*have completed the course

    */} + Accessibility Learning Lab 1: Accessibility to Sound and Speech

    + with score of {this.props.quizResult}

    + dated
    + {date}

    + {/**/} + {/*        */} +
    + +
    +
    +
    + + ); + + }; +} + +export default connect( + mapStateToProps, mapDispatchToProps +)(Certificate); diff --git a/frontend/src/quiz/components/Question.js b/frontend/src/quiz/components/Question.js new file mode 100644 index 0000000..1f3fa87 --- /dev/null +++ b/frontend/src/quiz/components/Question.js @@ -0,0 +1,12 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function Question(props) { + return

    {props.content}

    ; +} + +Question.propTypes = { + content: PropTypes.string.isRequired +}; + +export default Question; diff --git a/frontend/src/quiz/components/QuestionCount.js b/frontend/src/quiz/components/QuestionCount.js new file mode 100644 index 0000000..7bb4d50 --- /dev/null +++ b/frontend/src/quiz/components/QuestionCount.js @@ -0,0 +1,17 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +function QuestionCount(props) { + return ( +
    + Question {props.counter} of {props.total} +
    + ); +} + +QuestionCount.propTypes = { + counter: PropTypes.number.isRequired, + total: PropTypes.number.isRequired +}; + +export default QuestionCount; diff --git a/frontend/src/quiz/components/Quiz.js b/frontend/src/quiz/components/Quiz.js new file mode 100644 index 0000000..b065fb8 --- /dev/null +++ b/frontend/src/quiz/components/Quiz.js @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Question from '../components/Question'; +import QuestionCount from '../components/QuestionCount'; +import AnswerOption from '../components/AnswerOption'; + +function Quiz(props) { + function renderAnswerOptions(key) { + return ( + + ); + } + + + return ( +
    + + +
      + {props.answerOptions.map(renderAnswerOptions)} +
    +
    + +
    +
    + ); +} + + +Quiz.propTypes = { + answer: PropTypes.string.isRequired, + answerOptions: PropTypes.array.isRequired, + question: PropTypes.string.isRequired, + questionId: PropTypes.number.isRequired, + questionTotal: PropTypes.number.isRequired, + onAnswerSelected: PropTypes.func.isRequired, + multiChoice: PropTypes.func.isRequired +}; + +export default Quiz; \ No newline at end of file diff --git a/frontend/src/quiz/components/Result.js b/frontend/src/quiz/components/Result.js new file mode 100644 index 0000000..3ccfde5 --- /dev/null +++ b/frontend/src/quiz/components/Result.js @@ -0,0 +1,124 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import AnswerOption from "./AnswerOption"; +import quizQuestions from "../api/quizQuestions"; +import Certificate from "./Certificate"; + +function Result(props) { + + function renderTableHeader() { + let header = Object.keys(quizQuestions[0]) + return header.map((key, index) => { + return {key.toUpperCase()} + }) + } + + function isAnswerIncorrect(score) { + if (score == 1) { + return true; + } else { + return false; + } + + } + + function renderTableData() { + var counter = 0; + var isIncorrect = false; + return quizQuestions.map((quizQuestion, index) => { + const {question, answers} = quizQuestion //destructuring + counter += 1; + isIncorrect = isAnswerIncorrect(props.quizScore[counter - 1]); + return ( + + {question} + {renderTableAnswersData(answers)} + {renderTableSelectedAnswersData(props.selectedAnswers[counter - 1], answers)} + + + ); + + }) + + } + + function renderTableAnswersData(answers) { + var counter = 0; + return ( +
      + {answers.map(function (answer, index) { + counter += 1; + if (answer['val'] == 1) { + return ( +
    • {counter}. {answer['content']} +
      +
    • + ); + } + + })} +
    + ) + } + + + function renderTableSelectedAnswersData(selectedAnswers, answers) { + const choices = Object.values(selectedAnswers); + var counter = 0; + return ( +
      + {choices.map(function (selectedAnswer, index) { + counter += 1; + if (selectedAnswer == 1) { + return ( +
    • {counter}. {answers[counter - 1]['content']} +
      +
    • + + ); + } + + + })} +
    + ) + + } + + + + return ( + +
    +
    + Results Score: {props.quizResult} +
    +
    + + + + {/*{renderTableHeader()}*/} + + + + + {renderTableData()} + +
    QUESTIONANSWERSSELECTED ANSWERS
    +
    + +
    +
    +
    +
    + ); +} + + +Result.propTypes = { + quizResult: PropTypes.string.isRequired, + quizScore: PropTypes.string.isRequired, + selectedAnswers: PropTypes.string.isRequired +}; + +export default Result; From d57a0d82680682f670ed444431f73002e6da6bb8 Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Wed, 22 Jul 2020 11:15:45 -0400 Subject: [PATCH 4/7] Copying over files for "svg" folder --- frontend/src/quiz/svg/icon-check copy.svg | 4 +++ frontend/src/quiz/svg/logo copy.svg | 35 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 frontend/src/quiz/svg/icon-check copy.svg create mode 100644 frontend/src/quiz/svg/logo copy.svg diff --git a/frontend/src/quiz/svg/icon-check copy.svg b/frontend/src/quiz/svg/icon-check copy.svg new file mode 100644 index 0000000..36840b5 --- /dev/null +++ b/frontend/src/quiz/svg/icon-check copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/quiz/svg/logo copy.svg b/frontend/src/quiz/svg/logo copy.svg new file mode 100644 index 0000000..467e1dc --- /dev/null +++ b/frontend/src/quiz/svg/logo copy.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + From c616b47f2eb3a7120f22443695457985ebad00a0 Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Wed, 22 Jul 2020 11:20:50 -0400 Subject: [PATCH 5/7] Copying over all other files in the "quiz" folder --- frontend/src/quiz/App.css | 24 ++++ frontend/src/quiz/App.js | 206 +++++++++++++++++++++++++++++ frontend/src/quiz/App.test.js | 9 ++ frontend/src/quiz/index.css | 148 +++++++++++++++++++++ frontend/src/quiz/index.js | 12 ++ frontend/src/quiz/serviceWorker.js | 127 ++++++++++++++++++ 6 files changed, 526 insertions(+) create mode 100644 frontend/src/quiz/App.css create mode 100644 frontend/src/quiz/App.js create mode 100644 frontend/src/quiz/App.test.js create mode 100644 frontend/src/quiz/index.css create mode 100644 frontend/src/quiz/index.js create mode 100644 frontend/src/quiz/serviceWorker.js diff --git a/frontend/src/quiz/App.css b/frontend/src/quiz/App.css new file mode 100644 index 0000000..659e7f9 --- /dev/null +++ b/frontend/src/quiz/App.css @@ -0,0 +1,24 @@ +.App-logo { + animation: spin infinite 20s linear; + height: 80px; +} + +.App-header { + background-color: #222; + padding: 20px; + color: white; + text-align: center; +} + +.App-intro { + font-size: large; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/frontend/src/quiz/App.js b/frontend/src/quiz/App.js new file mode 100644 index 0000000..15081e0 --- /dev/null +++ b/frontend/src/quiz/App.js @@ -0,0 +1,206 @@ +import React, {Component} from 'react'; +import quizQuestions from './api/quizQuestions'; +import Quiz from './components/Quiz'; +import Result from './components/Result'; +import logo from './svg/logo.svg'; +import './App.css'; + +class App extends Component { + constructor(props) { + super(props); + + this.state = { + counter: 0, + questionId: 1, + question: '', + answerOptions: [], + answer: '', + result: '', + myCount: {}, + disableNextQuestion: true, + selectedAnswers: {}, + multiChoice: false + }; + + this.handleAnswerSelected = this.handleAnswerSelected.bind(this); + this.setNextQuestion = this.setNextQuestion.bind(this) + } + + componentWillMount() { + for (var i = 0; i < quizQuestions.length; i++) { + for (var x = 0; x < quizQuestions[i]['answers'].length; x++) { + quizQuestions[i]['answers'][x]['type'] = "" + x; + } + } + + console.log(quizQuestions); + + } + + componentDidMount() { + for (var i = 0; i < quizQuestions.length; i++) { + quizQuestions[i]['answers'].sort(function (a, b) { + return parseInt(a.type) - parseInt(b.type); + }); + } + this.setState({ + question: quizQuestions[0].question, + answerOptions: quizQuestions[0]['answers'], + multiChoice: quizQuestions[0]['multiChoice'] + }); + } + + shuffleArray(array) { + var currentIndex = array.length, + temporaryValue, + randomIndex; + + // While there remain elements to shuffle... + while (0 !== currentIndex) { + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // And swap it with the current element. + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + + return array; + } + + handleAnswerSelected(event) { + this.setState((state, props) => ({ + disableNextQuestion: false + }), () => console.log(this.state)); + } + + setUserAnswer(answer, correctanswer) { + this.setState((state, props) => ({ + disableNextQuestion: false, + myCount: { + ...state.myCount, + [this.state.counter]: correctanswer + }, + selectedAnswers: { + ...state.selectedAnswers, + [this.state.counter]: answer + }, + answer: answer + }), () => console.log(this.state)); + } + + checkMultipleAnswers(currentAnswers) { + var correctAnswer = 0; + var options = quizQuestions[this.state.counter]['answers'].length; + for (var index = 0; index < options; index++) { + if (quizQuestions[this.state.counter]['answers'][index]['val'] === currentAnswers[index]) { + correctAnswer = 1; + } else { + correctAnswer = 0; + break; + } + } + + this.setUserAnswer(currentAnswers, correctAnswer); + } + + getCheckedAnswers() { + var checked = document.getElementsByName('checkboxGroup'); + var currentAnswers = {}; + for (var index = 0; index < checked.length; index++) { + if (checked[index].checked === true) { + currentAnswers[index] = 1 + + } else { + currentAnswers[index] = 0 + } + + } + return currentAnswers; + } + + setNextQuestion() { + var currentAnswers = this.getCheckedAnswers(); + console.log("get selected answers:"); + console.log(currentAnswers); + + //Calculate correct answers and set accordingly + this.checkMultipleAnswers(currentAnswers); + + //Set next question + if (this.state.questionId < quizQuestions.length) { + const counter = this.state.counter + 1; + const questionId = this.state.questionId + 1; + + this.setState({ + counter: counter, + questionId: questionId, + question: quizQuestions[counter].question, + answerOptions: quizQuestions[counter].answers, + answer: '', + disableNextQuestion: true, + multiChoice: quizQuestions[counter].multiChoice + }); + } else { + setTimeout(() => this.setResults(this.getResults()), 300); + } + + } + + getResults() { + const myCount = this.state.myCount; + var correct = 0; + var total = 0; + for (var item in myCount) { + total++; + if (myCount.hasOwnProperty(item)) { + if (myCount[item] === 1) correct++; + } + } + var percent = Math.floor(correct / total * 100); + return "" + percent + "%" + } + + setResults(result) { + this.setState({result: result}); + } + + renderQuiz() { + return ( +
    + +
    + ); + } + + renderResult() { + return ( + ); + } + + render() { + return ( +
    + {this.state.result ? this.renderResult() : this.renderQuiz()} +
    + ); + } +} + +export default App; diff --git a/frontend/src/quiz/App.test.js b/frontend/src/quiz/App.test.js new file mode 100644 index 0000000..d1c2db9 --- /dev/null +++ b/frontend/src/quiz/App.test.js @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); diff --git a/frontend/src/quiz/index.css b/frontend/src/quiz/index.css new file mode 100644 index 0000000..b2db352 --- /dev/null +++ b/frontend/src/quiz/index.css @@ -0,0 +1,148 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + background: #eee; + font-family: sans-serif; +} + +.container { + position: relative; + max-width: 800px; + margin: 0 auto; + background: #fff; + border-radius: 3px; +} + +@media (min-width: 769px) { + .container { + margin: 2.5rem auto; + } +} + +/* Result Component */ +.result { + padding: 1.5rem 2.5rem; +} + +/* Quiz Component */ +.answerOptions { + margin: 0; + padding: 0; + list-style: none; +} + +/* QuestionCount Component */ +.questionCount { + padding: 1.5rem 2.5rem 0; + font-size: 14px; +} + +/* Question Component */ +.question { + margin: 0; + padding: 0.5rem 2.5rem 1.5rem 2.5rem; +} + +/* AnswerOption Component */ +.answerOption { + border-top: 1px solid #eee; +} + +.answerOption:hover { + background-color: #eefbfe; +} + +.radioCustomButton { + position: absolute; + width: auto; + opacity: 0; +} + +.radioCustomButton, +.radioCustomLabel { + display: inline-block; + vertical-align: middle; + cursor: pointer; +} + +.radioCustomLabel { + position: relative; + width: 100%; + margin: 0; + padding: 1.5rem 2.5rem 1.5rem 5rem; + font-size: 16px; + line-height: 1.5; +} + +.radioCustomButton ~ .radioCustomLabel:before { + position: absolute; + top: 20px; + left: 38px; + width: 28px; + height: 28px; + content: ''; + display: inline-block; + vertical-align: middle; + background: #fff; + border: 1px solid #bbb; + border-radius: 50%; + transition: all 0.3s; +} + +.radioCustomButton:checked ~ .radioCustomLabel:before { + content: ''; + background: #8bc53f no-repeat; + background-size: 27px; + border-color: #8bc53f; +} + +/* Animation */ +.fade-enter { + opacity: 0; +} + +.fade-enter.fade-enter-active { + opacity: 1; + transition: opacity 0.5s ease-in-out 0.3s; +} + +.fade-leave { + position: absolute; + top: 0; + left: 0; + width: 100%; + opacity: 1; +} + +.fade-leave.fade-leave-active { + opacity: 0; + transition: opacity 0.5s ease-in-out; +} + +.fade-appear { + opacity: 0; +} + +.fade-appear.fade-appear-active { + opacity: 1; + transition: opacity 0.5s ease-in-out; +} diff --git a/frontend/src/quiz/index.js b/frontend/src/quiz/index.js new file mode 100644 index 0000000..0c5e75d --- /dev/null +++ b/frontend/src/quiz/index.js @@ -0,0 +1,12 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(, document.getElementById('root')); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: http://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/frontend/src/quiz/serviceWorker.js b/frontend/src/quiz/serviceWorker.js new file mode 100644 index 0000000..ec7e8fb --- /dev/null +++ b/frontend/src/quiz/serviceWorker.js @@ -0,0 +1,127 @@ +// In production, we register a service worker to serve assets from local cache. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on the "N+1" visit to a page, since previously +// cached resources are updated in the background. + +// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. +// This link also includes instructions on opting out of this behavior. + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.1/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://goo.gl/SC7cgQ' + ); + }); + } else { + // Is not local host. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the old content will have been purged and + // the fresh content will have been added to the cache. + // It's the perfect time to display a "New content is + // available; please refresh." message in your web app. + console.log('New content is available; please refresh.'); + + // Execute callback + if (config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + if ( + response.status === 404 || + response.headers.get('content-type').indexOf('javascript') === -1 + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister(); + }); + } +} From 852b700f5a4631b240cdceb0f3a8a65d76227899 Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Wed, 22 Jul 2020 11:35:14 -0400 Subject: [PATCH 6/7] Adding quiz styling (quiz.scss) --- .../src/assets/stylesheets/pages/quiz.scss | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 frontend/src/assets/stylesheets/pages/quiz.scss diff --git a/frontend/src/assets/stylesheets/pages/quiz.scss b/frontend/src/assets/stylesheets/pages/quiz.scss new file mode 100644 index 0000000..9a2c2a6 --- /dev/null +++ b/frontend/src/assets/stylesheets/pages/quiz.scss @@ -0,0 +1,231 @@ +.quiz { + + .quizHeader { + text-align: center; + margin-top: 110px; + } + + .body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background: #eee; + + } + + code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; + } + + * { + box-sizing: border-box; + } + + .body { + margin: 0; + padding: 0; + background: #eee; + font-family: sans-serif; + } + + .container { + position: relative; + max-width: 800px; + margin: 0 auto; + background: #fff; + border-radius: 3px; + } + + @media (min-width: 769px) { + .container { + margin: 2.5rem auto; + } + } + + /* Result Component */ + .result { + padding: 1.5rem 2.5rem; + } + + /* Quiz Component */ + .answerOptions { + margin: 16px; + padding: 0; + list-style: none; + display: list-item; + } + + /* QuestionCount Component */ + .questionCount { + padding: 1.5rem 2.5rem 0; + font-size: 14px; + } + + /* Question Component */ + .question { + margin: 0; + padding: 0.5rem 2.5rem 1.5rem 2.5rem; + } + + /* AnswerOption Component */ + .answerOption { + border-top: 1px solid #eee; + } + + .answerOption:hover { + background-color: #eefbfe; + } + + .checkboxCustomButton { + position: absolute; + width: auto; + opacity: 0; + } + + .checkboxCustomButton, + .checkboxCustomLabel { + display: inline-block; + vertical-align: middle; + cursor: pointer; + } + + .checkboxCustomLabel { + position: relative; + width: 100%; + margin: 0; + padding: 1.5rem 2.5rem 1.5rem 5rem; + font-size: 16px; + line-height: 1.5; + text-align: left; + } + + .checkboxCustomButton ~ .checkboxCustomLabel:before { + position: absolute; + top: 20px; + left: 38px; + width: 28px; + height: 28px; + content: ''; + display: inline-block; + vertical-align: middle; + background: #fff; + border: 1px solid #bbb; + transition: all 0.3s; + } + + .checkboxCustomButton:checked ~ .checkboxCustomLabel:before { + content: ''; + background: #8bc53f no-repeat; + background-size: 27px; + border-color: #8bc53f; + } + + .checkboxCustomButton:checked ~ .checkboxCustomLabel:after { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } + + .radioCustomButton { + position: absolute; + width: auto; + opacity: 0; + } + + .radioCustomButton, + .radioCustomLabel { + display: inline-block; + vertical-align: middle; + cursor: pointer; + } + + .radioCustomLabel { + position: relative; + width: 100%; + margin: 0; + padding: 1.5rem 2.5rem 1.5rem 5rem; + font-size: 16px; + line-height: 1.5; + text-align: left; + } + + .radioCustomButton ~ .radioCustomLabel:before { + position: absolute; + top: 20px; + left: 38px; + width: 28px; + height: 28px; + content: ''; + display: inline-block; + vertical-align: middle; + background: #fff; + border: 1px solid #bbb; + border-radius: 50%; + transition: all 0.3s; + } + + .radioCustomButton:checked ~ .radioCustomLabel:before { + content: ''; + background: #8bc53f no-repeat; + background-size: 27px; + border-color: #8bc53f; + } + + .radioCustomButton:checked ~ .radioCustomButton:after { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } + + .nextButton { + margin: 20px; + padding: 8px !important; + } + + .align-right { + text-align: right; + } + + .top-margin { + margin-top: 150px !important; + } + + /* Animation */ + .fade-enter { + opacity: 0; + } + + .fade-enter.fade-enter-active { + opacity: 1; + transition: opacity 0.5s ease-in-out 0.3s; + } + + .fade-leave { + position: absolute; + top: 0; + left: 0; + width: 100%; + opacity: 1; + } + + .fade-leave.fade-leave-active { + opacity: 0; + transition: opacity 0.5s ease-in-out; + } + + .fade-appear { + opacity: 0; + } + + .fade-appear.fade-appear-active { + opacity: 1; + transition: opacity 0.5s ease-in-out; + } + + +} From 5e3336a1ae54200bfc08a00237f601cdf777f103 Mon Sep 17 00:00:00 2001 From: Heather Moses Date: Mon, 3 Aug 2020 11:05:52 -0400 Subject: [PATCH 7/7] Updating components to match Lab 1 --- .../assets/stylesheets/components/App.scss | 23 ++++++++++ .../stylesheets/components/CodeEditor.scss | 7 +-- .../assets/stylesheets/components/Game.scss | 1 - .../stylesheets/components/Playthrough.scss | 3 +- .../stylesheets/components/Results.scss | 45 +++++++++++++++++-- frontend/src/assets/stylesheets/main.scss | 3 ++ .../assets/stylesheets/pages/CaseStudy.scss | 1 - frontend/src/components/body/quiz.js | 12 +++-- .../{icon-check copy.svg => icon-check.svg} | 0 .../src/quiz/svg/{logo copy.svg => logo.svg} | 0 10 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 frontend/src/assets/stylesheets/components/App.scss rename frontend/src/quiz/svg/{icon-check copy.svg => icon-check.svg} (100%) rename frontend/src/quiz/svg/{logo copy.svg => logo.svg} (100%) diff --git a/frontend/src/assets/stylesheets/components/App.scss b/frontend/src/assets/stylesheets/components/App.scss new file mode 100644 index 0000000..f14519b --- /dev/null +++ b/frontend/src/assets/stylesheets/components/App.scss @@ -0,0 +1,23 @@ +.app { + text-align: center; + + &__name { + font-size: 3.125rem; + } + + &__instructions { + font-size: 1.25rem; + margin-top: 3rem; + margin-bottom: 3rem; + } + + &__list { + margin-bottom: 2rem; + margin-left: 2.5rem; + list-style-type: disc; + + > li { + margin-bottom: 0.5rem; + } + } +} diff --git a/frontend/src/assets/stylesheets/components/CodeEditor.scss b/frontend/src/assets/stylesheets/components/CodeEditor.scss index 04a9b76..9164f7d 100755 --- a/frontend/src/assets/stylesheets/components/CodeEditor.scss +++ b/frontend/src/assets/stylesheets/components/CodeEditor.scss @@ -3,7 +3,7 @@ left: 0; right: 0; bottom: 0; - top: 0; + top: 300px; display: flex; align-items: center; @@ -153,11 +153,12 @@ .code_editor__background { position: absolute; - top: 0; + top: -150px; left: 0; right: 0; bottom: 0; - background-color: rgba(0, 0, 0, 0.3); + height:100vh; + //background-color: rgba(0, 0, 0, 0.3); z-index: 0; cursor: pointer; } diff --git a/frontend/src/assets/stylesheets/components/Game.scss b/frontend/src/assets/stylesheets/components/Game.scss index 3052783..05aac50 100755 --- a/frontend/src/assets/stylesheets/components/Game.scss +++ b/frontend/src/assets/stylesheets/components/Game.scss @@ -12,7 +12,6 @@ } &__congratulation { - margin-bottom: 5rem; font-size: 1.5rem; } } diff --git a/frontend/src/assets/stylesheets/components/Playthrough.scss b/frontend/src/assets/stylesheets/components/Playthrough.scss index 454309c..cb6e95b 100755 --- a/frontend/src/assets/stylesheets/components/Playthrough.scss +++ b/frontend/src/assets/stylesheets/components/Playthrough.scss @@ -1,8 +1,8 @@ .playthrough { padding: 2rem 0; - max-width: 700px; margin: 0 auto; text-align: left; + padding-top: 0; &__title { font-size: 2.2rem; @@ -19,7 +19,6 @@ } &__list { - margin-bottom: 2rem; margin-left: 2.5rem; list-style-type: disc; diff --git a/frontend/src/assets/stylesheets/components/Results.scss b/frontend/src/assets/stylesheets/components/Results.scss index 7f4d558..a98c9b4 100755 --- a/frontend/src/assets/stylesheets/components/Results.scss +++ b/frontend/src/assets/stylesheets/components/Results.scss @@ -1,5 +1,6 @@ .results { padding: 2rem 0; + padding-top: 0; &__title { font-size: 2.2rem; @@ -13,14 +14,50 @@ } .result { - margin: 0 auto; + //margin: 0 auto; display: grid; - grid-template-columns: 2fr 1fr; - margin-bottom: 0.75rem; - max-width: 300px; + //grid-template-columns: 2fr 1fr; + //margin-bottom: 0.75rem; + //max-width: 300px; font-size: 1.25rem; + text-align: center; &__category { font-weight: bold; } + .column-width{ + width: 33%; + } + /* Result Table */ + #title { + text-align: left; + font-family: arial, sans-serif; + } + #quizResults { + text-align: left; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + border-collapse: collapse; + border: 1px solid #6c757d; + width: 100%; + } + #quizResults td, #quizResults th { + border: 1px solid #6c757d; + font-size: 16px; + padding: 10px; + } + #quizResults th { + text-align: center; + color: #fed136; + background-color: rgb(72, 72, 72); + } + .answer-wrong{ + color: #721c24; + background-color: #f8d7da; + } + .answer-correct{ + color: #155724; + background-color: #d4edda; + } } diff --git a/frontend/src/assets/stylesheets/main.scss b/frontend/src/assets/stylesheets/main.scss index b2b740e..e42688b 100755 --- a/frontend/src/assets/stylesheets/main.scss +++ b/frontend/src/assets/stylesheets/main.scss @@ -7,6 +7,8 @@ @import "base/base"; @import "base/helpers"; +@import "components/App"; + @import "components/CodeEditor"; @import "components/Header"; @import "components/Instructions"; @@ -22,3 +24,4 @@ @import "pages/Supplementary"; @import "pages/CaseStudy"; +@import "pages/quiz"; diff --git a/frontend/src/assets/stylesheets/pages/CaseStudy.scss b/frontend/src/assets/stylesheets/pages/CaseStudy.scss index 9c40dee..ef6a806 100755 --- a/frontend/src/assets/stylesheets/pages/CaseStudy.scss +++ b/frontend/src/assets/stylesheets/pages/CaseStudy.scss @@ -1,5 +1,4 @@ .study { - width: 960px; margin: 2rem auto; font-size: 1.5rem; diff --git a/frontend/src/components/body/quiz.js b/frontend/src/components/body/quiz.js index 0791b92..9330a1b 100644 --- a/frontend/src/components/body/quiz.js +++ b/frontend/src/components/body/quiz.js @@ -1,17 +1,17 @@ import React from "react"; +import Quiz from "./../../quiz/App" import "./../../vendor/bootstrap/css/bootstrap.min.css"; import "./../../css/agency.min.css"; import "./../../css/style.css"; -import Form from "./../forms/form"; -const Quiz = ({ title, description, links }) => { +const Reading = ({ title, description, links }) => { if (links === undefined) { links = [null, null, null]; } return (
    -
    +
    @@ -22,13 +22,11 @@ const Quiz = ({ title, description, links }) => {
    -
    -
    -
    +
    ); }; -export default Quiz; +export default Reading; diff --git a/frontend/src/quiz/svg/icon-check copy.svg b/frontend/src/quiz/svg/icon-check.svg similarity index 100% rename from frontend/src/quiz/svg/icon-check copy.svg rename to frontend/src/quiz/svg/icon-check.svg diff --git a/frontend/src/quiz/svg/logo copy.svg b/frontend/src/quiz/svg/logo.svg similarity index 100% rename from frontend/src/quiz/svg/logo copy.svg rename to frontend/src/quiz/svg/logo.svg