mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-28 14:16:34 +08:00
Refactor: UmiJs -> Vite (#12410)
### What problem does this PR solve? Refactor: UmiJs -> Vite+React ### Type of change - [x] Refactoring --------- Co-authored-by: Liu An <asiro@qq.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
import { useIsDarkTheme } from '@/components/theme-provider';
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { LangfuseCard } from '@/pages/user-setting/setting-model/langfuse';
|
||||
import apiDoc from '@parent/docs/references/http_api_reference.md';
|
||||
import apiDoc from '@parent/docs/references/http_api_reference.md?raw';
|
||||
import MarkdownPreview from '@uiw/react-markdown-preview';
|
||||
import ChatApiKeyModal from '../chat-api-key-modal';
|
||||
import BackendServiceApi from './backend-service-api';
|
||||
|
||||
@ -5,7 +5,7 @@ import { formatDate } from '@/utils/date';
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { useSelectChartStatsList } from '../hooks';
|
||||
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const StatsLineChart = ({ statsType }: { statsType: keyof IStats }) => {
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
@ -2,11 +2,10 @@ import { cn } from '@/lib/utils';
|
||||
import { t } from 'i18next';
|
||||
import { ArrowBigLeft } from 'lucide-react';
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'umi';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { Button } from '../ui/button';
|
||||
|
||||
interface BackButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
interface BackButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
to?: string;
|
||||
}
|
||||
|
||||
|
||||
@ -57,11 +57,10 @@ import {
|
||||
|
||||
const FormId = 'ChunkMethodDialogForm';
|
||||
|
||||
interface IProps
|
||||
extends IModalProps<{
|
||||
parserId: string;
|
||||
parserConfig: IChangeParserConfigRequestBody;
|
||||
}> {
|
||||
interface IProps extends IModalProps<{
|
||||
parserId: string;
|
||||
parserConfig: IChangeParserConfigRequestBody;
|
||||
}> {
|
||||
loading: boolean;
|
||||
parserId: string;
|
||||
pipelineId?: string;
|
||||
|
||||
@ -14,7 +14,7 @@ import { Spin } from '@/components/ui/spin';
|
||||
import { Authorization } from '@/constants/authorization';
|
||||
import FileError from '@/pages/document-viewer/file-error';
|
||||
import { getAuthorization } from '@/utils/authorization-util';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
type PdfLoaderProps = React.ComponentProps<typeof PdfLoader> & {
|
||||
httpHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
@ -952,8 +952,8 @@ const DynamicForm = {
|
||||
onClick={() => {
|
||||
(async () => {
|
||||
try {
|
||||
let beValid = await form.formControl.trigger();
|
||||
console.log('form valid', beValid, form, form.formControl);
|
||||
let beValid = await form.trigger();
|
||||
console.log('form valid', beValid, form);
|
||||
// if (beValid) {
|
||||
// form.handleSubmit(async (values) => {
|
||||
// console.log('form values', values);
|
||||
|
||||
65
web/src/components/fallback-component/index.tsx
Normal file
65
web/src/components/fallback-component/index.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface FallbackComponentProps {
|
||||
error?: Error;
|
||||
reset?: () => void;
|
||||
}
|
||||
|
||||
const FallbackComponent: React.FC<FallbackComponentProps> = ({
|
||||
error,
|
||||
reset,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px', textAlign: 'center' }}>
|
||||
<h2>{t('error_boundary.title', 'Something went wrong')}</h2>
|
||||
<p>
|
||||
{t(
|
||||
'error_boundary.description',
|
||||
'Sorry, an error occurred while loading the page.',
|
||||
)}
|
||||
</p>
|
||||
{error && (
|
||||
<details style={{ whiteSpace: 'pre-wrap', marginTop: '16px' }}>
|
||||
<summary>{t('error_boundary.details', 'Error details')}</summary>
|
||||
{error.toString()}
|
||||
</details>
|
||||
)}
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#1890ff',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
{t('error_boundary.reload', 'Reload Page')}
|
||||
</button>
|
||||
{reset && (
|
||||
<button
|
||||
onClick={reset}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#52c41a',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
{t('error_boundary.retry', 'Retry')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FallbackComponent;
|
||||
@ -3,7 +3,7 @@ import SvgIcon from '../svg-icon';
|
||||
|
||||
import { useFetchDocumentThumbnailsByIds } from '@/hooks/use-document-request';
|
||||
import { useEffect } from 'react';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface IProps {
|
||||
name: string;
|
||||
|
||||
@ -287,11 +287,10 @@ function useFileUploadContext(consumerName: string) {
|
||||
return context;
|
||||
}
|
||||
|
||||
interface FileUploadRootProps
|
||||
extends Omit<
|
||||
React.ComponentPropsWithoutRef<'div'>,
|
||||
'defaultValue' | 'onChange'
|
||||
> {
|
||||
interface FileUploadRootProps extends Omit<
|
||||
React.ComponentPropsWithoutRef<'div'>,
|
||||
'defaultValue' | 'onChange'
|
||||
> {
|
||||
value?: File[];
|
||||
defaultValue?: File[];
|
||||
onValueChange?: (files: File[]) => void;
|
||||
@ -639,8 +638,7 @@ function FileUploadRoot(props: FileUploadRootProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FileUploadDropzoneProps
|
||||
extends React.ComponentPropsWithoutRef<'div'> {
|
||||
interface FileUploadDropzoneProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
@ -836,8 +834,7 @@ function FileUploadDropzone(props: FileUploadDropzoneProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FileUploadTriggerProps
|
||||
extends React.ComponentPropsWithoutRef<'button'> {
|
||||
interface FileUploadTriggerProps extends React.ComponentPropsWithoutRef<'button'> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
@ -1069,8 +1066,7 @@ function getFileIcon(file: File) {
|
||||
return <FileIcon />;
|
||||
}
|
||||
|
||||
interface FileUploadItemPreviewProps
|
||||
extends React.ComponentPropsWithoutRef<'div'> {
|
||||
interface FileUploadItemPreviewProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
render?: (file: File) => React.ReactNode;
|
||||
asChild?: boolean;
|
||||
}
|
||||
@ -1122,8 +1118,7 @@ function FileUploadItemPreview(props: FileUploadItemPreviewProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FileUploadItemMetadataProps
|
||||
extends React.ComponentPropsWithoutRef<'div'> {
|
||||
interface FileUploadItemMetadataProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
asChild?: boolean;
|
||||
size?: 'default' | 'sm';
|
||||
}
|
||||
@ -1184,8 +1179,7 @@ function FileUploadItemMetadata(props: FileUploadItemMetadataProps) {
|
||||
</ItemMetadataPrimitive>
|
||||
);
|
||||
}
|
||||
interface FileUploadItemProgressProps
|
||||
extends React.ComponentPropsWithoutRef<'div'> {
|
||||
interface FileUploadItemProgressProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
variant?: 'linear' | 'circular' | 'fill';
|
||||
size?: number;
|
||||
asChild?: boolean;
|
||||
@ -1315,8 +1309,7 @@ function FileUploadItemProgress(props: FileUploadItemProgressProps) {
|
||||
}
|
||||
}
|
||||
|
||||
interface FileUploadItemDeleteProps
|
||||
extends React.ComponentPropsWithoutRef<'button'> {
|
||||
interface FileUploadItemDeleteProps extends React.ComponentPropsWithoutRef<'button'> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
@ -1356,8 +1349,7 @@ function FileUploadItemDelete(props: FileUploadItemDeleteProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FileUploadClearProps
|
||||
extends React.ComponentPropsWithoutRef<'button'> {
|
||||
interface FileUploadClearProps extends React.ComponentPropsWithoutRef<'button'> {
|
||||
forceMount?: boolean;
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
@ -92,8 +92,10 @@ function FileCard({ file, progress, onRemove }: FileCardProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface FileUploaderProps
|
||||
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
|
||||
interface FileUploaderProps extends Omit<
|
||||
React.HTMLAttributes<HTMLDivElement>,
|
||||
'title'
|
||||
> {
|
||||
/**
|
||||
* Value of the uploader.
|
||||
* @type File[]
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
}
|
||||
|
||||
.widget-citation-content {
|
||||
|
||||
p,
|
||||
div,
|
||||
span,
|
||||
@ -35,7 +34,6 @@
|
||||
}
|
||||
|
||||
.floating-chat-widget {
|
||||
|
||||
/* General styles for markdown content within the widget */
|
||||
p,
|
||||
div,
|
||||
@ -55,4 +53,4 @@
|
||||
margin: 8px 0 !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ import rehypeRaw from 'rehype-raw';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkMath from 'remark-math';
|
||||
import { visitParents } from 'unist-util-visit-parents';
|
||||
import styles from './floating-chat-widget-markdown.less';
|
||||
import styles from './floating-chat-widget-markdown.module.less';
|
||||
import { useIsDarkTheme } from './theme-provider';
|
||||
|
||||
const getChunkIndex = (match: string) => Number(match.replace(/\[|\]/g, ''));
|
||||
|
||||
@ -14,7 +14,7 @@ import 'katex/dist/katex.min.css'; // `rehype-katex` does not import the CSS for
|
||||
|
||||
import { preprocessLaTeX } from '@/utils/chat';
|
||||
import { useIsDarkTheme } from '../theme-provider';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const HighLightMarkdown = ({
|
||||
children,
|
||||
|
||||
@ -11,7 +11,7 @@ import { useComposeLlmOptionsByModelTypes } from '@/hooks/use-llm-request';
|
||||
import { setChatVariableEnabledFieldValuePage } from '@/utils/chat';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface IProps {
|
||||
prefix?: string;
|
||||
|
||||
@ -33,7 +33,7 @@ import {
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '../ui/hover-card';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const getChunkIndex = (match: string) => Number(match);
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
|
||||
import { MessageType } from '@/constants/chat';
|
||||
import {
|
||||
IMessage,
|
||||
@ -21,9 +20,10 @@ import {
|
||||
removePDFDownloadInfo,
|
||||
} from '../pdf-download-button';
|
||||
import { RAGFlowAvatar } from '../ragflow-avatar';
|
||||
import SvgIcon from '../svg-icon';
|
||||
import { useTheme } from '../theme-provider';
|
||||
import { AssistantGroupButton, UserGroupButton } from './group-button';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface IProps extends Partial<IRemoveMessageById>, IRegenerateMessage {
|
||||
item: IMessage;
|
||||
@ -117,7 +117,11 @@ const MessageItem = ({
|
||||
isPerson
|
||||
/>
|
||||
) : (
|
||||
<AssistantIcon />
|
||||
<SvgIcon
|
||||
name={'assistant'}
|
||||
width={'100%'}
|
||||
className={cn('size-10 fill-current')}
|
||||
></SvgIcon>
|
||||
))}
|
||||
|
||||
<section className="flex gap-2 flex-1 flex-col">
|
||||
|
||||
@ -35,7 +35,7 @@ import {
|
||||
HoverCardContent,
|
||||
HoverCardTrigger,
|
||||
} from '../ui/hover-card';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
const getChunkIndex = (match: string) => Number(match);
|
||||
// TODO: The display of the table is inconsistent with the display previously placed in the MessageItem.
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
|
||||
import { MessageType } from '@/constants/chat';
|
||||
import {
|
||||
IMessage,
|
||||
@ -31,18 +30,17 @@ import {
|
||||
removePDFDownloadInfo,
|
||||
} from '../pdf-download-button';
|
||||
import { RAGFlowAvatar } from '../ragflow-avatar';
|
||||
import SvgIcon from '../svg-icon';
|
||||
import { useTheme } from '../theme-provider';
|
||||
import { Button } from '../ui/button';
|
||||
import { AssistantGroupButton, UserGroupButton } from './group-button';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
import { ReferenceDocumentList } from './reference-document-list';
|
||||
import { ReferenceImageList } from './reference-image-list';
|
||||
import { UploadedMessageFiles } from './uploaded-message-files';
|
||||
|
||||
interface IProps
|
||||
extends Partial<IRemoveMessageById>,
|
||||
IRegenerateMessage,
|
||||
PropsWithChildren {
|
||||
extends Partial<IRemoveMessageById>, IRegenerateMessage, PropsWithChildren {
|
||||
item: IMessage;
|
||||
conversationId?: string;
|
||||
currentEventListWithoutMessageById?: (messageId: string) => INodeEvent[];
|
||||
@ -208,7 +206,11 @@ function MessageItem({
|
||||
isPerson
|
||||
/>
|
||||
) : (
|
||||
<AssistantIcon />
|
||||
<SvgIcon
|
||||
name={'assistant'}
|
||||
width={'100%'}
|
||||
className={cn('size-10 fill-current')}
|
||||
></SvgIcon>
|
||||
))}
|
||||
<section className="flex-col gap-2 flex-1">
|
||||
<div className="flex justify-between items-center">
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
useGetChunkHighlights,
|
||||
useGetDocumentUrl,
|
||||
} from '@/hooks/use-document-request';
|
||||
import styles from './index.less';
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface IProps {
|
||||
chunk: IChunk | IReferenceChunk;
|
||||
|
||||
@ -61,8 +61,8 @@ export function RAGFlowFormItem({
|
||||
)}
|
||||
<div
|
||||
className={cn('flex flex-col', {
|
||||
'w-3/4': horizontal,
|
||||
'w-full': !horizontal,
|
||||
'w-3/4': horizontal,
|
||||
})}
|
||||
>
|
||||
<FormControl>
|
||||
|
||||
@ -4,26 +4,39 @@ import Icon, { UserOutlined } from '@ant-design/icons';
|
||||
import { IconComponentProps } from '@ant-design/icons/lib/components/Icon';
|
||||
import { Avatar } from 'antd';
|
||||
import { AvatarSize } from 'antd/es/avatar/AvatarContext';
|
||||
import { useMemo } from 'react';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { IconFontFill } from './icon-font';
|
||||
import { useIsDarkTheme } from './theme-provider';
|
||||
|
||||
const importAll = (requireContext: __WebpackModuleApi.RequireContext) => {
|
||||
const list = requireContext.keys().map((key) => {
|
||||
const name = key.replace(/\.\/(.*)\.\w+$/, '$1');
|
||||
return { name, value: requireContext(key) };
|
||||
});
|
||||
return list;
|
||||
};
|
||||
// const importAll = (requireContext: __WebpackModuleApi.RequireContext) => {
|
||||
// const list = requireContext.keys().map((key) => {
|
||||
// const name = key.replace(/\.\/(.*)\.\w+$/, '$1');
|
||||
// return { name, value: requireContext(key) };
|
||||
// });
|
||||
// return list;
|
||||
// };
|
||||
|
||||
let routeList: { name: string; value: string }[] = [];
|
||||
// let routeList: { name: string; value: string }[] = [];
|
||||
|
||||
try {
|
||||
routeList = importAll(require.context('@/assets/svg', true, /\.svg$/));
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
routeList = [];
|
||||
}
|
||||
// try {
|
||||
// routeList = importAll(require.context('@/assets/svg', true, /\.svg$/));
|
||||
// } catch (error) {
|
||||
// console.warn(error);
|
||||
// routeList = [];
|
||||
// }
|
||||
|
||||
const svgModules = import.meta.glob('@/assets/svg/**/*.svg', {
|
||||
eager: true,
|
||||
query: '?url',
|
||||
});
|
||||
|
||||
const routeList: { name: string; value: string }[] = Object.entries(
|
||||
svgModules,
|
||||
).map(([path, module]) => {
|
||||
const name = path.replace(/^.*\/assets\/svg\//, '').replace(/\.[^/.]+$/, '');
|
||||
// @ts-ignore
|
||||
return { name, value: module.default || module };
|
||||
});
|
||||
|
||||
interface IProps extends IconComponentProps {
|
||||
name: string;
|
||||
@ -32,23 +45,25 @@ interface IProps extends IconComponentProps {
|
||||
imgClass?: string;
|
||||
}
|
||||
|
||||
const SvgIcon = ({ name, width, height, imgClass, ...restProps }: IProps) => {
|
||||
const ListItem = routeList.find((item) => item.name === name);
|
||||
return (
|
||||
<Icon
|
||||
component={() => (
|
||||
<img
|
||||
src={ListItem?.value}
|
||||
alt=""
|
||||
width={width}
|
||||
height={height}
|
||||
className={cn(imgClass, 'max-w-full')}
|
||||
/>
|
||||
)}
|
||||
{...(restProps as any)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const SvgIcon = memo(
|
||||
({ name, width, height, imgClass, ...restProps }: IProps) => {
|
||||
const ListItem = routeList.find((item) => item.name === name);
|
||||
return (
|
||||
<Icon
|
||||
component={() => (
|
||||
<img
|
||||
src={ListItem?.value}
|
||||
alt=""
|
||||
width={width}
|
||||
height={height}
|
||||
className={cn(imgClass, 'max-w-full')}
|
||||
/>
|
||||
)}
|
||||
{...(restProps as any)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const LlmIcon = ({
|
||||
name,
|
||||
|
||||
@ -40,8 +40,10 @@ const segmentedVariants = {
|
||||
xl: 'px-6 py-2',
|
||||
},
|
||||
};
|
||||
export interface SegmentedProps
|
||||
extends Omit<React.HTMLProps<HTMLDivElement>, 'onChange'> {
|
||||
export interface SegmentedProps extends Omit<
|
||||
React.HTMLProps<HTMLDivElement>,
|
||||
'onChange'
|
||||
> {
|
||||
options: SegmentedOptions;
|
||||
defaultValue?: SegmentedValue;
|
||||
value?: SegmentedValue;
|
||||
|
||||
Reference in New Issue
Block a user