Skip to content

Commit

Permalink
✨ Implement the Task Manager drawer (#1955)
Browse files Browse the repository at this point in the history
Resolves: #1938

Add a queued tasks count badge and a task list drawer.
  - Add a `TaskManagerContext` to control the count indicator and
    visibility of the drawer. This is a top level context so the task
    manager is available on all pages. The context itself monitors the task
    queue report endpoint[^1] that drives the notification badge count.

  - Use the standard `NotificationDrawer` attached to the `Page` layout to
    render the task manager item drawer.

  - The `TaskNotificationBadge` is integrated to the application's
    `HeaderApp`.

  - The `TaskManagerDrawer` shows the list of currently "queued" tasks[^2]
    in task id descending sort order (most recently created tasks on the
    top).

  - Each task item is rendered in a "collapsed" state and after a click
    will render "expanded". The expanded state include the started
    timestamp.

  - **_Note 1:_** Until fetch more / infinite scroll is implemented in the
    task manager drawer list, only the first 20 queued tasks will be
    displayed.

  - **_Note 2:_** Task actions need to be added to the task items. These
    should reuse the same set of actions as the task table in #1957.

Related changes:
  - Update the `HeaderApp` to handle visibility of masthead toolbar items
    at the `ToolbarGroup` level.

  - Rename `SSOMenu` to `SsoToolbarItem`.

  - Updated the typing on a few task related API functions.


[^1]: konveyor/tackle2-hub#641
[^2]: konveyor/tackle2-hub#640

---------

Signed-off-by: Scott J Dickerson <sdickers@redhat.com>
  • Loading branch information
sjd78 authored Jun 20, 2024
1 parent eeea000 commit 5b2352d
Show file tree
Hide file tree
Showing 14 changed files with 653 additions and 137 deletions.
9 changes: 6 additions & 3 deletions client/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import { BrowserRouter } from "react-router-dom";
import { AppRoutes } from "./Routes";
import { DefaultLayout } from "./layout";
import { NotificationsProvider } from "./components/NotificationsContext";
import { TaskManagerProvider } from "./components/task-manager/TaskManagerContext";

import "./app.css";

const App: React.FC = () => {
return (
<BrowserRouter>
<NotificationsProvider>
<DefaultLayout>
<AppRoutes />
</DefaultLayout>
<TaskManagerProvider>
<DefaultLayout>
<AppRoutes />
</DefaultLayout>
</TaskManagerProvider>
</NotificationsProvider>
</BrowserRouter>
);
Expand Down
13 changes: 13 additions & 0 deletions client/src/app/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,19 @@ export interface Taskgroup {
tasks: TaskgroupTask[];
}

export interface TaskQueue {
/** Total number of tasks scheduled */
total: number;
/** number of tasks ready to run */
ready: number;
/** number of postponed tasks */
postponed: number;
/** number of tasks with pods created awaiting node scheduler */
pending: number;
/** number of tasks with running pods */
running: number;
}

export interface Cache {
path: string;
capacity: string;
Expand Down
44 changes: 25 additions & 19 deletions client/src/app/api/rest.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,52 @@
import axios, { AxiosPromise, RawAxiosRequestHeaders } from "axios";

import {
AnalysisAppDependency,
AnalysisAppReport,
AnalysisDependency,
BaseAnalysisRuleReport,
BaseAnalysisIssueReport,
AnalysisIssue,
AnalysisFileReport,
AnalysisIncident,
AnalysisIssue,
Application,
ApplicationAdoptionPlan,
ApplicationDependency,
ApplicationImport,
ApplicationImportSummary,
Archetype,
Assessment,
BaseAnalysisIssueReport,
BaseAnalysisRuleReport,
BusinessService,
Cache,
HubFile,
HubPaginatedResult,
HubRequestParams,
Identity,
InitialAssessment,
IReadFile,
Tracker,
JobFunction,
MigrationWave,
MimeType,
New,
Proxy,
Questionnaire,
Ref,
Review,
Setting,
SettingTypes,
Stakeholder,
StakeholderGroup,
Tag,
TagCategory,
Target,
Task,
Taskgroup,
MigrationWave,
TaskQueue,
Ticket,
New,
Ref,
Tracker,
TrackerProject,
TrackerProjectIssuetype,
UnstructuredFact,
AnalysisAppDependency,
AnalysisAppReport,
Target,
HubFile,
Questionnaire,
Archetype,
InitialAssessment,
MimeType,
} from "./models";
import { serializeRequestParamsForHub } from "@app/hooks/table-controls";

Expand Down Expand Up @@ -332,7 +333,7 @@ export function getTaskById(id: number): Promise<Task> {

export function getTaskByIdAndFormat(
id: number,
format: string,
format: "json" | "yaml",
merged: boolean = false
): Promise<string> {
const isYaml = format === "yaml";
Expand All @@ -345,7 +346,7 @@ export function getTaskByIdAndFormat(
}

return axios
.get(url, {
.get<Task | string>(url, {
headers: headers,
responseType: responseType,
})
Expand All @@ -362,10 +363,15 @@ export const getTasks = () =>
export const getServerTasks = (params: HubRequestParams = {}) =>
getHubPaginatedResult<Task>(TASKS, params);

export const deleteTask = (id: number) => axios.delete<Task>(`${TASKS}/${id}`);
export const deleteTask = (id: number) => axios.delete<void>(`${TASKS}/${id}`);

export const cancelTask = (id: number) =>
axios.put<Task>(`${TASKS}/${id}/cancel`);
axios.put<void>(`${TASKS}/${id}/cancel`);

export const getTaskQueue = (addon?: string): Promise<TaskQueue> =>
axios
.get<TaskQueue>(`${TASKS}/report/queue`, { params: { addon } })
.then(({ data }) => data);

export const createTaskgroup = (obj: Taskgroup) =>
axios.post<Taskgroup>(TASKGROUPS, obj).then((response) => response.data);
Expand Down
48 changes: 48 additions & 0 deletions client/src/app/components/task-manager/TaskManagerContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { useFetchTaskQueue } from "@app/queries/tasks";
import React, { useContext, useMemo, useState } from "react";

interface TaskManagerContextProps {
/** Count of the currently "queued" Tasks */
queuedCount: number;

/** Is the task manager drawer currently visible? */
isExpanded: boolean;

/** Control if the task manager drawer is visible */
setIsExpanded: (value: boolean) => void;
}

const TaskManagerContext = React.createContext<TaskManagerContextProps>({
queuedCount: 0,

isExpanded: false,
setIsExpanded: () => undefined,
});

export const useTaskManagerContext = () => {
const values = useContext(TaskManagerContext);

return values;
};

export const TaskManagerProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const { taskQueue } = useFetchTaskQueue();
const [isExpanded, setIsExpanded] = useState(false);

const contextValue = useMemo(
() => ({
queuedCount: taskQueue.total,
isExpanded,
setIsExpanded,
}),
[taskQueue.total, isExpanded, setIsExpanded]
);

return (
<TaskManagerContext.Provider value={contextValue}>
{children}
</TaskManagerContext.Provider>
);
};
3 changes: 3 additions & 0 deletions client/src/app/components/task-manager/TaskManagerDrawer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.task-manager-item-collapsed .pf-v5-c-notification-drawer__list-item-header {
margin-bottom: 0;
}
Loading

0 comments on commit 5b2352d

Please sign in to comment.