From d8998de4ebe83a32246d193022d4de0c60b1c3bb Mon Sep 17 00:00:00 2001 From: Aaron Chong Date: Mon, 19 Aug 2024 11:02:48 +0800 Subject: [PATCH] Configurable schedule event color based on task type (#998) * Allow configurable schedule event color based on task type Signed-off-by: Aaron Chong * Document use of CSS color string Signed-off-by: Aaron Chong --------- Signed-off-by: Aaron Chong --- packages/dashboard/app-config.schema.json | 4 ++++ packages/dashboard/src/app-config.ts | 20 +++++++++++-------- .../components/tasks/task-schedule-utils.ts | 19 ++++++++++++++++++ .../src/components/tasks/task-schedule.tsx | 11 ++++++++-- .../lib/tasks/create-task.tsx | 1 + .../lib/tasks/types/compose-clean.tsx | 1 + .../lib/tasks/types/custom-compose.tsx | 1 + .../lib/tasks/types/delivery-custom.tsx | 3 +++ .../lib/tasks/types/delivery.tsx | 1 + .../lib/tasks/types/patrol.tsx | 1 + 10 files changed, 52 insertions(+), 10 deletions(-) diff --git a/packages/dashboard/app-config.schema.json b/packages/dashboard/app-config.schema.json index 567d67695..1b5e02262 100644 --- a/packages/dashboard/app-config.schema.json +++ b/packages/dashboard/app-config.schema.json @@ -113,6 +113,10 @@ "description": "Configure the display name for the task definition.", "type": "string" }, + "scheduleEventColor": { + "description": "The color of the event when rendered on the task scheduler in the form of a CSS color string.", + "type": "string" + }, "taskDefinitionId": { "description": "The task definition to configure.", "enum": [ diff --git a/packages/dashboard/src/app-config.ts b/packages/dashboard/src/app-config.ts index 66d12903c..6d217c596 100644 --- a/packages/dashboard/src/app-config.ts +++ b/packages/dashboard/src/app-config.ts @@ -49,6 +49,11 @@ export interface TaskResource { * Configure the display name for the task definition. */ displayName?: string; + + /** + * The color of the event when rendered on the task scheduler in the form of a CSS color string. + */ + scheduleEventColor?: string; } export interface StubAuthConfig {} @@ -191,16 +196,15 @@ export const ResourcesContext = React.createContext(appConfig.resourc // FIXME(koonepng): This should be fully definition in app config when the dashboard actually // supports configurating all the fields. export const allowedTasks: TaskDefinition[] = appConfig.allowedTasks.map((taskResource) => { - const defaultTaskDefinition = getDefaultTaskDefinition(taskResource.taskDefinitionId); - if (!defaultTaskDefinition) { + const taskDefinition = getDefaultTaskDefinition(taskResource.taskDefinitionId); + if (!taskDefinition) { throw Error(`Invalid tasks configured for dashboard: [${taskResource.taskDefinitionId}]`); } if (taskResource.displayName !== undefined) { - return { - ...defaultTaskDefinition, - taskDisplayName: taskResource.displayName, - }; - } else { - return defaultTaskDefinition; + taskDefinition.taskDisplayName = taskResource.displayName; + } + if (taskResource.scheduleEventColor !== undefined) { + taskDefinition.scheduleEventColor = taskResource.scheduleEventColor; } + return taskDefinition; }); diff --git a/packages/dashboard/src/components/tasks/task-schedule-utils.ts b/packages/dashboard/src/components/tasks/task-schedule-utils.ts index 60c78d198..1990895c0 100644 --- a/packages/dashboard/src/components/tasks/task-schedule-utils.ts +++ b/packages/dashboard/src/components/tasks/task-schedule-utils.ts @@ -48,6 +48,7 @@ export const scheduleToEvents = ( task: ScheduledTask, getEventId: () => number, getEventTitle: () => string, + getEventColor: () => string | undefined, ): ProcessedEvent[] => { if (!schedule.at) { console.warn('Unable to convert schedule without [at] to an event'); @@ -119,6 +120,7 @@ export const scheduleToEvents = ( end: addMinutes(cur, 45), event_id: getEventId(), title: getEventTitle(), + color: getEventColor(), }); } } @@ -191,6 +193,23 @@ export const getScheduledTaskTitle = ( return shortDescription; }; +export const getScheduledTaskColor = ( + task: ScheduledTask, + supportedTasks?: TaskDefinition[], +): string | undefined => { + const taskBookingLabel = getTaskBookingLabelFromTaskRequest(task.task_request); + + let customEventColor: string | undefined = undefined; + if (supportedTasks && taskBookingLabel && 'task_definition_id' in taskBookingLabel) { + for (const s of supportedTasks) { + if (s.taskDefinitionId === taskBookingLabel['task_definition_id']) { + customEventColor = s.scheduleEventColor; + } + } + } + return customEventColor; +}; + // Pad a number to 2 digits function pad(n: number): string { return `${Math.floor(Math.abs(n))}`.padStart(2, '0'); diff --git a/packages/dashboard/src/components/tasks/task-schedule.tsx b/packages/dashboard/src/components/tasks/task-schedule.tsx index 9f4704520..cfbeedd5a 100644 --- a/packages/dashboard/src/components/tasks/task-schedule.tsx +++ b/packages/dashboard/src/components/tasks/task-schedule.tsx @@ -27,6 +27,7 @@ import { AppEvents } from '../app-events'; import { RmfAppContext } from '../rmf-app'; import { apiScheduleToSchedule, + getScheduledTaskColor, getScheduledTaskTitle, scheduleToEvents, scheduleWithSelectedDay, @@ -132,8 +133,14 @@ export const TaskSchedule = () => { eventsMap.current = {}; return tasks.flatMap((t: ScheduledTask) => t.schedules.flatMap((s: ApiSchedule) => { - const events = scheduleToEvents(params.start, params.end, s, t, getEventId, () => - getScheduledTaskTitle(t, allowedTasks), + const events = scheduleToEvents( + params.start, + params.end, + s, + t, + getEventId, + () => getScheduledTaskTitle(t, allowedTasks), + () => getScheduledTaskColor(t, allowedTasks), ); events.forEach((ev) => { eventsMap.current[Number(ev.event_id)] = t; diff --git a/packages/react-components/lib/tasks/create-task.tsx b/packages/react-components/lib/tasks/create-task.tsx index e783106b3..86c8b652b 100644 --- a/packages/react-components/lib/tasks/create-task.tsx +++ b/packages/react-components/lib/tasks/create-task.tsx @@ -88,6 +88,7 @@ export interface TaskDefinition { taskDefinitionId: string; taskDisplayName: string; requestCategory: string; + scheduleEventColor?: string; } export type TaskDescription = diff --git a/packages/react-components/lib/tasks/types/compose-clean.tsx b/packages/react-components/lib/tasks/types/compose-clean.tsx index 958a2bd10..1318cb301 100644 --- a/packages/react-components/lib/tasks/types/compose-clean.tsx +++ b/packages/react-components/lib/tasks/types/compose-clean.tsx @@ -8,6 +8,7 @@ export const ComposeCleanTaskDefinition: TaskDefinition = { taskDefinitionId: 'compose-clean', taskDisplayName: 'Clean', requestCategory: 'compose', + scheduleEventColor: undefined, }; interface GoToPlaceActivity { diff --git a/packages/react-components/lib/tasks/types/custom-compose.tsx b/packages/react-components/lib/tasks/types/custom-compose.tsx index dec57fc4f..c06df7da1 100644 --- a/packages/react-components/lib/tasks/types/custom-compose.tsx +++ b/packages/react-components/lib/tasks/types/custom-compose.tsx @@ -8,6 +8,7 @@ export const CustomComposeTaskDefinition: TaskDefinition = { taskDefinitionId: 'custom_compose', taskDisplayName: 'Custom Compose Task', requestCategory: 'compose', + scheduleEventColor: undefined, }; export type CustomComposeTaskDescription = string; diff --git a/packages/react-components/lib/tasks/types/delivery-custom.tsx b/packages/react-components/lib/tasks/types/delivery-custom.tsx index e25e976eb..d6121b2e9 100644 --- a/packages/react-components/lib/tasks/types/delivery-custom.tsx +++ b/packages/react-components/lib/tasks/types/delivery-custom.tsx @@ -9,18 +9,21 @@ export const DeliveryPickupTaskDefinition: TaskDefinition = { taskDefinitionId: 'delivery_pickup', taskDisplayName: 'Delivery - 1:1', requestCategory: 'compose', + scheduleEventColor: undefined, }; export const DeliverySequentialLotPickupTaskDefinition: TaskDefinition = { taskDefinitionId: 'delivery_sequential_lot_pickup', taskDisplayName: 'Delivery - Sequential lot pick up', requestCategory: 'compose', + scheduleEventColor: undefined, }; export const DeliveryAreaPickupTaskDefinition: TaskDefinition = { taskDefinitionId: 'delivery_area_pickup', taskDisplayName: 'Delivery - Area pick up', requestCategory: 'compose', + scheduleEventColor: undefined, }; export interface LotPickupActivity { diff --git a/packages/react-components/lib/tasks/types/delivery.tsx b/packages/react-components/lib/tasks/types/delivery.tsx index ed553f5af..a3bbdab50 100644 --- a/packages/react-components/lib/tasks/types/delivery.tsx +++ b/packages/react-components/lib/tasks/types/delivery.tsx @@ -10,6 +10,7 @@ export const DeliveryTaskDefinition: TaskDefinition = { taskDefinitionId: 'delivery', taskDisplayName: 'Delivery', requestCategory: 'delivery', + scheduleEventColor: undefined, }; interface TaskPlace { diff --git a/packages/react-components/lib/tasks/types/patrol.tsx b/packages/react-components/lib/tasks/types/patrol.tsx index a179cf162..703ea5455 100644 --- a/packages/react-components/lib/tasks/types/patrol.tsx +++ b/packages/react-components/lib/tasks/types/patrol.tsx @@ -22,6 +22,7 @@ export const PatrolTaskDefinition: TaskDefinition = { taskDefinitionId: 'patrol', taskDisplayName: 'Patrol', requestCategory: 'patrol', + scheduleEventColor: undefined, }; export interface PatrolTaskDescription {