onSubmit()}
+ isDisabled={loading || inputQuestion.trim().length === 0 || !selectedSource}
display="base"
size="s"
iconType="returnKey"
@@ -453,13 +474,23 @@ export const Text2Viz = () => {
paddingSize="none"
scrollable={false}
>
- {usageCollection ? (
-
- ) : null}
+
+ {usageCollection ? (
+
+
+
+ ) : null}
+
+ onSubmit(instruction)}
+ value={currentInstruction}
+ />
+
+
diff --git a/public/components/visualization/viz_style_editor.test.tsx b/public/components/visualization/viz_style_editor.test.tsx
new file mode 100644
index 00000000..7c2c6a61
--- /dev/null
+++ b/public/components/visualization/viz_style_editor.test.tsx
@@ -0,0 +1,44 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import { VizStyleEditor } from './viz_style_editor';
+
+describe('', () => {
+ test('should render visual style editor', () => {
+ const onApplyFn = jest.fn();
+ render();
+ expect(screen.queryByText('Edit visual')).toBeInTheDocument();
+
+ // click Edit visual button to open the modal
+ expect(screen.queryByTestId('text2vizStyleEditorModal')).toBe(null);
+ fireEvent.click(screen.getByText('Edit visual'));
+ expect(screen.queryByTestId('text2vizStyleEditorModal')).toBeInTheDocument();
+
+ // Click cancel to close the modal
+ fireEvent.click(screen.getByText('Cancel'));
+ expect(screen.queryByTestId('text2vizStyleEditorModal')).toBe(null);
+
+ // Apply button is disabled
+ fireEvent.click(screen.getByText('Edit visual'));
+ expect(screen.getByTestId('text2vizStyleEditorModalApply')).toBeDisabled();
+
+ // After input text, Apply button is enabled
+ fireEvent.input(screen.getByLabelText('Input instructions to tweak the visual'), {
+ target: { value: 'test input' },
+ });
+ expect(screen.getByTestId('text2vizStyleEditorModalApply')).not.toBeDisabled();
+ fireEvent.click(screen.getByText('Apply'));
+ expect(onApplyFn).toHaveBeenCalledWith('test input');
+ expect(screen.queryByTestId('text2vizStyleEditorModal')).toBe(null);
+ });
+
+ test('should open the modal with initial value', () => {
+ render();
+ fireEvent.click(screen.getByText('Edit visual'));
+ expect(screen.getByDisplayValue('test input')).toBeInTheDocument();
+ });
+});
diff --git a/public/components/visualization/viz_style_editor.tsx b/public/components/visualization/viz_style_editor.tsx
new file mode 100644
index 00000000..0d35796e
--- /dev/null
+++ b/public/components/visualization/viz_style_editor.tsx
@@ -0,0 +1,101 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { useCallback, useState } from 'react';
+import {
+ EuiButton,
+ EuiButtonEmpty,
+ EuiModal,
+ EuiModalBody,
+ EuiModalFooter,
+ EuiModalHeader,
+ EuiModalHeaderTitle,
+ EuiSpacer,
+ EuiTextArea,
+} from '@elastic/eui';
+import { i18n } from '@osd/i18n';
+
+interface Props {
+ onApply: (input: string) => void;
+ value?: string;
+ iconType: string;
+ className?: string;
+}
+
+export const VizStyleEditor = ({ onApply, className, iconType, value }: Props) => {
+ const [modalVisible, setModalVisible] = useState(false);
+ const [inputValue, setInputValue] = useState('');
+
+ const onApplyClick = useCallback(() => {
+ onApply(inputValue.trim());
+ setModalVisible(false);
+ }, [inputValue, onApply]);
+
+ const openModal = useCallback(() => {
+ if (value) {
+ setInputValue(value);
+ }
+ setModalVisible(true);
+ }, [value]);
+
+ return (
+
+
+ {i18n.translate('dashboardAssistant.feature.text2viz.editVisualButton.label', {
+ defaultMessage: 'Edit visual',
+ })}
+
+ {modalVisible && (
+ setModalVisible(false)}>
+
+
+
+ {i18n.translate('dashboardAssistant.feature.text2viz.editVisualModal.title', {
+ defaultMessage: 'Edit visual',
+ })}
+
+
+
+
+ {i18n.translate('dashboardAssistant.feature.text2viz.editVisualModal.body', {
+ defaultMessage: 'How would you like to edit the visual?',
+ })}
+
+ setInputValue(e.target.value)}
+ />
+
+
+ setModalVisible(false)}>
+ {i18n.translate('dashboardAssistant.feature.text2viz.editVisualModal.cancel', {
+ defaultMessage: 'Cancel',
+ })}
+
+
+ {i18n.translate('dashboardAssistant.feature.text2viz.editVisualModal.apply', {
+ defaultMessage: 'Apply',
+ })}
+
+
+
+ )}
+
+ );
+};
diff --git a/server/routes/agent_routes.ts b/server/routes/agent_routes.ts
index 227143a7..57e85e66 100644
--- a/server/routes/agent_routes.ts
+++ b/server/routes/agent_routes.ts
@@ -39,7 +39,7 @@ export function registerAgentRoutes(router: IRouter, assistantService: Assistant
);
return res.ok({ body: response });
} catch (e) {
- return res.internalError();
+ return res.badRequest();
}
})
);