mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 01:53:33 -06:00
* Share button works now. Removed add to dashboard button for now * WIP explore link * Remove settings dropdown for now * Use getExploreUrl to generate explore link * Fix conflicts * Update betterer * Navigate to a new trail when the recent trails list is empty * Address PR comments
114 lines
3.1 KiB
TypeScript
114 lines
3.1 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import React from 'react';
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
|
import { AdHocFiltersVariable, sceneGraph } from '@grafana/scenes';
|
|
import { useStyles2, Stack, Tooltip, Button } from '@grafana/ui';
|
|
|
|
import { DataTrail } from './DataTrail';
|
|
import { LOGS_METRIC, VAR_FILTERS } from './shared';
|
|
import { getDataSource, getDataSourceName } from './utils';
|
|
|
|
export interface Props {
|
|
trail: DataTrail;
|
|
onSelect: (trail: DataTrail) => void;
|
|
onDelete?: () => void;
|
|
}
|
|
|
|
export function DataTrailCard({ trail, onSelect, onDelete }: Props) {
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const filtersVariable = sceneGraph.lookupVariable(VAR_FILTERS, trail)!;
|
|
if (!(filtersVariable instanceof AdHocFiltersVariable)) {
|
|
return null;
|
|
}
|
|
|
|
const filters = filtersVariable.state.set.state.filters;
|
|
const dsValue = getDataSource(trail);
|
|
|
|
return (
|
|
<button className={styles.container} onClick={() => onSelect(trail)}>
|
|
<div className={styles.wrapper}>
|
|
<div className={styles.heading}>{getMetricName(trail.state.metric)}</div>
|
|
{onDelete && (
|
|
<Tooltip content={'Remove bookmark'}>
|
|
<Button size="sm" icon="trash-alt" variant="destructive" fill="text" onClick={onDelete} />
|
|
</Tooltip>
|
|
)}
|
|
</div>
|
|
|
|
<Stack gap={1.5}>
|
|
{dsValue && (
|
|
<Stack direction="column" gap={0.5}>
|
|
<div className={styles.label}>Datasource</div>
|
|
<div className={styles.value}>{getDataSourceName(dsValue)}</div>
|
|
</Stack>
|
|
)}
|
|
{filters.map((filter, index) => (
|
|
<Stack key={index} direction="column" gap={0.5}>
|
|
<div className={styles.label}>{filter.key}</div>
|
|
<div className={styles.value}>{filter.value}</div>
|
|
</Stack>
|
|
))}
|
|
</Stack>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
function getMetricName(metric?: string) {
|
|
if (!metric) {
|
|
return 'Select metric';
|
|
}
|
|
|
|
if (metric === LOGS_METRIC) {
|
|
return 'Logs';
|
|
}
|
|
|
|
return metric;
|
|
}
|
|
|
|
function getStyles(theme: GrafanaTheme2) {
|
|
return {
|
|
container: css({
|
|
padding: theme.spacing(1),
|
|
flexGrow: 1,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: theme.spacing(2),
|
|
width: '100%',
|
|
border: `1px solid ${theme.colors.border.weak}`,
|
|
borderRadius: theme.shape.radius.default,
|
|
cursor: 'pointer',
|
|
boxShadow: 'none',
|
|
background: 'transparent',
|
|
textAlign: 'left',
|
|
'&:hover': {
|
|
background: theme.colors.emphasize(theme.colors.background.primary, 0.03),
|
|
},
|
|
}),
|
|
label: css({
|
|
fontWeight: theme.typography.fontWeightMedium,
|
|
fontSize: theme.typography.bodySmall.fontSize,
|
|
}),
|
|
value: css({
|
|
fontSize: theme.typography.bodySmall.fontSize,
|
|
}),
|
|
heading: css({
|
|
padding: theme.spacing(0),
|
|
display: 'flex',
|
|
fontWeight: theme.typography.fontWeightMedium,
|
|
overflowX: 'hidden',
|
|
}),
|
|
body: css({
|
|
padding: theme.spacing(0),
|
|
}),
|
|
wrapper: css({
|
|
position: 'relative',
|
|
display: 'flex',
|
|
gap: theme.spacing.x1,
|
|
justifyContent: 'space-between',
|
|
width: '100%',
|
|
}),
|
|
};
|
|
}
|