import { css } from '@emotion/css'; import React from 'react'; import { GrafanaTheme2 } from '@grafana/data/src'; import { Checkbox, useTheme2 } from '@grafana/ui/src'; import { fieldNameMeta } from './LogsTableWrap'; function getStyles(theme: GrafanaTheme2) { return { labelCount: css({ marginLeft: theme.spacing(0.5), marginRight: theme.spacing(0.5), }), wrap: css({ display: 'flex', alignItems: 'center', marginTop: theme.spacing(1), marginBottom: theme.spacing(1), justifyContent: 'space-between', }), // Making the checkbox sticky and label scrollable for labels that are wider then the container // However, the checkbox component does not support this, so we need to do some css hackery for now until the API of that component is updated. checkboxLabel: css({ '> :first-child': { position: 'sticky', left: 0, bottom: 0, top: 0, }, '> span': { overflow: 'scroll', '&::-webkit-scrollbar': { display: 'none', }, '&::-moz-scrollbar': { display: 'none', }, }, }), columnWrapper: css({ marginBottom: theme.spacing(1.5), // need some space or the outline of the checkbox is cut off paddingLeft: theme.spacing(0.5), }), empty: css({ marginBottom: theme.spacing(2), marginLeft: theme.spacing(1.75), fontSize: theme.typography.fontSize, }), }; } function sortLabels(labels: Record) { return (a: string, b: string) => { // First sort by active if (labels[a].active && labels[b].active) { // If both fields are active, sort time first if (labels[a]?.type === 'TIME_FIELD') { return -1; } if (labels[b]?.type === 'TIME_FIELD') { return 1; } // And then line second if (labels[a]?.type === 'BODY_FIELD') { return -1; } // special fields are next if (labels[b]?.type === 'BODY_FIELD') { return 1; } } if (labels[b].active && labels[a].active) { // Sort alphabetically if (a < b) { return -1; } if (a > b) { return 1; } } // If just one label is active, sort it first if (labels[b].active) { return 1; } if (labels[a].active) { return -1; } // If both fields are special, and not selected, sort time first if (labels[a]?.type && labels[b]?.type) { if (labels[a]?.type === 'TIME_FIELD') { return -1; } return 0; } // If only one special field, stick to the top of inactive fields if (labels[a]?.type && !labels[b]?.type) { return -1; } // if the b field is special, sort it first if (!labels[a]?.type && labels[b]?.type) { return 1; } // Finally sort by name if (a < b) { return -1; } if (a > b) { return 1; } // otherwise do not sort return 0; }; } export const LogsTableNavColumn = (props: { labels: Record; valueFilter: (value: number) => boolean; toggleColumn: (columnName: string) => void; }): JSX.Element => { const { labels, valueFilter, toggleColumn } = props; const theme = useTheme2(); const styles = getStyles(theme); const labelKeys = Object.keys(labels).filter((labelName) => valueFilter(labels[labelName].percentOfLinesWithLabel)); if (labelKeys.length) { return (
{labelKeys.sort(sortLabels(labels)).map((labelName) => (
toggleColumn(labelName)} checked={labels[labelName]?.active ?? false} /> ({labels[labelName]?.percentOfLinesWithLabel}%)
))}
); } return
No fields
; };