From 0821c3aff29af887f4d32249af68662d97d0eaf6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 27 Sep 2024 06:59:27 +0000 Subject: [PATCH] T2viz ux improvements (#330) * fix(t2viz): UI fix and improvements 1. Only preselect index pattern that is enabled 2. Display an error toast when PPL query returns no result 3. Disable nature language input if no index pattern was selected Signed-off-by: Yulong Ruan --------- Signed-off-by: Yulong Ruan (cherry picked from commit 3cdd0e2ea1a6949cbf1a44138567b5d28f76d324) Signed-off-by: github-actions[bot] # Conflicts: # CHANGELOG.md --- common/types/config.ts | 3 +- public/components/ui_action_context_menu.tsx | 1 + .../visualization/source_selector.tsx | 57 +++++++++++-------- public/components/visualization/text2vega.ts | 3 + public/components/visualization/text2viz.tsx | 10 ++-- public/plugin.tsx | 1 + public/types.ts | 2 + 7 files changed, 49 insertions(+), 28 deletions(-) diff --git a/common/types/config.ts b/common/types/config.ts index 74531362..2b92644f 100644 --- a/common/types/config.ts +++ b/common/types/config.ts @@ -26,7 +26,8 @@ export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), }), branding: schema.object({ - label: schema.string({ defaultValue: '' }), + label: schema.maybe(schema.string()), + logo: schema.maybe(schema.string()), }), }); diff --git a/public/components/ui_action_context_menu.tsx b/public/components/ui_action_context_menu.tsx index 0e5b9f14..e15fbed6 100644 --- a/public/components/ui_action_context_menu.tsx +++ b/public/components/ui_action_context_menu.tsx @@ -31,6 +31,7 @@ export const ActionContextMenu = (props: Props) => { trigger: AI_ASSISTANT_QUERY_EDITOR_TRIGGER as any, })), closeMenu: () => setOpen(false), + title: '', }), [] ); diff --git a/public/components/visualization/source_selector.tsx b/public/components/visualization/source_selector.tsx index 90438a4e..3cbb620d 100644 --- a/public/components/visualization/source_selector.tsx +++ b/public/components/visualization/source_selector.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useCallback, useMemo, useState, useEffect } from 'react'; +import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react'; import { i18n } from '@osd/i18n'; import { useOpenSearchDashboards } from '../../../../../src/plugins/opensearch_dashboards_react/public'; @@ -38,6 +38,8 @@ export const SourceSelector = ({ } = useOpenSearchDashboards(); const [currentDataSources, setCurrentDataSources] = useState([]); const [dataSourceOptions, setDataSourceOptions] = useState([]); + const onChangeRef = useRef(onChange); + onChangeRef.current = onChange; const selectedSources = useMemo(() => { if (selectedSourceId) { @@ -52,13 +54,20 @@ export const SourceSelector = ({ return []; }, [selectedSourceId, dataSourceOptions]); + /** + * When initialized, select the first non-disabled option + */ useEffect(() => { if ( !selectedSourceId && dataSourceOptions.length > 0 && dataSourceOptions[0].options.length > 0 ) { - onChange(dataSourceOptions[0].options[0]); + const options = dataSourceOptions[0].options; + const selectedOption = options.find((o) => !o.disabled); + if (selectedOption) { + onChangeRef.current(selectedOption); + } } }, [selectedSourceId, dataSourceOptions]); @@ -81,7 +90,7 @@ export const SourceSelector = ({ const onSetDataSourceOptions = useCallback( async (options: DataSourceGroup[]) => { - // Only support opensearch default data source + // Only support OpenSearch default data source const indexPatternOptions = options.find( (item) => item.groupType === DEFAULT_DATA_SOURCE_TYPE ); @@ -117,28 +126,30 @@ export const SourceSelector = ({ * Check each data source to see if text to vega agents are configured or not * If not configured, disable the corresponding index pattern from the selection list */ - Object.keys(dataSourceIdToIndexPatternIds).forEach(async (key) => { - const res = await assistantService.client.agentConfigExists( - [ - TEXT2VEGA_RULE_BASED_AGENT_CONFIG_ID, - TEXT2VEGA_WITH_INSTRUCTIONS_AGENT_CONFIG_ID, - TEXT2PPL_AGENT_CONFIG_ID, - ], - { - dataSourceId: key !== 'DEFAULT' ? key : undefined, - } - ); - if (!res.exists) { - dataSourceIdToIndexPatternIds[key].forEach((indexPatternId) => { - indexPatternOptions.options.forEach((option) => { - if (option.value === indexPatternId) { - option.disabled = true; - } + const updateIndexPatternPromises = Object.keys(dataSourceIdToIndexPatternIds).map( + async (key) => { + const res = await assistantService.client.agentConfigExists( + [ + TEXT2VEGA_RULE_BASED_AGENT_CONFIG_ID, + TEXT2VEGA_WITH_INSTRUCTIONS_AGENT_CONFIG_ID, + TEXT2PPL_AGENT_CONFIG_ID, + ], + { + dataSourceId: key !== 'DEFAULT' ? key : undefined, + } + ); + if (!res.exists) { + dataSourceIdToIndexPatternIds[key].forEach((indexPatternId) => { + indexPatternOptions.options.forEach((option) => { + if (option.value === indexPatternId) { + option.disabled = true; + } + }); }); - }); + } } - }); - + ); + await Promise.allSettled(updateIndexPatternPromises); setDataSourceOptions([indexPatternOptions]); }, [currentDataSources] diff --git a/public/components/visualization/text2vega.ts b/public/components/visualization/text2vega.ts index 44964971..aba0e388 100644 --- a/public/components/visualization/text2vega.ts +++ b/public/components/visualization/text2vega.ts @@ -63,6 +63,9 @@ export class Text2Vega { ) // eslint-disable-next-line @typescript-eslint/no-explicit-any .toPromise(); + if (res.rawResponse.total === 0) { + throw new Error(`There is no result with the generated query: '${value.ppl}'.`); + } return { ...value, sample: res.rawResponse }; }), // call llm to generate vega diff --git a/public/components/visualization/text2viz.tsx b/public/components/visualization/text2viz.tsx index a3b2ad78..99ee35e8 100644 --- a/public/components/visualization/text2viz.tsx +++ b/public/components/visualization/text2viz.tsx @@ -67,6 +67,7 @@ export const Text2Viz = () => { data, uiSettings, savedObjects, + config, }, } = useOpenSearchDashboards(); @@ -106,7 +107,7 @@ export const Text2Viz = () => { if (result.error) { notifications.toasts.addError(result.error, { title: i18n.translate('dashboardAssistant.feature.text2viz.error', { - defaultMessage: 'Error while executing text to vega', + defaultMessage: 'Error while executing text to visualization', }), }); } else { @@ -198,7 +199,7 @@ export const Text2Viz = () => { }); setSubmitting(false); - }, [selectedSource, input, status]); + }, [selectedSource, input, status, notifications.toasts]); /** * Display the save visualization dialog to persist the current generated visualization @@ -342,16 +343,17 @@ export const Text2Viz = () => { onChange={(e) => setInput(e.target.value)} fullWidth compressed - prepend={} + prepend={} placeholder="Generate visualization with a natural language question." onKeyDown={(e) => e.key === 'Enter' && onSubmit()} + disabled={!selectedSource} /> { diff --git a/public/types.ts b/public/types.ts index f6c279ae..317f78c2 100644 --- a/public/types.ts +++ b/public/types.ts @@ -22,6 +22,7 @@ import { ExpressionsSetup, ExpressionsStart } from '../../../src/plugins/express import { SavedObjectsStart } from '../../../src/plugins/saved_objects/public'; import { UsageCollectionSetup } from '../../../src/plugins/usage_collection/public'; +import { ConfigSchema } from '../common/types/config'; export interface RenderProps { props: MessageContentProps; @@ -95,6 +96,7 @@ export interface AssistantStart { export type StartServices = CoreStart & Omit & { setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; + config: ConfigSchema; }; export interface UserAccount {