diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js
index d785327431ab5..cd8012a0fa45b 100644
--- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js
+++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/auto_follow_pattern_list.js
@@ -52,7 +52,7 @@ export class AutoFollowPatternListUI extends PureComponent {
diff --git a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js
index e9544cf9b2be2..68ba6e100d1ae 100644
--- a/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js
+++ b/x-pack/plugins/cross_cluster_replication/public/app/sections/home/home.js
@@ -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';
@@ -49,37 +49,51 @@ export class CrossClusterReplicationHomeUI extends PureComponent {
return (
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
+
+
-
-
+
+
+
);
@@ -91,7 +105,7 @@ export class CrossClusterReplicationHomeUI extends PureComponent {
return (
diff --git a/x-pack/plugins/remote_clusters/public/index.scss b/x-pack/plugins/remote_clusters/public/index.scss
index 33cca267d4075..b25832255cece 100644
--- a/x-pack/plugins/remote_clusters/public/index.scss
+++ b/x-pack/plugins/remote_clusters/public/index.scss
@@ -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;
+}
diff --git a/x-pack/plugins/remote_clusters/public/sections/components/index.js b/x-pack/plugins/remote_clusters/public/sections/components/index.js
new file mode 100644
index 0000000000000..a4b2c63ec552e
--- /dev/null
+++ b/x-pack/plugins/remote_clusters/public/sections/components/index.js
@@ -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';
diff --git a/x-pack/plugins/remote_clusters/public/sections/remote_cluster_form/index.js b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/index.js
similarity index 100%
rename from x-pack/plugins/remote_clusters/public/sections/remote_cluster_form/index.js
rename to x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/index.js
diff --git a/x-pack/plugins/remote_clusters/public/sections/remote_cluster_form/remote_cluster_form.js b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/remote_cluster_form.js
similarity index 84%
rename from x-pack/plugins/remote_clusters/public/sections/remote_cluster_form/remote_cluster_form.js
rename to x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/remote_cluster_form.js
index ab7345374a1ae..6eaade2a95404 100644
--- a/x-pack/plugins/remote_clusters/public/sections/remote_cluster_form/remote_cluster_form.js
+++ b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_form/remote_cluster_form.js
@@ -34,7 +34,9 @@ import {
import {
isSeedNodeValid,
isSeedNodePortValid,
-} from '../../services';
+} from '../../../services';
+
+import { skippingDisconnectedClustersUrl } from '../../../services/documentation_links';
const defaultFields = {
name: '',
@@ -97,7 +99,7 @@ export class RemoteClusterFormUi extends Component {
errors.seeds = (
);
}
@@ -116,7 +118,7 @@ export class RemoteClusterFormUi extends Component {
this.setState({
fields: newFields,
fieldsErrors: this.getFieldsErrors(newFields),
- areErrorsVisible: false,
+ // areErrorsVisible: false,
});
};
@@ -138,9 +140,8 @@ 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,
});
@@ -148,7 +149,6 @@ export class RemoteClusterFormUi extends Component {
}
const cluster = this.getAllFields();
-
save(cluster);
};
@@ -157,6 +157,10 @@ export class RemoteClusterFormUi extends Component {
const errors = [];
+ if (!seedNode) {
+ return errors;
+ }
+
const isInvalid = !isSeedNodeValid(seedNode);
if (isInvalid) {
@@ -172,7 +176,7 @@ 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.',
}));
}
@@ -180,6 +184,11 @@ export class RemoteClusterFormUi extends Component {
};
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) {
@@ -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,
@@ -274,7 +290,7 @@ export class RemoteClusterFormUi extends Component {
@@ -284,9 +300,8 @@ export class RemoteClusterFormUi extends Component {
@@ -297,14 +312,13 @@ export class RemoteClusterFormUi extends Component {
label={(
)}
helpText={(
)}
isInvalid={showErrors}
@@ -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}
@@ -343,7 +357,7 @@ export class RemoteClusterFormUi extends Component {
@@ -353,10 +367,27 @@ export class RemoteClusterFormUi extends Component {
+
+
+ ),
+ learnMoreLink: (
+
+
+
+ ),
+ }}
/>
@@ -364,6 +395,7 @@ export class RemoteClusterFormUi extends Component {
fullWidth
>
@@ -437,6 +472,7 @@ export class RemoteClusterFormUi extends Component {
iconType="check"
onClick={this.save}
fill
+ disabled={isSaveDisabled}
>
{
- 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;
@@ -518,7 +553,7 @@ export class RemoteClusterFormUi extends Component {
title={(
)}
color="danger"
@@ -564,8 +599,7 @@ export class RemoteClusterFormUi extends Component {
description={(
)}
fullWidth
diff --git a/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/index.js b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/index.js
new file mode 100644
index 0000000000000..316cb05087725
--- /dev/null
+++ b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/index.js
@@ -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';
diff --git a/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/remote_cluster_page_title.js b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/remote_cluster_page_title.js
new file mode 100644
index 0000000000000..f8bd3535b34f1
--- /dev/null
+++ b/x-pack/plugins/remote_clusters/public/sections/components/remote_cluster_page_title/remote_cluster_page_title.js
@@ -0,0 +1,55 @@
+/*
+ * 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, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import {
+ EuiButtonEmpty,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPageContentHeader,
+ EuiSpacer,
+ EuiTitle,
+} from '@elastic/eui';
+
+import { remoteClustersUrl } from '../../../services/documentation_links';
+
+export const RemoteClusterPageTitle = ({ title }) => (
+
+
+
+
+
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+);
+
+RemoteClusterPageTitle.propTypes = {
+ title: PropTypes.node.isRequired,
+};
diff --git a/x-pack/plugins/remote_clusters/public/sections/remote_cluster_add/remote_cluster_add.js b/x-pack/plugins/remote_clusters/public/sections/remote_cluster_add/remote_cluster_add.js
index 5729eb950ff3f..9b9989705578b 100644
--- a/x-pack/plugins/remote_clusters/public/sections/remote_cluster_add/remote_cluster_add.js
+++ b/x-pack/plugins/remote_clusters/public/sections/remote_cluster_add/remote_cluster_add.js
@@ -14,14 +14,11 @@ import {
EuiPage,
EuiPageBody,
EuiPageContent,
- EuiPageContentHeader,
- EuiSpacer,
- EuiTitle,
} from '@elastic/eui';
import { CRUD_APP_BASE_PATH } from '../../constants';
import { listBreadcrumb, addBreadcrumb } from '../../services';
-import { RemoteClusterForm } from '../remote_cluster_form';
+import { RemoteClusterPageTitle, RemoteClusterForm } from '../components';
export class RemoteClusterAddUi extends Component {
static propTypes = {
@@ -61,18 +58,14 @@ export class RemoteClusterAddUi extends Component {
horizontalPosition="center"
className="remoteClusterAddPage"
>
-
-
-
-
-
-
-
-
-
+
+ )}
+ />
-
-
-
-
-
-
-
-
-
+
+ )}
+ />
{this.renderContent()}
diff --git a/x-pack/plugins/remote_clusters/public/services/documentation_links.js b/x-pack/plugins/remote_clusters/public/services/documentation_links.js
new file mode 100644
index 0000000000000..a7ccaa7df8800
--- /dev/null
+++ b/x-pack/plugins/remote_clusters/public/services/documentation_links.js
@@ -0,0 +1,12 @@
+/*
+ * 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 { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
+
+const esBase = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}`;
+
+export const skippingDisconnectedClustersUrl = `${esBase}/modules-cross-cluster-search.html#_skipping_disconnected_clusters`;
+export const remoteClustersUrl = `${esBase}/modules-remote-clusters.html`;