mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: locate the specific location of the document based on the coordinates of the chunk and add Upload to AssistantSetting (#92)
* feat: add Upload to AssistantSetting * feat: locate the specific location of the document based on the coordinates of the chunk
This commit is contained in:
@ -74,6 +74,7 @@ export interface IChunk {
|
|||||||
docnm_kwd: string;
|
docnm_kwd: string;
|
||||||
img_id: string;
|
img_id: string;
|
||||||
important_kwd: any[];
|
important_kwd: any[];
|
||||||
|
positions: number[][];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITestingChunk {
|
export interface ITestingChunk {
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
@gray11: rgba(232, 232, 234, 1);
|
@gray11: rgba(232, 232, 234, 1);
|
||||||
@purple: rgba(127, 86, 217, 1);
|
@purple: rgba(127, 86, 217, 1);
|
||||||
@selectedBackgroundColor: rgba(239, 248, 255, 1);
|
@selectedBackgroundColor: rgba(239, 248, 255, 1);
|
||||||
|
@blurBackground: rgba(22, 119, 255, 0.5);
|
||||||
|
@blurBackgroundHover: rgba(22, 119, 255, 0.2);
|
||||||
|
|
||||||
@fontSize12: 12px;
|
@fontSize12: 12px;
|
||||||
@fontSize14: 14px;
|
@fontSize14: 14px;
|
||||||
|
|||||||
@ -13,6 +13,28 @@
|
|||||||
color: red;
|
color: red;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
color: @blurBackground;
|
||||||
|
font-size: 20px;
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
color: #fff;
|
||||||
|
background-color: @blurBackground;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:hover {
|
||||||
|
background: @blurBackgroundHover;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardSelected {
|
.cardSelected {
|
||||||
|
|||||||
@ -64,9 +64,7 @@ const ChunkCard = ({
|
|||||||
onClick={handleContentClick}
|
onClick={handleContentClick}
|
||||||
className={styles.content}
|
className={styles.content}
|
||||||
dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
|
dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
|
||||||
>
|
></section>
|
||||||
{/* {item.content_with_weight} */}
|
|
||||||
</section>
|
|
||||||
<div>
|
<div>
|
||||||
<Switch checked={enabled} onChange={onChange} />
|
<Switch checked={enabled} onChange={onChange} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,21 +6,27 @@ export const testHighlights = [
|
|||||||
position: {
|
position: {
|
||||||
boundingRect: {
|
boundingRect: {
|
||||||
x1: 219.7,
|
x1: 219.7,
|
||||||
|
// x1: 419.7,
|
||||||
y1: 204.3,
|
y1: 204.3,
|
||||||
|
// y1: 304.3,
|
||||||
x2: 547.0,
|
x2: 547.0,
|
||||||
|
// x2: 747.0,
|
||||||
y2: 264.0,
|
y2: 264.0,
|
||||||
width: 849,
|
// y2: 364.0,
|
||||||
height: 1200,
|
|
||||||
},
|
},
|
||||||
rects: [
|
rects: [
|
||||||
{
|
// {
|
||||||
x1: 219.7,
|
// x1: 219.7,
|
||||||
y1: 204.3,
|
// // x1: 419.7,
|
||||||
x2: 547.0,
|
// y1: 204.3,
|
||||||
y2: 264.0,
|
// // y1: 304.3,
|
||||||
width: 849,
|
// x2: 547.0,
|
||||||
height: 1200,
|
// // x2: 747.0,
|
||||||
},
|
// y2: 264.0,
|
||||||
|
// // y2: 364.0,
|
||||||
|
// width: 849,
|
||||||
|
// height: 1200,
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
pageNumber: 9,
|
pageNumber: 9,
|
||||||
},
|
},
|
||||||
@ -28,6 +34,56 @@ export const testHighlights = [
|
|||||||
text: 'Flow or TypeScript?',
|
text: 'Flow or TypeScript?',
|
||||||
emoji: '🔥',
|
emoji: '🔥',
|
||||||
},
|
},
|
||||||
id: '8245652131754351',
|
id: 'jsdlihdkghergjl',
|
||||||
},
|
},
|
||||||
];
|
{
|
||||||
|
content: {
|
||||||
|
text: '图2:乘联会预计6 月新能源乘用车厂商批发销量74 万辆,环比增长10%,同比增长30%。',
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
boundingRect: {
|
||||||
|
x1: 219.0,
|
||||||
|
x2: 546.0,
|
||||||
|
y1: 616.0,
|
||||||
|
y2: 674.7,
|
||||||
|
},
|
||||||
|
rects: [],
|
||||||
|
pageNumber: 6,
|
||||||
|
},
|
||||||
|
comment: {
|
||||||
|
text: 'Flow or TypeScript?',
|
||||||
|
emoji: '🔥',
|
||||||
|
},
|
||||||
|
id: 'bfdbtymkhjildbfghserrgrt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: {
|
||||||
|
text: '图2:乘联会预计6 月新能源乘用车厂商批发销量74 万辆,环比增长10%,同比增长30%。',
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
boundingRect: {
|
||||||
|
x1: 73.7,
|
||||||
|
x2: 391.7,
|
||||||
|
y1: 570.3,
|
||||||
|
y2: 676.3,
|
||||||
|
},
|
||||||
|
rects: [],
|
||||||
|
pageNumber: 1,
|
||||||
|
},
|
||||||
|
comment: {
|
||||||
|
text: '',
|
||||||
|
emoji: '',
|
||||||
|
},
|
||||||
|
id: 'fgnhxdvsesgmghyu',
|
||||||
|
},
|
||||||
|
].map((x) => {
|
||||||
|
const boundingRect = x.position.boundingRect;
|
||||||
|
const ret: any = {
|
||||||
|
width: 849,
|
||||||
|
height: 1200,
|
||||||
|
};
|
||||||
|
Object.entries(boundingRect).forEach(([key, value]) => {
|
||||||
|
ret[key] = value / 0.7;
|
||||||
|
});
|
||||||
|
return { ...x, position: { ...x.position, boundingRect: ret, rects: [ret] } };
|
||||||
|
});
|
||||||
|
|||||||
@ -6,6 +6,9 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
:global(.PdfHighlighter) {
|
:global(.PdfHighlighter) {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
// left: 0;
|
}
|
||||||
|
:global(.Highlight--scrolledTo .Highlight__part) {
|
||||||
|
overflow-x: hidden;
|
||||||
|
background-color: rgba(255, 226, 143, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import { useRef, useState } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import type { NewHighlight } from 'react-pdf-highlighter';
|
|
||||||
import {
|
import {
|
||||||
AreaHighlight,
|
AreaHighlight,
|
||||||
Highlight,
|
Highlight,
|
||||||
|
NewHighlight,
|
||||||
PdfHighlighter,
|
PdfHighlighter,
|
||||||
PdfLoader,
|
PdfLoader,
|
||||||
Popup,
|
Popup,
|
||||||
Tip,
|
Tip,
|
||||||
} from 'react-pdf-highlighter';
|
} from 'react-pdf-highlighter';
|
||||||
import { useGetSelectedChunk } from '../../hooks';
|
import { useGetChunkHighlights, useGetSelectedChunk } from '../../hooks';
|
||||||
import { testHighlights } from './hightlights';
|
|
||||||
import { useGetDocumentUrl } from './hooks';
|
import { useGetDocumentUrl } from './hooks';
|
||||||
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
@ -36,7 +35,9 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
|||||||
const url = useGetDocumentUrl();
|
const url = useGetDocumentUrl();
|
||||||
const selectedChunk = useGetSelectedChunk(selectedChunkId);
|
const selectedChunk = useGetSelectedChunk(selectedChunkId);
|
||||||
|
|
||||||
const [state, setState] = useState<any>(testHighlights);
|
// const [state, setState] = useState<any>(testHighlights);
|
||||||
|
const state = useGetChunkHighlights(selectedChunkId);
|
||||||
|
|
||||||
const ref = useRef((highlight: any) => {});
|
const ref = useRef((highlight: any) => {});
|
||||||
|
|
||||||
const parseIdFromHash = () =>
|
const parseIdFromHash = () =>
|
||||||
@ -67,7 +68,7 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
|||||||
|
|
||||||
console.log('Saving highlight', highlight);
|
console.log('Saving highlight', highlight);
|
||||||
|
|
||||||
setState([{ ...highlight, id: getNextId() }, ...highlights]);
|
// setState([{ ...highlight, id: getNextId() }, ...highlights]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateHighlight = (
|
const updateHighlight = (
|
||||||
@ -77,29 +78,31 @@ const Preview = ({ selectedChunkId }: IProps) => {
|
|||||||
) => {
|
) => {
|
||||||
console.log('Updating highlight', highlightId, position, content);
|
console.log('Updating highlight', highlightId, position, content);
|
||||||
|
|
||||||
setState(
|
// setState(
|
||||||
state.map((h: any) => {
|
// state.map((h: any) => {
|
||||||
const {
|
// const {
|
||||||
id,
|
// id,
|
||||||
position: originalPosition,
|
// position: originalPosition,
|
||||||
content: originalContent,
|
// content: originalContent,
|
||||||
...rest
|
// ...rest
|
||||||
} = h;
|
// } = h;
|
||||||
return id === highlightId
|
// return id === highlightId
|
||||||
? {
|
// ? {
|
||||||
id,
|
// id,
|
||||||
position: { ...originalPosition, ...position },
|
// position: { ...originalPosition, ...position },
|
||||||
content: { ...originalContent, ...content },
|
// content: { ...originalContent, ...content },
|
||||||
...rest,
|
// ...rest,
|
||||||
}
|
// }
|
||||||
: h;
|
// : h;
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// ref.current(testHighlights[0]);
|
if (state.length > 0) {
|
||||||
// }, [selectedChunk]);
|
ref.current(state[0]);
|
||||||
|
}
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.documentContainer}>
|
<div className={styles.documentContainer}>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { IHighlight } from 'react-pdf-highlighter';
|
||||||
import { useSelector } from 'umi';
|
import { useSelector } from 'umi';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
export const useSelectDocumentInfo = () => {
|
export const useSelectDocumentInfo = () => {
|
||||||
const documentInfo: IKnowledgeFile = useSelector(
|
const documentInfo: IKnowledgeFile = useSelector(
|
||||||
@ -28,5 +30,46 @@ export const useHandleChunkCardClick = () => {
|
|||||||
|
|
||||||
export const useGetSelectedChunk = (selectedChunkId: string) => {
|
export const useGetSelectedChunk = (selectedChunkId: string) => {
|
||||||
const chunkList: IChunk[] = useSelectChunkList();
|
const chunkList: IChunk[] = useSelectChunkList();
|
||||||
return chunkList.find((x) => x.chunk_id === selectedChunkId);
|
return (
|
||||||
|
chunkList.find((x) => x.chunk_id === selectedChunkId) ?? ({} as IChunk)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetChunkHighlights = (
|
||||||
|
selectedChunkId: string,
|
||||||
|
): IHighlight[] => {
|
||||||
|
const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
|
||||||
|
|
||||||
|
const highlights: IHighlight[] = useMemo(() => {
|
||||||
|
return Array.isArray(selectedChunk?.positions)
|
||||||
|
? selectedChunk?.positions?.map((x) => {
|
||||||
|
const actualPositions = x.map((y, index) =>
|
||||||
|
index !== 0 ? y / 0.7 : y,
|
||||||
|
);
|
||||||
|
const boundingRect = {
|
||||||
|
width: 849,
|
||||||
|
height: 1200,
|
||||||
|
x1: actualPositions[1],
|
||||||
|
x2: actualPositions[2],
|
||||||
|
y1: actualPositions[3],
|
||||||
|
y2: actualPositions[4],
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
id: uuid(),
|
||||||
|
comment: {
|
||||||
|
text: '',
|
||||||
|
emoji: '',
|
||||||
|
},
|
||||||
|
content: { text: selectedChunk.content_with_weight },
|
||||||
|
position: {
|
||||||
|
boundingRect: boundingRect,
|
||||||
|
rects: [boundingRect],
|
||||||
|
pageNumber: x[0],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
}, [selectedChunk]);
|
||||||
|
|
||||||
|
return highlights;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import {
|
|||||||
import type { ColumnsType } from 'antd/es/table';
|
import type { ColumnsType } from 'antd/es/table';
|
||||||
import { PaginationProps } from 'antd/lib';
|
import { PaginationProps } from 'antd/lib';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { Link, useDispatch, useNavigate, useSelector } from 'umi';
|
import { useDispatch, useNavigate, useSelector } from 'umi';
|
||||||
import CreateEPModal from './createEFileModal';
|
import CreateEPModal from './createEFileModal';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import ParsingActionCell from './parsing-action-cell';
|
import ParsingActionCell from './parsing-action-cell';
|
||||||
@ -144,19 +144,22 @@ const KnowledgeFile = () => {
|
|||||||
});
|
});
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const linkToUploadPage = useCallback(() => {
|
||||||
|
navigate(`/knowledge/dataset/upload?id=${knowledgeBaseId}`);
|
||||||
|
}, [navigate, knowledgeBaseId]);
|
||||||
|
|
||||||
const actionItems: MenuProps['items'] = useMemo(() => {
|
const actionItems: MenuProps['items'] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: '1',
|
key: '1',
|
||||||
|
onClick: linkToUploadPage,
|
||||||
label: (
|
label: (
|
||||||
<div>
|
<div>
|
||||||
<Button type="link">
|
<Button type="link">
|
||||||
<Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}>
|
<Space>
|
||||||
<Space>
|
<FileTextOutlined />
|
||||||
<FileTextOutlined />
|
Local files
|
||||||
Local files
|
</Space>
|
||||||
</Space>
|
|
||||||
</Link>
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@ -164,9 +167,10 @@ const KnowledgeFile = () => {
|
|||||||
{ type: 'divider' },
|
{ type: 'divider' },
|
||||||
{
|
{
|
||||||
key: '2',
|
key: '2',
|
||||||
|
onClick: showCEFModal,
|
||||||
label: (
|
label: (
|
||||||
<div>
|
<div>
|
||||||
<Button type="link" onClick={showCEFModal}>
|
<Button type="link">
|
||||||
<FileOutlined />
|
<FileOutlined />
|
||||||
Create empty file
|
Create empty file
|
||||||
</Button>
|
</Button>
|
||||||
@ -175,7 +179,7 @@ const KnowledgeFile = () => {
|
|||||||
// disabled: true,
|
// disabled: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [knowledgeBaseId, showCEFModal]);
|
}, [linkToUploadPage, showCEFModal]);
|
||||||
|
|
||||||
const toChunk = (id: string) => {
|
const toChunk = (id: string) => {
|
||||||
navigate(
|
navigate(
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { Form, Input, Select } from 'antd';
|
import { Form, Input, Select, Upload } from 'antd';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { ISegmentedContentProps } from '../interface';
|
import { ISegmentedContentProps } from '../interface';
|
||||||
|
|
||||||
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
||||||
@ -13,6 +14,13 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|||||||
value: x.id,
|
value: x.id,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const normFile = (e: any) => {
|
||||||
|
if (Array.isArray(e)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return e?.fileList;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={classNames({
|
className={classNames({
|
||||||
@ -26,8 +34,22 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|||||||
>
|
>
|
||||||
<Input placeholder="e.g. Resume Jarvis" />
|
<Input placeholder="e.g. Resume Jarvis" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name={'icon'} label="Assistant avatar">
|
<Form.Item
|
||||||
<Input />
|
name="icon"
|
||||||
|
label="Assistant avatar"
|
||||||
|
valuePropName="fileList"
|
||||||
|
getValueFromEvent={normFile}
|
||||||
|
>
|
||||||
|
<Upload
|
||||||
|
listType="picture-card"
|
||||||
|
maxCount={1}
|
||||||
|
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }}
|
||||||
|
>
|
||||||
|
<button style={{ border: 0, background: 'none' }} type="button">
|
||||||
|
<PlusOutlined />
|
||||||
|
<div style={{ marginTop: 8 }}>Upload</div>
|
||||||
|
</button>
|
||||||
|
</Upload>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name={'language'} label="Language" initialValue={'Chinese'}>
|
<Form.Item name={'language'} label="Language" initialValue={'Chinese'}>
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ReactComponent as ChatConfigurationAtom } from '@/assets/svg/chat-configuration-atom.svg';
|
import { ReactComponent as ChatConfigurationAtom } from '@/assets/svg/chat-configuration-atom.svg';
|
||||||
import { IModalManagerChildrenProps } from '@/components/modal-manager';
|
import { IModalManagerChildrenProps } from '@/components/modal-manager';
|
||||||
import { Divider, Flex, Form, Modal, Segmented } from 'antd';
|
import { Divider, Flex, Form, Modal, Segmented, UploadFile } from 'antd';
|
||||||
import { SegmentedValue } from 'antd/es/segmented';
|
import { SegmentedValue } from 'antd/es/segmented';
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
@ -67,6 +67,14 @@ const ChatConfigurationModal = ({ visible, hideModal, id }: IProps) => {
|
|||||||
...excludeUnEnabledVariables(values),
|
...excludeUnEnabledVariables(values),
|
||||||
]);
|
]);
|
||||||
const emptyResponse = nextValues.prompt_config?.empty_response ?? '';
|
const emptyResponse = nextValues.prompt_config?.empty_response ?? '';
|
||||||
|
|
||||||
|
const fileList = values.icon;
|
||||||
|
let icon;
|
||||||
|
|
||||||
|
if (Array.isArray(fileList) && fileList.length > 0) {
|
||||||
|
icon = fileList[0].thumbUrl;
|
||||||
|
}
|
||||||
|
|
||||||
const finalValues = {
|
const finalValues = {
|
||||||
dialog_id: id,
|
dialog_id: id,
|
||||||
...nextValues,
|
...nextValues,
|
||||||
@ -75,6 +83,7 @@ const ChatConfigurationModal = ({ visible, hideModal, id }: IProps) => {
|
|||||||
parameters: promptEngineRef.current,
|
parameters: promptEngineRef.current,
|
||||||
empty_response: emptyResponse,
|
empty_response: emptyResponse,
|
||||||
},
|
},
|
||||||
|
icon,
|
||||||
};
|
};
|
||||||
console.info(promptEngineRef.current);
|
console.info(promptEngineRef.current);
|
||||||
console.info(nextValues);
|
console.info(nextValues);
|
||||||
@ -112,7 +121,13 @@ const ChatConfigurationModal = ({ visible, hideModal, id }: IProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
form.setFieldsValue(currentDialog);
|
const icon = currentDialog.icon;
|
||||||
|
let fileList: UploadFile[] = [];
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
fileList = [{ uid: '1', name: 'file', thumbUrl: icon, status: 'done' }];
|
||||||
|
}
|
||||||
|
form.setFieldsValue({ ...currentDialog, icon: fileList });
|
||||||
}, [currentDialog, form]);
|
}, [currentDialog, form]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg';
|
|||||||
import { useSetModalState } from '@/hooks/commonHooks';
|
import { useSetModalState } from '@/hooks/commonHooks';
|
||||||
import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Divider,
|
Divider,
|
||||||
@ -208,8 +209,8 @@ const Chat = () => {
|
|||||||
onClick={handleDialogCardClick(x.id)}
|
onClick={handleDialogCardClick(x.id)}
|
||||||
>
|
>
|
||||||
<Flex justify="space-between" align="center">
|
<Flex justify="space-between" align="center">
|
||||||
<Space>
|
<Space size={15}>
|
||||||
{x.icon}
|
<Avatar src={x.icon} shape={'square'} />
|
||||||
<section>
|
<section>
|
||||||
<b>{x.name}</b>
|
<b>{x.name}</b>
|
||||||
<div>{x.description}</div>
|
<div>{x.description}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user