[Graph] Ensure inclusive language (#71416)

This commit is contained in:
Joe Reuter 2020-07-14 18:13:20 +02:00 committed by GitHub
parent f0787f1224
commit 4e97bb11eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 106 additions and 87 deletions

View file

@ -247,7 +247,7 @@ retrieved.
`timelion:es.timefield`:: The default field containing a timestamp when using the `.es()` query.
`timelion:graphite.url`:: [experimental] Used with graphite queries, this is the URL of your graphite host
in the form https://www.hostedgraphite.com/UID/ACCESS_KEY/graphite. This URL can be
selected from a whitelist configured in the `kibana.yml` under `timelion.graphiteUrls`.
selected from an allow-list configured in the `kibana.yml` under `timelion.graphiteUrls`.
`timelion:max_buckets`:: The maximum number of buckets a single data source can return.
This value is used for calculating automatic intervals in visualizations.
`timelion:min_interval`:: The smallest interval to calculate when using "auto".

View file

@ -107,7 +107,7 @@ function UnGroupOperation(parent, child) {
// The main constructor for our GraphWorkspace
function GraphWorkspace(options) {
const self = this;
this.blacklistedNodes = [];
this.blocklistedNodes = [];
this.options = options;
this.undoLog = [];
this.redoLog = [];
@ -379,7 +379,7 @@ function GraphWorkspace(options) {
this.redoLog = [];
this.nodesMap = {};
this.edgesMap = {};
this.blacklistedNodes = [];
this.blocklistedNodes = [];
this.selectedNodes = [];
this.lastResponse = null;
};
@ -630,11 +630,11 @@ function GraphWorkspace(options) {
self.runLayout();
};
this.unblacklist = function (node) {
self.arrRemove(self.blacklistedNodes, node);
this.unblocklist = function (node) {
self.arrRemove(self.blocklistedNodes, node);
};
this.blacklistSelection = function () {
this.blocklistSelection = function () {
const selection = self.getAllSelectedNodes();
const danglingEdges = [];
self.edges.forEach(function (edge) {
@ -645,7 +645,7 @@ function GraphWorkspace(options) {
});
selection.forEach((node) => {
delete self.nodesMap[node.id];
self.blacklistedNodes.push(node);
self.blocklistedNodes.push(node);
node.isSelected = false;
});
self.arrRemoveAll(self.nodes, selection);
@ -671,10 +671,10 @@ function GraphWorkspace(options) {
}
let step = {};
//Add any blacklisted nodes to exclusion list
//Add any blocklisted nodes to exclusion list
const excludeNodesByField = {};
const nots = [];
const avoidNodes = this.blacklistedNodes;
const avoidNodes = this.blocklistedNodes;
for (let i = 0; i < avoidNodes.length; i++) {
const n = avoidNodes[i];
let arr = excludeNodesByField[n.data.field];
@ -914,8 +914,8 @@ function GraphWorkspace(options) {
const nodesByField = {};
const excludeNodesByField = {};
//Add any blacklisted nodes to exclusion list
const avoidNodes = this.blacklistedNodes;
//Add any blocklisted nodes to exclusion list
const avoidNodes = this.blocklistedNodes;
for (let i = 0; i < avoidNodes.length; i++) {
const n = avoidNodes[i];
let arr = excludeNodesByField[n.data.field];
@ -1320,12 +1320,12 @@ function GraphWorkspace(options) {
allExistingNodes.forEach((existingNode) => {
addTermToFieldList(excludeNodesByField, existingNode.data.field, existingNode.data.term);
});
const blacklistedNodes = self.blacklistedNodes;
blacklistedNodes.forEach((blacklistedNode) => {
const blocklistedNodes = self.blocklistedNodes;
blocklistedNodes.forEach((blocklistedNode) => {
addTermToFieldList(
excludeNodesByField,
blacklistedNode.data.field,
blacklistedNode.data.term
blocklistedNode.data.field,
blocklistedNode.data.term
);
});

View file

@ -82,7 +82,7 @@ describe('graphui-workspace', function () {
expect(workspace.nodes.length).toEqual(2);
expect(workspace.edges.length).toEqual(1);
expect(workspace.selectedNodes.length).toEqual(0);
expect(workspace.blacklistedNodes.length).toEqual(0);
expect(workspace.blocklistedNodes.length).toEqual(0);
const nodeA = workspace.getNode(workspace.makeNodeId('field1', 'a'));
expect(typeof nodeA).toBe('object');
@ -124,7 +124,7 @@ describe('graphui-workspace', function () {
expect(workspace.nodes.length).toEqual(2);
expect(workspace.edges.length).toEqual(1);
expect(workspace.selectedNodes.length).toEqual(0);
expect(workspace.blacklistedNodes.length).toEqual(0);
expect(workspace.blocklistedNodes.length).toEqual(0);
mockedResult = {
vertices: [

View file

@ -124,7 +124,7 @@
<button class="kuiButton kuiButton--basic kuiButton--small" ng-disabled="workspace === null ||workspace.selectedNodes.length === 0"
tooltip="{{ ::'xpack.graph.sidebar.topMenu.blocklistButtonTooltip' | i18n: { defaultMessage: 'Block selection from appearing in workspace' } }}"
aria-label="{{ ::'xpack.graph.sidebar.topMenu.blocklistButtonTooltip' | i18n: { defaultMessage: 'Block selection from appearing in workspace' } }}"
ng-click="workspace.blacklistSelection();">
ng-click="workspace.blocklistSelection();">
<span class="kuiIcon fa-ban"></span>
</button>

View file

@ -562,8 +562,8 @@ export function initGraphApp(angularModule, deps) {
run: () => {
const settingsObservable = asAngularSyncedObservable(
() => ({
blacklistedNodes: $scope.workspace ? [...$scope.workspace.blacklistedNodes] : undefined,
unblacklistNode: $scope.workspace ? $scope.workspace.unblacklist : undefined,
blocklistedNodes: $scope.workspace ? [...$scope.workspace.blocklistedNodes] : undefined,
unblocklistNode: $scope.workspace ? $scope.workspace.unblocklist : undefined,
canEditDrillDownUrls: canEditDrillDownUrls,
}),
$scope.$digest.bind($scope)

View file

@ -20,16 +20,16 @@ import { SettingsProps } from './settings';
import { LegacyIcon } from '../legacy_icon';
import { useListKeys } from './use_list_keys';
export function BlacklistForm({
blacklistedNodes,
unblacklistNode,
}: Pick<SettingsProps, 'blacklistedNodes' | 'unblacklistNode'>) {
const getListKey = useListKeys(blacklistedNodes || []);
export function BlocklistForm({
blocklistedNodes,
unblocklistNode,
}: Pick<SettingsProps, 'blocklistedNodes' | 'unblocklistNode'>) {
const getListKey = useListKeys(blocklistedNodes || []);
return (
<>
{blacklistedNodes && blacklistedNodes.length > 0 ? (
{blocklistedNodes && blocklistedNodes.length > 0 ? (
<EuiText size="s">
{i18n.translate('xpack.graph.settings.blacklist.blacklistHelpText', {
{i18n.translate('xpack.graph.settings.blocklist.blocklistHelpText', {
defaultMessage: 'These terms are not allowed in the graph.',
})}
</EuiText>
@ -37,7 +37,7 @@ export function BlacklistForm({
<EuiCallOut
title={
<FormattedMessage
id="xpack.graph.blacklist.noEntriesDescription"
id="xpack.graph.blocklist.noEntriesDescription"
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" /> }}
/>
@ -45,25 +45,25 @@ export function BlacklistForm({
/>
)}
<EuiSpacer />
{blacklistedNodes && unblacklistNode && blacklistedNodes.length > 0 && (
{blocklistedNodes && unblocklistNode && blocklistedNodes.length > 0 && (
<>
<EuiListGroup bordered maxWidth={false}>
{blacklistedNodes.map((node) => (
{blocklistedNodes.map((node) => (
<EuiListGroupItem
icon={<LegacyIcon icon={node.icon} asListIcon />}
key={getListKey(node)}
label={node.label}
extraAction={{
iconType: 'trash',
'aria-label': i18n.translate('xpack.graph.blacklist.removeButtonAriaLabel', {
'aria-label': i18n.translate('xpack.graph.blocklist.removeButtonAriaLabel', {
defaultMessage: 'Delete',
}),
title: i18n.translate('xpack.graph.blacklist.removeButtonAriaLabel', {
title: i18n.translate('xpack.graph.blocklist.removeButtonAriaLabel', {
defaultMessage: 'Delete',
}),
color: 'danger',
onClick: () => {
unblacklistNode(node);
unblocklistNode(node);
},
}}
/>
@ -71,18 +71,18 @@ export function BlacklistForm({
</EuiListGroup>
<EuiSpacer />
<EuiButton
data-test-subj="graphUnblacklistAll"
data-test-subj="graphUnblocklistAll"
color="danger"
iconType="trash"
size="s"
fill
onClick={() => {
blacklistedNodes.forEach((node) => {
unblacklistNode(node);
blocklistedNodes.forEach((node) => {
unblocklistNode(node);
});
}}
>
{i18n.translate('xpack.graph.settings.blacklist.clearButtonLabel', {
{i18n.translate('xpack.graph.settings.blocklist.clearButtonLabel', {
defaultMessage: 'Delete all',
})}
</EuiButton>

View file

@ -46,7 +46,7 @@ describe('settings', () => {
};
const angularProps: jest.Mocked<AngularProps> = {
blacklistedNodes: [
blocklistedNodes: [
{
x: 0,
y: 0,
@ -57,7 +57,7 @@ describe('settings', () => {
field: 'A',
term: '1',
},
label: 'blacklisted node 1',
label: 'blocklisted node 1',
icon: {
class: 'test',
code: '1',
@ -74,7 +74,7 @@ describe('settings', () => {
field: 'A',
term: '1',
},
label: 'blacklisted node 2',
label: 'blocklisted node 2',
icon: {
class: 'test',
code: '1',
@ -82,7 +82,7 @@ describe('settings', () => {
},
},
],
unblacklistNode: jest.fn(),
unblocklistNode: jest.fn(),
canEditDrillDownUrls: true,
};
@ -201,15 +201,15 @@ describe('settings', () => {
});
});
describe('blacklist', () => {
describe('blocklist', () => {
beforeEach(() => {
toTab('Block list');
});
it('should switch tab to blacklist', () => {
it('should switch tab to blocklist', () => {
expect(instance.find(EuiListGroupItem).map((item) => item.prop('label'))).toEqual([
'blacklisted node 1',
'blacklisted node 2',
'blocklisted node 1',
'blocklisted node 2',
]);
});
@ -217,7 +217,7 @@ describe('settings', () => {
act(() => {
subject.next({
...angularProps,
blacklistedNodes: [
blocklistedNodes: [
{
x: 0,
y: 0,
@ -228,7 +228,7 @@ describe('settings', () => {
field: 'A',
term: '1',
},
label: 'blacklisted node 3',
label: 'blocklisted node 3',
icon: {
class: 'test',
code: '1',
@ -242,21 +242,21 @@ describe('settings', () => {
instance.update();
expect(instance.find(EuiListGroupItem).map((item) => item.prop('label'))).toEqual([
'blacklisted node 3',
'blocklisted node 3',
]);
});
it('should delete node', () => {
instance.find(EuiListGroupItem).at(0).prop('extraAction')!.onClick!({} as any);
expect(angularProps.unblacklistNode).toHaveBeenCalledWith(angularProps.blacklistedNodes![0]);
expect(angularProps.unblocklistNode).toHaveBeenCalledWith(angularProps.blocklistedNodes![0]);
});
it('should delete all nodes', () => {
instance.find('[data-test-subj="graphUnblacklistAll"]').find(EuiButton).simulate('click');
instance.find('[data-test-subj="graphUnblocklistAll"]').find(EuiButton).simulate('click');
expect(angularProps.unblacklistNode).toHaveBeenCalledWith(angularProps.blacklistedNodes![0]);
expect(angularProps.unblacklistNode).toHaveBeenCalledWith(angularProps.blacklistedNodes![1]);
expect(angularProps.unblocklistNode).toHaveBeenCalledWith(angularProps.blocklistedNodes![0]);
expect(angularProps.unblocklistNode).toHaveBeenCalledWith(angularProps.blocklistedNodes![1]);
});
});

View file

@ -11,7 +11,7 @@ import * as Rx from 'rxjs';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { AdvancedSettingsForm } from './advanced_settings_form';
import { BlacklistForm } from './blacklist_form';
import { BlocklistForm } from './blocklist_form';
import { UrlTemplateList } from './url_template_list';
import { WorkspaceNode, AdvancedSettings, UrlTemplate, WorkspaceField } from '../../types';
import {
@ -33,9 +33,9 @@ const tabs = [
component: AdvancedSettingsForm,
},
{
id: 'blacklist',
title: i18n.translate('xpack.graph.settings.blacklistTitle', { defaultMessage: 'Block list' }),
component: BlacklistForm,
id: 'blocklist',
title: i18n.translate('xpack.graph.settings.blocklistTitle', { defaultMessage: 'Block list' }),
component: BlocklistForm,
},
{
id: 'drillDowns',
@ -51,8 +51,8 @@ const tabs = [
* to catch update outside updates
*/
export interface AngularProps {
blacklistedNodes: WorkspaceNode[];
unblacklistNode: (node: WorkspaceNode) => void;
blocklistedNodes: WorkspaceNode[];
unblocklistNode: (node: WorkspaceNode) => void;
canEditDrillDownUrls: boolean;
}

View file

@ -26,7 +26,7 @@ describe('deserialize', () => {
{ color: 'black', name: 'field1', selected: true, iconClass: 'a' },
{ color: 'black', name: 'field2', selected: true, iconClass: 'b' },
],
blacklist: [
blocklist: [
{
color: 'black',
label: 'Z',
@ -192,7 +192,7 @@ describe('deserialize', () => {
it('should deserialize nodes and edges', () => {
callSavedWorkspaceToAppState();
expect(workspace.blacklistedNodes.length).toEqual(1);
expect(workspace.blocklistedNodes.length).toEqual(1);
expect(workspace.nodes.length).toEqual(5);
expect(workspace.edges.length).toEqual(2);

View file

@ -128,11 +128,11 @@ function getFieldsWithWorkspaceSettings(
return allFields;
}
function getBlacklistedNodes(
function getBlocklistedNodes(
serializedWorkspaceState: SerializedWorkspaceState,
allFields: WorkspaceField[]
) {
return serializedWorkspaceState.blacklist.map((serializedNode) => {
return serializedWorkspaceState.blocklist.map((serializedNode) => {
const currentField = allFields.find((field) => field.name === serializedNode.field)!;
return {
x: 0,
@ -235,9 +235,9 @@ export function savedWorkspaceToAppState(
workspaceInstance.mergeGraph(graph);
resolveGroups(persistedWorkspaceState.vertices, workspaceInstance);
// ================== blacklist =============================
const blacklistedNodes = getBlacklistedNodes(persistedWorkspaceState, allFields);
workspaceInstance.blacklistedNodes.push(...blacklistedNodes);
// ================== blocklist =============================
const blocklistedNodes = getBlocklistedNodes(persistedWorkspaceState, allFields);
workspaceInstance.blocklistedNodes.push(...blocklistedNodes);
return {
urlTemplates,

View file

@ -118,7 +118,7 @@ describe('serialize', () => {
parent: null,
},
],
blacklistedNodes: [
blocklistedNodes: [
{
color: 'black',
data: { field: 'field1', term: 'Z' },
@ -165,7 +165,7 @@ describe('serialize', () => {
const workspaceState = JSON.parse(savedWorkspace.wsState);
expect(workspaceState).toMatchInlineSnapshot(`
Object {
"blacklist": Array [
"blocklist": Array [
Object {
"color": "black",
"field": "field1",

View file

@ -96,8 +96,8 @@ export function appStateToSavedWorkspace(
},
canSaveData: boolean
) {
const blacklist: SerializedNode[] = canSaveData
? workspace.blacklistedNodes.map((node) => serializeNode(node))
const blocklist: SerializedNode[] = canSaveData
? workspace.blocklistedNodes.map((node) => serializeNode(node))
: [];
const vertices: SerializedNode[] = canSaveData
? workspace.nodes.map((node) => serializeNode(node, workspace.nodes))
@ -111,7 +111,7 @@ export function appStateToSavedWorkspace(
const persistedWorkspaceState: SerializedWorkspaceState = {
indexPattern: selectedIndex.title,
selectedFields: selectedFields.map(serializeField),
blacklist,
blocklist,
vertices,
links,
urlTemplates: mappedUrlTemplates,

View file

@ -46,7 +46,7 @@ export function createMockGraphStore({
nodes: [],
edges: [],
options: {},
blacklistedNodes: [],
blocklistedNodes: [],
} as unknown) as Workspace;
const savedWorkspace = ({

View file

@ -198,7 +198,7 @@ function showModal(
openSaveModal({
savePolicy: deps.savePolicy,
hasData: workspace.nodes.length > 0 || workspace.blacklistedNodes.length > 0,
hasData: workspace.nodes.length > 0 || workspace.blocklistedNodes.length > 0,
workspace: savedWorkspace,
showSaveModal: deps.showSaveModal,
saveWorkspace: saveWorkspaceHandler,

View file

@ -33,7 +33,7 @@ export interface GraphWorkspaceSavedObject {
export interface SerializedWorkspaceState {
indexPattern: string;
selectedFields: SerializedField[];
blacklist: SerializedNode[];
blocklist: SerializedNode[];
vertices: SerializedNode[];
links: SerializedEdge[];
urlTemplates: SerializedUrlTemplate[];

View file

@ -63,7 +63,7 @@ export interface Workspace {
nodesMap: Record<string, WorkspaceNode>;
nodes: WorkspaceNode[];
edges: WorkspaceEdge[];
blacklistedNodes: WorkspaceNode[];
blocklistedNodes: WorkspaceNode[];
getQuery(startNodes?: WorkspaceNode[], loose?: boolean): JsonObject;
getSelectedOrAllNodes(): WorkspaceNode[];

View file

@ -37,7 +37,7 @@ const wsState: any = {
iconClass: 'fa-heart',
},
],
blacklist: [
blocklist: [
{
x: 491.3880229084531,
y: 572.375603969653,

View file

@ -37,7 +37,7 @@ const wsState: any = {
iconClass: 'fa-cube',
},
],
blacklist: [],
blocklist: [],
vertices: [
{
x: 324.55695700802687,

View file

@ -45,7 +45,7 @@ const wsState: any = {
iconClass: 'fa-key',
},
],
blacklist: [
blocklist: [
{
x: 349.9814471314239,
y: 274.1259761174194,

View file

@ -37,4 +37,23 @@ export const graphMigrations = {
});
return doc;
},
'7.10.0': (doc: SavedObjectUnsanitizedDoc<any>) => {
const wsState = get(doc, 'attributes.wsState');
if (typeof wsState !== 'string') {
return doc;
}
let state;
try {
state = JSON.parse(JSON.parse(wsState));
} catch (e) {
// Let it go, the data is invalid and we'll leave it as is
return doc;
}
if (state.blacklist) {
state.blocklist = state.blacklist;
delete state.blacklist;
}
doc.attributes.wsState = JSON.stringify(JSON.stringify(state));
return doc;
},
};

View file

@ -6185,8 +6185,8 @@
"xpack.graph.bar.pickSourceLabel": "データソースを選択",
"xpack.graph.bar.pickSourceTooltip": "グラフの関係性を開始するデータソースを選択します。",
"xpack.graph.bar.searchFieldPlaceholder": "データを検索してグラフに追加",
"xpack.graph.blacklist.noEntriesDescription": "ブロックされた用語がありません。頂点を選択して、右側のコントロールパネルの {stopSign} をクリックしてブロックします。ブロックされた用語に一致するドキュメントは今後表示されず、関係性が非表示になります。",
"xpack.graph.blacklist.removeButtonAriaLabel": "削除",
"xpack.graph.blocklist.noEntriesDescription": "ブロックされた用語がありません。頂点を選択して、右側のコントロールパネルの {stopSign} をクリックしてブロックします。ブロックされた用語に一致するドキュメントは今後表示されず、関係性が非表示になります。",
"xpack.graph.blocklist.removeButtonAriaLabel": "削除",
"xpack.graph.clearWorkspace.confirmButtonLabel": "データソースを変更",
"xpack.graph.clearWorkspace.confirmText": "データソースを変更すると、現在のフィールドと頂点がリセットされます。",
"xpack.graph.clearWorkspace.modalTitle": "保存されていない変更",
@ -6322,9 +6322,9 @@
"xpack.graph.settings.advancedSettings.timeoutInputLabel": "タイムアウト (ms)",
"xpack.graph.settings.advancedSettings.timeoutUnit": "ms",
"xpack.graph.settings.advancedSettingsTitle": "高度な設定",
"xpack.graph.settings.blacklist.blacklistHelpText": "これらの用語は現在ワークスペースに再度表示されないようブラックリストに登録されています",
"xpack.graph.settings.blacklist.clearButtonLabel": "消去",
"xpack.graph.settings.blacklistTitle": "ブラックリスト",
"xpack.graph.settings.blocklist.blocklistHelpText": "これらの用語は現在ワークスペースに再度表示されないようブラックリストに登録されています",
"xpack.graph.settings.blocklist.clearButtonLabel": "消去",
"xpack.graph.settings.blocklistTitle": "ブラックリスト",
"xpack.graph.settings.closeLabel": "閉じる",
"xpack.graph.settings.drillDowns.cancelButtonLabel": "キャンセル",
"xpack.graph.settings.drillDowns.defaultUrlTemplateTitle": "生ドキュメント",

View file

@ -6189,8 +6189,8 @@
"xpack.graph.bar.pickSourceLabel": "选择数据源",
"xpack.graph.bar.pickSourceTooltip": "选择数据源以开始绘制关系图。",
"xpack.graph.bar.searchFieldPlaceholder": "搜索数据并将其添加到图表",
"xpack.graph.blacklist.noEntriesDescription": "您没有任何已阻止字词。选择顶点并单击右侧控制面板上的 {stopSign} 以阻止它们。匹配已阻止字词的文档将不再被浏览,与它们的关系将隐藏。",
"xpack.graph.blacklist.removeButtonAriaLabel": "删除",
"xpack.graph.blocklist.noEntriesDescription": "您没有任何已阻止字词。选择顶点并单击右侧控制面板上的 {stopSign} 以阻止它们。匹配已阻止字词的文档将不再被浏览,与它们的关系将隐藏。",
"xpack.graph.blocklist.removeButtonAriaLabel": "删除",
"xpack.graph.clearWorkspace.confirmButtonLabel": "更改数据源",
"xpack.graph.clearWorkspace.confirmText": "如果更改数据源,您当前的字段和顶点将会重置。",
"xpack.graph.clearWorkspace.modalTitle": "未保存更改",
@ -6326,9 +6326,9 @@
"xpack.graph.settings.advancedSettings.timeoutInputLabel": "超时 (ms)",
"xpack.graph.settings.advancedSettings.timeoutUnit": "ms",
"xpack.graph.settings.advancedSettingsTitle": "高级设置",
"xpack.graph.settings.blacklist.blacklistHelpText": "这些字词当前已列入黑名单,不允许重新显示在工作空间中。",
"xpack.graph.settings.blacklist.clearButtonLabel": "清除",
"xpack.graph.settings.blacklistTitle": "黑名单",
"xpack.graph.settings.blocklist.blocklistHelpText": "这些字词当前已列入黑名单,不允许重新显示在工作空间中。",
"xpack.graph.settings.blocklist.clearButtonLabel": "清除",
"xpack.graph.settings.blocklistTitle": "黑名单",
"xpack.graph.settings.closeLabel": "关闭",
"xpack.graph.settings.drillDowns.cancelButtonLabel": "取消",
"xpack.graph.settings.drillDowns.defaultUrlTemplateTitle": "原始文档",