diff --git a/packages/api/typings/app.ts b/packages/api/typings/app.ts index 17dd7c69..c68921b1 100644 --- a/packages/api/typings/app.ts +++ b/packages/api/typings/app.ts @@ -4,7 +4,7 @@ import { BaseAdapter } from '../src/queueAdapters/base'; export type JobCleanStatus = 'completed' | 'wait' | 'active' | 'delayed' | 'failed'; -export type JobFinishedStatus = 'completed' | 'failed'; +export type JobRetryStatus = 'completed' | 'failed'; export type Status = keyof typeof STATUSES; @@ -15,6 +15,7 @@ export type JobCounts = Record; export interface QueueAdapterOptions { readOnlyMode: boolean; allowRetries: boolean; + allowCompletedRetries: boolean; prefix: string; description: string; } @@ -30,7 +31,7 @@ export interface QueueJob { remove(): Promise; - retry(state?: JobFinishedStatus): Promise; + retry(state?: JobRetryStatus): Promise; toJSON(): QueueJobJson; } diff --git a/packages/ui/src/components/App.tsx b/packages/ui/src/components/App.tsx index 8bb29607..60609330 100644 --- a/packages/ui/src/components/App.tsx +++ b/packages/ui/src/components/App.tsx @@ -33,7 +33,7 @@ export const App = () => { path="/queue/:name" render={() => ( diff --git a/packages/ui/src/components/JobCard/JobActions/JobActions.tsx b/packages/ui/src/components/JobCard/JobActions/JobActions.tsx index 5bf57edf..9056ced2 100644 --- a/packages/ui/src/components/JobCard/JobActions/JobActions.tsx +++ b/packages/ui/src/components/JobCard/JobActions/JobActions.tsx @@ -13,8 +13,7 @@ interface JobActionsProps { allowRetries: boolean; actions: { promoteJob: () => Promise; - retryFailedJob: () => Promise; - retryCompletedJob: () => Promise; + retryJob: () => Promise; cleanJob: () => Promise; }; } @@ -22,35 +21,32 @@ interface JobActionsProps { interface ButtonType { title: string; Icon: React.ElementType; - actionKey: 'promoteJob' | 'cleanJob' | 'retryFailedJob' | 'retryCompletedJob'; + actionKey: 'promoteJob' | 'cleanJob' | 'retryJob'; } const buttonTypes: Record = { promote: { title: 'Promote', Icon: PromoteIcon, actionKey: 'promoteJob' }, clean: { title: 'Clean', Icon: TrashIcon, actionKey: 'cleanJob' }, - retryFailed: { title: 'Retry', Icon: RetryIcon, actionKey: 'retryFailedJob' }, - retryCompleted: { title: 'Retry', Icon: RetryIcon, actionKey: 'retryCompletedJob' }, + retry: { title: 'Retry', Icon: RetryIcon, actionKey: 'retryJob' }, }; const statusToButtonsMap: Record = { - [STATUSES.failed]: [buttonTypes.retryFailed, buttonTypes.clean], + [STATUSES.failed]: [buttonTypes.retry, buttonTypes.clean], [STATUSES.delayed]: [buttonTypes.promote, buttonTypes.clean], - [STATUSES.completed]: [buttonTypes.retryCompleted, buttonTypes.clean], + [STATUSES.completed]: [buttonTypes.retry, buttonTypes.clean], [STATUSES.waiting]: [buttonTypes.clean], }; -function isRetry(actionKey: ButtonType['actionKey']) { - return ['retryFailedJob', 'retryCompletedJob'].includes(actionKey); -} - export const JobActions = ({ actions, status, allowRetries }: JobActionsProps) => { let buttons = statusToButtonsMap[status]; if (!buttons) { return null; } + if (!allowRetries) { - buttons = buttons.filter((btn) => !isRetry(btn.actionKey)); + buttons = buttons.filter((btn) => btn.actionKey !== 'retryJob'); } + return (
    {buttons.map((type) => ( diff --git a/packages/ui/src/components/JobCard/JobCard.tsx b/packages/ui/src/components/JobCard/JobCard.tsx index 524f9666..eefa73d6 100644 --- a/packages/ui/src/components/JobCard/JobCard.tsx +++ b/packages/ui/src/components/JobCard/JobCard.tsx @@ -14,8 +14,7 @@ interface JobCardProps { allowRetries: boolean; actions: { promoteJob: () => Promise; - retryFailedJob: () => Promise; - retryCompletedJob: () => Promise; + retryJob: () => Promise; cleanJob: () => Promise; getJobLogs: () => Promise; }; diff --git a/packages/ui/src/components/QueueActions/QueueActions.tsx b/packages/ui/src/components/QueueActions/QueueActions.tsx index 7abf58eb..8b8d27f0 100644 --- a/packages/ui/src/components/QueueActions/QueueActions.tsx +++ b/packages/ui/src/components/QueueActions/QueueActions.tsx @@ -43,7 +43,7 @@ export const QueueActions = ({ status, actions, queue, allowRetries }: QueueActi <> {allowRetries && (
  • - +
  • )}
  • @@ -60,7 +60,7 @@ export const QueueActions = ({ status, actions, queue, allowRetries }: QueueActi <> {allowRetries && (
  • - +
  • )}
  • diff --git a/packages/ui/src/components/QueuePage/QueuePage.tsx b/packages/ui/src/components/QueuePage/QueuePage.tsx index 2e509ecf..464f0abd 100644 --- a/packages/ui/src/components/QueuePage/QueuePage.tsx +++ b/packages/ui/src/components/QueuePage/QueuePage.tsx @@ -4,7 +4,7 @@ import { JobCard } from '../JobCard/JobCard'; import { QueueActions } from '../QueueActions/QueueActions'; import { StatusMenu } from '../StatusMenu/StatusMenu'; import s from './QueuePage.module.css'; -import { AppQueue } from '@bull-board/api/typings/app'; +import { AppQueue, JobRetryStatus } from '@bull-board/api/typings/app'; import { Pagination } from '../Pagination/Pagination'; export const QueuePage = ({ @@ -12,7 +12,7 @@ export const QueuePage = ({ actions, queue, }: { - queue: AppQueue | undefined; + queue: AppQueue | null; actions: Store['actions']; selectedStatus: Store['selectedStatuses']; }) => { @@ -20,6 +20,8 @@ export const QueuePage = ({ return
    Queue Not found
    ; } + const status = selectedStatus[queue.name]; + return (
    @@ -31,7 +33,10 @@ export const QueuePage = ({ queue={queue} actions={actions} status={selectedStatus[queue.name]} - allowRetries={(selectedStatus[queue.name] == 'failed' || queue.allowCompletedRetries) && queue.allowRetries} + allowRetries={ + (selectedStatus[queue.name] == 'failed' || queue.allowCompletedRetries) && + queue.allowRetries + } /> )}
    @@ -42,12 +47,11 @@ export const QueuePage = ({ ; } export const QueueTitle = ({ queue }: QueueTitleProps) => (
    diff --git a/packages/ui/src/hooks/useStore.ts b/packages/ui/src/hooks/useStore.ts index c5181b08..ae160386 100644 --- a/packages/ui/src/hooks/useStore.ts +++ b/packages/ui/src/hooks/useStore.ts @@ -1,4 +1,4 @@ -import { AppJob, JobFinishedStatus } from '@bull-board/api/typings/app'; +import { AppJob, JobRetryStatus } from '@bull-board/api/typings/app'; import { GetQueuesResponse } from '@bull-board/api/typings/responses'; import { useState } from 'react'; import { QueueActions, SelectedStatuses } from '../../typings/app'; @@ -88,7 +88,7 @@ export const useStore = (): Store => { confirmJobActions ); - const retryJob = (queueName: string) => (job: AppJob, status: JobFinishedStatus) => + const retryJob = (queueName: string, status: JobRetryStatus) => (job: AppJob) => withConfirmAndUpdate( () => api.retryJob(queueName, job.id, status), 'Are you sure that you want to retry this job?', @@ -102,7 +102,7 @@ export const useStore = (): Store => { confirmJobActions ); - const retryAll = (queueName: string, status: JobFinishedStatus) => + const retryAll = (queueName: string, status: JobRetryStatus) => withConfirmAndUpdate( () => api.retryAll(queueName, status), `Are you sure that you want to retry all ${status} jobs?`, @@ -150,7 +150,7 @@ export const useStore = (): Store => { 'Are you sure that you want to empty the queue?', confirmQueueActions ); - + const getJobLogs = (queueName: string) => (job: AppJob) => () => api.getJobLogs(queueName, job.id); diff --git a/packages/ui/src/services/Api.ts b/packages/ui/src/services/Api.ts index af15861a..2b2aa260 100644 --- a/packages/ui/src/services/Api.ts +++ b/packages/ui/src/services/Api.ts @@ -1,4 +1,4 @@ -import { AppJob, JobFinishedStatus, RedisStats, Status } from '@bull-board/api/typings/app'; +import { AppJob, JobRetryStatus, RedisStats, Status } from '@bull-board/api/typings/app'; import { GetQueuesResponse } from '@bull-board/api/typings/responses'; import Axios, { AxiosInstance, AxiosResponse } from 'axios'; import { toast } from 'react-toastify'; @@ -25,8 +25,10 @@ export class Api { return this.axios.get(`/queues`, { params: { activeQueue, status, page, jobsPerPage } }); } - public retryAll(queueName: string, status: JobFinishedStatus): Promise { - return this.axios.put(`/queues/${encodeURIComponent(queueName)}/retry/${encodeURIComponent(status)}`); + public retryAll(queueName: string, status: JobRetryStatus): Promise { + return this.axios.put( + `/queues/${encodeURIComponent(queueName)}/retry/${encodeURIComponent(status)}` + ); } public cleanAllDelayed(queueName: string): Promise { @@ -47,9 +49,11 @@ export class Api { ); } - public retryJob(queueName: string, jobId: AppJob['id'], status: JobFinishedStatus): Promise { + public retryJob(queueName: string, jobId: AppJob['id'], status: JobRetryStatus): Promise { return this.axios.put( - `/queues/${encodeURIComponent(queueName)}/${encodeURIComponent(`${jobId}`)}/retry/${encodeURIComponent(status)}`, + `/queues/${encodeURIComponent(queueName)}/${encodeURIComponent( + `${jobId}` + )}/retry/${encodeURIComponent(status)}` ); } diff --git a/packages/ui/typings/app.d.ts b/packages/ui/typings/app.d.ts index 4c73523f..a652cd5b 100644 --- a/packages/ui/typings/app.d.ts +++ b/packages/ui/typings/app.d.ts @@ -1,4 +1,4 @@ -import { AppJob, AppQueue, JobFinishedStatus, Status } from '@bull-board/api/typings/app'; +import { AppJob, AppQueue, JobRetryStatus, Status } from '@bull-board/api/typings/app'; export { Status } from '@bull-board/api/typings/app'; @@ -6,10 +6,10 @@ export type SelectedStatuses = Record; export interface QueueActions { promoteJob: (queueName: string) => (job: AppJob) => () => Promise; - retryJob: (queueName: string) => (job: AppJob, status: JobFinishedStatus) => () => Promise; + retryJob: (queueName: string, status: JobRetryStatus) => (job: AppJob) => () => Promise; cleanJob: (queueName: string) => (job: AppJob) => () => Promise; getJobLogs: (queueName: string) => (job: AppJob) => () => Promise; - retryAll: (queueName: string, status: JobFinishedStatus) => () => Promise; + retryAll: (queueName: string, status: JobRetryStatus) => () => Promise; cleanAllDelayed: (queueName: string) => () => Promise; cleanAllFailed: (queueName: string) => () => Promise; cleanAllCompleted: (queueName: string) => () => Promise;