Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class AutoFollowPatternListUI extends PureComponent {
<p>
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternList.emptyPromptDescription"
defaultMessage="Auto-follow patterns replicate leader indices from a remote cluster to follower indices on the local cluster." //eslint-disable-line max-len
defaultMessage="Use an auto-follow pattern to automatically replicate indices from a remote cluster."
/>
</p>
</Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import chrome from 'ui/chrome';
import { MANAGEMENT_BREADCRUMB } from 'ui/management';

import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiPage,
EuiPageBody,
EuiPageContent,
EuiPageContentHeaderSection,
EuiTitle,
EuiSpacer,
EuiPageContentHeader,
EuiButton,
EuiText,
EuiTitle,
} from '@elastic/eui';

import { listBreadcrumb } from '../../services/breadcrumbs';
Expand Down Expand Up @@ -49,37 +49,51 @@ export class CrossClusterReplicationHomeUI extends PureComponent {

return (
<Fragment>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle size="l">
<h1>
<EuiTitle size="l">
<h1>
<FormattedMessage
id="xpack.crossClusterReplication.autoFollowPatternList.crossClusterReplicationTitle"
defaultMessage="Cross Cluster Replication"
/>
</h1>
</EuiTitle>

<EuiSpacer size="s" />

<EuiFlexGroup justifyContent="spaceBetween" alignItem="center">
<EuiFlexItem grow={false}>
<EuiTitle size="m">
<h2>
<FormattedMessage
id="xpack.crossClusterReplication.crossClusterReplicationTitle"
defaultMessage="Cross Cluster Replication"
id="xpack.crossClusterReplication.autoFollowPatternList.autoFollowPatternsTitle"
defaultMessage="Auto-follow patterns"
/>
</h1>
</h2>
</EuiTitle>

<EuiText>
<p>
<FormattedMessage
id="xpack.crossClusterReplication.autofolloPatternList.sectionDescription"
id="xpack.crossClusterReplication.autoFollowPatternList.autoFollowPatternsDescription"
defaultMessage="Auto-follow patterns replicate leader indices from a remote cluster to follower indices on the local cluster." //eslint-disable-line max-len
/>
</p>
</EuiText>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiButton
{...routing.getRouterLinkProps('/auto_follow_patterns/add')}
fill
>
<FormattedMessage
id="xpack.crossClusterReplication.addAutofollowPatternButtonLabel"
id="xpack.crossClusterReplication.autoFollowPatternList.addAutofollowPatternButtonLabel"
defaultMessage="Create an auto-follow pattern"
/>
</EuiButton>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer />
</Fragment>
);
Expand All @@ -91,7 +105,7 @@ export class CrossClusterReplicationHomeUI extends PureComponent {
return (
<SectionUnauthorized>
<FormattedMessage
id="xpack.crossClusterReplication.autofollowPatternList.noPermissionText"
id="xpack.crossClusterReplication.autoFollowPatternList.noPermissionText"
defaultMessage="You do not have permission to view or add auto-follow patterns."
/>
</SectionUnauthorized>
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/remote_clusters/public/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@
max-width: 1000px !important; /* 1 */
width: 100% !important; /* 1 */
}

/**
* 1. Override EuiFormRow styles. Otherwise the switch will jump around when toggled on and off,
* as the 'Reset to defaults' link is added to and removed from the DOM.
* 2. Fix the positioning.
*/

.remoteClusterSkipIfUnavailableSwitch {
justify-content: flex-start !important; /* 1 */
padding-top: $euiSizeS !important;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export { RemoteClusterForm } from './remote_cluster_form';
export { RemoteClusterPageTitle } from './remote_cluster_page_title';
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ import {
import {
isSeedNodeValid,
isSeedNodePortValid,
} from '../../services';
} from '../../../services';

import { skippingDisconnectedClustersUrl } from '../../../services/documentation_links';

const defaultFields = {
name: '',
Expand Down Expand Up @@ -97,7 +99,7 @@ export class RemoteClusterFormUi extends Component {
errors.seeds = (
<FormattedMessage
id="xpack.remoteClusters.form.errors.seedMissing"
defaultMessage="At least one seed is required."
defaultMessage="At least one seed node is required."
/>
);
}
Expand All @@ -116,7 +118,7 @@ export class RemoteClusterFormUi extends Component {
this.setState({
fields: newFields,
fieldsErrors: this.getFieldsErrors(newFields),
areErrorsVisible: false,
// areErrorsVisible: false,
});
};

Expand All @@ -138,17 +140,15 @@ export class RemoteClusterFormUi extends Component {

save = () => {
const { save } = this.props;
const { fieldsErrors } = this.state;

if (Object.keys(fieldsErrors).length > 0) {
if (this.hasErrors()) {
this.setState({
areErrorsVisible: true,
});
return;
}

const cluster = this.getAllFields();

save(cluster);
};

Expand All @@ -157,6 +157,10 @@ export class RemoteClusterFormUi extends Component {

const errors = [];

if (!seedNode) {
return errors;
}

const isInvalid = !isSeedNodeValid(seedNode);

if (isInvalid) {
Expand All @@ -172,14 +176,19 @@ export class RemoteClusterFormUi extends Component {
if (isPortInvalid) {
errors.push(intl.formatMessage({
id: 'xpack.remoteClusters.remoteClusterForm.localSeedError.invalidPortMessage',
defaultMessage: 'Seed node must define a numeric port.',
defaultMessage: 'A port is required.',
}));
}

return errors;
};

onCreateSeed = (newSeed) => {
// If the user just hit enter without typing anything, treat it as a no-op.
if (!newSeed) {
return;
}

const localSeedErrors = this.getLocalSeedErrors(newSeed);

if (localSeedErrors.length !== 0) {
Expand Down Expand Up @@ -246,6 +255,13 @@ export class RemoteClusterFormUi extends Component {
});
};

hasErrors = () => {
const { fieldsErrors, localSeedErrors } = this.state;
const errorValues = Object.values(fieldsErrors);
const hasErrors = errorValues.some(error => error !== undefined) || localSeedErrors.length;
return hasErrors;
};

renderSeeds() {
const {
areErrorsVisible,
Expand Down Expand Up @@ -274,7 +290,7 @@ export class RemoteClusterFormUi extends Component {
<h4>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSeedsTitle"
defaultMessage="Seed nodes"
defaultMessage="Seed nodes for cluster discovery"
/>
</h4>
</EuiTitle>
Expand All @@ -284,9 +300,8 @@ export class RemoteClusterFormUi extends Component {
<p>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSeedsDescription1"
defaultMessage="When connecting to this remote cluster, its cluster state will be
retrieved from one of its seed nodes so that by default up to three gateway nodes
are selected to be connected to as part of remote cluster requests."
defaultMessage="The nodes to query to get the cluster state from the remote cluster.
Specify multiple seed nodes so discovery doesn't fail if a node is unavailable."
/>
</p>
</Fragment>
Expand All @@ -297,14 +312,13 @@ export class RemoteClusterFormUi extends Component {
label={(
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.fieldSeedsLabel"
defaultMessage="IP addresses or hostnames"
defaultMessage="Seed nodes"
/>
)}
helpText={(
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSeedsHelpText"
defaultMessage="Seed nodes can be defined as IP addresses or host names, but they
must contain a port, e.g. 127.0.0.1:9400 or localhost:9400."
defaultMessage="An IP address or host name, followed by the port."
/>
)}
isInvalid={showErrors}
Expand All @@ -315,7 +329,7 @@ export class RemoteClusterFormUi extends Component {
noSuggestions
placeholder={intl.formatMessage({
id: 'xpack.remoteClusters.remoteClusterForm.fieldSeedsPlaceholder',
defaultMessage: '127.0.0.1:9400',
defaultMessage: 'host:port',
})}
selectedOptions={formattedSeeds}
onCreateOption={this.onCreateSeed}
Expand Down Expand Up @@ -343,7 +357,7 @@ export class RemoteClusterFormUi extends Component {
<h4>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSkipUnavailableTitle"
defaultMessage="Skip unavailable"
defaultMessage="Make remote cluster optional"
/>
</h4>
</EuiTitle>
Expand All @@ -353,17 +367,35 @@ export class RemoteClusterFormUi extends Component {
<p>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSkipUnavailableDescription"
defaultMessage="Per cluster boolean setting that allows to skip specific clusters
when no nodes belonging to them are available and they are the target of a remote
cluster request. Default is false, meaning that all clusters are mandatory by default,
but they can selectively be made optional by setting this setting to true."
defaultMessage="By default, a request fails if any of the queried remote clusters
are unavailable. To continue sending a request to other remote clusters if this
cluster is unavailable, enable {optionName}. {learnMoreLink}"
values={{
optionName: (
<strong>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSkipUnavailableDescription.optionNameLabel"
defaultMessage="Skip if unavailable"
/>
</strong>
),
learnMoreLink: (
<EuiLink href={skippingDisconnectedClustersUrl} target="_blank">
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionSkipUnavailableDescription.learnMoreLinkLabel"
defaultMessage="Learn more."
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
)}
fullWidth
>
<EuiFormRow
className="remoteClusterSkipIfUnavailableSwitch"
hasEmptyLabelSpace
fullWidth
helpText={
Expand All @@ -379,7 +411,7 @@ export class RemoteClusterFormUi extends Component {
>
<EuiSwitch
label={i18n.translate('xpack.remoteClusters.remoteClusterForm.sectionSkipUnavailableLabel', {
defaultMessage: 'Skip unavailable',
defaultMessage: 'Skip if unavailable',
})}
checked={skipUnavailable}
onChange={this.onSkipUnavailableChange}
Expand All @@ -391,6 +423,7 @@ export class RemoteClusterFormUi extends Component {

renderActions() {
const { isSaving, cancel } = this.props;
const { areErrorsVisible } = this.state;

if (isSaving) {
return (
Expand Down Expand Up @@ -429,6 +462,8 @@ export class RemoteClusterFormUi extends Component {
);
}

const isSaveDisabled = areErrorsVisible && this.hasErrors();

return (
<EuiFlexGroup alignItems="center" gutterSize="m">
<EuiFlexItem grow={false}>
Expand All @@ -437,6 +472,7 @@ export class RemoteClusterFormUi extends Component {
iconType="check"
onClick={this.save}
fill
disabled={isSaveDisabled}
>
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.saveButtonLabel"
Expand Down Expand Up @@ -503,9 +539,8 @@ export class RemoteClusterFormUi extends Component {
}

renderErrors = () => {
const { areErrorsVisible, fieldsErrors } = this.state;
const errorValues = Object.values(fieldsErrors);
const hasErrors = errorValues.some(error => error !== undefined);
const { areErrorsVisible } = this.state;
const hasErrors = this.hasErrors();

if (!areErrorsVisible || !hasErrors) {
return null;
Expand All @@ -518,7 +553,7 @@ export class RemoteClusterFormUi extends Component {
title={(
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.errorTitle"
defaultMessage="Fix errors before saving."
defaultMessage="Fix errors before continuing."
/>
)}
color="danger"
Expand Down Expand Up @@ -564,8 +599,7 @@ export class RemoteClusterFormUi extends Component {
description={(
<FormattedMessage
id="xpack.remoteClusters.remoteClusterForm.sectionNameDescription"
defaultMessage="Name this remote cluster so you can easily identify
it later."
defaultMessage="A unique name for the remote cluster."
/>
)}
fullWidth
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* 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.
*/

export { RemoteClusterPageTitle } from './remote_cluster_page_title';
Loading