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

feat: create chunk and edit chunk and delete chunk (#58)

Browse files

* feat: create chunk and edit chunk

* feat: delete chunk

* feat: search chunks

* feat: delete chunks in batches

* feat: set whether chunks are available in batches

web/package-lock.json CHANGED
@@ -17,6 +17,7 @@
17
  "jsencrypt": "^3.3.2",
18
  "lodash": "^4.17.21",
19
  "moment": "^2.30.1",
 
20
  "react-i18next": "^14.0.0",
21
  "react-infinite-scroll-component": "^6.1.0",
22
  "umi": "^4.0.90",
@@ -6508,6 +6509,16 @@
6508
  "type": "^1.0.1"
6509
  }
6510
  },
 
 
 
 
 
 
 
 
 
 
6511
  "node_modules/data-uri-to-buffer": {
6512
  "version": "4.0.1",
6513
  "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@@ -6994,6 +7005,11 @@
6994
  "dva-core": "^1.1.0 || ^1.5.0-0 || ^1.6.0-0"
6995
  }
6996
  },
 
 
 
 
 
6997
  "node_modules/easy-icons": {
6998
  "version": "1.1.5",
6999
  "resolved": "https://registry.npmmirror.com/easy-icons/-/easy-icons-1.1.5.tgz",
@@ -8324,6 +8340,24 @@
8324
  "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.",
8325
  "dev": true
8326
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8327
  "node_modules/follow-redirects": {
8328
  "version": "1.15.4",
8329
  "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.4.tgz",
@@ -11847,6 +11881,11 @@
11847
  "node": ">=0.12"
11848
  }
11849
  },
 
 
 
 
 
11850
  "node_modules/picocolors": {
11851
  "version": "1.0.0",
11852
  "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
@@ -12777,6 +12816,14 @@
12777
  "node": ">=8"
12778
  }
12779
  },
 
 
 
 
 
 
 
 
12780
  "node_modules/ramda": {
12781
  "version": "0.27.2",
12782
  "resolved": "https://registry.npmmirror.com/ramda/-/ramda-0.27.2.tgz",
@@ -13325,6 +13372,23 @@
13325
  "react-dom": "*"
13326
  }
13327
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13328
  "node_modules/rc-upload": {
13329
  "version": "4.5.2",
13330
  "resolved": "https://registry.npmmirror.com/rc-upload/-/rc-upload-4.5.2.tgz",
@@ -15285,6 +15349,11 @@
15285
  "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
15286
  "peer": true
15287
  },
 
 
 
 
 
15288
  "node_modules/stylelint": {
15289
  "version": "14.16.1",
15290
  "resolved": "https://registry.npmmirror.com/stylelint/-/stylelint-14.16.1.tgz",
@@ -15467,6 +15536,11 @@
15467
  "resolved": "https://registry.npmmirror.com/svg-parser/-/svg-parser-2.0.4.tgz",
15468
  "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
15469
  },
 
 
 
 
 
15470
  "node_modules/svg-tags": {
15471
  "version": "1.0.0",
15472
  "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -15501,6 +15575,11 @@
15501
  "node": ">= 10"
15502
  }
15503
  },
 
 
 
 
 
15504
  "node_modules/swr": {
15505
  "version": "2.2.4",
15506
  "resolved": "https://registry.npmmirror.com/swr/-/swr-2.2.4.tgz",
@@ -15815,6 +15894,24 @@
15815
  "resolved": "https://registry.npmmirror.com/toggle-selection/-/toggle-selection-1.0.6.tgz",
15816
  "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
15817
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15818
  "node_modules/trim-newlines": {
15819
  "version": "3.0.1",
15820
  "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz",
@@ -16235,6 +16332,24 @@
16235
  "resolved": "https://registry.npmmirror.com/tty-browserify/-/tty-browserify-0.0.0.tgz",
16236
  "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw=="
16237
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16238
  "node_modules/type": {
16239
  "version": "1.2.0",
16240
  "resolved": "https://registry.npmmirror.com/type/-/type-1.2.0.tgz",
 
17
  "jsencrypt": "^3.3.2",
18
  "lodash": "^4.17.21",
19
  "moment": "^2.30.1",
20
+ "rc-tween-one": "^3.0.6",
21
  "react-i18next": "^14.0.0",
22
  "react-infinite-scroll-component": "^6.1.0",
23
  "umi": "^4.0.90",
 
6509
  "type": "^1.0.1"
6510
  }
6511
  },
6512
+ "node_modules/d3-array": {
6513
+ "version": "1.2.4",
6514
+ "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-1.2.4.tgz",
6515
+ "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
6516
+ },
6517
+ "node_modules/d3-polygon": {
6518
+ "version": "1.0.6",
6519
+ "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-1.0.6.tgz",
6520
+ "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ=="
6521
+ },
6522
  "node_modules/data-uri-to-buffer": {
6523
  "version": "4.0.1",
6524
  "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
 
7005
  "dva-core": "^1.1.0 || ^1.5.0-0 || ^1.6.0-0"
7006
  }
7007
  },
7008
+ "node_modules/earcut": {
7009
+ "version": "2.2.4",
7010
+ "resolved": "https://registry.npmmirror.com/earcut/-/earcut-2.2.4.tgz",
7011
+ "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
7012
+ },
7013
  "node_modules/easy-icons": {
7014
  "version": "1.1.5",
7015
  "resolved": "https://registry.npmmirror.com/easy-icons/-/easy-icons-1.1.5.tgz",
 
8340
  "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.",
8341
  "dev": true
8342
  },
8343
+ "node_modules/flubber": {
8344
+ "version": "0.4.2",
8345
+ "resolved": "https://registry.npmmirror.com/flubber/-/flubber-0.4.2.tgz",
8346
+ "integrity": "sha512-79RkJe3rA4nvRCVc2uXjj7U/BAUq84TS3KHn6c0Hr9K64vhj83ZNLUziNx4pJoBumSPhOl5VjH+Z0uhi+eE8Uw==",
8347
+ "dependencies": {
8348
+ "d3-array": "^1.2.0",
8349
+ "d3-polygon": "^1.0.3",
8350
+ "earcut": "^2.1.1",
8351
+ "svg-path-properties": "^0.2.1",
8352
+ "svgpath": "^2.2.1",
8353
+ "topojson-client": "^3.0.0"
8354
+ }
8355
+ },
8356
+ "node_modules/flubber/node_modules/svg-path-properties": {
8357
+ "version": "0.2.2",
8358
+ "resolved": "https://registry.npmmirror.com/svg-path-properties/-/svg-path-properties-0.2.2.tgz",
8359
+ "integrity": "sha512-GmrB+b6woz6CCdQe6w1GHs/1lt25l7SR5hmhF8jRdarpv/OgjLyuQygLu1makJapixeb1aQhP/Oa1iKi93o/aQ=="
8360
+ },
8361
  "node_modules/follow-redirects": {
8362
  "version": "1.15.4",
8363
  "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.4.tgz",
 
11881
  "node": ">=0.12"
11882
  }
11883
  },
11884
+ "node_modules/performance-now": {
11885
+ "version": "2.1.0",
11886
+ "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
11887
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
11888
+ },
11889
  "node_modules/picocolors": {
11890
  "version": "1.0.0",
11891
  "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
 
12816
  "node": ">=8"
12817
  }
12818
  },
12819
+ "node_modules/raf": {
12820
+ "version": "3.4.1",
12821
+ "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
12822
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
12823
+ "dependencies": {
12824
+ "performance-now": "^2.1.0"
12825
+ }
12826
+ },
12827
  "node_modules/ramda": {
12828
  "version": "0.27.2",
12829
  "resolved": "https://registry.npmmirror.com/ramda/-/ramda-0.27.2.tgz",
 
13372
  "react-dom": "*"
13373
  }
13374
  },
13375
+ "node_modules/rc-tween-one": {
13376
+ "version": "3.0.6",
13377
+ "resolved": "https://registry.npmmirror.com/rc-tween-one/-/rc-tween-one-3.0.6.tgz",
13378
+ "integrity": "sha512-5zTSXyyv7bahDBQ/kJw/kNxxoBqTouttoelw8FOVOyWqmTMndizJEpvaj1N+yES5Xjss6Y2iVw+9vSJQZE8Z6g==",
13379
+ "dependencies": {
13380
+ "@babel/runtime": "^7.11.1",
13381
+ "style-utils": "^0.3.4",
13382
+ "tween-one": "^1.0.50"
13383
+ },
13384
+ "engines": {
13385
+ "node": ">=8.x"
13386
+ },
13387
+ "peerDependencies": {
13388
+ "react": ">=16.9.0",
13389
+ "react-dom": ">=16.9.0"
13390
+ }
13391
+ },
13392
  "node_modules/rc-upload": {
13393
  "version": "4.5.2",
13394
  "resolved": "https://registry.npmmirror.com/rc-upload/-/rc-upload-4.5.2.tgz",
 
15349
  "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
15350
  "peer": true
15351
  },
15352
+ "node_modules/style-utils": {
15353
+ "version": "0.3.8",
15354
+ "resolved": "https://registry.npmmirror.com/style-utils/-/style-utils-0.3.8.tgz",
15355
+ "integrity": "sha512-RmGftIhY4tqtD1ERwKsVEDlt/M6UyxN/rcr95UmlooWmhtL0RwVUYJkpo1kSx3ppd9/JZzbknhy742zbMAawjQ=="
15356
+ },
15357
  "node_modules/stylelint": {
15358
  "version": "14.16.1",
15359
  "resolved": "https://registry.npmmirror.com/stylelint/-/stylelint-14.16.1.tgz",
 
15536
  "resolved": "https://registry.npmmirror.com/svg-parser/-/svg-parser-2.0.4.tgz",
15537
  "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
15538
  },
15539
+ "node_modules/svg-path-properties": {
15540
+ "version": "1.3.0",
15541
+ "resolved": "https://registry.npmmirror.com/svg-path-properties/-/svg-path-properties-1.3.0.tgz",
15542
+ "integrity": "sha512-R1+z37FrqyS3UXDhajNfvMxKI0smuVdedqOo4YbAQUfGqA86B9mGvr2IEXrwjjvGzCtdIKy/ad9N8m6YclaKAw=="
15543
+ },
15544
  "node_modules/svg-tags": {
15545
  "version": "1.0.0",
15546
  "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",
 
15575
  "node": ">= 10"
15576
  }
15577
  },
15578
+ "node_modules/svgpath": {
15579
+ "version": "2.6.0",
15580
+ "resolved": "https://registry.npmmirror.com/svgpath/-/svgpath-2.6.0.tgz",
15581
+ "integrity": "sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg=="
15582
+ },
15583
  "node_modules/swr": {
15584
  "version": "2.2.4",
15585
  "resolved": "https://registry.npmmirror.com/swr/-/swr-2.2.4.tgz",
 
15894
  "resolved": "https://registry.npmmirror.com/toggle-selection/-/toggle-selection-1.0.6.tgz",
15895
  "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
15896
  },
15897
+ "node_modules/topojson-client": {
15898
+ "version": "3.1.0",
15899
+ "resolved": "https://registry.npmmirror.com/topojson-client/-/topojson-client-3.1.0.tgz",
15900
+ "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
15901
+ "dependencies": {
15902
+ "commander": "2"
15903
+ },
15904
+ "bin": {
15905
+ "topo2geo": "bin/topo2geo",
15906
+ "topomerge": "bin/topomerge",
15907
+ "topoquantize": "bin/topoquantize"
15908
+ }
15909
+ },
15910
+ "node_modules/topojson-client/node_modules/commander": {
15911
+ "version": "2.20.3",
15912
+ "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
15913
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
15914
+ },
15915
  "node_modules/trim-newlines": {
15916
  "version": "3.0.1",
15917
  "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz",
 
16332
  "resolved": "https://registry.npmmirror.com/tty-browserify/-/tty-browserify-0.0.0.tgz",
16333
  "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw=="
16334
  },
16335
+ "node_modules/tween-functions": {
16336
+ "version": "1.2.0",
16337
+ "resolved": "https://registry.npmmirror.com/tween-functions/-/tween-functions-1.2.0.tgz",
16338
+ "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA=="
16339
+ },
16340
+ "node_modules/tween-one": {
16341
+ "version": "1.2.7",
16342
+ "resolved": "https://registry.npmmirror.com/tween-one/-/tween-one-1.2.7.tgz",
16343
+ "integrity": "sha512-F+Z9LO9GsYqf0j5bgNhAF98RDrAZ7QjQrujJ2lVYSHl4+dBPW/atHluL2bwclZf8Vo0Yo96f6pw2uq1OGzpC/Q==",
16344
+ "dependencies": {
16345
+ "@babel/runtime": "^7.11.1",
16346
+ "flubber": "^0.4.2",
16347
+ "raf": "^3.4.1",
16348
+ "style-utils": "^0.3.6",
16349
+ "svg-path-properties": "^1.0.4",
16350
+ "tween-functions": "^1.2.0"
16351
+ }
16352
+ },
16353
  "node_modules/type": {
16354
  "version": "1.2.0",
16355
  "resolved": "https://registry.npmmirror.com/type/-/type-1.2.0.tgz",
web/package.json CHANGED
@@ -21,6 +21,7 @@
21
  "jsencrypt": "^3.3.2",
22
  "lodash": "^4.17.21",
23
  "moment": "^2.30.1",
 
24
  "react-i18next": "^14.0.0",
25
  "react-infinite-scroll-component": "^6.1.0",
26
  "umi": "^4.0.90",
 
21
  "jsencrypt": "^3.3.2",
22
  "lodash": "^4.17.21",
23
  "moment": "^2.30.1",
24
+ "rc-tween-one": "^3.0.6",
25
  "react-i18next": "^14.0.0",
26
  "react-infinite-scroll-component": "^6.1.0",
27
  "umi": "^4.0.90",
web/src/hooks/knowledgeHook.ts CHANGED
@@ -1,5 +1,6 @@
1
  import showDeleteConfirm from '@/components/deleting-confirm';
2
  import { IKnowledge } from '@/interfaces/database/knowledge';
 
3
  import { useDispatch, useSearchParams, useSelector } from 'umi';
4
 
5
  export const useKnowledgeBaseId = (): string => {
@@ -46,3 +47,33 @@ export const useGetDocumentDefaultParser = (knowledgeBaseId: string) => {
46
  parserConfig: item?.parser_config ?? '',
47
  };
48
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import showDeleteConfirm from '@/components/deleting-confirm';
2
  import { IKnowledge } from '@/interfaces/database/knowledge';
3
+ import { useCallback } from 'react';
4
  import { useDispatch, useSearchParams, useSelector } from 'umi';
5
 
6
  export const useKnowledgeBaseId = (): string => {
 
47
  parserConfig: item?.parser_config ?? '',
48
  };
49
  };
50
+
51
+ export const useDeleteChunkByIds = (): {
52
+ removeChunk: (chunkIds: string[], documentId: string) => Promise<number>;
53
+ } => {
54
+ const dispatch = useDispatch();
55
+
56
+ const removeChunk = useCallback(
57
+ (chunkIds: string[], documentId: string) => () => {
58
+ return dispatch({
59
+ type: 'chunkModel/rm_chunk',
60
+ payload: {
61
+ chunk_ids: chunkIds,
62
+ doc_id: documentId,
63
+ },
64
+ });
65
+ },
66
+ [dispatch],
67
+ );
68
+
69
+ const onRemoveChunk = useCallback(
70
+ (chunkIds: string[], documentId: string): Promise<number> => {
71
+ return showDeleteConfirm({ onOk: removeChunk(chunkIds, documentId) });
72
+ },
73
+ [removeChunk],
74
+ );
75
+
76
+ return {
77
+ removeChunk: onRemoveChunk,
78
+ };
79
+ };
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less CHANGED
@@ -6,3 +6,11 @@
6
  .imagePreview {
7
  width: 600px;
8
  }
 
 
 
 
 
 
 
 
 
6
  .imagePreview {
7
  width: 600px;
8
  }
9
+
10
+ .content {
11
+ flex: 1;
12
+ em {
13
+ color: red;
14
+ font-style: normal;
15
+ }
16
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx CHANGED
@@ -1,7 +1,6 @@
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';
@@ -9,6 +8,8 @@ import styles from './index.less';
9
  interface IProps {
10
  item: IChunk;
11
  checked: boolean;
 
 
12
  handleCheckboxClick: (chunkId: string, checked: boolean) => void;
13
  }
14
 
@@ -28,32 +29,29 @@ const Image = ({ id, className, ...props }: IImage) => {
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>
@@ -75,7 +73,13 @@ const ChunkCard = ({ item, checked, handleCheckboxClick }: IProps) => {
75
  </Popover>
76
  )}
77
 
78
- <section>{item.content_with_weight}</section>
 
 
 
 
 
 
79
  <div>
80
  <Switch checked={enabled} onChange={onChange} />
81
  </div>
 
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
 
5
  import { useState } from 'react';
6
  import styles from './index.less';
 
8
  interface IProps {
9
  item: IChunk;
10
  checked: boolean;
11
+ switchChunk: (available?: number, chunkIds?: string[]) => void;
12
+ editChunk: (chunkId: string) => void;
13
  handleCheckboxClick: (chunkId: string, checked: boolean) => void;
14
  }
15
 
 
29
  );
30
  };
31
 
32
+ const ChunkCard = ({
33
+ item,
34
+ checked,
35
+ handleCheckboxClick,
36
+ editChunk,
37
+ switchChunk,
38
+ }: IProps) => {
39
  const available = Number(item.available_int);
40
  const [enabled, setEnabled] = useState(available === 1);
41
 
 
 
 
 
 
 
 
 
 
 
 
42
  const onChange = (checked: boolean) => {
43
  setEnabled(checked);
44
+ switchChunk(available === 0 ? 1 : 0, [item.chunk_id]);
45
  };
46
 
47
  const handleCheck: CheckboxProps['onChange'] = (e) => {
48
  handleCheckboxClick(item.chunk_id, e.target.checked);
49
  };
50
 
51
+ const handleContentClick = () => {
52
+ editChunk(item.chunk_id);
53
+ };
54
+
55
  return (
56
  <div>
57
  <Card>
 
73
  </Popover>
74
  )}
75
 
76
+ <section
77
+ onDoubleClick={handleContentClick}
78
+ className={styles.content}
79
+ dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
80
+ >
81
+ {/* {item.content_with_weight} */}
82
+ </section>
83
  <div>
84
  <Switch checked={enabled} onChange={onChange} />
85
  </div>
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-creating-modal/index.less ADDED
File without changes
web/src/pages/add-knowledge/components/knowledge-chunk/components/{createModal.tsx → chunk-creating-modal/index.tsx} RENAMED
@@ -1,60 +1,59 @@
1
- import { Form, Input, Modal } from 'antd';
 
 
 
2
  import React, { useCallback, useEffect, useState } from 'react';
3
- import { useTranslation } from 'react-i18next';
4
- import { useDispatch } from 'umi';
5
- import EditTag from './editTag';
6
 
7
  type FieldType = {
8
- content_ltks?: string;
9
  };
10
  interface kFProps {
11
- getChunkList: () => void;
12
- isShowCreateModal: boolean;
13
  doc_id: string;
14
- chunk_id: string;
15
  }
16
 
17
- const Index: React.FC<kFProps> = ({
18
- getChunkList,
19
- doc_id,
20
- isShowCreateModal,
21
- chunk_id,
22
- }) => {
23
  const dispatch = useDispatch();
24
  const [form] = Form.useForm();
 
 
 
 
 
 
 
25
 
26
- // const { , chunkInfo } = chunkModel
27
- const [important_kwd, setImportantKwd] = useState([
28
- 'Unremovable',
29
- 'Tag 2',
30
- 'Tag 3',
31
- ]);
32
- const { t } = useTranslation();
33
  const handleCancel = () => {
34
  dispatch({
35
- type: 'chunkModel/updateState',
36
- payload: {
37
- isShowCreateModal: false,
38
- },
39
  });
40
  };
41
 
42
  const getChunk = useCallback(async () => {
43
- if (chunk_id && isShowCreateModal) {
 
44
  const data = await dispatch<any>({
45
  type: 'chunkModel/get_chunk',
46
  payload: {
47
- chunk_id,
48
  },
49
  });
50
 
51
  if (data?.retcode === 0) {
52
- const { content_ltks, important_kwd = [] } = data.data;
53
- form.setFieldsValue({ content_ltks });
54
- setImportantKwd(important_kwd);
55
  }
56
  }
57
- }, [chunk_id, isShowCreateModal]);
 
 
 
 
 
58
 
59
  useEffect(() => {
60
  getChunk();
@@ -64,53 +63,69 @@ const Index: React.FC<kFProps> = ({
64
  try {
65
  const values = await form.validateFields();
66
  dispatch({
67
- type: 'chunkModel/create_hunk',
68
  payload: {
69
- content_ltks: values.content_ltks,
70
  doc_id,
71
- chunk_id,
72
- important_kwd,
73
  },
74
- // callback: () => {
75
- // dispatch({
76
- // type: 'chunkModel/updateState',
77
- // payload: {
78
- // isShowCreateModal: false,
79
- // },
80
- // });
81
- // getChunkList && getChunkList();
82
- // },
83
  });
84
  } catch (errorInfo) {
85
  console.log('Failed:', errorInfo);
86
  }
87
  };
88
 
 
 
 
 
 
 
 
 
 
89
  return (
90
  <Modal
91
- title="Basic Modal"
92
  open={isShowCreateModal}
93
  onOk={handleOk}
94
  onCancel={handleCancel}
 
95
  >
96
  <Form
97
  form={form}
98
- name="validateOnly"
99
- labelCol={{ span: 5 }}
100
- wrapperCol={{ span: 19 }}
101
- style={{ maxWidth: 600 }}
102
  autoComplete="off"
 
103
  >
104
  <Form.Item<FieldType>
105
- label="chunk 内容"
106
- name="content_ltks"
107
  rules={[{ required: true, message: 'Please input value!' }]}
108
  >
109
- <Input.TextArea />
110
  </Form.Item>
111
- <EditTag tags={important_kwd} setTags={setImportantKwd} />
112
  </Form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  </Modal>
114
  );
115
  };
116
- export default Index;
 
1
+ import { useDeleteChunkByIds } from '@/hooks/knowledgeHook';
2
+ import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
3
+ import { DeleteOutlined } from '@ant-design/icons';
4
+ import { Checkbox, Form, Input, Modal, Space } from 'antd';
5
  import React, { useCallback, useEffect, useState } from 'react';
6
+ import { useDispatch, useSelector } from 'umi';
7
+ import EditTag from '../edit-tag';
 
8
 
9
  type FieldType = {
10
+ content?: string;
11
  };
12
  interface kFProps {
 
 
13
  doc_id: string;
14
+ chunkId: string | undefined;
15
  }
16
 
17
+ const ChunkCreatingModal: React.FC<kFProps> = ({ doc_id, chunkId }) => {
 
 
 
 
 
18
  const dispatch = useDispatch();
19
  const [form] = Form.useForm();
20
+ const isShowCreateModal: boolean = useSelector(
21
+ (state: any) => state.chunkModel.isShowCreateModal,
22
+ );
23
+ const [checked, setChecked] = useState(false);
24
+ const [keywords, setKeywords] = useState<string[]>([]);
25
+ const loading = useOneNamespaceEffectsLoading('chunkModel', ['create_chunk']);
26
+ const { removeChunk } = useDeleteChunkByIds();
27
 
 
 
 
 
 
 
 
28
  const handleCancel = () => {
29
  dispatch({
30
+ type: 'chunkModel/setIsShowCreateModal',
31
+ payload: false,
 
 
32
  });
33
  };
34
 
35
  const getChunk = useCallback(async () => {
36
+ console.info(chunkId);
37
+ if (chunkId && isShowCreateModal) {
38
  const data = await dispatch<any>({
39
  type: 'chunkModel/get_chunk',
40
  payload: {
41
+ chunk_id: chunkId,
42
  },
43
  });
44
 
45
  if (data?.retcode === 0) {
46
+ const { content_with_weight, important_kwd = [] } = data.data;
47
+ form.setFieldsValue({ content: content_with_weight });
48
+ setKeywords(important_kwd);
49
  }
50
  }
51
+
52
+ if (!chunkId) {
53
+ setKeywords([]);
54
+ form.setFieldsValue({ content: undefined });
55
+ }
56
+ }, [chunkId, isShowCreateModal, dispatch, form]);
57
 
58
  useEffect(() => {
59
  getChunk();
 
63
  try {
64
  const values = await form.validateFields();
65
  dispatch({
66
+ type: 'chunkModel/create_chunk',
67
  payload: {
68
+ content_with_weight: values.content,
69
  doc_id,
70
+ chunk_id: chunkId,
71
+ important_kwd: keywords, // keywords
72
  },
 
 
 
 
 
 
 
 
 
73
  });
74
  } catch (errorInfo) {
75
  console.log('Failed:', errorInfo);
76
  }
77
  };
78
 
79
+ const handleRemove = () => {
80
+ if (chunkId) {
81
+ return removeChunk([chunkId], doc_id);
82
+ }
83
+ };
84
+ const handleCheck = () => {
85
+ setChecked(!checked);
86
+ };
87
+
88
  return (
89
  <Modal
90
+ title={`${chunkId ? 'Edit' : 'Create'} Chunk`}
91
  open={isShowCreateModal}
92
  onOk={handleOk}
93
  onCancel={handleCancel}
94
+ okButtonProps={{ loading }}
95
  >
96
  <Form
97
  form={form}
98
+ // name="validateOnly"
 
 
 
99
  autoComplete="off"
100
+ layout={'vertical'}
101
  >
102
  <Form.Item<FieldType>
103
+ label="Chunk"
104
+ name="content"
105
  rules={[{ required: true, message: 'Please input value!' }]}
106
  >
107
+ <Input.TextArea autoSize={{ minRows: 4, maxRows: 10 }} />
108
  </Form.Item>
 
109
  </Form>
110
+ <section>
111
+ <p>Keyword*</p>
112
+ <EditTag tags={keywords} setTags={setKeywords} />
113
+ </section>
114
+ {chunkId && (
115
+ <section>
116
+ <p>Function*</p>
117
+ <Space size={'large'}>
118
+ <Checkbox onChange={handleCheck} checked={checked}>
119
+ Enabled
120
+ </Checkbox>
121
+
122
+ <span onClick={handleRemove}>
123
+ <DeleteOutlined /> Delete
124
+ </span>
125
+ </Space>
126
+ </section>
127
+ )}
128
  </Modal>
129
  );
130
  };
131
+ export default ChunkCreatingModal;
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx CHANGED
@@ -15,6 +15,7 @@ import {
15
  Button,
16
  Checkbox,
17
  Flex,
 
18
  Menu,
19
  MenuProps,
20
  Popover,
@@ -22,7 +23,7 @@ import {
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
 
@@ -30,24 +31,62 @@ 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
  {
@@ -64,7 +103,7 @@ const ChunkToolBar = ({ getChunkList, selectAllChunk, checked }: IProps) => {
64
  {
65
  key: '2',
66
  label: (
67
- <Space>
68
  <CheckCircleOutlined />
69
  <b>Enabled Selected</b>
70
  </Space>
@@ -73,7 +112,7 @@ const ChunkToolBar = ({ getChunkList, selectAllChunk, checked }: IProps) => {
73
  {
74
  key: '3',
75
  label: (
76
- <Space>
77
  <CloseCircleOutlined />
78
  <b>Disabled Selected</b>
79
  </Space>
@@ -83,20 +122,21 @@ const ChunkToolBar = ({ getChunkList, selectAllChunk, checked }: IProps) => {
83
  {
84
  key: '4',
85
  label: (
86
- <Space>
87
  <DeleteOutlined />
88
  <b>Delete Selected</b>
89
  </Space>
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
  };
@@ -129,12 +169,28 @@ const ChunkToolBar = ({ getChunkList, selectAllChunk, checked }: IProps) => {
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>
139
  </Flex>
140
  );
 
15
  Button,
16
  Checkbox,
17
  Flex,
18
+ Input,
19
  Menu,
20
  MenuProps,
21
  Popover,
 
23
  RadioChangeEvent,
24
  Space,
25
  } from 'antd';
26
+ import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
27
  import { Link, useDispatch, useSelector } from 'umi';
28
  import { ChunkModelState } from '../../model';
29
 
 
31
  checked: boolean;
32
  getChunkList: () => void;
33
  selectAllChunk: (checked: boolean) => void;
34
+ createChunk: () => void;
35
+ removeChunk: () => void;
36
+ switchChunk: (available: number) => void;
37
  }
38
 
39
+ const ChunkToolBar = ({
40
+ getChunkList,
41
+ selectAllChunk,
42
+ checked,
43
+ createChunk,
44
+ removeChunk,
45
+ switchChunk,
46
+ }: IProps) => {
47
+ const { documentInfo, available, searchString }: ChunkModelState =
48
+ useSelector((state: any) => state.chunkModel);
49
  const dispatch = useDispatch();
 
50
  const knowledgeBaseId = useKnowledgeBaseId();
51
+ const [isShowSearchBox, setIsShowSearchBox] = useState(false);
52
 
53
  const handleSelectAllCheck = useCallback(
54
  (e: any) => {
 
55
  selectAllChunk(e.target.checked);
56
  },
57
  [selectAllChunk],
58
  );
59
 
60
+ const handleSearchIconClick = () => {
61
+ setIsShowSearchBox(true);
62
+ };
63
+
64
+ const handleSearchChange: ChangeEventHandler<HTMLInputElement> = (e) => {
65
+ const val = e.target.value;
66
+ dispatch({ type: 'chunkModel/setSearchString', payload: val });
67
+ dispatch({
68
+ type: 'chunkModel/throttledGetChunkList',
69
+ payload: documentInfo.id,
70
+ });
71
+ };
72
+
73
+ const handleSearchBlur = () => {
74
+ if (!searchString.trim()) {
75
+ setIsShowSearchBox(false);
76
+ }
77
+ };
78
+
79
+ const handleDelete = useCallback(() => {
80
+ removeChunk();
81
+ }, [removeChunk]);
82
+
83
+ const handleEnabledClick = () => {
84
+ switchChunk(1);
85
+ };
86
+ const handleDisabledClick = () => {
87
+ switchChunk(0);
88
+ };
89
+
90
  const items: MenuProps['items'] = useMemo(() => {
91
  return [
92
  {
 
103
  {
104
  key: '2',
105
  label: (
106
+ <Space onClick={handleEnabledClick}>
107
  <CheckCircleOutlined />
108
  <b>Enabled Selected</b>
109
  </Space>
 
112
  {
113
  key: '3',
114
  label: (
115
+ <Space onClick={handleDisabledClick}>
116
  <CloseCircleOutlined />
117
  <b>Disabled Selected</b>
118
  </Space>
 
122
  {
123
  key: '4',
124
  label: (
125
+ <Space onClick={handleDelete}>
126
  <DeleteOutlined />
127
  <b>Delete Selected</b>
128
  </Space>
129
  ),
130
  },
131
  ];
132
+ }, [checked, handleSelectAllCheck, handleDelete]);
133
 
134
  const content = (
135
  <Menu style={{ width: 200 }} items={items} selectable={false} />
136
  );
137
 
138
  const handleFilterChange = (e: RadioChangeEvent) => {
139
+ selectAllChunk(false);
140
  dispatch({ type: 'chunkModel/setAvailable', payload: e.target.value });
141
  getChunkList();
142
  };
 
169
  <DownOutlined />
170
  </Button>
171
  </Popover>
172
+ {isShowSearchBox ? (
173
+ <Input
174
+ size="middle"
175
+ placeholder="Search"
176
+ prefix={<SearchOutlined />}
177
+ allowClear
178
+ onChange={handleSearchChange}
179
+ onBlur={handleSearchBlur}
180
+ value={searchString}
181
+ />
182
+ ) : (
183
+ <Button icon={<SearchOutlined />} onClick={handleSearchIconClick} />
184
+ )}
185
+
186
  <Popover content={filterContent} placement="bottom" arrow={false}>
187
  <Button icon={<FilterIcon />} />
188
  </Popover>
189
+ <Button
190
+ icon={<PlusOutlined />}
191
+ type="primary"
192
+ onClick={() => createChunk()}
193
+ />
194
  </Space>
195
  </Flex>
196
  );
web/src/pages/add-knowledge/components/knowledge-chunk/components/edit-tag/index.less ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .tweenGroup {
2
+ display: inline-block;
3
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/components/edit-tag/index.tsx ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { PlusOutlined } from '@ant-design/icons';
2
+ import type { InputRef } from 'antd';
3
+ import { Input, Tag, theme } from 'antd';
4
+ import { TweenOneGroup } from 'rc-tween-one';
5
+ import React, { useEffect, useRef, useState } from 'react';
6
+
7
+ import styles from './index.less';
8
+
9
+ interface EditTagsProps {
10
+ tags: string[];
11
+ setTags: (tags: string[]) => void;
12
+ }
13
+
14
+ const EditTag = ({ tags, setTags }: EditTagsProps) => {
15
+ const { token } = theme.useToken();
16
+ const [inputVisible, setInputVisible] = useState(false);
17
+ const [inputValue, setInputValue] = useState('');
18
+ const inputRef = useRef<InputRef>(null);
19
+
20
+ useEffect(() => {
21
+ if (inputVisible) {
22
+ inputRef.current?.focus();
23
+ }
24
+ }, [inputVisible]);
25
+
26
+ const handleClose = (removedTag: string) => {
27
+ const newTags = tags.filter((tag) => tag !== removedTag);
28
+ console.log(newTags);
29
+ setTags(newTags);
30
+ };
31
+
32
+ const showInput = () => {
33
+ setInputVisible(true);
34
+ };
35
+
36
+ const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
37
+ setInputValue(e.target.value);
38
+ };
39
+
40
+ const handleInputConfirm = () => {
41
+ if (inputValue && tags.indexOf(inputValue) === -1) {
42
+ setTags([...tags, inputValue]);
43
+ }
44
+ setInputVisible(false);
45
+ setInputValue('');
46
+ };
47
+
48
+ const forMap = (tag: string) => {
49
+ const tagElem = (
50
+ <Tag
51
+ closable
52
+ onClose={(e) => {
53
+ e.preventDefault();
54
+ handleClose(tag);
55
+ }}
56
+ >
57
+ {tag}
58
+ </Tag>
59
+ );
60
+ return (
61
+ <span key={tag} style={{ display: 'inline-block' }}>
62
+ {tagElem}
63
+ </span>
64
+ );
65
+ };
66
+
67
+ const tagChild = tags.map(forMap);
68
+
69
+ const tagPlusStyle: React.CSSProperties = {
70
+ background: token.colorBgContainer,
71
+ borderStyle: 'dashed',
72
+ };
73
+
74
+ return (
75
+ <>
76
+ <span>
77
+ <TweenOneGroup
78
+ className={styles.tweenGroup}
79
+ enter={{
80
+ scale: 0.8,
81
+ opacity: 0,
82
+ type: 'from',
83
+ duration: 100,
84
+ }}
85
+ onEnd={(e) => {
86
+ if (e.type === 'appear' || e.type === 'enter') {
87
+ (e.target as any).style = 'display: inline-block';
88
+ }
89
+ }}
90
+ leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
91
+ appear={false}
92
+ >
93
+ {tagChild}
94
+ </TweenOneGroup>
95
+ </span>
96
+ {inputVisible ? (
97
+ <Input
98
+ ref={inputRef}
99
+ type="text"
100
+ size="small"
101
+ style={{ width: 78 }}
102
+ value={inputValue}
103
+ onChange={handleInputChange}
104
+ onBlur={handleInputConfirm}
105
+ onPressEnter={handleInputConfirm}
106
+ />
107
+ ) : (
108
+ <Tag onClick={showInput} style={tagPlusStyle}>
109
+ <PlusOutlined />
110
+ </Tag>
111
+ )}
112
+ </>
113
+ );
114
+ };
115
+
116
+ export default EditTag;
web/src/pages/add-knowledge/components/knowledge-chunk/index.less CHANGED
@@ -23,6 +23,11 @@
23
  }
24
  }
25
 
 
 
 
 
 
26
  .pageFooter {
27
  height: 32px;
28
  }
 
23
  }
24
  }
25
 
26
+ .chunkContainer {
27
+ height: calc(100vh - 320px);
28
+ overflow: auto;
29
+ }
30
+
31
  .pageFooter {
32
  height: 32px;
33
  }
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx CHANGED
@@ -1,11 +1,11 @@
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';
@@ -21,16 +21,9 @@ const Chunk = () => {
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',
@@ -38,8 +31,10 @@ const Chunk = () => {
38
  'switch_chunk',
39
  ]);
40
  const documentId: string = searchParams.get('doc_id') || '';
 
 
41
 
42
- const getChunkList = () => {
43
  const payload: PayloadType = {
44
  doc_id: documentId,
45
  };
@@ -50,30 +45,19 @@ const Chunk = () => {
50
  ...payload,
51
  },
52
  });
53
- };
54
-
55
- const confirm = async (id: string) => {
56
- const retcode = await dispatch<any>({
57
- type: 'chunkModel/rm_chunk',
58
- payload: {
59
- chunk_ids: [id],
60
- },
61
- });
62
 
63
- retcode === 0 && getChunkList();
64
- };
 
65
 
66
- const handleEditchunk = (chunk_id?: string) => {
67
- dispatch({
68
- type: 'chunkModel/updateState',
69
- payload: {
70
- isShowCreateModal: true,
71
- chunk_id,
72
- doc_id: documentId,
73
- },
74
- });
75
- getChunkList();
76
- };
77
 
78
  const onPaginationChange: PaginationProps['onShowSizeChange'] = (
79
  page,
@@ -93,9 +77,6 @@ const Chunk = () => {
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
  );
@@ -115,6 +96,46 @@ const Chunk = () => {
115
  },
116
  [],
117
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  useEffect(() => {
120
  getChunkList();
@@ -123,22 +144,7 @@ const Chunk = () => {
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(
130
- (value: string) => debounceChange(value),
131
- [],
132
- );
133
-
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
  <>
@@ -146,36 +152,27 @@ const Chunk = () => {
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
154
- placeholder="搜索"
155
- style={{ width: 220 }}
156
- value={keywords}
157
- allowClear
158
- onChange={handleInputChange}
159
- />
160
- </div>
161
- <Button
162
- onClick={() => {
163
- handleEditchunk();
164
- }}
165
- type="link"
166
- >
167
- 添加分段
168
- </Button>
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>
@@ -188,19 +185,14 @@ const Chunk = () => {
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>
197
  </div>
198
- <CreateModal
199
- doc_id={documentId}
200
- isShowCreateModal={isShowCreateModal}
201
- chunk_id={chunk_id}
202
- getChunkList={getChunkList}
203
- />
204
  </>
205
  );
206
  };
 
1
  import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil';
2
  import type { PaginationProps } from 'antd';
3
+ import { Divider, Pagination, Space, Spin, message } from 'antd';
4
+ import { useCallback, useEffect, useState } from 'react';
 
5
  import { useDispatch, useSearchParams, useSelector } from 'umi';
6
+ import CreatingModal from './components/chunk-creating-modal';
7
 
8
+ import { useDeleteChunkByIds } from '@/hooks/knowledgeHook';
9
  import ChunkCard from './components/chunk-card';
10
  import ChunkToolBar from './components/chunk-toolbar';
11
  import styles from './index.less';
 
21
  const chunkModel: ChunkModelState = useSelector(
22
  (state: any) => state.chunkModel,
23
  );
 
24
  const [selectedChunkIds, setSelectedChunkIds] = useState<string[]>([]);
25
  const [searchParams] = useSearchParams();
26
+ const { data = [], total, pagination } = chunkModel;
 
 
 
 
 
 
27
  const effects = useSelector((state: any) => state.loading.effects);
28
  const loading = getOneNamespaceEffectsLoading('chunkModel', effects, [
29
  'create_hunk',
 
31
  'switch_chunk',
32
  ]);
33
  const documentId: string = searchParams.get('doc_id') || '';
34
+ const [chunkId, setChunkId] = useState<string | undefined>();
35
+ const { removeChunk } = useDeleteChunkByIds();
36
 
37
+ const getChunkList = useCallback(() => {
38
  const payload: PayloadType = {
39
  doc_id: documentId,
40
  };
 
45
  ...payload,
46
  },
47
  });
48
+ }, [dispatch, documentId]);
 
 
 
 
 
 
 
 
49
 
50
+ const handleEditChunk = useCallback(
51
+ (chunk_id?: string) => {
52
+ setChunkId(chunk_id);
53
 
54
+ dispatch({
55
+ type: 'chunkModel/setIsShowCreateModal',
56
+ payload: true,
57
+ });
58
+ },
59
+ [dispatch],
60
+ );
 
 
 
 
61
 
62
  const onPaginationChange: PaginationProps['onShowSizeChange'] = (
63
  page,
 
77
  const selectAllChunk = useCallback(
78
  (checked: boolean) => {
79
  setSelectedChunkIds(checked ? data.map((x) => x.chunk_id) : []);
 
 
 
80
  },
81
  [data],
82
  );
 
96
  },
97
  [],
98
  );
99
+ const showSelectedChunkWarning = () => {
100
+ message.warning('Please select chunk!');
101
+ };
102
+
103
+ const handleRemoveChunk = useCallback(async () => {
104
+ if (selectedChunkIds.length > 0) {
105
+ const resCode: number = await removeChunk(selectedChunkIds, documentId);
106
+ if (resCode === 0) {
107
+ setSelectedChunkIds([]);
108
+ }
109
+ } else {
110
+ showSelectedChunkWarning();
111
+ }
112
+ }, [selectedChunkIds, documentId, removeChunk]);
113
+
114
+ const switchChunk = useCallback(
115
+ async (available?: number, chunkIds?: string[]) => {
116
+ let ids = chunkIds;
117
+ if (!chunkIds) {
118
+ ids = selectedChunkIds;
119
+ if (selectedChunkIds.length === 0) {
120
+ showSelectedChunkWarning();
121
+ return;
122
+ }
123
+ }
124
+
125
+ const resCode: number = await dispatch<any>({
126
+ type: 'chunkModel/switch_chunk',
127
+ payload: {
128
+ chunk_ids: ids,
129
+ available_int: available,
130
+ doc_id: documentId,
131
+ },
132
+ });
133
+ if (!chunkIds && resCode === 0) {
134
+ getChunkList();
135
+ }
136
+ },
137
+ [dispatch, documentId, getChunkList, selectedChunkIds],
138
+ );
139
 
140
  useEffect(() => {
141
  getChunkList();
 
144
  type: 'chunkModel/resetFilter', // TODO: need to reset state uniformly
145
  });
146
  };
147
+ }, [dispatch, getChunkList]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
  return (
150
  <>
 
152
  <ChunkToolBar
153
  getChunkList={getChunkList}
154
  selectAllChunk={selectAllChunk}
155
+ createChunk={handleEditChunk}
156
+ removeChunk={handleRemoveChunk}
157
  checked={selectedChunkIds.length === data.length}
158
+ switchChunk={switchChunk}
159
  ></ChunkToolBar>
160
+ <Divider></Divider>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  <div className={styles.pageContent}>
162
  <Spin spinning={loading} className={styles.spin} size="large">
163
+ <Space
164
+ direction="vertical"
165
+ size={'middle'}
166
+ className={styles.chunkContainer}
167
+ >
168
  {data.map((item) => (
169
  <ChunkCard
170
  item={item}
171
  key={item.chunk_id}
172
+ editChunk={handleEditChunk}
173
  checked={selectedChunkIds.some((x) => x === item.chunk_id)}
174
  handleCheckboxClick={handleSingleCheckboxClick}
175
+ switchChunk={switchChunk}
176
  ></ChunkCard>
177
  ))}
178
  </Space>
 
185
  showQuickJumper
186
  showSizeChanger
187
  onChange={onPaginationChange}
188
+ pageSize={pagination.pageSize}
189
  pageSizeOptions={[10, 30, 60, 90]}
190
+ current={pagination.current}
191
  total={total}
192
  />
193
  </div>
194
  </div>
195
+ <CreatingModal doc_id={documentId} chunkId={chunkId} />
 
 
 
 
 
196
  </>
197
  );
198
  };
web/src/pages/add-knowledge/components/knowledge-chunk/model.ts CHANGED
@@ -2,6 +2,7 @@ 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
 
@@ -40,6 +41,13 @@ const model: DvaModel<ChunkModelState> = {
40
  ...payload,
41
  };
42
  },
 
 
 
 
 
 
 
43
  setAvailable(state, { payload }) {
44
  return { ...state, available: payload };
45
  },
@@ -49,7 +57,7 @@ const model: DvaModel<ChunkModelState> = {
49
  setPagination(state, { payload }) {
50
  return { ...state, pagination: { ...state.pagination, ...payload } };
51
  },
52
- resetFilter(state, { payload }) {
53
  return {
54
  ...state,
55
  pagination: {
@@ -84,7 +92,13 @@ const model: DvaModel<ChunkModelState> = {
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) {
@@ -93,15 +107,21 @@ const model: DvaModel<ChunkModelState> = {
93
  return retcode;
94
  },
95
  *rm_chunk({ payload = {} }, { call, put }) {
96
- console.log('shanchu');
97
- const { data, response } = yield call(kbService.rm_chunk, payload);
98
- const { retcode, data: res, retmsg } = data;
99
-
 
 
 
 
 
 
100
  return retcode;
101
  },
102
  *get_chunk({ payload = {} }, { call, put }) {
103
- const { data, response } = yield call(kbService.get_chunk, payload);
104
- const { retcode, data: res, retmsg } = data;
105
  if (retcode === 0) {
106
  yield put({
107
  type: 'updateState',
@@ -112,20 +132,20 @@ const model: DvaModel<ChunkModelState> = {
112
  }
113
  return data;
114
  },
115
- *create_hunk({ payload = {} }, { call, put }) {
116
  let service = kbService.create_chunk;
117
  if (payload.chunk_id) {
118
  service = kbService.set_chunk;
119
  }
120
- const { data, response } = yield call(service, payload);
121
- const { retcode, data: res, retmsg } = data;
122
  if (retcode === 0) {
123
  yield put({
124
- type: 'updateState',
125
- payload: {
126
- isShowCreateModal: false,
127
- },
128
  });
 
 
129
  }
130
  },
131
  },
 
2
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
3
  import kbService from '@/services/kbService';
4
  import { message } from 'antd';
5
+ import { pick } from 'lodash';
6
  // import { delay } from '@/utils/storeUtil';
7
  import { DvaModel } from 'umi';
8
 
 
41
  ...payload,
42
  };
43
  },
44
+ setIsShowCreateModal(state, { payload }) {
45
+ return {
46
+ ...state,
47
+ isShowCreateModal:
48
+ typeof payload === 'boolean' ? payload : !state.isShowCreateModal,
49
+ };
50
+ },
51
  setAvailable(state, { payload }) {
52
  return { ...state, available: payload };
53
  },
 
57
  setPagination(state, { payload }) {
58
  return { ...state, pagination: { ...state.pagination, ...payload } };
59
  },
60
+ resetFilter(state, {}) {
61
  return {
62
  ...state,
63
  pagination: {
 
92
  });
93
  }
94
  },
95
+ throttledGetChunkList: [
96
+ function* ({ payload }, { put }) {
97
+ yield put({ type: 'chunk_list', payload: { doc_id: payload } });
98
+ },
99
+ { type: 'throttle', ms: 1000 }, // TODO: Provide type support for this effect
100
+ ],
101
+ *switch_chunk({ payload = {} }, { call }) {
102
  const { data } = yield call(kbService.switch_chunk, payload);
103
  const { retcode } = data;
104
  if (retcode === 0) {
 
107
  return retcode;
108
  },
109
  *rm_chunk({ payload = {} }, { call, put }) {
110
+ const { data } = yield call(kbService.rm_chunk, payload);
111
+ const { retcode } = data;
112
+ if (retcode === 0) {
113
+ yield put({
114
+ type: 'setIsShowCreateModal',
115
+ payload: false,
116
+ });
117
+ yield put({ type: 'setPagination', payload: { current: 1 } });
118
+ yield put({ type: 'chunk_list', payload: pick(payload, ['doc_id']) });
119
+ }
120
  return retcode;
121
  },
122
  *get_chunk({ payload = {} }, { call, put }) {
123
+ const { data } = yield call(kbService.get_chunk, payload);
124
+ const { retcode, data: res } = data;
125
  if (retcode === 0) {
126
  yield put({
127
  type: 'updateState',
 
132
  }
133
  return data;
134
  },
135
+ *create_chunk({ payload = {} }, { call, put }) {
136
  let service = kbService.create_chunk;
137
  if (payload.chunk_id) {
138
  service = kbService.set_chunk;
139
  }
140
+ const { data } = yield call(service, payload);
141
+ const { retcode } = data;
142
  if (retcode === 0) {
143
  yield put({
144
+ type: 'setIsShowCreateModal',
145
+ payload: false,
 
 
146
  });
147
+
148
+ yield put({ type: 'chunk_list', payload: pick(payload, ['doc_id']) });
149
  }
150
  },
151
  },
web/src/pages/add-knowledge/components/knowledge-search/index.tsx CHANGED
@@ -17,7 +17,7 @@ import {
17
  import { debounce } from 'lodash';
18
  import React, { useCallback, useEffect } from 'react';
19
  import { useDispatch, useSelector } from 'umi';
20
- import CreateModal from '../knowledge-chunk/components/createModal';
21
 
22
  import styles from './index.less';
23
 
@@ -265,7 +265,6 @@ const KnowledgeSearching = () => {
265
  </div>
266
  </div>
267
  <CreateModal
268
- getChunkList={getChunkList}
269
  isShowCreateModal={isShowCreateModal}
270
  chunk_id={chunk_id}
271
  doc_id={doc_id}
 
17
  import { debounce } from 'lodash';
18
  import React, { useCallback, useEffect } from 'react';
19
  import { useDispatch, useSelector } from 'umi';
20
+ import CreateModal from '../knowledge-chunk/components/chunk-creating-modal';
21
 
22
  import styles from './index.less';
23
 
 
265
  </div>
266
  </div>
267
  <CreateModal
 
268
  isShowCreateModal={isShowCreateModal}
269
  chunk_id={chunk_id}
270
  doc_id={doc_id}
web/src/pages/add-knowledge/components/knowledge-search/model.ts CHANGED
@@ -138,8 +138,8 @@ const model: DvaModel<KSearchModelState> = {
138
  if (payload.chunk_id) {
139
  service = kbService.set_chunk;
140
  }
141
- const { data, response } = yield call(service, payload);
142
- const { retcode, data: res, retmsg } = data;
143
  yield put({
144
  type: 'updateState',
145
  payload: {
 
138
  if (payload.chunk_id) {
139
  service = kbService.set_chunk;
140
  }
141
+ const { data } = yield call(service, payload);
142
+ const { retcode } = data;
143
  yield put({
144
  type: 'updateState',
145
  payload: {