/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import {
createStyles,
Icon,
useAPIClient,
useApp,
usePlugin,
useRequest,
useCollectionManager,
useCompile,
} from '@nocobase/client';
import { Button, Empty, Modal, Popconfirm, Popover, Progress, Space, Table, Tag, Tooltip } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import { useCurrentAppInfo } from '@nocobase/client';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import relativeTime from 'dayjs/plugin/relativeTime';
import { useT } from '../locale';
const useStyles = createStyles(({ token }) => {
return {
button: {
// @ts-ignore
color: token.colorTextHeaderMenu + ' !important',
},
};
});
// Configure dayjs
dayjs.extend(relativeTime);
const renderTaskResult = (status, t) => {
if (status.type !== 'success' || !status.payload?.message?.messageId) {
return null;
}
const { messageId, messageValues } = status.payload.message;
return (
{t(messageId, messageValues)}
);
};
const useAsyncTask = () => {
const { data, refreshAsync, loading } = useRequest({
url: 'asyncTasks:list',
});
return { loading, tasks: data?.data || [], refresh: refreshAsync };
};
const AsyncTasksButton = (props) => {
const { popoverVisible, setPopoverVisible, tasks, refresh, loading, hasProcessingTasks } = props;
const app = useApp();
const api = useAPIClient();
const appInfo = useCurrentAppInfo();
const t = useT();
const { styles } = useStyles();
const plugin = usePlugin('async-task-manager');
const cm = useCollectionManager();
const compile = useCompile();
const showTaskResult = (task) => {
setPopoverVisible(false);
};
const columns = [
{
title: t('Created at'),
dataIndex: 'createdAt',
key: 'createdAt',
width: 180,
render: (createdAt: string) => (
{dayjs(createdAt).fromNow()}
),
},
{
title: t('Task'),
dataIndex: 'title',
key: 'title',
render: (_, record: any) => {
const title = record.title;
if (!title) {
return '-';
}
const collection = cm.getCollection(title.collection);
const actionTypeMap = {
export: t('Export'),
import: t('Import'),
'export-attachments': t('Export attachments'),
};
const actionText = actionTypeMap[title.actionType] || title.actionType;
const taskTypeMap = {
'export-attachments': t('Export {collection} attachments'),
export: t('Export {collection} data'),
import: t('Import {collection} data'),
};
const taskTemplate = taskTypeMap[title.actionType] || `${actionText}`;
return taskTemplate.replace('{collection}', compile(collection?.title || title.collection));
},
},
{
title: t('Status'),
dataIndex: 'status',
key: 'status',
width: 160,
render: (status: any, record: any) => {
const statusMap = {
pending: {
color: 'default',
text: t('Waiting'),
icon: 'ClockCircleOutlined',
},
running: {
color: 'processing',
text: t('Processing'),
icon: 'LoadingOutlined',
},
success: {
color: 'success',
text: t('Completed'),
icon: 'CheckCircleOutlined',
},
failed: {
color: 'error',
text: t('Failed'),
icon: 'CloseCircleOutlined',
},
cancelled: {
color: 'warning',
text: t('Cancelled'),
icon: 'StopOutlined',
},
};
const { color, text } = statusMap[status.type] || {};
const renderProgress = () => {
const commonStyle = {
width: 100,
margin: 0,
};
switch (status.indicator) {
case 'spinner':
return (
);
case 'progress':
return (