balibabu commited on
Commit
97d4387
·
1 Parent(s): eb38196

feat: set chunk to available state and select all chunk (#57)

Browse files

* feat: set chunk to available state

* feat: select all chunk

web/.eslintrc.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ // .eslintrc.js
2
+ module.exports = {
3
+ // Umi 项目
4
+ extends: [require.resolve('umi/eslint'), 'plugin:react-hooks/recommended'],
5
+ };
web/package-lock.json CHANGED
@@ -27,6 +27,7 @@
27
  "@types/lodash": "^4.14.202",
28
  "@types/react": "^18.0.33",
29
  "@types/react-dom": "^18.0.11",
 
30
  "@umijs/plugins": "^4.1.0",
31
  "cross-env": "^7.0.3",
32
  "prettier": "^3.2.4",
@@ -3479,16 +3480,17 @@
3479
  }
3480
  },
3481
  "node_modules/@umijs/lint": {
3482
- "version": "4.1.0",
3483
- "resolved": "https://registry.npmmirror.com/@umijs/lint/-/lint-4.1.0.tgz",
3484
- "integrity": "sha512-drXkAeBJGMLrPr/dDiOZ2Z+3VKkAf53MzoOIhwHy5atq+PFNG9Y7e6YuWrK3qVF75zg9culQzlHTvinCjDK97Q==",
 
3485
  "dependencies": {
3486
  "@babel/core": "7.23.6",
3487
  "@babel/eslint-parser": "7.23.3",
3488
  "@stylelint/postcss-css-in-js": "^0.38.0",
3489
  "@typescript-eslint/eslint-plugin": "^5.62.0",
3490
  "@typescript-eslint/parser": "^5.62.0",
3491
- "@umijs/babel-preset-umi": "4.1.0",
3492
  "eslint-plugin-jest": "27.2.3",
3493
  "eslint-plugin-react": "7.33.2",
3494
  "eslint-plugin-react-hooks": "4.6.0",
@@ -3501,6 +3503,7 @@
3501
  "version": "7.23.6",
3502
  "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.6.tgz",
3503
  "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
 
3504
  "dependencies": {
3505
  "@ampproject/remapping": "^2.2.0",
3506
  "@babel/code-frame": "^7.23.5",
@@ -3522,6 +3525,54 @@
3522
  "node": ">=6.9.0"
3523
  }
3524
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3525
  "node_modules/@umijs/mfsu": {
3526
  "version": "4.1.0",
3527
  "resolved": "https://registry.npmmirror.com/@umijs/mfsu/-/mfsu-4.1.0.tgz",
@@ -16319,6 +16370,31 @@
16319
  "qs": "^6.9.1"
16320
  }
16321
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16322
  "node_modules/umi/node_modules/@babel/runtime": {
16323
  "version": "7.23.6",
16324
  "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.6.tgz",
@@ -16330,6 +16406,25 @@
16330
  "node": ">=6.9.0"
16331
  }
16332
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16333
  "node_modules/umi/node_modules/fast-glob": {
16334
  "version": "3.3.2",
16335
  "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz",
 
27
  "@types/lodash": "^4.14.202",
28
  "@types/react": "^18.0.33",
29
  "@types/react-dom": "^18.0.11",
30
+ "@umijs/lint": "^4.1.1",
31
  "@umijs/plugins": "^4.1.0",
32
  "cross-env": "^7.0.3",
33
  "prettier": "^3.2.4",
 
3480
  }
3481
  },
3482
  "node_modules/@umijs/lint": {
3483
+ "version": "4.1.1",
3484
+ "resolved": "https://registry.npmmirror.com/@umijs/lint/-/lint-4.1.1.tgz",
3485
+ "integrity": "sha512-fy2edKuYw42eM3LuH/2AiH0ZKdembFx3SR8dIGKxf7BmEQOSfUhskLiNGE8tSRubCiVzGUWvZQDw1YQcU0bsHg==",
3486
+ "dev": true,
3487
  "dependencies": {
3488
  "@babel/core": "7.23.6",
3489
  "@babel/eslint-parser": "7.23.3",
3490
  "@stylelint/postcss-css-in-js": "^0.38.0",
3491
  "@typescript-eslint/eslint-plugin": "^5.62.0",
3492
  "@typescript-eslint/parser": "^5.62.0",
3493
+ "@umijs/babel-preset-umi": "4.1.1",
3494
  "eslint-plugin-jest": "27.2.3",
3495
  "eslint-plugin-react": "7.33.2",
3496
  "eslint-plugin-react-hooks": "4.6.0",
 
3503
  "version": "7.23.6",
3504
  "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.6.tgz",
3505
  "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
3506
+ "dev": true,
3507
  "dependencies": {
3508
  "@ampproject/remapping": "^2.2.0",
3509
  "@babel/code-frame": "^7.23.5",
 
3525
  "node": ">=6.9.0"
3526
  }
3527
  },
3528
+ "node_modules/@umijs/lint/node_modules/@babel/runtime": {
3529
+ "version": "7.23.6",
3530
+ "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.6.tgz",
3531
+ "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
3532
+ "dev": true,
3533
+ "dependencies": {
3534
+ "regenerator-runtime": "^0.14.0"
3535
+ },
3536
+ "engines": {
3537
+ "node": ">=6.9.0"
3538
+ }
3539
+ },
3540
+ "node_modules/@umijs/lint/node_modules/@umijs/babel-preset-umi": {
3541
+ "version": "4.1.1",
3542
+ "resolved": "https://registry.npmmirror.com/@umijs/babel-preset-umi/-/babel-preset-umi-4.1.1.tgz",
3543
+ "integrity": "sha512-6pYZnF03euAJGZN3VLe8PKKRNMH6Zxj4GKNooLvJ0Wz0eMufmYDcA4CpbR6h8i1JpgcQ0Sngr8bqHLb7oMqrvw==",
3544
+ "dev": true,
3545
+ "dependencies": {
3546
+ "@babel/runtime": "7.23.6",
3547
+ "@bloomberg/record-tuple-polyfill": "0.0.4",
3548
+ "@umijs/bundler-utils": "4.1.1",
3549
+ "@umijs/utils": "4.1.1",
3550
+ "core-js": "3.34.0"
3551
+ }
3552
+ },
3553
+ "node_modules/@umijs/lint/node_modules/@umijs/bundler-utils": {
3554
+ "version": "4.1.1",
3555
+ "resolved": "https://registry.npmmirror.com/@umijs/bundler-utils/-/bundler-utils-4.1.1.tgz",
3556
+ "integrity": "sha512-k1I1tjDePgB1XqpQHZiLJ/5gS4EykY8hqqzEzD1CSbd5KFE614+q6W/gcpFZ0YLJDWY1GdjOYpRokvuI/MSRfg==",
3557
+ "dev": true,
3558
+ "dependencies": {
3559
+ "@umijs/utils": "4.1.1",
3560
+ "esbuild": "0.17.19",
3561
+ "regenerate": "^1.4.2",
3562
+ "regenerate-unicode-properties": "10.1.1",
3563
+ "spdy": "^4.0.2"
3564
+ }
3565
+ },
3566
+ "node_modules/@umijs/lint/node_modules/@umijs/utils": {
3567
+ "version": "4.1.1",
3568
+ "resolved": "https://registry.npmmirror.com/@umijs/utils/-/utils-4.1.1.tgz",
3569
+ "integrity": "sha512-hbnbJR3RA7fu4E7q4JFZ47XMYArr6Zn5bftr8YZ+o6hzJlomr4gzoOXE+XxM7rVMK4AFZoc+QZgNTJyISd08Pg==",
3570
+ "dev": true,
3571
+ "dependencies": {
3572
+ "chokidar": "3.5.3",
3573
+ "pino": "7.11.0"
3574
+ }
3575
+ },
3576
  "node_modules/@umijs/mfsu": {
3577
  "version": "4.1.0",
3578
  "resolved": "https://registry.npmmirror.com/@umijs/mfsu/-/mfsu-4.1.0.tgz",
 
16370
  "qs": "^6.9.1"
16371
  }
16372
  },
16373
+ "node_modules/umi/node_modules/@babel/core": {
16374
+ "version": "7.23.6",
16375
+ "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.6.tgz",
16376
+ "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
16377
+ "dependencies": {
16378
+ "@ampproject/remapping": "^2.2.0",
16379
+ "@babel/code-frame": "^7.23.5",
16380
+ "@babel/generator": "^7.23.6",
16381
+ "@babel/helper-compilation-targets": "^7.23.6",
16382
+ "@babel/helper-module-transforms": "^7.23.3",
16383
+ "@babel/helpers": "^7.23.6",
16384
+ "@babel/parser": "^7.23.6",
16385
+ "@babel/template": "^7.22.15",
16386
+ "@babel/traverse": "^7.23.6",
16387
+ "@babel/types": "^7.23.6",
16388
+ "convert-source-map": "^2.0.0",
16389
+ "debug": "^4.1.0",
16390
+ "gensync": "^1.0.0-beta.2",
16391
+ "json5": "^2.2.3",
16392
+ "semver": "^6.3.1"
16393
+ },
16394
+ "engines": {
16395
+ "node": ">=6.9.0"
16396
+ }
16397
+ },
16398
  "node_modules/umi/node_modules/@babel/runtime": {
16399
  "version": "7.23.6",
16400
  "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.6.tgz",
 
16406
  "node": ">=6.9.0"
16407
  }
16408
  },
16409
+ "node_modules/umi/node_modules/@umijs/lint": {
16410
+ "version": "4.1.0",
16411
+ "resolved": "https://registry.npmmirror.com/@umijs/lint/-/lint-4.1.0.tgz",
16412
+ "integrity": "sha512-drXkAeBJGMLrPr/dDiOZ2Z+3VKkAf53MzoOIhwHy5atq+PFNG9Y7e6YuWrK3qVF75zg9culQzlHTvinCjDK97Q==",
16413
+ "dependencies": {
16414
+ "@babel/core": "7.23.6",
16415
+ "@babel/eslint-parser": "7.23.3",
16416
+ "@stylelint/postcss-css-in-js": "^0.38.0",
16417
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
16418
+ "@typescript-eslint/parser": "^5.62.0",
16419
+ "@umijs/babel-preset-umi": "4.1.0",
16420
+ "eslint-plugin-jest": "27.2.3",
16421
+ "eslint-plugin-react": "7.33.2",
16422
+ "eslint-plugin-react-hooks": "4.6.0",
16423
+ "postcss": "^8.4.21",
16424
+ "postcss-syntax": "0.36.2",
16425
+ "stylelint-config-standard": "25.0.0"
16426
+ }
16427
+ },
16428
  "node_modules/umi/node_modules/fast-glob": {
16429
  "version": "3.3.2",
16430
  "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.2.tgz",
web/package.json CHANGED
@@ -5,6 +5,7 @@
5
  "build": "umi build",
6
  "dev": "cross-env PORT=9000 umi dev",
7
  "postinstall": "umi setup",
 
8
  "setup": "umi setup",
9
  "start": "npm run dev"
10
  },
@@ -30,6 +31,7 @@
30
  "@types/lodash": "^4.14.202",
31
  "@types/react": "^18.0.33",
32
  "@types/react-dom": "^18.0.11",
 
33
  "@umijs/plugins": "^4.1.0",
34
  "cross-env": "^7.0.3",
35
  "prettier": "^3.2.4",
 
5
  "build": "umi build",
6
  "dev": "cross-env PORT=9000 umi dev",
7
  "postinstall": "umi setup",
8
+ "lint": "umi lint --eslint-only",
9
  "setup": "umi setup",
10
  "start": "npm run dev"
11
  },
 
31
  "@types/lodash": "^4.14.202",
32
  "@types/react": "^18.0.33",
33
  "@types/react-dom": "^18.0.11",
34
+ "@umijs/lint": "^4.1.1",
35
  "@umijs/plugins": "^4.1.0",
36
  "cross-env": "^7.0.3",
37
  "prettier": "^3.2.4",
web/src/app.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import React, { ReactNode } from "react";
2
- import { Inspector } from "react-dev-inspector";
3
 
4
  export function rootContainer(container: ReactNode) {
5
  return React.createElement(Inspector, null, container);
 
1
+ import React, { ReactNode } from 'react';
2
+ import { Inspector } from 'react-dev-inspector';
3
 
4
  export function rootContainer(container: ReactNode) {
5
  return React.createElement(Inspector, null, container);
web/src/interfaces/common.ts CHANGED
@@ -5,4 +5,5 @@ export interface Pagination {
5
 
6
  export interface BaseState {
7
  pagination: Pagination;
 
8
  }
 
5
 
6
  export interface BaseState {
7
  pagination: Pagination;
8
+ searchString: string;
9
  }
web/src/interfaces/database/knowledge.ts CHANGED
@@ -65,3 +65,13 @@ export interface ITenantInfo {
65
  chat_id: string;
66
  speech2text_id: string;
67
  }
 
 
 
 
 
 
 
 
 
 
 
65
  chat_id: string;
66
  speech2text_id: string;
67
  }
68
+
69
+ export interface IChunk {
70
+ available_int: number; // Whether to enable, 0: not enabled, 1: enabled
71
+ chunk_id: string;
72
+ content_with_weight: string;
73
+ doc_id: string;
74
+ docnm_kwd: string;
75
+ img_id: string;
76
+ important_kwd: any[];
77
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ .image {
2
+ width: 100px !important;
3
+ min-width: 100px;
4
+ }
5
+
6
+ .imagePreview {
7
+ width: 600px;
8
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { IChunk } from '@/interfaces/database/knowledge';
2
+ import { api_host } from '@/utils/api';
3
+ import { Card, Checkbox, CheckboxProps, Flex, Popover, Switch } from 'antd';
4
+ import { useDispatch } from 'umi';
5
+
6
+ import { useState } from 'react';
7
+ import styles from './index.less';
8
+
9
+ interface IProps {
10
+ item: IChunk;
11
+ checked: boolean;
12
+ handleCheckboxClick: (chunkId: string, checked: boolean) => void;
13
+ }
14
+
15
+ interface IImage {
16
+ id: string;
17
+ className: string;
18
+ }
19
+ // Pass onMouseEnter and onMouseLeave to img tag using props
20
+ const Image = ({ id, className, ...props }: IImage) => {
21
+ return (
22
+ <img
23
+ {...props}
24
+ src={`${api_host}/document/image/${id}`}
25
+ alt=""
26
+ className={className}
27
+ />
28
+ );
29
+ };
30
+
31
+ const ChunkCard = ({ item, checked, handleCheckboxClick }: IProps) => {
32
+ const dispatch = useDispatch();
33
+
34
+ const available = Number(item.available_int);
35
+ const [enabled, setEnabled] = useState(available === 1);
36
+
37
+ const switchChunk = () => {
38
+ dispatch({
39
+ type: 'chunkModel/switch_chunk',
40
+ payload: {
41
+ chunk_ids: [item.chunk_id],
42
+ available_int: available === 0 ? 1 : 0,
43
+ doc_id: item.doc_id,
44
+ },
45
+ });
46
+ };
47
+
48
+ const onChange = (checked: boolean) => {
49
+ setEnabled(checked);
50
+ switchChunk();
51
+ };
52
+
53
+ const handleCheck: CheckboxProps['onChange'] = (e) => {
54
+ handleCheckboxClick(item.chunk_id, e.target.checked);
55
+ };
56
+
57
+ return (
58
+ <div>
59
+ <Card>
60
+ <Flex gap={'middle'} justify={'space-between'}>
61
+ <Checkbox onChange={handleCheck} checked={checked}></Checkbox>
62
+ {item.img_id && (
63
+ <Popover
64
+ placement="topRight"
65
+ content={
66
+ <Image id={item.img_id} className={styles.imagePreview}></Image>
67
+ }
68
+ >
69
+ <img
70
+ src={`${api_host}/document/image/${item.img_id}`}
71
+ alt=""
72
+ className={styles.image}
73
+ />
74
+ <Image id={item.img_id} className={styles.image}></Image>
75
+ </Popover>
76
+ )}
77
+
78
+ <section>{item.content_with_weight}</section>
79
+ <div>
80
+ <Switch checked={enabled} onChange={onChange} />
81
+ </div>
82
+ </Flex>
83
+ </Card>
84
+ </div>
85
+ );
86
+ };
87
+
88
+ export default ChunkCard;
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx CHANGED
@@ -1,4 +1,6 @@
1
  import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
 
 
2
  import {
3
  ArrowLeftOutlined,
4
  CheckCircleOutlined,
@@ -9,17 +11,50 @@ import {
9
  PlusOutlined,
10
  SearchOutlined,
11
  } from '@ant-design/icons';
12
- import { Button, Checkbox, Flex, Menu, MenuProps, Popover, Space } from 'antd';
13
- import { useMemo } from 'react';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- const ChunkToolBar = () => {
16
  const items: MenuProps['items'] = useMemo(() => {
17
  return [
18
  {
19
  key: '1',
20
  label: (
21
  <>
22
- <Checkbox>
23
  <b>Select All</b>
24
  </Checkbox>
25
  </>
@@ -55,47 +90,49 @@ const ChunkToolBar = () => {
55
  ),
56
  },
57
  ];
58
- }, []);
59
 
60
  const content = (
61
  <Menu style={{ width: 200 }} items={items} selectable={false} />
62
  );
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  return (
65
  <Flex justify="space-between" align="center">
66
- <Space>
67
- <ArrowLeftOutlined />
 
 
 
 
68
  <FilePdfOutlined />
69
- xxx.pdf
70
  </Space>
71
  <Space>
72
- {/* <Select
73
- defaultValue="lucy"
74
- style={{ width: 100 }}
75
- popupMatchSelectWidth={false}
76
- optionRender={() => null}
77
- dropdownRender={(menu) => (
78
- <div style={{ width: 300 }}>
79
- {menu}
80
- <Menu
81
- // onClick={onClick}
82
- style={{ width: 256 }}
83
- // defaultSelectedKeys={['1']}
84
- // defaultOpenKeys={['sub1']}
85
- // mode="inline"
86
- items={actionItems}
87
- />
88
- </div>
89
- )}
90
- ></Select> */}
91
- <Popover content={content} placement="bottomLeft" arrow={false}>
92
  <Button>
93
  Bulk
94
  <DownOutlined />
95
  </Button>
96
  </Popover>
97
  <Button icon={<SearchOutlined />} />
98
- <Button icon={<FilterIcon />} />
 
 
99
  <Button icon={<DeleteOutlined />} />
100
  <Button icon={<PlusOutlined />} type="primary" />
101
  </Space>
 
1
  import { ReactComponent as FilterIcon } from '@/assets/filter.svg';
2
+ import { KnowledgeRouteKey } from '@/constants/knowledge';
3
+ import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
4
  import {
5
  ArrowLeftOutlined,
6
  CheckCircleOutlined,
 
11
  PlusOutlined,
12
  SearchOutlined,
13
  } from '@ant-design/icons';
14
+ import {
15
+ Button,
16
+ Checkbox,
17
+ Flex,
18
+ Menu,
19
+ MenuProps,
20
+ Popover,
21
+ Radio,
22
+ RadioChangeEvent,
23
+ Space,
24
+ } from 'antd';
25
+ import { useCallback, useMemo } from 'react';
26
+ import { Link, useDispatch, useSelector } from 'umi';
27
+ import { ChunkModelState } from '../../model';
28
+
29
+ interface IProps {
30
+ checked: boolean;
31
+ getChunkList: () => void;
32
+ selectAllChunk: (checked: boolean) => void;
33
+ }
34
+
35
+ const ChunkToolBar = ({ getChunkList, selectAllChunk, checked }: IProps) => {
36
+ const { documentInfo, available }: ChunkModelState = useSelector(
37
+ (state: any) => state.chunkModel,
38
+ );
39
+ const dispatch = useDispatch();
40
+
41
+ const knowledgeBaseId = useKnowledgeBaseId();
42
+
43
+ const handleSelectAllCheck = useCallback(
44
+ (e: any) => {
45
+ // console.info(e.target.checked);
46
+ selectAllChunk(e.target.checked);
47
+ },
48
+ [selectAllChunk],
49
+ );
50
 
 
51
  const items: MenuProps['items'] = useMemo(() => {
52
  return [
53
  {
54
  key: '1',
55
  label: (
56
  <>
57
+ <Checkbox onChange={handleSelectAllCheck} checked={checked}>
58
  <b>Select All</b>
59
  </Checkbox>
60
  </>
 
90
  ),
91
  },
92
  ];
93
+ }, [checked, handleSelectAllCheck]);
94
 
95
  const content = (
96
  <Menu style={{ width: 200 }} items={items} selectable={false} />
97
  );
98
 
99
+ const handleFilterChange = (e: RadioChangeEvent) => {
100
+ dispatch({ type: 'chunkModel/setAvailable', payload: e.target.value });
101
+ getChunkList();
102
+ };
103
+
104
+ const filterContent = (
105
+ <Radio.Group onChange={handleFilterChange} value={available}>
106
+ <Space direction="vertical">
107
+ <Radio value={undefined}>All</Radio>
108
+ <Radio value={1}>Enabled</Radio>
109
+ <Radio value={0}>Disabled</Radio>
110
+ </Space>
111
+ </Radio.Group>
112
+ );
113
+
114
  return (
115
  <Flex justify="space-between" align="center">
116
+ <Space size={'middle'}>
117
+ <Link
118
+ to={`/knowledge/${KnowledgeRouteKey.Dataset}?id=${knowledgeBaseId}`}
119
+ >
120
+ <ArrowLeftOutlined />
121
+ </Link>
122
  <FilePdfOutlined />
123
+ {documentInfo.name}
124
  </Space>
125
  <Space>
126
+ <Popover content={content} placement="bottom" arrow={false}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  <Button>
128
  Bulk
129
  <DownOutlined />
130
  </Button>
131
  </Popover>
132
  <Button icon={<SearchOutlined />} />
133
+ <Popover content={filterContent} placement="bottom" arrow={false}>
134
+ <Button icon={<FilterIcon />} />
135
+ </Popover>
136
  <Button icon={<DeleteOutlined />} />
137
  <Button icon={<PlusOutlined />} type="primary" />
138
  </Space>
web/src/pages/add-knowledge/components/knowledge-chunk/index.less CHANGED
@@ -1,70 +1,69 @@
1
  .chunkPage {
2
- padding: 24px;
3
 
4
- display: flex;
5
- height: calc(100vh - 112px);
6
- flex-direction: column;
7
 
8
- .filter {
9
- margin: 10px 0;
10
- display: flex;
11
- height: 32px;
12
- justify-content: space-between;
13
- }
14
 
15
- .pageContent {
16
- flex: 1;
17
- width: 100%;
18
- padding-right: 12px;
19
- overflow-y: auto;
20
 
21
- .spin {
22
- min-height: 400px;
23
- }
24
  }
 
25
 
26
- .pageFooter {
27
- height: 32px;
28
- }
29
  }
30
 
31
  .container {
32
- height: 100px;
 
 
 
 
 
33
  display: flex;
34
- flex-direction: column;
35
  justify-content: space-between;
36
 
37
- .content {
38
- display: flex;
39
- justify-content: space-between;
40
-
41
- .context {
42
- flex: 1;
43
- // width: 207px;
44
- height: 88px;
45
- overflow: hidden;
46
- }
47
  }
 
48
 
49
- .footer {
50
- height: 20px;
51
 
52
- .text {
53
- margin-left: 10px;
54
- }
55
  }
 
56
  }
57
 
58
  .card {
59
- :global {
60
- .ant-card-body {
61
- padding: 10px;
62
- margin: 0;
63
- }
64
-
65
- margin-bottom: 10px;
66
  }
67
 
68
- cursor: pointer;
 
69
 
70
- }
 
 
1
  .chunkPage {
2
+ padding: 24px;
3
 
4
+ display: flex;
5
+ // height: calc(100vh - 112px);
6
+ flex-direction: column;
7
 
8
+ .filter {
9
+ margin: 10px 0;
10
+ display: flex;
11
+ height: 32px;
12
+ justify-content: space-between;
13
+ }
14
 
15
+ .pageContent {
16
+ flex: 1;
17
+ width: 100%;
18
+ padding-right: 12px;
19
+ overflow-y: auto;
20
 
21
+ .spin {
22
+ min-height: 400px;
 
23
  }
24
+ }
25
 
26
+ .pageFooter {
27
+ height: 32px;
28
+ }
29
  }
30
 
31
  .container {
32
+ height: 100px;
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: space-between;
36
+
37
+ .content {
38
  display: flex;
 
39
  justify-content: space-between;
40
 
41
+ .context {
42
+ flex: 1;
43
+ // width: 207px;
44
+ height: 88px;
45
+ overflow: hidden;
 
 
 
 
 
46
  }
47
+ }
48
 
49
+ .footer {
50
+ height: 20px;
51
 
52
+ .text {
53
+ margin-left: 10px;
 
54
  }
55
+ }
56
  }
57
 
58
  .card {
59
+ :global {
60
+ .ant-card-body {
61
+ padding: 10px;
62
+ margin: 0;
 
 
 
63
  }
64
 
65
+ margin-bottom: 10px;
66
+ }
67
 
68
+ cursor: pointer;
69
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx CHANGED
@@ -1,41 +1,36 @@
1
- import { api_host } from '@/utils/api';
2
  import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
3
- import { DeleteOutlined, MinusSquareOutlined } from '@ant-design/icons';
4
  import type { PaginationProps } from 'antd';
5
- import {
6
- Button,
7
- Card,
8
- Col,
9
- Input,
10
- Pagination,
11
- Popconfirm,
12
- Row,
13
- Select,
14
- Spin,
15
- Switch,
16
- } from 'antd';
17
  import { debounce } from 'lodash';
18
  import React, { useCallback, useEffect, useState } from 'react';
19
  import { useDispatch, useSearchParams, useSelector } from 'umi';
20
  import CreateModal from './components/createModal';
21
 
 
22
  import ChunkToolBar from './components/chunk-toolbar';
23
  import styles from './index.less';
 
24
 
25
  interface PayloadType {
26
  doc_id: string;
27
  keywords?: string;
28
- available_int?: number;
29
  }
30
 
31
  const Chunk = () => {
32
  const dispatch = useDispatch();
33
- const chunkModel = useSelector((state: any) => state.chunkModel);
 
 
34
  const [keywords, SetKeywords] = useState('');
35
- const [available_int, setAvailableInt] = useState(-1);
36
  const [searchParams] = useSearchParams();
37
- const [pagination, setPagination] = useState({ page: 1, size: 30 });
38
- const { data = [], total, chunk_id, isShowCreateModal } = chunkModel;
 
 
 
 
 
39
  const effects = useSelector((state: any) => state.loading.effects);
40
  const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
41
  'create_hunk',
@@ -44,23 +39,19 @@ const Chunk = () => {
44
  ]);
45
  const documentId: string = searchParams.get('doc_id') || '';
46
 
47
- const getChunkList = (value?: string) => {
48
  const payload: PayloadType = {
49
  doc_id: documentId,
50
- keywords: value || keywords,
51
- available_int,
52
  };
53
- if (payload.available_int === -1) {
54
- delete payload.available_int;
55
- }
56
  dispatch({
57
  type: 'chunkModel/chunk_list',
58
  payload: {
59
  ...payload,
60
- ...pagination,
61
  },
62
  });
63
  };
 
64
  const confirm = async (id: string) => {
65
  const retcode = await dispatch<any>({
66
  type: 'chunkModel/rm_chunk',
@@ -84,29 +75,55 @@ const Chunk = () => {
84
  getChunkList();
85
  };
86
 
87
- const onShowSizeChange: PaginationProps['onShowSizeChange'] = (
88
  page,
89
  size,
90
  ) => {
91
- setPagination({ page, size });
92
- };
93
-
94
- const switchChunk = async (id: string, available_int: boolean) => {
95
- const retcode = await dispatch<any>({
96
- type: 'chunkModel/switch_chunk',
97
  payload: {
98
- chunk_ids: [id],
99
- available_int: Number(available_int),
100
- doc_id: documentId,
101
  },
102
  });
103
-
104
- retcode === 0 && getChunkList();
105
  };
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  useEffect(() => {
108
  getChunkList();
109
- }, [documentId, available_int, pagination]);
 
 
 
 
 
110
 
111
  const debounceChange = debounce(getChunkList, 300);
112
  const debounceCallback = useCallback(
@@ -117,17 +134,20 @@ const Chunk = () => {
117
  const handleInputChange = (
118
  e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
119
  ) => {
 
120
  const value = e.target.value;
121
  SetKeywords(value);
122
  debounceCallback(value);
123
  };
124
- const handleSelectChange = (value: number) => {
125
- setAvailableInt(value);
126
- };
127
  return (
128
  <>
129
  <div className={styles.chunkPage}>
130
- <ChunkToolBar></ChunkToolBar>
 
 
 
 
131
  <div className={styles.filter}>
132
  <div>
133
  <Input
@@ -137,28 +157,6 @@ const Chunk = () => {
137
  allowClear
138
  onChange={handleInputChange}
139
  />
140
- <Select
141
- showSearch
142
- placeholder="是否启用"
143
- optionFilterProp="children"
144
- value={available_int}
145
- onChange={handleSelectChange}
146
- style={{ width: 220 }}
147
- options={[
148
- {
149
- value: -1,
150
- label: '全部',
151
- },
152
- {
153
- value: 1,
154
- label: '启用',
155
- },
156
- {
157
- value: 0,
158
- label: '未启用',
159
- },
160
- ]}
161
- />
162
  </div>
163
  <Button
164
  onClick={() => {
@@ -171,86 +169,16 @@ const Chunk = () => {
171
  </div>
172
  <div className={styles.pageContent}>
173
  <Spin spinning={loading} className={styles.spin} size="large">
174
- <Row gutter={{ xs: 8, sm: 16, md: 24, lg: 24 }}>
175
- {data.map((item: any) => {
176
- return (
177
- <Col
178
- className="gutter-row"
179
- key={item.chunk_id}
180
- xs={24}
181
- sm={12}
182
- md={12}
183
- lg={8}
184
- >
185
- <Card
186
- className={styles.card}
187
- onClick={() => {
188
- handleEditchunk(item.chunk_id);
189
- }}
190
- >
191
- <img
192
- style={{ width: '50px' }}
193
- src={`${api_host}/document/image/${item.img_id}`}
194
- alt=""
195
- />
196
- <div className={styles.container}>
197
- <div className={styles.content}>
198
- <span className={styles.context}>
199
- {item.content_ltks}
200
- </span>
201
- <span className={styles.delete}>
202
- <Switch
203
- size="small"
204
- defaultValue={item.available_int == '1'}
205
- onChange={(checked: boolean, e: any) => {
206
- e.stopPropagation();
207
- e.nativeEvent.stopImmediatePropagation();
208
- switchChunk(item.chunk_id, checked);
209
- }}
210
- />
211
- </span>
212
- </div>
213
- <div className={styles.footer}>
214
- <span className={styles.text}>
215
- <MinusSquareOutlined />
216
- {item.doc_num}文档
217
- </span>
218
- <span className={styles.text}>
219
- <MinusSquareOutlined />
220
- {item.chunk_num}个
221
- </span>
222
- <span className={styles.text}>
223
- <MinusSquareOutlined />
224
- {item.token_num}千字符
225
- </span>
226
- <span style={{ float: 'right' }}>
227
- <Popconfirm
228
- title="Delete the task"
229
- description="Are you sure to delete this task?"
230
- onConfirm={(e: any) => {
231
- e.stopPropagation();
232
- e.nativeEvent.stopImmediatePropagation();
233
- console.log(confirm);
234
- confirm(item.chunk_id);
235
- }}
236
- okText="Yes"
237
- cancelText="No"
238
- >
239
- <DeleteOutlined
240
- onClick={(e) => {
241
- e.stopPropagation();
242
- e.nativeEvent.stopImmediatePropagation();
243
- }}
244
- />
245
- </Popconfirm>
246
- </span>
247
- </div>
248
- </div>
249
- </Card>
250
- </Col>
251
- );
252
- })}
253
- </Row>
254
  </Spin>
255
  </div>
256
  <div className={styles.pageFooter}>
@@ -259,10 +187,10 @@ const Chunk = () => {
259
  showLessItems
260
  showQuickJumper
261
  showSizeChanger
262
- onChange={onShowSizeChange}
263
- defaultPageSize={30}
264
- pageSizeOptions={[30, 60, 90]}
265
- defaultCurrent={pagination.page}
266
  total={total}
267
  />
268
  </div>
 
 
1
  import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
 
2
  import type { PaginationProps } from 'antd';
3
+ import { Button, Input, Pagination, Space, Spin } from 'antd';
 
 
 
 
 
 
 
 
 
 
 
4
  import { debounce } from 'lodash';
5
  import React, { useCallback, useEffect, useState } from 'react';
6
  import { useDispatch, useSearchParams, useSelector } from 'umi';
7
  import CreateModal from './components/createModal';
8
 
9
+ import ChunkCard from './components/chunk-card';
10
  import ChunkToolBar from './components/chunk-toolbar';
11
  import styles from './index.less';
12
+ import { ChunkModelState } from './model';
13
 
14
  interface PayloadType {
15
  doc_id: string;
16
  keywords?: string;
 
17
  }
18
 
19
  const Chunk = () => {
20
  const dispatch = useDispatch();
21
+ const chunkModel: ChunkModelState = useSelector(
22
+ (state: any) => state.chunkModel,
23
+ );
24
  const [keywords, SetKeywords] = useState('');
25
+ const [selectedChunkIds, setSelectedChunkIds] = useState<string[]>([]);
26
  const [searchParams] = useSearchParams();
27
+ const {
28
+ data = [],
29
+ total,
30
+ chunk_id,
31
+ isShowCreateModal,
32
+ pagination,
33
+ } = chunkModel;
34
  const effects = useSelector((state: any) => state.loading.effects);
35
  const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
36
  'create_hunk',
 
39
  ]);
40
  const documentId: string = searchParams.get('doc_id') || '';
41
 
42
+ const getChunkList = () => {
43
  const payload: PayloadType = {
44
  doc_id: documentId,
 
 
45
  };
46
+
 
 
47
  dispatch({
48
  type: 'chunkModel/chunk_list',
49
  payload: {
50
  ...payload,
 
51
  },
52
  });
53
  };
54
+
55
  const confirm = async (id: string) => {
56
  const retcode = await dispatch<any>({
57
  type: 'chunkModel/rm_chunk',
 
75
  getChunkList();
76
  };
77
 
78
+ const onPaginationChange: PaginationProps['onShowSizeChange'] = (
79
  page,
80
  size,
81
  ) => {
82
+ setSelectedChunkIds([]);
83
+ dispatch({
84
+ type: 'chunkModel/setPagination',
 
 
 
85
  payload: {
86
+ current: page,
87
+ pageSize: size,
 
88
  },
89
  });
90
+ getChunkList();
 
91
  };
92
 
93
+ const selectAllChunk = useCallback(
94
+ (checked: boolean) => {
95
+ setSelectedChunkIds(checked ? data.map((x) => x.chunk_id) : []);
96
+ // setSelectedChunkIds((previousIds) => {
97
+ // return checked ? [...previousIds, ...data.map((x) => x.chunk_id)] : [];
98
+ // });
99
+ },
100
+ [data],
101
+ );
102
+
103
+ const handleSingleCheckboxClick = useCallback(
104
+ (chunkId: string, checked: boolean) => {
105
+ setSelectedChunkIds((previousIds) => {
106
+ const idx = previousIds.findIndex((x) => x === chunkId);
107
+ const nextIds = [...previousIds];
108
+ if (checked && idx === -1) {
109
+ nextIds.push(chunkId);
110
+ } else if (!checked && idx !== -1) {
111
+ nextIds.splice(idx, 1);
112
+ }
113
+ return nextIds;
114
+ });
115
+ },
116
+ [],
117
+ );
118
+
119
  useEffect(() => {
120
  getChunkList();
121
+ return () => {
122
+ dispatch({
123
+ type: 'chunkModel/resetFilter', // TODO: need to reset state uniformly
124
+ });
125
+ };
126
+ }, [documentId]);
127
 
128
  const debounceChange = debounce(getChunkList, 300);
129
  const debounceCallback = useCallback(
 
134
  const handleInputChange = (
135
  e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
136
  ) => {
137
+ setSelectedChunkIds([]);
138
  const value = e.target.value;
139
  SetKeywords(value);
140
  debounceCallback(value);
141
  };
142
+
 
 
143
  return (
144
  <>
145
  <div className={styles.chunkPage}>
146
+ <ChunkToolBar
147
+ getChunkList={getChunkList}
148
+ selectAllChunk={selectAllChunk}
149
+ checked={selectedChunkIds.length === data.length}
150
+ ></ChunkToolBar>
151
  <div className={styles.filter}>
152
  <div>
153
  <Input
 
157
  allowClear
158
  onChange={handleInputChange}
159
  />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  </div>
161
  <Button
162
  onClick={() => {
 
169
  </div>
170
  <div className={styles.pageContent}>
171
  <Spin spinning={loading} className={styles.spin} size="large">
172
+ <Space direction="vertical" size={'middle'}>
173
+ {data.map((item) => (
174
+ <ChunkCard
175
+ item={item}
176
+ key={item.chunk_id}
177
+ checked={selectedChunkIds.some((x) => x === item.chunk_id)}
178
+ handleCheckboxClick={handleSingleCheckboxClick}
179
+ ></ChunkCard>
180
+ ))}
181
+ </Space>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  </Spin>
183
  </div>
184
  <div className={styles.pageFooter}>
 
187
  showLessItems
188
  showQuickJumper
189
  showSizeChanger
190
+ onChange={onPaginationChange}
191
+ defaultPageSize={10}
192
+ pageSizeOptions={[10, 30, 60, 90]}
193
+ defaultCurrent={pagination.current}
194
  total={total}
195
  />
196
  </div>
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts CHANGED
@@ -1,13 +1,19 @@
 
 
1
  import kbService from '@/services/kbService';
 
 
2
  import { DvaModel } from 'umi';
3
 
4
- export interface ChunkModelState {
5
  data: any[];
6
  total: number;
7
  isShowCreateModal: boolean;
8
  chunk_id: string;
9
  doc_id: string;
10
  chunkInfo: any;
 
 
11
  }
12
 
13
  const model: DvaModel<ChunkModelState> = {
@@ -19,6 +25,13 @@ const model: DvaModel<ChunkModelState> = {
19
  chunk_id: '',
20
  doc_id: '',
21
  chunkInfo: {},
 
 
 
 
 
 
 
22
  },
23
  reducers: {
24
  updateState(state, { payload }) {
@@ -27,33 +40,56 @@ const model: DvaModel<ChunkModelState> = {
27
  ...payload,
28
  };
29
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  },
31
- // subscriptions: {
32
- // setup({ dispatch, history }) {
33
- // history.listen(location => {
34
- // console.log(location)
35
- // });
36
- // }
37
- // },
38
  effects: {
39
- *chunk_list({ payload = {} }, { call, put }) {
40
- const { data, response } = yield call(kbService.chunk_list, payload);
41
-
42
- const { retcode, data: res, retmsg } = data;
 
 
 
 
 
 
 
43
  if (retcode === 0) {
44
- console.log(res);
45
  yield put({
46
  type: 'updateState',
47
  payload: {
48
  data: res.chunks,
49
  total: res.total,
 
50
  },
51
  });
52
  }
53
  },
54
  *switch_chunk({ payload = {} }, { call, put }) {
55
- const { data, response } = yield call(kbService.switch_chunk, payload);
56
- const { retcode, data: res, retmsg } = data;
 
 
 
57
  return retcode;
58
  },
59
  *rm_chunk({ payload = {} }, { call, put }) {
 
1
+ import { BaseState } from '@/interfaces/common';
2
+ import { IKnowledgeFile } from '@/interfaces/database/knowledge';
3
  import kbService from '@/services/kbService';
4
+ import { message } from 'antd';
5
+ // import { delay } from '@/utils/storeUtil';
6
  import { DvaModel } from 'umi';
7
 
8
+ export interface ChunkModelState extends BaseState {
9
  data: any[];
10
  total: number;
11
  isShowCreateModal: boolean;
12
  chunk_id: string;
13
  doc_id: string;
14
  chunkInfo: any;
15
+ documentInfo: Partial<IKnowledgeFile>;
16
+ available?: number;
17
  }
18
 
19
  const model: DvaModel<ChunkModelState> = {
 
25
  chunk_id: '',
26
  doc_id: '',
27
  chunkInfo: {},
28
+ documentInfo: {},
29
+ pagination: {
30
+ current: 1,
31
+ pageSize: 10,
32
+ },
33
+ searchString: '',
34
+ available: undefined, // set to undefined to select all
35
  },
36
  reducers: {
37
  updateState(state, { payload }) {
 
40
  ...payload,
41
  };
42
  },
43
+ setAvailable(state, { payload }) {
44
+ return { ...state, available: payload };
45
+ },
46
+ setSearchString(state, { payload }) {
47
+ return { ...state, searchString: payload };
48
+ },
49
+ setPagination(state, { payload }) {
50
+ return { ...state, pagination: { ...state.pagination, ...payload } };
51
+ },
52
+ resetFilter(state, { payload }) {
53
+ return {
54
+ ...state,
55
+ pagination: {
56
+ current: 1,
57
+ pageSize: 10,
58
+ },
59
+ searchString: '',
60
+ available: undefined,
61
+ };
62
+ },
63
  },
 
 
 
 
 
 
 
64
  effects: {
65
+ *chunk_list({ payload = {} }, { call, put, select }) {
66
+ const { available, searchString, pagination }: ChunkModelState =
67
+ yield select((state: any) => state.chunkModel);
68
+ const { data } = yield call(kbService.chunk_list, {
69
+ ...payload,
70
+ available_int: available,
71
+ keywords: searchString,
72
+ page: pagination.current,
73
+ size: pagination.pageSize,
74
+ });
75
+ const { retcode, data: res } = data;
76
  if (retcode === 0) {
 
77
  yield put({
78
  type: 'updateState',
79
  payload: {
80
  data: res.chunks,
81
  total: res.total,
82
+ documentInfo: res.doc,
83
  },
84
  });
85
  }
86
  },
87
  *switch_chunk({ payload = {} }, { call, put }) {
88
+ const { data } = yield call(kbService.switch_chunk, payload);
89
+ const { retcode } = data;
90
+ if (retcode === 0) {
91
+ message.success('Modified successfully !');
92
+ }
93
  return retcode;
94
  },
95
  *rm_chunk({ payload = {} }, { call, put }) {
web/src/pages/add-knowledge/components/knowledge-file/model.ts CHANGED
@@ -16,7 +16,6 @@ export interface KFModelState extends BaseState {
16
  data: IKnowledgeFile[];
17
  total: number;
18
  currentRecord: Nullable<IKnowledgeFile>;
19
- searchString: string;
20
  }
21
 
22
  const model: DvaModel<KFModelState> = {
 
16
  data: IKnowledgeFile[];
17
  total: number;
18
  currentRecord: Nullable<IKnowledgeFile>;
 
19
  }
20
 
21
  const model: DvaModel<KFModelState> = {
web/src/pages/knowledge/knowledge-card/index.tsx CHANGED
@@ -9,7 +9,6 @@ import {
9
  UserOutlined,
10
  } from '@ant-design/icons';
11
  import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd';
12
- import { MouseEvent } from 'react';
13
  import { useDispatch, useNavigate } from 'umi';
14
 
15
  import showDeleteConfirm from '@/components/deleting-confirm';
@@ -23,6 +22,15 @@ const KnowledgeCard = ({ item }: IProps) => {
23
  const navigate = useNavigate();
24
  const dispatch = useDispatch();
25
 
 
 
 
 
 
 
 
 
 
26
  const handleDelete = () => {
27
  showDeleteConfirm({ onOk: removeKnowledge });
28
  };
@@ -47,16 +55,7 @@ const KnowledgeCard = ({ item }: IProps) => {
47
  }
48
  };
49
 
50
- const removeKnowledge = () => {
51
- return dispatch({
52
- type: 'knowledgeModel/rmKb',
53
- payload: {
54
- kb_id: item.id,
55
- },
56
- });
57
- };
58
-
59
- const handleCardClick = (e: MouseEvent<HTMLElement>) => {
60
  navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${item.id}`);
61
  };
62
 
 
9
  UserOutlined,
10
  } from '@ant-design/icons';
11
  import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd';
 
12
  import { useDispatch, useNavigate } from 'umi';
13
 
14
  import showDeleteConfirm from '@/components/deleting-confirm';
 
22
  const navigate = useNavigate();
23
  const dispatch = useDispatch();
24
 
25
+ const removeKnowledge = () => {
26
+ return dispatch({
27
+ type: 'knowledgeModel/rmKb',
28
+ payload: {
29
+ kb_id: item.id,
30
+ },
31
+ });
32
+ };
33
+
34
  const handleDelete = () => {
35
  showDeleteConfirm({ onOk: removeKnowledge });
36
  };
 
55
  }
56
  };
57
 
58
+ const handleCardClick = () => {
 
 
 
 
 
 
 
 
 
59
  navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${item.id}`);
60
  };
61
 
web/src/utils/storeUtil.ts CHANGED
@@ -7,3 +7,8 @@ export const getOneNamespaceEffectsLoading = (
7
  (effectName) => effects[`${namespace}/${effectName}`],
8
  );
9
  };
 
 
 
 
 
 
7
  (effectName) => effects[`${namespace}/${effectName}`],
8
  );
9
  };
10
+
11
+ export const delay = (ms: number) =>
12
+ new Promise((resolve) => {
13
+ setTimeout(resolve, ms);
14
+ });