mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
parent
618b0bbbbe
commit
91f905c342
20 changed files with 480 additions and 141 deletions
|
@ -21,6 +21,7 @@ import 'ngreact';
|
|||
import React, { Fragment } from 'react';
|
||||
import { uiModules } from 'ui/modules';
|
||||
import chrome from 'ui/chrome';
|
||||
import { FormattedMessage, injectI18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
|
@ -43,9 +44,26 @@ const DiscoverFetchError = ({ fetchError }) => {
|
|||
|
||||
body = (
|
||||
<p>
|
||||
You can address this error by editing the ‘{fetchError.script}’ field
|
||||
in <a href={url}>Management > Index Patterns</a>,
|
||||
under the “Scripted fields” tab.
|
||||
<FormattedMessage
|
||||
id="kbn.discover.fetchError.howToAddressErrorDescription"
|
||||
defaultMessage="You can address this error by editing the {fetchErrorScript} field
|
||||
in {managementLink}, under the {scriptedFields} tab."
|
||||
values={{
|
||||
fetchErrorScript: '‘' + fetchError.script + '’',
|
||||
scriptedFields: <FormattedMessage
|
||||
id="kbn.discover.fetchError.scriptedFieldsText"
|
||||
defaultMessage="“Scripted fields”"
|
||||
/>,
|
||||
managementLink: (
|
||||
<a href={url}>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.fetchError.managmentLinkText"
|
||||
defaultMessage="Management > Index Patterns"
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
@ -77,4 +95,4 @@ const DiscoverFetchError = ({ fetchError }) => {
|
|||
|
||||
const app = uiModules.get('apps/discover', ['react']);
|
||||
|
||||
app.directive('discoverFetchError', reactDirective => reactDirective(DiscoverFetchError));
|
||||
app.directive('discoverFetchError', reactDirective => reactDirective(injectI18nProvider(DiscoverFetchError)));
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
ng-if="field.name !== '_source'"
|
||||
ng-click="toggleDisplay(field)"
|
||||
ng-class="::field.display ? 'kuiButton--danger' : 'kuiButton--primary'"
|
||||
ng-bind="::field.display ? 'remove' : 'add'"
|
||||
ng-bind="::addRemoveButtonLabel"
|
||||
class="dscSidebarItem__action kuiButton kuiButton--small"
|
||||
data-test-subj="fieldToggle-{{::field.name}}"
|
||||
></button>
|
||||
|
|
|
@ -26,7 +26,7 @@ import detailsHtml from './lib/detail_views/string.html';
|
|||
import { uiModules } from 'ui/modules';
|
||||
const app = uiModules.get('apps/discover');
|
||||
|
||||
app.directive('discoverField', function ($compile) {
|
||||
app.directive('discoverField', function ($compile, i18n) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: html,
|
||||
|
@ -42,11 +42,18 @@ app.directive('discoverField', function ($compile) {
|
|||
let detailsElem;
|
||||
let detailScope;
|
||||
|
||||
|
||||
const init = function () {
|
||||
if ($scope.field.details) {
|
||||
$scope.toggleDetails($scope.field, true);
|
||||
}
|
||||
|
||||
$scope.addRemoveButtonLabel = $scope.field.display
|
||||
? i18n('kbn.discover.fieldChooser.discoverField.removeButtonLabel', {
|
||||
defaultMessage: 'remove',
|
||||
})
|
||||
: i18n('kbn.discover.fieldChooser.discoverField.addButtonLabel', {
|
||||
defaultMessage: 'add',
|
||||
});
|
||||
};
|
||||
|
||||
const getWarnings = function (field) {
|
||||
|
@ -92,6 +99,18 @@ app.directive('discoverField', function ($compile) {
|
|||
$scope.onShowDetails(field, recompute);
|
||||
detailScope = $scope.$new();
|
||||
detailScope.warnings = getWarnings(field);
|
||||
detailScope.getBucketAriaLabel = (bucket) => {
|
||||
return i18n('kbn.discover.fieldChooser.discoverField.bucketAriaLabel', {
|
||||
defaultMessage: 'Value: {value}',
|
||||
values: {
|
||||
value: bucket.display === ''
|
||||
? i18n('kbn.discover.fieldChooser.discoverField.emptyStringText', {
|
||||
defaultMessage: 'Empty string',
|
||||
})
|
||||
: bucket.display,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
detailsElem = $(detailsHtml);
|
||||
$compile(detailsElem)(detailScope);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<section class="sidebar-list" aria-label="Index and fields">
|
||||
<section class="sidebar-list" aria-label="{{::'kbn.discover.fieldChooser.filter.indexAndFieldsSectionAriaLabel' | i18n: {defaultMessage: 'Index and fields'} }}">
|
||||
<div ng-show="indexPatternList.length > 1">
|
||||
<ui-select
|
||||
class="index-pattern-selection"
|
||||
|
@ -32,9 +32,13 @@
|
|||
</div>
|
||||
|
||||
<div class="dscSidebar__listHeader sidebar-list-header" ng-if="fields.length">
|
||||
<h3 class="sidebar-list-header-label" id="selected_fields" tabindex="0">
|
||||
Selected fields
|
||||
</h3>
|
||||
<h3
|
||||
class="sidebar-list-header-label"
|
||||
id="selected_fields"
|
||||
tabindex="0"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.selectedFieldsTitle"
|
||||
i18n-default-message="Selected fields"
|
||||
></h3>
|
||||
</div>
|
||||
<ul class="list-unstyled dscFieldList--selected" >
|
||||
<discover-field
|
||||
|
@ -49,9 +53,13 @@
|
|||
</ul>
|
||||
|
||||
<div class="sidebar-list-header sidebar-item euiFlexGroup euiFlexGroup--gutterMedium" ng-if="fields.length">
|
||||
<h3 class="euiFlexItem sidebar-list-header-label" id="available_fields" tabindex="0">
|
||||
Available fields
|
||||
</h3>
|
||||
<h3
|
||||
class="euiFlexItem sidebar-list-header-label"
|
||||
id="available_fields"
|
||||
tabindex="0"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.availableFieldsTitle"
|
||||
i18n-default-message="Available fields"
|
||||
></h3>
|
||||
|
||||
<div class="euiFlexItem euiFlexItem--flexGrowZero">
|
||||
<button
|
||||
|
@ -72,7 +80,7 @@
|
|||
ng-class="{ 'kuiButton--basic': !filter.active, 'kuiButton--primary': filter.active, 'hidden-xs': !$parent.showFields, 'hidden-sm': !$parent.showFields }"
|
||||
class="kuiButton kuiButton--small pull-right discover-field-filter-toggle"
|
||||
ng-click="$parent.showFilter = !$parent.showFilter"
|
||||
aria-label="{{$parent.showFilter ? 'Hide' : 'Show'}} field settings"
|
||||
aria-label="{{toggleFieldFilterButtonAriaLabel}}"
|
||||
aria-expanded="{{!!$parent.showFilter}}"
|
||||
aria-controls="discoverFieldFilter"
|
||||
data-test-subj="toggleFieldFilterButton"
|
||||
|
@ -85,9 +93,11 @@
|
|||
<div class="sidebar-item dscFieldDetails" ng-show="showFilter" id="discoverFieldFilter" data-test-subj="discoverFieldFilter">
|
||||
<form role="form">
|
||||
<div class="form-group">
|
||||
<label for="discoverFieldChooserFilterAggregatable">
|
||||
Aggregatable
|
||||
</label>
|
||||
<label
|
||||
for="discoverFieldChooserFilterAggregatable"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.aggregatableLabel"
|
||||
i18n-default-message="Aggregatable"
|
||||
></label>
|
||||
<select
|
||||
id="discoverFieldChooserFilterAggregatable"
|
||||
ng-options="opt.value as opt.label for opt in filter.boolOpts"
|
||||
|
@ -96,9 +106,11 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="discoverFieldChooserFilterSearchable">
|
||||
Searchable
|
||||
</label>
|
||||
<label
|
||||
for="discoverFieldChooserFilterSearchable"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.searchableLabel"
|
||||
i18n-default-message="Searchable"
|
||||
></label>
|
||||
<select
|
||||
id="discoverFieldChooserFilterSearchable"
|
||||
ng-options="opt.value as opt.label for opt in filter.boolOpts"
|
||||
|
@ -107,9 +119,11 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="discoverFieldChooserFilterType">
|
||||
Type
|
||||
</label>
|
||||
<label
|
||||
for="discoverFieldChooserFilterType"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.typeLabel"
|
||||
i18n-default-message="Type"
|
||||
></label>
|
||||
<select
|
||||
id="discoverFieldChooserFilterType"
|
||||
ng-options="field as field for field in fieldTypes"
|
||||
|
@ -118,9 +132,11 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="discoverFieldChooserFilterFieldName">
|
||||
Field name
|
||||
</label>
|
||||
<label
|
||||
for="discoverFieldChooserFilterFieldName"
|
||||
i18n-id="kbn.discover.fieldChooser.filter.fieldNameLabel"
|
||||
i18n-default-message="Field name"
|
||||
></label>
|
||||
<input
|
||||
id="discoverFieldChooserFilterFieldName"
|
||||
type="text"
|
||||
|
@ -131,16 +147,19 @@
|
|||
<div class="form-group">
|
||||
<label for="discoverFieldChooserHideMissingFields">
|
||||
<input id="discoverFieldChooserHideMissingFields" type="checkbox" ng-model="filter.vals.missing">
|
||||
Hide missing fields
|
||||
<span
|
||||
i18n-id="kbn.discover.fieldChooser.filter.hideMissingFieldsLabel"
|
||||
i18n-default-message="Hide missing fields"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
<button
|
||||
ng-click="filter.reset()"
|
||||
ng-disabled="!filter.active"
|
||||
class="kuiButton kuiButton--danger kuiButton--fullWidth"
|
||||
>
|
||||
Reset filters
|
||||
</button>
|
||||
i18n-id="kbn.discover.fieldChooser.filter.resetFiltersButtonLabel"
|
||||
i18n-default-message="Reset filters"
|
||||
></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -149,7 +168,10 @@
|
|||
ng-class="{ 'hidden-sm': !showFields, 'hidden-xs': !showFields }"
|
||||
class="list-unstyled sidebar-well dscFieldList--popular">
|
||||
<li class="sidebar-item sidebar-list-header">
|
||||
<h6>Popular</h6>
|
||||
<h6
|
||||
i18n-id="kbn.discover.fieldChooser.filter.popularTitle"
|
||||
i18n-default-message="Popular"
|
||||
></h6>
|
||||
</li>
|
||||
<discover-field
|
||||
ng-repeat="field in popularFields | filter:filter.isFieldFiltered"
|
||||
|
|
|
@ -31,7 +31,7 @@ import { uiModules } from 'ui/modules';
|
|||
import fieldChooserTemplate from './field_chooser.html';
|
||||
const app = uiModules.get('apps/discover');
|
||||
|
||||
app.directive('discFieldChooser', function ($location, globalState, config, $route) {
|
||||
app.directive('discFieldChooser', function ($location, globalState, config, $route, i18n) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
|
@ -47,6 +47,16 @@ app.directive('discFieldChooser', function ($location, globalState, config, $rou
|
|||
},
|
||||
template: fieldChooserTemplate,
|
||||
link: function ($scope) {
|
||||
$scope.$parent.$watch('showFilter', () =>{
|
||||
$scope.toggleFieldFilterButtonAriaLabel = $scope.$parent.showFilter
|
||||
? i18n('kbn.discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel', {
|
||||
defaultMessage: 'Hide field settings',
|
||||
})
|
||||
: i18n('kbn.discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel', {
|
||||
defaultMessage: 'Show field settings',
|
||||
});
|
||||
});
|
||||
|
||||
$scope.selectedIndexPattern = $scope.indexPatternList.find(
|
||||
(pattern) => pattern.id === $scope.indexPattern.id
|
||||
);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<div class="dscFieldDetails">
|
||||
<div class="kuiVerticalRhythmSmall">
|
||||
<p class="euiText euiText--extraSmall euiTextColor--subdued" ng-show="!field.details.error">
|
||||
Top 5 values in
|
||||
<span
|
||||
i18n-id="kbn.discover.fieldChooser.detailViews.topValuesInRecordsDescription"
|
||||
i18n-default-message="Top 5 values in"
|
||||
></span>
|
||||
<span ng-if="!field.details.error">
|
||||
<a
|
||||
class="kuiLink"
|
||||
|
@ -14,7 +17,11 @@
|
|||
ng-show="field.indexPattern.metaFields.includes(field.name) || field.scripted">
|
||||
{{::field.details.exists}}
|
||||
</span>
|
||||
/ {{::field.details.total}} records
|
||||
/ {{::field.details.total}}
|
||||
<span
|
||||
i18n-id="kbn.discover.fieldChooser.detailViews.recordsText"
|
||||
i18n-default-message="records"
|
||||
></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
|
@ -30,9 +37,14 @@
|
|||
css-truncate
|
||||
css-truncate-expandable="true"
|
||||
class="dscFieldDetails__value"
|
||||
aria-label="Value: {{:: bucket.display === '' ? 'Empty string' : bucket.display }}"
|
||||
aria-label="{{::getBucketAriaLabel(bucket)}}"
|
||||
>
|
||||
{{::bucket.display}} <em ng-show="bucket.display === ''">Empty string</em>
|
||||
{{::bucket.display}}
|
||||
<em
|
||||
ng-show="bucket.display === ''"
|
||||
i18n-id="kbn.discover.fieldChooser.detailViews.emptyStringText"
|
||||
i18n-default-message="Empty string"
|
||||
></em>
|
||||
</div>
|
||||
|
||||
<!-- Add/remove filter buttons -->
|
||||
|
@ -43,7 +55,7 @@
|
|||
<button
|
||||
class="dscFieldDetailsItem__button"
|
||||
ng-click="onAddFilter(field, bucket.value, '+')"
|
||||
aria-label="Filter for this value"
|
||||
aria-label="{{::'kbn.discover.fieldChooser.detailViews.filterValueButtonAriaLabel' | i18n: {defaultMessage: 'Filter for this value'} }}"
|
||||
data-test-subj="plus-{{::field.name}}-{{::bucket.display}}"
|
||||
>
|
||||
<span
|
||||
|
@ -55,7 +67,7 @@
|
|||
<button
|
||||
class="dscFieldDetailsItem__button"
|
||||
ng-click="onAddFilter(field, bucket.value, '-')"
|
||||
aria-label="Filter out this value"
|
||||
aria-label="{{::'kbn.discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel' | i18n: {defaultMessage: 'Filter out this value'} }}"
|
||||
data-test-subj="minus-{{::field.name}}-{{::bucket.display}}"
|
||||
>
|
||||
<span
|
||||
|
@ -84,9 +96,16 @@
|
|||
class="kuiButton kuiButton--secondary kuiButton--small kuiButton--fullWidth kuiVerticalRhythmSmall"
|
||||
data-test-subj="fieldVisualize-{{::field.name}}"
|
||||
>
|
||||
Visualize
|
||||
<span
|
||||
i18n-id="kbn.discover.fieldChooser.detailViews.visualizeLinkText"
|
||||
i18n-default-message="Visualize"
|
||||
></span>
|
||||
<span class="discover-field-vis-warning" ng-show="warnings.length" tooltip="{{warnings.join(' ')}}">
|
||||
( {{::warnings.length}} <ng-pluralize count="warnings.length" when="{'1':'warning', 'other':'warnings'}"></ng-pluralize> <i aria-hidden="true" class="fa fa-warning"></i> )
|
||||
( <span
|
||||
i18n-id="kbn.discover.fieldChooser.detailViews.warningsText"
|
||||
i18n-default-message="{warningsLength, plural, one {# warning} other {# warnings}}"
|
||||
i18n-values="{ warningsLength: warnings.length }"
|
||||
></span> <i aria-hidden="true" class="fa fa-warning"></i> )
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
function getFieldValues(hits, field) {
|
||||
const name = field.name;
|
||||
|
@ -38,7 +39,9 @@ function getFieldValueCounts(params) {
|
|||
|| params.field.type === 'geo_shape'
|
||||
|| params.field.type === 'attachment'
|
||||
) {
|
||||
return { error: 'Analysis is not available for geo fields.' };
|
||||
return { error: i18n.translate('kbn.discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage', {
|
||||
defaultMessage: 'Analysis is not available for geo fields.',
|
||||
}) };
|
||||
}
|
||||
|
||||
const allValues = getFieldValues(params.hits, params.field);
|
||||
|
@ -59,9 +62,13 @@ function getFieldValueCounts(params) {
|
|||
|
||||
if (params.hits.length - missing === 0) {
|
||||
return {
|
||||
error: 'This field is present in your Elasticsearch mapping' +
|
||||
' but not in the ' + params.hits.length + ' documents shown in the doc table.' +
|
||||
' You may still be able to visualize or search on it.'
|
||||
error: i18n.translate('kbn.discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage', {
|
||||
// eslint-disable-next-line max-len
|
||||
defaultMessage: 'This field is present in your Elasticsearch mapping but not in the {hitsLength} documents shown in the doc table. You may still be able to visualize or search on it.',
|
||||
values: {
|
||||
hitsLength: params.hits.length,
|
||||
},
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -89,7 +96,9 @@ function _groupValues(allValues, params) {
|
|||
|
||||
allValues.forEach(function (value) {
|
||||
if (_.isObject(value) && !Array.isArray(value)) {
|
||||
throw new Error('Analysis is not available for object fields');
|
||||
throw new Error(i18n.translate('kbn.discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage', {
|
||||
defaultMessage: 'Analysis is not available for object fields.',
|
||||
}));
|
||||
}
|
||||
|
||||
if (Array.isArray(value) && !params.grouped) {
|
||||
|
|
|
@ -64,7 +64,6 @@ import { showOpenSearchPanel } from '../top_nav/show_open_search_panel';
|
|||
import { tabifyAggResponse } from 'ui/agg_response/tabify';
|
||||
import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal';
|
||||
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
const app = uiModules.get('apps/discover', [
|
||||
'kibana/notify',
|
||||
|
@ -157,6 +156,7 @@ function discoverController(
|
|||
courier,
|
||||
kbnUrl,
|
||||
localStorage,
|
||||
i18n,
|
||||
) {
|
||||
const Vis = Private(VisProvider);
|
||||
const docTitle = Private(DocTitleProvider);
|
||||
|
@ -191,13 +191,21 @@ function discoverController(
|
|||
};
|
||||
|
||||
$scope.topNavMenu = [{
|
||||
key: 'new',
|
||||
description: 'New Search',
|
||||
key: i18n('kbn.discover.localMenu.localMenu.newSearchTitle', {
|
||||
defaultMessage: 'new',
|
||||
}),
|
||||
description: i18n('kbn.discover.localMenu.newSearchDescription', {
|
||||
defaultMessage: 'New Search',
|
||||
}),
|
||||
run: function () { kbnUrl.change('/discover'); },
|
||||
testId: 'discoverNewButton',
|
||||
}, {
|
||||
key: 'save',
|
||||
description: 'Save Search',
|
||||
key: i18n('kbn.discover.localMenu.saveTitle', {
|
||||
defaultMessage: 'save',
|
||||
}),
|
||||
description: i18n('kbn.discover.localMenu.saveSearchDescription', {
|
||||
defaultMessage: 'Save Search',
|
||||
}),
|
||||
testId: 'discoverSaveButton',
|
||||
run: async () => {
|
||||
const onSave = ({ newTitle, newCopyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate }) => {
|
||||
|
@ -229,8 +237,12 @@ function discoverController(
|
|||
showSaveModal(saveModal);
|
||||
}
|
||||
}, {
|
||||
key: 'open',
|
||||
description: 'Open Saved Search',
|
||||
key: i18n('kbn.discover.localMenu.openTitle', {
|
||||
defaultMessage: 'open',
|
||||
}),
|
||||
description: i18n('kbn.discover.localMenu.openSavedSearchDescription', {
|
||||
defaultMessage: 'Open Saved Search',
|
||||
}),
|
||||
testId: 'discoverOpenButton',
|
||||
run: () => {
|
||||
showOpenSearchPanel({
|
||||
|
@ -240,8 +252,12 @@ function discoverController(
|
|||
});
|
||||
}
|
||||
}, {
|
||||
key: 'share',
|
||||
description: 'Share Search',
|
||||
key: i18n('kbn.discover.localMenu.shareTitle', {
|
||||
defaultMessage: 'share',
|
||||
}),
|
||||
description: i18n('kbn.discover.localMenu.shareSearchDescription', {
|
||||
defaultMessage: 'Share Search',
|
||||
}),
|
||||
testId: 'shareTopNavButton',
|
||||
run: async (menuItem, navController, anchorElement) => {
|
||||
const sharingData = await this.getSharingData();
|
||||
|
@ -260,8 +276,12 @@ function discoverController(
|
|||
});
|
||||
}
|
||||
}, {
|
||||
key: 'inspect',
|
||||
description: 'Open Inspector for search',
|
||||
key: i18n('kbn.discover.localMenu.inspectTitle', {
|
||||
defaultMessage: 'inspect',
|
||||
}),
|
||||
description: i18n('kbn.discover.localMenu.openInspectorForSearchDescription', {
|
||||
defaultMessage: 'Open Inspector for search',
|
||||
}),
|
||||
testId: 'openInspectorButton',
|
||||
run() {
|
||||
Inspector.open(inspectorAdapters, {
|
||||
|
@ -295,8 +315,7 @@ function discoverController(
|
|||
|
||||
const pageTitleSuffix = savedSearch.id && savedSearch.title ? `: ${savedSearch.title}` : '';
|
||||
docTitle.change(`Discover${pageTitleSuffix}`);
|
||||
|
||||
const discoverBreadcrumbsTitle = i18n.translate('kbn.discover.discoverBreadcrumbsTitle', {
|
||||
const discoverBreadcrumbsTitle = i18n('kbn.discover.discoverBreadcrumbTitle', {
|
||||
defaultMessage: 'Discover',
|
||||
});
|
||||
|
||||
|
@ -397,8 +416,20 @@ function discoverController(
|
|||
|
||||
$scope.getBucketIntervalToolTipText = () => {
|
||||
return (
|
||||
`This interval creates ${$scope.bucketInterval.scale > 1 ? 'buckets that are too large' : 'too many buckets'}
|
||||
to show in the selected time range, so it has been scaled to ${$scope.bucketInterval.description }`
|
||||
i18n('kbn.discover.bucketIntervalTooltip', {
|
||||
// eslint-disable-next-line max-len
|
||||
defaultMessage: 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}',
|
||||
values: {
|
||||
bucketsDescription: $scope.bucketInterval.scale > 1
|
||||
? i18n('kbn.discover.bucketIntervalTooltip.tooLargeBucketsText', {
|
||||
defaultMessage: 'buckets that are too large',
|
||||
})
|
||||
: i18n('kbn.discover.bucketIntervalTooltip.tooManyBucketsText', {
|
||||
defaultMessage: 'too many buckets',
|
||||
}),
|
||||
bucketIntervalDescription: $scope.bucketInterval.description,
|
||||
},
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -544,7 +575,12 @@ function discoverController(
|
|||
stateMonitor.setInitialState($state.toJSON());
|
||||
if (id) {
|
||||
toastNotifications.addSuccess({
|
||||
title: `Search '${savedSearch.title}' was saved`,
|
||||
title: i18n('kbn.discover.notifications.savedSearchTitle', {
|
||||
defaultMessage: `Search '{savedSearchTitle}' was saved`,
|
||||
values: {
|
||||
savedSearchTitle: savedSearch.title,
|
||||
}
|
||||
}),
|
||||
'data-test-subj': 'saveSearchSuccess',
|
||||
});
|
||||
|
||||
|
@ -560,7 +596,12 @@ function discoverController(
|
|||
return { id };
|
||||
} catch(saveError) {
|
||||
toastNotifications.addDanger({
|
||||
title: `Search '${savedSearch.title}' was not saved.`,
|
||||
title: i18n('kbn.discover.notifications.notSavedSearchTitle', {
|
||||
defaultMessage: `Search '{savedSearchTitle}' was not saved.`,
|
||||
values: {
|
||||
savedSearchTitle: savedSearch.title,
|
||||
}
|
||||
}),
|
||||
text: saveError.message
|
||||
});
|
||||
return { error: saveError };
|
||||
|
@ -657,9 +698,16 @@ function discoverController(
|
|||
|
||||
if (status.remaining > 0) {
|
||||
const inspectorRequest = inspectorAdapters.requests.start(
|
||||
`Segment ${$scope.fetchStatus.complete}`,
|
||||
i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle', {
|
||||
defaultMessage: 'Segment {fetchCompleteStatus}',
|
||||
values: {
|
||||
fetchCompleteStatus: $scope.fetchStatus.complete,
|
||||
}
|
||||
}),
|
||||
{
|
||||
description: `This request queries Elasticsearch to fetch the data for the search.`,
|
||||
description: i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription', {
|
||||
defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.',
|
||||
}),
|
||||
});
|
||||
inspectorRequest.stats(getRequestInspectorStats($scope.searchSource));
|
||||
$scope.searchSource.getSearchRequestBody().then(body => {
|
||||
|
@ -887,19 +935,36 @@ function discoverController(
|
|||
}
|
||||
|
||||
if (stateVal && !stateValFound) {
|
||||
const warningTitle = `"${stateVal}" is not a configured index pattern ID`;
|
||||
const warningTitle = i18n('kbn.discover.valueIsNotConfiguredIndexPatternIDWarningTitle', {
|
||||
defaultMessage: '{stateVal} is not a configured index pattern ID',
|
||||
values: {
|
||||
stateVal: `"${stateVal}"`,
|
||||
},
|
||||
});
|
||||
|
||||
if (ownIndexPattern) {
|
||||
toastNotifications.addWarning({
|
||||
title: warningTitle,
|
||||
text: `Showing the saved index pattern: "${ownIndexPattern.title}" (${ownIndexPattern.id})`,
|
||||
text: i18n('kbn.discover.showingSavedIndexPatternWarningDescription', {
|
||||
defaultMessage: 'Showing the saved index pattern: "{ownIndexPatternTitle}" ({ownIndexPatternId})',
|
||||
values: {
|
||||
ownIndexPatternTitle: ownIndexPattern.title,
|
||||
ownIndexPatternId: ownIndexPattern.id,
|
||||
},
|
||||
}),
|
||||
});
|
||||
return ownIndexPattern;
|
||||
}
|
||||
|
||||
toastNotifications.addWarning({
|
||||
title: warningTitle,
|
||||
text: `Showing the default index pattern: "${loadedIndexPattern.title}" (${loadedIndexPattern.id})`,
|
||||
text: i18n('kbn.discover.showingDefaultIndexPatternWarningDescription', {
|
||||
defaultMessage: 'Showing the default index pattern: "{loadedIndexPatternTitle}" ({loadedIndexPatternId})',
|
||||
values: {
|
||||
loadedIndexPatternTitle: loadedIndexPattern.title,
|
||||
loadedIndexPatternId: loadedIndexPattern.id,
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { get } from 'lodash';
|
||||
|
||||
export function getPainlessError(error: Error) {
|
||||
|
@ -38,7 +39,10 @@ export function getPainlessError(error: Error) {
|
|||
return {
|
||||
lang,
|
||||
script,
|
||||
message: `Error with Painless scripted field '${script}'`,
|
||||
message: i18n.translate('kbn.discover.painlessError.painlessScriptedFieldErrorMessage', {
|
||||
defaultMessage: "Error with Painless scripted field '{script}'.",
|
||||
values: { script },
|
||||
}),
|
||||
error: error.message,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -317,9 +317,9 @@ Array [
|
|||
class="euiText euiText--extraSmall"
|
||||
>
|
||||
<strong>
|
||||
Index ‘A’
|
||||
Index ‘A’
|
||||
</strong>
|
||||
, shard ‘1’
|
||||
, shard ‘1’
|
||||
</div>
|
||||
<div
|
||||
class="euiSpacer euiSpacer--s"
|
||||
|
@ -346,9 +346,9 @@ Array [
|
|||
class="euiText euiText--extraSmall"
|
||||
>
|
||||
<strong>
|
||||
Index ‘B’
|
||||
Index ‘B’
|
||||
</strong>
|
||||
, shard ‘2’
|
||||
, shard ‘2’
|
||||
</div>
|
||||
<div
|
||||
class="euiSpacer euiSpacer--s"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import 'ngreact';
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { injectI18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
import {
|
||||
DiscoverNoResults,
|
||||
|
@ -32,9 +33,9 @@ import './timechart';
|
|||
|
||||
const app = uiModules.get('apps/discover', ['react']);
|
||||
|
||||
app.directive('discoverNoResults', reactDirective => reactDirective(DiscoverNoResults));
|
||||
app.directive('discoverNoResults', reactDirective => reactDirective(injectI18nProvider(DiscoverNoResults)));
|
||||
|
||||
app.directive(
|
||||
'discoverUnsupportedIndexPattern',
|
||||
reactDirective => reactDirective(DiscoverUnsupportedIndexPattern, ['unsupportedType'])
|
||||
reactDirective => reactDirective(injectI18nProvider(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
|
||||
);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
|
@ -61,7 +62,24 @@ export class DiscoverNoResults extends Component {
|
|||
const failures = shardFailures.map((failure, index) => (
|
||||
<div key={`${failure.index}${failure.shard}${failure.reason}`}>
|
||||
<EuiText size="xs">
|
||||
<strong>Index ‘{failure.index}’</strong>, shard ‘{failure.shard}’
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.indexFailureShardText"
|
||||
defaultMessage="{index}, shard {failureShard}"
|
||||
values={{
|
||||
index: (
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.indexFailureIndexText"
|
||||
defaultMessage="Index {failureIndex}"
|
||||
values={{
|
||||
failureIndex: `‘${failure.index}’`,
|
||||
}}
|
||||
/>
|
||||
</strong>
|
||||
),
|
||||
failureShard: `‘${failure.shard}’`,
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
@ -80,11 +98,17 @@ export class DiscoverNoResults extends Component {
|
|||
|
||||
<EuiText>
|
||||
<h3>
|
||||
Address shard failures
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.addressShardFailuresTitle"
|
||||
defaultMessage="Address shard failures"
|
||||
/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
The following shard failures occurred:
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.shardFailuresDescription"
|
||||
defaultMessage="The following shard failures occurred:"
|
||||
/>
|
||||
</p>
|
||||
|
||||
{failures}
|
||||
|
@ -102,21 +126,33 @@ export class DiscoverNoResults extends Component {
|
|||
|
||||
<EuiText>
|
||||
<h3>
|
||||
Expand your time range
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.expandYourTimeRangeTitle"
|
||||
defaultMessage="Expand your time range"
|
||||
/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
One or more of the indices you’re looking at contains a date field. Your query may
|
||||
not match anything in the current time range, or there may not be any data at all in
|
||||
the currently selected time range. You can try {(
|
||||
<EuiLink
|
||||
data-test-subj="discoverNoResultsTimefilter"
|
||||
onClick={this.onClickTimePickerButton}
|
||||
aria-expanded={isTimePickerOpen}
|
||||
>
|
||||
opening the time picker
|
||||
</EuiLink>
|
||||
)} and changing the time range to one which contains data.
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.queryMayNotMatchTitle"
|
||||
defaultMessage="One or more of the indices you’re looking at contains a date field. Your query may
|
||||
not match anything in the current time range, or there may not be any data at all in
|
||||
the currently selected time range. You can try {timepickerLink} and changing the time range to one which contains data."
|
||||
values={{
|
||||
timepickerLink: (
|
||||
<EuiLink
|
||||
data-test-subj="discoverNoResultsTimefilter"
|
||||
onClick={this.onClickTimePickerButton}
|
||||
aria-expanded={isTimePickerOpen}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.openingTimepickerLinkText"
|
||||
defaultMessage="opening the time picker"
|
||||
/>
|
||||
</EuiLink>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
|
||||
</EuiText>
|
||||
|
@ -129,19 +165,64 @@ export class DiscoverNoResults extends Component {
|
|||
if (queryLanguage === 'lucene') {
|
||||
const searchExamples = [{
|
||||
description: <EuiCode>200</EuiCode>,
|
||||
title: <EuiText><strong>Find requests that contain the number 200, in any field</strong></EuiText>,
|
||||
title: (
|
||||
<EuiText>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.anyField200StatusCodeExampleTitle"
|
||||
defaultMessage="Find requests that contain the number 200, in any field"
|
||||
/>
|
||||
</strong>
|
||||
</EuiText>
|
||||
),
|
||||
}, {
|
||||
description: <EuiCode>status:200</EuiCode>,
|
||||
title: <EuiText><strong>Find 200 in the status field</strong></EuiText>,
|
||||
title: (
|
||||
<EuiText>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.statusField200StatusCodeExampleTitle"
|
||||
defaultMessage="Find 200 in the status field"
|
||||
/>
|
||||
</strong>
|
||||
</EuiText>
|
||||
),
|
||||
}, {
|
||||
description: <EuiCode>status:[400 TO 499]</EuiCode>,
|
||||
title: <EuiText><strong>Find all status codes between 400-499</strong></EuiText>,
|
||||
title: (
|
||||
<EuiText>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.400to499StatusCodeExampleTitle"
|
||||
defaultMessage="Find all status codes between 400-499"
|
||||
/>
|
||||
</strong>
|
||||
</EuiText>
|
||||
),
|
||||
}, {
|
||||
description: <EuiCode>status:[400 TO 499] AND extension:PHP</EuiCode>,
|
||||
title: <EuiText><strong>Find status codes 400-499 with the extension php</strong></EuiText>,
|
||||
title: (
|
||||
<EuiText>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.400to499StatusCodeWithPhpExtensionExampleTitle"
|
||||
defaultMessage="Find status codes 400-499 with the extension php"
|
||||
/>
|
||||
</strong>
|
||||
</EuiText>
|
||||
),
|
||||
}, {
|
||||
description: <EuiCode>status:[400 TO 499] AND (extension:php OR extension:html)</EuiCode>,
|
||||
title: <EuiText><strong>Find status codes 400-499 with the extension php or html</strong></EuiText>,
|
||||
title: (
|
||||
<EuiText>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.400to499StatusCodeWithPhpOrHtmlExtensionExampleTitle"
|
||||
defaultMessage="Find status codes 400-499 with the extension php or html"
|
||||
/>
|
||||
</strong>
|
||||
</EuiText>
|
||||
),
|
||||
}];
|
||||
|
||||
luceneQueryMessage = (
|
||||
|
@ -150,19 +231,31 @@ export class DiscoverNoResults extends Component {
|
|||
|
||||
<EuiText>
|
||||
<h3>
|
||||
Refine your query
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.refineYourQueryTitle"
|
||||
defaultMessage="Refine your query"
|
||||
/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
The search bar at the top uses Elasticsearch’s support for Lucene {(
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href={getDocLink('query.luceneQuerySyntax')}
|
||||
>
|
||||
Query String syntax
|
||||
</EuiLink>
|
||||
)}. Here are some examples of how you can search for web server logs that have been
|
||||
parsed into a few fields.
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.howTosearchForWebServerLogsDescription"
|
||||
defaultMessage="The search bar at the top uses Elasticsearch’s support for Lucene {queryStringSyntaxLink}.
|
||||
Here are some examples of how you can search for web server logs that have been parsed into a few fields."
|
||||
values={{
|
||||
queryStringSyntaxLink: (
|
||||
<EuiLink
|
||||
target="_blank"
|
||||
href={getDocLink('query.luceneQuerySyntax')}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.queryStringSyntaxLinkText"
|
||||
defaultMessage="Query String syntax"
|
||||
/>
|
||||
</EuiLink>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
|
||||
|
@ -185,7 +278,10 @@ export class DiscoverNoResults extends Component {
|
|||
<EuiFlexGroup justifyContent="center">
|
||||
<EuiFlexItem grow={false} className="dscNoResults">
|
||||
<EuiCallOut
|
||||
title="No results match your search criteria"
|
||||
title={<FormattedMessage
|
||||
id="kbn.discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle"
|
||||
defaultMessage="No results match your search criteria"
|
||||
/>}
|
||||
color="warning"
|
||||
iconType="help"
|
||||
data-test-subj="discoverNoResults"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { render, mount } from 'enzyme';
|
||||
import { renderWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import sinon from 'sinon';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
|
||||
|
@ -40,7 +40,7 @@ describe('DiscoverNoResults', () => {
|
|||
reason: { reason: 'Bad error' },
|
||||
}];
|
||||
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
shardFailures={shardFailures}
|
||||
isTimePickerOpen={false}
|
||||
|
@ -55,7 +55,7 @@ describe('DiscoverNoResults', () => {
|
|||
test(`doesn't render failures list when there are no failures`, () => {
|
||||
const shardFailures = [];
|
||||
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
shardFailures={shardFailures}
|
||||
isTimePickerOpen={false}
|
||||
|
@ -70,7 +70,7 @@ describe('DiscoverNoResults', () => {
|
|||
|
||||
describe('isTimePickerOpen', () => {
|
||||
test('false is reflected in the aria-expanded state of the button', () => {
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
timeFieldName="awesome_time_field"
|
||||
isTimePickerOpen={false}
|
||||
|
@ -85,7 +85,7 @@ describe('DiscoverNoResults', () => {
|
|||
});
|
||||
|
||||
test('true is reflected in the aria-expanded state of the button', () => {
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
timeFieldName="awesome_time_field"
|
||||
isTimePickerOpen={true}
|
||||
|
@ -102,7 +102,7 @@ describe('DiscoverNoResults', () => {
|
|||
|
||||
describe('timeFieldName', () => {
|
||||
test('renders time range feedback', () => {
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
timeFieldName="awesome_time_field"
|
||||
isTimePickerOpen={false}
|
||||
|
@ -117,7 +117,7 @@ describe('DiscoverNoResults', () => {
|
|||
|
||||
describe('queryLanguage', () => {
|
||||
test('supports lucene and renders doc link', () => {
|
||||
const component = render(
|
||||
const component = renderWithIntl(
|
||||
<DiscoverNoResults
|
||||
queryLanguage="lucene"
|
||||
isTimePickerOpen={false}
|
||||
|
@ -133,7 +133,7 @@ describe('DiscoverNoResults', () => {
|
|||
describe('topNavToggle', () => {
|
||||
test('is called whe time picker button is clicked', () => {
|
||||
const topNavToggleSpy = sinon.stub();
|
||||
const component = mount(
|
||||
const component = mountWithIntl(
|
||||
<DiscoverNoResults
|
||||
timeFieldName="awesome_time_field"
|
||||
isTimePickerOpen={false}
|
||||
|
|
|
@ -25,12 +25,21 @@ import {
|
|||
EuiFlexItem,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export const DiscoverUnsupportedIndexPattern = ({ unsupportedType }) => {
|
||||
// This message makes the assumption that X-Pack will support this type, as is the case with
|
||||
// rollup index patterns.
|
||||
const message = `Index patterns based on ${unsupportedType} indices require the` +
|
||||
` ${unsupportedType} plugin from X-Pack, which is not installed or disabled`;
|
||||
const message = (
|
||||
<FormattedMessage
|
||||
id="kbn.discover.noResults.requiredPluginIsNotInstalledOrDisabledTitle"
|
||||
defaultMessage="Index patterns based on {unsupportedType} indices
|
||||
require the {unsupportedType} plugin from X-Pack, which is not installed or disabled"
|
||||
values={{
|
||||
unsupportedType,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
|
|
@ -10,15 +10,19 @@
|
|||
<span data-test-subj="discoverCurrentQuery" ng-bind="opts.savedSearch.lastSavedTitle"></span>
|
||||
<span
|
||||
id="reload_saved_search"
|
||||
aria-label="Reload Saved Search"
|
||||
tooltip="Reload Saved Search"
|
||||
aria-label="{{::'kbn.discover.reloadSavedSearchAriaLabel' | i18n: {defaultMessage: 'Reload Saved Search'} }}"
|
||||
tooltip="{{::'kbn.discover.reloadSavedSearchTooltip' | i18n: {defaultMessage: 'Reload Saved Search'} }}"
|
||||
ng-click="resetQuery()"
|
||||
kbn-accessible-click
|
||||
class="kuiIcon fa-undo small"
|
||||
></span>
|
||||
</span>
|
||||
<span data-test-subj="discoverQueryHits" class="kuiLocalBreadcrumb__emphasis">{{(hits || 0) | number:0}}</span>
|
||||
<ng-pluralize count="hits" when="{'1':'hit', 'other':'hits'}"></ng-pluralize>
|
||||
<span
|
||||
i18n-id="kbn.discover.hitsPluralTitle"
|
||||
i18n-default-message="{hits, plural, one {hit} other {hits}}"
|
||||
i18n-values="{ hits }"
|
||||
></span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
@ -87,7 +91,10 @@
|
|||
class="dscOverlay"
|
||||
>
|
||||
<div class="euiTitle" >
|
||||
<h2>Searching</h2>
|
||||
<h2
|
||||
i18n-id="kbn.discover.searchingTitle"
|
||||
i18n-default-message="Searching"
|
||||
></h2>
|
||||
</div>
|
||||
<div class="euiSpacer euiSpacer--m"></div>
|
||||
<div ng-show="fetchStatus">{{fetchStatus.complete}}/{{fetchStatus.total}}</div>
|
||||
|
@ -102,7 +109,10 @@
|
|||
>
|
||||
<span class="kuiButton__inner">
|
||||
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-chevron-down"></span>
|
||||
<span>Skip to bottom</span>
|
||||
<span
|
||||
i18n-id="kbn.discover.skipToBottomButtonLabel"
|
||||
i18n-default-message="Skip to bottom"
|
||||
></span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
|
@ -127,7 +137,13 @@
|
|||
content="getBucketIntervalToolTipText()"
|
||||
position="'top'"
|
||||
></icon-tip>
|
||||
Scaled to {{ bucketInterval.description }}
|
||||
<span
|
||||
i18n-id="kbn.discover.scaledToDescription"
|
||||
i18n-default-message="Scaled to {bucketIntervalDescription}"
|
||||
i18n-values="{
|
||||
bucketIntervalDescription: bucketInterval.description
|
||||
}"
|
||||
></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -163,10 +179,24 @@
|
|||
|
||||
<a tabindex="0" id="discoverBottomMarker"></a>
|
||||
|
||||
<div ng-if="rows.length == opts.sampleSize" class="dscTable__footer">
|
||||
These are the first {{opts.sampleSize}} documents matching
|
||||
your search, refine your search to see others.
|
||||
<a kbn-accessible-click ng-click="scrollToTop()">Back to top.</a>
|
||||
<div
|
||||
ng-if="rows.length == opts.sampleSize"
|
||||
class="dscTable__footer"
|
||||
>
|
||||
<span
|
||||
i18n-id="kbn.discover.howToSeeOtherMatchingDocumentsDescription"
|
||||
i18n-default-message="These are the first {sampleSize} documents matching
|
||||
your search, refine your search to see others. "
|
||||
i18n-values="{
|
||||
sampleSize: opts.sampleSize,
|
||||
}"
|
||||
></span>
|
||||
<a
|
||||
kbn-accessible-click
|
||||
ng-click="scrollToTop()"
|
||||
i18n-id="kbn.discover.backToTopLinkText"
|
||||
i18n-default-message="Back to top."
|
||||
></a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -25,11 +25,15 @@ import './controllers/discover';
|
|||
import 'ui/doc_table/components/table_row';
|
||||
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
|
||||
|
||||
FeatureCatalogueRegistryProvider.register(() => {
|
||||
FeatureCatalogueRegistryProvider.register(i18n => {
|
||||
return {
|
||||
id: 'discover',
|
||||
title: 'Discover',
|
||||
description: 'Interactively explore your data by querying and filtering raw documents.',
|
||||
title: i18n('kbn.discover.discoverTitle', {
|
||||
defaultMessage: 'Discover',
|
||||
}),
|
||||
description: i18n('kbn.discover.discoverDescription', {
|
||||
defaultMessage: 'Interactively explore your data by querying and filtering raw documents.',
|
||||
}),
|
||||
icon: 'discoverApp',
|
||||
path: '/app/kibana#/discover',
|
||||
showOnHomePage: true,
|
||||
|
|
|
@ -27,7 +27,7 @@ const module = uiModules.get('discover/saved_searches', [
|
|||
'kibana/courier'
|
||||
]);
|
||||
|
||||
module.factory('SavedSearch', function (Private) {
|
||||
module.factory('SavedSearch', function (Private, i18n) {
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
createLegacyClass(SavedSearch).inherits(SavedObject);
|
||||
function SavedSearch(id) {
|
||||
|
@ -38,7 +38,9 @@ module.factory('SavedSearch', function (Private) {
|
|||
|
||||
id: id,
|
||||
defaults: {
|
||||
title: 'New Saved Search',
|
||||
title: i18n('kbn.discover.savedSearch.newSavedSearchTitle', {
|
||||
defaultMessage: 'New Saved Search',
|
||||
}),
|
||||
description: '',
|
||||
columns: [],
|
||||
hits: 0,
|
||||
|
|
|
@ -16,7 +16,11 @@ exports[`render 1`] = `
|
|||
textTransform="none"
|
||||
>
|
||||
<h1>
|
||||
Open Search
|
||||
<FormattedMessage
|
||||
defaultMessage="Open Search"
|
||||
id="kbn.discover.topNav.openSearchPanel.openSearchTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
<EuiSpacer
|
||||
|
@ -32,11 +36,21 @@ exports[`render 1`] = `
|
|||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Manage searches
|
||||
<FormattedMessage
|
||||
defaultMessage="Manage searches"
|
||||
id="kbn.discover.topNav.openSearchPanel.manageSearchesButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
}
|
||||
makeUrl={[Function]}
|
||||
noItemsMessage="No matching searches found."
|
||||
noItemsMessage={
|
||||
<FormattedMessage
|
||||
defaultMessage="No matching searches found."
|
||||
id="kbn.discover.topNav.openSearchPanel.noSearchesFoundDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
onChoose={[Function]}
|
||||
savedObjectType="search"
|
||||
/>
|
||||
|
|
|
@ -21,6 +21,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
|
||||
import rison from 'rison-node';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import {
|
||||
EuiSpacer,
|
||||
|
@ -40,7 +41,10 @@ export class OpenSearchPanel extends React.Component {
|
|||
onClick={this.props.onClose}
|
||||
href={`#/management/kibana/objects?_a=${rison.encode({ tab: SEARCH_OBJECT_TYPE })}`}
|
||||
>
|
||||
Manage searches
|
||||
<FormattedMessage
|
||||
id="kbn.discover.topNav.openSearchPanel.manageSearchesButtonLabel"
|
||||
defaultMessage="Manage searches"
|
||||
/>
|
||||
</EuiButton>
|
||||
);
|
||||
}
|
||||
|
@ -55,13 +59,23 @@ export class OpenSearchPanel extends React.Component {
|
|||
<EuiFlyoutBody>
|
||||
|
||||
<EuiTitle size="s">
|
||||
<h1>Open Search</h1>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="kbn.discover.topNav.openSearchPanel.openSearchTitle"
|
||||
defaultMessage="Open Search"
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<SavedObjectFinder
|
||||
noItemsMessage="No matching searches found."
|
||||
noItemsMessage={
|
||||
<FormattedMessage
|
||||
id="kbn.discover.topNav.openSearchPanel.noSearchesFoundDescription"
|
||||
defaultMessage="No matching searches found."
|
||||
/>
|
||||
}
|
||||
savedObjectType={SEARCH_OBJECT_TYPE}
|
||||
makeUrl={this.props.makeUrl}
|
||||
onChoose={this.props.onClose}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { OpenSearchPanel } from './open_search_panel';
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
let isOpen = false;
|
||||
|
||||
|
@ -38,10 +39,12 @@ export function showOpenSearchPanel({ makeUrl }) {
|
|||
|
||||
document.body.appendChild(container);
|
||||
const element = (
|
||||
<OpenSearchPanel
|
||||
onClose={onClose}
|
||||
makeUrl={makeUrl}
|
||||
/>
|
||||
<I18nProvider>
|
||||
<OpenSearchPanel
|
||||
onClose={onClose}
|
||||
makeUrl={makeUrl}
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
ReactDOM.render(element, container);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue