From ac178504918a7e8b8e9ab0331d9118a92035921c Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 8 Jun 2016 13:47:11 -0400 Subject: [PATCH] Add teacher banner to splash page This only shows if the logged in user is a teacher, and persists for teachers. --- .../teacher-banner/teacher-banner.jsx | 74 +++++++++++++++++++ .../teacher-banner/teacher-banner.scss | 38 ++++++++++ src/lib/jar.js | 15 ++++ src/redux/permissions.js | 44 +++++++++++ src/redux/reducer.js | 2 + src/redux/token.js | 12 +-- src/views/splash/splash.jsx | 15 +++- src/views/splash/splash.scss | 3 +- 8 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 src/components/teacher-banner/teacher-banner.jsx create mode 100644 src/components/teacher-banner/teacher-banner.scss create mode 100644 src/redux/permissions.js diff --git a/src/components/teacher-banner/teacher-banner.jsx b/src/components/teacher-banner/teacher-banner.jsx new file mode 100644 index 000000000..6e58fa01f --- /dev/null +++ b/src/components/teacher-banner/teacher-banner.jsx @@ -0,0 +1,74 @@ +var classNames = require('classnames'); +var React = require('react'); + +var sessionActions = require('../../redux/session.js'); + +var TitleBanner = require('../title-banner/title-banner.jsx'); +var Button = require('../forms/button.jsx'); +var FlexRow = require('../flex-row/flex-row.jsx'); + +require('./teacher-banner.scss'); + +var TeacherBanner = React.createClass({ + type: 'TeacherBanner', + getDefaultProps: function () { + return { + messages: { + 'teacher-banner.greeting': 'Hi', + 'teacher-banner.subgreeting': 'Here are some helpful links to check out:', + 'teacher-banner.classesButton': 'My Classes', + 'teacher-banner.resourcesButton': 'Learning Resources', + 'teacher-banner.faqButton': 'Teacher Account FAQ' + }, + session: {} + }; + }, + render: function () { + var classes = classNames( + 'teacher-banner', + this.props.className + ); + return ( + + +
+ {this.props.session.status === sessionActions.Status.FETCHED ? ( + this.props.session.session.user ? [ +

+ {this.props.messages['teacher-banner.greeting']},{' '} + {this.props.session.session.user.username} +

, +

+ {this.props.messages['teacher-banner.subgreeting']} +

+ ] : [] + ): []} +
+ + {this.props.session.status === sessionActions.Status.FETCHED ? ( + this.props.session.session.user ? [ + + + , + + + , + + + + ] : [] + ): []} + +
+
+ ); + } +}); + +module.exports = TeacherBanner; diff --git a/src/components/teacher-banner/teacher-banner.scss b/src/components/teacher-banner/teacher-banner.scss new file mode 100644 index 000000000..360dc4011 --- /dev/null +++ b/src/components/teacher-banner/teacher-banner.scss @@ -0,0 +1,38 @@ +@import "../../colors"; +@import "../../frameless"; + +.teacher-banner { + background-color: $ui-purple; + min-height: 65px; + + &.title-banner { + transition: none; + margin-bottom: 20px; + text-align: left; + + h3, + p { + margin: 0; + padding: 0; + width: 100%; + text-align: left; + } + } + + h3 { + color: $ui-white; + } + + .flex-row { + &.inner { + justify-content: space-between; + } + } + + .button { + margin-left: 10px; + background-color: $ui-white; + padding: 13px 20px; + color: $ui-blue; + } +} diff --git a/src/lib/jar.js b/src/lib/jar.js index 89accd5a5..c20638e1f 100644 --- a/src/lib/jar.js +++ b/src/lib/jar.js @@ -73,6 +73,21 @@ var Jar = { var expires = '; expires=' + new Date(new Date().setYear(new Date().getFullYear() + 1)).toUTCString(); var path = '; path=/'; document.cookie = obj + expires + path; + }, + getSignedValue: function (cookieName, signedValue, callback) { + // Get a value from a signed object + Jar.get(cookieName, function (err, value) { + if (err) return callback(err); + Jar.unsign(value, function (err, contents) { + if (err) return callback(err); + try { + var data = JSON.parse(contents); + } catch (err) { + return callback(err); + } + return callback(null, data[signedValue]); + }); + }); } }; diff --git a/src/redux/permissions.js b/src/redux/permissions.js new file mode 100644 index 000000000..54421ff3a --- /dev/null +++ b/src/redux/permissions.js @@ -0,0 +1,44 @@ +var keyMirror = require('keymirror'); +var jar = require('../lib/jar.js'); + +var Types = keyMirror({ + SET_PERMISSIONS: null, + SET_PERMISSIONS_ERROR: null +}); + +module.exports.permissionsReducer = function (state, action) { + if (typeof state === 'undefined') { + state = ''; + } + switch (action.type) { + case Types.SET_PERMISSIONS: + return action.permissions; + case Types.SET_PERMISSIONS_ERROR: + return state; + default: + return state; + } +}; + +module.exports.getPermissions = function () { + return function (dispatch) { + jar.getSignedValue('scratchsessionsid', 'permissions', function (err, value) { + if (err) return dispatch(module.exports.setPermissionsError(err)); + return dispatch(module.exports.setPermissions(value)); + }); + }; +}; + +module.exports.setPermissions = function (permissions) { + return { + type: Types.SET_PERMISSIONS, + permissions: permissions + }; +}; + +module.exports.setPermissionsError = function (error) { + return { + type: Types.SET_PERMISSIONS_ERROR, + error: error + }; +}; diff --git a/src/redux/reducer.js b/src/redux/reducer.js index 71bdfc11c..b7dd7b31d 100644 --- a/src/redux/reducer.js +++ b/src/redux/reducer.js @@ -2,12 +2,14 @@ var combineReducers = require('redux').combineReducers; var scheduleReducer = require('./conference-schedule.js').scheduleReducer; var detailsReducer = require('./conference-details.js').detailsReducer; +var permissionsReducer = require('./permissions.js').permissionsReducer; var sessionReducer = require('./session.js').sessionReducer; var tokenReducer = require('./token.js').tokenReducer; var appReducer = combineReducers({ session: sessionReducer, token: tokenReducer, + permissions: permissionsReducer, conferenceSchedule: scheduleReducer, conferenceDetails: detailsReducer }); diff --git a/src/redux/token.js b/src/redux/token.js index 4e742ea75..c795d5567 100644 --- a/src/redux/token.js +++ b/src/redux/token.js @@ -25,17 +25,9 @@ module.exports.tokenReducer = function (state, action) { module.exports.getToken = function () { return function (dispatch) { - jar.get('scratchsessionsid', function (err, value) { + jar.getSignedValue('scratchsessionsid', 'token', function (err, value) { if (err) return dispatch(module.exports.setTokenError(err)); - jar.unsign(value, function (err, contents) { - if (err) return dispatch(module.exports.setTokenError(err)); - try { - var sessionData = JSON.parse(contents); - } catch (err) { - return dispatch(module.exports.setTokenError(err)); - } - return dispatch(module.exports.setToken(sessionData.token)); - }); + return dispatch(module.exports.setToken(value)); }); }; }; diff --git a/src/views/splash/splash.jsx b/src/views/splash/splash.jsx index 7860d3701..b47d21f0f 100644 --- a/src/views/splash/splash.jsx +++ b/src/views/splash/splash.jsx @@ -4,6 +4,7 @@ var omit = require('lodash.omit'); var React = require('react'); var render = require('../../lib/render.jsx'); +var permissionsActions = require('../../redux/permissions.js'); var sessionActions = require('../../redux/session.js'); var Api = require('../../mixins/api.jsx'); @@ -19,6 +20,7 @@ var Intro = require('../../components/intro/intro.jsx'); var Modal = require('../../components/modal/modal.jsx'); var News = require('../../components/news/news.jsx'); var Page = require('../../components/page/www/page.jsx'); +var TeacherBanner = require('../../components/teacher-banner/teacher-banner.jsx'); var Welcome = require('../../components/welcome/welcome.jsx'); require('./splash.scss'); @@ -41,7 +43,8 @@ var Splash = injectIntl(React.createClass({ }, getDefaultProps: function () { return { - session: {} + session: {}, + permissions: {} }; }, componentDidUpdate: function (prevProps) { @@ -63,6 +66,10 @@ var Splash = injectIntl(React.createClass({ } } }, + componentWillMount: function () { + // Determine whether to show the teacher banner or not + this.props.dispatch(permissionsActions.getPermissions()); + }, componentDidMount: function () { this.getFeaturedGlobal(); if (this.props.session.session.user) { @@ -371,6 +378,9 @@ var Splash = injectIntl(React.createClass({ {...omit(emailConfirmationStyle, 'padding')} /> ] : []} + {this.props.permissions.educator ? [ + + ] : []}
{this.props.session.status === sessionActions.Status.FETCHED ? ( @@ -431,7 +441,8 @@ var Splash = injectIntl(React.createClass({ var mapStateToProps = function (state) { return { - session: state.session + session: state.session, + permissions: state.permissions }; }; diff --git a/src/views/splash/splash.scss b/src/views/splash/splash.scss index 4eae2d87c..80706e4f1 100644 --- a/src/views/splash/splash.scss +++ b/src/views/splash/splash.scss @@ -27,7 +27,8 @@ } } - .cn-banner { + .cn-banner, + .teacher-banner { margin-top: -20px; }