mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugin admin: Add a page to show where panel plugins are used in dashboards (#50909)
This commit is contained in:
@@ -5025,11 +5025,11 @@ exports[`better eslint`] = {
|
|||||||
[264, 15, 56, "Do not use any type assertions.", "2674630592"],
|
[264, 15, 56, "Do not use any type assertions.", "2674630592"],
|
||||||
[266, 13, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[266, 13, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/containers/DashboardPage.tsx:707193595": [
|
"public/app/features/dashboard/containers/DashboardPage.tsx:3173260528": [
|
||||||
[107, 36, 40, "Do not use any type assertions.", "2547843745"],
|
[108, 36, 40, "Do not use any type assertions.", "2547843745"],
|
||||||
[107, 73, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[108, 73, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[142, 32, 40, "Do not use any type assertions.", "2547843745"],
|
[144, 32, 40, "Do not use any type assertions.", "2547843745"],
|
||||||
[142, 69, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[144, 69, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/containers/SoloPanelPage.test.tsx:1655234814": [
|
"public/app/features/dashboard/containers/SoloPanelPage.test.tsx:1655234814": [
|
||||||
[26, 29, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[26, 29, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
@@ -5366,8 +5366,8 @@ exports[`better eslint`] = {
|
|||||||
[143, 17, 41, "Do not use any type assertions.", "1363816804"],
|
[143, 17, 41, "Do not use any type assertions.", "1363816804"],
|
||||||
[145, 11, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[145, 11, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/state/initDashboard.ts:4291397377": [
|
"public/app/features/dashboard/state/initDashboard.ts:1143357497": [
|
||||||
[215, 71, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[216, 84, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/dashboard/state/reducers.ts:2272523560": [
|
"public/app/features/dashboard/state/reducers.ts:2272523560": [
|
||||||
[64, 9, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[64, 9, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
@@ -6420,8 +6420,8 @@ exports[`better eslint`] = {
|
|||||||
[32, 25, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[32, 25, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[61, 22, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[61, 22, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/plugins/admin/components/PluginDetailsBody.tsx:3199506957": [
|
"public/app/features/plugins/admin/components/PluginDetailsBody.tsx:2575001007": [
|
||||||
[45, 35, 25, "Do not use any type assertions.", "3298329852"]
|
[46, 35, 25, "Do not use any type assertions.", "3298329852"]
|
||||||
],
|
],
|
||||||
"public/app/features/plugins/admin/components/PluginDetailsHeader.tsx:4233259": [
|
"public/app/features/plugins/admin/components/PluginDetailsHeader.tsx:4233259": [
|
||||||
[64, 48, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[64, 48, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
@@ -6462,7 +6462,7 @@ exports[`better eslint`] = {
|
|||||||
"public/app/features/plugins/admin/pages/PluginDetails.test.tsx:186575126": [
|
"public/app/features/plugins/admin/pages/PluginDetails.test.tsx:186575126": [
|
||||||
[85, 15, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[85, 15, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/plugins/admin/pages/PluginDetails.tsx:4160094062": [
|
"public/app/features/plugins/admin/pages/PluginDetails.tsx:2558474094": [
|
||||||
[43, 18, 32, "Do not use any type assertions.", "4000149916"],
|
[43, 18, 32, "Do not use any type assertions.", "4000149916"],
|
||||||
[87, 24, 20, "Do not use any type assertions.", "2850977225"]
|
[87, 24, 20, "Do not use any type assertions.", "2850977225"]
|
||||||
],
|
],
|
||||||
@@ -6478,8 +6478,8 @@ exports[`better eslint`] = {
|
|||||||
"public/app/features/plugins/admin/state/selectors.ts:345773501": [
|
"public/app/features/plugins/admin/state/selectors.ts:345773501": [
|
||||||
[62, 23, 27, "Do not use any type assertions.", "1285719276"]
|
[62, 23, 27, "Do not use any type assertions.", "1285719276"]
|
||||||
],
|
],
|
||||||
"public/app/features/plugins/admin/types.ts:593250396": [
|
"public/app/features/plugins/admin/types.ts:1638901340": [
|
||||||
[236, 10, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[238, 10, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
],
|
],
|
||||||
"public/app/features/plugins/built_in_plugins.ts:2973583336": [
|
"public/app/features/plugins/built_in_plugins.ts:2973583336": [
|
||||||
[93, 22, 3, "Unexpected any. Specify a different type.", "193409811"]
|
[93, 22, 3, "Unexpected any. Specify a different type.", "193409811"]
|
||||||
@@ -6839,13 +6839,13 @@ 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:282017932": [
|
"public/app/features/search/page/components/columns.tsx:2440349722": [
|
||||||
[33, 20, 70, "Do not use any type assertions.", "512413936"],
|
[34, 20, 70, "Do not use any type assertions.", "512413936"],
|
||||||
[33, 21, 13, "Do not use any type assertions.", "3933930693"],
|
[34, 21, 13, "Do not use any type assertions.", "3933930693"],
|
||||||
[33, 31, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[34, 31, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[48, 32, 21, "Do not use any type assertions.", "3454251755"],
|
[49, 32, 21, "Do not use any type assertions.", "3454251755"],
|
||||||
[48, 50, 3, "Unexpected any. Specify a different type.", "193409811"],
|
[49, 50, 3, "Unexpected any. Specify a different type.", "193409811"],
|
||||||
[127, 15, 56, "Do not use any type assertions.", "1375039711"]
|
[145, 15, 56, "Do not use any type assertions.", "1375039711"]
|
||||||
],
|
],
|
||||||
"public/app/features/search/reducers/dashboardSearch.test.ts:1813679195": [
|
"public/app/features/search/reducers/dashboardSearch.test.ts:1813679195": [
|
||||||
[5, 66, 17, "Do not use any type assertions.", "3518965757"],
|
[5, 66, 17, "Do not use any type assertions.", "3518965757"],
|
||||||
|
|||||||
@@ -394,6 +394,12 @@ func doSearchQuery(
|
|||||||
hasConstraints = true
|
hasConstraints = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Panel type
|
||||||
|
if q.PanelType != "" {
|
||||||
|
fullQuery.AddMust(bluge.NewTermQuery(q.PanelType).SetField(documentFieldPanelType))
|
||||||
|
hasConstraints = true
|
||||||
|
}
|
||||||
|
|
||||||
// Datasource
|
// Datasource
|
||||||
if q.Datasource != "" {
|
if q.Datasource != "" {
|
||||||
fullQuery.AddMust(bluge.NewTermQuery(q.Datasource).SetField(documentFieldDSUID))
|
fullQuery.AddMust(bluge.NewTermQuery(q.Datasource).SetField(documentFieldDSUID))
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type DashboardQuery struct {
|
|||||||
Datasource string `json:"ds_uid,omitempty"` // "datasource" collides with the JSON value at the same leel :()
|
Datasource string `json:"ds_uid,omitempty"` // "datasource" collides with the JSON value at the same leel :()
|
||||||
Tags []string `json:"tags,omitempty"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
Kind []string `json:"kind,omitempty"`
|
Kind []string `json:"kind,omitempty"`
|
||||||
|
PanelType string `json:"panel_type,omitempty"`
|
||||||
UIDs []string `json:"uid,omitempty"`
|
UIDs []string `json:"uid,omitempty"`
|
||||||
Explain bool `json:"explain,omitempty"` // adds details on why document matched
|
Explain bool `json:"explain,omitempty"` // adds details on why document matched
|
||||||
Facet []FacetField `json:"facet,omitempty"`
|
Facet []FacetField `json:"facet,omitempty"`
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export type DashboardPageRouteSearchParams = {
|
|||||||
editPanel?: string;
|
editPanel?: string;
|
||||||
viewPanel?: string;
|
viewPanel?: string;
|
||||||
editview?: string;
|
editview?: string;
|
||||||
|
panelType?: string;
|
||||||
inspect?: string;
|
inspect?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
@@ -129,6 +130,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
|||||||
urlUid: match.params.uid,
|
urlUid: match.params.uid,
|
||||||
urlType: match.params.type,
|
urlType: match.params.type,
|
||||||
urlFolderId: queryParams.folderId,
|
urlFolderId: queryParams.folderId,
|
||||||
|
panelType: queryParams.panelType,
|
||||||
routeName: this.props.route.routeName,
|
routeName: this.props.route.routeName,
|
||||||
fixUrl: !isPublic,
|
fixUrl: !isPublic,
|
||||||
accessToken: match.params.accessToken,
|
accessToken: match.params.accessToken,
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ export interface InitDashboardArgs {
|
|||||||
urlUid?: string;
|
urlUid?: string;
|
||||||
urlSlug?: string;
|
urlSlug?: string;
|
||||||
urlType?: string;
|
urlType?: string;
|
||||||
urlFolderId?: string | null;
|
urlFolderId?: string;
|
||||||
|
panelType?: string;
|
||||||
accessToken?: string;
|
accessToken?: string;
|
||||||
routeName?: string;
|
routeName?: string;
|
||||||
fixUrl: boolean;
|
fixUrl: boolean;
|
||||||
@@ -84,7 +85,7 @@ async function fetchDashboard(
|
|||||||
return dashDTO;
|
return dashDTO;
|
||||||
}
|
}
|
||||||
case DashboardRoutes.New: {
|
case DashboardRoutes.New: {
|
||||||
return getNewDashboardModelData(args.urlFolderId);
|
return getNewDashboardModelData(args.urlFolderId, args.panelType);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw { message: 'Unknown route ' + args.routeName };
|
throw { message: 'Unknown route ' + args.routeName };
|
||||||
@@ -213,7 +214,7 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNewDashboardModelData(urlFolderId?: string | null): any {
|
export function getNewDashboardModelData(urlFolderId?: string, panelType?: string): any {
|
||||||
const data = {
|
const data = {
|
||||||
meta: {
|
meta: {
|
||||||
canStar: false,
|
canStar: false,
|
||||||
@@ -226,7 +227,7 @@ export function getNewDashboardModelData(urlFolderId?: string | null): any {
|
|||||||
title: 'New dashboard',
|
title: 'New dashboard',
|
||||||
panels: [
|
panels: [
|
||||||
{
|
{
|
||||||
type: 'add-panel',
|
type: panelType ?? 'add-panel',
|
||||||
gridPos: { x: 0, y: 0, w: 12, h: 9 },
|
gridPos: { x: 0, y: 0, w: 12, h: 9 },
|
||||||
title: 'Panel Title',
|
title: 'Panel Title',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { CatalogPlugin, PluginTabIds } from '../types';
|
|||||||
|
|
||||||
import { AppConfigCtrlWrapper } from './AppConfigWrapper';
|
import { AppConfigCtrlWrapper } from './AppConfigWrapper';
|
||||||
import { PluginDashboards } from './PluginDashboards';
|
import { PluginDashboards } from './PluginDashboards';
|
||||||
|
import { PluginUsage } from './PluginUsage';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
plugin: CatalogPlugin;
|
plugin: CatalogPlugin;
|
||||||
@@ -60,6 +61,14 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pageId === PluginTabIds.USAGE && pluginConfig) {
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<PluginUsage plugin={pluginConfig?.meta} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (pageId === PluginTabIds.DASHBOARDS && pluginConfig) {
|
if (pageId === PluginTabIds.DASHBOARDS && pluginConfig) {
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
@@ -78,6 +87,7 @@ export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.E
|
|||||||
export const getStyles = (theme: GrafanaTheme2) => ({
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
container: css`
|
container: css`
|
||||||
padding: ${theme.spacing(3, 4)};
|
padding: ${theme.spacing(3, 4)};
|
||||||
|
height: 100%;
|
||||||
`,
|
`,
|
||||||
readme: css`
|
readme: css`
|
||||||
& img {
|
& img {
|
||||||
|
|||||||
90
public/app/features/plugins/admin/components/PluginUsage.tsx
Normal file
90
public/app/features/plugins/admin/components/PluginUsage.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import { useAsync } from 'react-use';
|
||||||
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
|
||||||
|
import { GrafanaTheme2, PluginMeta } from '@grafana/data';
|
||||||
|
import { config } from '@grafana/runtime';
|
||||||
|
import { Alert, Spinner, useStyles2 } from '@grafana/ui';
|
||||||
|
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||||
|
import { SearchResultsTable } from 'app/features/search/page/components/SearchResultsTable';
|
||||||
|
import { getGrafanaSearcher, SearchQuery } from 'app/features/search/service';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
plugin: PluginMeta;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function PluginUsage({ plugin }: Props) {
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
|
const searchQuery = useMemo<SearchQuery>(() => {
|
||||||
|
return {
|
||||||
|
query: '*',
|
||||||
|
panel_type: plugin.id,
|
||||||
|
kind: ['panel'],
|
||||||
|
};
|
||||||
|
}, [plugin]);
|
||||||
|
|
||||||
|
const results = useAsync(() => {
|
||||||
|
return getGrafanaSearcher().search(searchQuery);
|
||||||
|
}, [searchQuery]);
|
||||||
|
|
||||||
|
const found = results.value;
|
||||||
|
if (found?.totalRows) {
|
||||||
|
return (
|
||||||
|
<div className={styles.wrap}>
|
||||||
|
<div className={styles.info}>
|
||||||
|
{plugin.name} is used <b>{found.totalRows}</b> times.
|
||||||
|
</div>
|
||||||
|
<AutoSizer>
|
||||||
|
{({ width, height }) => {
|
||||||
|
return (
|
||||||
|
<SearchResultsTable
|
||||||
|
response={found}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
clearSelection={() => {}}
|
||||||
|
keyboardEvents={of()}
|
||||||
|
onTagSelected={() => {}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</AutoSizer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.loading) {
|
||||||
|
return <Spinner />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.featureToggles.panelTitleSearch) {
|
||||||
|
return (
|
||||||
|
<Alert title="Missing feature toggle: panelTitleSearch">
|
||||||
|
Plugin usage requires the new search index to find usage across dashboards
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EmptyListCTA
|
||||||
|
title={`${plugin.name} is not used in any dashboards yet`}
|
||||||
|
buttonIcon="plus"
|
||||||
|
buttonTitle="Create Dashboard"
|
||||||
|
buttonLink={`dashboard/new?panelType=${plugin.id}&editPanel=1`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStyles = (theme: GrafanaTheme2) => {
|
||||||
|
return {
|
||||||
|
wrap: css`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
`,
|
||||||
|
info: css`
|
||||||
|
padding-bottom: 30px;
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { PluginIncludeType, PluginType } from '@grafana/data';
|
import { PluginIncludeType, PluginType } from '@grafana/data';
|
||||||
|
import { config } from '@grafana/runtime';
|
||||||
|
|
||||||
import { usePluginConfig } from '../hooks/usePluginConfig';
|
import { usePluginConfig } from '../hooks/usePluginConfig';
|
||||||
import { isOrgAdmin } from '../permissions';
|
import { isOrgAdmin } from '../permissions';
|
||||||
@@ -23,7 +24,6 @@ export const usePluginDetailsTabs = (plugin?: CatalogPlugin, defaultTabs: Plugin
|
|||||||
const canConfigurePlugins = isOrgAdmin();
|
const canConfigurePlugins = isOrgAdmin();
|
||||||
const tabs: PluginDetailsTab[] = [...defaultTabs];
|
const tabs: PluginDetailsTab[] = [...defaultTabs];
|
||||||
let defaultTab;
|
let defaultTab;
|
||||||
|
|
||||||
if (isPublished) {
|
if (isPublished) {
|
||||||
tabs.push({
|
tabs.push({
|
||||||
label: PluginTabLabels.VERSIONS,
|
label: PluginTabLabels.VERSIONS,
|
||||||
@@ -39,6 +39,15 @@ export const usePluginDetailsTabs = (plugin?: CatalogPlugin, defaultTabs: Plugin
|
|||||||
return [tabs, defaultTab];
|
return [tabs, defaultTab];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.featureToggles.panelTitleSearch && pluginConfig.meta.type === PluginType.panel) {
|
||||||
|
tabs.push({
|
||||||
|
label: PluginTabLabels.USAGE,
|
||||||
|
icon: 'list-ul',
|
||||||
|
id: PluginTabIds.USAGE,
|
||||||
|
href: `${pathname}?page=${PluginTabIds.USAGE}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (canConfigurePlugins) {
|
if (canConfigurePlugins) {
|
||||||
if (pluginConfig.meta.type === PluginType.app) {
|
if (pluginConfig.meta.type === PluginType.app) {
|
||||||
if (pluginConfig.angularConfigCtrl) {
|
if (pluginConfig.angularConfigCtrl) {
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ export const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
// Needed due to block formatting context
|
// Needed due to block formatting context
|
||||||
tabContent: css`
|
tabContent: css`
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ export enum PluginTabLabels {
|
|||||||
VERSIONS = 'Version history',
|
VERSIONS = 'Version history',
|
||||||
CONFIG = 'Config',
|
CONFIG = 'Config',
|
||||||
DASHBOARDS = 'Dashboards',
|
DASHBOARDS = 'Dashboards',
|
||||||
|
USAGE = 'Usage',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PluginTabIds {
|
export enum PluginTabIds {
|
||||||
@@ -219,6 +220,7 @@ export enum PluginTabIds {
|
|||||||
VERSIONS = 'version-history',
|
VERSIONS = 'version-history',
|
||||||
CONFIG = 'config',
|
CONFIG = 'config',
|
||||||
DASHBOARDS = 'dashboards',
|
DASHBOARDS = 'dashboards',
|
||||||
|
USAGE = 'usage',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RequestStatus {
|
export enum RequestStatus {
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ export const SearchResultsTable = React.memo(
|
|||||||
clearSelection,
|
clearSelection,
|
||||||
styles,
|
styles,
|
||||||
onTagSelected,
|
onTagSelected,
|
||||||
onDatasourceChange
|
onDatasourceChange,
|
||||||
|
response.view?.length >= response.totalRows
|
||||||
);
|
);
|
||||||
}, [response, width, styles, selection, selectionToggle, clearSelection, onTagSelected, onDatasourceChange]);
|
}, [response, width, styles, selection, selectionToggle, clearSelection, onTagSelected, onDatasourceChange]);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ export const generateColumns = (
|
|||||||
clearSelection: () => void,
|
clearSelection: () => void,
|
||||||
styles: { [key: string]: string },
|
styles: { [key: string]: string },
|
||||||
onTagSelected: (tag: string) => void,
|
onTagSelected: (tag: string) => void,
|
||||||
onDatasourceChange?: (datasource?: string) => void
|
onDatasourceChange?: (datasource?: string) => void,
|
||||||
|
showingEverything?: boolean
|
||||||
): TableColumn[] => {
|
): TableColumn[] => {
|
||||||
const columns: TableColumn[] = [];
|
const columns: TableColumn[] = [];
|
||||||
const access = response.view.fields;
|
const access = response.view.fields;
|
||||||
@@ -125,9 +126,26 @@ export const generateColumns = (
|
|||||||
columns.push(makeTypeColumn(access.kind, access.panel_type, width, styles));
|
columns.push(makeTypeColumn(access.kind, access.panel_type, width, styles));
|
||||||
availableWidth -= width;
|
availableWidth -= width;
|
||||||
|
|
||||||
|
// Show datasources if we have any
|
||||||
|
if (access.ds_uid && onDatasourceChange) {
|
||||||
|
width = Math.min(availableWidth / 2.5, DATASOURCE_COLUMN_WIDTH);
|
||||||
|
columns.push(
|
||||||
|
makeDataSourceColumn(
|
||||||
|
access.ds_uid,
|
||||||
|
width,
|
||||||
|
styles.typeIcon,
|
||||||
|
styles.datasourceItem,
|
||||||
|
styles.invalidDatasourceItem,
|
||||||
|
onDatasourceChange
|
||||||
|
)
|
||||||
|
);
|
||||||
|
availableWidth -= width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const showTags = !showingEverything || hasValue(response.view.fields.tags);
|
||||||
const meta = response.view.dataFrame.meta?.custom as SearchResultMeta;
|
const meta = response.view.dataFrame.meta?.custom as SearchResultMeta;
|
||||||
if (meta?.locationInfo && availableWidth > 0) {
|
if (meta?.locationInfo && availableWidth > 0) {
|
||||||
width = Math.max(availableWidth / 1.75, 300);
|
width = showTags ? Math.max(availableWidth / 1.75, 300) : availableWidth;
|
||||||
availableWidth -= width;
|
availableWidth -= width;
|
||||||
columns.push({
|
columns.push({
|
||||||
Cell: (p) => {
|
Cell: (p) => {
|
||||||
@@ -154,23 +172,7 @@ export const generateColumns = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show datasources if we have any
|
if (availableWidth > 0 && showTags) {
|
||||||
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));
|
columns.push(makeTagsColumn(access.tags, availableWidth, styles.tagList, onTagSelected));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +211,15 @@ function getIconForKind(v: string): IconName {
|
|||||||
return 'question-circle';
|
return 'question-circle';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasValue(f: Field): boolean {
|
||||||
|
for (let i = 0; i < f.values.length; i++) {
|
||||||
|
if (f.values.get(i) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function makeDataSourceColumn(
|
function makeDataSourceColumn(
|
||||||
field: Field<string[]>,
|
field: Field<string[]>,
|
||||||
width: number,
|
width: number,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export interface SearchQuery {
|
|||||||
ds_uid?: string;
|
ds_uid?: string;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
kind?: string[];
|
kind?: string[];
|
||||||
|
panel_type?: string;
|
||||||
uid?: string[];
|
uid?: string[];
|
||||||
id?: number[];
|
id?: number[];
|
||||||
facet?: FacetField[];
|
facet?: FacetField[];
|
||||||
|
|||||||
Reference in New Issue
Block a user