├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── client
│ ├── actions
│ │ ├── index.js
│ │ └── types.js
│ ├── assets
│ │ └── logo.svg
│ ├── components
│ │ ├── App.js
│ │ ├── Category
│ │ │ └── Category.js
│ │ ├── Contributor
│ │ │ └── ContributorForm.js
│ │ ├── Landing
│ │ │ ├── Landing.js
│ │ │ ├── Login.js
│ │ │ ├── gitHubLoginButton.js
│ │ │ ├── landingPageCategoryButtons.js
│ │ │ └── navbar.js
│ │ └── Questionnaire
│ │ │ ├── AnswerPage.js
│ │ │ ├── QuestionPage.js
│ │ │ ├── answerBox.js
│ │ │ ├── backButton.js
│ │ │ ├── categoryName.js
│ │ │ ├── getAnswerButton.js
│ │ │ ├── nextQuestionButton.js
│ │ │ └── questionBox.js
│ ├── containers
│ │ ├── gitHubLoginContainer.js
│ │ └── landingContainer.js
│ ├── css
│ │ ├── Contributor_Form.css
│ │ ├── Landing.css
│ │ ├── Question_Page.css
│ │ └── general.css
│ ├── index.js
│ └── reducers
│ │ ├── category_reducer.js
│ │ ├── index.js
│ │ └── question_answer.js
├── config
│ └── keys.js
└── server
│ ├── model.js
│ ├── routers.js
│ └── server.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | bundle.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TheCodingGym
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | The Coding Gym
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "thecodinggym",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/simonpark107/TheCodingGym.git"
9 | },
10 | "scripts": {
11 | "start": "./node_modules/.bin/webpack -w & nodemon src/server/server.js",
12 | "client": "./node_modules/.bin/webpack",
13 | "server": "nodemon src/server/server.js",
14 | "webpack": "./node_modules/.bin/webpack -w"
15 | },
16 | "author": "",
17 | "license": "ISC",
18 | "bugs": {
19 | "url": "https://github.com/simonpark107/TheCodingGym/issues"
20 | },
21 | "homepage": "https://github.com/simonpark107/TheCodingGym#readme",
22 | "dependencies": {
23 | "axios": "^0.18.0",
24 | "cookie-parser": "^1.4.3",
25 | "eslint": "^4.19.1",
26 | "express": "^4.16.3",
27 | "lodash": "^4.17.5",
28 | "material-ui": "^0.20.0",
29 | "mongoose": "^5.0.11",
30 | "path": "^0.12.7",
31 | "react": "^16.2.0",
32 | "react-dom": "^16.2.0",
33 | "react-github-login": "^1.0.3",
34 | "react-redux": "^5.0.7",
35 | "react-router": "^4.2.0",
36 | "react-router-dom": "^4.2.2",
37 | "redux": "^3.7.2",
38 | "redux-form": "^7.3.0",
39 | "redux-promise": "^0.5.3",
40 | "redux-thunk": "^2.2.0",
41 | "request": "^2.85.0",
42 | "reset-css": "^3.0.0"
43 | },
44 | "devDependencies": {
45 | "babel": "^6.23.0",
46 | "babel-core": "^6.26.0",
47 | "babel-loader": "^7.1.4",
48 | "babel-polyfill": "^6.26.0",
49 | "babel-preset-es2015": "^6.24.1",
50 | "babel-preset-react": "^6.24.1",
51 | "babel-preset-stage-0": "^6.24.1",
52 | "babel-preset-stage-1": "^6.24.1",
53 | "babel-preset-stage-2": "^6.24.1",
54 | "babel-preset-stage-3": "^6.24.1",
55 | "css-loader": "^0.28.11",
56 | "eslint-config-airbnb": "^16.1.0",
57 | "eslint-plugin-import": "^2.9.0",
58 | "eslint-plugin-jsx-a11y": "^6.0.3",
59 | "eslint-plugin-react": "^7.7.0",
60 | "file-loader": "^1.1.11",
61 | "image-webpack-loader": "^4.2.0",
62 | "nodemon": "^1.17.2",
63 | "react-svg-loader": "^2.1.0",
64 | "react-test-renderer": "^16.2.0",
65 | "style-loader": "^0.20.3",
66 | "svg-react-loader": "^0.4.5",
67 | "url-loader": "^1.0.1",
68 | "webpack": "^3.10.0",
69 | "webpack-cli": "^2.0.13"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/client/actions/index.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import {
3 | CREATE_CONTRIBUTION,
4 | FETCH_QUESTIONS,
5 | FETCH_QUESTION,
6 | FETCH_ANSWER,
7 | DELETE_QUESTION
8 | } from './types';
9 |
10 | // CREATE CATEGORY, QUESTION & ANSWER
11 | export function createContribution(values, callback) {
12 | console.log('ACTION VALUES === ', values);
13 |
14 | //make api request. After api is resolved then call the callback function
15 | const request = axios.post('api/questions', values).then(() => callback());
16 |
17 | return {
18 | type: CREATE_CONTRIBUTION,
19 | payload: request
20 | };
21 | }
22 |
23 | // FETCH ALL QUESTIONS OF SPECIFIED CATEGORY
24 | export const fetchQuestions = (category, topic) => async dispatch => {
25 | console.log('this is fetchQ category', category);
26 | console.log('this is fetchQ topic', topic);
27 |
28 | const request = await axios({
29 | method: 'post',
30 | url: 'api/questions/',
31 | data: { category, topic }
32 | });
33 |
34 | console.log('=== ACTION ===', request);
35 |
36 | dispatch({
37 | type: FETCH_QUESTIONS,
38 | payload: request
39 | });
40 | };
41 |
42 | // FETCH SPECIFIC QUESTION
43 | export const fetchQuestion = e => async dispatch => {
44 |
45 | dispatch({
46 | type: FETCH_QUESTION,
47 | payload: e
48 | });
49 | };
50 |
--------------------------------------------------------------------------------
/src/client/actions/types.js:
--------------------------------------------------------------------------------
1 | //CREATE DATA
2 | export const CREATE_CONTRIBUTION = 'create_contribution';
3 |
4 | //GET ALL QUESTIONS
5 | export const FETCH_QUESTIONS = 'fetch_questions';
6 |
7 | //GET SPECIFIC QUESTION
8 | export const FETCH_QUESTION = 'fetch_question';
9 |
10 | //GET SPECIFIC ANSWER
11 | export const FETCH_ANSWER = 'fetch_answer';
12 |
13 | //DELETE SPECIFIC DATA
14 | export const DELETE_QUESTION = 'delete_question';
15 |
--------------------------------------------------------------------------------
/src/client/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/client/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from "react";
2 | import { Route, Redirect, Switch } from "react-router-dom";
3 | import Navbar from "./Landing/navbar"
4 | import Landing from "./Landing/Landing";
5 | import Category from "./Category/Category";
6 | import QuestionPage from "./Questionnaire/QuestionPage";
7 | import ContributorForm from "./Contributor/ContributorForm";
8 | import AnswerPage from "./Questionnaire/AnswerPage"
9 | import reset from "reset-css";
10 |
11 | class App extends Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | contributor: false
16 | };
17 | }
18 |
19 | render() {
20 | return (
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 | }
36 |
37 | export default App;
38 |
--------------------------------------------------------------------------------
/src/client/components/Category/Category.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React, { Component } from 'react';
3 | import { Link } from 'react-router-dom';
4 | import { withRouter } from 'react-router';
5 |
6 | // REDUX
7 | import { connect } from 'react-redux';
8 |
9 | // MATERIAL UI
10 | import RaisedButton from 'material-ui/RaisedButton';
11 |
12 | //LODASH
13 | import _ from 'lodash';
14 |
15 | // ACTION CREATOR
16 | import { fetchQuestion } from './../../actions';
17 |
18 | class Category extends Component {
19 | handleClick = e => {
20 | this.props.fetchQuestion(e);
21 | // this.props.fetchQuestion(e).then(() => this.props.history.push('/questionpage'));
22 | };
23 |
24 | renderCategoryName = () => {
25 | const data = this.props.category;
26 | console.log('this is data!', data);
27 | let selectedCategory = data[0].results[0].category;
28 | return selectedCategory;
29 | };
30 |
31 | renderQuestions = () => {
32 | const categoryList = this.props.category;
33 | console.log('=== CATEGORY ===', categoryList);
34 | let arr = categoryList[0].results; //returns questions and id
35 |
36 | console.log('this is array in renderQ', arr);
37 | return (
38 |
39 | {arr.map(el => {
40 | return (
41 | this.handleClick(el)} to="/questionpage" key={el._id}>
42 | this.handleClick(el)}
44 | type="submit"
45 | className="list-group-item btn btn-primary">
46 | {el.question}
47 |
48 |
49 | );
50 | })}
51 |
52 | );
53 | };
54 |
55 | render() {
56 | const style = {
57 | margin: 12
58 | };
59 |
60 | return (
61 |
62 |
{this.renderCategoryName()}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | );
75 | }
76 | }
77 |
78 | function mapStateToProps(state) {
79 | return { category: state.category };
80 | }
81 |
82 | export default withRouter(connect(mapStateToProps, { fetchQuestion })(Category));
83 |
--------------------------------------------------------------------------------
/src/client/components/Contributor/ContributorForm.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React, { Component } from 'react';
3 | import { Link } from 'react-router-dom';
4 |
5 | // REDUX
6 | import { connect } from 'react-redux';
7 | import { Field, reduxForm } from 'redux-form';
8 |
9 | // MATERIAL UI
10 | import TextField from 'material-ui/TextField';
11 | import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton';
12 | import SelectField from 'material-ui/SelectField';
13 | import MenuItem from 'material-ui/MenuItem';
14 |
15 | // FILES
16 | import Category from '../Category/Category';
17 | import './../../css/Contributor_Form.css';
18 |
19 | // ACTION CREATOR
20 | import { createContribution } from './../../actions';
21 |
22 | class ContributorForm extends Component {
23 | renderRadioGroup({ input, ...rest }) {
24 | return (
25 |
26 | input.onChange(value)}
31 | />
32 |
33 | );
34 | }
35 |
36 | renderField(field) {
37 | const classNameDanger = `form-group ${
38 | field.meta.touched && field.meta.error ? 'has-danger' : ''
39 | }`;
40 | return (
41 |
42 |
{field.fieldTitle}
43 |
44 |
45 | {field.meta.touched ? field.meta.error : ''}
46 | {/* this .meta.error property is automatically added to that field object from our validate function */}
47 |
48 |
49 | );
50 | }
51 |
52 | onSubmit(values) {
53 | //if reduxform(handleSubmit) says that everything is valid... then call onSubmit
54 | console.log('onSubmit values=== ', values);
55 | console.log('=== CREATECONTRIBUTION === ', this.props.createContribution);
56 |
57 | this.props.createContribution(values, () => {
58 | this.props.history.push('/');
59 | });
60 | }
61 |
62 | render() {
63 | const handleSubmit = this.props.handleSubmit;
64 |
65 | const style = {
66 | display: 'flex',
67 | flexDirection: 'column',
68 | width: '100%'
69 | };
70 |
71 | return (
72 |
73 |
74 | Please Select a Topic
75 |
76 |
165 |
166 | );
167 | }
168 | }
169 |
170 | function validate(values) {
171 | const errors = {};
172 |
173 | if (!values.topic) {
174 | errors.topic = 'Select a topic';
175 | }
176 | if (!values.question) {
177 | errors.question = 'Enter a question';
178 | }
179 | if (!values.answer) {
180 | errors.answer = 'Enter an answer';
181 | }
182 | return errors;
183 | }
184 |
185 | export default reduxForm({
186 | validate: validate,
187 | form: 'CreateNewQuestion'
188 | })(connect(null, { createContribution })(ContributorForm));
189 |
--------------------------------------------------------------------------------
/src/client/components/Landing/Landing.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React, { Component } from 'react';
3 |
4 | // FILES
5 | import LandingPageCategoryButtons from './landingPageCategoryButtons';
6 | import GitHubLoginContainer from '../../containers/gitHubLoginContainer';
7 | // import LandingContainer from '../../containers/landingContainer';
8 | import GitHubLoginButton from './gitHubLoginButton';
9 | import Navbar from './navbar';
10 |
11 | class Landing extends Component {
12 | render() {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 | }
25 | export default Landing;
26 |
--------------------------------------------------------------------------------
/src/client/components/Landing/Login.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | class Login extends Component {
4 | render() {
5 | return this is Category Page
;
6 | }
7 | }
8 | export default Login;
9 |
--------------------------------------------------------------------------------
/src/client/components/Landing/gitHubLoginButton.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import RaisedButton from "material-ui/RaisedButton";
3 | import FontIcon from "material-ui/FontIcon";
4 | import GitHubLogin from "react-github-login";
5 | import Keys from "../../../config/keys";
6 |
7 | const onSuccess = res => console.log(res);
8 | const onFailure = res => console.log(res);
9 |
10 | const styles = {
11 | button: {
12 | margin: 12
13 | },
14 | exampleImageInput: {
15 | cursor: "pointer",
16 | position: "absolute",
17 | top: 0,
18 | bottom: 0,
19 | right: 0,
20 | left: 0,
21 | width: "100%",
22 | opacity: 0
23 | }
24 | };
25 |
26 | const GitHubLoginButton = () => (
27 |
28 |
35 | }
41 | />
42 |
43 |
44 | );
45 |
46 | export default GitHubLoginButton;
47 |
--------------------------------------------------------------------------------
/src/client/components/Landing/landingPageCategoryButtons.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React, { Component } from 'react';
3 | import { Link } from 'react-router-dom';
4 | import { withRouter } from 'react-router';
5 |
6 | // REDUX
7 | import { connect } from 'react-redux';
8 | // ACTION CREATOR
9 | import { fetchQuestions } from './../../actions';
10 | // MATERIAL UI & CSS
11 | import RaisedButton from 'material-ui/RaisedButton';
12 | import '../../css/Landing.css';
13 |
14 | const style = {
15 | margin: '12px auto',
16 | width: 300,
17 | height: 50,
18 | display: 'block'
19 | };
20 |
21 | const nested_style = {
22 | margin: '12px auto',
23 | width: 250,
24 | height: 30,
25 | display: 'block'
26 | };
27 |
28 | class LandingPageCategoryButtons extends Component {
29 | constructor(props) {
30 | super(props);
31 | }
32 |
33 | handleClick = e => {
34 | let topic = e.currentTarget.value;
35 | console.log('this is topic', topic);
36 | let allTopics = [
37 | ['Algorithm', 'Sort', 'Recursion', 'Asymptomatic Notation', 'Data Structures'],
38 | [
39 | 'System Design',
40 | 'Principles',
41 | 'System Design Patterns',
42 | 'Scalability',
43 | 'CAP Theorem'
44 | ],
45 | [
46 | 'Front End',
47 | 'ReactJS',
48 | 'Angular',
49 | 'JavaScript',
50 | 'Vue',
51 | 'Ember',
52 | 'Redux',
53 | 'jQuery'
54 | ],
55 | ['Back End', 'Node/Express', 'PHP', '.NET', 'Ruby on Rails', 'SQL', 'NoSQL', 'Java']
56 | ];
57 | let category;
58 | let getCategoryIndex;
59 |
60 | for (let i = 0; i < allTopics.length; i++) {
61 | if (allTopics[i].includes(topic)) getCategoryIndex = i;
62 | }
63 | // console.log('this is getCategoryIndex', getCategoryIndex);
64 | switch (getCategoryIndex) {
65 | case 0:
66 | category = 'Algorithm';
67 | break;
68 | case 1:
69 | category = 'System Design';
70 | break;
71 | case 2:
72 | category = 'Front End';
73 | break;
74 | case 3:
75 | category = 'Back End';
76 | break;
77 | default:
78 | break;
79 | }
80 |
81 | this.props.fetchQuestions(category, topic).then(() => {
82 | this.props.history.push('/category');
83 | });
84 |
85 | // this.props.fetchQuestions(category, () => {
86 | // this.props.history.push('/category');
87 | // });
88 | };
89 |
90 | render() {
91 | return (
92 |
93 | {/*
94 | ///////////
95 | /// CATEGORY LEFT - ALGORITHM & SYSTEM DESIGN
96 | ///////////
97 | */}
98 |
99 | {/* ALGORITHM */}
100 |
101 |
108 |
109 |
116 |
123 |
130 |
137 |
138 |
139 |
140 | {/* FRONT END */}
141 |
142 |
149 |
150 |
157 |
164 |
171 |
178 |
185 |
192 |
199 |
200 |
201 |
202 |
203 | {/*
204 | ///////////
205 | /// CATEGORY RIGHT - FRONT-END & BACK-END
206 | ///////////
207 | */}
208 |
209 | {/* SYSTEM DESIGN */}
210 |
211 |
218 |
219 |
226 |
233 |
240 |
247 |
248 |
249 |
250 | {/* BACK END */}
251 |
252 |
259 |
260 |
267 |
274 |
281 |
288 |
295 |
302 |
309 |
310 |
311 |
312 |
313 | );
314 | }
315 | }
316 |
317 | export default withRouter(connect(null, { fetchQuestions })(LandingPageCategoryButtons));
318 |
--------------------------------------------------------------------------------
/src/client/components/Landing/navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AppBar from 'material-ui/AppBar';
3 | import IconButton from 'material-ui/IconButton';
4 | import NavigationClose from 'material-ui/svg-icons/navigation/close';
5 | import FlatButton from 'material-ui/FlatButton';
6 | import GitHubLoginButton from './gitHubLoginButton';
7 | // import logo from './../../assets/logo.svg';
8 |
9 | function handleClick() {
10 | alert('onClick triggered on the title component');
11 | }
12 |
13 | const styles = {
14 | title: {
15 | cursor: 'pointer'
16 | },
17 | gitHub: {
18 | backgroundColor: 'black'
19 | }
20 | };
21 |
22 | const image_style = {
23 | height: '50px',
24 | width: 'auto'
25 | };
26 |
27 | /**
28 | * This example uses an [IconButton](/#/components/icon-button) on the left, has a clickable `title`
29 | * through the `onClick` property, and a [FlatButton](/#/components/flat-button) on the right.
30 | */
31 | const Navbar = () => (
32 |
38 | }
39 | // onTitleClick={handleClick}
40 | // iconElementLeft={ }
41 | iconElementRight={ }
42 | />
43 | );
44 |
45 | export default Navbar;
46 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/AnswerPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import CategoryName from './categoryName';
3 | import BackButton from './backButton';
4 | import NextQuestionButton from './nextQuestionButton'
5 | import GetAnswerButton from './getAnswerButton';
6 | import QuestionBox from './questionBox'
7 | import AnswerBox from './answerBox'
8 |
9 |
10 | class AnswerPage extends Component {
11 | render() {
12 | return
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | }
30 | }
31 |
32 | const styles = {
33 | categoryName: {
34 | display: 'flex',
35 | justifyContent: 'center',
36 | },
37 | backButton: {
38 | position: 'absolute',
39 | top: 810,
40 | left: 50,
41 | },
42 | nextQuestionButton: {
43 | position: 'absolute',
44 | top: 810,
45 | left: 1390,
46 | },
47 | answerBox: {
48 | position: 'absolute',
49 | top: 630,
50 | left: 320,
51 | },
52 | questionBox: {
53 | position: 'absolute',
54 | top: 180,
55 | left: 320,
56 | }
57 | }
58 | export default AnswerPage;
59 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/QuestionPage.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React, { Component } from 'react';
3 | import { Link } from 'react-router-dom';
4 |
5 | // REDUX
6 | import { connect } from 'react-redux';
7 |
8 | // LODASH
9 | import _ from 'lodash';
10 |
11 | // FILES
12 | import Paper from 'material-ui/Paper';
13 | import NextQuestionButton from './nextQuestionButton';
14 | import GetAnswerButton from './getAnswerButton';
15 | import './../../css/Question_Page.css';
16 |
17 | class QuestionPage extends Component {
18 | // const { category } = this.props;
19 | // const { question } = category;
20 | // const { answer } = category;
21 | // const { topic } = category;
22 |
23 | renderAnswer = () => {
24 | let answer_element = document.createElement('div');
25 | answer_element.textContent = this.props.category.answer;
26 | document.querySelector('#answer').appendChild(answer_element);
27 | const btn = document.querySelector('#answer-btn');
28 | document.querySelector('#remove-btn').removeChild(btn);
29 | };
30 |
31 | render() {
32 | return (
33 |
34 |
35 | {/*
36 | {this.props.category.category}
37 | */}
38 |
39 |
40 | {this.props.category.category}
41 |
42 |
43 |
44 |
45 | {/*
46 | {this.props.category.question}
47 | */}
48 |
49 |
50 | {this.props.category.question}
51 |
52 |
53 |
54 |
55 |
59 | get answer
60 |
61 |
62 |
63 |
66 |
67 |
68 |
69 | Back
70 |
71 |
72 |
73 | {/*
74 |
75 |
*/}
76 |
77 | );
78 | }
79 | }
80 |
81 | const style = {
82 | height: 410,
83 | width: 1000,
84 | margin: 20,
85 | textAlign: 'center',
86 | display: 'inline-block',
87 | color: 'black'
88 | };
89 |
90 | const category_style = {
91 | height: 70,
92 | width: 700,
93 | margin: 20,
94 | textAlign: 'center',
95 | display: 'inline-block',
96 | color: 'black'
97 | };
98 |
99 | function mapStateToProps(state) {
100 | return { category: state.category };
101 | }
102 |
103 | export default connect(mapStateToProps)(QuestionPage);
104 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/answerBox.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Paper from 'material-ui/Paper';
3 |
4 | const style = {
5 | height: 200,
6 | width: 1000,
7 | margin: 20,
8 | textAlign: 'center',
9 | display: 'inline-block',
10 | color: 'black'
11 | };
12 |
13 | const AnswerBox = () => (
14 |
17 | );
18 |
19 | export default AnswerBox;
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/backButton.js:
--------------------------------------------------------------------------------
1 | // import React from 'react';
2 | // import RaisedButton from 'material-ui/RaisedButton';
3 |
4 | // const style = {
5 | // margin: 12,
6 | // width: 200,
7 | // };
8 |
9 | // const BackButton = () => (
10 | //
11 | //
12 | //
13 | // );
14 |
15 | // export default BackButton;
16 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/categoryName.js:
--------------------------------------------------------------------------------
1 | // import React from 'react';
2 | // import Paper from 'material-ui/Paper';
3 |
4 | // const style = {
5 | // height: 70,
6 | // width: 700,
7 | // margin: 20,
8 | // textAlign: 'center',
9 | // display: 'inline-block',
10 | // color: 'black'
11 | // };
12 |
13 | // const CategoryName = () => (
14 | //
15 | //
Category Name
16 | //
17 | // );
18 |
19 | // export default CategoryName;
20 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/getAnswerButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import RaisedButton from 'material-ui/RaisedButton';
3 |
4 | const style = {
5 | margin: 12,
6 | width: 1000
7 | };
8 |
9 | const GetAnswerButton = () => (
10 |
11 |
12 |
13 | );
14 |
15 | export default GetAnswerButton;
16 |
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/nextQuestionButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import RaisedButton from 'material-ui/RaisedButton';
3 |
4 | const style = {
5 | margin: 12,
6 | width: 200,
7 | };
8 |
9 | const NextQuestionButton = () => (
10 |
11 |
12 |
13 | );
14 |
15 | export default NextQuestionButton;
--------------------------------------------------------------------------------
/src/client/components/Questionnaire/questionBox.js:
--------------------------------------------------------------------------------
1 | // import React from 'react';
2 | // import Paper from 'material-ui/Paper';
3 |
4 | // const style = {
5 | // height: 410,
6 | // width: 1000,
7 | // margin: 20,
8 | // textAlign: 'center',
9 | // display: 'inline-block',
10 | // color: 'black'
11 | // };
12 |
13 | // const QuestionBox = () => (
14 | //
17 | // );
18 |
19 | // export default QuestionBox;
20 |
--------------------------------------------------------------------------------
/src/client/containers/gitHubLoginContainer.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | export default class gitHubLoginContainer extends Component {
4 | render() {
5 | return {this.props.children}
;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/client/containers/landingContainer.js:
--------------------------------------------------------------------------------
1 | // import React, { Component } from 'react';
2 |
3 | // export default class gitHubLoginContainer extends Component {
4 | // render() {
5 | // return {this.props.children}
;
6 | // }
7 | // }
8 |
--------------------------------------------------------------------------------
/src/client/css/Contributor_Form.css:
--------------------------------------------------------------------------------
1 | .contributor-form-container {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | .contributor-message {
7 | text-align: center;
8 | }
9 |
10 | .form-container {
11 | display: flex;
12 | flex-direction: column;
13 | }
14 |
15 | .radiobutton-left {
16 | padding-top: 50px;
17 | display: flex;
18 | }
19 |
20 | .radiobutton-right {
21 | padding-top: 50px;
22 | padding-bottom: 20px;
23 | display: flex;
24 | }
25 |
26 | .radiobutton-algorithm {
27 | width: 50%;
28 | }
29 |
30 | .radiobutton-system-design {
31 | width: 50%;
32 | }
33 |
34 | .radiobutton-front-end {
35 | width: 50%;
36 | }
37 |
38 | .radiobutton-back-end {
39 | width: 50%;
40 | }
41 |
42 | .question-answer-container {
43 | display: flex;
44 | flex-direction: column;
45 | max-width: 100%;
46 | }
47 |
48 | .form-group {
49 | width: 60%;
50 | align-self: center;
51 | }
52 |
53 | .submit-back-btn-container {
54 | width: 60%;
55 | }
56 |
57 | .contributor-back-btn {
58 | float: left !important;
59 | }
60 | .contributor-submit-btn {
61 | float: right !important;
62 | }
63 |
--------------------------------------------------------------------------------
/src/client/css/Landing.css:
--------------------------------------------------------------------------------
1 | *,
2 | ::after,
3 | ::before {
4 | -webkit-box-sizing: border-box;
5 | -moz-box-sizing: border-box;
6 | box-sizing: border-box;
7 | position: relative;
8 | }
9 |
10 | .fontawesome-i2svg-active {
11 | width: 100%;
12 | height: 100%;
13 | }
14 |
15 | #root {
16 | height: 100%;
17 | display: flex;
18 | flex-direction: column;
19 | }
20 |
21 | article,
22 | aside,
23 | details,
24 | figcaption,
25 | figure,
26 | footer,
27 | header,
28 | hgroup,
29 | main,
30 | menu,
31 | nav,
32 | section,
33 | summary {
34 | display: block;
35 | }
36 |
37 | body {
38 | font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
39 | font-size: 16px;
40 | line-height: 1.5;
41 | color: #676e7b;
42 | background-color: #f7f7f7;
43 | margin: 0;
44 | height: 100%;
45 | }
46 |
47 | main {
48 | min-width: 500px;
49 | height: 100%;
50 | display: flex;
51 | flex-direction: column;
52 | justify-content: center;
53 | }
54 |
55 | .wrapper {
56 | height: 100%;
57 | }
58 |
59 | .landing-head-container {
60 | display: flex;
61 | height: 90%;
62 | width: 100%;
63 | flex-direction: row;
64 | justify-content: space-around;
65 | }
66 |
67 | #category-btn-container {
68 | /* margin-top: 128px; */
69 | /* width: 50%; */
70 | display: flex;
71 | order: 1;
72 | margin: auto;
73 | /* float: right; */
74 | }
75 |
76 | .github-container {
77 | display: flex;
78 | border-right: 1px solid black;
79 | height: 100%;
80 | width: 50%;
81 | }
82 |
83 | .gitHubWrap {
84 | /* margin-top: 128px; */
85 | /* width: 50%; */
86 | display: flex;
87 | margin: auto;
88 | /* float: left; */
89 | }
90 |
91 | .gitHubLogin {
92 | display: flex;
93 | padding: 0;
94 | border-width: 0px;
95 | border-style: none;
96 | border-color: transparent;
97 | background-color: transparent;
98 | }
99 |
--------------------------------------------------------------------------------
/src/client/css/Question_Page.css:
--------------------------------------------------------------------------------
1 | .questionpage-container {
2 | height: 100%;
3 | width: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | }
7 |
8 | .questionpage-category-container {
9 | text-align: center;
10 | display: inline-block;
11 | width: 700px;
12 | height: 70px;
13 | }
14 |
15 | .questionpage-category-paper {
16 | background: white;
17 | height: 100%;
18 | width: 100%;
19 | }
20 |
21 | .questionpage-question-container {
22 | text-align: center;
23 | display: inline-block;
24 | width: 100%;
25 | height: 400px;
26 | }
27 |
28 | .questionpage-question-paper {
29 | background: white;
30 | }
31 |
32 | .questionpage-answer-btn-container {
33 | width: 100%;
34 | /* height: 100%; */
35 | text-align: center;
36 | }
37 |
38 | .questionpage-answer-btn {
39 | width: 50%;
40 | /* height: 50%; */
41 | }
42 |
43 | .questionpage-answer-container {
44 | background: white;
45 | width: 80%;
46 | text-align: center;
47 | height: 100px;
48 | }
49 |
50 | .questionpage-answer {
51 | position: relative;
52 | top: 50%;
53 | }
54 |
55 | .questionpage-back-btn-container {
56 | width: 100%;
57 | margin-left: 37px;
58 | }
59 |
60 | .questionpage-back-btn {
61 | width: 120px;
62 | }
63 |
--------------------------------------------------------------------------------
/src/client/css/general.css:
--------------------------------------------------------------------------------
1 | /* body {
2 | background-color: lightgray
3 | } */
4 |
--------------------------------------------------------------------------------
/src/client/index.js:
--------------------------------------------------------------------------------
1 | // REACT
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { BrowserRouter } from 'react-router-dom';
5 |
6 | // REDUX
7 | import { Provider } from 'react-redux';
8 | import { createStore, applyMiddleware } from 'redux';
9 | import reduxThunk from 'redux-thunk';
10 | import promise from 'redux-promise';
11 |
12 | // MATERIAL UI
13 |
14 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
15 |
16 |
17 | // FILES
18 | import App from './components/App';
19 | import reducers from './reducers';
20 |
21 | const store = applyMiddleware(reduxThunk)(createStore); //Redux Store
22 | // const store = createStore(reducers, {}, applyMiddleware(reduxThunk));
23 |
24 | ReactDOM.render(
25 |
26 | {/* "Provider": react component that knows how to read changes from the redux store anytime the redux store gets some new state and then will update all its children with the changed state */}
27 |
28 |
29 |
30 |
31 |
32 | ,
33 | document.getElementById('root')
34 | );
35 |
--------------------------------------------------------------------------------
/src/client/reducers/category_reducer.js:
--------------------------------------------------------------------------------
1 | import { FETCH_QUESTIONS, FETCH_QUESTION } from './../actions/types';
2 | import _ from 'lodash';
3 |
4 | export default function(state = {}, action) {
5 | //REDUCER
6 | switch (action.type) {
7 | case FETCH_QUESTIONS:
8 | return _.map(action.payload);
9 |
10 | case FETCH_QUESTION:
11 | return action.payload;
12 |
13 | default:
14 | return state;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/client/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import { reducer as formReducer } from 'redux-form';
3 | import CategoryReducer from './category_reducer';
4 |
5 | const rootReducer = combineReducers({
6 | form: formReducer,
7 | category: CategoryReducer
8 | });
9 |
10 | export default rootReducer;
11 |
--------------------------------------------------------------------------------
/src/client/reducers/question_answer.js:
--------------------------------------------------------------------------------
1 | // import { FETCH_QUESTION } from './../actions/types';
2 | // import _ from 'lodash';
3 |
4 | // export default function(state = {}, action) {
5 | // //REDUCER
6 | // switch (action.type) {
7 | // case FETCH_QUESTION:
8 | // return _.map(action.playload);
9 |
10 | // default:
11 | // return state;
12 | // }
13 | // }
14 |
--------------------------------------------------------------------------------
/src/config/keys.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | mongoURI:
3 | "mongodb://thecodinggym:cs19@ds129796.mlab.com:29796/the-coding-gym",
4 | // googleClientID: //INSERT GITHUB ID & KEYS
5 | // '380358937727-p9i36pah8vgnipaqku2gntejanah2sje.apps.googleusercontent.com',
6 | // googleClientSecret: 'vqBPv_4nHJ7l3P_H8qkthWbi',
7 | // cookieKey: 'fjkldajflakjfopbinaidfjeapfdapinviadnsfjpaijfdpj'
8 | githubID: "7793c95e193ad6cbf9b5",
9 | githubSecret: "f557ac3461eb3e83e1df07832c9ee68ee55f5c50"
10 | };
11 |
--------------------------------------------------------------------------------
/src/server/model.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const Schema = mongoose.Schema;
3 |
4 | const QandASchema = new Schema({
5 | category: String,
6 | topic: String,
7 | question: String,
8 | answer: String
9 | });
10 |
11 | module.exports = mongoose.model('QandA', QandASchema);
--------------------------------------------------------------------------------
/src/server/routers.js:
--------------------------------------------------------------------------------
1 | // import { ActionQuestionAnswer } from 'material-ui';
2 |
3 | const express = require('express');
4 | const request = require('request');
5 | const router = express.Router();
6 | const QandA = require('./model.js');
7 |
8 | router.use((req, res, next) => {
9 | console.log('this workig hereee');
10 | next();
11 | });
12 | router.get('/', (req, res) => {
13 | //on the api route localhost3000/api
14 | console.log('in here');
15 | res.json({ message: 'welcome to our api!' });
16 | });
17 |
18 | router
19 | .route('/questions')
20 | .post((req, res) => {
21 | let qAndA = new QandA();
22 | console.log(req.body, 'this is the post method here'); // create a new instance of the model
23 | qAndA.category = req.body.category;
24 | qAndA.topic = req.body.topic;
25 | qAndA.question = req.body.question; // set the question coming from the request
26 | qAndA.answer = req.body.answer; // set the answer coming from the request
27 | qAndA.save(err => {
28 | if (err) {
29 | res.send(err);
30 | } else {
31 | let selectedTopic = req.body.topic;
32 | let selectedCategory = req.body.category;
33 | // console.log(
34 | // 'this is selectedTopic: ',
35 | // selectedTopic,
36 | // ' and this is the selectedCategory: ',
37 | // selectedCategory
38 | // );
39 | if (selectedTopic === selectedCategory) {
40 | //USER SELECTED GENERAL CATEGORY AS TOPIC
41 | QandA.find({ category: selectedCategory }, (err, question) => {
42 | // console.log('this the question returned in back', question);
43 | let results = [];
44 | for (let i = 0; i < question.length; i++) {
45 | let quest = question[i].question;
46 | let ans = question[i].answer;
47 | if (quest && ans) {
48 | results.push(question[i]);
49 | }
50 | }
51 | res.json({
52 | results
53 | });
54 | });
55 | } else {
56 | //USER WANTS SPECIFIC QUESTION TOPICS
57 | QandA.find({ topic: selectedTopic }, (err, question) => {
58 | // console.log(
59 | // 'this the question returned in back when a specific topic is selected',
60 | // question
61 | // );
62 | let results = [];
63 | for (let i = 0; i < question.length; i++) {
64 | let quest = question[i].question;
65 | let ans = question[i].answer;
66 | if (quest && ans) {
67 | results.push(question[i]);
68 | }
69 | }
70 | res.json({
71 | results
72 | });
73 | });
74 | }
75 | }
76 | });
77 | })
78 | .get((req, res) => {
79 | // console.log(req.data, 'cateogry!!!!');
80 | QandA.find(req.params.questions_id, (err, question) => {
81 | (err, question) => {
82 | console.log('we here in get');
83 | // console.log('this is data from get api side', question);
84 | // let category = question.category;
85 | // let questionList = question.question;
86 | if (err) {
87 | res.send(err);
88 | console.log('got an err');
89 | }
90 | // if (req.body.category === category) { //NEED TO MODIFY DEPENDING ON HOW API CALL IS MADE ON FRONT END
91 | // res.json(questionList); //send all algo questions
92 | // } else {
93 | // console.log('are we in here')
94 | res.json(question);
95 | };
96 | });
97 | });
98 | router
99 | .route('/questions/:id') //route added to get question by ID
100 | .get((req, res) => {
101 | QandA.findById(req.params.id, (err, question) => {
102 | if (err) {
103 | res.send(err);
104 | console.log('got an err up in hurr');
105 | }
106 | res.json(question);
107 | });
108 | })
109 | .put((req, res) => {
110 | //route to update question
111 | QandA.findById(req.params.questions_id, (err, question) => {
112 | if (err) {
113 | res.send(err);
114 | console.log('got an err up in hurr in the put route');
115 | }
116 | question.answer = req.body.answer; //updates the answer
117 | question.save(err => {
118 | if (err) res.send(err);
119 | res.json({ message: 'answer updated!' });
120 | });
121 | });
122 | })
123 | .delete((req, res) => {
124 | QandA.remove(
125 | {
126 | _id: req.params.questions_id
127 | },
128 | (err, question) => {
129 | if (err) res.send(err);
130 | res.json({ message: 'successfully deleted' });
131 | }
132 | );
133 | });
134 |
135 | router.all('*', (req, res, next) => {
136 | err = new Error('router.js - default catch all route - not found');
137 | err.status = 404;
138 | next(err);
139 | });
140 |
141 | module.exports = router;
142 |
--------------------------------------------------------------------------------
/src/server/server.js:
--------------------------------------------------------------------------------
1 | // REQUIRE
2 | const path = require('path');
3 | const bodyParser = require('body-parser');
4 | const cookieParser = require('cookie-parser');
5 |
6 | // EXPRESS
7 | const express = require('express');
8 | const app = express();
9 | app.use(bodyParser.urlencoded({ extended: true }));
10 | app.use(bodyParser.json());
11 |
12 | // MONGOOSE
13 | const mongoose = require('mongoose');
14 | const keys = require('../config/keys.js');
15 | mongoose.connect(keys.mongoURI);
16 | mongoose.connection.once('open', () => {
17 | console.log('^^^^^^CONNECTED TO THE DATABASE^^^^^');
18 | });
19 |
20 | // API ROUTING
21 | const routers = require('./routers');
22 | // COOKIES
23 | app.use(cookieParser('process.env.COOKIE_SECRET'));
24 | // PATH FOR STATIC FILES
25 | app.use(express.static(`${__dirname}./../../`));
26 |
27 | // app.use('/api', router);
28 | app.use('/api', routers);
29 | // ERROR HANDLING
30 | app.use((err, req, res, next) => {
31 | res.status(404).end('error')
32 | })
33 |
34 | app.use('/css', express.static(path.join(__dirname, './../client/css')));
35 | app.get('*', (req, res) => {
36 | res.sendFile(path.join(__dirname, './../../index.html'));
37 | });
38 |
39 |
40 | const PORT = process.env.PORT || 3000;
41 |
42 | app.listen(PORT, () => console.log('******SERVER LISTENING ON PORT 3000******'));
43 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const BUILD_DIR = path.resolve(__dirname, './build');
4 | const APP_DIR = path.resolve(__dirname, './src/client');
5 |
6 | const config = {
7 | entry: {
8 | main: ['babel-polyfill', `${APP_DIR}/index.js`]
9 | },
10 | output: {
11 | filename: 'bundle.js',
12 | path: BUILD_DIR
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.(jsx|js)?$/,
18 | use: [
19 | {
20 | loader: 'babel-loader',
21 | options: {
22 | cacheDirectory: true,
23 | presets: ['react', 'es2015', 'stage-3', 'stage-2', 'stage-0'] // Transpiles JSX and ES6
24 | }
25 | }
26 | ]
27 | },
28 | {
29 | test: /.css$/,
30 | use: ['style-loader', 'css-loader']
31 | },
32 | { test: /\.(png|jpg|jpeg|gif|svg)$/, loader: 'url-loader?limit=100000' }
33 | ]
34 | },
35 | resolve: {
36 | extensions: ['.js', '.jsx']
37 | }
38 | };
39 |
40 | module.exports = config;
41 |
--------------------------------------------------------------------------------