- Refactored types in `Knowledge/types.ts` to introduce new interfaces for document handling. - Added `KnowledgeDocItem`, `KnowledgeDocsListResponse`, `KnowledgeDocsUploadInput`, `KnowledgeDocsUploadResponse`, and `KnowledgeDocsDeleteResponse` for better structure and clarity. - Updated `KnowledgeDocsApiClient` interface to include methods for listing, uploading, and deleting documents. fix: replace deprecated icons in AccountSettingsPanel and SettingMenu - Replaced `CheckCircleIcon` with `CheckCircle` from `lucide-react` in `AccountSettingsPanel.tsx`. - Updated `SettingMenu.tsx` to use `Settings` and `User` from `lucide-react` instead of custom icons. test: add tests for knowledge docs routes and KnowledgePage - Created `knowledge-docs-routes.test.ts` to test API routes for listing, uploading, and deleting knowledge documents. - Added `knowledge-page.test.tsx` to test the rendering and functionality of the KnowledgePage component, including document loading and deletion.
180 lines
5.9 KiB
TypeScript
180 lines
5.9 KiB
TypeScript
import { useLocale } from '../../i18n';
|
||
import type { LanguageCode } from '../../types/runtime';
|
||
|
||
type Primitive = string | number;
|
||
type MessageTree = {
|
||
[key: string]: Primitive | MessageTree;
|
||
};
|
||
type InterpolationParams = Record<string, Primitive>;
|
||
|
||
export type KnowledgeTranslate = (path: string, params?: InterpolationParams, fallback?: string) => string;
|
||
|
||
function normalizeKnowledgePath(path: string): string {
|
||
return path.startsWith('knowledge.') ? path.slice('knowledge.'.length) : path;
|
||
}
|
||
|
||
const EN_KNOWLEDGE_MESSAGES: MessageTree = {
|
||
title: 'Knowledge Docs',
|
||
subtitle: 'Upload, review, and delete local documentation files stored in the knowledge directory.',
|
||
refresh: 'Refresh',
|
||
upload: 'Upload document',
|
||
uploadHint: 'This page fully replaces the previous Knowledge demo and now focuses on local docs only.',
|
||
documentsLabel: 'Documents',
|
||
storageLabel: 'Storage',
|
||
emptyTitle: 'No documents yet',
|
||
emptyDescription: 'Upload a file to start managing the local knowledge docs directory.',
|
||
deleteConfirm: 'Delete this document?',
|
||
table: {
|
||
name: 'Name',
|
||
size: 'Size',
|
||
modifiedAt: 'Modified At',
|
||
type: 'Type',
|
||
actions: 'Actions',
|
||
delete: 'Delete',
|
||
},
|
||
dialog: {
|
||
title: 'Upload document',
|
||
description: 'Choose a file and save it into the local knowledge docs directory.',
|
||
fileLabel: 'File',
|
||
fileHint: 'The uploaded file will be written with its file name and metadata preserved.',
|
||
cancel: 'Cancel',
|
||
confirm: 'Upload',
|
||
},
|
||
status: {
|
||
loading: 'Loading documents...',
|
||
uploading: 'Uploading...',
|
||
deleting: 'Deleting...',
|
||
uploadSuccess: 'Document uploaded successfully',
|
||
deleteSuccess: 'Document deleted successfully',
|
||
failed: 'Knowledge docs request failed: {error}',
|
||
},
|
||
common: {
|
||
cancel: 'Cancel',
|
||
confirm: 'Confirm',
|
||
},
|
||
};
|
||
|
||
const ZH_KNOWLEDGE_MESSAGES: MessageTree = {
|
||
title: '知识文档管理',
|
||
subtitle: '上传、查看和删除保存在知识目录中的本地文档文件。',
|
||
refresh: '刷新',
|
||
upload: '上传文档',
|
||
uploadHint: '此页面已完全替换旧 Knowledge demo,只保留本地文档管理能力。',
|
||
documentsLabel: '文档数量',
|
||
storageLabel: '占用空间',
|
||
emptyTitle: '暂无文档',
|
||
emptyDescription: '先上传一个文件,开始管理本地知识文档目录。',
|
||
deleteConfirm: '确定要删除此文档吗?',
|
||
table: {
|
||
name: '名称',
|
||
size: '大小',
|
||
modifiedAt: '修改时间',
|
||
type: '类型',
|
||
actions: '操作',
|
||
delete: '删除',
|
||
},
|
||
dialog: {
|
||
title: '上传文档',
|
||
description: '选择一个文件并保存到本地知识文档目录中。',
|
||
fileLabel: '文件',
|
||
fileHint: '上传后的文件会保留文件名和元信息。',
|
||
cancel: '取消',
|
||
confirm: '上传',
|
||
},
|
||
status: {
|
||
loading: '正在加载文档...',
|
||
uploading: '上传中...',
|
||
deleting: '删除中...',
|
||
uploadSuccess: '文档上传成功',
|
||
deleteSuccess: '文档删除成功',
|
||
failed: '知识文档请求失败:{error}',
|
||
},
|
||
common: {
|
||
cancel: '取消',
|
||
confirm: '确认',
|
||
},
|
||
};
|
||
|
||
const JA_KNOWLEDGE_MESSAGES: MessageTree = {
|
||
title: 'Knowledge Docs',
|
||
subtitle: 'ローカルのナレッジ文書をアップロード、確認、削除できます。',
|
||
refresh: '更新',
|
||
upload: '文書をアップロード',
|
||
uploadHint: 'このページは旧 Knowledge デモを置き換え、ローカル文書管理に専念します。',
|
||
documentsLabel: 'Documents',
|
||
storageLabel: 'Storage',
|
||
emptyTitle: '文書がありません',
|
||
emptyDescription: 'まずファイルをアップロードして、ローカルの knowledge docs を管理してください。',
|
||
deleteConfirm: 'この文書を削除しますか?',
|
||
table: {
|
||
name: '名前',
|
||
size: 'サイズ',
|
||
modifiedAt: '更新日時',
|
||
type: '種類',
|
||
actions: '操作',
|
||
delete: '削除',
|
||
},
|
||
dialog: {
|
||
title: '文書をアップロード',
|
||
description: 'ファイルを選んでローカルの knowledge docs ディレクトリに保存します。',
|
||
fileLabel: 'ファイル',
|
||
fileHint: 'アップロードしたファイルはファイル名とメタデータを保持します。',
|
||
cancel: 'キャンセル',
|
||
confirm: 'アップロード',
|
||
},
|
||
status: {
|
||
loading: '文書を読み込み中...',
|
||
uploading: 'アップロード中...',
|
||
deleting: '削除中...',
|
||
uploadSuccess: '文書をアップロードしました',
|
||
deleteSuccess: '文書を削除しました',
|
||
failed: 'Knowledge docs のリクエストに失敗しました: {error}',
|
||
},
|
||
common: {
|
||
cancel: 'キャンセル',
|
||
confirm: '確認',
|
||
},
|
||
};
|
||
|
||
const KNOWLEDGE_MESSAGES: Record<LanguageCode, MessageTree> = {
|
||
en: EN_KNOWLEDGE_MESSAGES,
|
||
zh: ZH_KNOWLEDGE_MESSAGES,
|
||
ja: JA_KNOWLEDGE_MESSAGES,
|
||
};
|
||
|
||
function lookupMessage(source: MessageTree, path: string): unknown {
|
||
return path.split('.').reduce<unknown>((current, segment) => {
|
||
if (!current || typeof current !== 'object') return undefined;
|
||
return (current as Record<string, unknown>)[segment];
|
||
}, source);
|
||
}
|
||
|
||
function interpolate(template: string, params?: InterpolationParams): string {
|
||
if (!params) return template;
|
||
|
||
return template.replace(/\{(\w+)\}/g, (_match, token) => {
|
||
const value = params[token];
|
||
return typeof value === 'undefined' ? `{${token}}` : String(value);
|
||
});
|
||
}
|
||
|
||
function createKnowledgeTranslate(locale: LanguageCode): KnowledgeTranslate {
|
||
return (path, params, fallback) => {
|
||
const normalizedPath = normalizeKnowledgePath(path);
|
||
const translated = lookupMessage(KNOWLEDGE_MESSAGES[locale] ?? KNOWLEDGE_MESSAGES.en, normalizedPath)
|
||
?? lookupMessage(KNOWLEDGE_MESSAGES.en, normalizedPath);
|
||
|
||
if (typeof translated === 'string' || typeof translated === 'number') {
|
||
return interpolate(String(translated), params);
|
||
}
|
||
|
||
return fallback ?? path;
|
||
};
|
||
}
|
||
|
||
export function useKnowledgeCopy(): KnowledgeTranslate {
|
||
const locale = useLocale();
|
||
|
||
return createKnowledgeTranslate(locale);
|
||
}
|