You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by am...@apache.org on 2018/01/03 17:12:21 UTC
[couchdb-fauxton] 03/06: Enable eslint-react recommended rules
This is an automated email from the ASF dual-hosted git repository.
amaranhao pushed a commit to branch upgrade-to-eslint-v4
in repository https://gitbox.apache.org/repos/asf/couchdb-fauxton.git
commit c59243dc1215815b295049196215b08b2d5f5ec3
Author: Antonio Maranhao <an...@Antonios-MacBook-Pro.local>
AuthorDate: Tue Jan 2 17:40:22 2018 -0500
Enable eslint-react recommended rules
---
.eslintrc | 12 +-
app/addons/activetasks/components.js | 2 +-
app/addons/auth/components/changepasswordform.js | 4 +-
app/addons/auth/components/createadminform.js | 4 +-
app/addons/auth/components/loginform.js | 23 +-
app/addons/components/components/bulkaction.js | 4 +-
app/addons/components/components/codeeditor.js | 8 +-
.../components/components/codeeditorpanel.js | 7 +-
.../components/components/deletedatabasemodal.js | 2 +-
app/addons/components/components/menudropdown.js | 1 -
.../components/components/stringeditmodal.js | 6 +-
app/addons/components/components/tray.js | 1 -
app/addons/components/components/zenmodeoverlay.js | 6 +-
app/addons/config/components.js | 4 +-
app/addons/databases/components.js | 4 +-
app/addons/documents/__tests__/table-row.test.js | 1 -
app/addons/documents/changes/components.js | 11 +-
.../documents/components/header-docs-left.js | 4 +-
.../__tests__/doc-editor.components.test.js | 2 +-
app/addons/documents/doc-editor/components.js | 12 +-
.../index-editor/components/ReduceEditor.js | 7 +-
.../components/queryoptions/KeySearchFields.js | 26 +-
.../documents/mango/components/MangoIndexEditor.js | 10 +-
.../documents/mango/components/MangoQueryEditor.js | 10 +-
.../rev-browser/rev-browser.components.js | 429 +++++++++++++++++++++
app/addons/documents/sidebar/sidebar.js | 4 +-
app/addons/fauxton/notifications/notifications.js | 2 +-
app/addons/replication/controller.js | 2 -
28 files changed, 531 insertions(+), 77 deletions(-)
diff --git a/.eslintrc b/.eslintrc
index e062325..491dae8 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -6,7 +6,10 @@
"react"
],
- "extends": "eslint:recommended",
+ "extends": [
+ "eslint:recommended",
+ "plugin:react/recommended"
+ ],
"rules": {
"semi": [2, "always"],
@@ -19,15 +22,16 @@
"computed-property-spacing": [2, "never"],
"eol-last": 2,
"no-case-declarations": 0,
- "no-console": [2, { "allow": ["warn", "error", "info"] }],
+ "no-console": [1, { "allow": ["warn", "error", "info"] }],
"no-mixed-spaces-and-tabs": [2, "smart-tabs"],
"no-trailing-spaces": 2,
"semi-spacing": [2, {"before": false, "after": true}],
"space-in-parens": [2, "never"],
"space-unary-ops": 2,
"no-unused-vars": [2, {"varsIgnorePattern": "ReactDOM"}],
- "react/jsx-uses-vars": 2,
- "react/jsx-uses-react": 2
+ "react/display-name": 0,
+ // disabling for now since there are too many components without PropTypes
+ "react/prop-types": 0
},
"parserOptions": {
diff --git a/app/addons/activetasks/components.js b/app/addons/activetasks/components.js
index c63927a..9ae1ce9 100644
--- a/app/addons/activetasks/components.js
+++ b/app/addons/activetasks/components.js
@@ -299,7 +299,7 @@ class ActiveTasksTableBody extends React.Component {
return (
<tr className="no-matching-database-on-search">
- <td colSpan="6">No active {type} tasks match with filter: "{this.props.searchTerm}"</td>
+ <td colSpan="6">No active {type} tasks match with filter: "{this.props.searchTerm}"</td>
</tr>
);
};
diff --git a/app/addons/auth/components/changepasswordform.js b/app/addons/auth/components/changepasswordform.js
index da77375..7ca0b8f 100644
--- a/app/addons/auth/components/changepasswordform.js
+++ b/app/addons/auth/components/changepasswordform.js
@@ -38,7 +38,7 @@ export class ChangePasswordForm extends React.Component {
}
componentDidMount() {
- ReactDOM.findDOMNode(this.refs.password).focus();
+ this.passwordField.focus();
}
changePassword(e) {
@@ -59,7 +59,7 @@ export class ChangePasswordForm extends React.Component {
<input
id="password"
type="password"
- ref="password"
+ ref={node => this.passwordField = node}
name="password"
placeholder="Password"
size="24"
diff --git a/app/addons/auth/components/createadminform.js b/app/addons/auth/components/createadminform.js
index 7229256..f92049b 100644
--- a/app/addons/auth/components/createadminform.js
+++ b/app/addons/auth/components/createadminform.js
@@ -37,7 +37,7 @@ export class CreateAdminForm extends React.Component {
}
componentDidMount() {
- ReactDOM.findDOMNode(this.refs.username).focus();
+ this.usernameField.focus();
}
createAdmin(e) {
@@ -74,7 +74,7 @@ export class CreateAdminForm extends React.Component {
<input
id="username"
type="text"
- ref="username"
+ ref={node => this.usernameField = node}
name="name"
placeholder="Username"
size="24"
diff --git a/app/addons/auth/components/loginform.js b/app/addons/auth/components/loginform.js
index 528d173..070a337 100644
--- a/app/addons/auth/components/loginform.js
+++ b/app/addons/auth/components/loginform.js
@@ -24,10 +24,13 @@ class LoginForm extends React.Component {
password: ""
};
}
- onInputChange(e) {
- this.state[e.target.name] = e.target.value;
- this.setState(this.state);
+ onUsernameChange(e) {
+ this.setState({username: e.target.value});
}
+ onPasswordChange(e) {
+ this.setState({password: e.target.value});
+ }
+
submit(e) {
e.preventDefault();
if (!this.checkUnrecognizedAutoFill()) {
@@ -42,10 +45,10 @@ class LoginForm extends React.Component {
}
let username = this.props.testBlankUsername
? this.props.testBlankUsername
- : ReactDOM.findDOMNode(this.refs.username).value;
+ : this.usernameField.value;
let password = this.props.testBlankPassword
? this.props.testBlankPassword
- : ReactDOM.findDOMNode(this.refs.password).value;
+ : this.passwordField.value;
this.setState({ username: username, password: password }); // doesn't set immediately, hence separate login() call
this.login(username, password);
@@ -55,7 +58,7 @@ class LoginForm extends React.Component {
login(username, password, this.props.urlBack);
}
componentDidMount() {
- ReactDOM.findDOMNode(this.refs.username).focus();
+ this.usernameField.focus();
}
render() {
return (
@@ -70,10 +73,10 @@ class LoginForm extends React.Component {
id="username"
type="text"
name="username"
- ref="username"
+ ref={node => this.usernameField = node}
placeholder="Username"
size="24"
- onChange={this.onInputChange.bind(this)}
+ onChange={this.onUsernameChange.bind(this)}
value={this.state.username}
/>
<br />
@@ -81,10 +84,10 @@ class LoginForm extends React.Component {
id="password"
type="password"
name="password"
- ref="password"
+ ref={node => this.passwordField = node}
placeholder="Password"
size="24"
- onChange={this.onInputChange.bind(this)}
+ onChange={this.onPasswordChange.bind(this)}
value={this.state.password}
/>
<br />
diff --git a/app/addons/components/components/bulkaction.js b/app/addons/components/components/bulkaction.js
index 12958be..fc63a81 100644
--- a/app/addons/components/components/bulkaction.js
+++ b/app/addons/components/components/bulkaction.js
@@ -70,14 +70,14 @@ export class BulkActionComponent extends React.Component {
};
selectAll = () => {
- this.refs.bulkActionPopover.hide();
+ this.bulkActionPopover.hide();
this.props.selectAll();
};
getOverlay = () => {
return (
<OverlayTrigger
- ref="bulkActionPopover"
+ ref={node => this.bulkActionPopover = node}
trigger="click"
placement="bottom"
rootClose={true}
diff --git a/app/addons/components/components/codeeditor.js b/app/addons/components/components/codeeditor.js
index 602de08..b9f8bf8 100644
--- a/app/addons/components/components/codeeditor.js
+++ b/app/addons/components/components/codeeditor.js
@@ -78,7 +78,7 @@ export class CodeEditor extends React.Component {
};
setupAce = (props, shouldUpdateCode) => {
- this.editor = ace.edit(ReactDOM.findDOMNode(this.refs.ace));
+ this.editor = ace.edit(this.ace);
// suppresses an Ace editor error
this.editor.$blockScrolling = Infinity;
@@ -351,13 +351,13 @@ export class CodeEditor extends React.Component {
render() {
return (
<div>
- <div ref="ace" className="js-editor" id={this.props.id}></div>
- <button ref="stringEditIcon" className="btn string-edit" title="Edit string" disabled={!this.state.stringEditIconVisible}
+ <div ref={node => this.ace = node} className="js-editor" id={this.props.id}></div>
+ <button ref={node => this.stringEditIcon = node} className="btn string-edit" title="Edit string" disabled={!this.state.stringEditIconVisible}
style={this.state.stringEditIconStyle} onClick={this.openStringEditModal}>
<i className="icon icon-edit"></i>
</button>
<StringEditModal
- ref="stringEditModal"
+ ref={node => this.stringEditModal = node}
visible={this.state.stringEditModalVisible}
value={this.state.stringEditModalValue}
onSave={this.saveStringEditModal}
diff --git a/app/addons/components/components/codeeditorpanel.js b/app/addons/components/components/codeeditorpanel.js
index 714304d..4853042 100644
--- a/app/addons/components/components/codeeditorpanel.js
+++ b/app/addons/components/components/codeeditorpanel.js
@@ -63,6 +63,7 @@ export class CodeEditorPanel extends React.Component {
data-bypass="true"
href={this.props.docLink}
target="_blank"
+ rel="noopener noreferrer"
>
<i className="icon-question-sign"></i>
</a>
@@ -85,7 +86,7 @@ export class CodeEditorPanel extends React.Component {
enterZenMode = () => {
this.setState({
zenModeEnabled: true,
- code: this.refs.codeEditor.getValue()
+ code: this.codeEditor.getValue()
});
};
@@ -95,7 +96,7 @@ export class CodeEditorPanel extends React.Component {
};
getEditor = () => {
- return this.refs.codeEditor;
+ return this.codeEditor;
};
getValue = () => {
@@ -127,7 +128,7 @@ export class CodeEditorPanel extends React.Component {
</label>
<CodeEditor
id={this.props.id}
- ref="codeEditor"
+ ref={node => this.codeEditor = node}
mode="javascript"
defaultCode={this.state.code}
showGutter={true}
diff --git a/app/addons/components/components/deletedatabasemodal.js b/app/addons/components/components/deletedatabasemodal.js
index e8213fe..65a2f33 100644
--- a/app/addons/components/components/deletedatabasemodal.js
+++ b/app/addons/components/components/deletedatabasemodal.js
@@ -94,7 +94,7 @@ export class DeleteDatabaseModal extends React.Component {
<p>
Warning: This action will permanently delete <code>{dbId}</code>.
To confirm the deletion of the database and all of the
- database's documents, you must enter the database's name.
+ database's documents, you must enter the database's name.
</p>
<input
type="text"
diff --git a/app/addons/components/components/menudropdown.js b/app/addons/components/components/menudropdown.js
index a2e90c4..d10f014 100644
--- a/app/addons/components/components/menudropdown.js
+++ b/app/addons/components/components/menudropdown.js
@@ -72,7 +72,6 @@ export class MenuDropDown extends React.Component {
<CustomMenu bsRole="menu" className="arrow">
{menuItems}
</CustomMenu>
- }
</Dropdown>
);
}
diff --git a/app/addons/components/components/stringeditmodal.js b/app/addons/components/components/stringeditmodal.js
index 9b8f06f..f960dd7 100644
--- a/app/addons/components/components/stringeditmodal.js
+++ b/app/addons/components/components/stringeditmodal.js
@@ -56,7 +56,7 @@ export class StringEditModal extends React.Component {
}
initEditor = (val) => {
- this.editor = ace.edit(ReactDOM.findDOMNode(this.refs.stringEditor));
+ this.editor = ace.edit(this.stringEditor);
this.editor.$blockScrolling = Infinity; // suppresses an Ace editor error
this.editor.setShowPrintMargin(false);
this.editor.setOption('highlightActiveLine', true);
@@ -80,7 +80,9 @@ export class StringEditModal extends React.Component {
</Modal.Header>
<Modal.Body>
<div id="modal-error" className="hide alert alert-error"/>
- <div id="string-editor-wrapper"><div ref="stringEditor" className="doc-code"></div></div>
+ <div id="string-editor-wrapper">
+ <div ref={node => this.stringEditor = node} className="doc-code"></div>
+ </div>
</Modal.Body>
<Modal.Footer>
<a className="cancel-link" onClick={this.closeModal}>Cancel</a>
diff --git a/app/addons/components/components/tray.js b/app/addons/components/components/tray.js
index 41be571..335c36a 100644
--- a/app/addons/components/components/tray.js
+++ b/app/addons/components/components/tray.js
@@ -82,7 +82,6 @@ export class TrayContents extends React.Component {
placement={"bottom"}
container={this.props.container}
rootClose={true}
- target={() => ReactDOM.findDOMNode(this.refs.target)}
onEnter={this.props.onEnter}
>
<TransitionMotion
diff --git a/app/addons/components/components/zenmodeoverlay.js b/app/addons/components/components/zenmodeoverlay.js
index 7cffb62..2834123 100644
--- a/app/addons/components/components/zenmodeoverlay.js
+++ b/app/addons/components/components/zenmodeoverlay.js
@@ -56,7 +56,7 @@ export class ZenModeOverlay extends React.Component {
};
getValue = () => {
- return this.refs.ace.getValue();
+ return this.ace.getValue();
};
toggleTheme = () => {
@@ -107,7 +107,7 @@ export class ZenModeOverlay extends React.Component {
</li>
<li>
<OverlayTrigger placement="left" overlay={tooltipTheme}>
- <span ref="theme"
+ <span
className="fonticon fonticon-picture js-toggle-theme"
data-container=".zen-mode-controls .tooltips"
title="Switch zen theme"
@@ -119,7 +119,7 @@ export class ZenModeOverlay extends React.Component {
<div className="tooltips"></div>
</div>
<CodeEditor
- ref="ace"
+ ref={node => this.ace = node}
autoFocus={true}
theme={themes[this.state.theme]}
defaultCode={this.props.defaultCode}
diff --git a/app/addons/config/components.js b/app/addons/config/components.js
index 3bd0d68..6fd6240 100644
--- a/app/addons/config/components.js
+++ b/app/addons/config/components.js
@@ -366,7 +366,7 @@ class AddOptionButton extends React.Component {
<Button
id="add-option-button"
onClick={this.togglePopover.bind(this)}
- ref="target">
+ ref={node => this.target = node}>
<i className="icon icon-plus header-icon"></i>
Add Option
</Button>
@@ -376,7 +376,7 @@ class AddOptionButton extends React.Component {
onHide={this.hidePopover.bind(this)}
placement="bottom"
rootClose={true}
- target={() => ReactDOM.findDOMNode(this.refs.target)}>
+ target={() => this.target}>
{this.getPopover()}
</Overlay>
</div>
diff --git a/app/addons/databases/components.js b/app/addons/databases/components.js
index 0bb9c31..f339679 100644
--- a/app/addons/databases/components.js
+++ b/app/addons/databases/components.js
@@ -227,7 +227,7 @@ class AddDatabaseWidget extends React.Component {
};
focusInput = () => {
- ReactDOM.findDOMNode(this.refs.newDbName).focus();
+ this.newDbName.focus();
};
onKeyUpInInput = (e) => {
@@ -258,7 +258,7 @@ class AddDatabaseWidget extends React.Component {
<span className="add-on">Create Database</span>
<input
id="js-new-database-name"
- ref="newDbName"
+ ref={node => this.newDbName = node}
type="text"
value={this.state.databaseName}
onChange={this.onChange} onKeyUp={this.onKeyUpInInput}
diff --git a/app/addons/documents/__tests__/table-row.test.js b/app/addons/documents/__tests__/table-row.test.js
index b2636c8..5f727f3 100644
--- a/app/addons/documents/__tests__/table-row.test.js
+++ b/app/addons/documents/__tests__/table-row.test.js
@@ -41,7 +41,6 @@ describe('Docs Table Row', () => {
const wrapper = shallow(<TableRow
onClick={sinon.stub()}
docChecked={sinon.stub()}
- isSelected={sinon.stub()}
el={elem}
data={data}
index={0}
diff --git a/app/addons/documents/changes/components.js b/app/addons/documents/changes/components.js
index 60afcd8..cb5ff21 100644
--- a/app/addons/documents/changes/components.js
+++ b/app/addons/documents/changes/components.js
@@ -178,7 +178,7 @@ class AddFilterForm extends React.Component {
}
focusFilterField () {
- ReactDOM.findDOMNode(this.refs.addItem).focus();
+ this.addItem.focus();
}
inputClassNames () {
@@ -194,8 +194,13 @@ class AddFilterForm extends React.Component {
<form className="form-inline js-filter-form" onSubmit={this.submitForm}>
<fieldset>
<i className="fonticon-filter" />
- <input type="text" ref="addItem" className={this.inputClassNames()} placeholder="Sequence or ID"
- onChange={(e) => this.setState({ filter: e.target.value })} value={this.state.filter} />
+ <input
+ type="text"
+ ref={node => this.addItem = node}
+ className={this.inputClassNames()}
+ placeholder="Sequence or ID"
+ onChange={(e) => this.setState({ filter: e.target.value })}
+ value={this.state.filter} />
<button type="submit" className="btn btn-secondary">Filter</button>
<div className="help-block"></div>
</fieldset>
diff --git a/app/addons/documents/components/header-docs-left.js b/app/addons/documents/components/header-docs-left.js
index 1d14778..8be0e58 100644
--- a/app/addons/documents/components/header-docs-left.js
+++ b/app/addons/documents/components/header-docs-left.js
@@ -31,11 +31,11 @@ function getDropdownItems (items) {
if (el.title && el.links) {
const items = el.links.map((subel) => {
- return <Item onClick={subel.onClick} icon={subel.icon} url={subel.url}>{subel.title}</Item>;
+ return <Item key={subel.title} onClick={subel.onClick} icon={subel.icon} url={subel.url}>{subel.title}</Item>;
});
return ([
- <li className="header-label">{el.title}</li>,
+ <li key={el.title} className="header-label">{el.title}</li>,
items
]);
}
diff --git a/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js b/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js
index bc72537..178eb47 100644
--- a/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js
+++ b/app/addons/documents/doc-editor/__tests__/doc-editor.components.test.js
@@ -202,7 +202,7 @@ describe("Custom Extension Buttons", () => {
render() {
return (
<div>
- <button>Oh no she di'n't!</button>
+ <button>Oh no she di'n't!</button>
<span id="testDatabaseName">{this.props.database.id}</span>
</div>
);
diff --git a/app/addons/documents/doc-editor/components.js b/app/addons/documents/doc-editor/components.js
index 7c9afbc..8f98824 100644
--- a/app/addons/documents/doc-editor/components.js
+++ b/app/addons/documents/doc-editor/components.js
@@ -60,7 +60,7 @@ class DocEditorController extends React.Component {
return (
<GeneralComponents.CodeEditor
id="doc-editor"
- ref="docEditor"
+ ref={node => this.docEditor = node}
defaultCode={code}
mode="json"
autoFocus={true}
@@ -110,7 +110,7 @@ class DocEditorController extends React.Component {
};
getEditor = () => {
- return (this.refs.docEditor) ? this.refs.docEditor.getEditor() : null;
+ return (this.docEditor) ? this.docEditor.getEditor() : null;
};
checkDocIsValid = () => {
@@ -124,7 +124,7 @@ class DocEditorController extends React.Component {
};
clearChanges = () => {
- this.refs.docEditor.clearChanges();
+ this.docEditor.clearChanges();
};
getExtensionIcons = () => {
@@ -184,7 +184,7 @@ class DocEditorController extends React.Component {
</div>
<UploadModal
- ref="uploadModal"
+ ref={node => this.uploadModal = node}
visible={this.state.uploadModalVisible}
doc={this.state.doc} />
<CloneDocModal
@@ -346,7 +346,7 @@ class UploadModal extends React.Component {
<Modal.Body>
<div className={errorClasses}>{this.state.errorMessage}</div>
<div>
- <form ref="uploadForm" className="form">
+ <form ref={node => this.uploadForm = node} className="form">
<p>
Select a file to upload as an attachment to this document. Uploading a file saves the document as a new
revision.
@@ -430,7 +430,7 @@ class CloneDocModal extends React.Component {
<p>
You can modify the following generated ID for your new document.
</p>
- <input ref="newDocId" type="text" autoFocus={true} className="input-block-level"
+ <input ref={node => this.newDocId = node} type="text" autoFocus={true} className="input-block-level"
onChange={this.docIDChange} value={this.state.uuid} />
</form>
</Modal.Body>
diff --git a/app/addons/documents/index-editor/components/ReduceEditor.js b/app/addons/documents/index-editor/components/ReduceEditor.js
index 3158f1c..3b4a4c1 100644
--- a/app/addons/documents/index-editor/components/ReduceEditor.js
+++ b/app/addons/documents/index-editor/components/ReduceEditor.js
@@ -65,11 +65,11 @@ export default class ReduceEditor extends Component {
return this.state.reduce;
}
- return this.refs.reduceEditor.getValue();
+ return this.reduceEditor.getValue();
}
getEditor() {
- return this.refs.reduceEditor.getEditor();
+ return this.reduceEditor.getEditor();
}
updateReduceCode(code) {
@@ -86,7 +86,7 @@ export default class ReduceEditor extends Component {
if (this.state.hasCustomReduce) {
customReduceSection = <CodeEditorPanel
- ref='reduceEditor'
+ ref={node => this.reduceEditor = node}
id='reduce-function'
title={'Custom Reduce function'}
defaultCode={this.state.reduce}
@@ -115,7 +115,6 @@ export default class ReduceEditor extends Component {
selectId="reduce-function-selector"
selectValue={this.state.reduceSelectedOption} />
</div>
-
{customReduceSection}
</div>
);
diff --git a/app/addons/documents/index-results/components/queryoptions/KeySearchFields.js b/app/addons/documents/index-results/components/queryoptions/KeySearchFields.js
index 76d192a..1fb2f90 100644
--- a/app/addons/documents/index-results/components/queryoptions/KeySearchFields.js
+++ b/app/addons/documents/index-results/components/queryoptions/KeySearchFields.js
@@ -28,8 +28,8 @@ export default class KeySearchFields extends React.Component {
updateBetweenKeys () {
this.props.updateBetweenKeys({
- startkey: ReactDOM.findDOMNode(this.refs.startkey).value,
- endkey: ReactDOM.findDOMNode(this.refs.endkey).value,
+ startkey: this.startkey.value,
+ endkey: this.endkey.value,
include: this.props.betweenKeys.include
});
}
@@ -91,13 +91,29 @@ export default class KeySearchFields extends React.Component {
<div className="controls controls-row">
<div>
<label htmlFor="startkey" className="drop-down">Start key</label>
- <input id="startkey" ref="startkey" type="text" onChange={this.updateBetweenKeys.bind(this)} value={this.props.betweenKeys.startkey} placeholder='e.g., "1234"' />
+ <input
+ id="startkey"
+ ref={node => this.startkey = node}
+ type="text"
+ onChange={this.updateBetweenKeys.bind(this)}
+ value={this.props.betweenKeys.startkey}
+ placeholder='e.g., "1234"' />
</div>
<div>
<label htmlFor="endkey" className="drop-down">End key</label>
- <input id="endkey" ref="endkey" onChange={this.updateBetweenKeys.bind(this)} value={this.props.betweenKeys.endkey} type="text" placeholder='e.g., "1234"'/>
+ <input
+ id="endkey"
+ ref={node => this.endkey = node}
+ onChange={this.updateBetweenKeys.bind(this)}
+ value={this.props.betweenKeys.endkey}
+ type="text"
+ placeholder='e.g., "1234"'/>
<div className="controls include-end-key-row checkbox controls-row inline">
- <input id="qoIncludeEndKeyInResults" ref="inclusive_end" type="checkbox" onChange={this.updateInclusiveEnd.bind(this)} checked={this.props.betweenKeys.include}/>
+ <input
+ id="qoIncludeEndKeyInResults"
+ type="checkbox"
+ onChange={this.updateInclusiveEnd.bind(this)}
+ checked={this.props.betweenKeys.include}/>
<label htmlFor="qoIncludeEndKeyInResults">Include End Key in results</label>
</div>
</div>
diff --git a/app/addons/documents/mango/components/MangoIndexEditor.js b/app/addons/documents/mango/components/MangoIndexEditor.js
index 6e98af7..739a651 100644
--- a/app/addons/documents/mango/components/MangoIndexEditor.js
+++ b/app/addons/documents/mango/components/MangoIndexEditor.js
@@ -48,15 +48,15 @@ export default class MangoIndexEditor extends Component {
}
setEditorValue(newValue = '') {
- return this.refs.codeEditor.getEditor().setValue(newValue);
+ return this.codeEditor.getEditor().setValue(newValue);
}
getEditorValue() {
- return this.refs.codeEditor.getValue();
+ return this.codeEditor.getValue();
}
editorHasErrors() {
- return this.refs.codeEditor.getEditor().hasErrors();
+ return this.codeEditor.getEditor().hasErrors();
}
onTemplateSelected(selectedItem) {
@@ -72,7 +72,7 @@ export default class MangoIndexEditor extends Component {
<ReactSelect
className="mango-select"
options={this.props.templates}
- ref="templates"
+ ref={node => this.templates = node}
placeholder="Examples"
searchable={false}
clearable={false}
@@ -83,7 +83,7 @@ export default class MangoIndexEditor extends Component {
<PaddedBorderedBox>
<CodeEditorPanel
id="query-field"
- ref="codeEditor"
+ ref={node => this.codeEditor = node}
title="Index"
docLink={getDocUrl('MANGO_INDEX')}
defaultCode={this.props.queryIndexCode} />
diff --git a/app/addons/documents/mango/components/MangoQueryEditor.js b/app/addons/documents/mango/components/MangoQueryEditor.js
index 88e9a2f..f04a158 100644
--- a/app/addons/documents/mango/components/MangoQueryEditor.js
+++ b/app/addons/documents/mango/components/MangoQueryEditor.js
@@ -46,15 +46,15 @@ export default class MangoQueryEditor extends Component {
}
setEditorValue (newValue = '') {
- return this.refs.codeEditor.getEditor().setValue(newValue);
+ return this.codeEditor.getEditor().setValue(newValue);
}
getEditorValue () {
- return this.refs.codeEditor.getValue();
+ return this.codeEditor.getValue();
}
editorHasErrors () {
- return this.refs.codeEditor.getEditor().hasErrors();
+ return this.codeEditor.getEditor().hasErrors();
}
onHistorySelected(selectedItem) {
@@ -69,7 +69,7 @@ export default class MangoQueryEditor extends Component {
<ReactSelect
className="mango-select"
options={this.props.history}
- ref="history"
+ ref={node => this.history = node}
placeholder="Query history"
searchable={false}
clearable={false}
@@ -80,7 +80,7 @@ export default class MangoQueryEditor extends Component {
<PaddedBorderedBox>
<CodeEditorPanel
id="query-field"
- ref="codeEditor"
+ ref={node => this.codeEditor = node}
title={this.props.editorTitle}
docLink={getDocUrl('MANGO_SEARCH')}
defaultCode={this.props.queryFindCode} />
diff --git a/app/addons/documents/rev-browser/rev-browser.components.js b/app/addons/documents/rev-browser/rev-browser.components.js
new file mode 100644
index 0000000..a6e4504
--- /dev/null
+++ b/app/addons/documents/rev-browser/rev-browser.components.js
@@ -0,0 +1,429 @@
+import app from "../../../app";
+
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import PropTypes from 'prop-types';
+
+import React from "react";
+import ReactDOM from "react-dom";
+import RevActions from "./rev-browser.actions";
+import RevStores from "./rev-browser.stores";
+import ReactComponents from "../../components/react-components";
+import { ButtonGroup, Button, Modal } from "react-bootstrap";
+import ReactSelect from "react-select";
+import jdp from "jsondiffpatch";
+import jdpformatters from "jsondiffpatch/src/formatters/html";
+import ace from "brace";
+import "jsondiffpatch/public/formatters-styles/html.css";
+
+const storageKeyDeleteConflictsModal = 'deleteConflictsHideModal';
+
+const store = RevStores.revBrowserStore;
+const ConfirmButton = ReactComponents.ConfirmButton;
+
+require('brace/ext/static_highlight');
+const highlight = ace.acequire('ace/ext/static_highlight');
+
+require('brace/mode/json');
+const JavaScriptMode = ace.acequire('ace/mode/json').Mode;
+
+require('brace/theme/idle_fingers');
+const theme = ace.acequire('ace/theme/idle_fingers');
+
+
+class DiffyController extends React.Component {
+
+ constructor (props) {
+ super(props);
+
+ this.state = this.getStoreState();
+ }
+
+ getStoreState () {
+
+ return {
+ tree: store.getRevTree(),
+ ours: store.getOurs(),
+ theirs: store.getTheirs(),
+ conflictingRevs: store.getConflictingRevs(),
+ dropdownData: store.getDropdownData(),
+ isDiffViewEnabled: store.getIsDiffViewEnabled(),
+ databaseName: store.getDatabaseName()
+ };
+ }
+
+ componentDidMount () {
+ store.on('change', this.onChange, this);
+ }
+
+ componentWillUnmount () {
+ store.off('change', this.onChange);
+ }
+
+ onChange () {
+ this.setState(this.getStoreState());
+ }
+
+ toggleDiffView (enableDiff) {
+ RevActions.toggleDiffView(enableDiff);
+ }
+
+ render () {
+ const {tree, ours, theirs, conflictingRevs, isDiffViewEnabled} = this.state;
+
+ if (!tree) {
+ return null;
+ }
+
+ // no conflicts happened for this doc
+ if (!theirs || !conflictingRevs.length) {
+ return <div style={{textAlign: 'center', color: '#fff'}}><h2>No conflicts</h2></div>;
+ }
+
+ return (
+ <div className="revision-wrapper scrollable">
+ <RevisionBrowserControls {...this.state} />
+ <div className="revision-view-controls">
+ <ButtonGroup className="two-sides-toggle-button">
+ <Button
+ style={{width: '120px'}}
+ className={isDiffViewEnabled ? 'active' : ''}
+ onClick={this.toggleDiffView.bind(this, true)}
+ >
+ <i className="icon-columns" /> Diff
+ </Button>
+ <Button
+ style={{width: '120px'}}
+ className={isDiffViewEnabled ? '' : 'active'}
+ onClick={this.toggleDiffView.bind(this, false)}
+ >
+ <i className="icon-file-text" /> Document
+ </Button>
+ </ButtonGroup>
+ </div>
+
+ {isDiffViewEnabled ?
+ <RevisionDiffArea ours={ours} theirs={theirs} /> :
+ <SplitScreenArea ours={ours} theirs={theirs} /> }
+ </div>
+ );
+ }
+}
+
+
+class SplitScreenArea extends React.Component {
+
+ constructor (props) {
+ super(props);
+ }
+
+ componentDidUpdate () {
+ this.hightlightAfterRender();
+ }
+
+ componentDidMount () {
+ this.hightlightAfterRender();
+ }
+
+ hightlightAfterRender () {
+ const format = (input) => { return JSON.stringify(input, null, ' '); };
+
+ const jsmode = new JavaScriptMode();
+ const left = this.revLeftOurs;
+ const right = this.revRightTheirs;
+
+ const leftRes = highlight.render(format(this.props.ours), jsmode, theme, 0, true);
+ left.innerHTML = leftRes.html;
+ const rightRes = highlight.render(format(this.props.theirs), jsmode, theme, 0, true);
+ right.innerHTML = rightRes.html;
+ }
+
+ render () {
+ const {ours, theirs} = this.props;
+
+ if (!ours || !theirs) {
+ return <div></div>;
+ }
+
+ return (
+ <div className="revision-split-area">
+ <div data-id="ours" style={{width: '50%'}}>
+ <div style={{marginBottom: '20px'}}>{ours._rev} (Server-Selected Rev)</div>
+ <pre ref={node => this.revLeftOurs = node}></pre>
+ </div>
+
+ <div data-id="theirs" style={{width: '50%'}}>
+ <div style={{marginBottom: '20px'}}>{theirs._rev}</div>
+ <pre ref={node => this.revRightTheirs = node}></pre>
+ </div>
+ </div>
+ );
+ }
+}
+
+const RevisionDiffArea = ({ours, theirs}) => {
+ if (!ours || !theirs) {
+ return <div></div>;
+ }
+
+ const delta = jdp.diff(ours, theirs);
+ const html = jdpformatters.format(delta, ours);
+
+ return (
+ <div className="revision-diff-area">
+ <div
+ style={{marginTop: '30px'}}
+ dangerouslySetInnerHTML={{__html: html}}
+ ></div>
+ </div>
+ );
+};
+RevisionDiffArea.propTypes = {
+ ours: PropTypes.object,
+ theirs: PropTypes.object,
+ currentRev: PropTypes.string
+};
+
+
+const ConflictingRevisionsDropDown = ({options, selected, onRevisionClick, onBackwardClick, onForwardClick}) => {
+ return (
+ <div className="conflicting-revs-dropdown">
+ <BackForwardControls backward onClick={onBackwardClick} />
+ <div style={{width: '345px', margin: '0 5px'}}>
+ <ReactSelect
+ name="form-field-name"
+ value={selected}
+ options={options}
+ clearable={false}
+ onChange={onRevisionClick} />
+ </div>
+ <BackForwardControls forward onClick={onForwardClick} />
+ </div>
+ );
+};
+ConflictingRevisionsDropDown.propTypes = {
+ options: PropTypes.array.isRequired,
+ selected: PropTypes.string.isRequired,
+ onRevisionClick: PropTypes.func.isRequired,
+ onBackwardClick: PropTypes.func.isRequired,
+ onForwardClick: PropTypes.func.isRequired,
+};
+
+class RevisionBrowserControls extends React.Component {
+
+ constructor (props) {
+ super(props);
+
+ this.state = {showModal: false};
+ }
+
+ onRevisionClick (revTheirs) {
+
+ RevActions.chooseLeaves(this.props.ours, revTheirs.value);
+ }
+
+ onForwardClick () {
+ const conflictingRevs = this.props.conflictingRevs;
+ const index = conflictingRevs.indexOf(this.props.theirs._rev);
+
+ const next = conflictingRevs[index + 1];
+
+ if (!next) {
+ return;
+ }
+
+ RevActions.chooseLeaves(this.props.ours, next);
+ }
+
+ onBackwardClick () {
+ const conflictingRevs = this.props.conflictingRevs;
+ const index = conflictingRevs.indexOf(this.props.theirs._rev);
+
+ const next = conflictingRevs[index - 1];
+
+ if (!next) {
+ return;
+ }
+
+ RevActions.chooseLeaves(this.props.ours, next);
+ }
+
+ selectAsWinner (docToWin, doNotShowModalAgain) {
+ if (doNotShowModalAgain) {
+ app.utils.localStorageSet(storageKeyDeleteConflictsModal, true);
+ }
+
+ RevActions.selectRevAsWinner(this.props.databaseName, docToWin._id, this.props.tree.paths, docToWin._rev);
+ }
+
+ onSelectAsWinnerClick (docToWin) {
+ if (app.utils.localStorageGet(storageKeyDeleteConflictsModal) !== true) {
+ RevActions.showConfirmModal(true, docToWin);
+ return;
+ }
+
+ this.selectAsWinner(docToWin);
+ }
+
+ render () {
+ const {tree} = this.props;
+ const cellStyle = {paddingRight: '30px'};
+
+ return (
+ <div className="revision-browser-controls">
+ <ConfirmModal onConfirm={this.selectAsWinner.bind(this)} />
+ <table style={{margin: '10px 60px', width: '100%'}}>
+ <tbody>
+ <tr style={{height: '60px'}}>
+ <td style={cellStyle}>Server-Selected Rev: </td>
+ <td style={cellStyle}>
+ <div style={{lineHeight: '36px', height: '36px', width: '337px', color: '#000', backgroundColor: '#ffbbbb'}}>
+ <b style={{paddingLeft: '10px'}}>{tree.winner}</b>
+ </div>
+ </td>
+ <td>
+ <ConfirmButton
+ onClick={this.onSelectAsWinnerClick.bind(this, this.props.ours)}
+ style={{marginRight: '10px', width: '220px'}}
+ text="Delete Other Conflicts"
+ buttonType="btn-secondary"
+ customIcon="icon-trophy" />
+ </td>
+ </tr>
+ <tr style={{height: '60px'}}>
+ <td style={cellStyle}>Conflicting Revisions: </td>
+ <td style={cellStyle}>
+ <ConflictingRevisionsDropDown
+ onRevisionClick={this.onRevisionClick.bind(this)}
+ onForwardClick={this.onForwardClick.bind(this)}
+ onBackwardClick={this.onBackwardClick.bind(this)}
+ options={this.props.dropdownData}
+ selected={this.props.theirs._rev} />
+ </td>
+ <td>
+ <ConfirmButton
+ data-id="button-select-theirs"
+ onClick={this.onSelectAsWinnerClick.bind(this, this.props.theirs)}
+ style={{marginRight: '10px', width: '220px'}}
+ text="Select as Winner"
+ buttonType="btn-secondary"
+ customIcon="icon-trophy" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ );
+ }
+}
+RevisionBrowserControls.propTypes = {
+ tree: PropTypes.object.isRequired,
+ ours: PropTypes.object.isRequired,
+ conflictingRevs: PropTypes.array.isRequired,
+};
+
+class ConfirmModal extends React.Component {
+
+ constructor (props) {
+ super(props);
+
+ this.state = this.getStoreState();
+ }
+
+ getStoreState () {
+ return {
+ show: store.getShowConfirmModal(),
+ docToWin: store.getDocToWin(),
+ checked: false
+ };
+ }
+
+ componentDidMount () {
+ store.on('change', this.onChange, this);
+ }
+
+ componentWillUnmount () {
+ store.off('change', this.onChange);
+ }
+
+ onChange () {
+ this.setState(this.getStoreState());
+ }
+
+ close () {
+ RevActions.showConfirmModal(false, null);
+ }
+
+ onDeleteConflicts () {
+ const hideModal = this.state.checked;
+ this.props.onConfirm(this.state.docToWin, hideModal);
+ }
+
+ render () {
+ return (
+ <Modal dialogClassName="delete-conflicts-modal" show={this.state.show} onHide={this.close}>
+ <Modal.Header closeButton={false}>
+ <Modal.Title>Solve Conflicts</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <p>
+ <i className="icon-warning-sign"></i> Do you want to delete all conflicting revisions for this document?
+ </p>
+
+
+ </Modal.Body>
+ <Modal.Footer>
+ <div style={{float: 'left', marginTop: '10px'}}>
+ <label>
+ <input
+ style={{margin: '0 5px 3px 0'}}
+ onChange={() => { this.setState({checked: !this.state.checked }); }}
+ type="checkbox" />
+ Do not show this warning message again
+ </label>
+ </div>
+ <a
+ style={{marginRight: '10px', cursor: 'pointer'}}
+ onClick={this.close}
+ data-bypass="true"
+ >
+ Cancel
+ </a>
+
+ <ConfirmButton
+ onClick={this.onDeleteConflicts.bind(this)}
+ text="Delete Revisions"
+ buttonType="btn-danger" />
+ </Modal.Footer>
+ </Modal>
+ );
+ }
+}
+ConfirmModal.propTypes = {
+ onConfirm: PropTypes.func.isRequired,
+};
+
+const BackForwardControls = ({onClick, forward}) => {
+ const icon = forward ? 'fonticon-right-open' : 'fonticon-left-open';
+ const style = {height: '20px', width: '11px', marginTop: '7px'};
+
+ return <div style={style} className={icon} onClick={onClick}></div>;
+};
+BackForwardControls.propTypes = {
+ onClick: PropTypes.func.isRequired,
+};
+
+export default {
+ DiffyController: DiffyController
+};
diff --git a/app/addons/documents/sidebar/sidebar.js b/app/addons/documents/sidebar/sidebar.js
index 90760bb..6ccc240 100644
--- a/app/addons/documents/sidebar/sidebar.js
+++ b/app/addons/documents/sidebar/sidebar.js
@@ -574,7 +574,7 @@ class CloneIndexModal extends React.Component {
};
submit = () => {
- if (!this.refs.designDocSelector.validate()) {
+ if (!this.designDocSelector.validate()) {
return;
}
if (this.props.newIndexName === '') {
@@ -615,7 +615,7 @@ class CloneIndexModal extends React.Component {
<div className="row">
<DesignDocSelector
- ref="designDocSelector"
+ ref={node => this.designDocSelector = node}
designDocList={this.props.designDocArray}
selectedDesignDocName={this.props.selectedDesignDoc}
newDesignDocName={this.props.newDesignDocName}
diff --git a/app/addons/fauxton/notifications/notifications.js b/app/addons/fauxton/notifications/notifications.js
index 3e0f8f4..930bebb 100644
--- a/app/addons/fauxton/notifications/notifications.js
+++ b/app/addons/fauxton/notifications/notifications.js
@@ -282,7 +282,7 @@ class Notification extends React.Component {
<div
style={{opacity: style.opacity, minHeight: style.minHeight + 'px'}}
className={'global-notification alert alert-' + this.props.type}
- ref="notification">
+ ref={node => this.notification = node}>
<a data-bypass href="#" onClick={this.hide}><i className="pull-right fonticon-cancel" /></a>
<i className={'notification-icon ' + iconMap[this.props.type]} />
<span dangerouslySetInnerHTML={this.getMsg()}></span>
diff --git a/app/addons/replication/controller.js b/app/addons/replication/controller.js
index 3d312b1..6e96f0c 100644
--- a/app/addons/replication/controller.js
+++ b/app/addons/replication/controller.js
@@ -170,7 +170,6 @@ export default class ReplicationController extends React.Component {
selectAllDocs={Actions.selectAllReplicates}
allDocsSelected={allReplicateSelected}
someDocsSelected={someReplicateSelected}
- deleteDocs={Actions.deleteDocs}
activitySort={activitySort}
changeActivitySort={Actions.changeActivitySort}
deleteDocs={Actions.deleteReplicates}
@@ -187,7 +186,6 @@ export default class ReplicationController extends React.Component {
onFilterChange={Actions.filterDocs}
selectAllDocs={Actions.selectAllDocs}
selectDoc={Actions.selectDoc}
- selectAllDocs={Actions.selectAllDocs}
allDocsSelected={allDocsSelected}
someDocsSelected={someDocsSelected}
deleteDocs={Actions.deleteDocs}
--
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.