(ui): Add actions and reducer for deleting completed tasks

This commit is contained in:
Ken Hibino
2021-10-18 07:40:48 -07:00
parent f65986db43
commit 4110955aab
6 changed files with 460 additions and 45 deletions

View File

@@ -4,6 +4,7 @@ import {
batchDeleteArchivedTasks, batchDeleteArchivedTasks,
batchDeleteRetryTasks, batchDeleteRetryTasks,
batchDeleteScheduledTasks, batchDeleteScheduledTasks,
batchDeleteCompletedTasks,
BatchDeleteTasksResponse, BatchDeleteTasksResponse,
batchArchiveRetryTasks, batchArchiveRetryTasks,
batchArchiveScheduledTasks, batchArchiveScheduledTasks,
@@ -17,9 +18,11 @@ import {
deleteAllArchivedTasks, deleteAllArchivedTasks,
deleteAllRetryTasks, deleteAllRetryTasks,
deleteAllScheduledTasks, deleteAllScheduledTasks,
deleteAllCompletedTasks,
deleteArchivedTask, deleteArchivedTask,
deleteRetryTask, deleteRetryTask,
deleteScheduledTask, deleteScheduledTask,
deleteCompletedTask,
archiveAllRetryTasks, archiveAllRetryTasks,
archiveAllScheduledTasks, archiveAllScheduledTasks,
archiveRetryTask, archiveRetryTask,
@@ -218,6 +221,21 @@ export const DELETE_ALL_ARCHIVED_TASKS_SUCCESS =
"DELETE_ALL_ARCHIVED_TASKS_SUCCESS"; "DELETE_ALL_ARCHIVED_TASKS_SUCCESS";
export const DELETE_ALL_ARCHIVED_TASKS_ERROR = export const DELETE_ALL_ARCHIVED_TASKS_ERROR =
"DELETE_ALL_ARCHIVED_TASKS_ERROR"; "DELETE_ALL_ARCHIVED_TASKS_ERROR";
export const DELETE_COMPLETED_TASK_BEGIN = "DELETE_COMPLETED_TASK_BEGIN";
export const DELETE_COMPLETED_TASK_SUCCESS = "DELETE_COMPLETED_TASK_SUCCESS";
export const DELETE_COMPLETED_TASK_ERROR = "DELETE_COMPLETED_TASK_ERROR";
export const DELETE_ALL_COMPLETED_TASKS_BEGIN =
"DELETE_ALL_COMPLETED_TASKS_BEGIN";
export const DELETE_ALL_COMPLETED_TASKS_SUCCESS =
"DELETE_ALL_COMPLETED_TASKS_SUCCESS";
export const DELETE_ALL_COMPLETED_TASKS_ERROR =
"DELETE_ALL_COMPLETED_TASKS_ERROR";
export const BATCH_DELETE_COMPLETED_TASKS_BEGIN =
"BATCH_DELETE_COMPLETED_TASKS_BEGIN";
export const BATCH_DELETE_COMPLETED_TASKS_SUCCESS =
"BATCH_DELETE_COMPLETED_TASKS_SUCCESS";
export const BATCH_DELETE_COMPLETED_TASKS_ERROR =
"BATCH_DELETE_COMPLETED_TASKS_ERROR";
interface GetTaskInfoBeginAction { interface GetTaskInfoBeginAction {
type: typeof GET_TASK_INFO_BEGIN; type: typeof GET_TASK_INFO_BEGIN;
@@ -933,6 +951,61 @@ interface DeleteAllArchivedTasksErrorAction {
error: string; error: string;
} }
interface DeleteCompletedTaskBeginAction {
type: typeof DELETE_COMPLETED_TASK_BEGIN;
queue: string;
taskId: string;
}
interface DeleteCompletedTaskSuccessAction {
type: typeof DELETE_COMPLETED_TASK_SUCCESS;
queue: string;
taskId: string;
}
interface DeleteCompletedTaskErrorAction {
type: typeof DELETE_COMPLETED_TASK_ERROR;
queue: string;
taskId: string;
error: string;
}
interface BatchDeleteCompletedTasksBeginAction {
type: typeof BATCH_DELETE_COMPLETED_TASKS_BEGIN;
queue: string;
taskIds: string[];
}
interface BatchDeleteCompletedTasksSuccessAction {
type: typeof BATCH_DELETE_COMPLETED_TASKS_SUCCESS;
queue: string;
payload: BatchDeleteTasksResponse;
}
interface BatchDeleteCompletedTasksErrorAction {
type: typeof BATCH_DELETE_COMPLETED_TASKS_ERROR;
queue: string;
taskIds: string[];
error: string;
}
interface DeleteAllCompletedTasksBeginAction {
type: typeof DELETE_ALL_COMPLETED_TASKS_BEGIN;
queue: string;
}
interface DeleteAllCompletedTasksSuccessAction {
type: typeof DELETE_ALL_COMPLETED_TASKS_SUCCESS;
queue: string;
deleted: number;
}
interface DeleteAllCompletedTasksErrorAction {
type: typeof DELETE_ALL_COMPLETED_TASKS_ERROR;
queue: string;
error: string;
}
// Union of all tasks related action types. // Union of all tasks related action types.
export type TasksActionTypes = export type TasksActionTypes =
| GetTaskInfoBeginAction | GetTaskInfoBeginAction
@@ -1054,7 +1127,16 @@ export type TasksActionTypes =
| RunAllArchivedTasksErrorAction | RunAllArchivedTasksErrorAction
| DeleteAllArchivedTasksBeginAction | DeleteAllArchivedTasksBeginAction
| DeleteAllArchivedTasksSuccessAction | DeleteAllArchivedTasksSuccessAction
| DeleteAllArchivedTasksErrorAction; | DeleteAllArchivedTasksErrorAction
| DeleteCompletedTaskBeginAction
| DeleteCompletedTaskSuccessAction
| DeleteCompletedTaskErrorAction
| BatchDeleteCompletedTasksBeginAction
| BatchDeleteCompletedTasksSuccessAction
| BatchDeleteCompletedTasksErrorAction
| DeleteAllCompletedTasksBeginAction
| DeleteAllCompletedTasksSuccessAction
| DeleteAllCompletedTasksErrorAction;
export function getTaskInfoAsync(qname: string, id: string) { export function getTaskInfoAsync(qname: string, id: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => { return async (dispatch: Dispatch<TasksActionTypes>) => {
@@ -1064,15 +1146,15 @@ export function getTaskInfoAsync(qname: string, id: string) {
dispatch({ dispatch({
type: GET_TASK_INFO_SUCCESS, type: GET_TASK_INFO_SUCCESS,
payload: response, payload: response,
}) });
} catch (error) { } catch (error) {
console.error("getTaskInfoAsync: ", toErrorStringWithHttpStatus(error)); console.error("getTaskInfoAsync: ", toErrorStringWithHttpStatus(error));
dispatch({ dispatch({
type: GET_TASK_INFO_ERROR, type: GET_TASK_INFO_ERROR,
error: toErrorString(error), error: toErrorString(error),
}) });
} }
} };
} }
export function listActiveTasksAsync( export function listActiveTasksAsync(
@@ -1210,16 +1292,19 @@ export function listArchivedTasksAsync(
}; };
} }
export function listCompletedTasksAsync(qname: string, pageOpts?: PaginationOptions) { export function listCompletedTasksAsync(
qname: string,
pageOpts?: PaginationOptions
) {
return async (dispatch: Dispatch<TasksActionTypes>) => { return async (dispatch: Dispatch<TasksActionTypes>) => {
try { try {
dispatch({ type: LIST_COMPLETED_TASKS_BEGIN, queue: qname }) dispatch({ type: LIST_COMPLETED_TASKS_BEGIN, queue: qname });
const response = await listCompletedTasks(qname, pageOpts); const response = await listCompletedTasks(qname, pageOpts);
dispatch({ dispatch({
type: LIST_COMPLETED_TASKS_SUCCESS, type: LIST_COMPLETED_TASKS_SUCCESS,
queue: qname, queue: qname,
payload: response, payload: response,
}) });
} catch (error) { } catch (error) {
console.error( console.error(
"listCompletedTasksAsync: ", "listCompletedTasksAsync: ",
@@ -1228,10 +1313,10 @@ export function listCompletedTasksAsync(qname: string, pageOpts?: PaginationOpti
dispatch({ dispatch({
type: LIST_COMPLETED_TASKS_ERROR, type: LIST_COMPLETED_TASKS_ERROR,
queue: qname, queue: qname,
error: toErrorString(error) error: toErrorString(error),
}) });
} }
} };
} }
export function cancelActiveTaskAsync(queue: string, taskId: string) { export function cancelActiveTaskAsync(queue: string, taskId: string) {
@@ -1444,10 +1529,7 @@ export function deletePendingTaskAsync(queue: string, taskId: string) {
}; };
} }
export function batchDeletePendingTasksAsync( export function batchDeletePendingTasksAsync(queue: string, taskIds: string[]) {
queue: string,
taskIds: string[]
) {
return async (dispatch: Dispatch<TasksActionTypes>) => { return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: BATCH_DELETE_PENDING_TASKS_BEGIN, queue, taskIds }); dispatch({ type: BATCH_DELETE_PENDING_TASKS_BEGIN, queue, taskIds });
try { try {
@@ -1987,3 +2069,76 @@ export function runAllArchivedTasksAsync(queue: string) {
} }
}; };
} }
export function deleteCompletedTaskAsync(queue: string, taskId: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: DELETE_COMPLETED_TASK_BEGIN, queue, taskId });
try {
await deleteCompletedTask(queue, taskId);
dispatch({ type: DELETE_COMPLETED_TASK_SUCCESS, queue, taskId });
} catch (error) {
console.error(
"deleteCompletedTaskAsync: ",
toErrorStringWithHttpStatus(error)
);
dispatch({
type: DELETE_COMPLETED_TASK_ERROR,
error: toErrorString(error),
queue,
taskId,
});
}
};
}
export function batchDeleteCompletedTasksAsync(
queue: string,
taskIds: string[]
) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: BATCH_DELETE_COMPLETED_TASKS_BEGIN, queue, taskIds });
try {
const response = await batchDeleteCompletedTasks(queue, taskIds);
dispatch({
type: BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
queue: queue,
payload: response,
});
} catch (error) {
console.error(
"batchDeleteCompletedTasksAsync: ",
toErrorStringWithHttpStatus(error)
);
dispatch({
type: BATCH_DELETE_COMPLETED_TASKS_ERROR,
error: toErrorString(error),
queue,
taskIds,
});
}
};
}
export function deleteAllCompletedTasksAsync(queue: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: DELETE_ALL_COMPLETED_TASKS_BEGIN, queue });
try {
const response = await deleteAllCompletedTasks(queue);
dispatch({
type: DELETE_ALL_COMPLETED_TASKS_SUCCESS,
deleted: response.deleted,
queue,
});
} catch (error) {
console.error(
"deleteAllCompletedTasksAsync: ",
toErrorStringWithHttpStatus(error)
);
dispatch({
type: DELETE_ALL_COMPLETED_TASKS_ERROR,
error: toErrorString(error),
queue,
});
}
};
}

View File

@@ -5,7 +5,9 @@ import queryString from "query-string";
// the static file server. // the static file server.
// In developement, we assume that the API server is listening on port 8080. // In developement, we assume that the API server is listening on port 8080.
const BASE_URL = const BASE_URL =
process.env.NODE_ENV === "production" ? `${window.ROOT_PATH}/api` : `http://localhost:8080${window.ROOT_PATH}/api`; process.env.NODE_ENV === "production"
? `${window.ROOT_PATH}/api`
: `http://localhost:8080${window.ROOT_PATH}/api`;
export interface ListQueuesResponse { export interface ListQueuesResponse {
queues: Queue[]; queues: Queue[];
@@ -244,7 +246,7 @@ export interface Queue {
scheduled: number; scheduled: number;
retry: number; retry: number;
archived: number; archived: number;
completed: number, completed: number;
processed: number; processed: number;
failed: number; failed: number;
timestamp: string; timestamp: string;
@@ -333,7 +335,7 @@ export interface CompletedTask extends BaseTask {
retried: number; retried: number;
completed_at: string; completed_at: string;
result: string; result: string;
ttl_seconds: number ttl_seconds: number;
} }
export interface ServerInfo { export interface ServerInfo {
@@ -415,7 +417,10 @@ export async function listQueueStats(): Promise<ListQueueStatsResponse> {
return resp.data; return resp.data;
} }
export async function getTaskInfo(qname: string, id: string): Promise<TaskInfo> { export async function getTaskInfo(
qname: string,
id: string
): Promise<TaskInfo> {
const url = `${BASE_URL}/queues/${qname}/tasks/${id}`; const url = `${BASE_URL}/queues/${qname}/tasks/${id}`;
const resp = await axios({ const resp = await axios({
method: "get", method: "get",
@@ -530,16 +535,19 @@ export async function listArchivedTasks(
return resp.data; return resp.data;
} }
export async function listCompletedTasks(qname: string, pageOpts?: PaginationOptions): Promise<ListCompletedTasksResponse> { export async function listCompletedTasks(
let url = `${BASE_URL}/queues/${qname}/completed_tasks` qname: string,
pageOpts?: PaginationOptions
): Promise<ListCompletedTasksResponse> {
let url = `${BASE_URL}/queues/${qname}/completed_tasks`;
if (pageOpts) { if (pageOpts) {
url += `?${queryString.stringify(pageOpts)}` url += `?${queryString.stringify(pageOpts)}`;
} }
const resp = await axios({ const resp = await axios({
method: "get", method: "get",
url, url,
}) });
return resp.data return resp.data;
} }
export async function archivePendingTask( export async function archivePendingTask(
@@ -864,6 +872,40 @@ export async function runAllArchivedTasks(qname: string): Promise<void> {
}); });
} }
export async function deleteCompletedTask(
qname: string,
taskId: string
): Promise<void> {
await axios({
method: "delete",
url: `${BASE_URL}/queues/${qname}/completed_tasks/${taskId}`,
});
}
export async function batchDeleteCompletedTasks(
qname: string,
taskIds: string[]
): Promise<BatchDeleteTasksResponse> {
const resp = await axios({
method: "post",
url: `${BASE_URL}/queues/${qname}/completed_tasks:batch_delete`,
data: {
task_ids: taskIds,
},
});
return resp.data;
}
export async function deleteAllCompletedTasks(
qname: string
): Promise<DeleteAllTasksResponse> {
const resp = await axios({
method: "delete",
url: `${BASE_URL}/queues/${qname}/completed_tasks:delete_all`,
});
return resp.data;
}
export async function listServers(): Promise<ListServersResponse> { export async function listServers(): Promise<ListServersResponse> {
const resp = await axios({ const resp = await axios({
method: "get", method: "get",

View File

@@ -20,7 +20,12 @@ import Alert from "@material-ui/lab/Alert";
import AlertTitle from "@material-ui/lab/AlertTitle"; import AlertTitle from "@material-ui/lab/AlertTitle";
import SyntaxHighlighter from "./SyntaxHighlighter"; import SyntaxHighlighter from "./SyntaxHighlighter";
import { AppState } from "../store"; import { AppState } from "../store";
import { listCompletedTasksAsync } from "../actions/tasksActions"; import {
listCompletedTasksAsync,
deleteAllCompletedTasksAsync,
deleteCompletedTaskAsync,
batchDeleteCompletedTasksAsync,
} from "../actions/tasksActions";
import TablePaginationActions, { import TablePaginationActions, {
rowsPerPageOptions, rowsPerPageOptions,
} from "./TablePaginationActions"; } from "./TablePaginationActions";
@@ -67,6 +72,9 @@ function mapStateToProps(state: AppState) {
const mapDispatchToProps = { const mapDispatchToProps = {
listCompletedTasksAsync, listCompletedTasksAsync,
deleteCompletedTaskAsync,
deleteAllCompletedTasksAsync,
batchDeleteCompletedTasksAsync,
taskRowsPerPageChange, taskRowsPerPageChange,
}; };
@@ -109,6 +117,16 @@ function CompletedTasksTable(props: Props & ReduxProps) {
} }
}; };
const handleDeleteAllClick = () => {
props.deleteAllCompletedTasksAsync(queue);
};
const handleBatchDeleteClick = () => {
props
.batchDeleteCompletedTasksAsync(queue, selectedIds)
.then(() => setSelectedIds([]));
};
const fetchData = useCallback(() => { const fetchData = useCallback(() => {
const pageOpts = { page: page + 1, size: pageSize }; const pageOpts = { page: page + 1, size: pageSize };
listCompletedTasksAsync(queue, pageOpts); listCompletedTasksAsync(queue, pageOpts);
@@ -153,18 +171,14 @@ function CompletedTasksTable(props: Props & ReduxProps) {
{ {
tooltip: "Delete", tooltip: "Delete",
icon: <DeleteIcon />, icon: <DeleteIcon />,
onClick: () => { onClick: handleBatchDeleteClick,
/* TODO */
},
disabled: props.batchActionPending, disabled: props.batchActionPending,
}, },
]} ]}
menuItemActions={[ menuItemActions={[
{ {
label: "Delete All", label: "Delete All",
onClick: () => { onClick: handleDeleteAllClick,
/* TODO */
},
disabled: props.allActionPending, disabled: props.allActionPending,
}, },
]} ]}
@@ -218,7 +232,7 @@ function CompletedTasksTable(props: Props & ReduxProps) {
} }
}} }}
onDeleteClick={() => { onDeleteClick={() => {
// props.deleteCompletedTaskAsync(queue, task.id); props.deleteCompletedTaskAsync(queue, task.id);
}} }}
allActionPending={props.allActionPending} allActionPending={props.allActionPending}
onActionCellEnter={() => setActiveTaskId(task.id)} onActionCellEnter={() => setActiveTaskId(task.id)}

View File

@@ -50,6 +50,9 @@ import {
BATCH_DELETE_PENDING_TASKS_SUCCESS, BATCH_DELETE_PENDING_TASKS_SUCCESS,
ARCHIVE_ALL_PENDING_TASKS_SUCCESS, ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
DELETE_ALL_PENDING_TASKS_SUCCESS, DELETE_ALL_PENDING_TASKS_SUCCESS,
DELETE_COMPLETED_TASK_SUCCESS,
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { Queue } from "../api"; import { Queue } from "../api";
@@ -550,8 +553,7 @@ function queuesReducer(
queueInfo.currentStats.pending + queueInfo.currentStats.pending +
action.payload.archived_ids.length, action.payload.archived_ids.length,
retry: retry:
queueInfo.currentStats.retry - queueInfo.currentStats.retry - action.payload.archived_ids.length,
action.payload.archived_ids.length,
}, },
}; };
}); });
@@ -647,6 +649,23 @@ function queuesReducer(
return { ...state, data: newData }; return { ...state, data: newData };
} }
case DELETE_COMPLETED_TASK_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {
return queueInfo;
}
return {
...queueInfo,
currentStats: {
...queueInfo.currentStats,
size: queueInfo.currentStats.size - 1,
completed: queueInfo.currentStats.completed - 1,
},
};
});
return { ...state, data: newData };
}
case BATCH_RUN_ARCHIVED_TASKS_SUCCESS: { case BATCH_RUN_ARCHIVED_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => { const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) { if (queueInfo.name !== action.queue) {
@@ -688,6 +707,26 @@ function queuesReducer(
return { ...state, data: newData }; return { ...state, data: newData };
} }
case BATCH_DELETE_COMPLETED_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {
return queueInfo;
}
return {
...queueInfo,
currentStats: {
...queueInfo.currentStats,
size:
queueInfo.currentStats.size - action.payload.deleted_ids.length,
completed:
queueInfo.currentStats.completed -
action.payload.deleted_ids.length,
},
};
});
return { ...state, data: newData };
}
case RUN_ALL_ARCHIVED_TASKS_SUCCESS: { case RUN_ALL_ARCHIVED_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => { const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) { if (queueInfo.name !== action.queue) {
@@ -723,6 +762,23 @@ function queuesReducer(
return { ...state, data: newData }; return { ...state, data: newData };
} }
case DELETE_ALL_COMPLETED_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {
return queueInfo;
}
return {
...queueInfo,
currentStats: {
...queueInfo.currentStats,
size: queueInfo.currentStats.size - action.deleted,
completed: 0,
},
};
});
return { ...state, data: newData };
}
default: default:
return state; return state;
} }

View File

@@ -36,6 +36,9 @@ import {
BATCH_DELETE_PENDING_TASKS_SUCCESS, BATCH_DELETE_PENDING_TASKS_SUCCESS,
ARCHIVE_ALL_PENDING_TASKS_SUCCESS, ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
DELETE_ALL_PENDING_TASKS_SUCCESS, DELETE_ALL_PENDING_TASKS_SUCCESS,
DELETE_COMPLETED_TASK_SUCCESS,
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
interface SnackbarState { interface SnackbarState {
@@ -285,6 +288,25 @@ function snackbarReducer(
message: "All archived tasks deleted", message: "All archived tasks deleted",
}; };
case DELETE_COMPLETED_TASK_SUCCESS:
return {
isOpen: true,
message: `Completed task deleted`,
};
case DELETE_ALL_COMPLETED_TASKS_SUCCESS:
return {
isOpen: true,
message: "All completed tasks deleted",
};
case BATCH_DELETE_COMPLETED_TASKS_SUCCESS:
const n = action.payload.deleted_ids.length;
return {
isOpen: true,
message: `${n} completed ${n === 1 ? "task" : "tasks"} deleted`,
};
default: default:
return state; return state;
} }

View File

@@ -120,6 +120,15 @@ import {
GET_TASK_INFO_BEGIN, GET_TASK_INFO_BEGIN,
GET_TASK_INFO_ERROR, GET_TASK_INFO_ERROR,
GET_TASK_INFO_SUCCESS, GET_TASK_INFO_SUCCESS,
DELETE_COMPLETED_TASK_BEGIN,
DELETE_COMPLETED_TASK_ERROR,
DELETE_COMPLETED_TASK_SUCCESS,
DELETE_ALL_COMPLETED_TASKS_BEGIN,
DELETE_ALL_COMPLETED_TASKS_ERROR,
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
BATCH_DELETE_COMPLETED_TASKS_BEGIN,
BATCH_DELETE_COMPLETED_TASKS_ERROR,
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { import {
ActiveTask, ActiveTask,
@@ -213,12 +222,12 @@ interface TasksState {
allActionPending: boolean; allActionPending: boolean;
error: string; error: string;
data: CompletedTaskExtended[]; data: CompletedTaskExtended[];
} };
taskInfo: { taskInfo: {
loading: boolean; loading: boolean;
error: string; error: string;
data?: TaskInfo; data?: TaskInfo;
}, };
} }
const initialState: TasksState = { const initialState: TasksState = {
@@ -267,7 +276,7 @@ const initialState: TasksState = {
taskInfo: { taskInfo: {
loading: false, loading: false,
error: "", error: "",
} },
}; };
function tasksReducer( function tasksReducer(
@@ -282,16 +291,16 @@ function tasksReducer(
...state.taskInfo, ...state.taskInfo,
loading: true, loading: true,
}, },
} };
case GET_TASK_INFO_ERROR: case GET_TASK_INFO_ERROR:
return { return {
...state, ...state,
taskInfo: { taskInfo: {
loading: false, loading: false,
error: action.error, error: action.error,
}, },
}; };
case GET_TASK_INFO_SUCCESS: case GET_TASK_INFO_SUCCESS:
return { return {
@@ -508,6 +517,123 @@ function tasksReducer(
}, },
}; };
case DELETE_COMPLETED_TASK_BEGIN:
return {
...state,
completedTasks: {
...state.completedTasks,
data: state.completedTasks.data.map((task) => {
if (task.id !== action.taskId) {
return task;
}
return { ...task, requestPending: true };
}),
},
};
case DELETE_COMPLETED_TASK_SUCCESS:
return {
...state,
completedTasks: {
...state.completedTasks,
data: state.completedTasks.data.filter(
(task) => task.id !== action.taskId
),
},
};
case DELETE_COMPLETED_TASK_ERROR:
return {
...state,
completedTasks: {
...state.completedTasks,
data: state.completedTasks.data.map((task) => {
if (task.id !== action.taskId) {
return task;
}
return { ...task, requestPending: false };
}),
},
};
case DELETE_ALL_COMPLETED_TASKS_BEGIN:
return {
...state,
completedTasks: {
...state.completedTasks,
allActionPending: true,
},
};
case DELETE_ALL_COMPLETED_TASKS_SUCCESS:
return {
...state,
completedTasks: {
...state.completedTasks,
allActionPending: false,
data: [],
},
};
case DELETE_ALL_COMPLETED_TASKS_ERROR:
return {
...state,
completedTasks: {
...state.completedTasks,
allActionPending: false,
},
};
case BATCH_DELETE_COMPLETED_TASKS_BEGIN:
return {
...state,
completedTasks: {
...state.completedTasks,
batchActionPending: true,
data: state.completedTasks.data.map((task) => {
if (!action.taskIds.includes(task.id)) {
return task;
}
return {
...task,
requestPending: true,
};
}),
},
};
case BATCH_DELETE_COMPLETED_TASKS_SUCCESS: {
const newData = state.completedTasks.data.filter(
(task) => !action.payload.deleted_ids.includes(task.id)
);
return {
...state,
completedTasks: {
...state.completedTasks,
batchActionPending: false,
data: newData,
},
};
}
case BATCH_DELETE_COMPLETED_TASKS_ERROR:
return {
...state,
completedTasks: {
...state.completedTasks,
batchActionPending: false,
data: state.completedTasks.data.map((task) => {
if (!action.taskIds.includes(task.id)) {
return task;
}
return {
...task,
requestPending: false,
};
}),
},
};
case CANCEL_ACTIVE_TASK_BEGIN: { case CANCEL_ACTIVE_TASK_BEGIN: {
const newData = state.activeTasks.data.map((task) => { const newData = state.activeTasks.data.map((task) => {
if (task.id !== action.taskId) { if (task.id !== action.taskId) {