mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 06:02:49 +08:00
TraceView: Refactor theming to use Grafana theme directly (#43856)
* Use grafana theme and utils * Use grafana colors * Fix tests * Use useStyles2
This commit is contained in:
@ -12,161 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React, { useContext } from 'react';
|
||||
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
const COLORS_HEX = [
|
||||
'#17B8BE',
|
||||
'#F8DCA1',
|
||||
'#B7885E',
|
||||
'#FFCB99',
|
||||
'#F89570',
|
||||
'#829AE3',
|
||||
'#E79FD5',
|
||||
'#1E96BE',
|
||||
'#89DAC1',
|
||||
'#B3AD9E',
|
||||
'#12939A',
|
||||
'#DDB27C',
|
||||
'#88572C',
|
||||
'#FF9833',
|
||||
'#EF5D28',
|
||||
'#162A65',
|
||||
'#DA70BF',
|
||||
'#125C77',
|
||||
'#4DC19C',
|
||||
'#776E57',
|
||||
];
|
||||
|
||||
const COLORS_HEX_DARK = [
|
||||
'#17B8BE',
|
||||
'#F8DCA1',
|
||||
'#B7885E',
|
||||
'#FFCB99',
|
||||
'#F89570',
|
||||
'#829AE3',
|
||||
'#E79FD5',
|
||||
'#1E96BE',
|
||||
'#89DAC1',
|
||||
'#B3AD9E',
|
||||
'#12939A',
|
||||
'#DDB27C',
|
||||
'#88572C',
|
||||
'#FF9833',
|
||||
'#EF5D28',
|
||||
'#DA70BF',
|
||||
'#4DC19C',
|
||||
'#776E57',
|
||||
];
|
||||
|
||||
export type ThemeOptions = Partial<Theme>;
|
||||
|
||||
export enum ThemeType {
|
||||
Dark,
|
||||
Light,
|
||||
}
|
||||
|
||||
export type Theme = {
|
||||
type: ThemeType;
|
||||
servicesColorPalette: string[];
|
||||
borderStyle: string;
|
||||
components?: {
|
||||
TraceName?: {
|
||||
fontSize?: number | string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const defaultTheme: Theme = {
|
||||
type: ThemeType.Light,
|
||||
borderStyle: '1px solid #bbb',
|
||||
servicesColorPalette: COLORS_HEX,
|
||||
};
|
||||
|
||||
export function isLight(theme?: Theme | ThemeOptions) {
|
||||
// Light theme is default type not set which only happens if called for ThemeOptions.
|
||||
return theme && theme.type ? theme.type === ThemeType.Light : false;
|
||||
}
|
||||
|
||||
const ThemeContext = React.createContext<ThemeOptions | undefined>(undefined);
|
||||
ThemeContext.displayName = 'ThemeContext';
|
||||
|
||||
export const ThemeProvider = ThemeContext.Provider;
|
||||
|
||||
type ThemeConsumerProps = {
|
||||
children: (theme: Theme) => React.ReactNode;
|
||||
};
|
||||
export function ThemeConsumer(props: ThemeConsumerProps) {
|
||||
return (
|
||||
<ThemeContext.Consumer>
|
||||
{(value: ThemeOptions | undefined) => {
|
||||
const theme = memoizedThemeMerge(value);
|
||||
return props.children(theme);
|
||||
}}
|
||||
</ThemeContext.Consumer>
|
||||
);
|
||||
}
|
||||
|
||||
const memoizedThemeMerge = memoizeOne((value?: ThemeOptions) => {
|
||||
const darkOverrides: Partial<Theme> = {};
|
||||
if (!isLight(value)) {
|
||||
darkOverrides.servicesColorPalette = COLORS_HEX_DARK;
|
||||
}
|
||||
return value
|
||||
? {
|
||||
...defaultTheme,
|
||||
...darkOverrides,
|
||||
...value,
|
||||
}
|
||||
: defaultTheme;
|
||||
});
|
||||
|
||||
type WrappedWithThemeComponent<Props> = React.ComponentType<Omit<Props, 'theme'>> & {
|
||||
wrapped: React.ComponentType<Props>;
|
||||
};
|
||||
|
||||
export const withTheme = <Props extends { theme: Theme }, Statics extends {} = {}>(
|
||||
Component: React.ComponentType<Props>
|
||||
): WrappedWithThemeComponent<Props> => {
|
||||
let WithTheme: React.ComponentType<Omit<Props, 'theme'>> = (props) => {
|
||||
return (
|
||||
<ThemeConsumer>
|
||||
{(theme: Theme) => {
|
||||
return (
|
||||
<Component
|
||||
{...({
|
||||
...props,
|
||||
theme,
|
||||
} as Props & { theme: Theme })}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</ThemeConsumer>
|
||||
);
|
||||
};
|
||||
|
||||
WithTheme.displayName = `WithTheme(${Component.displayName})`;
|
||||
WithTheme = hoistNonReactStatics<React.ComponentType<Omit<Props, 'theme'>>, React.ComponentType<Props>>(
|
||||
WithTheme,
|
||||
Component
|
||||
);
|
||||
(WithTheme as WrappedWithThemeComponent<Props>).wrapped = Component;
|
||||
return WithTheme as WrappedWithThemeComponent<Props>;
|
||||
};
|
||||
|
||||
export function useTheme(): Theme {
|
||||
const theme = useContext(ThemeContext);
|
||||
return {
|
||||
...defaultTheme,
|
||||
...theme,
|
||||
};
|
||||
}
|
||||
|
||||
export const createStyle = <Fn extends (this: any, ...newArgs: any[]) => ReturnType<Fn>>(fn: Fn) => {
|
||||
return memoizeOne(fn);
|
||||
};
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
/**
|
||||
* Tries to get a dark variant color. Either by simply inverting the luminosity and darkening or lightening the color
|
||||
@ -176,8 +23,8 @@ export const createStyle = <Fn extends (this: any, ...newArgs: any[]) => ReturnT
|
||||
* @param hex
|
||||
* @param base
|
||||
*/
|
||||
export function autoColor(theme: Theme, hex: string, base?: string) {
|
||||
if (isLight(theme)) {
|
||||
export function autoColor(theme: GrafanaTheme2, hex: string, base?: string) {
|
||||
if (theme.isLight) {
|
||||
return hex;
|
||||
} else {
|
||||
if (base) {
|
||||
@ -204,19 +51,3 @@ export function autoColor(theme: Theme, hex: string, base?: string) {
|
||||
return newColor.isLight() ? newColor.darken(5).toHex8String() : newColor.lighten(5).toHex8String();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* With theme overrides you can use both number or string (for things like rem units) so this makes sure we convert
|
||||
* the value accordingly or use fallback if not set
|
||||
*/
|
||||
export function safeSize(size: number | string | undefined, fallback: string): string {
|
||||
if (!size) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
if (typeof size === 'string') {
|
||||
return size;
|
||||
} else {
|
||||
return `${size}px`;
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import { UnthemedCanvasSpanGraph } from './CanvasSpanGraph';
|
||||
import { defaultTheme } from '../../Theme';
|
||||
|
||||
describe('<CanvasSpanGraph>', () => {
|
||||
it('renders without exploding', () => {
|
||||
const items = [{ valueWidth: 1, valueOffset: 1, serviceName: 'service-name-0' }];
|
||||
const wrapper = shallow(<UnthemedCanvasSpanGraph items={[]} valueWidth={4000} theme={defaultTheme} />);
|
||||
const wrapper = shallow(<UnthemedCanvasSpanGraph items={[]} valueWidth={4000} theme={createTheme()} />);
|
||||
expect(wrapper).toBeDefined();
|
||||
wrapper.instance()._setCanvasRef({
|
||||
getContext: () => ({
|
||||
|
@ -19,9 +19,11 @@ import renderIntoCanvas from './render-into-canvas';
|
||||
import { getRgbColorByKey } from '../../utils/color-generator';
|
||||
import { TNil } from '../../types';
|
||||
|
||||
import { autoColor, createStyle, Theme, withTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { withTheme2, stylesFactory } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
CanvasSpanGraph: css`
|
||||
label: CanvasSpanGraph;
|
||||
@ -36,7 +38,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
type CanvasSpanGraphProps = {
|
||||
items: Array<{ valueWidth: number; valueOffset: number; serviceName: string }>;
|
||||
valueWidth: number;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
};
|
||||
|
||||
export class UnthemedCanvasSpanGraph extends React.PureComponent<CanvasSpanGraphProps> {
|
||||
@ -73,4 +75,4 @@ export class UnthemedCanvasSpanGraph extends React.PureComponent<CanvasSpanGraph
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedCanvasSpanGraph);
|
||||
export default withTheme2(UnthemedCanvasSpanGraph);
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { createStyle } from '../../Theme';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
GraphTick: css`
|
||||
label: GraphTick;
|
||||
@ -24,7 +24,7 @@ const getStyles = createStyle(() => {
|
||||
stroke-width: 1px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type GraphTicksProps = {
|
||||
numTicks: number;
|
||||
@ -32,11 +32,12 @@ type GraphTicksProps = {
|
||||
|
||||
export default function GraphTicks(props: GraphTicksProps) {
|
||||
const { numTicks } = props;
|
||||
const styles = useStyles2(getStyles);
|
||||
const ticks = [];
|
||||
// i starts at 1, limit is `i < numTicks` so the first and last ticks aren't drawn
|
||||
for (let i = 1; i < numTicks; i++) {
|
||||
const x = `${(i / numTicks) * 100}%`;
|
||||
ticks.push(<line className={getStyles().GraphTick} x1={x} y1="0%" x2={x} y2="100%" key={i / numTicks} />);
|
||||
ticks.push(<line className={styles.GraphTick} x1={x} y1="0%" x2={x} y2="100%" key={i / numTicks} />);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -14,11 +14,10 @@
|
||||
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
import { createStyle } from '../../Theme';
|
||||
import { css } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = () => {
|
||||
return {
|
||||
ScrubberHandleExpansion: cx(
|
||||
css`
|
||||
@ -70,7 +69,7 @@ export const getStyles = createStyle(() => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type ScrubberProps = {
|
||||
isDragging: boolean;
|
||||
@ -82,7 +81,7 @@ type ScrubberProps = {
|
||||
|
||||
export default function Scrubber({ isDragging, onMouseDown, onMouseEnter, onMouseLeave, position }: ScrubberProps) {
|
||||
const xPercent = `${position * 100}%`;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
const className = cx({ [styles.ScrubberDragging]: isDragging });
|
||||
return (
|
||||
<g className={className}>
|
||||
|
@ -13,13 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { formatDuration } from '../../utils/date';
|
||||
|
||||
import { createStyle } from '../../Theme';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
TickLabels: css`
|
||||
label: TickLabels;
|
||||
@ -34,7 +33,7 @@ const getStyles = createStyle(() => {
|
||||
user-select: none;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TickLabelsProps = {
|
||||
numTicks: number;
|
||||
@ -43,7 +42,7 @@ type TickLabelsProps = {
|
||||
|
||||
export default function TickLabels(props: TickLabelsProps) {
|
||||
const { numTicks, duration } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const ticks = [];
|
||||
for (let i = 0; i < numTicks + 1; i++) {
|
||||
|
@ -14,13 +14,13 @@
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import GraphTicks from './GraphTicks';
|
||||
import Scrubber from './Scrubber';
|
||||
import ViewingLayer, { dragTypes, getStyles } from './ViewingLayer';
|
||||
import { EUpdateTypes } from '../../utils/DraggableManager';
|
||||
import { polyfill as polyfillAnimationFrame } from '../../utils/test/requestAnimationFrame';
|
||||
import { defaultTheme } from '../../Theme';
|
||||
|
||||
function getViewRange(viewStart, viewEnd) {
|
||||
return {
|
||||
@ -45,7 +45,6 @@ describe('<SpanGraph>', () => {
|
||||
viewRange: getViewRange(0, 1),
|
||||
};
|
||||
wrapper = shallow(<ViewingLayer {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
});
|
||||
@ -54,7 +53,6 @@ describe('<SpanGraph>', () => {
|
||||
beforeEach(() => {
|
||||
props = { ...props, viewRange: getViewRange(0.1, 0.9) };
|
||||
wrapper = shallow(<ViewingLayer {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
wrapper.instance()._setRoot({
|
||||
@ -130,7 +128,6 @@ describe('<SpanGraph>', () => {
|
||||
const time = { ...props.viewRange.time, reframe: { anchor } };
|
||||
props = { ...props, viewRange: { time } };
|
||||
wrapper = shallow(<ViewingLayer {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
wrapper.instance()._handleReframeDragUpdate({ value });
|
||||
@ -160,7 +157,6 @@ describe('<SpanGraph>', () => {
|
||||
const time = { ...props.viewRange.time, reframe: { anchor } };
|
||||
props = { ...props, viewRange: { time } };
|
||||
wrapper = shallow(<ViewingLayer {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
wrapper.instance()._handleReframeDragEnd({ manager, value });
|
||||
@ -176,7 +172,6 @@ describe('<SpanGraph>', () => {
|
||||
const time = { ...props.viewRange.time, reframe: { anchor } };
|
||||
props = { ...props, viewRange: { time } };
|
||||
wrapper = shallow(<ViewingLayer {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
wrapper.instance()._handleReframeDragEnd({ manager, value });
|
||||
@ -274,28 +269,28 @@ describe('<SpanGraph>', () => {
|
||||
|
||||
describe('.ViewingLayer--resetZoom', () => {
|
||||
it('should not render .ViewingLayer--resetZoom if props.viewRange.time.current = [0,1]', () => {
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
wrapper.setProps({ viewRange: { time: { current: [0, 1] } } });
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should render ViewingLayer--resetZoom if props.viewRange.time.current[0] !== 0', () => {
|
||||
// If the test fails on the following expect statement, this may be a false negative
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
wrapper.setProps({ viewRange: { time: { current: [0.1, 1] } } });
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(1);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should render ViewingLayer--resetZoom if props.viewRange.time.current[1] !== 1', () => {
|
||||
// If the test fails on the following expect statement, this may be a false negative
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(0);
|
||||
wrapper.setProps({ viewRange: { time: { current: [0, 0.9] } } });
|
||||
expect(wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`).length).toBe(1);
|
||||
expect(wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should call props.updateViewRangeTime when clicked', () => {
|
||||
wrapper.setProps({ viewRange: { time: { current: [0.1, 0.9] } } });
|
||||
const resetZoomButton = wrapper.find(`.${getStyles(defaultTheme).ViewingLayerResetZoom}`);
|
||||
const resetZoomButton = wrapper.find(`.${getStyles(createTheme()).ViewingLayerResetZoom}`);
|
||||
// If the test fails on the following expect statement, this may be a false negative caused
|
||||
// by a regression to rendering.
|
||||
expect(resetZoomButton.length).toBe(1);
|
||||
@ -313,11 +308,10 @@ describe('<SpanGraph>', () => {
|
||||
it('renders a filtering box if leftBound exists', () => {
|
||||
const _props = { ...props, viewRange: getViewRange(0.2, 1) };
|
||||
wrapper = shallow(<ViewingLayer {..._props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
|
||||
const leftBox = wrapper.find(`.${getStyles(defaultTheme).ViewingLayerInactive}`);
|
||||
const leftBox = wrapper.find(`.${getStyles(createTheme()).ViewingLayerInactive}`);
|
||||
expect(leftBox.length).toBe(1);
|
||||
const width = Number(leftBox.prop('width').slice(0, -1));
|
||||
const x = leftBox.prop('x');
|
||||
@ -328,11 +322,10 @@ describe('<SpanGraph>', () => {
|
||||
it('renders a filtering box if rightBound exists', () => {
|
||||
const _props = { ...props, viewRange: getViewRange(0, 0.8) };
|
||||
wrapper = shallow(<ViewingLayer {..._props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
|
||||
const rightBox = wrapper.find(`.${getStyles(defaultTheme).ViewingLayerInactive}`);
|
||||
const rightBox = wrapper.find(`.${getStyles(createTheme()).ViewingLayerInactive}`);
|
||||
expect(rightBox.length).toBe(1);
|
||||
const width = Number(rightBox.prop('width').slice(0, -1));
|
||||
const x = Number(rightBox.prop('x').slice(0, -1));
|
||||
|
@ -15,14 +15,16 @@
|
||||
import cx from 'classnames';
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { withTheme2, stylesFactory } from '@grafana/ui';
|
||||
|
||||
import GraphTicks from './GraphTicks';
|
||||
import Scrubber from './Scrubber';
|
||||
import { TUpdateViewRangeTimeFunction, UIButton, ViewRange, ViewRangeTimeUpdate, TNil } from '../..';
|
||||
import { withTheme, Theme, autoColor, createStyle } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import DraggableManager, { DraggableBounds, DraggingUpdate, EUpdateTypes } from '../../utils/DraggableManager';
|
||||
|
||||
export const getStyles = createStyle((theme: Theme) => {
|
||||
export const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
// Need this cause emotion will merge emotion generated classes into single className if used with cx from emotion
|
||||
// package and the selector won't work
|
||||
const ViewingLayerResetZoomHoverClassName = 'JaegerUiComponents__ViewingLayerResetZoomHoverClassName';
|
||||
@ -91,7 +93,7 @@ type ViewingLayerProps = {
|
||||
updateViewRangeTime: TUpdateViewRangeTimeFunction;
|
||||
updateNextViewRangeTime: (update: ViewRangeTimeUpdate) => void;
|
||||
viewRange: ViewRange;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
};
|
||||
|
||||
type ViewingLayerState = {
|
||||
@ -406,4 +408,4 @@ export class UnthemedViewingLayer extends React.PureComponent<ViewingLayerProps,
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedViewingLayer);
|
||||
export default withTheme2(UnthemedViewingLayer);
|
||||
|
@ -17,10 +17,12 @@ import { get as _get, maxBy as _maxBy, values as _values } from 'lodash';
|
||||
import MdKeyboardArrowRight from 'react-icons/lib/md/keyboard-arrow-right';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { dateTimeFormat, GrafanaTheme2, TimeZone } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import SpanGraph from './SpanGraph';
|
||||
import TracePageSearchBar from './TracePageSearchBar';
|
||||
import { autoColor, Theme, TUpdateViewRangeTimeFunction, useTheme, ViewRange, ViewRangeTimeUpdate } from '..';
|
||||
import { autoColor, TUpdateViewRangeTimeFunction, ViewRange, ViewRangeTimeUpdate } from '..';
|
||||
import LabeledList from '../common/LabeledList';
|
||||
import TraceName from '../common/TraceName';
|
||||
import { getTraceName } from '../model/trace-viewer';
|
||||
@ -30,11 +32,9 @@ import { formatDuration } from '../utils/date';
|
||||
import { getTraceLinks } from '../model/link-patterns';
|
||||
|
||||
import ExternalLinks from '../common/ExternalLinks';
|
||||
import { createStyle } from '../Theme';
|
||||
import { uTxMuted } from '../uberUtilityStyles';
|
||||
import { dateTimeFormat, TimeZone } from '@grafana/data';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
TracePageHeader: css`
|
||||
label: TracePageHeader;
|
||||
@ -135,7 +135,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
white-space: nowrap;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TracePageHeaderEmbedProps = {
|
||||
canCollapse: boolean;
|
||||
@ -225,7 +225,7 @@ export default function TracePageHeader(props: TracePageHeaderEmbedProps) {
|
||||
timeZone,
|
||||
} = props;
|
||||
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
const links = React.useMemo(() => {
|
||||
if (!trace) {
|
||||
return [];
|
||||
|
@ -16,18 +16,18 @@ import * as React from 'react';
|
||||
import cx from 'classnames';
|
||||
import IoAndroidLocate from 'react-icons/lib/io/android-locate';
|
||||
import { css } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import * as markers from './TracePageSearchBar.markers';
|
||||
import UiFindInput from '../common/UiFindInput';
|
||||
import { TNil } from '../types';
|
||||
|
||||
import { UIButton, UIInputGroup } from '../uiElementsContext';
|
||||
import { createStyle } from '../Theme';
|
||||
import { ubFlexAuto, ubJustifyEnd } from '../uberUtilityStyles';
|
||||
// eslint-disable-next-line no-duplicate-imports
|
||||
import { memo } from 'react';
|
||||
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = () => {
|
||||
return {
|
||||
TracePageSearchBar: css`
|
||||
label: TracePageSearchBar;
|
||||
@ -58,7 +58,7 @@ export const getStyles = createStyle(() => {
|
||||
padding: 1px 8px 4px;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TracePageSearchBarProps = {
|
||||
textFilter: string | TNil;
|
||||
@ -86,7 +86,7 @@ export default memo(function TracePageSearchBar(props: TracePageSearchBarProps)
|
||||
searchValue,
|
||||
hideSearchButtons,
|
||||
} = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
const count = textFilter ? <span className={styles.TracePageSearchBarCount}>{resultCount}</span> : null;
|
||||
|
||||
|
@ -14,14 +14,14 @@
|
||||
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { stylesFactory } from '@grafana/ui';
|
||||
|
||||
import NewWindowIcon from '../common/NewWindowIcon';
|
||||
import { TraceSpanReference } from '../types/trace';
|
||||
import { UITooltip, UIDropdown, UIMenuItem, UIMenu, TooltipPlacement } from '../uiElementsContext';
|
||||
|
||||
import ReferenceLink from '../url/ReferenceLink';
|
||||
import { createStyle } from '../Theme';
|
||||
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
MultiParent: css`
|
||||
padding: 0 5px;
|
||||
|
@ -17,14 +17,16 @@ import { css } from '@emotion/css';
|
||||
import { groupBy as _groupBy } from 'lodash';
|
||||
import React from 'react';
|
||||
import { compose, onlyUpdateForKeys, withProps, withState } from 'recompose';
|
||||
import { autoColor, createStyle, Theme } from '../Theme';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { autoColor } from '../Theme';
|
||||
import { TraceSpan } from '../types/trace';
|
||||
import { TNil } from '../types';
|
||||
import { UIPopover } from '../uiElementsContext';
|
||||
import AccordianLogs from './SpanDetail/AccordianLogs';
|
||||
import { ViewedBoundsFunctionType } from './utils';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
wrapper: css`
|
||||
label: wrapper;
|
||||
@ -86,7 +88,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TCommonProps = {
|
||||
color: string;
|
||||
@ -105,7 +107,6 @@ type TCommonProps = {
|
||||
span: TraceSpan;
|
||||
className?: string;
|
||||
labelClassName?: string;
|
||||
theme: Theme;
|
||||
};
|
||||
|
||||
type TInnerProps = {
|
||||
@ -136,7 +137,6 @@ function SpanBar(props: TInnerProps) {
|
||||
rpc,
|
||||
traceStartTime,
|
||||
span,
|
||||
theme,
|
||||
className,
|
||||
labelClassName,
|
||||
} = props;
|
||||
@ -146,7 +146,7 @@ function SpanBar(props: TInnerProps) {
|
||||
// round to the nearest 0.2%
|
||||
return toPercent(Math.round(posPercent * 500) / 500);
|
||||
});
|
||||
const styles = getStyles(theme);
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -19,6 +19,8 @@ import IoNetwork from 'react-icons/lib/io/network';
|
||||
import MdFileUpload from 'react-icons/lib/md/file-upload';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import ReferencesButton from './ReferencesButton';
|
||||
import TimelineRow from './TimelineRow';
|
||||
@ -29,7 +31,7 @@ import Ticks from './Ticks';
|
||||
|
||||
import { SpanLinkFunc, TNil } from '../types';
|
||||
import { TraceSpan } from '../types/trace';
|
||||
import { autoColor, createStyle, Theme, withTheme } from '../Theme';
|
||||
import { autoColor } from '../Theme';
|
||||
|
||||
const spanBarClassName = 'spanBar';
|
||||
const spanBarLabelClassName = 'spanBarLabel';
|
||||
@ -38,7 +40,7 @@ const nameWrapperMatchingFilterClassName = 'nameWrapperMatchingFilter';
|
||||
const viewClassName = 'jaegerView';
|
||||
const nameColumnClassName = 'nameColumn';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
nameWrapper: css`
|
||||
label: nameWrapper;
|
||||
@ -260,7 +262,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
|
||||
type SpanBarRowProps = {
|
||||
className?: string;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
color: string;
|
||||
columnDivision: number;
|
||||
isChildrenExpanded: boolean;
|
||||
@ -505,7 +507,6 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
rpc={rpc}
|
||||
viewStart={viewStart}
|
||||
viewEnd={viewEnd}
|
||||
theme={theme}
|
||||
getViewedBounds={getViewedBounds}
|
||||
color={color}
|
||||
shortLabel={label}
|
||||
@ -521,4 +522,4 @@ export class UnthemedSpanBarRow extends React.PureComponent<SpanBarRowProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedSpanBarRow);
|
||||
export default withTheme2(UnthemedSpanBarRow);
|
||||
|
@ -22,10 +22,12 @@ import * as markers from './AccordianKeyValues.markers';
|
||||
import KeyValuesTable from './KeyValuesTable';
|
||||
import { TNil } from '../../types';
|
||||
import { TraceKeyValuePair, TraceLink } from '../../types/trace';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { uAlignIcon, uTxEllipsis } from '../../uberUtilityStyles';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
export const getStyles = createStyle((theme: Theme) => {
|
||||
export const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
header: css`
|
||||
label: header;
|
||||
@ -80,7 +82,7 @@ export const getStyles = createStyle((theme: Theme) => {
|
||||
padding: 0 0.2em;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type AccordianKeyValuesProps = {
|
||||
className?: string | TNil;
|
||||
@ -96,7 +98,7 @@ type AccordianKeyValuesProps = {
|
||||
// export for tests
|
||||
export function KeyValuesSummary(props: { data?: TraceKeyValuePair[] }) {
|
||||
const { data } = props;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
if (!Array.isArray(data) || !data.length) {
|
||||
return null;
|
||||
@ -123,7 +125,7 @@ KeyValuesSummary.defaultProps = {
|
||||
export default function AccordianKeyValues(props: AccordianKeyValuesProps) {
|
||||
const { className, data, highContrast, interactive, isOpen, label, linksGetter, onToggle } = props;
|
||||
const isEmpty = !Array.isArray(data) || !data.length;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
const iconCls = cx(uAlignIcon, { [styles.emptyIcon]: isEmpty });
|
||||
let arrow: React.ReactNode | null = null;
|
||||
let headerProps: {} | null = null;
|
||||
|
@ -17,15 +17,17 @@ import { sortBy as _sortBy } from 'lodash';
|
||||
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
|
||||
import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right';
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import AccordianKeyValues from './AccordianKeyValues';
|
||||
import { formatDuration } from '../utils';
|
||||
import { TNil } from '../../types';
|
||||
import { TraceLog, TraceKeyValuePair, TraceLink } from '../../types/trace';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { uAlignIcon, ubMb1 } from '../../uberUtilityStyles';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
AccordianLogs: css`
|
||||
label: AccordianLogs;
|
||||
@ -54,7 +56,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
color: ${autoColor(theme, '#999')};
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type AccordianLogsProps = {
|
||||
interactive?: boolean;
|
||||
@ -82,7 +84,7 @@ export default function AccordianLogs(props: AccordianLogsProps) {
|
||||
};
|
||||
}
|
||||
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={styles.AccordianLogs}>
|
||||
<HeaderComponent className={styles.AccordianLogsHeader} {...headerProps}>
|
||||
|
@ -15,16 +15,15 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
|
||||
import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right';
|
||||
import { TraceSpanReference } from '../../types/trace';
|
||||
import ReferenceLink from '../../url/ReferenceLink';
|
||||
|
||||
import { createStyle } from '../../Theme';
|
||||
import { uAlignIcon } from '../../uberUtilityStyles';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
ReferencesList: css`
|
||||
background: #fff;
|
||||
@ -63,7 +62,7 @@ const getStyles = createStyle(() => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type AccordianReferencesProps = {
|
||||
data: TraceSpanReference[];
|
||||
@ -82,7 +81,7 @@ type ReferenceItemProps = {
|
||||
// export for test
|
||||
export function References(props: ReferenceItemProps) {
|
||||
const { data, focusSpan } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
return (
|
||||
<div className={cx(styles.ReferencesList)}>
|
||||
|
@ -17,13 +17,16 @@ import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
|
||||
import IoIosArrowRight from 'react-icons/lib/io/ios-arrow-right';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import TextList from './TextList';
|
||||
import { TNil } from '../../types';
|
||||
import { getStyles as getAccordianKeyValuesStyles } from './AccordianKeyValues';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { uAlignIcon } from '../../uberUtilityStyles';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
header: css`
|
||||
cursor: pointer;
|
||||
@ -36,7 +39,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type AccordianTextProps = {
|
||||
className?: string | TNil;
|
||||
@ -66,7 +69,7 @@ export default function AccordianText(props: AccordianTextProps) {
|
||||
TextComponent = DefaultTextComponent,
|
||||
} = props;
|
||||
const isEmpty = !Array.isArray(data) || !data.length;
|
||||
const accordianKeyValuesStyles = getAccordianKeyValuesStyles(useTheme());
|
||||
const accordianKeyValuesStyles = useStyles2(getAccordianKeyValuesStyles);
|
||||
const iconCls = cx(uAlignIcon, { [accordianKeyValuesStyles.emptyIcon]: isEmpty });
|
||||
let arrow: React.ReactNode | null = null;
|
||||
let headerProps: {} | null = null;
|
||||
@ -78,7 +81,7 @@ export default function AccordianText(props: AccordianTextProps) {
|
||||
role: 'switch',
|
||||
};
|
||||
}
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={className || ''}>
|
||||
<div className={cx(styles.header, headerClassName)} {...headerProps} data-test-id="AccordianText--header">
|
||||
|
@ -14,13 +14,13 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import CopyIcon from '../../common/CopyIcon';
|
||||
|
||||
import KeyValuesTable, { LinkValue, getStyles } from './KeyValuesTable';
|
||||
import { UIDropdown, UIIcon } from '../../uiElementsContext';
|
||||
import { ubInlineBlock } from '../../uberUtilityStyles';
|
||||
import { defaultTheme } from '../../Theme';
|
||||
|
||||
describe('LinkValue', () => {
|
||||
const title = 'titleValue';
|
||||
@ -39,7 +39,7 @@ describe('LinkValue', () => {
|
||||
});
|
||||
|
||||
it('renders correct Icon', () => {
|
||||
const styles = getStyles(defaultTheme);
|
||||
const styles = getStyles(createTheme());
|
||||
expect(wrapper.find(UIIcon).hasClass(styles.linkIcon)).toBe(true);
|
||||
expect(wrapper.find(UIIcon).prop('type')).toBe('export');
|
||||
});
|
||||
|
@ -16,18 +16,19 @@ import * as React from 'react';
|
||||
import jsonMarkup from 'json-markup';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import CopyIcon from '../../common/CopyIcon';
|
||||
|
||||
import { TNil } from '../../types';
|
||||
import { TraceKeyValuePair, TraceLink } from '../../types/trace';
|
||||
import { UIDropdown, UIIcon, UIMenu, UIMenuItem } from '../../uiElementsContext';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { ubInlineBlock, uWidth100 } from '../../uberUtilityStyles';
|
||||
|
||||
const copyIconClassName = 'copyIcon';
|
||||
|
||||
export const getStyles = createStyle((theme: Theme) => {
|
||||
export const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
KeyValueTable: css`
|
||||
label: KeyValueTable;
|
||||
@ -71,7 +72,7 @@ export const getStyles = createStyle((theme: Theme) => {
|
||||
font-weight: bold;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const jsonObjectOrArrayStartRegex = /^(\[|\{)/;
|
||||
|
||||
@ -88,7 +89,7 @@ function parseIfComplexJson(value: any) {
|
||||
}
|
||||
|
||||
export const LinkValue = (props: { href: string; title?: string; children: React.ReactNode }) => {
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<a href={props.href} title={props.title} target="_blank" rel="noopener noreferrer">
|
||||
{props.children} <UIIcon className={styles.linkIcon} type="export" />
|
||||
@ -118,7 +119,7 @@ type KeyValuesTableProps = {
|
||||
|
||||
export default function KeyValuesTable(props: KeyValuesTableProps) {
|
||||
const { data, linksGetter } = props;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={cx(styles.KeyValueTable)} data-test-id="KeyValueTable">
|
||||
<table className={uWidth100}>
|
||||
|
@ -15,10 +15,9 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { createStyle } from '../../Theme';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
TextList: css`
|
||||
max-height: 450px;
|
||||
@ -38,7 +37,7 @@ const getStyles = createStyle(() => {
|
||||
}
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TextListProps = {
|
||||
data: string[];
|
||||
@ -46,7 +45,7 @@ type TextListProps = {
|
||||
|
||||
export default function TextList(props: TextListProps) {
|
||||
const { data } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={cx(styles.TextList)} data-test-id="TextList">
|
||||
<ul className={styles.List}>
|
||||
|
@ -15,6 +15,8 @@
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { DataLinkButton, TextArea, useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import AccordianKeyValues from './AccordianKeyValues';
|
||||
import AccordianLogs from './AccordianLogs';
|
||||
@ -23,16 +25,14 @@ import DetailState from './DetailState';
|
||||
import { formatDuration } from '../utils';
|
||||
import CopyIcon from '../../common/CopyIcon';
|
||||
import LabeledList from '../../common/LabeledList';
|
||||
|
||||
import { SpanLinkFunc, TNil } from '../../types';
|
||||
import { TraceKeyValuePair, TraceLink, TraceLog, TraceSpan } from '../../types/trace';
|
||||
import AccordianReferences from './AccordianReferences';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { UIDivider } from '../../uiElementsContext';
|
||||
import { ubFlex, ubFlexAuto, ubItemsCenter, ubM0, ubMb1, ubMy1, ubTxRightAlign } from '../../uberUtilityStyles';
|
||||
import { DataLinkButton, TextArea } from '@grafana/ui';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
divider: css`
|
||||
label: divider;
|
||||
@ -100,7 +100,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
white-space: pre;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type SpanDetailProps = {
|
||||
detailState: DetailState;
|
||||
@ -172,7 +172,7 @@ export default function SpanDetail(props: SpanDetailProps) {
|
||||
},
|
||||
];
|
||||
const deepLinkCopyText = `${window.location.origin}${window.location.pathname}?uiFind=${spanID}`;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
const link = createSpanLink?.(span);
|
||||
|
||||
return (
|
||||
|
@ -14,8 +14,9 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import SpanDetailRow from './SpanDetailRow';
|
||||
import { UnthemedSpanDetailRow } from './SpanDetailRow';
|
||||
import SpanDetail from './SpanDetail';
|
||||
import DetailState from './SpanDetail/DetailState';
|
||||
import SpanTreeOffset from './SpanTreeOffset';
|
||||
@ -37,6 +38,7 @@ describe('<SpanDetailRow>', () => {
|
||||
span: { spanID, depth: 3 },
|
||||
tagsToggle: jest.fn(),
|
||||
traceStartTime: 1000,
|
||||
theme: createTheme(),
|
||||
};
|
||||
|
||||
let wrapper;
|
||||
@ -48,10 +50,7 @@ describe('<SpanDetailRow>', () => {
|
||||
props.logsToggle.mockReset();
|
||||
props.processToggle.mockReset();
|
||||
props.tagsToggle.mockReset();
|
||||
wrapper = shallow(<SpanDetailRow {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
wrapper = shallow(<UnthemedSpanDetailRow {...props} />);
|
||||
});
|
||||
|
||||
it('renders without exploding', () => {
|
||||
|
@ -19,12 +19,14 @@ import SpanDetail from './SpanDetail';
|
||||
import DetailState from './SpanDetail/DetailState';
|
||||
import SpanTreeOffset from './SpanTreeOffset';
|
||||
import TimelineRow from './TimelineRow';
|
||||
import { autoColor, createStyle, Theme, withTheme } from '../Theme';
|
||||
import { autoColor } from '../Theme';
|
||||
import { stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { TraceLog, TraceSpan, TraceKeyValuePair, TraceLink } from '../types/trace';
|
||||
import { SpanLinkFunc } from '../types';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
expandedAccent: css`
|
||||
cursor: pointer;
|
||||
@ -85,7 +87,7 @@ type SpanDetailRowProps = {
|
||||
hoverIndentGuideIds: Set<string>;
|
||||
addHoverIndentGuideId: (spanID: string) => void;
|
||||
removeHoverIndentGuideId: (spanID: string) => void;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
createSpanLink?: SpanLinkFunc;
|
||||
};
|
||||
|
||||
@ -166,4 +168,4 @@ export class UnthemedSpanDetailRow extends React.PureComponent<SpanDetailRowProp
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedSpanDetailRow);
|
||||
export default withTheme2(UnthemedSpanDetailRow);
|
||||
|
@ -16,10 +16,10 @@ import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import IoChevronRight from 'react-icons/lib/io/chevron-right';
|
||||
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import SpanTreeOffset, { getStyles } from './SpanTreeOffset';
|
||||
import spanAncestorIdsSpy from '../utils/span-ancestor-ids';
|
||||
import { defaultTheme } from '../Theme';
|
||||
|
||||
jest.mock('../utils/span-ancestor-ids');
|
||||
|
||||
@ -44,7 +44,6 @@ describe('SpanTreeOffset', () => {
|
||||
},
|
||||
};
|
||||
wrapper = shallow(<SpanTreeOffset {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
});
|
||||
@ -53,7 +52,6 @@ describe('SpanTreeOffset', () => {
|
||||
it('renders only one .SpanTreeOffset--indentGuide for entire trace if span has no ancestors', () => {
|
||||
spanAncestorIdsSpy.mockReturnValue([]);
|
||||
wrapper = shallow(<SpanTreeOffset {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
const indentGuides = wrapper.find('[data-test-id="SpanTreeOffset--indentGuide"]');
|
||||
@ -72,10 +70,9 @@ describe('SpanTreeOffset', () => {
|
||||
it('adds .is-active to correct indentGuide', () => {
|
||||
props.hoverIndentGuideIds = new Set([parentSpanID]);
|
||||
wrapper = shallow(<SpanTreeOffset {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
const styles = getStyles(defaultTheme);
|
||||
const styles = getStyles(createTheme());
|
||||
const activeIndentGuide = wrapper.find(`.${styles.indentGuideActive}`);
|
||||
expect(activeIndentGuide.length).toBe(1);
|
||||
expect(activeIndentGuide.prop('data-ancestor-id')).toBe(parentSpanID);
|
||||
|
@ -18,13 +18,14 @@ import IoChevronRight from 'react-icons/lib/io/chevron-right';
|
||||
import IoIosArrowDown from 'react-icons/lib/io/ios-arrow-down';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
|
||||
import { TraceSpan } from '../types/trace';
|
||||
import spanAncestorIds from '../utils/span-ancestor-ids';
|
||||
import { autoColor } from '../Theme';
|
||||
|
||||
import { autoColor, createStyle, Theme, withTheme } from '../Theme';
|
||||
|
||||
export const getStyles = createStyle((theme: Theme) => {
|
||||
export const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
SpanTreeOffset: css`
|
||||
label: SpanTreeOffset;
|
||||
@ -74,7 +75,7 @@ type TProps = {
|
||||
hoverIndentGuideIds: Set<string>;
|
||||
addHoverIndentGuideId: (spanID: string) => void;
|
||||
removeHoverIndentGuideId: (spanID: string) => void;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
};
|
||||
|
||||
export class UnthemedSpanTreeOffset extends React.PureComponent<TProps> {
|
||||
@ -167,4 +168,4 @@ export class UnthemedSpanTreeOffset extends React.PureComponent<TProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedSpanTreeOffset);
|
||||
export default withTheme2(UnthemedSpanTreeOffset);
|
||||
|
@ -15,12 +15,14 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { formatDuration } from './utils';
|
||||
import { TNil } from '../types';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../Theme';
|
||||
import { autoColor } from '../Theme';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
Ticks: css`
|
||||
label: Ticks;
|
||||
@ -47,7 +49,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
right: 0.25rem;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TicksProps = {
|
||||
endTime?: number | TNil;
|
||||
@ -68,7 +70,7 @@ export default function Ticks(props: TicksProps) {
|
||||
labels.push(formatDuration(durationAtTick));
|
||||
}
|
||||
}
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
const ticks: React.ReactNode[] = [];
|
||||
for (let i = 0; i < numTicks; i++) {
|
||||
const portion = i / (numTicks - 1);
|
||||
|
@ -12,12 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { IconButton } from '@grafana/ui';
|
||||
import { IconButton, useStyles2 } from '@grafana/ui';
|
||||
import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
import { createStyle } from '../../Theme';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
TimelineCollapser: css`
|
||||
align-items: center;
|
||||
@ -27,7 +26,7 @@ const getStyles = createStyle(() => {
|
||||
margin-right: 0.5rem;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type CollapserProps = {
|
||||
onCollapseAll: () => void;
|
||||
@ -38,7 +37,7 @@ type CollapserProps = {
|
||||
|
||||
export function TimelineCollapser(props: CollapserProps) {
|
||||
const { onExpandAll, onExpandOne, onCollapseAll, onCollapseOne } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={styles.TimelineCollapser} data-test-id="TimelineCollapser">
|
||||
<IconButton tooltip="Expand +1" size="xl" tooltipPlacement="top" name="angle-down" onClick={onExpandOne} />
|
||||
|
@ -15,12 +15,12 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { stylesFactory } from '@grafana/ui';
|
||||
|
||||
import { TNil } from '../../types';
|
||||
import DraggableManager, { DraggableBounds, DraggingUpdate } from '../../utils/DraggableManager';
|
||||
import { createStyle } from '../../Theme';
|
||||
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
TimelineColumnResizer: css`
|
||||
left: 0;
|
||||
|
@ -15,6 +15,8 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { TimelineCollapser } from './TimelineCollapser';
|
||||
import TimelineColumnResizer from './TimelineColumnResizer';
|
||||
@ -22,10 +24,10 @@ import TimelineViewingLayer from './TimelineViewingLayer';
|
||||
import Ticks from '../Ticks';
|
||||
import TimelineRow from '../TimelineRow';
|
||||
import { TUpdateViewRangeTimeFunction, ViewRangeTime, ViewRangeTimeUpdate } from '../types';
|
||||
import { autoColor, createStyle, Theme, useTheme } from '../../Theme';
|
||||
import { autoColor } from '../../Theme';
|
||||
import { ubFlex, ubPx2 } from '../../uberUtilityStyles';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
TimelineHeaderRow: css`
|
||||
label: TimelineHeaderRow;
|
||||
@ -50,7 +52,7 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
align-items: center;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TimelineHeaderRowProps = {
|
||||
duration: number;
|
||||
@ -83,7 +85,7 @@ export default function TimelineHeaderRow(props: TimelineHeaderRowProps) {
|
||||
columnResizeHandleHeight,
|
||||
} = props;
|
||||
const [viewStart, viewEnd] = viewRangeTime.current;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<TimelineRow className={styles.TimelineHeaderRow} data-test-id="TimelineHeaderRow">
|
||||
<TimelineRow.Cell className={cx(ubFlex, ubPx2, styles.TimelineHeaderWrapper)} width={nameColumnWidth}>
|
||||
|
@ -14,14 +14,13 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { css, cx } from '@emotion/css';
|
||||
|
||||
import { stylesFactory } from '@grafana/ui';
|
||||
import { TUpdateViewRangeTimeFunction, ViewRangeTime, ViewRangeTimeUpdate } from '../types';
|
||||
import { TNil } from '../../types';
|
||||
import DraggableManager, { DraggableBounds, DraggingUpdate } from '../../utils/DraggableManager';
|
||||
import { createStyle } from '../../Theme';
|
||||
|
||||
// exported for testing
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
TimelineViewingLayer: css`
|
||||
label: TimelineViewingLayer;
|
||||
|
@ -15,10 +15,10 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { createStyle } from '../Theme';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { ubRelative } from '../uberUtilityStyles';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
flexRow: css`
|
||||
display: flex;
|
||||
@ -26,7 +26,7 @@ const getStyles = createStyle(() => {
|
||||
flex-direction: row;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type TTimelineRowProps = {
|
||||
children: React.ReactNode;
|
||||
@ -42,7 +42,7 @@ interface TimelineRowCellProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
|
||||
export default function TimelineRow(props: TTimelineRowProps) {
|
||||
const { children, className = '', ...rest } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<div className={cx(styles.flexRow, className)} {...rest}>
|
||||
{children}
|
||||
|
@ -90,7 +90,6 @@ describe('<VirtualizedTraceViewImpl>', () => {
|
||||
}
|
||||
});
|
||||
wrapper = shallow(<VirtualizedTraceView {...props} />)
|
||||
.dive()
|
||||
.dive()
|
||||
.dive();
|
||||
instance = wrapper.instance();
|
||||
|
@ -17,6 +17,9 @@ import { css } from '@emotion/css';
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import { stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import ListView from './ListView';
|
||||
import SpanBarRow from './SpanBarRow';
|
||||
import DetailState from './SpanDetail/DetailState';
|
||||
@ -36,13 +39,11 @@ import { TraceLog, TraceSpan, Trace, TraceKeyValuePair, TraceLink } from '../typ
|
||||
import TTraceTimeline from '../types/TTraceTimeline';
|
||||
import { PEER_SERVICE } from '../constants/tag-keys';
|
||||
|
||||
import { createStyle, Theme, withTheme } from '../Theme';
|
||||
|
||||
type TExtractUiFindFromStateReturn = {
|
||||
uiFind: string | undefined;
|
||||
};
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
rowsWrapper: css`
|
||||
width: 100%;
|
||||
@ -82,7 +83,7 @@ type TVirtualizedTraceViewOwnProps = {
|
||||
hoverIndentGuideIds: Set<string>;
|
||||
addHoverIndentGuideId: (spanID: string) => void;
|
||||
removeHoverIndentGuideId: (spanID: string) => void;
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
createSpanLink?: SpanLinkFunc;
|
||||
scrollElement?: Element;
|
||||
};
|
||||
@ -486,4 +487,4 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedVirtualizedTraceView);
|
||||
export default withTheme2(UnthemedVirtualizedTraceView);
|
||||
|
@ -14,12 +14,12 @@
|
||||
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
import TraceTimelineViewer from './index';
|
||||
import traceGenerator from '../demo/trace-generators';
|
||||
import transformTraceData from '../model/transform-trace-data';
|
||||
import TimelineHeaderRow from './TimelineHeaderRow';
|
||||
import { defaultTheme } from '../Theme';
|
||||
|
||||
describe('<TraceTimelineViewer>', () => {
|
||||
const trace = transformTraceData(traceGenerator.trace({}));
|
||||
@ -38,7 +38,7 @@ describe('<TraceTimelineViewer>', () => {
|
||||
collapseAll: jest.fn(),
|
||||
expandOne: jest.fn(),
|
||||
collapseOne: jest.fn(),
|
||||
theme: defaultTheme,
|
||||
theme: createTheme(),
|
||||
history: {
|
||||
replace: () => {},
|
||||
},
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
import React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { stylesFactory, withTheme2 } from '@grafana/ui';
|
||||
|
||||
import TimelineHeaderRow from './TimelineHeaderRow';
|
||||
import VirtualizedTraceView from './VirtualizedTraceView';
|
||||
@ -23,14 +25,14 @@ import { TUpdateViewRangeTimeFunction, ViewRange, ViewRangeTimeUpdate } from './
|
||||
import { SpanLinkFunc, TNil } from '../types';
|
||||
import { TraceSpan, Trace, TraceLog, TraceKeyValuePair, TraceLink } from '../types/trace';
|
||||
import TTraceTimeline from '../types/TTraceTimeline';
|
||||
import { autoColor, createStyle, Theme, withTheme } from '../Theme';
|
||||
import { autoColor } from '../Theme';
|
||||
import ExternalLinkContext from '../url/externalLinkContext';
|
||||
|
||||
type TExtractUiFindFromStateReturn = {
|
||||
uiFind: string | undefined;
|
||||
};
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
return {
|
||||
TraceTimelineViewer: css`
|
||||
label: TraceTimelineViewer;
|
||||
@ -98,7 +100,7 @@ type TProps = TExtractUiFindFromStateReturn & {
|
||||
addHoverIndentGuideId: (spanID: string) => void;
|
||||
removeHoverIndentGuideId: (spanID: string) => void;
|
||||
linksGetter: (span: TraceSpan, items: TraceKeyValuePair[], itemIndex: number) => TraceLink[];
|
||||
theme: Theme;
|
||||
theme: GrafanaTheme2;
|
||||
createSpanLink?: SpanLinkFunc;
|
||||
scrollElement?: Element;
|
||||
};
|
||||
@ -193,4 +195,4 @@ export class UnthemedTraceTimelineViewer extends React.PureComponent<TProps, Sta
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(UnthemedTraceTimelineViewer);
|
||||
export default withTheme2(UnthemedTraceTimelineViewer);
|
||||
|
@ -14,10 +14,9 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { createStyle } from '../Theme';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
return {
|
||||
BreakableText: css`
|
||||
label: BreakableText;
|
||||
@ -25,7 +24,7 @@ const getStyles = createStyle(() => {
|
||||
white-space: pre;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const WORD_RX = /\W*\w+\W*/g;
|
||||
|
||||
@ -41,6 +40,7 @@ export default function BreakableText(
|
||||
props: Props
|
||||
): any /* React.ReactNode /* React.ReactElement | React.ReactElement[] \*\/ */ {
|
||||
const { className, text, wordRegexp = WORD_RX } = props;
|
||||
const styles = useStyles2(getStyles);
|
||||
if (!text) {
|
||||
return typeof text === 'string' ? text : null;
|
||||
}
|
||||
@ -50,7 +50,7 @@ export default function BreakableText(
|
||||
let match: RegExpExecArray | string[] | null = wordRegexp.exec(text) || [text];
|
||||
while (match) {
|
||||
spans.push(
|
||||
<span key={`${text}-${spans.length}`} className={className || getStyles().BreakableText}>
|
||||
<span key={`${text}-${spans.length}`} className={className || styles.BreakableText}>
|
||||
{match[0]}
|
||||
</span>
|
||||
);
|
||||
|
@ -16,11 +16,11 @@ import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { stylesFactory } from '@grafana/ui';
|
||||
|
||||
import { UITooltip, TooltipPlacement, UIButton } from '../uiElementsContext';
|
||||
import { createStyle } from '../Theme';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = stylesFactory(() => {
|
||||
return {
|
||||
CopyIcon: css`
|
||||
background-color: transparent;
|
||||
|
@ -15,11 +15,12 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { createStyle, isLight, Theme, useTheme } from '../Theme';
|
||||
import { UIDivider } from '../uiElementsContext';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
LabeledList: css`
|
||||
label: LabeledList;
|
||||
@ -33,11 +34,11 @@ const getStyles = createStyle((theme: Theme) => {
|
||||
`,
|
||||
LabeledListLabel: css`
|
||||
label: LabeledListLabel;
|
||||
color: ${isLight(theme) ? '#999' : '#666'};
|
||||
color: ${theme.isLight ? '#999' : '#666'};
|
||||
margin-right: 0.25rem;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type LabeledListProps = {
|
||||
className?: string;
|
||||
@ -47,7 +48,7 @@ type LabeledListProps = {
|
||||
|
||||
export default function LabeledList(props: LabeledListProps) {
|
||||
const { className, dividerClassName, items } = props;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
return (
|
||||
<ul className={cx(styles.LabeledList, className)}>
|
||||
{items.map(({ key, label, value }, i) => {
|
||||
|
@ -15,11 +15,11 @@
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
import { css, keyframes } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { createStyle } from '../Theme';
|
||||
import { UIIcon } from '../uiElementsContext';
|
||||
|
||||
const getStyles = createStyle(() => {
|
||||
const getStyles = () => {
|
||||
const LoadingIndicatorColorAnim = keyframes`
|
||||
/*
|
||||
rgb(0, 128, 128) == teal
|
||||
@ -52,7 +52,7 @@ const getStyles = createStyle(() => {
|
||||
font-size: 0.7em;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type LoadingIndicatorProps = {
|
||||
centered?: boolean;
|
||||
@ -62,7 +62,7 @@ type LoadingIndicatorProps = {
|
||||
|
||||
export default function LoadingIndicator(props: LoadingIndicatorProps) {
|
||||
const { centered, className, small, ...rest } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
const cls = cx(styles.LoadingIndicator, {
|
||||
[styles.LoadingIndicatorCentered]: centered,
|
||||
[styles.LoadingIndicatorSmall]: small,
|
||||
|
@ -16,17 +16,16 @@ import React from 'react';
|
||||
import cx from 'classnames';
|
||||
import IoAndroidOpen from 'react-icons/lib/io/android-open';
|
||||
import { css } from '@emotion/css';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { createStyle } from '../Theme';
|
||||
|
||||
export const getStyles = createStyle(() => {
|
||||
export const getStyles = () => {
|
||||
return {
|
||||
NewWindowIconLarge: css`
|
||||
label: NewWindowIconLarge;
|
||||
font-size: 1.5em;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type Props = {
|
||||
isLarge?: boolean;
|
||||
@ -35,7 +34,7 @@ type Props = {
|
||||
|
||||
export default function NewWindowIcon(props: Props) {
|
||||
const { isLarge, className, ...rest } = props;
|
||||
const styles = getStyles();
|
||||
const styles = useStyles2(getStyles);
|
||||
const cls = cx({ [styles.NewWindowIconLarge]: isLarge }, className);
|
||||
return <IoAndroidOpen className={cls} {...rest} />;
|
||||
}
|
||||
|
@ -15,27 +15,27 @@
|
||||
import * as React from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import cx from 'classnames';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import BreakableText from './BreakableText';
|
||||
import LoadingIndicator from './LoadingIndicator';
|
||||
import { fetchedState, FALLBACK_TRACE_NAME } from '../constants';
|
||||
|
||||
import { FetchedState, TNil } from '../types';
|
||||
import { ApiError } from '../types/api-error';
|
||||
import { createStyle, safeSize, Theme, useTheme } from '../Theme';
|
||||
|
||||
const getStyles = createStyle((theme: Theme) => {
|
||||
const getStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
TraceName: css`
|
||||
label: TraceName;
|
||||
font-size: ${safeSize(theme.components?.TraceName?.fontSize, 'unset')};
|
||||
font-size: ${theme.typography.size.lg};
|
||||
`,
|
||||
TraceNameError: css`
|
||||
label: TraceNameError;
|
||||
color: #c00;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
type Props = {
|
||||
className?: string;
|
||||
@ -48,7 +48,7 @@ export default function TraceName(props: Props) {
|
||||
const { className, error, state, traceName } = props;
|
||||
const isErred = state === fetchedState.ERROR;
|
||||
let title: string | React.ReactNode = traceName || FALLBACK_TRACE_NAME;
|
||||
const styles = getStyles(useTheme());
|
||||
const styles = useStyles2(getStyles);
|
||||
let errorCssClass = '';
|
||||
if (isErred) {
|
||||
errorCssClass = styles.TraceNameError;
|
||||
|
@ -13,26 +13,26 @@
|
||||
// limitations under the License.
|
||||
|
||||
import { getColorByKey, clear } from './color-generator';
|
||||
import { defaultTheme } from '../Theme';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
it('gives the same color for the same key', () => {
|
||||
clear();
|
||||
const colorOne = getColorByKey('serviceA', defaultTheme);
|
||||
const colorTwo = getColorByKey('serviceA', defaultTheme);
|
||||
const colorOne = getColorByKey('serviceA', createTheme());
|
||||
const colorTwo = getColorByKey('serviceA', createTheme());
|
||||
expect(colorOne).toBe(colorTwo);
|
||||
});
|
||||
|
||||
it('gives different colors for each for each key', () => {
|
||||
clear();
|
||||
const colorOne = getColorByKey('serviceA', defaultTheme);
|
||||
const colorTwo = getColorByKey('serviceB', defaultTheme);
|
||||
const colorOne = getColorByKey('serviceA', createTheme());
|
||||
const colorTwo = getColorByKey('serviceB', createTheme());
|
||||
expect(colorOne).not.toBe(colorTwo);
|
||||
});
|
||||
|
||||
it('should clear cache', () => {
|
||||
clear();
|
||||
const colorOne = getColorByKey('serviceA', defaultTheme);
|
||||
const colorOne = getColorByKey('serviceA', createTheme());
|
||||
clear();
|
||||
const colorTwo = getColorByKey('serviceB', defaultTheme);
|
||||
const colorTwo = getColorByKey('serviceB', createTheme());
|
||||
expect(colorOne).toBe(colorTwo);
|
||||
});
|
||||
|
@ -12,8 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Theme } from '../Theme';
|
||||
import memoizeOne from 'memoize-one';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { colors } from '@grafana/ui';
|
||||
|
||||
// TS needs the precise return type
|
||||
function strToRgb(s: string): [number, number, number] {
|
||||
@ -83,10 +84,10 @@ export function clear() {
|
||||
getGenerator([]);
|
||||
}
|
||||
|
||||
export function getColorByKey(key: string, theme: Theme) {
|
||||
return getGenerator(theme.servicesColorPalette).getColorByKey(key);
|
||||
export function getColorByKey(key: string, theme: GrafanaTheme2) {
|
||||
return getGenerator(colors).getColorByKey(key);
|
||||
}
|
||||
|
||||
export function getRgbColorByKey(key: string, theme: Theme): [number, number, number] {
|
||||
return getGenerator(theme.servicesColorPalette).getRgbColorByKey(key);
|
||||
export function getRgbColorByKey(key: string, theme: GrafanaTheme2): [number, number, number] {
|
||||
return getGenerator(colors).getRgbColorByKey(key);
|
||||
}
|
||||
|
Reference in New Issue
Block a user