[Graph] Improve wording (#47324)

This commit is contained in:
Joe Reuter 2019-10-11 17:42:52 +02:00 committed by GitHub
parent 0564396523
commit 4de9290b98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 311 additions and 255 deletions

View file

@ -17,10 +17,10 @@
is-loading="loading"
is-initialized="workspaceInitialized || savedWorkspace.id"
initial-query="initialQuery"
on-fill-workspace="fillWorkspace"
plugin-data-start="pluginDataStart"
core-start="coreStart"
store="store"
no-index-patterns="noIndexPatterns"
></div>
<div class="gphGraph__container" id="GraphSvgContainer" ng-if="workspaceInitialized || savedWorkspace.id">
@ -107,7 +107,6 @@
<div>
<div class="gphSidebar__header">
<span class="kuiIcon fa-shopping-cart"></span>
{{ ::'xpack.graph.sidebar.selectionsTitle' | i18n: { defaultMessage: 'Selections' } }}
</div>
@ -150,7 +149,7 @@
ng-if="workspace.selectedNodes.length === 0"
class="help-block"
i18n-id="xpack.graph.sidebar.selections.noSelectionsHelpText"
i18n-default-message="No selections. Click on vertices to add"
i18n-default-message="No selections. Click on vertices to add."
></p>
<div ng-repeat="n in workspace.selectedNodes" class="gphSelectionList__field" ng-class="{'gphSelectionList__field--selected': isSelectedSelected(n)}"
@ -273,7 +272,7 @@
<div
class="help-block"
i18n-id="xpack.graph.sidebar.displayLabelHelpText"
i18n-default-message="Change the label for this vertex"
i18n-default-message="Change the label for this vertex."
></div>
</div>
</div>

View file

@ -7,4 +7,5 @@
listing-limit="listingLimit"
capabilities="capabilities"
initial-filter="initialFilter"
core-start="coreStart"
/>

View file

@ -16,6 +16,7 @@ import 'uiExports/fieldFormats';
import 'uiExports/savedObjectTypes';
import 'ui/autoload/all';
import 'ui/angular-bootstrap';
import 'ui/kbn_top_nav';
import 'ui/directives/saved_object_finder';
import 'ui/directives/input_focus';
@ -39,7 +40,6 @@ import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
import appTemplate from './angular/templates/index.html';
import listingTemplate from './angular/templates/listing_ng_wrapper.html';
import { getReadonlyBadge } from './badge';
import { FormattedMessage } from '@kbn/i18n/react';
import { GraphApp } from './components/app';
import { VennDiagram } from './components/venn_diagram';
@ -82,7 +82,18 @@ app.directive('vennDiagram', function (reactDirective) {
});
app.directive('graphListing', function (reactDirective) {
return reactDirective(Listing);
return reactDirective(Listing, [
['coreStart', { watchDepth: 'reference' }],
['createItem', { watchDepth: 'reference' }],
['findItems', { watchDepth: 'reference' }],
['deleteItems', { watchDepth: 'reference' }],
['editItem', { watchDepth: 'reference' }],
['getViewUrl', { watchDepth: 'reference' }],
['listingLimit', { watchDepth: 'reference' }],
['hideWriteControls', { watchDepth: 'reference' }],
['capabilities', { watchDepth: 'reference' }],
['initialFilter', { watchDepth: 'reference' }],
]);
});
app.directive('graphApp', function (reactDirective) {
@ -96,9 +107,9 @@ app.directive('graphApp', function (reactDirective) {
['initialQuery', { watchDepth: 'reference' }],
['confirmWipeWorkspace', { watchDepth: 'reference' }],
['coreStart', { watchDepth: 'reference' }],
['pluginDataStart', { watchDepth: 'reference' }],
['store', { watchDepth: 'reference' }],
['noIndexPatterns', { watchDepth: 'reference' }],
['reduxStore', { watchDepth: 'reference' }],
['pluginDataStart', { watchDepth: 'reference' }],
], { restrict: 'A' });
});
@ -136,6 +147,7 @@ uiRoutes
};
$scope.capabilities = capabilities.get().graph;
$scope.initialFilter = ($location.search()).filter || '';
$scope.coreStart = npStart.core;
setBreadcrumbs({ chrome });
}
})
@ -189,30 +201,26 @@ app.controller('graphuiPlugin', function (
checkLicense(kbnBaseUrl);
function handleError(err) {
return checkLicense(kbnBaseUrl)
.then(() => {
const toastTitle = i18n.translate('xpack.graph.errorToastTitle', {
defaultMessage: 'Graph Error',
description: '"Graph" is a product name and should not be translated.',
});
if (err instanceof Error) {
toastNotifications.addError(err, {
title: toastTitle,
});
} else {
toastNotifications.addDanger({
title: toastTitle,
text: String(err),
});
}
checkLicense(kbnBaseUrl);
const toastTitle = i18n.translate('xpack.graph.errorToastTitle', {
defaultMessage: 'Graph Error',
description: '"Graph" is a product name and should not be translated.',
});
if (err instanceof Error) {
toastNotifications.addError(err, {
title: toastTitle,
});
} else {
toastNotifications.addDanger({
title: toastTitle,
text: String(err),
});
}
}
function handleHttpError(error) {
return checkLicense(kbnBaseUrl)
.then(() => {
toastNotifications.addDanger(formatAngularHttpError(error));
});
async function handleHttpError(error) {
checkLicense(kbnBaseUrl);
toastNotifications.addDanger(formatAngularHttpError(error));
}
// Replacement function for graphClientWorkspace's comms so
@ -353,14 +361,14 @@ app.controller('graphuiPlugin', function (
onConfirm: callback,
onCancel: (() => {}),
confirmButtonText: i18n.translate('xpack.graph.clearWorkspace.confirmButtonLabel', {
defaultMessage: 'Continue',
defaultMessage: 'Leave anyway',
}),
title: i18n.translate('xpack.graph.clearWorkspace.modalTitle', {
defaultMessage: 'Discard changes to workspace?',
defaultMessage: 'Unsaved changes',
}),
};
confirmModal(i18n.translate('xpack.graph.clearWorkspace.confirmText', {
defaultMessage: 'Once you discard changes made to a workspace, there is no getting them back.',
defaultMessage: 'If you leave now, you will lose unsaved changes.',
}), confirmModalOptions);
}
$scope.confirmWipeWorkspace = canWipeWorkspace;
@ -373,7 +381,6 @@ app.controller('graphuiPlugin', function (
}
};
$scope.submit = function (searchTerm) {
$scope.workspaceInitialized = true;
const numHops = 2;
@ -577,34 +584,7 @@ app.controller('graphuiPlugin', function (
payload: $route.current.locals.savedWorkspace,
});
} else {
const managementUrl = npStart.core.chrome.navLinks.get('kibana:management').url;
const url = `${managementUrl}/kibana/index_patterns`;
if ($route.current.locals.indexPatterns.length === 0) {
toastNotifications.addWarning({
title: i18n.translate('xpack.graph.noDataSourceNotificationMessageTitle', {
defaultMessage: 'No data source',
}),
text: (
<p>
<FormattedMessage
id="xpack.graph.noDataSourceNotificationMessageText"
defaultMessage="Go to {managementIndexPatternsLink} and create an index pattern"
values={{
managementIndexPatternsLink: (
<a href={url}>
<FormattedMessage
id="xpack.graph.noDataSourceNotificationMessageText.managementIndexPatternLinkText"
defaultMessage="Management &gt; Index Patterns"
/>
</a>
)
}}
/>
</p>
),
});
}
$scope.noIndexPatterns = $route.current.locals.indexPatterns.length === 0;
}
});

View file

@ -26,11 +26,19 @@ export interface GraphAppProps extends SearchBarProps {
store: Storage;
reduxStore: GraphStore;
isInitialized: boolean;
noIndexPatterns: boolean;
}
export function GraphApp(props: GraphAppProps) {
const [pickerOpen, setPickerOpen] = useState(false);
const { coreStart, pluginDataStart, store, reduxStore, ...searchBarProps } = props;
const {
coreStart,
pluginDataStart,
store,
reduxStore,
noIndexPatterns,
...searchBarProps
} = props;
return (
<I18nProvider>
@ -51,6 +59,7 @@ export function GraphApp(props: GraphAppProps) {
</div>
{!props.isInitialized && (
<GuidancePanel
noIndexPatterns={noIndexPatterns}
onOpenFieldPicker={() => {
setPickerOpen(true);
}}

View file

@ -23,6 +23,7 @@ import {
EuiKeyboardAccessible,
EuiForm,
EuiSpacer,
EuiIconTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import classNames from 'classnames';
@ -157,18 +158,34 @@ export function FieldEditor({
{
name: isDisabled
? i18n.translate('xpack.graph.fieldManager.enableFieldLabel', {
defaultMessage: 'Enable',
defaultMessage: 'Enable field',
})
: i18n.translate('xpack.graph.fieldManager.disableFieldLabel', {
defaultMessage: 'Temporarily disable',
defaultMessage: 'Disable field',
}),
icon: <EuiIcon type={isDisabled ? 'eye' : 'eyeClosed'} size="m" />,
onClick: toggleDisabledState,
toolTipContent: isDisabled
? i18n.translate('xpack.graph.fieldManager.enableFieldTooltipContent', {
defaultMessage:
'Turn on discovery of vertices for this field. You can also Shift+click the field to enable it.',
})
: i18n.translate('xpack.graph.fieldManager.disableFieldTooltipContent', {
defaultMessage:
'Turn off discovery of vertices for this field. You can also Shift+click the field to disable it.',
}),
},
{
name: i18n.translate('xpack.graph.fieldManager.deleteFieldLabel', {
defaultMessage: 'Delete field',
defaultMessage: 'Deselect field',
}),
toolTipContent: i18n.translate(
'xpack.graph.fieldManager.deleteFieldTooltipContent',
{
defaultMessage:
'No new vertices for this field will be discovered. Existing vertices remain in the graph.',
}
),
icon: <EuiIcon type="trash" size="m" />,
onClick: () => {
deselectField(initialField.name);
@ -182,7 +199,7 @@ export function FieldEditor({
title: i18n.translate('xpack.graph.fieldManager.displayFormTitle', {
defaultMessage: 'Edit',
}),
width: 280,
width: 380,
content: (
<EuiForm className="gphFieldEditor__displayForm">
{/* This is a workaround to prevent the field combo box from being focussed when opening the panel. */}
@ -278,9 +295,23 @@ export function FieldEditor({
<EuiFormRow
display="columnCompressed"
label={i18n.translate('xpack.graph.fieldManager.maxHopsLabel', {
defaultMessage: 'Max hops',
})}
label={
<>
{i18n.translate('xpack.graph.fieldManager.maxTermsPerHopLabel', {
defaultMessage: 'Terms per hop',
})}{' '}
<EuiIconTip
content={i18n.translate(
'xpack.graph.fieldManager.maxTermsPerHopDescription',
{
defaultMessage:
'Controls the maximum number of terms to return for each search step.',
}
)}
position="right"
/>
</>
}
>
<EuiFieldNumber
step={1}
@ -318,7 +349,7 @@ export function FieldEditor({
onClick={updateField}
>
{i18n.translate('xpack.graph.fieldManager.updateLabel', {
defaultMessage: 'Update',
defaultMessage: 'Save changes',
})}
</EuiButton>
</EuiFlexItem>

View file

@ -138,7 +138,7 @@ describe('field_manager', () => {
.find(EuiContextMenu)
.prop('panels')![0].items![1];
expect(toggleItem.name).toEqual('Temporarily disable');
expect(toggleItem.name).toEqual('Disable field');
toggleItem.onClick!({} as any);
@ -160,7 +160,7 @@ describe('field_manager', () => {
.dive()
.find(EuiContextMenu)
.prop('panels')![0].items![1].name
).toEqual('Enable');
).toEqual('Enable field');
});
it('should enable field', () => {
@ -171,7 +171,7 @@ describe('field_manager', () => {
.find(EuiContextMenu)
.prop('panels')![0].items![1];
expect(toggleItem.name).toEqual('Enable');
expect(toggleItem.name).toEqual('Enable field');
toggleItem.onClick!({} as any);
@ -193,7 +193,7 @@ describe('field_manager', () => {
.dive()
.find(EuiContextMenu)
.prop('panels')![0].items![1].name
).toEqual('Temporarily disable');
).toEqual('Disable field');
});
it('should change color', () => {

View file

@ -27,8 +27,6 @@ export function FieldPicker({
setOpen,
}: FieldPickerProps) {
const allFields = Object.values(fieldMap);
const unselectedFields = allFields.filter(field => !field.selected);
const hasSelectedFields = unselectedFields.length < allFields.length;
const hasFields = allFields.length > 0;
@ -43,13 +41,9 @@ export function FieldPicker({
}
}, [fieldMap]);
const badgeDescription = hasSelectedFields
? i18n.translate('xpack.graph.bar.pickMoreFieldsLabel', {
defaultMessage: 'Add more fields',
})
: i18n.translate('xpack.graph.bar.pickFieldsLabel', {
defaultMessage: 'Add fields',
});
const badgeDescription = i18n.translate('xpack.graph.bar.pickFieldsLabel', {
defaultMessage: 'Add fields',
});
return (
<EuiPopover
@ -84,7 +78,7 @@ export function FieldPicker({
<EuiSelectable
searchProps={{
placeholder: i18n.translate('xpack.graph.fieldManager.fieldSearchPlaceholder', {
defaultMessage: 'Filter fields',
defaultMessage: 'Filter by',
}),
compressed: true,
'data-test-subj': 'graph-field-search',

View file

@ -5,7 +5,15 @@
*/
import React, { ReactNode } from 'react';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiLink } from '@elastic/eui';
import {
EuiPanel,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiText,
EuiLink,
EuiCallOut,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import classNames from 'classnames';
import { FormattedMessage } from '@kbn/i18n/react';
@ -29,6 +37,7 @@ export interface GuidancePanelProps {
hasDatasource: boolean;
hasFields: boolean;
onIndexPatternSelected: (indexPattern: IndexPatternSavedObject) => void;
noIndexPatterns: boolean;
}
function ListItem({
@ -67,98 +76,127 @@ function GuidancePanelComponent(props: GuidancePanelProps) {
onIndexPatternSelected,
hasDatasource,
hasFields,
noIndexPatterns,
} = props;
const kibana = useKibana<IDataPluginServices>();
const { overlays, savedObjects, uiSettings } = kibana.services;
if (!overlays) return null;
const { overlays, savedObjects, uiSettings, chrome, application } = kibana.services;
if (!overlays || !chrome || !application) return null;
const onOpenDatasourcePicker = () => {
openSourceModal({ overlays, savedObjects, uiSettings }, onIndexPatternSelected);
};
let content = (
<EuiPanel data-test-subj="graphGuidancePanel">
<EuiFlexGroup direction="column" alignItems="center">
<EuiFlexItem grow={false}>
<EuiIcon type="graphApp" size="xxl" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<h1>
{i18n.translate('xpack.graph.guidancePanel.title', {
defaultMessage: 'Three steps to your graph',
})}
</h1>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ul className="gphGuidancePanel__list">
<ListItem state={hasDatasource ? 'done' : 'active'}>
<EuiLink onClick={onOpenDatasourcePicker}>
{i18n.translate(
'xpack.graph.guidancePanel.datasourceItem.indexPatternButtonLabel',
{
defaultMessage: 'Select a data source.',
}
)}
</EuiLink>
</ListItem>
<ListItem state={hasFields ? 'done' : hasDatasource ? 'active' : 'disabled'}>
<EuiLink onClick={onOpenFieldPicker}>
{i18n.translate('xpack.graph.guidancePanel.fieldsItem.fieldsButtonLabel', {
defaultMessage: 'Add fields.',
})}
</EuiLink>
</ListItem>
<ListItem state={hasFields ? 'active' : 'disabled'}>
<FormattedMessage
id="xpack.graph.guidancePanel.nodesItem.description"
defaultMessage="Enter a query in the search bar to start exploring. Don't know where to start? {topTerms}."
values={{
topTerms: (
<EuiLink onClick={onFillWorkspace}>
{i18n.translate('xpack.graph.guidancePanel.nodesItem.topTermsButtonLabel', {
defaultMessage: 'Graph the top terms',
})}
</EuiLink>
),
}}
/>
</ListItem>
</ul>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
if (noIndexPatterns) {
const managementUrl = chrome.navLinks.get('kibana:management')!.url;
const indexPatternUrl = `${managementUrl}/kibana/index_patterns`;
const sampleDataUrl = `${application.getUrlForApp(
'kibana'
)}#/home/tutorial_directory/sampleData`;
content = (
<EuiPanel paddingSize="none">
<EuiCallOut
color="warning"
iconType="help"
title={i18n.translate('xpack.graph.noDataSourceNotificationMessageTitle', {
defaultMessage: 'No data source',
})}
>
<p>
<FormattedMessage
id="xpack.graph.noDataSourceNotificationMessageText"
defaultMessage="No data sources found. Go to {managementIndexPatternsLink} and create an index pattern for your Elasticsearch indices."
values={{
managementIndexPatternsLink: (
<a href={indexPatternUrl}>
<FormattedMessage
id="xpack.graph.noDataSourceNotificationMessageText.managementIndexPatternLinkText"
defaultMessage="Management &gt; Index Patterns"
/>
</a>
),
}}
/>
</p>
<p>
<FormattedMessage
id="xpack.graph.listing.noDataSource.newToKibanaDescription"
defaultMessage="New to Kibana? You can also use our {sampleDataInstallLink}."
values={{
sampleDataInstallLink: (
<EuiLink href={sampleDataUrl}>
<FormattedMessage
id="xpack.graph.listing.noDataSource.sampleDataInstallLinkText"
defaultMessage="sample data"
/>
</EuiLink>
),
}}
/>
</p>
</EuiCallOut>
</EuiPanel>
);
}
return (
<EuiFlexGroup justifyContent="center">
<EuiFlexItem className="gphGuidancePanel">
<EuiPanel data-test-subj="graphGuidancePanel">
<EuiFlexGroup direction="column" alignItems="center">
<EuiFlexItem grow={false}>
<EuiIcon type="graphApp" size="xxl" />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<h1
aria-label={i18n.translate('xpack.graph.guidancePanel.ariaLabel', {
defaultMessage: "Let's get started building your first graph!",
})}
>
{i18n.translate('xpack.graph.guidancePanel.title', {
defaultMessage: "Let's get started!",
})}
</h1>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ul className="gphGuidancePanel__list">
<ListItem state={hasDatasource ? 'done' : 'active'}>
<FormattedMessage
id="xpack.graph.guidancePanel.datasourceItem.description"
defaultMessage="Choose an {indexpattern}"
values={{
indexpattern: (
<EuiLink onClick={onOpenDatasourcePicker}>
{i18n.translate(
'xpack.graph.guidancePanel.datasourceItem.indexPatternButtonLabel',
{
defaultMessage: 'index pattern',
}
)}
</EuiLink>
),
}}
/>
</ListItem>
<ListItem state={hasFields ? 'done' : hasDatasource ? 'active' : 'disabled'}>
<FormattedMessage
id="xpack.graph.guidancePanel.fieldsItem.description"
defaultMessage="{fields} to explore"
values={{
fields: (
<EuiLink onClick={onOpenFieldPicker}>
{i18n.translate(
'xpack.graph.guidancePanel.fieldsItem.fieldsButtonLabel',
{
defaultMessage: 'Select fields',
}
)}
</EuiLink>
),
}}
/>
</ListItem>
<ListItem state={hasFields ? 'active' : 'disabled'}>
<FormattedMessage
id="xpack.graph.guidancePanel.nodesItem.description"
defaultMessage="Search for something in the search bar above to begin exploration. If you don't know where to start, you can also {topTerms}"
values={{
topTerms: (
<EuiLink onClick={onFillWorkspace}>
{i18n.translate(
'xpack.graph.guidancePanel.nodesItem.topTermsButtonLabel',
{
defaultMessage: 'show correlations of the top terms',
}
)}
</EuiLink>
),
}}
/>
</ListItem>
</ul>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem className="gphGuidancePanel">{content}</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -9,11 +9,13 @@ import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
import React, { Fragment } from 'react';
import { EuiEmptyPrompt, EuiLink, EuiButton } from '@elastic/eui';
import { CoreStart, ApplicationStart } from 'kibana/public';
// @ts-ignore
import { TableListView } from '../../../../../../src/legacy/core_plugins/kibana/public/table_list_view/table_list_view';
import { GraphWorkspaceSavedObject } from '../types';
export interface ListingProps {
coreStart: CoreStart;
createItem: () => void;
findItems: (query: string, limit: number) => Promise<GraphWorkspaceSavedObject[]>;
deleteItems: (ids: string[]) => Promise<void>;
@ -36,22 +38,30 @@ export function Listing(props: ListingProps) {
tableColumns={getTableColumns(props.getViewUrl)}
listingLimit={props.listingLimit}
initialFilter={props.initialFilter}
noItemsFragment={getNoItemsMessage(props.capabilities.save === false, props.createItem)}
noItemsFragment={getNoItemsMessage(
props.capabilities.save === false,
props.createItem,
props.coreStart.application
)}
entityName={i18n.translate('xpack.graph.listing.table.entityName', {
defaultMessage: 'workspace',
defaultMessage: 'graph',
})}
entityNamePlural={i18n.translate('xpack.graph.listing.table.entityNamePlural', {
defaultMessage: 'workspaces',
defaultMessage: 'graphs',
})}
tableListTitle={i18n.translate('xpack.graph.listing.workspacesTitle', {
defaultMessage: 'Workspaces',
tableListTitle={i18n.translate('xpack.graph.listing.graphsTitle', {
defaultMessage: 'Graphs',
})}
/>
</I18nProvider>
);
}
function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
function getNoItemsMessage(
hideWriteControls: boolean,
createItem: () => void,
application: ApplicationStart
) {
if (hideWriteControls) {
return (
<div>
@ -61,7 +71,7 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
<h2>
<FormattedMessage
id="xpack.graph.listing.noItemsMessage"
defaultMessage="Looks like you don't have any Graph workspaces."
defaultMessage="Looks like you don't have any graphs."
/>
</h2>
}
@ -70,6 +80,8 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
);
}
const sampleDataUrl = `${application.getUrlForApp('kibana')}#/home/tutorial_directory/sampleData`;
return (
<div>
<EuiEmptyPrompt
@ -77,8 +89,8 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
title={
<h2>
<FormattedMessage
id="xpack.graph.listing.createNewWorkspace.title"
defaultMessage="Create your first Graph workspace"
id="xpack.graph.listing.createNewGraph.title"
defaultMessage="Create your first graph"
/>
</h2>
}
@ -86,20 +98,20 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
<Fragment>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
defaultMessage="You can discover patterns and relationships in your Kibana index patterns."
id="xpack.graph.listing.createNewGraph.combineDataViewFromKibanaAppDescription"
defaultMessage="Discover patterns and relationships in your Elasticsearch indices."
/>
</p>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.newToKibanaDescription"
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="xpack.graph.listing.createNewGraph.newToKibanaDescription"
defaultMessage="New to Kibana? Get started with {sampleDataInstallLink}."
values={{
sampleDataInstallLink: (
<EuiLink href="#/home/tutorial_directory/sampleData">
<EuiLink href={sampleDataUrl}>
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.sampleDataInstallLinkText"
defaultMessage="Install some sample data"
id="xpack.graph.listing.createNewGraph.sampleDataInstallLinkText"
defaultMessage="sample data"
/>
</EuiLink>
),
@ -113,11 +125,11 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="graphCreateWorkspacePromptButton"
data-test-subj="graphCreateGraphPromptButton"
>
<FormattedMessage
id="xpack.graph.listing.createNewWorkspace.createButtonLabel"
defaultMessage="Create new graph workspace"
id="xpack.graph.listing.createNewGraph.createButtonLabel"
defaultMessage="Create graph"
/>
</EuiButton>
}

View file

@ -47,7 +47,7 @@ export function SaveModal({
title={title}
showCopyOnSave={showCopyOnSave}
objectType={i18n.translate('xpack.graph.topNavMenu.save.objectType', {
defaultMessage: 'workspace',
defaultMessage: 'graph',
})}
options={
<>

View file

@ -104,13 +104,13 @@ export function SearchBarComponent(props: SearchBarProps) {
bubbleSubmitEvent
indexPatterns={currentIndexPattern ? [currentIndexPattern] : []}
placeholder={i18n.translate('xpack.graph.bar.searchFieldPlaceholder', {
defaultMessage: 'Search your data and add to your graph',
defaultMessage: 'Search your data and add to graph',
})}
query={query}
prepend={
<EuiToolTip
content={i18n.translate('xpack.graph.bar.pickSourceTooltip', {
defaultMessage: 'Click here to pick another data source',
defaultMessage: 'Select a data source to begin graphing relationships.',
})}
>
<EuiButtonEmpty
@ -131,7 +131,7 @@ export function SearchBarComponent(props: SearchBarProps) {
: // This branch will be shown if the user exits the
// initial picker modal
i18n.translate('xpack.graph.bar.pickSourceLabel', {
defaultMessage: 'Click here to pick a data source',
defaultMessage: 'Select a data source',
})}
</EuiButtonEmpty>
</EuiToolTip>
@ -146,7 +146,7 @@ export function SearchBarComponent(props: SearchBarProps) {
disabled={isLoading || !currentIndexPattern}
data-test-subj="graph-explore-button"
>
{i18n.translate('xpack.graph.bar.exploreLabel', { defaultMessage: 'Explore' })}
{i18n.translate('xpack.graph.bar.exploreLabel', { defaultMessage: 'Graph' })}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -42,7 +42,7 @@ export function AdvancedSettingsForm({
fullWidth
helpText={i18n.translate('xpack.graph.settings.advancedSettings.sampleSizeInputHelpText', {
defaultMessage:
'Terms are identified from samples of the most relevant documents. Bigger is not necessarily better - can be slower and less relevant',
'Terms are identified from samples of the most relevant documents. Bigger samples are not necessarily better—they can be slower and less relevant.',
})}
label={i18n.translate('xpack.graph.settings.advancedSettings.sampleSizeInputLabel', {
defaultMessage: 'Sample size',
@ -62,7 +62,7 @@ export function AdvancedSettingsForm({
helpText={i18n.translate(
'xpack.graph.settings.advancedSettings.significantLinksCheckboxHelpText',
{
defaultMessage: 'Identify terms that are "significant" rather than simply popular.',
defaultMessage: 'Identify terms that are significant rather than popular.',
}
)}
label=""
@ -81,8 +81,7 @@ export function AdvancedSettingsForm({
<EuiFormRow
fullWidth
helpText={i18n.translate('xpack.graph.settings.advancedSettings.certaintyInputHelpText', {
defaultMessage:
'The min number of documents that are required as evidence before introducing a related term',
defaultMessage: 'The minimum number of documents before introducing a related term.',
})}
label={i18n.translate('xpack.graph.settings.advancedSettings.certaintyInputLabel', {
defaultMessage: 'Certainty',
@ -103,14 +102,13 @@ export function AdvancedSettingsForm({
<>
{i18n.translate('xpack.graph.settings.advancedSettings.diversityFieldInputHelpText1', {
defaultMessage:
'To avoid document samples being dominated by a single voice, pick the field that helps identify the source of bias.',
'To avoid dominating samples with a single voice, select a field to help identify the source of bias.',
})}{' '}
<em>
{i18n.translate(
'xpack.graph.settings.advancedSettings.diversityFieldInputHelpText2',
{
defaultMessage:
'This must be a single-term field or searches will be rejected with an error',
defaultMessage: 'This must be a single-term field, or searches will be rejected.',
}
)}
</em>
@ -124,7 +122,7 @@ export function AdvancedSettingsForm({
fullWidth
placeholder={i18n.translate(
'xpack.graph.settings.advancedSettings.diversityFieldInputOptionLabel',
{ defaultMessage: '[No diversification]' }
{ defaultMessage: 'No diversification' }
)}
singleSelection={{ asPlainText: true }}
options={allFields.map(field => ({ label: field.name, value: field }))}
@ -182,7 +180,7 @@ export function AdvancedSettingsForm({
<EuiFormRow
fullWidth
helpText={i18n.translate('xpack.graph.settings.advancedSettings.timeoutInputHelpText', {
defaultMessage: 'Max time in milliseconds a request can run',
defaultMessage: 'The maximum number of milliseconds that a request can run.',
})}
label={i18n.translate('xpack.graph.settings.advancedSettings.timeoutInputLabel', {
defaultMessage: 'Timeout',

View file

@ -30,8 +30,7 @@ export function BlacklistForm({
{blacklistedNodes && blacklistedNodes.length > 0 ? (
<EuiText size="s">
{i18n.translate('xpack.graph.settings.blacklist.blacklistHelpText', {
defaultMessage:
'These terms are currently blacklisted from re-appearing in the workspace',
defaultMessage: 'These terms are not allowed in the graph.',
})}
</EuiText>
) : (
@ -39,7 +38,7 @@ export function BlacklistForm({
title={
<FormattedMessage
id="xpack.graph.blacklist.noEntriesDescription"
defaultMessage="You don't have any blacklisted nodes. Select nodes and press the {stopSign} in the side bar to blacklist them."
defaultMessage="You don't have any blocked terms. Select vertices and click {stopSign} in the control panel on the right to block them. Documents that match blocked terms are no longer explored and relationships to them are hidden."
values={{ stopSign: <span className="kuiIcon fa-ban"></span> }}
/>
}
@ -57,10 +56,10 @@ export function BlacklistForm({
extraAction={{
iconType: 'trash',
'aria-label': i18n.translate('xpack.graph.blacklist.removeButtonAriaLabel', {
defaultMessage: 'Remove',
defaultMessage: 'Delete',
}),
title: i18n.translate('xpack.graph.blacklist.removeButtonAriaLabel', {
defaultMessage: 'Remove',
defaultMessage: 'Delete',
}),
color: 'danger',
onClick: () => {
@ -84,7 +83,7 @@ export function BlacklistForm({
}}
>
{i18n.translate('xpack.graph.settings.blacklist.clearButtonLabel', {
defaultMessage: 'Remove all',
defaultMessage: 'Delete all',
})}
</EuiButton>
</>

View file

@ -179,7 +179,7 @@ describe('settings', () => {
describe('blacklist', () => {
beforeEach(() => {
toTab('Blacklist');
toTab('Block list');
});
it('should switch tab to blacklist', () => {
@ -259,7 +259,7 @@ describe('settings', () => {
}
beforeEach(() => {
toTab('Drill-downs');
toTab('Drilldowns');
});
it('should switch tab to url templates', () => {

View file

@ -34,13 +34,13 @@ const tabs = [
},
{
id: 'blacklist',
title: i18n.translate('xpack.graph.settings.blacklistTitle', { defaultMessage: 'Blacklist' }),
title: i18n.translate('xpack.graph.settings.blacklistTitle', { defaultMessage: 'Block list' }),
component: BlacklistForm,
},
{
id: 'drillDowns',
title: i18n.translate('xpack.graph.settings.drillDownsTitle', {
defaultMessage: 'Drill-downs',
defaultMessage: 'Drilldowns',
}),
component: UrlTemplateList,
},

View file

@ -115,7 +115,7 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
isUpdateForm(props)
? props.initialTemplate.description
: i18n.translate('xpack.graph.templates.addLabel', {
defaultMessage: 'New drill-down',
defaultMessage: 'New drilldown',
})
}
extraAction={
@ -176,7 +176,7 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
<strong>
{i18n.translate(
'xpack.graph.settings.drillDowns.kibanaUrlWarningConvertOptionLinkText',
{ defaultMessage: 'convert it' }
{ defaultMessage: 'convert it.' }
)}
</strong>
</EuiLink>
@ -185,7 +185,7 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
)}
{i18n.translate('xpack.graph.settings.drillDowns.urlInputHelpText', {
defaultMessage:
'Define template URLs using {gquery} where the selected vertex terms are inserted',
'Define template URLs using {gquery} where the selected vertex terms are inserted.',
values: { gquery: '{{gquery}}' },
})}
</>
@ -196,7 +196,7 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
urlPlaceholderMissing
? [
i18n.translate('xpack.graph.settings.drillDowns.invalidUrlWarningText', {
defaultMessage: 'The URL must contain a {placeholder} string',
defaultMessage: 'The URL must contain a {placeholder} string.',
values: { placeholder: '{{gquery}}' },
}),
]
@ -279,9 +279,13 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
}}
data-test-subj="graphRemoveUrlTemplate"
>
{i18n.translate('xpack.graph.settings.drillDowns.removeButtonLabel', {
defaultMessage: 'Remove',
})}
{isUpdateForm(props)
? i18n.translate('xpack.graph.settings.drillDowns.removeButtonLabel', {
defaultMessage: 'Remove',
})
: i18n.translate('xpack.graph.settings.drillDowns.cancelButtonLabel', {
defaultMessage: 'Cancel',
})}
</EuiButtonEmpty>
}
</EuiFlexItem>
@ -297,10 +301,10 @@ export function UrlTemplateForm(props: UrlTemplateFormProps) {
<EuiButton type="submit" fill isDisabled={urlPlaceholderMissing || formIncomplete}>
{isUpdateForm(props)
? i18n.translate('xpack.graph.settings.drillDowns.updateSaveButtonLabel', {
defaultMessage: 'Update drill-down',
defaultMessage: 'Update drilldown',
})
: i18n.translate('xpack.graph.settings.drillDowns.newSaveButtonLabel', {
defaultMessage: 'Add drill-down',
defaultMessage: 'Save drilldown',
})}
</EuiButton>
</EuiFlexItem>

View file

@ -30,7 +30,7 @@ export function UrlTemplateList({
<EuiText size="s">
{i18n.translate('xpack.graph.drilldowns.description', {
defaultMessage:
'Drilldown links configured here can be used to link to other applications and carry over the selected nodes as part of the URL',
'Use drilldowns to link to other applications. The selected vertices become part of the URL.',
})}
</EuiText>
<EuiSpacer />
@ -73,7 +73,7 @@ export function UrlTemplateList({
}}
>
{i18n.translate('xpack.graph.templates.newTemplateFormLabel', {
defaultMessage: 'Add template',
defaultMessage: 'Add drilldown',
})}
</EuiButton>
</EuiTextAlign>

View file

@ -17,7 +17,7 @@ export function SourceModal(props: SourcePickerProps) {
<EuiModalHeaderTitle>
<FormattedMessage
id="xpack.graph.sourceModal.title"
defaultMessage="Choose index pattern"
defaultMessage="Select a data source"
/>
</EuiModalHeaderTitle>
</EuiModalHeader>

View file

@ -36,7 +36,7 @@ export function SourcePicker({
}}
showFilter={false}
noItemsMessage={i18n.translate('xpack.graph.sourceModal.notFoundLabel', {
defaultMessage: 'No matching indices found.',
defaultMessage: 'No data sources found.',
})}
savedObjectMetaData={[
{

View file

@ -25,7 +25,7 @@ export const outlinkEncoders: OutlinkEncoder[] = [
defaultMessage: 'KQL OR query',
}),
description: i18n.translate('xpack.graph.outlinkEncoders.kqlLooseDescription', {
defaultMessage: 'KQL query, compatible with Discover, Visualize and Dashboards',
defaultMessage: 'KQL query, compatible with Discover, Visualize, and Dashboards',
}),
encode(workspace) {
return asKQL(workspace, 'or');
@ -38,7 +38,7 @@ export const outlinkEncoders: OutlinkEncoder[] = [
defaultMessage: 'KQL AND query',
}),
description: i18n.translate('xpack.graph.outlinkEncoders.kqlLooseDescription', {
defaultMessage: 'KQL query, compatible with Discover, Visualize and Dashboards',
defaultMessage: 'KQL query, compatible with Discover, Visualize, and Dashboards',
}),
encode(workspace) {
return asKQL(workspace, 'and');

View file

@ -49,7 +49,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) {
},
{
text: options.metaData.title,
'data-test-subj': 'graphCurrentWorkspaceBreadcrumb',
'data-test-subj': 'graphCurrentGraphBreadcrumb',
},
]);
} else {

View file

@ -23,8 +23,8 @@ export interface MetaDataState {
export const updateMetaData = actionCreator<Partial<MetaDataState>>('UPDATE_META_DATA');
const initialMetaData: MetaDataState = {
title: i18n.translate('xpack.graph.newWorkspaceTitle', {
defaultMessage: 'Unsaved workspace',
title: i18n.translate('xpack.graph.newGraphTitle', {
defaultMessage: 'Unsaved graph',
}),
description: '',
};

View file

@ -50,10 +50,11 @@ export const fillWorkspaceSaga = ({
notifyAngular();
workspace.fillInGraph(fields.length * 10);
} catch (e) {
const message = 'body' in e ? e.body.message : e.message;
notifications.toasts.addDanger({
title: i18n.translate('xpack.graph.fillWorkspaceError', {
defaultMessage: 'Fetching top terms failed: {message}',
values: { message: e.message },
values: { message },
}),
});
}

View file

@ -4419,15 +4419,10 @@
"xpack.dashboardMode.uiSettings.dashboardsOnlyRolesTitle": "ダッシュボード専用ロール",
"xpack.graph.badge.readOnly.text": "読み込み専用",
"xpack.graph.badge.readOnly.tooltip": "Graph ワークスペースを保存できません",
"xpack.graph.clearWorkspace.confirmButtonLabel": "ワークスペースを消去",
"xpack.graph.clearWorkspace.confirmText": "これによりワークスペースが消去されます。よろしいですか?",
"xpack.graph.exploreGraph.timedOutWarningText": "閲覧がタイムアウトしました",
"xpack.graph.featureRegistry.graphFeatureName": "Graph",
"xpack.graph.home.breadcrumb": "Graph",
"xpack.graph.missingWorkspaceErrorMessage": "ワークスペースがありません",
"xpack.graph.noDataSourceNotificationMessageText": "{managementIndexPatternsLink} に移動してインデックスパターンを作成してください",
"xpack.graph.noDataSourceNotificationMessageText.managementIndexPatternLinkText": "管理 > インデックスパターン",
"xpack.graph.noDataSourceNotificationMessageTitle": "データソースがありません",
"xpack.graph.outlinkEncoders.esqPlainDescription": "標準 URL エンコードの JSON",
"xpack.graph.outlinkEncoders.esqPlainTitle": "Elasticsearch クエリ (プレインエンコード)",
"xpack.graph.outlinkEncoders.esqRisonDescription": "Rison エンコードの JSON、minimum_should_match=2、ほとんどの Kibana URL に対応",

View file

@ -4421,15 +4421,10 @@
"xpack.dashboardMode.uiSettings.dashboardsOnlyRolesTitle": "仅限仪表板的角色",
"xpack.graph.badge.readOnly.text": "只读",
"xpack.graph.badge.readOnly.tooltip": "无法保存 Graph 工作空间",
"xpack.graph.clearWorkspace.confirmButtonLabel": "清除工作空间",
"xpack.graph.clearWorkspace.confirmText": "此操作将清除工作空间,是否确定要执行?",
"xpack.graph.exploreGraph.timedOutWarningText": "浏览超时",
"xpack.graph.featureRegistry.graphFeatureName": "Graph",
"xpack.graph.home.breadcrumb": "Graph",
"xpack.graph.missingWorkspaceErrorMessage": "缺少工作空间",
"xpack.graph.noDataSourceNotificationMessageText": "前往 “{managementIndexPatternsLink}” 并创建索引模式",
"xpack.graph.noDataSourceNotificationMessageText.managementIndexPatternLinkText": "管理 > 索引模式",
"xpack.graph.noDataSourceNotificationMessageTitle": "无数据源",
"xpack.graph.outlinkEncoders.esqPlainDescription": "使用标准 URL 编码的 JSON",
"xpack.graph.outlinkEncoders.esqPlainTitle": "Elasticsearch 查询(纯编码)",
"xpack.graph.outlinkEncoders.esqRisonDescription": "rison 编码的 JSONminimum_should_match=2与大部分 Kibana URL 兼容",

View file

@ -71,10 +71,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
]);
});
it('landing page shows "Create new Workspace" button', async () => {
it('landing page shows "Create new graph" button', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateWorkspacePromptButton');
await testSubjects.existOrFail('graphLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateGraphPromptButton');
});
it(`doesn't show read-only badge`, async () => {
@ -83,9 +83,9 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('allows creating a new workspace', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.click('graphCreateWorkspacePromptButton');
const breadcrumb = await testSubjects.find('~graphCurrentWorkspaceBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace');
await testSubjects.click('graphCreateGraphPromptButton');
const breadcrumb = await testSubjects.find('~graphCurrentGraphBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved graph');
});
it('shows save button', async () => {
@ -138,7 +138,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
it('does not show a "Create new Workspace" button', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphLandingPage', { timeout: 10000 });
await testSubjects.missingOrFail('newItemButton');
});

View file

@ -41,21 +41,21 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expect(navLinks).to.contain('Graph');
});
it('landing page shows "Create new Workspace" button', async () => {
it('landing page shows "Create new graph" button', async () => {
await PageObjects.common.navigateToApp('graph', {
basePath: '/s/custom_space',
});
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateWorkspacePromptButton');
await testSubjects.existOrFail('graphLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateGraphPromptButton');
});
it('allows creating a new workspace', async () => {
it('allows creating a new graph', async () => {
await PageObjects.common.navigateToApp('graph', {
basePath: '/s/custom_space',
});
await testSubjects.click('graphCreateWorkspacePromptButton');
const breadcrumb = await testSubjects.find('~graphCurrentWorkspaceBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace');
await testSubjects.click('graphCreateGraphPromptButton');
const breadcrumb = await testSubjects.find('~graphCurrentGraphBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved graph');
});
});

View file

@ -181,7 +181,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon
}
async createWorkspace() {
await testSubjects.click('graphCreateWorkspacePromptButton');
await testSubjects.click('graphCreateGraphPromptButton');
}
async newGraph() {
@ -227,7 +227,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon
async goToListingPage() {
await retry.try(async () => {
await testSubjects.click('breadcrumb graphHomeBreadcrumb first');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 3000 });
await testSubjects.existOrFail('graphLandingPage', { timeout: 3000 });
});
}