Add teacher banner to splash page

This only shows if the logged in user is a teacher, and persists for teachers.
This commit is contained in:
Matthew Taylor 2016-06-08 13:47:11 -04:00
parent bf1fa2934d
commit ac17850491
8 changed files with 190 additions and 13 deletions

View file

@ -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 (
<TitleBanner className={classes}>
<FlexRow className="inner">
<div className="welcome">
{this.props.session.status === sessionActions.Status.FETCHED ? (
this.props.session.session.user ? [
<h3>
{this.props.messages['teacher-banner.greeting']},{' '}
{this.props.session.session.user.username}
</h3>,
<p>
{this.props.messages['teacher-banner.subgreeting']}
</p>
] : []
): []}
</div>
<FlexRow className="quick-links">
{this.props.session.status === sessionActions.Status.FETCHED ? (
this.props.session.session.user ? [
<a href="/educators/classes">
<Button>
{this.props.messages['teacher-banner.classesButton']}
</Button>
</a>,
<a href="/info/educators">
<Button>
{this.props.messages['teacher-banner.resourcesButton']}
</Button>
</a>,
<a href="/info/educators/faq">
<Button>
{this.props.messages['teacher-banner.faqButton']}
</Button>
</a>
] : []
): []}
</FlexRow>
</FlexRow>
</TitleBanner>
);
}
});
module.exports = TeacherBanner;

View file

@ -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;
}
}

View file

@ -73,6 +73,21 @@ var Jar = {
var expires = '; expires=' + new Date(new Date().setYear(new Date().getFullYear() + 1)).toUTCString(); var expires = '; expires=' + new Date(new Date().setYear(new Date().getFullYear() + 1)).toUTCString();
var path = '; path=/'; var path = '; path=/';
document.cookie = obj + expires + 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]);
});
});
} }
}; };

44
src/redux/permissions.js Normal file
View file

@ -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
};
};

View file

@ -2,12 +2,14 @@ var combineReducers = require('redux').combineReducers;
var scheduleReducer = require('./conference-schedule.js').scheduleReducer; var scheduleReducer = require('./conference-schedule.js').scheduleReducer;
var detailsReducer = require('./conference-details.js').detailsReducer; var detailsReducer = require('./conference-details.js').detailsReducer;
var permissionsReducer = require('./permissions.js').permissionsReducer;
var sessionReducer = require('./session.js').sessionReducer; var sessionReducer = require('./session.js').sessionReducer;
var tokenReducer = require('./token.js').tokenReducer; var tokenReducer = require('./token.js').tokenReducer;
var appReducer = combineReducers({ var appReducer = combineReducers({
session: sessionReducer, session: sessionReducer,
token: tokenReducer, token: tokenReducer,
permissions: permissionsReducer,
conferenceSchedule: scheduleReducer, conferenceSchedule: scheduleReducer,
conferenceDetails: detailsReducer conferenceDetails: detailsReducer
}); });

View file

@ -25,17 +25,9 @@ module.exports.tokenReducer = function (state, action) {
module.exports.getToken = function () { module.exports.getToken = function () {
return function (dispatch) { return function (dispatch) {
jar.get('scratchsessionsid', function (err, value) { jar.getSignedValue('scratchsessionsid', 'token', function (err, value) {
if (err) return dispatch(module.exports.setTokenError(err)); if (err) return dispatch(module.exports.setTokenError(err));
jar.unsign(value, function (err, contents) { return dispatch(module.exports.setToken(value));
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));
});
}); });
}; };
}; };

View file

@ -4,6 +4,7 @@ var omit = require('lodash.omit');
var React = require('react'); var React = require('react');
var render = require('../../lib/render.jsx'); var render = require('../../lib/render.jsx');
var permissionsActions = require('../../redux/permissions.js');
var sessionActions = require('../../redux/session.js'); var sessionActions = require('../../redux/session.js');
var Api = require('../../mixins/api.jsx'); 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 Modal = require('../../components/modal/modal.jsx');
var News = require('../../components/news/news.jsx'); var News = require('../../components/news/news.jsx');
var Page = require('../../components/page/www/page.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'); var Welcome = require('../../components/welcome/welcome.jsx');
require('./splash.scss'); require('./splash.scss');
@ -41,7 +43,8 @@ var Splash = injectIntl(React.createClass({
}, },
getDefaultProps: function () { getDefaultProps: function () {
return { return {
session: {} session: {},
permissions: {}
}; };
}, },
componentDidUpdate: function (prevProps) { 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 () { componentDidMount: function () {
this.getFeaturedGlobal(); this.getFeaturedGlobal();
if (this.props.session.session.user) { if (this.props.session.session.user) {
@ -371,6 +378,9 @@ var Splash = injectIntl(React.createClass({
{...omit(emailConfirmationStyle, 'padding')} /> {...omit(emailConfirmationStyle, 'padding')} />
</Modal> </Modal>
] : []} ] : []}
{this.props.permissions.educator ? [
<TeacherBanner />
] : []}
<CNBanner /> <CNBanner />
<div key="inner" className="inner"> <div key="inner" className="inner">
{this.props.session.status === sessionActions.Status.FETCHED ? ( {this.props.session.status === sessionActions.Status.FETCHED ? (
@ -431,7 +441,8 @@ var Splash = injectIntl(React.createClass({
var mapStateToProps = function (state) { var mapStateToProps = function (state) {
return { return {
session: state.session session: state.session,
permissions: state.permissions
}; };
}; };

View file

@ -27,7 +27,8 @@
} }
} }
.cn-banner { .cn-banner,
.teacher-banner {
margin-top: -20px; margin-top: -20px;
} }