diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js
index 3645fadf81..9643c59d63 100644
--- a/Parse-Dashboard/index.js
+++ b/Parse-Dashboard/index.js
@@ -52,6 +52,7 @@ let configUserId = program.userId || process.env.PARSE_DASHBOARD_USER_ID;
let configUserPassword = program.userPassword || process.env.PARSE_DASHBOARD_USER_PASSWORD;
let configSSLKey = program.sslKey || process.env.PARSE_DASHBOARD_SSL_KEY;
let configSSLCert = program.sslCert || process.env.PARSE_DASHBOARD_SSL_CERT;
+let configTimezone = program.timezone || process.env.PARSE_DASHBOARD_TIMEZONE;
if (!program.config && !process.env.PARSE_DASHBOARD_CONFIG) {
if (configServerURL && configMasterKey && configAppId) {
configFromCLI = {
@@ -62,6 +63,7 @@ if (!program.config && !process.env.PARSE_DASHBOARD_CONFIG) {
serverURL: configServerURL,
masterKey: configMasterKey,
appName: configAppName,
+ timezone: configTimezone,
},
]
}
diff --git a/Parse-Dashboard/parse-dashboard-config.json b/Parse-Dashboard/parse-dashboard-config.json
index 2efaa16103..e6d3efdfa4 100644
--- a/Parse-Dashboard/parse-dashboard-config.json
+++ b/Parse-Dashboard/parse-dashboard-config.json
@@ -4,6 +4,7 @@
"appId": "hello",
"masterKey": "world",
"appName": "",
+ "timezone": null,
"iconName": "",
"primaryBackgroundColor": "",
"secondaryBackgroundColor": ""
diff --git a/README.md b/README.md
index 1b834f7432..cd09c56a12 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ Parse Dashboard is a standalone dashboard for managing your Parse apps. You can
* [Multiple apps](#multiple-apps)
* [Single app](#single-app)
* [Managing Multiple Apps](#managing-multiple-apps)
+ * [Timezone configuration](#timezone-configuration)
* [App Icon Configuration](#app-icon-configuration)
* [App Background Color Configuration](#app-background-color-configuration)
* [Other Configuration Options](#other-configuration-options)
@@ -69,7 +70,8 @@ You can also start the dashboard from the command line with a config file. To d
"serverURL": "http://localhost:1337/parse",
"appId": "myAppId",
"masterKey": "myMasterKey",
- "appName": "MyApp"
+ "appName": "MyApp",
+ "timezone": "America/Bahia"
}
]
}
@@ -100,6 +102,7 @@ PARSE_DASHBOARD_SERVER_URL: "http://localhost:1337/parse"
PARSE_DASHBOARD_MASTER_KEY: "myMasterKey"
PARSE_DASHBOARD_APP_ID: "myAppId"
PARSE_DASHBOARD_APP_NAME: "MyApp"
+PARSE_DASHBOARD_TIMEZONE: "America/Bahia"
PARSE_DASHBOARD_USER_ID: "user1"
PARSE_DASHBOARD_USER_PASSWORD: "pass"
PARSE_DASHBOARD_SSL_KEY: "sslKey"
@@ -129,7 +132,26 @@ You can manage self-hosted [Parse Server](https://github.com/ParsePlatform/parse
"serverURL": "http://localhost:1337/parse", // Self-hosted Parse Server
"appId": "myAppId",
"masterKey": "myMasterKey",
- "appName": "My Parse Server App"
+ "appName": "My Parse Server App",
+ "timezone": "America/Chicago",
+ }
+ ]
+}
+```
+
+## Timezone Configuration
+
+Parse Dashboard supports adding an optional timezone for each app, if you dont set any timezone, the UTC will be used like default. Just set a `timezone` with a valid timezone name.
+
+```json
+{
+ "apps": [
+ {
+ "serverURL": "http://localhost:1337/parse",
+ "appId": "myAppId",
+ "masterKey": "myMasterKey",
+ "appName": "My Parse Server App",
+ "timezone": "America/Bahia",
}
]
}
@@ -367,7 +389,7 @@ You can mark a user as a read-only user:
"appId": "myAppId1",
"masterKey": "myMasterKey1",
"readOnlyMasterKey": "myReadOnlyMasterKey1",
- "serverURL": "myURL1",
+ "serverURL": "myURL1",
"port": 4040,
"production": true
},
@@ -375,7 +397,7 @@ You can mark a user as a read-only user:
"appId": "myAppId2",
"masterKey": "myMasterKey2",
"readOnlyMasterKey": "myReadOnlyMasterKey2",
- "serverURL": "myURL2",
+ "serverURL": "myURL2",
"port": 4041,
"production": true
}
@@ -410,7 +432,7 @@ You can give read only access to a user on a per-app basis:
"appId": "myAppId1",
"masterKey": "myMasterKey1",
"readOnlyMasterKey": "myReadOnlyMasterKey1",
- "serverURL": "myURL",
+ "serverURL": "myURL",
"port": 4040,
"production": true
},
diff --git a/package.json b/package.json
index 63001ef2d6..fe88d29229 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,8 @@
"json-file-plus": "^3.2.0",
"package-json": "^5.0.0",
"passport": "^0.4.0",
- "passport-local": "^1.0.0"
+ "passport-local": "^1.0.0",
+ "timezone-support": "^1.5.5"
},
"devDependencies": {
"@babel/core": "7.1.2",
diff --git a/src/components/BrowserCell/BrowserCell.react.js b/src/components/BrowserCell/BrowserCell.react.js
index fe6b81eb8c..90cd60c83e 100644
--- a/src/components/BrowserCell/BrowserCell.react.js
+++ b/src/components/BrowserCell/BrowserCell.react.js
@@ -5,7 +5,7 @@
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*/
-import { dateStringUTC } from 'lib/DateUtils';
+import { dateString } from 'lib/DateUtils';
import getFileName from 'lib/getFileName';
import Parse from 'parse';
import Pill from 'components/Pill/Pill.react';
@@ -13,7 +13,7 @@ import React from 'react';
import styles from 'components/BrowserCell/BrowserCell.scss';
import { unselectable } from 'stylesheets/base.scss';
-let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange, setRelation, onPointerClick }) => {
+let BrowserCell = ({ type, value, hidden, width, current, timezone, onSelect, onEditChange, setRelation, onPointerClick }) => {
let content = value;
let classes = [styles.cell, unselectable];
if (hidden) {
@@ -39,7 +39,7 @@ let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange
);
} else if (type === 'Date') {
- content = dateStringUTC(value);
+ content = dateString(value, timezone);
} else if (type === 'Boolean') {
content = value ? 'True' : 'False';
} else if (type === 'Array') {
diff --git a/src/components/PushCerts/CertsTable.react.js b/src/components/PushCerts/CertsTable.react.js
index db8db279fd..bfc3cb8792 100644
--- a/src/components/PushCerts/CertsTable.react.js
+++ b/src/components/PushCerts/CertsTable.react.js
@@ -7,11 +7,11 @@
*/
import FormTable from 'components/FormTable/FormTable.react';
import React from 'react';
-import { dateStringUTC } from 'lib/DateUtils';
+import { dateString } from 'lib/DateUtils';
const MONTH_IN_MS = 1000 * 60 * 60 * 24 * 30;
-let CertsTable = ({ certs, onDelete, uploadPending }) => {
+let CertsTable = ({ certs, timezone, onDelete, uploadPending }) => {
let tableData = certs.map(c => {
let color = '';
let expiresKeyColor = '';
@@ -36,7 +36,7 @@ let CertsTable = ({ certs, onDelete, uploadPending }) => {
{
key: isExpired ? 'Expired' : 'Expires',
keyColor: expiresKeyColor,
- value: dateStringUTC(new Date(c.expiration)),
+ value: dateString(new Date(c.expiration), timezone),
}
]
};
diff --git a/src/components/PushCerts/PushCerts.react.js b/src/components/PushCerts/PushCerts.react.js
index 20a3aaedc4..fea0911d9b 100644
--- a/src/components/PushCerts/PushCerts.react.js
+++ b/src/components/PushCerts/PushCerts.react.js
@@ -57,6 +57,7 @@ PushCerts.propTypes = {
onDelete: PropTypes.func.isRequired.describe(
'A handler for when a Push has been deleted from the server'
),
+ timezone: PropTypes.string,
};
-export default PushCerts;
\ No newline at end of file
+export default PushCerts;
diff --git a/src/dashboard/Account/AccountOverview.react.js b/src/dashboard/Account/AccountOverview.react.js
index c6966ad5f7..8b81a137b9 100644
--- a/src/dashboard/Account/AccountOverview.react.js
+++ b/src/dashboard/Account/AccountOverview.react.js
@@ -23,7 +23,7 @@ import renderFlowFooterChanges from 'lib/renderFlowFooterChanges';
import styles from 'dashboard/Settings/Settings.scss';
import TextInput from 'components/TextInput/TextInput.react';
import Toolbar from 'components/Toolbar/Toolbar.react';
-import { dateStringUTC } from 'lib/DateUtils';
+import { dateString } from 'lib/DateUtils';
const DEFAULT_LABEL_WIDTH = 56;
const XHR_KEY = 'AccountOverview';
@@ -136,7 +136,7 @@ export default class AccountOverview extends React.Component {
},
{
key: 'Expires',
- value: dateStringUTC(new Date(key.expiresAt)),
+ value: dateString(new Date(key.expiresAt)),
},
],
}))} />
diff --git a/src/dashboard/Data/Browser/BrowserTable.react.js b/src/dashboard/Data/Browser/BrowserTable.react.js
index 0dd18f7157..8e5a6ca6f0 100644
--- a/src/dashboard/Data/Browser/BrowserTable.react.js
+++ b/src/dashboard/Data/Browser/BrowserTable.react.js
@@ -124,6 +124,7 @@ export default class BrowserTable extends React.Component {
onPointerClick={this.props.onPointerClick}
setRelation={this.props.setRelation}
value={attr}
+ timezone={this.props.timezone}
hidden={hidden} />
);
})}
diff --git a/src/dashboard/Data/Browser/DataBrowser.react.js b/src/dashboard/Data/Browser/DataBrowser.react.js
index cbef02f7df..a6014b5656 100644
--- a/src/dashboard/Data/Browser/DataBrowser.react.js
+++ b/src/dashboard/Data/Browser/DataBrowser.react.js
@@ -10,7 +10,7 @@ import BrowserToolbar from 'dashboard/Data/Browser/BrowserToolbar.react'
import * as ColumnPreferences from 'lib/ColumnPreferences';
import ParseApp from 'lib/ParseApp';
import React from 'react';
-import PropTypes from 'lib/PropTypes';
+import PropTypes from 'lib/PropTypes';
import { SpecialClasses } from 'lib/Constants';
/**
@@ -200,6 +200,7 @@ export default class DataBrowser extends React.Component {
handleResize={this.handleResize.bind(this)}
setEditing={this.setEditing.bind(this)}
setCurrent={this.setCurrent.bind(this)}
+ timezone={this.context.currentApp.timezone}
{...other} />