Skip to content

Commit f5c7a31

Browse files
committed
🔀 pull from develop
2 parents 114ab9f + 1d9bd74 commit f5c7a31

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+759
-265
lines changed

client/common/icons.jsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ import More from '../images/more.svg';
1616
import Code from '../images/code.svg';
1717
import Terminal from '../images/terminal.svg';
1818

19+
import Folder from '../images/folder-padded.svg';
20+
21+
import CircleTerminal from '../images/circle-terminal.svg';
22+
import CircleFolder from '../images/circle-folder.svg';
23+
import CircleInfo from '../images/circle-info.svg';
24+
1925

2026
// HOC that adds the right web accessibility props
2127
// https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html
@@ -81,3 +87,9 @@ export const PlayIcon = withLabel(Play);
8187
export const MoreIcon = withLabel(More);
8288
export const TerminalIcon = withLabel(Terminal);
8389
export const CodeIcon = withLabel(Code);
90+
91+
export const FolderIcon = withLabel(Folder);
92+
93+
export const CircleTerminalIcon = withLabel(CircleTerminal);
94+
export const CircleFolderIcon = withLabel(CircleFolder);
95+
export const CircleInfoIcon = withLabel(CircleInfo);

client/components/Dropdown.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const DropdownWrapper = styled.ul`
2525
display: flex;
2626
flex-direction: column;
2727
height: auto;
28-
z-index: 9999;
28+
z-index: 2;
2929
border-radius: ${remSize(6)};
3030
3131
& li:first-child { border-radius: ${remSize(5)} ${remSize(5)} 0 0; }

client/components/Nav.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import i18next from 'i18next';
99
import * as IDEActions from '../modules/IDE/actions/ide';
1010
import * as toastActions from '../modules/IDE/actions/toast';
1111
import * as projectActions from '../modules/IDE/actions/project';
12-
import { setAllAccessibleOutput } from '../modules/IDE/actions/preferences';
12+
import { setAllAccessibleOutput, setLanguage } from '../modules/IDE/actions/preferences';
1313
import { logoutUser } from '../modules/User/actions';
1414

1515
import getConfig from '../utils/getConfig';
@@ -72,7 +72,6 @@ class Nav extends React.PureComponent {
7272
document.removeEventListener('mousedown', this.handleClick, false);
7373
document.removeEventListener('keydown', this.closeDropDown, false);
7474
}
75-
7675
setDropdown(dropdown) {
7776
this.setState({
7877
dropdownOpen: dropdown
@@ -170,7 +169,7 @@ class Nav extends React.PureComponent {
170169
}
171170

172171
handleLangSelection(event) {
173-
i18next.changeLanguage(event.target.value);
172+
this.props.setLanguage(event.target.value);
174173
this.props.showToast(1500);
175174
this.props.setToastText('Toast.LangChange');
176175
this.setDropdown('none');
@@ -808,8 +807,8 @@ Nav.propTypes = {
808807
params: PropTypes.shape({
809808
username: PropTypes.string
810809
}),
811-
t: PropTypes.func.isRequired
812-
810+
t: PropTypes.func.isRequired,
811+
setLanguage: PropTypes.func.isRequired,
813812
};
814813

815814
Nav.defaultProps = {
@@ -839,7 +838,8 @@ const mapDispatchToProps = {
839838
...projectActions,
840839
...toastActions,
841840
logoutUser,
842-
setAllAccessibleOutput
841+
setAllAccessibleOutput,
842+
setLanguage
843843
};
844844

845845
export default withTranslation()(withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav)));

client/components/__test__/Nav.test.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ describe('Nav', () => {
4545
rootFile: {
4646
id: 'root-file'
4747
},
48-
t: jest.fn()
48+
t: jest.fn(),
49+
setLanguage: jest.fn()
4950
};
5051

5152
it('renders correctly', () => {
Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,66 @@
11
import React from 'react';
22
import styled from 'styled-components';
3+
import PropTypes from 'prop-types';
34
import { bindActionCreators } from 'redux';
45
import { useDispatch, useSelector } from 'react-redux';
5-
import { remSize } from '../../theme';
6+
import { remSize, prop } from '../../theme';
67
import IconButton from './IconButton';
7-
import { TerminalIcon } from '../../common/icons';
8+
import { TerminalIcon, FolderIcon } from '../../common/icons';
89
import * as IDEActions from '../../modules/IDE/actions/ide';
910

10-
const BottomBarContent = styled.h2`
11+
const BottomBarContent = styled.div`
1112
padding: ${remSize(8)};
12-
13+
display: flex;
14+
1315
svg {
1416
max-height: ${remSize(32)};
17+
18+
}
19+
20+
path { fill: ${prop('primaryTextColor')} !important }
21+
22+
.inverted {
23+
path { fill: ${prop('backgroundColor')} !important }
24+
rect { fill: ${prop('primaryTextColor')} !important }
1525
}
1626
`;
1727

18-
export default () => {
28+
// Maybe this component shouldn't be connected, and instead just receive the `actions` prop
29+
const ActionStrip = ({ toggleExplorer }) => {
1930
const { expandConsole, collapseConsole } = bindActionCreators(IDEActions, useDispatch());
2031
const { consoleIsExpanded } = useSelector(state => state.ide);
2132

22-
const actions = [{ icon: TerminalIcon, aria: 'Say Something', action: consoleIsExpanded ? collapseConsole : expandConsole }];
33+
const actions = [
34+
{
35+
icon: TerminalIcon, inverted: true, aria: 'Open terminal console', action: consoleIsExpanded ? collapseConsole : expandConsole
36+
},
37+
{ icon: FolderIcon, aria: 'Open files explorer', action: toggleExplorer }
38+
];
2339

2440
return (
2541
<BottomBarContent>
26-
{actions.map(({ icon, aria, action }) =>
27-
(<IconButton
28-
icon={icon}
29-
aria-label={aria}
30-
key={`bottom-bar-${aria}`}
31-
onClick={() => action()}
32-
/>))}
42+
{actions.map(({
43+
icon, aria, action, inverted
44+
}) =>
45+
(
46+
<IconButton
47+
inverted={inverted}
48+
className={inverted && 'inverted'}
49+
icon={icon}
50+
aria-label={aria}
51+
key={`bottom-bar-${aria}`}
52+
onClick={() => action()}
53+
/>))}
3354
</BottomBarContent>
3455
);
3556
};
57+
58+
ActionStrip.propTypes = {
59+
toggleExplorer: PropTypes.func
60+
};
61+
62+
ActionStrip.defaultProps = {
63+
toggleExplorer: () => {}
64+
};
65+
66+
export default ActionStrip;

client/components/mobile/Explorer.jsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
import PropTypes from 'prop-types';
4+
import Sidebar from './Sidebar';
5+
import ConnectedFileNode from '../../modules/IDE/components/FileNode';
6+
7+
8+
const Explorer = ({ id, canEdit, onPressClose }) => (
9+
<Sidebar title="Files" onPressClose={onPressClose}>
10+
<ConnectedFileNode id={id} canEdit={canEdit} onClickFile={() => onPressClose()} />
11+
</Sidebar>
12+
);
13+
14+
Explorer.propTypes = {
15+
id: PropTypes.number.isRequired,
16+
onPressClose: PropTypes.func,
17+
canEdit: PropTypes.bool
18+
};
19+
Explorer.defaultProps = {
20+
canEdit: false,
21+
onPressClose: () => {}
22+
};
23+
24+
export default Explorer;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import styled from 'styled-components';
4+
import { remSize, prop } from '../../theme';
5+
import Button from '../../common/Button';
6+
import IconButton from './IconButton';
7+
8+
const FloatingContainer = styled.div`
9+
position: fixed;
10+
right: ${remSize(16)};
11+
top: ${remSize(80)};
12+
13+
text-align: right;
14+
z-index: 3;
15+
16+
svg { width: ${remSize(32)}; };
17+
svg > path { fill: ${prop('Button.default.background')} !important };
18+
`;
19+
20+
const FloatingNav = ({ items }) => (
21+
<FloatingContainer>
22+
{ items.map(({ icon, onPress }) =>
23+
(
24+
<IconButton
25+
onClick={onPress}
26+
icon={icon}
27+
/>
28+
))}
29+
</FloatingContainer>
30+
);
31+
32+
FloatingNav.propTypes = {
33+
items: PropTypes.arrayOf(PropTypes.shape({
34+
icon: PropTypes.element,
35+
onPress: PropTypes.func
36+
}))
37+
};
38+
39+
FloatingNav.defaultProps = {
40+
items: []
41+
};
42+
43+
export default FloatingNav;

client/components/mobile/Header.jsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const textColor = ({ transparent, inverted }) => prop((transparent === false &&
1414

1515

1616
const HeaderDiv = styled.div`
17-
position: fixed;
17+
${props => props.fixed && 'position: fixed;'}
1818
width: 100%;
1919
background: ${props => background(props)};
2020
color: ${textColor};
@@ -57,9 +57,9 @@ const TitleContainer = styled.div`
5757

5858
const Header = ({
5959
title, subtitle, leftButton, children,
60-
transparent, inverted, slim
60+
transparent, inverted, slim, fixed
6161
}) => (
62-
<HeaderDiv transparent={transparent} slim={slim} inverted={inverted}>
62+
<HeaderDiv transparent={transparent} slim={slim} inverted={inverted} fixed={fixed}>
6363
{leftButton}
6464
<TitleContainer padded={subtitle === null}>
6565
{title && <h2>{title}</h2>}
@@ -79,6 +79,7 @@ Header.propTypes = {
7979
transparent: PropTypes.bool,
8080
inverted: PropTypes.bool,
8181
slim: PropTypes.bool,
82+
fixed: PropTypes.bool,
8283
};
8384

8485
Header.defaultProps = {
@@ -88,7 +89,8 @@ Header.defaultProps = {
8889
children: [],
8990
transparent: false,
9091
inverted: false,
91-
slim: false
92+
slim: false,
93+
fixed: true
9294
};
9395

9496
export default Header;

client/components/mobile/IDEWrapper.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import React from 'react';
22
import styled from 'styled-components';
33
import { remSize } from '../../theme';
44

5+
// Applies padding to top and bottom so editor content is always visible
6+
57
export default styled.div`
68
z-index: 0;
79
margin-top: ${remSize(16)};
10+
.CodeMirror-sizer > * { padding-bottom: ${remSize(320)}; };
811
`;

client/components/mobile/Sidebar.jsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Link } from 'react-router';
4+
import styled from 'styled-components';
5+
import { remSize, prop, common } from '../../theme';
6+
import Header from './Header';
7+
import IconButton from './IconButton';
8+
import { ExitIcon } from '../../common/icons';
9+
10+
11+
const SidebarWrapper = styled.div`
12+
height: 100%;
13+
width: ${remSize(180)};
14+
15+
position: fixed;
16+
z-index: 2;
17+
left: 0;
18+
19+
background: white;
20+
box-shadow: 0 6px 6px 0 rgba(0,0,0,0.10);
21+
`;
22+
23+
const Sidebar = ({ title, onPressClose, children }) => (
24+
<SidebarWrapper>
25+
{title &&
26+
<Header slim title={title} fixed={false}>
27+
<IconButton onClick={onPressClose} icon={ExitIcon} aria-label="Return to ide view" />
28+
</Header>}
29+
{children}
30+
</SidebarWrapper>
31+
);
32+
33+
Sidebar.propTypes = {
34+
title: PropTypes.string,
35+
onPressClose: PropTypes.func,
36+
children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
37+
};
38+
39+
Sidebar.defaultProps = {
40+
title: null,
41+
children: [],
42+
onPressClose: () => {}
43+
};
44+
45+
46+
export default Sidebar;

0 commit comments

Comments
 (0)