Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

user session #3

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
138 changes: 18 additions & 120 deletions src/components/menu-bar/menu-bar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -625,126 +625,24 @@ class MenuBar extends React.Component {
<SaveStatus />
)}
</div>
{this.props.sessionExists ? (
this.props.username ? (
// ************ user is logged in ************
<React.Fragment>
<a href="/mystuff/">
<div
className={classNames(
styles.menuBarItem,
styles.hoverable,
styles.mystuffButton
)}
>
<img
className={styles.mystuffIcon}
src={mystuffIcon}
/>
</div>
</a>
<AccountNav
className={classNames(
styles.menuBarItem,
styles.hoverable,
{[styles.active]: this.props.accountMenuOpen}
)}
isOpen={this.props.accountMenuOpen}
isRtl={this.props.isRtl}
menuBarMenuClassName={classNames(styles.menuBarMenu)}
onClick={this.props.onClickAccount}
onClose={this.props.onRequestCloseAccount}
onLogOut={this.props.onLogOut}
/>
</React.Fragment>
) : (
// ********* user not logged in, but a session exists
// ********* so they can choose to log in
<React.Fragment>
<div
className={classNames(
styles.menuBarItem,
styles.hoverable
)}
key="join"
onMouseUp={this.props.onOpenRegistration}
>
<FormattedMessage
defaultMessage="Join Scratch"
description="Link for creating a Scratch account"
id="gui.menuBar.joinScratch"
/>
</div>
<div
className={classNames(
styles.menuBarItem,
styles.hoverable
)}
key="login"
onMouseUp={this.props.onClickLogin}
>
<FormattedMessage
defaultMessage="Sign in"
description="Link for signing in to your Scratch account"
id="gui.menuBar.signIn"
/>
<LoginDropdown
className={classNames(styles.menuBarMenu)}
isOpen={this.props.loginMenuOpen}
isRtl={this.props.isRtl}
renderLogin={this.props.renderLogin}
onClose={this.props.onRequestCloseLogin}
/>
</div>
</React.Fragment>
)
) : (
// ******** no login session is available, so don't show login stuff
<React.Fragment>
{this.props.showComingSoon ? (
<React.Fragment>
<MenuBarItemTooltip id="mystuff">
<div
className={classNames(
styles.menuBarItem,
styles.hoverable,
styles.mystuffButton
)}
>
<img
className={styles.mystuffIcon}
src={mystuffIcon}
/>
</div>
</MenuBarItemTooltip>
<MenuBarItemTooltip
id="account-nav"
place={this.props.isRtl ? 'right' : 'left'}
>
<div
className={classNames(
styles.menuBarItem,
styles.hoverable,
styles.accountNavMenu
)}
>
<img
className={styles.profileIcon}
src={profileIcon}
/>
<span>
{'scratch-cat'}
</span>
<img
className={styles.dropdownCaretIcon}
src={dropdownCaret}
/>
</div>
</MenuBarItemTooltip>
</React.Fragment>
) : []}
</React.Fragment>
)}
{/* // ************ user is logged in ************ */}
<React.Fragment>
<AccountNav
className={classNames(
styles.menuBarItem,
styles.hoverable,
{ [styles.active]: this.props.accountMenuOpen }
)}
isOpen={this.props.accountMenuOpen}
isRtl={this.props.isRtl}
menuBarMenuClassName={classNames(
styles.menuBarMenu
)}
onClick={this.props.onClickAccount}
onClose={this.props.onRequestCloseAccount}
onLogOut={this.props.onLogOut}
/>
</React.Fragment>
</div>

{aboutButton}
Expand Down
5 changes: 4 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import GuiReducer, {guiInitialState, guiMiddleware, initEmbedded, initFullScreen
import LocalesReducer, {localesInitialState, initLocale} from './reducers/locales';
import {ScratchPaintReducer} from 'scratch-paint';
import {setFullScreen, setPlayer} from './reducers/mode';
import SessionReducer, { sessionInitialState } from "./reducers/session.js";
import {remixProject} from './reducers/project-state';
import {setAppElement} from 'react-modal';

const guiReducers = {
locales: LocalesReducer,
scratchGui: GuiReducer,
scratchPaint: ScratchPaintReducer
scratchPaint: ScratchPaintReducer,
session: SessionReducer,
};

export {
Expand All @@ -25,6 +27,7 @@ export {
initFullScreen,
initLocale,
localesInitialState,
sessionInitialState,
remixProject,
setFullScreen,
setPlayer
Expand Down
8 changes: 5 additions & 3 deletions src/lib/app-state-hoc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {createStore, combineReducers, compose} from 'redux';
import ConnectedIntlProvider from './connected-intl-provider.jsx';

import localesReducer, {initLocale, localesInitialState} from '../reducers/locales';

import sessionReducer, { sessionInitialState } from "../reducers/session";
import {setPlayer, setFullScreen} from '../reducers/mode.js';

import locales from 'scratch-l10n';
Expand Down Expand Up @@ -69,11 +69,13 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
reducers = {
locales: localesReducer,
scratchGui: guiReducer,
scratchPaint: ScratchPaintReducer
scratchPaint: ScratchPaintReducer,
session: sessionReducer,
};
initialState = {
locales: initializedLocales,
scratchGui: initializedGui
scratchGui: initializedGui,
session: sessionInitialState,
};
enhancer = composeEnhancers(guiMiddleware);
}
Expand Down
29 changes: 27 additions & 2 deletions src/lib/project-fetcher-hoc.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
activateTab,
BLOCKS_TAB_INDEX
} from '../reducers/editor-tab';
import { setSession } from "../reducers/session";

import log from './log';
import storage from './storage';
Expand All @@ -33,7 +34,7 @@ const ProjectFetcherHOC = function (WrappedComponent) {
constructor (props) {
super(props);
bindAll(this, [
'fetchProject'
'fetchProject', 'fetchUserSessionFromApi'
]);
storage.setProjectHost(props.projectHost);
storage.setAssetHost(props.assetHost);
Expand All @@ -51,6 +52,7 @@ const ProjectFetcherHOC = function (WrappedComponent) {
}
}
componentDidUpdate (prevProps) {
this.fetchUserSessionFromApi();
if (prevProps.projectHost !== this.props.projectHost) {
storage.setProjectHost(this.props.projectHost);
}
Expand Down Expand Up @@ -84,6 +86,26 @@ const ProjectFetcherHOC = function (WrappedComponent) {
log.error(err);
});
}
fetchUserSessionFromApi() {
return fetch(
'http://localhost:3000/user-session'
)
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((data) => {
this.props.onSetSession(data.username);
})
.catch((error) => {
console.error(
'There was a problem with the fetch operation:',
error
);
});
}
render () {
const {
/* eslint-disable no-unused-vars */
Expand All @@ -95,6 +117,7 @@ const ProjectFetcherHOC = function (WrappedComponent) {
onError: onErrorProp,
onFetchedProjectData: onFetchedProjectDataProp,
onProjectUnchanged,
onSetSession,
projectHost,
projectId,
reduxProjectId,
Expand Down Expand Up @@ -124,6 +147,7 @@ const ProjectFetcherHOC = function (WrappedComponent) {
onError: PropTypes.func,
onFetchedProjectData: PropTypes.func,
onProjectUnchanged: PropTypes.func,
onSetSession: PropTypes.func,
projectHost: PropTypes.string,
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
reduxProjectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
Expand All @@ -148,7 +172,8 @@ const ProjectFetcherHOC = function (WrappedComponent) {
onFetchedProjectData: (projectData, loadingState) =>
dispatch(onFetchedProjectData(projectData, loadingState)),
setProjectId: projectId => dispatch(setProjectId(projectId)),
onProjectUnchanged: () => dispatch(setProjectUnchanged())
onProjectUnchanged: () => dispatch(setProjectUnchanged()),
onSetSession: (username) => dispatch(setSession(username)),
});
// Allow incoming props to override redux-provided props. Used to mock in tests.
const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign(
Expand Down
48 changes: 48 additions & 0 deletions src/reducers/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const SET_SESSION = 'SET_SESSION';
const GET_SESSION = 'GET_SESSION';

const initialState = {
session: {
user: {
username: 'Hello Kitty',
},
},
};

const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case SET_SESSION:
return Object.assign({}, state, {
session: {
user: {
username: action.username,
},
},
});
case GET_SESSION:
return state;
default:
return state;
}
};

const getSession = function () {
return {
type: GET_SESSION,
};
};

const setSession = function (username) {
return {
type: SET_SESSION,
username: username,
};
};

export {
reducer as default,
initialState as sessionInitialState,
setSession,
getSession,
};