mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
0975ea4df8
commit
a2478c3a32
@ -6784,29 +6784,29 @@ exports[`better eslint`] = {
|
|||||||
[62, 12, 21, "Do not use any type assertions.", "976337522"],
|
[62, 12, 21, "Do not use any type assertions.", "976337522"],
|
||||||
[63, 14, 26, "Do not use any type assertions.", "2909521803"]
|
[63, 14, 26, "Do not use any type assertions.", "2909521803"]
|
||||||
],
|
],
|
||||||
"public/app/features/search/page/components/columns.tsx:2440349722": [
|
"public/app/features/search/page/components/columns.tsx:1558772443": [
|
||||||
[34, 20, 70, "Do not use any type assertions.", "512413936"],
|
[33, 20, 70, "Do not use any type assertions.", "512413936"],
|
||||||
[34, 21, 13, "Do not use any type assertions.", "3933930693"],
|
[33, 21, 13, "Do not use any type assertions.", "3933930693"],
|
||||||
[34, 31, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[33, 31, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[49, 32, 21, "Do not use any type assertions.", "3454251755"],
|
[52, 32, 21, "Do not use any type assertions.", "3454251755"],
|
||||||
[49, 50, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[52, 50, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[145, 15, 56, "Do not use any type assertions.", "1375039711"]
|
[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"],
|
[21, 15, 68, "Do not use any type assertions.", "2766474629"],
|
||||||
[34, 17, 128, "Do not use any type assertions.", "437379020"],
|
[34, 17, 128, "Do not use any type assertions.", "437379020"],
|
||||||
[36, 17, 47, "Do not use any type assertions.", "610587748"],
|
[36, 17, 47, "Do not use any type assertions.", "610587748"],
|
||||||
[38, 13, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[38, 13, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[72, 13, 68, "Do not use any type assertions.", "2766474629"],
|
[76, 13, 68, "Do not use any type assertions.", "2766474629"],
|
||||||
[83, 13, 39, "Do not use any type assertions.", "246018916"],
|
[87, 13, 39, "Do not use any type assertions.", "246018916"],
|
||||||
[85, 9, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[89, 9, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[88, 17, 26, "Do not use any type assertions.", "387817714"],
|
[92, 17, 26, "Do not use any type assertions.", "387817714"],
|
||||||
[104, 15, 37, "Do not use any type assertions.", "1203314137"],
|
[108, 15, 37, "Do not use any type assertions.", "1203314137"],
|
||||||
[130, 20, 446, "Do not use any type assertions.", "258020179"],
|
[134, 20, 446, "Do not use any type assertions.", "258020179"],
|
||||||
[132, 19, 354, "Do not use any type assertions.", "4208037114"],
|
[136, 19, 354, "Do not use any type assertions.", "4208037114"],
|
||||||
[145, 15, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[149, 15, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[161, 24, 46, "Do not use any type assertions.", "1967560255"],
|
[165, 24, 46, "Do not use any type assertions.", "1967560255"],
|
||||||
[167, 22, 38, "Do not use any type assertions.", "1477056001"]
|
[171, 22, 38, "Do not use any type assertions.", "1477056001"]
|
||||||
],
|
],
|
||||||
"public/app/features/search/service/sql.ts:3331148655": [
|
"public/app/features/search/service/sql.ts:3331148655": [
|
||||||
[91, 36, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[91, 36, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
|
@ -30,6 +30,8 @@ const (
|
|||||||
documentFieldTransformer = "transformer"
|
documentFieldTransformer = "transformer"
|
||||||
documentFieldDSUID = "ds_uid"
|
documentFieldDSUID = "ds_uid"
|
||||||
documentFieldDSType = "ds_type"
|
documentFieldDSType = "ds_type"
|
||||||
|
DocumentFieldCreatedAt = "created_at"
|
||||||
|
DocumentFieldUpdatedAt = "updated_at"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*bluge.Reader, *bluge.Writer, error) {
|
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).
|
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 {
|
func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document {
|
||||||
@ -148,7 +152,9 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document {
|
|||||||
// Dashboard document
|
// Dashboard document
|
||||||
doc := newSearchDocument(dash.uid, dash.info.Title, dash.info.Description, url).
|
doc := newSearchDocument(dash.uid, dash.info.Title, dash.info.Description, url).
|
||||||
AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindDashboard)).Aggregatable().StoreValue()).
|
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 {
|
for _, tag := range dash.info.Tags {
|
||||||
doc.AddField(bluge.NewKeywordField(documentFieldTag, tag).
|
doc.AddField(bluge.NewKeywordField(documentFieldTag, tag).
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { cx } from '@emotion/css';
|
import { cx } from '@emotion/css';
|
||||||
import { isNumber } from 'lodash';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SVG from 'react-inlinesvg';
|
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 { config, getDataSourceSrv } from '@grafana/runtime';
|
||||||
import { Checkbox, Icon, IconButton, IconName, TagList } from '@grafana/ui';
|
import { Checkbox, Icon, IconButton, IconName, TagList } from '@grafana/ui';
|
||||||
import { PluginIconName } from 'app/features/plugins/admin/types';
|
import { PluginIconName } from 'app/features/plugins/admin/types';
|
||||||
@ -15,7 +14,6 @@ import { TableColumn } from './SearchResultsTable';
|
|||||||
|
|
||||||
const TYPE_COLUMN_WIDTH = 175;
|
const TYPE_COLUMN_WIDTH = 175;
|
||||||
const DATASOURCE_COLUMN_WIDTH = 200;
|
const DATASOURCE_COLUMN_WIDTH = 200;
|
||||||
const SORT_FIELD_WIDTH = 175;
|
|
||||||
|
|
||||||
export const generateColumns = (
|
export const generateColumns = (
|
||||||
response: QueryResponse,
|
response: QueryResponse,
|
||||||
@ -32,9 +30,14 @@ export const generateColumns = (
|
|||||||
const access = response.view.fields;
|
const access = response.view.fields;
|
||||||
const uidField = access.uid;
|
const uidField = access.uid;
|
||||||
const kindField = access.kind;
|
const kindField = access.kind;
|
||||||
|
let sortFieldWith = 0;
|
||||||
const sortField = (access as any)[response.view.dataFrame.meta?.custom?.sortBy] as Field;
|
const sortField = (access as any)[response.view.dataFrame.meta?.custom?.sortBy] as Field;
|
||||||
if (sortField) {
|
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;
|
let width = 50;
|
||||||
@ -176,25 +179,20 @@ export const generateColumns = (
|
|||||||
columns.push(makeTagsColumn(access.tags, availableWidth, styles.tagList, onTagSelected));
|
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({
|
columns.push({
|
||||||
Header: () => <div className={styles.sortedHeader}>{getFieldDisplayName(sortField)}</div>,
|
Header: () => <div className={styles.sortedHeader}>{getFieldDisplayName(sortField)}</div>,
|
||||||
Cell: (p) => {
|
Cell: (p) => {
|
||||||
let value = sortField.values.get(p.row.index);
|
|
||||||
try {
|
|
||||||
if (isNumber(value)) {
|
|
||||||
value = Number(value).toLocaleString();
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
return (
|
return (
|
||||||
<div {...p.cellProps} className={styles.sortedItems}>
|
<div {...p.cellProps} className={styles.sortedItems}>
|
||||||
{`${value}`}
|
{formattedValueToString(disp(sortField.values.get(p.row.index)))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
id: `column-sort-field`,
|
id: `column-sort-field`,
|
||||||
field: sortField,
|
field: sortField,
|
||||||
width: SORT_FIELD_WIDTH,
|
width: sortFieldWith,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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} (most)` });
|
||||||
opts.push({ value: `${sf.name}`, label: `${sf.display} (least)` });
|
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);
|
return Promise.resolve(opts);
|
||||||
@ -197,6 +201,12 @@ const sortFields = [
|
|||||||
{ name: 'errors_last_30_days', display: 'Errors 30 days' },
|
{ 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 */
|
/** Given the internal field name, this gives a reasonable display name for the table colum header */
|
||||||
function getSortFieldDisplayName(name: string) {
|
function getSortFieldDisplayName(name: string) {
|
||||||
for (const sf of sortFields) {
|
for (const sf of sortFields) {
|
||||||
@ -204,5 +214,10 @@ function getSortFieldDisplayName(name: string) {
|
|||||||
return sf.display;
|
return sf.display;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const sf of sortTimeFields) {
|
||||||
|
if (sf.name === name) {
|
||||||
|
return sf.display;
|
||||||
|
}
|
||||||
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user