Skip to content

Commit 8aca70d

Browse files
ning-yremo5000
authored andcommitted
Add help, about components, and rework profile (#265)
* Replace profile button with dropdown menu * Add the About component * Add the Help component * Add the Profile component * Remove close button on dialogs
1 parent 02841b6 commit 8aca70d

File tree

11 files changed

+419
-60
lines changed

11 files changed

+419
-60
lines changed

src/components/NavigationBar.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1-
import { Alignment, Icon, Navbar, NavbarGroup, NavbarHeading } from '@blueprintjs/core'
1+
import {
2+
Alignment,
3+
Icon,
4+
Navbar,
5+
NavbarDivider,
6+
NavbarGroup,
7+
NavbarHeading
8+
} from '@blueprintjs/core'
29
import { IconNames } from '@blueprintjs/icons'
310
import * as React from 'react'
411
import { NavLink } from 'react-router-dom'
512

613
import { Role } from '../reducers/states'
7-
import Status from './academy/Status'
14+
import Dropdown from './dropdown'
815

916
export interface INavigationBarProps {
1017
handleLogOut: () => void
@@ -54,11 +61,14 @@ const NavigationBar: React.SFC<INavigationBarProps> = props => (
5461
<div className="navbar-button-text hidden-xs">Playground</div>
5562
</NavLink>
5663

57-
{props.username !== undefined && props.role !== undefined ? (
58-
<Status username={props.username} role={props.role} handleLogOut={props.handleLogOut} />
59-
) : (
60-
undefined
61-
)}
64+
<div className="visible-xs">
65+
<NavbarDivider className="thin-divider" />
66+
</div>
67+
<div className="hidden-xs">
68+
<NavbarDivider className="default-divider" />
69+
</div>
70+
71+
<Dropdown handleLogOut={props.handleLogOut} username={props.username} />
6272
</NavbarGroup>
6373
</Navbar>
6474
)

src/components/__tests__/__snapshots__/NavigationBar.tsx.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ exports[`NavigationBar renders "Not logged in" correctly 1`] = `
2929
Playground
3030
</div>
3131
</NavLink>
32+
<div className=\\"visible-xs\\">
33+
<Blueprint2.NavbarDivider className=\\"thin-divider\\" />
34+
</div>
35+
<div className=\\"hidden-xs\\">
36+
<Blueprint2.NavbarDivider className=\\"default-divider\\" />
37+
</div>
38+
<Dropdown handleLogOut={[Function: handleLogOut]} username={[undefined]} />
3239
</Blueprint2.NavbarGroup>
3340
</Blueprint2.Navbar>"
3441
`;
@@ -62,6 +69,13 @@ exports[`NavigationBar renders correctly with username 1`] = `
6269
Playground
6370
</div>
6471
</NavLink>
72+
<div className=\\"visible-xs\\">
73+
<Blueprint2.NavbarDivider className=\\"thin-divider\\" />
74+
</div>
75+
<div className=\\"hidden-xs\\">
76+
<Blueprint2.NavbarDivider className=\\"default-divider\\" />
77+
</div>
78+
<Dropdown handleLogOut={[Function: handleLogOut]} username=\\"Evis Rucer\\" />
6579
</Blueprint2.NavbarGroup>
6680
</Blueprint2.Navbar>"
6781
`;

src/components/academy/Status.tsx

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/components/dropdown/about.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { Classes, Dialog, Tab, Tabs } from '@blueprintjs/core'
2+
import { IconNames } from '@blueprintjs/icons'
3+
import * as React from 'react'
4+
5+
type DialogProps = {
6+
isOpen: boolean
7+
onClose: () => void
8+
}
9+
10+
const About: React.SFC<DialogProps> = props => (
11+
<Dialog
12+
className="about"
13+
icon={IconNames.HELP}
14+
isCloseButtonShown={false}
15+
isOpen={props.isOpen}
16+
onClose={props.onClose}
17+
title="About"
18+
>
19+
<div className={Classes.DIALOG_BODY}>
20+
<Tabs id="about">
21+
<Tab id="abt" panel={panelAbout}>
22+
About
23+
</Tab>
24+
<Tab id="devs" panel={panelDevs()}>
25+
Developers
26+
</Tab>
27+
</Tabs>
28+
</div>
29+
</Dialog>
30+
)
31+
32+
const panelAbout = (
33+
<>
34+
<p>
35+
The <i>Source Academy</i> is an experimental environment for learning programming in the
36+
CS1101S module at the National University of Singapore.
37+
</p>
38+
<p>
39+
This iteration of Source Academy, code-named <i>Cadet</i>, is available under the MIT License.
40+
You may find the source code for Cadet at our GitHub organisation,{' '}
41+
<a href="https://github.com/source-academy">Source Academy</a>.
42+
</p>
43+
</>
44+
)
45+
46+
const dot = <span className="dot">&bull;</span>
47+
48+
const panelDevs = () => (
49+
<div className="devs">
50+
<p>
51+
<strong>Project Managers</strong>
52+
</p>
53+
<p>Martin Henz {dot} Evan Sebastian</p>
54+
<p>
55+
<strong>Frontend Team</strong>
56+
</p>
57+
{Math.round(Math.random()) === 0 ? (
58+
<p>Lee Ning Yuan {dot} Vignesh Shankar</p>
59+
) : (
60+
<p>Vignesh Shankar {dot} Lee Ning Yuan </p>
61+
)}
62+
<p>
63+
<strong>Backend Team</strong>
64+
</p>
65+
<p>
66+
Julius Putra Tanu Setiaji {dot} Chen Shaowei {dot} Sreyans Sipani
67+
</p>
68+
<p>
69+
<strong>Artistic Team</strong>
70+
</p>
71+
<p>
72+
Ng Tse Pei {dot} Joey Yeo {dot} Tan Yu Wei
73+
</p>
74+
</div>
75+
)
76+
77+
export default About

src/components/dropdown/help.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Classes, Dialog } from '@blueprintjs/core'
2+
import { IconNames } from '@blueprintjs/icons'
3+
import * as React from 'react'
4+
5+
type DialogProps = {
6+
isOpen: boolean
7+
onClose: () => void
8+
}
9+
10+
const Help: React.SFC<DialogProps> = props => (
11+
<Dialog
12+
className="help"
13+
icon={IconNames.ERROR}
14+
isCloseButtonShown={false}
15+
isOpen={props.isOpen}
16+
onClose={props.onClose}
17+
title="Help"
18+
>
19+
<div className={Classes.DIALOG_BODY}>
20+
<p>Please use the following resources when you encounter issues with this system.</p>
21+
<ul>
22+
<li>
23+
For critical technical issues that seriously affect your learning experience, email the
24+
Technical Services of the NUS School of Computing at{' '}
25+
<a href="mailto:[email protected]">[email protected]</a> or call 6516 2736.
26+
</li>
27+
<li>
28+
For non-critical technical issues, such as enhancement suggestions, please use the issue
29+
system of the{' '}
30+
<a href="https://github.com/source-academy">Source Academy repositories on GitHub</a>.
31+
</li>
32+
<li>
33+
For issues related to the content of missions, quests, paths and contests, use the
34+
respective forum at <a href="https://piazza.com/nus.edu.sg/fall2018/cs1101s"> piazza</a>,{' '}
35+
or approach your Avenger, Reflection instructor or lecturer.
36+
</li>
37+
</ul>
38+
</div>
39+
</Dialog>
40+
)
41+
42+
export default Help

src/components/dropdown/index.tsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Menu, MenuItem, Popover, Position } from '@blueprintjs/core'
2+
import { IconNames } from '@blueprintjs/icons'
3+
import * as React from 'react'
4+
5+
import Profile from '../../containers/ProfileContainer'
6+
import { controlButton } from '../commons/controlButton'
7+
import About from './about'
8+
import Help from './help'
9+
10+
type DropdownProps = {
11+
handleLogOut: () => void
12+
username?: string
13+
}
14+
15+
type DropdownState = {
16+
isAboutOpen: boolean
17+
isHelpOpen: boolean
18+
isProfileOpen: boolean
19+
}
20+
21+
class Dropdown extends React.Component<DropdownProps, DropdownState> {
22+
constructor(props: DropdownProps) {
23+
super(props)
24+
this.state = {
25+
isAboutOpen: false,
26+
isHelpOpen: false,
27+
isProfileOpen: false
28+
}
29+
}
30+
31+
public render() {
32+
return (
33+
<>
34+
<Popover
35+
content={this.menu(this.props)}
36+
inheritDarkTheme={false}
37+
position={Position.BOTTOM}
38+
>
39+
{controlButton('', IconNames.CARET_DOWN)}
40+
</Popover>
41+
<About isOpen={this.state.isAboutOpen} onClose={this.toggleAboutOpen} />
42+
<Help isOpen={this.state.isHelpOpen} onClose={this.toggleHelpOpen} />
43+
<Profile isOpen={this.state.isProfileOpen} onClose={this.toggleProfileOpen} />
44+
</>
45+
)
46+
}
47+
48+
private menu(props: DropdownProps) {
49+
const profile = this.props.username ? (
50+
<MenuItem
51+
icon={IconNames.USER}
52+
onClick={this.toggleProfileOpen}
53+
text={titleCase(this.props.username)}
54+
/>
55+
) : null
56+
57+
const logout = this.props.username ? (
58+
<MenuItem icon={IconNames.LOG_OUT} text="Logout" onClick={this.props.handleLogOut} />
59+
) : null
60+
61+
return (
62+
<Menu>
63+
{profile}
64+
<MenuItem icon={IconNames.HELP} onClick={this.toggleAboutOpen} text="About" />
65+
<MenuItem icon={IconNames.ERROR} onClick={this.toggleHelpOpen} text="Help" />
66+
{logout}
67+
</Menu>
68+
)
69+
}
70+
71+
private toggleAboutOpen = () => {
72+
this.setState({ ...this.state, isAboutOpen: !this.state.isAboutOpen })
73+
}
74+
75+
private toggleHelpOpen = () =>
76+
this.setState({ ...this.state, isHelpOpen: !this.state.isHelpOpen })
77+
78+
private toggleProfileOpen = () =>
79+
this.setState({ ...this.state, isProfileOpen: !this.state.isProfileOpen })
80+
}
81+
82+
const titleCase = (str: string) =>
83+
str.replace(/\w\S*/g, wrd => wrd.charAt(0).toUpperCase() + wrd.substr(1).toLowerCase())
84+
85+
export default Dropdown

0 commit comments

Comments
 (0)