Spaces:
Sleeping
Sleeping
GitHub Actions commited on
Commit ·
4ab7df8
1
Parent(s): 74a041f
Deploy from GitHub Actions [DEV] - 2025-10-31 05:57:32
Browse files
app/refresh-moments/improvement-result/improvement-proposal-client.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { RegulationModal } from '@/components/improvement-result/regulation-moda
|
|
| 11 |
import { Bread } from '@/components/parts/bread';
|
| 12 |
import { ErrorDisplay } from '@/components/parts/error-display';
|
| 13 |
import { Button } from '@/components/ui/button';
|
|
|
|
| 14 |
import { useEnvironment } from '@/hooks/use-environment';
|
| 15 |
import { useImprovementResultExpressTestMode } from '@/hooks/use-improvement-result-express-test-mode';
|
| 16 |
import { useNotificationPermission } from '@/hooks/use-notification-permission';
|
|
@@ -505,6 +506,13 @@ function ImprovementProposalContent({ isDummyMode: propIsDummyMode = false, isEx
|
|
| 505 |
dummyMode: isDummyMode,
|
| 506 |
});
|
| 507 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
// function markChangedWords(original: Record<string, unknown>, regulated: Record<string, unknown>): Record<string, unknown> {
|
| 509 |
// if (!regulated) return original;
|
| 510 |
|
|
@@ -693,8 +701,8 @@ function ImprovementProposalContent({ isDummyMode: propIsDummyMode = false, isEx
|
|
| 693 |
}
|
| 694 |
};
|
| 695 |
|
| 696 |
-
// ローディング状態を統合
|
| 697 |
-
const isLoading = isProposalsLoading || isAnalysisLoading ||
|
| 698 |
|
| 699 |
// エラー判定のデバッグ
|
| 700 |
useEffect(() => {
|
|
@@ -739,8 +747,8 @@ function ImprovementProposalContent({ isDummyMode: propIsDummyMode = false, isEx
|
|
| 739 |
);
|
| 740 |
}
|
| 741 |
|
| 742 |
-
// エラー表示(
|
| 743 |
-
if (
|
| 744 |
const errorMessage = proposalTabsError instanceof Error ? proposalTabsError.message : 'データの取得に失敗しました';
|
| 745 |
return (
|
| 746 |
<div className="flex flex-col space-y-10">
|
|
|
|
| 11 |
import { Bread } from '@/components/parts/bread';
|
| 12 |
import { ErrorDisplay } from '@/components/parts/error-display';
|
| 13 |
import { Button } from '@/components/ui/button';
|
| 14 |
+
import { useDelayedErrorDisplay } from '@/hooks/use-delayed-error-display';
|
| 15 |
import { useEnvironment } from '@/hooks/use-environment';
|
| 16 |
import { useImprovementResultExpressTestMode } from '@/hooks/use-improvement-result-express-test-mode';
|
| 17 |
import { useNotificationPermission } from '@/hooks/use-notification-permission';
|
|
|
|
| 506 |
dummyMode: isDummyMode,
|
| 507 |
});
|
| 508 |
|
| 509 |
+
// 遅延エラー表示Hook(90秒間ローディング表示を継続)
|
| 510 |
+
const { shouldShowError, shouldShowLoading } = useDelayedErrorDisplay({
|
| 511 |
+
error: proposalTabsError,
|
| 512 |
+
isLoading: proposalTabsLoading,
|
| 513 |
+
delayMs: 90000, // 90秒(本番設定)
|
| 514 |
+
});
|
| 515 |
+
|
| 516 |
// function markChangedWords(original: Record<string, unknown>, regulated: Record<string, unknown>): Record<string, unknown> {
|
| 517 |
// if (!regulated) return original;
|
| 518 |
|
|
|
|
| 701 |
}
|
| 702 |
};
|
| 703 |
|
| 704 |
+
// ローディング状態を統合(遅延エラー表示を考慮)
|
| 705 |
+
const isLoading = isProposalsLoading || isAnalysisLoading || shouldShowLoading;
|
| 706 |
|
| 707 |
// エラー判定のデバッグ
|
| 708 |
useEffect(() => {
|
|
|
|
| 747 |
);
|
| 748 |
}
|
| 749 |
|
| 750 |
+
// エラー表示(90秒遅延後に表示)
|
| 751 |
+
if (shouldShowError) {
|
| 752 |
const errorMessage = proposalTabsError instanceof Error ? proposalTabsError.message : 'データの取得に失敗しました';
|
| 753 |
return (
|
| 754 |
<div className="flex flex-col space-y-10">
|
components/pages/index/pre-analysis-check.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import Image from 'next/image';
|
|
| 6 |
|
| 7 |
import { usePreAnalysis } from '@/api-client/gradio-proxy/use-pre-analysis';
|
| 8 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
|
|
|
| 9 |
import { useGlobalStore } from '@/store/global';
|
| 10 |
import { useInputStore } from '@/store/input';
|
| 11 |
import { useResultStore } from '@/store/result';
|
|
@@ -40,7 +41,7 @@ export default function PreAnalysisCheck({ retryButtonRef }: PreAnalysisCheckPro
|
|
| 40 |
const [localCompetitionUrls] = useState(competitionUrls);
|
| 41 |
const [isFieldsChanged, setIsFieldsChanged] = useState(false);
|
| 42 |
const [errorMessage, setErrorMessage] = useState<string>('');
|
| 43 |
-
const [showError, setShowError] = useState(false);
|
| 44 |
const [imageErrors, setImageErrors] = useState<{ [url: string]: boolean }>({});
|
| 45 |
|
| 46 |
// メールアドレスが変わったらuserIdentifierを更新
|
|
@@ -99,6 +100,13 @@ export default function PreAnalysisCheck({ retryButtonRef }: PreAnalysisCheckPro
|
|
| 99 |
userIdentifier: getUserIdentifier(),
|
| 100 |
});
|
| 101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
const onSubmit = useCallback(async () => {
|
| 103 |
console.log('[DEBUG] onSubmit called');
|
| 104 |
console.log('[DEBUG] dummyMode:', dummyMode);
|
|
@@ -156,9 +164,8 @@ export default function PreAnalysisCheck({ retryButtonRef }: PreAnalysisCheckPro
|
|
| 156 |
setShowAnalysisError(true);
|
| 157 |
setGetScoreLoading(false);
|
| 158 |
|
| 159 |
-
// ローカル状態も設定(
|
| 160 |
setErrorMessage(message);
|
| 161 |
-
setShowError(true);
|
| 162 |
}
|
| 163 |
}, [dummyMode, checkUrlFvErrors, localUpdatedCompetitionUrls, setGetScoreLoading, preAnalysis, router, setAnalysisError, setShowAnalysisError]);
|
| 164 |
|
|
@@ -349,14 +356,16 @@ export default function PreAnalysisCheck({ retryButtonRef }: PreAnalysisCheckPro
|
|
| 349 |
)}
|
| 350 |
|
| 351 |
{/* エラー表示とリトライボタン */}
|
| 352 |
-
{showError && (
|
| 353 |
<div className="flex min-h-[400px] flex-col items-center justify-center p-8">
|
| 354 |
<div className="mx-auto max-w-md text-center">
|
| 355 |
<AlertTriangle className="mx-auto mb-4 h-16 w-16 text-red-500" />
|
| 356 |
<h2 className="mb-2 text-2xl font-semibold text-gray-900">エラーが発生しました</h2>
|
| 357 |
<p className="mb-6 text-gray-600">
|
| 358 |
申し訳ございません。予期しないエラーが発生しました。
|
| 359 |
-
{errorMessage &&
|
|
|
|
|
|
|
| 360 |
</p>
|
| 361 |
<div className="flex justify-center gap-3">
|
| 362 |
<Button
|
|
|
|
| 6 |
|
| 7 |
import { usePreAnalysis } from '@/api-client/gradio-proxy/use-pre-analysis';
|
| 8 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
| 9 |
+
import { useDelayedErrorDisplay } from '@/hooks/use-delayed-error-display';
|
| 10 |
import { useGlobalStore } from '@/store/global';
|
| 11 |
import { useInputStore } from '@/store/input';
|
| 12 |
import { useResultStore } from '@/store/result';
|
|
|
|
| 41 |
const [localCompetitionUrls] = useState(competitionUrls);
|
| 42 |
const [isFieldsChanged, setIsFieldsChanged] = useState(false);
|
| 43 |
const [errorMessage, setErrorMessage] = useState<string>('');
|
| 44 |
+
const [showError, setShowError] = useState(false); // バリデーションエラー用(即座に表示)
|
| 45 |
const [imageErrors, setImageErrors] = useState<{ [url: string]: boolean }>({});
|
| 46 |
|
| 47 |
// メールアドレスが変わったらuserIdentifierを更新
|
|
|
|
| 100 |
userIdentifier: getUserIdentifier(),
|
| 101 |
});
|
| 102 |
|
| 103 |
+
// 90秒遅延エラー表示
|
| 104 |
+
const { shouldShowError } = useDelayedErrorDisplay({
|
| 105 |
+
error: preAnalysis.error,
|
| 106 |
+
isLoading: preAnalysis.isLoading,
|
| 107 |
+
delayMs: 90000, // 90秒(本番設定)
|
| 108 |
+
});
|
| 109 |
+
|
| 110 |
const onSubmit = useCallback(async () => {
|
| 111 |
console.log('[DEBUG] onSubmit called');
|
| 112 |
console.log('[DEBUG] dummyMode:', dummyMode);
|
|
|
|
| 164 |
setShowAnalysisError(true);
|
| 165 |
setGetScoreLoading(false);
|
| 166 |
|
| 167 |
+
// ローカル状態も設定(カスタマイズされたエラーメッセージのため)
|
| 168 |
setErrorMessage(message);
|
|
|
|
| 169 |
}
|
| 170 |
}, [dummyMode, checkUrlFvErrors, localUpdatedCompetitionUrls, setGetScoreLoading, preAnalysis, router, setAnalysisError, setShowAnalysisError]);
|
| 171 |
|
|
|
|
| 356 |
)}
|
| 357 |
|
| 358 |
{/* エラー表示とリトライボタン */}
|
| 359 |
+
{(shouldShowError || showError) && (
|
| 360 |
<div className="flex min-h-[400px] flex-col items-center justify-center p-8">
|
| 361 |
<div className="mx-auto max-w-md text-center">
|
| 362 |
<AlertTriangle className="mx-auto mb-4 h-16 w-16 text-red-500" />
|
| 363 |
<h2 className="mb-2 text-2xl font-semibold text-gray-900">エラーが発生しました</h2>
|
| 364 |
<p className="mb-6 text-gray-600">
|
| 365 |
申し訳ございません。予期しないエラーが発生しました。
|
| 366 |
+
{(preAnalysis.error?.message || errorMessage) && (
|
| 367 |
+
<span className="mt-2 block text-sm text-gray-500">{preAnalysis.error?.message || errorMessage}</span>
|
| 368 |
+
)}
|
| 369 |
</p>
|
| 370 |
<div className="flex justify-center gap-3">
|
| 371 |
<Button
|
components/pages/updatedui/pre-analysis-check-update.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import Image from 'next/image';
|
|
| 6 |
|
| 7 |
import { usePreAnalysis } from '@/api-client/gradio-proxy/use-pre-analysis';
|
| 8 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
|
|
|
| 9 |
import { useGlobalStore } from '@/store/global';
|
| 10 |
import { useInputStore } from '@/store/input';
|
| 11 |
import { useResultStore } from '@/store/result';
|
|
@@ -31,7 +32,7 @@ export default function PreAnalysisCheckUpdate() {
|
|
| 31 |
competitionUrls.filter((url) => !checkUrlFvErrors.includes(url)),
|
| 32 |
);
|
| 33 |
const [errorMessage, setErrorMessage] = useState<string>('');
|
| 34 |
-
const [showError, setShowError] = useState(false);
|
| 35 |
const { tempImages, commonDict } = useResultStore();
|
| 36 |
const [imageErrors, setImageErrors] = useState<{ [url: string]: boolean }>({});
|
| 37 |
|
|
@@ -91,6 +92,13 @@ export default function PreAnalysisCheckUpdate() {
|
|
| 91 |
userIdentifier: getUserIdentifier(),
|
| 92 |
});
|
| 93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
const onSubmit = useCallback(async () => {
|
| 95 |
console.log('[DEBUG] onSubmit called');
|
| 96 |
console.log('[DEBUG] dummyMode:', dummyMode);
|
|
@@ -138,9 +146,8 @@ export default function PreAnalysisCheckUpdate() {
|
|
| 138 |
setShowAnalysisError(true);
|
| 139 |
setGetScoreLoading(false);
|
| 140 |
|
| 141 |
-
// ローカル状態も設定(
|
| 142 |
setErrorMessage(message);
|
| 143 |
-
setShowError(true);
|
| 144 |
}
|
| 145 |
}, [dummyMode, localUpdatedCompetitionUrls, checkUrlFvErrors, setGetScoreLoading, preAnalysis, router, setAnalysisError, setShowAnalysisError]);
|
| 146 |
|
|
@@ -315,14 +322,16 @@ export default function PreAnalysisCheckUpdate() {
|
|
| 315 |
)}
|
| 316 |
|
| 317 |
{/* エラー表示とリトライボタン */}
|
| 318 |
-
{showError && (
|
| 319 |
<div className="flex min-h-[400px] flex-col items-center justify-center p-8">
|
| 320 |
<div className="mx-auto max-w-md text-center">
|
| 321 |
<AlertTriangle className="mx-auto mb-4 h-16 w-16 text-red-500" />
|
| 322 |
<h2 className="mb-2 text-2xl font-semibold text-gray-900">エラーが発生しました</h2>
|
| 323 |
<p className="mb-6 text-gray-600">
|
| 324 |
申し訳ございません。予期しないエラーが発生しました。
|
| 325 |
-
{errorMessage &&
|
|
|
|
|
|
|
| 326 |
</p>
|
| 327 |
<div className="flex justify-center gap-3">
|
| 328 |
<Button
|
|
|
|
| 6 |
|
| 7 |
import { usePreAnalysis } from '@/api-client/gradio-proxy/use-pre-analysis';
|
| 8 |
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
| 9 |
+
import { useDelayedErrorDisplay } from '@/hooks/use-delayed-error-display';
|
| 10 |
import { useGlobalStore } from '@/store/global';
|
| 11 |
import { useInputStore } from '@/store/input';
|
| 12 |
import { useResultStore } from '@/store/result';
|
|
|
|
| 32 |
competitionUrls.filter((url) => !checkUrlFvErrors.includes(url)),
|
| 33 |
);
|
| 34 |
const [errorMessage, setErrorMessage] = useState<string>('');
|
| 35 |
+
const [showError, setShowError] = useState(false); // バリデーションエラー用(即座に表示)
|
| 36 |
const { tempImages, commonDict } = useResultStore();
|
| 37 |
const [imageErrors, setImageErrors] = useState<{ [url: string]: boolean }>({});
|
| 38 |
|
|
|
|
| 92 |
userIdentifier: getUserIdentifier(),
|
| 93 |
});
|
| 94 |
|
| 95 |
+
// 90秒遅延エラー表示
|
| 96 |
+
const { shouldShowError } = useDelayedErrorDisplay({
|
| 97 |
+
error: preAnalysis.error,
|
| 98 |
+
isLoading: preAnalysis.isLoading,
|
| 99 |
+
delayMs: 90000, // 90秒(本番設定)
|
| 100 |
+
});
|
| 101 |
+
|
| 102 |
const onSubmit = useCallback(async () => {
|
| 103 |
console.log('[DEBUG] onSubmit called');
|
| 104 |
console.log('[DEBUG] dummyMode:', dummyMode);
|
|
|
|
| 146 |
setShowAnalysisError(true);
|
| 147 |
setGetScoreLoading(false);
|
| 148 |
|
| 149 |
+
// ローカル状態も設定(カスタマイズされたエラーメッセージのため)
|
| 150 |
setErrorMessage(message);
|
|
|
|
| 151 |
}
|
| 152 |
}, [dummyMode, localUpdatedCompetitionUrls, checkUrlFvErrors, setGetScoreLoading, preAnalysis, router, setAnalysisError, setShowAnalysisError]);
|
| 153 |
|
|
|
|
| 322 |
)}
|
| 323 |
|
| 324 |
{/* エラー表示とリトライボタン */}
|
| 325 |
+
{(shouldShowError || showError) && (
|
| 326 |
<div className="flex min-h-[400px] flex-col items-center justify-center p-8">
|
| 327 |
<div className="mx-auto max-w-md text-center">
|
| 328 |
<AlertTriangle className="mx-auto mb-4 h-16 w-16 text-red-500" />
|
| 329 |
<h2 className="mb-2 text-2xl font-semibold text-gray-900">エラーが発生しました</h2>
|
| 330 |
<p className="mb-6 text-gray-600">
|
| 331 |
申し訳ございません。予期しないエラーが発生しました。
|
| 332 |
+
{(preAnalysis.error?.message || errorMessage) && (
|
| 333 |
+
<span className="mt-2 block text-sm text-gray-500">{preAnalysis.error?.message || errorMessage}</span>
|
| 334 |
+
)}
|
| 335 |
</p>
|
| 336 |
<div className="flex justify-center gap-3">
|
| 337 |
<Button
|
hooks/use-delayed-error-display.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useEffect, useState } from 'react';
|
| 2 |
+
|
| 3 |
+
export interface UseDelayedErrorDisplayOptions {
|
| 4 |
+
error: Error | null;
|
| 5 |
+
isLoading: boolean;
|
| 6 |
+
delayMs?: number; // デフォルト90000ms (90秒)
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
export interface UseDelayedErrorDisplayResult {
|
| 10 |
+
shouldShowError: boolean;
|
| 11 |
+
shouldShowLoading: boolean;
|
| 12 |
+
delayedError: Error | null;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
/**
|
| 16 |
+
* エラー発生後も指定時間(デフォルト90秒)はローディング表示を継続し、
|
| 17 |
+
* 時間経過後にエラーを表示するHook
|
| 18 |
+
*
|
| 19 |
+
* @param options エラー、ローディング状態、遅延時間(ミリ秒)
|
| 20 |
+
* @returns エラー表示すべきか、ローディング表示すべきか、遅延後のエラー
|
| 21 |
+
*/
|
| 22 |
+
export function useDelayedErrorDisplay({
|
| 23 |
+
error,
|
| 24 |
+
isLoading,
|
| 25 |
+
delayMs = 90000, // 90秒(本番設定)
|
| 26 |
+
}: UseDelayedErrorDisplayOptions): UseDelayedErrorDisplayResult {
|
| 27 |
+
const [errorTimestamp, setErrorTimestamp] = useState<number | null>(null);
|
| 28 |
+
const [shouldShowError, setShouldShowError] = useState(false);
|
| 29 |
+
|
| 30 |
+
// エラーが発生した時刻を記録
|
| 31 |
+
useEffect(() => {
|
| 32 |
+
if (error && !errorTimestamp) {
|
| 33 |
+
setErrorTimestamp(Date.now());
|
| 34 |
+
setShouldShowError(false);
|
| 35 |
+
} else if (!error) {
|
| 36 |
+
// エラーがクリアされた場合はリセット
|
| 37 |
+
setErrorTimestamp(null);
|
| 38 |
+
setShouldShowError(false);
|
| 39 |
+
}
|
| 40 |
+
}, [error, errorTimestamp]);
|
| 41 |
+
|
| 42 |
+
// 指定時間経過後にエラーを表示
|
| 43 |
+
useEffect(() => {
|
| 44 |
+
if (!errorTimestamp || !error || shouldShowError) {
|
| 45 |
+
// すでにエラー表示状態の場合は何もしない
|
| 46 |
+
return;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
const checkElapsed = () => {
|
| 50 |
+
const elapsed = Date.now() - errorTimestamp;
|
| 51 |
+
if (elapsed >= delayMs) {
|
| 52 |
+
setShouldShowError(true);
|
| 53 |
+
}
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
// 初回チェック
|
| 57 |
+
checkElapsed();
|
| 58 |
+
|
| 59 |
+
// 1秒ごとにチェック
|
| 60 |
+
const interval = setInterval(checkElapsed, 1000);
|
| 61 |
+
|
| 62 |
+
return () => clearInterval(interval);
|
| 63 |
+
}, [errorTimestamp, error, delayMs, shouldShowError]);
|
| 64 |
+
|
| 65 |
+
// ローディング表示判定:
|
| 66 |
+
// - 通常ローディング中、または
|
| 67 |
+
// - エラーが発生しているが、まだ遅延時間内
|
| 68 |
+
const shouldShowLoading = isLoading || (error !== null && errorTimestamp !== null && !shouldShowError);
|
| 69 |
+
|
| 70 |
+
return {
|
| 71 |
+
shouldShowError,
|
| 72 |
+
shouldShowLoading,
|
| 73 |
+
delayedError: shouldShowError ? error : null,
|
| 74 |
+
};
|
| 75 |
+
}
|
server/routes/gradio-proxy.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { scoreStep3RequestSchema } from '@/schema/gradio-proxy/score-step3';
|
|
| 10 |
import { summaryRequestSchema } from '@/schema/gradio-proxy/summary';
|
| 11 |
import { themeByMomentRequestSchema } from '@/schema/gradio-proxy/theme-by-moment';
|
| 12 |
import { visScoreRequestSchema } from '@/schema/gradio-proxy/vis-score';
|
|
|
|
| 13 |
import { getDummyData } from '@/server/utils/dummy-data';
|
| 14 |
import {
|
| 15 |
getCheckUrl,
|
|
@@ -28,6 +29,33 @@ import {
|
|
| 28 |
import { zValidator } from '@hono/zod-validator';
|
| 29 |
import { Hono } from 'hono';
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
export const gradioProxyRoute = new Hono()
|
| 32 |
// check_url API (POST /check-url)
|
| 33 |
.post('/check-url', zValidator('json', checkUrlRequestSchema), async (c) => {
|
|
@@ -71,24 +99,11 @@ export const gradioProxyRoute = new Hono()
|
|
| 71 |
return c.json(result);
|
| 72 |
} catch (error) {
|
| 73 |
console.error('[CHECK_URL API] Error:', error);
|
| 74 |
-
|
| 75 |
-
let errorMessage = '不明なエラーが発生しました。';
|
| 76 |
-
let statusCode = 500;
|
| 77 |
-
|
| 78 |
-
if (error instanceof Error) {
|
| 79 |
-
errorMessage = error.message;
|
| 80 |
-
|
| 81 |
-
// タイムアウトエラー
|
| 82 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 83 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 84 |
-
statusCode = 408;
|
| 85 |
-
}
|
| 86 |
-
}
|
| 87 |
-
|
| 88 |
return c.json(
|
| 89 |
{
|
| 90 |
status: 'error',
|
| 91 |
-
message
|
| 92 |
},
|
| 93 |
statusCode as 400 | 408 | 500,
|
| 94 |
);
|
|
@@ -144,23 +159,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 144 |
|
| 145 |
return c.json(result);
|
| 146 |
} catch (error) {
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
if (error instanceof Error) {
|
| 151 |
-
errorMessage = error.message;
|
| 152 |
-
|
| 153 |
-
// タイムアウトエラー
|
| 154 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 155 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 156 |
-
statusCode = 408;
|
| 157 |
-
}
|
| 158 |
-
}
|
| 159 |
-
|
| 160 |
return c.json(
|
| 161 |
{
|
| 162 |
status: 'error',
|
| 163 |
-
message
|
| 164 |
},
|
| 165 |
statusCode as 400 | 408 | 500,
|
| 166 |
);
|
|
@@ -202,22 +206,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 202 |
|
| 203 |
return c.json(result);
|
| 204 |
} catch (error) {
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
if (error instanceof Error) {
|
| 209 |
-
errorMessage = error.message;
|
| 210 |
-
|
| 211 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 212 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 213 |
-
statusCode = 408;
|
| 214 |
-
}
|
| 215 |
-
}
|
| 216 |
-
|
| 217 |
return c.json(
|
| 218 |
{
|
| 219 |
status: 'error',
|
| 220 |
-
message
|
| 221 |
},
|
| 222 |
statusCode as 400 | 408 | 500,
|
| 223 |
);
|
|
@@ -261,22 +255,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 261 |
|
| 262 |
return c.json(result);
|
| 263 |
} catch (error) {
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
if (error instanceof Error) {
|
| 268 |
-
errorMessage = error.message;
|
| 269 |
-
|
| 270 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 271 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 272 |
-
statusCode = 408;
|
| 273 |
-
}
|
| 274 |
-
}
|
| 275 |
-
|
| 276 |
return c.json(
|
| 277 |
{
|
| 278 |
status: 'error',
|
| 279 |
-
message
|
| 280 |
},
|
| 281 |
statusCode as 400 | 408 | 500,
|
| 282 |
);
|
|
@@ -317,22 +301,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 317 |
|
| 318 |
return c.json(result);
|
| 319 |
} catch (error) {
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
if (error instanceof Error) {
|
| 324 |
-
errorMessage = error.message;
|
| 325 |
-
|
| 326 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 327 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 328 |
-
statusCode = 408;
|
| 329 |
-
}
|
| 330 |
-
}
|
| 331 |
-
|
| 332 |
return c.json(
|
| 333 |
{
|
| 334 |
status: 'error',
|
| 335 |
-
message
|
| 336 |
},
|
| 337 |
statusCode as 400 | 408 | 500,
|
| 338 |
);
|
|
@@ -376,22 +350,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 376 |
|
| 377 |
return c.json(result);
|
| 378 |
} catch (error) {
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
if (error instanceof Error) {
|
| 383 |
-
errorMessage = error.message;
|
| 384 |
-
|
| 385 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 386 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 387 |
-
statusCode = 408;
|
| 388 |
-
}
|
| 389 |
-
}
|
| 390 |
-
|
| 391 |
return c.json(
|
| 392 |
{
|
| 393 |
status: 'error',
|
| 394 |
-
message
|
| 395 |
},
|
| 396 |
statusCode as 400 | 408 | 500,
|
| 397 |
);
|
|
@@ -747,22 +711,12 @@ export const gradioProxyRoute = new Hono()
|
|
| 747 |
|
| 748 |
return c.json(result);
|
| 749 |
} catch (error) {
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
if (error instanceof Error) {
|
| 754 |
-
errorMessage = error.message;
|
| 755 |
-
|
| 756 |
-
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 757 |
-
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 758 |
-
statusCode = 408;
|
| 759 |
-
}
|
| 760 |
-
}
|
| 761 |
-
|
| 762 |
return c.json(
|
| 763 |
{
|
| 764 |
status: 'error',
|
| 765 |
-
message
|
| 766 |
},
|
| 767 |
statusCode as 400 | 408 | 500,
|
| 768 |
);
|
|
|
|
| 10 |
import { summaryRequestSchema } from '@/schema/gradio-proxy/summary';
|
| 11 |
import { themeByMomentRequestSchema } from '@/schema/gradio-proxy/theme-by-moment';
|
| 12 |
import { visScoreRequestSchema } from '@/schema/gradio-proxy/vis-score';
|
| 13 |
+
import { AppError } from '@/lib/errors';
|
| 14 |
import { getDummyData } from '@/server/utils/dummy-data';
|
| 15 |
import {
|
| 16 |
getCheckUrl,
|
|
|
|
| 29 |
import { zValidator } from '@hono/zod-validator';
|
| 30 |
import { Hono } from 'hono';
|
| 31 |
|
| 32 |
+
/**
|
| 33 |
+
* Gradio APIエラーを統一的に処理するヘルパー関数
|
| 34 |
+
*/
|
| 35 |
+
function handleGradioError(error: unknown): { statusCode: number; message: string } {
|
| 36 |
+
let errorMessage = '不明なエラーが発生しました。';
|
| 37 |
+
let statusCode = 500;
|
| 38 |
+
|
| 39 |
+
if (error instanceof AppError) {
|
| 40 |
+
errorMessage = error.message;
|
| 41 |
+
statusCode = error.statusCode || 500;
|
| 42 |
+
} else if (error instanceof Error) {
|
| 43 |
+
errorMessage = error.message;
|
| 44 |
+
|
| 45 |
+
// タイムアウトエラー
|
| 46 |
+
if (error.message.includes('タイムアウト') || error.message.includes('timeout')) {
|
| 47 |
+
errorMessage = 'タイムアウトが発生しました。もう一度やり直してください。';
|
| 48 |
+
statusCode = 408;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
if ('statusCode' in error && typeof error.statusCode === 'number') {
|
| 52 |
+
statusCode = error.statusCode;
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
return { statusCode, message: errorMessage };
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
export const gradioProxyRoute = new Hono()
|
| 60 |
// check_url API (POST /check-url)
|
| 61 |
.post('/check-url', zValidator('json', checkUrlRequestSchema), async (c) => {
|
|
|
|
| 99 |
return c.json(result);
|
| 100 |
} catch (error) {
|
| 101 |
console.error('[CHECK_URL API] Error:', error);
|
| 102 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
return c.json(
|
| 104 |
{
|
| 105 |
status: 'error',
|
| 106 |
+
message,
|
| 107 |
},
|
| 108 |
statusCode as 400 | 408 | 500,
|
| 109 |
);
|
|
|
|
| 159 |
|
| 160 |
return c.json(result);
|
| 161 |
} catch (error) {
|
| 162 |
+
console.error('[SCORE_STEP3 API] Error:', error);
|
| 163 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
return c.json(
|
| 165 |
{
|
| 166 |
status: 'error',
|
| 167 |
+
message,
|
| 168 |
},
|
| 169 |
statusCode as 400 | 408 | 500,
|
| 170 |
);
|
|
|
|
| 206 |
|
| 207 |
return c.json(result);
|
| 208 |
} catch (error) {
|
| 209 |
+
console.error('[VIS_SCORE API] Error:', error);
|
| 210 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
return c.json(
|
| 212 |
{
|
| 213 |
status: 'error',
|
| 214 |
+
message,
|
| 215 |
},
|
| 216 |
statusCode as 400 | 408 | 500,
|
| 217 |
);
|
|
|
|
| 255 |
|
| 256 |
return c.json(result);
|
| 257 |
} catch (error) {
|
| 258 |
+
console.error('[SUMMARY API] Error:', error);
|
| 259 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
return c.json(
|
| 261 |
{
|
| 262 |
status: 'error',
|
| 263 |
+
message,
|
| 264 |
},
|
| 265 |
statusCode as 400 | 408 | 500,
|
| 266 |
);
|
|
|
|
| 301 |
|
| 302 |
return c.json(result);
|
| 303 |
} catch (error) {
|
| 304 |
+
console.error('[POX API] Error:', error);
|
| 305 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
return c.json(
|
| 307 |
{
|
| 308 |
status: 'error',
|
| 309 |
+
message,
|
| 310 |
},
|
| 311 |
statusCode as 400 | 408 | 500,
|
| 312 |
);
|
|
|
|
| 350 |
|
| 351 |
return c.json(result);
|
| 352 |
} catch (error) {
|
| 353 |
+
console.error('[EXCEL API] Error:', error);
|
| 354 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
return c.json(
|
| 356 |
{
|
| 357 |
status: 'error',
|
| 358 |
+
message,
|
| 359 |
},
|
| 360 |
statusCode as 400 | 408 | 500,
|
| 361 |
);
|
|
|
|
| 711 |
|
| 712 |
return c.json(result);
|
| 713 |
} catch (error) {
|
| 714 |
+
console.error('[REFRESH_MOMENT API] Error:', error);
|
| 715 |
+
const { statusCode, message } = handleGradioError(error);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 716 |
return c.json(
|
| 717 |
{
|
| 718 |
status: 'error',
|
| 719 |
+
message,
|
| 720 |
},
|
| 721 |
statusCode as 400 | 408 | 500,
|
| 722 |
);
|