diff --git a/changelogs/fragments/9277.yml b/changelogs/fragments/9277.yml new file mode 100644 index 000000000000..c9db1e8fa4e8 --- /dev/null +++ b/changelogs/fragments/9277.yml @@ -0,0 +1,2 @@ +fix: +- Hide the assistant entry when there isn't data2summary agent ([#9277](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9277)) \ No newline at end of file diff --git a/src/plugins/query_enhancements/public/plugin.tsx b/src/plugins/query_enhancements/public/plugin.tsx index 71ad2302b99e..c08c72d7f3a5 100644 --- a/src/plugins/query_enhancements/public/plugin.tsx +++ b/src/plugins/query_enhancements/public/plugin.tsx @@ -38,6 +38,7 @@ export class QueryEnhancementsPlugin private readonly config: ConfigSchema; private isQuerySummaryCollapsed$ = new BehaviorSubject(false); private resultSummaryEnabled$ = new BehaviorSubject(false); + private isSummaryAgentAvailable$ = new BehaviorSubject(false); constructor(initializerContext: PluginInitializerContext) { this.config = initializerContext.config.get(); @@ -192,6 +193,7 @@ export class QueryEnhancementsPlugin data, this.config.queryAssist, this.isQuerySummaryCollapsed$, + this.isSummaryAgentAvailable$, this.resultSummaryEnabled$, usageCollection ), @@ -203,6 +205,7 @@ export class QueryEnhancementsPlugin return { isQuerySummaryCollapsed$: this.isQuerySummaryCollapsed$, resultSummaryEnabled$: this.resultSummaryEnabled$, + isSummaryAgentAvailable$: this.isSummaryAgentAvailable$, }; } diff --git a/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.test.tsx b/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.test.tsx index a716b300704e..6b7f0d65ffd3 100644 --- a/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.test.tsx +++ b/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.test.tsx @@ -10,7 +10,6 @@ import { QueryAssistSummary, convertResult } from './query_assist_summary'; import { useQueryAssist } from '../hooks'; import { IDataFrame, Query } from '../../../../data/common'; import { FeedbackStatus as FEEDBACK } from '../../../common/query_assist'; -import { checkAgentsExist } from '../utils/get_is_summary_agent'; jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -22,8 +21,6 @@ jest.mock('../hooks', () => ({ useQueryAssist: jest.fn(), })); -jest.mock('../utils/get_is_summary_agent', () => ({ checkAgentsExist: jest.fn() })); - describe('query assist summary', () => { const PPL = 'ppl'; const question = 'Are there any errors in my logs?'; @@ -45,7 +42,6 @@ describe('query assist summary', () => { const setSummary = jest.fn(); const setLoading = jest.fn(); const setFeedback = jest.fn(); - const setIsSummaryAgentAvailable = jest.fn(); const setIsAssistantEnabledByCapability = jest.fn(); const getQuery = jest.fn(); const dataMock = { @@ -62,10 +58,6 @@ describe('query assist summary', () => { }, }; - beforeEach(() => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: false }); - }); - afterEach(() => { data$.next(undefined); question$.next(''); @@ -99,6 +91,11 @@ describe('query assist summary', () => { NO: false, }; + const ISSUMMARYAGENT = { + YES: true, + NO: false, + }; + const renderQueryAssistSummary = (isCollapsed: boolean) => { const component = render(
@@ -123,9 +120,9 @@ describe('query assist summary', () => { summary, loading, feedback, - isSummaryAgentAvailable = false, isAssistantEnabledByCapability = true, - isQuerySummaryCollapsed = COLLAPSED.NO + isQuerySummaryCollapsed = COLLAPSED.NO, + isSummaryAgentAvailable = ISSUMMARYAGENT.YES ) => { React.useState.mockImplementationOnce(() => [summary, setSummary]); React.useState.mockImplementationOnce(() => [loading, setLoading]); @@ -134,14 +131,12 @@ describe('query assist summary', () => { isAssistantEnabledByCapability, setIsAssistantEnabledByCapability, ]); - React.useState.mockImplementationOnce(() => [ - isSummaryAgentAvailable, - setIsSummaryAgentAvailable, - ]); + useQueryAssist.mockImplementationOnce(() => ({ question: 'question', question$, isQuerySummaryCollapsed, + isSummaryAgentAvailable, })); }; @@ -164,8 +159,7 @@ describe('query assist summary', () => { }); it('should not show if is not summary agent', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: false }); - mockUseState(null, LOADING.NO, FEEDBACK.NONE, false); + mockUseState(null, LOADING.NO, FEEDBACK.NONE, false, ISSUMMARYAGENT.NO); renderQueryAssistSummary(COLLAPSED.NO); const summaryPanels = screen.queryAllByTestId('queryAssist__summary'); expect(summaryPanels).toHaveLength(0); @@ -179,7 +173,6 @@ describe('query assist summary', () => { }); it('should show if collapsed is false', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState(null, LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); const summaryPanels = screen.queryAllByTestId('queryAssist__summary'); @@ -187,7 +180,6 @@ describe('query assist summary', () => { }); it('should show if summary agent', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState(null, LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); const summaryPanels = screen.queryAllByTestId('queryAssist__summary'); @@ -195,7 +187,6 @@ describe('query assist summary', () => { }); it('should display loading view if loading state is true', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState(null, LOADING.YES, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.queryAllByTestId('queryAssist_summary_result')).toHaveLength(0); @@ -203,7 +194,6 @@ describe('query assist summary', () => { }); it('should display loading view if loading state is true even with summary', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.YES, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_loading')).toBeInTheDocument(); @@ -212,7 +202,6 @@ describe('query assist summary', () => { }); it('should display initial view if loading state is false and no summary', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); defaultUseStateMock(); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_empty_text')).toBeInTheDocument(); @@ -221,7 +210,6 @@ describe('query assist summary', () => { }); it('should display summary result', () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_result')).toBeInTheDocument(); @@ -231,7 +219,6 @@ describe('query assist summary', () => { }); it('should report metric for thumbup click', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_result')).toBeInTheDocument(); @@ -246,7 +233,6 @@ describe('query assist summary', () => { }); it('should report metric for thumbdown click', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_result')).toBeInTheDocument(); @@ -261,7 +247,6 @@ describe('query assist summary', () => { }); it('should hide thumbdown button if thumbup button is clicked', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.THUMB_UP, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_result')).toBeInTheDocument(); @@ -270,8 +255,6 @@ describe('query assist summary', () => { }); it('should hide thumbup button if thumbdown button is clicked', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); - mockUseState('summary', LOADING.NO, FEEDBACK.THUMB_DOWN, true); renderQueryAssistSummary(COLLAPSED.NO); expect(screen.getByTestId('queryAssist_summary_result')).toBeInTheDocument(); @@ -280,7 +263,6 @@ describe('query assist summary', () => { }); it('should not fetch summary if data is empty', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState(null, LOADING.NO, FEEDBACK.NONE, true); renderQueryAssistSummary(COLLAPSED.NO); question$.next(question); @@ -330,7 +312,6 @@ describe('query assist summary', () => { }); it('should not update queryResults if subscription changed not in order', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.NONE); const RESPONSE_TEXT = 'response'; httpMock.post.mockResolvedValue(RESPONSE_TEXT); @@ -343,7 +324,6 @@ describe('query assist summary', () => { }); it('should update queryResults if subscriptions changed in order', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.NONE); const RESPONSE_TEXT = 'response'; httpMock.post.mockResolvedValue(RESPONSE_TEXT); @@ -362,7 +342,6 @@ describe('query assist summary', () => { }); it('should reset feedback state if re-fetch summary', async () => { - (checkAgentsExist as jest.Mock).mockResolvedValue({ exist: true }); mockUseState('summary', LOADING.NO, FEEDBACK.THUMB_UP); const RESPONSE_TEXT = 'response'; httpMock.post.mockResolvedValue(RESPONSE_TEXT); diff --git a/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.tsx b/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.tsx index 3cfc189dad14..0077ade27b9a 100644 --- a/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.tsx +++ b/src/plugins/query_enhancements/public/query_assist/components/query_assist_summary.tsx @@ -30,8 +30,6 @@ import { QueryAssistContextType } from '../../../common/query_assist'; import sparkleHollowSvg from '../../assets/sparkle_hollow.svg'; import sparkleSolidSvg from '../../assets/sparkle_solid.svg'; import { FeedbackStatus } from '../../../common/query_assist'; -import { checkAgentsExist } from '../utils/get_is_summary_agent'; -import { DATA2SUMMARY_AGENT_CONFIG_ID } from '../utils/constant'; export interface QueryContext { question: string; @@ -72,9 +70,8 @@ export const QueryAssistSummary: React.FC = (props) => const [loading, setLoading] = useState(false); // track loading state const [feedback, setFeedback] = useState(FeedbackStatus.NONE); const [isEnabledByCapability, setIsEnabledByCapability] = useState(false); - const [isSummaryAgentAvailable, setIsSummaryAgentAvailable] = useState(false); const selectedDataset = useRef(query.queryString.getQuery()?.dataset); - const { question$, isQuerySummaryCollapsed } = useQueryAssist(); + const { question$, isQuerySummaryCollapsed, isSummaryAgentAvailable } = useQueryAssist(); const METRIC_APP = `query-assist`; const afterFeedbackTip = i18n.translate('queryEnhancements.queryAssist.summary.afterFeedback', { defaultMessage: @@ -209,26 +206,6 @@ export const QueryAssistSummary: React.FC = (props) => }); }, [props.core]); - useEffect(() => { - setIsSummaryAgentAvailable(false); - const fetchSummaryAgent = async () => { - try { - const summaryAgentStatus = await checkAgentsExist( - props.http, - DATA2SUMMARY_AGENT_CONFIG_ID, - selectedDataset.current?.dataSource?.id - ); - setIsSummaryAgentAvailable(summaryAgentStatus.exists); - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); - } - }; - if (isEnabledByCapability) { - fetchSummaryAgent(); - } - }, [selectedDataset.current?.dataSource?.id, props.http, isEnabledByCapability]); - const onFeedback = useCallback( (satisfied: boolean) => { if (feedback !== FeedbackStatus.NONE) return; diff --git a/src/plugins/query_enhancements/public/query_assist/hooks/use_query_assist.ts b/src/plugins/query_enhancements/public/query_assist/hooks/use_query_assist.ts index 1fbff27fc9a0..bf4c481de5bd 100644 --- a/src/plugins/query_enhancements/public/query_assist/hooks/use_query_assist.ts +++ b/src/plugins/query_enhancements/public/query_assist/hooks/use_query_assist.ts @@ -10,6 +10,7 @@ export interface QueryAssistContextValue { question$: BehaviorSubject; updateQuestion: (question: string) => void; isQuerySummaryCollapsed: boolean; + isSummaryAgentAvailable: boolean; } export const QueryAssistContext = React.createContext( {} as QueryAssistContextValue diff --git a/src/plugins/query_enhancements/public/query_assist/utils/create_extension.tsx b/src/plugins/query_enhancements/public/query_assist/utils/create_extension.tsx index 04ec1941dc80..9c587ec5d1fd 100644 --- a/src/plugins/query_enhancements/public/query_assist/utils/create_extension.tsx +++ b/src/plugins/query_enhancements/public/query_assist/utils/create_extension.tsx @@ -6,7 +6,8 @@ import { i18n } from '@osd/i18n'; import { HttpSetup } from 'opensearch-dashboards/public'; import React, { useEffect, useState } from 'react'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, of } from 'rxjs'; +import { useObservable } from 'react-use'; import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; import { DATA_STRUCTURE_META_TYPES, DEFAULT_DATA } from '../../../../data/common'; import { @@ -93,6 +94,7 @@ export const createQueryAssistExtension = ( data: DataPublicPluginSetup, config: ConfigSchema['queryAssist'], isQuerySummaryCollapsed$: BehaviorSubject, + isSummaryAgentAvailable$: BehaviorSubject, resultSummaryEnabled$: BehaviorSubject, usageCollection?: UsageCollectionSetup ): QueryEditorExtensionConfig => { @@ -125,6 +127,7 @@ export const createQueryAssistExtension = ( http={http} data={data} isQuerySummaryCollapsed$={isQuerySummaryCollapsed$} + isSummaryAgentAvailable$={isSummaryAgentAvailable$} {...(config.summary.enabled && { resultSummaryEnabled$ })} question$={question$} > @@ -162,6 +165,7 @@ interface QueryAssistWrapperProps { invert?: boolean; isQuerySummaryCollapsed$?: BehaviorSubject; resultSummaryEnabled$?: BehaviorSubject; + isSummaryAgentAvailable$?: BehaviorSubject; question$?: BehaviorSubject; } @@ -169,6 +173,7 @@ const QueryAssistWrapper: React.FC = (props) => { const [visible, setVisible] = useState(false); const [question, setQuestion] = useState(''); const [isQuerySummaryCollapsed, setIsQuerySummaryCollapsed] = useState(true); + const isSummaryAgentAvailable = useObservable(props.isSummaryAgentAvailable$ ?? of(false), false); const updateQuestion = (newQuestion: string) => { props.question$?.next(newQuestion); }; @@ -178,6 +183,7 @@ const QueryAssistWrapper: React.FC = (props) => { const subscription = props.isQuerySummaryCollapsed$?.subscribe((isCollapsed) => { setIsQuerySummaryCollapsed(isCollapsed); }); + const questionSubscription = props.question$?.subscribe((newQuestion) => { setQuestion(newQuestion); }); @@ -216,6 +222,7 @@ const QueryAssistWrapper: React.FC = (props) => { question$, updateQuestion, isQuerySummaryCollapsed, + isSummaryAgentAvailable, }} > {props.children} diff --git a/src/plugins/query_enhancements/public/types.ts b/src/plugins/query_enhancements/public/types.ts index 628e1889cd1d..a2d3e4d9d570 100644 --- a/src/plugins/query_enhancements/public/types.ts +++ b/src/plugins/query_enhancements/public/types.ts @@ -12,6 +12,7 @@ import { UsageCollectionSetup } from '../../usage_collection/public'; export interface QueryEnhancementsPluginSetup { isQuerySummaryCollapsed$: BehaviorSubject; resultSummaryEnabled$: BehaviorSubject; + isSummaryAgentAvailable$: BehaviorSubject; } // eslint-disable-next-line @typescript-eslint/no-empty-interface