From a2478c3a32e6515310f4d042f5a75083b037dd0c Mon Sep 17 00:00:00 2001 From: Alexander Emelin Date: Fri, 1 Jul 2022 02:33:30 +0300 Subject: [PATCH] Search: Sort by updated at and created at (#50416) Co-authored-by: Artur Wierzbicki Co-authored-by: Ryan McKinley --- .betterer.results | 36 +++++++++---------- pkg/services/searchV2/bluge.go | 10 ++++-- .../search/page/components/columns.tsx | 24 ++++++------- public/app/features/search/service/bluge.ts | 15 ++++++++ 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/.betterer.results b/.betterer.results index 0acd2a6c43e..87321199593 100644 --- a/.betterer.results +++ b/.betterer.results @@ -6784,29 +6784,29 @@ exports[`better eslint`] = { [62, 12, 21, "Do not use any type assertions.", "976337522"], [63, 14, 26, "Do not use any type assertions.", "2909521803"] ], - "public/app/features/search/page/components/columns.tsx:2440349722": [ - [34, 20, 70, "Do not use any type assertions.", "512413936"], - [34, 21, 13, "Do not use any type assertions.", "3933930693"], - [34, 31, 3, "Unexpected any. Specify a different type.", "193409811"], - [49, 32, 21, "Do not use any type assertions.", "3454251755"], - [49, 50, 3, "Unexpected any. Specify a different type.", "193409811"], - [145, 15, 56, "Do not use any type assertions.", "1375039711"] + "public/app/features/search/page/components/columns.tsx:1558772443": [ + [33, 20, 70, "Do not use any type assertions.", "512413936"], + [33, 21, 13, "Do not use any type assertions.", "3933930693"], + [33, 31, 3, "Unexpected any. Specify a different type.", "193409811"], + [52, 32, 21, "Do not use any type assertions.", "3454251755"], + [52, 50, 3, "Unexpected any. Specify a different type.", "193409811"], + [148, 15, 56, "Do not use any type assertions.", "1375039711"] ], - "public/app/features/search/service/bluge.ts:59496993": [ + "public/app/features/search/service/bluge.ts:3991565237": [ [21, 15, 68, "Do not use any type assertions.", "2766474629"], [34, 17, 128, "Do not use any type assertions.", "437379020"], [36, 17, 47, "Do not use any type assertions.", "610587748"], [38, 13, 3, "Unexpected any. Specify a different type.", "193409811"], - [72, 13, 68, "Do not use any type assertions.", "2766474629"], - [83, 13, 39, "Do not use any type assertions.", "246018916"], - [85, 9, 3, "Unexpected any. Specify a different type.", "193409811"], - [88, 17, 26, "Do not use any type assertions.", "387817714"], - [104, 15, 37, "Do not use any type assertions.", "1203314137"], - [130, 20, 446, "Do not use any type assertions.", "258020179"], - [132, 19, 354, "Do not use any type assertions.", "4208037114"], - [145, 15, 3, "Unexpected any. Specify a different type.", "193409811"], - [161, 24, 46, "Do not use any type assertions.", "1967560255"], - [167, 22, 38, "Do not use any type assertions.", "1477056001"] + [76, 13, 68, "Do not use any type assertions.", "2766474629"], + [87, 13, 39, "Do not use any type assertions.", "246018916"], + [89, 9, 3, "Unexpected any. Specify a different type.", "193409811"], + [92, 17, 26, "Do not use any type assertions.", "387817714"], + [108, 15, 37, "Do not use any type assertions.", "1203314137"], + [134, 20, 446, "Do not use any type assertions.", "258020179"], + [136, 19, 354, "Do not use any type assertions.", "4208037114"], + [149, 15, 3, "Unexpected any. Specify a different type.", "193409811"], + [165, 24, 46, "Do not use any type assertions.", "1967560255"], + [171, 22, 38, "Do not use any type assertions.", "1477056001"] ], "public/app/features/search/service/sql.ts:3331148655": [ [91, 36, 3, "Unexpected any. Specify a different type.", "193409811"] diff --git a/pkg/services/searchV2/bluge.go b/pkg/services/searchV2/bluge.go index af2d048e940..c542d7a321c 100644 --- a/pkg/services/searchV2/bluge.go +++ b/pkg/services/searchV2/bluge.go @@ -30,6 +30,8 @@ const ( documentFieldTransformer = "transformer" documentFieldDSUID = "ds_uid" documentFieldDSType = "ds_type" + DocumentFieldCreatedAt = "created_at" + DocumentFieldUpdatedAt = "updated_at" ) func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*bluge.Reader, *bluge.Writer, error) { @@ -139,7 +141,9 @@ func getFolderDashboardDoc(dash dashboard) *bluge.Document { } return newSearchDocument(uid, dash.info.Title, dash.info.Description, url). - AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindFolder)).Aggregatable().StoreValue()) + AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindFolder)).Aggregatable().StoreValue()). + AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). + AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) } func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document { @@ -148,7 +152,9 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document { // Dashboard document doc := newSearchDocument(dash.uid, dash.info.Title, dash.info.Description, url). AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindDashboard)).Aggregatable().StoreValue()). - AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()) + AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()). + AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). + AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) for _, tag := range dash.info.Tags { doc.AddField(bluge.NewKeywordField(documentFieldTag, tag). diff --git a/public/app/features/search/page/components/columns.tsx b/public/app/features/search/page/components/columns.tsx index 5ff28cbb73a..12219de34ab 100644 --- a/public/app/features/search/page/components/columns.tsx +++ b/public/app/features/search/page/components/columns.tsx @@ -1,9 +1,8 @@ import { cx } from '@emotion/css'; -import { isNumber } from 'lodash'; import React from 'react'; import SVG from 'react-inlinesvg'; -import { Field, getFieldDisplayName } from '@grafana/data'; +import { Field, FieldType, formattedValueToString, getDisplayProcessor, getFieldDisplayName } from '@grafana/data'; import { config, getDataSourceSrv } from '@grafana/runtime'; import { Checkbox, Icon, IconButton, IconName, TagList } from '@grafana/ui'; import { PluginIconName } from 'app/features/plugins/admin/types'; @@ -15,7 +14,6 @@ import { TableColumn } from './SearchResultsTable'; const TYPE_COLUMN_WIDTH = 175; const DATASOURCE_COLUMN_WIDTH = 200; -const SORT_FIELD_WIDTH = 175; export const generateColumns = ( response: QueryResponse, @@ -32,9 +30,14 @@ export const generateColumns = ( const access = response.view.fields; const uidField = access.uid; const kindField = access.kind; + let sortFieldWith = 0; const sortField = (access as any)[response.view.dataFrame.meta?.custom?.sortBy] as Field; if (sortField) { - availableWidth -= SORT_FIELD_WIDTH; // pre-allocate the space for the last column + sortFieldWith = 175; + if (sortField.type === FieldType.time) { + sortFieldWith += 25; + } + availableWidth -= sortFieldWith; // pre-allocate the space for the last column } let width = 50; @@ -176,25 +179,20 @@ export const generateColumns = ( columns.push(makeTagsColumn(access.tags, availableWidth, styles.tagList, onTagSelected)); } - if (sortField) { + if (sortField && sortFieldWith) { + const disp = sortField.display ?? getDisplayProcessor({ field: sortField, theme: config.theme2 }); columns.push({ Header: () =>
{getFieldDisplayName(sortField)}
, Cell: (p) => { - let value = sortField.values.get(p.row.index); - try { - if (isNumber(value)) { - value = Number(value).toLocaleString(); - } - } catch {} return (
- {`${value}`} + {formattedValueToString(disp(sortField.values.get(p.row.index)))}
); }, id: `column-sort-field`, field: sortField, - width: SORT_FIELD_WIDTH, + width: sortFieldWith, }); } diff --git a/public/app/features/search/service/bluge.ts b/public/app/features/search/service/bluge.ts index ffbb27f2708..6d7e252fec7 100644 --- a/public/app/features/search/service/bluge.ts +++ b/public/app/features/search/service/bluge.ts @@ -59,6 +59,10 @@ export class BlugeSearcher implements GrafanaSearcher { opts.push({ value: `-${sf.name}`, label: `${sf.display} (most)` }); opts.push({ value: `${sf.name}`, label: `${sf.display} (least)` }); } + for (const sf of sortTimeFields) { + opts.push({ value: `-${sf.name}`, label: `${sf.display} (recent)` }); + opts.push({ value: `${sf.name}`, label: `${sf.display} (oldest)` }); + } } return Promise.resolve(opts); @@ -197,6 +201,12 @@ const sortFields = [ { name: 'errors_last_30_days', display: 'Errors 30 days' }, ]; +// Enterprise only time sort field values for dashboards +const sortTimeFields = [ + { name: 'created_at', display: 'Created time' }, + { name: 'updated_at', display: 'Updated time' }, +]; + /** Given the internal field name, this gives a reasonable display name for the table colum header */ function getSortFieldDisplayName(name: string) { for (const sf of sortFields) { @@ -204,5 +214,10 @@ function getSortFieldDisplayName(name: string) { return sf.display; } } + for (const sf of sortTimeFields) { + if (sf.name === name) { + return sf.display; + } + } return name; }