import React from 'react';
import { SpelService } from './SpelService';
import type { ITextInputProps } from '../forms/inputs';
import { TextAreaInput } from '../forms/inputs';
import { useInternalValidator } from '../forms/inputs/hooks';
import { asyncMessage, messageMessage, warningMessage } from '../forms/validation';
import { useData, useDebouncedValue, useIsMountedRef } from '../hooks';
import './SpelInput.less';
export interface IStageForSpelPreview {
executionLabel: string;
executionId: string;
stageId: string;
}
interface ISpelInputProps extends ITextInputProps {
previewStage: IStageForSpelPreview;
}
/** An Input that previews Spel expressions */
export function SpelInput(props: ISpelInputProps) {
const { previewStage, ...rest } = props;
const [expression, isDebouncing] = useDebouncedValue(props.value, 300);
const isInitialRender = !useIsMountedRef().current;
function previewExpressionValidator() {
const { status, error, result } = fetchSpelPreview;
if (status === 'NONE') {
return null;
} else if (status === 'PENDING' || isDebouncing) {
if (result) {
return asyncMessage('Updating preview...\n\n\n```\n' + JSON.stringify(result, null, 2) + '\n```');
}
return asyncMessage('Updating preview...');
} else if (status === 'RESOLVED') {
// Render as a code block
const previewMessage =
`Preview - based on previous execution: ${previewStage.executionLabel}\n\n\n` +
'```\n' +
JSON.stringify(result, null, 2) +
'\n```';
return messageMessage(previewMessage);
} else if (status === 'REJECTED') {
return warningMessage(error);
}
return null;
}
useInternalValidator(props.validation, previewExpressionValidator);
const fetchSpelPreview = useData(
() => SpelService.evaluateExpression(expression, previewStage.executionId, previewStage.stageId),
null,
[expression, previewStage.executionId, previewStage.stageId],
);
// re-validate whenever an async event occurs
React.useEffect(() => {
!isInitialRender && props.validation && props.validation.revalidate && props.validation.revalidate();
}, [fetchSpelPreview.status, isDebouncing]);
return ;
}
/** An Input for entering SpEL without preview functionality */
export function SimpleSpelInput(props: ITextInputProps) {
const hasNewlines = !!/\n/.exec(props.value);
return (
);
}