Something like session handling

This commit is contained in:
Ray Schamp 2015-09-16 14:44:26 -04:00
parent 438919ac72
commit d6576409f1
12 changed files with 101 additions and 18 deletions

View file

@ -48,6 +48,7 @@ lint:
$(ESLINT) ./*.js
$(ESLINT) ./server/*.js
$(ESLINT) ./src/*.jsx
$(ESLINT) ./src/providers/*.js*
$(ESLINT) ./src/mixins/*.jsx
$(ESLINT) ./src/views/**/*.jsx
$(ESLINT) ./src/components/**/*.jsx

View file

@ -31,6 +31,7 @@
"autoprefixer-loader": "2.1.0",
"classnames": "2.1.3",
"css-loader": "0.17.0",
"custom-event-polyfill": "0.2.1",
"eslint": "1.3.1",
"eslint-plugin-react": "3.3.1",
"file-loader": "0.8.4",

View file

@ -23,6 +23,9 @@
<!-- Shim/Sham ES5 polyfill for older browsers -->
<script src="/js/lib/polyfill.min.js"></script>
<!-- Session provider -->
<script src="/js/session.bundle.js"></script>
</head>
<body>

View file

@ -0,0 +1,31 @@
var React = require('react');
module.exports = React.createClass({
propTypes: {
path: React.PropTypes.string,
userId: React.PropTypes.number,
size: React.PropTypes.number,
extension: React.PropTypes.string,
version: React.PropTypes.number
},
getDefaultProps: function () {
return {
path: '//cdn2.scratch.mit.edu/get_image/user/',
userId: 2584924,
size: 32,
extension: 'png',
version: 1438702210.96
};
},
getImageUrl: function () {
return (
this.props.path + this.props.userId + '_' +
this.props.size + 'x' + this.props.size + '.' +
this.props.extension + '?v=' + this.props.version);
},
render: function () {
var url = this.getImageUrl();
return (
<img className="avatar" src={url} />);
}
});

View file

@ -0,0 +1,3 @@
.avatar {
border: 1px solid #ccc;
}

View file

@ -1,21 +1,21 @@
var React = require('react');
var classNames = require('classnames');
var Avatar = require('../avatar/avatar.jsx');
var Dropdown = require('./dropdown.jsx');
var Input = require('../forms/input.jsx');
var Login = require('../login/login.jsx');
var Session = require('../../mixins/session.jsx');
require('./navigation.scss');
module.exports = React.createClass({
mixins: [
Session
],
getInitialState: function () {
return {
'loginOpen': false,
'loggedIn': false,
'loggedInUser': {
'username': 'raimondious',
'thumbnail': '//cdn2.scratch.mit.edu/get_image/user/2584924_32x32.png'
},
'accountNavOpen': false
};
},
@ -27,10 +27,12 @@ module.exports = React.createClass({
this.setState({'loginOpen': false});
},
handleLogIn: function () {
this.setState({'loggedIn': true});
// @todo Use an api
window.updateSession(require('../../providers/session.json'));
},
handleLogOut: function () {
this.setState({'loggedIn': false});
// @todo Use an api
window.updateSession({});
},
handleClickAccountNav: function () {
this.setState({'accountNavOpen': true});
@ -39,6 +41,7 @@ module.exports = React.createClass({
this.setState({'accountNavOpen': false});
},
render: function () {
var loggedIn = !!this.state.session.token;
var classes = classNames({
'inner': true,
'logged-in': this.state.loggedIn
@ -62,7 +65,7 @@ module.exports = React.createClass({
<Input type="hidden" name="sort_by" value="datetime_shared" />
</form>
</li>
{this.state.loggedIn ? [
{loggedIn ? [
<li className="link right messages" key="messages">
<a href="/messages/" title="Messages">Messages</a>
</li>,
@ -71,8 +74,11 @@ module.exports = React.createClass({
</li>,
<li className="link right account-nav" key="account-nav">
<a className="userInfo" href="#" onClick={this.handleClickAccountNav}>
<img src={this.state.loggedInUser.thumbnail} />
{this.state.loggedInUser.username}
<Avatar
userId={this.state.session.user.id}
version={this.state.session.user.avatarVersion}
size={24} />
{this.state.session.user.username}
</a>
<Dropdown
as="ul"

View file

@ -178,11 +178,11 @@
> a {
font-weight: normal;
font-size: 0.8125rem;
img {
width: 30px;
height: 30px;
margin-right: 10px;
.avatar {
width: 24px;
height: 24px;
margin-right: 5px;
vertical-align: middle;
border-radius: 3px;
}

View file

@ -1,10 +1,13 @@
module.exports = {
getInitialState: function () {
return {
session: {}
session: window._session
};
},
updateSession: function () {
this.setState({'session': window._session});
},
componentWillMount: function () {
// @todo Fetch session from API
window.addEventListener('session', this.updateSession);
}
};

13
src/providers/session.js Normal file
View file

@ -0,0 +1,13 @@
require('xhr');
require('custom-event-polyfill');
window._session = {};
window.updateSession = function (session) {
window._session = session;
var sessionEvent = new CustomEvent('session', session);
window.dispatchEvent(sessionEvent);
};
// @todo Get the session from an API
window.updateSession(require('./session.json'));

View file

@ -0,0 +1,17 @@
{
"token": "62d43b28d86a14423e01bdb2995dbbb2",
"user": {
"id": 1709047,
"username": "thisandagain",
"avatarVersion": 1438702210.96
},
"permissions": {
"admin": true,
"social": true,
"educator": false
},
"flags": {
"has_outstanding_email_confirmation": false,
"show_welcome": false
}
}

View file

@ -30,13 +30,17 @@ var View = React.createClass({
// @todo API request for Featured
},
render: function () {
var loggedIn = !!this.state.session.token;
return (
<div className="inner">
<Intro projectCount={this.state.projectCount} />
{loggedIn ? [
<div className="splash-header">
<Activity />
<News />
</div>
] : [
<Intro projectCount={this.state.projectCount} key="intro"/>
]}
{this.state.featured.map(function (set) {
return (
<Box

View file

@ -4,6 +4,7 @@ var routes = require('./server/routes.json');
// Prepare all entry points
var entry = {
session: './src/providers/session.js',
main: './src/main.jsx'
};
routes.forEach(function (route) {