diff --git a/packages/api-client/lib/openapi/api.ts b/packages/api-client/lib/openapi/api.ts index 20bb5a3c4..db5e1689a 100644 --- a/packages/api-client/lib/openapi/api.ts +++ b/packages/api-client/lib/openapi/api.ts @@ -463,6 +463,67 @@ export interface ApiServerModelsTortoiseModelsTasksTaskFavoriteLeaf { */ user: string; } +/** + * + * @export + * @interface ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ +export interface ApiServerModelsTortoiseModelsTasksTaskStateLeaf { + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + id_: string; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + assigned_to?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + unix_millis_start_time?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + unix_millis_finish_time?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + status?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + unix_millis_request_time?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + requester?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + pickup?: string | null; + /** + * + * @type {string} + * @memberof ApiServerModelsTortoiseModelsTasksTaskStateLeaf + */ + destination?: string | null; +} /** * Which agent (robot) is the task assigned to * @export @@ -8375,6 +8436,47 @@ export const TasksApiAxiosParamCreator = function (configuration?: Configuration options: localVarRequestOptions, }; }, + /** + * Available in socket.io + * @summary Get Task Queue Entry + * @param {string} taskId task_id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTaskQueueEntryTasksTaskIdQueueEntryGet: async ( + taskId: string, + options: AxiosRequestConfig = {}, + ): Promise => { + // verify required parameter 'taskId' is not null or undefined + assertParamExists('getTaskQueueEntryTasksTaskIdQueueEntryGet', 'taskId', taskId); + const localVarPath = `/tasks/{task_id}/queue_entry`.replace( + `{${'task_id'}}`, + encodeURIComponent(String(taskId)), + ); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Get Task Request @@ -9086,6 +9188,118 @@ export const TasksApiAxiosParamCreator = function (configuration?: Configuration options: localVarRequestOptions, }; }, + /** + * + * @summary Query Task Queue Entry + * @param {string} [taskId] comma separated list of task ids + * @param {string} [category] comma separated list of task categories + * @param {string} [requester] comma separated list of requester names + * @param {string} [pickup] comma separated list of pickup names + * @param {string} [destination] comma separated list of destination names + * @param {string} [assignedTo] comma separated list of assigned robot names + * @param {string} [status] comma separated list of statuses + * @param {string} [requestTimeBetween] The period of request time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [startTimeBetween] The period of starting time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [finishTimeBetween] The period of finishing time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. \"-60000\" - Fetches logs in the last minute. + * @param {number} [limit] defaults to 100 + * @param {number} [offset] defaults to 0 + * @param {string} [orderBy] common separated list of fields to order by, prefix with \'-\' to sort descendingly. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + queryTaskQueueEntryTasksQueueEntryGet: async ( + taskId?: string, + category?: string, + requester?: string, + pickup?: string, + destination?: string, + assignedTo?: string, + status?: string, + requestTimeBetween?: string, + startTimeBetween?: string, + finishTimeBetween?: string, + limit?: number, + offset?: number, + orderBy?: string, + options: AxiosRequestConfig = {}, + ): Promise => { + const localVarPath = `/tasks/queue_entry`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + if (taskId !== undefined) { + localVarQueryParameter['task_id'] = taskId; + } + + if (category !== undefined) { + localVarQueryParameter['category'] = category; + } + + if (requester !== undefined) { + localVarQueryParameter['requester'] = requester; + } + + if (pickup !== undefined) { + localVarQueryParameter['pickup'] = pickup; + } + + if (destination !== undefined) { + localVarQueryParameter['destination'] = destination; + } + + if (assignedTo !== undefined) { + localVarQueryParameter['assigned_to'] = assignedTo; + } + + if (status !== undefined) { + localVarQueryParameter['status'] = status; + } + + if (requestTimeBetween !== undefined) { + localVarQueryParameter['request_time_between'] = requestTimeBetween; + } + + if (startTimeBetween !== undefined) { + localVarQueryParameter['start_time_between'] = startTimeBetween; + } + + if (finishTimeBetween !== undefined) { + localVarQueryParameter['finish_time_between'] = finishTimeBetween; + } + + if (limit !== undefined) { + localVarQueryParameter['limit'] = limit; + } + + if (offset !== undefined) { + localVarQueryParameter['offset'] = offset; + } + + if (orderBy !== undefined) { + localVarQueryParameter['order_by'] = orderBy; + } + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Query Task Requests @@ -9458,6 +9672,26 @@ export const TasksApiFp = function (configuration?: Configuration) { ); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * Available in socket.io + * @summary Get Task Queue Entry + * @param {string} taskId task_id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTaskQueueEntryTasksTaskIdQueueEntryGet( + taskId: string, + options?: AxiosRequestConfig, + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string, + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getTaskQueueEntryTasksTaskIdQueueEntryGet(taskId, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @summary Get Task Request @@ -9732,6 +9966,65 @@ export const TasksApiFp = function (configuration?: Configuration) { ); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @summary Query Task Queue Entry + * @param {string} [taskId] comma separated list of task ids + * @param {string} [category] comma separated list of task categories + * @param {string} [requester] comma separated list of requester names + * @param {string} [pickup] comma separated list of pickup names + * @param {string} [destination] comma separated list of destination names + * @param {string} [assignedTo] comma separated list of assigned robot names + * @param {string} [status] comma separated list of statuses + * @param {string} [requestTimeBetween] The period of request time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [startTimeBetween] The period of starting time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [finishTimeBetween] The period of finishing time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. \"-60000\" - Fetches logs in the last minute. + * @param {number} [limit] defaults to 100 + * @param {number} [offset] defaults to 0 + * @param {string} [orderBy] common separated list of fields to order by, prefix with \'-\' to sort descendingly. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async queryTaskQueueEntryTasksQueueEntryGet( + taskId?: string, + category?: string, + requester?: string, + pickup?: string, + destination?: string, + assignedTo?: string, + status?: string, + requestTimeBetween?: string, + startTimeBetween?: string, + finishTimeBetween?: string, + limit?: number, + offset?: number, + orderBy?: string, + options?: AxiosRequestConfig, + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string, + ) => AxiosPromise> + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.queryTaskQueueEntryTasksQueueEntryGet( + taskId, + category, + requester, + pickup, + destination, + assignedTo, + status, + requestTimeBetween, + startTimeBetween, + finishTimeBetween, + limit, + offset, + orderBy, + options, + ); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @summary Query Task Requests @@ -9962,6 +10255,21 @@ export const TasksApiFactory = function ( .getTaskLogTasksTaskIdLogGet(taskId, between, options) .then((request) => request(axios, basePath)); }, + /** + * Available in socket.io + * @summary Get Task Queue Entry + * @param {string} taskId task_id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTaskQueueEntryTasksTaskIdQueueEntryGet( + taskId: string, + options?: any, + ): AxiosPromise { + return localVarFp + .getTaskQueueEntryTasksTaskIdQueueEntryGet(taskId, options) + .then((request) => request(axios, basePath)); + }, /** * * @summary Get Task Request @@ -10181,6 +10489,60 @@ export const TasksApiFactory = function ( .postUndoSkipPhaseTasksUndoSkipPhasePost(undoPhaseSkipRequest, options) .then((request) => request(axios, basePath)); }, + /** + * + * @summary Query Task Queue Entry + * @param {string} [taskId] comma separated list of task ids + * @param {string} [category] comma separated list of task categories + * @param {string} [requester] comma separated list of requester names + * @param {string} [pickup] comma separated list of pickup names + * @param {string} [destination] comma separated list of destination names + * @param {string} [assignedTo] comma separated list of assigned robot names + * @param {string} [status] comma separated list of statuses + * @param {string} [requestTimeBetween] The period of request time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [startTimeBetween] The period of starting time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [finishTimeBetween] The period of finishing time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. \"-60000\" - Fetches logs in the last minute. + * @param {number} [limit] defaults to 100 + * @param {number} [offset] defaults to 0 + * @param {string} [orderBy] common separated list of fields to order by, prefix with \'-\' to sort descendingly. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + queryTaskQueueEntryTasksQueueEntryGet( + taskId?: string, + category?: string, + requester?: string, + pickup?: string, + destination?: string, + assignedTo?: string, + status?: string, + requestTimeBetween?: string, + startTimeBetween?: string, + finishTimeBetween?: string, + limit?: number, + offset?: number, + orderBy?: string, + options?: any, + ): AxiosPromise> { + return localVarFp + .queryTaskQueueEntryTasksQueueEntryGet( + taskId, + category, + requester, + pickup, + destination, + assignedTo, + status, + requestTimeBetween, + startTimeBetween, + finishTimeBetween, + limit, + offset, + orderBy, + options, + ) + .then((request) => request(axios, basePath)); + }, /** * * @summary Query Task Requests @@ -10405,6 +10767,20 @@ export class TasksApi extends BaseAPI { .then((request) => request(this.axios, this.basePath)); } + /** + * Available in socket.io + * @summary Get Task Queue Entry + * @param {string} taskId task_id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public getTaskQueueEntryTasksTaskIdQueueEntryGet(taskId: string, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .getTaskQueueEntryTasksTaskIdQueueEntryGet(taskId, options) + .then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Get Task Request @@ -10654,6 +11030,62 @@ export class TasksApi extends BaseAPI { .then((request) => request(this.axios, this.basePath)); } + /** + * + * @summary Query Task Queue Entry + * @param {string} [taskId] comma separated list of task ids + * @param {string} [category] comma separated list of task categories + * @param {string} [requester] comma separated list of requester names + * @param {string} [pickup] comma separated list of pickup names + * @param {string} [destination] comma separated list of destination names + * @param {string} [assignedTo] comma separated list of assigned robot names + * @param {string} [status] comma separated list of statuses + * @param {string} [requestTimeBetween] The period of request time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [startTimeBetween] The period of starting time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. + * @param {string} [finishTimeBetween] The period of finishing time to fetch, in unix millis. This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive. Example: \"1000,2000\" - Fetches logs between unix millis 1000 and 2000. \"-60000\" - Fetches logs in the last minute. + * @param {number} [limit] defaults to 100 + * @param {number} [offset] defaults to 0 + * @param {string} [orderBy] common separated list of fields to order by, prefix with \'-\' to sort descendingly. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public queryTaskQueueEntryTasksQueueEntryGet( + taskId?: string, + category?: string, + requester?: string, + pickup?: string, + destination?: string, + assignedTo?: string, + status?: string, + requestTimeBetween?: string, + startTimeBetween?: string, + finishTimeBetween?: string, + limit?: number, + offset?: number, + orderBy?: string, + options?: AxiosRequestConfig, + ) { + return TasksApiFp(this.configuration) + .queryTaskQueueEntryTasksQueueEntryGet( + taskId, + category, + requester, + pickup, + destination, + assignedTo, + status, + requestTimeBetween, + startTimeBetween, + finishTimeBetween, + limit, + offset, + orderBy, + options, + ) + .then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Query Task Requests diff --git a/packages/api-client/lib/version.ts b/packages/api-client/lib/version.ts index fd7b7b378..3cde0a954 100644 --- a/packages/api-client/lib/version.ts +++ b/packages/api-client/lib/version.ts @@ -3,6 +3,6 @@ import { version as rmfModelVer } from 'rmf-models'; export const version = { rmfModels: rmfModelVer, - rmfServer: '4f6e8567a0a3a44896f60898e84130c2be8a94c7', + rmfServer: '3641034b187d5457610280b42b05663b25444104', openapiGenerator: '6.2.1', }; diff --git a/packages/api-client/schema/index.ts b/packages/api-client/schema/index.ts index 6c36fad06..ef74ff49d 100644 --- a/packages/api-client/schema/index.ts +++ b/packages/api-client/schema/index.ts @@ -1037,6 +1037,226 @@ export default { }, }, }, + '/tasks/queue_entry': { + get: { + tags: ['Tasks'], + summary: 'Query Task Queue Entry', + operationId: 'query_task_queue_entry_tasks_queue_entry_get', + parameters: [ + { + description: 'comma separated list of task ids', + required: false, + schema: { + title: 'Task Id', + type: 'string', + description: 'comma separated list of task ids', + }, + name: 'task_id', + in: 'query', + }, + { + description: 'comma separated list of task categories', + required: false, + schema: { + title: 'Category', + type: 'string', + description: 'comma separated list of task categories', + }, + name: 'category', + in: 'query', + }, + { + description: 'comma separated list of requester names', + required: false, + schema: { + title: 'Requester', + type: 'string', + description: 'comma separated list of requester names', + }, + name: 'requester', + in: 'query', + }, + { + description: 'comma separated list of pickup names', + required: false, + schema: { + title: 'Pickup', + type: 'string', + description: 'comma separated list of pickup names', + }, + name: 'pickup', + in: 'query', + }, + { + description: 'comma separated list of destination names', + required: false, + schema: { + title: 'Destination', + type: 'string', + description: 'comma separated list of destination names', + }, + name: 'destination', + in: 'query', + }, + { + description: 'comma separated list of assigned robot names', + required: false, + schema: { + title: 'Assigned To', + type: 'string', + description: 'comma separated list of assigned robot names', + }, + name: 'assigned_to', + in: 'query', + }, + { + description: 'comma separated list of statuses', + required: false, + schema: { + title: 'Status', + type: 'string', + description: 'comma separated list of statuses', + }, + name: 'status', + in: 'query', + }, + { + description: + '\n The period of request time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n ', + required: false, + schema: { + title: 'Request Time Between', + type: 'string', + description: + '\n The period of request time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n ', + }, + name: 'request_time_between', + in: 'query', + }, + { + description: + '\n The period of starting time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n ', + required: false, + schema: { + title: 'Start Time Between', + type: 'string', + description: + '\n The period of starting time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n ', + }, + name: 'start_time_between', + in: 'query', + }, + { + description: + '\n The period of finishing time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n "-60000" - Fetches logs in the last minute.\n ', + required: false, + schema: { + title: 'Finish Time Between', + type: 'string', + description: + '\n The period of finishing time to fetch, in unix millis.\n\n This must be a comma separated string, \'X,Y\' to fetch between X millis and Y millis inclusive.\n\n Example:\n "1000,2000" - Fetches logs between unix millis 1000 and 2000.\n "-60000" - Fetches logs in the last minute.\n ', + }, + name: 'finish_time_between', + in: 'query', + }, + { + description: 'defaults to 100', + required: false, + schema: { + title: 'Limit', + maximum: 1000.0, + exclusiveMinimum: 0.0, + type: 'integer', + description: 'defaults to 100', + }, + name: 'limit', + in: 'query', + }, + { + description: 'defaults to 0', + required: false, + schema: { + title: 'Offset', + minimum: 0.0, + type: 'integer', + description: 'defaults to 0', + }, + name: 'offset', + in: 'query', + }, + { + description: + "common separated list of fields to order by, prefix with '-' to sort descendingly.", + required: false, + schema: { + title: 'Order By', + type: 'string', + description: + "common separated list of fields to order by, prefix with '-' to sort descendingly.", + }, + name: 'order_by', + in: 'query', + }, + ], + responses: { + '200': { + description: 'Successful Response', + content: { + 'application/json': { + schema: { + title: 'Response Query Task Queue Entry Tasks Queue Entry Get', + type: 'array', + items: { + $ref: '#/components/schemas/api_server.models.tortoise_models.tasks.TaskState.leaf', + }, + }, + }, + }, + }, + '422': { + description: 'Validation Error', + content: { + 'application/json': { schema: { $ref: '#/components/schemas/HTTPValidationError' } }, + }, + }, + }, + }, + }, + '/tasks/{task_id}/queue_entry': { + get: { + tags: ['Tasks'], + summary: 'Get Task Queue Entry', + description: 'Available in socket.io', + operationId: 'get_task_queue_entry_tasks__task_id__queue_entry_get', + parameters: [ + { + description: 'task_id', + required: true, + schema: { title: 'Task Id', type: 'string', description: 'task_id' }, + name: 'task_id', + in: 'path', + }, + ], + responses: { + '200': { + description: 'Successful Response', + content: { + 'application/json': { + schema: { + $ref: '#/components/schemas/api_server.models.tortoise_models.tasks.TaskState.leaf', + }, + }, + }, + }, + '422': { + description: 'Validation Error', + content: { + 'application/json': { schema: { $ref: '#/components/schemas/HTTPValidationError' } }, + }, + }, + }, + }, + }, '/tasks/{task_id}/log': { get: { tags: ['Tasks'], @@ -4194,6 +4414,38 @@ export default { }, additionalProperties: false, }, + 'api_server.models.tortoise_models.tasks.TaskState.leaf': { + title: 'TaskState', + required: ['id_'], + type: 'object', + properties: { + id_: { title: 'Id ', maxLength: 255, type: 'string' }, + assigned_to: { title: 'Assigned To', maxLength: 255, type: 'string', nullable: true }, + unix_millis_start_time: { + title: 'Unix Millis Start Time', + type: 'string', + format: 'date-time', + nullable: true, + }, + unix_millis_finish_time: { + title: 'Unix Millis Finish Time', + type: 'string', + format: 'date-time', + nullable: true, + }, + status: { title: 'Status', maxLength: 255, type: 'string', nullable: true }, + unix_millis_request_time: { + title: 'Unix Millis Request Time', + type: 'string', + format: 'date-time', + nullable: true, + }, + requester: { title: 'Requester', maxLength: 255, type: 'string', nullable: true }, + pickup: { title: 'Pickup', maxLength: 255, type: 'string', nullable: true }, + destination: { title: 'Destination', maxLength: 255, type: 'string', nullable: true }, + }, + additionalProperties: false, + }, api_server__models__rmf_api__fleet_log__FleetState: { title: 'FleetState', type: 'object', diff --git a/packages/api-server/api_server/models/tortoise_models/__init__.py b/packages/api-server/api_server/models/tortoise_models/__init__.py index 301bed861..67cccae09 100644 --- a/packages/api-server/api_server/models/tortoise_models/__init__.py +++ b/packages/api-server/api_server/models/tortoise_models/__init__.py @@ -27,6 +27,7 @@ TaskEventLogPhasesLog, TaskFavorite, TaskFavoritePydantic, + TaskQueueEntryPydantic, TaskRequest, TaskState, ) diff --git a/packages/api-server/api_server/models/tortoise_models/tasks.py b/packages/api-server/api_server/models/tortoise_models/tasks.py index f36ac3fbc..a7b4033cf 100644 --- a/packages/api-server/api_server/models/tortoise_models/tasks.py +++ b/packages/api-server/api_server/models/tortoise_models/tasks.py @@ -82,4 +82,7 @@ class TaskFavorite(Model): user = CharField(255, null=False, index=True) +TaskQueueEntryPydantic = pydantic_model_creator( + TaskState, exclude=("data", "category", "unix_millis_warn_time") +) TaskFavoritePydantic = pydantic_model_creator(TaskFavorite) diff --git a/packages/api-server/api_server/repositories/tasks.py b/packages/api-server/api_server/repositories/tasks.py index 717b16ab9..7cf785fed 100644 --- a/packages/api-server/api_server/repositories/tasks.py +++ b/packages/api-server/api_server/repositories/tasks.py @@ -14,6 +14,7 @@ LogEntry, Pagination, Phases, + Status, TaskEventLog, TaskRequest, TaskState, @@ -22,6 +23,7 @@ from api_server.models import tortoise_models as ttm from api_server.models.rmf_api.log_entry import Tier from api_server.models.rmf_api.task_state import Category, Id, Phase +from api_server.models.tortoise_models import TaskQueueEntryPydantic from api_server.models.tortoise_models import TaskRequest as DbTaskRequest from api_server.models.tortoise_models import TaskState as DbTaskState from api_server.query import add_pagination @@ -242,6 +244,58 @@ async def get_task_state(self, task_id: str) -> Optional[TaskState]: return None return TaskState(**result.data) + async def query_task_queue_entry( + self, query: QuerySet[DbTaskState], pagination: Optional[Pagination] = None + ) -> List[TaskQueueEntryPydantic]: + try: + if pagination: + query = add_pagination(query, pagination) + # TODO: enforce with authz + results = await query.values( + "id_", + "assigned_to", + "unix_millis_start_time", + "unix_millis_finish_time", + "status", + "unix_millis_request_time", + "requester", + "pickup", + "destination", + ) + entries = [] + for r in results: + print(r["assigned_to"]) + status = r["status"] + if "Status." in status: + r["status"] = r["status"].split("Status.")[1] + entries.append(TaskQueueEntryPydantic(**r)) + return entries + except FieldError as e: + raise HTTPException(422, str(e)) from e + + async def get_task_queue_entry( + self, task_id: str + ) -> Optional[TaskQueueEntryPydantic]: + # TODO: enforce with authz + result = await DbTaskState.get_or_none(id_=task_id).values( + "id_", + "assigned_to", + "unix_millis_start_time", + "unix_millis_finish_time", + "status", + "unix_millis_request_time", + "requester", + "pickup", + "destination", + ) + if result is None: + return None + + status = result["status"] + if status is not None and "Status." in status: + result["status"] = result["status"].split("Status.")[1] + return TaskQueueEntryPydantic(**result) + async def get_task_log( self, task_id: str, between: Tuple[int, int] ) -> Optional[TaskEventLog]: diff --git a/packages/api-server/api_server/routes/tasks/tasks.py b/packages/api-server/api_server/routes/tasks/tasks.py index 9c6e3d22b..e590cf55c 100644 --- a/packages/api-server/api_server/routes/tasks/tasks.py +++ b/packages/api-server/api_server/routes/tasks/tasks.py @@ -14,6 +14,7 @@ start_time_between_query, ) from api_server.fast_io import FastIORouter, SubscriptionRequest +from api_server.models.tortoise_models import TaskQueueEntryPydantic from api_server.models.tortoise_models import TaskState as DbTaskState from api_server.repositories import TaskRepository, task_repo_dep from api_server.response import RawJSONResponse @@ -138,6 +139,88 @@ async def get_task_state( return result +@router.get("/queue_entry", response_model=List[TaskQueueEntryPydantic]) +async def query_task_queue_entry( + task_repo: TaskRepository = Depends(task_repo_dep), + task_id: Optional[str] = Query( + None, description="comma separated list of task ids" + ), + category: Optional[str] = Query( + None, description="comma separated list of task categories" + ), + request_time_between: Optional[Tuple[datetime, datetime]] = Depends( + request_time_between_query + ), + requester: Optional[str] = Query( + None, description="comma separated list of requester names" + ), + pickup: Optional[str] = Query( + None, description="comma separated list of pickup names" + ), + destination: Optional[str] = Query( + None, description="comma separated list of destination names" + ), + assigned_to: Optional[str] = Query( + None, description="comma separated list of assigned robot names" + ), + start_time_between: Optional[Tuple[datetime, datetime]] = Depends( + start_time_between_query + ), + finish_time_between: Optional[Tuple[datetime, datetime]] = Depends( + finish_time_between_query + ), + status: Optional[str] = Query(None, description="comma separated list of statuses"), + pagination: mdl.Pagination = Depends(pagination_query), +): + filters = {} + if task_id is not None: + filters["id___in"] = task_id.split(",") + if category is not None: + filters["category__in"] = category.split(",") + if request_time_between is not None: + filters["unix_millis_request_time__gte"] = request_time_between[0] + filters["unix_millis_request_time__lte"] = request_time_between[1] + if requester is not None: + filters["requester__in"] = requester.split(",") + if pickup is not None: + filters["pickup__in"] = pickup.split(",") + if destination is not None: + filters["destination__in"] = destination.split(",") + if assigned_to is not None: + filters["assigned_to__in"] = assigned_to.split(",") + if start_time_between is not None: + filters["unix_millis_start_time__gte"] = start_time_between[0] + filters["unix_millis_start_time__lte"] = start_time_between[1] + if finish_time_between is not None: + filters["unix_millis_finish_time__gte"] = finish_time_between[0] + filters["unix_millis_finish_time__lte"] = finish_time_between[1] + if status is not None: + valid_values = [member.value for member in mdl.Status] + filters["status__in"] = [] + for status_string in status.split(","): + if status_string not in valid_values: + continue + filters["status__in"].append(mdl.Status(status_string)) + + return await task_repo.query_task_queue_entry( + DbTaskState.filter(**filters), pagination + ) + + +@router.get("/{task_id}/queue_entry", response_model=TaskQueueEntryPydantic) +async def get_task_queue_entry( + task_repo: TaskRepository = Depends(task_repo_dep), + task_id: str = Path(..., description="task_id"), +): + """ + Available in socket.io + """ + result = await task_repo.get_task_queue_entry(task_id) + if result is None: + raise HTTPException(status_code=404) + return result + + @router.sub("/{task_id}/state", response_model=mdl.TaskState) async def sub_task_state(req: SubscriptionRequest, task_id: str): user = sio_user(req) diff --git a/packages/dashboard/src/components/tasks/tasks-app.tsx b/packages/dashboard/src/components/tasks/tasks-app.tsx index 4cac726fb..b71217ec3 100644 --- a/packages/dashboard/src/components/tasks/tasks-app.tsx +++ b/packages/dashboard/src/components/tasks/tasks-app.tsx @@ -13,7 +13,11 @@ import { Tooltip, useMediaQuery, } from '@mui/material'; -import { TaskRequest, TaskState } from 'api-client'; +import { + ApiServerModelsTortoiseModelsTasksTaskStateLeaf as TaskQueueEntry, + TaskRequest, + TaskState, +} from 'api-client'; import React from 'react'; import { FilterFields, @@ -89,9 +93,9 @@ export const TasksApp = React.memo( const uploadFileInputRef = React.useRef(null); const [openTaskSummary, setOpenTaskSummary] = React.useState(false); const [selectedTask, setSelectedTask] = React.useState(null); - const [tasksState, setTasksState] = React.useState({ + const [taskQueueTableData, setTaskQueueTableData] = React.useState({ isLoading: true, - data: [], + entries: [], requests: {}, total: 0, page: 1, @@ -185,7 +189,7 @@ export const TasksApp = React.memo( } (async () => { - const resp = await rmf.tasksApi.queryTaskStatesTasksGet( + const resp = await rmf.tasksApi.queryTaskQueueEntryTasksQueueEntryGet( filterColumn && filterColumn === 'id_' ? filterValue : undefined, filterColumn && filterColumn === 'category' ? filterValue : undefined, filterColumn && filterColumn === 'requester' ? filterValue : undefined, @@ -197,16 +201,16 @@ export const TasksApp = React.memo( filterColumn && filterColumn === 'unix_millis_start_time' ? filterValue : undefined, filterColumn && filterColumn === 'unix_millis_finish_time' ? filterValue : undefined, GET_LIMIT, - (tasksState.page - 1) * GET_LIMIT, // Datagrid component need to start in page 1. Otherwise works wrong + (taskQueueTableData.page - 1) * GET_LIMIT, // Datagrid component need to start in page 1. Otherwise works wrong orderBy, undefined, ); - const results = resp.data as TaskState[]; + const results = resp.data as TaskQueueEntry[]; const newTasks = results.slice(0, GET_LIMIT); // NOTE(ac): we are not using getAllTaskRequests here to prevent // adding it into the dependency list. - const taskIds: string[] = newTasks.map((task) => task.booking.id); + const taskIds: string[] = newTasks.map((task) => task.id_); const taskIdsQuery = taskIds.join(','); const taskRequests = (await rmf.tasksApi.queryTaskRequestsTasksRequestsGet(taskIdsQuery)) .data; @@ -220,21 +224,21 @@ export const TasksApp = React.memo( ++requestIndex; } - setTasksState((old) => ({ + setTaskQueueTableData((old) => ({ ...old, isLoading: false, - data: newTasks, + entries: newTasks, requests: taskRequestMap, total: results.length === GET_LIMIT - ? tasksState.page * GET_LIMIT + 1 - : tasksState.page * GET_LIMIT - 9, + ? taskQueueTableData.page * GET_LIMIT + 1 + : taskQueueTableData.page * GET_LIMIT - 9, })); })(); }, [ rmf, refreshTaskAppCount, - tasksState.page, + taskQueueTableData.page, filterFields.model, sortFields.model, selectedPanelIndex, @@ -402,21 +406,26 @@ export const TasksApp = React.memo( { - setSelectedTask(task); - if (task.assigned_to) { - AppEvents.robotSelect.next([task.assigned_to.group, task.assigned_to.name]); + tasks={taskQueueTableData} + onTaskClick={async (_: MuiMouseEvent, task: TaskQueueEntry) => { + if (!rmf) { + console.error('Task API not available'); + return; + } + const state = (await rmf.tasksApi.getTaskStateTasksTaskIdStateGet(task.id_)).data; + setSelectedTask(state); + if (state.assigned_to) { + AppEvents.robotSelect.next([state.assigned_to.group, state.assigned_to.name]); } setOpenTaskSummary(true); }} setFilterFields={setFilterFields} setSortFields={setSortFields} onPageChange={(newPage: number) => - setTasksState((old: Tasks) => ({ ...old, page: newPage + 1 })) + setTaskQueueTableData((old: Tasks) => ({ ...old, page: newPage + 1 })) } onPageSizeChange={(newPageSize: number) => - setTasksState((old: Tasks) => ({ ...old, pageSize: newPageSize })) + setTaskQueueTableData((old: Tasks) => ({ ...old, pageSize: newPageSize })) } /> @@ -431,7 +440,9 @@ export const TasksApp = React.memo( setOpenTaskSummary(false)} task={selectedTask ?? undefined} - request={selectedTask ? tasksState.requests[selectedTask.booking.id] : undefined} + request={ + selectedTask ? taskQueueTableData.requests[selectedTask.booking.id] : undefined + } /> )} {children} diff --git a/packages/react-components/lib/tasks/task-table-datagrid.tsx b/packages/react-components/lib/tasks/task-table-datagrid.tsx index e5abc03e9..8962afa0b 100644 --- a/packages/react-components/lib/tasks/task-table-datagrid.tsx +++ b/packages/react-components/lib/tasks/task-table-datagrid.tsx @@ -13,7 +13,12 @@ import { } from '@mui/x-data-grid'; import { styled, Stack, Typography, Tooltip, useMediaQuery, SxProps, Theme } from '@mui/material'; import * as React from 'react'; -import { TaskState, TaskRequest, Status } from 'api-client'; +import { + ApiServerModelsTortoiseModelsTasksTaskStateLeaf as TaskQueueEntry, + TaskState, + TaskRequest, + Status, +} from 'api-client'; import { InsertInvitation as ScheduleIcon, Person as UserIcon } from '@mui/icons-material/'; import { parsePickup, parseDestination } from './utils'; @@ -56,7 +61,7 @@ const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ export interface Tasks { isLoading: boolean; - data: TaskState[]; + entries: TaskQueueEntry[]; requests: Record; total: number; page: number; @@ -75,7 +80,7 @@ export type MuiMouseEvent = MuiEvent>; export interface TableDataGridState { tasks: Tasks; - onTaskClick?(ev: MuiMouseEvent, task: TaskState): void; + onTaskClick?(ev: MuiMouseEvent, task: TaskQueueEntry): void; onPageChange: (newPage: number) => void; onPageSizeChange: (newPageSize: number) => void; setFilterFields: React.Dispatch>; @@ -159,11 +164,11 @@ export function TaskDataGridTable({ width: 150, editable: false, renderCell: (cellValues) => { - const date = new Date(cellValues.row.booking.unix_millis_request_time); + const date = new Date(cellValues.row.unix_millis_request_time); const day = date.toLocaleDateString(undefined, { day: 'numeric' }); const month = date.toLocaleDateString(undefined, { month: 'short' }); const year = date.toLocaleDateString(undefined, { year: 'numeric' }); - return cellValues.row.booking.unix_millis_request_time ? `${day} ${month} ${year}` : 'n/a'; + return cellValues.row.unix_millis_request_time ? `${day} ${month} ${year}` : 'n/a'; }, flex: 1, filterOperators: getMinimalDateOperators, @@ -174,7 +179,7 @@ export function TaskDataGridTable({ headerName: 'Requester', width: 150, editable: false, - renderCell: (cellValues) => TaskRequester(cellValues.row.booking.requester, sxProp), + renderCell: (cellValues) => TaskRequester(cellValues.row.requester, sxProp), flex: 1, filterOperators: getMinimalStringFilterOperators, filterable: true, @@ -185,7 +190,7 @@ export function TaskDataGridTable({ width: 150, editable: false, valueGetter: (params: GridValueGetterParams) => { - const request: TaskRequest | undefined = tasks.requests[params.row.booking.id]; + const request: TaskRequest | undefined = tasks.requests[params.row.id_]; return parsePickup(request); }, flex: 1, @@ -198,7 +203,7 @@ export function TaskDataGridTable({ width: 150, editable: false, valueGetter: (params: GridValueGetterParams) => { - const request: TaskRequest | undefined = tasks.requests[params.row.booking.id]; + const request: TaskRequest | undefined = tasks.requests[params.row.id_]; return parseDestination(params.row, request); }, flex: 1, @@ -211,7 +216,7 @@ export function TaskDataGridTable({ width: 100, editable: false, valueGetter: (params: GridValueGetterParams) => - params.row.assigned_to ? params.row.assigned_to.name : 'n/a', + params.row.assigned_to ? params.row.assigned_to : 'n/a', flex: 1, filterOperators: getMinimalStringFilterOperators, filterable: true, @@ -272,8 +277,8 @@ export function TaskDataGridTable({
r.booking.id} - rows={tasks.data} + getRowId={(r) => r.id_} + rows={tasks.entries} rowCount={tasks.total} loading={tasks.isLoading} pageSize={tasks.pageSize}