import { BehaviorSubject, Subject } from "rxjs"; export abstract class DataSource { protected data: T[] = []; protected dataChange: BehaviorSubject = new BehaviorSubject([]); protected itemUpdated: Subject = new Subject(); public getItems(): T[] { return this.data; } public add(item: T) { const index = this.findIndex(item); if (index >= 0) { this.update(item); } else { this.data.push(item); this.dataChange.next(this.data); } } public set(data: T[]) { data.forEach((item) => { const index = this.findIndex(item); if (index >= 0) { const updated = Object.assign(this.data[index], item); this.data[index] = updated; } else { this.data.push(item); } }); const toRemove = this.data.filter((item) => data.filter((i) => this.getItemKey(i) === this.getItemKey(item)).length === 0); toRemove.forEach((item) => this.remove(item)); this.dataChange.next(this.data); } public get(key: string | number) { const index = this.data.findIndex((i: T) => this.getItemKey(i) === key); if (index >= 0) { return this.data[index]; } } public update(item: T) { const index = this.findIndex(item); if (index >= 0) { const updated = Object.assign(this.data[index], item); this.data[index] = updated; this.dataChange.next(this.data); this.itemUpdated.next(updated); } } public remove(item: T) { const index = this.findIndex(item); if (index >= 0) { this.data.splice(index, 1); this.dataChange.next(this.data); } } public get changes() { return this.dataChange; } public get itemChanged() { return this.itemUpdated; } public clear() { this.data = []; this.dataChange.next(this.data); } private findIndex(item: T) { return this.data.findIndex((i: T) => this.getItemKey(i) === this.getItemKey(item)); } protected abstract getItemKey(item: T): any; }