diff --git a/.eslintrc b/.eslintrc index 4241933e..ea5baeef 100644 --- a/.eslintrc +++ b/.eslintrc @@ -27,7 +27,7 @@ "max-len": [1, 120, 4], }, "plugins": [ - "react", "import" + "react", "jsx-a11y", "import" ], "settings": { "import/parser": "babel-eslint", diff --git a/README.md b/README.md index 971d5de1..80276d5c 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ The p5.js Web Editor is built on a MERN stack - MongoDB, Express, React/Redux, a This project does not use CSS Modules, but uses Sass. I like to follow [BEM rules](http://getbem.com/) for CSS naming conventions, write OOSCSS with placeholders and mixins, and follow the [7-1 Pattern](https://sass-guidelin.es/#the-7-1-pattern) for Sass. +I'm using [ES6](http://es6-features.org/) and transpiling to ES5 using [Babel](https://babeljs.io/). For reference to the JavaScript style guide, see the [Airbnb Style Guide](https://github.com/airbnb/javascript), [React ESLint Plugin](https://github.com/yannickcr/eslint-plugin-react). + I'm new to using ESLint, but I decided on a configuration based on some popular React/Redux boilerplates. Open to suggestions on this. If in development, you're getting annoyed with ESLint, you can remove it from `webpack.config.dev.js` in the JavaScript loader, or disable any line from eslint by commenting at the end of the line `// eslint-disable-line`. ##Dump of links I'm saving for reference diff --git a/client/components/Nav.js b/client/components/Nav.js index 3fa29e7f..1485e041 100644 --- a/client/components/Nav.js +++ b/client/components/Nav.js @@ -59,24 +59,25 @@ function Nav(props) { return (
  • - + Open

  • ); } - if (!props.user.authenticated) { - return ( -
  • -

    - - Open - -

    -
  • - ); - } + return ( +
  • +

    + + Open + +

    +
  • + ); })()}
  • @@ -87,10 +88,34 @@ function Nav(props) {

  • ); @@ -107,7 +132,9 @@ Nav.propTypes = { }).isRequired, project: PropTypes.shape({ id: PropTypes.string - }) + }), + logoutUser: PropTypes.func.isRequired, + stopSketch: PropTypes.func.isRequired }; export default Nav; diff --git a/client/images/file.svg b/client/images/file.svg new file mode 100644 index 00000000..aa19bd0c --- /dev/null +++ b/client/images/file.svg @@ -0,0 +1,14 @@ + + + + "K" file icon Copy + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/client/modules/IDE/components/EditorAccessibility.js b/client/modules/IDE/components/EditorAccessibility.js index e98b4605..dbab82ad 100644 --- a/client/modules/IDE/components/EditorAccessibility.js +++ b/client/modules/IDE/components/EditorAccessibility.js @@ -7,18 +7,18 @@ class EditorAccessibility extends React.Component { render() { let messages = []; if (this.props.lintMessages.length > 0) { - for (let i = 0; i < this.props.lintMessages.length; i++) { + this.props.lintMessages.forEach((lintMessage, i) => { messages.push( -
  • - {this.props.lintMessages[i].severity} in line - {this.props.lintMessages[i].line} : - {this.props.lintMessages[i].message} +
  • + {lintMessage.severity} in line + {lintMessage.line} : + {lintMessage.message}
  • ); - } + }); } else { messages.push( -

    There are no lint messages

    +
  • There are no lint messages
  • ); } return ( diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js index d02a0cd5..b90224bb 100644 --- a/client/modules/IDE/pages/IDEView.js +++ b/client/modules/IDE/pages/IDEView.js @@ -15,6 +15,7 @@ import * as IDEActions from '../actions/ide'; import * as ProjectActions from '../actions/project'; import * as EditorAccessibilityActions from '../actions/editorAccessibility'; import * as PreferencesActions from '../actions/preferences'; +import * as UserActions from '../../User/actions'; import { getFile, getHTMLFile, getJSFiles, getCSSFiles, setSelectedFile } from '../reducers/files'; import SplitPane from 'react-split-pane'; import Overlay from '../../App/components/Overlay'; @@ -30,6 +31,7 @@ class IDEView extends React.Component { } componentDidMount() { + this.props.stopSketch(); if (this.props.params.project_id) { const id = this.props.params.project_id; this.props.getProject(id); @@ -117,6 +119,8 @@ class IDEView extends React.Component { exportProjectAsZip={this.props.exportProjectAsZip} cloneProject={this.props.cloneProject} project={this.props.project} + logoutUser={this.props.logoutUser} + stopSketch={this.props.stopSketch} /> { + axios.get(`${ROOT_URL}/logout`, { withCredentials: true }) + .then(() => { + dispatch({ + type: ActionTypes.UNAUTH_USER + }); + }) + .catch(response => dispatch(authError(response.data.error))); + }; +} + diff --git a/client/modules/User/reducers.js b/client/modules/User/reducers.js index db3dac3e..c2f3f8ab 100644 --- a/client/modules/User/reducers.js +++ b/client/modules/User/reducers.js @@ -5,6 +5,10 @@ const user = (state = { authenticated: false }, action) => { case ActionTypes.AUTH_USER: return { ...action.user, authenticated: true }; + case ActionTypes.UNAUTH_USER: + return { + authenticated: false + }; case ActionTypes.AUTH_ERROR: return { authenticated: false diff --git a/client/styles/base/_base.scss b/client/styles/base/_base.scss index 29568ba3..dbf361c6 100644 --- a/client/styles/base/_base.scss +++ b/client/styles/base/_base.scss @@ -11,6 +11,10 @@ body, input, button { color: $light-primary-text-color; } +body { + background-color: $light-background-color; +} + .root-app, .app { min-height: 100%; height: 100%; diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss index e1fd9658..d96dfd4c 100644 --- a/client/styles/components/_console.scss +++ b/client/styles/components/_console.scss @@ -4,6 +4,8 @@ background: $console-light-background-color; z-index: 1000; overflow: hidden; + display: flex; + flex-direction: column; & > { position:relative; @@ -13,14 +15,17 @@ // assign styles to different types of console messages .preview-console__log { color: $dark-secondary-text-color; + flex: 1 0 auto; } .preview-console__error { color: $console-error-color; + flex: 1 0 auto; } .preview-console__warn { color: $console-warn-color; + flex: 1 0 auto; } } @@ -41,7 +46,7 @@ display: flex; flex-direction: column; overflow-y: auto; - height: #{121 / $base-font-size}rem; + flex: 1 0 0%; } diff --git a/client/styles/components/_nav.scss b/client/styles/components/_nav.scss index 64867783..940f6af0 100644 --- a/client/styles/components/_nav.scss +++ b/client/styles/components/_nav.scss @@ -1,6 +1,6 @@ .nav { width: 100%; - padding: #{10 / $base-font-size}rem #{40 / $base-font-size}rem; + padding: #{10 / $base-font-size}rem #{70 / $base-font-size}rem; padding-left: #{170 / $base-font-size}rem; display: flex; flex-direction: row; @@ -24,4 +24,22 @@ & + & { margin-left: #{20 / $base-font-size}rem; } + position: relative; + &:hover .nav__dropdown { + display: flex; + } +} + +.nav__dropdown { + display: none; + position: absolute; + flex-direction: column; + background-color: $light-background-color; + padding: #{10 / $base-font-size}rem; + left: #{-10 / $base-font-size}rem; + border: 1px solid $ide-border-color; + & li + li { + margin-top: #{10 / $base-font-size}rem; + } + width: #{140 / $base-font-size}rem; } \ No newline at end of file diff --git a/server/controllers/session.controller.js b/server/controllers/session.controller.js index cbee93f4..77a9e20c 100644 --- a/server/controllers/session.controller.js +++ b/server/controllers/session.controller.js @@ -30,3 +30,9 @@ export function getSession(req, res) { } return res.status(404).send({ message: 'Session does not exist' }); } + +export function destroySession(req, res) { + req.logout(); + res.json({success: true}); +} + diff --git a/server/routes/session.routes.js b/server/routes/session.routes.js index b0305d70..8b68cefd 100644 --- a/server/routes/session.routes.js +++ b/server/routes/session.routes.js @@ -7,6 +7,8 @@ router.route('/login').post(SessionController.createSession); router.route('/session').get(SessionController.getSession); +router.route('/logout').get(SessionController.destroySession); + export default router; // TODO add github authentication stuff