eslint: use as-needed for arrow-body-style

When a function that is introduced by an arrow, don't insert a return
statement and its required curly braces when not needed.

Bad:

    const f = () => {
        return 1;
    }

Good:

    const f = () => 1

This patch consists of a change to .eslintrc, and automatically fixed
files (via eslint --fix).

Change-Id: I6afc3f91ee2cc44ae149e482d5633876c85c3cff
This commit is contained in:
Honza Pokorny 2018-02-21 13:28:30 -04:00
parent bc9804b753
commit 16514bf462
63 changed files with 753 additions and 913 deletions

View File

@ -1,5 +1,6 @@
{ {
"rules": { "rules": {
"arrow-body-style": [2, "as-needed"],
"default-case": 0, "default-case": 0,
"linebreak-style": [2, "unix"], "linebreak-style": [2, "unix"],
"no-cond-assign": [2, "except-parens"], "no-cond-assign": [2, "except-parens"],

View File

@ -121,8 +121,8 @@ describe('updateEnvironmentConfiguration', () => {
NotificationActions.notify = jest.fn(() => ({ type: 'NOTIFY' })); NotificationActions.notify = jest.fn(() => ({ type: 'NOTIFY' }));
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store store
.dispatch( .dispatch(
EnvironmentConfigurationActions.updateEnvironmentConfiguration('myPlan') EnvironmentConfigurationActions.updateEnvironmentConfiguration('myPlan')
) )
@ -140,6 +140,5 @@ describe('updateEnvironmentConfiguration', () => {
stopSubmit('environmentConfigurationForm'), stopSubmit('environmentConfigurationForm'),
NotificationActions.notify({ type: 'NOTIFY' }) NotificationActions.notify({ type: 'NOTIFY' })
]); ]);
}); }));
});
}); });

View File

@ -177,18 +177,15 @@ describe('Fetching Introspection data success', () => {
.mockReturnValue(() => Promise.resolve(response)); .mockReturnValue(() => Promise.resolve(response));
}); });
it('dispatches fetchNodeIntrospectionDataSuccess', () => { it('dispatches fetchNodeIntrospectionDataSuccess', () =>
return store store.dispatch(NodesActions.fetchNodeIntrospectionData(nodeId)).then(() => {
.dispatch(NodesActions.fetchNodeIntrospectionData(nodeId)) expect(
.then(() => { IronicInspectorApiService.getIntrospectionData
expect( ).toHaveBeenCalledWith(nodeId);
IronicInspectorApiService.getIntrospectionData expect(store.getActions()).toEqual([
).toHaveBeenCalledWith(nodeId); NodesActions.fetchNodeIntrospectionDataSuccess(nodeId, response)
expect(store.getActions()).toEqual([ ]);
NodesActions.fetchNodeIntrospectionDataSuccess(nodeId, response) }));
]);
});
});
}); });
describe('Fetching Introspection data error', () => { describe('Fetching Introspection data error', () => {
@ -208,18 +205,15 @@ describe('Fetching Introspection data error', () => {
ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {}); ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {});
}); });
it('dispatches fetchNodeIntrospectionDataFailed', () => { it('dispatches fetchNodeIntrospectionDataFailed', () =>
return store store.dispatch(NodesActions.fetchNodeIntrospectionData(nodeId)).then(() => {
.dispatch(NodesActions.fetchNodeIntrospectionData(nodeId)) expect(
.then(() => { IronicInspectorApiService.getIntrospectionData
expect( ).toHaveBeenCalledWith(nodeId);
IronicInspectorApiService.getIntrospectionData expect(store.getActions()).toEqual([
).toHaveBeenCalledWith(nodeId); NodesActions.fetchNodeIntrospectionDataFailed(nodeId)
expect(store.getActions()).toEqual([ ]);
NodesActions.fetchNodeIntrospectionDataFailed(nodeId) }));
]);
});
});
}); });
describe('Asynchronous Introspect Nodes Action', () => { describe('Asynchronous Introspect Nodes Action', () => {
@ -235,22 +229,19 @@ describe('Asynchronous Introspect Nodes Action', () => {
.mockReturnValue(() => {}); .mockReturnValue(() => {});
}); });
it('dispatches startOperation', () => { it('dispatches startOperation', () =>
return store store.dispatch(NodesActions.startNodesIntrospection(nodeIds)).then(() => {
.dispatch(NodesActions.startNodesIntrospection(nodeIds)) expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
.then(() => { MistralConstants.BAREMETAL_INTROSPECT,
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith( {
MistralConstants.BAREMETAL_INTROSPECT, node_uuids: nodeIds
{ }
node_uuids: nodeIds );
} expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled();
); expect(store.getActions()).toEqual([
expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled(); NodesActions.startOperation(nodeIds)
expect(store.getActions()).toEqual([ ]);
NodesActions.startOperation(nodeIds) }));
]);
});
});
}); });
describe('nodesIntrospectionFinished', () => { describe('nodesIntrospectionFinished', () => {
@ -327,8 +318,8 @@ describe('startProvideNodes Action', () => {
.mockReturnValue(() => {}); .mockReturnValue(() => {});
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store.dispatch(NodesActions.startProvideNodes(nodeIds)).then(() => { store.dispatch(NodesActions.startProvideNodes(nodeIds)).then(() => {
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith( expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
MistralConstants.BAREMETAL_PROVIDE, MistralConstants.BAREMETAL_PROVIDE,
{ {
@ -339,8 +330,7 @@ describe('startProvideNodes Action', () => {
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
NodesActions.startOperation(nodeIds) NodesActions.startOperation(nodeIds)
]); ]);
}); }));
});
}); });
describe('provideNodesFinished', () => { describe('provideNodesFinished', () => {
@ -402,14 +392,13 @@ describe('Update Node thunk action', () => {
.mockReturnValue(() => Promise.resolve({ uuid: 'someId' })); .mockReturnValue(() => Promise.resolve({ uuid: 'someId' }));
}); });
it('dispatches required actions', () => { it('dispatches required actions', () =>
return store.dispatch(NodesActions.updateNode(nodePatch)).then(() => { store.dispatch(NodesActions.updateNode(nodePatch)).then(() => {
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
NodesActions.updateNodePending('someId'), NodesActions.updateNodePending('someId'),
NodesActions.updateNodeSuccess({ uuid: 'someId' }) NodesActions.updateNodeSuccess({ uuid: 'someId' })
]); ]);
}); }));
});
}); });
describe('Delete Nodes thunk action', () => { describe('Delete Nodes thunk action', () => {
@ -422,12 +411,11 @@ describe('Delete Nodes thunk action', () => {
.mockReturnValue(() => Promise.resolve()); .mockReturnValue(() => Promise.resolve());
}); });
it('successfully deletes a set of nodes', () => { it('successfully deletes a set of nodes', () =>
return store.dispatch(NodesActions.deleteNodes(nodeIds)).then(() => { store.dispatch(NodesActions.deleteNodes(nodeIds)).then(() => {
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
NodesActions.startOperation(nodeIds), NodesActions.startOperation(nodeIds),
NodesActions.deleteNodeSuccess(nodeIds[0]) NodesActions.deleteNodeSuccess(nodeIds[0])
]); ]);
}); }));
});
}); });

View File

@ -77,8 +77,8 @@ describe('ParametersActions', () => {
.mockReturnValue(() => Promise.resolve(responseBody)); .mockReturnValue(() => Promise.resolve(responseBody));
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store store
.dispatch(ParametersActions.fetchParameters('overcloud')) .dispatch(ParametersActions.fetchParameters('overcloud'))
.then(() => { .then(() => {
expect(MistralApiService.runAction).toHaveBeenCalled(); expect(MistralApiService.runAction).toHaveBeenCalled();
@ -86,8 +86,7 @@ describe('ParametersActions', () => {
ParametersActions.fetchParametersPending(), ParametersActions.fetchParametersPending(),
ParametersActions.fetchParametersSuccess(normalizedResponse) ParametersActions.fetchParametersSuccess(normalizedResponse)
]); ]);
}); }));
});
}); });
describe('updateParameters (fail)', () => { describe('updateParameters (fail)', () => {
@ -101,8 +100,8 @@ describe('ParametersActions', () => {
ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {}); ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {});
}); });
it('calls required actions', () => { it('calls required actions', () =>
return store store
.dispatch( .dispatch(
ParametersActions.updateParameters('overcloud', { foo: 'bar' }) ParametersActions.updateParameters('overcloud', { foo: 'bar' })
) )
@ -123,7 +122,6 @@ describe('ParametersActions', () => {
} }
}) })
]); ]);
}); }));
});
}); });
}); });

View File

@ -36,8 +36,8 @@ describe('PlansActions', () => {
.mockReturnValue(() => Promise.resolve()); .mockReturnValue(() => Promise.resolve());
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store store
.dispatch( .dispatch(
PlansActions.updatePlan('somecloud', { PlansActions.updatePlan('somecloud', {
someFile: { contents: 'file contents' } someFile: { contents: 'file contents' }
@ -48,8 +48,7 @@ describe('PlansActions', () => {
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
PlansActions.updatePlanPending('somecloud') PlansActions.updatePlanPending('somecloud')
]); ]);
}); }));
});
}); });
describe('createPlan', () => { describe('createPlan', () => {
@ -67,15 +66,10 @@ describe('PlansActions', () => {
.mockReturnValue(() => Promise.resolve()); .mockReturnValue(() => Promise.resolve());
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store store.dispatch(PlansActions.createPlan('somecloud', {})).then(() => {
.dispatch(PlansActions.createPlan('somecloud', {})) expect(store.getActions()).toEqual([PlansActions.createPlanPending()]);
.then(() => { }));
expect(store.getActions()).toEqual([
PlansActions.createPlanPending()
]);
});
});
}); });
describe('deletePlans', () => { describe('deletePlans', () => {
@ -87,8 +81,8 @@ describe('PlansActions', () => {
.mockReturnValue(() => Promise.resolve()); .mockReturnValue(() => Promise.resolve());
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store store
.dispatch(PlansActions.deletePlan('somecloud', mockHistory)) .dispatch(PlansActions.deletePlan('somecloud', mockHistory))
.then(() => { .then(() => {
expect(store.getActions().map(action => action.type)).toEqual([ expect(store.getActions().map(action => action.type)).toEqual([
@ -96,8 +90,7 @@ describe('PlansActions', () => {
'DELETE_PLAN_SUCCESS', 'DELETE_PLAN_SUCCESS',
'NOTIFY' 'NOTIFY'
]); ]);
}); }));
});
}); });
describe('fetchPlans', () => { describe('fetchPlans', () => {
@ -124,15 +117,14 @@ describe('PlansActions', () => {
.mockReturnValue(() => Promise.resolve(apiResponseMistral)); .mockReturnValue(() => Promise.resolve(apiResponseMistral));
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store.dispatch(PlansActions.fetchPlans()).then(() => { store.dispatch(PlansActions.fetchPlans()).then(() => {
expect(MistralApiService.runAction).toHaveBeenCalled(); expect(MistralApiService.runAction).toHaveBeenCalled();
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
PlansActions.requestPlans(), PlansActions.requestPlans(),
PlansActions.receivePlans(expectedPlans) PlansActions.receivePlans(expectedPlans)
]); ]);
}); }));
});
}); });
describe('fetchPlan', () => { describe('fetchPlan', () => {
@ -152,14 +144,13 @@ describe('PlansActions', () => {
.mockReturnValue(() => Promise.resolve(apiResponse)); .mockReturnValue(() => Promise.resolve(apiResponse));
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store.dispatch(PlansActions.fetchPlan('overcloud')).then(() => { store.dispatch(PlansActions.fetchPlan('overcloud')).then(() => {
expect(SwiftApiService.getContainer).toHaveBeenCalled(); expect(SwiftApiService.getContainer).toHaveBeenCalled();
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
PlansActions.requestPlan(), PlansActions.requestPlan(),
PlansActions.receivePlan('overcloud', normalizedResponse) PlansActions.receivePlan('overcloud', normalizedResponse)
]); ]);
}); }));
});
}); });
}); });

View File

@ -35,15 +35,14 @@ describe('StacksActions', () => {
.mockReturnValue(() => Promise.resolve(serviceResponse)); .mockReturnValue(() => Promise.resolve(serviceResponse));
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store.dispatch(StacksActions.fetchStacks()).then(() => { store.dispatch(StacksActions.fetchStacks()).then(() => {
expect(HeatApiService.getStacks).toHaveBeenCalled(); expect(HeatApiService.getStacks).toHaveBeenCalled();
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
StacksActions.fetchStacksPending(), StacksActions.fetchStacksPending(),
StacksActions.fetchStacksSuccess(normalizedStacks) StacksActions.fetchStacksSuccess(normalizedStacks)
]); ]);
}); }));
});
}); });
describe('fetchStacks (failed)', () => { describe('fetchStacks (failed)', () => {
@ -56,15 +55,14 @@ describe('StacksActions', () => {
ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {}); ErrorActions.handleErrors = jest.fn().mockReturnValue(() => {});
}); });
it('dispatches actions', () => { it('dispatches actions', () =>
return store.dispatch(StacksActions.fetchStacks()).then(() => { store.dispatch(StacksActions.fetchStacks()).then(() => {
expect(HeatApiService.getStacks).toHaveBeenCalled(); expect(HeatApiService.getStacks).toHaveBeenCalled();
expect(store.getActions()).toEqual([ expect(store.getActions()).toEqual([
StacksActions.fetchStacksPending(), StacksActions.fetchStacksPending(),
StacksActions.fetchStacksFailed() StacksActions.fetchStacksFailed()
]); ]);
}); }));
});
}); });
// describe('fetchStacks (failed)', () => { // describe('fetchStacks (failed)', () => {

View File

@ -81,8 +81,8 @@ describe('FetchValidations action', () => {
.mockReturnValue(() => Promise.resolve(response)); .mockReturnValue(() => Promise.resolve(response));
}); });
it('dispatches appropriate actions and normalizes the response', () => { it('dispatches appropriate actions and normalizes the response', () =>
return store.dispatch(ValidationsActions.fetchValidations()).then(() => { store.dispatch(ValidationsActions.fetchValidations()).then(() => {
expect(MistralApiService.runAction).toHaveBeenCalledWith( expect(MistralApiService.runAction).toHaveBeenCalledWith(
MistralConstants.VALIDATIONS_LIST MistralConstants.VALIDATIONS_LIST
); );
@ -90,8 +90,7 @@ describe('FetchValidations action', () => {
ValidationsActions.fetchValidationsPending(), ValidationsActions.fetchValidationsPending(),
ValidationsActions.fetchValidationsSuccess(normalizedResponse) ValidationsActions.fetchValidationsSuccess(normalizedResponse)
]); ]);
}); }));
});
}); });
describe('RunValidation action', () => { describe('RunValidation action', () => {
@ -118,8 +117,8 @@ describe('RunValidation action', () => {
.mockReturnValue(() => Promise.resolve(addWorkflowExecutionResponse)); .mockReturnValue(() => Promise.resolve(addWorkflowExecutionResponse));
}); });
it('dispatches appropriate actions', () => { it('dispatches appropriate actions', () =>
return store store
.dispatch(ValidationsActions.runValidation('512e', 'overcloud')) .dispatch(ValidationsActions.runValidation('512e', 'overcloud'))
.then(() => { .then(() => {
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith( expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
@ -134,8 +133,7 @@ describe('RunValidation action', () => {
addWorkflowExecutionResponse addWorkflowExecutionResponse
) )
]); ]);
}); }));
});
}); });
// TODO(jtomasek): this test compares 2 immutable records and even though they're the same // TODO(jtomasek): this test compares 2 immutable records and even though they're the same

View File

@ -18,11 +18,9 @@ import configureMockStore from 'redux-mock-store';
import thunkMiddleware from 'redux-thunk'; import thunkMiddleware from 'redux-thunk';
export const mockGetIntl = { export const mockGetIntl = {
getIntl: () => { getIntl: () => ({
return { formatMessage: msgObj => msgObj.defaultMessage
formatMessage: msgObj => msgObj.defaultMessage })
};
}
}; };
export const mockStore = configureMockStore([ export const mockStore = configureMockStore([

View File

@ -45,8 +45,8 @@ describe('fetchWorkflowExecutions action', () => {
.mockReturnValue(() => Promise.resolve(response)); .mockReturnValue(() => Promise.resolve(response));
}); });
it('dispatches appropriate actions and normalizes the response', () => { it('dispatches appropriate actions and normalizes the response', () =>
return store store
.dispatch(WorkflowExecutionsActions.fetchWorkflowExecutions()) .dispatch(WorkflowExecutionsActions.fetchWorkflowExecutions())
.then(() => { .then(() => {
expect(MistralApiService.getWorkflowExecutions).toHaveBeenCalled(); expect(MistralApiService.getWorkflowExecutions).toHaveBeenCalled();
@ -56,8 +56,7 @@ describe('fetchWorkflowExecutions action', () => {
normalizedResponse normalizedResponse
) )
]); ]);
}); }));
});
}); });
describe('updateWorkflowExecution action', () => { describe('updateWorkflowExecution action', () => {
@ -69,8 +68,8 @@ describe('updateWorkflowExecution action', () => {
.mockReturnValue(() => Promise.resolve()); .mockReturnValue(() => Promise.resolve());
}); });
it('dispatches appropriate actions', () => { it('dispatches appropriate actions', () =>
return store store
.dispatch( .dispatch(
WorkflowExecutionsActions.updateWorkflowExecution('512e', { WorkflowExecutionsActions.updateWorkflowExecution('512e', {
state: 'PAUSED' state: 'PAUSED'
@ -87,6 +86,5 @@ describe('updateWorkflowExecution action', () => {
}), }),
WorkflowExecutionsActions.addWorkflowExecution() WorkflowExecutionsActions.addWorkflowExecution()
]); ]);
}); }));
});
}); });

View File

@ -34,9 +34,7 @@ const mockNoRowsRenderer = function() {
return 'There are no items in data'; return 'There are no items in data';
}; };
const mockOnFilter = () => { const mockOnFilter = () => 'Filtering Happened';
return 'Filtering Happened';
};
describe('DataTable component', () => { describe('DataTable component', () => {
let DataTableVdom, DataTableInstance; let DataTableVdom, DataTableInstance;

View File

@ -35,8 +35,8 @@ describe('HeatApiService', () => {
.mockReturnValue(() => Promise.resolve(apiResponse)); .mockReturnValue(() => Promise.resolve(apiResponse));
}); });
it('returns a stack object based on <planName>', () => { it('returns a stack object based on <planName>', () =>
return store.dispatch(HeatApiService.getStacks()).then(result => { store.dispatch(HeatApiService.getStacks()).then(result => {
expect(HeatApiService.defaultRequest).toHaveBeenCalled(); expect(HeatApiService.defaultRequest).toHaveBeenCalled();
expect(result).toEqual({ expect(result).toEqual({
stacks: [ stacks: [
@ -44,7 +44,6 @@ describe('HeatApiService', () => {
{ stack_name: 'anothercloud', stack_status: 'CREATE_FAILED' } { stack_name: 'anothercloud', stack_status: 'CREATE_FAILED' }
] ]
}); });
}); }));
});
}); });
}); });

View File

@ -87,13 +87,11 @@ UserAuthenticator.propTypes = {
location: PropTypes.object.isRequired location: PropTypes.object.isRequired
}; };
const mapStateToProps = state => { const mapStateToProps = state => ({
return { isAuthenticated: state.login.isAuthenticated,
isAuthenticated: state.login.isAuthenticated, isAuthenticating: state.login.isAuthenticating,
isAuthenticating: state.login.isAuthenticating, keystoneAuthTokenId: state.login.tokenId
keystoneAuthTokenId: state.login.tokenId });
};
};
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
authenticateUserViaToken: tokenId => authenticateUserViaToken: tokenId =>

View File

@ -134,23 +134,21 @@ ValidationsWarning.propTypes = {
}; };
export const DeployButton = injectIntl( export const DeployButton = injectIntl(
({ deploy, disabled, intl, isRequestingPlanDeploy }) => { ({ deploy, disabled, intl, isRequestingPlanDeploy }) => (
return ( <button
<button type="button"
type="button" disabled={disabled}
disabled={disabled} className="btn btn-lg btn-primary"
className="btn btn-lg btn-primary" onClick={() => deploy()}
onClick={() => deploy()} >
<InlineLoader
loaded={!isRequestingPlanDeploy}
content={intl.formatMessage(messages.requestingDeploymentLoader)}
> >
<InlineLoader <FormattedMessage {...messages.deployButton} />
loaded={!isRequestingPlanDeploy} </InlineLoader>
content={intl.formatMessage(messages.requestingDeploymentLoader)} </button>
> )
<FormattedMessage {...messages.deployButton} />
</InlineLoader>
</button>
);
}
); );
DeployButton.propTypes = { DeployButton.propTypes = {
deploy: PropTypes.func.isRequired, deploy: PropTypes.func.isRequired,

View File

@ -173,34 +173,30 @@ DeploymentDetail.propTypes = {
stacksLoaded: PropTypes.bool.isRequired stacksLoaded: PropTypes.bool.isRequired
}; };
const mapStateToProps = state => { const mapStateToProps = state => ({
return { allPreDeploymentValidationsSuccessful: allPreDeploymentValidationsSuccessful(
allPreDeploymentValidationsSuccessful: allPreDeploymentValidationsSuccessful( state
state ),
), currentPlan: getCurrentPlan(state),
currentPlan: getCurrentPlan(state), currentPlanName: getCurrentPlanName(state),
currentPlanName: getCurrentPlanName(state), currentStack: getCurrentStack(state),
currentStack: getCurrentStack(state), currentStackDeploymentProgress: getCurrentStackDeploymentProgress(state),
currentStackDeploymentProgress: getCurrentStackDeploymentProgress(state), currentStackResources: state.stacks.resources,
currentStackResources: state.stacks.resources, currentStackResourcesLoaded: state.stacks.resourcesLoaded,
currentStackResourcesLoaded: state.stacks.resourcesLoaded, environmentConfigurationSummary: getEnvironmentConfigurationSummary(state),
environmentConfigurationSummary: getEnvironmentConfigurationSummary(state), overcloudInfo: getOvercloudInfo(state),
overcloudInfo: getOvercloudInfo(state), stacksLoaded: state.stacks.isLoaded
stacksLoaded: state.stacks.isLoaded });
};
};
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { deployPlan: planName => dispatch(PlanActions.deployPlan(planName)),
deployPlan: planName => dispatch(PlanActions.deployPlan(planName)), fetchStackResources: stack =>
fetchStackResources: stack => dispatch(StacksActions.fetchResources(stack.stack_name, stack.id)),
dispatch(StacksActions.fetchResources(stack.stack_name, stack.id)), runPreDeploymentValidations: planName =>
runPreDeploymentValidations: planName => dispatch(
dispatch( ValidationsActions.runValidationGroups(['pre-deployment'], planName)
ValidationsActions.runValidationGroups(['pre-deployment'], planName) )
) });
};
};
export default injectIntl( export default injectIntl(
connect(mapStateToProps, mapDispatchToProps)(DeploymentDetail) connect(mapStateToProps, mapDispatchToProps)(DeploymentDetail)

View File

@ -87,11 +87,9 @@ class StackResourcesTable extends React.Component {
let dataKeys = ['resource_name', 'resource_status']; let dataKeys = ['resource_name', 'resource_status'];
return filterString return filterString
? data.filter(row => { ? data.filter(row => {
let result = dataKeys.filter(dataKey => { let result = dataKeys.filter(dataKey =>
return row[dataKey] row[dataKey].toLowerCase().includes(filterString.toLowerCase())
.toLowerCase() );
.includes(filterString.toLowerCase());
});
return result.length > 0; return result.length > 0;
}) })
: data; : data;

View File

@ -28,21 +28,19 @@ const messages = defineMessages({
} }
}); });
const ConfigurePlanStep = props => { const ConfigurePlanStep = props => (
return ( <div>
<div> <DeploymentConfigurationSummary {...props} />
<DeploymentConfigurationSummary {...props} /> <br />
<br /> <Link
<Link className="btn btn-default"
className="btn btn-default" id="ConfigurePlanStep__EditDeploymentLink"
id="ConfigurePlanStep__EditDeploymentLink" to={`/plans/${props.planName}/configuration`}
to={`/plans/${props.planName}/configuration`} >
> <FormattedMessage {...messages.editConfigurationLink} />
<FormattedMessage {...messages.editConfigurationLink} /> </Link>
</Link> </div>
</div> );
);
};
ConfigurePlanStep.propTypes = { ConfigurePlanStep.propTypes = {
fetchEnvironmentConfiguration: PropTypes.func.isRequired, fetchEnvironmentConfiguration: PropTypes.func.isRequired,
isFetching: PropTypes.bool.isRequired, isFetching: PropTypes.bool.isRequired,

View File

@ -17,21 +17,19 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
export const DeploymentPlanStep = ({ children, disabled, title, tooltip }) => { export const DeploymentPlanStep = ({ children, disabled, title, tooltip }) => (
return ( <li className={disabled ? 'disabled' : null}>
<li className={disabled ? 'disabled' : null}> <h3>
<h3> <span>{title}</span>
<span>{title}</span> {tooltip ? (
{tooltip ? ( <span data-tooltip={tooltip} className="tooltip-right">
<span data-tooltip={tooltip} className="tooltip-right"> <span className="pficon pficon-info" />
<span className="pficon pficon-info" /> </span>
</span> ) : null}
) : null} </h3>
</h3> {children}
{children} </li>
</li> );
);
};
DeploymentPlanStep.propTypes = { DeploymentPlanStep.propTypes = {
children: PropTypes.node, children: PropTypes.node,

View File

@ -25,12 +25,10 @@ const messages = defineMessages({
} }
}); });
const HardwareStep = () => { const HardwareStep = () => (
return ( <Link className="btn btn-default" to="/nodes/register">
<Link className="btn btn-default" to="/nodes/register"> <FormattedMessage {...messages.registerNodes} />
<FormattedMessage {...messages.registerNodes} /> </Link>
</Link> );
);
};
export default HardwareStep; export default HardwareStep;

View File

@ -40,22 +40,20 @@ const EnvironmentCheckBox = ({
meta, meta,
required, required,
...rest ...rest
}) => { }) => (
return ( <FormGroup
<FormGroup controlId={id}
controlId={id} validationState={getValidationState({ ...meta, touched: true })}
validationState={getValidationState({ ...meta, touched: true })} >
> <Col smOffset={labelColumns} sm={inputColumns}>
<Col smOffset={labelColumns} sm={inputColumns}> <Checkbox {...input} {...rest}>
<Checkbox {...input} {...rest}> <span className={cx({ 'required-pf': required })}>{label}</span>
<span className={cx({ 'required-pf': required })}>{label}</span> </Checkbox>
</Checkbox> <InputMessage {...meta} touched />
<InputMessage {...meta} touched /> <InputDescription description={description} />
<InputDescription description={description} /> </Col>
</Col> </FormGroup>
</FormGroup> );
);
};
EnvironmentCheckBox.propTypes = { EnvironmentCheckBox.propTypes = {
description: PropTypes.node, description: PropTypes.node,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,

View File

@ -71,18 +71,14 @@ I18nDropdown.propTypes = {
languages: ImmutablePropTypes.map.isRequired languages: ImmutablePropTypes.map.isRequired
}; };
const mapStateToProps = state => { const mapStateToProps = state => ({
return { languages: getEnabledLanguages(state),
languages: getEnabledLanguages(state), currentLanguage: getCurrentLanguage(state)
currentLanguage: getCurrentLanguage(state) });
};
};
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { chooseLanguage: language => dispatch(I18nActions.chooseLanguage(language))
chooseLanguage: language => dispatch(I18nActions.chooseLanguage(language)) });
};
};
export default injectIntl( export default injectIntl(
connect(mapStateToProps, mapDispatchToProps)(I18nDropdown) connect(mapStateToProps, mapDispatchToProps)(I18nDropdown)

View File

@ -58,17 +58,13 @@ I18nProvider.defaultProps = {
messages: {} messages: {}
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { detectLanguage: language => dispatch(I18nActions.detectLanguage(language))
detectLanguage: language => dispatch(I18nActions.detectLanguage(language)) });
};
};
const mapStateToProps = state => { const mapStateToProps = state => ({
return { language: getCurrentLanguage(state),
language: getCurrentLanguage(state), messages: getCurrentLanguageMessages(state)
messages: getCurrentLanguageMessages(state) });
};
};
export default connect(mapStateToProps, mapDispatchToProps)(I18nProvider); export default connect(mapStateToProps, mapDispatchToProps)(I18nProvider);

View File

@ -22,13 +22,11 @@ import { injectIntl } from 'react-intl';
class LanguageInput extends React.Component { class LanguageInput extends React.Component {
_renderOptions() { _renderOptions() {
return this.props.languages return this.props.languages
.map((langName, langKey) => { .map((langName, langKey) => (
return ( <option key={`lang-${langKey}`} value={langKey}>
<option key={`lang-${langKey}`} value={langKey}> {langName}
{langName} </option>
</option> ))
);
})
.toList(); .toList();
} }

View File

@ -226,12 +226,10 @@ function mapStateToProps(state) {
}; };
} }
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { chooseLanguage: language => dispatch(I18nActions.chooseLanguage(language)),
chooseLanguage: language => dispatch(I18nActions.chooseLanguage(language)), authenticateUser: (formData, formFields, nextPath) =>
authenticateUser: (formData, formFields, nextPath) => dispatch(LoginActions.authenticateUser(formData, formFields, nextPath))
dispatch(LoginActions.authenticateUser(formData, formFields, nextPath)) });
};
};
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Login)); export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Login));

View File

@ -118,21 +118,19 @@ class NodeExtendedInfo extends React.Component {
<dd> <dd>
{node {node
.getIn(['introspectionData', 'interfaces']) .getIn(['introspectionData', 'interfaces'])
.map((ifc, k) => { .map((ifc, k) => (
return ( <div key={k}>
<div key={k}> {k} -{' '}
{k} -{' '} <span title={intl.formatMessage(messages.macAddress)}>
<span title={intl.formatMessage(messages.macAddress)}> {ifc.get('mac')}
{ifc.get('mac')} </span>{' '}
</span>{' '} |{' '}
|{' '} <span title={intl.formatMessage(messages.ipAddress)}>
<span title={intl.formatMessage(messages.ipAddress)}> {ifc.get('ip')}
{ifc.get('ip')} </span>
</span> {ifc.get('pxe') && '| PXE'}
{ifc.get('pxe') && '| PXE'} </div>
</div> ))
);
})
.toList()} .toList()}
</dd> </dd>
</dl> </dl>

View File

@ -130,11 +130,9 @@ class NodesTable extends React.Component {
let dataKeys = ['name']; let dataKeys = ['name'];
return filterString return filterString
? data.filter(row => { ? data.filter(row => {
let result = dataKeys.filter(dataKey => { let result = dataKeys.filter(dataKey =>
return row[dataKey] row[dataKey].toLowerCase().includes(filterString.toLowerCase())
.toLowerCase() );
.includes(filterString.toLowerCase());
});
return result.length > 0; return result.length > 0;
}) })
: data; : data;

View File

@ -183,27 +183,23 @@ NodesToolbar.propTypes = {
submitNodesToolbarForm: PropTypes.func.isRequired, submitNodesToolbarForm: PropTypes.func.isRequired,
updateFilter: PropTypes.func.isRequired updateFilter: PropTypes.func.isRequired
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { clearActiveFilters: () => dispatch(clearActiveFilters('nodesToolbar')),
clearActiveFilters: () => dispatch(clearActiveFilters('nodesToolbar')), deleteActiveFilter: uuid =>
deleteActiveFilter: uuid => dispatch(deleteActiveFilter('nodesToolbar', uuid)),
dispatch(deleteActiveFilter('nodesToolbar', uuid)), submitNodesToolbarForm: () => dispatch(submit('nodesToolbar')),
submitNodesToolbarForm: () => dispatch(submit('nodesToolbar')), addActiveFilter: data => dispatch(addActiveFilter('nodesToolbar', data)),
addActiveFilter: data => dispatch(addActiveFilter('nodesToolbar', data)), updateFilter: data => dispatch(updateFilter('nodesToolbar', data))
updateFilter: data => dispatch(updateFilter('nodesToolbar', data)) });
}; const mapStateToProps = state => ({
}; activeFilters: getActiveFilters(state, 'nodesToolbar'),
const mapStateToProps = state => { filteredNodesCount: getFilteredNodes(state).size,
return { filteredNodes: getFilteredNodes(state),
activeFilters: getActiveFilters(state, 'nodesToolbar'), nodesToolbarFilter: getFilterByName(state, 'nodesToolbar').delete(
filteredNodesCount: getFilteredNodes(state).size, 'activeFilters'
filteredNodes: getFilteredNodes(state), ),
nodesToolbarFilter: getFilterByName(state, 'nodesToolbar').delete( nodesCount: getNodes(state).size
'activeFilters' });
),
nodesCount: getNodes(state).size
};
};
export default injectIntl( export default injectIntl(
connect(mapStateToProps, mapDispatchToProps)(NodesToolbar) connect(mapStateToProps, mapDispatchToProps)(NodesToolbar)
); );

View File

@ -65,24 +65,22 @@ class NodesFileUpload extends React.Component {
const file = event.target.files[0]; const file = event.target.files[0];
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (f => { reader.onload = (f => e => {
return e => { if (file.name.match(/(\.json)$/)) {
if (file.name.match(/(\.json)$/)) { this.addNodesFromInstackenvJSON(e.target.result);
this.addNodesFromInstackenvJSON(e.target.result); } else if (file.name.match(/(\.csv)$/)) {
} else if (file.name.match(/(\.csv)$/)) { // TODO(jtomasek): add CSV file support
// TODO(jtomasek): add CSV file support // this.addNodesFromCSV(e.target.result);
// this.addNodesFromCSV(e.target.result); notify({
notify({ title: formatMessage(messages.csvUnsupported),
title: formatMessage(messages.csvUnsupported), message: formatMessage(messages.selectedFileUnsupported)
message: formatMessage(messages.selectedFileUnsupported) });
}); } else {
} else { notify({
notify({ title: formatMessage(messages.unsupportedFileFormat),
title: formatMessage(messages.unsupportedFileFormat), message: formatMessage(messages.provideCsvOrInstackenvJson)
message: formatMessage(messages.provideCsvOrInstackenvJson) });
}); }
}
};
})(file); })(file);
reader.readAsText(file); reader.readAsText(file);
this.refs.regNodesUploadFileForm.reset(); this.refs.regNodesUploadFileForm.reset();

View File

@ -114,114 +114,112 @@ const RegisterNodeFields = ({
node, node,
intl: { formatMessage }, intl: { formatMessage },
selectedDriver selectedDriver
}) => { }) => (
return ( <div>
<div> <h4>
<h4> <FormattedMessage {...messages.nodeDetail} />
<FormattedMessage {...messages.nodeDetail} /> </h4>
</h4> <Fieldset legend={formatMessage(messages.general)}>
<Fieldset legend={formatMessage(messages.general)}> <Field
<Field name={`${node}.name`}
name={`${node}.name`} component={HorizontalInput}
component={HorizontalInput} id={`${node}.name`}
id={`${node}.name`} label={formatMessage(messages.name)}
label={formatMessage(messages.name)} validate={[
validate={[ format({
format({ with: NODE_NAME_REGEX,
with: NODE_NAME_REGEX, message: formatMessage(messages.nodeNameRegexp),
message: formatMessage(messages.nodeNameRegexp),
allowBlank: true
}),
length({ max: 255 })
]}
/>
</Fieldset>
<Fieldset legend={formatMessage(messages.management)}>
<Field
name={`${node}.pm_type`}
component={HorizontalSelect}
id={`${node}.pm_type`}
label={formatMessage(messages.driver)}
validate={required()}
required
>
{['pxe_ipmitool', 'pxe_drac'].map((value, index) => (
<option key={index}>{value}</option>
))}
</Field>
{renderDriverFields(selectedDriver, node)}
</Fieldset>
<Fieldset legend={formatMessage(messages.hardware)}>
<Field
name={`${node}.arch`}
component={HorizontalSelect}
id={`${node}.arch`}
label={formatMessage(messages.architecture)}
>
{[undefined, 'x86_64', 'i386'].map((value, index) => (
<option key={index}>{value}</option>
))}
</Field>
<Field
name={`${node}.cpu`}
component={HorizontalInput}
id={`${node}.cpu`}
label={formatMessage(messages.cpuCount)}
type="number"
min={1}
validate={numericality({
int: true,
'>': 0,
allowBlank: true allowBlank: true
})} }),
/> length({ max: 255 })
<Field ]}
name={`${node}.memory`} />
component={HorizontalInput} </Fieldset>
id={`${node}.memory`} <Fieldset legend={formatMessage(messages.management)}>
label={formatMessage(messages.memoryMb)} <Field
type="number" name={`${node}.pm_type`}
min={1} component={HorizontalSelect}
validate={numericality({ id={`${node}.pm_type`}
int: true, label={formatMessage(messages.driver)}
'>': 0, validate={required()}
allowBlank: true required
})} >
/> {['pxe_ipmitool', 'pxe_drac'].map((value, index) => (
<Field <option key={index}>{value}</option>
name={`${node}.disk`} ))}
component={HorizontalInput} </Field>
id={`${node}.disk`} {renderDriverFields(selectedDriver, node)}
label={formatMessage(messages.diskGb)} </Fieldset>
type="number" <Fieldset legend={formatMessage(messages.hardware)}>
min={1} <Field
validate={numericality({ name={`${node}.arch`}
int: true, component={HorizontalSelect}
'>': 0, id={`${node}.arch`}
allowBlank: true label={formatMessage(messages.architecture)}
})} >
/> {[undefined, 'x86_64', 'i386'].map((value, index) => (
</Fieldset> <option key={index}>{value}</option>
<Fieldset legend={formatMessage(messages.networking)}> ))}
<Field </Field>
name={`${node}.mac`} <Field
component={HorizontalInput} name={`${node}.cpu`}
id={`${node}.mac`} component={HorizontalInput}
label={formatMessage(messages.nicMacAddresses)} id={`${node}.cpu`}
description={formatMessage(messages.macAddressesDescription)} label={formatMessage(messages.cpuCount)}
validate={[ type="number"
arrayOfFormat({ min={1}
with: MAC_ADDRESS_REGEX, validate={numericality({
message: messages.enterValidMacAddress int: true,
}) '>': 0,
]} allowBlank: true
parse={value => value.split(',')} })}
required />
/> <Field
</Fieldset> name={`${node}.memory`}
</div> component={HorizontalInput}
); id={`${node}.memory`}
}; label={formatMessage(messages.memoryMb)}
type="number"
min={1}
validate={numericality({
int: true,
'>': 0,
allowBlank: true
})}
/>
<Field
name={`${node}.disk`}
component={HorizontalInput}
id={`${node}.disk`}
label={formatMessage(messages.diskGb)}
type="number"
min={1}
validate={numericality({
int: true,
'>': 0,
allowBlank: true
})}
/>
</Fieldset>
<Fieldset legend={formatMessage(messages.networking)}>
<Field
name={`${node}.mac`}
component={HorizontalInput}
id={`${node}.mac`}
label={formatMessage(messages.nicMacAddresses)}
description={formatMessage(messages.macAddressesDescription)}
validate={[
arrayOfFormat({
with: MAC_ADDRESS_REGEX,
message: messages.enterValidMacAddress
})
]}
parse={value => value.split(',')}
required
/>
</Fieldset>
</div>
);
RegisterNodeFields.propTypes = { RegisterNodeFields.propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
node: PropTypes.string.isRequired, node: PropTypes.string.isRequired,

View File

@ -36,23 +36,19 @@ const messages = defineMessages({
} }
}); });
export const RegisterNodesTabPanes = ({ fields, meta, selectedNodeIndex }) => { export const RegisterNodesTabPanes = ({ fields, meta, selectedNodeIndex }) => (
return ( <div className="tab-content">
<div className="tab-content"> {fields.map((node, index, fields) => (
{fields.map((node, index, fields) => { <TabPane
return ( key={index}
<TabPane isActive={selectedNodeIndex === index}
key={index} // renderOnlyActive
isActive={selectedNodeIndex === index} >
// renderOnlyActive <RegisterNodeFields node={node} />
> </TabPane>
<RegisterNodeFields node={node} /> ))}
</TabPane> </div>
); );
})}
</div>
);
};
RegisterNodesTabPanes.propTypes = { RegisterNodesTabPanes.propTypes = {
fields: PropTypes.object.isRequired, fields: PropTypes.object.isRequired,
meta: PropTypes.object.isRequired, meta: PropTypes.object.isRequired,

View File

@ -42,8 +42,9 @@ class NotificationsToaster extends React.Component {
} }
renderNotifications() { renderNotifications() {
return this.props.notifications.toList().map(notification => { return this.props.notifications
return ( .toList()
.map(notification => (
<Notification <Notification
key={notification.id} key={notification.id}
title={notification.title} title={notification.title}
@ -55,8 +56,7 @@ class NotificationsToaster extends React.Component {
this.props.removeNotification(notification.id) this.props.removeNotification(notification.id)
} }
/> />
); ));
});
} }
render() { render() {

View File

@ -36,19 +36,17 @@ class ParameterInputList extends React.Component {
this.props.emptyParametersMessage || this.props.emptyParametersMessage ||
this.props.intl.formatMessage(messages.noParameters); this.props.intl.formatMessage(messages.noParameters);
const parameters = this.props.parameters.map(parameter => { const parameters = this.props.parameters.map(parameter => (
return ( <ParameterInput
<ParameterInput key={parameter.name}
key={parameter.name} name={parameter.name}
name={parameter.name} label={parameter.label}
label={parameter.label} description={parameter.description}
description={parameter.description} defaultValue={parameter.default}
defaultValue={parameter.default} value={parameter.value}
value={parameter.value} type={parameter.type}
type={parameter.type} />
/> ));
);
});
if (parameters.isEmpty()) { if (parameters.isEmpty()) {
return ( return (

View File

@ -66,17 +66,15 @@ class Parameters extends React.Component {
</TabPane> </TabPane>
); );
} else { } else {
return this.props.enabledEnvironments.toList().map(environment => { return this.props.enabledEnvironments.toList().map(environment => (
return ( <TabPane
<TabPane isActive={this.state.activeTab === environment.file}
isActive={this.state.activeTab === environment.file} key={environment.file}
key={environment.file} renderOnlyActive
renderOnlyActive >
> <EnvironmentParameters environment={environment.file} />
<EnvironmentParameters environment={environment.file} /> </TabPane>
</TabPane> ));
);
});
} }
} }

View File

@ -166,8 +166,8 @@ const convertJsonTypeParameterValueToString = value =>
// accept empty string as valid value // accept empty string as valid value
['', undefined].includes(value) ? '' : JSON.stringify(value); ['', undefined].includes(value) ? '' : JSON.stringify(value);
const getFormInitialValues = parameters => { const getFormInitialValues = parameters =>
return parameters parameters
.map(p => { .map(p => {
const value = p.value === undefined ? p.default : p.value; const value = p.value === undefined ? p.default : p.value;
if (p.type.toLowerCase() === 'json') { if (p.type.toLowerCase() === 'json') {
@ -177,22 +177,20 @@ const getFormInitialValues = parameters => {
} }
}) })
.toJS(); .toJS();
};
/** /**
* Filter out non updated parameters, so only parameters which have been actually changed * Filter out non updated parameters, so only parameters which have been actually changed
* get sent to updateparameters * get sent to updateparameters
*/ */
const filterFormData = (values, initialValues) => { const filterFormData = (values, initialValues) =>
return pickBy(values, (value, key) => !isEqual(value, initialValues[key])); pickBy(values, (value, key) => !isEqual(value, initialValues[key]));
};
/** /**
* Json parameter values are sent as string, this function parses them and checks if they're object * Json parameter values are sent as string, this function parses them and checks if they're object
* or array. Also, parameters with undefined value are set to null * or array. Also, parameters with undefined value are set to null
*/ */
const parseJsonTypeValues = (values, parameters) => { const parseJsonTypeValues = (values, parameters) =>
return mapValues(values, (value, key) => { mapValues(values, (value, key) => {
if (parameters.get(key).type.toLowerCase() === 'json') { if (parameters.get(key).type.toLowerCase() === 'json') {
try { try {
return JSON.parse(value); return JSON.parse(value);
@ -202,7 +200,6 @@ const parseJsonTypeValues = (values, parameters) => {
} }
return value === undefined ? null : value; return value === undefined ? null : value;
}); });
};
const handleSubmit = ( const handleSubmit = (
{ saveAndClose, ...values }, { saveAndClose, ...values },

View File

@ -49,19 +49,17 @@ const ParametersSidebar = ({
</a> </a>
</Tab> </Tab>
<li className="spacer" /> <li className="spacer" />
{enabledEnvironments.map(environment => { {enabledEnvironments.map(environment => (
return ( <Tab key={environment.file} isActive={isTabActive(environment.file)}>
<Tab key={environment.file} isActive={isTabActive(environment.file)}> <a
<a className="link"
className="link" onClick={() => activateTab(environment.file)}
onClick={() => activateTab(environment.file)} title={environment.file}
title={environment.file} >
> {environment.title}
{environment.title} </a>
</a> </Tab>
</Tab> ))}
);
})}
</ul> </ul>
</div> </div>
); );

View File

@ -52,36 +52,32 @@ class PlanFileInput extends React.Component {
let reader = new FileReader(); let reader = new FileReader();
let file = inputFiles[i]; let file = inputFiles[i];
reader.onerror = (f => { reader.onerror = (f => e => {
return e => { this.setState({
this.setState({ unreadableFile: f.webkitRelativePath
unreadableFile: f.webkitRelativePath });
});
};
})(file); })(file);
reader.onload = (f => { reader.onload = (f => e => {
return e => { const filePath = f.webkitRelativePath.replace(/^[^\/]*\//, '');
const filePath = f.webkitRelativePath.replace(/^[^\/]*\//, ''); if (!filePath.match(IGNORED_FILE_PATHS)) {
if (!filePath.match(IGNORED_FILE_PATHS)) { let obj = {
let obj = { name: filePath,
name: filePath, content: e.target.result
content: e.target.result };
}; files.push(obj);
files.push(obj); }
} processedFilesCount += 1;
processedFilesCount += 1; this.setState(
this.setState( { progress: Math.round(100 / l * processedFilesCount) },
{ progress: Math.round(100 / l * processedFilesCount) }, () => {
() => { // if the last file is processed, setValue -> triggers onChange on Formsy
// if the last file is processed, setValue -> triggers onChange on Formsy if (processedFilesCount === l) {
if (processedFilesCount === l) { this.props.setValue(files);
this.props.setValue(files); this.setState({ progress: 0 });
this.setState({ progress: 0 });
}
} }
); }
}; );
})(file); })(file);
reader.readAsText(file); reader.readAsText(file);
} }

View File

@ -38,33 +38,31 @@ const NodesAssignment = ({
nodeCountParametersByRole, nodeCountParametersByRole,
roles, roles,
updateNodesAssignment updateNodesAssignment
}) => { }) => (
return ( <NodesAssignmentForm
<NodesAssignmentForm currentPlanName={currentPlanName}
currentPlanName={currentPlanName} initialValues={assignedNodesCountsByRole.toJS()}
initialValues={assignedNodesCountsByRole.toJS()} updateNodesAssignment={updateNodesAssignment}
updateNodesAssignment={updateNodesAssignment} >
> <div className="row row-cards-pf">
<div className="row row-cards-pf"> {roles
{roles.toList().map(role => { .toList()
return ( .map(role => (
<RoleCard <RoleCard
key={role.name} key={role.name}
currentPlanName={currentPlanName} currentPlanName={currentPlanName}
name={role.name} name={role.name}
title={startCase(role.name)} title={startCase(role.name)}
identifier={role.identifier} identifier={role.identifier}
assignedNodesCountParameter={nodeCountParametersByRole.get( assignedNodesCountParameter={nodeCountParametersByRole.get(
role.name role.name
)} )}
availableNodesCount={availableNodesCountsByRole.get(role.name)} availableNodesCount={availableNodesCountsByRole.get(role.name)}
/> />
); ))}
})} </div>
</div> </NodesAssignmentForm>
</NodesAssignmentForm> );
);
};
NodesAssignment.propTypes = { NodesAssignment.propTypes = {
assignedNodesCountsByRole: ImmutablePropTypes.map.isRequired, assignedNodesCountsByRole: ImmutablePropTypes.map.isRequired,
availableNodesCountsByRole: ImmutablePropTypes.map.isRequired, availableNodesCountsByRole: ImmutablePropTypes.map.isRequired,
@ -82,12 +80,10 @@ const mapStateToProps = state => ({
roles: getRoles(state) roles: getRoles(state)
}); });
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { updateNodesAssignment: (currentPlanName, data) => {
updateNodesAssignment: (currentPlanName, data) => { dispatch(ParametersActions.updateNodesAssignment(currentPlanName, data));
dispatch(ParametersActions.updateNodesAssignment(currentPlanName, data)); }
} });
};
};
export default connect(mapStateToProps, mapDispatchToProps)(NodesAssignment); export default connect(mapStateToProps, mapDispatchToProps)(NodesAssignment);

View File

@ -53,22 +53,17 @@ class RoleServices extends React.Component {
} }
renderServiceTabs() { renderServiceTabs() {
return this.props.services.toList().map(service => { return this.props.services.toList().map(service => (
return ( <Tab
<Tab key={service.type}
key={service.type} title={service.description}
title={service.description} isActive={service.id === this.state.selectedService}
isActive={service.id === this.state.selectedService} >
> <a className="link" onClick={this.selectService.bind(this, service.id)}>
<a {service.type.split('::').pop()}
className="link" </a>
onClick={this.selectService.bind(this, service.id)} </Tab>
> ));
{service.type.split('::').pop()}
</a>
</Tab>
);
});
} }
render() { render() {

View File

@ -18,20 +18,18 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { Link, Route } from 'react-router-dom'; import { Link, Route } from 'react-router-dom';
const NavTab = ({ activeClassName, children, to, exact, location, id }) => { const NavTab = ({ activeClassName, children, to, exact, location, id }) => (
return ( <Route
<Route location={location}
location={location} path={typeof to === 'object' ? to.pathname : to}
path={typeof to === 'object' ? to.pathname : to} exact={exact}
exact={exact} children={({ match, location }) => (
children={({ match, location }) => ( <li className={match ? activeClassName : ''} id={id}>
<li className={match ? activeClassName : ''} id={id}> <Link to={to}>{children}</Link>
<Link to={to}>{children}</Link> </li>
</li> )}
)} />
/> );
);
};
NavTab.propTypes = { NavTab.propTypes = {
activeClassName: PropTypes.string.isRequired, activeClassName: PropTypes.string.isRequired,
children: PropTypes.node, children: PropTypes.node,

View File

@ -18,18 +18,16 @@ import { Button } from 'react-bootstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
export const SortDirectionInput = ({ input: { onChange, value }, title }) => { export const SortDirectionInput = ({ input: { onChange, value }, title }) => (
return ( <Button
<Button title={title}
title={title} type="button"
type="button" bsStyle="link"
bsStyle="link" onClick={() => onChange(value === 'asc' ? 'desc' : 'asc')}
onClick={() => onChange(value === 'asc' ? 'desc' : 'asc')} >
> <span className={`fa fa-sort-alpha-${value}`} />
<span className={`fa fa-sort-alpha-${value}`} /> </Button>
</Button> );
);
};
SortDirectionInput.propTypes = { SortDirectionInput.propTypes = {
children: PropTypes.node, children: PropTypes.node,
input: PropTypes.object.isRequired, input: PropTypes.object.isRequired,
@ -50,24 +48,22 @@ const getIconClass = optionKey => {
export const ContentViewSelectorInput = ({ export const ContentViewSelectorInput = ({
input: { onChange, value }, input: { onChange, value },
options options
}) => { }) => (
return ( <div>
<div> {Object.keys(options).map(k => (
{Object.keys(options).map(k => ( <Button
<Button key={k}
key={k} type="button"
type="button" bsStyle="link"
bsStyle="link" title={options[k]['title']}
title={options[k]['title']} id={options[k]['id']}
id={options[k]['id']} onClick={() => onChange(k)}
onClick={() => onChange(k)} >
> <i className={getIconClass(k)} />
<i className={getIconClass(k)} /> </Button>
</Button> ))}
))} </div>
</div> );
);
};
ContentViewSelectorInput.propTypes = { ContentViewSelectorInput.propTypes = {
input: PropTypes.object.isRequired, input: PropTypes.object.isRequired,
options: PropTypes.object.isRequired options: PropTypes.object.isRequired

View File

@ -18,20 +18,14 @@ import { Dropdown } from 'react-bootstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
const DropdownKebab = ({ children, id, pullRight }) => { const DropdownKebab = ({ children, id, pullRight }) => (
return ( <Dropdown className="dropdown-kebab-pf" id={id} pullRight={pullRight}>
<Dropdown className="dropdown-kebab-pf" id={id} pullRight={pullRight}> <Dropdown.Toggle bsStyle="link" noCaret onClick={e => e.stopPropagation()}>
<Dropdown.Toggle <span className="fa fa-ellipsis-v" />
bsStyle="link" </Dropdown.Toggle>
noCaret <Dropdown.Menu>{children}</Dropdown.Menu>
onClick={e => e.stopPropagation()} </Dropdown>
> );
<span className="fa fa-ellipsis-v" />
</Dropdown.Toggle>
<Dropdown.Menu>{children}</Dropdown.Menu>
</Dropdown>
);
};
DropdownKebab.propTypes = { DropdownKebab.propTypes = {
children: PropTypes.node, children: PropTypes.node,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,

View File

@ -18,21 +18,19 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { Link, Route } from 'react-router-dom'; import { Link, Route } from 'react-router-dom';
const MenuItemLink = ({ children, to, exact, location, ...rest }) => { const MenuItemLink = ({ children, to, exact, location, ...rest }) => (
return ( <Route
<Route path={to}
path={to} exact={exact}
exact={exact} children={({ match, location }) => (
children={({ match, location }) => ( <li onClick={e => e.stopPropagation()}>
<li onClick={e => e.stopPropagation()}> <Link {...rest} to={to}>
<Link {...rest} to={to}> {children}
{children} </Link>
</Link> </li>
</li> )}
)} />
/> );
);
};
MenuItemLink.propTypes = { MenuItemLink.propTypes = {
children: PropTypes.node, children: PropTypes.node,

View File

@ -22,13 +22,11 @@ export default class FormErrorList extends React.Component {
renderErrors() { renderErrors() {
const { errors } = this.props; const { errors } = this.props;
if (errors.length > 1) { if (errors.length > 1) {
const errorList = errors.map((error, index) => { const errorList = errors.map((error, index) => (
return ( <li key={index}>
<li key={index}> {error.title} {error.message}
{error.title} {error.message} </li>
</li> ));
);
});
return ( return (
<div> <div>
<strong>{`${errors.length} Errors Found:`}</strong> <strong>{`${errors.length} Errors Found:`}</strong>

View File

@ -32,24 +32,22 @@ const HorizontalCheckBox = ({
meta, meta,
required, required,
...rest ...rest
}) => { }) => (
return ( <FormGroup controlId={id} validationState={getValidationState(meta)}>
<FormGroup controlId={id} validationState={getValidationState(meta)}> <Col
<Col componentClass={ControlLabel}
componentClass={ControlLabel} sm={labelColumns}
sm={labelColumns} className={cx({ 'required-pf': required })}
className={cx({ 'required-pf': required })} >
> {label}
{label} </Col>
</Col> <Col sm={inputColumns}>
<Col sm={inputColumns}> <Checkbox {...input} {...rest} />
<Checkbox {...input} {...rest} /> <InputMessage {...meta} />
<InputMessage {...meta} /> <InputDescription description={description} />
<InputDescription description={description} /> </Col>
</Col> </FormGroup>
</FormGroup> );
);
};
HorizontalCheckBox.propTypes = { HorizontalCheckBox.propTypes = {
description: PropTypes.node, description: PropTypes.node,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,

View File

@ -32,24 +32,22 @@ const HorizontalInput = ({
meta, meta,
required, required,
...rest ...rest
}) => { }) => (
return ( <FormGroup controlId={id} validationState={getValidationState(meta)}>
<FormGroup controlId={id} validationState={getValidationState(meta)}> <Col
<Col componentClass={ControlLabel}
componentClass={ControlLabel} sm={labelColumns}
sm={labelColumns} className={cx({ 'required-pf': required })}
className={cx({ 'required-pf': required })} >
> {label}
{label} </Col>
</Col> <Col sm={inputColumns}>
<Col sm={inputColumns}> <FormControl type={type} {...input} {...rest} />
<FormControl type={type} {...input} {...rest} /> <InputMessage {...meta} />
<InputMessage {...meta} /> <InputDescription description={description} />
<InputDescription description={description} /> </Col>
</Col> </FormGroup>
</FormGroup> );
);
};
HorizontalInput.propTypes = { HorizontalInput.propTypes = {
description: PropTypes.node, description: PropTypes.node,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,

View File

@ -33,31 +33,29 @@ const HorizontalSelect = ({
meta, meta,
required, required,
...rest ...rest
}) => { }) => (
return ( <FormGroup controlId={id} validationState={getValidationState(meta)}>
<FormGroup controlId={id} validationState={getValidationState(meta)}> <Col
<Col componentClass={ControlLabel}
componentClass={ControlLabel} sm={labelColumns}
sm={labelColumns} className={cx({ 'required-pf': required })}
className={cx({ 'required-pf': required })} >
{label}
</Col>
<Col sm={inputColumns}>
<FormControl
componentClass="select"
multiple={multiple}
{...rest}
{...input}
> >
{label} {children}
</Col> </FormControl>
<Col sm={inputColumns}> <InputMessage {...meta} />
<FormControl <InputDescription description={description} />
componentClass="select" </Col>
multiple={multiple} </FormGroup>
{...rest} );
{...input}
>
{children}
</FormControl>
<InputMessage {...meta} />
<InputDescription description={description} />
</Col>
</FormGroup>
);
};
HorizontalSelect.propTypes = { HorizontalSelect.propTypes = {
children: PropTypes.node, children: PropTypes.node,
description: PropTypes.node, description: PropTypes.node,

View File

@ -70,18 +70,16 @@ NodePickerInput.defaultProps = {
}; };
export default NodePickerInput; export default NodePickerInput;
const PickerArrow = ({ direction, disabled, onClick }) => { const PickerArrow = ({ direction, disabled, onClick }) => (
return ( <button
<button type="button"
type="button" className={`btn btn-default btn-node-picker btn-node-picker-${direction}`}
className={`btn btn-default btn-node-picker btn-node-picker-${direction}`} onClick={onClick}
onClick={onClick} disabled={disabled}
disabled={disabled} >
> <span className={`fa fa-angle-${direction}`} aria-hidden="true" />
<span className={`fa fa-angle-${direction}`} aria-hidden="true" /> </button>
</button> );
);
};
PickerArrow.propTypes = { PickerArrow.propTypes = {
direction: PropTypes.oneOf(['up', 'down']).isRequired, direction: PropTypes.oneOf(['up', 'down']).isRequired,
disabled: PropTypes.bool.isRequired, disabled: PropTypes.bool.isRequired,

View File

@ -83,9 +83,7 @@ class DataTable extends React.Component {
render() { render() {
let columns = this._getColumns(); let columns = this._getColumns();
let headers = columns.map(column => { let headers = columns.map(column => column.props.header);
return column.props.header;
});
let rows = []; let rows = [];
for (var i = 0; i < this.props.rowsCount; ++i) { for (var i = 0; i < this.props.rowsCount; ++i) {

View File

@ -19,12 +19,12 @@ import React from 'react';
export default class DataTableRow extends React.Component { export default class DataTableRow extends React.Component {
render() { render() {
let cells = this.props.columns.map((column, index) => { let cells = this.props.columns.map((column, index) =>
return React.cloneElement(column.props.cell, { React.cloneElement(column.props.cell, {
rowIndex: this.props.index, rowIndex: this.props.index,
key: index key: index
}); })
}); );
return <tr>{cells}</tr>; return <tr>{cells}</tr>;
} }
} }

View File

@ -50,23 +50,21 @@ export default class Validation extends React.Component {
} }
renderValidationGroups() { renderValidationGroups() {
return this.props.groups.map(group => { return this.props.groups.map(group => (
return ( <div key={group} className="list-view-pf-additional-info-item">
<div key={group} className="list-view-pf-additional-info-item"> <span
<span className="label label-default"
className="label label-default" onClick={() =>
onClick={() => this.props.addActiveFilter({
this.props.addActiveFilter({ filterBy: 'group',
filterBy: 'group', filterString: group
filterString: group })
}) }
} >
> <small>{group}</small>
<small>{group}</small> </span>
</span> </div>
</div> ));
);
});
} }
render() { render() {

View File

@ -86,14 +86,12 @@ class ValidationDetail extends React.Component {
} }
renderValidationGroups() { renderValidationGroups() {
return this.props.groups.map(group => { return this.props.groups.map(group => (
return ( <small key={group}>
<small key={group}> <span className="label label-default">{group}</span>
<span className="label label-default">{group}</span> &nbsp;
&nbsp; </small>
</small> ));
);
});
} }
renderValidationOutput() { renderValidationOutput() {

View File

@ -117,8 +117,9 @@ class ValidationsList extends React.Component {
</BlankSlate> </BlankSlate>
); );
} else { } else {
return validations.toList().map(validation => { return validations
return ( .toList()
.map(validation => (
<Validation <Validation
key={validation.id} key={validation.id}
name={validation.name} name={validation.name}
@ -139,8 +140,7 @@ class ValidationsList extends React.Component {
id={validation.id} id={validation.id}
addActiveFilter={this.props.addActiveFilter} addActiveFilter={this.props.addActiveFilter}
/> />
); ));
});
} }
} }
@ -226,36 +226,32 @@ ValidationsList.propTypes = {
validationsLoaded: PropTypes.bool.isRequired validationsLoaded: PropTypes.bool.isRequired
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { addActiveFilter: data =>
addActiveFilter: data => dispatch(addActiveFilter('validationsToolbar', data)),
dispatch(addActiveFilter('validationsToolbar', data)), fetchValidations: () => dispatch(ValidationsActions.fetchValidations()),
fetchValidations: () => dispatch(ValidationsActions.fetchValidations()), fetchWorkflowExecutions: () =>
fetchWorkflowExecutions: () => dispatch(WorkflowExecutionsActions.fetchWorkflowExecutions()),
dispatch(WorkflowExecutionsActions.fetchWorkflowExecutions()), runValidation: (id, currentPlanName) => {
runValidation: (id, currentPlanName) => { dispatch(ValidationsActions.runValidation(id, currentPlanName));
dispatch(ValidationsActions.runValidation(id, currentPlanName)); },
}, stopValidation: executionId => {
stopValidation: executionId => { dispatch(
dispatch( WorkflowExecutionsActions.updateWorkflowExecution(executionId, {
WorkflowExecutionsActions.updateWorkflowExecution(executionId, { state: 'PAUSED'
state: 'PAUSED' })
}) );
); }
} });
};
};
const mapStateToProps = state => { const mapStateToProps = state => ({
return { executionsLoaded: state.executions.get('executionsLoaded'),
executionsLoaded: state.executions.get('executionsLoaded'), isFetchingValidations: state.validations.get('isFetching'),
isFetchingValidations: state.validations.get('isFetching'), validations: getFilteredValidations(state),
validations: getFilteredValidations(state), validationsLoaded: state.validations.get('validationsLoaded'),
validationsLoaded: state.validations.get('validationsLoaded'), currentPlanName: getCurrentPlanName(state),
currentPlanName: getCurrentPlanName(state), showValidations: state.validations.showValidations
showValidations: state.validations.showValidations });
};
};
export default injectIntl( export default injectIntl(
connect(mapStateToProps, mapDispatchToProps)(ValidationsList) connect(mapStateToProps, mapDispatchToProps)(ValidationsList)

View File

@ -140,23 +140,18 @@ ValidationsToolbar.propTypes = {
intl: PropTypes.object, intl: PropTypes.object,
validationsCount: PropTypes.number.isRequired validationsCount: PropTypes.number.isRequired
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => ({
return { addActiveFilter: data =>
addActiveFilter: data => dispatch(addActiveFilter('validationsToolbar', data)),
dispatch(addActiveFilter('validationsToolbar', data)), clearActiveFilters: () => dispatch(clearActiveFilters('validationsToolbar')),
clearActiveFilters: () => deleteActiveFilter: uuid =>
dispatch(clearActiveFilters('validationsToolbar')), dispatch(deleteActiveFilter('validationsToolbar', uuid))
deleteActiveFilter: uuid => });
dispatch(deleteActiveFilter('validationsToolbar', uuid)) const mapStateToProps = state => ({
}; activeFilters: getActiveFilters(state, 'validationsToolbar'),
}; filteredValidationsCount: getFilteredValidations(state).size,
const mapStateToProps = state => { validationsCount: getValidationsWithResults(state).size
return { });
activeFilters: getActiveFilters(state, 'validationsToolbar'),
filteredValidationsCount: getFilteredValidations(state).size,
validationsCount: getValidationsWithResults(state).size
};
};
export default injectIntl( export default injectIntl(
connect(mapStateToProps, mapDispatchToProps)(ValidationsToolbar) connect(mapStateToProps, mapDispatchToProps)(ValidationsToolbar)
); );

View File

@ -50,12 +50,12 @@ export default function environmentConfigurationReducer(
case EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_SUCCESS: { case EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_SUCCESS: {
const enabledEnvs = fromJS(action.payload); const enabledEnvs = fromJS(action.payload);
const updatedEnvs = state.environments.map(environment => { const updatedEnvs = state.environments.map(environment =>
return environment.set( environment.set(
'enabled', 'enabled',
enabledEnvs.includes(environment.get('file')) enabledEnvs.includes(environment.get('file'))
); )
}); );
return state.set('environments', updatedEnvs); return state.set('environments', updatedEnvs);
} }

View File

@ -30,11 +30,12 @@ export default function filtersReducer(state = initialState, action) {
// Don't add a new filter if there already is one with the same // Don't add a new filter if there already is one with the same
// filterBy and filterString. // filterBy and filterString.
if ( if (
state.getIn([filter, 'activeFilters']).filter(value => { state
return ( .getIn([filter, 'activeFilters'])
value.filterBy === filterBy && value.filterString === filterString .filter(
); value =>
}).size > 0 value.filterBy === filterBy && value.filterString === filterString
).size > 0
) { ) {
return state; return state;
} }

View File

@ -30,17 +30,16 @@ export const getEnvironment = (state, environmentFileName) =>
export const getEnabledEnvironments = createSelector( export const getEnabledEnvironments = createSelector(
getEnvironments, getEnvironments,
environments => { environments => environments.filter(environment => environment.get('enabled'))
return environments.filter(environment => environment.get('enabled'));
}
); );
export const getEnvironmentConfigurationSummary = createSelector( export const getEnvironmentConfigurationSummary = createSelector(
getEnabledEnvironments, getEnabledEnvironments,
environments => { environments => {
const titlesList = environments.reduce((titlesList, environment) => { const titlesList = environments.reduce(
return titlesList.push(environment.get('title')); (titlesList, environment) => titlesList.push(environment.get('title')),
}, List()); List()
);
return titlesList.toArray().join(', '); return titlesList.toArray().join(', ');
} }
); );
@ -50,17 +49,16 @@ export const getEnvironmentConfigurationSummary = createSelector(
*/ */
export const getTopicsTree = createSelector( export const getTopicsTree = createSelector(
[topics, environmentGroups, getEnvironments], [topics, environmentGroups, getEnvironments],
(topics, environmentGroups, environments) => { (topics, environmentGroups, environments) =>
return topics.map(topic => { topics.map(topic =>
return topic.update('environment_groups', envGroups => { topic.update('environment_groups', envGroups =>
return envGroups.map(envGroup => { envGroups.map(envGroup =>
return environmentGroups environmentGroups
.get(envGroup) .get(envGroup)
.update('environments', envs => { .update('environments', envs =>
return environments.filter((p, k) => envs.includes(k)); environments.filter((p, k) => envs.includes(k))
}); )
}); )
}); )
}); )
}
); );

View File

@ -16,9 +16,7 @@
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
export const getFilterByName = (state, filterName) => { export const getFilterByName = (state, filterName) => state.filters[filterName];
return state.filters[filterName];
};
export const getActiveFilters = createSelector(getFilterByName, filter => export const getActiveFilters = createSelector(getFilterByName, filter =>
filter.get('activeFilters') filter.get('activeFilters')

View File

@ -103,11 +103,11 @@ export const getFilteredNodes = createSelector(
.update(nodes => .update(nodes =>
nodesToolbarFilter.get('activeFilters').reduce( nodesToolbarFilter.get('activeFilters').reduce(
(filteredNodes, filter) => (filteredNodes, filter) =>
filteredNodes.filter(node => { filteredNodes.filter(node =>
return getNodePropertyString(node, filter.filterBy) getNodePropertyString(node, filter.filterBy)
.toLowerCase() .toLowerCase()
.includes(filter.filterString.toLowerCase()); .includes(filter.filterString.toLowerCase())
}), ),
nodes nodes
) )
) )

View File

@ -20,7 +20,5 @@ const notifications = state => state.notifications.get('all');
export const getNonViewedNotifications = createSelector( export const getNonViewedNotifications = createSelector(
notifications, notifications,
notifications => { notifications => notifications.filterNot(notification => notification.viewed)
return notifications.filterNot(notification => notification.viewed);
}
); );

View File

@ -126,30 +126,27 @@ export const getRoleNetworkConfig = createSelector(
export const getEnvironmentParameters = createSelector( export const getEnvironmentParameters = createSelector(
[getParametersExclInternal, getResources, getEnvironment], [getParametersExclInternal, getResources, getEnvironment],
(parameters, resources, environment) => { (parameters, resources, environment) =>
return ( resources
resources // get list of resources from environment resource_registry
// get list of resources from environment resource_registry .filter(r => environment.resourceRegistry.keySeq().includes(r.type))
.filter(r => environment.resourceRegistry.keySeq().includes(r.type)) // collect parameter names from those resources
// collect parameter names from those resources .reduce(
.reduce( (result, resource) =>
(result, resource) => result.union(
result.union( _extractParameters(
_extractParameters( resource.parameters,
resource.parameters, resource.resources,
resource.resources, resources
resources )
) ),
), Set()
Set() )
) // add parameters from environment's 'parameters' section to the list
// add parameters from environment's 'parameters' section to the list .union(environment.parameterDefaults.keySeq())
.union(environment.parameterDefaults.keySeq()) .toMap()
.toMap() // convert list of parameter names to map of actual parameter records
// convert list of parameter names to map of actual parameter records .update(filterParameters(parameters))
.update(filterParameters(parameters))
);
}
); );
/** /**
@ -195,8 +192,8 @@ export const getResourceParametersDeep = createSelector(
/** /**
* Recursively extracts Parameter names from a Resource and it's nested Resources * Recursively extracts Parameter names from a Resource and it's nested Resources
*/ */
const _extractParameters = (parameters, nestedResources, allResources) => { const _extractParameters = (parameters, nestedResources, allResources) =>
return nestedResources.reduce((pars, res) => { nestedResources.reduce((pars, res) => {
const resource = allResources.get(res); const resource = allResources.get(res);
return _extractParameters( return _extractParameters(
pars pars
@ -207,4 +204,3 @@ const _extractParameters = (parameters, nestedResources, allResources) => {
allResources allResources
); );
}, parameters); }, parameters);
};

View File

@ -40,9 +40,6 @@ export const getPlans = createSelector(plans, plans => plans);
// TODO(jtomasek): update this to list 3 last used plans // TODO(jtomasek): update this to list 3 last used plans
export const getAllPlansButCurrent = createSelector( export const getAllPlansButCurrent = createSelector(
[plans, getCurrentPlanName], [plans, getCurrentPlanName],
(plans, currentPlanName) => { (plans, currentPlanName) =>
return plans plans.filter(plan => plan.name != currentPlanName).sortBy(plan => plan.name)
.filter(plan => plan.name != currentPlanName)
.sortBy(plan => plan.name);
}
); );

View File

@ -41,13 +41,12 @@ export const getCurrentStack = createSelector(
*/ */
export const getCurrentStackDeploymentInProgress = createSelector( export const getCurrentStackDeploymentInProgress = createSelector(
[stacksSelector, getCurrentPlanName], [stacksSelector, getCurrentPlanName],
(stacks, currentPlanName) => { (stacks, currentPlanName) =>
return [ [
stackStates.CREATE_IN_PROGRESS, stackStates.CREATE_IN_PROGRESS,
stackStates.UPDATE_IN_PROGRESS, stackStates.UPDATE_IN_PROGRESS,
stackStates.DELETE_IN_PROGRESS stackStates.DELETE_IN_PROGRESS
].includes(stacks.get(currentPlanName, new Stack()).stack_status); ].includes(stacks.get(currentPlanName, new Stack()).stack_status)
}
); );
/** /**
@ -58,9 +57,9 @@ export const getCurrentStackDeploymentProgress = createSelector(
resources => { resources => {
let allResources = resources.size; let allResources = resources.size;
if (allResources > 0) { if (allResources > 0) {
let completeResources = resources.filter(r => { let completeResources = resources.filter(
return r.resource_status === 'CREATE_COMPLETE'; r => r.resource_status === 'CREATE_COMPLETE'
}).size; ).size;
return Math.ceil(completeResources / allResources * 100); return Math.ceil(completeResources / allResources * 100);
} }
return 0; return 0;

View File

@ -49,14 +49,13 @@ export const getValidationExecutionsForCurrentPlan = createSelector(
*/ */
export const getValidationsWithResults = createSelector( export const getValidationsWithResults = createSelector(
[validations, getValidationExecutionsForCurrentPlan], [validations, getValidationExecutionsForCurrentPlan],
(validations, results) => { (validations, results) =>
return validations.map(validation => { validations.map(validation => {
const validationResults = getValidationResults(validation.id, results); const validationResults = getValidationResults(validation.id, results);
return validation return validation
.set('results', validationResults) .set('results', validationResults)
.set('status', getValidationStatus(validationResults)); .set('status', getValidationStatus(validationResults));
}); })
}
); );
/** /**
@ -114,29 +113,25 @@ export const getValidationStatusCounts = createSelector(
* Helper function to get the most recent time a plan has been updated or * Helper function to get the most recent time a plan has been updated or
* created. * created.
*/ */
export const getMostRecentPlanUpdate = (executions, planName) => { export const getMostRecentPlanUpdate = (executions, planName) =>
return ( executions
executions .filter(
.filter( execution =>
execution => [MistralConstants.PLAN_UPDATE, MistralConstants.PLAN_CREATE].includes(
[MistralConstants.PLAN_UPDATE, MistralConstants.PLAN_CREATE].includes( execution.workflow_name
execution.workflow_name ) && execution.getIn(['input', 'container']) === planName
) && execution.getIn(['input', 'container']) === planName )
) .map(execution => execution.get('updated_at'))
.map(execution => execution.get('updated_at')) .sort()
.sort() .last() || 0;
.last() || 0
);
};
/** /**
* Helper function to get a validation results by validation name * Helper function to get a validation results by validation name
*/ */
const getValidationResults = (validationId, results) => { const getValidationResults = (validationId, results) =>
return results.filter( results.filter(
result => result.getIn(['input', 'validation_name']) === validationId result => result.getIn(['input', 'validation_name']) === validationId
); );
};
/** /**
* Helper function to determine validation status based on validation's results * Helper function to determine validation status based on validation's results

View File

@ -29,8 +29,8 @@ export const parseNodeCapabilities = capabilities => {
/** /**
* Convert Node's capabilities object to string * Convert Node's capabilities object to string
*/ */
export const stringifyNodeCapabilities = capabilities => { export const stringifyNodeCapabilities = capabilities =>
return Object.keys(capabilities) Object.keys(capabilities)
.reduce((caps, key) => { .reduce((caps, key) => {
if (!capabilities[key]) { if (!capabilities[key]) {
return caps; return caps;
@ -40,7 +40,6 @@ export const stringifyNodeCapabilities = capabilities => {
} }
}, []) }, [])
.join(','); .join(',');
};
/** /**
* Set or update Node capability * Set or update Node capability