diff --git a/.eslintrc.json b/.eslintrc.json index e1cc3e6a2d..6013b6a961 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,6 +15,15 @@ }, "plugins": ["react"], "rules": { + "indent": ["error", 2, { "SwitchCase": 1 }], + "linebreak-style": ["error", "unix"], + "no-trailing-spaces": 2, + "eol-last": 2, + "space-in-parens": ["error", "never"], + "no-multiple-empty-lines": 1, + "space-infix-ops": "error", + "no-useless-escape": "off", + "require-atomic-updates": "off", "react/jsx-uses-vars": 1, "react/jsx-uses-react": 1, "react/react-in-jsx-scope": 1, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f811dc2a66..c7c27d5148 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,26 +44,26 @@ jobs: steps: - uses: actions/checkout@v2 - uses: dangoslen/changelog-enforcer@v2 - # check-lint: - # name: Lint - # timeout-minutes: 15 - # runs-on: ubuntu-18.04 - # steps: - # - uses: actions/checkout@v2 - # - name: Use Node.js ${{ env.NODE_VERSION }} - # uses: actions/setup-node@v1 - # with: - # node-version: ${{ env.node-version }} - # - name: Cache Node.js modules - # uses: actions/cache@v2 - # with: - # path: ~/.npm - # key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }} - # restore-keys: | - # ${{ runner.os }}-node-${{ env.NODE_VERSION }}- - # - name: Install dependencies - # run: npm ci - # - run: npm run lint + check-lint: + name: Lint + timeout-minutes: 15 + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v1 + with: + node-version: ${{ env.node-version }} + - name: Cache Node.js modules + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node-${{ env.NODE_VERSION }}- + - name: Install dependencies + run: npm ci + - run: npm run lint check-circular: name: Circular Dependencies timeout-minutes: 5 diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh new file mode 100644 index 0000000000..6809ccca28 --- /dev/null +++ b/.husky/_/husky.sh @@ -0,0 +1,31 @@ +#!/bin/sh +if [ -z "$husky_skip_init" ]; then + debug () { + if [ "$HUSKY_DEBUG" = "1" ]; then + echo "husky (debug) - $1" + fi + } + + readonly hook_name="$(basename "$0")" + debug "starting $hook_name..." + + if [ "$HUSKY" = "0" ]; then + debug "HUSKY env variable is set to 0, skipping hook" + exit 0 + fi + + if [ -f ~/.huskyrc ]; then + debug "sourcing ~/.huskyrc" + . ~/.huskyrc + fi + + export readonly husky_skip_init=1 + sh -e "$0" "$@" + exitCode="$?" + + if [ $exitCode != 0 ]; then + echo "husky - $hook_name hook exited with code $exitCode (error)" + fi + + exit $exitCode +fi diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000000..e73e439601 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" +npm run lint +git add + diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e343eeba1..4701610fda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Add CI check to add changelog entry (Manuel Trezza) [#1764](https://github.com/parse-community/parse-dashboard/pull/1764) - Refactor: uniform issue templates across repos (Manuel Trezza) [#1767](https://github.com/parse-community/parse-dashboard/pull/1767) - fix: date cell value not selected on double clicks (fn-faisal) [#1730](https://github.com/parse-community/parse-dashboard/pull/1730) +- Adds `npm run lint:fix` and pre-commit hook (Daniel Blyth) [#1791](https://github.com/parse-community/parse-dashboard/pull/1730) ## Fixes - Fixed bug after creating new class, wrong CLP was shown for that class [#1784](https://github.com/parse-community/parse-dashboard/issues/1784) (Prerna Mehra) [#1785](https://github.com/parse-community/parse-dashboard/pull/1785) diff --git a/Parse-Dashboard/CLI/mfa.js b/Parse-Dashboard/CLI/mfa.js index f862f2cf45..8c5ca70ee6 100644 --- a/Parse-Dashboard/CLI/mfa.js +++ b/Parse-Dashboard/CLI/mfa.js @@ -101,20 +101,20 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt, if (secret) { console.log( - `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` + - `\n\n ${secret}` + + `\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` + + `\n\n ${secret}` + '\n\n If the secret code generates incorrect one-time passwords, try this alternative:' + - `\n\n ${url}` + + `\n\n ${url}` + `\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.` ); } - + if (encrypt) { console.log( `\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` + '\n You chose to generate an encrypted password for this user.' + '\n Any existing users with non-encrypted passwords will require newly created, encrypted passwords.' - ); + ); } console.log( '\n------------------------------------------------------------------------------\n' @@ -214,7 +214,7 @@ module.exports = { const { url, secret } = generateSecret({ app, username, algorithm, digits, period }); showQR(url); - + // Compose config const config = { mfa: secret }; if (algorithm !== 'SHA1') { diff --git a/Parse-Dashboard/app.js b/Parse-Dashboard/app.js index 2a793e5610..b19b861a63 100644 --- a/Parse-Dashboard/app.js +++ b/Parse-Dashboard/app.js @@ -33,16 +33,16 @@ function checkIfIconsExistForApps(apps, iconsFolder) { fs.stat(path, function(err) { if (err) { - if ('ENOENT' == err.code) {// file does not exist - console.warn('Icon with file name: ' + iconName +' couldn\'t be found in icons folder!'); - } else { - console.log( - 'An error occurd while checking for icons, please check permission!'); - } + if ('ENOENT' == err.code) {// file does not exist + console.warn('Icon with file name: ' + iconName + ' couldn\'t be found in icons folder!'); + } else { + console.log( + 'An error occurd while checking for icons, please check permission!'); + } } else { - //every thing was ok so for example you can read it and send it to client + //every thing was ok so for example you can read it and send it to client } - } ); + }); } } @@ -203,7 +203,7 @@ module.exports = function(config, options) { if (users && (!req.user || !req.user.isAuthenticated)) { return res.redirect(`${mountPath}login`); } - if (users && req.user && req.user.matchingUsername ) { + if (users && req.user && req.user.matchingUsername) { res.append('username', req.user.matchingUsername); } res.send(` diff --git a/Parse-Dashboard/index.js b/Parse-Dashboard/index.js index d5ed2019fc..055b3b288b 100644 --- a/Parse-Dashboard/index.js +++ b/Parse-Dashboard/index.js @@ -193,7 +193,7 @@ p.then(config => { process.exit(-1); } }) -.catch(error => { - console.log('There was a problem loading the dashboard. Exiting.', error); - process.exit(-1); -}); + .catch(error => { + console.log('There was a problem loading the dashboard. Exiting.', error); + process.exit(-1); + }); diff --git a/ci/nodeEngineCheck.js b/ci/nodeEngineCheck.js index 018fcb643a..da68f314b1 100644 --- a/ci/nodeEngineCheck.js +++ b/ci/nodeEngineCheck.js @@ -46,7 +46,7 @@ class NodeEngineCheck { const dirents = await fs.readdir(basePath, { withFileTypes: true }); const validFiles = dirents.filter(d => d.name.toLowerCase() == 'package.json').map(d => path.join(basePath, d.name)); files.push(...validFiles); - + // For each directory entry for (const dirent of dirents) { if (dirent.isDirectory()) { @@ -80,7 +80,7 @@ class NodeEngineCheck { const contentString = await fs.readFile(file, 'utf-8'); const contentJson = JSON.parse(contentString); const version = ((contentJson || {}).engines || {}).node; - + // Add response response.push({ file: file, @@ -112,14 +112,14 @@ class NodeEngineCheck { // Sort by min version const sortedMinVersions = minVersions.sort((v1, v2) => semver.compare(v1.nodeMinVersion, v2.nodeMinVersion)); - + // Filter by higher versions const higherVersions = sortedMinVersions.filter(v => semver.gt(v.nodeMinVersion, baseVersion)); // console.log(`getHigherVersions: ${JSON.stringify(higherVersions)}`); return higherVersions; } -/** + /** * Returns the node version of the parent package. * @return {Object} The parent package info. */ @@ -153,7 +153,7 @@ async function check() { // Determine parent min version const parentMinVersion = semver.minVersion(parentVersion.nodeVersion); - + // Get package.json files const files = await check.getPackageFiles(); core.info(`Checking the minimum node version requirement of ${files.length} dependencies`); @@ -170,13 +170,13 @@ async function check() { // If there are higher versions if (higherVersions.length > 0) { console.log(`\nThere are ${higherVersions.length} dependencies that require a higher node engine version than the parent package (${parentVersion.nodeVersion}):`); - + // For each dependency for (const higherVersion of higherVersions) { - + // Get package name - const package = higherVersion.file.split('node_modules/').pop().replace('/package.json', ''); - console.log(`- ${package} requires at least node ${higherVersion.nodeMinVersion} (${higherVersion.nodeVersion})`); + const _package = higherVersion.file.split('node_modules/').pop().replace('/package.json', ''); + console.log(`- ${_package} requires at least node ${higherVersion.nodeMinVersion} (${higherVersion.nodeVersion})`); } console.log(''); core.setFailed(`❌ Upgrade the node engine version in package.json to at least '${highestVersion}' to satisfy the dependencies.`); diff --git a/package-lock.json b/package-lock.json index d9d84c00ee..093f511a8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8951,6 +8951,12 @@ } } }, + "husky": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.2.tgz", + "integrity": "sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", diff --git a/package.json b/package.json index 9f932d1553..aa03a877e2 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "eslint-plugin-react": "7.19.0", "file-loader": "6.0.0", "http-server": "0.12.0", + "husky": "7.0.2", "jest": "24.8.0", "madge": "5.0.1", "marked": "0.8.2", @@ -124,6 +125,7 @@ "build": "cross-env NODE_ENV=production webpack --config webpack/production.config.js && webpack --config webpack/PIG.config.js", "test": "cross-env NODE_PATH=./node_modules jest", "lint": "eslint . --ignore-path .gitignore --cache", + "lint:fix": "eslint . --ignore-path .gitignore --cache --fix", "pretest": "npm run lint", "generate": "node scripts/generate.js", "prepare": "webpack --config webpack/publish.config.js --progress", @@ -135,7 +137,7 @@ "parse-dashboard": "./bin/parse-dashboard" }, "engines": { - "node": ">=12" + "node": ">=12.20.0" }, "main": "Parse-Dashboard/app.js", "jest": { diff --git a/scripts/generate.js b/scripts/generate.js index 36070e8728..4de778b79f 100644 --- a/scripts/generate.js +++ b/scripts/generate.js @@ -26,7 +26,7 @@ function padding(length) { function generateReact(name) { return ( -`/* + `/* * Copyright (c) 2016-present, Parse, LLC * All rights reserved. * @@ -49,7 +49,7 @@ ${name}.propTypes = { function generateExample(name) { return ( -`/* + `/* * Copyright (c) 2016-present, Parse, LLC * All rights reserved. * @@ -57,7 +57,7 @@ function generateExample(name) { * the root directory of this source tree. */ import React${padding(name.length - 5)} from 'react'; -import ${name}${padding(5 - name.length)} f`+ 'rom' +` 'components/${name}/${name}.react'; +import ${name}${padding(5 - name.length)} f` + 'rom' + ` 'components/${name}/${name}.react'; export const component = ${name}; @@ -74,7 +74,7 @@ export const demos = [ function generateTest(name) { return ( -`/* + `/* * Copyright (c) 2016-present, Parse, LLC * All rights reserved. * @@ -109,12 +109,12 @@ function updateComponentMap(name) { } let spaces = ''; - for (let i = 0; i - suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1 - ); + suggestion => + suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1 + ); return filteredSuggestions; } @@ -226,15 +226,15 @@ export default class Autocomplete extends Component { // Enter const { userInput } = this.state; - if (e.keyCode === 13) { - if (userInput && userInput.length > 0) { + if (e.keyCode === 13) { + if (userInput && userInput.length > 0) { this.props.onSubmit(userInput); } } else if (e.keyCode === 9) { // Tab // do not type it e.preventDefault(); - + e.stopPropagation(); // move focus to input this.inputRef.current.focus(); @@ -317,7 +317,7 @@ export default class Autocomplete extends Component { onClick={onClick} /> ); - } + } return ( @@ -371,5 +371,5 @@ Autocomplete.propTypes = { ), error: PropTypes.string.describe( 'Error to be rendered in place of label if defined' - ) -} + ) +} diff --git a/src/components/BrowserCell/BrowserCell.react.js b/src/components/BrowserCell/BrowserCell.react.js index ccf8da4f2f..d3842b8ed7 100644 --- a/src/components/BrowserCell/BrowserCell.react.js +++ b/src/components/BrowserCell/BrowserCell.react.js @@ -117,7 +117,7 @@ export default class BrowserCell extends Component { } }); - if ( this.props.type === 'Pointer' ) { + if (this.props.type === 'Pointer') { onEditSelectedRow && contextMenuOptions.push({ text: 'Open pointer in new tab', callback: () => { @@ -264,10 +264,10 @@ export default class BrowserCell extends Component { this.copyableValue = value.id; } else if (type === 'Array') { - if ( value[0] && typeof value[0] === 'object' && value[0].__type === 'Pointer' ) { + if (value[0] && typeof value[0] === 'object' && value[0].__type === 'Pointer') { const array = []; - value.map( (v, i) => { - if ( typeof v !== 'object' || v.__type !== 'Pointer' ) { + value.map((v) => { + if (typeof v !== 'object' || v.__type !== 'Pointer') { throw new Error('Invalid type found in pointer array'); } const object = new Parse.Object(v.className); @@ -282,10 +282,10 @@ export default class BrowserCell extends Component { ); }); content = this.copyableValue = JSON.stringify(value); - if ( array.length > 1 ) { + if (array.length > 1) { classes.push(styles.removePadding); } } @@ -339,8 +339,8 @@ export default class BrowserCell extends Component { setRelation(value)} value='View relation' followClick={true} /> ) : ( - 'Relation' - ); + 'Relation' + ); this.copyableValue = undefined; } @@ -359,7 +359,7 @@ export default class BrowserCell extends Component { className={classes.join(' ')} style={{ width }} onClick={(e) => { - if ( e.metaKey === true && type === 'Pointer') { + if (e.metaKey === true && type === 'Pointer') { onPointerCmdClick(value); } else { onSelect({ row, col }); @@ -386,7 +386,7 @@ export default class BrowserCell extends Component { className={classes.join(' ')} style={{ width }} onClick={(e) => { - if ( e.metaKey === true && type === 'Pointer' ) { + if (e.metaKey === true && type === 'Pointer') { onPointerCmdClick(value); } else { diff --git a/src/components/BrowserFilter/FilterRow.react.js b/src/components/BrowserFilter/FilterRow.react.js index f7c2eb05ef..2a4b6a3cc7 100644 --- a/src/components/BrowserFilter/FilterRow.react.js +++ b/src/components/BrowserFilter/FilterRow.react.js @@ -70,26 +70,26 @@ function compareValue(info, value, onChangeCompareTo, active, parentContentId) { className={styles.date} value={Parse._decode('date', value)} onChange={(value) => onChangeCompareTo(Parse._encode(value))} - ref={setFocus} + ref={setFocus} parentContentId={parentContentId} /> ); } } let FilterRow = ({ - fields, - constraints, - compareInfo, - currentField, - currentConstraint, - compareTo, - onChangeField, - onChangeConstraint, - onChangeCompareTo, - onDeleteRow, - active, - parentContentId, - }) => ( + fields, + constraints, + compareInfo, + currentField, + currentConstraint, + compareTo, + onChangeField, + onChangeConstraint, + onChangeCompareTo, + onDeleteRow, + active, + parentContentId, +}) => (
(
{value}
{ - try{ - e.stopPropagation(); - e.nativeEvent.stopPropagation(); - } catch(e){ - console.error(e); - } - - onClose(value); + try{ + e.stopPropagation(); + e.nativeEvent.stopPropagation(); + } catch(e){ + console.error(e); } + + onClose(value); + } }> - + />
diff --git a/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js b/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js index a681b5d0f6..cb2c0315b7 100644 --- a/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js +++ b/src/components/ColumnsConfiguration/ColumnConfigurationItem.react.js @@ -9,7 +9,7 @@ const DND_TYPE = 'ColumnConfigurationItem'; export default ({ name, handleColumnDragDrop, index, onChangeVisible, visible }) => { const [ { isDragging}, drag ] = useDrag({ item: { type: DND_TYPE, index }, - collect: monitor => ({ isDragging: !!monitor.isDragging() }) + collect: monitor => ({ isDragging: !!monitor.isDragging() }) }); const [ { canDrop, isOver }, drop ] = useDrop({ @@ -40,4 +40,4 @@ export default ({ name, handleColumnDragDrop, index, onChangeVisible, visible })
)); -}; \ No newline at end of file +}; diff --git a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js index 04007d4426..20e44979ba 100644 --- a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js +++ b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js @@ -20,9 +20,9 @@ export default class DataBrowserHeaderBar extends React.Component { {readonly ? null : selectAll(e.target.checked)} /> + type='checkbox' + checked={selected} + onChange={(e) => selectAll(e.target.checked)} /> } ]; diff --git a/src/components/DatePicker/DatePicker.react.js b/src/components/DatePicker/DatePicker.react.js index 6fe9aba736..b27b6247d4 100644 --- a/src/components/DatePicker/DatePicker.react.js +++ b/src/components/DatePicker/DatePicker.react.js @@ -73,7 +73,7 @@ export default class DatePicker extends React.Component { ); } - + return (
{content} diff --git a/src/components/DateTimeEntry/DateTimeEntry.react.js b/src/components/DateTimeEntry/DateTimeEntry.react.js index d1eb69c093..8ae9fd8477 100644 --- a/src/components/DateTimeEntry/DateTimeEntry.react.js +++ b/src/components/DateTimeEntry/DateTimeEntry.react.js @@ -96,7 +96,7 @@ export default class DateTimeEntry extends React.Component { ); } - + return (
); } - + return (
{content} diff --git a/src/components/DateTimePicker/DateTimePicker.react.js b/src/components/DateTimePicker/DateTimePicker.react.js index a4fdabe5b2..39ce34dbcb 100644 --- a/src/components/DateTimePicker/DateTimePicker.react.js +++ b/src/components/DateTimePicker/DateTimePicker.react.js @@ -75,13 +75,13 @@ export default class DateTimePicker extends React.Component { parseInt(this.state.hours, 10), parseInt(this.state.minutes, 10) ) : - new Date(Date.UTC( - dateRef.getUTCFullYear(), - dateRef.getUTCMonth(), - dateRef.getUTCDate(), - parseInt(this.state.hours, 10), - parseInt(this.state.minutes, 10) - )); + new Date(Date.UTC( + dateRef.getUTCFullYear(), + dateRef.getUTCMonth(), + dateRef.getUTCDate(), + parseInt(this.state.hours, 10), + parseInt(this.state.minutes, 10) + )); this.props.onChange(newDate); if (this.props.close) { this.props.close(); @@ -100,13 +100,13 @@ export default class DateTimePicker extends React.Component { timeRef.getHours(), timeRef.getMinutes() ) : - new Date(Date.UTC( - newValue.getUTCFullYear(), - newValue.getUTCMonth(), - newValue.getUTCDate(), - timeRef.getUTCHours(), - timeRef.getUTCMinutes() - )); + new Date(Date.UTC( + newValue.getUTCFullYear(), + newValue.getUTCMonth(), + newValue.getUTCDate(), + timeRef.getUTCHours(), + timeRef.getUTCMinutes() + )); this.props.onChange(newDate); }} />
diff --git a/src/components/DonutChart/DonutChart.example.js b/src/components/DonutChart/DonutChart.example.js index 3f2e2ea9ea..f8f31f73a4 100644 --- a/src/components/DonutChart/DonutChart.example.js +++ b/src/components/DonutChart/DonutChart.example.js @@ -24,7 +24,7 @@ export const demos = [ label='Installations' /> ) }, { - name: 'Progress Bar with DonutChart', + name: 'Progress Bar with DonutChart', render: () => ( { +let DonutChart = ({ segments = [], diameter = 200, label = '', isMonochrome = false, printPercentage = false }) => { let centerX = diameter / 2; let centerY = centerX; let radius = centerX * 0.9; diff --git a/src/components/EmptyState/EmptyState.react.js b/src/components/EmptyState/EmptyState.react.js index c56770d5c8..eb87e7724a 100644 --- a/src/components/EmptyState/EmptyState.react.js +++ b/src/components/EmptyState/EmptyState.react.js @@ -23,11 +23,11 @@ let ctaButton = (cta, action) => { ); } else { return ( -
); diff --git a/src/components/MultiSelect/MultiSelect.react.js b/src/components/MultiSelect/MultiSelect.react.js index 327b7d5303..91a7a3ea5f 100644 --- a/src/components/MultiSelect/MultiSelect.react.js +++ b/src/components/MultiSelect/MultiSelect.react.js @@ -35,7 +35,7 @@ export default class MultiSelect extends React.Component { componentDidMount() { this.node = ReactDOM.findDOMNode(this); window.addEventListener('scroll', this.handleScroll) - + } componentWillUnmount(){ window.removeEventListener('scroll', this.handleScroll) @@ -79,7 +79,7 @@ export default class MultiSelect extends React.Component { let popover = null; if (this.state.open) { let width = this.node.clientWidth; - + let classes = [styles.menu]; if (this.props.dense){ classes.push(styles.dense); @@ -89,11 +89,11 @@ export default class MultiSelect extends React.Component {
{React.Children.map(this.props.children, c => React.cloneElement(c, - { - ...c.props, - checked: this.props.value.indexOf(c.props.value) > -1, - onClick: c.props.disabled? null : this.select.bind(this, c.props.value) - } + { + ...c.props, + checked: this.props.value.indexOf(c.props.value) > -1, + onClick: c.props.disabled ? null : this.select.bind(this, c.props.value) + } ))}
@@ -127,29 +127,29 @@ export default class MultiSelect extends React.Component { classes.push(styles.placeholder); } else { - content = this.props.chips? - selection.map((child,index) => { - let item; - if(Array.isArray(this.props.value)){ - item = this.props.value[index] - } - return ( - { - if(removed) this.select(removed); - }}> - {child} - )} - ) : - stringList(selection, this.props.endDelineator); + content = this.props.chips ? + selection.map((child,index) => { + let item; + if(Array.isArray(this.props.value)){ + item = this.props.value[index] + } + return ( + { + if(removed) this.select(removed); + }}> + {child} + )} + ) : + stringList(selection, this.props.endDelineator); } return (
- {content} + {content}
{popover}
diff --git a/src/components/MultiSelect/MultiSelectOption.react.js b/src/components/MultiSelect/MultiSelectOption.react.js index 3e8bf8ad08..f50169bfd6 100644 --- a/src/components/MultiSelect/MultiSelectOption.react.js +++ b/src/components/MultiSelect/MultiSelectOption.react.js @@ -10,11 +10,11 @@ import React from 'react'; import styles from 'components/MultiSelect/MultiSelect.scss'; let MultiSelectOption = ({ checked, children, dense, disabled, ...other }) => { - + const classes = [styles.option, - disabled? styles.disabled: undefined + disabled ? styles.disabled : undefined ]; - + const icon = checked ? (
{ ) : (
) - + return ( -
- {children} - {disabled ?
-); +
+ {children} + {disabled ?
+ ); } export default MultiSelectOption; diff --git a/src/components/PermissionsDialog/PermissionsDialog.example.js b/src/components/PermissionsDialog/PermissionsDialog.example.js index 5f21a96bdb..82c2a871b0 100644 --- a/src/components/PermissionsDialog/PermissionsDialog.example.js +++ b/src/components/PermissionsDialog/PermissionsDialog.example.js @@ -28,7 +28,7 @@ function validateSimple(text) { } function validateAdvanced(text) { - if (text==='*') { + if (text === '*') { return Promise.resolve({ entry: '*' , type:'public'}); } if (text.startsWith('u')) { diff --git a/src/components/PermissionsDialog/PermissionsDialog.react.js b/src/components/PermissionsDialog/PermissionsDialog.react.js index cd06a20bdb..23a9ba3971 100644 --- a/src/components/PermissionsDialog/PermissionsDialog.react.js +++ b/src/components/PermissionsDialog/PermissionsDialog.react.js @@ -6,8 +6,8 @@ * the root directory of this source tree. */ import { - unselectable, - verticalCenter } from 'stylesheets/base.scss'; + unselectable, + verticalCenter } from 'stylesheets/base.scss'; import Button from 'components/Button/Button.react'; import Checkbox from 'components/Checkbox/Checkbox.react'; import Icon from 'components/Icon/Icon.react'; @@ -592,12 +592,12 @@ export default class PermissionsDialog extends React.Component { // The double check is necessary because the permissions object seems to be empty when accessing the CLP section // if the class was recently created. (pointerPermsSubset.get = permissions.get && permissions.get.pointerFields || []), - (pointerPermsSubset.find = permissions.find && permissions.find.pointerFields || []), - (pointerPermsSubset.count = permissions.count && permissions.count.pointerFields || []), - (pointerPermsSubset.create = permissions.create && permissions.create.pointerFields || []), - (pointerPermsSubset.update = permissions.update && permissions.update.pointerFields || []), - (pointerPermsSubset.delete = permissions.delete && permissions.delete.pointerFields || []), - (pointerPermsSubset.addField = permissions.addField && permissions.addField.pointerFields || []); + (pointerPermsSubset.find = permissions.find && permissions.find.pointerFields || []), + (pointerPermsSubset.count = permissions.count && permissions.count.pointerFields || []), + (pointerPermsSubset.create = permissions.create && permissions.create.pointerFields || []), + (pointerPermsSubset.update = permissions.update && permissions.update.pointerFields || []), + (pointerPermsSubset.delete = permissions.delete && permissions.delete.pointerFields || []), + (pointerPermsSubset.addField = permissions.addField && permissions.addField.pointerFields || []); } let pointerPerms = {}; @@ -1257,8 +1257,8 @@ export default class PermissionsDialog extends React.Component { )} {this.props.advanced ? this.state.pointers.map(pointer => - this.renderRow(pointer, this.state.columns) - ) + this.renderRow(pointer, this.state.columns) + ) : null} {this.state.newKeys.map(key => this.renderRow(key, this.state.columns, this.state.entryTypes) @@ -1285,7 +1285,7 @@ export default class PermissionsDialog extends React.Component { buildSuggestions={input => this.suggestInput(input)} buildLabel={input => this.buildLabel(input)} error={this.state.entryError} - /> + />
diff --git a/src/components/Pill/Pill.react.js b/src/components/Pill/Pill.react.js index 45c6aa9d5a..764f1f9eb2 100644 --- a/src/components/Pill/Pill.react.js +++ b/src/components/Pill/Pill.react.js @@ -7,7 +7,7 @@ */ import React from 'react'; import styles from 'components/Pill/Pill.scss'; -import Icon from "components/Icon/Icon.react"; +import Icon from 'components/Icon/Icon.react'; //TODO: refactor, may want to move onClick outside or need to make onClick able to handle link/button a11y let Pill = ({ value, onClick, fileDownloadLink, followClick = false }) => ( @@ -15,7 +15,7 @@ let Pill = ({ value, onClick, fileDownloadLink, followClick = false }) => ( className={[ styles.pill, !followClick && onClick ? styles.action : void 0 - ].join(" ")} + ].join(' ')} onClick={!followClick && onClick ? onClick : null} > {value} diff --git a/src/components/PlatformCard/PlatformCard.example.js b/src/components/PlatformCard/PlatformCard.example.js index 3c54ac5549..023eceb1eb 100644 --- a/src/components/PlatformCard/PlatformCard.example.js +++ b/src/components/PlatformCard/PlatformCard.example.js @@ -15,47 +15,47 @@ export const demos = [ name: 'iOS PlatformCard', render: () => ( + platform='apple' + name='iOS' + subtitle='Swift' + color='blue' /> ) }, { name: 'Xamarin PlatformCard', render: () => ( + platform='xamarin' + name='iOS' + subtitle='Xamarin' + color='blue' /> ) }, { name: 'OSX PlatformCard', render: () => ( + platform='apple' + name='OSX' + color='green' /> ) }, { name: 'RPi PlatformCard', render: () => ( + platform='rpi' + name='Linux C (Raspberry Pi)' + color='red' /> ) }, { name: 'Arduino PlatformCard', render: () => ( + platform='arduino' + name='Arduino Yun' + color='red' /> ) }, ]; diff --git a/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.example.js b/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.example.js index 6eb0e024d2..2eef2fb77c 100644 --- a/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.example.js +++ b/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.example.js @@ -6,18 +6,18 @@ * the root directory of this source tree. */ import React from 'react'; -import ProtectedFieldsDialog - from 'components/ProtectedFieldsDialog/ProtectedFieldsDialog.react'; +import ProtectedFieldsDialog + from 'components/ProtectedFieldsDialog/ProtectedFieldsDialog.react'; import Button from 'components/Button/Button.react'; export const component = ProtectedFieldsDialog; function validateDemo(text) { - if (text===('*')) { + if (text === ('*')) { return Promise.resolve({ entry: '*' , type:'public'}); } - if (text===('authenticated')) { + if (text === ('authenticated')) { return Promise.resolve({ entry: 'authenticated' , type:'auth'}); } if (text.startsWith('u')) { @@ -73,28 +73,28 @@ class ProtectedFieldsDemo extends React.Component { }); }}/> - Learn more about CLPs and app security} - protectedFields={{ - '*': ['password', 'email'], - 'userField:ptr_owner': [], - 'us3r1d': ['password'] - }} - userPointers={userPointers} - columns={columns} - validateEntry={validateDemo} - onCancel={() => { - this.setState({ - show: false, - }); - }} - onClose={()=>{}} - onConfirm={(perms) => { - console.log(perms); - }} /> + Learn more about CLPs and app security} + protectedFields={{ + '*': ['password', 'email'], + 'userField:ptr_owner': [], + 'us3r1d': ['password'] + }} + userPointers={userPointers} + columns={columns} + validateEntry={validateDemo} + onCancel={() => { + this.setState({ + show: false, + }); + }} + onClose={()=>{}} + onConfirm={(perms) => { + console.log(perms); + }} />
); } diff --git a/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.react.js b/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.react.js index 652aaf453f..40e51a38ac 100644 --- a/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.react.js +++ b/src/components/ProtectedFieldsDialog/ProtectedFieldsDialog.react.js @@ -19,7 +19,7 @@ import styles from 'components/ProtectedFieldsDialog/ProtectedFields import MultiSelect from 'components/MultiSelect/MultiSelect.react'; import MultiSelectOption from 'components/MultiSelect/MultiSelectOption.react'; import TrackVisibility from 'components/TrackVisibility/TrackVisibility.react'; -import { +import { unselectable, verticalCenter } from 'stylesheets/base.scss'; @@ -240,12 +240,12 @@ export default class ProtectedFieldsDialog extends React.Component { if(noAvailableFields){ options.push( - {'This class has no fields to protect'} + {'This class has no fields to protect'} ) } - const placeholder = 'All fields allowed.'+ (noAvailableFields ? '': ' Click to protect.'); + const placeholder = 'All fields allowed.' + (noAvailableFields ? '' : ' Click to protect.'); return (
diff --git a/src/components/PushAudienceDialog/InstallationCondition.react.js b/src/components/PushAudienceDialog/InstallationCondition.react.js index b9f3b68564..c3fbe844e9 100644 --- a/src/components/PushAudienceDialog/InstallationCondition.react.js +++ b/src/components/PushAudienceDialog/InstallationCondition.react.js @@ -51,8 +51,8 @@ function compareValue(info, value, onChangeCompareTo) { return onChangeCompareTo(_value === 'True')} > - {['True', 'False'].map(value => )} - + {['True', 'False'].map(value => )} + case 'Number': return onChangeCompareTo(validateNumeric(_value) ? Number(_value) : Number(value))} ref={setFocus}/>; case 'Date': diff --git a/src/components/PushAudienceDialog/PushAudienceDialog.react.js b/src/components/PushAudienceDialog/PushAudienceDialog.react.js index 8fb0355dbd..505972f6e4 100644 --- a/src/components/PushAudienceDialog/PushAudienceDialog.react.js +++ b/src/components/PushAudienceDialog/PushAudienceDialog.react.js @@ -245,18 +245,18 @@ export default class PushAudienceDialog extends React.Component { label={
- )}> + )}>
diff --git a/src/components/TrackVisibility/TrackVisibility.example.js b/src/components/TrackVisibility/TrackVisibility.example.js index 7cea63daf6..9ba6fecc58 100644 --- a/src/components/TrackVisibility/TrackVisibility.example.js +++ b/src/components/TrackVisibility/TrackVisibility.example.js @@ -32,12 +32,12 @@ class DemoTrackVisibility extends React.Component { }); this.state = { - visibility: 0 + visibility: 0 }; } render() { - + return (
{'Yellow block is ' + this.state.visibility + '% visible'}
@@ -59,7 +59,7 @@ class DemoTrackVisibility extends React.Component { export const demos = [ { render: () => ( - + ) } ]; diff --git a/src/dashboard/Account/AccountLinkField.react.js b/src/dashboard/Account/AccountLinkField.react.js index ff6489a19b..736f5e9666 100644 --- a/src/dashboard/Account/AccountLinkField.react.js +++ b/src/dashboard/Account/AccountLinkField.react.js @@ -20,20 +20,20 @@ export class AccountLinkField extends React.Component { return (
+ method='post' + action={this.props.metadata.linked ? + this.props.metadata.deauthorize_url : + this.props.metadata.authorize_url}> } input={ this.refs.modify.submit()} />}/> + value={this.props.metadata.linked ? + 'Unlink ' + this.props.serviceName : + 'Connect ' + this.props.serviceName} + onClick={() => this.refs.modify.submit()} />}/>
); } diff --git a/src/dashboard/Account/AccountOverview.react.js b/src/dashboard/Account/AccountOverview.react.js index c6966ad5f7..250fff0b3f 100644 --- a/src/dashboard/Account/AccountOverview.react.js +++ b/src/dashboard/Account/AccountOverview.react.js @@ -86,8 +86,8 @@ export default class AccountOverview extends React.Component { let linkedAccountsFields = this.state.linkedAccounts !== null ?
+ legend='Linked Accounts' + description='Manage the accounts you have linked to Parse.' > diff --git a/src/dashboard/Analytics/Explorer/Explorer.react.js b/src/dashboard/Analytics/Explorer/Explorer.react.js index b92034bab0..5d54144680 100644 --- a/src/dashboard/Analytics/Explorer/Explorer.react.js +++ b/src/dashboard/Analytics/Explorer/Explorer.react.js @@ -132,7 +132,7 @@ class Explorer extends DashboardView { // Update activeQueries[existingQueryIndex] = query; } - + // Update the state to trigger rendering pipeline. this.setState({ activeQueries, diff --git a/src/dashboard/Analytics/Performance/Performance.react.js b/src/dashboard/Analytics/Performance/Performance.react.js index bfaecf7d5b..0b4d31435b 100644 --- a/src/dashboard/Analytics/Performance/Performance.react.js +++ b/src/dashboard/Analytics/Performance/Performance.react.js @@ -156,7 +156,7 @@ export default class Performance extends DashboardView { renderContent() { let toolbar = ( ); diff --git a/src/dashboard/Analytics/Retention/Retention.react.js b/src/dashboard/Analytics/Retention/Retention.react.js index 5fe7e4a905..8a3064dc7b 100644 --- a/src/dashboard/Analytics/Retention/Retention.react.js +++ b/src/dashboard/Analytics/Retention/Retention.react.js @@ -25,13 +25,13 @@ const REVERSED_RETENTION_DAYS = RETENTION_DAYS.slice().reverse(); let retentionChartColor = percent => { let red, blue, green; if (percent > 50) { - red = 23 + ( ( percent - 50 ) * 2 ) * 11 / 100; - green = 166 - ( ( percent - 50 ) * 2 ) * 166 / 100; + red = 23 + ((percent - 50) * 2) * 11 / 100; + green = 166 - ((percent - 50) * 2) * 166 / 100; blue = 255; } else { - red = 228 - ( percent * 2 ) * 205 / 100; - green = 233 - ( percent * 2 ) * 67 / 100; - blue = 237 + ( percent * 2 ) * 18 / 100; + red = 228 - (percent * 2) * 205 / 100; + green = 233 - (percent * 2) * 67 / 100; + blue = 237 + (percent * 2) * 18 / 100; } //return without decimals since css doesn't allow them return 'rgb(' + red.toFixed(0) + ', ' + green.toFixed(0) + ', ' + blue.toFixed(0) + ')'; @@ -101,7 +101,7 @@ export default class Retention extends DashboardView {
{active} of {total} users who signed up on {monthDayPretty} were still active on their {englishOrdinalIndicator(day)} day
- )}> + )}>
{percentage}%
@@ -145,12 +145,12 @@ export default class Retention extends DashboardView { return ( -
- {(daysAgo === 28 || formattedDateDay === '1' ? formattedDateMonth : '')} +
+ {(daysAgo === 28 || formattedDateDay === '1' ? formattedDateMonth : '')} {formattedDateDay}
- {(daysAgo === 28 || formattedDateDay === '1' ? 'Users ' : '')} + {(daysAgo === 28 || formattedDateDay === '1' ? 'Users ' : '')} {prettyNumber(dayData.total)}
diff --git a/src/dashboard/Analytics/SlowQueries/SlowQueries.react.js b/src/dashboard/Analytics/SlowQueries/SlowQueries.react.js index c0ac36aee7..772a646412 100644 --- a/src/dashboard/Analytics/SlowQueries/SlowQueries.react.js +++ b/src/dashboard/Analytics/SlowQueries/SlowQueries.react.js @@ -177,7 +177,7 @@ class SlowQueries extends TableView { } return ( - {actions} @@ -235,7 +235,7 @@ class SlowQueries extends TableView { onClick={this.fetchSlowQueries.bind(this, this.context.currentApp)} value='Run query' /> )} - /> + /> ); } } diff --git a/src/dashboard/Apps/AppsIndex.react.js b/src/dashboard/Apps/AppsIndex.react.js index 164151d96a..ce0916b2d9 100644 --- a/src/dashboard/Apps/AppsIndex.react.js +++ b/src/dashboard/Apps/AppsIndex.react.js @@ -46,10 +46,10 @@ let CloningNote = ({ app, clone_status, clone_progress }) => { }; let CountsSection = ({ className, title, children }) => -
-
{title}
- {children} -
+
+
{title}
+ {children} +
let Metric = (props) => { return ( @@ -66,7 +66,7 @@ let AppCard = ({ }) => { let canBrowse = app.serverInfo.error ? null : () => history.push(html`/apps/${app.slug}/browser`); let versionMessage = app.serverInfo.error ? -
Server not reachable: {app.serverInfo.error.toString()}
: +
Server not reachable: {app.serverInfo.error.toString()}
:
Server URL: {app.serverURL || 'unknown'} Server version: {app.serverInfo.parseServerVersion || 'unknown'} diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 0dfe25ce1a..4cfc87fa92 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -67,10 +67,10 @@ let Empty = createClass({ }); const AccountSettingsPage = () => ( - - - - ); + + + +); const PARSE_DOT_COM_SERVER_INFO = { features: { diff --git a/src/dashboard/DashboardView.react.js b/src/dashboard/DashboardView.react.js index c1d53a6e0e..37f18e66fe 100644 --- a/src/dashboard/DashboardView.react.js +++ b/src/dashboard/DashboardView.react.js @@ -235,18 +235,18 @@ export default class DashboardView extends React.Component { } let sidebar = ( - - {sidebarChildren} - ); + {sidebarChildren} + ); return (
diff --git a/src/dashboard/Data/ApiConsole/RestConsole.react.js b/src/dashboard/Data/ApiConsole/RestConsole.react.js index 23afd3abfc..c6b04d42a0 100644 --- a/src/dashboard/Data/ApiConsole/RestConsole.react.js +++ b/src/dashboard/Data/ApiConsole/RestConsole.react.js @@ -52,8 +52,8 @@ export default class RestConsole extends Component { return; } Parse.Query.or( - new Parse.Query(Parse.User).equalTo('username', this.state.runAsIdentifier ), - new Parse.Query(Parse.User).equalTo('objectId', this.state.runAsIdentifier ) + new Parse.Query(Parse.User).equalTo('username', this.state.runAsIdentifier), + new Parse.Query(Parse.User).equalTo('objectId', this.state.runAsIdentifier) ).first({ useMasterKey: true }).then((found) => { if (found) { if (found.getSessionToken()) { diff --git a/src/dashboard/Data/ApiConsole/generateCurl.js b/src/dashboard/Data/ApiConsole/generateCurl.js index fbce5620b9..47141eeda8 100644 --- a/src/dashboard/Data/ApiConsole/generateCurl.js +++ b/src/dashboard/Data/ApiConsole/generateCurl.js @@ -18,7 +18,7 @@ export default function generateCurl(app, method, path, body, options) { if (path[0] === '/') { path = path.substr(1); } - + let headers = [[`-H "X-Parse-Application-Id: ${app.applicationId}" \\`]]; if (options.useMasterKey) { headers.push([`-H "X-Parse-Master-Key: ${app.masterKey}" \\`]); @@ -31,7 +31,7 @@ export default function generateCurl(app, method, path, body, options) { let _body = escapeValueForCURL(body); - let request = 'curl -X ' + method +' \\\n' + headers.join('\n') + '\n'; + let request = 'curl -X ' + method + ' \\\n' + headers.join('\n') + '\n'; if (_body && _body.length) { if (method === 'GET') { request += '-G \\\n'; diff --git a/src/dashboard/Data/Browser/AttachSelectedRowsDialog.react.js b/src/dashboard/Data/Browser/AttachSelectedRowsDialog.react.js index aea434f49d..4981a1cb74 100644 --- a/src/dashboard/Data/Browser/AttachSelectedRowsDialog.react.js +++ b/src/dashboard/Data/Browser/AttachSelectedRowsDialog.react.js @@ -79,49 +79,49 @@ export default class AttachSelectedRowsDialog extends React.Component { } = this.props; let targetRelationSelector; let targetEntityIdInsert; - if (this.state.touchableColumns.length) { - targetRelationSelector = ( - - } - input={ - - {this.state.touchableColumns.map(column => ( - - ))} - - } - /> - ); - } - if (this.state.currentColumn) { - targetEntityIdInsert = ( - - } - input={ - - } - /> - ); - } + if (this.state.touchableColumns.length) { + targetRelationSelector = ( + + } + input={ + + {this.state.touchableColumns.map(column => ( + + ))} + + } + /> + ); + } + if (this.state.currentColumn) { + targetEntityIdInsert = ( + + } + input={ + + } + /> + ); + } return ( this.handleFetchedSchema()); + .then(() => this.handleFetchedSchema()); if (!this.props.params.className && this.props.schema.data.get('classes')) { this.redirectToFirstClass(this.props.schema.data.get('classes')); } else if (this.props.params.className) { @@ -169,7 +169,7 @@ class Browser extends DashboardView { } this.prefetchData(nextProps, nextContext); nextProps.schema.dispatch(ActionTypes.FETCH) - .then(() => this.handleFetchedSchema()); + .then(() => this.handleFetchedSchema()); } if (!nextProps.params.className && nextProps.schema.data.get('classes')) { this.redirectToFirstClass(nextProps.schema.data.get('classes')); @@ -362,7 +362,7 @@ class Browser extends DashboardView { this.setState({ newObject: (relation ? new Parse.Object(relation.targetClassName) - : new Parse.Object(this.props.params.className) ), + : new Parse.Object(this.props.params.className)), }); } } @@ -393,27 +393,27 @@ class Browser extends DashboardView { if (className) { let classColumns = this.props.schema.data.get('classes').get(className); classColumns.forEach(({ required }, name) => { - if (name === 'objectId' || this.state.isUnique && name !== this.state.uniqueField) { - return; - } - if (!!required) { - requiredCols.push(name); - } - if (className === '_User' && (name === 'username' || name === 'password')) { - if (!obj.get('authData')) { - requiredCols.push(name); - } - } - if (className === '_Role' && (name === 'name' || name === 'ACL')) { + if (name === 'objectId' || this.state.isUnique && name !== this.state.uniqueField) { + return; + } + if (required) { + requiredCols.push(name); + } + if (className === '_User' && (name === 'username' || name === 'password')) { + if (!obj.get('authData')) { requiredCols.push(name); } - }); + } + if (className === '_Role' && (name === 'name' || name === 'ACL')) { + requiredCols.push(name); + } + }); } if (requiredCols.length) { for (let idx = 0; idx < requiredCols.length; idx++) { const name = requiredCols[idx]; if (!obj.get(name)) { - this.showNote("Please enter all required fields", true); + this.showNote('Please enter all required fields', true); this.setState({ markRequiredFieldRow: -1 }); @@ -451,11 +451,11 @@ class Browser extends DashboardView { }); }, error => { - let msg = typeof error === "string" ? error : error.message; + let msg = typeof error === 'string' ? error : error.message; if (msg) { msg = msg[0].toUpperCase() + msg.substr(1); } - obj.set(attr, prev); + // obj.set(attr, prev); this.setState({ data: this.state.data }); this.showNote(msg, true); } @@ -471,7 +471,7 @@ class Browser extends DashboardView { this.setState(state); }, error => { - let msg = typeof error === "string" ? error : error.message; + let msg = typeof error === 'string' ? error : error.message; if (msg) { msg = msg[0].toUpperCase() + msg.substr(1); } @@ -497,27 +497,27 @@ class Browser extends DashboardView { if (className) { let classColumns = this.props.schema.data.get('classes').get(className); classColumns.forEach(({ required }, name) => { - if (name === 'objectId' || this.state.isUnique && name !== this.state.uniqueField) { - return; - } - if (!!required) { - requiredCols.push(name); - } - if (className === '_User' && (name === 'username' || name === 'password')) { - if (!obj.get('authData')) { - requiredCols.push(name); - } - } - if (className === '_Role' && (name === 'name' || name === 'ACL')) { + if (name === 'objectId' || this.state.isUnique && name !== this.state.uniqueField) { + return; + } + if (required) { + requiredCols.push(name); + } + if (className === '_User' && (name === 'username' || name === 'password')) { + if (!obj.get('authData')) { requiredCols.push(name); } - }); + } + if (className === '_Role' && (name === 'name' || name === 'ACL')) { + requiredCols.push(name); + } + }); } if (requiredCols.length) { for (let idx = 0; idx < requiredCols.length; idx++) { const name = requiredCols[idx]; if (!obj.get(name)) { - this.showNote("Please enter all required fields", true); + this.showNote('Please enter all required fields', true); this.setState({ markRequiredFieldRow: rowIndex }); @@ -608,7 +608,7 @@ class Browser extends DashboardView { handleFetchedSchema() { this.props.schema.data.get('classes').forEach((_, className) => { this.context.currentApp.getClassCount(className) - .then(count => this.setState({ counts: { [className]: count, ...this.state.counts } })); + .then(count => this.setState({ counts: { [className]: count, ...this.state.counts } })); }) this.setState({clp: this.props.schema.data.get('CLPs').toJS()}); } @@ -829,9 +829,9 @@ class Browser extends DashboardView { handlePointerClick({ className, id, field = 'objectId' }) { let filters = JSON.stringify([{ - field, - constraint: 'eq', - compareTo: id + field, + constraint: 'eq', + compareTo: id }]); history.push(this.context.generatePath(`browser/${className}?filters=${encodeURIComponent(filters)}`)); } @@ -1343,10 +1343,10 @@ class Browser extends DashboardView { let columns = []; const classes = this.props.schema.data.get('classes'); classes.get(className).forEach((field, name) => { - columns.push({ - ...field, - name, - }); + columns.push({ + ...field, + name, + }); }); if (onlyTouchable) { let untouchable = DefaultColumns.All; diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index d200c01fb1..2b35ce3712 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -73,11 +73,11 @@ let BrowserToolbar = ({ let isPendingEditCloneRows = editCloneRows && editCloneRows.length > 0; let details = []; if (count !== undefined) { - if (count === 1) { - details.push('1 object'); - } else { - details.push(prettyNumber(count) + ' objects'); - } + if (count === 1) { + details.push('1 object'); + } else { + details.push(prettyNumber(count) + ' objects'); + } } if (!relation && !isUnique) { @@ -185,7 +185,7 @@ let BrowserToolbar = ({ if (col === 'objectId' || isUnique && col !== uniqueField) { return; } - if ((type ==='Pointer' && targetClass === '_User') || type === 'Array' ) { + if ((type === 'Pointer' && targetClass === '_User') || type === 'Array') { userPointers.push(col); } }); @@ -232,15 +232,15 @@ let BrowserToolbar = ({ )} {onAddRow && ( - - {currentUser ? Use Master Key } onClick={toggleMasterKeyUsage} /> :
); } export default class GeneralSettings extends DashboardView { @@ -506,7 +506,7 @@ export default class GeneralSettings extends DashboardView { clearFields={() => this.setState({ password: '', transferNewOwner: '', - })}> + })}> this.setState({transferNewOwner: collaborator})}> - {((this.props.initialFields||{}).collaborators||[]).map(collaborator => - {collaborator.userEmail} - )} + {((this.props.initialFields || {}).collaborators || []).map(collaborator => + {collaborator.userEmail} + )} } /> {AccountManager.currentUser().has_password ? passwordField : null} ; @@ -568,7 +568,7 @@ export default class GeneralSettings extends DashboardView { input={ this.setState({cloneAppName: value}) - } /> } /> + } /> } /> } diff --git a/src/dashboard/Settings/HostingSettings.react.js b/src/dashboard/Settings/HostingSettings.react.js index 494cf8b800..b3394dd3d1 100644 --- a/src/dashboard/Settings/HostingSettings.react.js +++ b/src/dashboard/Settings/HostingSettings.react.js @@ -22,350 +22,350 @@ import Toolbar from 'components/Toolbar/Toolbar.react'; import unique from 'lib/unique'; export default class HostingSettings extends DashboardView { - constructor() { - super(); - this.section = 'App Settings'; - this.subsection = 'Hosting and Emails'; + constructor() { + super(); + this.section = 'App Settings'; + this.subsection = 'Hosting and Emails'; - this.state = { - sslPublicCertUploading: false, - sslPublicCertError: '', + this.state = { + sslPublicCertUploading: false, + sslPublicCertError: '', - sslPrivateKeyUploading: false, - sslPrivateKeyError:'', - }; - } + sslPrivateKeyUploading: false, + sslPrivateKeyError:'', + }; + } - renderForm({fields, setField}) { - let hostingSubdomainFields =
- } - input={ - } - /> -
; + renderForm({fields, setField}) { + let hostingSubdomainFields =
+ } + input={ + } + /> +
; - let customDomainsFields =
- } - input={} - /> - } - input={ {}}/> - } /> - - } - input={ { - this.setState({ - sslPublicCertUploading: true, - sslPublicCertError: '', - }); - //TODO: do something here to indicate success and/or upload when you click the FlowView save button rather than immediately - this.context.currentApp.uploadSSLPublicCertificate(file).catch(({ error }) => { - this.setState({ sslPublicCertError: error }); - }).finally(() => { - this.setState({ sslPublicCertUploading: false }); - }); - }} /> - } /> - 0} - color='red'> - {this.state.sslPublicCertError} - - - } - input={ { - this.setState({ - sslPrivateKeyUploading: true, - sslPrivateKeyError: '', - }); - //TODO: do something here to indicate success and/or upload when you click the FlowView save button rather than immediately - this.context.currentApp.uploadSSLPrivateKey(file).catch(({ error }) => { - this.setState({ sslPrivateKeyError: error }); - }).finally(() => { - this.setState({ sslPrivateKeyUploading: false }); - }); - }} /> - } /> - {this.state.sslPrivateKeyError.length > 0 ? 0} - color='red'> - {this.state.sslPrivateKeyError} - : null} -
; + let customDomainsFields =
+ } + input={} + /> + } + input={ {}}/> + } /> + + } + input={ { + this.setState({ + sslPublicCertUploading: true, + sslPublicCertError: '', + }); + //TODO: do something here to indicate success and/or upload when you click the FlowView save button rather than immediately + this.context.currentApp.uploadSSLPublicCertificate(file).catch(({ error }) => { + this.setState({ sslPublicCertError: error }); + }).finally(() => { + this.setState({ sslPublicCertUploading: false }); + }); + }} /> + } /> + 0} + color='red'> + {this.state.sslPublicCertError} + + + } + input={ { + this.setState({ + sslPrivateKeyUploading: true, + sslPrivateKeyError: '', + }); + //TODO: do something here to indicate success and/or upload when you click the FlowView save button rather than immediately + this.context.currentApp.uploadSSLPrivateKey(file).catch(({ error }) => { + this.setState({ sslPrivateKeyError: error }); + }).finally(() => { + this.setState({ sslPrivateKeyUploading: false }); + }); + }} /> + } /> + {this.state.sslPrivateKeyError.length > 0 ? 0} + color='red'> + {this.state.sslPrivateKeyError} + : null} +
; - let emailSettingsFields =
- - } - input={ - } - /> - - } - input={ - } - /> - - } - input={ - } - /> -
; + let emailSettingsFields =
+ + } + input={ + } + /> + + } + input={ + } + /> + + } + input={ + } + /> +
; - let emailTemplatesFields =
- } - input={ - } /> - } - input={ - } /> - } - input={ - } /> - } - input={ - } /> -
; + let emailTemplatesFields =
+ } + input={ + } /> + } + input={ + } /> + } + input={ + } /> + } + input={ + } /> +
; - let userFacingPagesFields =
- This page will be loaded when users click on a reset password link. Download the template.} /> - } - input={ - } /> - This page will be loaded when users successfully change their password. Download the template.} /> - } - input={ - } /> - This page will be loaded when users verify their email address. Download the template.} /> - } - input={ - } /> - This page will be loaded whenever users mistype the reset password or verify email links. Download the template.} /> - } - input={ - } /> -
+ let userFacingPagesFields =
+ This page will be loaded when users click on a reset password link. Download the template.} /> + } + input={ + } /> + This page will be loaded when users successfully change their password. Download the template.} /> + } + input={ + } /> + This page will be loaded when users verify their email address. Download the template.} /> + } + input={ + } /> + This page will be loaded whenever users mistype the reset password or verify email links. Download the template.} /> + } + input={ + } /> +
- let whiteLabelURLsFields =
- Upload this file to your server and tell us where you put it.} /> - } - input={ - } /> -
; - return
- {hostingSubdomainFields} - {customDomainsFields} - {emailSettingsFields} - {emailTemplatesFields} - {userFacingPagesFields} - {whiteLabelURLsFields} - -
; - } + let whiteLabelURLsFields =
+ Upload this file to your server and tell us where you put it.} /> + } + input={ + } /> +
; + return
+ {hostingSubdomainFields} + {customDomainsFields} + {emailSettingsFields} + {emailTemplatesFields} + {userFacingPagesFields} + {whiteLabelURLsFields} + +
; + } - renderContent() { - let initialFields = { - ...(this.props.initialFields || {}) - }; - return renderFlowFooterChanges(changes, initialFields, hostingFieldOptions)} - onSubmit={({ changes, setField }) => { - return this.props.saveChanges(changes).then(({ successes, failures }) => { - for (let k in successes) { - setField(k, successes[k]); - } - if (Object.keys(failures).length > 0) { - return Promise.reject({ error: Object.values(failures).join(' ') }); - } - }).catch(({ error, failures = {} }) => { - return Promise.reject({ error: unique(Object.values(failures).concat(error)).join(' ') }); - }); - }} - validate={() => '' /*TODO: do some validation*/} - renderForm={this.renderForm.bind(this)} - />; - } + renderContent() { + let initialFields = { + ...(this.props.initialFields || {}) + }; + return renderFlowFooterChanges(changes, initialFields, hostingFieldOptions)} + onSubmit={({ changes, setField }) => { + return this.props.saveChanges(changes).then(({ successes, failures }) => { + for (let k in successes) { + setField(k, successes[k]); + } + if (Object.keys(failures).length > 0) { + return Promise.reject({ error: Object.values(failures).join(' ') }); + } + }).catch(({ error, failures = {} }) => { + return Promise.reject({ error: unique(Object.values(failures).concat(error)).join(' ') }); + }); + }} + validate={() => '' /*TODO: do some validation*/} + renderForm={this.renderForm.bind(this)} + />; + } } let hostingFieldOptions = { - external_frame_link: { - friendlyName: 'parse frame URL', - showTo: true, - }, - invalid_link_link: { - friendlyName: 'custom 404 page', - }, - choose_password_link: { - friendlyName: 'custom "choose a new password" page', - }, - email_verification_link: { - friendlyName: 'custom "email verified" page' - }, - password_updated_link: { - friendlyName: 'custom "password changed" page', - }, + external_frame_link: { + friendlyName: 'parse frame URL', + showTo: true, + }, + invalid_link_link: { + friendlyName: 'custom 404 page', + }, + choose_password_link: { + friendlyName: 'custom "choose a new password" page', + }, + email_verification_link: { + friendlyName: 'custom "email verified" page' + }, + password_updated_link: { + friendlyName: 'custom "password changed" page', + }, - subdomain_name: { - friendlyName: 'subdomain name', - showFrom: true, - showTo: true, - }, + subdomain_name: { + friendlyName: 'subdomain name', + showFrom: true, + showTo: true, + }, - send_email_address: { - friendlyName: 'reply-to address', - showTo: true, - }, - sender_display_name: { - friendlyName: 'display name', - showTo: true, - showFrom: true, - }, - verify_emails: { - friendlyName: 'user email verification', - type: 'boolean' - }, + send_email_address: { + friendlyName: 'reply-to address', + showTo: true, + }, + sender_display_name: { + friendlyName: 'display name', + showTo: true, + showFrom: true, + }, + verify_emails: { + friendlyName: 'user email verification', + type: 'boolean' + }, - host_name: { - friendlyName: 'host name', - showTo: true, - }, + host_name: { + friendlyName: 'host name', + showTo: true, + }, - email_verification_mail_subject: { - friendlyName: 'verification email subject', - }, - email_verification_mail_body: { - friendlyName: 'verification email body', - }, - reset_password_mail_subject: { - friendlyName: 'password reset subject', - }, - reset_password_mail_body: { - friendlyName: 'password reset email body', - }, + email_verification_mail_subject: { + friendlyName: 'verification email subject', + }, + email_verification_mail_body: { + friendlyName: 'verification email body', + }, + reset_password_mail_subject: { + friendlyName: 'password reset subject', + }, + reset_password_mail_body: { + friendlyName: 'password reset email body', + }, } diff --git a/src/dashboard/Settings/PushSettings.react.js b/src/dashboard/Settings/PushSettings.react.js index a0f2524f43..3cbc36fc92 100644 --- a/src/dashboard/Settings/PushSettings.react.js +++ b/src/dashboard/Settings/PushSettings.react.js @@ -85,24 +85,24 @@ export default class PushSettings extends DashboardView { label={
}> - Disable legacy session tokens to make your app more secure. If enabled, all requests with legacy tokens will error. Learn more} - />} - input={} - /> - We’ll automatically delete revocable sessions that have not made an API request in the last year.} - />} - input={} - /> - When a user changes or resets their password, we’ll
automatically delete all Session objects associated with this user.} - />} - input={} - /> - + twitterConsumerKey: '', + }; + let renderForm = ({fields, setField}) => { + let userSessionsFields =
This feature allows for better security and management
of sessions for users.Learn more}> + Disable legacy session tokens to make your app more secure. If enabled, all requests with legacy tokens will error. Learn more} + />} + input={} + /> + We’ll automatically delete revocable sessions that have not made an API request in the last year.} + />} + input={} + /> + When a user changes or resets their password, we’ll
automatically delete all Session objects associated with this user.} + />} + input={} + /> +
- let userAuthenticationFields =
- } - input={} - /> - } - input={} - /> - } - input={} - /> -
+ let userAuthenticationFields =
+ } + input={} + /> + } + input={} + /> + } + input={} + /> +
- let socialLoginFields =
- } - input={ { - setField('allowFacebookAuthentication', enabled); - if (!enabled) { - setField('facebookAppID', ''); - setField('facebookAppSecret', ''); - } - }} - value={fields.allowFacebookAuthentication} - />} - /> - {fields.allowFacebookAuthentication ? } - input={[ - , - , - ]} - /> : null} - {fields.facebookAppIDList.length > 0 ? } - input={ ({ - title: 'App #' + (index + 1).toString(), - color: 'green', - onDelete: () => { - let newFacebookAppIDList = fields.facebookAppIDList.slice(); - newFacebookAppIDList.splice(index, 1); + let socialLoginFields =
+ } + input={ { + setField('allowFacebookAuthentication', enabled); + if (!enabled) { + setField('facebookAppID', ''); + setField('facebookAppSecret', ''); + } + }} + value={fields.allowFacebookAuthentication} + />} + /> + {fields.allowFacebookAuthentication ? } + input={[ + , + , + ]} + /> : null} + {fields.facebookAppIDList.length > 0 ? } + input={ ({ + title: 'App #' + (index + 1).toString(), + color: 'green', + onDelete: () => { + let newFacebookAppIDList = fields.facebookAppIDList.slice(); + newFacebookAppIDList.splice(index, 1); - let newFacebookAppSecretList = fields.facebookAppSecretList.slice(); - newFacebookAppSecretList.splice(index, 1); + let newFacebookAppSecretList = fields.facebookAppSecretList.slice(); + newFacebookAppSecretList.splice(index, 1); - //TODO(drewgross): handle errors, display progress, etc. - this.context.currentApp.setConnectedFacebookApps(newFacebookAppIDList, newFacebookAppSecretList).then(() => { - this.forceUpdate(); - }); - }, - notes: [ - { - key: 'App ID', - value: fields.facebookAppIDList[index], - }, - { - key: 'App Secret', - value: fields.facebookAppSecretList[index], - } - ], - }))} - />} - /> : null} - } - input={ { - setField('allowTwitterAuthentication', enabled); - if (!enabled) { - setField('twitterConsumerKey', ''); - } - }} - value={fields.allowTwitterAuthentication} - />} /> - {fields.allowTwitterAuthentication ? } - input={ - }/> : null} - {fields.twitterConsumerKeysList.length > 0 ? } - input={ ({ - title: 'App #' + (index + 1).toString(), - color: 'green', - onDelete: () => { - let twitterConsumerKeyList = fields.twitterConsumerKeysList.slice(); - twitterConsumerKeyList.splice(index, 1); + //TODO(drewgross): handle errors, display progress, etc. + this.context.currentApp.setConnectedFacebookApps(newFacebookAppIDList, newFacebookAppSecretList).then(() => { + this.forceUpdate(); + }); + }, + notes: [ + { + key: 'App ID', + value: fields.facebookAppIDList[index], + }, + { + key: 'App Secret', + value: fields.facebookAppSecretList[index], + } + ], + }))} + />} + /> : null} + } + input={ { + setField('allowTwitterAuthentication', enabled); + if (!enabled) { + setField('twitterConsumerKey', ''); + } + }} + value={fields.allowTwitterAuthentication} + />} /> + {fields.allowTwitterAuthentication ? } + input={ + }/> : null} + {fields.twitterConsumerKeysList.length > 0 ? } + input={ ({ + title: 'App #' + (index + 1).toString(), + color: 'green', + onDelete: () => { + let twitterConsumerKeyList = fields.twitterConsumerKeysList.slice(); + twitterConsumerKeyList.splice(index, 1); - //TODO(drewgross): handle errors, display progress, etc. - this.context.currentApp.setConnectedTwitterApps(twitterConsumerKeyList).then(() => { - this.forceUpdate(); - }); - }, - notes: [ - { - key: 'Consumer Key', - value: fields.twitterConsumerKeysList[index], - }, - ], - }))} - />} - /> : null} -
+ //TODO(drewgross): handle errors, display progress, etc. + this.context.currentApp.setConnectedTwitterApps(twitterConsumerKeyList).then(() => { + this.forceUpdate(); + }); + }, + notes: [ + { + key: 'Consumer Key', + value: fields.twitterConsumerKeysList[index], + }, + ], + }))} + />} + /> : null} +
- return
- {userSessionsFields} - {userAuthenticationFields} - {socialLoginFields} - {toolbar} -
; - } + return
+ {userSessionsFields} + {userAuthenticationFields} + {socialLoginFields} + {toolbar} +
; + } - return renderFlowFooterChanges(changes, initialFields, userFieldOptions)} - onSubmit={({ changes, setField }) => { - let promiseList = []; - if (changes.requireRevocableSessions !== undefined) { - promiseList.push(this.context.currentApp.setRequireRevocableSessions(changes.requireRevocableSessions)); - } - if (changes.expireInactiveSessions !== undefined) { - promiseList.push(this.context.currentApp.setExpireInactiveSessions(changes.expireInactiveSessions)); - } - if (changes.revokeSessionOnPasswordChange !== undefined) { - promiseList.push(this.context.currentApp.setRevokeSessionOnPasswordChange(changes.revokeSessionOnPasswordChange)); - } - if (changes.enableNewMethodsByDefault !== undefined) { - promiseList.push(this.context.currentApp.setEnableNewMethodsByDefault(changes.enableNewMethodsByDefault)); - } - if (changes.allowUsernameAndPassword !== undefined) { - promiseList.push(this.context.currentApp.setAllowUsernameAndPassword(changes.allowUsernameAndPassword)); - } - if (changes.allowAnonymousUsers !== undefined) { - promiseList.push(this.context.currentApp.setAllowAnonymousUsers(changes.allowAnonymousUsers)); - } - if (changes.allowFacebookAuthentication !== undefined) { - promiseList.push(this.context.currentApp.setAllowFacebookAuth(changes.allowFacebookAuthentication)); - } - if (changes.allowCustomAuthentication !== undefined) { - promiseList.push(this.context.currentApp.setAllowCustomAuthentication(changes.allowCustomAuthentication)); - } - if (changes.facebookAppID !== undefined && changes.facebookAppSecret !== undefined) { - let fbAppPromise = this.context.currentApp.addConnectedFacebookApp(changes.facebookAppID, changes.facebookAppSecret); - fbAppPromise.then(() => { - setField('facebookAppID', ''); - setField('facebookAppSecret', ''); - }) - promiseList.push(fbAppPromise); - } - if (changes.twitterConsumerKey !== undefined) { - let twitterAppPromise = this.context.currentApp.addConnectedTwitterApp(changes.twitterConsumerKey); - twitterAppPromise.then(() => { - setField('twitterConsumerKey', ''); - }); - promiseList.push(twitterAppPromise); - } - if (changes.allowTwitterAuthentication !== undefined) { - promiseList.push(this.context.currentApp.setAllowTwitterAuth(changes.allowTwitterAuthentication)); - } + return renderFlowFooterChanges(changes, initialFields, userFieldOptions)} + onSubmit={({ changes, setField }) => { + let promiseList = []; + if (changes.requireRevocableSessions !== undefined) { + promiseList.push(this.context.currentApp.setRequireRevocableSessions(changes.requireRevocableSessions)); + } + if (changes.expireInactiveSessions !== undefined) { + promiseList.push(this.context.currentApp.setExpireInactiveSessions(changes.expireInactiveSessions)); + } + if (changes.revokeSessionOnPasswordChange !== undefined) { + promiseList.push(this.context.currentApp.setRevokeSessionOnPasswordChange(changes.revokeSessionOnPasswordChange)); + } + if (changes.enableNewMethodsByDefault !== undefined) { + promiseList.push(this.context.currentApp.setEnableNewMethodsByDefault(changes.enableNewMethodsByDefault)); + } + if (changes.allowUsernameAndPassword !== undefined) { + promiseList.push(this.context.currentApp.setAllowUsernameAndPassword(changes.allowUsernameAndPassword)); + } + if (changes.allowAnonymousUsers !== undefined) { + promiseList.push(this.context.currentApp.setAllowAnonymousUsers(changes.allowAnonymousUsers)); + } + if (changes.allowFacebookAuthentication !== undefined) { + promiseList.push(this.context.currentApp.setAllowFacebookAuth(changes.allowFacebookAuthentication)); + } + if (changes.allowCustomAuthentication !== undefined) { + promiseList.push(this.context.currentApp.setAllowCustomAuthentication(changes.allowCustomAuthentication)); + } + if (changes.facebookAppID !== undefined && changes.facebookAppSecret !== undefined) { + let fbAppPromise = this.context.currentApp.addConnectedFacebookApp(changes.facebookAppID, changes.facebookAppSecret); + fbAppPromise.then(() => { + setField('facebookAppID', ''); + setField('facebookAppSecret', ''); + }) + promiseList.push(fbAppPromise); + } + if (changes.twitterConsumerKey !== undefined) { + let twitterAppPromise = this.context.currentApp.addConnectedTwitterApp(changes.twitterConsumerKey); + twitterAppPromise.then(() => { + setField('twitterConsumerKey', ''); + }); + promiseList.push(twitterAppPromise); + } + if (changes.allowTwitterAuthentication !== undefined) { + promiseList.push(this.context.currentApp.setAllowTwitterAuth(changes.allowTwitterAuthentication)); + } - return Promise.all(promiseList).then(() => { + return Promise.all(promiseList).then(() => { this.forceUpdate(); //Need to forceUpdate to see changes applied to source ParseApp - }).catch(errors => { - return Promise.reject({ error: unique(pluck(errors, 'error')).join(' ') }); - }); - }} - />; + }).catch(errors => { + return Promise.reject({ error: unique(pluck(errors, 'error')).join(' ') }); + }); + }} + />; } } const userFieldOptions = { - requireRevocableSessions: { - friendlyName: 'require revocable sessions', - type: 'boolean', - }, - expireInactiveSessions: { - friendlyName: 'expire inactive sessions', - type: 'boolean', - }, - revokeSessionOnPasswordChange: { - friendlyName: 'revoke session on password change', - type: 'boolean', - }, - enableNewMethodsByDefault: { - friendlyName: 'new authentication methods by default', - type: 'boolean', - }, - allowUsernameAndPassword: { - friendlyName: 'user name and password login', - type: 'boolean', - }, - allowAnonymousUsers: { - friendlyName: 'annonymous users', - type: 'boolean', - }, - allowFacebookAuthentication: { - friendlyName: 'Facebook authentication', - type: 'boolean', - }, - facebookAppID: { - friendlyName: 'Facebook app ID', - type: 'addition', - }, - facebookAppSecret: { - friendlyName: 'Facebook app secret', - type: 'addition', - }, - allowTwitterAuthentication: { - friendlyName: 'Twitter authentication', - type: 'boolean', - }, - twitterConsumerKey: { - friendlyName: 'Twitter Consumer Key', - type: 'addition', - }, - allowCustomAuthentication: { - friendlyName: 'custom authentication', - type: 'boolean', - }, + requireRevocableSessions: { + friendlyName: 'require revocable sessions', + type: 'boolean', + }, + expireInactiveSessions: { + friendlyName: 'expire inactive sessions', + type: 'boolean', + }, + revokeSessionOnPasswordChange: { + friendlyName: 'revoke session on password change', + type: 'boolean', + }, + enableNewMethodsByDefault: { + friendlyName: 'new authentication methods by default', + type: 'boolean', + }, + allowUsernameAndPassword: { + friendlyName: 'user name and password login', + type: 'boolean', + }, + allowAnonymousUsers: { + friendlyName: 'annonymous users', + type: 'boolean', + }, + allowFacebookAuthentication: { + friendlyName: 'Facebook authentication', + type: 'boolean', + }, + facebookAppID: { + friendlyName: 'Facebook app ID', + type: 'addition', + }, + facebookAppSecret: { + friendlyName: 'Facebook app secret', + type: 'addition', + }, + allowTwitterAuthentication: { + friendlyName: 'Twitter authentication', + type: 'boolean', + }, + twitterConsumerKey: { + friendlyName: 'Twitter Consumer Key', + type: 'addition', + }, + allowCustomAuthentication: { + friendlyName: 'custom authentication', + type: 'boolean', + }, }; diff --git a/src/lib/AJAX.js b/src/lib/AJAX.js index 74824324ce..91b34e1034 100644 --- a/src/lib/AJAX.js +++ b/src/lib/AJAX.js @@ -12,7 +12,7 @@ let basePath = ''; export function setBasePath(newBasePath) { basePath = newBasePath || ''; if (basePath.endsWith('/')) { - basePath = basePath.slice(0, basePath.length-1); + basePath = basePath.slice(0, basePath.length - 1); } } diff --git a/src/lib/Email.js b/src/lib/Email.js index c1083d08f4..c3b7cd1fbc 100644 --- a/src/lib/Email.js +++ b/src/lib/Email.js @@ -148,4 +148,4 @@ export function suggestion(email, checkTLD) { return null; } return match[1] + '@' + closestDomain; -} \ No newline at end of file +} diff --git a/src/lib/Filters.js b/src/lib/Filters.js index f95a705a93..c53e41a008 100644 --- a/src/lib/Filters.js +++ b/src/lib/Filters.js @@ -233,4 +233,4 @@ export function availableFilters(schema, currentFilters, blacklist) { return available; } -export const BLACKLISTED_FILTERS = [ 'containsAny', 'doesNotContainAny' ]; \ No newline at end of file +export const BLACKLISTED_FILTERS = [ 'containsAny', 'doesNotContainAny' ]; diff --git a/src/lib/ParseApp.js b/src/lib/ParseApp.js index 6cf0881f2b..9aed04f064 100644 --- a/src/lib/ParseApp.js +++ b/src/lib/ParseApp.js @@ -65,8 +65,8 @@ export default class ParseApp { this.serverURL = serverURL; this.serverInfo = serverInfo; this.icon = iconName; - this.primaryBackgroundColor=primaryBackgroundColor; - this.secondaryBackgroundColor=secondaryBackgroundColor; + this.primaryBackgroundColor = primaryBackgroundColor; + this.secondaryBackgroundColor = secondaryBackgroundColor; this.supportedPushLocales = supportedPushLocales ? supportedPushLocales : []; this.preventSchemaEdits = preventSchemaEdits || false; this.graphQLServerURL = graphQLServerURL; @@ -115,7 +115,7 @@ export default class ParseApp { * since - only fetch lines since this Date */ getLogs(level, since) { - let path = 'scriptlog?level=' + encodeURIComponent(level.toLowerCase()) + '&n=100' + (since?'&startDate=' + encodeURIComponent(since.getTime()):''); + let path = 'scriptlog?level=' + encodeURIComponent(level.toLowerCase()) + '&n=100' + (since ? '&startDate=' + encodeURIComponent(since.getTime()) : ''); return this.apiRequest('GET', path, {}, { useMasterKey: true }); } @@ -309,14 +309,14 @@ export default class ParseApp { uploadSSLPublicCertificate(file) { let path = '/apps/' + this.slug + '/update_hosting_certificates'; - let data= new FormData(); + let data = new FormData(); data.append('new_hosting_certificate[certificate_data]', file); return AJAX.put(path, data); } uploadSSLPrivateKey(file) { let path = '/apps/' + this.slug + '/update_hosting_certificates'; - let data= new FormData(); + let data = new FormData(); data.append('new_hosting_certificate[key_data]', file); return AJAX.put(path, data); } @@ -409,7 +409,7 @@ export default class ParseApp { if (type != 'all') { query.equalTo('source', type || 'rest'); } - query.skip(page*limit); + query.skip(page * limit); query.limit(limit); query.descending('createdAt'); return query.find({ useMasterKey: true }); @@ -764,7 +764,7 @@ export default class ParseApp { } deleteGCMPushCredentials(GCMSenderID) { - let path = '/apps/' + this.slug + '/delete_gcm_push_credential?gcm_sender_id='+GCMSenderID; + let path = '/apps/' + this.slug + '/delete_gcm_push_credential?gcm_sender_id=' + GCMSenderID; let promise = AJAX.get(path); promise.then(() => { this.settings.fields.fields.gcm_credentials = this.settings.fields.fields.gcm_credentials.filter(cred => diff --git a/src/lib/PushUtils.js b/src/lib/PushUtils.js index 6a9e7b16b8..13dec76bf8 100644 --- a/src/lib/PushUtils.js +++ b/src/lib/PushUtils.js @@ -89,7 +89,7 @@ let humanizedList = (value, inclusive, all) => { break; default: prefix = all ? 'all of' : 'any of'; - res = `${join} ${objectToReadable(value[value.length-1])}`; + res = `${join} ${objectToReadable(value[value.length - 1])}`; break; } return res; @@ -138,8 +138,8 @@ let formatConstraintComponent = (key, operation, value, schema) => { } else if (schema[key]['type'] === 'Array'){ let isAll = operation === '$all'; res = [key, - isInclusive || isAll ? 'contains' : 'does not contain', - humanizedList(value, isInclusive, isAll)]; + isInclusive || isAll ? 'contains' : 'does not contain', + humanizedList(value, isInclusive, isAll)]; } break; default: @@ -182,7 +182,7 @@ export function formatConstraint(key, constraints, schema) { rows.push(formatStructure(key, constraints, schema)); } else if(constraints.constructor === Array) { // legacy comment: Not sure how we want to display grouped subclauses - for(let i = 0; i { let friendlyAddition = additionsToSet.length > 1 ? fieldOptions[key].friendlyNamePlural : fieldOptions[key].friendlyName; let friendlyRemoval = removalsFromSet.length > 1 ? fieldOptions[key].friendlyNamePlural : fieldOptions[key].friendlyName; if (additionsToSet.length > 0) { - setChanges.push(added {additionsToSet.length} {friendlyAddition}); + setChanges.push(added {additionsToSet.length} {friendlyAddition}); } if (removalsFromSet.length > 0) { - setChanges.push(removed {removalsFromSet.length} {friendlyRemoval}); + setChanges.push(removed {removalsFromSet.length} {friendlyRemoval}); } } else { diff --git a/src/lib/setDifference.js b/src/lib/setDifference.js index d6853452df..723746f406 100644 --- a/src/lib/setDifference.js +++ b/src/lib/setDifference.js @@ -6,5 +6,5 @@ * the root directory of this source tree. */ export default function(first, second, equalityPredicate) { - return first.filter(itemFromFirst => !second.find(itemFromSecond => equalityPredicate(itemFromFirst, itemFromSecond))); + return first.filter(itemFromFirst => !second.find(itemFromSecond => equalityPredicate(itemFromFirst, itemFromSecond))); } diff --git a/src/lib/stores/ConfigStore.js b/src/lib/stores/ConfigStore.js index d30907b800..300ae9c49e 100644 --- a/src/lib/stores/ConfigStore.js +++ b/src/lib/stores/ConfigStore.js @@ -38,8 +38,8 @@ function ConfigStore(state, action) { { useMasterKey: true } ).then(() => { return state - .setIn(['params', action.param], action.value) - .setIn(['masterKeyOnly', action.param], action.masterKeyOnly); + .setIn(['params', action.param], action.value) + .setIn(['masterKeyOnly', action.param], action.masterKeyOnly); }); case ActionTypes.DELETE: return Parse._request( diff --git a/src/lib/stores/PushAudiencesStore.js b/src/lib/stores/PushAudiencesStore.js index 0cc42e05a8..45b4743499 100644 --- a/src/lib/stores/PushAudiencesStore.js +++ b/src/lib/stores/PushAudiencesStore.js @@ -37,27 +37,27 @@ function PushAudiencesStore(state, action) { }); case ActionTypes.CREATE: return Parse._request('POST', 'push_audiences', { query: action.query, name: action.name, }, { useMasterKey: true }) - .then(({ new_audience }) => { - return state.update('audiences',(audiences) => { - return audiences.unshift({ - createdAt: new Date(), - name: action.name, - objectId: new_audience ? new_audience.objectId || -1 : -1, - count: 0, - query: JSON.parse(action.query), - }); + .then(({ new_audience }) => { + return state.update('audiences',(audiences) => { + return audiences.unshift({ + createdAt: new Date(), + name: action.name, + objectId: new_audience ? new_audience.objectId || -1 : -1, + count: 0, + query: JSON.parse(action.query), }); }); + }); case ActionTypes.DESTROY: return Parse._request('DELETE', `push_audiences/${action.objectId}`, {}, { useMasterKey: true }) - .then(() => { - return state.update('audiences',(audiences) => { - let index = audiences.findIndex(function(audience) { - return audience.objectId === action.objectId; - }); - return audiences.delete(index); + .then(() => { + return state.update('audiences',(audiences) => { + let index = audiences.findIndex(function(audience) { + return audience.objectId === action.objectId; }); + return audiences.delete(index); }); + }); case ActionTypes.ABORT_FETCH: return Promise.resolve(state); } diff --git a/src/lib/stores/SchemaStore.js b/src/lib/stores/SchemaStore.js index 2faf186dd5..9016b9fafc 100644 --- a/src/lib/stores/SchemaStore.js +++ b/src/lib/stores/SchemaStore.js @@ -57,8 +57,8 @@ function SchemaStore(state, action) { { useMasterKey: true } ).then(({ fields, classLevelPermissions }) => { return state - .setIn(['classes', action.className], Map(fields)) - .setIn(['CLPs', action.className], Map(classLevelPermissions)); + .setIn(['classes', action.className], Map(fields)) + .setIn(['CLPs', action.className], Map(classLevelPermissions)); }); case ActionTypes.DROP_CLASS: return action.app.apiRequest( @@ -68,8 +68,8 @@ function SchemaStore(state, action) { { useMasterKey: true } ).then(() => { return state - .deleteIn(['classes', action.className]) - .deleteIn(['CLPs', action.className]); + .deleteIn(['classes', action.className]) + .deleteIn(['CLPs', action.className]); }); case ActionTypes.ADD_COLUMN: let newField = { diff --git a/src/lib/stores/StateManager.js b/src/lib/stores/StateManager.js index 01b0541df7..216dcbfa67 100644 --- a/src/lib/stores/StateManager.js +++ b/src/lib/stores/StateManager.js @@ -65,4 +65,4 @@ export function setGlobalState(name, state) { let prev = getGlobalState(name); globalStates[name] = state; return prev; -} \ No newline at end of file +} diff --git a/src/lib/stores/StoreManager.js b/src/lib/stores/StoreManager.js index 7eca956810..dd12cbf4de 100644 --- a/src/lib/stores/StoreManager.js +++ b/src/lib/stores/StoreManager.js @@ -74,4 +74,4 @@ export function getStore(name) { delete storeData.subscribers[id]; } } -} \ No newline at end of file +} diff --git a/src/lib/stores/WebhookStore.js b/src/lib/stores/WebhookStore.js index 2e390efef6..9565e4189d 100644 --- a/src/lib/stores/WebhookStore.js +++ b/src/lib/stores/WebhookStore.js @@ -35,7 +35,7 @@ function WebhookStore(state, action) { ); return Promise.all([functionsPromise, triggersPromise]).then(( [functions, - triggers] + triggers] ) => { return Map({ lastFetch: new Date(), webhooks: List(functions.concat(triggers))}); }); diff --git a/src/lib/subscribeTo.js b/src/lib/subscribeTo.js index 9d5a8ac765..8019f3dbba 100644 --- a/src/lib/subscribeTo.js +++ b/src/lib/subscribeTo.js @@ -44,7 +44,7 @@ export default function subscribeTo(name, prop) { } render() { - let dispatch = (type, params={}) => { + let dispatch = (type, params = {}) => { if (store.isGlobal) { return store.dispatch(type, params); } @@ -71,4 +71,4 @@ export default function subscribeTo(name, prop) { return SubscribedComponent; }; -} \ No newline at end of file +} diff --git a/src/lib/tests/Authentication.test.js b/src/lib/tests/Authentication.test.js index 0cf381abc1..3d1f688ed9 100644 --- a/src/lib/tests/Authentication.test.js +++ b/src/lib/tests/Authentication.test.js @@ -10,7 +10,7 @@ jest.dontMock('bcryptjs'); const Authentication = require('../../../Parse-Dashboard/Authentication'); const apps = [{appId: 'test123'}, {appId: 'test789'}]; -const readOnlyApps = apps.map((app) => { +const readOnlyApps = apps.map((app) => { app.readOnly = true; return app; }); diff --git a/src/lib/tests/e2e.js b/src/lib/tests/e2e.js index a1d72f6f96..ddf051a295 100644 --- a/src/lib/tests/e2e.js +++ b/src/lib/tests/e2e.js @@ -34,14 +34,14 @@ describe('e2e', () => { return p.then(() => { return rp('http://localhost:5051/dashboard'); }) - .then(result => { - let bundleLocation = result.match(/