diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx index 45f0385d..6561e9e5 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_expression_modal.tsx @@ -53,6 +53,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -94,6 +96,11 @@ const MAX_INPUT_DOCS = 10; export function ConfigureExpressionModal(props: ConfigureExpressionModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -407,6 +414,8 @@ export function ConfigureExpressionModal(props: ConfigureExpressionModalProps) { style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx index 3d3116fe..45b336a4 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_multi_expression_modal.tsx @@ -51,6 +51,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -91,6 +93,11 @@ export function ConfigureMultiExpressionModal( ) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -433,6 +440,8 @@ export function ConfigureMultiExpressionModal( style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx index f12c9eda..680cfb37 100644 --- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/modals/configure_template_modal.tsx @@ -57,6 +57,8 @@ import { injectParameters, prepareDocsForSimulate, unwrapTransformedDocs, + useDataSourceVersion, + useMissingDataSourceVersion, } from '../../../../../../utils'; import { TextField } from '../../../input_fields'; import { @@ -102,6 +104,11 @@ const PROMPT_EDITOR_ID = 'promptEditor'; export function ConfigureTemplateModal(props: ConfigureTemplateModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); + const dataSourceVersion = useDataSourceVersion(dataSourceId); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); const { values, setFieldValue, setFieldTouched } = useFormikContext< WorkflowFormValues >(); @@ -638,6 +645,8 @@ export function ConfigureTemplateModal(props: ConfigureTemplateModalProps) { style={{ width: '100px' }} isLoading={isFetching} disabled={ + (props.context === PROCESSOR_CONTEXT.INGEST && + missingDataSourceVersion) || onIngestAndNoDocs || onSearchAndNoQuery || !props.isDataFetchingAvailable || diff --git a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx index 4668d28d..88cc6b73 100644 --- a/public/pages/workflow_detail/workflow_inputs/processors_list.tsx +++ b/public/pages/workflow_detail/workflow_inputs/processors_list.tsx @@ -32,7 +32,7 @@ import { import { formikToUiConfig, getDataSourceFromURL, - getEffectiveVersion, + getDataSourceVersion, } from '../../../utils'; import { CollapseProcessor, @@ -120,9 +120,9 @@ export function ProcessorsList(props: ProcessorsListProps) { } if (dataSourceId !== undefined) { - getEffectiveVersion(dataSourceId) + getDataSourceVersion(dataSourceId) .then((ver) => { - setVersion(ver); + setVersion(ver || MIN_SUPPORTED_VERSION); }) .catch(console.error); } diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx index 8f529b0b..2fcfafd2 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/search_inputs.tsx @@ -11,11 +11,12 @@ import { EnrichSearchRequest } from './enrich_search_request'; import { EnrichSearchResponse } from './enrich_search_response'; import { CachedFormikState, + MIN_SUPPORTED_VERSION, OMIT_SYSTEM_INDEX_PATTERN, WorkflowConfig, } from '../../../../../common'; import { catIndices, useAppDispatch } from '../../../../store'; -import { getDataSourceId, getEffectiveVersion } from '../../../../utils'; +import { getDataSourceId, getDataSourceVersion } from '../../../../utils'; interface SearchInputsProps { uiConfig: WorkflowConfig; @@ -42,10 +43,11 @@ export function SearchInputs(props: SearchInputsProps) { const checkVersion = async () => { try { if (dataSourceId !== undefined) { - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; setShowTransformQuery(semver.gte(version, '2.19.0')); } else { - setShowTransformQuery(true); + setShowTransformQuery(true); } } catch (error) { console.error('Error checking version:', error); diff --git a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx index 35252a21..16be17e2 100644 --- a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx @@ -60,6 +60,7 @@ import { sleep, useDataSourceVersion, getIsPreV219, + useMissingDataSourceVersion, } from '../../../utils'; import { BooleanField } from './input_fields'; import '../workspace/workspace-styles.scss'; @@ -104,6 +105,10 @@ export function WorkflowInputs(props: WorkflowInputsProps) { const dataSourceId = getDataSourceId(); const dataSourceVersion = useDataSourceVersion(dataSourceId); const isPreV219 = getIsPreV219(dataSourceVersion); + const missingDataSourceVersion = useMissingDataSourceVersion( + dataSourceId, + dataSourceVersion + ); // transient running states const [isUpdatingSearchPipeline, setIsUpdatingSearchPipeline] = useState< @@ -610,7 +615,10 @@ export function WorkflowInputs(props: WorkflowInputsProps) { if ( !isEmpty(values?.ingest?.enrich) && values?.ingest?.pipelineName !== undefined && - values?.ingest?.pipelineName !== '' + values?.ingest?.pipelineName !== '' && + // if the data source version is missing/undefined, we cannot + // guarantee that the simulate API will be available + !missingDataSourceVersion ) { const curDocs = prepareDocsForSimulate( values?.ingest?.docs, diff --git a/public/pages/workflows/import_workflow/import_workflow_modal.tsx b/public/pages/workflows/import_workflow/import_workflow_modal.tsx index 8fcef547..d6e11b04 100644 --- a/public/pages/workflows/import_workflow/import_workflow_modal.tsx +++ b/public/pages/workflows/import_workflow/import_workflow_modal.tsx @@ -44,7 +44,11 @@ import { WORKFLOW_NAME_RESTRICTIONS, } from '../../../../common'; import { WORKFLOWS_TAB } from '../workflows'; -import { getDataSourceId, getEffectiveVersion, formatDisplayVersion } from '../../../utils/utils'; +import { + getDataSourceId, + formatDisplayVersion, + useDataSourceVersion, +} from '../../../utils/utils'; interface ImportWorkflowModalProps { isImportModalOpen: boolean; @@ -62,17 +66,7 @@ interface ImportWorkflowModalProps { export function ImportWorkflowModal(props: ImportWorkflowModalProps) { const dispatch = useAppDispatch(); const dataSourceId = getDataSourceId(); - const [dataSourceVersion, setDataSourceVersion] = useState< - string | undefined - >(undefined); - useEffect(() => { - async function getVersion() { - if (dataSourceId !== undefined) { - setDataSourceVersion(await getEffectiveVersion(dataSourceId)); - } - } - getVersion(); - }, [dataSourceId]); + const dataSourceVersion = useDataSourceVersion(dataSourceId); const { workflows } = useSelector((state: AppState) => state.workflows); // workflow name state @@ -171,7 +165,9 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) { <> diff --git a/public/pages/workflows/new_workflow/new_workflow.tsx b/public/pages/workflows/new_workflow/new_workflow.tsx index cf5fb25b..aed2d0c3 100644 --- a/public/pages/workflows/new_workflow/new_workflow.tsx +++ b/public/pages/workflows/new_workflow/new_workflow.tsx @@ -30,7 +30,7 @@ import { enrichPresetWorkflowWithUiMetadata } from './utils'; import { getDataSourceId, isDataSourceReady, - getEffectiveVersion, + getDataSourceVersion, } from '../../../utils'; import { getDataSourceEnabled } from '../../../services'; import semver from 'semver'; @@ -64,7 +64,8 @@ const filterPresetsByVersion = async ( WORKFLOW_TYPE.CUSTOM, ]; - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; if (semver.lt(version, MIN_SUPPORTED_VERSION)) { return []; @@ -159,7 +160,8 @@ export function NewWorkflow(props: NewWorkflowProps) { return; } - const version = await getEffectiveVersion(dataSourceId); + const version = + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; const enrichedWorkflows = presetWorkflows.map((presetWorkflow) => enrichPresetWorkflowWithUiMetadata(presetWorkflow, version) diff --git a/public/pages/workflows/new_workflow/quick_configure_modal.tsx b/public/pages/workflows/new_workflow/quick_configure_modal.tsx index 1f158742..9515f415 100644 --- a/public/pages/workflows/new_workflow/quick_configure_modal.tsx +++ b/public/pages/workflows/new_workflow/quick_configure_modal.tsx @@ -260,7 +260,7 @@ export function QuickConfigureModal(props: QuickConfigureModalProps) { { const compatibility = workflowObj?.version?.compatibility; // Default to true when compatibility cannot be assessed (empty/invalid compatibility array or MDS disabled.) - if (!Array.isArray(compatibility) || compatibility.length === 0 || dataSourceId === undefined) { + if ( + !Array.isArray(compatibility) || + compatibility.length === 0 || + dataSourceId === undefined + ) { return true; } - const dataSourceVersion = await getEffectiveVersion(dataSourceId); - const [effectiveMajorVersion, effectiveMinorVersion] = dataSourceVersion.split('.').map(Number); - + const dataSourceVersion = + (await getDataSourceVersion(dataSourceId)) || MIN_SUPPORTED_VERSION; + const [ + effectiveMajorVersion, + effectiveMinorVersion, + ] = dataSourceVersion.split('.').map(Number); + // Checks if any version in compatibility array matches the current dataSourceVersion (major.minor) - return compatibility.some(compatibleVersion => { - const [compatibleMajor, compatibleMinor] = compatibleVersion.split('.').map(Number); - return effectiveMajorVersion === compatibleMajor && effectiveMinorVersion === compatibleMinor; + return compatibility.some((compatibleVersion) => { + const [compatibleMajor, compatibleMinor] = compatibleVersion + .split('.') + .map(Number); + return ( + effectiveMajorVersion === compatibleMajor && + effectiveMinorVersion === compatibleMinor + ); }); } - export function isValidUiWorkflow(workflowObj: any): boolean { return ( isValidWorkflow(workflowObj) && @@ -561,7 +573,7 @@ export function useDataSourceVersion( useEffect(() => { async function getVersion() { if (dataSourceId !== undefined) { - setDataSourceVersion(await getEffectiveVersion(dataSourceId)); + setDataSourceVersion(await getDataSourceVersion(dataSourceId)); } } getVersion(); @@ -933,13 +945,13 @@ export function getFieldValue(jsonObj: {}, fieldName: string): any | undefined { return undefined; } -// Get the version from the selected data source -export const getEffectiveVersion = async ( +// Get the version from the selected data source, if found +export const getDataSourceVersion = async ( dataSourceId: string | undefined -): Promise => { +): Promise => { try { if (dataSourceId === undefined) { - throw new Error('Data source is required'); + throw new Error(); } if (dataSourceId === '') { @@ -951,16 +963,26 @@ export const getEffectiveVersion = async ( 'data-source', dataSourceId ); - const version = - dataSource?.attributes?.dataSourceVersion || MIN_SUPPORTED_VERSION; - return version; + return dataSource?.attributes?.dataSourceVersion; } catch (error) { - console.error('Error getting version:', error); - return MIN_SUPPORTED_VERSION; + console.error('Error getting version: ', error); + return undefined; } }; - +export function useMissingDataSourceVersion( + dataSourceId: string | undefined, + dataSourceVersion: string | undefined +): boolean { + const [missingVersion, setMissingVersion] = useState(false); + useEffect(() => { + setMissingVersion( + dataSourceId !== undefined && dataSourceVersion === undefined + ); + }, [dataSourceId, dataSourceVersion]); + return missingVersion; +} + /** * Formats version string to show only major.minor numbers * Example: "3.0.0-alpha1" -> "3.0" @@ -970,4 +992,3 @@ export function formatDisplayVersion(version: string): string { const [major, minor] = version.split('.'); return `${major}.${minor}`; } -