Commit 460561a2 by Torkel Ödegaard Committed by GitHub

Transformations: UX updates (#23574)

parent 8b48a1c8
......@@ -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,29 +72,27 @@ const OrganizeFieldsTransformerEditor: React.FC<OrganizeFieldsTransformerEditorP
);
return (
<VerticalGroup>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="sortable-fields-transformer" direction="vertical">
{provided => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{orderedFieldNames.map((fieldName, index) => {
return (
<DraggableFieldName
fieldName={fieldName}
index={index}
onToggleVisibility={onToggleVisibility}
onRenameField={onRenameField}
visible={!excludeByName[fieldName]}
key={fieldName}
/>
);
})}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</VerticalGroup>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="sortable-fields-transformer" direction="vertical">
{provided => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{orderedFieldNames.map((fieldName, index) => {
return (
<DraggableFieldName
fieldName={fieldName}
index={index}
onToggleVisibility={onToggleVisibility}
onRenameField={onRenameField}
visible={!excludeByName[fieldName]}
key={fieldName}
/>
);
})}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
};
......@@ -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}>
<i className={cx('fa fa-ellipsis-v', styles.draggable)} />
<Button
className={styles.toggle}
variant="link"
size="md"
icon={visible ? 'eye' : 'eye-slash'}
onClick={() => onToggleVisibility(fieldName, visible)}
/>
<span className={styles.name}>{fieldName}</span>
</div>
<div className={styles.right}>
<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)} />
<IconButton
className={styles.toggle}
size="md"
name={visible ? 'eye' : 'eye-slash'}
surface="header"
onClick={() => onToggleVisibility(fieldName, visible)}
/>
<span className={styles.name}>{fieldName}</span>
</div>
<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}
className={styles.icon}
disabled={!!disabled}
onClick={onClick}
aria-label={`${title} query operation action`}
/>
</div>
<IconButton
name={icon}
title={title}
className={styles.icon}
disabled={!!disabled}
onClick={onClick}
surface="header"
aria-label={`${title} query operation action`}
/>
);
};
......
......@@ -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};
`,
};
......
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,42 +17,27 @@ export const TransformationEditor = ({ editor, input, output, debugMode }: Trans
const styles = getStyles(theme);
return (
<div>
<div className={styles.editor}>
{editor}
{debugMode && (
<div className={styles.debugWrapper}>
<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 className={styles.editor}>
{editor}
{debugMode && (
<div className={styles.debugWrapper}>
<div className={styles.debug}>
<div className={styles.debugTitle}>Input</div>
<div className={styles.debugJson}>
<JSONFormatter json={input} />
</div>
<div className={styles.debugSeparator}>
<Icon name="arrow-right" />
</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 className={styles.debugSeparator}>
<Icon name="arrow-right" />
</div>
<div className={styles.debug}>
<div className={styles.debugTitle}>Output</div>
<div className={styles.debugJson}>
<JSONFormatter json={output} />
</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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment