mirror of
https://github.com/grafana/grafana.git
synced 2026-08-26 13:27:30 -05:00
Explore / Query Library : Show user data (#88258)
* Add basic button for adding a query template * Add hook to create a template * Handle notifications * Add tags to invalidate cache * Generate translations * Updates types * Add tests * Simplify code * Add user to type * Add a better default title * bring in piotrs pr and try to add user data * Move out of metadata (reserved in k8s) and make new values exportable * Show user data * Fix bad merge * WIP * Add annotation data to FE * add (failing) test * Fix types and test * Cleanup * Enhance user data and send to component for display * Fix type * Fix expected values * fix betterer * Fix test * Remove user lookup * testing slug usage for api * Revert "testing slug usage for api" This reverts commitcc4556c3b7. * change types, display userid if login isnt returned * Simply display whatever is in property * skip test on removed logic * Try waiting for query to finish before eval * Revert "Try waiting for query to finish before eval" This reverts commit6220cabd17. * Handle attribute not existing when storage type is file --------- Co-authored-by: Piotr Jamroz <pm.jamroz@gmail.com>
This commit is contained in:
@@ -3992,9 +3992,6 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"],
|
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "5"],
|
||||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "6"]
|
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "6"]
|
||||||
],
|
],
|
||||||
"public/app/features/explore/QueryLibrary/QueryTemplatesTable/AddedByCell.tsx:5381": [
|
|
||||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
|
|
||||||
],
|
|
||||||
"public/app/features/explore/QueryLibrary/QueryTemplatesTable/QueryDescriptionCell.tsx:5381": [
|
"public/app/features/explore/QueryLibrary/QueryTemplatesTable/QueryDescriptionCell.tsx:5381": [
|
||||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
|
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export function QueryTemplatesList() {
|
|||||||
createdAtTimestamp: queryTemplate?.createdAtTimestamp || 0,
|
createdAtTimestamp: queryTemplate?.createdAtTimestamp || 0,
|
||||||
query: queryTemplate.targets[0],
|
query: queryTemplate.targets[0],
|
||||||
description: queryTemplate.title,
|
description: queryTemplate.title,
|
||||||
|
user: queryTemplate.user,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { Avatar } from '@grafana/ui';
|
|
||||||
|
|
||||||
import { useQueryLibraryListStyles } from './styles';
|
import { useQueryLibraryListStyles } from './styles';
|
||||||
|
|
||||||
export function AddedByCell() {
|
type AddedByCellProps = {
|
||||||
|
user?: string;
|
||||||
|
};
|
||||||
|
export function AddedByCell(props: AddedByCellProps) {
|
||||||
const styles = useQueryLibraryListStyles();
|
const styles = useQueryLibraryListStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span className={styles.logo}>
|
<span className={styles.otherText}>{props.user || 'Unknown'}</span>
|
||||||
<Avatar src="https://secure.gravatar.com/avatar" alt="unknown" />
|
|
||||||
</span>
|
|
||||||
<span className={styles.otherText}>Unknown</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const timestampSort: SortByFn<QueryTemplateRow> = (rowA, rowB, _, desc) => {
|
|||||||
|
|
||||||
const columns: Array<Column<QueryTemplateRow>> = [
|
const columns: Array<Column<QueryTemplateRow>> = [
|
||||||
{ id: 'description', header: 'Data source and query', cell: QueryDescriptionCell },
|
{ id: 'description', header: 'Data source and query', cell: QueryDescriptionCell },
|
||||||
{ id: 'addedBy', header: 'Added by', cell: AddedByCell },
|
{ id: 'addedBy', header: 'Added by', cell: ({ row: { original } }) => <AddedByCell user={original.user} /> },
|
||||||
{ id: 'datasourceType', header: 'Datasource type', cell: DatasourceTypeCell, sortType: 'string' },
|
{ id: 'datasourceType', header: 'Datasource type', cell: DatasourceTypeCell, sortType: 'string' },
|
||||||
{ id: 'createdAtTimestamp', header: 'Date added', cell: DateAddedCell, sortType: timestampSort },
|
{ id: 'createdAtTimestamp', header: 'Date added', cell: DateAddedCell, sortType: timestampSort },
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ export type QueryTemplateRow = {
|
|||||||
datasourceRef?: DataSourceRef | null;
|
datasourceRef?: DataSourceRef | null;
|
||||||
datasourceType?: string;
|
datasourceType?: string;
|
||||||
createdAtTimestamp?: number;
|
createdAtTimestamp?: number;
|
||||||
|
user?: string;
|
||||||
uid?: string;
|
uid?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { parseCreatedByValue } from './mappers';
|
||||||
|
|
||||||
|
describe.skip('mappers', () => {
|
||||||
|
describe('parseCreatedByValue', () => {
|
||||||
|
it.each`
|
||||||
|
value | expected
|
||||||
|
${''} | ${undefined}
|
||||||
|
${'api-key:1'} | ${{ userId: 1 }}
|
||||||
|
${'service-account:1:admin'} | ${{ userId: 1, login: 'admin' }}
|
||||||
|
${'user:1:admin'} | ${{ userId: 1, login: 'admin' }}
|
||||||
|
${'anonymous:0'} | ${undefined}
|
||||||
|
${'render:0'} | ${undefined}
|
||||||
|
${':0'} | ${undefined}
|
||||||
|
`("parsing '$value' should be '$expected'", ({ value, expected }) => {
|
||||||
|
expect(parseCreatedByValue(value)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +1,29 @@
|
|||||||
import { AddQueryTemplateCommand, QueryTemplate } from '../types';
|
import { AddQueryTemplateCommand, QueryTemplate } from '../types';
|
||||||
|
|
||||||
import { API_VERSION, QueryTemplateKinds } from './query';
|
import { API_VERSION, QueryTemplateKinds } from './query';
|
||||||
import { DataQuerySpec, DataQuerySpecResponse, DataQueryTarget } from './types';
|
import { CREATED_BY_KEY, DataQuerySpec, DataQuerySpecResponse, DataQueryTarget } from './types';
|
||||||
|
|
||||||
|
export const parseCreatedByValue = (value?: string) => {
|
||||||
|
// https://github.com/grafana/grafana/blob/main/pkg/services/user/identity.go#L194
|
||||||
|
/*if (value !== undefined && value !== '') {
|
||||||
|
const vals = value.split(':');
|
||||||
|
if (vals.length >= 2) {
|
||||||
|
if (vals[0] === 'anonymous' || vals[0] === 'render' || vals[0] === '') {
|
||||||
|
return undefined;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
userId: vals[1],
|
||||||
|
login: vals[2],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}*/
|
||||||
|
return !!value ? value : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export const convertDataQueryResponseToQueryTemplates = (result: DataQuerySpecResponse): QueryTemplate[] => {
|
export const convertDataQueryResponseToQueryTemplates = (result: DataQuerySpecResponse): QueryTemplate[] => {
|
||||||
if (!result.items) {
|
if (!result.items) {
|
||||||
@@ -13,6 +35,7 @@ export const convertDataQueryResponseToQueryTemplates = (result: DataQuerySpecRe
|
|||||||
title: spec.spec.title,
|
title: spec.spec.title,
|
||||||
targets: spec.spec.targets.map((target: DataQueryTarget) => target.properties),
|
targets: spec.spec.targets.map((target: DataQueryTarget) => target.properties),
|
||||||
createdAtTimestamp: new Date(spec.metadata.creationTimestamp || '').getTime(),
|
createdAtTimestamp: new Date(spec.metadata.creationTimestamp || '').getTime(),
|
||||||
|
user: parseCreatedByValue(spec.metadata?.annotations?.[CREATED_BY_KEY]),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const getTestQueryList = () => ({
|
|||||||
uid: '65327fce-c545-489d-ada5-16f909453d12',
|
uid: '65327fce-c545-489d-ada5-16f909453d12',
|
||||||
resourceVersion: '1783293341664808960',
|
resourceVersion: '1783293341664808960',
|
||||||
creationTimestamp: '2024-04-25T20:32:58Z',
|
creationTimestamp: '2024-04-25T20:32:58Z',
|
||||||
|
annotations: { 'grafana.app/createdBy': 'user:1:admin' },
|
||||||
},
|
},
|
||||||
spec: {
|
spec: {
|
||||||
title: 'Elastic Query Template',
|
title: 'Elastic Query Template',
|
||||||
@@ -62,6 +63,7 @@ export const getTestQueryList = () => ({
|
|||||||
uid: '3e71de65-efa7-40e3-8f23-124212cca455',
|
uid: '3e71de65-efa7-40e3-8f23-124212cca455',
|
||||||
resourceVersion: '1783214217151647744',
|
resourceVersion: '1783214217151647744',
|
||||||
creationTimestamp: '2024-04-25T11:05:55Z',
|
creationTimestamp: '2024-04-25T11:05:55Z',
|
||||||
|
annotations: { 'grafana.app/createdBy': 'user:1:admin' },
|
||||||
},
|
},
|
||||||
spec: {
|
spec: {
|
||||||
title: 'Loki Query Template',
|
title: 'Loki Query Template',
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type DataQuerySpec = {
|
|||||||
generateName: string;
|
generateName: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
creationTimestamp?: string;
|
creationTimestamp?: string;
|
||||||
|
annotations?: { [key: string]: string };
|
||||||
};
|
};
|
||||||
spec: {
|
spec: {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -24,3 +25,5 @@ export type DataQuerySpecResponse = {
|
|||||||
apiVersion: string;
|
apiVersion: string;
|
||||||
items: DataQuerySpec[];
|
items: DataQuerySpec[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CREATED_BY_KEY = 'grafana.app/createdBy';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export type QueryTemplate = {
|
|||||||
title: string;
|
title: string;
|
||||||
targets: DataQuery[];
|
targets: DataQuery[];
|
||||||
createdAtTimestamp: number;
|
createdAtTimestamp: number;
|
||||||
|
user?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AddQueryTemplateCommand = {
|
export type AddQueryTemplateCommand = {
|
||||||
|
|||||||
Reference in New Issue
Block a user