@lobehub/chat 1.47.14 → 1.47.15

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 CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.47.15](https://github.com/lobehub/lobe-chat/compare/v1.47.14...v1.47.15)
6
+
7
+ <sup>Released on **2025-01-22**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Improve discover model page.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Improve discover model page, closes [#5544](https://github.com/lobehub/lobe-chat/issues/5544) ([979849c](https://github.com/lobehub/lobe-chat/commit/979849c))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.47.14](https://github.com/lobehub/lobe-chat/compare/v1.47.13...v1.47.14)
6
31
 
7
32
  <sup>Released on **2025-01-22**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Improve discover model page."
6
+ ]
7
+ },
8
+ "date": "2025-01-22",
9
+ "version": "1.47.15"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "improvements": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.47.14",
3
+ "version": "1.47.15",
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",
@@ -3,6 +3,7 @@
3
3
  import { ModelIcon } from '@lobehub/icons';
4
4
  import { Button } from 'antd';
5
5
  import { createStyles } from 'antd-style';
6
+ import dayjs from 'dayjs';
6
7
  import Link from 'next/link';
7
8
  import { memo } from 'react';
8
9
  import { useTranslation } from 'react-i18next';
@@ -20,7 +21,9 @@ export const useStyles = createStyles(({ css, token }) => ({
20
21
  background: ${token.colorFillSecondary};
21
22
  `,
22
23
  time: css`
24
+ display: flex;
23
25
  font-size: 12px;
26
+ line-height: 22px;
24
27
  color: ${token.colorTextDescription};
25
28
  `,
26
29
  title: css`
@@ -41,6 +44,7 @@ const Header = memo<HeaderProps>(({ identifier, data, mobile }) => {
41
44
  const { styles, theme } = useStyles();
42
45
  const { t } = useTranslation(['discover', 'models']);
43
46
 
47
+ const releasedAt = data.meta.releasedAt;
44
48
  return (
45
49
  <Flexbox gap={12} width={'100%'}>
46
50
  {!mobile && <Back href={'/discover/models'} />}
@@ -56,9 +60,11 @@ const Header = memo<HeaderProps>(({ identifier, data, mobile }) => {
56
60
  style={{ color: theme.colorTextSecondary }}
57
61
  >
58
62
  <div>{identifier}</div>
59
- <time className={styles.time} dateTime={new Date(data.createdAt).toISOString()}>
60
- {data.createdAt}
61
- </time>
63
+ {releasedAt && (
64
+ <time className={styles.time} dateTime={dayjs(releasedAt).toISOString()}>
65
+ {releasedAt}
66
+ </time>
67
+ )}
62
68
  </Flexbox>
63
69
  </Flexbox>
64
70
  </Flexbox>
@@ -44,13 +44,13 @@ export interface SuggestionItemProps
44
44
  extends Omit<DiscoverModelItem, 'suggestions' | 'socialData' | 'providers'>,
45
45
  FlexboxProps {}
46
46
 
47
- const SuggestionItem = memo<SuggestionItemProps>(({ className, meta, identifier, ...rest }) => {
47
+ const SuggestionItem = memo<SuggestionItemProps>(({ className, meta, identifier }) => {
48
48
  const { title, description, contextWindowTokens, vision, functionCall } = meta;
49
49
  const { t } = useTranslation('models');
50
50
  const { cx, styles } = useStyles();
51
51
 
52
52
  return (
53
- <Flexbox className={cx(styles.container, className)} gap={12} key={identifier} {...rest}>
53
+ <Flexbox className={cx(styles.container, className)} gap={12} key={identifier}>
54
54
  <Flexbox align={'center'} gap={12} horizontal width={'100%'}>
55
55
  <ModelIcon model={identifier} size={36} type={'avatar'} />
56
56
  <Flexbox style={{ overflow: 'hidden' }}>
@@ -89,10 +89,10 @@ const ParameterList = memo<ParameterListProps>(({ data }) => {
89
89
  <Block title={t('models.parameterList.title')}>
90
90
  <Collapse
91
91
  defaultActiveKey={items.map((item) => item.key)}
92
- expandIconPosition={'right'}
92
+ expandIconPosition={'end'}
93
93
  gap={16}
94
94
  items={items.map((item) => ({
95
- children: <ParameterItem {...item} />,
95
+ children: <ParameterItem {...item} key={item.key} />,
96
96
  key: item.key,
97
97
  label: (
98
98
  <Flexbox align={'center'} gap={8} horizontal>
@@ -4,7 +4,7 @@ import { ModelIcon } from '@lobehub/icons';
4
4
  import { Divider } from 'antd';
5
5
  import { useTheme } from 'antd-style';
6
6
  import { BrainCircuit } from 'lucide-react';
7
- import { memo } from 'react';
7
+ import { Fragment, memo } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
10
  import { DiscoverProviderItem } from '@/types/discover';
@@ -33,10 +33,10 @@ const ProviderList = memo<ProviderListProps>(({ mobile, data, identifier }) => {
33
33
  title={t('models.supportedProviders')}
34
34
  >
35
35
  {data.map((item, index) => (
36
- <>
37
- <ProviderItem key={item.identifier} mobile={mobile} modelId={identifier} {...item} />
38
- {index < data.length - 1 && <Divider key={index} style={{ margin: 0 }} />}
39
- </>
36
+ <Fragment key={item.identifier}>
37
+ <ProviderItem mobile={mobile} modelId={identifier} {...item} />
38
+ {index < data.length - 1 && <Divider style={{ margin: 0 }} />}
39
+ </Fragment>
40
40
  ))}
41
41
  </HighlightBlock>
42
42
  );
@@ -2,13 +2,8 @@ import { createStyles } from 'antd-style';
2
2
  import React from 'react';
3
3
  import { Center } from 'react-layout-kit';
4
4
  import { TableVirtuoso } from 'react-virtuoso';
5
- import useSWR from 'swr';
6
5
 
7
- import { tableViewerService } from '@/services/tableViewer';
8
- import { useGlobalStore } from '@/store/global';
9
- import { systemStatusSelectors } from '@/store/global/selectors';
10
-
11
- import { useTableColumns } from '../useTableColumns';
6
+ import { usePgTable, useTableColumns } from '../usePgTable';
12
7
  import TableCell from './TableCell';
13
8
 
14
9
  const useStyles = createStyles(({ token, css }) => ({
@@ -100,12 +95,8 @@ const Table = ({ tableName }: TableProps) => {
100
95
  const { styles } = useStyles();
101
96
 
102
97
  const tableColumns = useTableColumns(tableName);
103
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
104
98
 
105
- const tableData = useSWR(
106
- isDBInited && tableName ? ['fetch-table-data', tableName] : null,
107
- ([, table]) => tableViewerService.getTableData(table),
108
- );
99
+ const tableData = usePgTable(tableName);
109
100
 
110
101
  const columns = tableColumns.data?.map((t) => t.name) || [];
111
102
  const isLoading = tableColumns.isLoading || tableData.isLoading;
@@ -3,7 +3,9 @@ import { Button } from 'antd';
3
3
  import { createStyles } from 'antd-style';
4
4
  import { Download, Filter, RefreshCw } from 'lucide-react';
5
5
  import React from 'react';
6
+ import { mutate } from 'swr';
6
7
 
8
+ import { FETCH_TABLE_DATA_KEY } from '../usePgTable';
7
9
  import Table from './Table';
8
10
 
9
11
  const useStyles = createStyles(({ token, css }) => ({
@@ -54,7 +56,13 @@ const DataTable = ({ tableName }: DataTableProps) => {
54
56
  Filter
55
57
  </Button>
56
58
  <ActionIcon icon={Download} title={'Export'} />
57
- <ActionIcon icon={RefreshCw} title={'Refresh'} />
59
+ <ActionIcon
60
+ icon={RefreshCw}
61
+ onClick={async () => {
62
+ await mutate(FETCH_TABLE_DATA_KEY(tableName));
63
+ }}
64
+ title={'Refresh'}
65
+ />
58
66
  </div>
59
67
  </div>
60
68
 
@@ -3,15 +3,10 @@ import { createStyles } from 'antd-style';
3
3
  import { ChevronDown, ChevronRight, Database, Table as TableIcon } from 'lucide-react';
4
4
  import React, { useState } from 'react';
5
5
  import { Flexbox } from 'react-layout-kit';
6
- import useSWR from 'swr';
7
-
8
- import { tableViewerService } from '@/services/tableViewer';
9
- import { useGlobalStore } from '@/store/global';
10
- import { systemStatusSelectors } from '@/store/global/selectors';
11
6
 
12
7
  import TableColumns from './TableColumns';
8
+ import { useFetchTables } from './usePgTable';
13
9
 
14
- // 样式定义
15
10
  const useStyles = createStyles(({ token, css }) => ({
16
11
  button: css`
17
12
  cursor: pointer;
@@ -138,11 +133,7 @@ const SchemaPanel = ({ onTableSelect, selectedTable }: SchemaPanelProps) => {
138
133
  const { styles, cx } = useStyles();
139
134
  const [expandedTables, setExpandedTables] = useState(new Set());
140
135
 
141
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
142
-
143
- const { data, isLoading } = useSWR(isDBInited ? 'fetch-tables' : null, () =>
144
- tableViewerService.getAllTables(),
145
- );
136
+ const { data, isLoading } = useFetchTables();
146
137
 
147
138
  const toggleTable = (tableName: string) => {
148
139
  const newExpanded = new Set(expandedTables);
@@ -3,7 +3,7 @@ import { createStyles } from 'antd-style';
3
3
  import React from 'react';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
- import { useTableColumns } from './useTableColumns';
6
+ import { useTableColumns } from './usePgTable';
7
7
 
8
8
  const useStyles = createStyles(({ token, css }) => ({
9
9
  container: css`
@@ -0,0 +1,31 @@
1
+ import useSWR from 'swr';
2
+
3
+ import { tableViewerService } from '@/services/tableViewer';
4
+ import { useGlobalStore } from '@/store/global';
5
+ import { systemStatusSelectors } from '@/store/global/selectors';
6
+
7
+ const FETCH_TABLES = 'fetch-tables';
8
+ const FETCH_TABLE_COLUMN_KEY = (tableName: string) => ['fetch-table-columns', tableName];
9
+ export const FETCH_TABLE_DATA_KEY = (tableName: string) => ['fetch-table-data', tableName];
10
+
11
+ export const useFetchTables = () => {
12
+ const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
13
+
14
+ return useSWR(isDBInited ? FETCH_TABLES : null, () => tableViewerService.getAllTables());
15
+ };
16
+
17
+ export const useTableColumns = (tableName?: string) => {
18
+ const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
19
+
20
+ return useSWR(isDBInited && tableName ? FETCH_TABLE_COLUMN_KEY(tableName) : null, ([, table]) =>
21
+ tableViewerService.getTableDetails(table),
22
+ );
23
+ };
24
+
25
+ export const usePgTable = (tableName?: string) => {
26
+ const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
27
+
28
+ return useSWR(isDBInited && tableName ? FETCH_TABLE_DATA_KEY(tableName) : null, ([, table]) =>
29
+ tableViewerService.getTableData(table),
30
+ );
31
+ };
@@ -23,6 +23,9 @@ export interface ImportResults {
23
23
  type?: string;
24
24
  }
25
25
 
26
+ /**
27
+ * @deprecated
28
+ */
26
29
  class ConfigService {
27
30
  importConfigState = async (config: ConfigFile, callbacks?: OnImportCallbacks): Promise<void> => {
28
31
  if (config.exportType === 'settings') {
@@ -1,13 +0,0 @@
1
- import useSWR from 'swr';
2
-
3
- import { tableViewerService } from '@/services/tableViewer';
4
- import { useGlobalStore } from '@/store/global';
5
- import { systemStatusSelectors } from '@/store/global/selectors';
6
-
7
- export const useTableColumns = (tableName?: string) => {
8
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
9
-
10
- return useSWR(isDBInited && tableName ? ['fetch-table-columns', tableName] : null, ([, table]) =>
11
- tableViewerService.getTableDetails(table),
12
- );
13
- };