Skip to content

Commit

Permalink
Merge 43e5962 into ad70de0
Browse files Browse the repository at this point in the history
  • Loading branch information
ning-y committed Jul 24, 2018
2 parents ad70de0 + 43e5962 commit be45b50
Show file tree
Hide file tree
Showing 17 changed files with 100 additions and 44 deletions.
3 changes: 3 additions & 0 deletions src/actions/actionTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export interface IAction extends ReduxAction {
/** Academy */
export const SAVE_CANVAS = 'SAVE_CANVAS'

/** Commons (used by many) */
export const LOG_OUT = 'LOG_OUT'

/** Playground */
export const CHANGE_QUERY_STRING = 'CHANGE_QUERY_STRING'
export const GENERATE_LZ_STRING = 'GENERATE_LZ_STRING'
Expand Down
5 changes: 5 additions & 0 deletions src/actions/commons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as actionTypes from './actionTypes'

export const logOut = () => ({
type: actionTypes.LOG_OUT
})
1 change: 1 addition & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './commons'
export * from './game'
export * from './interpreter'
export * from './playground'
Expand Down
14 changes: 10 additions & 4 deletions src/components/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ import NotFound from './NotFound'
export interface IApplicationProps extends IDispatchProps, IStateProps, RouteComponentProps<{}> {}

export interface IStateProps {
title: string
accessToken?: string
role?: Role
username?: string
currentPlaygroundChapter: number
currentPlaygroundExternals: string[]
role?: Role
title: string
username?: string
}

export interface IDispatchProps {
handleClearContext: (chapter: number, externals: string[]) => void
handleEditorValueChange: (val: string) => void
handleLogOut: () => void
}

const Application: React.SFC<IApplicationProps> = props => {
Expand All @@ -34,7 +35,12 @@ const Application: React.SFC<IApplicationProps> = props => {

return (
<div className="Application">
<NavigationBar title={props.title} username={props.username} role={props.role} />
<NavigationBar
handleLogOut={props.handleLogOut}
role={props.role}
username={props.username}
title={props.title}
/>
<div className="Application__main">
<Switch>
<Route path="/academy" component={toAcademy(props)} />
Expand Down
5 changes: 3 additions & 2 deletions src/components/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { Role } from '../reducers/states'
import Status from './academy/Status'

export interface INavigationBarProps {
handleLogOut: () => void
role?: Role
title: string
username?: string
role?: Role
}

const NavigationBar: React.SFC<INavigationBarProps> = props => (
Expand Down Expand Up @@ -54,7 +55,7 @@ const NavigationBar: React.SFC<INavigationBarProps> = props => (
</NavLink>

{props.username !== undefined && props.role !== undefined ? (
<Status username={props.username} role={props.role} />
<Status username={props.username} role={props.role} handleLogOut={props.handleLogOut} />
) : (
undefined
)}
Expand Down
3 changes: 2 additions & 1 deletion src/components/__tests__/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ test('Application renders correctly', () => {
currentPlaygroundChapter: 2,
currentPlaygroundExternals: [],
handleClearContext: (chapter: number, externals: string[]) => {},
handleEditorValueChange: (val: string) => {}
handleEditorValueChange: (val: string) => {},
handleLogOut: () => {}
}
const app = <Application {...props} />
const tree = shallow(app)
Expand Down
13 changes: 11 additions & 2 deletions src/components/__tests__/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@ import { shallow } from 'enzyme'
import NavigationBar from '../NavigationBar'

test('NavigationBar renders "Not logged in" correctly', () => {
const tree = shallow(<NavigationBar title="Cadet" />)
const props = {
handleLogOut: () => {},
title: 'Source Academy'
}
const tree = shallow(<NavigationBar {...props} />)
expect(tree.debug()).toMatchSnapshot()
})

test('NavigationBar renders correctly with username', () => {
const tree = shallow(<NavigationBar title="Cadet" username="Evis Rucer" />)
const props = {
handleLogOut: () => {},
title: 'Source Academy',
username: 'Evis Rucer'
}
const tree = shallow(<NavigationBar {...props} />)
expect(tree.debug()).toMatchSnapshot()
})
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`Application renders correctly 1`] = `
"<div className=\\"Application\\">
<NavigationBar title=\\"Cadet\\" username={[undefined]} role={[undefined]} />
<NavigationBar handleLogOut={[Function: handleLogOut]} role={[undefined]} username={[undefined]} title=\\"Cadet\\" />
<div className=\\"Application__main\\">
<Switch>
<Route path=\\"/academy\\" component={[Function]} />
Expand Down
23 changes: 17 additions & 6 deletions src/components/academy/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { controlButton } from '../commons'
type StatusProps = OwnProps

type OwnProps = {
handleLogOut: () => void
username: string
role: Role
}
Expand All @@ -20,15 +21,25 @@ const Status: React.SFC<StatusProps> = props => (
<div className="hidden-xs">
<NavbarDivider className="default-divider" />
</div>
<Popover popoverClassName="Popover-share pt-dark" inheritDarkTheme={true}>
<div className="navbar-button-text hidden-xs">
{controlButton(titleCase(props.username), IconNames.USER)}
</div>
{StatusPopover(props)}
</>
)

const StatusPopover = (props: StatusProps) => (
<Popover popoverClassName="Popover-share pt-dark" inheritDarkTheme={true}>
<div className="navbar-button-text hidden-xs">
{controlButton(titleCase(props.username), IconNames.USER)}
</div>
<div className="Popover-status-content">
<Text>
<h4>{`Source Academy, ${titleCase(props.role)}`}</h4>
</Text>
</Popover>
</>
{controlButton('Log Out', IconNames.LOG_OUT, props.handleLogOut, {
minimal: false,
iconOnRight: true
})}
</div>
</Popover>
)

const titleCase = (str: string) =>
Expand Down
5 changes: 3 additions & 2 deletions src/containers/ApplicationContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'
import { withRouter } from 'react-router'
import { bindActionCreators, Dispatch } from 'redux'

import { clearContext, updateEditorValue } from '../actions'
import { clearContext, logOut, updateEditorValue } from '../actions'
import { WorkspaceLocations } from '../actions/workspaces'
import Application, { IDispatchProps, IStateProps } from '../components/Application'
import { ExternalLibraryNames } from '../components/assessment/assessmentShape'
Expand Down Expand Up @@ -31,7 +31,8 @@ const mapDispatchToProps: MapDispatchToProps<IDispatchProps, {}> = (dispatch: Di
{
handleClearContext: (chapter: number, externals: string[]) =>
clearContext(chapter, externals, ExternalLibraryNames.NONE, workspaceLocation),
handleEditorValueChange: (val: string) => updateEditorValue(val, workspaceLocation)
handleEditorValueChange: (val: string) => updateEditorValue(val, workspaceLocation),
handleLogOut: logOut
},
dispatch
)
Expand Down
8 changes: 7 additions & 1 deletion src/createStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ function createStore(history: History): Store<IState> {
...defaultState,
session: {
...defaultState.session,
...loadedStore
...loadedStore.session
},
workspaces: {
...defaultState.workspaces,
playground: loadedStore.playgroundWorkspace
? loadedStore.playgroundWorkspace
: defaultState.workspaces.playground
}
}
const createdStore = _createStore<IState>(rootReducer, initialStore, enchancers)
Expand Down
38 changes: 16 additions & 22 deletions src/localStorage.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import { IState, Role } from './reducers/states'
import { HistoryHelper } from './utils/history'
import { compressToUTF16, decompressFromUTF16 } from 'lz-string'

/**
* Note that the properties in this interface are a
* subset of the properties in IState.session, so an instance
* of an object that implements this interface cannot
* be used as a substitute for IState. Rather, it can be used
* to complement defaultState.session with saved properties.
*/
export interface ISavedState {
historyHelper: HistoryHelper
accessToken?: string
refreshToken?: string
role?: Role
username?: string
import { IPlaygroundWorkspace, ISessionState, IState } from './reducers/states'

export type ISavedState = {
session: Partial<ISessionState>
playgroundWorkspace: IPlaygroundWorkspace
}

export const loadStoredState = (): ISavedState | undefined => {
Expand All @@ -22,7 +13,7 @@ export const loadStoredState = (): ISavedState | undefined => {
if (serializedState === null) {
return undefined
} else {
return JSON.parse(serializedState) as ISavedState
return JSON.parse(decompressFromUTF16(serializedState)) as ISavedState
}
} catch (err) {
// Issue #143
Expand All @@ -33,13 +24,16 @@ export const loadStoredState = (): ISavedState | undefined => {
export const saveState = (state: IState) => {
try {
const stateToBeSaved: ISavedState = {
accessToken: state.session.accessToken,
historyHelper: state.session.historyHelper,
refreshToken: state.session.refreshToken,
role: state.session.role,
username: state.session.username
session: {
accessToken: state.session.accessToken,
historyHelper: state.session.historyHelper,
refreshToken: state.session.refreshToken,
role: state.session.role,
username: state.session.username
},
playgroundWorkspace: state.workspaces.playground
}
const serialized = JSON.stringify(stateToBeSaved)
const serialized = compressToUTF16(JSON.stringify(stateToBeSaved))
localStorage.setItem('storedState', serialized)
} catch (err) {
// Issue #143
Expand Down
4 changes: 3 additions & 1 deletion src/reducers/academy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Reducer } from 'redux'

import { IAction, SAVE_CANVAS } from '../actions/actionTypes'
import { IAction, LOG_OUT, SAVE_CANVAS } from '../actions/actionTypes'
import { defaultAcademy, IAcademyState } from './states'

export const reducer: Reducer<IAcademyState> = (state = defaultAcademy, action: IAction) => {
switch (action.type) {
case LOG_OUT:
return defaultAcademy
case SAVE_CANVAS:
return {
...state,
Expand Down
3 changes: 3 additions & 0 deletions src/reducers/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Reducer } from 'redux'

import {
IAction,
LOG_OUT,
SET_ROLE,
SET_TOKENS,
SET_USERNAME,
Expand All @@ -15,6 +16,8 @@ import { defaultSession, ISessionState } from './states'

export const reducer: Reducer<ISessionState> = (state = defaultSession, action: IAction) => {
switch (action.type) {
case LOG_OUT:
return defaultSession
case SET_ROLE:
return {
...state,
Expand Down
2 changes: 1 addition & 1 deletion src/reducers/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ interface IGradingWorkspace extends IWorkspaceState {
readonly gradingXP: number | undefined
}

interface IPlaygroundWorkspace extends IWorkspaceState {
export interface IPlaygroundWorkspace extends IWorkspaceState {
readonly playgroundExternal: ExternalLibraryName
}

Expand Down
8 changes: 8 additions & 0 deletions src/reducers/workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
EVAL_REPL,
HANDLE_CONSOLE_LOG,
IAction,
LOG_OUT,
RESET_WORKSPACE,
SEND_REPL_INPUT_TO_OUTPUT,
UPDATE_CURRENT_ASSESSMENT_ID,
Expand Down Expand Up @@ -253,6 +254,13 @@ export const reducer: Reducer<IWorkspaceManagerState> = (
output: newOutput
}
}
case LOG_OUT:
// Preserve the playground workspace even after log out
const playgroundWorkspace = state.playground
return {
...defaultWorkspaceManager,
playground: playgroundWorkspace
}
case EVAL_EDITOR:
// Forces re-render of workspace on editor eval
return {
Expand Down
7 changes: 6 additions & 1 deletion src/styles/_navigationBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@

.Popover-share {
h4 {
margin: 0.3rem 0 0.3rem 0;
margin: 0.3rem 0.5rem 0.3rem 0;
}

.Popover-status-content {
display: flex;
justify-content: center;
}
}

Expand Down

0 comments on commit be45b50

Please sign in to comment.