mirror of https://github.com/grafana/grafana
Transforms: Adds beta notice and updates transform descriptions (#24158)
* Transforms: Adds beta notice and updates transform descriptions * Rename organize fields * Webpack - enable images import * Introduce FeatureState type * Alow Container component grow/shrink config * Enable svg import in main app * Jest + webpack for svgs * InfoBox refactor (+ added feature info box), Badge component introduced * Update packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx Co-authored-by: Carl Bergquist <carl@grafana.com> * Minor fixes * Update packages/grafana-ui/src/components/TransformersUI/OrganizeFieldsTransformerEditor.tsx Co-authored-by: Carl Bergquist <carl@grafana.com> * Update packages/grafana-ui/src/components/TransformersUI/SeriesToFieldsTransformerEditor.tsx Co-authored-by: Carl Bergquist <carl@grafana.com> * fix typo * Build storybook fixed * Fix padding Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com> Co-authored-by: Carl Bergquist <carl@grafana.com>pull/24235/head
parent
0fe9e7e242
commit
92a16d2e10
@ -0,0 +1,9 @@ |
||||
/** |
||||
* Enumeration of documentation topics |
||||
* @internal |
||||
*/ |
||||
export enum DocsId { |
||||
Transformations, |
||||
FieldConfig, |
||||
FieldConfigOverrides, |
||||
} |
@ -0,0 +1,35 @@ |
||||
import React from 'react'; |
||||
import { boolean, text, select } from '@storybook/addon-knobs'; |
||||
import { Badge, BadgeColor } from './Badge'; |
||||
|
||||
export default { |
||||
title: 'Other/Badge', |
||||
component: Badge, |
||||
decorators: [], |
||||
parameters: { |
||||
docs: {}, |
||||
}, |
||||
}; |
||||
|
||||
export const basic = () => { |
||||
const badgeColor = select<BadgeColor>( |
||||
'Badge color', |
||||
{ |
||||
Red: 'red', |
||||
Green: 'green', |
||||
Blue: 'blue', |
||||
Orange: 'orange', |
||||
}, |
||||
'blue' |
||||
); |
||||
const withIcon = boolean('With icon', true); |
||||
const tooltipText = text('Tooltip text', ''); |
||||
return ( |
||||
<Badge |
||||
text={'Badge label'} |
||||
color={badgeColor} |
||||
icon={withIcon ? 'rocket' : undefined} |
||||
tooltip={tooltipText.trim() === '' ? undefined : tooltipText} |
||||
/> |
||||
); |
||||
}; |
@ -0,0 +1,90 @@ |
||||
import React from 'react'; |
||||
import { Icon } from '../Icon/Icon'; |
||||
import { useTheme } from '../../themes/ThemeContext'; |
||||
import { stylesFactory } from '../../themes/stylesFactory'; |
||||
import { IconName } from '../../types'; |
||||
import { Tooltip } from '../Tooltip/Tooltip'; |
||||
import { getColorFromHexRgbOrName, GrafanaTheme } from '@grafana/data'; |
||||
import tinycolor from 'tinycolor2'; |
||||
import { css } from 'emotion'; |
||||
import { HorizontalGroup } from '..'; |
||||
|
||||
export type BadgeColor = 'blue' | 'red' | 'green' | 'orange'; |
||||
|
||||
export interface BadgeProps { |
||||
text: string; |
||||
color: BadgeColor; |
||||
icon?: IconName; |
||||
tooltip?: string; |
||||
} |
||||
|
||||
export const Badge = React.memo<BadgeProps>(({ icon, color, text, tooltip }) => { |
||||
const theme = useTheme(); |
||||
const styles = getStyles(theme, color); |
||||
const badge = ( |
||||
<div className={styles.wrapper}> |
||||
<HorizontalGroup align="center" spacing="xs"> |
||||
{icon && <Icon name={icon} size="sm" />} |
||||
<span>{text}</span> |
||||
</HorizontalGroup> |
||||
</div> |
||||
); |
||||
|
||||
return tooltip ? ( |
||||
<Tooltip content={tooltip} placement="auto"> |
||||
{badge} |
||||
</Tooltip> |
||||
) : ( |
||||
badge |
||||
); |
||||
}); |
||||
|
||||
Badge.displayName = 'Badge'; |
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme, color: BadgeColor) => { |
||||
let sourceColor = getColorFromHexRgbOrName(color); |
||||
let borderColor = ''; |
||||
let bgColor = ''; |
||||
let textColor = ''; |
||||
|
||||
if (theme.isDark) { |
||||
bgColor = tinycolor(sourceColor) |
||||
.darken(38) |
||||
.toString(); |
||||
borderColor = tinycolor(sourceColor) |
||||
.darken(25) |
||||
.toString(); |
||||
textColor = tinycolor(sourceColor) |
||||
.lighten(45) |
||||
.toString(); |
||||
} else { |
||||
bgColor = tinycolor(sourceColor) |
||||
.lighten(30) |
||||
.toString(); |
||||
borderColor = tinycolor(sourceColor) |
||||
.lighten(15) |
||||
.toString(); |
||||
textColor = tinycolor(sourceColor) |
||||
.darken(40) |
||||
.toString(); |
||||
} |
||||
|
||||
return { |
||||
wrapper: css` |
||||
font-size: ${theme.typography.size.sm}; |
||||
display: inline-flex; |
||||
padding: 1px 4px; |
||||
border-radius: 3px; |
||||
margin-top: 6px; |
||||
background: ${bgColor}; |
||||
border: 1px solid ${borderColor}; |
||||
color: ${textColor}; |
||||
|
||||
> span { |
||||
position: relative; |
||||
top: 1px; |
||||
margin-left: 2px; |
||||
} |
||||
`,
|
||||
}; |
||||
}); |
@ -0,0 +1,63 @@ |
||||
import React from 'react'; |
||||
import { InfoBox, InfoBoxProps } from './InfoBox'; |
||||
import { FeatureState, GrafanaTheme } from '@grafana/data'; |
||||
import { stylesFactory, useTheme } from '../../themes'; |
||||
import { Badge, BadgeProps } from '../Badge/Badge'; |
||||
import { css } from 'emotion'; |
||||
|
||||
interface FeatureInfoBox extends Omit<InfoBoxProps, 'branded' | 'title' | 'urlTitle'> { |
||||
title: string; |
||||
featureState?: FeatureState; |
||||
} |
||||
export const FeatureInfoBox = React.memo( |
||||
React.forwardRef<HTMLDivElement, FeatureInfoBox>(({ title, featureState, ...otherProps }, ref) => { |
||||
const theme = useTheme(); |
||||
const styles = getFeatureInfoBoxStyles(theme); |
||||
|
||||
const titleEl = featureState ? ( |
||||
<> |
||||
<div className={styles.badge}> |
||||
<FeatureBadge featureState={featureState} /> |
||||
</div> |
||||
<h3>{title}</h3> |
||||
</> |
||||
) : ( |
||||
<h3>{title}</h3> |
||||
); |
||||
return <InfoBox branded title={titleEl} urlTitle="Read documentation" {...otherProps} />; |
||||
}) |
||||
); |
||||
|
||||
const getFeatureInfoBoxStyles = stylesFactory((theme: GrafanaTheme) => { |
||||
return { |
||||
badge: css` |
||||
margin-bottom: ${theme.spacing.sm}; |
||||
`,
|
||||
}; |
||||
}); |
||||
|
||||
interface FeatureBadgeProps { |
||||
featureState: FeatureState; |
||||
} |
||||
|
||||
export const FeatureBadge: React.FC<FeatureBadgeProps> = ({ featureState }) => { |
||||
const display = getPanelStateBadgeDisplayModel(featureState); |
||||
return <Badge text={display.text} color={display.color} icon={display.icon} />; |
||||
}; |
||||
|
||||
function getPanelStateBadgeDisplayModel(featureState: FeatureState): BadgeProps { |
||||
switch (featureState) { |
||||
case FeatureState.alpha: |
||||
return { |
||||
text: 'Alpha', |
||||
icon: 'exclamation-triangle', |
||||
color: 'orange', |
||||
}; |
||||
} |
||||
|
||||
return { |
||||
text: 'Beta', |
||||
icon: 'rocket', |
||||
color: 'blue', |
||||
}; |
||||
} |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,10 @@ |
||||
import { DocsId } from '@grafana/data'; |
||||
|
||||
// TODO: Documentation links
|
||||
const DOCS_LINKS: Record<DocsId, string> = { |
||||
[DocsId.Transformations]: 'https://docs.grafana.com', |
||||
[DocsId.FieldConfig]: 'https://docs.grafana.com', |
||||
[DocsId.FieldConfigOverrides]: 'https://docs.grafana.com', |
||||
}; |
||||
|
||||
export const getDocsLink = (id: DocsId) => DOCS_LINKS[id]; |
@ -0,0 +1,4 @@ |
||||
declare module '*.svg' { |
||||
const content: string; |
||||
export default content; |
||||
} |
@ -0,0 +1 @@ |
||||
export const svg = 'svg'; |
Loading…
Reference in new issue