Skip to content

Commit 96eb6f8

Browse files
committed
Move components back into / temporarily to fix https://twitter.com/vjeux/status/706128843015237632 Closes #87
1 parent f077046 commit 96eb6f8

File tree

257 files changed

+18580
-0
lines changed

Some content is hidden

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

257 files changed

+18580
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
import Parse from 'parse';
9+
import PermissionsDialog from 'components/PermissionsDialog/PermissionsDialog.react';
10+
import React from 'react';
11+
12+
function validateEntry(text) {
13+
let userQuery = Parse.Query.or(
14+
new Parse.Query(Parse.User).equalTo('username', text),
15+
new Parse.Query(Parse.User).equalTo('objectId', text)
16+
);
17+
let roleQuery = new Parse.Query(Parse.Role).equalTo('name', text);
18+
let promise = new Parse.Promise();
19+
Parse.Promise.when(userQuery.find({ useMasterKey: true }), roleQuery.find({ useMasterKey: true })).then((user, role) => {
20+
if (user.length > 0) {
21+
promise.resolve({ user: user[0] });
22+
} else if (role.length > 0) {
23+
promise.resolve({ role: role[0] });
24+
} else {
25+
promise.reject();
26+
}
27+
});
28+
29+
return promise;
30+
}
31+
32+
function toPerms(acl) {
33+
if (!acl) {
34+
return { read: { '*': true }, write: { '*': true } };
35+
}
36+
let json = acl.toJSON();
37+
let perms = { read: {}, write: {} };
38+
for (let key in json) {
39+
if (json[key].read) {
40+
perms.read[key] = true;
41+
}
42+
if (json[key].write) {
43+
perms.write[key] = true;
44+
}
45+
}
46+
return perms;
47+
}
48+
49+
function toACL(perms) {
50+
let acl = {};
51+
for (let key in perms.read) {
52+
if (perms.read[key]) {
53+
acl[key] = { read: true };
54+
}
55+
}
56+
for (let key in perms.write) {
57+
if (perms.write[key]) {
58+
if (acl[key]) {
59+
acl[key].write = true;
60+
} else {
61+
acl[key] = { write: true };
62+
}
63+
}
64+
}
65+
return new Parse.ACL(acl);
66+
}
67+
68+
let ACLEditor = ({ value, onCommit }) => (
69+
<PermissionsDialog
70+
title='Edit Access Control List (ACL)'
71+
confirmText='Save ACL'
72+
details={<a href='https://parse.com/docs/ios/guide#security-object-level-access-control'>Learn more about ACLs and app security</a>}
73+
permissions={toPerms(value)}
74+
validateEntry={validateEntry}
75+
onCancel={() => {
76+
onCommit(value);
77+
}}
78+
onConfirm={(perms) => {
79+
onCommit(toACL(perms));
80+
}} />
81+
);
82+
83+
export default ACLEditor;

components/AppBadge/AppBadge.react.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
import PropTypes from 'lib/PropTypes';
9+
import React from 'react';
10+
import styles from 'components/AppBadge/AppBadge.scss';
11+
12+
let AppBadge = ({ production }) => (
13+
<span className={production ? [styles.badge, styles.prod].join(' ') : styles.badge}>
14+
{production ? 'PROD' : 'DEV'}
15+
</span>
16+
);
17+
18+
export default AppBadge;
19+
20+
AppBadge.propTypes = {
21+
production: PropTypes.bool.describe(
22+
'Indicates whether the app is in production mode or not.'
23+
)
24+
};

components/AppBadge/AppBadge.scss

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
@import 'stylesheets/globals.scss';
9+
10+
.badge {
11+
@include DosisFont;
12+
display: inline-block;
13+
height: 26px;
14+
line-height: 26px;
15+
vertical-align: middle;
16+
text-align: center;
17+
border: 1px solid #768C97;
18+
color: #768C97;
19+
border-radius: 5px;
20+
font-size: 10px;
21+
letter-spacing: 4px;
22+
width: 60px;
23+
padding-left: 3px;
24+
}
25+
26+
.prod {
27+
color: #00dc7c;
28+
border-color: #00dc7c;
29+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
import hasAncestor from 'lib/hasAncestor';
9+
import React from 'react';
10+
import styles from 'components/BooleanEditor/BooleanEditor.scss';
11+
import Toggle from 'components/Toggle/Toggle.react';
12+
13+
export default class BooleanEditor extends React.Component {
14+
constructor(props) {
15+
super();
16+
17+
this.state = {
18+
value: !!props.value
19+
};
20+
21+
this.checkExternalClick = this.checkExternalClick.bind(this);
22+
this.handleKey = this.handleKey.bind(this);
23+
}
24+
25+
componentDidMount() {
26+
document.body.addEventListener('click', this.checkExternalClick);
27+
document.body.addEventListener('keypress', this.handleKey);
28+
}
29+
30+
componentWillUnmount() {
31+
document.body.removeEventListener('click', this.checkExternalClick);
32+
document.body.removeEventListener('keypress', this.handleKey);
33+
}
34+
35+
checkExternalClick(e) {
36+
if (!hasAncestor(e.target, this.refs.input)) {
37+
this.props.onCommit(this.state.value);
38+
}
39+
}
40+
41+
handleKey(e) {
42+
if (e.keyCode === 13) {
43+
this.props.onCommit(this.state.value);
44+
}
45+
}
46+
47+
render() {
48+
return (
49+
<div ref='input' style={{ minWidth: this.props.width }} className={styles.editor}>
50+
<Toggle
51+
type={Toggle.Types.TRUE_FALSE}
52+
value={this.state.value}
53+
onChange={(value) => this.setState({ value })} />
54+
</div>
55+
);
56+
}
57+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
.editor {
9+
background: white;
10+
white-space: nowrap;
11+
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
12+
13+
> *:first-child {
14+
margin: 6px 0;
15+
}
16+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
import { dateStringUTC, isDate } from 'lib/DateUtils';
9+
import getFileName from 'lib/getFileName';
10+
import Parse from 'parse';
11+
import Pill from 'components/Pill/Pill.react';
12+
import React from 'react';
13+
import styles from 'components/BrowserCell/BrowserCell.scss';
14+
import { unselectable } from 'stylesheets/base.scss';
15+
16+
let BrowserCell = ({ type, value, hidden, width, current, onSelect, readonly, onEditChange, setRelation, onPointerClick }) => {
17+
let content = value;
18+
let classes = [styles.cell, unselectable];
19+
if (hidden) {
20+
content = '(hidden)';
21+
classes.push(styles.empty);
22+
} else if (value === undefined) {
23+
if (type === 'ACL') {
24+
content = 'Public Read + Write';
25+
} else {
26+
content = '(undefined)';
27+
classes.push(styles.empty);
28+
}
29+
} else if (value === null) {
30+
content = '(null)';
31+
classes.push(styles.empty);
32+
} else if (type === 'Pointer') {
33+
content = (
34+
<a href='javascript:;' onClick={onPointerClick.bind(undefined, value)}>
35+
<Pill value={value.id} />
36+
</a>
37+
);
38+
} else if (type === 'Date') {
39+
content = dateStringUTC(value);
40+
} else if (type === 'Boolean') {
41+
content = value ? 'True' : 'False';
42+
} else if (type === 'Array' || type === 'Object') {
43+
if (type === 'Array') {
44+
let _value = [];
45+
value.forEach((val) => {
46+
_value.push(val.constructor === Parse.Object ? val.toPointer() : val);
47+
});
48+
content = JSON.stringify(_value);
49+
} else {
50+
content = JSON.stringify(value);
51+
}
52+
} else if (type === 'File') {
53+
if (value.url()) {
54+
content = <a href={value.url()} target='_blank'><Pill value={getFileName(value)} /></a>;
55+
} else {
56+
content = <Pill value={'Uploading\u2026'} />;
57+
}
58+
} else if (type === 'ACL') {
59+
let pieces = [];
60+
let json = value.toJSON();
61+
if (json.hasOwnProperty('*')) {
62+
if (json['*'].read && json['*'].write) {
63+
pieces.push('Public Read + Write');
64+
} else if (json['*'].read) {
65+
pieces.push('Public Read');
66+
} else if (json['*'].write) {
67+
pieces.push('Public Write');
68+
}
69+
}
70+
for (let role in json) {
71+
if (role !== '*') {
72+
pieces.push(role);
73+
}
74+
}
75+
if (pieces.length === 0) {
76+
pieces.push('Master Key Only');
77+
}
78+
content = pieces.join(', ');
79+
} else if (type === 'GeoPoint') {
80+
content = `(${value.latitude}, ${value.longitude})`;
81+
} else if (type === 'Relation') {
82+
content = (
83+
<div style={{ textAlign: 'center', cursor: 'pointer' }}>
84+
<Pill onClick={() => setRelation(value)} value='View relation' />
85+
</div>
86+
);
87+
}
88+
89+
if (current) {
90+
classes.push(styles.current);
91+
}
92+
return (
93+
<span
94+
className={classes.join(' ')}
95+
style={{ width }}
96+
onClick={onSelect}
97+
onDoubleClick={() => {
98+
if (type !== 'Relation') {
99+
onEditChange(true)
100+
}
101+
}}>
102+
{content}
103+
</span>
104+
);
105+
};
106+
107+
export default BrowserCell;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
.cell {
9+
display: inline-block;
10+
overflow: hidden;
11+
text-overflow: ellipsis;
12+
cursor: default;
13+
color: #0E69A1;
14+
height: 30px;
15+
line-height: 22px;
16+
padding: 5px 4px 0;
17+
border-right: 1px solid #e3e3ea;
18+
}
19+
20+
.empty {
21+
color: #7D929F;
22+
}
23+
24+
.current {
25+
position: relative;
26+
27+
&:after {
28+
position: absolute;
29+
pointer-events: none;
30+
content: '';
31+
border: 2px solid #555572;
32+
top: 0;
33+
left: 0;
34+
right: 0;
35+
bottom: 0;
36+
}
37+
}

0 commit comments

Comments
 (0)