Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.x] Feature/translate monitoring access denied (#24985) #25718

Merged
merged 1 commit into from
Nov 20, 2018
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
12 changes: 8 additions & 4 deletions x-pack/plugins/monitoring/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';

/**
* Helper string to add as a tag in every logging call
*/
Expand Down Expand Up @@ -129,10 +131,12 @@ export const LOGSTASH = {
}
};

export const DEFAULT_NO_DATA_MESSAGE = 'There are no records that match your query. Try changing the time range selection.';
export const DEFAULT_NO_DATA_MESSAGE_WITH_FILTER = (
'There are no records that match your query with the filter [{{FILTER}}]. Try changing the filter or the time range selection.'
);
export const DEFAULT_NO_DATA_MESSAGE = i18n.translate('xpack.monitoring.defaultNoDataMessage', {
defaultMessage: 'There are no records that match your query. Try changing the time range selection.' });
export const DEFAULT_NO_DATA_MESSAGE_WITH_FILTER = i18n.translate('xpack.monitoring.defaultNoDataWithFilterMessage', {
defaultMessage:
'There are no records that match your query with the filter [{filter}]. Try changing the filter or the time range selection.',
values: { filter: '{{FILTER}}' } });

export const TABLE_ACTION_UPDATE_FILTER = 'UPDATE_FILTER';
export const TABLE_ACTION_RESET_PAGING = 'RESET_PAGING';
Expand Down
24 changes: 20 additions & 4 deletions x-pack/plugins/monitoring/public/lib/ajax_error_handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

export function formatMonitoringError(err) {
// TODO: We should stop using Boom for errors and instead write a custom handler to return richer error objects
Expand All @@ -24,7 +25,11 @@ export function formatMonitoringError(err) {
{ err.data.message }
</p>
<EuiText size="xs">
HTTP { err.status }
<FormattedMessage
id="xpack.monitoring.ajaxErrorHandler.httpErrorMessage"
defaultMessage="HTTP {errStatus}"
values={{ errStatus: err.status }}
/>
</EuiText>
</EuiText>
);
Expand All @@ -43,7 +48,11 @@ export function ajaxErrorHandlersProvider($injector) {
kbnUrl.redirect('access-denied');
} else if (err.status === 404 && !contains($window.location.hash, 'no-data')) { // pass through if this is a 404 and we're already on the no-data page
toastNotifications.addDanger({
title: 'Monitoring Request Failed',
title: (
<FormattedMessage
id="xpack.monitoring.ajaxErrorHandler.requestFailedNotificationTitle"
defaultMessage="Monitoring Request Failed"
/>),
text: (
<div>
{ formatMonitoringError(err) }
Expand All @@ -53,14 +62,21 @@ export function ajaxErrorHandlersProvider($injector) {
color="danger"
onClick={() => $window.location.reload()}
>
Retry
<FormattedMessage
id="xpack.monitoring.ajaxErrorHandler.requestFailedNotification.retryButtonLabel"
defaultMessage="Retry"
/>
</EuiButton>
</div>
)
});
} else {
toastNotifications.addDanger({
title: 'Monitoring Request Error',
title: (
<FormattedMessage
id="xpack.monitoring.ajaxErrorHandler.requestErrorNotificationTitle"
defaultMessage="Monitoring Request Error"
/>),
text: formatMonitoringError(err)
});
}
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/monitoring/public/lib/format_number.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import moment from 'moment';
import 'moment-duration-format';
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';

export function formatBytesUsage(used, max) {
return formatNumber(used, 'byte') + ' / ' + formatNumber(max, 'byte');
Expand Down Expand Up @@ -61,5 +62,5 @@ export function formatMetric(value, format, suffix, options = {}) {
}
return formatNumber(value, format) + _suffix;
}
return 'N/A';
return i18n.translate('xpack.monitoring.formatNumbers.notAvailableLabel', { defaultMessage: 'N/A' });
}
10 changes: 7 additions & 3 deletions x-pack/plugins/monitoring/public/register_feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import chrome from 'ui/chrome';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';

if (chrome.getInjected('monitoringUiEnabled')) {
FeatureCatalogueRegistryProvider.register(() => {
FeatureCatalogueRegistryProvider.register((i18n) => {
return {
id: 'monitoring',
title: 'Monitoring',
description: 'Track the real-time health and performance of your Elastic Stack.',
title: i18n('xpack.monitoring.monitoringTitle', {
defaultMessage: 'Monitoring'
}),
description: i18n('xpack.monitoring.monitoringDescription', {
defaultMessage: 'Track the real-time health and performance of your Elastic Stack.'
}),
icon: 'monitoringApp',
path: '/app/monitoring',
showOnHomePage: true,
Expand Down
59 changes: 42 additions & 17 deletions x-pack/plugins/monitoring/public/services/breadcrumbs_provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { set as setBreadcrumbs } from 'ui/chrome/services/breadcrumb_state';
import { i18n } from '@kbn/i18n';

// Helper for making objects to use in a link element
const createCrumb = (url, label, testSubj) => {
Expand All @@ -21,14 +22,20 @@ function getElasticsearchBreadcrumbs(mainInstance) {
if (mainInstance.instance) {
breadcrumbs.push(createCrumb('#/elasticsearch', 'Elasticsearch'));
if (mainInstance.name === 'indices') {
breadcrumbs.push(createCrumb('#/elasticsearch/indices', 'Indices', 'breadcrumbEsIndices'));
breadcrumbs.push(createCrumb('#/elasticsearch/indices', i18n.translate(
'xpack.monitoring.breadcrumbs.es.indicesLabel', { defaultMessage: 'Indices' }), 'breadcrumbEsIndices'));
} else if (mainInstance.name === 'nodes') {
breadcrumbs.push(createCrumb('#/elasticsearch/nodes', 'Nodes', 'breadcrumbEsNodes'));
breadcrumbs.push(createCrumb('#/elasticsearch/nodes', i18n.translate(
'xpack.monitoring.breadcrumbs.es.nodesLabel', { defaultMessage: 'Nodes' }), 'breadcrumbEsNodes'));
} else if (mainInstance.name === 'ml') {
// ML Instance (for user later)
breadcrumbs.push(createCrumb('#/elasticsearch/ml_jobs', 'Jobs'));
breadcrumbs.push(createCrumb('#/elasticsearch/ml_jobs', i18n.translate(
'xpack.monitoring.breadcrumbs.es.jobsLabel', { defaultMessage: 'Jobs' })
));
} else if (mainInstance.name === 'ccr_shard') {
breadcrumbs.push(createCrumb('#/elasticsearch/ccr', 'CCR'));
breadcrumbs.push(createCrumb('#/elasticsearch/ccr', i18n.translate(
'xpack.monitoring.breadcrumbs.es.ccrLabel', { defaultMessage: 'CCR' })
));
}
breadcrumbs.push(createCrumb(null, mainInstance.instance));
} else {
Expand All @@ -43,7 +50,9 @@ function getKibanaBreadcrumbs(mainInstance) {
const breadcrumbs = [];
if (mainInstance.instance) {
breadcrumbs.push(createCrumb('#/kibana', 'Kibana'));
breadcrumbs.push(createCrumb('#/kibana/instances', 'Instances'));
breadcrumbs.push(createCrumb('#/kibana/instances', i18n.translate(
'xpack.monitoring.breadcrumbs.kibana.instancesLabel', { defaultMessage: 'Instances' })
));
} else {
// don't link to Overview when we're possibly on Overview or its sibling tabs
breadcrumbs.push(createCrumb(null, 'Kibana'));
Expand All @@ -53,54 +62,70 @@ function getKibanaBreadcrumbs(mainInstance) {

// generate Logstash breadcrumbs
function getLogstashBreadcrumbs(mainInstance) {
const logstashLabel = i18n.translate('xpack.monitoring.breadcrumbs.logstashLabel', { defaultMessage: 'Logstash' });
const breadcrumbs = [];
if (mainInstance.instance) {
breadcrumbs.push(createCrumb('#/logstash', 'Logstash'));
breadcrumbs.push(createCrumb('#/logstash', logstashLabel));
if (mainInstance.name === 'nodes') {
breadcrumbs.push(createCrumb('#/logstash/nodes', 'Nodes'));
breadcrumbs.push(createCrumb('#/logstash/nodes', i18n.translate(
'xpack.monitoring.breadcrumbs.logstash.nodesLabel', { defaultMessage: 'Nodes' })
));
}
breadcrumbs.push(createCrumb(null, mainInstance.instance));
} else if (mainInstance.page === 'pipeline') {
breadcrumbs.push(createCrumb('#/logstash', 'Logstash'));
breadcrumbs.push(createCrumb('#/logstash/pipelines', 'Pipelines'));
breadcrumbs.push(createCrumb('#/logstash', logstashLabel));
breadcrumbs.push(createCrumb('#/logstash/pipelines', i18n.translate(
'xpack.monitoring.breadcrumbs.logstash.pipelinesLabel', { defaultMessage: 'Pipelines' })
));
} else {
// don't link to Overview when we're possibly on Overview or its sibling tabs
breadcrumbs.push(createCrumb(null, 'Logstash'));
breadcrumbs.push(createCrumb(null, logstashLabel));
}

return breadcrumbs;
}

// generate Beats breadcrumbs
function getBeatsBreadcrumbs(mainInstance) {
const beatsLabel = i18n.translate('xpack.monitoring.breadcrumbs.beatsLabel', { defaultMessage: 'Beats' });
const breadcrumbs = [];
if (mainInstance.instance) {
breadcrumbs.push(createCrumb('#/beats', 'Beats'));
breadcrumbs.push(createCrumb('#/beats/beats', 'Instances'));
breadcrumbs.push(createCrumb('#/beats', beatsLabel));
breadcrumbs.push(createCrumb('#/beats/beats', i18n.translate(
'xpack.monitoring.breadcrumbs.beats.instancesLabel', { defaultMessage: 'Instances' })
));
breadcrumbs.push(createCrumb(null, mainInstance.instance));
} else {
breadcrumbs.push(createCrumb(null, 'Beats'));
breadcrumbs.push(createCrumb(null, beatsLabel));
}

return breadcrumbs;
}

// generate Apm breadcrumbs
function getApmBreadcrumbs(mainInstance) {
const apmLabel = i18n.translate('xpack.monitoring.breadcrumbs.apmLabel', { defaultMessage: 'APM' });
const breadcrumbs = [];
if (mainInstance.instance) {
breadcrumbs.push(createCrumb('#/apm', 'APM'));
breadcrumbs.push(createCrumb('#/apm/instances', 'Instances'));
breadcrumbs.push(createCrumb('#/apm', apmLabel));
breadcrumbs.push(createCrumb('#/apm/instances', i18n.translate(
'xpack.monitoring.breadcrumbs.apm.instancesLabel', { defaultMessage: 'Instances' })
));
} else {
// don't link to Overview when we're possibly on Overview or its sibling tabs
breadcrumbs.push(createCrumb(null, 'APM'));
breadcrumbs.push(createCrumb(null, apmLabel));
}
return breadcrumbs;
}

export function breadcrumbsProvider() {
return function createBreadcrumbs(clusterName, mainInstance) {
let breadcrumbs = [ createCrumb('#/home', 'Clusters', 'breadcrumbClusters') ];
let breadcrumbs = [ createCrumb('#/home',
i18n.translate(
'xpack.monitoring.breadcrumbs.clustersLabel', { defaultMessage: 'Clusters' }
),
'breadcrumbClusters')
];

if (!mainInstance.inOverview && clusterName) {
breadcrumbs.push(createCrumb('#/overview', clusterName));
Expand Down
8 changes: 6 additions & 2 deletions x-pack/plugins/monitoring/public/services/title.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ import { uiModules } from 'ui/modules';
import { DocTitleProvider } from 'ui/doc_title';

const uiModule = uiModules.get('monitoring/title', []);
uiModule.service('title', (Private) => {
uiModule.service('title', (Private, i18n) => {
const docTitle = Private(DocTitleProvider);
return function changeTitle(cluster, suffix) {
let clusterName = _.get(cluster, 'cluster_name');
clusterName = (clusterName) ? `- ${clusterName}` : '';
suffix = (suffix) ? `- ${suffix}` : '';
docTitle.change(`Monitoring ${clusterName} ${suffix}`, true);
docTitle.change(
i18n('xpack.monitoring.monitoringDocTitle', {
defaultMessage: 'Monitoring {clusterName} {suffix}',
values: { clusterName, suffix }
}), true);
};
});
38 changes: 23 additions & 15 deletions x-pack/plugins/monitoring/public/views/access_denied/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,40 @@
<div class="kuiInfoPanel kuiInfoPanel--error">
<div class="kuiInfoPanelHeader">
<span class="kuiInfoPanelHeader__icon kuiIcon kuiIcon--error fa-warning"></span>
<span class="kuiInfoPanelHeader__title" data-test-subj="accessDeniedTitle">
Access Denied
</span>
<span
class="kuiInfoPanelHeader__title"
data-test-subj="accessDeniedTitle"
i18n-id="xpack.monitoring.accessDeniedTitle"
i18n-default-message="Access Denied"
></span>
</div>

<div class="kuiInfoPanelBody">
<div class="kuiInfoPanelBody__message">
You are not authorized to access Monitoring. To use Monitoring, you
need the privileges granted by both the `kibana_user` and
`monitoring_user` roles.
</div>
<div
class="kuiInfoPanelBody__message"
i18n-id="xpack.monitoring.accessDenied.notAuthorizedDescription"
i18n-default-message="You are not authorized to access Monitoring. To use Monitoring, you
need the privileges granted by both the `{kibanaUser}` and
`{monitoringUser}` roles."
i18n-values="{ kibanaUser: 'kibana_user', monitoringUser: 'monitoring_user' }"
></div>

<div class="kuiInfoPanelBody__message">
If you are attempting to access a dedicated monitoring cluster, this
<div
class="kuiInfoPanelBody__message"
i18n-id="xpack.monitoring.accessDenied.clusterNotConfiguredDescription"
i18n-default-message="If you are attempting to access a dedicated monitoring cluster, this
might be because you are logged in as a user that is not configured on
the monitoring cluster.
</div>
the monitoring cluster."
></div>

<div class="kuiInfoPanelBody__message">
<div class="kuiButtonGroup">
<button
ng-click="accessDenied.goToKibana();"
class="kuiButton kuiButton--primary"
>
Back to Kibana
</button>
i18n-id="xpack.monitoring.accessDenied.backToKibanaButtonLabel"
i18n-default-message="Back to Kibana"
></button>
</div>
</div>
</div>
Expand Down