Skip to content

Commit

Permalink
Show requests for creating a follower index and creating/updating an …
Browse files Browse the repository at this point in the history
…auto-follow pattern in CCR. (elastic#42924)
  • Loading branch information
cjcenizal authored Aug 13, 2019
1 parent 9470d8a commit 2b7d676
Show file tree
Hide file tree
Showing 18 changed files with 429 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import { AutoFollowPatternIndicesPreview } from './auto_follow_pattern_indices_p
import { RemoteClustersFormField } from './remote_clusters_form_field';
import { validateAutoFollowPattern, validateLeaderIndexPattern } from '../services/auto_follow_pattern_validators';

import { AutoFollowPatternRequestFlyout } from './auto_follow_pattern_request_flyout';

const indexPatternIllegalCharacters = INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.join(' ');
const indexNameIllegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');

Expand Down Expand Up @@ -88,9 +90,16 @@ export class AutoFollowPatternForm extends PureComponent {
fieldsErrors: validateAutoFollowPattern(autoFollowPattern),
areErrorsVisible: false,
isNew,
isRequestVisible: false,
};
}

toggleRequest = () => {
this.setState(({ isRequestVisible }) => ({
isRequestVisible: !isRequestVisible,
}));
};

onFieldsChange = (fields) => {
this.setState(({ autoFollowPattern }) => ({
autoFollowPattern: {
Expand Down Expand Up @@ -590,7 +599,7 @@ export class AutoFollowPatternForm extends PureComponent {
*/
const renderActions = () => {
const { apiStatus, saveButtonLabel } = this.props;
const { areErrorsVisible } = this.state;
const { areErrorsVisible, isRequestVisible } = this.state;

if (apiStatus === API_STATUS.SAVING) {
return (
Expand All @@ -614,30 +623,49 @@ export class AutoFollowPatternForm extends PureComponent {
const isSaveDisabled = areErrorsVisible && !this.isFormValid();

return (
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton
color="secondary"
iconType="check"
onClick={this.sendForm}
fill
disabled={isSaveDisabled}
data-test-subj="submitButton"
>
{saveButtonLabel}
</EuiButton>
</EuiFlexItem>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton
color="secondary"
iconType="check"
onClick={this.sendForm}
fill
disabled={isSaveDisabled}
data-test-subj="submitButton"
>
{saveButtonLabel}
</EuiButton>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="primary"
onClick={this.cancelForm}
>
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.cancelButtonLabel"
defaultMessage="Cancel"
data-test-subj="cancelButton"
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="primary"
onClick={this.cancelForm}
onClick={this.toggleRequest}
>
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.cancelButtonLabel"
defaultMessage="Cancel"
data-test-subj="cancelButton"
/>
{isRequestVisible ? (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.hideRequestButtonLabel"
defaultMessage="Hide request"
/>
) : (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternFormm.showRequestButtonLabel"
defaultMessage="Show request"
/>
)}
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down Expand Up @@ -674,10 +702,25 @@ export class AutoFollowPatternForm extends PureComponent {
}

render() {
const {
autoFollowPattern,
isRequestVisible,
isNew,
} = this.state;

return (
<Fragment>
{this.renderForm()}
{this.renderLoading()}

{isRequestVisible ? (
<AutoFollowPatternRequestFlyout
name={autoFollowPattern.name}
autoFollowPattern={this.getFields()}
isNew={isNew}
close={() => this.setState({ isRequestVisible: false })}
/>
) : null}
</Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* 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.
*/

/*
* 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, { PureComponent } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import PropTypes from 'prop-types';

import {
EuiButtonEmpty,
EuiCodeBlock,
EuiFlyout,
EuiFlyoutBody,
EuiFlyoutFooter,
EuiFlyoutHeader,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';

import { serializeAutoFollowPattern } from '../../../common/services/auto_follow_pattern_serialization';

export class AutoFollowPatternRequestFlyout extends PureComponent {
static propTypes = {
close: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
autoFollowPattern: PropTypes.object.isRequired,
isNew: PropTypes.bool,
};

render() {
const { name, autoFollowPattern, close, isNew } = this.props;
const endpoint = `PUT /_ccr/auto_follow/${name ? name : '<autoFollowPatternName>'}`;
const payload = JSON.stringify(serializeAutoFollowPattern(autoFollowPattern), null, 2);
const request = `${endpoint}\n${payload}`;

return (
<EuiFlyout maxWidth={480} onClose={close}>
<EuiFlyoutHeader>
<EuiTitle>
<h2>
{name ? (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.requestFlyout.namedTitle"
defaultMessage="Request for '{name}'"
values={{ name }}
/>
) : (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.requestFlyout.unnamedTitle"
defaultMessage="Request"
/>
)}
</h2>
</EuiTitle>
</EuiFlyoutHeader>

<EuiFlyoutBody>
<EuiText>
<p>
{isNew ? (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.requestFlyout.createDescriptionText"
defaultMessage="This Elasticsearch request will create this auto-follow pattern."
/>
) : (
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.requestFlyout.editDescriptionText"
defaultMessage="This Elasticsearch request will update this auto-follow pattern."
/>
)}
</p>
</EuiText>

<EuiSpacer />

<EuiCodeBlock
language="json"
isCopyable
>
{request}
</EuiCodeBlock>
</EuiFlyoutBody>

<EuiFlyoutFooter>
<EuiButtonEmpty
iconType="cross"
onClick={close}
flush="left"
>
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternForm.requestFlyout.closeButtonLabel"
defaultMessage="Close"
/>
</EuiButtonEmpty>
</EuiFlyoutFooter>
</EuiFlyout>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import { extractQueryParams } from '../../services/query_params';
import { getRemoteClusterName } from '../../services/get_remote_cluster_name';
import { RemoteClustersFormField } from '../remote_clusters_form_field';

import { FollowerIndexRequestFlyout } from './follower_index_request_flyout';

const indexNameIllegalCharacters = INDEX_ILLEGAL_CHARACTERS_VISIBLE.join(' ');

const fieldToValidatorMap = advancedSettingsFields.reduce((map, advancedSetting) => {
Expand Down Expand Up @@ -121,12 +123,19 @@ export class FollowerIndexForm extends PureComponent {
areErrorsVisible: false,
areAdvancedSettingsVisible,
isValidatingIndexName: false,
isRequestVisible: false,
};

this.cachedAdvancedSettings = {};
this.validateIndexName = debounce(this.validateIndexName, 500);
}

toggleRequest = () => {
this.setState(({ isRequestVisible }) => ({
isRequestVisible: !isRequestVisible,
}));
};

onFieldsChange = (fields) => {
this.setState(updateFields(fields));

Expand Down Expand Up @@ -633,7 +642,7 @@ export class FollowerIndexForm extends PureComponent {
*/
const renderActions = () => {
const { apiStatus, saveButtonLabel } = this.props;
const { areErrorsVisible } = this.state;
const { areErrorsVisible, isRequestVisible } = this.state;

if (apiStatus === API_STATUS.SAVING) {
return (
Expand All @@ -657,30 +666,50 @@ export class FollowerIndexForm extends PureComponent {
const isSaveDisabled = areErrorsVisible && !this.isFormValid();

return (
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton
color="secondary"
iconType="check"
onClick={this.sendForm}
fill
disabled={isSaveDisabled}
data-test-subj="submitButton"
>
{saveButtonLabel}
</EuiButton>
</EuiFlexItem>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButton
color="secondary"
iconType="check"
onClick={this.sendForm}
fill
disabled={isSaveDisabled}
data-test-subj="submitButton"
>
{saveButtonLabel}
</EuiButton>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="primary"
onClick={this.cancelForm}
data-test-subj="cancelButton"
>
<FormattedMessage
id="xpack.crossClusterReplication.followerIndexForm.cancelButtonLabel"
defaultMessage="Cancel"
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>

<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="primary"
onClick={this.cancelForm}
data-test-subj="cancelButton"
onClick={this.toggleRequest}
>
<FormattedMessage
id="xpack.crossClusterReplication.followerIndexForm.cancelButtonLabel"
defaultMessage="Cancel"
/>
{isRequestVisible ? (
<FormattedMessage
id="xpack.crossClusterReplication.followerIndexForm.hideRequestButtonLabel"
defaultMessage="Hide request"
/>
) : (
<FormattedMessage
id="xpack.crossClusterReplication.followerIndexForm.showRequestButtonLabel"
defaultMessage="Show request"
/>
)}
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down Expand Up @@ -718,10 +747,23 @@ export class FollowerIndexForm extends PureComponent {
}

render() {
const {
followerIndex,
isRequestVisible,
} = this.state;

return (
<Fragment>
{this.renderForm()}
{this.renderLoading()}

{isRequestVisible ? (
<FollowerIndexRequestFlyout
name={followerIndex.name}
followerIndex={this.getFields()}
close={() => this.setState({ isRequestVisible: false })}
/>
) : null}
</Fragment>
);
}
Expand Down
Loading

0 comments on commit 2b7d676

Please sign in to comment.