### What problem does this PR solve? Feat: Replace the submit form button with ButtonLoading #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.0
| @@ -43,8 +43,8 @@ import { | |||
| import RaptorFormFields, { | |||
| showRaptorParseConfiguration, | |||
| } from '../parse-configuration/raptor-form-fields'; | |||
| import { ButtonLoading } from '../ui/button'; | |||
| import { Input } from '../ui/input'; | |||
| import { LoadingButton } from '../ui/loading-button'; | |||
| import { RAGFlowSelect } from '../ui/select'; | |||
| import { DynamicPageRange } from './dynamic-page-range'; | |||
| import { useFetchParserListOnMount, useShowAutoKeywords } from './hooks'; | |||
| @@ -324,9 +324,9 @@ export function ChunkMethodDialog({ | |||
| </form> | |||
| </Form> | |||
| <DialogFooter> | |||
| <LoadingButton type="submit" form={FormId} loading={loading}> | |||
| <ButtonLoading type="submit" form={FormId} loading={loading}> | |||
| {t('common.save')} | |||
| </LoadingButton> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||
| @@ -1,4 +1,4 @@ | |||
| import { Button } from '@/components/ui/button'; | |||
| import { ButtonLoading } from '@/components/ui/button'; | |||
| import { | |||
| Dialog, | |||
| DialogContent, | |||
| @@ -38,7 +38,11 @@ export function UploaderTabs({ setFiles }: UploaderTabsProps) { | |||
| ); | |||
| } | |||
| export function FileUploadDialog({ hideModal, onOk }: IModalProps<File[]>) { | |||
| export function FileUploadDialog({ | |||
| hideModal, | |||
| onOk, | |||
| loading, | |||
| }: IModalProps<File[]>) { | |||
| const { t } = useTranslation(); | |||
| const [files, setFiles] = useState<File[]>([]); | |||
| @@ -54,14 +58,9 @@ export function FileUploadDialog({ hideModal, onOk }: IModalProps<File[]>) { | |||
| </DialogHeader> | |||
| <UploaderTabs setFiles={setFiles}></UploaderTabs> | |||
| <DialogFooter> | |||
| <Button | |||
| type="submit" | |||
| variant={'tertiary'} | |||
| size={'sm'} | |||
| onClick={handleOk} | |||
| > | |||
| <ButtonLoading type="submit" onClick={handleOk} loading={loading}> | |||
| {t('common.save')} | |||
| </Button> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||
| @@ -5,11 +5,11 @@ import { | |||
| DialogHeader, | |||
| DialogTitle, | |||
| } from '@/components/ui/dialog'; | |||
| import { LoadingButton } from '@/components/ui/loading-button'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| import { TagRenameId } from '@/pages/add-knowledge/constant'; | |||
| import { ReactNode } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { ButtonLoading } from '../ui/button'; | |||
| import { RenameForm } from './rename-form'; | |||
| export function RenameDialog({ | |||
| @@ -33,9 +33,9 @@ export function RenameDialog({ | |||
| onOk={onOk} | |||
| ></RenameForm> | |||
| <DialogFooter> | |||
| <LoadingButton type="submit" form={TagRenameId} loading={loading}> | |||
| <ButtonLoading type="submit" form={TagRenameId} loading={loading}> | |||
| {t('common.save')} | |||
| </LoadingButton> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||
| @@ -3,6 +3,7 @@ import { cva, type VariantProps } from 'class-variance-authority'; | |||
| import * as React from 'react'; | |||
| import { cn } from '@/lib/utils'; | |||
| import { Loader2 } from 'lucide-react'; | |||
| const buttonVariants = cva( | |||
| 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | |||
| @@ -57,4 +58,38 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | |||
| ); | |||
| Button.displayName = 'Button'; | |||
| export const ButtonLoading = React.forwardRef< | |||
| HTMLButtonElement, | |||
| ButtonProps & { loading?: boolean } | |||
| >( | |||
| ( | |||
| { | |||
| className, | |||
| variant, | |||
| size, | |||
| asChild = false, | |||
| children, | |||
| loading = false, | |||
| disabled, | |||
| ...props | |||
| }, | |||
| ref, | |||
| ) => { | |||
| const Comp = asChild ? Slot : 'button'; | |||
| return ( | |||
| <Comp | |||
| className={cn(buttonVariants({ variant, size, className }))} | |||
| ref={ref} | |||
| {...props} | |||
| disabled={loading || disabled} | |||
| > | |||
| {loading && <Loader2 className="animate-spin" />} | |||
| {children} | |||
| </Comp> | |||
| ); | |||
| }, | |||
| ); | |||
| ButtonLoading.displayName = 'ButtonLoading'; | |||
| export { Button, buttonVariants }; | |||
| @@ -5,7 +5,6 @@ import { | |||
| DialogHeader, | |||
| DialogTitle, | |||
| } from '@/components/ui/dialog'; | |||
| import { LoadingButton } from '@/components/ui/loading-button'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| import { TagRenameId } from '@/pages/add-knowledge/constant'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| @@ -14,6 +13,7 @@ import { zodResolver } from '@hookform/resolvers/zod'; | |||
| import { useForm } from 'react-hook-form'; | |||
| import { z } from 'zod'; | |||
| import { ButtonLoading } from '@/components/ui/button'; | |||
| import { | |||
| Form, | |||
| FormControl, | |||
| @@ -118,9 +118,9 @@ export function SetMetaDialog({ | |||
| </form> | |||
| </Form> | |||
| <DialogFooter> | |||
| <LoadingButton type="submit" form={TagRenameId} loading={loading}> | |||
| <ButtonLoading type="submit" form={TagRenameId} loading={loading}> | |||
| {t('common.save')} | |||
| </LoadingButton> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||
| @@ -1,3 +1,4 @@ | |||
| import { ButtonLoading } from '@/components/ui/button'; | |||
| import { | |||
| Dialog, | |||
| DialogContent, | |||
| @@ -13,7 +14,6 @@ import { | |||
| FormLabel, | |||
| FormMessage, | |||
| } from '@/components/ui/form'; | |||
| import { LoadingButton } from '@/components/ui/loading-button'; | |||
| import { MultiSelect } from '@/components/ui/multi-select'; | |||
| import { useSelectKnowledgeOptions } from '@/hooks/knowledge-hooks'; | |||
| import { IModalProps } from '@/interfaces/common'; | |||
| @@ -113,16 +113,11 @@ export function LinkToDatasetDialog({ | |||
| onConnectToKnowledgeOk={onConnectToKnowledgeOk} | |||
| ></LinkToDatasetForm> | |||
| <DialogFooter> | |||
| <LoadingButton | |||
| type="submit" | |||
| variant={'tertiary'} | |||
| form={FormId} | |||
| loading={loading} | |||
| > | |||
| <ButtonLoading type="submit" form={FormId} loading={loading}> | |||
| <div className="flex gap-2 items-center"> | |||
| <Link2 /> Save | |||
| </div> | |||
| </LoadingButton> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||
| @@ -2,7 +2,7 @@ import { | |||
| AsyncTreeSelect, | |||
| TreeNodeType, | |||
| } from '@/components/ui/async-tree-select'; | |||
| import { Button } from '@/components/ui/button'; | |||
| import { ButtonLoading } from '@/components/ui/button'; | |||
| import { | |||
| Dialog, | |||
| DialogContent, | |||
| @@ -17,7 +17,7 @@ import { isEmpty } from 'lodash'; | |||
| import { useCallback, useState } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| export function MoveDialog({ hideModal, onOk }: IModalProps<any>) { | |||
| export function MoveDialog({ hideModal, onOk, loading }: IModalProps<any>) { | |||
| const { t } = useTranslation(); | |||
| const { fetchList } = useFetchPureFileList(); | |||
| @@ -69,13 +69,14 @@ export function MoveDialog({ hideModal, onOk }: IModalProps<any>) { | |||
| ></AsyncTreeSelect> | |||
| </div> | |||
| <DialogFooter> | |||
| <Button | |||
| <ButtonLoading | |||
| type="submit" | |||
| onClick={handleSubmit} | |||
| disabled={isEmpty(treeValue)} | |||
| loading={loading} | |||
| > | |||
| {t('common.save')} | |||
| </Button> | |||
| </ButtonLoading> | |||
| </DialogFooter> | |||
| </DialogContent> | |||
| </Dialog> | |||