Skip to content

Commit 8bb93c2

Browse files
authored
Merge pull request #116 from back4app/improve-database-class-ui
Improve database class ui
2 parents e9afd98 + 6650de8 commit 8bb93c2

File tree

7 files changed

+78
-43
lines changed

7 files changed

+78
-43
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"commander": "^2.9.0",
4141
"connect-flash": "^0.1.1",
4242
"cookie-session": "^2.0.0-alpha.1",
43+
"copy-to-clipboard": "^3.0.8",
4344
"csurf": "^1.9.0",
4445
"express": "^4.13.4",
4546
"html-webpack-externals-plugin": "^3.8.0",
@@ -58,6 +59,7 @@
5859
"react-player": "^1.7.0",
5960
"react-syntax-highlighter": "^9.0.0",
6061
"react-tabs": "^2.2.2",
62+
"react-tooltip": "^3.9.2",
6163
"sweetalert2": "^7.28.10",
6264
"sweetalert2-react-content": "^1.0.1",
6365
"whatwg-fetch": "^2.0.3"

src/components/BrowserCell/BrowserCell.react.js

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,34 @@
55
* This source code is licensed under the license found in the LICENSE file in
66
* the root directory of this source tree.
77
*/
8-
import { dateStringUTC } 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';
8+
import { dateStringUTC } 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+
import ReactTooltip from 'react-tooltip'
1516

16-
let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange, setRelation, onPointerClick }) => {
17+
let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange, setRelation, onPointerClick, readonly }) => {
1718
let content = value;
1819
let classes = [styles.cell, unselectable];
20+
let readableValue = value
21+
22+
// Set read only style
23+
readonly && classes.push(styles.readonly)
1924
if (hidden) {
2025
content = '(hidden)';
2126
classes.push(styles.empty);
2227
} else if (value === undefined) {
2328
if (type === 'ACL') {
24-
content = 'Public Read + Write';
29+
readableValue = content = 'Public Read + Write';
2530
} else {
26-
content = '(undefined)';
31+
readableValue = content = '(undefined)';
2732
classes.push(styles.empty);
2833
}
2934
} else if (value === null) {
30-
content = '(null)';
35+
readableValue = content = '(null)';
3136
classes.push(styles.empty);
3237
} else if (value === '') {
3338
content = <span>&nbsp;</span>;
@@ -38,20 +43,22 @@ let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange
3843
<Pill value={value.id} />
3944
</a>
4045
);
46+
readableValue = value.id;
4147
} else if (type === 'Date') {
42-
content = dateStringUTC(value);
48+
readableValue = content = dateStringUTC(value);
4349
} else if (type === 'Boolean') {
44-
content = value ? 'True' : 'False';
50+
readableValue = content = value ? 'True' : 'False';
4551
} else if (type === 'Array') {
46-
content = JSON.stringify(value.map(val => val instanceof Parse.Object ? val.toPointer() : val))
52+
readableValue = content = JSON.stringify(value.map(val => val instanceof Parse.Object ? val.toPointer() : val))
4753
} else if (type === 'Object' || type === 'Bytes') {
48-
content = JSON.stringify(value);
54+
readableValue = content = JSON.stringify(value);
4955
} else if (type === 'File') {
5056
if (value.url()) {
5157
content = <Pill value={getFileName(value)} />;
5258
} else {
5359
content = <Pill value={'Uploading\u2026'} />;
5460
}
61+
readableValue = getFileName(value)
5562
} else if (type === 'ACL') {
5663
let pieces = [];
5764
let json = value.toJSON();
@@ -72,34 +79,45 @@ let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange
7279
if (pieces.length === 0) {
7380
pieces.push('Master Key Only');
7481
}
75-
content = pieces.join(', ');
82+
readableValue = content = pieces.join(', ');
7683
} else if (type === 'GeoPoint') {
77-
content = `(${value.latitude}, ${value.longitude})`;
84+
readableValue = content = `(${value.latitude}, ${value.longitude})`;
7885
} else if (type === 'Polygon') {
79-
content = value.coordinates.map(coord => `(${coord})`)
86+
readableValue = content = value.coordinates.map(coord => `(${coord})`)
8087
} else if (type === 'Relation') {
8188
content = (
8289
<div style={{ textAlign: 'center', cursor: 'pointer' }}>
8390
<Pill onClick={() => setRelation(value)} value='View relation' />
8491
</div>
8592
);
93+
readableValue = value
8694
}
8795

8896
if (current) {
8997
classes.push(styles.current);
9098
}
9199
return (
92-
<span
93-
className={classes.join(' ')}
94-
style={{ width }}
95-
onClick={onSelect}
96-
onDoubleClick={() => {
97-
if (type !== 'Relation') {
98-
onEditChange(true)
99-
}
100-
}}>
101-
{content}
102-
</span>
100+
readonly ?
101+
<span
102+
className={classes.join(' ')}
103+
style={{ width }}
104+
data-tip='Read Only'
105+
onClick={() => onSelect(readableValue)} >
106+
{content}
107+
<ReactTooltip event={'dblclick'} place={'bottom'} afterShow={() => setTimeout(ReactTooltip.hide, 2000)} />
108+
</span> :
109+
<span
110+
className={classes.join(' ')}
111+
style={{ width }}
112+
onClick={() => onSelect(readableValue)}
113+
onDoubleClick={() => {
114+
if (type !== 'Relation') {
115+
onEditChange(true)
116+
}
117+
}}>
118+
{content}
119+
</span>
120+
103121
);
104122
};
105123

src/components/BrowserCell/BrowserCell.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@
3535
bottom: 0;
3636
}
3737
}
38+
39+
.readonly {
40+
color: #353446;
41+
opacity: .9;
42+
}

src/dashboard/Data/Browser/B4ABrowserToolbar.react.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ const apiDocsButtonStyle = {
1515
display: 'inline-block',
1616
height: '20px',
1717
border: '1px solid #169cee',
18-
'line-height': '20px',
18+
'lineHeight': '20px',
1919
outline: '0',
20-
'text-decoration': 'none',
21-
'text-align': 'center',
22-
'border-radius': '5px',
20+
'textDecoration': 'none',
21+
'textAlign': 'center',
22+
'borderRadius': '5px',
2323
cursor: 'pointer',
24-
'min-width': '90px',
24+
'minWidth': '90px',
2525
padding: '0 5px',
26-
'font-size': '12px',
27-
'font-weight': 'bold',
28-
'margin-bottom': '4px',
26+
'fontSize': '12px',
27+
'fontWeight': 'bold',
28+
'marginBottom': '4px',
2929
}
3030

3131
let B4ABrowserToolbar = ({
@@ -151,7 +151,7 @@ let B4ABrowserToolbar = ({
151151
classApiId = `#${className === 'User' ? 'user-api' : `${className}-custom-class`}`
152152
apiDocsButton = <Button value='API Reference'
153153
primary={true}
154-
width={90}
154+
width={'90px'}
155155
additionalStyles={apiDocsButtonStyle}
156156
onClick={() => {
157157
back4AppNavigation && back4AppNavigation.atApiReferenceClassesEvent()

src/dashboard/Data/Browser/Browser.react.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export default class Browser extends DashboardView {
107107
this.createClass = this.createClass.bind(this);
108108
this.addColumn = this.addColumn.bind(this);
109109
this.removeColumn = this.removeColumn.bind(this);
110+
this.showNote = this.showNote.bind(this);
110111
}
111112

112113
componentWillMount() {
@@ -997,7 +998,8 @@ export default class Browser extends DashboardView {
997998
onAddRow={this.addRow}
998999
onAddClass={this.showCreateClass}
9991000
err={this.state.err}
1000-
playVideoTutorial={playVideoTutorial}/>
1001+
playVideoTutorial={playVideoTutorial}
1002+
showNote={this.showNote}/>
10011003
);
10021004
}
10031005
}

src/dashboard/Data/Browser/BrowserTable.react.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export default class BrowserTable extends React.Component {
122122
readonly={READ_ONLY.indexOf(name) > -1}
123123
width={width}
124124
current={current}
125-
onSelect={() => this.props.setCurrent({ row: row, col: j })}
125+
onSelect={(readableValue) => this.props.setCurrent({ row: row, col: j }, readableValue)}
126126
onEditChange={(state) => this.props.setEditing(state)}
127127
onPointerClick={this.props.onPointerClick}
128128
setRelation={this.props.setRelation}

src/dashboard/Data/Browser/DataBrowser.react.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as ColumnPreferences from 'lib/ColumnPreferences';
1111
import ParseApp from 'lib/ParseApp';
1212
import React from 'react';
1313
import { SpecialClasses } from 'lib/Constants';
14+
import copy from 'copy-to-clipboard';
1415

1516
/**
1617
* DataBrowser renders the browser toolbar and data table
@@ -30,7 +31,7 @@ export default class DataBrowser extends React.Component {
3031
this.state = {
3132
order: order,
3233
current: null,
33-
editing: false,
34+
editing: false
3435
};
3536

3637
this.handleKey = this.handleKey.bind(this);
@@ -171,6 +172,13 @@ export default class DataBrowser extends React.Component {
171172
});
172173
e.preventDefault();
173174
break;
175+
case 67: // c key
176+
if (e.ctrlKey || e.metaKey) {
177+
copy(this.state.currentValue) // copy current value to clipboard
178+
this.props.showNote('Value copied to clipboard', false)
179+
e.preventDefault()
180+
}
181+
break;
174182
}
175183
}
176184

@@ -180,9 +188,9 @@ export default class DataBrowser extends React.Component {
180188
}
181189
}
182190

183-
setCurrent(current) {
191+
setCurrent(current, currentValue) {
184192
if (this.state.current !== current) {
185-
this.setState({ current: current });
193+
this.setState({ current, currentValue });
186194
}
187195
}
188196

0 commit comments

Comments
 (0)