From 7bd5acaa3c214fcb31b02a8d8093533cfd3c3cb2 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 9 Dec 2024 10:22:30 -0800 Subject: [PATCH 01/10] Add includeSearch bool in hook when re-checking template diffs Signed-off-by: Tyler Ohlsen --- .../pages/workflow_detail/workflow_inputs/workflow_inputs.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx index 9794e624..96fb205e 100644 --- a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx @@ -171,10 +171,10 @@ export function WorkflowInputs(props: WorkflowInputsProps) { formikToUiConfig(values, props.uiConfig as WorkflowConfig), true, includeSearchDuringProvision - ).provision.nodes) || + )?.provision?.nodes) || [] ); - }, [values, props.uiConfig, props.workflow]); + }, [values, props.uiConfig, props.workflow, includeSearchDuringProvision]); // fetch the persisted template nodes for ingest & search useEffect(() => { From 6759a24dbdd316dbf96ea06f54a9b0dfb43fb6fd Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 9 Dec 2024 10:30:32 -0800 Subject: [PATCH 02/10] Small state updates Signed-off-by: Tyler Ohlsen --- .../pages/workflow_detail/workflow_inputs/workflow_inputs.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx index 96fb205e..fc1485ea 100644 --- a/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx +++ b/public/pages/workflow_detail/workflow_inputs/workflow_inputs.tsx @@ -502,6 +502,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { .unwrap() .then(async (resp) => { props.setIngestResponse(customStringify(resp)); + props.setIsRunningIngest(false); setLastIngested(Date.now()); }) .catch((error: any) => { @@ -792,6 +793,7 @@ export function WorkflowInputs(props: WorkflowInputsProps) { 'Search pipeline updated' ); props.displaySearchPanel(); + setSearchProvisioned(true); } }} > From 402d9abd4c0342dc48153559cb0f109d79b895f8 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 9 Dec 2024 10:47:24 -0800 Subject: [PATCH 03/10] Add btn to optionally open/close search in edit query modal Signed-off-by: Tyler Ohlsen --- .../search_inputs/edit_query_modal.tsx | 285 ++++++++++-------- 1 file changed, 156 insertions(+), 129 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx index 48affada..a8c215be 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx @@ -82,6 +82,9 @@ export function EditQueryModal(props: EditQueryModalProps) { // popover state const [popoverOpen, setPopoverOpen] = useState(false); + // optional search panel state. allows searching within the modal + const [searchPanelOpen, setSearchPanelOpen] = useState(false); + // results state const [tempResults, setTempResults] = useState(''); const [tempResultsError, setTempResultsError] = useState(''); @@ -171,43 +174,62 @@ export function EditQueryModal(props: EditQueryModalProps) { Query definition - + + setPopoverOpen(!popoverOpen)} + data-testid="searchQueryPresetButton" + iconSide="right" + iconType="arrowDown" + > + Query samples + + } + isOpen={popoverOpen} + closePopover={() => setPopoverOpen(false)} + anchorPosition="downLeft" + > + ({ + name: preset.name, + onClick: () => { + formikProps.setFieldValue( + 'request', + preset.query + ); + setPopoverOpen(false); + }, + }) + ), + }, + ]} + /> + + + setPopoverOpen(!popoverOpen)} - data-testid="searchQueryPresetButton" + data-testid="showOrHideSearchPanelButton" + fill={false} + iconType={ + searchPanelOpen ? 'menuLeft' : 'menuRight' + } iconSide="right" - iconType="arrowDown" + onClick={() => { + setSearchPanelOpen(!searchPanelOpen); + }} > - Query samples + Test query - } - isOpen={popoverOpen} - closePopover={() => setPopoverOpen(false)} - anchorPosition="downLeft" - > - ({ - name: preset.name, - onClick: () => { - formikProps.setFieldValue( - 'request', - preset.query - ); - setPopoverOpen(false); - }, - }) - ), - }, - ]} - /> - + + @@ -221,103 +243,108 @@ export function EditQueryModal(props: EditQueryModalProps) { - - - - - - Test query - - - { - dispatch( - searchIndex({ - apiBody: { - index: values?.search?.index?.name, - body: injectParameters( - queryParams, - tempRequest - ), - // Run the query independent of the pipeline inside this modal - searchPipeline: '_none', - }, - dataSourceId, - }) - ) - .unwrap() - .then(async (resp) => { - setTempResults( - customStringify( - resp?.hits?.hits?.map( - (hit: SearchHit) => hit._source + {searchPanelOpen && ( + + + + + + Test query + + + { + dispatch( + searchIndex({ + apiBody: { + index: values?.search?.index?.name, + body: injectParameters( + queryParams, + tempRequest + ), + // Run the query independent of the pipeline inside this modal + searchPipeline: '_none', + }, + dataSourceId, + }) + ) + .unwrap() + .then(async (resp) => { + setTempResults( + customStringify( + resp?.hits?.hits?.map( + (hit: SearchHit) => hit._source + ) ) - ) - ); - setTempResultsError(''); - }) - .catch((error: any) => { - setTempResults(''); - const errorMsg = `Error running query: ${error}`; - setTempResultsError(errorMsg); - console.error(errorMsg); - }); - }} - > - Search - - - - - {/** - * This may return nothing if the list of params are empty - */} - - - <> - Results - {isEmpty(tempResults) && isEmpty(tempResultsError) ? ( - No results} - titleSize="s" - body={ - <> - - Run search to view results. - - - } - /> - ) : !isEmpty(tempResultsError) ? ( - - ) : ( - - )} - - - - + ); + setTempResultsError(''); + }) + .catch((error: any) => { + setTempResults(''); + const errorMsg = `Error running query: ${error}`; + setTempResultsError(errorMsg); + console.error(errorMsg); + }); + }} + > + Search + + + + + {/** + * This may return nothing if the list of params are empty + */} + + + <> + Results + {isEmpty(tempResults) && isEmpty(tempResultsError) ? ( + No results} + titleSize="s" + body={ + <> + + Run search to view results. + + + } + /> + ) : !isEmpty(tempResultsError) ? ( + + ) : ( + + )} + + + + + )} From 65f9d2e18eb927f2cd2cbd5c0f9f0b80e9e97499 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Mon, 9 Dec 2024 17:06:41 -0800 Subject: [PATCH 04/10] Add initial components for improving search results rendering; Signed-off-by: Tyler Ohlsen --- common/interfaces.ts | 21 +++++ public/general_components/index.ts | 1 + public/general_components/results/index.ts | 6 ++ public/general_components/results/results.tsx | 77 ++++++++++++++++ .../results/results_json.tsx | 35 ++++++++ .../results/results_table.tsx | 87 +++++++++++++++++++ .../workflow_detail/tools/query/query.tsx | 37 ++++---- .../workflow_detail/workspace/workspace.tsx | 4 +- 8 files changed, 245 insertions(+), 23 deletions(-) create mode 100644 public/general_components/results/index.ts create mode 100644 public/general_components/results/results.tsx create mode 100644 public/general_components/results/results_json.tsx create mode 100644 public/general_components/results/results_table.tsx diff --git a/common/interfaces.ts b/common/interfaces.ts index 27712cdd..037b552f 100644 --- a/common/interfaces.ts +++ b/common/interfaces.ts @@ -596,6 +596,27 @@ export type SimulateIngestPipelineResponse = { export type SearchHit = SimulateIngestPipelineDoc; +export type SearchResponse = { + took: number; + timed_out: boolean; + _shards: { + total: number; + successful: number; + skipped: number; + failed: number; + }; + hits?: { + total: { + value: number; + relation: string; + }; + max_score: number; + hits: SearchHit[]; + }; + aggregations?: {}; + ext: {}; +}; + export type IndexResponse = { indexName: string; indexDetails: IndexConfiguration; diff --git a/public/general_components/index.ts b/public/general_components/index.ts index 1ce91089..60528d1e 100644 --- a/public/general_components/index.ts +++ b/public/general_components/index.ts @@ -7,4 +7,5 @@ export { MultiSelectFilter } from './multi_select_filter'; export { ProcessorsTitle } from './processors_title'; export { ExperimentalBadge } from './experimental_badge'; export { QueryParamsList } from './query_params_list'; +export * from './results'; export * from './service_card'; diff --git a/public/general_components/results/index.ts b/public/general_components/results/index.ts new file mode 100644 index 00000000..b5201bd4 --- /dev/null +++ b/public/general_components/results/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { Results } from './results'; diff --git a/public/general_components/results/results.tsx b/public/general_components/results/results.tsx new file mode 100644 index 00000000..d73416f8 --- /dev/null +++ b/public/general_components/results/results.tsx @@ -0,0 +1,77 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from 'react'; +import { + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiSmallButtonGroup, +} from '@elastic/eui'; +import { SearchResponse } from '../../../common'; +import { ResultsTable } from './results_table'; +import { ResultsJSON } from './results_json'; + +interface ResultsProps { + response: SearchResponse; +} + +enum VIEW { + HITS_TABLE = 'hits_table', + RAW_JSON = 'raw_json', +} + +/** + * Basic component to view OpenSearch response results. Can view hits in a tabular format, + * or the raw JSON response. + */ +export function Results(props: ResultsProps) { + // selected view state + const [selectedView, setSelectedView] = useState(VIEW.HITS_TABLE); + + return ( + + + + setSelectedView(id as VIEW)} + data-testid="resultsToggleButtonGroup" + /> + + + <> + {selectedView === VIEW.HITS_TABLE && ( + + )} + {selectedView === VIEW.RAW_JSON && ( + + )} + + + + + ); +} diff --git a/public/general_components/results/results_json.tsx b/public/general_components/results/results_json.tsx new file mode 100644 index 00000000..8cc18f5e --- /dev/null +++ b/public/general_components/results/results_json.tsx @@ -0,0 +1,35 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { EuiCodeEditor } from '@elastic/eui'; +import { customStringify, SearchResponse } from '../../../common'; + +interface ResultsJSONProps { + response: SearchResponse; +} + +/** + * Small component to render the raw search response. Grows to fill + * the parent container by setting 100% width/height. + */ +export function ResultsJSON(props: ResultsJSONProps) { + return ( + + ); +} diff --git a/public/general_components/results/results_table.tsx b/public/general_components/results/results_table.tsx new file mode 100644 index 00000000..4d4b34ae --- /dev/null +++ b/public/general_components/results/results_table.tsx @@ -0,0 +1,87 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from 'react'; +import { + EuiText, + EuiButtonIcon, + RIGHT_ALIGNMENT, + EuiInMemoryTable, + EuiPanel, +} from '@elastic/eui'; +import { customStringify, SearchHit } from '../../../common'; + +interface ResultsTableProps { + hits: SearchHit[]; +} + +/** + * Small component to display a list of search results with pagination. + * Wrapped in a flexible panel with overflow handling. + */ +export function ResultsTable(props: ResultsTableProps) { + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<{ + [itemId: string]: any; + }>({}); + + const toggleDetails = (hit: SearchHit) => { + const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMapValues[hit._id]) { + delete itemIdToExpandedRowMapValues[hit._id]; + } else { + itemIdToExpandedRowMapValues[hit._id] = ( + {customStringify(hit._source)} + ); + } + setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); + }; + + return ( + + { + return ( + {customStringify(item._source)} + ); + }, + }, + { + align: RIGHT_ALIGNMENT, + width: '40px', + isExpander: true, + render: (item: SearchHit) => ( + toggleDetails(item)} + aria-label={ + itemIdToExpandedRowMap[item._id] ? 'Collapse' : 'Expand' + } + iconType={ + itemIdToExpandedRowMap[item._id] ? 'arrowUp' : 'arrowDown' + } + /> + ), + }, + ]} + /> + + ); +} diff --git a/public/pages/workflow_detail/tools/query/query.tsx b/public/pages/workflow_detail/tools/query/query.tsx index ba617465..d4a9098e 100644 --- a/public/pages/workflow_detail/tools/query/query.tsx +++ b/public/pages/workflow_detail/tools/query/query.tsx @@ -22,6 +22,7 @@ import { FETCH_ALL_QUERY, QueryParam, SearchHit, + SearchResponse, WorkflowFormValues, } from '../../../../../common'; import { searchIndex, useAppDispatch } from '../../../../store'; @@ -32,7 +33,7 @@ import { getPlaceholdersFromQuery, injectParameters, } from '../../../../utils'; -import { QueryParamsList } from '../../../../general_components'; +import { QueryParamsList, Results } from '../../../../general_components'; interface QueryProps { queryResponse: string; @@ -65,6 +66,12 @@ export function Query(props: QueryProps) { // use custom query state const [useCustomQuery, setUseCustomQuery] = useState(false); + // query response state + // TODO: clean up how/what responses we are persisting and where. + const [tempResponse, setTempResponse] = useState( + undefined + ); + // Standalone / sandboxed search request state. Users can test things out // without updating the base form / persisted value. We default to different values // based on the context (ingest or search), and update based on changes to the context @@ -182,12 +189,13 @@ export function Query(props: QueryProps) { }) ) .unwrap() - .then(async (resp) => { + .then(async (resp: SearchResponse) => { + setTempResponse(resp); props.setQueryResponse( customStringify( resp?.hits?.hits?.map( (hit: SearchHit) => hit._source - ) + ) || [] ) ); }) @@ -283,7 +291,10 @@ export function Query(props: QueryProps) { Results - {isEmpty(props.queryResponse) ? ( + {/** + * TODO: clean up how/what responses we are persisting + */} + {isEmpty(tempResponse) ? ( No results} titleSize="s" @@ -294,23 +305,7 @@ export function Query(props: QueryProps) { } /> ) : ( - // Known issue with the editor where resizing the resizablecontainer does not - // trigger vertical scroll updates. Updating the window, or reloading the component - // by switching tabs etc. will refresh it correctly - + )} diff --git a/public/pages/workflow_detail/workspace/workspace.tsx b/public/pages/workflow_detail/workspace/workspace.tsx index d9daf1d2..302a012f 100644 --- a/public/pages/workflow_detail/workspace/workspace.tsx +++ b/public/pages/workflow_detail/workspace/workspace.tsx @@ -66,11 +66,11 @@ export function Workspace(props: WorkspaceProps) { >(TOGGLE_BUTTON_ID.VISUAL); const toggleButtons = [ { - id: `workspaceVisualButton`, + id: TOGGLE_BUTTON_ID.VISUAL, label: 'Visual', }, { - id: `workspaceJSONButton`, + id: TOGGLE_BUTTON_ID.JSON, label: 'JSON', }, ]; From 4cca6b5e7bddbe28d1ef04a5eebce859f5601a0b Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 10 Dec 2024 09:48:04 -0800 Subject: [PATCH 05/10] Clean up rendering of preview and details of results table Signed-off-by: Tyler Ohlsen --- public/general_components/results/results.tsx | 2 +- .../results/results_table.tsx | 112 +++++++++++------- 2 files changed, 69 insertions(+), 45 deletions(-) diff --git a/public/general_components/results/results.tsx b/public/general_components/results/results.tsx index d73416f8..a85e320c 100644 --- a/public/general_components/results/results.tsx +++ b/public/general_components/results/results.tsx @@ -36,7 +36,7 @@ export function Results(props: ResultsProps) { hasBorder={false} hasShadow={false} paddingSize="none" - style={{ height: '10vh', overflowY: 'scroll' }} + style={{ height: '10vh', overflowY: 'scroll', overflowX: 'hidden' }} > {customStringify(hit._source)} + + + ); } setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); }; return ( - - { - return ( - {customStringify(item._source)} - ); - }, + { + return ( + + {customStringify(item._source)} + + ); }, - { - align: RIGHT_ALIGNMENT, - width: '40px', - isExpander: true, - render: (item: SearchHit) => ( - toggleDetails(item)} - aria-label={ - itemIdToExpandedRowMap[item._id] ? 'Collapse' : 'Expand' - } - iconType={ - itemIdToExpandedRowMap[item._id] ? 'arrowUp' : 'arrowDown' - } - /> - ), - }, - ]} - /> - + }, + { + align: RIGHT_ALIGNMENT, + width: '40px', + isExpander: true, + render: (item: SearchHit) => ( + toggleDetails(item)} + aria-label={ + itemIdToExpandedRowMap[item._id] ? 'Collapse' : 'Expand' + } + iconType={ + itemIdToExpandedRowMap[item._id] ? 'arrowUp' : 'arrowDown' + } + /> + ), + }, + ]} + /> ); } From 0f92885cbc814022e410c6648b8dc7bcdb0e82a5 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 10 Dec 2024 09:53:49 -0800 Subject: [PATCH 06/10] Remove query resp props Signed-off-by: Tyler Ohlsen --- .../workflow_detail/resizable_workspace.tsx | 3 --- .../workflow_detail/tools/query/query.tsx | 26 ++++++------------- public/pages/workflow_detail/tools/tools.tsx | 11 -------- 3 files changed, 8 insertions(+), 32 deletions(-) diff --git a/public/pages/workflow_detail/resizable_workspace.tsx b/public/pages/workflow_detail/resizable_workspace.tsx index b7976c6d..89d13268 100644 --- a/public/pages/workflow_detail/resizable_workspace.tsx +++ b/public/pages/workflow_detail/resizable_workspace.tsx @@ -82,7 +82,6 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) { // Inspector panel state vars. Actions taken in the form can update the Inspector panel, // hence we keep top-level vars here to pass to both form and inspector components. const [ingestResponse, setIngestResponse] = useState(''); - const [queryResponse, setQueryResponse] = useState(''); const [selectedInspectorTabId, setSelectedInspectorTabId] = useState< INSPECTOR_TAB_ID >(INSPECTOR_TAB_ID.INGEST); @@ -207,8 +206,6 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) { void; hasSearchPipeline: boolean; hasIngestResources: boolean; selectedStep: CONFIG_STEP; @@ -68,9 +65,9 @@ export function Query(props: QueryProps) { // query response state // TODO: clean up how/what responses we are persisting and where. - const [tempResponse, setTempResponse] = useState( - undefined - ); + const [queryResponse, setQueryResponse] = useState< + SearchResponse | undefined + >(undefined); // Standalone / sandboxed search request state. Users can test things out // without updating the base form / persisted value. We default to different values @@ -123,7 +120,7 @@ export function Query(props: QueryProps) { })) ); } - props.setQueryResponse(''); + setQueryResponse(undefined); }, [tempRequest]); // empty states @@ -190,17 +187,10 @@ export function Query(props: QueryProps) { ) .unwrap() .then(async (resp: SearchResponse) => { - setTempResponse(resp); - props.setQueryResponse( - customStringify( - resp?.hits?.hits?.map( - (hit: SearchHit) => hit._source - ) || [] - ) - ); + setQueryResponse(resp); }) .catch((error: any) => { - props.setQueryResponse(''); + setQueryResponse(undefined); console.error('Error running query: ', error); }); }} @@ -294,7 +284,7 @@ export function Query(props: QueryProps) { {/** * TODO: clean up how/what responses we are persisting */} - {isEmpty(tempResponse) ? ( + {queryResponse === undefined || isEmpty(queryResponse) ? ( No results} titleSize="s" @@ -305,7 +295,7 @@ export function Query(props: QueryProps) { } /> ) : ( - + )} diff --git a/public/pages/workflow_detail/tools/tools.tsx b/public/pages/workflow_detail/tools/tools.tsx index 15fc4725..b973ca18 100644 --- a/public/pages/workflow_detail/tools/tools.tsx +++ b/public/pages/workflow_detail/tools/tools.tsx @@ -33,8 +33,6 @@ import { interface ToolsProps { workflow?: Workflow; ingestResponse: string; - queryResponse: string; - setQueryResponse: (queryResponse: string) => void; selectedTabId: INSPECTOR_TAB_ID; setSelectedTabId: (tabId: INSPECTOR_TAB_ID) => void; selectedStep: CONFIG_STEP; @@ -83,13 +81,6 @@ export function Tools(props: ToolsProps) { } }, [props.ingestResponse]); - // auto-navigate to query tab if a populated value has been set, indicating search has been ran - useEffect(() => { - if (!isEmpty(props.queryResponse)) { - props.setSelectedTabId(INSPECTOR_TAB_ID.QUERY); - } - }, [props.queryResponse]); - return ( Date: Tue, 10 Dec 2024 10:02:38 -0800 Subject: [PATCH 07/10] Integrate in edit query modal Signed-off-by: Tyler Ohlsen --- .../search_inputs/edit_query_modal.tsx | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx index a8c215be..132bd67d 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx @@ -33,6 +33,7 @@ import { QueryPreset, RequestFormValues, SearchHit, + SearchResponse, WorkflowFormValues, } from '../../../../../common'; import { @@ -45,7 +46,7 @@ import { injectParameters, } from '../../../../utils'; import { searchIndex, useAppDispatch } from '../../../../store'; -import { QueryParamsList } from '../../../../general_components'; +import { QueryParamsList, Results } from '../../../../general_components'; interface EditQueryModalProps { queryFieldPath: string; @@ -86,7 +87,9 @@ export function EditQueryModal(props: EditQueryModalProps) { const [searchPanelOpen, setSearchPanelOpen] = useState(false); // results state - const [tempResults, setTempResults] = useState(''); + const [queryResponse, setQueryResponse] = useState< + SearchResponse | undefined + >(undefined); const [tempResultsError, setTempResultsError] = useState(''); // query/request params state @@ -114,7 +117,7 @@ export function EditQueryModal(props: EditQueryModalProps) { ); } setTempResultsError(''); - setTempResults(''); + setQueryResponse(undefined); }, [tempRequest]); // Clear any error if the parameters have been updated in any way @@ -274,18 +277,12 @@ export function EditQueryModal(props: EditQueryModalProps) { }) ) .unwrap() - .then(async (resp) => { - setTempResults( - customStringify( - resp?.hits?.hits?.map( - (hit: SearchHit) => hit._source - ) - ) - ); + .then(async (resp: SearchResponse) => { + setQueryResponse(resp); setTempResultsError(''); }) .catch((error: any) => { - setTempResults(''); + setQueryResponse(undefined); const errorMsg = `Error running query: ${error}`; setTempResultsError(errorMsg); console.error(errorMsg); @@ -307,7 +304,9 @@ export function EditQueryModal(props: EditQueryModalProps) { <> Results - {isEmpty(tempResults) && isEmpty(tempResultsError) ? ( + {(queryResponse === undefined || + isEmpty(queryResponse)) && + isEmpty(tempResultsError) ? ( No results} titleSize="s" @@ -319,25 +318,16 @@ export function EditQueryModal(props: EditQueryModalProps) { } /> - ) : !isEmpty(tempResultsError) ? ( + ) : (queryResponse === undefined || + isEmpty(queryResponse)) && + !isEmpty(tempResultsError) ? ( ) : ( - )} From c086392e476b309bd4479b5fb95651cdcce210e0 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 10 Dec 2024 10:07:25 -0800 Subject: [PATCH 08/10] cleanup Signed-off-by: Tyler Ohlsen --- public/pages/workflow_detail/tools/query/query.tsx | 4 ---- .../workflow_inputs/search_inputs/edit_query_modal.tsx | 3 --- 2 files changed, 7 deletions(-) diff --git a/public/pages/workflow_detail/tools/query/query.tsx b/public/pages/workflow_detail/tools/query/query.tsx index bb4d225f..155751d6 100644 --- a/public/pages/workflow_detail/tools/query/query.tsx +++ b/public/pages/workflow_detail/tools/query/query.tsx @@ -64,7 +64,6 @@ export function Query(props: QueryProps) { const [useCustomQuery, setUseCustomQuery] = useState(false); // query response state - // TODO: clean up how/what responses we are persisting and where. const [queryResponse, setQueryResponse] = useState< SearchResponse | undefined >(undefined); @@ -281,9 +280,6 @@ export function Query(props: QueryProps) { Results - {/** - * TODO: clean up how/what responses we are persisting - */} {queryResponse === undefined || isEmpty(queryResponse) ? ( No results} diff --git a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx index 132bd67d..3823bd29 100644 --- a/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx +++ b/public/pages/workflow_detail/workflow_inputs/search_inputs/edit_query_modal.tsx @@ -20,19 +20,16 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, - EuiCodeEditor, EuiEmptyPrompt, EuiCallOut, } from '@elastic/eui'; import { JsonField } from '../input_fields'; import { - customStringify, IConfigField, QUERY_PRESETS, QueryParam, QueryPreset, RequestFormValues, - SearchHit, SearchResponse, WorkflowFormValues, } from '../../../../../common'; From 49d22a8e064cff06cde637849d173eda5f2965b1 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 10 Dec 2024 10:14:07 -0800 Subject: [PATCH 09/10] clean up optional params on SearchResponse interface Signed-off-by: Tyler Ohlsen --- common/interfaces.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/interfaces.ts b/common/interfaces.ts index 037b552f..39cad171 100644 --- a/common/interfaces.ts +++ b/common/interfaces.ts @@ -605,7 +605,7 @@ export type SearchResponse = { skipped: number; failed: number; }; - hits?: { + hits: { total: { value: number; relation: string; @@ -614,7 +614,7 @@ export type SearchResponse = { hits: SearchHit[]; }; aggregations?: {}; - ext: {}; + ext?: {}; }; export type IndexResponse = { From 97b8cc21eaf2c6b4ef4eb6f041ca364c04121ea1 Mon Sep 17 00:00:00 2001 From: Tyler Ohlsen Date: Tue, 10 Dec 2024 10:16:30 -0800 Subject: [PATCH 10/10] more cleanup Signed-off-by: Tyler Ohlsen --- public/general_components/results/results_json.tsx | 3 +-- public/general_components/results/results_table.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/public/general_components/results/results_json.tsx b/public/general_components/results/results_json.tsx index 8cc18f5e..e2000c5f 100644 --- a/public/general_components/results/results_json.tsx +++ b/public/general_components/results/results_json.tsx @@ -12,8 +12,7 @@ interface ResultsJSONProps { } /** - * Small component to render the raw search response. Grows to fill - * the parent container by setting 100% width/height. + * Small component to render the raw search response. */ export function ResultsJSON(props: ResultsJSONProps) { return ( diff --git a/public/general_components/results/results_table.tsx b/public/general_components/results/results_table.tsx index 3c53a18b..d423dbd5 100644 --- a/public/general_components/results/results_table.tsx +++ b/public/general_components/results/results_table.tsx @@ -20,7 +20,7 @@ interface ResultsTableProps { /** * Small component to display a list of search results with pagination. - * Wrapped in a flexible panel with overflow handling. + * Can expand each entry to view the full _source response */ export function ResultsTable(props: ResultsTableProps) { const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<{