@@ -0,0 +1,79 @@
|
||||
import {ColumnConfig} from '@common/datatable/column-config';
|
||||
import {Trans} from '@common/i18n/trans';
|
||||
import {NameWithAvatar} from '@common/datatable/column-templates/name-with-avatar';
|
||||
import {BooleanIndicator} from '@common/datatable/column-templates/boolean-indicator';
|
||||
import {FormattedNumber} from '@common/i18n/formatted-number';
|
||||
import {Tooltip} from '@common/ui/tooltip/tooltip';
|
||||
import {IconButton} from '@common/ui/buttons/icon-button';
|
||||
import React from 'react';
|
||||
import {ScheduleLogItem} from '@common/admin/logging/schedule/schedule-log-item';
|
||||
import {useRerunScheduledCommand} from '@common/admin/logging/schedule/use-rerurun-scheduled-command';
|
||||
import {EventRepeatIcon} from '@common/icons/material/EventRepeat';
|
||||
import {FormattedRelativeTime} from '@common/i18n/formatted-relative-time';
|
||||
|
||||
export const ScheduleDatatableColumns: ColumnConfig<ScheduleLogItem>[] = [
|
||||
{
|
||||
key: 'command',
|
||||
allowsSorting: true,
|
||||
visibleInMode: 'all',
|
||||
width: 'flex-3 min-w-200',
|
||||
header: () => <Trans message="Name" />,
|
||||
body: item => (
|
||||
<NameWithAvatar label={item.command} description={item.output} />
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'ran_at',
|
||||
allowsSorting: true,
|
||||
header: () => <Trans message="Ran at" />,
|
||||
body: item => <FormattedRelativeTime date={item.ran_at} />,
|
||||
},
|
||||
{
|
||||
key: 'duration',
|
||||
allowsSorting: true,
|
||||
header: () => <Trans message="Duration" />,
|
||||
body: item => `${item.duration}ms`,
|
||||
},
|
||||
{
|
||||
key: 'exit_code',
|
||||
allowsSorting: true,
|
||||
header: () => <Trans message="Completed" />,
|
||||
body: item => <BooleanIndicator value={item.exit_code === 0} />,
|
||||
},
|
||||
{
|
||||
key: 'count_in_last_hour',
|
||||
allowsSorting: true,
|
||||
header: () => <Trans message="Runs recently" />,
|
||||
body: item => <FormattedNumber value={item.count_in_last_hour} />,
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
header: () => <Trans message="Actions" />,
|
||||
hideHeader: true,
|
||||
align: 'end',
|
||||
width: 'w-42 flex-shrink-0',
|
||||
visibleInMode: 'all',
|
||||
body: item => <RerunButton item={item} />,
|
||||
},
|
||||
];
|
||||
|
||||
interface RerunButtonProps {
|
||||
item: ScheduleLogItem;
|
||||
}
|
||||
function RerunButton({item}: RerunButtonProps) {
|
||||
const rerunCommand = useRerunScheduledCommand();
|
||||
return (
|
||||
<Tooltip label={<Trans message="Rerun now" />}>
|
||||
<IconButton
|
||||
size="md"
|
||||
className="text-muted"
|
||||
disabled={rerunCommand.isPending}
|
||||
onClick={() => {
|
||||
rerunCommand.mutate({id: item.id});
|
||||
}}
|
||||
>
|
||||
<EventRepeatIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
41
common/resources/client/admin/logging/schedule/schedule-log-datatable.tsx
Executable file
41
common/resources/client/admin/logging/schedule/schedule-log-datatable.tsx
Executable file
@@ -0,0 +1,41 @@
|
||||
import {DataTablePage} from '@common/datatable/page/data-table-page';
|
||||
import {Trans} from '@common/i18n/trans';
|
||||
import {DataTableEmptyStateMessage} from '@common/datatable/page/data-table-emty-state-message';
|
||||
import React from 'react';
|
||||
import {ScheduleDatatableColumns} from '@common/admin/logging/schedule/schedule-datatable-columns';
|
||||
import timelineImage from '@common/admin/logging/schedule/timeline.svg';
|
||||
import {DataTableAddItemButton} from '@common/datatable/data-table-add-item-button';
|
||||
import {DownloadIcon} from '@common/icons/material/Download';
|
||||
|
||||
export function ScheduleLogDatatable() {
|
||||
return (
|
||||
<DataTablePage
|
||||
padding="pt-12 md:pt-24"
|
||||
endpoint="logs/schedule"
|
||||
title={<Trans message="CRON schedule log" />}
|
||||
columns={ScheduleDatatableColumns}
|
||||
actions={<Actions />}
|
||||
enableSelection={false}
|
||||
emptyStateMessage={
|
||||
<DataTableEmptyStateMessage
|
||||
image={timelineImage}
|
||||
title={<Trans message="No scheduled commands have ran yet" />}
|
||||
filteringTitle={<Trans message="No matching scheduled commands" />}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function Actions() {
|
||||
return (
|
||||
<DataTableAddItemButton
|
||||
elementType="a"
|
||||
href="api/v1/logs/schedule/download"
|
||||
download
|
||||
icon={<DownloadIcon />}
|
||||
>
|
||||
<Trans message="Download log" />
|
||||
</DataTableAddItemButton>
|
||||
);
|
||||
}
|
||||
9
common/resources/client/admin/logging/schedule/schedule-log-item.tsx
Executable file
9
common/resources/client/admin/logging/schedule/schedule-log-item.tsx
Executable file
@@ -0,0 +1,9 @@
|
||||
export interface ScheduleLogItem {
|
||||
id: number;
|
||||
command: string;
|
||||
output: string;
|
||||
ran_at: string;
|
||||
duration: number;
|
||||
count_in_last_hour: number;
|
||||
exit_code: number;
|
||||
}
|
||||
1
common/resources/client/admin/logging/schedule/timeline.svg
Executable file
1
common/resources/client/admin/logging/schedule/timeline.svg
Executable file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,32 @@
|
||||
import {useMutation} from '@tanstack/react-query';
|
||||
import {apiClient, queryClient} from '@common/http/query-client';
|
||||
import {useTrans} from '@common/i18n/use-trans';
|
||||
import {BackendResponse} from '@common/http/backend-response/backend-response';
|
||||
import {showHttpErrorToast} from '@common/utils/http/show-http-error-toast';
|
||||
import {message} from '@common/i18n/message';
|
||||
import {toast} from '@common/ui/toast/toast';
|
||||
import {DatatableDataQueryKey} from '@common/datatable/requests/paginated-resources';
|
||||
|
||||
interface Response extends BackendResponse {}
|
||||
|
||||
interface Payload {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export function useRerunScheduledCommand() {
|
||||
const {trans} = useTrans();
|
||||
return useMutation({
|
||||
mutationFn: (payload: Payload) => rerunCommand(payload),
|
||||
onSuccess: async (response, props) => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: DatatableDataQueryKey('logs/schedule'),
|
||||
});
|
||||
toast.positive(trans(message('Command reran')));
|
||||
},
|
||||
onError: err => showHttpErrorToast(err),
|
||||
});
|
||||
}
|
||||
|
||||
function rerunCommand({id}: Payload): Promise<Response> {
|
||||
return apiClient.post(`logs/schedule/rerun/${id}`).then(r => r.data);
|
||||
}
|
||||
Reference in New Issue
Block a user