mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-01-19 03:05:53 +08:00
Implement in-browser task search
This commit is contained in:
parent
1597dac66e
commit
2ec7a68d4a
@ -60,9 +60,11 @@ import {
|
||||
runAggregatingTask,
|
||||
archiveAggregatingTask,
|
||||
ListAggregatingTasksResponse,
|
||||
Queue,
|
||||
} from "../api";
|
||||
import { Dispatch } from "redux";
|
||||
import { toErrorString, toErrorStringWithHttpStatus } from "../utils";
|
||||
import { AppState } from "../store";
|
||||
|
||||
// List of tasks related action types.
|
||||
export const GET_TASK_INFO_BEGIN = "GET_TASK_INFO_BEGIN";
|
||||
@ -89,6 +91,11 @@ export const LIST_COMPLETED_TASKS_ERROR = "LIST_COMPLETED_TASKS_ERROR";
|
||||
export const LIST_AGGREGATING_TASKS_BEGIN = "LIST_AGGREGATING_TASKS_BEGIN";
|
||||
export const LIST_AGGREGATING_TASKS_SUCCESS = "LIST_AGGREGATING_TASKS_SUCCESS";
|
||||
export const LIST_AGGREGATING_TASKS_ERROR = "LIST_AGGREGATING_TASKS_ERROR";
|
||||
export const FILTER_TASKS_BEGIN = "FILTER_TASKS_BEGIN";
|
||||
export const FILTER_TASKS_PROGRESS = "FILTER_TASKS_PROGRESS";
|
||||
export const FILTER_TASKS_SUCCESS = "FILTER_TASKS_SUCCESS";
|
||||
export const FILTER_TASKS_ERROR = "FILTER_TASKS_ERROR";
|
||||
export const FILTER_TASKS_CANCEL = "FILTER_TASKS_CANCEL";
|
||||
export const CANCEL_ACTIVE_TASK_BEGIN = "CANCEL_ACTIVE_TASK_BEGIN";
|
||||
export const CANCEL_ACTIVE_TASK_SUCCESS = "CANCEL_ACTIVE_TASK_SUCCESS";
|
||||
export const CANCEL_ACTIVE_TASK_ERROR = "CANCEL_ACTIVE_TASK_ERROR";
|
||||
@ -429,6 +436,30 @@ interface ListAggregatingTasksErrorAction {
|
||||
error: string; // error description
|
||||
}
|
||||
|
||||
interface FilterTasksBeginAction {
|
||||
type: typeof FILTER_TASKS_BEGIN;
|
||||
}
|
||||
|
||||
interface FilterTasksProgressAction {
|
||||
type: typeof FILTER_TASKS_PROGRESS;
|
||||
processedTasks: number;
|
||||
filterResults: TaskInfo[];
|
||||
newStats: Queue;
|
||||
}
|
||||
|
||||
interface FilterTasksSuccessAction {
|
||||
type: typeof FILTER_TASKS_SUCCESS;
|
||||
}
|
||||
|
||||
interface FilterTasksErrorAction {
|
||||
type: typeof FILTER_TASKS_ERROR;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface FilterTasksCancelAction {
|
||||
type: typeof FILTER_TASKS_CANCEL;
|
||||
}
|
||||
|
||||
interface CancelActiveTaskBeginAction {
|
||||
type: typeof CANCEL_ACTIVE_TASK_BEGIN;
|
||||
queue: string;
|
||||
@ -1291,6 +1322,11 @@ export type TasksActionTypes =
|
||||
| ListAggregatingTasksBeginAction
|
||||
| ListAggregatingTasksSuccessAction
|
||||
| ListAggregatingTasksErrorAction
|
||||
| FilterTasksBeginAction
|
||||
| FilterTasksProgressAction
|
||||
| FilterTasksSuccessAction
|
||||
| FilterTasksErrorAction
|
||||
| FilterTasksCancelAction
|
||||
| CancelActiveTaskBeginAction
|
||||
| CancelActiveTaskSuccessAction
|
||||
| CancelActiveTaskErrorAction
|
||||
@ -1446,14 +1482,42 @@ export function getTaskInfoAsync(qname: string, id: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function getFilterResults(
|
||||
state: AppState,
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
): ListTasksResponse | null {
|
||||
const filterOp = state.tasks.filterOp;
|
||||
if (filterOp == null || !filterOp.done) return null;
|
||||
const curQueueStats = state.queues.data.find((it) => it.name === qname);
|
||||
if (curQueueStats == null) return null;
|
||||
|
||||
const size = pageOpts?.size ?? 20;
|
||||
const page = pageOpts?.page ?? 1;
|
||||
|
||||
const start = (page - 1) * size;
|
||||
const end = start + size;
|
||||
const results = filterOp.result.slice(start, end);
|
||||
|
||||
return {
|
||||
tasks: results,
|
||||
stats: curQueueStats.currentStats,
|
||||
};
|
||||
}
|
||||
|
||||
export function listActiveTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: LIST_ACTIVE_TASKS_BEGIN, queue: qname });
|
||||
try {
|
||||
const response = await listActiveTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listActiveTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_ACTIVE_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1477,10 +1541,15 @@ export function listPendingTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: LIST_PENDING_TASKS_BEGIN, queue: qname });
|
||||
try {
|
||||
const response = await listPendingTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listPendingTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_PENDING_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1504,10 +1573,15 @@ export function listScheduledTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: LIST_SCHEDULED_TASKS_BEGIN, queue: qname });
|
||||
try {
|
||||
const response = await listScheduledTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listScheduledTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_SCHEDULED_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1531,10 +1605,15 @@ export function listRetryTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: LIST_RETRY_TASKS_BEGIN, queue: qname });
|
||||
try {
|
||||
const response = await listRetryTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listRetryTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_RETRY_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1558,10 +1637,15 @@ export function listArchivedTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: LIST_ARCHIVED_TASKS_BEGIN, queue: qname });
|
||||
try {
|
||||
const response = await listArchivedTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listArchivedTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_ARCHIVED_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1585,10 +1669,15 @@ export function listCompletedTasksAsync(
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
try {
|
||||
dispatch({ type: LIST_COMPLETED_TASKS_BEGIN, queue: qname });
|
||||
const response = await listCompletedTasks(qname, pageOpts);
|
||||
const response =
|
||||
getFilterResults(getState(), qname, pageOpts) ??
|
||||
(await listCompletedTasks(qname, pageOpts));
|
||||
dispatch({
|
||||
type: LIST_COMPLETED_TASKS_SUCCESS,
|
||||
queue: qname,
|
||||
@ -1613,6 +1702,7 @@ export function listAggregatingTasksAsync(
|
||||
gname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) {
|
||||
// TODO Add filter support
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
try {
|
||||
dispatch({
|
||||
@ -1642,6 +1732,160 @@ export function listAggregatingTasksAsync(
|
||||
};
|
||||
}
|
||||
|
||||
export interface TasksFilter {
|
||||
payloadQuery?: string;
|
||||
resultQuery?: string;
|
||||
payloadRegex?: RegExp;
|
||||
resultRegex?: RegExp;
|
||||
customJs?: string;
|
||||
resultLimit?: number;
|
||||
}
|
||||
|
||||
function parseIfJson(str: string) {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function evalCustomJsFilter(js: string, task: TaskInfo): any {
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
const {
|
||||
id,
|
||||
queue,
|
||||
type,
|
||||
state,
|
||||
start_time,
|
||||
max_retry,
|
||||
retried,
|
||||
last_failed_at,
|
||||
error_message,
|
||||
next_process_at,
|
||||
timeout_seconds,
|
||||
deadline,
|
||||
group,
|
||||
completed_at,
|
||||
ttl_seconds,
|
||||
is_orphaned,
|
||||
} = task;
|
||||
// Parse payload and result into JSON for convenience
|
||||
const payload = parseIfJson(task.payload);
|
||||
const result = parseIfJson(task.result);
|
||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||
return eval(js); // eslint-disable-line no-eval
|
||||
}
|
||||
|
||||
function filterTask(filter: TasksFilter, task: TaskInfo): boolean {
|
||||
if (
|
||||
filter.payloadQuery != null &&
|
||||
!task.payload.includes(filter.payloadQuery)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (filter.resultQuery != null && !task.result.includes(filter.resultQuery)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
filter.payloadRegex != null &&
|
||||
task.payload.match(filter.payloadRegex) == null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
filter.resultRegex != null &&
|
||||
task.result.match(filter.resultRegex) == null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (filter.customJs != null) {
|
||||
let customJsResult;
|
||||
try {
|
||||
customJsResult = evalCustomJsFilter(filter.customJs, task);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
"Custom JS filter error:",
|
||||
e,
|
||||
"task:",
|
||||
task,
|
||||
"skipping task."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Custom JS can return anything so sanitize output into a boolean
|
||||
return !!customJsResult;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function filterTasksAsync(
|
||||
filter: TasksFilter,
|
||||
fetchTasks: (
|
||||
page?: number // page number (1 being the first page)
|
||||
) => Promise<ListTasksResponse>
|
||||
) {
|
||||
return async (
|
||||
dispatch: Dispatch<TasksActionTypes>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({ type: FILTER_TASKS_BEGIN });
|
||||
|
||||
let page = 1;
|
||||
let processed = 0;
|
||||
let finished = false;
|
||||
do {
|
||||
// Check if operation was cancelled, if so, return
|
||||
if (getState().tasks.filterOp == null) return;
|
||||
|
||||
// Fetch next page
|
||||
let response;
|
||||
try {
|
||||
response = await fetchTasks(page);
|
||||
} catch (error) {
|
||||
dispatch({
|
||||
type: FILTER_TASKS_ERROR,
|
||||
error: toErrorString(error),
|
||||
});
|
||||
return;
|
||||
}
|
||||
page++;
|
||||
|
||||
// Process page
|
||||
const filterResults: TaskInfo[] = [];
|
||||
for (const task of response.tasks) {
|
||||
if (filterTask(filter, task)) {
|
||||
filterResults.push(task);
|
||||
processed++;
|
||||
if (filter.resultLimit != null && processed >= filter.resultLimit) {
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update state
|
||||
dispatch({
|
||||
type: FILTER_TASKS_PROGRESS,
|
||||
processedTasks: response.tasks.length,
|
||||
newStats: response.stats,
|
||||
filterResults,
|
||||
});
|
||||
if (response.tasks.length === 0) finished = true;
|
||||
} while (!finished);
|
||||
|
||||
dispatch({
|
||||
type: FILTER_TASKS_SUCCESS,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function cancelFilterTasks() {
|
||||
return {
|
||||
type: FILTER_TASKS_CANCEL,
|
||||
};
|
||||
}
|
||||
|
||||
export function cancelActiveTaskAsync(queue: string, taskId: string) {
|
||||
return async (dispatch: Dispatch<TasksActionTypes>) => {
|
||||
dispatch({ type: CANCEL_ACTIVE_TASK_BEGIN, queue, taskId });
|
||||
|
165
ui/src/components/TasksFilterDialog.tsx
Normal file
165
ui/src/components/TasksFilterDialog.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import React, {
|
||||
ChangeEventHandler,
|
||||
KeyboardEventHandler,
|
||||
useState,
|
||||
} from "react";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import DialogActions from "@material-ui/core/DialogActions";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import { TasksFilter } from "../actions/tasksActions";
|
||||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
|
||||
interface TasksFilterDialogProps {
|
||||
open: boolean;
|
||||
onClose?: () => void;
|
||||
onFilter?: (filter: TasksFilter) => void;
|
||||
}
|
||||
|
||||
function TasksFilterDialog(props: TasksFilterDialogProps) {
|
||||
const [customJs, setCustomJs] = useState("");
|
||||
const [payloadQuery, setPayloadQuery] = useState("");
|
||||
const [resultQuery, setResultQuery] = useState("");
|
||||
const [payloadRegex, setPayloadRegex] = useState("");
|
||||
const [resultRegex, setResultRegex] = useState("");
|
||||
const [resultLimitStr, setResultLimitStr] = useState("");
|
||||
const [resultLimit, setResultLimit] = useState(-1);
|
||||
const [resultLimitError, setResultLimitError] = useState<string | null>(null);
|
||||
|
||||
const buildFilter = () => {
|
||||
if (resultLimitError != null) return null;
|
||||
|
||||
const filter: TasksFilter = {};
|
||||
if (payloadQuery.trim().length > 0) filter.payloadQuery = payloadQuery;
|
||||
if (resultQuery.trim().length > 0) filter.resultQuery = resultQuery;
|
||||
if (payloadRegex.trim().length > 0)
|
||||
filter.payloadRegex = RegExp(payloadRegex);
|
||||
if (resultRegex.trim().length > 0) filter.resultRegex = RegExp(resultRegex);
|
||||
if (customJs.trim().length > 0) filter.customJs = customJs;
|
||||
if (resultLimit >= 0) filter.resultLimit = resultLimit;
|
||||
return filter;
|
||||
};
|
||||
|
||||
const handleRunFilter = () => {
|
||||
const filter = buildFilter();
|
||||
if (filter != null) {
|
||||
if (props.onClose != null) props.onClose();
|
||||
if (props.onFilter != null) props.onFilter(filter);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown: KeyboardEventHandler = (event) => {
|
||||
if (event.key === "Enter") {
|
||||
handleRunFilter();
|
||||
}
|
||||
};
|
||||
|
||||
const handleResultLimitChange: ChangeEventHandler<HTMLInputElement> = (
|
||||
event
|
||||
) => {
|
||||
const value = event.target.value;
|
||||
setResultLimitStr(value);
|
||||
const trimmedValue = value.trim();
|
||||
if (trimmedValue.length === 0) {
|
||||
setResultLimit(-1);
|
||||
setResultLimitError(null);
|
||||
} else {
|
||||
const parsed = parseInt(trimmedValue, 10);
|
||||
if (isNaN(parsed) || parsed < 0) {
|
||||
setResultLimit(-1);
|
||||
setResultLimitError("Please enter a valid positive number.");
|
||||
} else {
|
||||
setResultLimit(parsed);
|
||||
setResultLimitError(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={props.open} onClose={props.onClose}>
|
||||
<DialogTitle>Filter tasks</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
<p style={{ marginTop: 0 }}>
|
||||
Filter results are stored in browser memory, please ensure that your
|
||||
filter does not return too many results.
|
||||
</p>
|
||||
<p>
|
||||
This feature may not behave correctly if the payload or result are
|
||||
truncated due to <code>MaxPayloadLength</code> or{" "}
|
||||
<code>MaxResultLength</code> being misconfigured.
|
||||
</p>
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
label="Payload keyword"
|
||||
placeholder="Search for tasks with payloads containing the specified text"
|
||||
value={payloadQuery}
|
||||
fullWidth
|
||||
variant="filled"
|
||||
onChange={(e) => setPayloadQuery(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<TextField
|
||||
label="Result keyword"
|
||||
placeholder="Search for tasks with results containing the specified text"
|
||||
value={resultQuery}
|
||||
fullWidth
|
||||
variant="filled"
|
||||
onChange={(e) => setResultQuery(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<TextField
|
||||
label="Payload regex"
|
||||
placeholder="Search for tasks with payloads matching the specified regex"
|
||||
value={payloadRegex}
|
||||
fullWidth
|
||||
variant="filled"
|
||||
onChange={(e) => setPayloadRegex(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<TextField
|
||||
label="Query regex"
|
||||
placeholder="Search for tasks with results matching the specified regex"
|
||||
value={resultRegex}
|
||||
fullWidth
|
||||
variant="filled"
|
||||
onChange={(e) => setResultRegex(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<TextField
|
||||
label="JavaScript expression"
|
||||
placeholder={
|
||||
"Example:\npayload.auth.user_id === 'f094d054-64c0-42a3-a413-3f5a4eae0088'\n\nAvailable variables: " +
|
||||
"id, queue, type, state, start_time, max_retry, retried, last_failed_at, error_message, next_process_at, " +
|
||||
"timeout_seconds, deadline, group, completed_at, ttl_seconds, is_orphaned, payload, result"
|
||||
}
|
||||
value={customJs}
|
||||
multiline
|
||||
minRows={7}
|
||||
fullWidth
|
||||
variant="filled"
|
||||
onChange={(e) => setCustomJs(e.target.value)}
|
||||
/>
|
||||
<TextField
|
||||
label={"Limit number of results"}
|
||||
placeholder={"Leave blank for no limit"}
|
||||
variant="filled"
|
||||
fullWidth
|
||||
value={resultLimitStr}
|
||||
onKeyDown={handleKeyDown}
|
||||
onChange={handleResultLimitChange}
|
||||
error={resultLimitError != null}
|
||||
helperText={resultLimitError}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={props.onClose}>Cancel</Button>
|
||||
<Button onClick={handleRunFilter}>Run</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default TasksFilterDialog;
|
55
ui/src/components/TasksFilterProgressDialog.tsx
Normal file
55
ui/src/components/TasksFilterProgressDialog.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||
import React from "react";
|
||||
import DialogActions from "@material-ui/core/DialogActions";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Dialog from "@material-ui/core/Dialog";
|
||||
import DialogContent from "@material-ui/core/DialogContent";
|
||||
import LinearProgress from "@material-ui/core/LinearProgress";
|
||||
import { AppState } from "../store";
|
||||
import { connect, ConnectedProps } from "react-redux";
|
||||
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||
import { cancelFilterTasks } from "../actions/tasksActions";
|
||||
|
||||
function mapStateToProps(state: AppState) {
|
||||
const filterOp = state.tasks.filterOp;
|
||||
return {
|
||||
open: filterOp != null && !filterOp.done,
|
||||
processedTasks: filterOp?.processedTasks ?? 0,
|
||||
matches: filterOp?.result?.length ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
cancelFilterTasks,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
type ReduxProps = ConnectedProps<typeof connector>;
|
||||
|
||||
interface TasksFilterDialogProps extends ReduxProps {
|
||||
totalTasks: number;
|
||||
}
|
||||
|
||||
function TasksFilterDialog(props: TasksFilterDialogProps) {
|
||||
let progress;
|
||||
if (props.totalTasks > 0) progress = props.processedTasks / props.totalTasks;
|
||||
else progress = 0;
|
||||
|
||||
return (
|
||||
<Dialog open={props.open} fullWidth>
|
||||
<DialogTitle>Running filter</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
Processed {props.processedTasks} of {props.totalTasks} total tasks,{" "}
|
||||
{props.matches} matches so far.
|
||||
</DialogContentText>
|
||||
<LinearProgress variant="determinate" value={progress * 100} />
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={props.cancelFilterTasks}>Cancel</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default connector(TasksFilterDialog);
|
@ -26,6 +26,18 @@ import { TaskInfoExtended } from "../reducers/tasksReducer";
|
||||
import { TableColumn } from "../types/table";
|
||||
import { PaginationOptions } from "../api";
|
||||
import { TaskState } from "../types/taskState";
|
||||
import TasksFilterProgressDialog from "./TasksFilterProgressDialog";
|
||||
import { AppState } from "../store";
|
||||
import { connect, ConnectedProps } from "react-redux";
|
||||
|
||||
function mapStateToProps(state: AppState) {
|
||||
return {
|
||||
filterEnabled: state.tasks.filterOp?.done ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
const connector = connect(mapStateToProps);
|
||||
type ReduxProps = ConnectedProps<typeof connector>;
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
table: {
|
||||
@ -43,7 +55,7 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
interface Props {
|
||||
interface Props extends ReduxProps {
|
||||
queue: string; // name of the queue.
|
||||
totalTaskCount: number; // totoal number of tasks in the given state.
|
||||
taskState: TaskState;
|
||||
@ -75,12 +87,15 @@ interface Props {
|
||||
renderRow: (rowProps: RowProps) => JSX.Element;
|
||||
}
|
||||
|
||||
export default function TasksTable(props: Props) {
|
||||
function TasksTable(props: Props) {
|
||||
const { pollInterval, listTasks, queue, pageSize } = props;
|
||||
const classes = useStyles();
|
||||
const [page, setPage] = useState(0);
|
||||
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
||||
const [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||
const [lastFilterEnabled, setLastFilterEnabled] = useState(
|
||||
props.filterEnabled
|
||||
);
|
||||
|
||||
const handlePageChange = (
|
||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||
@ -123,6 +138,8 @@ export default function TasksTable(props: Props) {
|
||||
}
|
||||
|
||||
let allActions = [];
|
||||
if (!props.filterEnabled) {
|
||||
// Protect against using all actions while filter enabled
|
||||
if (props.deleteAllTasks) {
|
||||
allActions.push({
|
||||
label: "Delete All",
|
||||
@ -151,6 +168,7 @@ export default function TasksTable(props: Props) {
|
||||
disabled: props.allActionPending,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let batchActions = [];
|
||||
if (props.batchDeleteTasks) {
|
||||
@ -193,6 +211,12 @@ export default function TasksTable(props: Props) {
|
||||
|
||||
usePolling(fetchData, pollInterval);
|
||||
|
||||
if (props.filterEnabled !== lastFilterEnabled) {
|
||||
setLastFilterEnabled(props.filterEnabled);
|
||||
setPage(0);
|
||||
fetchData();
|
||||
}
|
||||
|
||||
if (props.error.length > 0) {
|
||||
return (
|
||||
<Alert severity="error" className={classes.alert}>
|
||||
@ -320,6 +344,7 @@ export default function TasksTable(props: Props) {
|
||||
</TableFooter>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<TasksFilterProgressDialog totalTasks={props.totalTaskCount} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -376,3 +401,5 @@ export interface RowProps {
|
||||
onActionCellEnter: () => void;
|
||||
onActionCellLeave: () => void;
|
||||
}
|
||||
|
||||
export default connector(TasksTable);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { connect, ConnectedProps } from "react-redux";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
@ -18,6 +18,24 @@ import { queueDetailsPath, taskDetailsPath } from "../paths";
|
||||
import { QueueInfo } from "../reducers/queuesReducer";
|
||||
import { AppState } from "../store";
|
||||
import { isDarkTheme } from "../theme";
|
||||
import { Divider } from "@material-ui/core";
|
||||
import FilterListIcon from "@material-ui/icons/FilterList";
|
||||
import TasksFilterDialog from "./TasksFilterDialog";
|
||||
import {
|
||||
listActiveTasks,
|
||||
listArchivedTasks,
|
||||
listCompletedTasks,
|
||||
listPendingTasks,
|
||||
listRetryTasks,
|
||||
listScheduledTasks,
|
||||
ListTasksResponse,
|
||||
PaginationOptions,
|
||||
} from "../api";
|
||||
import {
|
||||
cancelFilterTasks,
|
||||
filterTasksAsync,
|
||||
TasksFilter,
|
||||
} from "../actions/tasksActions";
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
@ -65,10 +83,18 @@ function mapStatetoProps(state: AppState, ownProps: Props) {
|
||||
failed: 0,
|
||||
timestamp: "n/a",
|
||||
};
|
||||
return { currentStats };
|
||||
const filterOp = state.tasks.filterOp;
|
||||
const filterActive = filterOp != null;
|
||||
const filterCount = filterOp?.done === true ? filterOp?.result?.length : null;
|
||||
return { currentStats, filterActive, filterCount };
|
||||
}
|
||||
|
||||
const connector = connect(mapStatetoProps);
|
||||
const mapDispatchToProps = {
|
||||
filterTasksAsync,
|
||||
cancelFilterTasks,
|
||||
};
|
||||
|
||||
const connector = connect(mapStatetoProps, mapDispatchToProps);
|
||||
|
||||
type ReduxProps = ConnectedProps<typeof connector>;
|
||||
|
||||
@ -146,24 +172,92 @@ const useStyles = makeStyles((theme) => ({
|
||||
}));
|
||||
|
||||
function TasksTableContainer(props: Props & ReduxProps) {
|
||||
const { currentStats } = props;
|
||||
const { currentStats, cancelFilterTasks } = props;
|
||||
const classes = useStyles();
|
||||
const history = useHistory();
|
||||
const chips = [
|
||||
{ key: "active", label: "Active", count: currentStats.active },
|
||||
{ key: "pending", label: "Pending", count: currentStats.pending },
|
||||
{
|
||||
key: "active",
|
||||
label: "Active",
|
||||
count: currentStats.active,
|
||||
fetcher: listActiveTasks,
|
||||
},
|
||||
{
|
||||
key: "pending",
|
||||
label: "Pending",
|
||||
count: currentStats.pending,
|
||||
fetcher: listPendingTasks,
|
||||
},
|
||||
{
|
||||
key: "aggregating",
|
||||
label: "Aggregating",
|
||||
count: currentStats.aggregating,
|
||||
fetcher: null, // TODO Support aggregating table
|
||||
},
|
||||
{
|
||||
key: "scheduled",
|
||||
label: "Scheduled",
|
||||
count: currentStats.scheduled,
|
||||
fetcher: listScheduledTasks,
|
||||
},
|
||||
{
|
||||
key: "retry",
|
||||
label: "Retry",
|
||||
count: currentStats.retry,
|
||||
fetcher: listRetryTasks,
|
||||
},
|
||||
{
|
||||
key: "archived",
|
||||
label: "Archived",
|
||||
count: currentStats.archived,
|
||||
fetcher: listArchivedTasks,
|
||||
},
|
||||
{
|
||||
key: "completed",
|
||||
label: "Completed",
|
||||
count: currentStats.completed,
|
||||
fetcher: listCompletedTasks,
|
||||
},
|
||||
{ key: "scheduled", label: "Scheduled", count: currentStats.scheduled },
|
||||
{ key: "retry", label: "Retry", count: currentStats.retry },
|
||||
{ key: "archived", label: "Archived", count: currentStats.archived },
|
||||
{ key: "completed", label: "Completed", count: currentStats.completed },
|
||||
];
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
||||
const [filterModalOpen, setFilterModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Clear filter when the user selects a different task status
|
||||
cancelFilterTasks();
|
||||
return () => {
|
||||
// Clear filter when leaving the page
|
||||
cancelFilterTasks();
|
||||
};
|
||||
}, [props.selected, cancelFilterTasks]);
|
||||
|
||||
const taskPageFetcher = (
|
||||
fetcherApi: (
|
||||
qname: string,
|
||||
pageOpts?: PaginationOptions
|
||||
) => Promise<ListTasksResponse>
|
||||
) => {
|
||||
const qname = props.queue;
|
||||
return async (page?: number) => {
|
||||
return fetcherApi(qname, {
|
||||
page,
|
||||
size: 10_000, // TODO Choose a value here intelligently?
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const dispatchFilterAction = (filter: TasksFilter) => {
|
||||
const fetcherApi = chips.find((c) => c.key === props.selected)?.fetcher;
|
||||
if (fetcherApi == null) {
|
||||
console.error(
|
||||
"Failed to find fetcher API for selected task type:",
|
||||
props.selected
|
||||
);
|
||||
return;
|
||||
}
|
||||
props.filterTasksAsync(filter, taskPageFetcher(fetcherApi));
|
||||
};
|
||||
|
||||
return (
|
||||
<Paper variant="outlined" className={classes.container}>
|
||||
@ -187,6 +281,25 @@ function TasksTableContainer(props: Props & ReduxProps) {
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<Divider orientation="vertical" variant="middle" flexItem />
|
||||
<div>
|
||||
{chips.find((c) => c.key === props.selected)?.fetcher && (
|
||||
<Chip
|
||||
icon={<FilterListIcon />}
|
||||
label="Filter"
|
||||
onClick={() => setFilterModalOpen(true)}
|
||||
onDelete={
|
||||
props.filterActive ? props.cancelFilterTasks : undefined
|
||||
}
|
||||
color={props.filterActive ? "primary" : "default"}
|
||||
/>
|
||||
)}
|
||||
<TasksFilterDialog
|
||||
open={filterModalOpen}
|
||||
onClose={() => setFilterModalOpen(false)}
|
||||
onFilter={dispatchFilterAction}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.searchbar}>
|
||||
<div className={classes.search}>
|
||||
<div className={classes.searchIcon}>
|
||||
@ -219,13 +332,13 @@ function TasksTableContainer(props: Props & ReduxProps) {
|
||||
<TabPanel value="active" selected={props.selected}>
|
||||
<ActiveTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.active}
|
||||
totalTaskCount={props.filterCount ?? currentStats.active}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value="pending" selected={props.selected}>
|
||||
<PendingTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.pending}
|
||||
totalTaskCount={props.filterCount ?? currentStats.pending}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value="aggregating" selected={props.selected}>
|
||||
@ -234,25 +347,25 @@ function TasksTableContainer(props: Props & ReduxProps) {
|
||||
<TabPanel value="scheduled" selected={props.selected}>
|
||||
<ScheduledTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.scheduled}
|
||||
totalTaskCount={props.filterCount ?? currentStats.scheduled}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value="retry" selected={props.selected}>
|
||||
<RetryTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.retry}
|
||||
totalTaskCount={props.filterCount ?? currentStats.retry}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value="archived" selected={props.selected}>
|
||||
<ArchivedTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.archived}
|
||||
totalTaskCount={props.filterCount ?? currentStats.archived}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel value="completed" selected={props.selected}>
|
||||
<CompletedTasksTable
|
||||
queue={props.queue}
|
||||
totalTaskCount={currentStats.completed}
|
||||
totalTaskCount={props.filterCount ?? currentStats.completed}
|
||||
/>
|
||||
</TabPanel>
|
||||
</Paper>
|
||||
|
149
ui/src/reducers/filterReducer.ts
Normal file
149
ui/src/reducers/filterReducer.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import {
|
||||
ARCHIVE_AGGREGATING_TASK_SUCCESS,
|
||||
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_SUCCESS,
|
||||
ARCHIVE_SCHEDULED_TASK_SUCCESS,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_RUN_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_RUN_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_RUN_RETRY_TASKS_SUCCESS,
|
||||
BATCH_RUN_SCHEDULED_TASKS_SUCCESS,
|
||||
DELETE_AGGREGATING_TASK_SUCCESS,
|
||||
DELETE_ARCHIVED_TASK_SUCCESS,
|
||||
DELETE_COMPLETED_TASK_SUCCESS,
|
||||
DELETE_PENDING_TASK_SUCCESS,
|
||||
DELETE_RETRY_TASK_SUCCESS,
|
||||
DELETE_SCHEDULED_TASK_SUCCESS,
|
||||
FILTER_TASKS_BEGIN,
|
||||
FILTER_TASKS_CANCEL,
|
||||
FILTER_TASKS_PROGRESS,
|
||||
FILTER_TASKS_SUCCESS,
|
||||
RUN_AGGREGATING_TASK_SUCCESS,
|
||||
RUN_ARCHIVED_TASK_SUCCESS,
|
||||
RUN_RETRY_TASK_SUCCESS,
|
||||
RUN_SCHEDULED_TASK_SUCCESS,
|
||||
TasksActionTypes,
|
||||
} from "../actions/tasksActions";
|
||||
import { TasksState } from "./tasksReducer";
|
||||
import { TaskInfo } from "../api";
|
||||
|
||||
function modifyFilterResults(
|
||||
state: TasksState,
|
||||
action: (tasks: TaskInfo[]) => TaskInfo[]
|
||||
): TasksState {
|
||||
const filterOp = state.filterOp;
|
||||
if (filterOp == null || !filterOp.done) return state;
|
||||
|
||||
return {
|
||||
...state,
|
||||
filterOp: {
|
||||
...filterOp,
|
||||
result: action(filterOp.result),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function filterReducer(
|
||||
state: TasksState,
|
||||
action: TasksActionTypes
|
||||
): TasksState {
|
||||
switch (action.type) {
|
||||
case FILTER_TASKS_BEGIN:
|
||||
return {
|
||||
...state,
|
||||
filterOp: {
|
||||
done: false,
|
||||
processedTasks: 0,
|
||||
result: [],
|
||||
},
|
||||
};
|
||||
|
||||
case FILTER_TASKS_PROGRESS: {
|
||||
const filterOp = state.filterOp;
|
||||
if (filterOp == null) return state;
|
||||
return {
|
||||
...state,
|
||||
filterOp: {
|
||||
done: false,
|
||||
processedTasks: filterOp.processedTasks + action.processedTasks,
|
||||
result: filterOp.result.concat(action.filterResults),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case FILTER_TASKS_SUCCESS: {
|
||||
const filterOp = state.filterOp;
|
||||
if (filterOp == null) return state;
|
||||
return {
|
||||
...state,
|
||||
filterOp: {
|
||||
...filterOp,
|
||||
done: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
case FILTER_TASKS_CANCEL: {
|
||||
const { filterOp, ...newState } = state;
|
||||
return newState;
|
||||
}
|
||||
|
||||
// Replicate actions made to queues to filter results
|
||||
|
||||
case ARCHIVE_PENDING_TASK_SUCCESS:
|
||||
case DELETE_PENDING_TASK_SUCCESS:
|
||||
case DELETE_COMPLETED_TASK_SUCCESS:
|
||||
case RUN_SCHEDULED_TASK_SUCCESS:
|
||||
case ARCHIVE_SCHEDULED_TASK_SUCCESS:
|
||||
case DELETE_SCHEDULED_TASK_SUCCESS:
|
||||
case RUN_AGGREGATING_TASK_SUCCESS:
|
||||
case ARCHIVE_AGGREGATING_TASK_SUCCESS:
|
||||
case DELETE_AGGREGATING_TASK_SUCCESS:
|
||||
case RUN_RETRY_TASK_SUCCESS:
|
||||
case ARCHIVE_RETRY_TASK_SUCCESS:
|
||||
case DELETE_RETRY_TASK_SUCCESS:
|
||||
case RUN_ARCHIVED_TASK_SUCCESS:
|
||||
case DELETE_ARCHIVED_TASK_SUCCESS:
|
||||
return modifyFilterResults(state, (tasks) =>
|
||||
tasks.filter((task) => task.id !== action.taskId)
|
||||
);
|
||||
|
||||
case BATCH_ARCHIVE_PENDING_TASKS_SUCCESS:
|
||||
case BATCH_ARCHIVE_SCHEDULED_TASKS_SUCCESS:
|
||||
case BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS:
|
||||
case BATCH_ARCHIVE_RETRY_TASKS_SUCCESS:
|
||||
return modifyFilterResults(state, (tasks) =>
|
||||
tasks.filter((task) => !action.payload.archived_ids.includes(task.id))
|
||||
);
|
||||
|
||||
case BATCH_DELETE_COMPLETED_TASKS_SUCCESS:
|
||||
case BATCH_DELETE_PENDING_TASKS_SUCCESS:
|
||||
case BATCH_DELETE_SCHEDULED_TASKS_SUCCESS:
|
||||
case BATCH_DELETE_AGGREGATING_TASKS_SUCCESS:
|
||||
case BATCH_DELETE_RETRY_TASKS_SUCCESS:
|
||||
case BATCH_DELETE_ARCHIVED_TASKS_SUCCESS:
|
||||
return modifyFilterResults(state, (tasks) =>
|
||||
tasks.filter((task) => !action.payload.deleted_ids.includes(task.id))
|
||||
);
|
||||
|
||||
case BATCH_RUN_SCHEDULED_TASKS_SUCCESS:
|
||||
case BATCH_RUN_AGGREGATING_TASKS_SUCCESS:
|
||||
case BATCH_RUN_RETRY_TASKS_SUCCESS:
|
||||
case BATCH_RUN_ARCHIVED_TASKS_SUCCESS:
|
||||
return modifyFilterResults(state, (tasks) =>
|
||||
tasks.filter((task) => !action.payload.pending_ids.includes(task.id))
|
||||
);
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@ -3,44 +3,64 @@ import {
|
||||
LIST_GROUPS_SUCCESS,
|
||||
} from "../actions/groupsActions";
|
||||
import {
|
||||
LIST_QUEUES_SUCCESS,
|
||||
LIST_QUEUES_BEGIN,
|
||||
QueuesActionTypes,
|
||||
PAUSE_QUEUE_BEGIN,
|
||||
PAUSE_QUEUE_SUCCESS,
|
||||
PAUSE_QUEUE_ERROR,
|
||||
RESUME_QUEUE_BEGIN,
|
||||
RESUME_QUEUE_ERROR,
|
||||
RESUME_QUEUE_SUCCESS,
|
||||
DELETE_QUEUE_BEGIN,
|
||||
DELETE_QUEUE_ERROR,
|
||||
DELETE_QUEUE_SUCCESS,
|
||||
LIST_QUEUES_BEGIN,
|
||||
LIST_QUEUES_ERROR,
|
||||
LIST_QUEUES_SUCCESS,
|
||||
PAUSE_QUEUE_BEGIN,
|
||||
PAUSE_QUEUE_ERROR,
|
||||
PAUSE_QUEUE_SUCCESS,
|
||||
QueuesActionTypes,
|
||||
RESUME_QUEUE_BEGIN,
|
||||
RESUME_QUEUE_ERROR,
|
||||
RESUME_QUEUE_SUCCESS,
|
||||
} from "../actions/queuesActions";
|
||||
import {
|
||||
BATCH_DELETE_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_AGGREGATING_TASK_SUCCESS,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_RETRY_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_SUCCESS,
|
||||
ARCHIVE_SCHEDULED_TASK_SUCCESS,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_RUN_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_RUN_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_RUN_RETRY_TASKS_SUCCESS,
|
||||
BATCH_RUN_SCHEDULED_TASKS_SUCCESS,
|
||||
DELETE_AGGREGATING_TASK_SUCCESS,
|
||||
DELETE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
DELETE_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
|
||||
DELETE_ALL_PENDING_TASKS_SUCCESS,
|
||||
DELETE_ALL_RETRY_TASKS_SUCCESS,
|
||||
DELETE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
DELETE_ARCHIVED_TASK_SUCCESS,
|
||||
DELETE_COMPLETED_TASK_SUCCESS,
|
||||
DELETE_PENDING_TASK_SUCCESS,
|
||||
DELETE_RETRY_TASK_SUCCESS,
|
||||
DELETE_SCHEDULED_TASK_SUCCESS,
|
||||
ARCHIVE_ALL_RETRY_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_SUCCESS,
|
||||
ARCHIVE_SCHEDULED_TASK_SUCCESS,
|
||||
FILTER_TASKS_PROGRESS,
|
||||
LIST_ACTIVE_TASKS_SUCCESS,
|
||||
LIST_AGGREGATING_TASKS_SUCCESS,
|
||||
LIST_ARCHIVED_TASKS_SUCCESS,
|
||||
LIST_PENDING_TASKS_SUCCESS,
|
||||
LIST_RETRY_TASKS_SUCCESS,
|
||||
LIST_SCHEDULED_TASKS_SUCCESS,
|
||||
RUN_AGGREGATING_TASK_SUCCESS,
|
||||
RUN_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
RUN_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
RUN_ALL_RETRY_TASKS_SUCCESS,
|
||||
RUN_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
@ -48,25 +68,6 @@ import {
|
||||
RUN_RETRY_TASK_SUCCESS,
|
||||
RUN_SCHEDULED_TASK_SUCCESS,
|
||||
TasksActionTypes,
|
||||
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||
DELETE_PENDING_TASK_SUCCESS,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
|
||||
DELETE_ALL_PENDING_TASKS_SUCCESS,
|
||||
DELETE_COMPLETED_TASK_SUCCESS,
|
||||
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
|
||||
DELETE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
RUN_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_RUN_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS,
|
||||
DELETE_AGGREGATING_TASK_SUCCESS,
|
||||
RUN_AGGREGATING_TASK_SUCCESS,
|
||||
ARCHIVE_AGGREGATING_TASK_SUCCESS,
|
||||
LIST_AGGREGATING_TASKS_SUCCESS,
|
||||
} from "../actions/tasksActions";
|
||||
import { Queue } from "../api";
|
||||
|
||||
@ -190,6 +191,17 @@ function queuesReducer(
|
||||
return { ...state, data: newData };
|
||||
}
|
||||
|
||||
case FILTER_TASKS_PROGRESS: {
|
||||
const newData = state.data
|
||||
.filter((queueInfo) => queueInfo.name !== action.newStats.queue)
|
||||
.concat({
|
||||
name: action.newStats.queue,
|
||||
currentStats: action.newStats,
|
||||
requestPending: false,
|
||||
});
|
||||
return { ...state, data: newData };
|
||||
}
|
||||
|
||||
case RUN_AGGREGATING_TASK_SUCCESS: {
|
||||
const newData = state.data.map((queueInfo) => {
|
||||
if (queueInfo.name !== action.queue) {
|
||||
|
@ -1,166 +1,167 @@
|
||||
import {
|
||||
LIST_ACTIVE_TASKS_BEGIN,
|
||||
LIST_ACTIVE_TASKS_SUCCESS,
|
||||
LIST_ACTIVE_TASKS_ERROR,
|
||||
TasksActionTypes,
|
||||
LIST_PENDING_TASKS_BEGIN,
|
||||
LIST_PENDING_TASKS_SUCCESS,
|
||||
LIST_PENDING_TASKS_ERROR,
|
||||
LIST_SCHEDULED_TASKS_BEGIN,
|
||||
LIST_SCHEDULED_TASKS_SUCCESS,
|
||||
LIST_SCHEDULED_TASKS_ERROR,
|
||||
LIST_RETRY_TASKS_BEGIN,
|
||||
LIST_RETRY_TASKS_SUCCESS,
|
||||
LIST_RETRY_TASKS_ERROR,
|
||||
LIST_ARCHIVED_TASKS_BEGIN,
|
||||
LIST_ARCHIVED_TASKS_SUCCESS,
|
||||
LIST_ARCHIVED_TASKS_ERROR,
|
||||
LIST_COMPLETED_TASKS_BEGIN,
|
||||
LIST_COMPLETED_TASKS_SUCCESS,
|
||||
LIST_COMPLETED_TASKS_ERROR,
|
||||
CANCEL_ACTIVE_TASK_BEGIN,
|
||||
CANCEL_ACTIVE_TASK_SUCCESS,
|
||||
CANCEL_ACTIVE_TASK_ERROR,
|
||||
DELETE_RETRY_TASK_BEGIN,
|
||||
DELETE_RETRY_TASK_SUCCESS,
|
||||
DELETE_RETRY_TASK_ERROR,
|
||||
DELETE_SCHEDULED_TASK_BEGIN,
|
||||
DELETE_SCHEDULED_TASK_SUCCESS,
|
||||
DELETE_SCHEDULED_TASK_ERROR,
|
||||
DELETE_ARCHIVED_TASK_BEGIN,
|
||||
DELETE_ARCHIVED_TASK_SUCCESS,
|
||||
DELETE_ARCHIVED_TASK_ERROR,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_BEGIN,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_ERROR,
|
||||
RUN_ARCHIVED_TASK_BEGIN,
|
||||
RUN_ARCHIVED_TASK_SUCCESS,
|
||||
RUN_ARCHIVED_TASK_ERROR,
|
||||
BATCH_RUN_ARCHIVED_TASKS_BEGIN,
|
||||
BATCH_RUN_ARCHIVED_TASKS_ERROR,
|
||||
BATCH_RUN_ARCHIVED_TASKS_SUCCESS,
|
||||
DELETE_ALL_ARCHIVED_TASKS_BEGIN,
|
||||
DELETE_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
DELETE_ALL_ARCHIVED_TASKS_ERROR,
|
||||
RUN_ALL_ARCHIVED_TASKS_BEGIN,
|
||||
RUN_ALL_ARCHIVED_TASKS_ERROR,
|
||||
RUN_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_ERROR,
|
||||
BATCH_RUN_RETRY_TASKS_ERROR,
|
||||
BATCH_DELETE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_RUN_RETRY_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_BEGIN,
|
||||
BATCH_RUN_RETRY_TASKS_BEGIN,
|
||||
DELETE_ALL_RETRY_TASKS_ERROR,
|
||||
RUN_ALL_RETRY_TASKS_ERROR,
|
||||
DELETE_ALL_RETRY_TASKS_SUCCESS,
|
||||
RUN_ALL_RETRY_TASKS_SUCCESS,
|
||||
DELETE_ALL_RETRY_TASKS_BEGIN,
|
||||
RUN_ALL_RETRY_TASKS_BEGIN,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_ERROR,
|
||||
BATCH_RUN_SCHEDULED_TASKS_ERROR,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_RUN_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_BEGIN,
|
||||
BATCH_RUN_SCHEDULED_TASKS_BEGIN,
|
||||
DELETE_ALL_SCHEDULED_TASKS_ERROR,
|
||||
RUN_ALL_SCHEDULED_TASKS_ERROR,
|
||||
DELETE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
RUN_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
DELETE_ALL_SCHEDULED_TASKS_BEGIN,
|
||||
RUN_ALL_SCHEDULED_TASKS_BEGIN,
|
||||
RUN_RETRY_TASK_BEGIN,
|
||||
RUN_RETRY_TASK_SUCCESS,
|
||||
RUN_RETRY_TASK_ERROR,
|
||||
RUN_SCHEDULED_TASK_BEGIN,
|
||||
RUN_SCHEDULED_TASK_SUCCESS,
|
||||
RUN_SCHEDULED_TASK_ERROR,
|
||||
ARCHIVE_SCHEDULED_TASK_BEGIN,
|
||||
ARCHIVE_SCHEDULED_TASK_SUCCESS,
|
||||
ARCHIVE_SCHEDULED_TASK_ERROR,
|
||||
ARCHIVE_AGGREGATING_TASK_BEGIN,
|
||||
ARCHIVE_AGGREGATING_TASK_ERROR,
|
||||
ARCHIVE_AGGREGATING_TASK_SUCCESS,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_ERROR,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_PENDING_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_PENDING_TASKS_ERROR,
|
||||
ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_RETRY_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_RETRY_TASKS_ERROR,
|
||||
ARCHIVE_ALL_RETRY_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_ERROR,
|
||||
ARCHIVE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_PENDING_TASK_BEGIN,
|
||||
ARCHIVE_PENDING_TASK_ERROR,
|
||||
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_BEGIN,
|
||||
ARCHIVE_RETRY_TASK_ERROR,
|
||||
ARCHIVE_RETRY_TASK_SUCCESS,
|
||||
ARCHIVE_SCHEDULED_TASK_BEGIN,
|
||||
ARCHIVE_SCHEDULED_TASK_ERROR,
|
||||
ARCHIVE_SCHEDULED_TASK_SUCCESS,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_SCHEDULED_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_SCHEDULED_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_SCHEDULED_TASKS_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_BEGIN,
|
||||
ARCHIVE_RETRY_TASK_SUCCESS,
|
||||
ARCHIVE_RETRY_TASK_ERROR,
|
||||
ARCHIVE_ALL_RETRY_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_RETRY_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_RETRY_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_RETRY_TASKS_ERROR,
|
||||
BATCH_CANCEL_ACTIVE_TASKS_BEGIN,
|
||||
BATCH_CANCEL_ACTIVE_TASKS_SUCCESS,
|
||||
BATCH_CANCEL_ACTIVE_TASKS_ERROR,
|
||||
CANCEL_ALL_ACTIVE_TASKS_BEGIN,
|
||||
CANCEL_ALL_ACTIVE_TASKS_SUCCESS,
|
||||
CANCEL_ALL_ACTIVE_TASKS_ERROR,
|
||||
ARCHIVE_PENDING_TASK_BEGIN,
|
||||
DELETE_PENDING_TASK_BEGIN,
|
||||
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||
DELETE_PENDING_TASK_SUCCESS,
|
||||
ARCHIVE_PENDING_TASK_ERROR,
|
||||
DELETE_PENDING_TASK_ERROR,
|
||||
ARCHIVE_ALL_PENDING_TASKS_BEGIN,
|
||||
DELETE_ALL_PENDING_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
|
||||
DELETE_ALL_PENDING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_PENDING_TASKS_ERROR,
|
||||
DELETE_ALL_PENDING_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_BEGIN,
|
||||
BATCH_DELETE_PENDING_TASKS_BEGIN,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_PENDING_TASKS_ERROR,
|
||||
BATCH_DELETE_PENDING_TASKS_ERROR,
|
||||
GET_TASK_INFO_BEGIN,
|
||||
GET_TASK_INFO_ERROR,
|
||||
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_CANCEL_ACTIVE_TASKS_SUCCESS,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_BEGIN,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_BEGIN,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_ERROR,
|
||||
BATCH_DELETE_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_DELETE_COMPLETED_TASKS_BEGIN,
|
||||
BATCH_DELETE_COMPLETED_TASKS_ERROR,
|
||||
BATCH_DELETE_COMPLETED_TASKS_SUCCESS,
|
||||
LIST_AGGREGATING_TASKS_BEGIN,
|
||||
LIST_AGGREGATING_TASKS_SUCCESS,
|
||||
LIST_AGGREGATING_TASKS_ERROR,
|
||||
DELETE_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
DELETE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
DELETE_ALL_AGGREGATING_TASKS_ERROR,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
ARCHIVE_ALL_AGGREGATING_TASKS_ERROR,
|
||||
RUN_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
RUN_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
RUN_ALL_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_BEGIN,
|
||||
BATCH_DELETE_PENDING_TASKS_BEGIN,
|
||||
BATCH_DELETE_PENDING_TASKS_ERROR,
|
||||
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||
BATCH_DELETE_RETRY_TASKS_BEGIN,
|
||||
BATCH_DELETE_RETRY_TASKS_ERROR,
|
||||
BATCH_DELETE_RETRY_TASKS_SUCCESS,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_BEGIN,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_ERROR,
|
||||
BATCH_DELETE_SCHEDULED_TASKS_SUCCESS,
|
||||
BATCH_RUN_AGGREGATING_TASKS_BEGIN,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_BEGIN,
|
||||
BATCH_RUN_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_ERROR,
|
||||
BATCH_DELETE_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_RUN_AGGREGATING_TASKS_SUCCESS,
|
||||
BATCH_ARCHIVE_AGGREGATING_TASKS_SUCCESS,
|
||||
RUN_AGGREGATING_TASK_BEGIN,
|
||||
ARCHIVE_AGGREGATING_TASK_BEGIN,
|
||||
BATCH_RUN_ARCHIVED_TASKS_BEGIN,
|
||||
BATCH_RUN_ARCHIVED_TASKS_ERROR,
|
||||
BATCH_RUN_ARCHIVED_TASKS_SUCCESS,
|
||||
BATCH_RUN_RETRY_TASKS_BEGIN,
|
||||
BATCH_RUN_RETRY_TASKS_ERROR,
|
||||
BATCH_RUN_RETRY_TASKS_SUCCESS,
|
||||
BATCH_RUN_SCHEDULED_TASKS_BEGIN,
|
||||
BATCH_RUN_SCHEDULED_TASKS_ERROR,
|
||||
BATCH_RUN_SCHEDULED_TASKS_SUCCESS,
|
||||
CANCEL_ACTIVE_TASK_BEGIN,
|
||||
CANCEL_ACTIVE_TASK_ERROR,
|
||||
CANCEL_ACTIVE_TASK_SUCCESS,
|
||||
CANCEL_ALL_ACTIVE_TASKS_BEGIN,
|
||||
CANCEL_ALL_ACTIVE_TASKS_ERROR,
|
||||
CANCEL_ALL_ACTIVE_TASKS_SUCCESS,
|
||||
DELETE_AGGREGATING_TASK_BEGIN,
|
||||
RUN_AGGREGATING_TASK_ERROR,
|
||||
ARCHIVE_AGGREGATING_TASK_ERROR,
|
||||
DELETE_AGGREGATING_TASK_ERROR,
|
||||
RUN_AGGREGATING_TASK_SUCCESS,
|
||||
ARCHIVE_AGGREGATING_TASK_SUCCESS,
|
||||
DELETE_AGGREGATING_TASK_SUCCESS,
|
||||
DELETE_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
DELETE_ALL_AGGREGATING_TASKS_ERROR,
|
||||
DELETE_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
DELETE_ALL_ARCHIVED_TASKS_BEGIN,
|
||||
DELETE_ALL_ARCHIVED_TASKS_ERROR,
|
||||
DELETE_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
DELETE_ALL_COMPLETED_TASKS_BEGIN,
|
||||
DELETE_ALL_COMPLETED_TASKS_ERROR,
|
||||
DELETE_ALL_COMPLETED_TASKS_SUCCESS,
|
||||
DELETE_ALL_PENDING_TASKS_BEGIN,
|
||||
DELETE_ALL_PENDING_TASKS_ERROR,
|
||||
DELETE_ALL_PENDING_TASKS_SUCCESS,
|
||||
DELETE_ALL_RETRY_TASKS_BEGIN,
|
||||
DELETE_ALL_RETRY_TASKS_ERROR,
|
||||
DELETE_ALL_RETRY_TASKS_SUCCESS,
|
||||
DELETE_ALL_SCHEDULED_TASKS_BEGIN,
|
||||
DELETE_ALL_SCHEDULED_TASKS_ERROR,
|
||||
DELETE_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
DELETE_ARCHIVED_TASK_BEGIN,
|
||||
DELETE_ARCHIVED_TASK_ERROR,
|
||||
DELETE_ARCHIVED_TASK_SUCCESS,
|
||||
DELETE_COMPLETED_TASK_BEGIN,
|
||||
DELETE_COMPLETED_TASK_ERROR,
|
||||
DELETE_COMPLETED_TASK_SUCCESS,
|
||||
DELETE_PENDING_TASK_BEGIN,
|
||||
DELETE_PENDING_TASK_ERROR,
|
||||
DELETE_PENDING_TASK_SUCCESS,
|
||||
DELETE_RETRY_TASK_BEGIN,
|
||||
DELETE_RETRY_TASK_ERROR,
|
||||
DELETE_RETRY_TASK_SUCCESS,
|
||||
DELETE_SCHEDULED_TASK_BEGIN,
|
||||
DELETE_SCHEDULED_TASK_ERROR,
|
||||
DELETE_SCHEDULED_TASK_SUCCESS,
|
||||
GET_TASK_INFO_BEGIN,
|
||||
GET_TASK_INFO_ERROR,
|
||||
GET_TASK_INFO_SUCCESS,
|
||||
LIST_ACTIVE_TASKS_BEGIN,
|
||||
LIST_ACTIVE_TASKS_ERROR,
|
||||
LIST_ACTIVE_TASKS_SUCCESS,
|
||||
LIST_AGGREGATING_TASKS_BEGIN,
|
||||
LIST_AGGREGATING_TASKS_ERROR,
|
||||
LIST_AGGREGATING_TASKS_SUCCESS,
|
||||
LIST_ARCHIVED_TASKS_BEGIN,
|
||||
LIST_ARCHIVED_TASKS_ERROR,
|
||||
LIST_ARCHIVED_TASKS_SUCCESS,
|
||||
LIST_COMPLETED_TASKS_BEGIN,
|
||||
LIST_COMPLETED_TASKS_ERROR,
|
||||
LIST_COMPLETED_TASKS_SUCCESS,
|
||||
LIST_PENDING_TASKS_BEGIN,
|
||||
LIST_PENDING_TASKS_ERROR,
|
||||
LIST_PENDING_TASKS_SUCCESS,
|
||||
LIST_RETRY_TASKS_BEGIN,
|
||||
LIST_RETRY_TASKS_ERROR,
|
||||
LIST_RETRY_TASKS_SUCCESS,
|
||||
LIST_SCHEDULED_TASKS_BEGIN,
|
||||
LIST_SCHEDULED_TASKS_ERROR,
|
||||
LIST_SCHEDULED_TASKS_SUCCESS,
|
||||
RUN_AGGREGATING_TASK_BEGIN,
|
||||
RUN_AGGREGATING_TASK_ERROR,
|
||||
RUN_AGGREGATING_TASK_SUCCESS,
|
||||
RUN_ALL_AGGREGATING_TASKS_BEGIN,
|
||||
RUN_ALL_AGGREGATING_TASKS_ERROR,
|
||||
RUN_ALL_AGGREGATING_TASKS_SUCCESS,
|
||||
RUN_ALL_ARCHIVED_TASKS_BEGIN,
|
||||
RUN_ALL_ARCHIVED_TASKS_ERROR,
|
||||
RUN_ALL_ARCHIVED_TASKS_SUCCESS,
|
||||
RUN_ALL_RETRY_TASKS_BEGIN,
|
||||
RUN_ALL_RETRY_TASKS_ERROR,
|
||||
RUN_ALL_RETRY_TASKS_SUCCESS,
|
||||
RUN_ALL_SCHEDULED_TASKS_BEGIN,
|
||||
RUN_ALL_SCHEDULED_TASKS_ERROR,
|
||||
RUN_ALL_SCHEDULED_TASKS_SUCCESS,
|
||||
RUN_ARCHIVED_TASK_BEGIN,
|
||||
RUN_ARCHIVED_TASK_ERROR,
|
||||
RUN_ARCHIVED_TASK_SUCCESS,
|
||||
RUN_RETRY_TASK_BEGIN,
|
||||
RUN_RETRY_TASK_ERROR,
|
||||
RUN_RETRY_TASK_SUCCESS,
|
||||
RUN_SCHEDULED_TASK_BEGIN,
|
||||
RUN_SCHEDULED_TASK_ERROR,
|
||||
RUN_SCHEDULED_TASK_SUCCESS,
|
||||
TasksActionTypes,
|
||||
} from "../actions/tasksActions";
|
||||
import { TaskInfo } from "../api";
|
||||
import { filterReducer } from "./filterReducer";
|
||||
|
||||
export interface TaskInfoExtended extends TaskInfo {
|
||||
// Indicates that a request has been sent for this
|
||||
@ -174,7 +175,7 @@ export interface TaskInfoExtended extends TaskInfo {
|
||||
canceling?: boolean;
|
||||
}
|
||||
|
||||
interface TasksState {
|
||||
export interface TasksState {
|
||||
activeTasks: {
|
||||
loading: boolean;
|
||||
batchActionPending: boolean;
|
||||
@ -230,6 +231,12 @@ interface TasksState {
|
||||
error: string;
|
||||
data?: TaskInfo;
|
||||
};
|
||||
filterOp?: {
|
||||
done: boolean;
|
||||
processedTasks: number;
|
||||
result: TaskInfo[];
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const initialState: TasksState = {
|
||||
@ -293,6 +300,7 @@ function tasksReducer(
|
||||
state = initialState,
|
||||
action: TasksActionTypes
|
||||
): TasksState {
|
||||
state = filterReducer(state, action);
|
||||
switch (action.type) {
|
||||
case GET_TASK_INFO_BEGIN:
|
||||
return {
|
||||
|
@ -32,6 +32,12 @@ export type AppState = ReturnType<typeof rootReducer>;
|
||||
const store = configureStore({
|
||||
reducer: rootReducer,
|
||||
preloadedState,
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
// Disable debug middleware for tasks.filterOp as it may contain large state
|
||||
getDefaultMiddleware({
|
||||
immutableCheck: { ignoredPaths: ["tasks.filterOp"] },
|
||||
serializableCheck: { ignoredPaths: ["tasks.filterOp"] },
|
||||
}),
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
Loading…
Reference in New Issue
Block a user