From fa08692258f8dd92becc2640a149aeabd8cf0172 Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Fri, 24 May 2024 12:32:44 -0700 Subject: [PATCH 1/8] feat: add status message below prompt editor --- web-src/src/components/PromptEditor.js | 52 +++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 81e43391..6fdb9f6c 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -20,7 +20,9 @@ import { useRecoilState, useRecoilValue } from 'recoil'; import { css, injectGlobal } from '@emotion/css'; import { Global } from '@emotion/react'; import { motion, AnimatePresence } from 'framer-motion'; +import CheckmarkCircle from '@spectrum-icons/workflow/CheckmarkCircle'; import Close from '@spectrum-icons/workflow/Close'; +import Alert from '@spectrum-icons/workflow/Alert'; import { useIntl } from 'react-intl'; import { intlMessages } from './PromptSessionSideView.l10n.js'; @@ -75,6 +77,15 @@ const style = { border-radius: 4px; padding: 12px; `, + containerError: css` + width: 100%; + height: 100%; + position: relative; + overflow: auto; + border: 1px solid var(--spectrum-red-900); + border-radius: 4px; + padding: 12px; + `, editor: css` font-family: Monospaced, monospace; font-size: 12px; @@ -86,24 +97,45 @@ const style = { textarea: css` outline: none; `, + errorHelpText: css` + margin-top: 15px; + color: var(--spectrum-red-900); + `, + validHelpText: css` + margin-top: 15px; + color: var(--spectrum-green-700); + `, + hidden: css` + display: none; + `, }; function PromptEditor({ isOpen, onClose, ...props }) { const [prompt, setPrompt] = useRecoilState(promptState); const [promptText, setPromptText] = useState(prompt); const [viewSource, setViewSource] = useState(false); + const [editorSyntaxError, setEditorSyntaxError] = useState(false); const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); const { formatMessage } = useIntl(); - useEffect(() => { setPrompt(promptText); const promptEditorTextArea = document.getElementById('promptEditorTextArea'); if (promptEditorTextArea) { promptEditorTextArea.setAttribute('title', 'Prompt Editor'); } + + // detect unsupported characters in editor + const regex = /=".*[{"}]+.*",/gm; + const matches = [...promptText.matchAll(regex)]; + + if (matches.length > 0) { + setEditorSyntaxError(true); + } else { + setEditorSyntaxError(false); + } }, [promptText, setPrompt]); useEffect(() => { @@ -181,7 +213,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { -
+
+ + + + + Prompt is valid + + + + + + + The characters {, }, + and " are reserved and can't be used within quoted text values. + Please remove or replace these characters and try again. + + )} From ef412eb0e795ed5e0986011069cb08011964804a Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Wed, 29 May 2024 09:02:00 -0700 Subject: [PATCH 2/8] feat: disable generate button on prompt syntax error --- web-src/src/components/GenerateButton.js | 4 +++- web-src/src/components/PromptEditor.js | 9 +++++---- web-src/src/state/PromptSyntaxErrorState.js | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 web-src/src/state/PromptSyntaxErrorState.js diff --git a/web-src/src/components/GenerateButton.js b/web-src/src/components/GenerateButton.js index 41dd5574..41ddddfe 100644 --- a/web-src/src/components/GenerateButton.js +++ b/web-src/src/components/GenerateButton.js @@ -34,6 +34,7 @@ import { log } from '../helpers/MetricsHelper.js'; import { contentFragmentState } from '../state/ContentFragmentState.js'; import { RUN_MODE_CF } from '../state/RunMode.js'; import { FIREFALL_ACTION_TYPES } from '../services/FirefallService.js'; +import { promptSyntaxErrorState } from '../state/PromptSyntaxErrorState.js'; const createWaitMessagesController = (intlFn) => { const displayToast = (msg, timeout = 1500) => { @@ -92,6 +93,7 @@ export function GenerateButton() { const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); const temperature = useRecoilValue(temperatureState); + const syntaxError = useRecoilValue(promptSyntaxErrorState); const setResults = useSetRecoilState(resultsState); const setIsOpenPromptEditor = useSetRecoilState(promptEditorState); @@ -154,7 +156,7 @@ export function GenerateButton() { variant="cta" style="fill" onPress={handleGenerate} - isDisabled={generationInProgress}> + isDisabled={generationInProgress || syntaxError}> {generationInProgress ? : } {formatMessage(intlMessages.promptSessionSideView.generateButtonLabel)} diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 6fdb9f6c..865fab8f 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -29,6 +29,7 @@ import { intlMessages } from './PromptSessionSideView.l10n.js'; import { parametersState } from '../state/ParametersState.js'; import { promptState } from '../state/PromptState.js'; +import { promptSyntaxErrorState } from '../state/PromptSyntaxErrorState.js'; import { NO_VALUE_STRING, renderPrompt } from '../helpers/PromptRenderer.js'; import { log } from '../helpers/MetricsHelper.js'; @@ -114,7 +115,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { const [prompt, setPrompt] = useRecoilState(promptState); const [promptText, setPromptText] = useState(prompt); const [viewSource, setViewSource] = useState(false); - const [editorSyntaxError, setEditorSyntaxError] = useState(false); + const [editorSyntaxError, setEditorSyntaxError] = useRecoilState(promptSyntaxErrorState); const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); @@ -128,7 +129,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { } // detect unsupported characters in editor - const regex = /=".*[{"}]+.*",/gm; + const regex = /=".*[{}"]+.*"/g; const matches = [...promptText.matchAll(regex)]; if (matches.length > 0) { @@ -239,8 +240,8 @@ function PromptEditor({ isOpen, onClose, ...props }) { - The characters {, }, - and " are reserved and can't be used within quoted text values. + The characters {, }, + and " are reserved and can't be used within quoted text values. Please remove or replace these characters and try again. diff --git a/web-src/src/state/PromptSyntaxErrorState.js b/web-src/src/state/PromptSyntaxErrorState.js new file mode 100644 index 00000000..b0bf2182 --- /dev/null +++ b/web-src/src/state/PromptSyntaxErrorState.js @@ -0,0 +1,18 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { atom } from 'recoil'; + +export const promptSyntaxErrorState = atom({ + key: 'promptSyntaxErrorState', + default: false, +}); From cce6097a6c22b9ff7f07906958b8741d458086d5 Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Fri, 31 May 2024 10:21:28 -0700 Subject: [PATCH 3/8] test: syntax error finder function --- web-src/src/components/PromptEditor.js | 18 +- web-src/src/components/PromptEditor.test.js | 200 ++++++++++++++++++++ 2 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 web-src/src/components/PromptEditor.test.js diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 865fab8f..0ac8412d 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -111,6 +111,11 @@ const style = { `, }; +export function findSyntaxError(prompt) { + const matches = [...prompt.matchAll(/=".*[{}"]+.*"/g)]; + return matches.length > 0; +} + function PromptEditor({ isOpen, onClose, ...props }) { const [prompt, setPrompt] = useRecoilState(promptState); const [promptText, setPromptText] = useState(prompt); @@ -121,6 +126,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { const contentFragment = useRecoilValue(contentFragmentState); const { formatMessage } = useIntl(); + useEffect(() => { setPrompt(promptText); const promptEditorTextArea = document.getElementById('promptEditorTextArea'); @@ -128,15 +134,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { promptEditorTextArea.setAttribute('title', 'Prompt Editor'); } - // detect unsupported characters in editor - const regex = /=".*[{}"]+.*"/g; - const matches = [...promptText.matchAll(regex)]; - - if (matches.length > 0) { - setEditorSyntaxError(true); - } else { - setEditorSyntaxError(false); - } + setEditorSyntaxError(findSyntaxError(promptText)); }, [promptText, setPrompt]); useEffect(() => { @@ -233,7 +231,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { - Prompt is valid + Prompt is valid. diff --git a/web-src/src/components/PromptEditor.test.js b/web-src/src/components/PromptEditor.test.js new file mode 100644 index 00000000..c5c8ee2d --- /dev/null +++ b/web-src/src/components/PromptEditor.test.js @@ -0,0 +1,200 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { findSyntaxError } from './PromptEditor.js'; + +describe('findSyntaxError', () => { + it('empty prompt', () => { + const prompt = ''; + expect(findSyntaxError(prompt)).toBe(false); + }); + + it('simple prompt with valid syntax', () => { + const prompt = 'This is a valid prompt.'; + expect(findSyntaxError(prompt)).toBe(false); + }); + + it('prompt with valid syntax', () => { + const prompt = `{{# -------------------------------------------------------------------------- }} + {{# REQUIREMENTS }} + {{# Specify any and all conditions your content must comply with to meet your }} + {{# brand writing guidelines. }} + {{# -------------------------------------------------------------------------- }} + Requirements: \`\`\` + - The text must consist of three parts: a Title, a Body and an "AI Rationale". + - The text must be brief, such that: + * In 20 words (100 characters) or less, compose the "AI Rationale" text first and use it to explain your reasoning for composing the copy, before composing the other parts. + * The Title text must not exceed 6 words or 30 characters, including spaces. + * The Body text must not exceed 13 words or 65 characters, including spaces. + - The tone of the text needs to be: {{tone_of_voice}}. + - The product name must appear once either in the Title text or Body text. + - Never abbreviate or shorten the name of the product in the text. + - Compose the text without using the same adjective more than once. + - Do not use exclamation marks or points at the end of sentences in the text. + - Do not use exclamation marks or points in the text. + - Format the response as an array of valid, iterable RFC8259 compliant JSON. Always list the "AI Rationale" attribute last. + \`\`\` + + {{# -------------------------------------------------------------------------- }} + {{# DOMAIN KNOWLEDGE AND TRUSTED SOURCE DOCUMENTS }} + {{# Here you will Provide more background information or specific details to }} + {{# guide the creation of the content. }} + {{# -------------------------------------------------------------------------- }} + Additional Context: [[ + {{domain_knowledge_and_trusted_source_documents}} + ]] + + {{# -------------------------------------------------------------------------- }} + {{# METADATA }} + {{# -------------------------------------------------------------------------- }} + {{@explain_interaction, + label="Explain user interaction", + description="Elaborate on the user's interaction with the element, emphasizing the results and impacts of the interaction", + default="the user is taken to a product page displaying a detailed view of our bestselling wireless headphones. Here, they can read product specifications, customer reviews, and make a purchase if they so choose", + type=text + }};`; + + expect(findSyntaxError(prompt)).toBe(false); + }); + + it('prompt with invalid syntax', () => { + const prompt = `{{# -------------------------------------------------------------------------- }} + {{# REQUIREMENTS }} + {{# Specify any and all conditions your content must comply with to meet your }} + {{# brand writing guidelines. }} + {{# -------------------------------------------------------------------------- }} + Requirements: \`\`\` + - The text must consist of three parts: a Title, a Body and an "AI Rationale". + - The text must be brief, such that: + * In 20 words (100 characters) or less, compose the "AI Rationale" text first and use it to explain your reasoning for composing the copy, before composing the other parts. + * The Title text must not exceed 6 words or 30 characters, including spaces. + * The Body text must not exceed 13 words or 65 characters, including spaces. + - The tone of the text needs to be: {{tone_of_voice}}. + - The product name must appear once either in the Title text or Body text. + - Never abbreviate or shorten the name of the product in the text. + - Compose the text without using the same adjective more than once. + - Do not use exclamation marks or points at the end of sentences in the text. + - Do not use exclamation marks or points in the text. + - Format the response as an array of valid, iterable RFC8259 compliant JSON. Always list the "AI Rationale" attribute last. + \`\`\` + + {{# -------------------------------------------------------------------------- }} + {{# DOMAIN KNOWLEDGE AND TRUSTED SOURCE DOCUMENTS }} + {{# Here you will Provide more background information or specific details to }} + {{# guide the creation of the content. }} + {{# -------------------------------------------------------------------------- }} + Additional Context: [[ + {{domain_knowledge_and_trusted_source_documents}} + ]] + + {{# -------------------------------------------------------------------------- }} + {{# METADATA }} + {{# -------------------------------------------------------------------------- }} + {{@explain_interaction, + label="Explain user interaction", + description="Elaborate on the user's interaction with the element, emphasizing the results and impacts of the interaction", + default="the user is taken to a {product page displaying a detailed view of our bestselling wireless headphones. Here, they can read product specifications, customer reviews, and make a purchase if they so choose", + type=text + }};`; + + expect(findSyntaxError(prompt)).toBe(true); + }); + + it('prompt with invalid syntax', () => { + const prompt = `{{# -------------------------------------------------------------------------- }} + {{# REQUIREMENTS }} + {{# Specify any and all conditions your content must comply with to meet your }} + {{# brand writing guidelines. }} + {{# -------------------------------------------------------------------------- }} + Requirements: \`\`\` + - The text must consist of three parts: a Title, a Body and an "AI Rationale". + - The text must be brief, such that: + * In 20 words (100 characters) or less, compose the "AI Rationale" text first and use it to explain your reasoning for composing the copy, before composing the other parts. + * The Title text must not exceed 6 words or 30 characters, including spaces. + * The Body text must not exceed 13 words or 65 characters, including spaces. + - The tone of the text needs to be: {{tone_of_voice}}. + - The product name must appear once either in the Title text or Body text. + - Never abbreviate or shorten the name of the product in the text. + - Compose the text without using the same adjective more than once. + - Do not use exclamation marks or points at the end of sentences in the text. + - Do not use exclamation marks or points in the text. + - Format the response as an array of valid, iterable RFC8259 compliant JSON. Always list the "AI Rationale" attribute last. + \`\`\` + + {{# -------------------------------------------------------------------------- }} + {{# DOMAIN KNOWLEDGE AND TRUSTED SOURCE DOCUMENTS }} + {{# Here you will Provide more background information or specific details to }} + {{# guide the creation of the content. }} + {{# -------------------------------------------------------------------------- }} + Additional Context: [[ + {{domain_knowledge_and_trusted_source_documents}} + ]] + + {{# -------------------------------------------------------------------------- }} + {{# METADATA }} + {{# -------------------------------------------------------------------------- }} + {{@explain_interaction, + label="Explain user interaction", + description="Elaborate on the user's interaction with the element, emphasizing the results and impacts of the interaction", + default="the user is taken to a {product page displaying a detailed view of our bestselling wireless headphones. Here, they can read product specifications, customer reviews, and make a purchase if they so choose", + type=text + }};`; + + expect(findSyntaxError(prompt)).toBe(true); + }); + + it('prompt with invalid syntax', () => { + const prompt = `{{# -------------------------------------------------------------------------- }} + {{# DOMAIN KNOWLEDGE AND TRUSTED SOURCE DOCUMENTS }} + {{# Here you will Provide more background information or specific details to }} + {{# guide the creation of the content. }} + {{# -------------------------------------------------------------------------- }} + Additional Context: [[ + {{domain_knowledge_and_trusted_source_documents}} + ]] + + {{# -------------------------------------------------------------------------- }} + {{# METADATA }} + {{# -------------------------------------------------------------------------- }} + {{@explain_interaction, + label="Explain user interaction", + description="Elaborate on the user's interaction}} with the element, emphasizing the results and impacts of the interaction", + default="the user is taken to a product page displaying a detailed view of our bestselling wireless headphones. Here, they can read product specifications, customer reviews, and make a purchase if they so choose", + type=text + }};`; + + expect(findSyntaxError(prompt)).toBe(true); + }); + + it('prompt with invalid syntax', () => { + const prompt = `{{# -------------------------------------------------------------------------- }} + {{# DOMAIN KNOWLEDGE AND TRUSTED SOURCE DOCUMENTS }} + {{# Here you will Provide more background information or specific details to }} + {{# guide the creation of the content. }} + {{# -------------------------------------------------------------------------- }} + Additional Context: [[ + {{domain_knowledge_and_trusted_source_documents}} + ]] + + {{# -------------------------------------------------------------------------- }} + {{# METADATA }} + {{# -------------------------------------------------------------------------- }} + {{@explain_interaction, + label="Explain user i"nteraction", + description="Elaborate on the user's interaction with the element, emphasizing the results and impacts of the interaction", + default="the user is taken to a product page displaying a detailed view of our bestselling wireless headphones. Here, they can read product specifications, customer reviews, and make a purchase if they so choose", + type=text + }};`; + + expect(findSyntaxError(prompt)).toBe(true); + }); +}); From 6b914e4535f195478cb0ba394e4324e060c161cb Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Tue, 4 Jun 2024 11:33:55 -0700 Subject: [PATCH 4/8] refactor: remove prompt editor error recoil state + valid prompt message --- web-src/src/components/GenerateButton.js | 6 ++--- web-src/src/components/PromptEditor.js | 24 +++++-------------- web-src/src/components/PromptSessionPanel.js | 14 +++++++---- .../src/components/PromptSessionSideView.js | 6 +++-- web-src/src/state/PromptSyntaxErrorState.js | 18 -------------- 5 files changed, 22 insertions(+), 46 deletions(-) delete mode 100644 web-src/src/state/PromptSyntaxErrorState.js diff --git a/web-src/src/components/GenerateButton.js b/web-src/src/components/GenerateButton.js index 41ddddfe..617b30fb 100644 --- a/web-src/src/components/GenerateButton.js +++ b/web-src/src/components/GenerateButton.js @@ -34,7 +34,6 @@ import { log } from '../helpers/MetricsHelper.js'; import { contentFragmentState } from '../state/ContentFragmentState.js'; import { RUN_MODE_CF } from '../state/RunMode.js'; import { FIREFALL_ACTION_TYPES } from '../services/FirefallService.js'; -import { promptSyntaxErrorState } from '../state/PromptSyntaxErrorState.js'; const createWaitMessagesController = (intlFn) => { const displayToast = (msg, timeout = 1500) => { @@ -87,13 +86,12 @@ const createWaitMessagesController = (intlFn) => { }; }; -export function GenerateButton() { +export function GenerateButton({ disabled }) { const { runMode, firefallService } = useApplicationContext(); const prompt = useRecoilValue(promptState); const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); const temperature = useRecoilValue(temperatureState); - const syntaxError = useRecoilValue(promptSyntaxErrorState); const setResults = useSetRecoilState(resultsState); const setIsOpenPromptEditor = useSetRecoilState(promptEditorState); @@ -156,7 +154,7 @@ export function GenerateButton() { variant="cta" style="fill" onPress={handleGenerate} - isDisabled={generationInProgress || syntaxError}> + isDisabled={disabled || generationInProgress}> {generationInProgress ? : } {formatMessage(intlMessages.promptSessionSideView.generateButtonLabel)} diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 0ac8412d..822b02c5 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -20,7 +20,6 @@ import { useRecoilState, useRecoilValue } from 'recoil'; import { css, injectGlobal } from '@emotion/css'; import { Global } from '@emotion/react'; import { motion, AnimatePresence } from 'framer-motion'; -import CheckmarkCircle from '@spectrum-icons/workflow/CheckmarkCircle'; import Close from '@spectrum-icons/workflow/Close'; import Alert from '@spectrum-icons/workflow/Alert'; import { useIntl } from 'react-intl'; @@ -29,7 +28,6 @@ import { intlMessages } from './PromptSessionSideView.l10n.js'; import { parametersState } from '../state/ParametersState.js'; import { promptState } from '../state/PromptState.js'; -import { promptSyntaxErrorState } from '../state/PromptSyntaxErrorState.js'; import { NO_VALUE_STRING, renderPrompt } from '../helpers/PromptRenderer.js'; import { log } from '../helpers/MetricsHelper.js'; @@ -102,10 +100,6 @@ const style = { margin-top: 15px; color: var(--spectrum-red-900); `, - validHelpText: css` - margin-top: 15px; - color: var(--spectrum-green-700); - `, hidden: css` display: none; `, @@ -116,11 +110,12 @@ export function findSyntaxError(prompt) { return matches.length > 0; } -function PromptEditor({ isOpen, onClose, ...props }) { +function PromptEditor({ + isOpen, onClose, error, setError, ...props +}) { const [prompt, setPrompt] = useRecoilState(promptState); const [promptText, setPromptText] = useState(prompt); const [viewSource, setViewSource] = useState(false); - const [editorSyntaxError, setEditorSyntaxError] = useRecoilState(promptSyntaxErrorState); const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); @@ -134,7 +129,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { promptEditorTextArea.setAttribute('title', 'Prompt Editor'); } - setEditorSyntaxError(findSyntaxError(promptText)); + setError(findSyntaxError(promptText)); }, [promptText, setPrompt]); useEffect(() => { @@ -212,7 +207,7 @@ function PromptEditor({ isOpen, onClose, ...props }) { -
+
- - - - Prompt is valid. - - - - + The characters {, }, diff --git a/web-src/src/components/PromptSessionPanel.js b/web-src/src/components/PromptSessionPanel.js index d7f50920..b7f336f5 100644 --- a/web-src/src/components/PromptSessionPanel.js +++ b/web-src/src/components/PromptSessionPanel.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ import { Flex, Grid } from '@adobe/react-spectrum'; -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { useRecoilState } from 'recoil'; import { PromptSessionSideView } from './PromptSessionSideView.js'; import { PromptResultListView } from './PromptResultListView.js'; @@ -20,6 +20,7 @@ import { log } from '../helpers/MetricsHelper.js'; export function PromptSessionPanel() { const [isOpenPromptEditor, setIsOpenPromptEditor] = useRecoilState(promptEditorState); + const [promptEditorError, setPromptEditorError] = useState(false); useEffect(() => { if (isOpenPromptEditor) { @@ -37,7 +38,8 @@ export function PromptSessionPanel() { height={'100%'}> setIsOpenPromptEditor(!isOpenPromptEditor)} /> + onTogglePrompt={() => setIsOpenPromptEditor(!isOpenPromptEditor)} + disableTextGeneration={promptEditorError} /> setIsOpenPromptEditor(false)} /> - setIsOpenPromptEditor(false)} /> + setIsOpenPromptEditor(false)} + error={promptEditorError} + setError={setPromptEditorError} + /> - ); } diff --git a/web-src/src/components/PromptSessionSideView.js b/web-src/src/components/PromptSessionSideView.js index f4c2bd1a..a5b2b67f 100644 --- a/web-src/src/components/PromptSessionSideView.js +++ b/web-src/src/components/PromptSessionSideView.js @@ -61,7 +61,9 @@ const styles = { `, }; -export function PromptSessionSideView({ isOpenPromptEditor, onTogglePrompt, ...props }) { +export function PromptSessionSideView({ + isOpenPromptEditor, onTogglePrompt, disableTextGeneration, ...props +}) { const currentSession = useRecoilValue(sessionState); const [viewType, setViewType] = useRecoilState(viewTypeState); const { formatMessage } = useIntl(); @@ -116,7 +118,7 @@ export function PromptSessionSideView({ isOpenPromptEditor, onTogglePrompt, ...p - +
diff --git a/web-src/src/state/PromptSyntaxErrorState.js b/web-src/src/state/PromptSyntaxErrorState.js deleted file mode 100644 index b0bf2182..00000000 --- a/web-src/src/state/PromptSyntaxErrorState.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2023 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -import { atom } from 'recoil'; - -export const promptSyntaxErrorState = atom({ - key: 'promptSyntaxErrorState', - default: false, -}); From b902eada8352258b3cec921900b57788171d71ab Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Mon, 10 Jun 2024 10:49:25 -0700 Subject: [PATCH 5/8] feat: disable save button on prompt error --- web-src/src/components/GenerateButton.js | 4 ++-- web-src/src/components/PromptSessionPanel.js | 2 +- web-src/src/components/PromptSessionSideView.js | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/web-src/src/components/GenerateButton.js b/web-src/src/components/GenerateButton.js index 617b30fb..5865b3cc 100644 --- a/web-src/src/components/GenerateButton.js +++ b/web-src/src/components/GenerateButton.js @@ -86,7 +86,7 @@ const createWaitMessagesController = (intlFn) => { }; }; -export function GenerateButton({ disabled }) { +export function GenerateButton({ isDisabled }) { const { runMode, firefallService } = useApplicationContext(); const prompt = useRecoilValue(promptState); const parameters = useRecoilValue(parametersState); @@ -154,7 +154,7 @@ export function GenerateButton({ disabled }) { variant="cta" style="fill" onPress={handleGenerate} - isDisabled={disabled || generationInProgress}> + isDisabled={isDisabled || generationInProgress}> {generationInProgress ? : } {formatMessage(intlMessages.promptSessionSideView.generateButtonLabel)} diff --git a/web-src/src/components/PromptSessionPanel.js b/web-src/src/components/PromptSessionPanel.js index b7f336f5..912c3602 100644 --- a/web-src/src/components/PromptSessionPanel.js +++ b/web-src/src/components/PromptSessionPanel.js @@ -39,7 +39,7 @@ export function PromptSessionPanel() { setIsOpenPromptEditor(!isOpenPromptEditor)} - disableTextGeneration={promptEditorError} /> + promptEditorError /> - + - +
- ); } From f45c361f8d38da6b1b0579c6b832d6890fbfd348 Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Mon, 10 Jun 2024 11:52:05 -0700 Subject: [PATCH 6/8] fix: state bug --- web-src/src/components/PromptEditor.js | 5 ++--- web-src/src/components/PromptSessionPanel.js | 6 ++++-- web-src/src/components/PromptSessionSideView.js | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 822b02c5..207b9445 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -226,9 +226,8 @@ function PromptEditor({ - The characters {, }, - and " are reserved and can't be used within quoted text values. - Please remove or replace these characters and try again. + The characters {, }, and " are reserved and can't + be used within quoted text values. Please remove or replace these characters and try again. diff --git a/web-src/src/components/PromptSessionPanel.js b/web-src/src/components/PromptSessionPanel.js index 912c3602..85ed7e88 100644 --- a/web-src/src/components/PromptSessionPanel.js +++ b/web-src/src/components/PromptSessionPanel.js @@ -37,9 +37,11 @@ export function PromptSessionPanel() { gap={'size-300'} height={'100%'}> - setIsOpenPromptEditor(!isOpenPromptEditor)} - promptEditorError /> + promptEditorError={promptEditorError} + /> Date: Mon, 10 Jun 2024 14:20:40 -0700 Subject: [PATCH 7/8] refactor: separate state hook for error message in PromptEditor --- web-src/src/components/PromptEditor.js | 11 +++++++---- web-src/src/components/PromptSessionPanel.js | 3 +-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/web-src/src/components/PromptEditor.js b/web-src/src/components/PromptEditor.js index 207b9445..cba71246 100644 --- a/web-src/src/components/PromptEditor.js +++ b/web-src/src/components/PromptEditor.js @@ -111,11 +111,12 @@ export function findSyntaxError(prompt) { } function PromptEditor({ - isOpen, onClose, error, setError, ...props + isOpen, onClose, setPromptValidationError, ...props }) { const [prompt, setPrompt] = useRecoilState(promptState); const [promptText, setPromptText] = useState(prompt); const [viewSource, setViewSource] = useState(false); + const [showErrorMsg, setShowErrorMsg] = useState(false); const parameters = useRecoilValue(parametersState); const contentFragment = useRecoilValue(contentFragmentState); @@ -129,7 +130,9 @@ function PromptEditor({ promptEditorTextArea.setAttribute('title', 'Prompt Editor'); } - setError(findSyntaxError(promptText)); + const isErrorFound = findSyntaxError(promptText); + setShowErrorMsg(isErrorFound); + setPromptValidationError(isErrorFound); }, [promptText, setPrompt]); useEffect(() => { @@ -207,7 +210,7 @@ function PromptEditor({ -
+
- + The characters {, }, and " are reserved and can't diff --git a/web-src/src/components/PromptSessionPanel.js b/web-src/src/components/PromptSessionPanel.js index 85ed7e88..d9fd1645 100644 --- a/web-src/src/components/PromptSessionPanel.js +++ b/web-src/src/components/PromptSessionPanel.js @@ -58,8 +58,7 @@ export function PromptSessionPanel() { setIsOpenPromptEditor(false)} - error={promptEditorError} - setError={setPromptEditorError} + setPromptValidationError={setPromptEditorError} /> From 4133731f4648347bc26c5509776933b5ca106373 Mon Sep 17 00:00:00 2001 From: Audrey Kho Date: Tue, 11 Jun 2024 07:21:52 -0700 Subject: [PATCH 8/8] chore: remove log --- web-src/src/components/PromptSessionSideView.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/web-src/src/components/PromptSessionSideView.js b/web-src/src/components/PromptSessionSideView.js index 25f9018c..0da380db 100644 --- a/web-src/src/components/PromptSessionSideView.js +++ b/web-src/src/components/PromptSessionSideView.js @@ -68,8 +68,6 @@ export function PromptSessionSideView({ const [viewType, setViewType] = useRecoilState(viewTypeState); const { formatMessage } = useIntl(); - console.log('PromptSessionSideView.js: promptEditorError:', promptEditorError); - return (