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

Merge pull request #9600 from weseek/feat/160855-edit-referenced-page

feat: Edit referenced page
Shun Miyazawa 1 год назад
Родитель
Сommit
0bb96fd405

+ 52 - 0
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/AiAssistantManagementEditPages.tsx

@@ -0,0 +1,52 @@
+import React, { useCallback } from 'react';
+
+import { ModalBody } from 'reactstrap';
+
+import type { IPageForItem } from '~/interfaces/page';
+import { usePageSelectModal } from '~/stores/modal';
+
+import type { SelectedPage } from '../../../../interfaces/selected-page';
+import { SelectedPageList } from '../../Common/SelectedPageList';
+
+import { AiAssistantManagementHeader } from './AiAssistantManagementHeader';
+
+
+type Props = {
+  selectedPages: SelectedPage[];
+  onSelect: (page: IPageForItem, isIncludeSubPage: boolean) => void;
+  onRemove: (pageId: string) => void;
+}
+
+export const AiAssistantManagementEditPages = (props: Props): JSX.Element => {
+  const { selectedPages, onSelect, onRemove } = props;
+
+  const { open: openPageSelectModal } = usePageSelectModal();
+
+  const clickOpenPageSelectModalHandler = useCallback(() => {
+    openPageSelectModal({ onSelected: onSelect, isHierarchicalSelectionMode: true });
+  }, [onSelect, openPageSelectModal]);
+
+  return (
+    <>
+      <AiAssistantManagementHeader />
+
+      <ModalBody className="px-4">
+        <p className="text-secondary py-1">
+          アシスタントが参照するページを編集します。<br />
+          参照できるページは配下ページも含めて200ページまでです。
+        </p>
+
+        <button
+          type="button"
+          onClick={clickOpenPageSelectModalHandler}
+          className="btn btn-outline-primary w-100 mb-3 d-flex align-items-center justify-content-center"
+        >
+          <span className="material-symbols-outlined me-2">add</span>
+          ページを追加する
+        </button>
+
+        <SelectedPageList selectedPages={selectedPages} onRemove={onRemove} />
+      </ModalBody>
+    </>
+  );
+};

+ 1 - 0
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/AiAssistantManagementHome.tsx

@@ -65,6 +65,7 @@ export const AiAssistantManagementHome = (props: Props): JSX.Element => {
 
             <button
               type="button"
+              onClick={() => { changePageMode(AiAssistantManagementModalPageMode.PAGES) }}
               className="btn w-100 d-flex justify-content-between align-items-center py-3 mb-2 border-0"
             >
               <span className="fw-normal">{t('modal_ai_assistant.page_mode_title.pages')}</span>

+ 24 - 18
apps/app/src/features/openai/client/components/AiAssistant/AiAssistantManagementModal/AiAssistantManagementModal.tsx

@@ -5,15 +5,14 @@ import { Modal } from 'reactstrap';
 
 import { toastError, toastSuccess } from '~/client/util/toastr';
 import type { IPageForItem } from '~/interfaces/page';
-import { usePageSelectModal } from '~/stores/modal';
 import loggerFactory from '~/utils/logger';
 
 import type { SelectedPage } from '../../../../interfaces/selected-page';
 import { createAiAssistant } from '../../../services/ai-assistant';
 import { useAiAssistantManagementModal, AiAssistantManagementModalPageMode } from '../../../stores/ai-assistant';
-import { SelectedPageList } from '../../Common/SelectedPageList';
 
 import { AiAssistantManagementEditInstruction } from './AiAssistantManagementEditInstruction';
+import { AiAssistantManagementEditPages } from './AiAssistantManagementEditPages';
 import { AiAssistantManagementHome } from './AiAssistantManagementHome';
 
 import styles from './AiAssistantManagementModal.module.scss';
@@ -25,7 +24,6 @@ const logger = loggerFactory('growi:openai:client:components:AiAssistantManageme
 const AiAssistantManagementModalSubstance = (): JSX.Element => {
   // Hooks
   const { t } = useTranslation();
-  const { open: openPageSelectModal } = usePageSelectModal();
   const { data: aiAssistantManagementModalData } = useAiAssistantManagementModal();
 
   const pageMode = aiAssistantManagementModalData?.pageMode ?? AiAssistantManagementModalPageMode.HOME;
@@ -35,21 +33,6 @@ const AiAssistantManagementModalSubstance = (): JSX.Element => {
   const [instruction, setInstruction] = useState<string>(t('modal_ai_assistant.default_instruction'));
 
   // Functions
-  const clickOpenPageSelectModalHandler = useCallback(() => {
-    const onSelected = (page: IPageForItem, isIncludeSubPage: boolean) => {
-      const selectedPageIds = selectedPages.map(selectedPage => selectedPage.page._id);
-      if (page._id != null && !selectedPageIds.includes(page._id)) {
-        setSelectedPages([...selectedPages, { page, isIncludeSubPage }]);
-      }
-    };
-
-    openPageSelectModal({ onSelected, isHierarchicalSelectionMode: true });
-  }, [openPageSelectModal, selectedPages]);
-
-  const clickRmoveSelectedPageHandler = useCallback((pageId: string) => {
-    setSelectedPages(selectedPages.filter(selectedPage => selectedPage.page._id !== pageId));
-  }, [selectedPages]);
-
   const clickCreateAiAssistantHandler = useCallback(async() => {
     try {
       const pagePathPatterns = selectedPages
@@ -73,6 +56,21 @@ const AiAssistantManagementModalSubstance = (): JSX.Element => {
   }, [instruction, selectedPages]);
 
 
+  /*
+  *  For AiAssistantManagementEditPages methods
+  */
+  const selectPageHandler = useCallback((page: IPageForItem, isIncludeSubPage: boolean) => {
+    const selectedPageIds = selectedPages.map(selectedPage => selectedPage.page._id);
+    if (page._id != null && !selectedPageIds.includes(page._id)) {
+      setSelectedPages([...selectedPages, { page, isIncludeSubPage }]);
+    }
+  }, [selectedPages]);
+
+  const removePageHandler = useCallback((pageId: string) => {
+    setSelectedPages(selectedPages.filter(selectedPage => selectedPage.page._id !== pageId));
+  }, [selectedPages]);
+
+
   /*
   *  For AiAssistantManagementEditInstruction methods
   */
@@ -92,6 +90,14 @@ const AiAssistantManagementModalSubstance = (): JSX.Element => {
         />
       )}
 
+      {pageMode === AiAssistantManagementModalPageMode.PAGES && (
+        <AiAssistantManagementEditPages
+          selectedPages={selectedPages}
+          onSelect={selectPageHandler}
+          onRemove={removePageHandler}
+        />
+      )}
+
       {pageMode === AiAssistantManagementModalPageMode.INSTRUCTION && (
         <AiAssistantManagementEditInstruction
           instruction={instruction}

+ 17 - 11
apps/app/src/features/openai/client/components/Common/SelectedPageList.tsx

@@ -1,8 +1,5 @@
-import type { FC } from 'react';
 import { memo } from 'react';
 
-import { useTranslation } from 'react-i18next';
-
 import type { SelectedPage } from '../../../interfaces/selected-page';
 
 type SelectedPageListProps = {
@@ -10,9 +7,7 @@ type SelectedPageListProps = {
   onRemove?: (pageId?: string) => void;
 };
 
-const SelectedPageListBase: FC<SelectedPageListProps> = ({ selectedPages, onRemove }) => {
-  const { t } = useTranslation();
-
+const SelectedPageListBase: React.FC<SelectedPageListProps> = ({ selectedPages, onRemove }: SelectedPageListProps) => {
   if (selectedPages.length === 0) {
     return <></>;
   }
@@ -20,12 +15,23 @@ const SelectedPageListBase: FC<SelectedPageListProps> = ({ selectedPages, onRemo
   return (
     <div className="mb-3">
       {selectedPages.map(({ page, isIncludeSubPage }) => (
-        <div key={page._id} className="mb-1 d-flex align-items-center">
-          <code>{ page.path }</code>
-          {isIncludeSubPage && <span className="badge rounded-pill text-bg-secondary ms-2">{t('Include Subordinated Page')}</span>}
+        <div
+          key={page._id}
+          className="mb-2 d-flex justify-content-between align-items-center bg-light rounded py-2 px-3"
+        >
+          <div className="d-flex align-items-center overflow-hidden">
+            { isIncludeSubPage
+              ? <>{`${page.path}/*`}</>
+              : <>{page.path}</>
+            }
+          </div>
           {onRemove != null && page._id != null && page._id && (
-            <button className="btn border-0 " type="button" onClick={() => onRemove(page._id)}>
-              <span className="fs-5 material-symbols-outlined text-secondary">delete</span>
+            <button
+              type="button"
+              className="btn p-0 ms-3 text-secondary"
+              onClick={() => onRemove(page._id)}
+            >
+              <span className="material-symbols-outlined fs-4">delete</span>
             </button>
           )}
         </div>