@lobehub/chat 0.162.12 → 0.162.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +4 -4
- package/README.zh-CN.md +4 -4
- package/docs/self-hosting/environment-variables/basic.mdx +2 -2
- package/docs/self-hosting/environment-variables/basic.zh-CN.mdx +2 -2
- package/locales/ar/common.json +11 -1
- package/locales/bg-BG/common.json +11 -1
- package/locales/de-DE/common.json +11 -1
- package/locales/en-US/common.json +11 -1
- package/locales/es-ES/common.json +11 -1
- package/locales/fr-FR/common.json +11 -1
- package/locales/it-IT/common.json +11 -1
- package/locales/ja-JP/common.json +11 -1
- package/locales/ko-KR/common.json +11 -1
- package/locales/nl-NL/common.json +11 -1
- package/locales/pl-PL/common.json +11 -1
- package/locales/pt-BR/common.json +11 -1
- package/locales/ru-RU/common.json +11 -1
- package/locales/tr-TR/common.json +11 -1
- package/locales/vi-VN/common.json +11 -1
- package/locales/zh-CN/common.json +11 -1
- package/locales/zh-TW/common.json +11 -1
- package/netlify.toml +2 -0
- package/package.json +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +18 -4
- package/src/app/(main)/chat/(workspace)/@topic/features/TopicListContent/TopicItem.tsx +5 -2
- package/src/features/Conversation/Error/OllamaBizError/InvalidOllamaModel/useDownloadMonitor.ts +2 -10
- package/src/features/DataImporter/Error.tsx +65 -0
- package/src/features/DataImporter/FileUploading.tsx +50 -0
- package/src/features/DataImporter/Loading.tsx +125 -0
- package/src/features/DataImporter/SuccessResult.tsx +61 -0
- package/src/features/DataImporter/index.tsx +127 -208
- package/src/features/DataImporter/style.ts +17 -0
- package/src/hooks/useDownloadSpeed.ts +50 -0
- package/src/locales/default/common.ts +10 -0
- package/src/services/config.ts +15 -11
- package/src/services/github.ts +17 -0
- package/src/services/import/client.ts +18 -6
- package/src/store/chat/slices/message/action.ts +3 -3
- package/src/store/chat/slices/message/initialState.ts +2 -0
- package/src/store/chat/slices/message/selectors.ts +5 -0
- package/src/store/chat/slices/topic/action.ts +3 -2
- package/src/store/chat/slices/topic/initialState.ts +2 -0
- package/src/store/chat/slices/topic/selectors.ts +2 -0
- package/src/types/importer.ts +128 -0
- package/src/utils/config.ts +18 -15
- package/src/utils/speed.ts +32 -0
- package/src/features/DataImporter/useImportConfig.ts +0 -27
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"historyRange": "Phạm vi lịch sử",
|
|
40
40
|
"import": "Nhập cấu hình",
|
|
41
41
|
"importModal": {
|
|
42
|
+
"error": {
|
|
43
|
+
"desc": "Xin lỗi vì quá trình nhập dữ liệu gặp sự cố. Vui lòng thử nhập lại hoặc <1>gửi vấn đề</1>, chúng tôi sẽ kiểm tra vấn đề ngay lập tức.",
|
|
44
|
+
"title": "Nhập dữ liệu thất bại"
|
|
45
|
+
},
|
|
42
46
|
"finish": {
|
|
43
47
|
"onlySettings": "Nhập cài đặt hệ thống thành công",
|
|
44
48
|
"start": "Bắt đầu sử dụng",
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
"title": "Hoàn tất nhập dữ liệu"
|
|
47
51
|
},
|
|
48
52
|
"loading": "Đang nhập dữ liệu, vui lòng chờ...",
|
|
53
|
+
"preparing": "Đang chuẩn bị mô-đun nhập dữ liệu...",
|
|
49
54
|
"result": {
|
|
50
55
|
"added": "Nhập thành công",
|
|
51
56
|
"errors": "Lỗi nhập",
|
|
@@ -56,7 +61,12 @@
|
|
|
56
61
|
"topics": "Chủ đề",
|
|
57
62
|
"type": "Loại dữ liệu"
|
|
58
63
|
},
|
|
59
|
-
"title": "Nhập dữ liệu"
|
|
64
|
+
"title": "Nhập dữ liệu",
|
|
65
|
+
"uploading": {
|
|
66
|
+
"desc": "Tập tin hiện tại quá lớn, đang cố gắng tải lên...",
|
|
67
|
+
"restTime": "Thời gian còn lại",
|
|
68
|
+
"speed": "Tốc độ tải lên"
|
|
69
|
+
}
|
|
60
70
|
},
|
|
61
71
|
"installPWA": "Cài đặt ứng dụng trình duyệt",
|
|
62
72
|
"lang": {
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"historyRange": "历史范围",
|
|
40
40
|
"import": "导入配置",
|
|
41
41
|
"importModal": {
|
|
42
|
+
"error": {
|
|
43
|
+
"desc": "非常抱歉,数据导入过程发生异常。请尝试重新导入,或 <1>提交问题</1>,我们将会第一时间帮你排查问题。",
|
|
44
|
+
"title": "数据导入失败"
|
|
45
|
+
},
|
|
42
46
|
"finish": {
|
|
43
47
|
"onlySettings": "系统设置导入成功",
|
|
44
48
|
"start": "开始使用",
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
"title": "数据导入完成"
|
|
47
51
|
},
|
|
48
52
|
"loading": "数据导入中,请耐心等待...",
|
|
53
|
+
"preparing": "数据导入模块准备中...",
|
|
49
54
|
"result": {
|
|
50
55
|
"added": "导入成功",
|
|
51
56
|
"errors": "导入出错",
|
|
@@ -56,7 +61,12 @@
|
|
|
56
61
|
"topics": "话题",
|
|
57
62
|
"type": "数据类型"
|
|
58
63
|
},
|
|
59
|
-
"title": "导入数据"
|
|
64
|
+
"title": "导入数据",
|
|
65
|
+
"uploading": {
|
|
66
|
+
"desc": "当前文件较大,正在努力上传中...",
|
|
67
|
+
"restTime": "剩余时间",
|
|
68
|
+
"speed": "上传速度"
|
|
69
|
+
}
|
|
60
70
|
},
|
|
61
71
|
"installPWA": "安装浏览器应用 (PWA)",
|
|
62
72
|
"lang": {
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"historyRange": "歷史範圍",
|
|
40
40
|
"import": "匯入設定",
|
|
41
41
|
"importModal": {
|
|
42
|
+
"error": {
|
|
43
|
+
"desc": "非常抱歉,資料匯入過程發生異常。請嘗試重新匯入,或 <1>提交問題</1>,我們將會第一時間幫你排查問題。",
|
|
44
|
+
"title": "資料匯入失敗"
|
|
45
|
+
},
|
|
42
46
|
"finish": {
|
|
43
47
|
"onlySettings": "系統設定匯入成功",
|
|
44
48
|
"start": "開始使用",
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
"title": "資料匯入完成"
|
|
47
51
|
},
|
|
48
52
|
"loading": "資料匯入中,請耐心等候...",
|
|
53
|
+
"preparing": "資料匯入模組準備中...",
|
|
49
54
|
"result": {
|
|
50
55
|
"added": "匯入成功",
|
|
51
56
|
"errors": "匯入出錯",
|
|
@@ -56,7 +61,12 @@
|
|
|
56
61
|
"topics": "話題",
|
|
57
62
|
"type": "資料類型"
|
|
58
63
|
},
|
|
59
|
-
"title": "匯入資料"
|
|
64
|
+
"title": "匯入資料",
|
|
65
|
+
"uploading": {
|
|
66
|
+
"desc": "當前檔案較大,正在努力上傳中...",
|
|
67
|
+
"restTime": "剩餘時間",
|
|
68
|
+
"speed": "上傳速度"
|
|
69
|
+
}
|
|
60
70
|
},
|
|
61
71
|
"installPWA": "安裝瀏覽器應用 (PWA)",
|
|
62
72
|
"lang": {
|
package/netlify.toml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.162.
|
|
3
|
+
"version": "0.162.14",
|
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
package/src/app/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import { useSendMessage } from '@/features/ChatInput/useSend';
|
|
|
13
13
|
import { useAgentStore } from '@/store/agent';
|
|
14
14
|
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
15
15
|
import { useChatStore } from '@/store/chat';
|
|
16
|
-
import { chatSelectors } from '@/store/chat/selectors';
|
|
16
|
+
import { chatSelectors, topicSelectors } from '@/store/chat/selectors';
|
|
17
17
|
import { filesSelectors, useFileStore } from '@/store/file';
|
|
18
18
|
import { useUserStore } from '@/store/user';
|
|
19
19
|
import { modelProviderSelectors, preferenceSelectors } from '@/store/user/selectors';
|
|
@@ -61,10 +61,20 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
61
61
|
|
|
62
62
|
const { theme, styles } = useStyles();
|
|
63
63
|
|
|
64
|
-
const [
|
|
64
|
+
const [
|
|
65
|
+
isAIGenerating,
|
|
66
|
+
isHasMessageLoading,
|
|
67
|
+
isCreatingMessage,
|
|
68
|
+
isCreatingTopic,
|
|
69
|
+
stopGenerateMessage,
|
|
70
|
+
] = useChatStore((s) => [
|
|
65
71
|
chatSelectors.isAIGenerating(s),
|
|
72
|
+
chatSelectors.isHasMessageLoading(s),
|
|
73
|
+
chatSelectors.isCreatingMessage(s),
|
|
74
|
+
topicSelectors.isCreatingTopic(s),
|
|
66
75
|
s.stopGenerateMessage,
|
|
67
76
|
]);
|
|
77
|
+
|
|
68
78
|
const isImageUploading = useFileStore(filesSelectors.isImageUploading);
|
|
69
79
|
|
|
70
80
|
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
@@ -93,6 +103,9 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
93
103
|
|
|
94
104
|
const wrapperShortcut = useCmdEnterToSend ? enter : cmdEnter;
|
|
95
105
|
|
|
106
|
+
const buttonDisabled =
|
|
107
|
+
isImageUploading || isHasMessageLoading || isCreatingTopic || isCreatingMessage;
|
|
108
|
+
|
|
96
109
|
return (
|
|
97
110
|
<Flexbox
|
|
98
111
|
align={'end'}
|
|
@@ -136,7 +149,8 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
136
149
|
) : (
|
|
137
150
|
<Space.Compact>
|
|
138
151
|
<Button
|
|
139
|
-
disabled={
|
|
152
|
+
disabled={buttonDisabled}
|
|
153
|
+
loading={buttonDisabled}
|
|
140
154
|
onClick={() => {
|
|
141
155
|
sendMessage();
|
|
142
156
|
setExpand?.(false);
|
|
@@ -145,7 +159,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
145
159
|
>
|
|
146
160
|
{t('input.send')}
|
|
147
161
|
</Button>
|
|
148
|
-
<SendMore disabled={
|
|
162
|
+
<SendMore disabled={buttonDisabled} />
|
|
149
163
|
</Space.Compact>
|
|
150
164
|
)}
|
|
151
165
|
</Flexbox>
|
|
@@ -20,13 +20,16 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
|
20
20
|
container: css`
|
|
21
21
|
cursor: pointer;
|
|
22
22
|
|
|
23
|
-
width: calc(100% - 16px);
|
|
24
23
|
margin-block: 2px;
|
|
25
24
|
margin-inline: 8px;
|
|
26
25
|
padding: 8px;
|
|
27
26
|
|
|
28
27
|
border-radius: ${token.borderRadius}px;
|
|
29
28
|
|
|
29
|
+
&.topic-item {
|
|
30
|
+
width: calc(100% - 16px);
|
|
31
|
+
}
|
|
32
|
+
|
|
30
33
|
&:hover {
|
|
31
34
|
background: ${token.colorFillSecondary};
|
|
32
35
|
}
|
|
@@ -52,7 +55,7 @@ const TopicItem = memo<ConfigCellProps>(({ title, active, id, fav }) => {
|
|
|
52
55
|
return (
|
|
53
56
|
<Flexbox
|
|
54
57
|
align={'center'}
|
|
55
|
-
className={cx(styles.container, active && styles.active)}
|
|
58
|
+
className={cx(styles.container, 'topic-item', active && styles.active)}
|
|
56
59
|
distribution={'space-between'}
|
|
57
60
|
horizontal
|
|
58
61
|
onClick={() => {
|
package/src/features/Conversation/Error/OllamaBizError/InvalidOllamaModel/useDownloadMonitor.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { formatTime } from '@/utils/speed';
|
|
4
|
+
|
|
3
5
|
export const formatSize = (bytes: number): string => {
|
|
4
6
|
const kbSize = bytes / 1024;
|
|
5
7
|
if (kbSize < 1024) {
|
|
@@ -17,16 +19,6 @@ const formatSpeed = (speed: number): string => {
|
|
|
17
19
|
return `${formatSize(speed)}/s`;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
const formatTime = (timeInSeconds: number): string => {
|
|
21
|
-
if (timeInSeconds < 60) {
|
|
22
|
-
return `${timeInSeconds.toFixed(1)} s`;
|
|
23
|
-
} else if (timeInSeconds < 3600) {
|
|
24
|
-
return `${(timeInSeconds / 60).toFixed(1)} min`;
|
|
25
|
-
} else {
|
|
26
|
-
return `${(timeInSeconds / 3600).toFixed(2)} h`;
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
22
|
export const useDownloadMonitor = (totalSize: number, completedSize: number) => {
|
|
31
23
|
const [downloadSpeed, setDownloadSpeed] = useState<string>('0 KB/s');
|
|
32
24
|
const [remainingTime, setRemainingTime] = useState<string>('-');
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Alert, Highlighter, Icon } from '@lobehub/ui';
|
|
2
|
+
import { Button, Result } from 'antd';
|
|
3
|
+
import { ShieldAlert } from 'lucide-react';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import React, { memo } from 'react';
|
|
6
|
+
import { Trans, useTranslation } from 'react-i18next';
|
|
7
|
+
import { Flexbox } from 'react-layout-kit';
|
|
8
|
+
import Balancer from 'react-wrap-balancer';
|
|
9
|
+
|
|
10
|
+
import { GITHUB_ISSUES } from '@/const/url';
|
|
11
|
+
import { githubService } from '@/services/github';
|
|
12
|
+
import { ErrorShape } from '@/types/importer';
|
|
13
|
+
|
|
14
|
+
interface ErrorProps {
|
|
15
|
+
error?: ErrorShape;
|
|
16
|
+
onClick: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Error = memo<ErrorProps>(({ error, onClick }) => {
|
|
20
|
+
const { t } = useTranslation('common');
|
|
21
|
+
return (
|
|
22
|
+
<Result
|
|
23
|
+
extra={
|
|
24
|
+
<Flexbox gap={12} style={{ textAlign: 'start' }}>
|
|
25
|
+
<Alert
|
|
26
|
+
extra={
|
|
27
|
+
<Highlighter copyButtonSize={'small'} language={'json'}>
|
|
28
|
+
{JSON.stringify(error, null, 2)}
|
|
29
|
+
</Highlighter>
|
|
30
|
+
}
|
|
31
|
+
message={error?.message}
|
|
32
|
+
style={{ flex: 1 }}
|
|
33
|
+
type={'error'}
|
|
34
|
+
/>
|
|
35
|
+
<Button onClick={onClick}>{t('close')}</Button>
|
|
36
|
+
</Flexbox>
|
|
37
|
+
}
|
|
38
|
+
icon={<Icon icon={ShieldAlert} />}
|
|
39
|
+
status={'error'}
|
|
40
|
+
style={{ paddingBlock: 24, width: 450 }}
|
|
41
|
+
subTitle={
|
|
42
|
+
<Balancer>
|
|
43
|
+
<Trans i18nKey="importModal.error.desc" ns={'common'}>
|
|
44
|
+
非常抱歉,数据库升级过程发生异常。请重试升级,或
|
|
45
|
+
<Link
|
|
46
|
+
aria-label={'issue'}
|
|
47
|
+
href={GITHUB_ISSUES}
|
|
48
|
+
onClick={(e) => {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
githubService.submitImportError(error!);
|
|
51
|
+
}}
|
|
52
|
+
target="_blank"
|
|
53
|
+
>
|
|
54
|
+
提交问题
|
|
55
|
+
</Link>
|
|
56
|
+
我们将会第一时间帮你排查问题。
|
|
57
|
+
</Trans>
|
|
58
|
+
</Balancer>
|
|
59
|
+
}
|
|
60
|
+
title={t('importModal.error.title')}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export default Error;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Progress } from 'antd';
|
|
2
|
+
import { useTheme } from 'antd-style';
|
|
3
|
+
import React, { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import { formatSpeed, formatTime } from '@/utils/speed';
|
|
8
|
+
|
|
9
|
+
import DataLoading from './Loading';
|
|
10
|
+
|
|
11
|
+
interface FileUploadingProps {
|
|
12
|
+
progress?: number;
|
|
13
|
+
restTime?: number;
|
|
14
|
+
speed?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const FileUploading = memo<FileUploadingProps>(({ progress = 0, speed = 0, restTime }) => {
|
|
18
|
+
const { t } = useTranslation('common');
|
|
19
|
+
|
|
20
|
+
const theme = useTheme();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<DataLoading />
|
|
25
|
+
<Flexbox align={'center'} gap={8} width={'100%'}>
|
|
26
|
+
{t('importModal.uploading.desc')}
|
|
27
|
+
<Flexbox flex={1} gap={8} width={'100%'}>
|
|
28
|
+
<Progress
|
|
29
|
+
percent={progress}
|
|
30
|
+
showInfo
|
|
31
|
+
strokeColor={theme.colorSuccess}
|
|
32
|
+
trailColor={theme.colorSuccessBg}
|
|
33
|
+
/>
|
|
34
|
+
<Flexbox
|
|
35
|
+
distribution={'space-between'}
|
|
36
|
+
horizontal
|
|
37
|
+
style={{ color: theme.colorTextDescription, fontSize: 12 }}
|
|
38
|
+
>
|
|
39
|
+
<span>
|
|
40
|
+
{t('importModal.uploading.restTime')}: {restTime ? formatTime(restTime) : '-'}
|
|
41
|
+
</span>
|
|
42
|
+
<span>
|
|
43
|
+
{t('importModal.uploading.speed')}: {formatSpeed(speed)}
|
|
44
|
+
</span>
|
|
45
|
+
</Flexbox>
|
|
46
|
+
</Flexbox>
|
|
47
|
+
</Flexbox>
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createStyles } from 'antd-style';
|
|
4
|
+
import React, { memo } from 'react';
|
|
5
|
+
import { Center } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
const useStyles = createStyles(({ css, token }) => {
|
|
8
|
+
const size = 28;
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
loader: css`
|
|
12
|
+
transform: translateX(-${size * 2}px);
|
|
13
|
+
|
|
14
|
+
aspect-ratio: 1;
|
|
15
|
+
width: 6px;
|
|
16
|
+
|
|
17
|
+
color: ${token.colorPrimary};
|
|
18
|
+
|
|
19
|
+
border-radius: 50%;
|
|
20
|
+
box-shadow:
|
|
21
|
+
${size}px -${size}px 0 0,
|
|
22
|
+
${size * 2}px -${size}px 0 0,
|
|
23
|
+
${size * 3}px -${size}px 0 0,
|
|
24
|
+
${size}px 0 0 5px,
|
|
25
|
+
${size * 2}px 0 0 5px,
|
|
26
|
+
${size * 3}px 0 0 5px,
|
|
27
|
+
${size}px ${size}px 0 0,
|
|
28
|
+
${size * 2}px ${size}px 0 0,
|
|
29
|
+
${size * 3}px ${size}px 0 0;
|
|
30
|
+
|
|
31
|
+
animation: loading 2s infinite linear;
|
|
32
|
+
|
|
33
|
+
@keyframes loading {
|
|
34
|
+
12.5% {
|
|
35
|
+
box-shadow:
|
|
36
|
+
${size}px -${size}px 0 0,
|
|
37
|
+
${size * 2}px -${size}px 0 0,
|
|
38
|
+
${size * 3}px -${size}px 0 5px,
|
|
39
|
+
${size}px 0 0 5px,
|
|
40
|
+
${size * 2}px 0 0 0,
|
|
41
|
+
${size * 3}px 0 0 5px,
|
|
42
|
+
${size}px ${size}px 0 0,
|
|
43
|
+
${size * 2}px ${size}px 0 0,
|
|
44
|
+
${size * 3}px ${size}px 0 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
25% {
|
|
48
|
+
box-shadow:
|
|
49
|
+
${size}px -${size}px 0 5px,
|
|
50
|
+
${size * 2}px -${size}px 0 0,
|
|
51
|
+
${size * 3}px -${size}px 0 5px,
|
|
52
|
+
${size}px 0 0 0,
|
|
53
|
+
${size * 2}px 0 0 0,
|
|
54
|
+
${size * 3}px 0 0 0,
|
|
55
|
+
${size}px ${size}px 0 0,
|
|
56
|
+
${size * 2}px ${size}px 0 5px,
|
|
57
|
+
${size * 3}px ${size}px 0 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
50% {
|
|
61
|
+
box-shadow:
|
|
62
|
+
${size}px -${size}px 0 5px,
|
|
63
|
+
${size * 2}px -${size}px 0 5px,
|
|
64
|
+
${size * 3}px -${size}px 0 0,
|
|
65
|
+
${size}px 0 0 0,
|
|
66
|
+
${size * 2}px 0 0 0,
|
|
67
|
+
${size * 3}px 0 0 0,
|
|
68
|
+
${size}px ${size}px 0 0,
|
|
69
|
+
${size * 2}px ${size}px 0 0,
|
|
70
|
+
${size * 3}px ${size}px 0 5px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
62.5% {
|
|
74
|
+
box-shadow:
|
|
75
|
+
${size}px -${size}px 0 0,
|
|
76
|
+
${size * 2}px -${size}px 0 0,
|
|
77
|
+
${size * 3}px -${size}px 0 0,
|
|
78
|
+
${size}px 0 0 5px,
|
|
79
|
+
${size * 2}px 0 0 0,
|
|
80
|
+
${size * 3}px 0 0 0,
|
|
81
|
+
${size}px ${size}px 0 0,
|
|
82
|
+
${size * 2}px ${size}px 0 5px,
|
|
83
|
+
${size * 3}px ${size}px 0 5px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
75% {
|
|
87
|
+
box-shadow:
|
|
88
|
+
${size}px -${size}px 0 0,
|
|
89
|
+
${size * 2}px -${size}px 0 5px,
|
|
90
|
+
${size * 3}px -${size}px 0 0,
|
|
91
|
+
${size}px 0 0 0,
|
|
92
|
+
${size * 2}px 0 0 0,
|
|
93
|
+
${size * 3}px 0 0 5px,
|
|
94
|
+
${size}px ${size}px 0 0,
|
|
95
|
+
${size * 2}px ${size}px 0 0,
|
|
96
|
+
${size * 3}px ${size}px 0 5px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
87.5% {
|
|
100
|
+
box-shadow:
|
|
101
|
+
${size}px -${size}px 0 0,
|
|
102
|
+
${size * 2}px -${size}px 0 5px,
|
|
103
|
+
${size * 3}px -${size}px 0 0,
|
|
104
|
+
${size}px 0 0 0,
|
|
105
|
+
${size * 2}px 0 0 5px,
|
|
106
|
+
${size * 3}px 0 0 0,
|
|
107
|
+
${size}px ${size}px 0 5px,
|
|
108
|
+
${size * 2}px ${size}px 0 0,
|
|
109
|
+
${size * 3}px ${size}px 0 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const DataLoading = memo(() => {
|
|
117
|
+
const { styles } = useStyles();
|
|
118
|
+
return (
|
|
119
|
+
<Center style={{ height: 80 }}>
|
|
120
|
+
<div className={styles.loader} />
|
|
121
|
+
</Center>
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export default DataLoading;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Icon } from '@lobehub/ui';
|
|
4
|
+
import { Button, Result, Table } from 'antd';
|
|
5
|
+
import { CheckCircle } from 'lucide-react';
|
|
6
|
+
import React, { memo } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import { Flexbox } from 'react-layout-kit';
|
|
9
|
+
|
|
10
|
+
interface SuccessResultProps {
|
|
11
|
+
dataSource?: {
|
|
12
|
+
added: number;
|
|
13
|
+
error: number;
|
|
14
|
+
skips: number;
|
|
15
|
+
title: string;
|
|
16
|
+
}[];
|
|
17
|
+
duration: number;
|
|
18
|
+
onClickFinish?: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const SuccessResult = memo<SuccessResultProps>(({ duration, dataSource, onClickFinish }) => {
|
|
22
|
+
const { t } = useTranslation('common');
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Result
|
|
26
|
+
extra={
|
|
27
|
+
<Button onClick={onClickFinish} size={'large'} type={'primary'}>
|
|
28
|
+
{t('importModal.finish.start')}
|
|
29
|
+
</Button>
|
|
30
|
+
}
|
|
31
|
+
icon={<Icon icon={CheckCircle} />}
|
|
32
|
+
status={'success'}
|
|
33
|
+
style={{ paddingBlock: 24 }}
|
|
34
|
+
subTitle={
|
|
35
|
+
// if there is no importData, means it's only import the settings
|
|
36
|
+
!dataSource ? (
|
|
37
|
+
t('importModal.finish.onlySettings')
|
|
38
|
+
) : (
|
|
39
|
+
<Flexbox gap={16} width={400}>
|
|
40
|
+
{t('importModal.finish.subTitle', { duration: (duration / 1000).toFixed(2) })}
|
|
41
|
+
<Table
|
|
42
|
+
bordered
|
|
43
|
+
columns={[
|
|
44
|
+
{ dataIndex: 'title', title: t('importModal.result.type') },
|
|
45
|
+
{ dataIndex: 'added', title: t('importModal.result.added') },
|
|
46
|
+
{ dataIndex: 'skips', title: t('importModal.result.skips') },
|
|
47
|
+
{ dataIndex: 'error', title: t('importModal.result.errors') },
|
|
48
|
+
]}
|
|
49
|
+
dataSource={dataSource}
|
|
50
|
+
pagination={false}
|
|
51
|
+
size={'small'}
|
|
52
|
+
/>
|
|
53
|
+
</Flexbox>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
title={t('importModal.finish.title')}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default SuccessResult;
|