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 { config, getDataSourceSrv } from '@grafana/runtime';
import { Checkbox, Icon, IconButton, IconName, TagList } from '@grafana/ui';
import { PluginIconName } from 'app/features/plugins/admin/types';
import { QueryResponse, SearchResultMeta } from '../../service';
import { SelectionChecker, SelectionToggle } from '../selection';
import { TableColumn } from './SearchResultsTable';
const TYPE_COLUMN_WIDTH = 250;
const DATASOURCE_COLUMN_WIDTH = 200;
const SORT_FIELD_WIDTH = 175;
export const generateColumns = (
response: QueryResponse,
availableWidth: number,
selection: SelectionChecker | undefined,
selectionToggle: SelectionToggle | undefined,
clearSelection: () => void,
styles: { [key: string]: string },
onTagSelected: (tag: string) => void,
onDatasourceChange?: (datasource?: string) => void
): TableColumn[] => {
const columns: TableColumn[] = [];
const access = response.view.fields;
const uidField = access.uid;
const kindField = access.kind;
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
}
let width = 50;
if (selection && selectionToggle) {
width = 30;
columns.push({
id: `column-checkbox`,
width,
Header: () => {
if (selection('*', '*')) {
return (
);
}
return (
{
e.stopPropagation();
e.preventDefault();
const { view } = response;
const count = Math.min(view.length, 50);
for (let i = 0; i < count; i++) {
const item = view.get(i);
if (item.uid && item.kind) {
if (!selection(item.kind, item.uid)) {
selectionToggle(item.kind, item.uid);
}
}
}
}}
/>
);
},
Cell: (p) => {
const uid = uidField.values.get(p.row.index);
const kind = kindField ? kindField.values.get(p.row.index) : 'dashboard'; // HACK for now
const selected = selection(kind, uid);
const hasUID = uid != null; // Panels don't have UID! Likely should not be shown on pages with manage options
return (
{
selectionToggle(kind, uid);
}}
/>
);
},
field: uidField,
});
availableWidth -= width;
}
// Name column
width = Math.max(availableWidth * 0.2, 300);
columns.push({
Cell: (p) => {
let classNames = cx(styles.nameCellStyle);
let name = access.name.values.get(p.row.index);
if (!name?.length) {
name = 'Missing title'; // normal for panels
classNames += ' ' + styles.missingTitleText;
}
return (
{name}
);
},
id: `column-name`,
field: access.name!,
Header: () => {
return Name
;
},
width,
});
availableWidth -= width;
width = TYPE_COLUMN_WIDTH;
columns.push(makeTypeColumn(access.kind, access.panel_type, width, styles));
availableWidth -= width;
const meta = response.view.dataFrame.meta?.custom as SearchResultMeta;
if (meta?.locationInfo && availableWidth > 0) {
width = Math.max(availableWidth / 1.75, 300);
availableWidth -= width;
columns.push({
Cell: (p) => {
const parts = (access.location?.values.get(p.row.index) ?? '').split('/');
return (
{parts.map((p) => {
const info = meta.locationInfo[p];
return info ? (
{info.name}
) : (
{p}
);
})}
);
},
id: `column-location`,
field: access.location ?? access.url,
Header: 'Location',
width,
});
}
// Show datasources if we have any
if (access.ds_uid && onDatasourceChange) {
width = DATASOURCE_COLUMN_WIDTH;
columns.push(
makeDataSourceColumn(
access.ds_uid,
width,
styles.typeIcon,
styles.datasourceItem,
styles.invalidDatasourceItem,
onDatasourceChange
)
);
availableWidth -= width;
}
if (availableWidth > 0) {
columns.push(makeTagsColumn(access.tags, availableWidth, styles.tagList, onTagSelected));
}
if (sortField) {
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}`}
);
},
id: `column-sort-field`,
field: sortField,
width: SORT_FIELD_WIDTH,
});
}
return columns;
};
function getIconForKind(v: string): IconName {
if (v === 'dashboard') {
return 'apps';
}
if (v === 'folder') {
return 'folder';
}
return 'question-circle';
}
function makeDataSourceColumn(
field: Field,
width: number,
iconClass: string,
datasourceItemClass: string,
invalidDatasourceItemClass: string,
onDatasourceChange: (datasource?: string) => void
): TableColumn {
const srv = getDataSourceSrv();
return {
id: `column-datasource`,
field,
Header: 'Data source',
Cell: (p) => {
const dslist = field.values.get(p.row.index);
if (!dslist?.length) {
return null;
}
return (
{dslist.map((v, i) => {
const settings = srv.getInstanceSettings(v);
const icon = settings?.meta?.info?.logos?.small;
if (icon) {
return (
{
e.stopPropagation();
e.preventDefault();
onDatasourceChange(settings.uid);
}}
>
{settings.name}
);
}
return (
{v}
);
})}
);
},
width,
};
}
function makeTypeColumn(
kindField: Field,
typeField: Field,
width: number,
styles: Record
): TableColumn {
return {
id: `column-type`,
field: kindField ?? typeField,
Header: 'Type',
Cell: (p) => {
const i = p.row.index;
const kind = kindField?.values.get(i) ?? 'dashboard';
let icon = 'public/img/icons/unicons/apps.svg';
let txt = 'Dashboard';
if (kind) {
txt = kind;
switch (txt) {
case 'dashboard':
txt = 'Dashboard';
break;
case 'folder':
icon = 'public/img/icons/unicons/folder.svg';
txt = 'Folder';
break;
case 'panel':
icon = `public/img/icons/unicons/${PluginIconName.panel}.svg`;
const type = typeField.values.get(i);
if (type) {
txt = type;
const info = config.panels[txt];
if (info?.name) {
txt = info.name;
} else {
switch (type) {
case 'row':
txt = 'Row';
icon = `public/img/icons/unicons/bars.svg`;
break;
case 'singlestat': // auto-migration
txt = 'Singlestat';
break;
default:
icon = `public/img/icons/unicons/question.svg`; // plugin not found
}
}
}
break;
}
}
return (
{txt}
);
},
width,
};
}
function makeTagsColumn(
field: Field,
width: number,
tagListClass: string,
onTagSelected: (tag: string) => void
): TableColumn {
return {
Cell: (p) => {
const tags = field.values.get(p.row.index);
return tags ? (
) : null;
},
id: `column-tags`,
field: field,
Header: 'Tags',
width,
};
}