Skip to content

Commit 127660a

Browse files
authored
Merge pull request #1528 from ghalestrilo/feature/mobile-examples
Feature/mobile examples
2 parents 371e859 + 6638035 commit 127660a

26 files changed

+701
-213
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ S3_BUCKET_URL_BASE=<alt-for-s3-url>
2626
SESSION_SECRET=whatever_you_want_this_to_be_it_only_matters_for_production
2727
UI_ACCESS_TOKEN_ENABLED=false
2828
UPLOAD_LIMIT=250000000
29+
MOBILE_ENABLED=true

client/components/mobile/Header.jsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ import styled from 'styled-components';
33
import PropTypes from 'prop-types';
44
import { prop, remSize } from '../../theme';
55

6-
const background = transparent => prop(transparent ? 'backgroundColor' : 'MobilePanel.default.background');
7-
const textColor = prop('primaryTextColor');
6+
7+
const background = ({ transparent, inverted }) => prop(transparent === true
8+
? 'backgroundColor'
9+
: `MobilePanel.default.${inverted === true ? 'foreground' : 'background'}`);
10+
11+
const textColor = ({ transparent, inverted }) => prop((transparent === false && inverted === true)
12+
? 'MobilePanel.default.background'
13+
: 'primaryTextColor');
814

915

1016
const HeaderDiv = styled.div`
1117
position: fixed;
1218
width: 100%;
13-
background: ${props => background(props.transparent === true)};
19+
background: ${props => background(props)};
1420
color: ${textColor};
15-
padding: ${remSize(12)};
21+
padding: ${props => remSize(props.slim === true ? 2 : 12)};
1622
padding-left: ${remSize(16)};
1723
padding-right: ${remSize(16)};
1824
z-index: 1;
@@ -25,8 +31,10 @@ const HeaderDiv = styled.div`
2531
2632
svg {
2733
max-height: ${remSize(32)};
28-
padding: ${remSize(4)}
34+
padding: ${remSize(4)};
2935
}
36+
37+
& svg path { fill: ${textColor} !important; }
3038
`;
3139

3240
const IconContainer = styled.div`
@@ -48,9 +56,10 @@ const TitleContainer = styled.div`
4856
`;
4957

5058
const Header = ({
51-
title, subtitle, leftButton, children, transparent
59+
title, subtitle, leftButton, children,
60+
transparent, inverted, slim
5261
}) => (
53-
<HeaderDiv transparent={transparent}>
62+
<HeaderDiv transparent={transparent} slim={slim} inverted={inverted}>
5463
{leftButton}
5564
<TitleContainer padded={subtitle === null}>
5665
{title && <h2>{title}</h2>}
@@ -67,15 +76,19 @@ Header.propTypes = {
6776
subtitle: PropTypes.string,
6877
leftButton: PropTypes.element,
6978
children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),
70-
transparent: PropTypes.bool
79+
transparent: PropTypes.bool,
80+
inverted: PropTypes.bool,
81+
slim: PropTypes.bool,
7182
};
7283

7384
Header.defaultProps = {
7485
title: null,
7586
subtitle: null,
7687
leftButton: null,
7788
children: [],
78-
transparent: false
89+
transparent: false,
90+
inverted: false,
91+
slim: false
7992
};
8093

8194
export default Header;

client/components/mobile/Tab.jsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
import { Link } from 'react-router';
4+
import { prop, remSize } from '../../theme';
5+
6+
export default styled(Link)`
7+
box-sizing: border-box;
8+
9+
10+
background: transparent;
11+
/* border-top: ${remSize(4)} solid ${props => prop(props.selected ? 'colors.p5jsPink' : 'MobilePanel.default.background')}; */
12+
border-top: ${remSize(4)} solid ${props => (props.selected ? prop('TabHighlight') : 'transparent')};
13+
14+
color: ${prop('primaryTextColor')};
15+
16+
padding: ${remSize(8)} ${remSize(16)};
17+
width: 30%;
18+
`;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
import { prop, remSize } from '../../theme';
5+
6+
export default styled.div`
7+
display: flex;
8+
justify-content: space-between;
9+
10+
h3 { text-align: center; width: 100%; }
11+
border-top: 1px solid ${prop('Separator')};
12+
13+
background: ${props => prop('backgroundColor')};
14+
`;
15+

client/modules/IDE/actions/collections.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function getCollections(username) {
1717
} else {
1818
url = '/collections';
1919
}
20+
console.log(url);
2021
apiClient.get(url)
2122
.then((response) => {
2223
dispatch({

client/modules/IDE/components/CollectionList/CollectionList.jsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import CollectionListRow from './CollectionListRow';
2121
import ArrowUpIcon from '../../../../images/sort-arrow-up.svg';
2222
import ArrowDownIcon from '../../../../images/sort-arrow-down.svg';
2323

24+
2425
class CollectionList extends React.Component {
2526
constructor(props) {
2627
super(props);
@@ -127,6 +128,7 @@ class CollectionList extends React.Component {
127128

128129
render() {
129130
const username = this.props.username !== undefined ? this.props.username : this.props.user.username;
131+
const { mobile } = this.props;
130132

131133
return (
132134
<article className="sketches-table-container">
@@ -141,15 +143,16 @@ class CollectionList extends React.Component {
141143
<thead>
142144
<tr>
143145
{this._renderFieldHeader('name', 'Name')}
144-
{this._renderFieldHeader('createdAt', 'Date Created')}
145-
{this._renderFieldHeader('updatedAt', 'Date Updated')}
146-
{this._renderFieldHeader('numItems', '# sketches')}
146+
{this._renderFieldHeader('createdAt', `${mobile ? '' : 'Date '}Created`)}
147+
{this._renderFieldHeader('updatedAt', `${mobile ? '' : 'Date '}Updated`)}
148+
{this._renderFieldHeader('numItems', mobile ? 'Sketches' : '# sketches')}
147149
<th scope="col"></th>
148150
</tr>
149151
</thead>
150152
<tbody>
151153
{this.props.collections.map(collection =>
152154
(<CollectionListRow
155+
mobile={mobile}
153156
key={collection.id}
154157
collection={collection}
155158
user={this.props.user}
@@ -209,7 +212,8 @@ CollectionList.propTypes = {
209212
owner: PropTypes.shape({
210213
id: PropTypes.string
211214
})
212-
})
215+
}),
216+
mobile: PropTypes.bool,
213217
};
214218

215219
CollectionList.defaultProps = {
@@ -218,7 +222,8 @@ CollectionList.defaultProps = {
218222
id: undefined,
219223
owner: undefined
220224
},
221-
username: undefined
225+
username: undefined,
226+
mobile: false
222227
};
223228

224229
function mapStateToProps(state, ownProps) {

client/modules/IDE/components/CollectionList/CollectionListRow.jsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import * as ToastActions from '../../actions/toast';
1111

1212
import DownFilledTriangleIcon from '../../../../images/down-filled-triangle.svg';
1313

14+
const formatDateCell = (date, mobile = false) => format(new Date(date), 'MMM D, YYYY');
15+
1416
class CollectionListRowBase extends React.Component {
1517
static projectInCollection(project, collection) {
1618
return collection.items.find(item => item.project.id === project.id) != null;
@@ -199,7 +201,7 @@ class CollectionListRowBase extends React.Component {
199201
}
200202

201203
render() {
202-
const { collection } = this.props;
204+
const { collection, mobile } = this.props;
203205

204206
return (
205207
<tr
@@ -211,9 +213,9 @@ class CollectionListRowBase extends React.Component {
211213
{this.renderCollectionName()}
212214
</span>
213215
</th>
214-
<td>{format(new Date(collection.createdAt), 'MMM D, YYYY')}</td>
215-
<td>{format(new Date(collection.updatedAt), 'MMM D, YYYY')}</td>
216-
<td>{(collection.items || []).length}</td>
216+
<td>{mobile && 'Created: '}{format(new Date(collection.createdAt), 'MMM D, YYYY')}</td>
217+
<td>{mobile && 'Updated: '}{formatDateCell(collection.updatedAt)}</td>
218+
<td>{mobile && '# sketches: '}{(collection.items || []).length}</td>
217219
<td className="sketch-list__dropdown-column">
218220
{this.renderActions()}
219221
</td>
@@ -245,6 +247,11 @@ CollectionListRowBase.propTypes = {
245247
deleteCollection: PropTypes.func.isRequired,
246248
editCollection: PropTypes.func.isRequired,
247249
onAddSketches: PropTypes.func.isRequired,
250+
mobile: PropTypes.bool,
251+
};
252+
253+
CollectionListRowBase.defaultProps = {
254+
mobile: false,
248255
};
249256

250257
function mapDispatchToPropsSketchListRow(dispatch) {

client/modules/IDE/components/EditableInput.jsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ import EditIcon from '../../../images/pencil.svg';
55

66
// TODO I think this needs a description prop so that it's accessible
77
function EditableInput({
8-
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
8+
validate,
9+
value,
10+
emptyPlaceholder,
11+
InputComponent,
12+
inputProps,
13+
onChange,
914
}) {
1015
const [isEditing, setIsEditing] = React.useState(false);
1116
const [currentValue, setCurrentValue] = React.useState(value || '');
1217
const displayValue = currentValue || emptyPlaceholder;
1318
const hasValue = currentValue !== '';
14-
const classes = `editable-input editable-input--${isEditing ? 'is-editing' : 'is-not-editing'} editable-input--${hasValue ? 'has-value' : 'has-placeholder'}`;
19+
const classes = `editable-input editable-input--${
20+
isEditing ? 'is-editing' : 'is-not-editing'
21+
} editable-input--${hasValue ? 'has-value' : 'has-placeholder'}`;
1522
const inputRef = React.createRef();
1623

1724
React.useEffect(() => {
@@ -54,7 +61,11 @@ function EditableInput({
5461
aria-label={`Edit ${displayValue} value`}
5562
>
5663
<span>{displayValue}</span>
57-
<EditIcon className="editable-input__icon" focusable="false" aria-hidden="true" />
64+
<EditIcon
65+
className="editable-input__icon"
66+
focusable="false"
67+
aria-hidden="true"
68+
/>
5869
</button>
5970

6071
<InputComponent
@@ -68,7 +79,7 @@ function EditableInput({
6879
ref={inputRef}
6980
value={currentValue}
7081
/>
71-
</span >
82+
</span>
7283
);
7384
}
7485

@@ -84,7 +95,7 @@ EditableInput.propTypes = {
8495
emptyPlaceholder: PropTypes.string,
8596
InputComponent: PropTypes.elementType,
8697
// eslint-disable-next-line react/forbid-prop-types
87-
inputProps: PropTypes.object,
98+
inputProps: PropTypes.object, // eslint-disable-line
8899
onChange: PropTypes.func.isRequired,
89100
validate: PropTypes.func,
90101
value: PropTypes.string,

client/modules/IDE/components/NewFileForm.jsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ class NewFileForm extends React.Component {
1616
}
1717

1818
render() {
19-
const { fields: { name }, handleSubmit } = this.props;
19+
const {
20+
fields: { name },
21+
handleSubmit,
22+
} = this.props;
2023
return (
2124
<form
2225
className="new-file-form"
@@ -26,22 +29,28 @@ class NewFileForm extends React.Component {
2629
}}
2730
>
2831
<div className="new-file-form__input-wrapper">
29-
<label className="new-file-form__name-label" htmlFor="name">Name:</label>
32+
<label className="new-file-form__name-label" htmlFor="name">
33+
Name:
34+
</label>
3035
<input
3136
className="new-file-form__name-input"
3237
id="name"
3338
type="text"
3439
placeholder={this.props.t('NewFileForm.Placeholder')}
3540
maxLength="128"
3641
{...domOnlyProps(name)}
37-
ref={(element) => { this.fileName = element; }}
42+
ref={(element) => {
43+
this.fileName = element;
44+
}}
3845
/>
3946
<Button
4047
type="submit"
4148
>{this.props.t('NewFileForm.AddFileSubmit')}
4249
</Button>
4350
</div>
44-
{name.touched && name.error && <span className="form-error">{name.error}</span>}
51+
{name.touched && name.error && (
52+
<span className="form-error">{name.error}</span>
53+
)}
4554
</form>
4655
);
4756
}

client/modules/IDE/components/NewFolderForm.jsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class NewFolderForm extends React.Component {
1818

1919
render() {
2020
const {
21-
fields: { name }, handleSubmit
21+
fields: { name },
22+
handleSubmit,
2223
} = this.props;
2324
return (
2425
<form
@@ -28,7 +29,9 @@ class NewFolderForm extends React.Component {
2829
}}
2930
>
3031
<div className="new-folder-form__input-wrapper">
31-
<label className="new-folder-form__name-label" htmlFor="name">Name:</label>
32+
<label className="new-folder-form__name-label" htmlFor="name">
33+
Name:
34+
</label>
3235
<input
3336
className="new-folder-form__name-input"
3437
id="name"
@@ -43,7 +46,9 @@ class NewFolderForm extends React.Component {
4346
>{this.props.t('NewFolderForm.AddFolderSubmit')}
4447
</Button>
4548
</div>
46-
{name.touched && name.error && <span className="form-error">{name.error}</span>}
49+
{name.touched && name.error && (
50+
<span className="form-error">{name.error}</span>
51+
)}
4752
</form>
4853
);
4954
}
@@ -62,6 +67,6 @@ NewFolderForm.propTypes = {
6267
};
6368
NewFolderForm.defaultProps = {
6469
submitting: false,
65-
pristine: true
70+
pristine: true,
6671
};
6772
export default withTranslation()(NewFolderForm);

0 commit comments

Comments
 (0)