diff --git a/client/src/app/core/services/config.service.ts b/client/src/app/core/services/config.service.ts index eba1fc629..0319ec4b7 100644 --- a/client/src/app/core/services/config.service.ts +++ b/client/src/app/core/services/config.service.ts @@ -34,7 +34,7 @@ export class ConfigService extends OpenSlidesComponent { public constructor() { super(); - this.DS.getObservable().subscribe(data => { + this.DS.changeObservable.subscribe(data => { // on changes notify the observers for specific keys. if (data instanceof Config && this.configSubjects[data.key]) { this.configSubjects[data.key].next(data.value); diff --git a/client/src/app/core/services/data-store.service.ts b/client/src/app/core/services/data-store.service.ts index f9fdf261f..92feec958 100644 --- a/client/src/app/core/services/data-store.service.ts +++ b/client/src/app/core/services/data-store.service.ts @@ -1,10 +1,20 @@ import { Injectable } from '@angular/core'; -import { Observable, BehaviorSubject } from 'rxjs'; +import { Observable, Subject } from 'rxjs'; -import { BaseModel, ModelId, ModelConstructor } from 'app/shared/models/base.model'; +import { BaseModel, ModelConstructor } from 'app/shared/models/base.model'; import { CacheService } from './cache.service'; import { CollectionStringModelMapperService } from './collectionStringModelMapper.service'; +/** + * Represents information about a deleted model. + * + * As the model doesn't exist anymore, just the former id and collection is known. + */ +export interface DeletedInformation { + collection: string; + id: number; +} + /** * represents a collection on the Django server, uses an ID to access a {@link BaseModel}. * @@ -62,9 +72,32 @@ export class DataStoreService { private JsonStore: JsonStorage = {}; /** - * Observable subject with changes to enable dynamic changes in models and views + * Observable subject for changed models in the datastore. */ - private dataStoreSubject: BehaviorSubject = new BehaviorSubject(null); + private changedSubject: Subject = new Subject(); + + /** + * Observe the datastore for changes. + * + * @return an observable for changed models + */ + public get changeObservable(): Observable { + return this.changedSubject.asObservable(); + } + + /** + * Observable subject for changed models in the datastore. + */ + private deletedSubject: Subject = new Subject(); + + /** + * Observe the datastore for deletions. + * + * @return an observable for deleted objects. + */ + public get deletedObservable(): Observable { + return this.deletedSubject.asObservable(); + } /** * The maximal change id from this DataStore. @@ -166,14 +199,14 @@ export class DataStoreService { * @example: this.DS.get(User, 1) * @example: this.DS.get('core/countdown', 2) */ - public get(collectionType: ModelConstructor | string, id: ModelId): T { + public get(collectionType: ModelConstructor | string, id: number): T { const collectionString = this.getCollectionString(collectionType); const collection: ModelCollection = this.modelStore[collectionString]; if (!collection) { return; } else { - return collection[id]; + return collection[id] as T; } } @@ -184,7 +217,7 @@ export class DataStoreService { * @return The BaseModel-list corresponding to the given ID(s) * @example: this.DS.get(User, [1,2,3,4,5]) */ - public getMany(collectionType: ModelConstructor | string, ids: ModelId[]): T[] { + public getMany(collectionType: ModelConstructor | string, ids: number[]): T[] { const collectionString = this.getCollectionString(collectionType); const collection: ModelCollection = this.modelStore[collectionString]; @@ -196,7 +229,7 @@ export class DataStoreService { return collection[id]; }) .filter(model => !!model); // remove non valid models. - return models; + return models as T[]; } /** @@ -257,7 +290,7 @@ export class DataStoreService { } this.JsonStore[collectionString][model.id] = JSON.stringify(model); // if (model.changeId > maxChangeId) {maxChangeId = model.maxChangeId;} - this.setObservable(model); + this.changedSubject.next(model); }); this.storeToCache(maxChangeId); } @@ -268,7 +301,7 @@ export class DataStoreService { * @param ...ids An or multiple IDs or a list of IDs of BaseModels. use spread operator ("...") for arrays * @example this.DS.remove(User, myUser.id, 3, 4) */ - public remove(collectionType, ...ids: ModelId[]): void { + public remove(collectionType, ...ids: number[]): void { let collectionString: string; if (typeof collectionType === 'string') { collectionString = collectionType; @@ -287,6 +320,10 @@ export class DataStoreService { if (this.JsonStore[collectionString]) { delete this.JsonStore[collectionString][id]; } + this.deletedSubject.next({ + collection: collectionString, + id: id + }); }); this.storeToCache(maxChangeId); } @@ -303,22 +340,6 @@ export class DataStoreService { } } - /** - * Observe the dataStore for changes. - * @return an observable behaviorSubject - */ - public getObservable(): Observable { - return this.dataStoreSubject.asObservable(); - } - - /** - * Informs the observers for changes - * @param value the change that have been made - */ - private setObservable(value): void { - this.dataStoreSubject.next(value); - } - /** * Prints the whole dataStore * @deprecated Shouldn't be used, will be removed later diff --git a/client/src/app/core/services/operator.service.ts b/client/src/app/core/services/operator.service.ts index 0983ff233..fa9754a43 100644 --- a/client/src/app/core/services/operator.service.ts +++ b/client/src/app/core/services/operator.service.ts @@ -83,7 +83,7 @@ export class OperatorService extends OpenSlidesComponent { * permissions if the user or groups changes. */ public setupSubscription() { - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (this._user) { if (newModel instanceof Group) { this.updatePermissions(); diff --git a/client/src/app/shared/models/base.model.ts b/client/src/app/shared/models/base.model.ts index 5de4186d4..04da7eca8 100644 --- a/client/src/app/shared/models/base.model.ts +++ b/client/src/app/shared/models/base.model.ts @@ -2,11 +2,6 @@ import { OpenSlidesComponent } from 'app/openslides.component'; import { Deserializable } from './deserializable.model'; import { CollectionStringModelMapperService } from '../../core/services/collectionStringModelMapper.service'; -/** - * Define that an ID might be a number or a string. - */ -export type ModelId = number | string; - export interface ModelConstructor { new (...args: any[]): BaseModel; } @@ -34,7 +29,7 @@ export abstract class BaseModel extends OpenSlidesComponent implements Deseriali /** * force children of BaseModel to have an id */ - public abstract id: ModelId; + public abstract id: number; /** * constructor that calls super from parent class diff --git a/client/src/app/shared/models/motions/motion.ts b/client/src/app/shared/models/motions/motion.ts index 4f6ab77bf..dced05639 100644 --- a/client/src/app/shared/models/motions/motion.ts +++ b/client/src/app/shared/models/motions/motion.ts @@ -81,7 +81,7 @@ export class Motion extends BaseModel { }); // observe for new models - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (newModel instanceof Workflow) { if (newModel.isStateContained(this.state_id)) { this.workflow = newModel as Workflow; diff --git a/client/src/app/site/motions/category-list/category-list.component.ts b/client/src/app/site/motions/category-list/category-list.component.ts index 41cd371a6..42ae05538 100644 --- a/client/src/app/site/motions/category-list/category-list.component.ts +++ b/client/src/app/site/motions/category-list/category-list.component.ts @@ -59,7 +59,7 @@ export class CategoryListComponent extends BaseComponent implements OnInit { // Observe DataStore for motions. Initially, executes once for every motion. // The alternative approach is to put the observable as DataSource to the table - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (newModel instanceof Category) { this.categoryArray = this.DS.getAll(Category); this.dataSource.data = this.categoryArray; diff --git a/client/src/app/site/motions/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/motion-detail/motion-detail.component.ts index 7b3ca61cf..8a39d7891 100644 --- a/client/src/app/site/motions/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/motion-detail/motion-detail.component.ts @@ -91,7 +91,7 @@ export class MotionDetailComponent extends BaseComponent implements OnInit { this.motion = this.DS.get(Motion, params.id) as Motion; // Observe motion to get the motion in the parameter and also get the changes - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (newModel instanceof Motion) { if (newModel.id === +params.id) { this.motion = newModel as Motion; diff --git a/client/src/app/site/motions/motion-list/motion-list.component.ts b/client/src/app/site/motions/motion-list/motion-list.component.ts index b55032f92..290771bd1 100644 --- a/client/src/app/site/motions/motion-list/motion-list.component.ts +++ b/client/src/app/site/motions/motion-list/motion-list.component.ts @@ -101,7 +101,7 @@ export class MotionListComponent extends BaseComponent implements OnInit { // Observe DataStore for motions. Initially, executes once for every motion. // The alternative approach is to put the observable as DataSource to the table - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (newModel instanceof Motion) { this.motionArray = this.DS.getAll(Motion); this.dataSource.data = this.motionArray; diff --git a/client/src/app/site/start/start.component.ts b/client/src/app/site/start/start.component.ts index 56a354860..b873d10ea 100644 --- a/client/src/app/site/start/start.component.ts +++ b/client/src/app/site/start/start.component.ts @@ -64,7 +64,7 @@ export class StartComponent extends BaseComponent implements OnInit { } // observe title and text in DS - this.DS.getObservable().subscribe(newModel => { + this.DS.changeObservable.subscribe(newModel => { if (newModel instanceof Config) { if (newModel.key === 'general_event_welcome_title') { this.welcomeTitle = newModel.value as string;