Просмотр исходного кода

Merge pull request #9750 from weseek/feat/163079-implement-preset-prompt-view

feat: Implement preset prompt view
Shun Miyazawa 1 год назад
Родитель
Сommit
39e0280abb

+ 11 - 1
apps/app/public/static/locales/en_US/translation.json

@@ -509,7 +509,17 @@
     "budget_exceeded": "You have reached your usage limit for OpenAI's API. To use the Knowledge Assistant again, please add credits from the OpenAI billing page.",
     "budget_exceeded_for_growi_cloud": "You have reached your OpenAI API usage limit. To use the Knowledge Assistant again, please add credits from the GROWI.cloud admin page for Hosted users or from the OpenAI billing page for Owned users.",
     "error_message": "An error has occurred",
-    "show_error_detail": "Show error details"
+    "show_error_detail": "Show error details",
+    "preset_menu": {
+      "summarize": {
+        "title": "Summarize this article",
+        "prompt": ""
+      },
+      "correct": {
+        "title": "Correct errors in the text",
+        "prompt": ""
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {

+ 11 - 1
apps/app/public/static/locales/fr_FR/translation.json

@@ -503,7 +503,17 @@
     "budget_exceeded": "Vous avez atteint votre limite d'utilisation de l'API de l'OpenAI. Pour utiliser à nouveau l'assistant de connaissance, veuillez ajouter des crédits à partir de la page de facturation d'OpenAI.",
     "budget_exceeded_for_growi_cloud": "Vous avez atteint votre limite d'utilisation de l'API de l'OpenAI. Pour utiliser à nouveau l'assistant de connaissance, veuillez ajouter des crédits à partir de la page d'administration de GROWI.cloud pour les utilisateurs hébergés ou à partir de la page de facturation de l'OpenAI pour les utilisateurs propriétaires.",
     "error_message": "Erreur",
-    "show_error_detail": "Détails de l'exposition"
+    "show_error_detail": "Détails de l'exposition",
+    "preset_menu": {
+      "summarize": {
+        "title": "Résumer cet article'",
+        "prompt": ""
+      },
+      "correct": {
+        "title": "Corriger les erreurs du texte",
+        "prompt": ""
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {

+ 11 - 1
apps/app/public/static/locales/ja_JP/translation.json

@@ -541,7 +541,17 @@
     "budget_exceeded": "OpenAI の API の利用上限に達しました。ナレッジアシスタントを再度利用するには OpenAI の請求ページからクレジットを追加してください。",
     "budget_exceeded_for_growi_cloud": "OpenAI の API の利用上限に達しました。ナレッジアシスタントを再度利用するには Hosted の場合は GROWI.cloud の管理画面から Owned の場合は OpenAI の請求ページからクレジットを追加してください。",
     "error_message": "エラーが発生しました",
-    "show_error_detail": "詳細を表示"
+    "show_error_detail": "詳細を表示",
+    "preset_menu": {
+      "summarize": {
+        "title": "この記事の要約をつくる",
+        "prompt": ""
+      },
+      "correct": {
+        "title": "文章の誤りを修正する",
+        "prompt": ""
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {

+ 11 - 1
apps/app/public/static/locales/zh_CN/translation.json

@@ -498,7 +498,17 @@
     "budget_exceeded": "您已达到 OpenAI API 的使用上限。要再次使用知识助手,请从 OpenAI 账单页面添加点数。",
     "budget_exceeded_for_growi_cloud": "您已达到 OpenAI API 使用上限。如需再次使用知识助手,请从GROWI.cloud管理页面为托管用户添加点数,或从OpenAI计费页面为自有用户添加点数。",
     "error_message": "错误",
-    "show_error_detail": "显示详情"
+    "show_error_detail": "显示详情",
+    "preset_menu": {
+      "summarize": {
+        "title": "为此文章创建摘要",
+        "prompt": ""
+      },
+      "correct": {
+        "title": "修正文本中的错误",
+        "prompt": ""
+      }
+    }
   },
   "modal_ai_assistant": {
     "header": {

+ 10 - 1
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/AiAssistantSidebar.tsx

@@ -24,6 +24,7 @@ import { useSWRMUTxThreads } from '../../../stores/thread';
 
 import { AiAssistantChatInitialView } from './AiAssistantChatInitialView';
 import { MessageCard } from './MessageCard';
+import { QuickMenuList } from './QuickMenuList';
 import { ResizableTextarea } from './ResizableTextArea';
 
 import styles from './AiAssistantSidebar.module.scss';
@@ -126,6 +127,10 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
       : 'sidebar_ai_assistant.knowledge_assistant_placeholder');
   }, [form.formState.isSubmitting, isEditorAssistant, t]);
 
+  const clickQuickMenuHandler = useCallback((quickMenu: string) => {
+    // todo: https://redmine.weseek.co.jp/issues/163264
+  }, []);
+
   const isGenerating = generatingAnswerMessage != null;
   const submit = useCallback(async(data: FormData) => {
     // do nothing when the assistant is generating an answer
@@ -336,7 +341,11 @@ const AiAssistantSidebarSubstance: React.FC<AiAssistantSidebarSubstanceProps> =
             )
             : (
               <>{isEditorAssistant
-                ? <></> // TODO https://redmine.weseek.co.jp/issues/163079
+                ? (
+                  <QuickMenuList
+                    onClick={clickQuickMenuHandler}
+                  />
+                )
                 : (
                   <AiAssistantChatInitialView
                     description={aiAssistantData?.description ?? ''}

+ 40 - 0
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantSidebar/QuickMenuList.tsx

@@ -0,0 +1,40 @@
+import { useCallback } from 'react';
+
+import { useTranslation } from 'react-i18next';
+
+type Props = {
+  onClick: (presetPrompt: string) => void
+}
+
+const presetMenus = [
+  'summarize',
+  'correct',
+];
+
+export const QuickMenuList: React.FC<Props> = ({ onClick }: Props) => {
+  const { t } = useTranslation();
+
+  const clickQuickMenuHandler = useCallback((quickMenu: string) => {
+    onClick(t(`sidebar_ai_assistant.preset_menu.${quickMenu}.prompt`));
+  }, [onClick, t]);
+
+  return (
+    <div className="container py-4">
+      <div className="d-flex flex-column gap-3">
+        {presetMenus.map(presetMenu => (
+          <button
+            type="button"
+            key={presetMenu}
+            onClick={() => clickQuickMenuHandler(presetMenu)}
+            className="btn text-body-secondary p-3 rounded-3 border border-1"
+          >
+            <div className="d-flex align-items-center">
+              <span className="material-symbols-outlined fs-5 me-3">lightbulb</span>
+              <span className="fs-6">{t(`sidebar_ai_assistant.preset_menu.${presetMenu}.title`)}</span>
+            </div>
+          </button>
+        ))}
+      </div>
+    </div>
+  );
+};