Transformations: State feature (alpha/beta) and more (#36630)

* Adding plugin state feature to transforms

* initial help box

* New HelpBox component

* More progress

* Testing

* Removing HelpBox, simple new design, new active state for OperationRowAction

* Updated tests

* Fixed typing issue

* Removed AlphaNotice

* Made focus and enter key trigger OnClick and sorted transformations

* Fixed e2e tests
This commit is contained in:
Torkel Ödegaard
2021-07-12 16:42:04 +02:00
committed by GitHub
parent 5e62bddd1d
commit 863b412d54
24 changed files with 248 additions and 319 deletions

View File

@@ -0,0 +1,45 @@
import React from 'react';
import { css, cx } from '@emotion/css';
import { GrafanaTheme2, renderMarkdown } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
export interface Props extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode;
markdown?: string;
onRemove?: () => void;
}
export const OperationRowHelp = React.memo(
React.forwardRef<HTMLDivElement, Props>(({ className, children, markdown, onRemove, ...otherProps }, ref) => {
const styles = useStyles2(getStyles);
return (
<div className={cx(styles.wrapper, className)} {...otherProps} ref={ref}>
{markdown && markdownHelper(markdown)}
{children}
</div>
);
})
);
function markdownHelper(markdown: string) {
const helpHtml = renderMarkdown(markdown);
return <div className="markdown-html" dangerouslySetInnerHTML={{ __html: helpHtml }} />;
}
OperationRowHelp.displayName = 'OperationRowHelp';
const getStyles = (theme: GrafanaTheme2) => {
const borderRadius = theme.shape.borderRadius();
return {
wrapper: css`
padding: ${theme.spacing(2)};
border: 2px solid ${theme.colors.background.secondary};
border-top: none;
border-radius: 0 0 ${borderRadius} ${borderRadius};
position: relative;
top: -4px;
`,
};
};

View File

@@ -1,7 +1,7 @@
import { IconButton, IconName, stylesFactory, useTheme } from '@grafana/ui';
import { IconButton, IconName, useStyles2 } from '@grafana/ui';
import React from 'react';
import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { css, cx } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
interface QueryOperationActionProps {
@@ -9,37 +9,55 @@ interface QueryOperationActionProps {
title: string;
onClick: (e: React.MouseEvent) => void;
disabled?: boolean;
active?: boolean;
}
export const QueryOperationAction: React.FC<QueryOperationActionProps> = ({ icon, disabled, title, ...otherProps }) => {
const theme = useTheme();
const styles = getStyles(theme);
export const QueryOperationAction: React.FC<QueryOperationActionProps> = ({
icon,
active,
disabled,
title,
onClick,
}) => {
const styles = useStyles2(getStyles);
const onClick = (e: React.MouseEvent) => {
if (!disabled) {
otherProps.onClick(e);
}
};
return (
<IconButton
name={icon}
title={title}
className={styles.icon}
disabled={!!disabled}
onClick={onClick}
surface="header"
type="button"
aria-label={selectors.components.QueryEditorRow.actionButton(title)}
/>
<div className={cx(styles.icon, active && styles.active)}>
<IconButton
name={icon}
title={title}
className={styles.icon}
disabled={!!disabled}
onClick={onClick}
surface="header"
type="button"
aria-label={selectors.components.QueryEditorRow.actionButton(title)}
/>
</div>
);
};
QueryOperationAction.displayName = 'QueryOperationAction';
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
icon: css`
color: ${theme.colors.textWeak};
display: flex;
position: relative;
color: ${theme.colors.text.secondary};
`,
active: css`
&::before {
display: block;
content: ' ';
position: absolute;
left: -1px;
right: 2px;
height: 3px;
border-radius: 2px;
bottom: -8px;
background-image: ${theme.colors.gradients.brandHorizontal} !important;
}
`,
};
});
};