diff --git a/src/app/core/_datasources/agent-error.datasource.ts b/src/app/core/_datasources/agent-error.datasource.ts index 7ddab35b..33f3308b 100644 --- a/src/app/core/_datasources/agent-error.datasource.ts +++ b/src/app/core/_datasources/agent-error.datasource.ts @@ -30,7 +30,11 @@ export class AgentErrorDatasource extends BaseDataSource { // Use stored filter if no new filter is provided const activeFilter = query || this._currentFilter; - let agentParams = new RequestParamBuilder().addInitial(this).addInclude('task'); + let agentParams = new RequestParamBuilder().addInitial(this).addInclude('task').addAggregate({ + field: 'task', + values: [] + }); + if (this._agentId) { agentParams.addFilter({ field: 'agentId', operator: FilterType.EQUAL, value: this._agentId }); } diff --git a/src/app/core/_datasources/agents.datasource.ts b/src/app/core/_datasources/agents.datasource.ts index da859b84..173ded5b 100644 --- a/src/app/core/_datasources/agents.datasource.ts +++ b/src/app/core/_datasources/agents.datasource.ts @@ -50,7 +50,11 @@ export class AgentsDataSource extends BaseDataSource { .addInclude('accessGroups') .addInclude('tasks') .addInclude('assignments') - .addInclude('user'); + .addInclude('user') + .addAggregate({ + field: 'task', + values: [] + }); if (this.agentStatsRequired) { agentParams = agentParams.addInclude('agentStats'); } diff --git a/src/app/core/_datasources/chunks.datasource.ts b/src/app/core/_datasources/chunks.datasource.ts index 9a21bd29..508b14e4 100644 --- a/src/app/core/_datasources/chunks.datasource.ts +++ b/src/app/core/_datasources/chunks.datasource.ts @@ -31,7 +31,11 @@ export class ChunksDataSource extends BaseDataSource { // Use stored filter if no new filter is provided const activeFilter = query || this._currentFilter; - let params = new RequestParamBuilder().addInitial(this).addInclude('task').addInclude('agent'); + let params = new RequestParamBuilder().addInitial(this).addInclude('agent').addInclude('task').addAggregate({ + field: 'task', + values: [] + }); + if (this._agentId) { params.addFilter({ field: 'agentId', operator: FilterType.EQUAL, value: this._agentId }); } diff --git a/src/app/core/_datasources/files.datasource.ts b/src/app/core/_datasources/files.datasource.ts index 3be7ed67..f05fe26e 100644 --- a/src/app/core/_datasources/files.datasource.ts +++ b/src/app/core/_datasources/files.datasource.ts @@ -62,12 +62,17 @@ export class FilesDataSource extends BaseDataSource { if (this.editIndex !== undefined) { if (this.editType === 0) { - files$ = this.service.get(SERV.TASKS, this.editIndex, paramsBuilder.addInclude('files').create(), httpOptions); + files$ = this.service.get( + SERV.TASKS, + this.editIndex, + paramsBuilder.addInclude('files').addAggregate({ field: 'task', values: [] }).create(), + httpOptions + ); } else if (this.editType === 1) { files$ = this.service.get( SERV.PRETASKS, this.editIndex, - paramsBuilder.addInclude('pretaskFiles').create(), + paramsBuilder.addInclude('pretaskFiles').addAggregate({ field: 'pretask', values: [] }).create(), httpOptions ); } diff --git a/src/app/core/_datasources/tasks-chunks.datasource.ts b/src/app/core/_datasources/tasks-chunks.datasource.ts index 3c7ae8ab..ecdd1ca6 100644 --- a/src/app/core/_datasources/tasks-chunks.datasource.ts +++ b/src/app/core/_datasources/tasks-chunks.datasource.ts @@ -36,7 +36,7 @@ export class TasksChunksDataSource extends BaseDataSource { const activeFilter = query || this._currentFilter; - let chunkParams = new RequestParamBuilder().addInitial(this).addInclude('task').addInclude('agent').addFilter({ + let chunkParams = new RequestParamBuilder().addInitial(this).addInclude('agent').addFilter({ field: 'taskId', operator: FilterType.EQUAL, value: this._taskId @@ -46,8 +46,13 @@ export class TasksChunksDataSource extends BaseDataSource { if (this._taskId) { const httpOptions = { headers: new HttpHeaders({ 'X-Skip-Error-Dialog': 'true' }) }; try { + const taskParams = new RequestParamBuilder().addAggregate({ + field: 'task', + values: [] + }); + const response = await firstValueFrom( - this.service.get(SERV.TASKS, this._taskId, undefined, httpOptions).pipe( + this.service.get(SERV.TASKS, this._taskId, taskParams.create(), httpOptions).pipe( catchError((error) => { this.handleFilterError(error); throw error; diff --git a/src/app/core/_models/request-params.model.ts b/src/app/core/_models/request-params.model.ts index f922f349..5057b987 100644 --- a/src/app/core/_models/request-params.model.ts +++ b/src/app/core/_models/request-params.model.ts @@ -33,6 +33,16 @@ export interface Filter { parent?: string; } +/** + * Interface definition for aggregate fieldsets + * @prop field Aggregate field name + * @prop values Values to aggregate for the field + */ +export interface Aggregate { + field: string; + values: string[]; +} + /** * Interface definition for request params */ @@ -46,6 +56,8 @@ interface IRequestParams { include?: Array; // Array of Filter objects that have to be performed filter?: Array; + //array of aggregated fields to include ex. [active agents for tasks] + aggregate?: Array; //array of attributes to sort on where '-' implies descending order on ex. [id, -name] sort?: Array; //Parameter for count endpoints to also include the count without filters diff --git a/src/app/core/_services/buildparams.ts b/src/app/core/_services/buildparams.ts index c70f6d9b..36f8ccf3 100644 --- a/src/app/core/_services/buildparams.ts +++ b/src/app/core/_services/buildparams.ts @@ -39,6 +39,14 @@ export function setParameter(params: RequestParams): HttpParams { }); } + // Handle aggregate array + const aggregate = params.aggregate; + if (Array.isArray(aggregate) && aggregate.length > 0) { + aggregate.forEach((aggregate) => { + httpParams = httpParams.set(`aggregate[${aggregate.field}]`, aggregate.values.join(',')); + }); + } + // Handle ordering parameter const sort = params.sort; if (Array.isArray(sort) && sort.length > 0) { diff --git a/src/app/core/_services/params/builder-implementation.service.ts b/src/app/core/_services/params/builder-implementation.service.ts index dd9cddaa..3ed78b6b 100644 --- a/src/app/core/_services/params/builder-implementation.service.ts +++ b/src/app/core/_services/params/builder-implementation.service.ts @@ -1,7 +1,7 @@ import { SortingColumn } from '@components/tables/ht-table/ht-table.models'; import { BaseDataSource } from '@src/app/core/_datasources/base.datasource'; -import { Filter, type RequestParams } from '@src/app/core/_models/request-params.model'; +import { Aggregate, Filter, type RequestParams } from '@src/app/core/_models/request-params.model'; import { IParamBuilder, RequestParamsIntermediate } from '@src/app/core/_services/params/builder-types.service'; /** @@ -98,6 +98,16 @@ export class RequestParamBuilder implements IParamBuilder { return this; } + /** + * Adds a new value to the aggregate fieldsets array + * @param include new include value + * @returns object instance + */ + addAggregate(aggregate: Aggregate): IParamBuilder { + this.params.aggregate = this.addToArray(this.params.aggregate, aggregate); + return this; + } + /** * Adds a new value from the given column to the sort array * @param sortingColumn column to get sort values from @@ -131,6 +141,7 @@ export class RequestParamBuilder implements IParamBuilder { if (this.params.sortOrder) requestParams.sort = this.params.sortOrder; if (this.params.filters) requestParams.filter = this.params.filters; if (this.params.includeTotal !== undefined) requestParams.include_total = this.params.includeTotal; + if (this.params.aggregate !== undefined) requestParams.aggregate = this.params.aggregate; return requestParams; } diff --git a/src/app/core/_services/params/builder-types.service.ts b/src/app/core/_services/params/builder-types.service.ts index 08ae1acb..f4a2bed6 100644 --- a/src/app/core/_services/params/builder-types.service.ts +++ b/src/app/core/_services/params/builder-types.service.ts @@ -7,7 +7,7 @@ import { SortingColumn } from '@components/tables/ht-table/ht-table.models'; import { BaseDataSource } from '@datasources/base.datasource'; -import { Filter, type RequestParams } from '@src/app/core/_models/request-params.model'; +import { Aggregate, Filter, type RequestParams } from '@src/app/core/_models/request-params.model'; /** * Intermediate class to build RequestParams from using a builder interface implementation @@ -20,6 +20,7 @@ export class RequestParamsIntermediate { public filters?: Array; public sortOrder?: Array; public includeTotal?: boolean; + public aggregate?: Array; } /** @@ -40,6 +41,8 @@ export interface IParamBuilder { addIncludeTotal(includeTotal: boolean): IParamBuilder; + addAggregate(aggregate: Aggregate): IParamBuilder; + addInitial(datasource: BaseDataSource): IParamBuilder; create(): RequestParams;