Speedup DS and repo updates, DSUpdateSlots, lazyloading history objects
This commit is contained in:
parent
8fb12a6882
commit
fe81ea6ff9
@ -3,7 +3,7 @@ import { Injectable, Injector } from '@angular/core';
|
|||||||
import { plugins } from '../../../plugins';
|
import { plugins } from '../../../plugins';
|
||||||
import { CommonAppConfig } from '../../site/common/common.config';
|
import { CommonAppConfig } from '../../site/common/common.config';
|
||||||
import { AppConfig, SearchableModelEntry, ModelEntry } from '../app-config';
|
import { AppConfig, SearchableModelEntry, ModelEntry } from '../app-config';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
import { MediafileAppConfig } from '../../site/mediafiles/mediafile.config';
|
import { MediafileAppConfig } from '../../site/mediafiles/mediafile.config';
|
||||||
import { MotionsAppConfig } from '../../site/motions/motions.config';
|
import { MotionsAppConfig } from '../../site/motions/motions.config';
|
||||||
import { ConfigAppConfig } from '../../site/config/config.config';
|
import { ConfigAppConfig } from '../../site/config/config.config';
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { WebsocketService } from './websocket.service';
|
import { WebsocketService } from './websocket.service';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
import { DataStoreService } from './data-store.service';
|
import { DataStoreService } from './data-store.service';
|
||||||
import { BaseModel } from '../../shared/models/base/base-model';
|
import { BaseModel } from '../../shared/models/base/base-model';
|
||||||
|
import { DataStoreUpdateManagerService } from './data-store-update-manager.service';
|
||||||
|
|
||||||
interface AutoupdateFormat {
|
interface AutoupdateFormat {
|
||||||
/**
|
/**
|
||||||
@ -54,7 +55,8 @@ export class AutoupdateService {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private websocketService: WebsocketService,
|
private websocketService: WebsocketService,
|
||||||
private DS: DataStoreService,
|
private DS: DataStoreService,
|
||||||
private modelMapper: CollectionStringMapperService
|
private modelMapper: CollectionStringMapperService,
|
||||||
|
private DSUpdateManager: DataStoreUpdateManagerService
|
||||||
) {
|
) {
|
||||||
this.websocketService.getOberservable<AutoupdateFormat>('autoupdate').subscribe(response => {
|
this.websocketService.getOberservable<AutoupdateFormat>('autoupdate').subscribe(response => {
|
||||||
this.storeResponse(response);
|
this.storeResponse(response);
|
||||||
@ -105,6 +107,8 @@ export class AutoupdateService {
|
|||||||
|
|
||||||
// Normal autoupdate
|
// Normal autoupdate
|
||||||
if (autoupdate.from_change_id <= maxChangeId + 1 && autoupdate.to_change_id > maxChangeId) {
|
if (autoupdate.from_change_id <= maxChangeId + 1 && autoupdate.to_change_id > maxChangeId) {
|
||||||
|
const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS);
|
||||||
|
|
||||||
// Delete the removed objects from the DataStore
|
// Delete the removed objects from the DataStore
|
||||||
for (const collection of Object.keys(autoupdate.deleted)) {
|
for (const collection of Object.keys(autoupdate.deleted)) {
|
||||||
await this.DS.remove(collection, autoupdate.deleted[collection]);
|
await this.DS.remove(collection, autoupdate.deleted[collection]);
|
||||||
@ -120,6 +124,8 @@ export class AutoupdateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await this.DS.flushToStorage(autoupdate.to_change_id);
|
await this.DS.flushToStorage(autoupdate.to_change_id);
|
||||||
|
|
||||||
|
this.DSUpdateManager.commit(updateSlot);
|
||||||
} else {
|
} else {
|
||||||
// autoupdate fully in the future. we are missing something!
|
// autoupdate fully in the future. we are missing something!
|
||||||
this.requestChanges();
|
this.requestChanges();
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { E2EImportsModule } from '../../../e2e-imports.module';
|
||||||
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
|
|
||||||
|
describe('CollectionStringMapperService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
|
providers: [CollectionStringMapperService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([CollectionStringMapperService], (service: CollectionStringMapperService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
@ -17,6 +17,12 @@ interface UnifiedConstructors {
|
|||||||
*/
|
*/
|
||||||
type TypeIdentifier = UnifiedConstructors | BaseRepository<any, any> | string;
|
type TypeIdentifier = UnifiedConstructors | BaseRepository<any, any> | string;
|
||||||
|
|
||||||
|
type CollectionStringMappedTypes = [
|
||||||
|
ModelConstructor<BaseModel>,
|
||||||
|
ViewModelConstructor<BaseViewModel>,
|
||||||
|
BaseRepository<BaseViewModel, BaseModel>
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registeres the mapping between collection strings, models constructors, view
|
* Registeres the mapping between collection strings, models constructors, view
|
||||||
* model constructors and repositories.
|
* model constructors and repositories.
|
||||||
@ -30,11 +36,7 @@ export class CollectionStringMapperService {
|
|||||||
* Maps collection strings to mapping entries
|
* Maps collection strings to mapping entries
|
||||||
*/
|
*/
|
||||||
private collectionStringMapping: {
|
private collectionStringMapping: {
|
||||||
[collectionString: string]: [
|
[collectionString: string]: CollectionStringMappedTypes;
|
||||||
ModelConstructor<BaseModel>,
|
|
||||||
ViewModelConstructor<BaseViewModel>,
|
|
||||||
BaseRepository<BaseViewModel, BaseModel>
|
|
||||||
];
|
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
public constructor() {}
|
public constructor() {}
|
||||||
@ -65,6 +67,9 @@ export class CollectionStringMapperService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true, if the given collection is known by this service.
|
||||||
|
*/
|
||||||
public isCollectionRegistered(collectionString: string): boolean {
|
public isCollectionRegistered(collectionString: string): boolean {
|
||||||
return !!this.collectionStringMapping[collectionString];
|
return !!this.collectionStringMapping[collectionString];
|
||||||
}
|
}
|
||||||
@ -100,4 +105,11 @@ export class CollectionStringMapperService {
|
|||||||
return this.collectionStringMapping[this.getCollectionString(obj)][2] as BaseRepository<V, M>;
|
return this.collectionStringMapping[this.getCollectionString(obj)][2] as BaseRepository<V, M>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns all registered repositories.
|
||||||
|
*/
|
||||||
|
public getAllRepositories(): BaseRepository<any, any>[] {
|
||||||
|
return Object.values(this.collectionStringMapping).map((types: CollectionStringMappedTypes) => types[2]);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,3 +0,0 @@
|
|||||||
describe('CollectionStringModelMapperService', () => {
|
|
||||||
beforeEach(() => {});
|
|
||||||
});
|
|
@ -0,0 +1,17 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { E2EImportsModule } from '../../../e2e-imports.module';
|
||||||
|
import { DataStoreUpdateManagerService } from './data-store-update-manager.service';
|
||||||
|
|
||||||
|
describe('DataStoreUpdateManagerService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
|
providers: [DataStoreUpdateManagerService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([DataStoreUpdateManagerService], (service: DataStoreUpdateManagerService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
@ -0,0 +1,182 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Deferred } from '../deferred';
|
||||||
|
import { DataStoreService } from './data-store.service';
|
||||||
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
|
|
||||||
|
export interface CollectionIds {
|
||||||
|
[collection: string]: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for collecting data during the update phase of the DataStore.
|
||||||
|
*/
|
||||||
|
export class UpdateSlot {
|
||||||
|
/**
|
||||||
|
* Count instnaces of this class to easily compare them.
|
||||||
|
*/
|
||||||
|
private static ID_COUTNER = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of changed model ids to their collection.
|
||||||
|
*/
|
||||||
|
private changedModels: CollectionIds = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of deleted models to their collection.
|
||||||
|
*/
|
||||||
|
private deletedModels: CollectionIds = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object's id.
|
||||||
|
*/
|
||||||
|
private _id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param DS Carries the DataStore: TODO (see below `DataStoreUpdateManagerService.getNewUpdateSlot`)
|
||||||
|
*/
|
||||||
|
public constructor(public readonly DS: DataStoreService) {
|
||||||
|
this._id = UpdateSlot.ID_COUTNER++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds changed model information
|
||||||
|
*
|
||||||
|
* @param collection The collection
|
||||||
|
* @param id The id
|
||||||
|
*/
|
||||||
|
public addChangedModel(collection: string, id: number): void {
|
||||||
|
if (!this.changedModels[collection]) {
|
||||||
|
this.changedModels[collection] = [];
|
||||||
|
}
|
||||||
|
this.changedModels[collection].push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds deleted model information
|
||||||
|
*
|
||||||
|
* @param collection The collection
|
||||||
|
* @param id The id
|
||||||
|
*/
|
||||||
|
public addDeletedModel(collection: string, id: number): void {
|
||||||
|
if (!this.deletedModels[collection]) {
|
||||||
|
this.deletedModels[collection] = [];
|
||||||
|
}
|
||||||
|
this.deletedModels[collection].push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param collection The collection
|
||||||
|
* @returns the list of changed model ids for the collection
|
||||||
|
*/
|
||||||
|
public getChangedModelIdsForCollection(collection: string): number[] {
|
||||||
|
return this.changedModels[collection] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the mapping of all changed models
|
||||||
|
*/
|
||||||
|
public getChangedModels(): CollectionIds {
|
||||||
|
return this.changedModels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param collection The collection
|
||||||
|
* @returns the list of deleted model ids for the collection
|
||||||
|
*/
|
||||||
|
public getDeletedModelIdsForCollection(collection: string): number[] {
|
||||||
|
return this.deletedModels[collection] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this object to another update slot.
|
||||||
|
*/
|
||||||
|
public equal(other: UpdateSlot): boolean {
|
||||||
|
return this._id === other._id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages updates in the DS. Collects all ids for changed and deleted models and bulk-update
|
||||||
|
* affected repositories.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DataStoreUpdateManagerService {
|
||||||
|
/**
|
||||||
|
* The current update slot
|
||||||
|
*/
|
||||||
|
private currentUpdateSlot: UpdateSlot | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests for getting an update slot.
|
||||||
|
*/
|
||||||
|
private updateSlotRequests: Deferred[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mapperService
|
||||||
|
*/
|
||||||
|
public constructor(private mapperService: CollectionStringMapperService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current update slot.
|
||||||
|
*/
|
||||||
|
public getCurrentUpdateSlot(): UpdateSlot | null {
|
||||||
|
return this.currentUpdateSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new update slot. Returns a promise that must be awaited, if there is another
|
||||||
|
* update in progress.
|
||||||
|
*
|
||||||
|
* @param DS The DataStore. This is a hack, becuase we cannot use the DataStore
|
||||||
|
* here, because these are cyclic dependencies... --> TODO
|
||||||
|
*/
|
||||||
|
public async getNewUpdateSlot(DS: DataStoreService): Promise<UpdateSlot> {
|
||||||
|
if (this.currentUpdateSlot) {
|
||||||
|
const request = new Deferred();
|
||||||
|
this.updateSlotRequests.push(request);
|
||||||
|
await request.promise;
|
||||||
|
}
|
||||||
|
this.currentUpdateSlot = new UpdateSlot(DS);
|
||||||
|
return this.currentUpdateSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits the given update slot. THis slot must be the current one. If there are requests
|
||||||
|
* for update slots queued, the next one will be served.
|
||||||
|
*
|
||||||
|
* Note: I added this param to make sure, that only the user of the slot
|
||||||
|
* can commit the update and no one else.
|
||||||
|
*
|
||||||
|
* @param slot The slot to commit
|
||||||
|
*/
|
||||||
|
public commit(slot: UpdateSlot): void {
|
||||||
|
if (!this.currentUpdateSlot || !this.currentUpdateSlot.equal(slot)) {
|
||||||
|
throw new Error('No or wrong update slot to be finished!');
|
||||||
|
}
|
||||||
|
this.currentUpdateSlot = null;
|
||||||
|
|
||||||
|
// notify repositories in two phases
|
||||||
|
const repositories = this.mapperService.getAllRepositories();
|
||||||
|
|
||||||
|
// Phase 1: deleting and creating of view models (in this order)
|
||||||
|
repositories.forEach(repo => {
|
||||||
|
repo.deleteModels(slot.getDeletedModelIdsForCollection(repo.collectionString));
|
||||||
|
repo.changedModels(slot.getChangedModelIdsForCollection(repo.collectionString));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Phase 2: updating dependencies
|
||||||
|
repositories.forEach(repo => {
|
||||||
|
repo.updateDependencies(slot.getChangedModels());
|
||||||
|
});
|
||||||
|
|
||||||
|
slot.DS.triggerModifiedObservable();
|
||||||
|
|
||||||
|
// serve next slot request
|
||||||
|
if (this.updateSlotRequests.length > 0) {
|
||||||
|
const request = this.updateSlotRequests.pop();
|
||||||
|
request.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,8 @@ import { Observable, Subject } from 'rxjs';
|
|||||||
|
|
||||||
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
|
import { DataStoreUpdateManagerService } from './data-store-update-manager.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents information about a deleted model.
|
* Represents information about a deleted model.
|
||||||
@ -68,59 +69,23 @@ export class DataStoreService {
|
|||||||
private jsonStore: JsonStorage = {};
|
private jsonStore: JsonStorage = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable subject for changed models in the datastore.
|
* Subjects for changed elements (notified, even if there is a current update slot) for
|
||||||
|
* a specific collection.
|
||||||
*/
|
*/
|
||||||
private readonly changedSubject: Subject<BaseModel> = new Subject<BaseModel>();
|
private changedSubjects: { [collection: string]: Subject<BaseModel> } = {};
|
||||||
|
|
||||||
/**
|
|
||||||
* This is subject notify all subscribers _before_ the `secondaryModelChangeSubject`.
|
|
||||||
* It's the same subject as the changedSubject.
|
|
||||||
*/
|
|
||||||
public readonly primaryModelChangeSubject = new Subject<BaseModel>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is subject notify all subscribers _after_ the `primaryModelChangeSubject`.
|
|
||||||
* It's the same subject as the changedSubject.
|
|
||||||
*/
|
|
||||||
public readonly secondaryModelChangeSubject = new Subject<BaseModel>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe the datastore for changes.
|
|
||||||
*
|
|
||||||
* @return an observable for changed models
|
|
||||||
*/
|
|
||||||
public get changeObservable(): Observable<BaseModel> {
|
|
||||||
return this.changedSubject.asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observable subject for changed models in the datastore.
|
|
||||||
*/
|
|
||||||
private readonly deletedSubject: Subject<DeletedInformation> = new Subject<DeletedInformation>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observe the datastore for deletions.
|
|
||||||
*
|
|
||||||
* @return an observable for deleted objects.
|
|
||||||
*/
|
|
||||||
public get deletedObservable(): Observable<DeletedInformation> {
|
|
||||||
return this.deletedSubject.asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable subject for changed or deleted models in the datastore.
|
* Observable subject for changed or deleted models in the datastore.
|
||||||
*/
|
*/
|
||||||
private readonly changedOrDeletedSubject: Subject<BaseModel | DeletedInformation> = new Subject<
|
private readonly modifiedSubject: Subject<void> = new Subject<void>();
|
||||||
BaseModel | DeletedInformation
|
|
||||||
>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observe the datastore for changes and deletions.
|
* Observe the datastore for changes and deletions.
|
||||||
*
|
*
|
||||||
* @return an observable for changed and deleted objects.
|
* @return an observable for changed and deleted objects.
|
||||||
*/
|
*/
|
||||||
public get changedOrDeletedObservable(): Observable<BaseModel | DeletedInformation> {
|
public get modifiedObservable(): Observable<void> {
|
||||||
return this.changedOrDeletedSubject.asObservable();
|
return this.modifiedSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,12 +117,26 @@ export class DataStoreService {
|
|||||||
/**
|
/**
|
||||||
* @param storageService use StorageService to preserve the DataStore.
|
* @param storageService use StorageService to preserve the DataStore.
|
||||||
* @param modelMapper
|
* @param modelMapper
|
||||||
|
* @param DSUpdateManager
|
||||||
*/
|
*/
|
||||||
public constructor(private storageService: StorageService, private modelMapper: CollectionStringMapperService) {
|
public constructor(
|
||||||
this.changeObservable.subscribe(model => {
|
private storageService: StorageService,
|
||||||
this.primaryModelChangeSubject.next(model);
|
private modelMapper: CollectionStringMapperService,
|
||||||
this.secondaryModelChangeSubject.next(model);
|
private DSUpdateManager: DataStoreUpdateManagerService
|
||||||
});
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an model observable for models from a given collection. These observable will be notified,
|
||||||
|
* even if there is an active update slot. So use this with caution (-> only collections with less models).
|
||||||
|
*
|
||||||
|
* @param collectionType The collection
|
||||||
|
*/
|
||||||
|
public getChangeObservable<T extends BaseModel>(collectionType: ModelConstructor<T> | string): Observable<T> {
|
||||||
|
const collection = this.getCollectionString(collectionType);
|
||||||
|
if (!this.changedSubjects[collection]) {
|
||||||
|
this.changedSubjects[collection] = new Subject();
|
||||||
|
}
|
||||||
|
return this.changedSubjects[collection].asObservable() as Observable<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,12 +144,15 @@ export class DataStoreService {
|
|||||||
* @returns The max change id.
|
* @returns The max change id.
|
||||||
*/
|
*/
|
||||||
public async initFromStorage(): Promise<number> {
|
public async initFromStorage(): Promise<number> {
|
||||||
// This promise will be resolved with the maximal change id of the cache.
|
// This promise will be resolved with cached datastore.
|
||||||
const store = await this.storageService.get<JsonStorage>(DataStoreService.cachePrefix + 'DS');
|
const store = await this.storageService.get<JsonStorage>(DataStoreService.cachePrefix + 'DS');
|
||||||
if (store) {
|
if (store) {
|
||||||
|
const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this);
|
||||||
|
|
||||||
// There is a store. Deserialize it
|
// There is a store. Deserialize it
|
||||||
this.jsonStore = store;
|
this.jsonStore = store;
|
||||||
this.modelStore = this.deserializeJsonStore(this.jsonStore);
|
this.modelStore = this.deserializeJsonStore(this.jsonStore);
|
||||||
|
|
||||||
// Get the maxChangeId from the cache
|
// Get the maxChangeId from the cache
|
||||||
let maxChangeId = await this.storageService.get<number>(DataStoreService.cachePrefix + 'maxChangeId');
|
let maxChangeId = await this.storageService.get<number>(DataStoreService.cachePrefix + 'maxChangeId');
|
||||||
if (!maxChangeId) {
|
if (!maxChangeId) {
|
||||||
@ -184,6 +166,8 @@ export class DataStoreService {
|
|||||||
this.publishChangedInformation(this.modelStore[collection][id]);
|
this.publishChangedInformation(this.modelStore[collection][id]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.DSUpdateManager.commit(updateSlot);
|
||||||
} else {
|
} else {
|
||||||
await this.clear();
|
await this.clear();
|
||||||
}
|
}
|
||||||
@ -414,8 +398,17 @@ export class DataStoreService {
|
|||||||
* @param model The model to publish
|
* @param model The model to publish
|
||||||
*/
|
*/
|
||||||
private publishChangedInformation(model: BaseModel): void {
|
private publishChangedInformation(model: BaseModel): void {
|
||||||
this.changedSubject.next(model);
|
const slot = this.DSUpdateManager.getCurrentUpdateSlot();
|
||||||
this.changedOrDeletedSubject.next(model);
|
if (slot) {
|
||||||
|
slot.addChangedModel(model.collectionString, model.id);
|
||||||
|
// triggerModifiedObservable will be called by committing the update slot.
|
||||||
|
} else {
|
||||||
|
this.triggerModifiedObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.changedSubjects[model.collectionString]) {
|
||||||
|
this.changedSubjects[model.collectionString].next(model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -424,8 +417,20 @@ export class DataStoreService {
|
|||||||
* @param information The information about the deleted model
|
* @param information The information about the deleted model
|
||||||
*/
|
*/
|
||||||
private publishDeletedInformation(information: DeletedInformation): void {
|
private publishDeletedInformation(information: DeletedInformation): void {
|
||||||
this.deletedSubject.next(information);
|
const slot = this.DSUpdateManager.getCurrentUpdateSlot();
|
||||||
this.changedOrDeletedSubject.next(information);
|
if (slot) {
|
||||||
|
slot.addDeletedModel(information.collection, information.id);
|
||||||
|
// triggerModifiedObservable will be called by committing the update slot.
|
||||||
|
} else {
|
||||||
|
this.triggerModifiedObservable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the modified subject.
|
||||||
|
*/
|
||||||
|
public triggerModifiedObservable(): void {
|
||||||
|
this.modifiedSubject.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,7 +12,7 @@ import { OpenSlidesStatusService } from './openslides-status.service';
|
|||||||
import { ViewUser } from 'app/site/users/models/view-user';
|
import { ViewUser } from 'app/site/users/models/view-user';
|
||||||
import { OnAfterAppsLoaded } from '../onAfterAppsLoaded';
|
import { OnAfterAppsLoaded } from '../onAfterAppsLoaded';
|
||||||
import { UserRepositoryService } from '../repositories/users/user-repository.service';
|
import { UserRepositoryService } from '../repositories/users/user-repository.service';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { HttpService } from './http.service';
|
import { HttpService } from './http.service';
|
||||||
import { filter, auditTime } from 'rxjs/operators';
|
import { filter, auditTime } from 'rxjs/operators';
|
||||||
@ -139,23 +139,23 @@ export class OperatorService implements OnAfterAppsLoaded {
|
|||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private OSStatus: OpenSlidesStatusService
|
private OSStatus: OpenSlidesStatusService
|
||||||
) {
|
) {
|
||||||
this.DS.changeObservable.subscribe(newModel => {
|
this.DS.getChangeObservable(User).subscribe(newModel => {
|
||||||
if (this._user && newModel instanceof User && this._user.id === newModel.id) {
|
if (this._user && this._user.id === newModel.id) {
|
||||||
this._user = newModel;
|
this._user = newModel;
|
||||||
this.updateUserInCurrentWhoAmI();
|
this.updateUserInCurrentWhoAmI();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.DS.changeObservable
|
this.DS.getChangeObservable(Group)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(
|
filter(
|
||||||
model =>
|
model =>
|
||||||
// Any group has changed if we have an operator or
|
// Any group has changed if we have an operator or
|
||||||
// group 1 (default) for anonymous changed
|
// group 1 (default) for anonymous changed
|
||||||
model instanceof Group && (!!this._user || model.id === 1)
|
!!this._user || model.id === 1
|
||||||
),
|
),
|
||||||
auditTime(10)
|
auditTime(10)
|
||||||
)
|
)
|
||||||
.subscribe(newModel => this.updatePermissions());
|
.subscribe(_ => this.updatePermissions());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
import { History } from 'app/shared/models/core/history';
|
import { History } from 'app/shared/models/core/history';
|
||||||
import { DataStoreService } from './data-store.service';
|
import { DataStoreService } from './data-store.service';
|
||||||
import { WebsocketService } from './websocket.service';
|
import { WebsocketService } from './websocket.service';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CollectionStringMapperService } from './collectionStringMapper.service';
|
import { CollectionStringMapperService } from './collection-string-mapper.service';
|
||||||
import { BaseViewModel, ViewModelConstructor } from 'app/site/base/base-view-model';
|
import { BaseViewModel, ViewModelConstructor } from 'app/site/base/base-view-model';
|
||||||
import { BaseRepository } from '../repositories/base-repository';
|
import { BaseRepository } from '../repositories/base-repository';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* //
|
* //
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class Deferred<T> {
|
export class Deferred<T = void> {
|
||||||
/**
|
/**
|
||||||
* The promise to wait for
|
* The promise to wait for
|
||||||
*/
|
*/
|
||||||
@ -22,7 +22,7 @@ export class Deferred<T> {
|
|||||||
/**
|
/**
|
||||||
* custom resolve function
|
* custom resolve function
|
||||||
*/
|
*/
|
||||||
private _resolve: () => void;
|
private _resolve: (val?: T) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the promise and overloads the resolve function
|
* Creates the promise and overloads the resolve function
|
||||||
@ -36,7 +36,7 @@ export class Deferred<T> {
|
|||||||
/**
|
/**
|
||||||
* Entry point for the resolve function
|
* Entry point for the resolve function
|
||||||
*/
|
*/
|
||||||
public resolve(): void {
|
public resolve(val?: T): void {
|
||||||
this._resolve();
|
this._resolve(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { Observable } from 'rxjs';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
@ -17,6 +17,10 @@ import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model';
|
|||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||||
|
import { Motion } from 'app/shared/models/motions/motion';
|
||||||
|
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||||
|
import { Topic } from 'app/shared/models/topics/topic';
|
||||||
|
import { Assignment } from 'app/shared/models/assignments/assignment';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository service for users
|
* Repository service for users
|
||||||
@ -47,25 +51,18 @@ export class ItemRepositoryService extends BaseRepository<ViewItem, Item> {
|
|||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private treeService: TreeService
|
private treeService: TreeService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, translate, Item);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Item, [
|
||||||
|
Topic,
|
||||||
|
Assignment,
|
||||||
|
Motion,
|
||||||
|
MotionBlock
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
return this.translate.instant(plural ? 'Items' : 'Item');
|
return this.translate.instant(plural ? 'Items' : 'Item');
|
||||||
};
|
};
|
||||||
|
|
||||||
protected setupDependencyObservation(): void {
|
|
||||||
this.DS.secondaryModelChangeSubject.subscribe(model => {
|
|
||||||
const viewModel = this.viewModelStoreService.get(model.collectionString, model.id);
|
|
||||||
const somethingChanged = this.getViewModelList().some(ownViewModel => {
|
|
||||||
return ownViewModel.updateDependencies(viewModel);
|
|
||||||
});
|
|
||||||
if (somethingChanged) {
|
|
||||||
this.updateAllObservables(model.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the viewItem out of a given item
|
* Creates the viewItem out of a given item
|
||||||
*
|
*
|
||||||
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { Item } from 'app/shared/models/agenda/item';
|
import { Item } from 'app/shared/models/agenda/item';
|
||||||
|
@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { Assignment } from 'app/shared/models/assignments/assignment';
|
import { Assignment } from 'app/shared/models/assignments/assignment';
|
||||||
import { AssignmentRelatedUser } from 'app/shared/models/assignments/assignment-related-user';
|
import { AssignmentRelatedUser } from 'app/shared/models/assignments/assignment-related-user';
|
||||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
|
@ -2,7 +2,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
|
|
||||||
import { BaseViewModel } from '../../site/base/base-view-model';
|
import { BaseViewModel } from '../../site/base/base-view-model';
|
||||||
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
||||||
import { CollectionStringMapperService } from '../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from '../core-services/data-send.service';
|
import { DataSendService } from '../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../core-services/data-store.service';
|
import { DataStoreService } from '../core-services/data-store.service';
|
||||||
import { ViewModelStoreService } from '../core-services/view-model-store.service';
|
import { ViewModelStoreService } from '../core-services/view-model-store.service';
|
||||||
|
@ -3,7 +3,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
|
|
||||||
import { BaseViewModel } from '../../site/base/base-view-model';
|
import { BaseViewModel } from '../../site/base/base-view-model';
|
||||||
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
||||||
import { CollectionStringMapperService } from '../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from '../core-services/data-send.service';
|
import { DataSendService } from '../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../core-services/data-store.service';
|
import { DataStoreService } from '../core-services/data-store.service';
|
||||||
import { Identifiable } from '../../shared/models/base/identifiable';
|
import { Identifiable } from '../../shared/models/base/identifiable';
|
||||||
@ -11,6 +11,7 @@ import { auditTime } from 'rxjs/operators';
|
|||||||
import { ViewModelStoreService } from '../core-services/view-model-store.service';
|
import { ViewModelStoreService } from '../core-services/view-model-store.service';
|
||||||
import { OnAfterAppsLoaded } from '../onAfterAppsLoaded';
|
import { OnAfterAppsLoaded } from '../onAfterAppsLoaded';
|
||||||
import { Collection } from 'app/shared/models/base/collection';
|
import { Collection } from 'app/shared/models/base/collection';
|
||||||
|
import { CollectionIds } from '../core-services/data-store-update-manager.service';
|
||||||
|
|
||||||
export abstract class BaseRepository<V extends BaseViewModel, M extends BaseModel>
|
export abstract class BaseRepository<V extends BaseViewModel, M extends BaseModel>
|
||||||
implements OnAfterAppsLoaded, Collection {
|
implements OnAfterAppsLoaded, Collection {
|
||||||
@ -107,6 +108,10 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
this.updateViewModelListObservable();
|
this.updateViewModelListObservable();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.loadInitialFromDS();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected loadInitialFromDS(): void {
|
||||||
// Populate the local viewModelStore with ViewModel Objects.
|
// Populate the local viewModelStore with ViewModel Objects.
|
||||||
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
||||||
this.viewModelStore[model.id] = this.createViewModel(model);
|
this.viewModelStore[model.id] = this.createViewModel(model);
|
||||||
@ -117,61 +122,72 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
||||||
this.updateViewModelObservable(model.id);
|
this.updateViewModelObservable(model.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Could be raise in error if the root injector is not known
|
|
||||||
this.DS.primaryModelChangeSubject.subscribe(model => {
|
|
||||||
if (model instanceof this.baseModelCtor) {
|
|
||||||
// Add new and updated motions to the viewModelStore
|
|
||||||
this.viewModelStore[model.id] = this.createViewModel(model as M);
|
|
||||||
this.updateAllObservables(model.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setupDependencyObservation();
|
|
||||||
|
|
||||||
// Watch the Observables for deleting
|
|
||||||
// TODO: What happens, if some related object was deleted?
|
|
||||||
// My quess: This must trigger an autoupdate also for this model, because some IDs changed, so the
|
|
||||||
// affected models will be newly created by the primaryModelChangeSubject.
|
|
||||||
this.DS.deletedObservable.subscribe(model => {
|
|
||||||
if (model.collection === this.collectionStringMapperService.getCollectionString(this.baseModelCtor)) {
|
|
||||||
delete this.viewModelStore[model.id];
|
|
||||||
this.updateAllObservables(model.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the observation of dependency subjects.
|
* Deletes all models from the repository (internally, no requests). Informs all subjects.
|
||||||
*/
|
|
||||||
protected setupDependencyObservation(): void {
|
|
||||||
if (this.depsModelCtors) {
|
|
||||||
this.DS.secondaryModelChangeSubject.subscribe(model => {
|
|
||||||
const dependencyChanged: boolean = this.depsModelCtors.some(ctor => {
|
|
||||||
return model instanceof ctor;
|
|
||||||
});
|
|
||||||
if (dependencyChanged) {
|
|
||||||
const viewModel = this.viewModelStoreService.get(model.collectionString, model.id);
|
|
||||||
this.updateDependency(viewModel);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates all models with the provided `update` which is a dependency.
|
|
||||||
*
|
*
|
||||||
* @param update The dependency to update.
|
* @param ids All model ids
|
||||||
*/
|
*/
|
||||||
protected updateDependency(update: BaseViewModel): void {
|
public deleteModels(ids: number[]): void {
|
||||||
// if an domain object we need was added or changed, update viewModelStore
|
ids.forEach(id => {
|
||||||
this.getViewModelList().forEach(ownViewModel => {
|
delete this.viewModelStore[id];
|
||||||
ownViewModel.updateDependencies(update);
|
this.updateViewModelObservable(id);
|
||||||
this.updateViewModelObservable(ownViewModel.id);
|
|
||||||
});
|
});
|
||||||
this.updateViewModelListObservable();
|
this.updateViewModelListObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates or creates all given models in the repository (internally, no requests).
|
||||||
|
* Informs all subjects.
|
||||||
|
*
|
||||||
|
* @param ids All model ids.
|
||||||
|
*/
|
||||||
|
public changedModels(ids: number[]): void {
|
||||||
|
ids.forEach(id => {
|
||||||
|
this.viewModelStore[id] = this.createViewModel(this.DS.get(this.collectionString, id));
|
||||||
|
this.updateViewModelObservable(id);
|
||||||
|
});
|
||||||
|
this.updateViewModelListObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates all models in this repository with all changed models.
|
||||||
|
*
|
||||||
|
* @param changedModels A mapping of collections to ids of all changed models.
|
||||||
|
*/
|
||||||
|
public updateDependencies(changedModels: CollectionIds): void {
|
||||||
|
if (!this.depsModelCtors || this.depsModelCtors.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all viewModels from this repo once.
|
||||||
|
const viewModels = this.getViewModelList();
|
||||||
|
let somethingUpdated = false;
|
||||||
|
Object.keys(changedModels).forEach(collection => {
|
||||||
|
const dependencyChanged: boolean = this.depsModelCtors.some(ctor => {
|
||||||
|
return ctor.COLLECTIONSTRING === collection;
|
||||||
|
});
|
||||||
|
if (collection === this.collectionString || !dependencyChanged) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, we are affected by this collection. Update all viewModels from this repo.
|
||||||
|
viewModels.forEach(ownViewModel => {
|
||||||
|
changedModels[collection].forEach(id => {
|
||||||
|
ownViewModel.updateDependencies(this.viewModelStoreService.get(collection, id));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
somethingUpdated = true;
|
||||||
|
});
|
||||||
|
if (somethingUpdated) {
|
||||||
|
viewModels.forEach(ownViewModel => {
|
||||||
|
this.updateViewModelObservable(ownViewModel.id);
|
||||||
|
});
|
||||||
|
this.updateViewModelListObservable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the (full) update to an existing model. So called "update"-function
|
* Saves the (full) update to an existing model. So called "update"-function
|
||||||
* Provides a default procedure, but can be overwritten if required
|
* Provides a default procedure, but can be overwritten if required
|
||||||
|
@ -10,7 +10,7 @@ import { DataStoreService } from 'app/core/core-services/data-store.service';
|
|||||||
import { ConstantsService } from 'app/core/core-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { ViewConfig } from 'app/site/config/models/view-config';
|
import { ViewConfig } from 'app/site/config/models/view-config';
|
||||||
|
|
||||||
@ -88,6 +88,16 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
*/
|
*/
|
||||||
protected configListSubject: BehaviorSubject<ConfigGroup[]> = new BehaviorSubject<ConfigGroup[]>(null);
|
protected configListSubject: BehaviorSubject<ConfigGroup[]> = new BehaviorSubject<ConfigGroup[]>(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves, if we got config variables (the structure) from the server.
|
||||||
|
*/
|
||||||
|
protected gotConfigsVariables = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves, if we got first configs via autoupdate or cache.
|
||||||
|
*/
|
||||||
|
protected gotFirstUpdate = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for ConfigRepositoryService. Requests the constants from the server and creates the config group structure.
|
* Constructor for ConfigRepositoryService. Requests the constants from the server and creates the config group structure.
|
||||||
*
|
*
|
||||||
@ -109,7 +119,9 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
|
|
||||||
this.constantsService.get('ConfigVariables').subscribe(constant => {
|
this.constantsService.get('ConfigVariables').subscribe(constant => {
|
||||||
this.createConfigStructure(constant);
|
this.createConfigStructure(constant);
|
||||||
this.updateConfigStructure(true, ...Object.values(this.viewModelStore));
|
this.updateConfigStructure(false, ...Object.values(this.viewModelStore));
|
||||||
|
this.gotConfigsVariables = true;
|
||||||
|
this.checkConfigStructure();
|
||||||
this.updateConfigListObservable();
|
this.updateConfigListObservable();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -146,30 +158,23 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
throw new Error('Config variables cannot be created');
|
throw new Error('Config variables cannot be created');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected loadInitialFromDS(): void {
|
||||||
* Overwritten setup. Does only care about the custom list observable and inserts changed configs into the
|
|
||||||
* config group structure.
|
|
||||||
*/
|
|
||||||
public onAfterAppsLoaded(): void {
|
|
||||||
if (!this.configListSubject) {
|
|
||||||
this.configListSubject = new BehaviorSubject<ConfigGroup[]>(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.DS.getAll(Config).forEach((config: Config) => {
|
this.DS.getAll(Config).forEach((config: Config) => {
|
||||||
this.viewModelStore[config.id] = this.createViewModel(config);
|
this.viewModelStore[config.id] = this.createViewModel(config);
|
||||||
this.updateConfigStructure(false, this.viewModelStore[config.id]);
|
this.updateConfigStructure(false, this.viewModelStore[config.id]);
|
||||||
});
|
});
|
||||||
this.updateConfigListObservable();
|
this.updateConfigListObservable();
|
||||||
|
}
|
||||||
|
|
||||||
// Could be raise in error if the root injector is not known
|
public changedModels(ids: number[]): void {
|
||||||
// TODO go over repo
|
super.changedModels(ids);
|
||||||
this.DS.changeObservable.subscribe(model => {
|
|
||||||
if (model instanceof Config) {
|
ids.forEach(id => {
|
||||||
this.viewModelStore[model.id] = this.createViewModel(model as Config);
|
this.updateConfigStructure(false, this.viewModelStore[id]);
|
||||||
this.updateConfigStructure(false, this.viewModelStore[model.id]);
|
|
||||||
this.updateConfigListObservable();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
this.gotFirstUpdate = true;
|
||||||
|
this.checkConfigStructure();
|
||||||
|
this.updateConfigListObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,6 +200,16 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
return this.configs;
|
return this.configs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the config structure, if we got configs (first data) and the
|
||||||
|
* structure (config variables)
|
||||||
|
*/
|
||||||
|
protected checkConfigStructure(): void {
|
||||||
|
if (this.gotConfigsVariables && this.gotFirstUpdate) {
|
||||||
|
this.updateConfigStructure(true, ...Object.values(this.viewModelStore));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With a given (and maybe partially filled) config structure, all given view configs are put into it.
|
* With a given (and maybe partially filled) config structure, all given view configs are put into it.
|
||||||
* @param check Whether to check, if all given configs are there (according to the config structure).
|
* @param check Whether to check, if all given configs are there (according to the config structure).
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
||||||
import { BaseRepository } from 'app/core/repositories/base-repository';
|
import { BaseRepository } from 'app/core/repositories/base-repository';
|
||||||
import { History } from 'app/shared/models/core/history';
|
import { History } from 'app/shared/models/core/history';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { User } from 'app/shared/models/users/user';
|
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { ViewHistory } from 'app/site/history/models/view-history';
|
import { ViewHistory, ProxyHistory } from 'app/site/history/models/view-history';
|
||||||
import { TimeTravelService } from 'app/core/core-services/time-travel.service';
|
import { TimeTravelService } from 'app/core/core-services/time-travel.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { ViewUser } from 'app/site/users/models/view-user';
|
import { ViewUser } from 'app/site/users/models/view-user';
|
||||||
@ -40,7 +39,7 @@ export class HistoryRepositoryService extends BaseRepository<ViewHistory, Histor
|
|||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private timeTravel: TimeTravelService
|
private timeTravel: TimeTravelService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, translate, History, [User]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, History);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
@ -54,12 +53,29 @@ export class HistoryRepositoryService extends BaseRepository<ViewHistory, Histor
|
|||||||
* @return a new ViewHistory object
|
* @return a new ViewHistory object
|
||||||
*/
|
*/
|
||||||
public createViewModel(history: History): ViewHistory {
|
public createViewModel(history: History): ViewHistory {
|
||||||
const user = this.viewModelStoreService.get(ViewUser, history.user_id);
|
const viewHistory = new ViewHistory(this.createProxyHistory(history));
|
||||||
const viewHistory = new ViewHistory(history, user);
|
|
||||||
viewHistory.getVerboseName = this.getVerboseName;
|
viewHistory.getVerboseName = this.getVerboseName;
|
||||||
return viewHistory;
|
return viewHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ProxyHistory from a History by wrapping it and give access to the user.
|
||||||
|
*
|
||||||
|
* @param history The History object
|
||||||
|
* @returns the ProxyHistory
|
||||||
|
*/
|
||||||
|
private createProxyHistory(history: History): ProxyHistory {
|
||||||
|
return new Proxy(history, {
|
||||||
|
get: (instance, property) => {
|
||||||
|
if (property === 'user') {
|
||||||
|
return this.viewModelStoreService.get(ViewUser, instance.user_id);
|
||||||
|
} else {
|
||||||
|
return instance[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overwrites the default procedure
|
* Overwrites the default procedure
|
||||||
*
|
*
|
||||||
|
@ -6,7 +6,7 @@ import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
|||||||
import { User } from 'app/shared/models/users/user';
|
import { User } from 'app/shared/models/users/user';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { HttpHeaders } from '@angular/common/http';
|
import { HttpHeaders } from '@angular/common/http';
|
||||||
|
@ -4,7 +4,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { Category } from 'app/shared/models/motions/category';
|
import { Category } from 'app/shared/models/motions/category';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
|
@ -13,7 +13,7 @@ import { DataStoreService } from 'app/core/core-services/data-store.service';
|
|||||||
import { MotionChangeRecommendation } from 'app/shared/models/motions/motion-change-reco';
|
import { MotionChangeRecommendation } from 'app/shared/models/motions/motion-change-reco';
|
||||||
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-change-recommendation';
|
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-change-recommendation';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,7 @@ import { Observable } from 'rxjs';
|
|||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
|
@ -6,7 +6,7 @@ import { BaseRepository } from '../base-repository';
|
|||||||
import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section';
|
import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section';
|
||||||
import { MotionCommentSection } from 'app/shared/models/motions/motion-comment-section';
|
import { MotionCommentSection } from 'app/shared/models/motions/motion-comment-section';
|
||||||
import { Group } from 'app/shared/models/users/group';
|
import { Group } from 'app/shared/models/users/group';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { ViewGroup } from 'app/site/users/models/view-group';
|
import { ViewGroup } from 'app/site/users/models/view-group';
|
||||||
|
@ -7,7 +7,7 @@ import { tap, map } from 'rxjs/operators';
|
|||||||
|
|
||||||
import { Category } from 'app/shared/models/motions/category';
|
import { Category } from 'app/shared/models/motions/category';
|
||||||
import { ChangeRecoMode, ViewMotion } from 'app/site/motions/models/view-motion';
|
import { ChangeRecoMode, ViewMotion } from 'app/site/motions/models/view-motion';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
|
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
@ -39,10 +39,10 @@ import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
|
|||||||
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
||||||
import { ViewTag } from 'app/site/tags/models/view-tag';
|
import { ViewTag } from 'app/site/tags/models/view-tag';
|
||||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
|
||||||
import { PersonalNote, PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
import { PersonalNote, PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
||||||
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
import { CollectionIds } from 'app/core/core-services/data-store-update-manager.service';
|
||||||
|
|
||||||
type SortProperty = 'callListWeight' | 'identifier';
|
type SortProperty = 'callListWeight' | 'identifier';
|
||||||
|
|
||||||
@ -261,30 +261,48 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Special handling of updating personal notes.
|
||||||
* @param update
|
* @override
|
||||||
*
|
|
||||||
* @overwrite
|
|
||||||
*/
|
*/
|
||||||
protected updateDependency(update: BaseViewModel): void {
|
public updateDependencies(changedModels: CollectionIds): void {
|
||||||
if (update instanceof ViewPersonalNote) {
|
if (!this.depsModelCtors || this.depsModelCtors.length === 0) {
|
||||||
if (this.operator.isAnonymous || update.userId !== this.operator.user.id) {
|
return;
|
||||||
|
}
|
||||||
|
const viewModels = this.getViewModelList();
|
||||||
|
let somethingUpdated = false;
|
||||||
|
Object.keys(changedModels).forEach(collection => {
|
||||||
|
const dependencyChanged: boolean = this.depsModelCtors.some(ctor => {
|
||||||
|
return ctor.COLLECTIONSTRING === collection;
|
||||||
|
});
|
||||||
|
if (collection === this.collectionString || !dependencyChanged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const notes = update.notes;
|
|
||||||
const collection = Motion.COLLECTIONSTRING;
|
|
||||||
|
|
||||||
this.getViewModelList().forEach(ownViewModel => {
|
// Do not update personal notes, if the operator is anonymous
|
||||||
if (notes && notes[collection] && notes[collection][ownViewModel.id]) {
|
if (collection === PersonalNote.COLLECTIONSTRING && this.operator.isAnonymous) {
|
||||||
ownViewModel.personalNote = notes[collection][ownViewModel.id];
|
return;
|
||||||
} else {
|
}
|
||||||
ownViewModel.personalNote = null;
|
|
||||||
}
|
viewModels.forEach(ownViewModel => {
|
||||||
|
changedModels[collection].forEach(id => {
|
||||||
|
const viewModel = this.viewModelStoreService.get(collection, id);
|
||||||
|
// Only update the personal note, if the operator is the right user.
|
||||||
|
if (
|
||||||
|
collection === PersonalNote.COLLECTIONSTRING &&
|
||||||
|
(<ViewPersonalNote>viewModel).userId !== this.operator.user.id
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ownViewModel.updateDependencies(viewModel);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
somethingUpdated = true;
|
||||||
|
});
|
||||||
|
if (somethingUpdated) {
|
||||||
|
viewModels.forEach(ownViewModel => {
|
||||||
this.updateViewModelObservable(ownViewModel.id);
|
this.updateViewModelObservable(ownViewModel.id);
|
||||||
});
|
});
|
||||||
this.updateViewModelListObservable();
|
this.updateViewModelListObservable();
|
||||||
} else {
|
|
||||||
super.updateDependency(update);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { DataStoreService } from '../../core-services/data-store.service';
|
|||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
|
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
|
||||||
import { StatuteParagraph } from 'app/shared/models/motions/statute-paragraph';
|
import { StatuteParagraph } from 'app/shared/models/motions/statute-paragraph';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { ViewWorkflow } from 'app/site/motions/models/view-workflow';
|
|||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { WorkflowState } from 'app/shared/models/motions/workflow-state';
|
import { WorkflowState } from 'app/shared/models/motions/workflow-state';
|
||||||
import { ViewMotion } from 'app/site/motions/models/view-motion';
|
import { ViewMotion } from 'app/site/motions/models/view-motion';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
|
@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ViewCountdown } from 'app/site/projector/models/view-countdown';
|
import { ViewCountdown } from 'app/site/projector/models/view-countdown';
|
||||||
import { Countdown } from 'app/shared/models/core/countdown';
|
import { Countdown } from 'app/shared/models/core/countdown';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ProjectorMessage } from 'app/shared/models/core/projector-message';
|
import { ProjectorMessage } from 'app/shared/models/core/projector-message';
|
||||||
import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-message';
|
import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-message';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
|
@ -5,7 +5,7 @@ import { ViewTag } from 'app/site/tags/models/view-tag';
|
|||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ConstantsService } from '../../core-services/constants.service';
|
import { ConstantsService } from '../../core-services/constants.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
|
@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { PersonalNote } from 'app/shared/models/users/personal-note';
|
import { PersonalNote } from 'app/shared/models/users/personal-note';
|
||||||
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
||||||
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
|
@ -33,9 +33,9 @@ export class ConfigService {
|
|||||||
* Listen for changes of config variables.
|
* Listen for changes of config variables.
|
||||||
*/
|
*/
|
||||||
public constructor(private DS: DataStoreService) {
|
public constructor(private DS: DataStoreService) {
|
||||||
this.DS.changeObservable.subscribe(data => {
|
this.DS.getChangeObservable(Config).subscribe(data => {
|
||||||
// on changes notify the observers for specific keys.
|
// on changes notify the observers for specific keys.
|
||||||
if (data instanceof Config && this.configSubjects[data.key]) {
|
if (this.configSubjects[data.key]) {
|
||||||
this.configSubjects[data.key].next(data.value);
|
this.configSubjects[data.key].next(data.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -24,10 +24,8 @@ export class PersonalNoteService {
|
|||||||
*/
|
*/
|
||||||
public constructor(private operator: OperatorService, private DS: DataStoreService, private http: HttpService) {
|
public constructor(private operator: OperatorService, private DS: DataStoreService, private http: HttpService) {
|
||||||
operator.getUserObservable().subscribe(() => this.updatePersonalNoteObject());
|
operator.getUserObservable().subscribe(() => this.updatePersonalNoteObject());
|
||||||
this.DS.changeObservable.subscribe(model => {
|
this.DS.getChangeObservable(PersonalNote).subscribe(_ => {
|
||||||
if (model instanceof PersonalNote) {
|
this.updatePersonalNoteObject();
|
||||||
this.updatePersonalNoteObject();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import { UserRepositoryService } from 'app/core/repositories/users/user-reposito
|
|||||||
import { DurationService } from 'app/core/ui-services/duration.service';
|
import { DurationService } from 'app/core/ui-services/duration.service';
|
||||||
import { CurrentAgendaItemService } from 'app/site/projector/services/current-agenda-item.service';
|
import { CurrentAgendaItemService } from 'app/site/projector/services/current-agenda-item.service';
|
||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { CurrentListOfSpeakersSlideService } from 'app/site/projector/services/current-list-of-of-speakers-slide.service';
|
import { CurrentListOfSpeakersSlideService } from 'app/site/projector/services/current-list-of-of-speakers-slide.service';
|
||||||
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
|
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ export class SearchComponent extends BaseViewComponent implements OnInit {
|
|||||||
|
|
||||||
this.registeredModels = this.searchService.getRegisteredModels().map(rm => ({ ...rm, enabled: true }));
|
this.registeredModels = this.searchService.getRegisteredModels().map(rm => ({ ...rm, enabled: true }));
|
||||||
|
|
||||||
this.DS.changedOrDeletedObservable.pipe(auditTime(100)).subscribe(() => this.search());
|
this.DS.modifiedObservable.pipe(auditTime(100)).subscribe(() => this.search());
|
||||||
this.quickSearchSubject.pipe(debounceTime(250)).subscribe(query => this.search(query));
|
this.quickSearchSubject.pipe(debounceTime(250)).subscribe(query => this.search(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<!-- User -->
|
<!-- User -->
|
||||||
<ng-container matColumnDef="user">
|
<ng-container matColumnDef="user">
|
||||||
<mat-header-cell *matHeaderCellDef translate>Changed by</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef translate>Changed by</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let history">{{ history.user }}</mat-cell>
|
<mat-cell *matCellDef="let history">{{ history.user_full_name }}</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<mat-header-row *matHeaderRowDef="getRowDef()"></mat-header-row>
|
<mat-header-row *matHeaderRowDef="getRowDef()"></mat-header-row>
|
||||||
|
@ -2,6 +2,8 @@ import { BaseViewModel } from 'app/site/base/base-view-model';
|
|||||||
import { History } from 'app/shared/models/core/history';
|
import { History } from 'app/shared/models/core/history';
|
||||||
import { ViewUser } from 'app/site/users/models/view-user';
|
import { ViewUser } from 'app/site/users/models/view-user';
|
||||||
|
|
||||||
|
export type ProxyHistory = History & { user?: ViewUser };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View model for history objects
|
* View model for history objects
|
||||||
*/
|
*/
|
||||||
@ -11,38 +13,39 @@ export class ViewHistory extends BaseViewModel {
|
|||||||
/**
|
/**
|
||||||
* Private BaseModel of the history
|
* Private BaseModel of the history
|
||||||
*/
|
*/
|
||||||
private _history: History;
|
private _history: ProxyHistory;
|
||||||
|
|
||||||
/**
|
|
||||||
* Real representation of the user who altered the history.
|
|
||||||
* Determined from `History.user_id`
|
|
||||||
*/
|
|
||||||
private _user: ViewUser | null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the history property
|
* Read the history property
|
||||||
*/
|
*/
|
||||||
public get history(): History {
|
public get history(): ProxyHistory {
|
||||||
return this._history;
|
return this._history;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the user property
|
* Gets the users ViewUser.
|
||||||
*/
|
*/
|
||||||
public get user(): ViewUser {
|
public get user(): ViewUser | null {
|
||||||
return this._user ? this._user : null;
|
return this.history.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID of the history object
|
* Get the id of the history object
|
||||||
* Required by BaseViewModel
|
* Required by BaseViewModel
|
||||||
*
|
*
|
||||||
* @returns the ID as number
|
* @returns the id as number
|
||||||
*/
|
*/
|
||||||
public get id(): number {
|
public get id(): number {
|
||||||
return this.history.id;
|
return this.history.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the users full name
|
||||||
|
*/
|
||||||
|
public get user_full_name(): string {
|
||||||
|
return this.history.user ? this.history.user.full_name : '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the elementIDs of the history object
|
* Get the elementIDs of the history object
|
||||||
*
|
*
|
||||||
@ -81,10 +84,9 @@ export class ViewHistory extends BaseViewModel {
|
|||||||
* @param history the real history BaseModel
|
* @param history the real history BaseModel
|
||||||
* @param user the real user BaseModel
|
* @param user the real user BaseModel
|
||||||
*/
|
*/
|
||||||
public constructor(history: History, user?: ViewUser) {
|
public constructor(history: ProxyHistory) {
|
||||||
super(History.COLLECTIONSTRING);
|
super(History.COLLECTIONSTRING);
|
||||||
this._history = history;
|
this._history = history;
|
||||||
this._user = user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,14 +119,5 @@ export class ViewHistory extends BaseViewModel {
|
|||||||
return this.history;
|
return this.history;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public updateDependencies(update: BaseViewModel): void {}
|
||||||
* Updates the history object with new values
|
|
||||||
*
|
|
||||||
* @param update potentially the new values for history or it's components.
|
|
||||||
*/
|
|
||||||
public updateDependencies(update: BaseViewModel): void {
|
|
||||||
if (update instanceof ViewUser && this.history.user_id === update.id) {
|
|
||||||
this._user = update;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||||
import { CommonListOfSpeakersSlideData } from './common-list-of-speakers-slide-data';
|
import { CommonListOfSpeakersSlideData } from './common-list-of-speakers-slide-data';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { isBaseAgendaContentObjectRepository } from 'app/core/repositories/base-agenda-content-object-repository';
|
import { isBaseAgendaContentObjectRepository } from 'app/core/repositories/base-agenda-content-object-repository';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||||
import { ItemListSlideData, SlideItem } from './item-list-slide-data';
|
import { ItemListSlideData, SlideItem } from './item-list-slide-data';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service';
|
||||||
import { isBaseAgendaContentObjectRepository } from 'app/core/repositories/base-agenda-content-object-repository';
|
import { isBaseAgendaContentObjectRepository } from 'app/core/repositories/base-agenda-content-object-repository';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
Loading…
Reference in New Issue
Block a user