Resolve CI issues
* update prettier dependency to version which works with npm5 [MIT] https://github.com/prettier/prettier * remove favicons-webpack-plugin * autofix linting errors to make tests pass * add simple favicon using html-webpack-plugin * remove unused .gitignore lines Change-Id: I6b7d1116f522a6a1dd5e8455e85f4db958424e7c Partial-Bug: 1743722 Closes-Bug: 1743898
This commit is contained in:
parent
9941b07efb
commit
27dfe42f5e
|
@ -1,8 +1,6 @@
|
||||||
node_modules
|
node_modules
|
||||||
node_modules.tar.gz
|
node_modules.tar.gz
|
||||||
dist
|
dist
|
||||||
!dist/index.html
|
|
||||||
!dist/tripleo_ui_config.js.sample
|
|
||||||
tests_results.xml
|
tests_results.xml
|
||||||
tripleo-ui-*.tgz
|
tripleo-ui-*.tgz
|
||||||
tripleo-ui-*.tar.gz
|
tripleo-ui-*.tar.gz
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -59,14 +59,13 @@
|
||||||
"eslint-config-prettier": "^1.7.0",
|
"eslint-config-prettier": "^1.7.0",
|
||||||
"eslint-plugin-prettier": "2.1.2",
|
"eslint-plugin-prettier": "2.1.2",
|
||||||
"eslint-plugin-react": "5.1.1",
|
"eslint-plugin-react": "5.1.1",
|
||||||
"favicons-webpack-plugin": "0.0.7",
|
|
||||||
"file-loader": "~0.9.0",
|
"file-loader": "~0.9.0",
|
||||||
"html-webpack-plugin": "^2.28.0",
|
"html-webpack-plugin": "^2.28.0",
|
||||||
"jest": "19.0.2",
|
"jest": "19.0.2",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"less": "~2.7.1",
|
"less": "~2.7.1",
|
||||||
"less-loader": "~2.2.3",
|
"less-loader": "~2.2.3",
|
||||||
"prettier": "1.3.1",
|
"prettier": "1.10.2",
|
||||||
"react-addons-test-utils": "^15.5.1",
|
"react-addons-test-utils": "^15.5.1",
|
||||||
"react-intl-po": "^1.1.0",
|
"react-intl-po": "^1.1.0",
|
||||||
"react-test-renderer": "^15.5.4",
|
"react-test-renderer": "^15.5.4",
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
import configureMockStore from 'redux-mock-store';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import thunkMiddleware from 'redux-thunk';
|
import thunkMiddleware from 'redux-thunk';
|
||||||
|
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../js/actions/EnvironmentConfigurationActions';
|
||||||
from '../../js/actions/EnvironmentConfigurationActions';
|
|
||||||
import NotificationActions from '../../js/actions/NotificationActions';
|
import NotificationActions from '../../js/actions/NotificationActions';
|
||||||
import MistralApiService from '../../js/services/MistralApiService';
|
import MistralApiService from '../../js/services/MistralApiService';
|
||||||
import { mockGetIntl } from './utils';
|
import { mockGetIntl } from './utils';
|
||||||
|
@ -35,7 +34,8 @@ describe('fetchEnvironmentConfiguration', () => {
|
||||||
'General Deployment Options': {
|
'General Deployment Options': {
|
||||||
environment_groups: [
|
environment_groups: [
|
||||||
{
|
{
|
||||||
description: 'Enable basic configuration required for OpenStack Deployment',
|
description:
|
||||||
|
'Enable basic configuration required for OpenStack Deployment',
|
||||||
environments: [
|
environments: [
|
||||||
{
|
{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -54,7 +54,8 @@ describe('fetchEnvironmentConfiguration', () => {
|
||||||
const normalizedResponse = {
|
const normalizedResponse = {
|
||||||
environmentGroups: {
|
environmentGroups: {
|
||||||
'Enable basic configuration required for OpenStack Deployment': {
|
'Enable basic configuration required for OpenStack Deployment': {
|
||||||
description: 'Enable basic configuration required for OpenStack Deployment',
|
description:
|
||||||
|
'Enable basic configuration required for OpenStack Deployment',
|
||||||
environments: ['overcloud-resource-registry-puppet.yaml'],
|
environments: ['overcloud-resource-registry-puppet.yaml'],
|
||||||
title: null
|
title: null
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import IronicApiService from '../../js/services/IronicApiService';
|
import IronicApiService from '../../js/services/IronicApiService';
|
||||||
import IronicInspectorApiService
|
import IronicInspectorApiService from '../../js/services/IronicInspectorApiService';
|
||||||
from '../../js/services/IronicInspectorApiService';
|
|
||||||
import MistralApiService from '../../js/services/MistralApiService';
|
import MistralApiService from '../../js/services/MistralApiService';
|
||||||
import { mockStore } from './utils';
|
import { mockStore } from './utils';
|
||||||
import NodesActions from '../../js/actions/NodesActions';
|
import NodesActions from '../../js/actions/NodesActions';
|
||||||
|
@ -240,11 +239,12 @@ describe('Asynchronous Introspect Nodes Action', () => {
|
||||||
return store
|
return store
|
||||||
.dispatch(NodesActions.startNodesIntrospection(nodeIds))
|
.dispatch(NodesActions.startNodesIntrospection(nodeIds))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(
|
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
|
||||||
MistralApiService.runWorkflow
|
MistralConstants.BAREMETAL_INTROSPECT,
|
||||||
).toHaveBeenCalledWith(MistralConstants.BAREMETAL_INTROSPECT, {
|
{
|
||||||
node_uuids: nodeIds
|
node_uuids: nodeIds
|
||||||
});
|
}
|
||||||
|
);
|
||||||
expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled();
|
expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled();
|
||||||
expect(store.getActions()).toEqual([
|
expect(store.getActions()).toEqual([
|
||||||
NodesActions.startOperation(nodeIds)
|
NodesActions.startOperation(nodeIds)
|
||||||
|
@ -329,11 +329,12 @@ describe('startProvideNodes Action', () => {
|
||||||
|
|
||||||
it('dispatches actions', () => {
|
it('dispatches actions', () => {
|
||||||
return store.dispatch(NodesActions.startProvideNodes(nodeIds)).then(() => {
|
return store.dispatch(NodesActions.startProvideNodes(nodeIds)).then(() => {
|
||||||
expect(
|
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
|
||||||
MistralApiService.runWorkflow
|
MistralConstants.BAREMETAL_PROVIDE,
|
||||||
).toHaveBeenCalledWith(MistralConstants.BAREMETAL_PROVIDE, {
|
{
|
||||||
node_uuids: nodeIds
|
node_uuids: nodeIds
|
||||||
});
|
}
|
||||||
|
);
|
||||||
expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled();
|
expect(NodesActions.pollNodeslistDuringProgress).toHaveBeenCalled();
|
||||||
expect(store.getActions()).toEqual([
|
expect(store.getActions()).toEqual([
|
||||||
NodesActions.startOperation(nodeIds)
|
NodesActions.startOperation(nodeIds)
|
||||||
|
|
|
@ -107,12 +107,13 @@ describe('ParametersActions', () => {
|
||||||
ParametersActions.updateParameters('overcloud', { foo: 'bar' })
|
ParametersActions.updateParameters('overcloud', { foo: 'bar' })
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(
|
expect(MistralApiService.runAction).toHaveBeenCalledWith(
|
||||||
MistralApiService.runAction
|
MistralConstants.PARAMETERS_UPDATE,
|
||||||
).toHaveBeenCalledWith(MistralConstants.PARAMETERS_UPDATE, {
|
{
|
||||||
container: 'overcloud',
|
container: 'overcloud',
|
||||||
parameters: { foo: 'bar' }
|
parameters: { foo: 'bar' }
|
||||||
});
|
}
|
||||||
|
);
|
||||||
expect(store.getActions()).toEqual([
|
expect(store.getActions()).toEqual([
|
||||||
ReduxFormActions.startSubmit('nodesAssignment'),
|
ReduxFormActions.startSubmit('nodesAssignment'),
|
||||||
ParametersActions.updateParametersPending(),
|
ParametersActions.updateParametersPending(),
|
||||||
|
|
|
@ -19,11 +19,8 @@ import { Map } from 'immutable';
|
||||||
import MistralApiService from '../../js/services/MistralApiService';
|
import MistralApiService from '../../js/services/MistralApiService';
|
||||||
import ValidationsActions from '../../js/actions/ValidationsActions';
|
import ValidationsActions from '../../js/actions/ValidationsActions';
|
||||||
import ValidationsConstants from '../../js/constants/ValidationsConstants';
|
import ValidationsConstants from '../../js/constants/ValidationsConstants';
|
||||||
import WorkflowExecutionsActions
|
import WorkflowExecutionsActions from '../../js/actions/WorkflowExecutionsActions';
|
||||||
from '../../js/actions/WorkflowExecutionsActions';
|
import { WorkflowExecution } from '../../js/immutableRecords/workflowExecutions';
|
||||||
import {
|
|
||||||
WorkflowExecution
|
|
||||||
} from '../../js/immutableRecords/workflowExecutions';
|
|
||||||
import MistralConstants from '../../js/constants/MistralConstants';
|
import MistralConstants from '../../js/constants/MistralConstants';
|
||||||
import { mockStore } from './utils';
|
import { mockStore } from './utils';
|
||||||
|
|
||||||
|
@ -125,12 +122,13 @@ describe('RunValidation action', () => {
|
||||||
return store
|
return store
|
||||||
.dispatch(ValidationsActions.runValidation('512e', 'overcloud'))
|
.dispatch(ValidationsActions.runValidation('512e', 'overcloud'))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(
|
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
|
||||||
MistralApiService.runWorkflow
|
MistralConstants.VALIDATIONS_RUN,
|
||||||
).toHaveBeenCalledWith(MistralConstants.VALIDATIONS_RUN, {
|
{
|
||||||
validation_name: '512e',
|
validation_name: '512e',
|
||||||
plan: 'overcloud'
|
plan: 'overcloud'
|
||||||
});
|
}
|
||||||
|
);
|
||||||
expect(store.getActions()).toEqual([
|
expect(store.getActions()).toEqual([
|
||||||
WorkflowExecutionsActions.addWorkflowExecution(
|
WorkflowExecutionsActions.addWorkflowExecution(
|
||||||
addWorkflowExecutionResponse
|
addWorkflowExecutionResponse
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import MistralApiService from '../../js/services/MistralApiService';
|
import MistralApiService from '../../js/services/MistralApiService';
|
||||||
import WorkflowExecutionsActions
|
import WorkflowExecutionsActions from '../../js/actions/WorkflowExecutionsActions';
|
||||||
from '../../js/actions/WorkflowExecutionsActions';
|
|
||||||
import { mockStore } from './utils';
|
import { mockStore } from './utils';
|
||||||
|
|
||||||
describe('fetchWorkflowExecutions action', () => {
|
describe('fetchWorkflowExecutions action', () => {
|
||||||
|
@ -78,9 +77,10 @@ describe('updateWorkflowExecution action', () => {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(
|
expect(MistralApiService.updateWorkflowExecution).toHaveBeenCalledWith(
|
||||||
MistralApiService.updateWorkflowExecution
|
'512e',
|
||||||
).toHaveBeenCalledWith('512e', { state: 'PAUSED' });
|
{ state: 'PAUSED' }
|
||||||
|
);
|
||||||
expect(store.getActions()).toEqual([
|
expect(store.getActions()).toEqual([
|
||||||
WorkflowExecutionsActions.updateWorkflowExecutionPending('512e', {
|
WorkflowExecutionsActions.updateWorkflowExecutionPending('512e', {
|
||||||
state: 'PAUSED'
|
state: 'PAUSED'
|
||||||
|
|
|
@ -73,25 +73,20 @@ describe('Login component', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('When user is logged in', () => {
|
describe('When user is logged in', () => {
|
||||||
xit(
|
xit('redirects to nextPath when user is logged in and visits login page', () => {
|
||||||
'redirects to nextPath when user is logged in and visits login page',
|
loginInstance = new Login();
|
||||||
() => {
|
loginInstance.context = {
|
||||||
loginInstance = new Login();
|
router: {
|
||||||
loginInstance.context = {
|
getCurrentQuery() {
|
||||||
router: {
|
return {
|
||||||
getCurrentQuery() {
|
nextPath: 'nodes'
|
||||||
return {
|
};
|
||||||
nextPath: 'nodes'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
// loginInstance.context.router.transitionTo = jest.genMockFunction();
|
};
|
||||||
loginInstance.componentWillMount();
|
// loginInstance.context.router.transitionTo = jest.genMockFunction();
|
||||||
expect(loginInstance.context.router.transitionTo).toBeCalledWith(
|
loginInstance.componentWillMount();
|
||||||
'nodes'
|
expect(loginInstance.context.router.transitionTo).toBeCalledWith('nodes');
|
||||||
);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,8 +18,7 @@ import { Map } from 'immutable';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
||||||
|
|
||||||
import EnvironmentConfiguration
|
import EnvironmentConfiguration from '../../../js/components/environment_configuration/EnvironmentConfiguration';
|
||||||
from '../../../js/components/environment_configuration/EnvironmentConfiguration';
|
|
||||||
|
|
||||||
describe('EnvironmentConfiguration component', () => {
|
describe('EnvironmentConfiguration component', () => {
|
||||||
let EnvConfVdom;
|
let EnvConfVdom;
|
||||||
|
|
|
@ -18,8 +18,7 @@ import { fromJS } from 'immutable';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
||||||
|
|
||||||
import EnvironmentConfigurationTopic
|
import EnvironmentConfigurationTopic from '../../../js/components/environment_configuration/EnvironmentConfigurationTopic';
|
||||||
from '../../../js/components/environment_configuration/EnvironmentConfigurationTopic';
|
|
||||||
import MockPlan from '../../mocks/MockPlan';
|
import MockPlan from '../../mocks/MockPlan';
|
||||||
|
|
||||||
const topic = MockPlan.capabilities.topics[0];
|
const topic = MockPlan.capabilities.topics[0];
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
import ReactShallowRenderer from 'react-test-renderer/shallow';
|
||||||
|
|
||||||
import EnvironmentGroup
|
import EnvironmentGroup from '../../../js/components/environment_configuration/EnvironmentGroup';
|
||||||
from '../../../js/components/environment_configuration/EnvironmentGroup';
|
|
||||||
import MockPlan from '../../mocks/MockPlan';
|
import MockPlan from '../../mocks/MockPlan';
|
||||||
|
|
||||||
const envGroup = MockPlan.capabilities.topics[0].environment_groups[0];
|
const envGroup = MockPlan.capabilities.topics[0].environment_groups[0];
|
||||||
|
|
|
@ -42,10 +42,7 @@ describe('Nodes Component', () => {
|
||||||
|
|
||||||
xit('should listen to NodesStore changes', () => {});
|
xit('should listen to NodesStore changes', () => {});
|
||||||
|
|
||||||
xit(
|
xit('should get nodes from NodesStore and store them in state on change in NodesStore', () => {});
|
||||||
'should get nodes from NodesStore and store them in state on change in NodesStore',
|
|
||||||
() => {}
|
|
||||||
);
|
|
||||||
|
|
||||||
xit('should issue a request to list Nodes on when mounted', () => {
|
xit('should issue a request to list Nodes on when mounted', () => {
|
||||||
spyOn(IronicApiService, 'handleGetNodes');
|
spyOn(IronicApiService, 'handleGetNodes');
|
||||||
|
|
|
@ -23,8 +23,7 @@ import {
|
||||||
DataTableHeaderCell,
|
DataTableHeaderCell,
|
||||||
DataTableDataFieldCell
|
DataTableDataFieldCell
|
||||||
} from '../../../../js/components/ui/tables/DataTableCells';
|
} from '../../../../js/components/ui/tables/DataTableCells';
|
||||||
import DataTableColumn
|
import DataTableColumn from '../../../../js/components/ui/tables/DataTableColumn';
|
||||||
from '../../../../js/components/ui/tables/DataTableColumn';
|
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ uuid: 1, provision_state: 'failed' },
|
{ uuid: 1, provision_state: 'failed' },
|
||||||
|
|
|
@ -26,7 +26,8 @@ export default {
|
||||||
environment_groups: [
|
environment_groups: [
|
||||||
{
|
{
|
||||||
title: null,
|
title: null,
|
||||||
description: 'Enable basic configuration required for OpenStack Deployment',
|
description:
|
||||||
|
'Enable basic configuration required for OpenStack Deployment',
|
||||||
environments: {
|
environments: {
|
||||||
'overcloud-resource-registry-puppet.yaml': {
|
'overcloud-resource-registry-puppet.yaml': {
|
||||||
file: 'overcloud-resource-registry-puppet.yaml',
|
file: 'overcloud-resource-registry-puppet.yaml',
|
||||||
|
@ -43,12 +44,14 @@ export default {
|
||||||
'environments/neutron-ml2-bigswitch.yaml': {
|
'environments/neutron-ml2-bigswitch.yaml': {
|
||||||
file: 'environments/neutron-ml2-bigswitch.yaml',
|
file: 'environments/neutron-ml2-bigswitch.yaml',
|
||||||
title: 'BigSwitch extensions',
|
title: 'BigSwitch extensions',
|
||||||
description: 'Enable Big Switch extensions, configured via puppet\n'
|
description:
|
||||||
|
'Enable Big Switch extensions, configured via puppet\n'
|
||||||
},
|
},
|
||||||
'environments/neutron-ml2-cisco-n1kv.yaml': {
|
'environments/neutron-ml2-cisco-n1kv.yaml': {
|
||||||
file: 'environments/neutron-ml2-cisco-n1kv.yaml',
|
file: 'environments/neutron-ml2-cisco-n1kv.yaml',
|
||||||
title: 'Cisco N1KV backend',
|
title: 'Cisco N1KV backend',
|
||||||
description: 'Enable a Cisco N1KV backend, configured via puppet\n'
|
description:
|
||||||
|
'Enable a Cisco N1KV backend, configured via puppet\n'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,10 @@
|
||||||
|
|
||||||
import { Map, fromJS } from 'immutable';
|
import { Map, fromJS } from 'immutable';
|
||||||
|
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../js/actions/EnvironmentConfigurationActions';
|
||||||
from '../../js/actions/EnvironmentConfigurationActions';
|
import EnvironmentConfigurationConstants from '../../js/constants/EnvironmentConfigurationConstants';
|
||||||
import EnvironmentConfigurationConstants
|
import environmentConfigurationReducer from '../../js/reducers/environmentConfigurationReducer';
|
||||||
from '../../js/constants/EnvironmentConfigurationConstants';
|
import { EnvironmentConfigurationState } from '../../js/immutableRecords/environmentConfiguration';
|
||||||
import environmentConfigurationReducer
|
|
||||||
from '../../js/reducers/environmentConfigurationReducer';
|
|
||||||
import {
|
|
||||||
EnvironmentConfigurationState
|
|
||||||
} from '../../js/immutableRecords/environmentConfiguration';
|
|
||||||
|
|
||||||
const initialState = new EnvironmentConfigurationState();
|
const initialState = new EnvironmentConfigurationState();
|
||||||
|
|
||||||
|
@ -55,7 +50,8 @@ describe('environmentConfigurationReducer', () => {
|
||||||
describe('fetchEnvironmentConfigurationPending', () => {
|
describe('fetchEnvironmentConfigurationPending', () => {
|
||||||
let newState;
|
let newState;
|
||||||
let action = {
|
let action = {
|
||||||
type: EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_PENDING
|
type:
|
||||||
|
EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_PENDING
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -16,13 +16,9 @@
|
||||||
|
|
||||||
import { Map, OrderedMap } from 'immutable';
|
import { Map, OrderedMap } from 'immutable';
|
||||||
|
|
||||||
import {
|
import { WorkflowExecution } from '../../js/immutableRecords/workflowExecutions';
|
||||||
WorkflowExecution
|
import WorkflowExecutionsConstants from '../../js/constants/WorkflowExecutionsConstants';
|
||||||
} from '../../js/immutableRecords/workflowExecutions';
|
import workflowExecutionsReducer from '../../js/reducers/workflowExecutionsReducer';
|
||||||
import WorkflowExecutionsConstants
|
|
||||||
from '../../js/constants/WorkflowExecutionsConstants';
|
|
||||||
import workflowExecutionsReducer
|
|
||||||
from '../../js/reducers/workflowExecutionsReducer';
|
|
||||||
import MistralConstants from '../../js/constants/MistralConstants';
|
import MistralConstants from '../../js/constants/MistralConstants';
|
||||||
|
|
||||||
const updatedAt = '1970-01-01T00:00:01Z';
|
const updatedAt = '1970-01-01T00:00:01Z';
|
||||||
|
|
|
@ -23,9 +23,7 @@ import {
|
||||||
FiltersInitialState
|
FiltersInitialState
|
||||||
} from '../../js/immutableRecords/filters';
|
} from '../../js/immutableRecords/filters';
|
||||||
import { InitialPlanState, Plan } from '../../js/immutableRecords/plans';
|
import { InitialPlanState, Plan } from '../../js/immutableRecords/plans';
|
||||||
import {
|
import { WorkflowExecution } from '../../js/immutableRecords/workflowExecutions';
|
||||||
WorkflowExecution
|
|
||||||
} from '../../js/immutableRecords/workflowExecutions';
|
|
||||||
import MistralConstants from '../../js/constants/MistralConstants';
|
import MistralConstants from '../../js/constants/MistralConstants';
|
||||||
|
|
||||||
describe(' validations selectors', () => {
|
describe(' validations selectors', () => {
|
||||||
|
|
|
@ -18,8 +18,7 @@ import { defineMessages } from 'react-intl';
|
||||||
import { normalize, arrayOf } from 'normalizr';
|
import { normalize, arrayOf } from 'normalizr';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
import EnvironmentConfigurationConstants
|
import EnvironmentConfigurationConstants from '../constants/EnvironmentConfigurationConstants';
|
||||||
from '../constants/EnvironmentConfigurationConstants';
|
|
||||||
import { handleErrors } from './ErrorActions';
|
import { handleErrors } from './ErrorActions';
|
||||||
import MistralApiService from '../services/MistralApiService';
|
import MistralApiService from '../services/MistralApiService';
|
||||||
import NotificationActions from '../actions/NotificationActions';
|
import NotificationActions from '../actions/NotificationActions';
|
||||||
|
@ -30,7 +29,8 @@ import SwiftApiService from '../services/SwiftApiService';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
envConfigUpdatedNotificationMessage: {
|
envConfigUpdatedNotificationMessage: {
|
||||||
id: 'EnvironmentConfigurationActions.envConfigUpdatedNotificationMessage',
|
id: 'EnvironmentConfigurationActions.envConfigUpdatedNotificationMessage',
|
||||||
defaultMessage: 'The Environment Configuration has been successfully updated.'
|
defaultMessage:
|
||||||
|
'The Environment Configuration has been successfully updated.'
|
||||||
},
|
},
|
||||||
envConfigUpdatedNotificationTitle: {
|
envConfigUpdatedNotificationTitle: {
|
||||||
id: 'EnvironmentConfigurationActions.envConfigUpdatedNotificationTitle',
|
id: 'EnvironmentConfigurationActions.envConfigUpdatedNotificationTitle',
|
||||||
|
@ -48,8 +48,8 @@ export default {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const entities = normalize(response, arrayOf(topicSchema))
|
const entities =
|
||||||
.entities || {};
|
normalize(response, arrayOf(topicSchema)).entities || {};
|
||||||
dispatch(this.fetchEnvironmentConfigurationSuccess(entities));
|
dispatch(this.fetchEnvironmentConfigurationSuccess(entities));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
@ -66,20 +66,23 @@ export default {
|
||||||
|
|
||||||
fetchEnvironmentConfigurationPending() {
|
fetchEnvironmentConfigurationPending() {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_PENDING
|
type:
|
||||||
|
EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_PENDING
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchEnvironmentConfigurationSuccess(entities) {
|
fetchEnvironmentConfigurationSuccess(entities) {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_SUCCESS,
|
type:
|
||||||
|
EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_SUCCESS,
|
||||||
payload: entities
|
payload: entities
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchEnvironmentConfigurationFailed(environment) {
|
fetchEnvironmentConfigurationFailed(environment) {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_FAILED
|
type:
|
||||||
|
EnvironmentConfigurationConstants.FETCH_ENVIRONMENT_CONFIGURATION_FAILED
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -128,20 +131,23 @@ export default {
|
||||||
|
|
||||||
updateEnvironmentConfigurationPending() {
|
updateEnvironmentConfigurationPending() {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_PENDING
|
type:
|
||||||
|
EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_PENDING
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
updateEnvironmentConfigurationSuccess(enabledEnvironments) {
|
updateEnvironmentConfigurationSuccess(enabledEnvironments) {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_SUCCESS,
|
type:
|
||||||
|
EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_SUCCESS,
|
||||||
payload: enabledEnvironments
|
payload: enabledEnvironments
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
updateEnvironmentConfigurationFailed(formErrors = [], formFieldErrors = {}) {
|
updateEnvironmentConfigurationFailed(formErrors = [], formFieldErrors = {}) {
|
||||||
return {
|
return {
|
||||||
type: EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_FAILED,
|
type:
|
||||||
|
EnvironmentConfigurationConstants.UPDATE_ENVIRONMENT_CONFIGURATION_FAILED,
|
||||||
payload: {
|
payload: {
|
||||||
formErrors,
|
formErrors,
|
||||||
formFieldErrors
|
formFieldErrors
|
||||||
|
@ -154,13 +160,13 @@ export default {
|
||||||
dispatch(this.fetchEnvironmentPending(environmentPath));
|
dispatch(this.fetchEnvironmentPending(environmentPath));
|
||||||
dispatch(SwiftApiService.getObject(planName, environmentPath))
|
dispatch(SwiftApiService.getObject(planName, environmentPath))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const {
|
const { resource_registry, parameter_defaults } = yaml.safeLoad(
|
||||||
resource_registry,
|
response,
|
||||||
parameter_defaults
|
{
|
||||||
} = yaml.safeLoad(response, {
|
filename: environmentPath,
|
||||||
filename: environmentPath,
|
json: true
|
||||||
json: true
|
}
|
||||||
});
|
);
|
||||||
dispatch(
|
dispatch(
|
||||||
this.fetchEnvironmentSuccess({
|
this.fetchEnvironmentSuccess({
|
||||||
file: environmentPath,
|
file: environmentPath,
|
||||||
|
|
|
@ -34,9 +34,10 @@ export default {
|
||||||
navigator.userLanguage;
|
navigator.userLanguage;
|
||||||
// If the locale contains the country but we can't find
|
// If the locale contains the country but we can't find
|
||||||
// messages for it then we only use the country part:
|
// messages for it then we only use the country part:
|
||||||
language = locale.match(/^[A-Za-z]+-[A-Za-z]+$/) && !MESSAGES[locale]
|
language =
|
||||||
? locale.split('-')[0]
|
locale.match(/^[A-Za-z]+-[A-Za-z]+$/) && !MESSAGES[locale]
|
||||||
: locale;
|
? locale.split('-')[0]
|
||||||
|
: locale;
|
||||||
}
|
}
|
||||||
dispatch(this.chooseLanguage(language));
|
dispatch(this.chooseLanguage(language));
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,8 +143,9 @@ export default {
|
||||||
dispatch(this.requestPlan());
|
dispatch(this.requestPlan());
|
||||||
return dispatch(SwiftApiService.getContainer(planName))
|
return dispatch(SwiftApiService.getContainer(planName))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const planFiles = normalize(response, arrayOf(planFileSchema))
|
const planFiles =
|
||||||
.entities.planFiles || {};
|
normalize(response, arrayOf(planFileSchema)).entities.planFiles ||
|
||||||
|
{};
|
||||||
dispatch(this.receivePlan(planName, planFiles));
|
dispatch(this.receivePlan(planName, planFiles));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -34,8 +34,8 @@ export default {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const roles = normalize(response, arrayOf(roleSchema)).entities
|
const roles =
|
||||||
.roles || {};
|
normalize(response, arrayOf(roleSchema)).entities.roles || {};
|
||||||
dispatch(this.fetchRolesSuccess(roles));
|
dispatch(this.fetchRolesSuccess(roles));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -46,8 +46,9 @@ export default {
|
||||||
dispatch(this.fetchStacksPending());
|
dispatch(this.fetchStacksPending());
|
||||||
return dispatch(HeatApiService.getStacks())
|
return dispatch(HeatApiService.getStacks())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const stacks = normalize(response.stacks, arrayOf(stackSchema))
|
const stacks =
|
||||||
.entities.stacks || {};
|
normalize(response.stacks, arrayOf(stackSchema)).entities.stacks ||
|
||||||
|
{};
|
||||||
dispatch(this.fetchStacksSuccess(stacks));
|
dispatch(this.fetchStacksSuccess(stacks));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
@ -81,8 +82,9 @@ export default {
|
||||||
dispatch(this.fetchResourcesPending());
|
dispatch(this.fetchResourcesPending());
|
||||||
dispatch(HeatApiService.getResources(stackName, stackId))
|
dispatch(HeatApiService.getResources(stackName, stackId))
|
||||||
.then(({ resources }) => {
|
.then(({ resources }) => {
|
||||||
const res = normalize(resources, arrayOf(stackResourceSchema))
|
const res =
|
||||||
.entities.stackResources || {};
|
normalize(resources, arrayOf(stackResourceSchema)).entities
|
||||||
|
.stackResources || {};
|
||||||
dispatch(this.fetchResourcesSuccess(res));
|
dispatch(this.fetchResourcesSuccess(res));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -32,8 +32,9 @@ export default {
|
||||||
MistralApiService.runAction(MistralConstants.VALIDATIONS_LIST)
|
MistralApiService.runAction(MistralConstants.VALIDATIONS_LIST)
|
||||||
)
|
)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const validations = normalize(response, arrayOf(validationSchema))
|
const validations =
|
||||||
.entities.validations || {};
|
normalize(response, arrayOf(validationSchema)).entities
|
||||||
|
.validations || {};
|
||||||
dispatch(this.fetchValidationsSuccess(validations));
|
dispatch(this.fetchValidationsSuccess(validations));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -18,11 +18,8 @@ import { normalize, arrayOf } from 'normalizr';
|
||||||
|
|
||||||
import { handleErrors } from './ErrorActions';
|
import { handleErrors } from './ErrorActions';
|
||||||
import MistralApiService from '../services/MistralApiService';
|
import MistralApiService from '../services/MistralApiService';
|
||||||
import WorkflowExecutionsConstants
|
import WorkflowExecutionsConstants from '../constants/WorkflowExecutionsConstants';
|
||||||
from '../constants/WorkflowExecutionsConstants';
|
import { workflowExecutionSchema } from '../normalizrSchemas/workflowExecutions';
|
||||||
import {
|
|
||||||
workflowExecutionSchema
|
|
||||||
} from '../normalizrSchemas/workflowExecutions';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fetchWorkflowExecutions() {
|
fetchWorkflowExecutions() {
|
||||||
|
@ -30,10 +27,9 @@ export default {
|
||||||
dispatch(this.fetchWorkflowExecutionsPending());
|
dispatch(this.fetchWorkflowExecutionsPending());
|
||||||
return dispatch(MistralApiService.getWorkflowExecutions())
|
return dispatch(MistralApiService.getWorkflowExecutions())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const executions = normalize(
|
const executions =
|
||||||
response,
|
normalize(response, arrayOf(workflowExecutionSchema)).entities
|
||||||
arrayOf(workflowExecutionSchema)
|
.executions || {};
|
||||||
).entities.executions || {};
|
|
||||||
dispatch(this.fetchWorkflowExecutionsSuccess(executions));
|
dispatch(this.fetchWorkflowExecutionsSuccess(executions));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
|
@ -60,9 +60,11 @@ class AuthenticatedContent extends React.Component {
|
||||||
<Route path="/nodes" component={Nodes} />
|
<Route path="/nodes" component={Nodes} />
|
||||||
<Route path="/plans/manage" component={Plans} />
|
<Route path="/plans/manage" component={Plans} />
|
||||||
<Route path="/plans/:planName" component={DeploymentPlan} />
|
<Route path="/plans/:planName" component={DeploymentPlan} />
|
||||||
{currentPlanName
|
{currentPlanName ? (
|
||||||
? <Redirect from="/" to={`/plans/${currentPlanName}`} />
|
<Redirect from="/" to={`/plans/${currentPlanName}`} />
|
||||||
: <Redirect from="/" to="/plans/manage" />}
|
) : (
|
||||||
|
<Redirect from="/" to="/plans/manage" />
|
||||||
|
)}
|
||||||
</Switch>
|
</Switch>
|
||||||
</MainContent>
|
</MainContent>
|
||||||
</GlobalLoader>
|
</GlobalLoader>
|
||||||
|
|
|
@ -65,11 +65,11 @@ class NavBar extends React.Component {
|
||||||
_renderLanguageDropdown() {
|
_renderLanguageDropdown() {
|
||||||
// Only include the I18nDropdown if there's more than one
|
// Only include the I18nDropdown if there's more than one
|
||||||
// language to choose from.
|
// language to choose from.
|
||||||
return this.props.languages.size > 1
|
return this.props.languages.size > 1 ? (
|
||||||
? <li>
|
<li>
|
||||||
<I18nDropdown />
|
<I18nDropdown />
|
||||||
</li>
|
</li>
|
||||||
: null;
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderHelpDropdown() {
|
_renderHelpDropdown() {
|
||||||
|
|
|
@ -52,7 +52,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
downloadLogsMessage: {
|
downloadLogsMessage: {
|
||||||
id: 'DebugScreen.downloadLogsMessage',
|
id: 'DebugScreen.downloadLogsMessage',
|
||||||
defaultMessage: 'The file you requested is ready. Please click the button below to ' +
|
defaultMessage:
|
||||||
|
'The file you requested is ready. Please click the button below to ' +
|
||||||
'download the export. You might need to right-click the button and choose ' +
|
'download the export. You might need to right-click the button and choose ' +
|
||||||
'"Save link as...".'
|
'"Save link as...".'
|
||||||
},
|
},
|
||||||
|
@ -102,19 +103,21 @@ class DebugScreen extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.props.logsUrl
|
return this.props.logsUrl ? (
|
||||||
? <div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage {...messages.downloadLogsMessage} />
|
<FormattedMessage {...messages.downloadLogsMessage} />
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<a href={this.props.logsUrl} className="btn btn-success">
|
|
||||||
<FormattedMessage {...messages.downloadLogs} />
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
: <div>
|
<br />
|
||||||
<FormattedMessage {...messages.downloadError} />
|
<a href={this.props.logsUrl} className="btn btn-success">
|
||||||
</div>;
|
<FormattedMessage {...messages.downloadLogs} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage {...messages.downloadError} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -50,7 +50,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
validationsWarningMessage: {
|
validationsWarningMessage: {
|
||||||
id: 'DeploymentConfirmation.validationsWarningMessage',
|
id: 'DeploymentConfirmation.validationsWarningMessage',
|
||||||
defaultMessage: 'It is highly recommended that you resolve all validation issues before ' +
|
defaultMessage:
|
||||||
|
'It is highly recommended that you resolve all validation issues before ' +
|
||||||
'continuing.'
|
'continuing.'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -78,8 +79,9 @@ class DeploymentConfirmation extends React.Component {
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<strong><FormattedMessage {...messages.summary} /></strong>
|
<strong>
|
||||||
{' '}
|
<FormattedMessage {...messages.summary} />
|
||||||
|
</strong>{' '}
|
||||||
{environmentSummary}
|
{environmentSummary}
|
||||||
</p>
|
</p>
|
||||||
<ValidationsWarning
|
<ValidationsWarning
|
||||||
|
@ -144,8 +146,7 @@ export const DeployButton = injectIntl(
|
||||||
loaded={!isRequestingPlanDeploy}
|
loaded={!isRequestingPlanDeploy}
|
||||||
content={intl.formatMessage(messages.requestingDeploymentLoader)}
|
content={intl.formatMessage(messages.requestingDeploymentLoader)}
|
||||||
>
|
>
|
||||||
<span className="fa fa-cloud-upload" />
|
<span className="fa fa-cloud-upload" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.deployButton} />
|
<FormattedMessage {...messages.deployButton} />
|
||||||
</InlineLoader>
|
</InlineLoader>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -21,9 +21,7 @@ import { ModalHeader, ModalTitle, ModalFooter } from 'react-bootstrap';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {
|
import { allPreDeploymentValidationsSuccessful } from '../../selectors/validations';
|
||||||
allPreDeploymentValidationsSuccessful
|
|
||||||
} from '../../selectors/validations';
|
|
||||||
import DeploymentConfirmation from './DeploymentConfirmation';
|
import DeploymentConfirmation from './DeploymentConfirmation';
|
||||||
import DeploymentProgress from './DeploymentProgress';
|
import DeploymentProgress from './DeploymentProgress';
|
||||||
import DeploymentSuccess from './DeploymentSuccess';
|
import DeploymentSuccess from './DeploymentSuccess';
|
||||||
|
@ -33,9 +31,7 @@ import {
|
||||||
getCurrentStack,
|
getCurrentStack,
|
||||||
getCurrentStackDeploymentProgress
|
getCurrentStackDeploymentProgress
|
||||||
} from '../../selectors/stacks';
|
} from '../../selectors/stacks';
|
||||||
import {
|
import { getEnvironmentConfigurationSummary } from '../../selectors/environmentConfiguration';
|
||||||
getEnvironmentConfigurationSummary
|
|
||||||
} from '../../selectors/environmentConfiguration';
|
|
||||||
import { Loader } from '../ui/Loader';
|
import { Loader } from '../ui/Loader';
|
||||||
import {
|
import {
|
||||||
CloseModalButton,
|
CloseModalButton,
|
||||||
|
|
|
@ -46,7 +46,9 @@ class DeploymentFailure extends React.Component {
|
||||||
<InlineNotification type="error" title={status}>
|
<InlineNotification type="error" title={status}>
|
||||||
<p>{this.props.stack.stack_status_reason}</p>
|
<p>{this.props.stack.stack_status_reason}</p>
|
||||||
</InlineNotification>
|
</InlineNotification>
|
||||||
<h2><FormattedMessage {...messages.resources} /></h2>
|
<h2>
|
||||||
|
<FormattedMessage {...messages.resources} />
|
||||||
|
</h2>
|
||||||
<div className="flex-column">
|
<div className="flex-column">
|
||||||
<StackResourcesTable
|
<StackResourcesTable
|
||||||
isFetchingResources={!this.props.stackResourcesLoaded}
|
isFetchingResources={!this.props.stackResourcesLoaded}
|
||||||
|
|
|
@ -41,13 +41,13 @@ export default class DeploymentProgress extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProgressBar() {
|
renderProgressBar() {
|
||||||
return this.props.stack.stack_status === stackStates.CREATE_IN_PROGRESS
|
return this.props.stack.stack_status === stackStates.CREATE_IN_PROGRESS ? (
|
||||||
? <ProgressBar
|
<ProgressBar
|
||||||
value={this.props.deploymentProgress}
|
value={this.props.deploymentProgress}
|
||||||
label={this.props.deploymentProgress + '%'}
|
label={this.props.deploymentProgress + '%'}
|
||||||
labelPosition="topRight"
|
labelPosition="topRight"
|
||||||
/>
|
/>
|
||||||
: null;
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -65,7 +65,9 @@ export default class DeploymentProgress extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
{this.renderProgressBar()}
|
{this.renderProgressBar()}
|
||||||
</div>
|
</div>
|
||||||
<h2><FormattedMessage {...messages.resources} /></h2>
|
<h2>
|
||||||
|
<FormattedMessage {...messages.resources} />
|
||||||
|
</h2>
|
||||||
<div className="flex-column">
|
<div className="flex-column">
|
||||||
<StackResourcesTable
|
<StackResourcesTable
|
||||||
isFetchingResources={!this.props.stackResourcesLoaded}
|
isFetchingResources={!this.props.stackResourcesLoaded}
|
||||||
|
|
|
@ -52,15 +52,23 @@ const OvercloudInfo = ({ intl, overcloudInfo }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h4><FormattedMessage {...messages.overcloudInformationHeader} /></h4>
|
<h4>
|
||||||
|
<FormattedMessage {...messages.overcloudInformationHeader} />
|
||||||
|
</h4>
|
||||||
<Loader
|
<Loader
|
||||||
loaded={!!(ip && password)}
|
loaded={!!(ip && password)}
|
||||||
content={intl.formatMessage(messages.loadingOvercloudInformation)}
|
content={intl.formatMessage(messages.loadingOvercloudInformation)}
|
||||||
>
|
>
|
||||||
<ul className="list">
|
<ul className="list">
|
||||||
<li><FormattedMessage {...messages.overcloudIpAddress} /> {ip}</li>
|
<li>
|
||||||
<li><FormattedMessage {...messages.username} /> admin</li>
|
<FormattedMessage {...messages.overcloudIpAddress} /> {ip}
|
||||||
<li><FormattedMessage {...messages.password} /> {password}</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<FormattedMessage {...messages.username} /> admin
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FormattedMessage {...messages.password} /> {password}
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Loader>
|
</Loader>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -37,17 +37,14 @@ import {
|
||||||
getNodeCountParametersByRole,
|
getNodeCountParametersByRole,
|
||||||
getTotalAssignedNodesCount
|
getTotalAssignedNodesCount
|
||||||
} from '../../selectors/nodesAssignment';
|
} from '../../selectors/nodesAssignment';
|
||||||
import {
|
import { getEnvironmentConfigurationSummary } from '../../selectors/environmentConfiguration';
|
||||||
getEnvironmentConfigurationSummary
|
|
||||||
} from '../../selectors/environmentConfiguration';
|
|
||||||
import { getCurrentPlan } from '../../selectors/plans';
|
import { getCurrentPlan } from '../../selectors/plans';
|
||||||
import { getRoles } from '../../selectors/roles';
|
import { getRoles } from '../../selectors/roles';
|
||||||
import ConfigurePlanStep from './ConfigurePlanStep';
|
import ConfigurePlanStep from './ConfigurePlanStep';
|
||||||
import CurrentPlanActions from '../../actions/CurrentPlanActions';
|
import CurrentPlanActions from '../../actions/CurrentPlanActions';
|
||||||
import { DeploymentPlanStep } from './DeploymentPlanStep';
|
import { DeploymentPlanStep } from './DeploymentPlanStep';
|
||||||
import DeployStep from './DeployStep';
|
import DeployStep from './DeployStep';
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../actions/EnvironmentConfigurationActions';
|
||||||
from '../../actions/EnvironmentConfigurationActions';
|
|
||||||
import HardwareStep from './HardwareStep';
|
import HardwareStep from './HardwareStep';
|
||||||
import NodesActions from '../../actions/NodesActions';
|
import NodesActions from '../../actions/NodesActions';
|
||||||
import NotificationActions from '../../actions/NotificationActions';
|
import NotificationActions from '../../actions/NotificationActions';
|
||||||
|
@ -83,7 +80,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
hardwareStepTooltip: {
|
hardwareStepTooltip: {
|
||||||
id: 'CurrentPlan.hardwareStepTooltip',
|
id: 'CurrentPlan.hardwareStepTooltip',
|
||||||
defaultMessage: 'This step registers and introspects your nodes. Registration involves ' +
|
defaultMessage:
|
||||||
|
'This step registers and introspects your nodes. Registration involves ' +
|
||||||
'defining the power management details of each node so that you so that the director can ' +
|
'defining the power management details of each node so that you so that the director can ' +
|
||||||
'control them during the introspection and provisioning stages. After registration, you ' +
|
'control them during the introspection and provisioning stages. After registration, you ' +
|
||||||
'introspect the nodes, which identifies the hardware each node uses and builds a profile of ' +
|
'introspect the nodes, which identifies the hardware each node uses and builds a profile of ' +
|
||||||
|
@ -92,13 +90,15 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
configurePlanStepTooltip: {
|
configurePlanStepTooltip: {
|
||||||
id: 'CurrentPlan.configurePlanStepTooltip',
|
id: 'CurrentPlan.configurePlanStepTooltip',
|
||||||
defaultMessage: "This step allows you edit specific settings for the overcloud's network, " +
|
defaultMessage:
|
||||||
|
"This step allows you edit specific settings for the overcloud's network, " +
|
||||||
'storage, and other certified plugins. Use this step to define your network isolation ' +
|
'storage, and other certified plugins. Use this step to define your network isolation ' +
|
||||||
'configuration and your backend storage settings.'
|
'configuration and your backend storage settings.'
|
||||||
},
|
},
|
||||||
configureRolesStepTooltip: {
|
configureRolesStepTooltip: {
|
||||||
id: 'CurrentPlan.configureRolesStepTooltip',
|
id: 'CurrentPlan.configureRolesStepTooltip',
|
||||||
defaultMessage: 'This step assigns and removes nodes from roles in your overcloud. On each ' +
|
defaultMessage:
|
||||||
|
'This step assigns and removes nodes from roles in your overcloud. On each ' +
|
||||||
"role's selection dialog, you can tag available nodes into the role or untag nodes already " +
|
"role's selection dialog, you can tag available nodes into the role or untag nodes already " +
|
||||||
'assigned to the role. Click "Assign Nodes" for a particular role to open the selection ' +
|
'assigned to the role. Click "Assign Nodes" for a particular role to open the selection ' +
|
||||||
'dialog and start assigning nodes. ' +
|
'dialog and start assigning nodes. ' +
|
||||||
|
@ -108,7 +108,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
deployStepTooltip: {
|
deployStepTooltip: {
|
||||||
id: 'CurrentPlan.deploymentStepTooltip',
|
id: 'CurrentPlan.deploymentStepTooltip',
|
||||||
defaultMessage: 'This step performs the deployment of the overcloud. Once the deployment ' +
|
defaultMessage:
|
||||||
|
'This step performs the deployment of the overcloud. Once the deployment ' +
|
||||||
'begins, the director tracks the progress and provides a report of each completed, running, ' +
|
'begins, the director tracks the progress and provides a report of each completed, running, ' +
|
||||||
'or failed step. When the deployment completes, the director displays the current overcloud ' +
|
'or failed step. When the deployment completes, the director displays the current overcloud ' +
|
||||||
'status and login details, which you use to interact with your overcloud. Click "Deploy" to ' +
|
'status and login details, which you use to interact with your overcloud. Click "Deploy" to ' +
|
||||||
|
@ -329,8 +330,8 @@ export function mapStateToProps(state, props) {
|
||||||
currentStackDeploymentProgress: getCurrentStackDeploymentProgress(state),
|
currentStackDeploymentProgress: getCurrentStackDeploymentProgress(state),
|
||||||
environmentConfigurationLoaded: state.environmentConfiguration.loaded,
|
environmentConfigurationLoaded: state.environmentConfiguration.loaded,
|
||||||
environmentConfigurationSummary: getEnvironmentConfigurationSummary(state),
|
environmentConfigurationSummary: getEnvironmentConfigurationSummary(state),
|
||||||
isFetchingEnvironmentConfiguration: state.environmentConfiguration
|
isFetchingEnvironmentConfiguration:
|
||||||
.isFetching,
|
state.environmentConfiguration.isFetching,
|
||||||
isFetchingNodes: state.nodes.get('isFetching'),
|
isFetchingNodes: state.nodes.get('isFetching'),
|
||||||
isFetchingParameters: state.parameters.isFetching,
|
isFetchingParameters: state.parameters.isFetching,
|
||||||
isFetchingRoles: state.roles.get('isFetching'),
|
isFetchingRoles: state.roles.get('isFetching'),
|
||||||
|
|
|
@ -66,8 +66,7 @@ export const DeployStep = ({
|
||||||
loaded={!currentPlan.isRequestingPlanDeploy}
|
loaded={!currentPlan.isRequestingPlanDeploy}
|
||||||
content={intl.formatMessage(messages.requestingDeploy)}
|
content={intl.formatMessage(messages.requestingDeploy)}
|
||||||
>
|
>
|
||||||
<span className="fa fa-cloud-upload" />
|
<span className="fa fa-cloud-upload" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.validateAndDeploy} />
|
<FormattedMessage {...messages.validateAndDeploy} />
|
||||||
</InlineLoader>
|
</InlineLoader>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -21,8 +21,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { checkRunningDeployment } from '../utils/checkRunningDeploymentHOC';
|
import { checkRunningDeployment } from '../utils/checkRunningDeploymentHOC';
|
||||||
import EnvironmentConfiguration
|
import EnvironmentConfiguration from '../environment_configuration/EnvironmentConfiguration';
|
||||||
from '../environment_configuration/EnvironmentConfiguration';
|
|
||||||
import NavTab from '../ui/NavTab';
|
import NavTab from '../ui/NavTab';
|
||||||
import { CloseModalXButton, RoutedModal } from '../ui/Modals';
|
import { CloseModalXButton, RoutedModal } from '../ui/Modals';
|
||||||
import Parameters from '../parameters/Parameters';
|
import Parameters from '../parameters/Parameters';
|
||||||
|
|
|
@ -54,8 +54,7 @@ class DeploymentFailure extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
<InlineNotification type="error" title={status}>
|
<InlineNotification type="error" title={status}>
|
||||||
<p>
|
<p>
|
||||||
{stack.stack_status_reason}
|
{stack.stack_status_reason}{' '}
|
||||||
{' '}
|
|
||||||
<Link to={`/plans/${currentPlanName}/deployment-detail`}>
|
<Link to={`/plans/${currentPlanName}/deployment-detail`}>
|
||||||
<FormattedMessage {...messages.moreDetails} />
|
<FormattedMessage {...messages.moreDetails} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -22,11 +22,11 @@ export const DeploymentPlanStep = ({ children, disabled, title, tooltip }) => {
|
||||||
<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>
|
||||||
|
|
|
@ -49,13 +49,13 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class DeploymentProgress extends React.Component {
|
class DeploymentProgress extends React.Component {
|
||||||
renderProgressBar() {
|
renderProgressBar() {
|
||||||
return this.props.stack.stack_status === stackStates.CREATE_IN_PROGRESS
|
return this.props.stack.stack_status === stackStates.CREATE_IN_PROGRESS ? (
|
||||||
? <ProgressBar
|
<ProgressBar
|
||||||
value={this.props.deploymentProgress}
|
value={this.props.deploymentProgress}
|
||||||
label={this.props.deploymentProgress + '%'}
|
label={this.props.deploymentProgress + '%'}
|
||||||
labelPosition="topRight"
|
labelPosition="topRight"
|
||||||
/>
|
/>
|
||||||
: null;
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -73,8 +73,9 @@ class DeploymentProgress extends React.Component {
|
||||||
</strong>
|
</strong>
|
||||||
);
|
);
|
||||||
|
|
||||||
const deleteButton = stack.stack_status !== stackStates.DELETE_IN_PROGRESS
|
const deleteButton =
|
||||||
? <DeleteStackButton
|
stack.stack_status !== stackStates.DELETE_IN_PROGRESS ? (
|
||||||
|
<DeleteStackButton
|
||||||
content={formatMessage(messages.cancelDeployment)}
|
content={formatMessage(messages.cancelDeployment)}
|
||||||
buttonIconClass="fa fa-ban"
|
buttonIconClass="fa fa-ban"
|
||||||
deleteStack={deleteStack}
|
deleteStack={deleteStack}
|
||||||
|
@ -83,12 +84,14 @@ class DeploymentProgress extends React.Component {
|
||||||
loaderContent={formatMessage(messages.requestingDeletion)}
|
loaderContent={formatMessage(messages.requestingDeletion)}
|
||||||
stack={stack}
|
stack={stack}
|
||||||
/>
|
/>
|
||||||
: null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<span><FormattedMessage {...messages.deploymentInProgress} /> </span>
|
<span>
|
||||||
|
<FormattedMessage {...messages.deploymentInProgress} />{' '}
|
||||||
|
</span>
|
||||||
<Link to={`/plans/${currentPlanName}/deployment-detail`}>
|
<Link to={`/plans/${currentPlanName}/deployment-detail`}>
|
||||||
<FormattedMessage {...messages.viewInformation} />
|
<FormattedMessage {...messages.viewInformation} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
@ -41,7 +41,8 @@ const messages = defineMessages({
|
||||||
availableNodesCount: {
|
availableNodesCount: {
|
||||||
id: 'RoleCard.availableNodesCount',
|
id: 'RoleCard.availableNodesCount',
|
||||||
defaultMessage: 'of {count, number}',
|
defaultMessage: 'of {count, number}',
|
||||||
description: 'Used to display available nodes to assign, e.g. 1 of 2 Nodes Assigned'
|
description:
|
||||||
|
'Used to display available nodes to assign, e.g. 1 of 2 Nodes Assigned'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,21 +81,23 @@ const RoleCard = ({
|
||||||
<div className="card-pf-body">
|
<div className="card-pf-body">
|
||||||
<div className="card-pf-utilization-details">
|
<div className="card-pf-utilization-details">
|
||||||
<div className="node-picker-cell">
|
<div className="node-picker-cell">
|
||||||
{assignedNodesCountParameter
|
{assignedNodesCountParameter ? (
|
||||||
? <Field
|
<Field
|
||||||
component={NodePickerInput}
|
component={NodePickerInput}
|
||||||
increment={1}
|
increment={1}
|
||||||
validate={validations}
|
validate={validations}
|
||||||
name={assignedNodesCountParameter.name}
|
name={assignedNodesCountParameter.name}
|
||||||
max={availableNodesCount}
|
max={availableNodesCount}
|
||||||
/>
|
/>
|
||||||
: <NodePickerInput
|
) : (
|
||||||
increment={1}
|
<NodePickerInput
|
||||||
input={{ value: '-' }}
|
increment={1}
|
||||||
meta={{ submitting: true }}
|
input={{ value: '-' }}
|
||||||
max={availableNodesCount}
|
meta={{ submitting: true }}
|
||||||
min={0}
|
max={availableNodesCount}
|
||||||
/>}
|
min={0}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="card-pf-utilization-card-details-description">
|
<span className="card-pf-utilization-card-details-description">
|
||||||
<span className="card-pf-utilization-card-details-line-1">
|
<span className="card-pf-utilization-card-details-line-1">
|
||||||
|
|
|
@ -23,8 +23,7 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { CloseModalButton } from '../ui/Modals';
|
import { CloseModalButton } from '../ui/Modals';
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../actions/EnvironmentConfigurationActions';
|
||||||
from '../../actions/EnvironmentConfigurationActions';
|
|
||||||
import EnvironmentConfigurationTopic from './EnvironmentConfigurationTopic';
|
import EnvironmentConfigurationTopic from './EnvironmentConfigurationTopic';
|
||||||
import { getCurrentPlanName } from '../../selectors/plans';
|
import { getCurrentPlanName } from '../../selectors/plans';
|
||||||
import ModalFormErrorList from '../ui/forms/ModalFormErrorList';
|
import ModalFormErrorList from '../ui/forms/ModalFormErrorList';
|
||||||
|
@ -208,9 +207,7 @@ class EnvironmentConfiguration extends React.Component {
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-8">
|
<div className="col-sm-8">
|
||||||
<div className="tab-content">
|
<div className="tab-content">{topics}</div>
|
||||||
{topics}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -293,10 +290,10 @@ export default injectIntl(
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* requiresEnvironments validation
|
* requiresEnvironments validation
|
||||||
* Invalidates input if it is selected and environment it requires is not.
|
* Invalidates input if it is selected and environment it requires is not.
|
||||||
* example: validations="requiredEnvironments:['some_environment.yaml']"
|
* example: validations="requiredEnvironments:['some_environment.yaml']"
|
||||||
*/
|
*/
|
||||||
Formsy.addValidationRule('requiredEnvironments', function(
|
Formsy.addValidationRule('requiredEnvironments', function(
|
||||||
values,
|
values,
|
||||||
value,
|
value,
|
||||||
|
|
|
@ -40,7 +40,11 @@ export default class EnvironmentConfigurationTopic extends React.Component {
|
||||||
const { description } = this.props;
|
const { description } = this.props;
|
||||||
return (
|
return (
|
||||||
<fieldset className="environment-topic">
|
<fieldset className="environment-topic">
|
||||||
{description && <p><i>{description}</i></p>}
|
{description && (
|
||||||
|
<p>
|
||||||
|
<i>{description}</i>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{environmentGroups}
|
{environmentGroups}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
);
|
);
|
||||||
|
|
|
@ -139,7 +139,8 @@ class EnvironmentGroupHeading extends React.Component {
|
||||||
if (this.props.title) {
|
if (this.props.title) {
|
||||||
return (
|
return (
|
||||||
<h4>
|
<h4>
|
||||||
{this.props.title}<br />
|
{this.props.title}
|
||||||
|
<br />
|
||||||
<small>{this.props.description}</small>
|
<small>{this.props.description}</small>
|
||||||
</h4>
|
</h4>
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,15 +40,15 @@ class I18nDropdown extends React.Component {
|
||||||
return languages
|
return languages
|
||||||
.map((langName, langKey) => {
|
.map((langName, langKey) => {
|
||||||
const active = currentLanguage === langKey;
|
const active = currentLanguage === langKey;
|
||||||
return MESSAGES[langKey] || langKey === 'en'
|
return MESSAGES[langKey] || langKey === 'en' ? (
|
||||||
? <DropdownItem
|
<DropdownItem
|
||||||
key={`lang-${langKey}`}
|
key={`lang-${langKey}`}
|
||||||
active={active}
|
active={active}
|
||||||
onClick={this.props.chooseLanguage.bind(this, langKey)}
|
onClick={this.props.chooseLanguage.bind(this, langKey)}
|
||||||
>
|
>
|
||||||
{langName}
|
{langName}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
: null;
|
) : null;
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
id: 'Login.description',
|
id: 'Login.description',
|
||||||
defaultMessage: 'This tool will walk you through the process of configuring and ' +
|
defaultMessage:
|
||||||
|
'This tool will walk you through the process of configuring and ' +
|
||||||
'deploying an OpenStack environment.'
|
'deploying an OpenStack environment.'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -183,7 +184,9 @@ class Login extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="col-sm-5 col-md-6 col-lg-7 details">
|
<div className="col-sm-5 col-md-6 col-lg-7 details">
|
||||||
<p>
|
<p>
|
||||||
<strong><FormattedMessage {...messages.welcome} /></strong>
|
<strong>
|
||||||
|
<FormattedMessage {...messages.welcome} />
|
||||||
|
</strong>
|
||||||
<br />
|
<br />
|
||||||
<FormattedMessage {...messages.description} />
|
<FormattedMessage {...messages.description} />
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -89,23 +89,37 @@ const NodeDrive = ({ drive }) => {
|
||||||
<Row>
|
<Row>
|
||||||
<Col sm={11}>
|
<Col sm={11}>
|
||||||
<dl className="dl-horizontal">
|
<dl className="dl-horizontal">
|
||||||
<dt><FormattedMessage {...messages.model} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.model} />
|
||||||
|
</dt>
|
||||||
<dd>{drive.model || <FormattedMessage {...messages.na} />}</dd>
|
<dd>{drive.model || <FormattedMessage {...messages.na} />}</dd>
|
||||||
<dt><FormattedMessage {...messages.serial} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.serial} />
|
||||||
|
</dt>
|
||||||
<dd>{drive.serial || <FormattedMessage {...messages.na} />}</dd>
|
<dd>{drive.serial || <FormattedMessage {...messages.na} />}</dd>
|
||||||
<dt><FormattedMessage {...messages.vendor} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.vendor} />
|
||||||
|
</dt>
|
||||||
<dd>{drive.vendor || <FormattedMessage {...messages.na} />}</dd>
|
<dd>{drive.vendor || <FormattedMessage {...messages.na} />}</dd>
|
||||||
<dt><FormattedMessage {...messages.wwn} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.wwn} />
|
||||||
|
</dt>
|
||||||
<dd>{drive.wwn || <FormattedMessage {...messages.na} />}</dd>
|
<dd>{drive.wwn || <FormattedMessage {...messages.na} />}</dd>
|
||||||
<dt><FormattedMessage {...messages.wwnVendorExtension} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.wwnVendorExtension} />
|
||||||
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{drive.wwn_vendor_extension ||
|
{drive.wwn_vendor_extension || (
|
||||||
<FormattedMessage {...messages.na} />}
|
<FormattedMessage {...messages.na} />
|
||||||
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
<dt><FormattedMessage {...messages.wwnWithExtension} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.wwnWithExtension} />
|
||||||
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{drive.wwn_with_extension ||
|
{drive.wwn_with_extension || (
|
||||||
<FormattedMessage {...messages.na} />}
|
<FormattedMessage {...messages.na} />
|
||||||
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -67,15 +67,17 @@ class Nodes extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContentView() {
|
renderContentView() {
|
||||||
return this.props.contentView === 'table'
|
return this.props.contentView === 'table' ? (
|
||||||
? <NodesTableView />
|
<NodesTableView />
|
||||||
: <NodesListForm>
|
) : (
|
||||||
<NodesListView
|
<NodesListForm>
|
||||||
fetchNodeIntrospectionData={this.props.fetchNodeIntrospectionData}
|
<NodesListView
|
||||||
nodes={this.props.nodes}
|
fetchNodeIntrospectionData={this.props.fetchNodeIntrospectionData}
|
||||||
nodesInProgress={this.props.nodesInProgress}
|
nodes={this.props.nodes}
|
||||||
/>
|
nodesInProgress={this.props.nodesInProgress}
|
||||||
</NodesListForm>;
|
/>
|
||||||
|
</NodesListForm>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -107,7 +109,9 @@ class Nodes extends React.Component {
|
||||||
<FormattedMessage {...messages.registerNodes} />
|
<FormattedMessage {...messages.registerNodes} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<h1><FormattedMessage {...messages.nodes} /></h1>
|
<h1>
|
||||||
|
<FormattedMessage {...messages.nodes} />
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<Loader
|
<Loader
|
||||||
loaded={this.props.nodesLoaded}
|
loaded={this.props.nodesLoaded}
|
||||||
|
|
|
@ -103,26 +103,29 @@ class NodeExtendedInfo extends React.Component {
|
||||||
if (node.getIn(['introspectionData', 'interfaces']).isEmpty()) {
|
if (node.getIn(['introspectionData', 'interfaces']).isEmpty()) {
|
||||||
return (
|
return (
|
||||||
<dl>
|
<dl>
|
||||||
<dt><FormattedMessage {...messages.macAddresses} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.macAddresses} />
|
||||||
|
</dt>
|
||||||
{node.get('macs').map(mac => <dd key={mac}>{mac}</dd>)}
|
{node.get('macs').map(mac => <dd key={mac}>{mac}</dd>)}
|
||||||
</dl>
|
</dl>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<dl>
|
<dl>
|
||||||
<dt><FormattedMessage {...messages.interfaces} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.interfaces} />
|
||||||
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{node
|
{node
|
||||||
.getIn(['introspectionData', 'interfaces'])
|
.getIn(['introspectionData', 'interfaces'])
|
||||||
.map((ifc, k) => {
|
.map((ifc, k) => {
|
||||||
return (
|
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>
|
||||||
|
@ -140,58 +143,71 @@ class NodeExtendedInfo extends React.Component {
|
||||||
renderBios() {
|
renderBios() {
|
||||||
const bios = this.props.node.getIn(['introspectionData', 'bios']);
|
const bios = this.props.node.getIn(['introspectionData', 'bios']);
|
||||||
return (
|
return (
|
||||||
!bios.isEmpty() &&
|
!bios.isEmpty() && (
|
||||||
<div>
|
<div>
|
||||||
<dt><FormattedMessage {...messages.bios} /></dt>
|
<dt>
|
||||||
<dd className="NodeExtendedInfo__bios">
|
<FormattedMessage {...messages.bios} />
|
||||||
{bios
|
</dt>
|
||||||
.map((i, k) => <span key={k} title={startCase(k)}>{i} </span>)
|
<dd className="NodeExtendedInfo__bios">
|
||||||
.toList()}
|
{bios
|
||||||
</dd>
|
.map((i, k) => (
|
||||||
</div>
|
<span key={k} title={startCase(k)}>
|
||||||
|
{i}{' '}
|
||||||
|
</span>
|
||||||
|
))
|
||||||
|
.toList()}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRootDisk() {
|
renderRootDisk() {
|
||||||
const rootDisk = this.props.node.getIn(['introspectionData', 'rootDisk']);
|
const rootDisk = this.props.node.getIn(['introspectionData', 'rootDisk']);
|
||||||
return (
|
return (
|
||||||
rootDisk &&
|
rootDisk && (
|
||||||
<div>
|
<div>
|
||||||
<dt><FormattedMessage {...messages.rootDisk} /></dt>
|
<dt>
|
||||||
<dd className="NodeExtendedInfo__rootDisk">{rootDisk}</dd>
|
<FormattedMessage {...messages.rootDisk} />
|
||||||
</div>
|
</dt>
|
||||||
|
<dd className="NodeExtendedInfo__rootDisk">{rootDisk}</dd>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProduct() {
|
renderProduct() {
|
||||||
const product = this.props.node.getIn(['introspectionData', 'product']);
|
const product = this.props.node.getIn(['introspectionData', 'product']);
|
||||||
return (
|
return (
|
||||||
!product.isEmpty() &&
|
!product.isEmpty() && (
|
||||||
<div>
|
<div>
|
||||||
<dt><FormattedMessage {...messages.product} /></dt>
|
<dt>
|
||||||
<dd>
|
<FormattedMessage {...messages.product} />
|
||||||
<span
|
</dt>
|
||||||
className="NodeExtendedInfo__productName"
|
<dd>
|
||||||
title={this.props.intl.formatMessage(messages.productName)}
|
<span
|
||||||
>
|
className="NodeExtendedInfo__productName"
|
||||||
{product.get('name')}
|
title={this.props.intl.formatMessage(messages.productName)}
|
||||||
</span>
|
>
|
||||||
{' '} - {' '}
|
{product.get('name')}
|
||||||
<span
|
</span>{' '}
|
||||||
className="NodeExtendedInfo__productVendor"
|
-{' '}
|
||||||
title={this.props.intl.formatMessage(messages.productVendor)}
|
<span
|
||||||
>
|
className="NodeExtendedInfo__productVendor"
|
||||||
{product.get('vendor')}
|
title={this.props.intl.formatMessage(messages.productVendor)}
|
||||||
</span>
|
>
|
||||||
{' '} | {' '}
|
{product.get('vendor')}
|
||||||
<span
|
</span>{' '}
|
||||||
className="NodeExtendedInfo__productVersion"
|
|{' '}
|
||||||
title={this.props.intl.formatMessage(messages.productVersion)}
|
<span
|
||||||
>
|
className="NodeExtendedInfo__productVersion"
|
||||||
{product.get('version')}
|
title={this.props.intl.formatMessage(messages.productVersion)}
|
||||||
</span>
|
>
|
||||||
</dd>
|
{product.get('version')}
|
||||||
</div>
|
</span>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,13 +217,14 @@ class NodeExtendedInfo extends React.Component {
|
||||||
'kernelVersion'
|
'kernelVersion'
|
||||||
]);
|
]);
|
||||||
return (
|
return (
|
||||||
kernelVersion &&
|
kernelVersion && (
|
||||||
<div>
|
<div>
|
||||||
<dt><FormattedMessage {...messages.kernel} /></dt>
|
<dt>
|
||||||
<dd className="NodeExtendedInfo__kernelVersion">
|
<FormattedMessage {...messages.kernel} />
|
||||||
{kernelVersion}
|
</dt>
|
||||||
</dd>
|
<dd className="NodeExtendedInfo__kernelVersion">{kernelVersion}</dd>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,15 +234,21 @@ class NodeExtendedInfo extends React.Component {
|
||||||
<Row className="NodeExtendedInfo__extendedInfoRow">
|
<Row className="NodeExtendedInfo__extendedInfoRow">
|
||||||
<Col lg={4} md={6}>
|
<Col lg={4} md={6}>
|
||||||
<dl className="dl-horizontal dl-horizontal-condensed">
|
<dl className="dl-horizontal dl-horizontal-condensed">
|
||||||
<dt><FormattedMessage {...messages.uuid} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.uuid} />
|
||||||
|
</dt>
|
||||||
<dd className="NodeExtendedInfo__uuid">{node.get('uuid')}</dd>
|
<dd className="NodeExtendedInfo__uuid">{node.get('uuid')}</dd>
|
||||||
<dt><FormattedMessage {...messages.registered} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.registered} />
|
||||||
|
</dt>
|
||||||
<dd className="NodeExtendedInfo__registered">
|
<dd className="NodeExtendedInfo__registered">
|
||||||
<FormattedDate value={node.get('created_at')} />
|
<FormattedDate value={node.get('created_at')} />
|
||||||
|
|
||||||
<FormattedTime value={node.get('created_at')} />
|
<FormattedTime value={node.get('created_at')} />
|
||||||
</dd>
|
</dd>
|
||||||
<dt><FormattedMessage {...messages.architecture} /></dt>
|
<dt>
|
||||||
|
<FormattedMessage {...messages.architecture} />
|
||||||
|
</dt>
|
||||||
<dd className="NodeExtendedInfo__architecture">
|
<dd className="NodeExtendedInfo__architecture">
|
||||||
{node.getIn(['properties', 'cpu_arch'])}
|
{node.getIn(['properties', 'cpu_arch'])}
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -237,10 +260,10 @@ class NodeExtendedInfo extends React.Component {
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg={4} md={6}>
|
<Col lg={4} md={6}>
|
||||||
<dl className="dl-horizontal dl-horizontal-condensed">
|
<dl className="dl-horizontal dl-horizontal-condensed">
|
||||||
<dt><FormattedMessage {...messages.driver} /></dt>
|
<dt>
|
||||||
<dd className="NodeExtendedInfo__driver">
|
<FormattedMessage {...messages.driver} />
|
||||||
{node.get('driver')}
|
</dt>
|
||||||
</dd>
|
<dd className="NodeExtendedInfo__driver">{node.get('driver')}</dd>
|
||||||
{node
|
{node
|
||||||
.get('driver_info')
|
.get('driver_info')
|
||||||
.map((dInfo, key) => (
|
.map((dInfo, key) => (
|
||||||
|
|
|
@ -75,12 +75,13 @@ export const NodeListItem = ({
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
node.getIn(['introspectionStatus', 'state']) === 'finished' &&
|
node.getIn(['introspectionStatus', 'state']) === 'finished' && (
|
||||||
<DropdownKebab id={`${node.get('uuid')}Actions`} pullRight>
|
<DropdownKebab id={`${node.get('uuid')}Actions`} pullRight>
|
||||||
<MenuItemLink to={`/nodes/${node.get('uuid')}/drives`}>
|
<MenuItemLink to={`/nodes/${node.get('uuid')}/drives`}>
|
||||||
<FormattedMessage {...messages.manageDrives} />
|
<FormattedMessage {...messages.manageDrives} />
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
</DropdownKebab>
|
</DropdownKebab>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
leftContent={
|
leftContent={
|
||||||
<ListViewIcon
|
<ListViewIcon
|
||||||
|
@ -137,9 +138,7 @@ export const NodeListItem = ({
|
||||||
</ListViewInfoItem>,
|
</ListViewInfoItem>,
|
||||||
<ListViewInfoItem key="memory" className="NodeListItem__memorySize">
|
<ListViewInfoItem key="memory" className="NodeListItem__memorySize">
|
||||||
<span className="pficon pficon-memory" />
|
<span className="pficon pficon-memory" />
|
||||||
<strong>
|
<strong>{node.getIn(['properties', 'memory_mb'], '-')}</strong>
|
||||||
{node.getIn(['properties', 'memory_mb'], '-')}
|
|
||||||
</strong>
|
|
||||||
|
|
||||||
<FormattedMessage {...messages.ram} />
|
<FormattedMessage {...messages.ram} />
|
||||||
</ListViewInfoItem>,
|
</ListViewInfoItem>,
|
||||||
|
|
|
@ -85,16 +85,17 @@ export const NodeProvisionState = ({
|
||||||
...rest
|
...rest
|
||||||
}) => (
|
}) => (
|
||||||
<span {...rest}>
|
<span {...rest}>
|
||||||
<strong><FormattedMessage {...messages.provisionState} /></strong>
|
<strong>
|
||||||
{targetProvisionState
|
<FormattedMessage {...messages.provisionState} />
|
||||||
? <span>
|
</strong>
|
||||||
{provisionState}
|
{targetProvisionState ? (
|
||||||
{' '}
|
<span>
|
||||||
<span className="fa fa-long-arrow-right" />
|
{provisionState} <span className="fa fa-long-arrow-right" />{' '}
|
||||||
{' '}
|
{targetProvisionState}
|
||||||
{targetProvisionState}
|
</span>
|
||||||
</span>
|
) : (
|
||||||
: provisionState}
|
provisionState
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
NodeProvisionState.propTypes = {
|
NodeProvisionState.propTypes = {
|
||||||
|
@ -107,7 +108,9 @@ export const NodeIntrospectionStatus = ({
|
||||||
...rest
|
...rest
|
||||||
}) => (
|
}) => (
|
||||||
<span title={error} {...rest}>
|
<span title={error} {...rest}>
|
||||||
<strong><FormattedMessage {...messages.introspectionState} /></strong>
|
<strong>
|
||||||
|
<FormattedMessage {...messages.introspectionState} />
|
||||||
|
</strong>
|
||||||
{state}
|
{state}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,7 +32,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
operationInProgress: {
|
operationInProgress: {
|
||||||
id: 'NodesListForm.operationInProgressValidationMessage',
|
id: 'NodesListForm.operationInProgressValidationMessage',
|
||||||
defaultMessage: 'There is an operation in progress on some of the selected Nodes'
|
defaultMessage:
|
||||||
|
'There is an operation in progress on some of the selected Nodes'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -303,11 +303,7 @@ export default injectIntl(NodesTable);
|
||||||
|
|
||||||
export const NodesTableMaintenanceCell = props => {
|
export const NodesTableMaintenanceCell = props => {
|
||||||
const value = _.result(props.data[props.rowIndex], props.field).toString();
|
const value = _.result(props.data[props.rowIndex], props.field).toString();
|
||||||
return (
|
return <DataTableCell {...props}>{value}</DataTableCell>;
|
||||||
<DataTableCell {...props}>
|
|
||||||
{value}
|
|
||||||
</DataTableCell>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
NodesTableMaintenanceCell.propTypes = {
|
NodesTableMaintenanceCell.propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
|
@ -317,11 +313,7 @@ NodesTableMaintenanceCell.propTypes = {
|
||||||
|
|
||||||
export const NodesTableMacsCell = props => {
|
export const NodesTableMacsCell = props => {
|
||||||
const value = _.result(props.data[props.rowIndex], props.field).join(', ');
|
const value = _.result(props.data[props.rowIndex], props.field).join(', ');
|
||||||
return (
|
return <DataTableCell {...props}>{value}</DataTableCell>;
|
||||||
<DataTableCell {...props}>
|
|
||||||
{value}
|
|
||||||
</DataTableCell>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
NodesTableMacsCell.propTypes = {
|
NodesTableMacsCell.propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -47,7 +47,8 @@ const messages = defineMessages({
|
||||||
provideNodes: {
|
provideNodes: {
|
||||||
id: 'NodesTableView.provideNodes',
|
id: 'NodesTableView.provideNodes',
|
||||||
defaultMessage: 'Provide Nodes',
|
defaultMessage: 'Provide Nodes',
|
||||||
description: '"Providing" the nodes changes the provisioning state to "available" so that ' +
|
description:
|
||||||
|
'"Providing" the nodes changes the provisioning state to "available" so that ' +
|
||||||
'they can be used in a deployment.'
|
'they can be used in a deployment.'
|
||||||
},
|
},
|
||||||
deleteNodes: {
|
deleteNodes: {
|
||||||
|
@ -238,7 +239,8 @@ class NodesTableView extends React.Component {
|
||||||
availableProfiles={this.props.availableProfiles.toArray()}
|
availableProfiles={this.props.availableProfiles.toArray()}
|
||||||
onProfileSelected={this.onTagNodesSubmit.bind(this)}
|
onProfileSelected={this.onTagNodesSubmit.bind(this)}
|
||||||
onCancel={() =>
|
onCancel={() =>
|
||||||
this.setState({ showTagNodesModal: false, submitParameters: {} })}
|
this.setState({ showTagNodesModal: false, submitParameters: {} })
|
||||||
|
}
|
||||||
show={this.state.showTagNodesModal}
|
show={this.state.showTagNodesModal}
|
||||||
/>
|
/>
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
|
|
|
@ -60,7 +60,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
nonFilteredToolbarResults: {
|
nonFilteredToolbarResults: {
|
||||||
id: 'NodesToolbar.nonFilteredToolbarResults',
|
id: 'NodesToolbar.nonFilteredToolbarResults',
|
||||||
defaultMessage: '{totalCount, number} {totalCount, plural, one {Node} other {Nodes}}'
|
defaultMessage:
|
||||||
|
'{totalCount, number} {totalCount, plural, one {Node} other {Nodes}}'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,7 +90,8 @@ class NodesToolbar extends React.Component {
|
||||||
id="NodesToolbar_toolbarFiltersForm"
|
id="NodesToolbar_toolbarFiltersForm"
|
||||||
form="nodesToolbarFilter"
|
form="nodesToolbarFilter"
|
||||||
formatSelectValue={value =>
|
formatSelectValue={value =>
|
||||||
intl.formatMessage(nodeColumnMessages[value])}
|
intl.formatMessage(nodeColumnMessages[value])
|
||||||
|
}
|
||||||
initialValues={{ filterBy: 'name' }}
|
initialValues={{ filterBy: 'name' }}
|
||||||
onSubmit={addActiveFilter}
|
onSubmit={addActiveFilter}
|
||||||
options={{
|
options={{
|
||||||
|
|
|
@ -36,7 +36,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
disabledButtonsWarning: {
|
disabledButtonsWarning: {
|
||||||
id: 'NodesToolbarActions.disabledButtonsWarning',
|
id: 'NodesToolbarActions.disabledButtonsWarning',
|
||||||
defaultMessage: 'You need to select Nodes first, or there is an operation already in ' +
|
defaultMessage:
|
||||||
|
'You need to select Nodes first, or there is an operation already in ' +
|
||||||
'progress on some of the selected Nodes.'
|
'progress on some of the selected Nodes.'
|
||||||
},
|
},
|
||||||
introspectNodes: {
|
introspectNodes: {
|
||||||
|
@ -50,13 +51,15 @@ const messages = defineMessages({
|
||||||
provideNodes: {
|
provideNodes: {
|
||||||
id: 'NodesToolbarActions.provideNodes',
|
id: 'NodesToolbarActions.provideNodes',
|
||||||
defaultMessage: 'Provide Nodes',
|
defaultMessage: 'Provide Nodes',
|
||||||
description: '"Providing" the nodes changes the provisioning state to "available" so that ' +
|
description:
|
||||||
|
'"Providing" the nodes changes the provisioning state to "available" so that ' +
|
||||||
'they can be used in a deployment.'
|
'they can be used in a deployment.'
|
||||||
},
|
},
|
||||||
manageNodes: {
|
manageNodes: {
|
||||||
id: 'NodesToolbarActions.manageNodes',
|
id: 'NodesToolbarActions.manageNodes',
|
||||||
defaultMessage: 'Manage Nodes',
|
defaultMessage: 'Manage Nodes',
|
||||||
description: '"Managing" the nodes changes the provisioning state to "manageable" so that ' +
|
description:
|
||||||
|
'"Managing" the nodes changes the provisioning state to "manageable" so that ' +
|
||||||
'they can be introspected.'
|
'they can be introspected.'
|
||||||
},
|
},
|
||||||
deleteNodes: {
|
deleteNodes: {
|
||||||
|
@ -98,68 +101,64 @@ class NodesToolbarActions extends React.Component {
|
||||||
// TODO(jtomasek): include proper error message from the form accessed via getFormSyncErrors
|
// TODO(jtomasek): include proper error message from the form accessed via getFormSyncErrors
|
||||||
// selector once the 'error' is available via selector
|
// selector once the 'error' is available via selector
|
||||||
// https://github.com/erikras/redux-form/issues/2872
|
// https://github.com/erikras/redux-form/issues/2872
|
||||||
(
|
<FormGroup
|
||||||
<FormGroup
|
title={
|
||||||
title={
|
disabled ? intl.formatMessage(messages.disabledButtonsWarning) : ''
|
||||||
disabled ? intl.formatMessage(messages.disabledButtonsWarning) : ''
|
}
|
||||||
}
|
>
|
||||||
|
<Button
|
||||||
|
id="NodesToolbarActions__introspectNodesAction"
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
onClick={this.submitForm.bind(this, 'introspect')}
|
||||||
>
|
>
|
||||||
<Button
|
<FormattedMessage {...messages.introspectNodes} />
|
||||||
id="NodesToolbarActions__introspectNodesAction"
|
</Button>
|
||||||
|
<Button
|
||||||
|
id="NodesToolbarActions__provideNodesAction"
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
onClick={this.submitForm.bind(this, 'provide')}
|
||||||
|
>
|
||||||
|
<FormattedMessage {...messages.provideNodes} />
|
||||||
|
</Button>
|
||||||
|
<DropdownKebab id="NodesToolbarActions__nodesActionsKebab" pullRight>
|
||||||
|
<MenuItem
|
||||||
|
id="NodesToolbarActions__manageNodesAction"
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
onClick={this.submitForm.bind(this, 'introspect')}
|
onSelect={this.submitForm.bind(this, 'manage')}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.introspectNodes} />
|
<FormattedMessage {...messages.manageNodes} />
|
||||||
</Button>
|
</MenuItem>
|
||||||
<Button
|
<MenuItem
|
||||||
id="NodesToolbarActions__provideNodesAction"
|
id="NodesToolbarActions__tagNodesAction"
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
onClick={this.submitForm.bind(this, 'provide')}
|
onSelect={() => this.setState({ showTagNodesModal: true })}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.provideNodes} />
|
<FormattedMessage {...messages.tagNodes} />
|
||||||
</Button>
|
</MenuItem>
|
||||||
<DropdownKebab id="NodesToolbarActions__nodesActionsKebab" pullRight>
|
<MenuItem
|
||||||
<MenuItem
|
id="NodesToolbarActions__deleteNodesAction"
|
||||||
id="NodesToolbarActions__manageNodesAction"
|
className="bg-danger"
|
||||||
disabled={this.props.disabled}
|
disabled={this.props.disabled}
|
||||||
onSelect={this.submitForm.bind(this, 'manage')}
|
onSelect={() => this.setState({ showDeleteModal: true })}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.manageNodes} />
|
<FormattedMessage {...messages.deleteNodes} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
</DropdownKebab>
|
||||||
id="NodesToolbarActions__tagNodesAction"
|
<ConfirmationModal
|
||||||
disabled={this.props.disabled}
|
show={this.state.showDeleteModal}
|
||||||
onSelect={() => this.setState({ showTagNodesModal: true })}
|
title={this.props.intl.formatMessage(messages.deleteNodesModalTitle)}
|
||||||
>
|
question={this.props.intl.formatMessage(
|
||||||
<FormattedMessage {...messages.tagNodes} />
|
messages.deleteNodesModalMessage
|
||||||
</MenuItem>
|
)}
|
||||||
<MenuItem
|
onConfirm={() => this.deleteNodes('delete')}
|
||||||
id="NodesToolbarActions__deleteNodesAction"
|
onCancel={() => this.setState({ showDeleteModal: false })}
|
||||||
className="bg-danger"
|
/>
|
||||||
disabled={this.props.disabled}
|
<TagNodesModal
|
||||||
onSelect={() => this.setState({ showDeleteModal: true })}
|
onProfileSelected={this.tagNodes.bind(this)}
|
||||||
>
|
onCancel={() => this.setState({ showTagNodesModal: false })}
|
||||||
<FormattedMessage {...messages.deleteNodes} />
|
show={this.state.showTagNodesModal}
|
||||||
</MenuItem>
|
/>
|
||||||
</DropdownKebab>
|
</FormGroup>
|
||||||
<ConfirmationModal
|
|
||||||
show={this.state.showDeleteModal}
|
|
||||||
title={this.props.intl.formatMessage(
|
|
||||||
messages.deleteNodesModalTitle
|
|
||||||
)}
|
|
||||||
question={this.props.intl.formatMessage(
|
|
||||||
messages.deleteNodesModalMessage
|
|
||||||
)}
|
|
||||||
onConfirm={() => this.deleteNodes('delete')}
|
|
||||||
onCancel={() => this.setState({ showDeleteModal: false })}
|
|
||||||
/>
|
|
||||||
<TagNodesModal
|
|
||||||
onProfileSelected={this.tagNodes.bind(this)}
|
|
||||||
onCancel={() => this.setState({ showTagNodesModal: false })}
|
|
||||||
show={this.state.showTagNodesModal}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,7 @@ const NodeTab = ({
|
||||||
}) => (
|
}) => (
|
||||||
<Tab isActive={isActive}>
|
<Tab isActive={isActive}>
|
||||||
<a className="link" onClick={selectNode}>
|
<a className="link" onClick={selectNode}>
|
||||||
<span className={cx('pficon', { 'pficon-error-circle-o': invalid })} />
|
<span className={cx('pficon', { 'pficon-error-circle-o': invalid })} />{' '}
|
||||||
{' '}
|
|
||||||
{node.name ||
|
{node.name ||
|
||||||
(node.pm_addr &&
|
(node.pm_addr &&
|
||||||
node.pm_addr + (node.pm_port ? `:${node.pm_port}` : '')) ||
|
node.pm_addr + (node.pm_port ? `:${node.pm_port}` : '')) ||
|
||||||
|
|
|
@ -35,7 +35,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
nodeNameRegexp: {
|
nodeNameRegexp: {
|
||||||
id: 'RegisterNodeForm.nodeNameRegexp',
|
id: 'RegisterNodeForm.nodeNameRegexp',
|
||||||
defaultMessage: 'Name may only consist of RFC3986 unreserved characters: alphanumeric, hyphen (-),' +
|
defaultMessage:
|
||||||
|
'Name may only consist of RFC3986 unreserved characters: alphanumeric, hyphen (-),' +
|
||||||
' period (.), underscore (_) and tilde (~) characters.'
|
' period (.), underscore (_) and tilde (~) characters.'
|
||||||
},
|
},
|
||||||
nodeNameMaxLength: {
|
nodeNameMaxLength: {
|
||||||
|
@ -92,7 +93,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
macAddressesDescription: {
|
macAddressesDescription: {
|
||||||
id: 'RegisterNodeForm.macAddressesDescription',
|
id: 'RegisterNodeForm.macAddressesDescription',
|
||||||
defaultMessage: 'If you are specifying multiple MAC Addresses, please enter a comma separated list. (e.g. aa:bb:cc:dd:ee:ff,12:34:56:78:90:xx,do:re:mi:fa:so:ra)'
|
defaultMessage:
|
||||||
|
'If you are specifying multiple MAC Addresses, please enter a comma separated list. (e.g. aa:bb:cc:dd:ee:ff,12:34:56:78:90:xx,do:re:mi:fa:so:ra)'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -114,7 +116,9 @@ const RegisterNodeFields = ({
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h4><FormattedMessage {...messages.nodeDetail} /></h4>
|
<h4>
|
||||||
|
<FormattedMessage {...messages.nodeDetail} />
|
||||||
|
</h4>
|
||||||
<Fieldset legend={formatMessage(messages.general)}>
|
<Fieldset legend={formatMessage(messages.general)}>
|
||||||
<Field
|
<Field
|
||||||
name={`${node}.name`}
|
name={`${node}.name`}
|
||||||
|
|
|
@ -203,8 +203,7 @@ class RegisterNodesDialog extends React.Component {
|
||||||
<div className="col-sm-4 col-lg-3 sidebar-pf sidebar-pf-left">
|
<div className="col-sm-4 col-lg-3 sidebar-pf sidebar-pf-left">
|
||||||
<div className="nav-stacked-actions">
|
<div className="nav-stacked-actions">
|
||||||
<Button onClick={e => this.addNode()}>
|
<Button onClick={e => this.addNode()}>
|
||||||
<span className="fa fa-plus" />
|
<span className="fa fa-plus" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.addNew} />
|
<FormattedMessage {...messages.addNew} />
|
||||||
</Button>
|
</Button>
|
||||||
<FormattedMessage {...messages.or} />
|
<FormattedMessage {...messages.or} />
|
||||||
|
@ -268,9 +267,11 @@ function mapStateToProps(state) {
|
||||||
syncErrors: getFormSyncErrors('registerNodesForm')(state),
|
syncErrors: getFormSyncErrors('registerNodesForm')(state),
|
||||||
invalid: isInvalid('registerNodesForm')(state),
|
invalid: isInvalid('registerNodesForm')(state),
|
||||||
pristine: isPristine('registerNodesForm')(state),
|
pristine: isPristine('registerNodesForm')(state),
|
||||||
nodesToRegister: (getFormValues('registerNodesForm')(state) || {
|
nodesToRegister: (
|
||||||
nodes: []
|
getFormValues('registerNodesForm')(state) || {
|
||||||
}).nodes,
|
nodes: []
|
||||||
|
}
|
||||||
|
).nodes,
|
||||||
submitting: isSubmitting('registerNodesForm')(state)
|
submitting: isSubmitting('registerNodesForm')(state)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,22 +66,23 @@ const RegisterNodesForm = ({
|
||||||
selectedNodeIndex
|
selectedNodeIndex
|
||||||
}) => (
|
}) => (
|
||||||
<Form onSubmit={handleSubmit} horizontal>
|
<Form onSubmit={handleSubmit} horizontal>
|
||||||
{error &&
|
{error && <InlineNotification>{error}</InlineNotification>}
|
||||||
<InlineNotification>
|
{selectedNodeIndex !== -1 ? (
|
||||||
{error}
|
<FieldArray
|
||||||
</InlineNotification>}
|
name="nodes"
|
||||||
{selectedNodeIndex !== -1
|
component={RegisterNodesTabPanes}
|
||||||
? <FieldArray
|
selectedNodeIndex={selectedNodeIndex}
|
||||||
name="nodes"
|
/>
|
||||||
component={RegisterNodesTabPanes}
|
) : (
|
||||||
selectedNodeIndex={selectedNodeIndex}
|
<BlankSlate
|
||||||
/>
|
iconClass="fa fa-cubes"
|
||||||
: <BlankSlate
|
title={formatMessage(messages.noNodesToRegister)}
|
||||||
iconClass="fa fa-cubes"
|
>
|
||||||
title={formatMessage(messages.noNodesToRegister)}
|
<p>
|
||||||
>
|
<FormattedMessage {...messages.addANodeManually} />
|
||||||
<p><FormattedMessage {...messages.addANodeManually} /></p>
|
</p>
|
||||||
</BlankSlate>}
|
</BlankSlate>
|
||||||
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
RegisterNodesForm.propTypes = {
|
RegisterNodesForm.propTypes = {
|
||||||
|
|
|
@ -34,7 +34,8 @@ const messages = defineMessages({
|
||||||
noRolesInfo: {
|
noRolesInfo: {
|
||||||
id: 'TagNodesForm.noRolesInfo',
|
id: 'TagNodesForm.noRolesInfo',
|
||||||
defaultMessage: '{link} to select profiles which match available Roles',
|
defaultMessage: '{link} to select profiles which match available Roles',
|
||||||
description: 'A second part of noRolesInfo message - rest of the text after link'
|
description:
|
||||||
|
'A second part of noRolesInfo message - rest of the text after link'
|
||||||
},
|
},
|
||||||
confirm: {
|
confirm: {
|
||||||
id: 'TagNodesForm.confirm',
|
id: 'TagNodesForm.confirm',
|
||||||
|
@ -104,7 +105,9 @@ class TagNodesForm extends React.Component {
|
||||||
return this.props.profiles
|
return this.props.profiles
|
||||||
.map((profile, index) => <option key={index}>{profile}</option>)
|
.map((profile, index) => <option key={index}>{profile}</option>)
|
||||||
.concat([
|
.concat([
|
||||||
<option key="spacer1" value="spacer" disabled>──────────</option>,
|
<option key="spacer1" value="spacer" disabled>
|
||||||
|
──────────
|
||||||
|
</option>,
|
||||||
<option key="noProfile" value="">
|
<option key="noProfile" value="">
|
||||||
{this.props.intl.formatMessage(messages.noProfileOption)}
|
{this.props.intl.formatMessage(messages.noProfileOption)}
|
||||||
</option>,
|
</option>,
|
||||||
|
@ -126,7 +129,7 @@ class TagNodesForm extends React.Component {
|
||||||
onInvalid={this.disableButton.bind(this)}
|
onInvalid={this.disableButton.bind(this)}
|
||||||
>
|
>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
{roles.isEmpty() &&
|
{roles.isEmpty() && (
|
||||||
<InlineNotification type="info">
|
<InlineNotification type="info">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
{...messages.noRolesInfo}
|
{...messages.noRolesInfo}
|
||||||
|
@ -138,7 +141,8 @@ class TagNodesForm extends React.Component {
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</InlineNotification>}
|
</InlineNotification>
|
||||||
|
)}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<HorizontalSelect
|
<HorizontalSelect
|
||||||
name="profile"
|
name="profile"
|
||||||
|
@ -149,22 +153,22 @@ class TagNodesForm extends React.Component {
|
||||||
>
|
>
|
||||||
{this.renderOptions()}
|
{this.renderOptions()}
|
||||||
</HorizontalSelect>
|
</HorizontalSelect>
|
||||||
{this.state.showCustomInput
|
{this.state.showCustomInput ? (
|
||||||
? <HorizontalInput
|
<HorizontalInput
|
||||||
name="customProfile"
|
name="customProfile"
|
||||||
title={formatMessage(messages.customProfileLabel)}
|
title={formatMessage(messages.customProfileLabel)}
|
||||||
type="text"
|
type="text"
|
||||||
inputColumnClasses="col-sm-7"
|
inputColumnClasses="col-sm-7"
|
||||||
labelColumnClasses="col-sm-3"
|
labelColumnClasses="col-sm-3"
|
||||||
value=""
|
value=""
|
||||||
validations={{ matchRegexp: /^[0-9a-z]+(-[0-9a-z]+)*$/ }}
|
validations={{ matchRegexp: /^[0-9a-z]+(-[0-9a-z]+)*$/ }}
|
||||||
validationError={formatMessage(
|
validationError={formatMessage(
|
||||||
messages.customProfileErrorMessage
|
messages.customProfileErrorMessage
|
||||||
)}
|
)}
|
||||||
description={formatMessage(messages.customProfileDescription)}
|
description={formatMessage(messages.customProfileDescription)}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
|
|
|
@ -54,8 +54,7 @@ class TagNodesModal extends React.Component {
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<CloseModalXButton />
|
<CloseModalXButton />
|
||||||
<ModalTitle>
|
<ModalTitle>
|
||||||
<span className="fa fa-tag" />
|
<span className="fa fa-tag" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.title} />
|
<FormattedMessage {...messages.title} />
|
||||||
</ModalTitle>
|
</ModalTitle>
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
|
|
|
@ -58,11 +58,7 @@ export default class Notification extends React.Component {
|
||||||
|
|
||||||
renderMessage(message) {
|
renderMessage(message) {
|
||||||
if (typeof message === 'object') {
|
if (typeof message === 'object') {
|
||||||
return (
|
return <ul>{message.map((msg, i) => <li key={i}>{msg}</li>)}</ul>;
|
||||||
<ul>
|
|
||||||
{message.map((msg, i) => <li key={i}>{msg}</li>)}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return <p>{message}</p>;
|
return <p>{message}</p>;
|
||||||
}
|
}
|
||||||
|
@ -90,16 +86,18 @@ export default class Notification extends React.Component {
|
||||||
<div className="clearfix">
|
<div className="clearfix">
|
||||||
<div className={classes} role="alert">
|
<div className={classes} role="alert">
|
||||||
<span className={iconClass} aria-hidden="true" />
|
<span className={iconClass} aria-hidden="true" />
|
||||||
{this.props.dismissable
|
{this.props.dismissable ? (
|
||||||
? <button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="close"
|
className="close"
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
onClick={this.props.removeNotification}
|
onClick={this.props.removeNotification}
|
||||||
>
|
>
|
||||||
<span className="pficon pficon-close" aria-hidden="true" />
|
<span className="pficon pficon-close" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
: false}
|
) : (
|
||||||
|
false
|
||||||
|
)}
|
||||||
<strong>{this.props.title}</strong>
|
<strong>{this.props.title}</strong>
|
||||||
{this.renderMessage(this.props.message)}
|
{this.renderMessage(this.props.message)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -52,7 +52,8 @@ class NotificationsToaster extends React.Component {
|
||||||
timeoutable={notification.type !== 'error'}
|
timeoutable={notification.type !== 'error'}
|
||||||
timerPaused={this.state.isHovered}
|
timerPaused={this.state.isHovered}
|
||||||
removeNotification={() =>
|
removeNotification={() =>
|
||||||
this.props.removeNotification(notification.id)}
|
this.props.removeNotification(notification.id)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,8 +19,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../actions/EnvironmentConfigurationActions';
|
||||||
from '../../actions/EnvironmentConfigurationActions';
|
|
||||||
import { getCurrentPlanName } from '../../selectors/plans';
|
import { getCurrentPlanName } from '../../selectors/plans';
|
||||||
import { getEnvironmentParameters } from '../../selectors/parameters';
|
import { getEnvironmentParameters } from '../../selectors/parameters';
|
||||||
import { getEnvironment } from '../../selectors/environmentConfiguration';
|
import { getEnvironment } from '../../selectors/environmentConfiguration';
|
||||||
|
@ -44,13 +43,15 @@ class EnvironmentParameters extends React.Component {
|
||||||
loaded={!isFetchingEnvironment}
|
loaded={!isFetchingEnvironment}
|
||||||
content="Fetching Parameters..."
|
content="Fetching Parameters..."
|
||||||
>
|
>
|
||||||
{environmentError
|
{environmentError ? (
|
||||||
? <fieldset>
|
<fieldset>
|
||||||
<InlineNotification title={environmentError.title} type="error">
|
<InlineNotification title={environmentError.title} type="error">
|
||||||
{environmentError.message}
|
{environmentError.message}
|
||||||
</InlineNotification>
|
</InlineNotification>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
: <ParameterInputList parameters={parameters.toList()} />}
|
) : (
|
||||||
|
<ParameterInputList parameters={parameters.toList()} />
|
||||||
|
)}
|
||||||
</Loader>
|
</Loader>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ const messages = defineMessages({
|
||||||
|
|
||||||
class ParameterInput extends React.Component {
|
class ParameterInput extends React.Component {
|
||||||
/**
|
/**
|
||||||
* Process the parameter, generate relevant input
|
* Process the parameter, generate relevant input
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { name, label, description, defaultValue, value, type } = this.props;
|
const { name, label, description, defaultValue, value, type } = this.props;
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
|
@ -25,7 +25,8 @@ import ParameterInput from './ParameterInput';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
noParameters: {
|
noParameters: {
|
||||||
id: 'ParameterInputList.noParameters',
|
id: 'ParameterInputList.noParameters',
|
||||||
defaultMessage: 'There are currently no parameters to configure in this section.'
|
defaultMessage:
|
||||||
|
'There are currently no parameters to configure in this section.'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,11 +59,7 @@ class ParameterInputList extends React.Component {
|
||||||
</fieldset>
|
</fieldset>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return <fieldset>{parameters}</fieldset>;
|
||||||
<fieldset>
|
|
||||||
{parameters}
|
|
||||||
</fieldset>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,14 +24,11 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { CloseModalButton } from '../ui/Modals';
|
import { CloseModalButton } from '../ui/Modals';
|
||||||
import EnvironmentConfigurationActions
|
import EnvironmentConfigurationActions from '../../actions/EnvironmentConfigurationActions';
|
||||||
from '../../actions/EnvironmentConfigurationActions';
|
|
||||||
import EnvironmentParameters from './EnvironmentParameters';
|
import EnvironmentParameters from './EnvironmentParameters';
|
||||||
import { getCurrentPlanName } from '../../selectors/plans';
|
import { getCurrentPlanName } from '../../selectors/plans';
|
||||||
import { getRootParameters } from '../../selectors/parameters';
|
import { getRootParameters } from '../../selectors/parameters';
|
||||||
import {
|
import { getEnabledEnvironments } from '../../selectors/environmentConfiguration';
|
||||||
getEnabledEnvironments
|
|
||||||
} from '../../selectors/environmentConfiguration';
|
|
||||||
import { Loader } from '../ui/Loader';
|
import { Loader } from '../ui/Loader';
|
||||||
import ModalFormErrorList from '../ui/forms/ModalFormErrorList';
|
import ModalFormErrorList from '../ui/forms/ModalFormErrorList';
|
||||||
import ParametersActions from '../../actions/ParametersActions';
|
import ParametersActions from '../../actions/ParametersActions';
|
||||||
|
@ -92,9 +89,9 @@ class Parameters extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
_filterFormData(formData) {
|
_filterFormData(formData) {
|
||||||
return fromJS(formData)
|
return fromJS(formData)
|
||||||
.filterNot((value, key) => {
|
.filterNot((value, key) => {
|
||||||
|
@ -104,9 +101,9 @@ class Parameters extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
_jsonParseFormData(formData) {
|
_jsonParseFormData(formData) {
|
||||||
return mapValues(formData, value => {
|
return mapValues(formData, value => {
|
||||||
try {
|
try {
|
||||||
|
@ -212,7 +209,6 @@ class Parameters extends React.Component {
|
||||||
onValid={this.enableButton.bind(this)}
|
onValid={this.enableButton.bind(this)}
|
||||||
onInvalid={this.disableButton.bind(this)}
|
onInvalid={this.disableButton.bind(this)}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="row row-eq-height">
|
<div className="row row-eq-height">
|
||||||
<div className="col-sm-4 sidebar-pf sidebar-pf-left">
|
<div className="col-sm-4 sidebar-pf sidebar-pf-left">
|
||||||
|
@ -240,9 +236,7 @@ class Parameters extends React.Component {
|
||||||
loaded={this.props.parametersLoaded}
|
loaded={this.props.parametersLoaded}
|
||||||
>
|
>
|
||||||
<ModalFormErrorList errors={this.props.formErrors.toJS()} />
|
<ModalFormErrorList errors={this.props.formErrors.toJS()} />
|
||||||
<div className="tab-content">
|
<div className="tab-content">{this.renderTabPanes()}</div>
|
||||||
{this.renderTabPanes()}
|
|
||||||
</div>
|
|
||||||
</Loader>
|
</Loader>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -100,60 +100,60 @@ class EditPlan extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const { plan } = this.props;
|
const { plan } = this.props;
|
||||||
|
|
||||||
return plan
|
return plan ? (
|
||||||
? <RoutedModal bsSize="lg" redirectPath="/plans/manage">
|
<RoutedModal bsSize="lg" redirectPath="/plans/manage">
|
||||||
<Formsy.Form
|
<Formsy.Form
|
||||||
ref="EditPlanForm"
|
ref="EditPlanForm"
|
||||||
role="form"
|
role="form"
|
||||||
className="form-horizontal"
|
className="form-horizontal"
|
||||||
onChange={this.onPlanFilesChange.bind(this)}
|
onChange={this.onPlanFilesChange.bind(this)}
|
||||||
onValidSubmit={this.onFormSubmit.bind(this)}
|
onValidSubmit={this.onFormSubmit.bind(this)}
|
||||||
onValid={this.onFormValid.bind(this)}
|
onValid={this.onFormValid.bind(this)}
|
||||||
onInvalid={this.onFormInvalid.bind(this)}
|
onInvalid={this.onFormInvalid.bind(this)}
|
||||||
|
>
|
||||||
|
<ModalHeader>
|
||||||
|
<CloseModalXButton />
|
||||||
|
<ModalTitle>
|
||||||
|
<FormattedMessage
|
||||||
|
{...messages.updatePlanNameFiles}
|
||||||
|
values={{ planName: plan.name }}
|
||||||
|
/>
|
||||||
|
</ModalTitle>
|
||||||
|
</ModalHeader>
|
||||||
|
<Loader
|
||||||
|
loaded={!this.props.isTransitioningPlan}
|
||||||
|
size="lg"
|
||||||
|
height={60}
|
||||||
|
content={this.props.intl.formatMessage(messages.updatingPlanLoader)}
|
||||||
>
|
>
|
||||||
<ModalHeader>
|
<ModalFormErrorList errors={this.props.planFormErrors.toJS()} />
|
||||||
<CloseModalXButton />
|
<div className="modal-body">
|
||||||
<ModalTitle>
|
<PlanEditFormTabs
|
||||||
<FormattedMessage
|
selectedFiles={this.state.selectedFiles}
|
||||||
{...messages.updatePlanNameFiles}
|
planName={plan.name}
|
||||||
values={{ planName: plan.name }}
|
planFiles={plan.files}
|
||||||
/>
|
setUploadType={this.setUploadType.bind(this)}
|
||||||
</ModalTitle>
|
uploadType={this.state.uploadType}
|
||||||
</ModalHeader>
|
/>
|
||||||
<Loader
|
</div>
|
||||||
loaded={!this.props.isTransitioningPlan}
|
</Loader>
|
||||||
size="lg"
|
<ModalFooter>
|
||||||
height={60}
|
<button
|
||||||
content={this.props.intl.formatMessage(
|
disabled={!this.state.canSubmit}
|
||||||
messages.updatingPlanLoader
|
className="btn btn-primary"
|
||||||
)}
|
type="submit"
|
||||||
>
|
>
|
||||||
<ModalFormErrorList errors={this.props.planFormErrors.toJS()} />
|
<FormattedMessage {...messages.uploadAndUpdate} />
|
||||||
<div className="modal-body">
|
</button>
|
||||||
<PlanEditFormTabs
|
<CloseModalButton>
|
||||||
selectedFiles={this.state.selectedFiles}
|
<FormattedMessage {...messages.cancel} />
|
||||||
planName={plan.name}
|
</CloseModalButton>
|
||||||
planFiles={plan.files}
|
</ModalFooter>
|
||||||
setUploadType={this.setUploadType.bind(this)}
|
</Formsy.Form>
|
||||||
uploadType={this.state.uploadType}
|
</RoutedModal>
|
||||||
/>
|
) : (
|
||||||
</div>
|
<Redirect to="/plans" />
|
||||||
</Loader>
|
);
|
||||||
<ModalFooter>
|
|
||||||
<button
|
|
||||||
disabled={!this.state.canSubmit}
|
|
||||||
className="btn btn-primary"
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<FormattedMessage {...messages.uploadAndUpdate} />
|
|
||||||
</button>
|
|
||||||
<CloseModalButton>
|
|
||||||
<FormattedMessage {...messages.cancel} />
|
|
||||||
</CloseModalButton>
|
|
||||||
</ModalFooter>
|
|
||||||
</Formsy.Form>
|
|
||||||
</RoutedModal>
|
|
||||||
: <Redirect to="/plans" />;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
downloadPlanExportMessage: {
|
downloadPlanExportMessage: {
|
||||||
id: 'ExportPlan.downloadMessage',
|
id: 'ExportPlan.downloadMessage',
|
||||||
defaultMessage: 'The plan export you requested is ready. Please click the button below to ' +
|
defaultMessage:
|
||||||
|
'The plan export you requested is ready. Please click the button below to ' +
|
||||||
'download the export. You might need to right-click the button and choose ' +
|
'download the export. You might need to right-click the button and choose ' +
|
||||||
'"Save link as...".'
|
'"Save link as...".'
|
||||||
},
|
},
|
||||||
|
@ -94,21 +95,20 @@ class ExportPlan extends React.Component {
|
||||||
messages.exportingPlanLoader
|
messages.exportingPlanLoader
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{this.props.planExportUrl
|
{this.props.planExportUrl ? (
|
||||||
? <div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage {...messages.downloadPlanExportMessage} />
|
<FormattedMessage {...messages.downloadPlanExportMessage} />
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a href={this.props.planExportUrl} className="btn btn-success">
|
||||||
href={this.props.planExportUrl}
|
<FormattedMessage {...messages.downloadPlanExport} />
|
||||||
className="btn btn-success"
|
</a>
|
||||||
>
|
</div>
|
||||||
<FormattedMessage {...messages.downloadPlanExport} />
|
) : (
|
||||||
</a>
|
<div>
|
||||||
</div>
|
<FormattedMessage {...messages.exportError} />
|
||||||
: <div>
|
</div>
|
||||||
<FormattedMessage {...messages.exportError} />
|
)}
|
||||||
</div>}
|
|
||||||
</Loader>
|
</Loader>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
|
|
@ -91,9 +91,7 @@ export default class FileList extends React.Component {
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<table className="table upload-files">
|
<table className="table upload-files">
|
||||||
<tbody>
|
<tbody>{files}</tbody>
|
||||||
{files}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,7 +25,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
noPlansAvailableMessage: {
|
noPlansAvailableMessage: {
|
||||||
id: 'NoPlans.noPlansAvailableMessage',
|
id: 'NoPlans.noPlansAvailableMessage',
|
||||||
defaultMessage: 'There are no Deployment Plans available. Please create one first.'
|
defaultMessage:
|
||||||
|
'There are no Deployment Plans available. Please create one first.'
|
||||||
},
|
},
|
||||||
importPlan: {
|
importPlan: {
|
||||||
id: 'NoPlans.importPlan',
|
id: 'NoPlans.importPlan',
|
||||||
|
@ -40,12 +41,15 @@ export default class NoPlans extends React.Component {
|
||||||
<div className="blank-slate-pf-icon">
|
<div className="blank-slate-pf-icon">
|
||||||
<span className="fa fa-ban" />
|
<span className="fa fa-ban" />
|
||||||
</div>
|
</div>
|
||||||
<h1><FormattedMessage {...messages.noPlansAvailable} /></h1>
|
<h1>
|
||||||
<p><FormattedMessage {...messages.noPlansAvailableMessage} /></p>
|
<FormattedMessage {...messages.noPlansAvailable} />
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
<FormattedMessage {...messages.noPlansAvailableMessage} />
|
||||||
|
</p>
|
||||||
<div className="blank-slate-pf-main-action">
|
<div className="blank-slate-pf-main-action">
|
||||||
<Link to="/plans/manage/new" className="btn btn-lg btn-primary">
|
<Link to="/plans/manage/new" className="btn btn-lg btn-primary">
|
||||||
<span className="fa fa-plus" />
|
<span className="fa fa-plus" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.importPlan} />
|
<FormattedMessage {...messages.importPlan} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -50,7 +50,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
badExtension: {
|
badExtension: {
|
||||||
id: 'PlanEditFormTabs.badExtension',
|
id: 'PlanEditFormTabs.badExtension',
|
||||||
defaultMessage: 'Invalid type: plan file must be a tar archive (.tar.gz or .tgz)'
|
defaultMessage:
|
||||||
|
'Invalid type: plan file must be a tar archive (.tar.gz or .tgz)'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,9 +90,8 @@ export default class PlanEditFormTabs extends React.Component {
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab isActive={this.isActiveTab('planFiles')}>
|
<Tab isActive={this.isActiveTab('planFiles')}>
|
||||||
<a className="link" onClick={() => this.setActiveTab('planFiles')}>
|
<a className="link" onClick={() => this.setActiveTab('planFiles')}>
|
||||||
<FormattedMessage {...messages.files} /> <span className="badge">
|
<FormattedMessage {...messages.files} />{' '}
|
||||||
{this.getFileCount.bind(this)()}
|
<span className="badge">{this.getFileCount.bind(this)()}</span>
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
</Tab>
|
</Tab>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -104,27 +104,33 @@ class PlanFileInput extends React.Component {
|
||||||
if (!errorMessage && this.state.unreadableFile) {
|
if (!errorMessage && this.state.unreadableFile) {
|
||||||
errorMessage = `${this.state.unreadableFile} could not be read.`;
|
errorMessage = `${this.state.unreadableFile} could not be read.`;
|
||||||
}
|
}
|
||||||
return errorMessage
|
return errorMessage ? (
|
||||||
? <span className="help-block">{errorMessage}</span>
|
<span className="help-block">{errorMessage}</span>
|
||||||
: false;
|
) : (
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDescription() {
|
renderDescription() {
|
||||||
let description = this.props.description;
|
let description = this.props.description;
|
||||||
return description
|
return description ? (
|
||||||
? <small className="help-block">{description}</small>
|
<small className="help-block">{description}</small>
|
||||||
: false;
|
) : (
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderProgress() {
|
renderProgress() {
|
||||||
return this.state.progress > 0
|
return this.state.progress > 0 ? (
|
||||||
? <div className="progress active help-block">
|
<div className="progress active help-block">
|
||||||
<div
|
<div
|
||||||
className="progress-bar"
|
className="progress-bar"
|
||||||
style={{ width: `${this.state.progress}%` }}
|
style={{ width: `${this.state.progress}%` }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: false;
|
) : (
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -58,7 +58,8 @@ const messages = defineMessages({
|
||||||
},
|
},
|
||||||
badExtension: {
|
badExtension: {
|
||||||
id: 'PlanFormTabs.badExtension',
|
id: 'PlanFormTabs.badExtension',
|
||||||
defaultMessage: 'Invalid type: plan file must be a tar archive (.tar.gz or .tgz)'
|
defaultMessage:
|
||||||
|
'Invalid type: plan file must be a tar archive (.tar.gz or .tgz)'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,9 +90,8 @@ export default class PlanFormTabs extends React.Component {
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab isActive={this.isActiveTab('planFiles')}>
|
<Tab isActive={this.isActiveTab('planFiles')}>
|
||||||
<a className="link" onClick={() => this.setActiveTab('planFiles')}>
|
<a className="link" onClick={() => this.setActiveTab('planFiles')}>
|
||||||
<FormattedMessage {...messages.files} /> <span className="badge">
|
<FormattedMessage {...messages.files} />{' '}
|
||||||
{this.props.selectedFiles.length}
|
<span className="badge">{this.props.selectedFiles.length}</span>
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
</Tab>
|
</Tab>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -46,8 +46,7 @@ export default class PlanUploadTypeRadios extends React.Component {
|
||||||
value="tarball"
|
value="tarball"
|
||||||
onChange={this.props.setUploadType}
|
onChange={this.props.setUploadType}
|
||||||
defaultChecked
|
defaultChecked
|
||||||
/>
|
/>{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.tarArchive} />
|
<FormattedMessage {...messages.tarArchive} />
|
||||||
</label>
|
</label>
|
||||||
<label className="radio-inline" htmlFor="checkbox-folder">
|
<label className="radio-inline" htmlFor="checkbox-folder">
|
||||||
|
@ -58,8 +57,7 @@ export default class PlanUploadTypeRadios extends React.Component {
|
||||||
name="uploadType"
|
name="uploadType"
|
||||||
onChange={this.props.setUploadType}
|
onChange={this.props.setUploadType}
|
||||||
value="folder"
|
value="folder"
|
||||||
/>
|
/>{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.localFolder} />
|
<FormattedMessage {...messages.localFolder} />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -79,16 +79,18 @@ class PlansList extends React.Component {
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
{this.props.plans.isEmpty()
|
{this.props.plans.isEmpty() ? (
|
||||||
? <NoPlans />
|
<NoPlans />
|
||||||
: <div className="panel panel-default">
|
) : (
|
||||||
<div className="cards-pf">
|
<div className="panel panel-default">
|
||||||
<div className="row row-cards-pf">
|
<div className="cards-pf">
|
||||||
<ImportPlanCard />
|
<div className="row row-cards-pf">
|
||||||
{this.renderCards()}
|
<ImportPlanCard />
|
||||||
</div>
|
{this.renderCards()}
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,10 +63,11 @@ const PlanActions = ({ planName, stack }) => {
|
||||||
<MenuItemLink to={`/plans/manage/${planName}/export`}>
|
<MenuItemLink to={`/plans/manage/${planName}/export`}>
|
||||||
<FormattedMessage {...messages.export} />
|
<FormattedMessage {...messages.export} />
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
{!stack &&
|
{!stack && (
|
||||||
<MenuItemLink to={`/plans/manage/${planName}/delete`}>
|
<MenuItemLink to={`/plans/manage/${planName}/delete`}>
|
||||||
<FormattedMessage {...messages.delete} />
|
<FormattedMessage {...messages.delete} />
|
||||||
</MenuItemLink>}
|
</MenuItemLink>
|
||||||
|
)}
|
||||||
</DropdownKebab>
|
</DropdownKebab>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -96,15 +96,10 @@ class PlanCard extends React.Component {
|
||||||
return (
|
return (
|
||||||
<ul className="list-unstyled">
|
<ul className="list-unstyled">
|
||||||
<li>
|
<li>
|
||||||
<strong>Status:</strong>
|
<strong>Status:</strong> {this.renderStackIcon(stack)}{' '}
|
||||||
{' '}
|
|
||||||
{this.renderStackIcon(stack)}
|
|
||||||
{' '}
|
|
||||||
{this.getDeploymentStatus(stack)}
|
{this.getDeploymentStatus(stack)}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>{modified}</li>
|
||||||
{modified}
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -143,13 +138,10 @@ class PlanCard extends React.Component {
|
||||||
{plan.name}
|
{plan.name}
|
||||||
<PlanActions planName={plan.name} stack={stack} />
|
<PlanActions planName={plan.name} stack={stack} />
|
||||||
</h2>
|
</h2>
|
||||||
{plan.description &&
|
{plan.description && (
|
||||||
<div className="card-pf-body">
|
<div className="card-pf-body">{plan.description}</div>
|
||||||
{plan.description}
|
)}
|
||||||
</div>}
|
<div className="card-pf-footer">{this.renderStackInfo()}</div>
|
||||||
<div className="card-pf-footer">
|
|
||||||
{this.renderStackInfo()}
|
|
||||||
</div>
|
|
||||||
</OverlayLoader>
|
</OverlayLoader>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -100,9 +100,9 @@ class RoleDetail extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
_filterFormData(formData) {
|
_filterFormData(formData) {
|
||||||
return fromJS(formData)
|
return fromJS(formData)
|
||||||
.filterNot((value, key) => {
|
.filterNot((value, key) => {
|
||||||
|
@ -112,9 +112,9 @@ class RoleDetail extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
_jsonParseFormData(formData) {
|
_jsonParseFormData(formData) {
|
||||||
return mapValues(formData, value => {
|
return mapValues(formData, value => {
|
||||||
try {
|
try {
|
||||||
|
@ -154,17 +154,23 @@ class RoleDetail extends React.Component {
|
||||||
return (
|
return (
|
||||||
<ul className="nav nav-tabs">
|
<ul className="nav nav-tabs">
|
||||||
<NavTab
|
<NavTab
|
||||||
to={`/plans/${currentPlanName}/roles/${urlParams.roleName}/parameters`}
|
to={`/plans/${currentPlanName}/roles/${
|
||||||
|
urlParams.roleName
|
||||||
|
}/parameters`}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.parameters} />
|
<FormattedMessage {...messages.parameters} />
|
||||||
</NavTab>
|
</NavTab>
|
||||||
<NavTab
|
<NavTab
|
||||||
to={`/plans/${currentPlanName}/roles/${urlParams.roleName}/services`}
|
to={`/plans/${currentPlanName}/roles/${
|
||||||
|
urlParams.roleName
|
||||||
|
}/services`}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.services} />
|
<FormattedMessage {...messages.services} />
|
||||||
</NavTab>
|
</NavTab>
|
||||||
<NavTab
|
<NavTab
|
||||||
to={`/plans/${currentPlanName}/roles/${urlParams.roleName}/network-configuration`}
|
to={`/plans/${currentPlanName}/roles/${
|
||||||
|
urlParams.roleName
|
||||||
|
}/network-configuration`}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.networkConfiguration} />
|
<FormattedMessage {...messages.networkConfiguration} />
|
||||||
</NavTab>
|
</NavTab>
|
||||||
|
@ -226,24 +232,26 @@ class RoleDetail extends React.Component {
|
||||||
/>
|
/>
|
||||||
<Redirect
|
<Redirect
|
||||||
from="/plans/:planName/roles/:roleName"
|
from="/plans/:planName/roles/:roleName"
|
||||||
to={`/plans/${currentPlanName}/roles/${urlParams.roleName}/parameters`}
|
to={`/plans/${currentPlanName}/roles/${
|
||||||
|
urlParams.roleName
|
||||||
|
}/parameters`}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Loader>
|
</Loader>
|
||||||
{dataLoaded
|
{dataLoaded ? (
|
||||||
? <ModalFooter>
|
<ModalFooter>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!this.state.canSubmit}
|
disabled={!this.state.canSubmit}
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
>
|
>
|
||||||
<FormattedMessage {...messages.saveChanges} />
|
<FormattedMessage {...messages.saveChanges} />
|
||||||
</button>
|
</button>
|
||||||
<CloseModalButton>
|
<CloseModalButton>
|
||||||
<FormattedMessage {...messages.cancel} />
|
<FormattedMessage {...messages.cancel} />
|
||||||
</CloseModalButton>
|
</CloseModalButton>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
: null}
|
) : null}
|
||||||
</Formsy.Form>
|
</Formsy.Form>
|
||||||
</RoutedModalPanel>
|
</RoutedModalPanel>
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,7 +29,8 @@ import Tab from '../ui/Tab';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
noParameters: {
|
noParameters: {
|
||||||
id: 'RoleServices.noParameters',
|
id: 'RoleServices.noParameters',
|
||||||
defaultMessage: 'There are currently no parameters to configure in this section.'
|
defaultMessage:
|
||||||
|
'There are currently no parameters to configure in this section.'
|
||||||
},
|
},
|
||||||
selectService: {
|
selectService: {
|
||||||
id: 'RoleServices.selectService',
|
id: 'RoleServices.selectService',
|
||||||
|
|
|
@ -31,7 +31,11 @@ export default class ConfirmationModal extends React.Component {
|
||||||
renderTitle() {
|
renderTitle() {
|
||||||
const iconClass = this.props.iconClass;
|
const iconClass = this.props.iconClass;
|
||||||
if (iconClass) {
|
if (iconClass) {
|
||||||
return <span><span className={iconClass} /> {this.props.title}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<span className={iconClass} /> {this.props.title}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return <span>{this.props.title}</span>;
|
return <span>{this.props.title}</span>;
|
||||||
}
|
}
|
||||||
|
@ -51,9 +55,7 @@ export default class ConfirmationModal extends React.Component {
|
||||||
<Modal bsSize="sm" show={show} onHide={onCancel}>
|
<Modal bsSize="sm" show={show} onHide={onCancel}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<CloseModalXButton />
|
<CloseModalXButton />
|
||||||
<ModalTitle>
|
<ModalTitle>{this.renderTitle()}</ModalTitle>
|
||||||
{this.renderTitle()}
|
|
||||||
</ModalTitle>
|
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<p>{question}</p>
|
<p>{question}</p>
|
||||||
|
|
|
@ -81,9 +81,7 @@ class ModalPanel extends React.Component {
|
||||||
className={cx('modal-panel', modalPanelClassName)}
|
className={cx('modal-panel', modalPanelClassName)}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
<div className="row flex-container">
|
<div className="row flex-container">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,11 +32,7 @@ export default class TabPane extends React.Component {
|
||||||
active: this.props.isActive
|
active: this.props.isActive
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return <div className={classes}>{this.renderChildren()}</div>;
|
||||||
<div className={classes}>
|
|
||||||
{this.renderChildren()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TabPane.propTypes = {
|
TabPane.propTypes = {
|
||||||
|
|
|
@ -27,9 +27,7 @@ export const ActiveFiltersList = ({
|
||||||
return (
|
return (
|
||||||
<span className="toolbar-pf-active-filters">
|
<span className="toolbar-pf-active-filters">
|
||||||
<p>{label} </p>
|
<p>{label} </p>
|
||||||
<ul className="list-inline">
|
<ul className="list-inline">{children}</ul>
|
||||||
{children}
|
|
||||||
</ul>
|
|
||||||
<p>
|
<p>
|
||||||
<a className="link" onClick={() => handleClearAll()}>
|
<a className="link" onClick={() => handleClearAll()}>
|
||||||
{clearAllLabel}
|
{clearAllLabel}
|
||||||
|
|
|
@ -94,9 +94,11 @@ export const SelectAllButton = selectAll(
|
||||||
onClick={() => toggleSelectAll()}
|
onClick={() => toggleSelectAll()}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{shouldSelectAll
|
{shouldSelectAll ? (
|
||||||
? <FormattedMessage {...messages.selectAll} />
|
<FormattedMessage {...messages.selectAll} />
|
||||||
: <FormattedMessage {...messages.deselectAll} />}
|
) : (
|
||||||
|
<FormattedMessage {...messages.deselectAll} />
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,7 +30,9 @@ class ToolbarFiltersForm extends React.Component {
|
||||||
renderFilterByOptions() {
|
renderFilterByOptions() {
|
||||||
const { options } = this.props;
|
const { options } = this.props;
|
||||||
return Object.keys(options).map(k => (
|
return Object.keys(options).map(k => (
|
||||||
<MenuItem key={k} eventKey={k}>{options[k]}</MenuItem>
|
<MenuItem key={k} eventKey={k}>
|
||||||
|
{options[k]}
|
||||||
|
</MenuItem>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,20 +54,22 @@ class ToolbarFiltersForm extends React.Component {
|
||||||
return (
|
return (
|
||||||
<form id={id} onSubmit={handleSubmit(this.submit.bind(this))}>
|
<form id={id} onSubmit={handleSubmit(this.submit.bind(this))}>
|
||||||
<FormGroup className="toolbar-pf-filter">
|
<FormGroup className="toolbar-pf-filter">
|
||||||
{options
|
{options ? (
|
||||||
? <InputGroup>
|
<InputGroup>
|
||||||
<InputGroup.Button>
|
<InputGroup.Button>
|
||||||
<Field
|
<Field
|
||||||
name="filterBy"
|
name="filterBy"
|
||||||
component={DropdownSelect}
|
component={DropdownSelect}
|
||||||
format={formatSelectValue}
|
format={formatSelectValue}
|
||||||
>
|
>
|
||||||
{this.renderFilterByOptions()}
|
{this.renderFilterByOptions()}
|
||||||
</Field>
|
</Field>
|
||||||
</InputGroup.Button>
|
</InputGroup.Button>
|
||||||
{this.renderFilterStringField()}
|
{this.renderFilterStringField()}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
: this.renderFilterStringField()}
|
) : (
|
||||||
|
this.renderFilterStringField()
|
||||||
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,18 +21,14 @@ export const Toolbar = ({ children, tableView }) => {
|
||||||
if (tableView) {
|
if (tableView) {
|
||||||
return (
|
return (
|
||||||
<div className="toolbar-pf row table-view-pf-toolbar">
|
<div className="toolbar-pf row table-view-pf-toolbar">
|
||||||
<div className="col-sm-12">
|
<div className="col-sm-12">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="toolbar-pf row">
|
<div className="toolbar-pf row">
|
||||||
<div className="col-sm-12">
|
<div className="col-sm-12">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -47,9 +43,7 @@ Toolbar.defaultProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ToolbarActions = ({ children }) => (
|
export const ToolbarActions = ({ children }) => (
|
||||||
<div className="toolbar-pf-actions">
|
<div className="toolbar-pf-actions">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
ToolbarActions.propTypes = {
|
ToolbarActions.propTypes = {
|
||||||
children: PropTypes.node
|
children: PropTypes.node
|
||||||
|
@ -57,9 +51,7 @@ ToolbarActions.propTypes = {
|
||||||
|
|
||||||
export const ToolbarResults = ({ children }) => (
|
export const ToolbarResults = ({ children }) => (
|
||||||
<div className="toolbar-pf-results row">
|
<div className="toolbar-pf-results row">
|
||||||
<div className="col-sm-12">
|
<div className="col-sm-12">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
ToolbarResults.propTypes = {
|
ToolbarResults.propTypes = {
|
||||||
|
|
|
@ -29,9 +29,7 @@ export const ActionCard = ({ children, className, onClick, ...rest }) => (
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<div className="card-pf-body">
|
<div className="card-pf-body">
|
||||||
<p className="text-center">
|
<p className="text-center">{children}</p>
|
||||||
{children}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -76,12 +76,12 @@ export default class Dropdown extends React.Component {
|
||||||
{items}
|
{items}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{this.state.isOpen
|
{this.state.isOpen ? (
|
||||||
? <div
|
<div
|
||||||
onClick={this.toggleDropdown.bind(this)}
|
onClick={this.toggleDropdown.bind(this)}
|
||||||
className="modal-backdrop fade"
|
className="modal-backdrop fade"
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,7 @@ const DropdownKebab = ({ children, id, pullRight }) => {
|
||||||
>
|
>
|
||||||
<span className="fa fa-ellipsis-v" />
|
<span className="fa fa-ellipsis-v" />
|
||||||
</Dropdown.Toggle>
|
</Dropdown.Toggle>
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>{children}</Dropdown.Menu>
|
||||||
{children}
|
|
||||||
</Dropdown.Menu>
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,9 +32,7 @@ export default class FormErrorList extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<strong>{`${errors.length} Errors Found:`}</strong>
|
<strong>{`${errors.length} Errors Found:`}</strong>
|
||||||
<ul>
|
<ul>{errorList}</ul>
|
||||||
{errorList}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,9 +19,9 @@ import React from 'react';
|
||||||
|
|
||||||
export default class InputDescription extends React.Component {
|
export default class InputDescription extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return this.props.description
|
return this.props.description ? (
|
||||||
? <small className="help-block">{this.props.description}</small>
|
<small className="help-block">{this.props.description}</small>
|
||||||
: null;
|
) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputDescription.propTypes = {
|
InputDescription.propTypes = {
|
||||||
|
|
|
@ -20,9 +20,9 @@ import React from 'react';
|
||||||
export default class InputDescription extends React.Component {
|
export default class InputDescription extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const errorMessage = this.props.getErrorMessage();
|
const errorMessage = this.props.getErrorMessage();
|
||||||
return errorMessage
|
return errorMessage ? (
|
||||||
? <span className="help-block">{errorMessage}</span>
|
<span className="help-block">{errorMessage}</span>
|
||||||
: null;
|
) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputDescription.propTypes = {
|
InputDescription.propTypes = {
|
||||||
|
|
|
@ -38,7 +38,7 @@ InputDescription.propTypes = {
|
||||||
export const InputMessage = ({ fieldMeta: { touched, error, warning } }) =>
|
export const InputMessage = ({ fieldMeta: { touched, error, warning } }) =>
|
||||||
touched
|
touched
|
||||||
? (error ? <HelpBlock>{error}</HelpBlock> : null) ||
|
? (error ? <HelpBlock>{error}</HelpBlock> : null) ||
|
||||||
(warning ? <HelpBlock>{warning}</HelpBlock> : null)
|
(warning ? <HelpBlock>{warning}</HelpBlock> : null)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
InputMessage.propTypes = {
|
InputMessage.propTypes = {
|
||||||
|
|
|
@ -120,9 +120,7 @@ class DataTable extends React.Component {
|
||||||
role="grid"
|
role="grid"
|
||||||
>
|
>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>{headers}</tr>
|
||||||
{headers}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{rows.length > 0 ? rows : this.props.noRowsRenderer()}
|
{rows.length > 0 ? rows : this.props.noRowsRenderer()}
|
||||||
|
|
|
@ -22,15 +22,11 @@ import TableCheckBox from '../forms/TableCheckBox';
|
||||||
import { InlineLoader } from '../Loader';
|
import { InlineLoader } from '../Loader';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default table header cell class
|
* Default table header cell class
|
||||||
*/
|
*/
|
||||||
export class DataTableHeaderCell extends React.Component {
|
export class DataTableHeaderCell extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <th {...this.props}>{this.props.children}</th>;
|
||||||
<th {...this.props}>
|
|
||||||
{this.props.children}
|
|
||||||
</th>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataTableHeaderCell.propTypes = {
|
DataTableHeaderCell.propTypes = {
|
||||||
|
@ -38,15 +34,11 @@ DataTableHeaderCell.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default table cell class
|
* Default table cell class
|
||||||
*/
|
*/
|
||||||
export class DataTableCell extends React.Component {
|
export class DataTableCell extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <td>{this.props.children}</td>;
|
||||||
<td>
|
|
||||||
{this.props.children}
|
|
||||||
</td>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataTableCell.propTypes = {
|
DataTableCell.propTypes = {
|
||||||
|
@ -54,19 +46,15 @@ DataTableCell.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table cell class able to render value from data set passed to columns
|
* Table cell class able to render value from data set passed to columns
|
||||||
*/
|
*/
|
||||||
export class DataTableDataFieldCell extends React.Component {
|
export class DataTableDataFieldCell extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
let value = _.result(
|
let value = _.result(
|
||||||
this.props.data[this.props.rowIndex],
|
this.props.data[this.props.rowIndex],
|
||||||
this.props.field
|
this.props.field
|
||||||
);
|
);
|
||||||
return (
|
return <DataTableCell {...this.props}>{value}</DataTableCell>;
|
||||||
<DataTableCell {...this.props}>
|
|
||||||
{value}
|
|
||||||
</DataTableCell>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataTableDataFieldCell.propTypes = {
|
DataTableDataFieldCell.propTypes = {
|
||||||
|
@ -79,11 +67,7 @@ export const DataTableDateFieldCell = props => {
|
||||||
//TODO(jtomasek): Update this component to parse date and format it using React Intl's
|
//TODO(jtomasek): Update this component to parse date and format it using React Intl's
|
||||||
// FormatedDate
|
// FormatedDate
|
||||||
const value = _.result(props.data[props.rowIndex], props.field);
|
const value = _.result(props.data[props.rowIndex], props.field);
|
||||||
return (
|
return <DataTableCell {...props}>{value}</DataTableCell>;
|
||||||
<DataTableCell {...props}>
|
|
||||||
{value}
|
|
||||||
</DataTableCell>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
DataTableDateFieldCell.propTypes = {
|
DataTableDateFieldCell.propTypes = {
|
||||||
data: PropTypes.array.isRequired,
|
data: PropTypes.array.isRequired,
|
||||||
|
|
|
@ -29,16 +29,20 @@ export const checkRunningDeployment = WrappedComponent => {
|
||||||
if (this.props.currentStackDeploymentInProgress) {
|
if (this.props.currentStackDeploymentInProgress) {
|
||||||
this.props.notify({
|
this.props.notify({
|
||||||
title: 'Not allowed',
|
title: 'Not allowed',
|
||||||
message: `A deployment for the plan ${this.props.currentPlanName} is already in progress.`,
|
message: `A deployment for the plan ${
|
||||||
|
this.props.currentPlanName
|
||||||
|
} is already in progress.`,
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.props.currentStackDeploymentInProgress
|
return this.props.currentStackDeploymentInProgress ? (
|
||||||
? <Redirect to={`/plans/${this.props.currentPlanName}`} />
|
<Redirect to={`/plans/${this.props.currentPlanName}`} />
|
||||||
: <WrappedComponent {...this.props} />;
|
) : (
|
||||||
|
<WrappedComponent {...this.props} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CheckRunningDeploymentHOC.propTypes = {
|
CheckRunningDeploymentHOC.propTypes = {
|
||||||
|
|
|
@ -59,11 +59,10 @@ export default class Validation extends React.Component {
|
||||||
this.props.addActiveFilter({
|
this.props.addActiveFilter({
|
||||||
filterBy: 'group',
|
filterBy: 'group',
|
||||||
filterString: group
|
filterString: group
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<small>
|
<small>{group}</small>
|
||||||
{group}
|
|
||||||
</small>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -92,7 +92,11 @@ class ValidationDetail extends React.Component {
|
||||||
if (lastResult && !includes(['running', 'paused'], this.props.status)) {
|
if (lastResult && !includes(['running', 'paused'], this.props.status)) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p><strong><FormattedMessage {...messages.output} /></strong></p>
|
<p>
|
||||||
|
<strong>
|
||||||
|
<FormattedMessage {...messages.output} />
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
{lastResult.output.get('stdout', lastResult.output.get('result'))}
|
{lastResult.output.get('stdout', lastResult.output.get('result'))}
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -128,19 +132,22 @@ class ValidationDetail extends React.Component {
|
||||||
<h3>{this.props.name}</h3>
|
<h3>{this.props.name}</h3>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<strong><FormattedMessage {...messages.description} /></strong>
|
<strong>
|
||||||
{' '}
|
<FormattedMessage {...messages.description} />
|
||||||
|
</strong>{' '}
|
||||||
<br />
|
<br />
|
||||||
{this.props.description}
|
{this.props.description}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong><FormattedMessage {...messages.groups} /></strong>
|
<strong>
|
||||||
{' '}
|
<FormattedMessage {...messages.groups} />
|
||||||
|
</strong>{' '}
|
||||||
{this.renderValidationGroups()}
|
{this.renderValidationGroups()}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong><FormattedMessage {...messages.status} /></strong>
|
<strong>
|
||||||
{' '}
|
<FormattedMessage {...messages.status} />
|
||||||
|
</strong>{' '}
|
||||||
{this.props.status}
|
{this.props.status}
|
||||||
</p>
|
</p>
|
||||||
{this.renderValidationOutput()}
|
{this.renderValidationOutput()}
|
||||||
|
|
|
@ -111,7 +111,9 @@ class ValidationsList extends React.Component {
|
||||||
iconClass="pficon pficon-flag"
|
iconClass="pficon pficon-flag"
|
||||||
title={this.props.intl.formatMessage(messages.noValidations)}
|
title={this.props.intl.formatMessage(messages.noValidations)}
|
||||||
>
|
>
|
||||||
<p><FormattedMessage {...messages.noValidationsMessage} /></p>
|
<p>
|
||||||
|
<FormattedMessage {...messages.noValidationsMessage} />
|
||||||
|
</p>
|
||||||
</BlankSlate>
|
</BlankSlate>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -170,8 +172,10 @@ class ValidationsList extends React.Component {
|
||||||
<div className="actions pull-right">
|
<div className="actions pull-right">
|
||||||
<InlineLoader
|
<InlineLoader
|
||||||
loaded={
|
loaded={
|
||||||
!(this.props.validationsLoaded &&
|
!(
|
||||||
this.props.isFetchingValidations)
|
this.props.validationsLoaded &&
|
||||||
|
this.props.isFetchingValidations
|
||||||
|
)
|
||||||
}
|
}
|
||||||
component="small"
|
component="small"
|
||||||
content={formatMessage(messages.loadingValidations)}
|
content={formatMessage(messages.loadingValidations)}
|
||||||
|
@ -180,8 +184,7 @@ class ValidationsList extends React.Component {
|
||||||
className="link refresh"
|
className="link refresh"
|
||||||
onClick={this.refreshValidations.bind(this)}
|
onClick={this.refreshValidations.bind(this)}
|
||||||
>
|
>
|
||||||
<span className="pficon pficon-refresh" />
|
<span className="pficon pficon-refresh" />{' '}
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.refresh} />
|
<FormattedMessage {...messages.refresh} />
|
||||||
</a>
|
</a>
|
||||||
</InlineLoader>
|
</InlineLoader>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue