stitch-ui
Version:
298 lines (286 loc) • 10.8 kB
JavaScript
/* eslint-disable jsx-a11y/no-static-element-interactions */
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { rulesEditMapper } from "../../actions";
import * as actions from "../actions";
import AddNamespaceForm from "./AddNamespaceForm";
import RuleEditor from "./RuleEditor";
import { pluralize } from "../../../util";
import {
Confirm,
SplitPanelContainer,
EditList,
EditListItem,
EditListHeader,
SplitPanel
} from "../../../core";
class EditRules extends React.Component {
constructor(props) {
super(props);
this.state = { addNamespaceModalOpen: false };
this.createNamespace = this.createNamespace.bind(this);
this.openNamespaceForm = this.openNamespaceForm.bind(this);
this.closeNamespaceForm = this.closeNamespaceForm.bind(this);
this.deleteRule = this.deleteRule.bind(this);
}
openNamespaceForm() {
this.setState({ addNamespaceFormOpen: true });
}
closeNamespaceForm() {
this.setState({ addNamespaceFormOpen: false });
}
deleteRule(ruleId, ns) {
return Confirm.confirm(
`Are you sure you want to delete namespace ${ns}?`
).then(
() =>
this.props.deleteRule(ruleId).then(this.props.reloadService).catch(),
() => Promise.resolve()
);
}
createNamespace(db, collection) {
return this.props
.addRule()
.then(r =>
this.props.updateRule(r._id, {
...r,
namespace: `${db}.${collection}`
})
)
.then(this.closeNamespaceForm)
.then(this.props.reloadService);
}
render() {
const { app, rules, ruleSaveState, rulesEditState } = this.props;
const {
setRule,
addAlert,
addFilter,
removeFilter,
discardFilterChanges,
setFieldType,
setOtherFieldsEnabled,
discardPermissionsFieldChanges,
changePermissionsField,
updateRule,
reloadService,
setEditingPath,
setFilterWhenInput,
setFilterMatchInput
} = this.props;
const {
changeCollection,
changeDatabase,
collection,
database,
setCreateNamespaceError,
createNamespaceError
} = this.props;
const ruleEditState =
this.state.editingRuleId &&
rulesEditState.has(this.state.editingRuleId) &&
rules.has(this.state.editingRuleId)
? rulesEditState.get(this.state.editingRuleId).toJS()
: {};
let editingFieldRule;
if (ruleEditState.editingPath) {
editingFieldRule = rules
.get(this.state.editingRuleId)
.fieldRules.getFieldRuleAtPath(ruleEditState.editingPath.path);
}
return (
<div className="mongo-rules-editor">
<SplitPanelContainer>
<SplitPanel left>
<EditListHeader>
<h3>MongoDB Collections</h3>
{!this.state.addNamespaceFormOpen &&
<button
className="button button-is-small button-is-primary"
onClick={this.openNamespaceForm}
>
New
</button>}
</EditListHeader>
<EditList>
{rules
.entrySeq()
.map(([ruleId, rule]) =>
<EditListItem
key={ruleId}
active={this.state.editingRuleId === ruleId}
onClick={() => this.setState({ editingRuleId: ruleId })}
>
<div className="splitpanel-leftside-listitem-info">
<div className="splitpanel-leftside-listitem-info-name">
{rule.namespace}
</div>
<div className="splitpanel-leftside-listitem-info-description">
<div>
{`${rule.filters.size} ${pluralize(
rule.filters.size,
"Filter",
"Filters"
)}`}
</div>
{rule.fieldRules.fields &&
<div>
{`${rule.fieldRules.fields.size} ${pluralize(
rule.fieldRules.fields.size,
"Field Rule",
"Field Rules"
)}`}
</div>}
</div>
<div className="splitpanel-leftside-listitem-info-description" />
</div>
</EditListItem>
)
.toArray()}
<AddNamespaceForm
open={this.state.addNamespaceFormOpen}
onCancel={() => this.setState({ addNamespaceFormOpen: false })}
createNamespace={this.createNamespace}
changeCollection={changeCollection}
changeDatabase={changeDatabase}
collection={collection}
database={database}
createNamespaceError={createNamespaceError}
setCreateNamespaceError={setCreateNamespaceError}
/>
</EditList>
</SplitPanel>
{this.state.editingRuleId &&
rules.has(this.state.editingRuleId) &&
<SplitPanel right>
<RuleEditor
addAlert={addAlert}
setRule={setRule}
app={app}
deleteRule={this.deleteRule}
rule={this.props.rules.get(this.state.editingRuleId)}
setOtherFieldsEnabled={setOtherFieldsEnabled}
setEditingPath={(path, elements, other) =>
setEditingPath(
this.state.editingRuleId,
path,
elements,
other
)}
discardPermissionsFieldChanges={discardPermissionsFieldChanges}
changePermissionsField={changePermissionsField}
setFieldType={(field, type) =>
setFieldType(this.state.editingRuleId, field, type)}
editingFieldRule={editingFieldRule}
ruleEditState={ruleEditState}
ruleSaveState={
ruleSaveState.has(this.state.editingRuleId)
? ruleSaveState.get(this.state.editingRuleId).toJS()
: {}
}
updateRule={updateRule}
addFilter={addFilter}
removeFilter={removeFilter}
discardFilterChanges={discardFilterChanges}
reloadService={reloadService}
setFilterWhenInput={(index, value) =>
setFilterWhenInput(this.state.editingRuleId, index, value)}
setFilterMatchInput={(index, value) =>
setFilterMatchInput(this.state.editingRuleId, index, value)}
/>
</SplitPanel>}
</SplitPanelContainer>
</div>
);
}
}
const mapStateToProps = state => {
const {
rules,
rulesEditState,
database,
collection,
createNamespaceError
} = state.service.serviceTypes.mongodb;
const { ruleSaveState } = state.service.base;
return {
rules,
rulesEditState,
ruleSaveState,
database,
collection,
createNamespaceError
};
};
const mapDispatchToProps = (dispatch, ownProps) => ({
...rulesEditMapper.mapDispatchToProps(dispatch, ownProps),
setFieldType: (ruleId, field, type) =>
dispatch(actions.setFieldType({ ruleId, field, type })),
setCreateNamespaceError: error =>
dispatch(actions.setCreateNamespaceError(error)),
setOtherFieldsEnabled: (ruleId, path, enabled) =>
dispatch(actions.setOtherFieldsEnabled({ ruleId, path, enabled })),
discardPermissionsFieldChanges: (ruleId, field, type) =>
dispatch(actions.discardPermissionsInput({ ruleId, field, type })),
changePermissionsField: (ruleId, field, value) =>
dispatch(actions.setPermissionsInput({ ruleId, field, value })),
setRule: rule => dispatch(actions.setRule({ rule })),
setFilterWhenInput: (ruleId, index, value) =>
dispatch(actions.setFilterWhenInput({ ruleId, index, value })),
setFilterMatchInput: (ruleId, index, value) =>
dispatch(actions.setFilterMatchInput({ ruleId, index, value })),
setNewFieldInput: (ruleId, path, value) =>
dispatch(actions.setNewFieldInput({ path, value })),
popHoveringPath: ruleId => dispatch(actions.popHoveringPath(ruleId)),
pushHoveringPath: (ruleId, path, elements) =>
dispatch(actions.pushHoveringPath({ ruleId, path, elements })),
addField: (ruleId, path, field) =>
dispatch(actions.addField({ ruleId, path, field })),
removeField: (ruleId, path) =>
dispatch(actions.removeField({ ruleId, path })),
setEditingPath: (ruleId, path, elements, other) =>
dispatch(actions.setEditingPath({ ruleId, path, elements, other })),
changeCollection: collection => dispatch(actions.setCollection(collection)),
changeDatabase: database => dispatch(actions.setDatabase(database)),
addFilter: ruleId => dispatch(actions.addFilter({ ruleId })),
removeFilter: (ruleId, index) =>
dispatch(actions.removeFilter({ ruleId, index })),
discardFilterChanges: (ruleId, index) =>
dispatch(actions.discardFilterChanges({ ruleId, index }))
});
/* eslint-disable react/forbid-prop-types */
EditRules.propTypes = {
app: PropTypes.object.isRequired,
rules: PropTypes.object.isRequired,
ruleSaveState: PropTypes.object.isRequired,
rulesEditState: PropTypes.object.isRequired,
addAlert: PropTypes.func.isRequired,
addRule: PropTypes.func.isRequired,
deleteRule: PropTypes.func.isRequired,
reloadService: PropTypes.func.isRequired,
updateRule: PropTypes.func.isRequired,
setFieldType: PropTypes.func.isRequired,
setCreateNamespaceError: PropTypes.func.isRequired,
discardPermissionsFieldChanges: PropTypes.func.isRequired,
discardFilterChanges: PropTypes.func.isRequired,
setOtherFieldsEnabled: PropTypes.func.isRequired,
changePermissionsField: PropTypes.func.isRequired,
setEditingPath: PropTypes.func.isRequired,
setRule: PropTypes.func.isRequired,
setFilterWhenInput: PropTypes.func.isRequired,
setFilterMatchInput: PropTypes.func.isRequired,
changeCollection: PropTypes.func.isRequired,
changeDatabase: PropTypes.func.isRequired,
addFilter: PropTypes.func.isRequired,
removeFilter: PropTypes.func.isRequired,
createNamespaceError: PropTypes.string,
collection: PropTypes.string,
database: PropTypes.string
};
EditRules.defaultProps = {
createNamespaceError: "",
collection: "",
database: ""
};
export default connect(mapStateToProps, mapDispatchToProps)(EditRules);