From 2203e4cfad03ef0e529ed3346adc0dfc1a27f08e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 20:13:47 +0000 Subject: [PATCH 1/5] Initial plan From 9cd4b89730500dff05e2da29676a53ffb19f2a0c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 20:41:14 +0000 Subject: [PATCH 2/5] Add generic SimpleCollection and SimpleCollectionWithParent base classes to reduce boilerplate in collection management Co-authored-by: sridmad <7445097+sridmad@users.noreply.github.com> --- .../collections/CollectionBase.spec.ts | 159 ++++++++++++++++++ .../DataModels/collections/CollectionBase.ts | 67 ++++++++ .../DataModels/collections/Collections.ts | 70 ++++---- 3 files changed, 259 insertions(+), 37 deletions(-) create mode 100644 src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts new file mode 100644 index 000000000..b6d135d35 --- /dev/null +++ b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts @@ -0,0 +1,159 @@ +import { of, Observable } from 'rxjs'; +import { DataService } from 'src/app/services/data.service'; +import { RestClientService } from 'src/app/services/rest-client.service'; +import { DataModelBase, IDataModel } from '../Base'; +import { SimpleCollection, SimpleCollectionWithParent } from './CollectionBase'; + +// Mock raw data type +interface IRawTestItem { + Id: string; + Name: string; +} + +// Mock model class +class TestModel extends DataModelBase { + constructor(data: DataService, raw: IRawTestItem) { + super(data, raw); + } + + public get uniqueId(): string { + return this.raw.Id; + } +} + +// Mock model class with parent +class TestModelWithParent extends DataModelBase { + constructor(data: DataService, raw: IRawTestItem, public parent: { id: string }) { + super(data, raw, parent); + } + + public get uniqueId(): string { + return this.raw.Id; + } +} + +// Mock parent type +interface ITestParent { + id: string; + name: string; +} + +describe('CollectionBase', () => { + const restClientMock: RestClientService = {} as RestClientService; + + const mockDataService: DataService = { + restClient: restClientMock, + } as DataService; + + describe('SimpleCollection', () => { + let collection: SimpleCollection; + let mockFetchFn: (data: DataService) => Observable; + const mockRawItems: IRawTestItem[] = [ + { Id: '1', Name: 'Item 1' }, + { Id: '2', Name: 'Item 2' }, + { Id: '3', Name: 'Item 3' } + ]; + + beforeEach(() => { + mockFetchFn = jasmine.createSpy('fetchFn').and.returnValue(of(mockRawItems)); + collection = new SimpleCollection( + mockDataService, + TestModel, + mockFetchFn + ); + }); + + it('should create a collection instance', () => { + expect(collection).toBeTruthy(); + expect(collection.length).toBe(0); + expect(collection.isInitialized).toBe(false); + }); + + it('should fetch and map items on refresh', async () => { + await collection.refresh().toPromise(); + + expect(mockFetchFn).toHaveBeenCalled(); + expect(collection.length).toBe(3); + expect(collection.isInitialized).toBe(true); + }); + + it('should create correct model instances', async () => { + await collection.refresh().toPromise(); + + expect(collection.collection[0]).toBeInstanceOf(TestModel); + expect(collection.collection[0].raw.Id).toBe('1'); + expect(collection.collection[0].raw.Name).toBe('Item 1'); + }); + + it('should find items by uniqueId', async () => { + await collection.refresh().toPromise(); + + const found = collection.find('2'); + expect(found).toBeTruthy(); + expect(found.raw.Name).toBe('Item 2'); + }); + + it('should return null for non-existing uniqueId', async () => { + await collection.refresh().toPromise(); + + const found = collection.find('999'); + expect(found).toBeFalsy(); + }); + }); + + describe('SimpleCollectionWithParent', () => { + let collection: SimpleCollectionWithParent; + let mockFetchFn: (data: DataService, parent: ITestParent) => Observable; + const mockParent: ITestParent = { id: 'parent-1', name: 'Parent' }; + const mockRawItems: IRawTestItem[] = [ + { Id: 'p1-1', Name: 'Item 1' }, + { Id: 'p1-2', Name: 'Item 2' } + ]; + + beforeEach(() => { + mockFetchFn = jasmine.createSpy('fetchFn').and.returnValue(of(mockRawItems)); + collection = new SimpleCollectionWithParent( + mockDataService, + mockParent, + TestModelWithParent, + mockFetchFn + ); + }); + + it('should create a collection instance with parent', () => { + expect(collection).toBeTruthy(); + expect(collection.parent).toBe(mockParent); + expect(collection.length).toBe(0); + expect(collection.isInitialized).toBe(false); + }); + + it('should fetch items using parent in fetch function', async () => { + await collection.refresh().toPromise(); + + expect(mockFetchFn).toHaveBeenCalled(); + expect(collection.length).toBe(2); + }); + + it('should create model instances with parent reference', async () => { + await collection.refresh().toPromise(); + + expect(collection.collection[0]).toBeInstanceOf(TestModelWithParent); + expect(collection.collection[0].parent).toBe(mockParent); + }); + + it('should handle empty collections', async () => { + mockFetchFn = jasmine.createSpy('fetchFn').and.returnValue(of([])); + collection = new SimpleCollectionWithParent( + mockDataService, + mockParent, + TestModelWithParent, + mockFetchFn + ); + + await collection.refresh().toPromise(); + + expect(collection.length).toBe(0); + expect(collection.isInitialized).toBe(true); + }); + }); +}); diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.ts b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.ts index 1d9eb81b9..97ee0c082 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.ts @@ -212,3 +212,70 @@ export class DataModelCollectionBase> implements IData return null; } } + +/** + * Type definition for a model constructor that takes DataService and raw data only. + */ +export type ModelConstructorNoParent = new (data: DataService, raw: R) => T; + +/** + * Type definition for a model constructor that takes DataService, raw data, and a parent. + */ +export type ModelConstructorWithParent = new (data: DataService, raw: R, parent: P) => T; + +/** + * A generic collection class that reduces boilerplate for simple collections without a parent. + * + * This class handles the common pattern of fetching data via REST API and mapping to model instances. + * + * @example + * class MyCollection extends SimpleCollection { + * constructor(data: DataService) { + * super(data, MyModel, (data, messageHandler) => data.restClient.getItems(messageHandler)); + * } + * } + */ +export class SimpleCollection, R> extends DataModelCollectionBase { + constructor( + data: DataService, + protected modelClass: ModelConstructorNoParent, + protected fetchFn: (data: DataService, messageHandler?: IResponseMessageHandler) => Observable + ) { + super(data); + } + + protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { + return this.fetchFn(this.data, messageHandler).pipe( + map(rawItems => rawItems.map(raw => new this.modelClass(this.data, raw))) + ); + } +} + +/** + * A generic collection class that reduces boilerplate for simple collections with a parent. + * + * This class handles the common pattern of fetching data via REST API and mapping to model instances. + * + * @example + * class MyCollection extends SimpleCollectionWithParent { + * constructor(data: DataService, parent: ParentType) { + * super(data, parent, MyModel, (data, parent, messageHandler) => data.restClient.getItems(parent.id, messageHandler)); + * } + * } + */ +export class SimpleCollectionWithParent, R, P> extends DataModelCollectionBase { + constructor( + data: DataService, + public parent: P, + protected modelClass: ModelConstructorWithParent, + protected fetchFn: (data: DataService, parent: P, messageHandler?: IResponseMessageHandler) => Observable + ) { + super(data, parent); + } + + protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { + return this.fetchFn(this.data, this.parent, messageHandler).pipe( + map(rawItems => rawItems.map(raw => new this.modelClass(this.data, raw, this.parent))) + ); + } +} diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts index 6c6abd780..8d5a2b144 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts @@ -2,7 +2,7 @@ import { IClusterHealthChunk, IDeployedServicePackageHealthStateChunk } from '.. import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers'; import { Observable, of, throwError } from 'rxjs'; import { ValueResolver, ITextAndBadge } from 'src/app/Utils/ValueResolver'; -import { IRawDeployedServicePackage } from '../../RawDataTypes'; +import { IRawDeployedServicePackage, IRawBackupPolicy, IRawBackupConfigurationInfo, IRawPartitionBackup } from '../../RawDataTypes'; import { IdGenerator } from 'src/app/Utils/IdGenerator'; import { DataService } from 'src/app/services/data.service'; import { HealthStateConstants } from 'src/app/Common/Constants'; @@ -22,7 +22,7 @@ import { FabricEventBase, FabricEventInstanceModel, ClusterEvent, NodeEvent, App import { ListSettings, ListColumnSetting, ListColumnSettingWithFilter, ListColumnSettingWithEventStoreFullDescription, ListColumnSettingWithEventStoreRowDisplay } from '../../ListSettings'; import { TimeUtils } from 'src/app/Utils/TimeUtils'; import { PartitionBackup, PartitionBackupInfo } from '../PartitionBackupInfo'; -import { DataModelCollectionBase, IDataModelCollection } from './CollectionBase'; +import { DataModelCollectionBase, IDataModelCollection, SimpleCollection, SimpleCollectionWithParent } from './CollectionBase'; import groupBy from 'lodash/groupBy'; import { RoutesService } from 'src/app/services/routes.service'; // ----------------------------------------------------------------------------- @@ -30,11 +30,13 @@ import { RoutesService } from 'src/app/services/routes.service'; // Licensed under the MIT License. See License file under the project root for license information. // ----------------------------------------------------------------------------- -export class BackupPolicyCollection extends DataModelCollectionBase { - protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getBackupPolicies(messageHandler).pipe(map(items => { - return items.map(raw => new BackupPolicy(this.data, raw)); - })); +/** + * BackupPolicyCollection using generic SimpleCollection pattern. + * Fetches backup policies from REST API and maps to BackupPolicy model instances. + */ +export class BackupPolicyCollection extends SimpleCollection { + constructor(data: DataService) { + super(data, BackupPolicy, (dataService, messageHandler) => dataService.restClient.getBackupPolicies(messageHandler)); } } @@ -136,29 +138,25 @@ export class ApplicationTypeGroupCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: Application) { - super(data, parent); - } - - protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getApplicationBackupConfigurationInfoCollection(this.parent.id, messageHandler) - .pipe(map(items => { - return items.map(raw => new ApplicationBackupConfigurationInfo(this.data, raw, this.parent)); - })); +/** + * ApplicationBackupConfigurationInfoCollection using generic SimpleCollectionWithParent pattern. + * Fetches application backup configuration info from REST API and maps to model instances. + */ +export class ApplicationBackupConfigurationInfoCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: Application) { + super(data, parent, ApplicationBackupConfigurationInfo, + (dataService, parentApp, messageHandler) => dataService.restClient.getApplicationBackupConfigurationInfoCollection(parentApp.id, messageHandler)); } } -export class ServiceBackupConfigurationInfoCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: Service) { - super(data, parent); - } - - protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getServiceBackupConfigurationInfoCollection(this.parent.id, messageHandler) - .pipe(map(items => { - return items.map(raw => new ServiceBackupConfigurationInfo(this.data, raw, this.parent)); - })); +/** + * ServiceBackupConfigurationInfoCollection using generic SimpleCollectionWithParent pattern. + * Fetches service backup configuration info from REST API and maps to model instances. + */ +export class ServiceBackupConfigurationInfoCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: Service) { + super(data, parent, ServiceBackupConfigurationInfo, + (dataService, parentService, messageHandler) => dataService.restClient.getServiceBackupConfigurationInfoCollection(parentService.id, messageHandler)); } } @@ -179,16 +177,14 @@ export class PartitionBackupCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: PartitionBackupInfo) { - super(data, parent); - } - - public retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getLatestPartitionBackup(this.parent.parent.id, messageHandler) - .pipe(map(items => { - return items.map(raw => new PartitionBackup(this.data, raw, this.parent)); - })); +/** + * SinglePartitionBackupCollection using generic SimpleCollectionWithParent pattern. + * Fetches the latest partition backup from REST API and maps to model instances. + */ +export class SinglePartitionBackupCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: PartitionBackupInfo) { + super(data, parent, PartitionBackup, + (dataService, parentInfo, messageHandler) => dataService.restClient.getLatestPartitionBackup(parentInfo.parent.id, messageHandler)); } } From 6268c0f86a7564d609c0b9410ea49c1be5d2e1f6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 20:56:43 +0000 Subject: [PATCH 3/5] Fix type imports and generic type parameters based on code review feedback Co-authored-by: sridmad <7445097+sridmad@users.noreply.github.com> --- .../Models/DataModels/collections/CollectionBase.spec.ts | 2 +- .../src/app/Models/DataModels/collections/Collections.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts index b6d135d35..f6eacda3c 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/CollectionBase.spec.ts @@ -1,7 +1,7 @@ import { of, Observable } from 'rxjs'; import { DataService } from 'src/app/services/data.service'; import { RestClientService } from 'src/app/services/rest-client.service'; -import { DataModelBase, IDataModel } from '../Base'; +import { DataModelBase } from '../Base'; import { SimpleCollection, SimpleCollectionWithParent } from './CollectionBase'; // Mock raw data type diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts index 8d5a2b144..b5a18186f 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts @@ -2,7 +2,7 @@ import { IClusterHealthChunk, IDeployedServicePackageHealthStateChunk } from '.. import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers'; import { Observable, of, throwError } from 'rxjs'; import { ValueResolver, ITextAndBadge } from 'src/app/Utils/ValueResolver'; -import { IRawDeployedServicePackage, IRawBackupPolicy, IRawBackupConfigurationInfo, IRawPartitionBackup } from '../../RawDataTypes'; +import { IRawDeployedServicePackage, IRawBackupPolicy, IRawBackupConfigurationInfo, IRawPartitionBackup, IRawApplicationBackupConfigurationInfo, IRawServiceBackupConfigurationInfo } from '../../RawDataTypes'; import { IdGenerator } from 'src/app/Utils/IdGenerator'; import { DataService } from 'src/app/services/data.service'; import { HealthStateConstants } from 'src/app/Common/Constants'; @@ -142,7 +142,7 @@ export class ApplicationTypeGroupCollection extends DataModelCollectionBase { +export class ApplicationBackupConfigurationInfoCollection extends SimpleCollectionWithParent { constructor(data: DataService, parent: Application) { super(data, parent, ApplicationBackupConfigurationInfo, (dataService, parentApp, messageHandler) => dataService.restClient.getApplicationBackupConfigurationInfoCollection(parentApp.id, messageHandler)); @@ -153,7 +153,7 @@ export class ApplicationBackupConfigurationInfoCollection extends SimpleCollecti * ServiceBackupConfigurationInfoCollection using generic SimpleCollectionWithParent pattern. * Fetches service backup configuration info from REST API and maps to model instances. */ -export class ServiceBackupConfigurationInfoCollection extends SimpleCollectionWithParent { +export class ServiceBackupConfigurationInfoCollection extends SimpleCollectionWithParent { constructor(data: DataService, parent: Service) { super(data, parent, ServiceBackupConfigurationInfo, (dataService, parentService, messageHandler) => dataService.restClient.getServiceBackupConfigurationInfoCollection(parentService.id, messageHandler)); From 24d5e96922eee73b9ea6cc44af505b44362c88bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:10:27 +0000 Subject: [PATCH 4/5] Remove unused IRawBackupConfigurationInfo import Co-authored-by: sridmad <7445097+sridmad@users.noreply.github.com> --- src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts index b5a18186f..6efd7f583 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts @@ -2,7 +2,7 @@ import { IClusterHealthChunk, IDeployedServicePackageHealthStateChunk } from '.. import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers'; import { Observable, of, throwError } from 'rxjs'; import { ValueResolver, ITextAndBadge } from 'src/app/Utils/ValueResolver'; -import { IRawDeployedServicePackage, IRawBackupPolicy, IRawBackupConfigurationInfo, IRawPartitionBackup, IRawApplicationBackupConfigurationInfo, IRawServiceBackupConfigurationInfo } from '../../RawDataTypes'; +import { IRawDeployedServicePackage, IRawBackupPolicy, IRawPartitionBackup, IRawApplicationBackupConfigurationInfo, IRawServiceBackupConfigurationInfo } from '../../RawDataTypes'; import { IdGenerator } from 'src/app/Utils/IdGenerator'; import { DataService } from 'src/app/services/data.service'; import { HealthStateConstants } from 'src/app/Common/Constants'; From 49bfe62bfb5e431753f759e25697e1948619c107 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:16:18 +0000 Subject: [PATCH 5/5] Refactor PartitionCollection, ReplicaOnPartitionCollection, and ServiceCollection to use generic base classes Co-authored-by: jeffj6123 <15344718+jeffj6123@users.noreply.github.com> --- .../DataModels/collections/Collections.ts | 39 +++++++++---------- .../collections/ServiceCollection.ts | 24 +++++------- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts index 6efd7f583..77d72e127 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/Collections.ts @@ -2,7 +2,7 @@ import { IClusterHealthChunk, IDeployedServicePackageHealthStateChunk } from '.. import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers'; import { Observable, of, throwError } from 'rxjs'; import { ValueResolver, ITextAndBadge } from 'src/app/Utils/ValueResolver'; -import { IRawDeployedServicePackage, IRawBackupPolicy, IRawPartitionBackup, IRawApplicationBackupConfigurationInfo, IRawServiceBackupConfigurationInfo } from '../../RawDataTypes'; +import { IRawDeployedServicePackage, IRawBackupPolicy, IRawPartitionBackup, IRawApplicationBackupConfigurationInfo, IRawServiceBackupConfigurationInfo, IRawPartition, IRawReplicaOnPartition, IRawService } from '../../RawDataTypes'; import { IdGenerator } from 'src/app/Utils/IdGenerator'; import { DataService } from 'src/app/services/data.service'; import { HealthStateConstants } from 'src/app/Common/Constants'; @@ -211,9 +211,14 @@ export class ServiceTypeCollection extends DataModelCollectionBase } } -export class PartitionCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: Service) { - super(data, parent); +/** + * PartitionCollection using generic SimpleCollectionWithParent pattern. + * Extends with mergeClusterHealthStateChunk for health state management. + */ +export class PartitionCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: Service) { + super(data, parent, Partition, + (dataService, parentService, messageHandler) => dataService.restClient.getPartitions(parentService.parent.id, parentService.id, messageHandler)); } public mergeClusterHealthStateChunk(clusterHealthChunk: IClusterHealthChunk): Observable { @@ -226,18 +231,17 @@ export class PartitionCollection extends DataModelCollectionBase { } return of(true); } - - protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getPartitions(this.parent.parent.id, this.parent.id, messageHandler) - .pipe(map(items => { - return items.map(raw => new Partition(this.data, raw, this.parent)); - })); - } } -export class ReplicaOnPartitionCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: Partition) { - super(data, parent); +/** + * ReplicaOnPartitionCollection using generic SimpleCollectionWithParent pattern. + * Extends with additional getters for service type information. + */ +export class ReplicaOnPartitionCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: Partition) { + super(data, parent, ReplicaOnPartition, + (dataService, parentPartition, messageHandler) => dataService.restClient.getReplicasOnPartition( + parentPartition.parent.parent.id, parentPartition.parent.id, parentPartition.id, messageHandler)); } public get isStatefulService(): boolean { @@ -247,13 +251,6 @@ export class ReplicaOnPartitionCollection extends DataModelCollectionBase { - return this.data.restClient.getReplicasOnPartition(this.parent.parent.parent.id, this.parent.parent.id, this.parent.id, messageHandler) - .pipe(map(items => { - return items.map(raw => new ReplicaOnPartition(this.data, raw, this.parent)); - })); - } } export class DeployedServicePackageCollection extends DataModelCollectionBase { diff --git a/src/SfxWeb/src/app/Models/DataModels/collections/ServiceCollection.ts b/src/SfxWeb/src/app/Models/DataModels/collections/ServiceCollection.ts index 6badfc6dc..941974538 100644 --- a/src/SfxWeb/src/app/Models/DataModels/collections/ServiceCollection.ts +++ b/src/SfxWeb/src/app/Models/DataModels/collections/ServiceCollection.ts @@ -4,15 +4,19 @@ import { DataService } from 'src/app/services/data.service'; import { Constants } from 'src/app/Common/Constants'; import { IClusterHealthChunk, IServiceHealthStateChunk } from '../../HealthChunkRawDataTypes'; import { Observable, of } from 'rxjs'; -import { IResponseMessageHandler } from 'src/app/Common/ResponseMessageHandlers'; import { IdGenerator } from 'src/app/Utils/IdGenerator'; import { IdUtils } from 'src/app/Utils/IdUtils'; -import { map } from 'rxjs/operators'; -import { DataModelCollectionBase } from './CollectionBase'; +import { SimpleCollectionWithParent } from './CollectionBase'; +import { IRawService } from '../../RawDataTypes'; -export class ServiceCollection extends DataModelCollectionBase { - public constructor(data: DataService, public parent: Application) { - super(data, parent); +/** + * ServiceCollection using generic SimpleCollectionWithParent pattern. + * Extends with mergeClusterHealthStateChunk for health state management. + */ +export class ServiceCollection extends SimpleCollectionWithParent { + constructor(data: DataService, parent: Application) { + super(data, parent, Service, + (dataService, parentApp, messageHandler) => dataService.restClient.getServices(parentApp.id, messageHandler)); } public mergeClusterHealthStateChunk(clusterHealthChunk: IClusterHealthChunk): Observable { @@ -30,12 +34,4 @@ export class ServiceCollection extends DataModelCollectionBase { } return of(true); } - - protected retrieveNewCollection(messageHandler?: IResponseMessageHandler): Observable { - return this.data.restClient.getServices(this.parent.id, messageHandler).pipe(map( - items => { - return items.map(raw => new Service(this.data, raw, this.parent)); - } - )); - } }