Skip to content

Commit 0b5a24b

Browse files
author
Krit
committed
Merge commit '3ae3f256b0645d0a558bb5b09c75214f6ad3fd63'
2 parents ff567f9 + 3ae3f25 commit 0b5a24b

23 files changed

+342
-155
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
language: node_js
22
node_js:
3-
- "4.3"
3+
- "4.4"
4+
- "5.7"
5+
- "6.1"

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
## Parse Dashboard Changelog
22

3+
### 1.0.14
4+
5+
* Fix bug in past push page
6+
7+
### 1.0.13
8+
9+
* Fix log retrieval, thanks to [Jérémy Thiry](https://github.com/poltib)
10+
* Improved GeoPoint editor and ESC button in editors, thanks to [Sam Schooler](https://github.com/samschooler)
11+
* Add push status page to dashboard, thanks to [Jeremy Pease](https://github.com/JeremyPlease)
12+
13+
### 1.0.12
14+
15+
* Fix minor style issues
16+
* Add pointer permissions editor
17+
* Allow cancellation of edits in data browser using ESC key, thanks to [Manuel](https://github.com/mtrezza)
18+
* Show error messages in the console when your app's icons can't be found, thanks to [Saif Al-Dilaimi](https://github.com/deada92)
19+
20+
### 1.0.11
21+
22+
* Add the ability to specify SSL cert and key, thanks to [Cory Imdieke](https://github.com/Vortec4800)
23+
* Trust proxy when enabling --allowInsecureHTTP, thanks to [Andrew Chen](https://github.com/yongjhih)
24+
* Fix App index when apps have an apostrophe in the name
25+
* Fix display of prod/dev flag
26+
* Support for Node 6
27+
328
### 1.0.10
429

530
* Add the ability to specify icons for your app, thanks to [Natan Rolnik](https://github.com/natanrolnik)

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ We want to make contributing to this project as easy and transparent as
33
possible.
44

55
## Our Development Process
6-
Get started by cloning this repository and and running `npm install` inside it. Create a file called `parse-dashboad-config.json` in the Parse-Dashboard folder inside the repo, using the format described in the readme.
6+
Get started by cloning this repository and and running `npm install` inside it. Create a file called `parse-dashboard-config.json` in the Parse-Dashboard folder inside the repo, using the format described in the readme.
77

88
When working on the dashboard, use `npm run dashboard` and visit `localhost:4040` to see your dashboard. The `npm run dashboard` script will automatically re-build your files when you change them, so after making a change, all you need to do is refresh the page.
99

Parse-Dashboard/app.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const express = require('express');
33
const basicAuth = require('basic-auth');
44
const path = require('path');
55
const packageJson = require('package-json');
6+
var fs = require('fs');
67

78
const currentVersionFeatures = require('../package.json').parseDashboardFeatures;
89

@@ -26,6 +27,27 @@ function getMount(req) {
2627
return mountPath;
2728
}
2829

30+
function checkIfIconsExistForApps(apps, iconsFolder) {
31+
for (var i in apps) {
32+
var currentApp = apps[i];
33+
var iconName = currentApp.iconName;
34+
var path = iconsFolder + "/" + iconName;
35+
36+
fs.stat(path, function(err, stat) {
37+
if (err) {
38+
if ('ENOENT' == err.code) {// file does not exist
39+
console.warn("Icon with file name: " + iconName +" couldn't be found in icons folder!");
40+
} else {
41+
console.log(
42+
'An error occurd while checking for icons, please check permission!');
43+
}
44+
} else {
45+
//every thing was ok so for example you can read it and send it to client
46+
}
47+
} );
48+
}
49+
}
50+
2951
module.exports = function(config, allowInsecureHTTP) {
3052
var app = express();
3153
// Serve public files.
@@ -116,7 +138,18 @@ module.exports = function(config, allowInsecureHTTP) {
116138
// We are explicitly not using `__dirpath` here because one may be
117139
// running parse-dashboard from globally installed npm.
118140
if (config.iconsFolder) {
119-
app.use('/appicons', express.static(config.iconsFolder));
141+
try {
142+
var stat = fs.statSync(config.iconsFolder);
143+
if (stat.isDirectory()) {
144+
app.use('/appicons', express.static(config.iconsFolder));
145+
//Check also if the icons really exist
146+
checkIfIconsExistForApps(config.apps, config.iconsFolder);
147+
}
148+
} catch (e) {
149+
// Directory doesn't exist or something.
150+
console.warn("Iconsfolder at path: " + config.iconsFolder +
151+
" not found!");
152+
}
120153
}
121154

122155
// For every other request, go to index.html. Let client-side handle the rest.

Parse-Dashboard/index.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ program.option('--host [host]', 'the host to run parse-dashboard');
2222
program.option('--port [port]', 'the port to run parse-dashboard');
2323
program.option('--mountPath [mountPath]', 'the mount path to run parse-dashboard');
2424
program.option('--allowInsecureHTTP [allowInsecureHTTP]', 'set this flag when you are running the dashboard behind an HTTPS load balancer or proxy with early SSL termination.');
25+
program.option('--sslKey [sslKey]', 'the path to the SSL private key.');
26+
program.option('--sslCert [sslCert]', 'the path to the SSL certificate.');
2527

2628
program.parse(process.argv);
2729

@@ -39,6 +41,8 @@ let configAppId = program.appId || process.env.PARSE_DASHBOARD_APP_ID;
3941
let configAppName = program.appName || process.env.PARSE_DASHBOARD_APP_NAME;
4042
let configUserId = program.userId || process.env.PARSE_DASHBOARD_USER_ID;
4143
let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USER_PASSWORD;
44+
let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY;
45+
let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT;
4246
if (!program.config && !process.env.PARSE_DASHBOARD_CONFIG) {
4347
if (configServerURL && configMasterKey && configAppId) {
4448
configFromCLI = {
@@ -101,11 +105,26 @@ p.then(config => {
101105

102106
const app = express();
103107

108+
if (allowInsecureHTTP) app.enable('trust proxy');
104109
app.use(mountPath, parseDashboard(config.data, allowInsecureHTTP));
105-
// Start the server.
106-
const server = app.listen(port, host, function () {
107-
console.log(`The dashboard is now available at http://${server.address().address}:${server.address().port}${mountPath}`);
108-
});
110+
if(!configSSLKey || !configSSLCert){
111+
// Start the server.
112+
const server = app.listen(port, host, function () {
113+
console.log(`The dashboard is now available at http://${server.address().address}:${server.address().port}${mountPath}`);
114+
});
115+
} else {
116+
// Start the server using SSL.
117+
var fs = require('fs');
118+
var privateKey = fs.readFileSync(configSSLKey);
119+
var certificate = fs.readFileSync(configSSLCert);
120+
121+
const server = require('https').createServer({
122+
key: privateKey,
123+
cert: certificate
124+
}, app).listen(port, host, function () {
125+
console.log(`The dashboard is now available at https://${server.address().address}:${server.address().port}${mountPath}`);
126+
});
127+
}
109128
}, error => {
110129
if (error instanceof SyntaxError) {
111130
console.log('Your config file contains invalid JSON. Exiting.');
@@ -124,6 +143,6 @@ p.then(config => {
124143
}
125144
})
126145
.catch(error => {
127-
console.log('There was a problem loading the dashboard. Exiting.');
146+
console.log('There was a problem loading the dashboard. Exiting.', error);
128147
process.exit(-1);
129148
});
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
{
2-
"apps": [
3-
4-
]
2+
"apps": [{
3+
"serverURL": "",
4+
"appId": "",
5+
"masterKey": "",
6+
"appName": "",
7+
"iconName": ""
8+
}],
9+
"iconsFolder": "icons"
510
}

README.md

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Parse Dashboard is a standalone dashboard for managing your Parse apps. You can
1010
* [Configuring Parse Dashboard](#configuring-parse-dashboard)
1111
* [Managing Multiple Apps](#managing-multiple-apps)
1212
* [Other Configuration Options](#other-configuration-options)
13+
* [Running as Express Middleware](#running-as-express-middleware)
1314
* [Deploying Parse Dashboard](#deploying-parse-dashboard)
1415
* [Preparing for Deployment](#preparing-for-deployment)
1516
* [Security Considerations](#security-considerations)
@@ -20,7 +21,7 @@ Parse Dashboard is a standalone dashboard for managing your Parse apps. You can
2021

2122
# Getting Started
2223

23-
[Node.js](https://nodejs.org) version >= 4.3 is required to run the dashboard. You also need to be using Parse Server version 2.1.4 or higher.
24+
[Node.js](https://nodejs.org) version >= 4.3 is required to run the dashboard. You also need to be using Parse Server version 2.1.4 or higher.
2425

2526
# Local Installation
2627

@@ -66,7 +67,7 @@ Managing multiple apps from the same dashboard is also possible. Simply add add
6667

6768
You can manage self-hosted [Parse Server](https://github.com/ParsePlatform/parse-server) apps, *and* apps that are hosted on [Parse.com](http://parse.com/) from the same dashboard. In your config file, you will need to add the `restKey` and `javascriptKey` as well as the other paramaters, which you can find on `dashboard.parse.com`. Set the serverURL to `http://api.parse.com/1`:
6869

69-
```json
70+
```js
7071
{
7172
"apps": [
7273
{
@@ -90,7 +91,7 @@ You can manage self-hosted [Parse Server](https://github.com/ParsePlatform/parse
9091

9192
## App Icon Configuration
9293

93-
Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file:
94+
Parse Dashboard supports adding an optional icon for each app, so you can identify them easier in the list. To do so, you *must* use the configuration file, define an `iconsFolder` in it, and define the `iconName` parameter for each app (including the extension). The path of the `iconsFolder` is relative to the configuration file. If you have installed ParseDashboard globally you need to use the full path as value for the `iconsFolder`. To visualize what it means, in the following example `icons` is a directory located under the same directory as the configuration file:
9495

9596
```json
9697
{
@@ -109,18 +110,73 @@ Parse Dashboard supports adding an optional icon for each app, so you can identi
109110

110111
## Other Configuration Options
111112

112-
You can set `appNameForURL` in the config file for each app to control the url of your app within the dashboard. This can make it easier to use bookmarks or share links on your dashboard.
113+
You can set `appNameForURL` in the config file for each app to control the url of your app within the dashboard. This can make it easier to use bookmarks or share links on your dashboard.
113114

114115
To change the app to production, simply set `production` to `true` in your config file. The default value is false if not specified.
115116

117+
# Running as Express Middleware
118+
119+
Instead of starting Parse Dashboard with the CLI, you can also run it as an [express](https://github.com/expressjs/express) middleware.
120+
121+
```
122+
var express = require('express');
123+
var ParseDashboard = require('parse-dashboard');
124+
125+
var dashboard = new ParseDashboard({
126+
"apps": [
127+
{
128+
"serverURL": "http://localhost:1337/parse",
129+
"appId": "myAppId",
130+
"masterKey": "myMasterKey",
131+
"appName": "MyApp"
132+
}
133+
]
134+
});
135+
136+
var app = express();
137+
138+
// make the Parse Dashboard available at /dashboard
139+
app.use('/dashboard', dashboard);
140+
141+
var httpServer = require('http').createServer(app);
142+
httpServer.listen(4040);
143+
```
144+
145+
If you want to run both [Parse Server](https://github.com/ParsePlatform/parse-server) and Parse Dashboard on the same server/port, you can run them both as express middleware:
146+
147+
```
148+
var express = require('express');
149+
var ParseServer = require('parse-server').ParseServer;
150+
var ParseDashboard = require('parse-dashboard');
151+
152+
var api = new ParseServer({
153+
// Parse Server settings
154+
});
155+
156+
var dashboard = new ParseDashboard({
157+
// Parse Dashboard settings
158+
});
159+
160+
var app = express();
161+
162+
// make the Parse Server available at /parse
163+
app.use('/parse', api);
164+
165+
// make the Parse Dashboard available at /dashboard
166+
app.use('/dashboard', dashboard);
167+
168+
var httpServer = require('http').createServer(app);
169+
httpServer.listen(4040);
170+
```
171+
116172
# Deploying Parse Dashboard
117173

118174
## Preparing for Deployment
119175

120176
Make sure the server URLs for your apps can be accessed by your browser. If you are deploying the dashboard, then `localhost` urls will not work.
121177

122178
## Security Considerations
123-
In order to securely deploy the dashboard without leaking your apps master key, you will need to use HTTPS and Basic Authentication.
179+
In order to securely deploy the dashboard without leaking your apps master key, you will need to use HTTPS and Basic Authentication.
124180

125181
The deployed dashboard detects if you are using a secure connection. If you are deploying the dashboard behind a load balancer or proxy that does early SSL termination, then the app won't be able to detect that the connection is secure. In this case, you can start the dashboard with the `--allowInsecureHTTP=1` option. You will then be responsible for ensureing that your proxy or load balancer only allows HTTPS.
126182

@@ -155,20 +211,20 @@ To do so, update your `parse-dashboard-config.json` configuration file to match
155211
{
156212
"user":"user1",
157213
"pass":"pass1",
158-
"apps": [{"appId1": "myAppId1"}, {"appId2": "myAppId2"}]
214+
"apps": [{"appId": "myAppId1"}, {"appId": "myAppId2"}]
159215
},
160216
{
161217
"user":"user2",
162218
"pass":"pass2",
163-
"apps": [{"appId1": "myAppId1"}]
219+
"apps": [{"appId": "myAppId1"}]
164220
} ]
165221
}
166222
```
167223
The effect of such a configuration is as follows:
168224

169-
When `user1` logs in, he/she will be able to manage `appId1` and `appId2` from the dashboard.
225+
When `user1` logs in, he/she will be able to manage `myAppId1` and `myAppId2` from the dashboard.
170226

171-
When *`user2`* logs in, he/she will only be able to manage *`appId1`* from the dashboard.
227+
When *`user2`* logs in, he/she will only be able to manage *`myAppId1`* from the dashboard.
172228

173229

174230
## Run with Docker

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
"Parse Config",
77
"API Console",
88
"Class Level Permissions Editor",
9+
"Pointer Permissions Editor",
910
"Send Push Notifications",
10-
"Logs Viewer"
11+
"Logs Viewer",
12+
"Push Status Page"
1113
],
1214
"description": "The Parse Dashboard",
1315
"keywords": [
@@ -16,7 +18,7 @@
1618
],
1719
"homepage": "https://github.com/ParsePlatform/parse-dashboard",
1820
"bugs": "https://github.com/ParsePlatform/parse-dashboard/issues",
19-
"version": "1.0.10",
21+
"version": "1.0.14",
2022
"repository": {
2123
"type": "git",
2224
"url": "https://github.com/ParsePlatform/parse-dashboard"
@@ -47,10 +49,10 @@
4749
"http-server": "~0.8.5",
4850
"immutable": "~3.7.5",
4951
"immutable-devtools": "~0.0.4",
50-
"jest-cli": "^0.7.1",
52+
"jest-cli": "^12.0.2",
5153
"js-beautify": "~1.5.0",
5254
"marked": "^0.3.5",
53-
"node-sass": "~3.4.2",
55+
"node-sass": "^3.7.0",
5456
"parse": "1.6.14",
5557
"prismjs": "~1.2.0",
5658
"react": "^15.0.1",

src/components/AppBadge/AppBadge.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
letter-spacing: 4px;
2222
width: 60px;
2323
padding-left: 3px;
24+
float: right;
2425
}
2526

2627
.prod {

src/components/GeoPointEditor/GeoPointEditor.react.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default class GeoPointEditor extends React.Component {
4646
}
4747

4848
handleKeyLatitude(e) {
49-
if (e.keyCode === 13) {
49+
if (e.keyCode === 13 || e.keyCode === 44) {
5050
this.refs.longitude.focus();
5151
this.refs.longitude.setSelectionRange(0, String(this.state.longitude).length);
5252
}
@@ -83,6 +83,32 @@ export default class GeoPointEditor extends React.Component {
8383
render() {
8484
let onChange = (target, e) => {
8585
let value = e.target.value;
86+
87+
if (!validateNumeric(value)) {
88+
var values = value.split(",");
89+
90+
if (values.length == 2) {
91+
values = values.map(val => val.trim());
92+
93+
if (values[0].length > 0 && validateNumeric(values[0])) {
94+
95+
if (values[1].length <= 0 || !validateNumeric(values[1])) {
96+
this.setState({ latitude: values[0] });
97+
this.refs.longitude.focus();
98+
this.refs.longitude.setSelectionRange(0, String(this.state.longitude).length);
99+
return;
100+
}
101+
102+
if (validateNumeric(values[1])) {
103+
this.setState({ latitude: values[0] });
104+
this.setState({ longitude: values[1] });
105+
this.refs.longitude.focus();
106+
return;
107+
}
108+
}
109+
}
110+
}
111+
86112
this.setState({ [target]: validateNumeric(value) ? value : this.state[target] });
87113
};
88114
return (

0 commit comments

Comments
 (0)