294 lines
8.5 KiB
JavaScript
294 lines
8.5 KiB
JavaScript
/**
|
|
* Copyright 2017 Red Hat Inc.
|
|
*
|
|
* 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 * as _ from 'lodash';
|
|
import { connect } from 'react-redux';
|
|
import { List, Map } from 'immutable';
|
|
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
|
import PropTypes from 'prop-types';
|
|
import React from 'react';
|
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
import Formsy from 'formsy-react';
|
|
|
|
import {
|
|
getAvailableNodeProfiles,
|
|
getFilteredNodes,
|
|
getNodesOperationInProgress
|
|
} from '../../selectors/nodes';
|
|
import { ConfirmationModal } from '../ui/Modals';
|
|
import FormErrorList from '../ui/forms/FormErrorList';
|
|
import NodesActions from '../../actions/NodesActions';
|
|
import NodesTable from './NodesTable';
|
|
import TagNodesModal from './tag_nodes/TagNodesModal';
|
|
import { findClosestWithAttribute } from '../utils/Dom';
|
|
|
|
const messages = defineMessages({
|
|
introspectNodes: {
|
|
id: 'NodesTableView.introspectNodes',
|
|
defaultMessage: 'Introspect Nodes'
|
|
},
|
|
tagNodes: {
|
|
id: 'NodesTableView.tagNodes',
|
|
defaultMessage: 'Tag Nodes'
|
|
},
|
|
provideNodes: {
|
|
id: 'NodesTableView.provideNodes',
|
|
defaultMessage: 'Provide Nodes',
|
|
description:
|
|
'"Providing" the nodes changes the provisioning state to "available" so that ' +
|
|
'they can be used in a deployment.'
|
|
},
|
|
deleteNodes: {
|
|
id: 'NodesTableView.deleteNodes',
|
|
defaultMessage: 'Delete Nodes'
|
|
},
|
|
deleteNodesModalTitle: {
|
|
id: 'NodesTableView.deleteNodesModalTitle',
|
|
defaultMessage: 'Delete Nodes'
|
|
},
|
|
deleteNodesModalMessage: {
|
|
id: 'NodesTableView.deleteNodesModalMessage',
|
|
defaultMessage: 'Are you sure you want to delete the selected nodes?'
|
|
}
|
|
});
|
|
|
|
class NodesTableView extends React.Component {
|
|
constructor() {
|
|
super();
|
|
this.state = {
|
|
canSubmit: false,
|
|
showDeleteModal: false,
|
|
showTagNodesModal: false,
|
|
submitParameters: {},
|
|
submitType: 'introspect'
|
|
};
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
this.invalidateForm(this.props.formFieldErrors.toJS());
|
|
}
|
|
|
|
canSubmit() {
|
|
if (
|
|
_.includes(
|
|
_.values(this.refs.registeredNodesTableForm.getCurrentValues()),
|
|
true
|
|
)
|
|
) {
|
|
this.enableButton();
|
|
} else {
|
|
this.disableButton();
|
|
}
|
|
}
|
|
|
|
enableButton() {
|
|
this.setState({ canSubmit: true });
|
|
}
|
|
|
|
disableButton() {
|
|
this.setState({ canSubmit: false });
|
|
}
|
|
|
|
invalidateForm(formFieldErrors) {
|
|
this.refs.registeredNodesTableForm.updateInputsWithError(formFieldErrors);
|
|
}
|
|
|
|
getTableActions() {
|
|
return (
|
|
<div className="btn-group">
|
|
<button
|
|
className="btn btn-default"
|
|
type="button"
|
|
name="introspect"
|
|
onClick={this.multipleSubmit.bind(this)}
|
|
disabled={
|
|
!this.state.canSubmit || this.props.nodesOperationInProgress
|
|
}
|
|
>
|
|
<FormattedMessage {...messages.introspectNodes} />
|
|
</button>
|
|
<button
|
|
className="btn btn-default"
|
|
type="button"
|
|
name="tag"
|
|
onClick={() => this.setState({ showTagNodesModal: true })}
|
|
disabled={
|
|
!this.state.canSubmit || this.props.nodesOperationInProgress
|
|
}
|
|
>
|
|
<FormattedMessage {...messages.tagNodes} />
|
|
</button>
|
|
<button
|
|
className="btn btn-default"
|
|
type="button"
|
|
name="provide"
|
|
onClick={this.multipleSubmit.bind(this)}
|
|
disabled={
|
|
!this.state.canSubmit || this.props.nodesOperationInProgress
|
|
}
|
|
>
|
|
<FormattedMessage {...messages.provideNodes} />
|
|
</button>
|
|
<button
|
|
className="btn btn-danger"
|
|
type="button"
|
|
name="delete"
|
|
onClick={() => this.setState({ showDeleteModal: true })}
|
|
disabled={
|
|
!this.state.canSubmit || this.props.nodesOperationInProgress
|
|
}
|
|
>
|
|
<FormattedMessage {...messages.deleteNodes} />
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
onTagNodesSubmit(tag) {
|
|
this.setState(
|
|
{
|
|
submitType: 'tag',
|
|
showTagNodesModal: false,
|
|
submitParameters: { tag: tag }
|
|
},
|
|
this.refs.registeredNodesTableForm.submit
|
|
);
|
|
}
|
|
|
|
multipleSubmit(e) {
|
|
this.setState(
|
|
{
|
|
submitType: findClosestWithAttribute(e.target, 'name')
|
|
},
|
|
this.refs.registeredNodesTableForm.submit
|
|
);
|
|
}
|
|
|
|
handleSubmit(formData, resetForm, invalidateForm) {
|
|
this.disableButton();
|
|
const nodeIds = _.keys(_.pickBy(formData, value => !!value));
|
|
|
|
switch (this.state.submitType) {
|
|
case 'introspect':
|
|
this.props.introspectNodes(nodeIds);
|
|
break;
|
|
case 'tag':
|
|
this.props.tagNodes(nodeIds, this.state.submitParameters.tag);
|
|
this.setState({ submitParameters: {} });
|
|
break;
|
|
case 'provide':
|
|
this.props.provideNodes(nodeIds);
|
|
break;
|
|
case 'delete':
|
|
this.setState({ showDeleteModal: false });
|
|
this.props.deleteNodes(nodeIds);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
resetForm();
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<div>
|
|
<Formsy.Form
|
|
ref="registeredNodesTableForm"
|
|
role="form"
|
|
className="form"
|
|
onSubmit={this.handleSubmit.bind(this)}
|
|
onValid={this.canSubmit.bind(this)}
|
|
onInvalid={this.disableButton.bind(this)}
|
|
>
|
|
<FormErrorList errors={this.props.formErrors.toJS()} />
|
|
<NodesTable
|
|
nodes={this.props.nodes}
|
|
dataOperationInProgress={this.props.nodesOperationInProgress}
|
|
nodesInProgress={this.props.nodesInProgress}
|
|
isFetchingNodes={this.props.isFetchingNodes}
|
|
tableActions={this.getTableActions.bind(this)}
|
|
/>
|
|
<ConfirmationModal
|
|
show={this.state.showDeleteModal}
|
|
title={this.props.intl.formatMessage(
|
|
messages.deleteNodesModalTitle
|
|
)}
|
|
question={this.props.intl.formatMessage(
|
|
messages.deleteNodesModalMessage
|
|
)}
|
|
iconClass="pficon pficon-delete"
|
|
confirmActionName="delete"
|
|
onConfirm={this.multipleSubmit.bind(this)}
|
|
onCancel={() => this.setState({ showDeleteModal: false })}
|
|
/>
|
|
<TagNodesModal
|
|
availableProfiles={this.props.availableProfiles.toArray()}
|
|
onProfileSelected={this.onTagNodesSubmit.bind(this)}
|
|
onCancel={() =>
|
|
this.setState({ showTagNodesModal: false, submitParameters: {} })
|
|
}
|
|
show={this.state.showTagNodesModal}
|
|
/>
|
|
</Formsy.Form>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
NodesTableView.propTypes = {
|
|
availableProfiles: ImmutablePropTypes.list.isRequired,
|
|
children: PropTypes.node,
|
|
deleteNodes: PropTypes.func.isRequired,
|
|
formErrors: ImmutablePropTypes.list,
|
|
formFieldErrors: ImmutablePropTypes.map,
|
|
intl: PropTypes.object,
|
|
introspectNodes: PropTypes.func.isRequired,
|
|
isFetchingNodes: PropTypes.bool.isRequired,
|
|
nodes: ImmutablePropTypes.map,
|
|
nodesInProgress: ImmutablePropTypes.set,
|
|
nodesOperationInProgress: PropTypes.bool.isRequired,
|
|
provideNodes: PropTypes.func.isRequired,
|
|
tagNodes: PropTypes.func.isRequired
|
|
};
|
|
NodesTableView.defaultProps = {
|
|
formErrors: List(),
|
|
formFieldErrors: Map()
|
|
};
|
|
|
|
function mapStateToProps(state) {
|
|
return {
|
|
availableProfiles: getAvailableNodeProfiles(state),
|
|
nodes: getFilteredNodes(state),
|
|
nodesInProgress: state.nodes.get('nodesInProgress'),
|
|
nodesOperationInProgress: getNodesOperationInProgress(state),
|
|
isFetchingNodes: state.nodes.get('isFetching')
|
|
};
|
|
}
|
|
|
|
function mapDispatchToProps(dispatch) {
|
|
return {
|
|
deleteNodes: nodeIds => dispatch(NodesActions.deleteNodes(nodeIds)),
|
|
introspectNodes: nodeIds =>
|
|
dispatch(NodesActions.startNodesIntrospection(nodeIds)),
|
|
provideNodes: nodeIds => dispatch(NodesActions.startProvideNodes(nodeIds)),
|
|
tagNodes: (nodeIds, tag) => dispatch(NodesActions.tagNodes(nodeIds, tag))
|
|
};
|
|
}
|
|
|
|
export default injectIntl(
|
|
connect(mapStateToProps, mapDispatchToProps)(NodesTableView)
|
|
);
|