From 1d718dcb740066a5b8474033352c1bbd69a49102 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Tue, 13 Aug 2019 16:45:39 +0200 Subject: [PATCH] Fixed two little issues with relations and reverse mapping - Reverse setup for normal autoupdates (no initial loading) - reverse "set null" to be reflected to the mapping Also fixed a bug with redis --- .../core/core-services/autoupdate.service.ts | 4 +- .../core/core-services/data-store.service.ts | 10 +- .../core-services/relation-manager.service.ts | 120 ++++++++++++++---- .../core/core-services/time-travel.service.ts | 2 +- client/src/app/core/definitions/relations.ts | 15 ++- .../list-of-speakers-repository.service.ts | 6 +- .../assignment-repository.service.ts | 19 ++- .../base-has-content-object-repository.ts | 4 +- ...t-of-speakers-content-object-repository.ts | 8 +- ...s-agenda-item-content-object-repository.ts | 6 +- ...t-of-speakers-content-object-repository.ts | 6 +- .../app/core/repositories/base-repository.ts | 18 ++- .../config/config-repository.service.ts | 4 +- .../mediafile-repository.service.ts | 6 +- .../motions/category-repository.service.ts | 6 +- .../motion-block-repository.service.ts | 2 +- ...tion-comment-section-repository.service.ts | 4 +- .../motions/motion-repository.service.ts | 32 ++--- .../motions/state-repository.service.ts | 4 +- .../motions/workflow-repository.service.ts | 4 +- .../projector/projector-repository.service.ts | 2 +- .../topics/topic-repository.service.ts | 2 +- .../users/user-repository.service.ts | 6 +- .../assignments/assignment-poll-option.ts | 8 +- .../models/view-assignment-poll-option.ts | 5 +- openslides/utils/cache_providers.py | 2 +- 26 files changed, 198 insertions(+), 107 deletions(-) diff --git a/client/src/app/core/core-services/autoupdate.service.ts b/client/src/app/core/core-services/autoupdate.service.ts index d12a5b235..75ea1e2f7 100644 --- a/client/src/app/core/core-services/autoupdate.service.ts +++ b/client/src/app/core/core-services/autoupdate.service.ts @@ -97,7 +97,7 @@ export class AutoupdateService { elements = elements.concat(this.mapObjectsToBaseModels(collection, autoupdate.changed[collection])); }); - const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS); + const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS, true); await this.DS.set(elements, autoupdate.to_change_id); this.DSUpdateManager.commit(updateSlot); } @@ -172,7 +172,7 @@ export class AutoupdateService { const oldChangeId = this.DS.maxChangeId; const response = await this.websocketService.sendAndGetResponse<{}, AutoupdateFormat>('getElements', {}); - const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS); + const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS, true); let allModels: BaseModel[] = []; for (const collection of Object.keys(response.changed)) { if (this.modelMapper.isCollectionRegistered(collection)) { diff --git a/client/src/app/core/core-services/data-store.service.ts b/client/src/app/core/core-services/data-store.service.ts index 5b37c71d2..9c31da88e 100644 --- a/client/src/app/core/core-services/data-store.service.ts +++ b/client/src/app/core/core-services/data-store.service.ts @@ -49,7 +49,7 @@ export class UpdateSlot { /** * @param DS Carries the DataStore: TODO (see below `DataStoreUpdateManagerService.getNewUpdateSlot`) */ - public constructor(public readonly DS: DataStoreService) { + public constructor(public readonly DS: DataStoreService, public readonly initialLoading: boolean) { this._id = UpdateSlot.ID_COUTNER++; } @@ -185,13 +185,13 @@ export class DataStoreUpdateManagerService { * @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 { + public async getNewUpdateSlot(DS: DataStoreService, initialLoading: boolean = false): Promise { if (this.currentUpdateSlot) { const request = new Deferred(); this.updateSlotRequests.push(request); await request; } - this.currentUpdateSlot = new UpdateSlot(DS); + this.currentUpdateSlot = new UpdateSlot(DS, initialLoading); return this.currentUpdateSlot; } @@ -221,7 +221,7 @@ export class DataStoreUpdateManagerService { const deletedModelIds = slot.getDeletedModelIdsForCollection(repo.collectionString); repo.deleteModels(deletedModelIds); const changedModelIds = slot.getChangedModelIdsForCollection(repo.collectionString); - repo.changedModels(changedModelIds); + repo.changedModels(changedModelIds, slot.initialLoading); if (deletedModelIds.length || changedModelIds.length) { affectedRepos[repo.collectionString] = repo; @@ -350,7 +350,7 @@ export class DataStoreService { // This promise will be resolved with cached datastore. const store = await this.storageService.get(DataStoreService.cachePrefix + 'DS'); if (store) { - const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this); + const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this, true); // There is a store. Deserialize it this.jsonStore = store; diff --git a/client/src/app/core/core-services/relation-manager.service.ts b/client/src/app/core/core-services/relation-manager.service.ts index 7b9f4d55d..b7bdeb210 100644 --- a/client/src/app/core/core-services/relation-manager.service.ts +++ b/client/src/app/core/core-services/relation-manager.service.ts @@ -48,12 +48,13 @@ export class RelationManagerService { public createViewModel( model: M, modelCtor: ViewModelConstructor, - relations: RelationDefinition[] + relations: RelationDefinition[], + initialLoading: boolean ): V { const viewModel = new modelCtor(model) as V; relations.forEach(relation => { - this.setRelationsInViewModel(model, viewModel, relation); + this.setRelationsInViewModel(model, viewModel, relation, initialLoading); }); return viewModel; @@ -66,30 +67,65 @@ export class RelationManagerService { protected setRelationsInViewModel( model: M, viewModel: V, - relation: RelationDefinition + relation: RelationDefinition, + initialLoading: boolean ): void { - // no reverse setting needed. This is done in the second phase of the ds-upgrade-manager - if (isReverseRelationDefinition(relation)) { - return; - } - - if ( - (relation.type === 'M2M' || relation.type === 'O2M') && - model[relation.ownIdKey] && - model[relation.ownIdKey].constructor === Array - ) { - const foreignViewModels = this.viewModelStoreService.getMany( - relation.foreignModel, - model[relation.ownIdKey] - ); - viewModel['_' + relation.ownKey] = foreignViewModels; - this.sortByRelation(relation, viewModel); - } else if (relation.type === 'M2O') { - const foreignViewModel = this.viewModelStoreService.get(relation.foreignModel, model[relation.ownIdKey]); - viewModel['_' + relation.ownKey] = foreignViewModel; + if (isNormalRelationDefinition(relation)) { + if ( + (relation.type === 'M2M' || relation.type === 'O2M') && + model[relation.ownIdKey] && + model[relation.ownIdKey].constructor === Array + ) { + const foreignViewModels = this.viewModelStoreService.getMany( + relation.foreignViewModel, + model[relation.ownIdKey] + ); + viewModel['_' + relation.ownKey] = foreignViewModels; + this.sortByRelation(relation, viewModel); + } else if (relation.type === 'M2O') { + const foreignViewModel = this.viewModelStoreService.get( + relation.foreignViewModel, + model[relation.ownIdKey] + ); + viewModel['_' + relation.ownKey] = foreignViewModel; + } + } else if (isReverseRelationDefinition(relation) && !initialLoading) { + if (relation.type === 'M2M') { + const foreignViewModels = this.viewModelStoreService.filter( + relation.foreignViewModel, + foreignViewModel => + foreignViewModel[relation.foreignIdKey] && + foreignViewModel[relation.foreignIdKey].constructor === Array && + foreignViewModel[relation.foreignIdKey].includes(model.id) + ); + viewModel['_' + relation.ownKey] = foreignViewModels; + this.sortByRelation(relation, viewModel); + } else if (relation.type === 'O2M') { + const foreignViewModels = this.viewModelStoreService.filter( + relation.foreignViewModel, + foreignViewModel => + foreignViewModel[relation.foreignIdKey] && foreignViewModel[relation.foreignIdKey] === model.id + ); + viewModel['_' + relation.ownKey] = foreignViewModels; + this.sortByRelation(relation, viewModel); + } else if (relation.type === 'M2O') { + const foreignViewModel = this.viewModelStoreService.find( + relation.foreignViewModel, + _foreignViewModel => + _foreignViewModel[relation.foreignIdKey] && + _foreignViewModel[relation.foreignIdKey] === model.id + ); + viewModel['_' + relation.ownKey] = foreignViewModel; + } } else if (isNestedRelationDefinition(relation)) { - const foreignViewModels: BaseViewModel[] = model[relation.ownKey].map(foreignModel => - this.createViewModel(foreignModel, relation.foreignModel, relation.relationDefinition || []) + const foreignModels = model[relation.ownKey].map(m => new relation.foreignModel(m)); + const foreignViewModels: BaseViewModel[] = foreignModels.map((foreignModel: BaseModel) => + this.createViewModel( + foreignModel, + relation.foreignViewModel, + relation.relationDefinition || [], + initialLoading + ) ); viewModel['_' + relation.ownKey] = foreignViewModels; this.sortByRelation(relation, viewModel); @@ -181,15 +217,29 @@ export class RelationManagerService { // The foreign model has one id. Check, if the ownViewModel is the matching view model. // If so, add the foreignViewModel to the array from the ownViewModel (with many foreignViewModels) + // If not, check, if the model _was_ in our foreignViewModel array and remove it. if (relation.type === 'O2M') { if (foreignViewModel[relation.foreignIdKey] === ownViewModel.id) { this.setForeingViewModelInOwnViewModelArray(foreignViewModel, ownViewModel, relation.ownKey); return true; + } else { + const ownViewModelArray = ownViewModel['_' + relation.ownKey]; + if (ownViewModelArray) { + // We have the array of foreign view models for our own view model. Remove the foreignViewModel (if it was there). + const index = ownViewModelArray.findIndex( + _foreignViewModel => _foreignViewModel.id === foreignViewModel.id + ); + if (index > -1) { + ownViewModelArray.splice(index, 1); + return true; + } + } } } // The foreign model should hold an array of ids. If the ownViewModel is in it, the foreignViewModel must - // be included into the array from the ownViewModel (with many foreignViewModels) + // be included into the array from the ownViewModel (with many foreignViewModels). + // If not, check, if the model _was_ in our foreignViewModel array and remove it. else if (relation.type === 'M2M') { if ( foreignViewModel[relation.foreignIdKey] && @@ -198,11 +248,24 @@ export class RelationManagerService { ) { this.setForeingViewModelInOwnViewModelArray(foreignViewModel, ownViewModel, relation.ownKey); return true; + } else { + const ownViewModelArray = ownViewModel['_' + relation.ownKey]; + if (ownViewModelArray) { + // We have the array of foreign view models for our own view model. Remove the foreignViewModel (if it was there). + const index = ownViewModelArray.findIndex( + _foreignViewModel => _foreignViewModel.id === foreignViewModel.id + ); + if (index > -1) { + ownViewModelArray.splice(index, 1); + return true; + } + } } } // The foreign model should hold an array of ids. If the ownViewModel is in it, the foreignViewModel is the - // one and only matching model for the ownViewModel + // one and only matching model for the ownViewModel. If the ownViewModel is not in it, check if the + // foreignViewModel _was_ the matching model. If so, set the reference to null. else if (relation.type === 'M2O') { if ( foreignViewModel[relation.foreignIdKey] && @@ -211,6 +274,11 @@ export class RelationManagerService { ) { ownViewModel['_' + relation.ownKey] = foreignViewModel; return true; + } else if ( + ownViewModel['_' + relation.ownKey] && + ownViewModel['_' + relation.ownKey].id === foreignViewModel.id + ) { + ownViewModel['_' + relation.ownKey] = null; } } } else if (isNestedRelationDefinition(relation)) { diff --git a/client/src/app/core/core-services/time-travel.service.ts b/client/src/app/core/core-services/time-travel.service.ts index cba21feb0..a8ac3fdc7 100644 --- a/client/src/app/core/core-services/time-travel.service.ts +++ b/client/src/app/core/core-services/time-travel.service.ts @@ -53,7 +53,7 @@ export class TimeTravelService { * @param history the desired point in the history of OpenSlides */ public async loadHistoryPoint(history: History): Promise { - const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS); + const updateSlot = await this.DSUpdateManager.getNewUpdateSlot(this.DS, true); await this.stopTime(history); const historyData: HistoryData = await this.getHistoryData(history); diff --git a/client/src/app/core/definitions/relations.ts b/client/src/app/core/definitions/relations.ts index 0f462b542..c2adffe35 100644 --- a/client/src/app/core/definitions/relations.ts +++ b/client/src/app/core/definitions/relations.ts @@ -1,4 +1,4 @@ -import { BaseModel } from 'app/shared/models/base/base-model'; +import { BaseModel, ModelConstructor } from 'app/shared/models/base/base-model'; import { BaseViewModel, ViewModelConstructor } from 'app/site/base/base-view-model'; // All "standard" relations. @@ -21,7 +21,7 @@ interface BaseRelationDefinition { /** * The model on the other side of the relation. */ - foreignModel: ViewModelConstructor; + foreignViewModel: ViewModelConstructor; } export interface BaseOrderedRelation extends BaseRelationDefinition { @@ -97,7 +97,7 @@ interface BaseReverseRelationDefinition { /** * The model on the other side of the relation. */ - foreignModel: ViewModelConstructor; + foreignViewModel: ViewModelConstructor; } interface ReverseM2MRelationDefinition @@ -130,7 +130,7 @@ export function isReverseRelationDefinition(obj: RelationDefinition): obj is Rev * Nested relations in the REST-API. For the most values see * `NormalRelationDefinition`. */ -interface NestedRelationDefinition extends BaseOrderedRelation { +export interface NestedRelationDefinition extends BaseOrderedRelation { type: 'nested'; ownKey: string; @@ -138,6 +138,11 @@ interface NestedRelationDefinition extends BaseO * The nested relations. */ relationDefinition?: RelationDefinition[]; + + /** + * The matching model for the foreignViewModel. + */ + foreignModel: ModelConstructor; } export function isNestedRelationDefinition(obj: RelationDefinition): obj is NestedRelationDefinition { @@ -172,7 +177,7 @@ export function isGenericRelationDefinition(obj: RelationDefinition): obj is Gen */ interface CustomRelationDefinition { type: 'custom'; - foreignModel: ViewModelConstructor; + foreignViewModel: ViewModelConstructor; /** * Called, when the view model is created from the model. diff --git a/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts b/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts index 75c23ccbe..1acc8358e 100644 --- a/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts +++ b/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts @@ -8,6 +8,7 @@ import { RelationManagerService } from 'app/core/core-services/relation-manager. import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; import { RelationDefinition } from 'app/core/definitions/relations'; import { ListOfSpeakers } from 'app/shared/models/agenda/list-of-speakers'; +import { Speaker } from 'app/shared/models/agenda/speaker'; import { Identifiable } from 'app/shared/models/base/identifiable'; import { ListOfSpeakersTitleInformation, ViewListOfSpeakers } from 'app/site/agenda/models/view-list-of-speakers'; import { ViewSpeaker } from 'app/site/agenda/models/view-speaker'; @@ -39,14 +40,15 @@ const ListOfSpeakersRelations: RelationDefinition[] = [ { type: 'nested', ownKey: 'speakers', - foreignModel: ViewSpeaker, + foreignViewModel: ViewSpeaker, + foreignModel: Speaker, order: 'weight', relationDefinition: [ { type: 'M2O', ownIdKey: 'user_id', ownKey: 'user', - foreignModel: ViewUser + foreignViewModel: ViewUser } ] } diff --git a/client/src/app/core/repositories/assignments/assignment-repository.service.ts b/client/src/app/core/repositories/assignments/assignment-repository.service.ts index 527a84e58..a16f6c91a 100644 --- a/client/src/app/core/repositories/assignments/assignment-repository.service.ts +++ b/client/src/app/core/repositories/assignments/assignment-repository.service.ts @@ -9,6 +9,8 @@ import { ViewModelStoreService } from 'app/core/core-services/view-model-store.s import { RelationDefinition } from 'app/core/definitions/relations'; import { Assignment } from 'app/shared/models/assignments/assignment'; import { AssignmentPoll } from 'app/shared/models/assignments/assignment-poll'; +import { AssignmentPollOption } from 'app/shared/models/assignments/assignment-poll-option'; +import { AssignmentRelatedUser } from 'app/shared/models/assignments/assignment-related-user'; import { AssignmentTitleInformation, ViewAssignment } from 'app/site/assignments/models/view-assignment'; import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll'; import { ViewAssignmentPollOption } from 'app/site/assignments/models/view-assignment-poll-option'; @@ -25,44 +27,47 @@ const AssignmentRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'tags_id', ownKey: 'tags', - foreignModel: ViewTag + foreignViewModel: ViewTag }, { type: 'M2M', ownIdKey: 'attachments_id', ownKey: 'attachments', - foreignModel: ViewMediafile + foreignViewModel: ViewMediafile }, { type: 'nested', ownKey: 'assignment_related_users', - foreignModel: ViewAssignmentRelatedUser, + foreignViewModel: ViewAssignmentRelatedUser, + foreignModel: AssignmentRelatedUser, order: 'weight', relationDefinition: [ { type: 'M2O', ownIdKey: 'user_id', ownKey: 'user', - foreignModel: ViewUser + foreignViewModel: ViewUser } ] }, { type: 'nested', ownKey: 'polls', - foreignModel: ViewAssignmentPoll, + foreignViewModel: ViewAssignmentPoll, + foreignModel: AssignmentPoll, relationDefinition: [ { type: 'nested', ownKey: 'options', - foreignModel: ViewAssignmentPollOption, + foreignViewModel: ViewAssignmentPollOption, + foreignModel: AssignmentPollOption, order: 'weight', relationDefinition: [ { type: 'M2O', ownIdKey: 'user_id', ownKey: 'user', - foreignModel: ViewUser + foreignViewModel: ViewUser } ] } diff --git a/client/src/app/core/repositories/base-has-content-object-repository.ts b/client/src/app/core/repositories/base-has-content-object-repository.ts index 283e9c1e4..8a654fe80 100644 --- a/client/src/app/core/repositories/base-has-content-object-repository.ts +++ b/client/src/app/core/repositories/base-has-content-object-repository.ts @@ -40,9 +40,9 @@ export abstract class BaseHasContentObjectRepository< /** * @override */ - public changedModels(ids: number[]): void { + public changedModels(ids: number[], initialLoading: boolean): void { ids.forEach(id => { - const v = this.createViewModelWithTitles(this.DS.get(this.collectionString, id)); + const v = this.createViewModelWithTitles(this.DS.get(this.collectionString, id), initialLoading); this.viewModelStore[id] = v; const contentObject = v.contentObjectData; diff --git a/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts b/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts index 77bdd1ca5..e9ea37edc 100644 --- a/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts +++ b/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts @@ -42,13 +42,13 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< type: 'M2O', ownIdKey: 'agenda_item_id', ownKey: 'item', - foreignModel: ViewItem + foreignViewModel: ViewItem }); this.relationDefinitions.push({ type: 'M2O', ownIdKey: 'list_of_speakers_id', ownKey: 'list_of_speakers', - foreignModel: ViewListOfSpeakers + foreignViewModel: ViewListOfSpeakers }); super.groupRelationsByCollections(); } @@ -72,8 +72,8 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< return this.getAgendaSlideTitle(titleInformation); }; - protected createViewModelWithTitles(model: M): V { - const viewModel = super.createViewModelWithTitles(model); + protected createViewModelWithTitles(model: M, initialLoading: boolean): V { + const viewModel = super.createViewModelWithTitles(model, initialLoading); viewModel.getAgendaListTitle = () => this.getAgendaListTitle(viewModel); viewModel.getAgendaSlideTitle = () => this.getAgendaSlideTitle(viewModel); viewModel.getListOfSpeakersTitle = () => this.getListOfSpeakersTitle(viewModel); diff --git a/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts b/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts index eeaa8ad12..1953a8215 100644 --- a/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts +++ b/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts @@ -68,7 +68,7 @@ export abstract class BaseIsAgendaItemContentObjectRepository< type: 'M2O', ownIdKey: 'agenda_item_id', ownKey: 'item', - foreignModel: ViewItem + foreignViewModel: ViewItem }); super.groupRelationsByCollections(); } @@ -93,8 +93,8 @@ export abstract class BaseIsAgendaItemContentObjectRepository< /** * Adds the agenda titles to the viewmodel. */ - protected createViewModelWithTitles(model: M): V { - const viewModel = super.createViewModelWithTitles(model); + protected createViewModelWithTitles(model: M, initialLoading: boolean): V { + const viewModel = super.createViewModelWithTitles(model, initialLoading); viewModel.getAgendaListTitle = () => this.getAgendaListTitle(viewModel); viewModel.getAgendaSlideTitle = () => this.getAgendaSlideTitle(viewModel); return viewModel; diff --git a/client/src/app/core/repositories/base-is-list-of-speakers-content-object-repository.ts b/client/src/app/core/repositories/base-is-list-of-speakers-content-object-repository.ts index 8ae1ffefa..41bfd22cc 100644 --- a/client/src/app/core/repositories/base-is-list-of-speakers-content-object-repository.ts +++ b/client/src/app/core/repositories/base-is-list-of-speakers-content-object-repository.ts @@ -66,7 +66,7 @@ export abstract class BaseIsListOfSpeakersContentObjectRepository< type: 'M2O', ownIdKey: 'list_of_speakers_id', ownKey: 'list_of_speakers', - foreignModel: ViewListOfSpeakers + foreignViewModel: ViewListOfSpeakers }); super.groupRelationsByCollections(); } @@ -82,8 +82,8 @@ export abstract class BaseIsListOfSpeakersContentObjectRepository< /** * Adds the list of speakers titles to the view model */ - protected createViewModelWithTitles(model: M): V { - const viewModel = super.createViewModelWithTitles(model); + protected createViewModelWithTitles(model: M, initialLoading: boolean): V { + const viewModel = super.createViewModelWithTitles(model, initialLoading); viewModel.getListOfSpeakersTitle = () => this.getListOfSpeakersTitle(viewModel); viewModel.getListOfSpeakersSlideTitle = () => this.getListOfSpeakersSlideTitle(viewModel); return viewModel; diff --git a/client/src/app/core/repositories/base-repository.ts b/client/src/app/core/repositories/base-repository.ts index 4fb65da0e..d7aa45357 100644 --- a/client/src/app/core/repositories/base-repository.ts +++ b/client/src/app/core/repositories/base-repository.ts @@ -153,7 +153,7 @@ export abstract class BaseRepository { - this.viewModelStore[id] = this.createViewModelWithTitles(this.DS.get(this.collectionString, id)); + this.viewModelStore[id] = this.createViewModelWithTitles( + this.DS.get(this.collectionString, id), + initialLoading + ); this.updateViewModelObservable(id); }); } @@ -225,8 +228,13 @@ export abstract class BaseRepository this.getTitle(viewModel); viewModel.getListTitle = () => this.getListTitle(viewModel); viewModel.getVerboseName = this.getVerboseName; diff --git a/client/src/app/core/repositories/config/config-repository.service.ts b/client/src/app/core/repositories/config/config-repository.service.ts index 0c6fe3140..8324ee948 100644 --- a/client/src/app/core/repositories/config/config-repository.service.ts +++ b/client/src/app/core/repositories/config/config-repository.service.ts @@ -154,8 +154,8 @@ export class ConfigRepositoryService extends BaseRepository { this.updateConfigStructure(false, this.viewModelStore[id]); diff --git a/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts b/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts index 81f4b72a9..7a2c7d309 100644 --- a/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts +++ b/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts @@ -23,19 +23,19 @@ const MediafileRelations: RelationDefinition[] = [ type: 'M2O', ownIdKey: 'parent_id', ownKey: 'parent', - foreignModel: ViewMediafile + foreignViewModel: ViewMediafile }, { type: 'M2M', ownIdKey: 'access_groups_id', ownKey: 'access_groups', - foreignModel: ViewGroup + foreignViewModel: ViewGroup }, { type: 'M2M', ownIdKey: 'inherited_access_groups_id', ownKey: 'inherited_access_groups', - foreignModel: ViewGroup + foreignViewModel: ViewGroup } ]; diff --git a/client/src/app/core/repositories/motions/category-repository.service.ts b/client/src/app/core/repositories/motions/category-repository.service.ts index e42e415f5..cdd6d8171 100644 --- a/client/src/app/core/repositories/motions/category-repository.service.ts +++ b/client/src/app/core/repositories/motions/category-repository.service.ts @@ -20,20 +20,20 @@ const CategoryRelations: RelationDefinition[] = [ type: 'M2O', ownIdKey: 'parent_id', ownKey: 'parent', - foreignModel: ViewCategory + foreignViewModel: ViewCategory }, { type: 'O2M', foreignIdKey: 'category_id', ownKey: 'motions', - foreignModel: ViewMotion, + foreignViewModel: ViewMotion, order: 'category_weight' }, { type: 'O2M', foreignIdKey: 'parent_id', ownKey: 'children', - foreignModel: ViewCategory, + foreignViewModel: ViewCategory, order: 'weight' } ]; diff --git a/client/src/app/core/repositories/motions/motion-block-repository.service.ts b/client/src/app/core/repositories/motions/motion-block-repository.service.ts index b6411a514..b93aa81df 100644 --- a/client/src/app/core/repositories/motions/motion-block-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-block-repository.service.ts @@ -20,7 +20,7 @@ const MotionBlockRelations: RelationDefinition[] = [ type: 'O2M', foreignIdKey: 'motion_block_id', ownKey: 'motions', - foreignModel: ViewMotion + foreignViewModel: ViewMotion } ]; diff --git a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts index ef64e7aa9..59e327833 100644 --- a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts @@ -23,13 +23,13 @@ const MotionCommentSectionRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'read_groups_id', ownKey: 'read_groups', - foreignModel: ViewGroup + foreignViewModel: ViewGroup }, { type: 'M2M', ownIdKey: 'write_groups_id', ownKey: 'write_groups', - foreignModel: ViewGroup + foreignViewModel: ViewGroup } ]; diff --git a/client/src/app/core/repositories/motions/motion-repository.service.ts b/client/src/app/core/repositories/motions/motion-repository.service.ts index d55bf1e38..4bb21e9ef 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -16,6 +16,7 @@ import { DiffLinesInParagraph, DiffService } from 'app/core/ui-services/diff.ser import { TreeIdNode } from 'app/core/ui-services/tree.service'; import { Motion } from 'app/shared/models/motions/motion'; import { MotionPoll } from 'app/shared/models/motions/motion-poll'; +import { Submitter } from 'app/shared/models/motions/submitter'; import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change'; import { PersonalNoteContent } from 'app/shared/models/users/personal-note'; import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; @@ -73,43 +74,44 @@ const MotionRelations: RelationDefinition[] = [ type: 'M2O', ownIdKey: 'state_id', ownKey: 'state', - foreignModel: ViewState + foreignViewModel: ViewState }, { type: 'M2O', ownIdKey: 'recommendation_id', ownKey: 'recommendation', - foreignModel: ViewState + foreignViewModel: ViewState }, { type: 'M2O', ownIdKey: 'workflow_id', ownKey: 'workflow', - foreignModel: ViewWorkflow + foreignViewModel: ViewWorkflow }, { type: 'M2O', ownIdKey: 'category_id', ownKey: 'category', - foreignModel: ViewCategory + foreignViewModel: ViewCategory }, { type: 'M2O', ownIdKey: 'motion_block_id', ownKey: 'motion_block', - foreignModel: ViewMotionBlock + foreignViewModel: ViewMotionBlock }, { type: 'nested', ownKey: 'submitters', - foreignModel: ViewSubmitter, + foreignViewModel: ViewSubmitter, + foreignModel: Submitter, order: 'weight', relationDefinition: [ { type: 'M2O', ownIdKey: 'user_id', ownKey: 'user', - foreignModel: ViewUser + foreignViewModel: ViewUser } ] }, @@ -117,31 +119,31 @@ const MotionRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'supporters_id', ownKey: 'supporters', - foreignModel: ViewUser + foreignViewModel: ViewUser }, { type: 'M2M', ownIdKey: 'attachments_id', ownKey: 'attachments', - foreignModel: ViewMediafile + foreignViewModel: ViewMediafile }, { type: 'M2M', ownIdKey: 'tags_id', ownKey: 'tags', - foreignModel: ViewTag + foreignViewModel: ViewTag }, { type: 'M2O', ownIdKey: 'parent_id', ownKey: 'parent', - foreignModel: ViewMotion + foreignViewModel: ViewMotion }, { type: 'M2M', ownIdKey: 'change_recommendations_id', ownKey: 'changeRecommendations', - foreignModel: ViewMotionChangeRecommendation + foreignViewModel: ViewMotionChangeRecommendation } // Personal notes are dynamically added in the repo. ]; @@ -212,7 +214,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo protected groupRelationsByCollections(): void { this.relationDefinitions.push({ type: 'custom', - foreignModel: ViewPersonalNote, + foreignViewModel: ViewPersonalNote, setRelations: (motion: Motion, viewMotion: ViewMotion) => { viewMotion.personalNote = this.getPersonalNoteForMotion(motion); }, @@ -269,8 +271,8 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo return this.translate.instant(plural ? 'Motions' : 'Motion'); }; - protected createViewModelWithTitles(model: Motion): ViewMotion { - const viewModel = super.createViewModelWithTitles(model); + protected createViewModelWithTitles(model: Motion, initialLoading: boolean): ViewMotion { + const viewModel = super.createViewModelWithTitles(model, initialLoading); viewModel.getIdentifierOrTitle = () => this.getIdentifierOrTitle(viewModel); viewModel.getProjectorTitle = () => this.getAgendaSlideTitle(viewModel); return viewModel; diff --git a/client/src/app/core/repositories/motions/state-repository.service.ts b/client/src/app/core/repositories/motions/state-repository.service.ts index e931e9d4a..0786f6cc4 100644 --- a/client/src/app/core/repositories/motions/state-repository.service.ts +++ b/client/src/app/core/repositories/motions/state-repository.service.ts @@ -18,13 +18,13 @@ const StateRelations: RelationDefinition[] = [ type: 'M2O', ownIdKey: 'workflow_id', ownKey: 'workflow', - foreignModel: ViewWorkflow + foreignViewModel: ViewWorkflow }, { type: 'M2M', ownIdKey: 'next_states_id', ownKey: 'next_states', - foreignModel: ViewState + foreignViewModel: ViewState } ]; diff --git a/client/src/app/core/repositories/motions/workflow-repository.service.ts b/client/src/app/core/repositories/motions/workflow-repository.service.ts index 47707bc55..4a4af3ba7 100644 --- a/client/src/app/core/repositories/motions/workflow-repository.service.ts +++ b/client/src/app/core/repositories/motions/workflow-repository.service.ts @@ -19,13 +19,13 @@ const WorkflowRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'states_id', ownKey: 'states', - foreignModel: ViewState + foreignViewModel: ViewState }, { type: 'M2O', ownIdKey: 'first_state_id', ownKey: 'first_state', - foreignModel: ViewState + foreignViewModel: ViewState } ]; diff --git a/client/src/app/core/repositories/projector/projector-repository.service.ts b/client/src/app/core/repositories/projector/projector-repository.service.ts index 32fe13801..0e1deb597 100644 --- a/client/src/app/core/repositories/projector/projector-repository.service.ts +++ b/client/src/app/core/repositories/projector/projector-repository.service.ts @@ -28,7 +28,7 @@ const ProjectorRelations: RelationDefinition[] = [ type: 'M2O', ownIdKey: 'reference_projector_id', ownKey: 'referenceProjector', - foreignModel: ViewProjector + foreignViewModel: ViewProjector } ]; diff --git a/client/src/app/core/repositories/topics/topic-repository.service.ts b/client/src/app/core/repositories/topics/topic-repository.service.ts index 336835955..b0668d066 100644 --- a/client/src/app/core/repositories/topics/topic-repository.service.ts +++ b/client/src/app/core/repositories/topics/topic-repository.service.ts @@ -18,7 +18,7 @@ const TopicRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'attachments_id', ownKey: 'attachments', - foreignModel: ViewMediafile + foreignViewModel: ViewMediafile } ]; diff --git a/client/src/app/core/repositories/users/user-repository.service.ts b/client/src/app/core/repositories/users/user-repository.service.ts index 8f6581f92..5c6bbc31b 100644 --- a/client/src/app/core/repositories/users/user-repository.service.ts +++ b/client/src/app/core/repositories/users/user-repository.service.ts @@ -30,7 +30,7 @@ const UserRelations: RelationDefinition[] = [ type: 'M2M', ownIdKey: 'groups_id', ownKey: 'groups', - foreignModel: ViewGroup + foreignViewModel: ViewGroup } ]; @@ -147,8 +147,8 @@ export class UserRepositoryService extends BaseRepository this.getFullName(viewModel); viewModel.getShortName = () => this.getShortName(viewModel); return viewModel; diff --git a/client/src/app/shared/models/assignments/assignment-poll-option.ts b/client/src/app/shared/models/assignments/assignment-poll-option.ts index 78da1f667..943a9a259 100644 --- a/client/src/app/shared/models/assignments/assignment-poll-option.ts +++ b/client/src/app/shared/models/assignments/assignment-poll-option.ts @@ -15,8 +15,12 @@ export interface AssignmentOptionVote { export class AssignmentPollOption extends BaseModel { public static COLLECTIONSTRING = 'assignments/assignment-poll-option'; - public id: number; // The AssignmentUser id of the candidate - public candidate_id: number; // the User id of the candidate + public id: number; // The AssignmentPollOption id + public candidate_id: number; // the user id of the candidate + public get user_id(): number { + // to be consistent with user... + return this.candidate_id; + } public is_elected: boolean; public votes: AssignmentOptionVote[]; public poll_id: number; diff --git a/client/src/app/site/assignments/models/view-assignment-poll-option.ts b/client/src/app/site/assignments/models/view-assignment-poll-option.ts index 508f23c15..1ff62e51e 100644 --- a/client/src/app/site/assignments/models/view-assignment-poll-option.ts +++ b/client/src/app/site/assignments/models/view-assignment-poll-option.ts @@ -29,11 +29,8 @@ export class ViewAssignmentPollOption extends BaseViewModel 0) then max = 3 + nc + nd redis.call('hdel', KEYS[1], unpack(ARGV, 4 + nc, max)) - for i = 4 + nc, max, 2 do + for i = 4 + nc, max, 1 do redis.call('zadd', KEYS[2], change_id, ARGV[i]) end end