import React, { useState } from 'react'
import PropTypes from 'prop-types';
import {
Icon,
Button,
} from 'patternfly-react';
import * as resolve from 'table-resolver';
import ForemanModal from 'foremanReact/components/ForemanModal';
import Select from 'foremanReact/components/common/forms/Select';
import ParameterSelection from '../ParameterSelection';
import AddTableEntry from '../common/AddTableEntry';
import DeleteTableEntry from '../common/DeleteTableEntry';
import RailsData from '../common/RailsData';
import EasyHeaderFormatter from '../common/EasyHeaderFormatter';
import AppDefinitionSelector from './components/AppDefinitionSelector';
import ServiceCounter from './components/ServiceCounter';
import { arrayToObject } from '../../helper';
import {
Table,
FormControl,
inlineEditFormatterFactory,
} from 'patternfly-react';
import {
PARAMETER_SELECTION_PARAM_TYPE_FOREMAN,
PARAMETER_SELECTION_PARAM_TYPE_ANSIBLE,
} from '../ParameterSelection/ParameterSelectionConstants';
class ApplicationInstance extends React.Component {
constructor(props) {
super(props);
}
isEditing({rowData}) {
return (rowData.backup !== undefined);
}
validateParameters() {
let result = true;
let msg = "";
this.props.hosts.forEach(h => {
if (h.parameters.map(e => e.value).filter(i => i == "").length > 0) {
result = false;
if (msg == "") {
msg += "For some hosts the values for some parameters are missing. Check the values for these hosts:\n";
}
msg += "- "+ h.hostname +"\n";
}
});
const invalidMinServices = this.props.services.filter(s => (Number(s.minCount) != 0) && (s.currentCount < s.minCount));
const invalidMaxServices = this.props.services.filter(s => (Number(s.maxCount) != 0) && (s.currentCount > s.maxCount));
if (invalidMinServices.length > 0 || invalidMaxServices.length > 0) {
result = false;
if (msg != "") {
msg += "\n";
}
msg += "Unachieved service counts: \n";
invalidMinServices.map(s => { msg += "- service "+ s.name +" expects at least "+ s.minCount +" configured hosts" });
invalidMaxServices.map(s => { msg += "- service "+ s.name +" expects no more than "+ s.maxCount +" configured hosts" });
}
if (result === false) {
window.alert(msg);
}
return result;
}
componentDidMount() {
const {
data: { mode, appDefinition, hosts, ansibleVarsAll, appDefinitionUrl },
initApplicationInstance,
addApplicationInstanceHost,
deleteApplicationInstanceHost,
activateEditApplicationInstanceHost,
changeEditApplicationInstanceHost,
openForemanParameterSelectionModal,
openAnsibleParameterSelectionModal,
loadApplicationDefinition,
} = this.props;
if (mode === 'editInstance') {
loadApplicationDefinition(appDefinition.id, { url: appDefinitionUrl });
}
const inlineEditButtonsFormatter = inlineEditFormatterFactory({
isEditing: additionalData => this.props.editMode,
renderValue: (value, additionalData) => (
|
),
renderEdit: (value, additionalData) => (
|
)
});
this.inlineEditButtonsFormatter = inlineEditButtonsFormatter;
this.headerFormatter = EasyHeaderFormatter;
const inlineEditFormatterImpl = {
renderValue: (value, additionalData) => (
{value}
|
),
renderEditText: (value, additionalData, subtype='text') => (
changeEditApplicationInstanceHost(e.target.value, additionalData) }
/>
|
),
renderEditSelect: (value, additionalData, options) => (
|
)
};
const inlineEditFormatter = inlineEditFormatterFactory({
isEditing: additionalData => this.isEditing(additionalData),
renderValue: (value, additionalData) => {
let prettyValue = value;
if (additionalData.property == 'service') {
const serviceList = arrayToObject(this.props.services, "id", "name");
prettyValue = serviceList[value];
}
return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
},
renderEdit: (value, additionalData) => {
let prettyValue = value;
if (additionalData.property == 'service') {
const availableServices = this.props.services.filter(service => ((Number(service['maxCount']) == 0) || (service['currentCount'] < service['maxCount'])));
const serviceList = arrayToObject(availableServices, "id", "name");
if (additionalData.rowData.newEntry === true) {
return inlineEditFormatterImpl.renderEditSelect(value, additionalData, serviceList);
}
prettyValue = serviceList[value];
return inlineEditFormatterImpl.renderValue(prettyValue, additionalData)
}
return inlineEditFormatterImpl.renderEditText(prettyValue, additionalData);
}
});
this.inlineEditFormatter = inlineEditFormatter;
initApplicationInstance(
appDefinition,
hosts,
ansibleVarsAll,
this.headerFormatter,
this.inlineEditFormatter,
this.inlineEditButtonsFormatter,
);
};
render() {
const {
data: { mode, applications, organization, location, foremanDataUrl, appDefinitionUrl },
appDefinition,
services,
hosts,
columns,
addApplicationInstanceHost,
confirmEditApplicationInstanceHost,
cancelEditApplicationInstanceHost,
closeForemanParameterSelectionModal,
openAnsibleParameterSelectionModal,
closeAnsibleParameterSelectionModal,
loadApplicationDefinition,
} = this.props;
// Start from validation when pressing submit. This should be in componentDidMount() but
// unfortunatley then the event wasn't fired. To make sure, that the on-click is only added
// once, there is a workaround to check if a css class "bound" exists.
$('input[type="submit"][name="commit"]:not(.bound)').addClass('bound').on('click', () => this.validateParameters());
return (
cellProps.children
}
}}
>
({
role: 'row',
isEditing: () => this.isEditing({ rowData }),
onCancel: () => cancelEditApplicationInstanceHost({ rowData, rowIndex }),
onConfirm: () => confirmEditApplicationInstanceHost({ rowData, rowIndex }),
last: rowIndex === services.length - 1
})}
/>
Ansible group vars 'all':
Parameter specification
{this.props.parametersData ? (
) : (Empty)
}
Parameter specification
{this.props.parametersData ? (
) : (Empty)
}
)};
}
ApplicationInstance.defaultProps = {
error: {},
appDefinition: { "id": '', "name": '' },
editMode: false,
services: [],
hosts: [],
ansibleVarsAll: [],
parametersData: {},
columns: [],
editParamsOfRowId: null,
}
ApplicationInstance.propTypes = {
initApplicationInstance: PropTypes.func,
editMode: PropTypes.bool.isRequired,
services: PropTypes.array,
appDefinition: PropTypes.object,
columns: PropTypes.array,
hosts: PropTypes.array,
ansibleVarsAll: PropTypes.array,
loadApplicationDefinition: PropTypes.func,
addApplicationInstanceHost: PropTypes.func,
deleteApplicationInstanceHost: PropTypes.func,
activateEditApplicationInstanceHost: PropTypes.func,
confirmEditApplicationInstanceHost: PropTypes.func,
cancelEditApplicationInstanceHost: PropTypes.func,
changeEditApplicationInstanceHost: PropTypes.func,
openForemanParameterSelectionModal: PropTypes.func,
closeForemanParameterSelectionModal: PropTypes.func,
openAnsibleParameterSelectionModal: PropTypes.func,
closeAnsibleParameterSelectionModal: PropTypes.func,
parametersData: PropTypes.object,
};
export default ApplicationInstance;