diff --git a/public/components/ui_action_context_menu.tsx b/public/components/ui_action_context_menu.tsx index e15fbed6..f57d1279 100644 --- a/public/components/ui_action_context_menu.tsx +++ b/public/components/ui_action_context_menu.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { EuiButtonEmpty, EuiContextMenu, EuiPopover } from '@elastic/eui'; import { i18n } from '@osd/i18n'; @@ -11,8 +11,10 @@ import { i18n } from '@osd/i18n'; import { buildContextMenuForActions } from '../../../../src/plugins/ui_actions/public'; import { AI_ASSISTANT_QUERY_EDITOR_TRIGGER } from '../ui_triggers'; import { getUiActions } from '../services'; +import { DataPublicPluginSetup } from '../../../../src/plugins/data/public'; interface Props { + data: DataPublicPluginSetup; label?: string; } @@ -20,26 +22,54 @@ export const ActionContextMenu = (props: Props) => { const uiActions = getUiActions(); const actionsRef = useRef(uiActions.getTriggerActions(AI_ASSISTANT_QUERY_EDITOR_TRIGGER)); const [open, setOpen] = useState(false); + const [actionContext, setActionContext] = useState({ + datasetId: props.data.query.queryString.getQuery().dataset?.id ?? '', + datasetType: props.data.query.queryString.getQuery().dataset?.type ?? '', + dataSourceId: props.data.query.queryString.getQuery().dataset?.dataSource?.id, + }); + + useEffect(() => { + const subscription = props.data.query.queryString.getUpdates$().subscribe((query) => { + if (query.dataset) { + setActionContext((state) => ({ + ...state, + datasetId: query.dataset?.id ?? '', + datasetType: query.dataset?.type ?? '', + dataSourceId: query.dataset?.dataSource?.id, + })); + } + }); + return () => { + subscription.unsubscribe(); + }; + }, [props.data.query.queryString]); const panels = useAsync( () => buildContextMenuForActions({ actions: actionsRef.current.map((action) => ({ action, - context: {}, + context: { + datasetId: actionContext.datasetId, + datasetType: actionContext.datasetType, + dataSourceId: actionContext.dataSourceId, + }, // eslint-disable-next-line @typescript-eslint/no-explicit-any trigger: AI_ASSISTANT_QUERY_EDITOR_TRIGGER as any, })), closeMenu: () => setOpen(false), title: '', }), - [] + [actionContext.datasetId, actionContext.datasetType, actionContext.dataSourceId] ); if (actionsRef.current.length === 0) { return null; } + // If context menu has no item, the action button should be disabled + const actionDisabled = (panels.value?.[0]?.items ?? []).length === 0; + return ( { onClick={() => setOpen(!open)} iconSide="right" flush="both" + isDisabled={actionDisabled} + isLoading={panels.loading} > {props.label || i18n.translate('dashboardAssistant.branding.assistantActionButton.label', { diff --git a/public/plugin.tsx b/public/plugin.tsx index fc18eb60..eac6bafc 100644 --- a/public/plugin.tsx +++ b/public/plugin.tsx @@ -47,7 +47,13 @@ import { } from './services'; import { ConfigSchema } from '../common/types/config'; import { DataSourceService } from './services/data_source_service'; -import { ASSISTANT_API, DEFAULT_USER_NAME } from '../common/constants/llm'; +import { + ASSISTANT_API, + DEFAULT_USER_NAME, + TEXT2PPL_AGENT_CONFIG_ID, + TEXT2VEGA_RULE_BASED_AGENT_CONFIG_ID, + TEXT2VEGA_WITH_INSTRUCTIONS_AGENT_CONFIG_ID, +} from '../common/constants/llm'; import { IncontextInsightProps } from './components/incontext_insight'; import { AssistantService } from './services/assistant_service'; import { ActionContextMenu } from './components/ui_action_context_menu'; @@ -260,7 +266,7 @@ export class AssistantPlugin order: 2000, isEnabled$: () => of(true), getSearchBarButton: () => { - return ; + return ; }, }, }, @@ -328,6 +334,24 @@ export class AssistantPlugin order: 1, getDisplayName: () => 'Generate visualization', getIconType: () => 'visLine' as const, + // T2Viz is only compatible with data sources that have certain agents configured + isCompatible: async (context) => { + // t2viz only supports selecting index pattern at the moment + if (context.datasetType === 'INDEX_PATTERN' && context.datasetId) { + const res = await assistantServiceStart.client.agentConfigExists( + [ + TEXT2VEGA_RULE_BASED_AGENT_CONFIG_ID, + TEXT2VEGA_WITH_INSTRUCTIONS_AGENT_CONFIG_ID, + TEXT2PPL_AGENT_CONFIG_ID, + ], + { + dataSourceId: context.dataSourceId, + } + ); + return res.exists; + } + return false; + }, execute: async () => { core.application.navigateToApp(TEXT2VIZ_APP_ID); }, diff --git a/public/ui_triggers.ts b/public/ui_triggers.ts index 48718b45..1cad3e1d 100644 --- a/public/ui_triggers.ts +++ b/public/ui_triggers.ts @@ -9,7 +9,11 @@ export const AI_ASSISTANT_QUERY_EDITOR_TRIGGER = 'AI_ASSISTANT_QUERY_EDITOR_TRIG declare module '../../../src/plugins/ui_actions/public' { export interface TriggerContextMapping { - [AI_ASSISTANT_QUERY_EDITOR_TRIGGER]: {}; + [AI_ASSISTANT_QUERY_EDITOR_TRIGGER]: { + datasetId: string; + datasetType: string; + dataSourceId?: string; + }; } }