2022-04-22 14:33:13 +01:00
|
|
|
import { css, cx } from '@emotion/css';
|
2021-07-27 13:10:39 +02:00
|
|
|
import React, { useState } from 'react';
|
2022-04-22 14:33:13 +01:00
|
|
|
|
2021-07-27 13:10:39 +02:00
|
|
|
import { GrafanaTheme2 } from '@grafana/data';
|
2022-04-22 14:33:13 +01:00
|
|
|
import { HorizontalGroup, InlineLabel, useStyles2 } from '@grafana/ui';
|
|
|
|
|
|
2021-07-27 13:10:39 +02:00
|
|
|
import { FuncInstance } from '../gfunc';
|
|
|
|
|
import { actions } from '../state/actions';
|
2022-04-22 14:33:13 +01:00
|
|
|
import { useDispatch } from '../state/context';
|
|
|
|
|
|
2021-08-17 18:50:31 +02:00
|
|
|
import { FunctionEditor } from './FunctionEditor';
|
2022-04-22 14:33:13 +01:00
|
|
|
import { EditableParam, FunctionParamEditor } from './FunctionParamEditor';
|
2021-07-27 13:10:39 +02:00
|
|
|
import { mapFuncInstanceToParams } from './helpers';
|
|
|
|
|
|
|
|
|
|
export type FunctionEditorProps = {
|
|
|
|
|
func: FuncInstance;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Allows editing function params and removing/moving a function (note: editing function name is not supported)
|
|
|
|
|
*/
|
2021-08-17 18:50:31 +02:00
|
|
|
export function GraphiteFunctionEditor({ func }: FunctionEditorProps) {
|
|
|
|
|
const dispatch = useDispatch();
|
2021-07-27 13:10:39 +02:00
|
|
|
const styles = useStyles2(getStyles);
|
|
|
|
|
|
|
|
|
|
// keep track of mouse over and isExpanded state to display buttons for adding optional/multiple params
|
|
|
|
|
// only when the user mouse over over the function editor OR any param editor is expanded.
|
|
|
|
|
const [mouseOver, setIsMouseOver] = useState(false);
|
|
|
|
|
const [expanded, setIsExpanded] = useState(false);
|
|
|
|
|
|
|
|
|
|
let params = mapFuncInstanceToParams(func);
|
|
|
|
|
params = params.filter((p: EditableParam, index: number) => {
|
|
|
|
|
// func.added is set for newly added functions - see autofocus below
|
|
|
|
|
return (index < func.def.params.length && !p.optional) || func.added || p.value || expanded || mouseOver;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={cx(styles.container, { [styles.error]: func.def.unknown })}
|
2022-11-03 10:22:50 +00:00
|
|
|
onBlur={() => setIsMouseOver(false)}
|
|
|
|
|
onFocus={() => setIsMouseOver(true)}
|
2021-07-27 13:10:39 +02:00
|
|
|
onMouseOver={() => setIsMouseOver(true)}
|
2022-11-03 10:22:50 +00:00
|
|
|
onMouseOut={() => setIsMouseOver(false)}
|
2021-07-27 13:10:39 +02:00
|
|
|
>
|
|
|
|
|
<HorizontalGroup spacing="none">
|
|
|
|
|
<FunctionEditor
|
|
|
|
|
func={func}
|
|
|
|
|
onMoveLeft={() => {
|
|
|
|
|
dispatch(actions.moveFunction({ func, offset: -1 }));
|
|
|
|
|
}}
|
|
|
|
|
onMoveRight={() => {
|
|
|
|
|
dispatch(actions.moveFunction({ func, offset: 1 }));
|
|
|
|
|
}}
|
|
|
|
|
onRemove={() => {
|
|
|
|
|
dispatch(actions.removeFunction({ func }));
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<InlineLabel className={styles.label}>(</InlineLabel>
|
|
|
|
|
{params.map((editableParam: EditableParam, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<React.Fragment key={index}>
|
|
|
|
|
<FunctionParamEditor
|
|
|
|
|
autofocus={index === 0 && func.added}
|
|
|
|
|
editableParam={editableParam}
|
|
|
|
|
onChange={(value) => {
|
|
|
|
|
if (value !== '' || editableParam.optional) {
|
|
|
|
|
dispatch(actions.updateFunctionParam({ func, index, value }));
|
|
|
|
|
}
|
|
|
|
|
setIsExpanded(false);
|
|
|
|
|
setIsMouseOver(false);
|
|
|
|
|
}}
|
|
|
|
|
onExpandedChange={setIsExpanded}
|
|
|
|
|
/>
|
|
|
|
|
{index !== params.length - 1 ? ',' : ''}
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
<InlineLabel className={styles.label}>)</InlineLabel>
|
|
|
|
|
</HorizontalGroup>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => ({
|
|
|
|
|
container: css({
|
|
|
|
|
backgroundColor: theme.colors.background.secondary,
|
2023-08-01 14:46:07 +01:00
|
|
|
borderRadius: theme.shape.radius.default,
|
2021-07-27 13:10:39 +02:00
|
|
|
marginRight: theme.spacing(0.5),
|
|
|
|
|
padding: `0 ${theme.spacing(1)}`,
|
2021-08-17 18:50:31 +02:00
|
|
|
height: `${theme.v1.spacing.formInputHeight}px`,
|
2021-07-27 13:10:39 +02:00
|
|
|
}),
|
|
|
|
|
error: css`
|
|
|
|
|
border: 1px solid ${theme.colors.error.main};
|
|
|
|
|
`,
|
|
|
|
|
label: css({
|
|
|
|
|
padding: 0,
|
|
|
|
|
margin: 0,
|
|
|
|
|
}),
|
|
|
|
|
button: css({
|
|
|
|
|
padding: theme.spacing(0.5),
|
|
|
|
|
}),
|
|
|
|
|
});
|