[Discover] Add clock icon to time field column (#114996)

* [Discover] Add clock icon to time field column

* [Discover] fix linting

* [Discover] fix functional tests

* [Discover] fix functional test

* [Discover] apply suggestion

* [Discover] apply wording suggestion

* [Discover] fix i18n

* [Discover] update unit tests

* [Discover] add custom label for classic table

* [Discover] color icon black

* [Discover] fix unit tests

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dmitry Tomashevich 2021-10-25 14:26:45 +03:00 committed by GitHub
parent 780c43513a
commit 8f75a715f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 78 additions and 27 deletions

View file

@ -1,7 +1,8 @@
.kbnDocTableHeader {
white-space: nowrap;
}
.kbnDocTableHeader button {
.kbnDocTableHeader button,
.kbnDocTableHeader svg {
margin-left: $euiSizeXS * .5;
}
.kbnDocTableHeader__move,

View file

@ -15,7 +15,16 @@ exports[`TableHeader with time column renders correctly 1`] = `
class="kbnDocTableHeader__actions"
data-test-subj="docTableHeader-time"
>
Time
time
<span
class="euiToolTipAnchor"
>
<span
aria-label="Primary time field."
data-euiicon-type="clock"
tabindex="0"
/>
</span>
<span
class="euiToolTipAnchor"
>

View file

@ -28,7 +28,7 @@ export interface ColumnProps {
export function getTimeColumn(timeFieldName: string): ColumnProps {
return {
name: timeFieldName,
displayName: 'Time',
displayName: timeFieldName,
isSortable: true,
isRemoveable: false,
colLeftIdx: -1,

View file

@ -45,6 +45,8 @@ export function TableHeader({
<TableHeaderColumn
key={col.name}
{...col}
customLabel={indexPattern.getFieldByName(col.name)?.customLabel}
isTimeColumn={indexPattern.timeFieldName === col.name}
sortOrder={
sortOrder.length ? sortOrder : getDefaultSort(indexPattern, defaultSortOrder)
}

View file

@ -8,7 +8,7 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiButtonIcon, EuiToolTip } from '@elastic/eui';
import { EuiButtonIcon, EuiToolTip, EuiIconTip } from '@elastic/eui';
import { SortOrder } from './helpers';
import { DocViewTableScoreSortWarning } from './score_sort_warning';
@ -18,6 +18,8 @@ interface Props {
displayName?: string;
isRemoveable: boolean;
isSortable: boolean;
isTimeColumn: boolean;
customLabel?: string;
name: string;
onChangeSortOrder?: (sortOrder: SortOrder[]) => void;
onMoveColumn?: (name: string, idx: number) => void;
@ -54,6 +56,8 @@ export function TableHeaderColumn({
displayName,
isRemoveable,
isSortable,
isTimeColumn,
customLabel,
name,
onChangeSortOrder,
onMoveColumn,
@ -65,6 +69,14 @@ export function TableHeaderColumn({
const curColSort = sortOrder.find((pair) => pair[0] === name);
const curColSortDir = (curColSort && curColSort[1]) || '';
const timeAriaLabel = i18n.translate(
'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel',
{ defaultMessage: 'Primary time field.' }
);
const timeTooltip = i18n.translate('discover.docTable.tableHeader.timeFieldIconTooltip', {
defaultMessage: 'This field represents the time that events occurred.',
});
// If this is the _score column, and _score is not one of the columns inside the sort, show a
// warning that the _score will not be retrieved from Elasticsearch
const showScoreSortWarning = name === '_score' && !curColSort;
@ -183,7 +195,15 @@ export function TableHeaderColumn({
<th data-test-subj="docTableHeaderField">
<span data-test-subj={`docTableHeader-${name}`} className="kbnDocTableHeader__actions">
{showScoreSortWarning && <DocViewTableScoreSortWarning />}
{displayName}
{customLabel ?? displayName}
{isTimeColumn && (
<EuiIconTip
key="time-icon"
type="clock"
aria-label={timeAriaLabel}
content={timeTooltip}
/>
)}
{buttons
.filter((button) => button.active)
.map((button, idx) => (

View file

@ -117,7 +117,15 @@ describe('Discover grid columns ', function () {
[Function],
[Function],
],
"display": "Time (timestamp)",
"display": <React.Fragment>
timestamp
<EuiIconTip
aria-label="Primary time field."
content="This field represents the time that events occurred."
type="clock"
/>
</React.Fragment>,
"id": "timestamp",
"initialWidth": 190,
"isSortable": true,

View file

@ -6,9 +6,9 @@
* Side Public License, v 1.
*/
import React from 'react';
import React, { Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiDataGridColumn, EuiScreenReaderOnly } from '@elastic/eui';
import { EuiDataGridColumn, EuiIconTip, EuiScreenReaderOnly } from '@elastic/eui';
import { ExpandButton } from './discover_grid_expand_button';
import { DiscoverGridSettings } from './types';
import type { IndexPattern } from '../../../../../data/common';
@ -57,9 +57,6 @@ export function buildEuiGridColumn(
defaultColumns: boolean,
isSortEnabled: boolean
) {
const timeString = i18n.translate('discover.timeLabel', {
defaultMessage: 'Time',
});
const indexPatternField = indexPattern.getFieldByName(columnName);
const column: EuiDataGridColumn = {
id: columnName,
@ -88,7 +85,23 @@ export function buildEuiGridColumn(
};
if (column.id === indexPattern.timeFieldName) {
column.display = `${timeString} (${indexPattern.timeFieldName})`;
const primaryTimeAriaLabel = i18n.translate(
'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel',
{ defaultMessage: 'Primary time field.' }
);
const primaryTimeTooltip = i18n.translate(
'discover.docTable.tableHeader.timeFieldIconTooltip',
{
defaultMessage: 'This field represents the time that events occurred.',
}
);
column.display = (
<Fragment>
{indexPatternField?.customLabel ?? indexPattern.timeFieldName}{' '}
<EuiIconTip type="clock" aria-label={primaryTimeAriaLabel} content={primaryTimeTooltip} />
</Fragment>
);
column.initialWidth = defaultTimeColumnWidth;
}
if (columnWidth > 0) {

View file

@ -74,7 +74,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('should open the context view with the same columns', async () => {
const columnNames = await docTable.getHeaderFields();
expect(columnNames).to.eql(['Time', ...TEST_COLUMN_NAMES]);
expect(columnNames).to.eql(['@timestamp', ...TEST_COLUMN_NAMES]);
});
it('should open the context view with the filters disabled', async () => {

View file

@ -39,19 +39,19 @@ export default function ({
const getTitles = async () =>
(await testSubjects.getVisibleText('dataGridHeader')).replace(/\s|\r?\n|\r/g, ' ');
expect(await getTitles()).to.be('Time (@timestamp) Document');
expect(await getTitles()).to.be('@timestamp Document');
await PageObjects.discover.clickFieldListItemAdd('bytes');
expect(await getTitles()).to.be('Time (@timestamp) bytes');
expect(await getTitles()).to.be('@timestamp bytes');
await PageObjects.discover.clickFieldListItemAdd('agent');
expect(await getTitles()).to.be('Time (@timestamp) bytes agent');
expect(await getTitles()).to.be('@timestamp bytes agent');
await PageObjects.discover.clickFieldListItemRemove('bytes');
expect(await getTitles()).to.be('Time (@timestamp) agent');
expect(await getTitles()).to.be('@timestamp agent');
await PageObjects.discover.clickFieldListItemRemove('agent');
expect(await getTitles()).to.be('Time (@timestamp) Document');
expect(await getTitles()).to.be('@timestamp Document');
});
});
}

View file

@ -76,7 +76,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('should open the context view with the same columns', async () => {
const columnNames = await dataGrid.getHeaderFields();
expect(columnNames).to.eql(['Time (@timestamp)', ...TEST_COLUMN_NAMES]);
expect(columnNames).to.eql(['@timestamp', ...TEST_COLUMN_NAMES]);
});
it('should open the context view with the filters disabled', async () => {

View file

@ -59,8 +59,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});
it('doc view should show Time and _source columns', async function () {
const expectedHeader = 'Time (@timestamp) Document';
it('doc view should show @timestamp and _source columns', async function () {
const expectedHeader = '@timestamp Document';
const DocHeader = await dataGrid.getHeaderFields();
expect(DocHeader.join(' ')).to.be(expectedHeader);
});

View file

@ -107,8 +107,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
after(async function () {
await kibanaServer.uiSettings.replace({});
});
it('doc view should show Time and _source columns', async function () {
const expectedHeader = 'Time\n_source';
it('doc view should show @timestamp and _source columns', async function () {
const expectedHeader = '@timestamp\n_source';
const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
const docHeaderText = await docHeader.getVisibleText();
expect(docHeaderText).to.be(expectedHeader);

View file

@ -64,9 +64,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});
it('doc view should show Time and Document columns', async function () {
it('doc view should show @timestamp and Document columns', async function () {
const Docheader = await PageObjects.discover.getDocHeader();
expect(Docheader).to.contain('Time');
expect(Docheader).to.contain('@timestamp');
expect(Docheader).to.contain('Document');
});

View file

@ -2532,7 +2532,6 @@
"discover.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。",
"discover.sourceViewer.errorMessageTitle": "エラーが発生しました",
"discover.sourceViewer.refresh": "更新",
"discover.timeLabel": "時間",
"discover.toggleSidebarAriaLabel": "サイドバーを切り替える",
"discover.topNav.openOptionsPopover.description": "お知らせDiscoverでは、データの並べ替え、列のドラッグアンドドロップ、ドキュメントの比較を行う方法が改善されました。詳細設定でクラシックテーブルを使用を切り替えて、開始します。",
"discover.topNav.openSearchPanel.manageSearchesButtonLabel": "検索の管理",

View file

@ -2557,7 +2557,6 @@
"discover.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。",
"discover.sourceViewer.errorMessageTitle": "发生错误",
"discover.sourceViewer.refresh": "刷新",
"discover.timeLabel": "时间",
"discover.toggleSidebarAriaLabel": "切换侧边栏",
"discover.topNav.openOptionsPopover.description": "好消息Discover 有更好的方法排序数据、拖放列和比较文档。在“高级模式”中切换“使用经典表”来开始。",
"discover.topNav.openSearchPanel.manageSearchesButtonLabel": "管理搜索",