Skip to content

Commit

Permalink
Add confirm modal with agent count
Browse files Browse the repository at this point in the history
  • Loading branch information
nchaulet committed Apr 8, 2020
1 parent 21f2f7f commit d22ea9f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 85 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiCallOut } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { AgentConfig } from '../../../../types';

export const ConfirmCreateDatasourceModal: React.FunctionComponent<{
onConfirm: () => void;
onCancel: () => void;
agentCount: number;
agentConfig: AgentConfig;
}> = ({ onConfirm, onCancel, agentCount, agentConfig }) => {
return (
<EuiOverlayMask>
<EuiConfirmModal
maxWidth="566px"
title={
<FormattedMessage
id="xpack.ingestManager.createDatasource.confirmModalTitle"
defaultMessage="Save and deploy changes"
/>
}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText={
<FormattedMessage
id="xpack.ingestManager.deleteApiKeys.confirmModal.cancelButtonLabel"
defaultMessage="Cancel"
/>
}
confirmButtonText={
<FormattedMessage
id="xpack.ingestManager.createDatasource.confirmModalConfirmButtonLabel"
defaultMessage="Save and deploy changes"
/>
}
buttonColor="primary"
>
<EuiCallOut
iconType="iInCircle"
title={i18n.translate('xpack.ingestManager.createDatasource.confirmModalCalloutTitle', {
defaultMessage: 'This action will update {agentCount} agents',
values: {
agentCount,
},
})}
>
<FormattedMessage
id="xpack.ingestManager.createDatasource.confirmModalCalloutDescription"
defaultMessage="Fleet has detected that the selected agent configuration, {configName}, is already in use by
some of your agents. As a result of this action, Fleet will deploy updates to all agents
that use this configuration."
values={{
configName: <b>{agentConfig.name}</b>,
}}
/>
</EuiCallOut>
<EuiSpacer size="l" />
<FormattedMessage
id="xpack.ingestManager.createDatasource.confirmModalDescription"
defaultMessage="This action can not be undone. Are you sure you wish to continue?"
/>
</EuiConfirmModal>
</EuiOverlayMask>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/
export { CreateDatasourcePageLayout } from './layout';
export { DatasourceInputPanel } from './datasource_input_panel';
export { ConfirmCreateDatasourceModal } from './confirm_modal';
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { useRouteMatch, useHistory } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
Expand All @@ -18,9 +18,15 @@ import {
import { EuiStepProps } from '@elastic/eui/src/components/steps/step';
import { AGENT_CONFIG_DETAILS_PATH } from '../../../constants';
import { AgentConfig, PackageInfo, NewDatasource } from '../../../types';
import { useLink, sendCreateDatasource, useCore } from '../../../hooks';
import {
useLink,
sendCreateDatasource,
useCore,
useConfig,
sendGetAgentStatus,
} from '../../../hooks';
import { useLinks as useEPMLinks } from '../../epm/hooks';
import { CreateDatasourcePageLayout } from './components';
import { CreateDatasourcePageLayout, ConfirmCreateDatasourceModal } from './components';
import { CreateDatasourceFrom, CreateDatasourceStep } from './types';
import { StepSelectPackage } from './step_select_package';
import { StepSelectConfig } from './step_select_config';
Expand All @@ -30,19 +36,39 @@ import { StepDefineDatasource } from './step_define_datasource';

export const CreateDatasourcePage: React.FunctionComponent = () => {
const { notifications } = useCore();
const {
fleet: { enabled: isFleetEnabled },
} = useConfig();
const {
params: { configId, pkgkey },
url: basePath,
} = useRouteMatch();
const history = useHistory();
const from: CreateDatasourceFrom = configId ? 'config' : 'package';
const [maxStep, setMaxStep] = useState<CreateDatasourceStep | ''>('');
const [isSaving, setIsSaving] = useState<boolean>(false);

// Agent config and package info states
const [agentConfig, setAgentConfig] = useState<AgentConfig>();
const [packageInfo, setPackageInfo] = useState<PackageInfo>();

const agentConfigId = agentConfig?.id;
// Retrieve agent count
useEffect(() => {
const getAgentCount = async () => {
if (agentConfigId) {
const { data } = await sendGetAgentStatus({ configId: agentConfigId });
if (data?.results.total) {
setAgentCount(data.results.total);
}
}
};

if (isFleetEnabled && agentConfigId) {
getAgentCount();
}
}, [agentConfigId, isFleetEnabled]);
const [agentCount, setAgentCount] = useState<number>(0);

// New datasource state
const [datasource, setDatasource] = useState<NewDatasource>({
name: '',
Expand Down Expand Up @@ -87,6 +113,9 @@ export const CreateDatasourcePage: React.FunctionComponent = () => {
};
setDatasource(newDatasource);

if (newDatasource.package && newDatasource.config_id && newDatasource.config_id !== '') {
setFormState('VALID');
}
// eslint-disable-next-line no-console
console.debug('Datasource updated', newDatasource);
};
Expand All @@ -102,21 +131,29 @@ export const CreateDatasourcePage: React.FunctionComponent = () => {
const cancelUrl = from === 'config' ? CONFIG_URL : PACKAGE_URL;

// Save datasource
const [formState, setFormState] = useState<
'VALID' | 'INVALID' | 'CONFIRM' | 'LOADING' | 'SUBMITTED'
>('INVALID');
const saveDatasource = async () => {
setIsSaving(true);
setFormState('LOADING');
const result = await sendCreateDatasource(datasource);
setIsSaving(false);
setFormState('SUBMITTED');
return result;
};

const onSubmit = async () => {
if (agentCount !== 0 && formState !== 'CONFIRM') {
setFormState('CONFIRM');
return;
}
const { error } = await saveDatasource();
if (!error) {
history.push(`${AGENT_CONFIG_DETAILS_PATH}${agentConfig ? agentConfig.id : configId}`);
} else {
notifications.toasts.addError(error, {
title: 'Error',
});
setFormState('VALID');
}
};

Expand Down Expand Up @@ -191,35 +228,42 @@ export const CreateDatasourcePage: React.FunctionComponent = () => {

return (
<CreateDatasourcePageLayout {...layoutProps}>
<EuiSteps steps={steps} />
{packageInfo && agentConfig && (
<EuiBottomBar>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButtonEmpty color="ghost" href={cancelUrl}>
<FormattedMessage
id="xpack.ingestManager.createDatasource.cancelButton"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={onSubmit}
isLoading={isSaving}
iconType="save"
color="primary"
fill
>
<FormattedMessage
id="xpack.ingestManager.createDatasource.saveButton"
defaultMessage="Save data source"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
{formState === 'CONFIRM' && agentConfig && (
<ConfirmCreateDatasourceModal
agentCount={agentCount}
agentConfig={agentConfig}
onConfirm={onSubmit}
onCancel={() => setFormState('VALID')}
/>
)}
<EuiSteps steps={steps} />
<EuiBottomBar>
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButtonEmpty color="ghost" href={cancelUrl}>
<FormattedMessage
id="xpack.ingestManager.createDatasource.cancelButton"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
onClick={onSubmit}
isLoading={formState === 'LOADING'}
disabled={formState !== 'VALID'}
iconType="save"
color="primary"
fill
>
<FormattedMessage
id="xpack.ingestManager.createDatasource.saveButton"
defaultMessage="Save data source"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiBottomBar>
</CreateDatasourcePageLayout>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useEffect, useState, Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiSteps,
EuiPanel,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiFieldText,
EuiButtonEmpty,
EuiSpacer,
EuiEmptyPrompt,
EuiText,
EuiButton,
EuiComboBox,
} from '@elastic/eui';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiEmptyPrompt, EuiText } from '@elastic/eui';
import {
AgentConfig,
PackageInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@
import React, { useEffect, useState, Fragment } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiPanel,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiFieldText,
EuiButtonEmpty,
EuiSpacer,
EuiEmptyPrompt,
EuiText,
EuiComboBox,
} from '@elastic/eui';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,8 @@
import React, { useEffect, useState, Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiSelectable,
EuiSpacer,
EuiTextColor,
} from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSelectable, EuiSpacer, EuiTextColor } from '@elastic/eui';
import { Error } from '../../../components';
import { AGENT_CONFIG_PATH } from '../../../constants';
import { useCapabilities, useLink } from '../../../hooks';
import { AgentConfig, PackageInfo, GetAgentConfigsResponseItem } from '../../../types';
import { useGetPackageInfoByKey, useGetAgentConfigs, sendGetOneAgentConfig } from '../../../hooks';

Expand All @@ -26,16 +17,12 @@ export const StepSelectConfig: React.FunctionComponent<{
agentConfig: AgentConfig | undefined;
updateAgentConfig: (config: AgentConfig | undefined) => void;
}> = ({ pkgkey, updatePackageInfo, agentConfig, updateAgentConfig }) => {
const hasWriteCapabilites = useCapabilities().write;
// Selected config state
const [selectedConfigId, setSelectedConfigId] = useState<string | undefined>(
agentConfig ? agentConfig.id : undefined
);
const [selectedConfigError, setSelectedConfigError] = useState<Error>();

// Todo: replace with create agent config flyout
const CREATE_NEW_CONFIG_URI = useLink(AGENT_CONFIG_PATH);

// Fetch package info
const { data: packageInfoData, error: packageInfoError } = useGetPackageInfoByKey(pkgkey);

Expand Down Expand Up @@ -115,23 +102,6 @@ export const StepSelectConfig: React.FunctionComponent<{

return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
isDisabled={!hasWriteCapabilites}
iconType="plusInCircle"
href={CREATE_NEW_CONFIG_URI}
size="s"
>
<FormattedMessage
id="xpack.ingestManager.createDatasource.StepSelectConfig.createNewConfigButtonText"
defaultMessage="Create new configuration"
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiSelectable
searchable
Expand Down

0 comments on commit d22ea9f

Please sign in to comment.