mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Transformations: UX updates (#23574)
This commit is contained in:
@@ -78,6 +78,7 @@ export interface GrafanaThemeCommons {
|
||||
formLabelMargin: string;
|
||||
formValidationMessagePadding: string;
|
||||
formValidationMessageMargin: string;
|
||||
inlineFormMargin: string;
|
||||
};
|
||||
border: {
|
||||
radius: {
|
||||
|
||||
@@ -48,7 +48,7 @@ IconButton.displayName = 'IconButton';
|
||||
function getHoverColor(theme: GrafanaTheme, surface: SurfaceType): string {
|
||||
switch (surface) {
|
||||
case 'body':
|
||||
return theme.isLight ? theme.palette.gray95 : theme.palette.gray10;
|
||||
return theme.isLight ? theme.palette.gray95 : theme.palette.gray15;
|
||||
case 'panel':
|
||||
return theme.isLight ? theme.palette.gray6 : theme.palette.gray15;
|
||||
case 'header':
|
||||
|
||||
@@ -36,13 +36,22 @@ export const Layout: React.FC<LayoutProps> = ({
|
||||
return (
|
||||
<div className={styles.layout}>
|
||||
{React.Children.map(children, (child, index) => {
|
||||
return <div className={styles.buttonWrapper}>{child}</div>;
|
||||
return (
|
||||
<div className={styles.buttonWrapper} key={index}>
|
||||
{child}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const HorizontalGroup: React.FC<Omit<LayoutProps, 'orientation'>> = ({ children, spacing, justify, align }) => (
|
||||
export const HorizontalGroup: React.FC<Omit<LayoutProps, 'orientation'>> = ({
|
||||
children,
|
||||
spacing,
|
||||
justify,
|
||||
align = 'center',
|
||||
}) => (
|
||||
<Layout spacing={spacing} justify={justify} orientation={Orientation.Horizontal} align={align}>
|
||||
{children}
|
||||
</Layout>
|
||||
@@ -72,6 +81,9 @@ const getStyles = stylesFactory(
|
||||
buttonWrapper: css`
|
||||
margin-bottom: ${orientation === Orientation.Horizontal ? 0 : theme.spacing[spacing]};
|
||||
margin-right: ${orientation === Orientation.Horizontal ? theme.spacing[spacing] : 0};
|
||||
display: flex;
|
||||
align-items: ${align};
|
||||
height: 100%;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
||||
@@ -208,6 +208,7 @@ exports[`TimePicker renders buttons correctly 1`] = `
|
||||
"formValidationMessageMargin": "4px 0 0 0",
|
||||
"formValidationMessagePadding": "4px 8px",
|
||||
"gutter": "30px",
|
||||
"inlineFormMargin": "4px",
|
||||
"insetSquishMd": "4px 8px",
|
||||
"lg": "24px",
|
||||
"md": "16px",
|
||||
@@ -522,6 +523,7 @@ exports[`TimePicker renders content correctly after beeing open 1`] = `
|
||||
"formValidationMessageMargin": "4px 0 0 0",
|
||||
"formValidationMessagePadding": "4px 8px",
|
||||
"gutter": "30px",
|
||||
"inlineFormMargin": "4px",
|
||||
"insetSquishMd": "4px 8px",
|
||||
"lg": "24px",
|
||||
"md": "16px",
|
||||
|
||||
@@ -12,9 +12,8 @@ import {
|
||||
TransformerUIProps,
|
||||
} from '@grafana/data';
|
||||
import { stylesFactory, useTheme } from '../../themes';
|
||||
import { Button } from '../Button/Button';
|
||||
import { VerticalGroup } from '../Layout/Layout';
|
||||
import { Input } from '../Input/Input';
|
||||
import { IconButton } from '../IconButton/IconButton';
|
||||
|
||||
interface OrganizeFieldsTransformerEditorProps extends TransformerUIProps<OrganizeFieldsTransformerOptions> {}
|
||||
|
||||
@@ -73,7 +72,6 @@ const OrganizeFieldsTransformerEditor: React.FC<OrganizeFieldsTransformerEditorP
|
||||
);
|
||||
|
||||
return (
|
||||
<VerticalGroup>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId="sortable-fields-transformer" direction="vertical">
|
||||
{provided => (
|
||||
@@ -95,7 +93,6 @@ const OrganizeFieldsTransformerEditor: React.FC<OrganizeFieldsTransformerEditorP
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
</VerticalGroup>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -121,24 +118,25 @@ const DraggableFieldName: React.FC<DraggableFieldProps> = ({
|
||||
<Draggable draggableId={fieldName} index={index}>
|
||||
{provided => (
|
||||
<div
|
||||
className={styles.container}
|
||||
className="gf-form-inline"
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
>
|
||||
<div className={styles.left}>
|
||||
<div className="gf-form gf-form--grow">
|
||||
<div className="gf-form-label gf-form-label--justify-left width-30">
|
||||
<i className={cx('fa fa-ellipsis-v', styles.draggable)} />
|
||||
<Button
|
||||
<IconButton
|
||||
className={styles.toggle}
|
||||
variant="link"
|
||||
size="md"
|
||||
icon={visible ? 'eye' : 'eye-slash'}
|
||||
name={visible ? 'eye' : 'eye-slash'}
|
||||
surface="header"
|
||||
onClick={() => onToggleVisibility(fieldName, visible)}
|
||||
/>
|
||||
<span className={styles.name}>{fieldName}</span>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
<Input
|
||||
className="flex-grow-1"
|
||||
placeholder={`Rename ${fieldName}`}
|
||||
onChange={event => onRenameField(fieldName, event.currentTarget.value)}
|
||||
/>
|
||||
@@ -150,28 +148,17 @@ const DraggableFieldName: React.FC<DraggableFieldProps> = ({
|
||||
};
|
||||
|
||||
const getFieldNameStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
container: css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8px;
|
||||
`,
|
||||
left: css`
|
||||
width: 35%;
|
||||
padding: 0 8px;
|
||||
border-radius: 3px;
|
||||
background-color: ${theme.colors.bg2};
|
||||
`,
|
||||
right: css`
|
||||
width: 65%;
|
||||
margin-left: 8px;
|
||||
`,
|
||||
toggle: css`
|
||||
padding: 5px;
|
||||
margin: 0 5px;
|
||||
margin: 0 8px;
|
||||
color: ${theme.colors.textWeak};
|
||||
`,
|
||||
draggable: css`
|
||||
padding: 0 ${theme.spacing.xs};
|
||||
font-size: ${theme.typography.size.md};
|
||||
opacity: 0.4;
|
||||
&:hover {
|
||||
color: ${theme.colors.textStrong};
|
||||
}
|
||||
`,
|
||||
name: css`
|
||||
font-size: ${theme.typography.size.sm};
|
||||
|
||||
@@ -352,7 +352,7 @@ $variable-option-bg: $dropdownLinkBackgroundHover;
|
||||
$switch-bg: $input-bg;
|
||||
$switch-slider-color: $dark-3;
|
||||
$switch-slider-off-bg: $gray-1;
|
||||
$switch-slider-on-bg: ${theme.palette.blue77};
|
||||
$switch-slider-on-bg: ${theme.palette.blue95};
|
||||
$switch-slider-shadow: 0 0 3px black;
|
||||
|
||||
//Checkbox
|
||||
|
||||
@@ -102,6 +102,7 @@ const theme: GrafanaThemeCommons = {
|
||||
formLabelMargin: `0 0 ${SPACING_BASE / 2 + 'px'} 0`,
|
||||
formValidationMessagePadding: '4px 8px',
|
||||
formValidationMessageMargin: '4px 0 0 0',
|
||||
inlineFormMargin: '4px',
|
||||
},
|
||||
border: {
|
||||
radius: {
|
||||
|
||||
@@ -36,7 +36,7 @@ const basicColors = {
|
||||
const backgrounds = {
|
||||
bg1: basicColors.white,
|
||||
bg2: basicColors.gray97,
|
||||
bg3: basicColors.gray95,
|
||||
bg3: basicColors.gray90,
|
||||
dashboardBg: basicColors.gray98,
|
||||
bgBlue1: basicColors.blue80,
|
||||
bgBlue2: basicColors.blue77,
|
||||
|
||||
@@ -20,15 +20,15 @@ export const QueryOperationAction: React.FC<QueryOperationActionProps> = ({ icon
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div title={title}>
|
||||
<IconButton
|
||||
name={icon}
|
||||
title={title}
|
||||
className={styles.icon}
|
||||
disabled={!!disabled}
|
||||
onClick={onClick}
|
||||
surface="header"
|
||||
aria-label={`${title} query operation action`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -77,10 +77,11 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
margin-bottom: ${theme.spacing.formSpacingBase * 2}px;
|
||||
`,
|
||||
header: css`
|
||||
padding: ${theme.spacing.sm};
|
||||
padding: 0 ${theme.spacing.sm};
|
||||
border-radius: ${theme.border.radius.sm};
|
||||
background: ${theme.colors.bg2};
|
||||
height: ${theme.spacing.formInputHeight};
|
||||
line-height: ${theme.spacing.formInputHeight};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -93,14 +94,13 @@ const getQueryOperationRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
`,
|
||||
|
||||
title: css`
|
||||
font-weight: ${theme.typography.weight.semibold};
|
||||
color: ${theme.colors.textBlue};
|
||||
margin-left: ${theme.spacing.sm};
|
||||
`,
|
||||
content: css`
|
||||
margin-top: ${theme.spacing.xs};
|
||||
margin-top: ${theme.spacing.inlineFormMargin};
|
||||
margin-left: ${theme.spacing.xl};
|
||||
`,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { CustomScrollbar, Icon, JSONFormatter, ThemeContext } from '@grafana/ui';
|
||||
import { Icon, JSONFormatter, ThemeContext } from '@grafana/ui';
|
||||
import { GrafanaTheme, DataFrame } from '@grafana/data';
|
||||
|
||||
interface TransformationEditorProps {
|
||||
@@ -17,7 +17,6 @@ export const TransformationEditor = ({ editor, input, output, debugMode }: Trans
|
||||
const styles = getStyles(theme);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.editor}>
|
||||
{editor}
|
||||
{debugMode && (
|
||||
@@ -25,13 +24,7 @@ export const TransformationEditor = ({ editor, input, output, debugMode }: Trans
|
||||
<div className={styles.debug}>
|
||||
<div className={styles.debugTitle}>Input</div>
|
||||
<div className={styles.debugJson}>
|
||||
<CustomScrollbar
|
||||
className={css`
|
||||
height: 100%;
|
||||
`}
|
||||
>
|
||||
<JSONFormatter json={input} />
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.debugSeparator}>
|
||||
@@ -39,21 +32,13 @@ export const TransformationEditor = ({ editor, input, output, debugMode }: Trans
|
||||
</div>
|
||||
<div className={styles.debug}>
|
||||
<div className={styles.debugTitle}>Output</div>
|
||||
|
||||
<div className={styles.debugJson}>
|
||||
<CustomScrollbar
|
||||
className={css`
|
||||
height: 100%;
|
||||
`}
|
||||
>
|
||||
<JSONFormatter json={output} />
|
||||
</CustomScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -63,7 +48,6 @@ const getStyles = (theme: GrafanaTheme) => ({
|
||||
padding: 4px 8px 4px 8px;
|
||||
position: relative;
|
||||
height: 35px;
|
||||
background: ${theme.colors.textFaint};
|
||||
border-radius: 4px 4px 0 0;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
@@ -87,9 +71,7 @@ const getStyles = (theme: GrafanaTheme) => ({
|
||||
color: ${theme.colors.text};
|
||||
}
|
||||
`,
|
||||
editor: css`
|
||||
padding-top: ${theme.spacing.sm};
|
||||
`,
|
||||
editor: css``,
|
||||
debugWrapper: css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -23,7 +23,7 @@ export const TransformationOperationRow: React.FC<TransformationOperationRowProp
|
||||
|
||||
const renderActions = ({ isOpen }: { isOpen: boolean }) => {
|
||||
return (
|
||||
<HorizontalGroup>
|
||||
<HorizontalGroup align="center">
|
||||
<QueryOperationAction
|
||||
disabled={!isOpen}
|
||||
icon="bug"
|
||||
@@ -31,6 +31,7 @@ export const TransformationOperationRow: React.FC<TransformationOperationRowProp
|
||||
setShowDebug(!showDebug);
|
||||
}}
|
||||
/>
|
||||
|
||||
<QueryOperationAction icon="trash-alt" onClick={onRemove} />
|
||||
</HorizontalGroup>
|
||||
);
|
||||
|
||||
@@ -112,7 +112,7 @@ export class TransformationsEditor extends React.PureComponent<Props> {
|
||||
return (
|
||||
<CustomScrollbar autoHeightMin="100%">
|
||||
<Container padding="md">
|
||||
<p className="muted text-center" style={{ padding: '8px' }}>
|
||||
<p className="muted">
|
||||
Transformations allow you to combine, re-order, hide and rename specific parts the the data set before being
|
||||
visualized.
|
||||
</p>
|
||||
|
||||
@@ -355,7 +355,7 @@ $variable-option-bg: $dropdownLinkBackgroundHover;
|
||||
$switch-bg: $input-bg;
|
||||
$switch-slider-color: $dark-3;
|
||||
$switch-slider-off-bg: $gray-1;
|
||||
$switch-slider-on-bg: #1f60c4;
|
||||
$switch-slider-on-bg: #5794f2;
|
||||
$switch-slider-shadow: 0 0 3px black;
|
||||
|
||||
//Checkbox
|
||||
|
||||
@@ -135,6 +135,10 @@ $input-border: 1px solid $input-border-color;
|
||||
border: $panel-border;
|
||||
}
|
||||
|
||||
&--justify-left {
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
&--btn {
|
||||
border: none;
|
||||
border-radius: $border-radius;
|
||||
|
||||
Reference in New Issue
Block a user