Search: Sort by updated at and created at (#50416)

Co-authored-by: Artur Wierzbicki <artur.wierzbicki@grafana.com>
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Alexander Emelin 2022-07-01 02:33:30 +03:00 committed by GitHub
parent 0975ea4df8
commit a2478c3a32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 33 deletions

View File

@ -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"]

View File

@ -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).

View File

@ -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: () => <div className={styles.sortedHeader}>{getFieldDisplayName(sortField)}</div>,
Cell: (p) => {
let value = sortField.values.get(p.row.index);
try {
if (isNumber(value)) {
value = Number(value).toLocaleString();
}
} catch {}
return (
<div {...p.cellProps} className={styles.sortedItems}>
{`${value}`}
{formattedValueToString(disp(sortField.values.get(p.row.index)))}
</div>
);
},
id: `column-sort-field`,
field: sortField,
width: SORT_FIELD_WIDTH,
width: sortFieldWith,
});
}

View File

@ -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;
}