|
@@ -4,6 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react';
|
|
|
import { useForm, Controller } from 'react-hook-form';
|
|
import { useForm, Controller } from 'react-hook-form';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
import {
|
|
import {
|
|
|
|
|
+ Collapse,
|
|
|
Modal, ModalBody, ModalFooter, ModalHeader,
|
|
Modal, ModalBody, ModalFooter, ModalHeader,
|
|
|
} from 'reactstrap';
|
|
} from 'reactstrap';
|
|
|
|
|
|
|
@@ -48,6 +49,8 @@ const AiChatModalSubstance = (): JSX.Element => {
|
|
|
const [threadId, setThreadId] = useState<string | undefined>();
|
|
const [threadId, setThreadId] = useState<string | undefined>();
|
|
|
const [messageLogs, setMessageLogs] = useState<Message[]>([]);
|
|
const [messageLogs, setMessageLogs] = useState<Message[]>([]);
|
|
|
const [generatingAnswerMessage, setGeneratingAnswerMessage] = useState<Message>();
|
|
const [generatingAnswerMessage, setGeneratingAnswerMessage] = useState<Message>();
|
|
|
|
|
+ const [errorMessage, setErrorMessage] = useState<string | undefined>();
|
|
|
|
|
+ const [isErrorDetailCollapsed, setIsErrorDetailCollapsed] = useState<boolean>(false);
|
|
|
|
|
|
|
|
const { data: growiCloudUri } = useGrowiCloudUri();
|
|
const { data: growiCloudUri } = useGrowiCloudUri();
|
|
|
|
|
|
|
@@ -95,6 +98,7 @@ const AiChatModalSubstance = (): JSX.Element => {
|
|
|
|
|
|
|
|
// reset form
|
|
// reset form
|
|
|
form.reset();
|
|
form.reset();
|
|
|
|
|
+ setErrorMessage(undefined);
|
|
|
|
|
|
|
|
// add an empty assistant message
|
|
// add an empty assistant message
|
|
|
const newAnswerMessage = { id: (logLength + 1).toString(), content: '' };
|
|
const newAnswerMessage = { id: (logLength + 1).toString(), content: '' };
|
|
@@ -157,11 +161,8 @@ const AiChatModalSubstance = (): JSX.Element => {
|
|
|
logger.error(error.errorMessage);
|
|
logger.error(error.errorMessage);
|
|
|
form.setError('input', { type: 'manual', message: error.message });
|
|
form.setError('input', { type: 'manual', message: error.message });
|
|
|
|
|
|
|
|
- if (error.code === StreamErrorCode.RATE_LIMIT_EXCEEDED) {
|
|
|
|
|
- const toastErrorMessage = growiCloudUri != null
|
|
|
|
|
- ? 'modal_aichat.rate_limit_exceeded_for_growi_cloud'
|
|
|
|
|
- : 'modal_aichat.rate_limit_exceeded';
|
|
|
|
|
- toastError(t(toastErrorMessage));
|
|
|
|
|
|
|
+ if (error.code === StreamErrorCode.BUDGET_EXCEEDED) {
|
|
|
|
|
+ setErrorMessage(growiCloudUri != null ? 'modal_aichat.budget_exceeded_for_growi_cloud' : 'modal_aichat.budget_exceeded');
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
@@ -241,7 +242,34 @@ const AiChatModalSubstance = (): JSX.Element => {
|
|
|
</form>
|
|
</form>
|
|
|
|
|
|
|
|
{form.formState.errors.input != null && (
|
|
{form.formState.errors.input != null && (
|
|
|
- <span className="text-danger small">{form.formState.errors.input?.message}</span>
|
|
|
|
|
|
|
+ <div className="mt-4 bg-danger bg-opacity-10 rounded-3 p-2 w-100">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span className="material-symbols-outlined text-danger me-2">error</span>
|
|
|
|
|
+ <span className="text-danger">{ errorMessage != null ? t(errorMessage) : t('modal_aichat.error_message') }</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-link text-secondary p-0"
|
|
|
|
|
+ aria-expanded={isErrorDetailCollapsed}
|
|
|
|
|
+ onClick={() => setIsErrorDetailCollapsed(!isErrorDetailCollapsed)}
|
|
|
|
|
+ >
|
|
|
|
|
+ <span className={`material-symbols-outlined mt-2 me-1 ${isErrorDetailCollapsed ? 'rotate-90' : ''}`}>
|
|
|
|
|
+ chevron_right
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="small">{t('modal_aichat.show_error_detail')}</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+
|
|
|
|
|
+ <Collapse isOpen={isErrorDetailCollapsed}>
|
|
|
|
|
+ <div className="ms-2">
|
|
|
|
|
+ <div className="">
|
|
|
|
|
+ <div className="text-secondary small">
|
|
|
|
|
+ {form.formState.errors.input?.message}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </Collapse>
|
|
|
|
|
+ </div>
|
|
|
)}
|
|
)}
|
|
|
</ModalFooter>
|
|
</ModalFooter>
|
|
|
</>
|
|
</>
|