blob: 56207fb129213ed7607002604dd2a2428774f316 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { FC, useEffect, useState } from 'react';
import { Button, ButtonProps, Spinner } from 'react-bootstrap';
import { request } from '@/utils';
import type { UIAction, FormKit } from '../types';
import { useToast } from '@/hooks';
import { Icon } from '@/components';
interface Props {
fieldName: string;
text: string;
action: UIAction | undefined;
actionType?: 'submit' | 'click';
clickCallback?: () => void;
formKit: FormKit;
readOnly: boolean;
variant?: ButtonProps['variant'];
size?: ButtonProps['size'];
iconName?: string;
nowrap?: boolean;
title?: string;
}
const Index: FC<Props> = ({
fieldName,
action,
actionType = 'submit',
formKit,
text = '',
readOnly = false,
variant = 'primary',
size,
iconName = '',
nowrap = false,
clickCallback,
title,
}) => {
const Toast = useToast();
const [isLoading, setLoading] = useState(false);
const handleToast = (msg, type: 'success' | 'danger' = 'success') => {
const tm = action?.on_complete?.toast_return_message;
if (tm === false || !msg) {
return;
}
Toast.onShow({
msg,
variant: type,
});
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleCallback = (resp) => {
const callback = action?.on_complete;
if (callback?.refresh_form_config) {
formKit.refreshConfig();
}
};
const handleAction = () => {
if (actionType === 'click') {
if (typeof clickCallback === 'function') {
clickCallback();
}
return;
}
if (!action) {
return;
}
setLoading(true);
request
.request({
method: action.method,
url: action.url,
timeout: 0,
})
.then((resp) => {
if ('message' in resp) {
handleToast(resp.message, 'success');
}
handleCallback(resp);
})
.catch((ex) => {
if (ex && 'msg' in ex) {
handleToast(ex.msg, 'danger');
}
})
.finally(() => {
setLoading(false);
});
};
useEffect(() => {
if (action?.loading?.state === 'pending') {
setLoading(true);
}
}, []);
const loadingText = action?.loading?.text || text;
const disabled = isLoading || readOnly;
if (nowrap) {
return (
<Button
name={fieldName}
onClick={handleAction}
disabled={disabled}
size={size}
title={title}
variant={variant}>
{isLoading ? (
<>
<Spinner
className="align-middle me-2"
animation="border"
size="sm"
variant={variant}
/>
{loadingText}
</>
) : (
text
)}
{iconName && <Icon name={iconName} />}
</Button>
);
}
return (
<div className="d-flex">
<Button
name={fieldName}
onClick={handleAction}
disabled={disabled}
size={size}
title={title}
variant={variant}>
{isLoading ? (
<>
<Spinner
className="align-middle me-2"
animation="border"
size="sm"
variant={variant}
/>
{loadingText}
</>
) : (
text
)}
{iconName && <Icon name={iconName} />}
</Button>
</div>
);
};
export default Index;