[I18n] Translate Graph (#23987) (#26090)

* [I18n] Add Graph translations

* Fix typo

* Use template strings
This commit is contained in:
Leanid Shutau 2018-11-22 17:03:25 +03:00 committed by GitHub
parent 439e0a82bb
commit f19323d027
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 617 additions and 212 deletions

View file

@ -14,6 +14,7 @@
"tileMap": "src/core_plugins/tile_map",
"timelion": "src/core_plugins/timelion",
"tagCloud": "src/core_plugins/tagcloud",
"xpack.graph": "x-pack/plugins/graph",
"xpack.grokDebugger": "x-pack/plugins/grokdebugger",
"xpack.idxMgmt": "x-pack/plugins/index_management",
"xpack.infra": "x-pack/plugins/infra",

View file

@ -39,7 +39,7 @@ import {
drillDownIconChoicesByClass
} from './style_choices';
import {
outlinkEncoders
getOutlinkEncoders,
} from './services/outlink_encoders';
const app = uiModules.get('app/graph');
@ -96,11 +96,15 @@ uiRoutes
.when('/workspace/:id', {
template: appTemplate,
resolve: {
savedWorkspace: function (savedGraphWorkspaces, courier, $route) {
savedWorkspace: function (savedGraphWorkspaces, courier, $route, i18n) {
return savedGraphWorkspaces.get($route.current.params.id)
.catch(
function () {
toastNotifications.addDanger('Missing workspace');
toastNotifications.addDanger(
i18n('xpack.graph.missingWorkspaceErrorMessage', {
defaultMessage: 'Missing workspace',
})
);
}
);
@ -131,7 +135,7 @@ uiRoutes
//======== Controller for basic UI ==================
app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnUrl, Private, Promise, confirmModal, kbnBaseUrl) {
app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnUrl, Private, Promise, confirmModal, kbnBaseUrl, i18n) {
function handleSuccess(data) {
return checkLicense(Private, Promise, kbnBaseUrl)
@ -151,7 +155,7 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
$scope.colors = colorChoices;
$scope.iconChoicesByClass = iconChoicesByClass;
$scope.outlinkEncoders = outlinkEncoders;
$scope.outlinkEncoders = getOutlinkEncoders(i18n);
$scope.fields = [];
$scope.canEditDrillDownUrls = chrome.getInjected('canEditDrillDownUrls');
@ -290,9 +294,13 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
const confirmModalOptions = {
onConfirm: yesFn,
onCancel: noFn,
confirmButtonText: 'Clear workspace'
confirmButtonText: i18n('xpack.graph.clearWorkspace.confirmButtonLabel', {
defaultMessage: 'Clear workspace',
})
};
confirmModal('This will clear the workspace - are you sure?', confirmModalOptions);
confirmModal(i18n('xpack.graph.clearWorkspace.confirmText', {
defaultMessage: 'This will clear the workspace - are you sure?',
}), confirmModalOptions);
}
$scope.uiSelectIndex = function () {
@ -387,7 +395,11 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
return $http.post('../api/graph/graphExplore', request)
.then(function (resp) {
if (resp.data.resp.timed_out) {
toastNotifications.addWarning('Exploration timed out');
toastNotifications.addWarning(
i18n('xpack.graph.exploreGraph.timedOutWarningText', {
defaultMessage: 'Exploration timed out',
})
);
}
responseHandler(resp.data.resp);
})
@ -536,8 +548,15 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
const found = $scope.newUrlTemplate.url.search(drillDownRegex) > -1;
if (!found) {
toastNotifications.addWarning({
title: 'Invalid URL',
text: 'The URL must contain a {{gquery}} string',
title: i18n('xpack.graph.settings.drillDowns.invalidUrlWarningTitle', {
defaultMessage: 'Invalid URL',
}),
text: i18n('xpack.graph.settings.drillDowns.invalidUrlWarningText', {
defaultMessage: 'The URL must contain a {placeholder} string',
values: {
placeholder: '{{gquery}}'
}
}),
});
return;
}
@ -556,10 +575,18 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
$scope.removeUrlTemplate = function (urlTemplate) {
const i = $scope.urlTemplates.indexOf(urlTemplate);
if (i != -1) {
confirmModal('Remove "' + urlTemplate.description + '" drill-down?', {
onConfirm: () => $scope.urlTemplates.splice(i, 1),
confirmButtonText: 'Remove drill-down'
});
confirmModal(
i18n('xpack.graph.settings.drillDowns.removeConfirmText', {
defaultMessage: 'Remove "{urlTemplateDesciption}" drill-down?',
values: { urlTemplateDesciption: urlTemplate.description },
}),
{
onConfirm: () => $scope.urlTemplates.splice(i, 1),
confirmButtonText: i18n('xpack.graph.settings.drillDowns.removeConfirmButtonLabel', {
defaultMessage: 'Remove drill-down',
}),
},
);
}
};
@ -651,7 +678,9 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
$scope.urlTemplates.push({
url: discoverUrl,
description: 'Raw documents',
description: i18n('xpack.graph.settings.drillDowns.defaultUrlTemplateTitle', {
defaultMessage: 'Raw documents',
}),
encoder: $scope.outlinkEncoders[0]
});
}
@ -730,30 +759,46 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
$scope.topNavMenu = [];
$scope.topNavMenu.push({
key: 'new',
description: 'New Workspace',
tooltip: 'Create a new workspace',
description: i18n('xpack.graph.topNavMenu.newWorkspaceAriaLabel', {
defaultMessage: 'New Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.newWorkspaceTooltip', {
defaultMessage: 'Create a new workspace',
}),
run: function () {canWipeWorkspace(function () {kbnUrl.change('/home', {}); }); },
});
if (!$scope.allSavingDisabled) {
$scope.topNavMenu.push({
key: 'save',
description: 'Save Workspace',
tooltip: 'Save this workspace',
description: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', {
defaultMessage: 'Save Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.enabledTooltip', {
defaultMessage: 'Save this workspace',
}),
disableButton: function () {return $scope.selectedFields.length === 0;},
template: require('./templates/save_workspace.html')
});
}else {
$scope.topNavMenu.push({
key: 'save',
description: 'Save Workspace',
tooltip: 'No changes to saved workspaces are permitted by the current save policy',
description: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledAriaLabel', {
defaultMessage: 'Save Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.saveWorkspace.disabledTooltip', {
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
}),
disableButton: true
});
}
$scope.topNavMenu.push({
key: 'open',
description: 'Load Saved Workspace',
tooltip: 'Load a saved workspace',
description: i18n('xpack.graph.topNavMenu.loadWorkspaceAriaLabel', {
defaultMessage: 'Load Saved Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.loadWorkspaceTooltip', {
defaultMessage: 'Load a saved workspace',
}),
template: require('./templates/load_workspace.html')
});
if (!$scope.allSavingDisabled) {
@ -762,35 +807,58 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
disableButton: function () {
return $route.current.locals === undefined || $route.current.locals.savedWorkspace === undefined;
},
description: 'Delete Saved Workspace',
tooltip: 'Delete this workspace',
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel', {
defaultMessage: 'Delete Saved Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip', {
defaultMessage: 'Delete this workspace',
}),
run: function () {
const title = $route.current.locals.savedWorkspace.title;
function doDelete() {
$route.current.locals.SavedWorkspacesProvider.delete($route.current.locals.savedWorkspace.id);
kbnUrl.change('/home', {});
toastNotifications.addSuccess(`Deleted '${title}'`);
toastNotifications.addSuccess(
i18n('xpack.graph.topNavMenu.deleteWorkspaceNotification', {
defaultMessage: `Deleted '{workspaceTitle}'`,
values: { workspaceTitle: title },
})
);
}
const confirmModalOptions = {
onConfirm: doDelete,
confirmButtonText: 'Delete workspace'
confirmButtonText: i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel', {
defaultMessage: 'Delete workspace',
}),
};
confirmModal('Are you sure you want to delete the workspace ' + title + ' ?', confirmModalOptions);
confirmModal(
i18n('xpack.graph.topNavMenu.deleteWorkspace.confirmText', {
defaultMessage: 'Are you sure you want to delete the workspace {title} ?',
values: { title },
}),
confirmModalOptions
);
}
});
}else {
$scope.topNavMenu.push({
key: 'delete',
disableButton: true,
description: 'Delete Saved Workspace',
tooltip: 'No changes to saved workspaces are permitted by the current save policy'
description: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel', {
defaultMessage: 'Delete Saved Workspace',
}),
tooltip: i18n('xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip', {
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
}),
});
}
$scope.topNavMenu.push({
key: 'settings',
disableButton: function () { return $scope.selectedIndex === null; },
description: 'Settings',
description: i18n('xpack.graph.topNavMenu.settingsAriaLabel', {
defaultMessage: 'Settings',
}),
template: require('./templates/settings.html')
});
@ -829,7 +897,12 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
}
});
if(!savedObjectIndexPattern) {
toastNotifications.addDanger(`'Missing index pattern ${wsObj.indexPattern}`);
toastNotifications.addDanger(
i18n('xpack.graph.loadWorkspace.missingIndexPatternErrorMessage', {
defaultMessage: `'Missing index pattern {indexPattern}`,
values: { indexPattern: wsObj.indexPattern },
})
);
return;
}
@ -946,7 +1019,9 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
if ($scope.allSavingDisabled) {
// It should not be possible to navigate to this function if allSavingDisabled is set
// but adding check here as a safeguard.
toastNotifications.addWarning('Saving is disabled');
toastNotifications.addWarning(
i18n('xpack.graph.saveWorkspace.disabledWarning', { defaultMessage: 'Saving is disabled' })
);
return;
}
initWorkspaceIfRequired();
@ -1034,10 +1109,15 @@ app.controller('graphuiPlugin', function ($scope, $route, $interval, $http, kbnU
$scope.kbnTopNav.close('save');
$scope.userHasConfirmedSaveWorkspaceData = false; //reset flag
if (id) {
const title = `Saved "${$scope.savedWorkspace.title}"`;
const title = i18n('xpack.graph.saveWorkspace.successNotificationTitle', {
defaultMessage: 'Saved "{workspaceTitle}"',
values: { workspaceTitle: $scope.savedWorkspace.title },
});
let text;
if (!canSaveData && $scope.workspace.nodes.length > 0) {
text = 'The configuration was saved, but the data was not saved';
text = i18n('xpack.graph.saveWorkspace.successNotification.noDataSavedText', {
defaultMessage: 'The configuration was saved, but the data was not saved',
});
}
toastNotifications.addSuccess({

View file

@ -8,11 +8,13 @@
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
FeatureCatalogueRegistryProvider.register(() => {
FeatureCatalogueRegistryProvider.register((i18n) => {
return {
id: 'graph',
title: 'Graph',
description: 'Surface and analyze relevant relationships in your Elasticsearch data.',
description: i18n('xpack.graph.pluginDescription', {
defaultMessage: 'Surface and analyze relevant relationships in your Elasticsearch data.',
}),
icon: 'graphApp',
path: '/app/graph',
showOnHomePage: true,

View file

@ -6,38 +6,58 @@
import rison from 'rison-node';
export const outlinkEncoders = [{
export const getOutlinkEncoders = i18n => [{
id: 'esq-rison-loose',
title: 'elasticsearch OR query (rison encoded)',
description: 'rison-encoded JSON, minimum_should_match=1, compatible with most Kibana URLs',
title: i18n('xpack.graph.outlinkEncoders.esqRisonLooseTitle', {
defaultMessage: 'elasticsearch OR query (rison encoded)',
}),
description: i18n('xpack.graph.outlinkEncoders.esqRisonLooseDescription', {
defaultMessage: 'rison-encoded JSON, minimum_should_match=1, compatible with most Kibana URLs',
}),
encode: function (workspace) {
return encodeURIComponent(rison.encode(workspace.getQuery(workspace.getSelectedOrAllNodes(), true)));
}
}, {
id: 'esq-rison',
title: 'elasticsearch AND query (rison encoded)',
description: 'rison-encoded JSON, minimum_should_match=2, compatible with most Kibana URLs',
title: i18n('xpack.graph.outlinkEncoders.esqRisonTitle', {
defaultMessage: 'elasticsearch AND query (rison encoded)',
}),
description: i18n('xpack.graph.outlinkEncoders.esqRisonDescription', {
defaultMessage: 'rison-encoded JSON, minimum_should_match=2, compatible with most Kibana URLs',
}),
encode: function (workspace) {
return encodeURIComponent(rison.encode(workspace.getQuery(workspace.getSelectedOrAllNodes())));
}
}, {
id: 'esq-similar-rison',
title: 'elasticsearch more like this query (rison encoded)',
description: 'rison-encoded JSON, "like this but not this" type query to find missing docs',
title: i18n('xpack.graph.outlinkEncoders.esqSimilarRisonTitle', {
defaultMessage: 'elasticsearch more like this query (rison encoded)',
}),
description: i18n('xpack.graph.outlinkEncoders.esqSimilarRisonDescription', {
defaultMessage: 'rison-encoded JSON, "like this but not this" type query to find missing docs',
}),
encode: function (workspace) {
return encodeURIComponent(rison.encode(workspace.getLikeThisButNotThisQuery(workspace.getSelectedOrAllNodes())));
}
}, {
id: 'esq-plain',
title: 'elasticsearch query (plain encoding)',
description: 'JSON encoded using standard url encoding',
title: i18n('xpack.graph.outlinkEncoders.esqPlainTitle', {
defaultMessage: 'elasticsearch query (plain encoding)',
}),
description: i18n('xpack.graph.outlinkEncoders.esqPlainDescription', {
defaultMessage: 'JSON encoded using standard url encoding',
}),
encode: function (workspace) {
return encodeURIComponent(JSON.stringify(workspace.getQuery(workspace.getSelectedOrAllNodes())));
}
}, {
id: 'text-plain',
title: 'plain text',
description: 'Text of selected vertex labels as a plain url-encoded string',
title: i18n('xpack.graph.outlinkEncoders.textPlainTitle', {
defaultMessage: 'plain text',
}),
description: i18n('xpack.graph.outlinkEncoders.textPlainDescription', {
defaultMessage: 'Text of selected vertex labels as a plain url-encoded string',
}),
encode: function (workspace) {
let q = '';
const nodes = workspace.getSelectedOrAllNodes();
@ -52,8 +72,12 @@ export const outlinkEncoders = [{
}
}, {
id: 'text-lucene',
title: 'Lucene-escaped text',
description: 'Text of selected vertex labels with any Lucene special characters encoded',
title: i18n('xpack.graph.outlinkEncoders.textLuceneTitle', {
defaultMessage: 'Lucene-escaped text',
}),
description: i18n('xpack.graph.outlinkEncoders.textLuceneDescription', {
defaultMessage: 'Text of selected vertex labels with any Lucene special characters encoded',
}),
encode: function (workspace) {
let q = '';
const nodes = workspace.getSelectedOrAllNodes();

View file

@ -5,18 +5,36 @@
<div data-transclude-slots>
<!-- Title. -->
<div data-transclude-slot="topLeftCorner" class="kuiLocalTitle">
<strong>{{ savedWorkspace.lastSavedTitle || 'New Graph Workspace' }}</strong>
<strong
ng-if="savedWorkspace.lastSavedTitle"
>{{ savedWorkspace.lastSavedTitle }}</strong>
<strong
ng-if="!savedWorkspace.lastSavedTitle"
i18n-id="xpack.graph.topNavMenu.defaultNewWorkspaceTitle"
i18n-default-message="New Graph Workspace"
></strong>
</div>
<div data-transclude-slot="bottomRow" class="flexGroup">
<!-- Select index pattern. -->
<select class="form-control gphIndexSelect" name="mySelect" ng-change="uiSelectIndex()" ng-class="{'gphIndexSelect-unselected':selectedIndex === null}"
ng-options="option.attributes.title for option in indices" ng-model="grr.proposedIndex">
<option value="">Select index pattern...</option>
<option
value=""
i18n-id="xpack.graph.topNavMenu.selectIndexPatternOptionLabel"
i18n-default-message="Select index pattern..."
></option>
</select>
<!-- Added fields. -->
<span class="gphNoUserSelect" ng-repeat="f in selectedFields" ng-attr-tooltip="Shift + click to toggle if search returns {{f.name}}">
<span
class="gphNoUserSelect"
ng-repeat="f in selectedFields"
ng-attr-tooltip="{{ ::'xpack.graph.topNavMenu.addedFieldTooltip' | i18n: {
defaultMessage: 'Shift + click to toggle if search returns {fName}',
values: { fName: f.name }
} }}"
>
<svg class="gphNode" width="30" height="30" ng-click="clickVertexFieldIcon(f, $event)" ng-class="{'gphNode-disabled':f.hopSize<=0}">
<circle class="gphNode__circle" r="13" cx="15" cy="15" ng-class="{selectedNode:kbnTopNav.currentKey === 'fieldConfig'&&f === selectedFieldConfig}"
ng-attr-style="fill:{{f.color}}" />
@ -27,9 +45,18 @@
</span>
<!-- Add field button. -->
<span class="gphNoUserSelect" ng-attr-tooltip="Add a field source for vertices">
<button class="gphAddButton" ng-disabled="selectedIndex === null" aria-label="Add a field" id="addVertexFieldButton"
ng-class="{'gphAddButton-focus':selectedIndex !== null&&selectedFields.length === 0}" ng-click="toggleShowAdvancedFieldsConfig()">
<span
class="gphNoUserSelect"
ng-attr-tooltip="{{ ::'xpack.graph.topNavMenu.addFieldButtonTooltip' | i18n: { defaultMessage: 'Add a field source for vertices' } }}"
>
<button
class="gphAddButton"
ng-disabled="selectedIndex === null"
aria-label="{{ ::'xpack.graph.topNavMenu.addFieldButtonAriaLabel' | i18n: { defaultMessage: 'Add a field' } }}"
id="addVertexFieldButton"
ng-class="{'gphAddButton-focus':selectedIndex !== null&&selectedFields.length === 0}"
ng-click="toggleShowAdvancedFieldsConfig()"
>
<span aria-hidden="true" class="kuiIcon fa-plus"></span>
</button>
</span>
@ -39,7 +66,12 @@
<div class="kuiLocalSearch">
<input name="searchTerm" type="text" class="kuiLocalSearchInput" ng-model="grr.searchTerm" ng-disabled="liveResponseFields.length === 0"
ng-focus="kbnTopNav.close()" placeholder="foo AND bar NOT baz" autocomplete="off">
<button class="kuiLocalSearchButton" type="submit" ng-disabled="liveResponseFields.length === 0" aria-label="Search">
<button
class="kuiLocalSearchButton"
type="submit"
ng-disabled="liveResponseFields.length === 0"
aria-label="{{ ::'xpack.graph.topNavMenu.searchButtonAriaLabel' | i18n: { defaultMessage: 'Search' } }}"
>
<span aria-hidden="true" class="kuiIcon fa-search"></span>
</button>
</div>
@ -51,14 +83,23 @@
<div class="config" ng-show="kbnTopNav.currentKey === 'fields'" data-test-subj="fieldSelectionList">
<div class="config">
<div class="container-fluid">
<label>Add a field source for vertices</label>
<label
i18n-id="xpack.graph.queryConfig.addFieldLabel"
i18n-default-message="Add a field source for vertices"
></label>
<form>
<div class="input-group form-group" style="width:100%">
<span class="input-group-addon">
<span class="kuiIcon fa-search"></span>
</span>
<input input-focus ng-model="fieldNamesFilterString" placeholder="Filter..."
ng-change="filterFieldsKeyDown()" class="form-control" name="filter" type="text" autocomplete="off" />
<input
input-focus ng-model="fieldNamesFilterString"
placeholder="{{ ::'xpack.graph.queryConfig.filterPlaceholder' | i18n: { defaultMessage: 'Filter...' } }}"
ng-change="filterFieldsKeyDown()"
class="form-control"
name="filter"
type="text"
autocomplete="off" />
</div>
</form>
@ -68,13 +109,21 @@
<div class="kuiVerticalRhythm">
<!-- TODO look at the field chooser directive in Discover to give type icons etc to
field types. This may filter out indexed-only fields though? -->
<button ng-disabled="!selectedField" ng-click="addFieldToSelection()" class="kuiButton kuiButton--primary">
Add
</button>
<button
ng-disabled="!selectedField"
ng-click="addFieldToSelection()"
class="kuiButton kuiButton--primary"
i18n-id="xpack.graph.queryConfig.addFieldButtonLabel"
i18n-default-message="Add"
></button>
</div>
</div>
<button class="kuiLocalDropdownCloseButton" ng-click="kbnTopNav.close()" aria-label="Close">
<button
class="kuiLocalDropdownCloseButton"
ng-click="kbnTopNav.close()"
aria-label="{{ ::'xpack.graph.queryConfig.closeConfigButtonAriaLabel' | i18n: { defaultMessage: 'Close' } }}"
>
<span class="kuiIcon fa-chevron-circle-up"></span>
</button>
</div>
@ -94,7 +143,12 @@
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<label for="colorPicker" class="col-sm-4 control-label"> Color</label>
<label
for="colorPicker"
class="col-sm-4 control-label"
i18n-id="xpack.graph.queryConfig.colorPickerLabel"
i18n-default-message="Color"
></label>
<div class="col-sm-6">
<span id="colorPicker">
<span ng-repeat="c in colors" ng-click="applyColor(selectedFieldConfig,c)" ng-class="c === selectedFieldConfig.color ? 'fa-circle-o' : 'fa-circle'"
@ -105,7 +159,12 @@
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<label for="iconPicker" class="col-sm-4 control-label"> Icon</label>
<label
for="iconPicker"
class="col-sm-4 control-label"
i18n-id="xpack.graph.queryConfig.iconPickerLabel"
i18n-default-message="Icon"
></label>
<div class="col-sm-6">
<span class="gphIconPicker">
<span ng-repeat="i in iconChoices" ng-click="applyIcon(selectedFieldConfig,i)" ng-class="{selectedNode:i==selectedFieldConfig.icon}"
@ -116,18 +175,30 @@
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<label for="qHopSize" class="col-sm-4 control-label">Max terms per hop</label>
<label
for="qHopSize"
class="col-sm-4 control-label"
i18n-id="xpack.graph.queryConfig.maxTermsInputLabel"
i18n-default-message="Max terms per hop"
></label>
<div class="col-sm-6">
<input ng-change="selectedFieldConfigHopSizeChanged()" type="number" class="input-sm" min="0" max="100"
step="1" id="qHopSize" ng-model="selectedFieldConfig.hopSize">
<div class="help-block">
<div class="euiText">
<p>Controls the number of terms returned each search step.</p>
<p
i18n-id="xpack.graph.queryConfig.maxTermsInputDescription"
i18n-default-message="Controls the number of terms returned each search step."
></p>
</div>
<div class="hintbox">
<span class="kuiIcon fa-info text-info"></span> Shift-clicking the field icons in the menu bar
provides a quick way to toggle this number to zero and back
<span class="kuiIcon fa-info text-info"></span>
{{
::'xpack.graph.queryConfig.maxTermsHelpText' | i18n: {
defaultMessage: 'Shift-clicking the field icons in the menu bar provides a quick way to toggle this number to zero and back'
}
}}
</div>
</div>
@ -137,9 +208,12 @@
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<div>
<button ng-click="removeVertexFieldSelection()" class="kuiButton kuiButton--danger">
Remove
</button>
<button
ng-click="removeVertexFieldSelection()"
class="kuiButton kuiButton--danger"
i18n-id="xpack.graph.queryConfig.removeFieldButtonLabel"
i18n-default-message="Remove"
></button>
</div>
</div>
</div>
@ -222,86 +296,122 @@
<div id="sidebar" class="gphSidebar" ng-if="workspace !== null">
<div>
<button class="kuiButton kuiButton--basic kuiButton--small" tooltip="Undo" type="button" ng-click="workspace.undo()"
ng-disabled="workspace === null||workspace.undoLog.length <1">
<button
class="kuiButton kuiButton--basic kuiButton--small"
tooltip="{{ ::'xpack.graph.sidebar.topMenu.undoButtonTooltip' | i18n: { defaultMessage: 'Undo' } }}"
type="button"
ng-click="workspace.undo()"
ng-disabled="workspace === null||workspace.undoLog.length <1"
>
<span class="kuiIcon fa-history"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" tooltip="Redo" type="button" ng-disabled="workspace === null ||workspace.redoLog.length === 0"
ng-click="workspace.redo()">
<button
class="kuiButton kuiButton--basic kuiButton--small"
tooltip="{{ ::'xpack.graph.sidebar.topMenu.redoButtonTooltip' | i18n: { defaultMessage: 'Redo' } }}"
type="button"
ng-disabled="workspace === null ||workspace.redoLog.length === 0"
ng-click="workspace.redo()"
>
<span class="kuiIcon fa-repeat"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||liveResponseFields.length === 0||workspace.nodes.length === 0"
tooltip="Expand selection" ng-click="setDetail(null);workspace.expandSelecteds({toFields:liveResponseFields});">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.expandSelectionButtonTooltip' | i18n: { defaultMessage: 'Expand selection' } }}"
ng-click="setDetail(null);workspace.expandSelecteds({toFields:liveResponseFields});">
<span class="kuiIcon fa-plus"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||workspace.nodes.length === 0"
tooltip="Add links between existing terms" ng-click="workspace.fillInGraph();">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.addLinksButtonTooltip' | i18n: { defaultMessage: 'Add links between existing terms' } }}"
ng-click="workspace.fillInGraph();">
<span class="kuiIcon fa-link"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||workspace.nodes.length === 0"
tooltip="Remove vertices from workspace" ng-click="setDetail(null);workspace.deleteSelection();">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.removeVerticesButtonTooltip' | i18n: { defaultMessage: 'Remove vertices from workspace' } }}"
ng-click="setDetail(null);workspace.deleteSelection();">
<span class="kuiIcon fa-trash"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||workspace.selectedNodes.length === 0"
tooltip="Blacklist selection from return to workspace" ng-click="workspace.blacklistSelection();">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.blacklistButtonTooltip' | i18n: { defaultMessage: 'Blacklist selection from return to workspace' } }}"
ng-click="workspace.blacklistSelection();">
<span class="kuiIcon fa-ban"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||workspace.selectedNodes.length === 0"
tooltip="Custom style selected vertices" ng-click="setDetail({showStyle:true})">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.customStyleButtonTooltip' | i18n: { defaultMessage: 'Custom style selected vertices' } }}"
ng-click="setDetail({showStyle:true})">
<span class="kuiIcon fa-paint-brush"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null||workspace.nodes.length === 0"
tooltip="Drill down" ng-click="setDetail({showDrillDowns:true})">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.drillDownButtonTooltip' | i18n: { defaultMessage: 'Drill down' } }}"
ng-click="setDetail({showDrillDowns:true})">
<span class="kuiIcon fa-info"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace.nodes.length === 0" ng-if="workspace.nodes.length === 0||workspace.force === null"
tooltip="Run layout" ng-click="workspace.runLayout()">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.runLayoutButtonTooltip' | i18n: { defaultMessage: 'Run layout' } }}"
ng-click="workspace.runLayout()">
<span class="kuiIcon fa-play"></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--small" ng-if="workspace.force !== null&&workspace.nodes.length>0"
tooltip="Pause layout" ng-click="workspace.stopLayout()">
tooltip="{{ ::'xpack.graph.sidebar.topMenu.pauseLayoutButtonTooltip' | i18n: { defaultMessage: 'Pause layout' } }}"
ng-click="workspace.stopLayout()">
<span class="kuiIcon fa-pause"></span>
</button>
</div>
<div>
<div class="gphSidebar__header">
<span class="kuiIcon fa-shopping-cart"></span> Selections
<span class="kuiIcon fa-shopping-cart"></span>
{{ ::'xpack.graph.sidebar.selectionsTitle' | i18n: { defaultMessage: 'Selections' } }}
</div>
<div id="vertexSelectionTypesBar">
<button tooltip="Select all" type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectAll()">
all
</button>
<button
tooltip="{{ ::'xpack.graph.sidebar.selections.selectAllButtonTooltip' | i18n: { defaultMessage: 'Select all' } }}"
type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectAll()"
i18n-id="xpack.graph.sidebar.selections.selectAllButtonLabel"
i18n-default-message="all"
></button>
<button tooltip="Select none" type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectNone()">
none
</button>
<button
tooltip="{{ ::'xpack.graph.sidebar.selections.selectNoneButtonTooltip' | i18n: { defaultMessage: 'Select none' } }}"
type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectNone()"
i18n-id="xpack.graph.sidebar.selections.selectNoneButtonLabel"
i18n-default-message="none"
></button>
<button tooltip="Invert selection" type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectInvert()">
invert
</button>
<button
tooltip="{{ ::'xpack.graph.sidebar.selections.invertSelectionButtonTooltip' | i18n: { defaultMessage: 'Invert selection' } }}"
type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.nodes.length === 0" ng-click="setDetail(null);workspace.selectInvert()"
i18n-id="xpack.graph.sidebar.selections.invertSelectionButtonLabel"
i18n-default-message="invert"
></button>
<button tooltip="Select neighbours" type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.selectedNodes.length === 0" ng-click="setDetail(null);workspace.selectNeighbours()">
linked
</button>
<button
tooltip="{{ ::'xpack.graph.sidebar.selections.selectNeighboursButtonTooltip' | i18n: { defaultMessage: 'Select neighbours' } }}"
type="button" class="kuiButton kuiButton--basic kuiButton--small gphVertexSelect__button"
ng-disabled="workspace.selectedNodes.length === 0" ng-click="setDetail(null);workspace.selectNeighbours()"
i18n-id="xpack.graph.sidebar.selections.selectNeighboursButtonLabel"
i18n-default-message="linked"
></button>
</div>
<div class="gphSelectionList">
<p ng-if="workspace.selectedNodes.length === 0" class="help-block">No selections. Click on vertices to add</p>
<p
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"
></p>
<div ng-repeat="n in workspace.selectedNodes" class="gphSelectionList__field" ng-class="{'gphSelectionList__field--selected': isSelectedSelected(n)}"
ng-click="selectSelected(n)">
@ -329,13 +439,17 @@
<div ng-if="detail.showDrillDowns">
<div class="gphSidebar__header">
<span class="kuiIcon fa-info"></span> Drill-downs
<span class="kuiIcon fa-info"></span>
{{ ::'xpack.graph.sidebar.drillDownsTitle' | i18n: { defaultMessage: 'Drill-downs' } }}
</div>
<div class="gphSidebar__panel">
<p ng-if="urlTemplates.length === 0" class="help-block">
Configure drill-downs from the settings menu
</p>
<p
ng-if="urlTemplates.length === 0"
class="help-block"
i18n-id="xpack.graph.sidebar.drillDowns.noDrillDownsHelpText"
i18n-default-message="Configure drill-downs from the settings menu"
></p>
<ul class="list-group">
<li class="list-group-item" ng-repeat="urlTemplate in urlTemplates">
@ -349,7 +463,8 @@
<div class="gphSidebar__panel" ng-if="(detail.showStyle)&&(workspace.selectedNodes.length>0)">
<div class="gphSidebar__header">
<span class="kuiIcon fa-paint-brush"></span> Style selected vertices
<span class="kuiIcon fa-paint-brush"></span>
{{ ::'xpack.graph.sidebar.styleVerticesTitle' | i18n: { defaultMessage: 'Style selected vertices' } }}
</div>
<div class="form-group form-group-sm gphFormGroup--small">
@ -368,21 +483,36 @@
<button class="kuiButton kuiButton--basic kuiButton--iconText kuiButton--small" ng-if="workspace.selectedNodes.length>1||(workspace.selectedNodes.length>0&&workspace.selectedNodes[0] !== detail.latestNodeSelection)"
tooltip="group the currently selected items into {{detail.latestNodeSelection.label}}" ng-click="workspace.groupSelections(detail.latestNodeSelection)">
<span class="kuiButton__icon kuiIcon fa-object-group"></span>
<span>group</span>
<span
i18n-id="xpack.graph.sidebar.groupButtonLabel"
i18n-default-message="group"
></span>
</button>
<button class="kuiButton kuiButton--basic kuiButton--iconText kuiButton--small" ng-if="detail.latestNodeSelection.numChildren>0"
tooltip="ungroup {{detail.latestNodeSelection.label}}" ng-click="workspace.ungroup(detail.latestNodeSelection)">
<span class="kuiIcon fa-object-ungroup"></span>
<span>ungroup</span>
<span
i18n-id="xpack.graph.sidebar.ungroupButtonLabel"
i18n-default-message="ungroup"
></span>
</button>
<form class="form-horizontal">
<div class="form-group form-group-sm gphFormGroup--small">
<label for="labelEdit" class="col-sm-3 control-label">Display label</label>
<label
for="labelEdit"
class="col-sm-3 control-label"
i18n-id="xpack.graph.sidebar.displayLabelLabel"
i18n-default-message="Display label"
></label>
<div class="col-sm-9">
<input type="text" id="labelEdit" class="form-control input-sm" ng-model="detail.latestNodeSelection.label">
<div class="help-block">Change the label for this vertex</div>
<div
class="help-block"
i18n-id="xpack.graph.sidebar.displayLabelHelpText"
i18n-default-message="Change the label for this vertex"
></div>
</div>
</div>
</form>
@ -390,11 +520,17 @@
<div ng-if="detail.mergeCandidates.length>0" class="gphSidebar__panel">
<div class="gphSidebar__header">
<span class="kuiIcon fa-link"></span> Link summary
<span class="kuiIcon fa-link"></span>
{{ ::'xpack.graph.sidebar.linkSummaryTitle' | i18n: { defaultMessage: 'Link summary' } }}
</div>
<div ng-repeat="mc in detail.mergeCandidates">
<span>
<button tooltip="Merge {{mc.term1}} into {{mc.term2}}" type="button" ng-attr-style="opacity:{{0.2+(mc.overlap/mc.v1)}};"
<button
tooltip="{{ ::'xpack.graph.sidebar.linkSummary.mergeTerm1ToTerm2ButtonTooltip' | i18n: {
defaultMessage: 'Merge {term1} into {term2}',
values: { term1: mc.term1, term2: mc.term2 },
} }}"
type="button" ng-attr-style="opacity:{{0.2+(mc.overlap/mc.v1)}};"
class="kuiButton kuiButton--basic kuiButton--small" ng-click="performMerge(mc.id2, mc.id1)">
<span class="kuiIcon fa-chevron-circle-right"></span>
</button>
@ -402,7 +538,12 @@
<span class="gphLinkSummary__term--1">{{mc.term1}}</span>
<span class="gphLinkSummary__term--2">{{mc.term2}}</span>
<button tooltip="Merge {{mc.term2}} into {{mc.term1}}" type="button" class="kuiButton kuiButton--basic kuiButton--small"
<button
tooltip="{{ ::'xpack.graph.sidebar.linkSummary.mergeTerm2ToTerm1ButtonTooltip' | i18n: {
defaultMessage: 'Merge {term2} into {term1}',
values: { term1: mc.term1, term2: mc.term2 },
} }}"
type="button" class="kuiButton kuiButton--basic kuiButton--small"
ng-attr-style="opacity:{{0.2+(mc.overlap/mc.v2)}};" ng-click="performMerge(mc.id1, mc.id2)">
<span class="kuiIcon fa-chevron-circle-left"></span>
</button>
@ -411,21 +552,44 @@
<!-- Venn diagram of term/shared doc intersections -->
<div class="gphLinkSummary__venn" venn="mc"></div>
<small class="gphLinkSummary__term--1" tooltip="{{mc.v1}} documents have term {{mc.term1}}">{{mc.v1}}</small>
<small class="gphLinkSummary__term--1-2" tooltip="{{mc.overlap}} documents have both terms">&nbsp;({{mc.overlap}})&nbsp;</small>
<small class="gphLinkSummary__term--2" tooltip="{{mc.v2}} documents have term {{mc.term2}}">{{mc.v2}}</small>
<small
class="gphLinkSummary__term--1"
tooltip="{{ ::'xpack.graph.sidebar.linkSummary.leftTermCountTooltip' | i18n: {
defaultMessage: '{count} documents have term {term}',
values: { count: mc.v1, term: mc.term1 },
} }}"
>{{mc.v1}}</small>
<small
class="gphLinkSummary__term--1-2"
tooltip="{{ ::'xpack.graph.sidebar.linkSummary.bothTermsCountTooltip' | i18n: {
defaultMessage: '{count} documents have both terms',
values: { count: mc.overlap },
} }}"
>&nbsp;({{mc.overlap}})&nbsp;</small>
<small
class="gphLinkSummary__term--2"
tooltip="{{ ::'xpack.graph.sidebar.linkSummary.rightTermCountTooltip' | i18n: {
defaultMessage: '{count} documents have term {term}',
values: { count: mc.v2, term: mc.term2 },
} }}"
>{{mc.v2}}</small>
</div>
<div class="gphSidebar__panel" ng-if="(detail.inferredEdge)">
<div class="gphSidebar__header">
<span class="kuiIcon fa-cog"></span> Similar labels
<span class="kuiIcon fa-cog"></span>
{{ ::'xpack.graph.sidebar.similarLabelsTitle' | i18n: { defaultMessage: 'Similar labels' } }}
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<div style="line-height: 24px;">
<button tooltip="Merge {{detail.inferredEdge.topTarget.label}} into {{detail.inferredEdge.topSrc.label}}"
<button
tooltip="{{ ::'xpack.graph.sidebar.similarLabels.mergeTargetToSrcButtonTooltip' | i18n: {
defaultMessage: 'Merge {targetLabel} into {srcLabel}',
values: { targetLabel: detail.inferredEdge.topTarget.label, srcLabel: detail.inferredEdge.topSrc.label },
} }}"
type="button" style="vertical-align: top;" class="kuiButton kuiButton--basic kuiButton--small"
ng-click="performMerge(detail.inferredEdge.topTarget.id, detail.inferredEdge.topSrc.id)">
<span class="kui fa-chevron-circle-down"></span>
@ -438,7 +602,11 @@
<span style="vertical-align: top;">{{detail.inferredEdge.topSrc.label}}</span>
</div>
<div style="line-height: 24px;">
<button tooltip="Merge {{detail.inferredEdge.topSrc.label}} into {{detail.inferredEdge.topTarget.label}}"
<button
tooltip="{{ ::'xpack.graph.sidebar.similarLabels.mergeSrcToTargetButtonTooltip' | i18n: {
defaultMessage: 'Merge {srcLabel} into {targetLabel}',
values: { targetLabel: detail.inferredEdge.topTarget.label, srcLabel: detail.inferredEdge.topSrc.label },
} }}"
type="button" style="vertical-align: top;" class="kuiButton kuiButton--basic kuiButton--small"
ng-click="performMerge(detail.inferredEdge.topSrc.id, detail.inferredEdge.topTarget.id)">
<span class="kuiIcon fa-chevron-circle-up"></span>
@ -453,9 +621,12 @@
</div>
<div class="col-sm-10">
Key terms: <small> {{detail.inferredEdge.label}}
</div>
<div
class="col-sm-10"
i18n-id="xpack.graph.sidebar.similarLabels.keyTermsText"
i18n-default-message="Key terms: {inferredEdgeLabel}"
i18n-values="{ inferredEdgeLabel: '<small>' + detail.inferredEdge.label + '</small>' }"
></div>
</div>
</div>
</div>

View file

@ -1,7 +1,11 @@
<div class="kuiLocalDropdownTitle">Open Workspace</div>
<div
class="kuiLocalDropdownTitle"
i18n-id="xpack.graph.topNavMenu.open.openWorkspaceTitle"
i18n-default-message="Open Workspace"
></div>
<saved-object-finder
title="Saved Workspaces"
title="{{ ::'xpack.graph.topNavMenu.open.workspacesListTooltip' | i18n: { defaultMessage: 'Saved Workspaces' } }}"
type="Graph workspace"
use-local-management="true"
on-choose="openSavedWorkspace"

View file

@ -1,20 +1,43 @@
<form ng-submit="saveWorkspace()" role="form">
<div class="kuiLocalDropdownTitle">Save Workspace</div>
<div
class="kuiLocalDropdownTitle"
i18n-id="xpack.graph.topNavMenu.save.saveWorkspaceTitle"
i18n-default-message="Save Workspace"
></div>
<div class="form-group">
<label for="workspaceTitle">Name</label>
<input id="workspaceTitle" type="text" ng-model="savedWorkspace.title" class="form-control" placeholder="Graph workspace name" input-focus="select">
<label
for="workspaceTitle"
i18n-id="xpack.graph.topNavMenu.save.nameInputLabel"
i18n-default-message="Name"
></label>
<input id="workspaceTitle" type="text" ng-model="savedWorkspace.title" class="form-control"
placeholder="{{ ::'xpack.graph.topNavMenu.save.nameInputPlaceholder' | i18n: { defaultMessage: 'Graph workspace name' } }}"
input-focus="select"
>
</div>
<saved-object-save-as-check-box saved-object="savedWorkspace"></saved-object-save-as-check-box>
<div class="form-group">
<label for="workspaceTitle">Description</label>
<textarea class="form-control input-sm" rows="5" id="notesEdit" placeholder="Any notes.." ng-model="grr.description"></textarea>
<label
for="workspaceTitle"
i18n-id="xpack.graph.topNavMenu.save.descriptionInputLabel"
i18n-default-message="Description"
></label>
<textarea
class="form-control input-sm" rows="5" id="notesEdit"
placeholder="{{ ::'xpack.graph.topNavMenu.save.descriptionInputPlaceholder' | i18n: { defaultMessage: 'Any notes..' } }}"
ng-model="grr.description"
></textarea>
</div>
<div class="text-warning " ng-if="workspace.nodes.length>0 && !grr.userHasConfirmedSaveWorkspaceData && graphSavePolicy=='configAndDataWithConsent'">
<i class="fa fa-warning"></i> The data in this workspace will be cleared and only the configuration will be saved
<i class="fa fa-warning"></i>
{{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning' | i18n: {
defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved',
} }}
</div>
<div class="gphNoUserSelect checkbox" ng-if="graphSavePolicy=='configAndDataWithConsent'">
<label>
<input type="checkbox" ng-model="grr.userHasConfirmedSaveWorkspaceData"> Save Graph Content
<input type="checkbox" ng-model="grr.userHasConfirmedSaveWorkspaceData">
{{ ::'xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel' | i18n: { defaultMessage: 'Save Graph Content' } }}
</label>
</div>
@ -22,14 +45,17 @@
type="submit"
ng-disabled="!savedWorkspace.title"
class="kuiButton kuiButton--primary"
aria-label="Save workspace"
>
Save
</button>
aria-label="{{ ::'xpack.graph.topNavMenu.save.confirmButtonAriaLabel' | i18n: { defaultMessage: 'Save workspace' } }}"
i18n-id="xpack.graph.topNavMenu.save.confirmButtonLabel"
i18n-default-message="Save"
></button>
<div ng-if="workspace.nodes.length>0 && graphSavePolicy=='config'">
<span class="text-info" >
<i class="fa fa-info"></i> The data in this workspace will be cleared and only the configuration will be saved
<i class="fa fa-info"></i>
{{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyText' | i18n: {
defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved',
} }}
</span>
</div>

View file

@ -1,30 +1,46 @@
<div class="kuiLocalDropdownTitle">Settings</div>
<div
class="kuiLocalDropdownTitle"
i18n-id="xpack.graph.topNavMenu.settingsTitle"
i18n-default-message="Settings"
></div>
<!-- ====== start tabs ====== -->
<ul class="nav nav-tabs" ng-show="selectedIndex !== null">
<li ng-show="workspace" ng-class="{active: configPanel === 'lastRequest'}" >
<a ng-click="configPanel='lastRequest'" class="navbar-link">
Last request
</a>
<a
ng-click="configPanel='lastRequest'"
class="navbar-link"
i18n-id="xpack.graph.settings.lastRequestTitle"
i18n-default-message="Last request"
></a>
</li>
<li ng-show="workspace" ng-class="{active: configPanel ==='blacklist'}">
<a ng-click="configPanel='blacklist'" class="navbar-link">
Blacklist
</a>
<a
ng-click="configPanel='blacklist'"
class="navbar-link"
i18n-id="xpack.graph.settings.blacklistTitle"
i18n-default-message="Blacklist"
></a>
</li>
<li ng-class="{active: configPanel === 'settings'}">
<a ng-click="configPanel='settings'" class="navbar-link" >
Advanced settings
</a>
<a
ng-click="configPanel='settings'"
class="navbar-link"
i18n-id="xpack.graph.settings.advancedSettingsTitle"
i18n-default-message="Advanced settings"
></a>
</li>
<li ng-show="canEditDrillDownUrls" ng-class="{active: configPanel === 'drillDowns'}" >
<a ng-click="configPanel='drillDowns'" class="navbar-link">
Drill-downs
</a>
<a
ng-click="configPanel='drillDowns'"
class="navbar-link"
i18n-id="xpack.graph.settings.drillDownsTitle"
i18n-default-message="Drill-downs"
></a>
</li>
</ul>
<!-- ====== stop tabs ====== -->
@ -38,10 +54,18 @@
<small class="help-block">http://host:port/{{selectedIndex.name}}/_xpack/graph/_explore</small>
<ul class="nav nav-tabs">
<li ng-class="{active: spymode === 'request'}">
<a ng-click="spymode='request'">Request</a>
<a
ng-click="spymode='request'"
i18n-id="xpack.graph.settings.lastRequest.requestTabTitle"
i18n-default-message="Request"
></a>
</li>
<li ng-class="{active: spymode === 'response'}">
<a ng-click="spymode='response'">Response</a>
<a
ng-click="spymode='response'"
i18n-id="xpack.graph.settings.lastRequest.responseTabTitle"
i18n-default-message="Response"
></a>
</li>
</ul>
@ -66,9 +90,11 @@
class="list-group-item list-group-item--noBorder"
ng-if="(workspace!==null) && (configPanel==='blacklist')"
>
<p class="help-block">
These terms are currently blacklisted from re-appearing in the workspace
</p>
<p
class="help-block"
i18n-id="xpack.graph.settings.blacklist.blacklistHelpText"
i18n-default-message="These terms are currently blacklisted from re-appearing in the workspace"
></p>
<div class="gphSelectionList kuiVerticalRhythm">
<!-- ====== start terms ====== -->
@ -101,7 +127,10 @@
ng-disabled="workspace.blacklistedNodes.length === 0"
>
<span class="kuiButton__icon kuiIcon fa-trash"></span>
<span>Clear</span>
<span
i18n-id="xpack.graph.settings.blacklist.clearButtonLabel"
i18n-default-message="Clear"
></span>
</button>
</div>
<!-- ====== end term blacklist tab content ====== -->
@ -119,7 +148,11 @@
<!-- ====== start url ====== -->
<div class="form-group">
<div class="col-sm-1 control-label">
<label for="urlTemplateUrl">URL</label>
<label
for="urlTemplateUrl"
i18n-id="xpack.graph.settings.drillDowns.urlInputLabel"
i18n-default-message="URL"
></label>
</div>
<div class="col-sm-11">
<input
@ -134,14 +167,29 @@
>
<span ng-if="suggestTemplateFix">
<i tooltip="Kibana URL pasted" class="text-color-warning fa fa-warning"></i>
This looks like a Kibana URL. Would you like us to convert it to a template for you?
<a ng-click="replaceKibanaUrlParam()">yes</a> / <a ng-click="rejectKibanaUrlSuggestion()">no</a>
<i
tooltip="{{ ::'xpack.graph.settings.drillDowns.kibanaUrlWarningTooltip' | i18n: { defaultMessage: 'Kibana URL pasted' } }}"
class="text-color-warning fa fa-warning"
></i>
{{ ::'xpack.graph.settings.drillDowns.kibanaUrlWarningText' | i18n: { defaultMessage: 'This looks like a Kibana URL. Would you like us to convert it to a template for you?' } }}
<a
ng-click="replaceKibanaUrlParam()"
i18n-id="xpack.graph.settings.drillDowns.kibanaUrlWarningYesOptionLinkText"
i18n-default-message="yes"
></a> / <a
ng-click="rejectKibanaUrlSuggestion()"
i18n-id="xpack.graph.settings.drillDowns.kibanaUrlWarningNoOptionLinkText"
i18n-default-message="no"
></a>
</span>
<p class="help-block" ng-non-bindable>
Define template URLs using {{gquery}} where the selected vertex terms are inserted
</p>
<p
class="help-block"
ng-non-bindable
i18n-id="xpack.graph.settings.drillDowns.urlInputHelpText"
i18n-default-message="Define template URLs using {gquery} where the selected vertex terms are inserted"
i18n-values="{ gquery: '{{gquery}}' }"
></p>
</div>
</div>
<!-- ====== stop url ====== -->
@ -149,7 +197,11 @@
<!-- ====== start title ====== -->
<div class="form-group">
<div class="col-sm-1 control-label">
<label for="urlDescription">Title</label>
<label
for="urlDescription"
i18n-id="xpack.graph.settings.drillDowns.urlDescriptionInputLabel"
i18n-default-message="Title"
></label>
</div>
<div class="col-sm-5">
<input
@ -157,12 +209,16 @@
type="text"
autocomplete="off"
ng-model="newUrlTemplate.description"
placeholder="Search on Google"
placeholder="{{ :: 'xpack.graph.settings.drillDowns.urlDescriptionInputPlaceholder' | i18n: { defaultMessage: 'Search on Google' } }}"
class="form-control"
>
</div>
<div class="col-sm-2 control-label">
<label for="encoder">URL parameter type</label>
<label
for="encoder"
i18n-id="xpack.graph.settings.drillDowns.urlEncoderInputLabel"
i18n-default-message="URL parameter type"
></label>
</div>
<div class="col-sm-4">
<select
@ -179,7 +235,11 @@
<!-- ====== start icon ====== -->
<div class="form-group">
<div class="col-sm-1 control-label">
<label for="encoder">Toolbar icon</label>
<label
for="encoder"
i18n-id="xpack.graph.settings.drillDowns.toolbarIconPickerLabel"
i18n-default-message="Toolbar icon"
></label>
</div>
<div class="col-sm-9">
@ -201,18 +261,18 @@
ng-disabled="!newUrlTemplate.url&&!newUrlTemplate.description&&!newUrlTemplate.icon"
class="kuiButton kuiButton--basic"
ng-click="resetNewUrlTemplate()"
>
Reset
</button>
i18n-id="xpack.graph.settings.drillDowns.resetButtonLabel"
i18n-default-message="Reset"
></button>
<button
type="submit"
ng-disabled="!newUrlTemplate.url||!newUrlTemplate.description"
class="kuiButton kuiButton--primary"
aria-label="Save drill-down"
>
Save
</button>
aria-label="{{ ::'xpack.graph.settings.drillDowns.resetButtonAriaLabel' | i18n: { defaultMessage: 'Save drill-down' } }}"
i18n-id="xpack.graph.settings.drillDowns.saveButtonLabel"
i18n-default-message="Save"
></button>
</div>
</div>
</div>
@ -238,7 +298,7 @@
<button
ng-click="editUrlTemplate(urlTemplate)"
class="kuiButton kuiButton--basic kuiButton--iconText kuiButton--small"
aria-label="Edit"
aria-label="{{ ::'xpack.graph.settings.drillDowns.editButtonAriaLabel' | i18n: { defaultMessage: 'Edit' } }}"
>
<span aria-hidden="true" class="kuiIcon fa-pencil"></span>
</button>
@ -246,7 +306,7 @@
<button
ng-click="removeUrlTemplate(urlTemplate)"
class="kuiButton kuiButton--danger kuiButton--iconText kuiButton--small"
aria-label="Remove"
aria-label="{{ ::'xpack.graph.settings.drillDowns.removeButtonAriaLabel' | i18n: { defaultMessage: 'Remove' } }}"
>
<span aria-hidden="true" class="kuiIcon fa-trash"></span>
</button>
@ -267,9 +327,12 @@
>
<form class="form-horizontal">
<div class="form-group form-group-sm gphFormGroup--small">
<label for="qIndexSampleSize" class="col-sm-4 control-label">
Sample size
</label>
<label
for="qIndexSampleSize"
class="col-sm-4 control-label"
i18n-id="xpack.graph.settings.advancedSettings.sampleSizeInputLabel"
i18n-default-message="Sample size"
></label>
<div class="col-sm-6">
<input
@ -281,9 +344,11 @@
ng-model="exploreControls.sampleSize"
>
<div class="help-block">
Terms are identified from samples of the most relevant documents. Bigger is not necessarily better - can be slower and less relevant.
</div>
<div
class="help-block"
i18n-id="xpack.graph.settings.advancedSettings.sampleSizeInputHelpText"
i18n-default-message="Terms are identified from samples of the most relevant documents. Bigger is not necessarily better - can be slower and less relevant."
></div>
</div>
</div>
@ -296,18 +361,25 @@
id="isSignifChk2"
ng-model="exploreControls.useSignificance"
>
Significant links
{{ ::'xpack.graph.settings.advancedSettings.significantLinksCheckboxLabel' | i18n: { defaultMessage: 'Significant links' } }}
</label>
</div>
<span class="help-block">
Identify terms that are "significant" rather than simply popular
</span>
<span
class="help-block"
i18n-id="xpack.graph.settings.advancedSettings.significantLinksCheckboxHelpText"
i18n-default-message="Identify terms that are &quot;significant&quot; rather than simply popular"
></span>
</div>
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<label for="minDocCount" class="col-sm-4 control-label">Certainty</label>
<label
for="minDocCount"
class="col-sm-4 control-label"
i18n-id="xpack.graph.settings.advancedSettings.certaintyInputLabel"
i18n-default-message="Certainty"
></label>
<div class="col-sm-6">
<input
type="number"
@ -319,16 +391,21 @@
ng-model="exploreControls.minDocCount"
>
<div class="help-block">
The min number of documents that are required as evidence before introducing a related term
</div>
<div
class="help-block"
i18n-id="xpack.graph.settings.advancedSettings.certaintyInputHelpText"
i18n-default-message="The min number of documents that are required as evidence before introducing a related term"
></div>
</div>
</div>
<div class="form-group form-group-sm gphFormGroup--small">
<label for="qDiversityField" class="col-sm-4 control-label">
Diversity field
</label>
<label
for="qDiversityField"
class="col-sm-4 control-label"
i18n-id="xpack.graph.settings.advancedSettings.diversityFieldInputLabel"
i18n-default-message="Diversity field"
></label>
<div class="col-sm-6">
<select
@ -337,12 +414,16 @@
ng-options="field.name for field in allFields"
ng-model="exploreControls.sampleDiversityField"
>
<option value="">[No diversification]</option>
<option
value=""
i18n-id="xpack.graph.settings.advancedSettings.diversityFieldInputOptionLabel"
i18n-default-message="[No diversification]"
></option>
</select>
<span class="help-block">
To avoid document samples being dominated by a single voice, pick the field that helps identify the source of bias.
<em>This must be a single-term field or searches will be rejected with an error</em>
{{ ::'xpack.graph.settings.advancedSettings.diversityFieldInputHelpText1' | i18n: { defaultMessage: 'To avoid document samples being dominated by a single voice, pick the field that helps identify the source of bias.' } }}
<em>{{ ::'xpack.graph.settings.advancedSettings.diversityFieldInputHelpText2' | i18n: { defaultMessage: 'This must be a single-term field or searches will be rejected with an error' } }}</em>
</span>
</div>
</div>
@ -354,9 +435,9 @@
<label
for="qMaxValuesPerDoc"
class="col-sm-4 control-label"
>
Max docs per field
</label>
i18n-id="xpack.graph.settings.advancedSettings.maxValuesInputLabel"
i18n-default-message="Max docs per field"
></label>
<div class="col-sm-6">
<input
@ -370,8 +451,8 @@
>
<span class="help-block">
Max number of documents in a sample that can contain the same value for the
<em>{{selectedDiversityField.name}}</em> field
{{ ::'xpack.graph.settings.advancedSettings.maxValuesInputHelpText' | i18n: { defaultMessage: 'Max number of documents in a sample that can contain the same value for the' } }}
<em>{{selectedDiversityField.name}}</em> {{ ::'xpack.graph.settings.advancedSettings.maxValuesInputHelpText.fieldText' | i18n: { defaultMessage: 'field' } }}
</span>
</div>
</div>
@ -380,9 +461,9 @@
<label
for="qTimeoutMillis"
class="col-sm-4 control-label"
>
Timeout (ms)
</label>
i18n-id="xpack.graph.settings.advancedSettings.timeoutInputLabel"
i18n-default-message="Timeout (ms)"
></label>
<div class="col-sm-6">
<input
@ -395,9 +476,11 @@
ng-model="exploreControls.timeoutMillis"
>
<span class="help-block">
Max time in milliseconds a request can run
</span>
<span
class="help-block"
i18n-id="xpack.graph.settings.advancedSettings.timeoutInputHelpText"
i18n-default-message="Max time in milliseconds a request can run"
></span>
</div>
</div>
</form>

View file

@ -4,13 +4,17 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export function checkLicense(xpackLicenseInfo) {
if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) {
return {
showAppLink: true,
enableAppLink: false,
message: 'Graph is unavailable - license information is not available at this time.'
message: i18n.translate('xpack.graph.serverSideErrors.unavailableLicenseInformationErrorMessage', {
defaultMessage: 'Graph is unavailable - license information is not available at this time.',
})
};
}
@ -19,14 +23,18 @@ export function checkLicense(xpackLicenseInfo) {
return {
showAppLink: false,
enableAppLink: false,
message: 'Graph is unavailable'
message: i18n.translate('xpack.graph.serverSideErrors.unavailableGraphErrorMessage', {
defaultMessage: 'Graph is unavailable',
})
};
}
const isLicenseActive = xpackLicenseInfo.license.isActive();
let message;
if (!isLicenseActive) {
message = `Graph is unavailable - license has expired.`;
message = i18n.translate('xpack.graph.serverSideErrors.expiredLicenseErrorMessage', {
defaultMessage: 'Graph is unavailable - license has expired.',
});
}
if (xpackLicenseInfo.license.isOneOf([ 'trial', 'platinum' ])) {
@ -37,7 +45,13 @@ export function checkLicense(xpackLicenseInfo) {
};
}
message = `Graph is unavailable for the current ${xpackLicenseInfo.license.getType()} license. Please upgrade your license.`;
message = i18n.translate('xpack.graph.serverSideErrors.wrongLicenseTypeErrorMessage', {
defaultMessage: 'Graph is unavailable for the current {licenseType} license. Please upgrade your license.',
values: {
licenseType: xpackLicenseInfo.license.getType(),
},
});
return {
showAppLink: false,
enableAppLink: false,