diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/configure_search_request.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/configure_search_request.tsx index a5ba1122..096267b9 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/configure_search_request.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/configure_search_request.tsx @@ -3,11 +3,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useEffect } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; +import React, { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiSuperSelect, + EuiSuperSelectOption, + EuiText, + EuiTitle, +} from '@elastic/eui'; import { useFormikContext } from 'formik'; import { IConfigField, WorkspaceFormValues } from '../../../../../common'; import { JsonField } from '../input_fields'; +import { AppState, catIndices, useAppDispatch } from '../../../../store'; interface ConfigureSearchRequestProps { setQuery: (query: string) => void; @@ -18,7 +29,20 @@ interface ConfigureSearchRequestProps { * Input component for configuring a search request */ export function ConfigureSearchRequest(props: ConfigureSearchRequestProps) { + const dispatch = useAppDispatch(); + + // Form state const { values } = useFormikContext(); + const indexName = values.ingest.index.name; + const ingestEnabled = values.ingest.enabled; + + // All indices state + const indices = useSelector((state: AppState) => state.opensearch.indices); + + // Selected index state + const [selectedIndex, setSelectedIndex] = useState( + undefined + ); // Hook to listen when the query form value changes. // Try to set the query request if possible @@ -28,6 +52,14 @@ export function ConfigureSearchRequest(props: ConfigureSearchRequestProps) { } }, [values?.search?.request]); + // Initialization hook to fetch available indices (if applicable) + useEffect(() => { + if (!ingestEnabled) { + // Fetch all indices besides system indices + dispatch(catIndices('*,-.*')); + } + }, []); + return ( @@ -35,6 +67,29 @@ export function ConfigureSearchRequest(props: ConfigureSearchRequestProps) {

Configure query

+ + + {ingestEnabled ? ( + + ) : ( + + ({ + value: option.name, + inputDisplay: {option.name}, + disabled: false, + } as EuiSuperSelectOption) + )} + valueOfSelected={selectedIndex} + onChange={(option) => { + setSelectedIndex(option); + }} + isInvalid={selectedIndex !== undefined} + /> + )} + + (); const dispatch = useAppDispatch(); + // Overall workspace state + const { isDirty } = useSelector((state: AppState) => state.workspace); + // selected step state const [selectedStep, setSelectedStep] = useState(STEP.INGEST); - // ingest state + // provisioned resources states const [ingestProvisioned, setIngestProvisioned] = useState(false); + const [searchProvisioned, setSearchProvisioned] = useState(false); + + // confirm modal state + const [isModalOpen, setIsModalOpen] = useState(false); // maintain global states const onIngest = selectedStep === STEP.INGEST; @@ -100,6 +117,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { useEffect(() => { setIngestProvisioned(hasProvisionedIngestResources(props.workflow)); + setSearchProvisioned(hasProvisionedSearchResources(props.workflow)); }, [props.workflow]); // Utility fn to update the workflow, including any updated/new resources @@ -203,6 +221,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { .unwrap() .then(async (resp) => { props.setIngestResponse(JSON.stringify(resp, undefined, 2)); + dispatch(removeDirty()); }) .catch((error: any) => { getCore().notifications.toasts.addDanger(error); @@ -235,6 +254,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { .then(async (resp) => { const hits = resp.hits.hits; props.setQueryResponse(JSON.stringify(hits, undefined, 2)); + dispatch(removeDirty()); }) .catch((error: any) => { getCore().notifications.toasts.addDanger(error); @@ -286,7 +306,50 @@ export function WorkflowInputs(props: WorkflowInputsProps) { }, ]} /> - {onIngest && ( + {isModalOpen && ( + setIsModalOpen(false)}> + + +

{`Delete resources for workflow ${props.workflow.name}?`}

+
+
+ + + The resources for this workflow will be permanently deleted. + This action cannot be undone. + + + + setIsModalOpen(false)}> + {' '} + Cancel + + { + // @ts-ignore + await dispatch(deprovisionWorkflow(props.workflow.id)) + .unwrap() + .then(async (result) => { + setFieldValue('ingest.enabled', false); + // @ts-ignore + await dispatch(getWorkflow(props.workflow.id)); + }) + .catch((error: any) => { + getCore().notifications.toasts.addDanger(error); + }) + .finally(() => { + setIsModalOpen(false); + }); + }} + fill={true} + color="danger" + > + Delete resources + + +
+ )} + {onIngestAndUnprovisioned && ( <>

- {onIngestAndUnprovisioned - ? 'Define ingest pipeline' - : onIngestAndProvisioned - ? 'Edit ingest pipeline' - : onSearch - ? 'Define search pipeline' - : 'Export project as'} + {onIngestAndUnprovisioned ? ( + 'Define ingest pipeline' + ) : onIngestAndProvisioned ? ( + + + Edit ingest pipeline + + + setIsModalOpen(true)} + > + + {` `}Delete resources + + + + ) : onSearch ? ( + 'Define search pipeline' + ) : ( + 'Export project as' + )}

@@ -380,27 +461,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { {`Search pipeline >`} - ) : onIngestAndUnprovisioned ? ( - <> - - setSelectedStep(STEP.SEARCH)} - > - Skip - - - - { - validateAndRunIngestion(); - }} - > - Run ingestion - - - - ) : onIngestAndProvisioned ? ( + ) : onIngest ? ( <> { validateAndRunIngestion(); }} + disabled={ingestProvisioned && !isDirty} > Run ingestion @@ -416,6 +478,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { setSelectedStep(STEP.SEARCH)} + disabled={!ingestProvisioned || isDirty} > {`Search pipeline >`} @@ -432,7 +495,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { { validateAndRunQuery(); @@ -443,7 +506,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { { setSelectedStep(STEP.EXPORT); diff --git a/public/utils/utils.ts b/public/utils/utils.ts index b84d0230..947e84ca 100644 --- a/public/utils/utils.ts +++ b/public/utils/utils.ts @@ -29,3 +29,17 @@ export function hasProvisionedIngestResources( }); return result; } + +export function hasProvisionedSearchResources( + workflow: Workflow | undefined +): boolean { + let result = false; + workflow?.resourcesCreated?.some((resource) => { + if ( + resource.stepType === WORKFLOW_STEP_TYPE.CREATE_SEARCH_PIPELINE_STEP_TYPE + ) { + result = true; + } + }); + return result; +}