mirror of https://gitee.com/answerdev/answer.git
feat(SchemaForm): Optimising the action feedback of the Button component
This commit is contained in:
parent
9f2607cf35
commit
c843dddf0b
|
@ -1,9 +1,10 @@
|
|||
import React, { FC, useState } from 'react';
|
||||
import { Button, ButtonProps } from 'react-bootstrap';
|
||||
import React, { FC, useLayoutEffect, useState } from 'react';
|
||||
import { Button, ButtonProps, Spinner } from 'react-bootstrap';
|
||||
|
||||
import { request } from '@/utils';
|
||||
import type * as Type from '@/common/interface';
|
||||
import type { UIAction } from '../index.d';
|
||||
import type { UIAction } from '../types';
|
||||
import { useToast } from '@/hooks';
|
||||
|
||||
interface Props {
|
||||
fieldName: string;
|
||||
|
@ -24,17 +25,51 @@ const Index: FC<Props> = ({
|
|||
variant = 'primary',
|
||||
size,
|
||||
}) => {
|
||||
const Toast = useToast();
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const handleAction = async () => {
|
||||
const handleNotify = (msg, type: 'success' | 'danger' = 'success') => {
|
||||
const tm = action?.toastMessage;
|
||||
if (tm === false || !msg) {
|
||||
return;
|
||||
}
|
||||
Toast.onShow({
|
||||
msg,
|
||||
variant: type,
|
||||
});
|
||||
};
|
||||
const handleAction = () => {
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
const method = action.method || 'get';
|
||||
await request[method](action.url);
|
||||
setLoading(false);
|
||||
request
|
||||
.request({
|
||||
method: action.method,
|
||||
url: action.url,
|
||||
timeout: 0,
|
||||
})
|
||||
.then((resp) => {
|
||||
if ('message' in resp) {
|
||||
handleNotify(resp.message, 'success');
|
||||
}
|
||||
})
|
||||
.catch((ex) => {
|
||||
if (ex && 'msg' in ex) {
|
||||
handleNotify(ex.msg, 'danger');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
useLayoutEffect(() => {
|
||||
if (action?.loading?.state === 'pending') {
|
||||
setLoading(true);
|
||||
}
|
||||
}, []);
|
||||
const loadingText = action?.loading?.text || text;
|
||||
const disabled = isLoading || readOnly;
|
||||
|
||||
return (
|
||||
<div className="d-flex">
|
||||
<Button
|
||||
|
@ -43,8 +78,19 @@ const Index: FC<Props> = ({
|
|||
disabled={disabled}
|
||||
size={size}
|
||||
variant={variant}>
|
||||
{text || fieldName}
|
||||
{isLoading ? '...' : ''}
|
||||
{isLoading ? (
|
||||
<>
|
||||
<Spinner
|
||||
className="align-middle me-2"
|
||||
animation="border"
|
||||
size="sm"
|
||||
variant={variant}
|
||||
/>
|
||||
{loadingText}
|
||||
</>
|
||||
) : (
|
||||
text
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
export interface UIAction {
|
||||
url: string;
|
||||
method?: 'get' | 'post' | 'put' | 'delete';
|
||||
event?: 'click' | 'change';
|
||||
handler?: ({evt, formData, request}) => Promise<void>
|
||||
}
|
|
@ -11,7 +11,7 @@ import classnames from 'classnames';
|
|||
|
||||
import type * as Type from '@/common/interface';
|
||||
|
||||
import type { UIAction } from './index.d';
|
||||
import type { UIAction } from './types';
|
||||
import {
|
||||
Legend,
|
||||
Select,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* A few notes on button control:
|
||||
* - Mainly used to send a request and notify the result of the request, and to update the data as required
|
||||
* - A scenario where a message notification is displayed directly after a click without sending a request, implementing a dedicated control
|
||||
* - Scenarios where the page jumps directly after a click without sending a request, implementing a dedicated control
|
||||
*
|
||||
* @field url : Target address for sending requests
|
||||
* @field method : Method for sending requests, default `get`
|
||||
* @field callback: Button event handler function that will fully take over the button events when this field is configured
|
||||
* *** Incomplete, DO NOT USE ***
|
||||
* @field loading: Set button loading information
|
||||
* @field notify: Configure how button action processing results are prompted
|
||||
*/
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* - Refining the type of `notify.options`
|
||||
*/
|
||||
export interface UIAction {
|
||||
url: string;
|
||||
method?: 'get' | 'post' | 'put' | 'delete';
|
||||
callback?: () => Promise<void>;
|
||||
loading?: {
|
||||
text: string;
|
||||
state?: 'none' | 'pending' | 'completed';
|
||||
}
|
||||
toastMessage?: boolean;
|
||||
}
|
Loading…
Reference in New Issue