Merge pull request #4917 from FinnStutzenstein/relationFix

Fixed two little issues with relations and reverse mapping
This commit is contained in:
Finn Stutzenstein 2019-08-15 13:29:02 +02:00 committed by GitHub
commit c641a5ba3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 198 additions and 107 deletions

View File

@ -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)) {

View File

@ -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<UpdateSlot> {
public async getNewUpdateSlot(DS: DataStoreService, initialLoading: boolean = false): Promise<UpdateSlot> {
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<JsonStorage>(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;

View File

@ -48,12 +48,13 @@ export class RelationManagerService {
public createViewModel<M extends BaseModel, V extends BaseViewModel>(
model: M,
modelCtor: ViewModelConstructor<V>,
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<M extends BaseModel, V extends BaseViewModel>(
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 (isNormalRelationDefinition(relation)) {
if (
(relation.type === 'M2M' || relation.type === 'O2M') &&
model[relation.ownIdKey] &&
model[relation.ownIdKey].constructor === Array
) {
const foreignViewModels = this.viewModelStoreService.getMany(
relation.foreignModel,
relation.foreignViewModel,
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]);
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 = <any>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 = <any>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)) {

View File

@ -53,7 +53,7 @@ export class TimeTravelService {
* @param history the desired point in the history of OpenSlides
*/
public async loadHistoryPoint(history: History): Promise<void> {
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);

View File

@ -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<VForeign extends BaseViewModel> {
/**
* The model on the other side of the relation.
*/
foreignModel: ViewModelConstructor<VForeign>;
foreignViewModel: ViewModelConstructor<VForeign>;
}
export interface BaseOrderedRelation<VForeign extends BaseViewModel> extends BaseRelationDefinition<VForeign> {
@ -97,7 +97,7 @@ interface BaseReverseRelationDefinition<VForeign extends BaseViewModel> {
/**
* The model on the other side of the relation.
*/
foreignModel: ViewModelConstructor<VForeign>;
foreignViewModel: ViewModelConstructor<VForeign>;
}
interface ReverseM2MRelationDefinition<VForeign extends BaseViewModel>
@ -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<VForeign extends BaseViewModel> extends BaseOrderedRelation<VForeign> {
export interface NestedRelationDefinition<VForeign extends BaseViewModel> extends BaseOrderedRelation<VForeign> {
type: 'nested';
ownKey: string;
@ -138,6 +138,11 @@ interface NestedRelationDefinition<VForeign extends BaseViewModel> extends BaseO
* The nested relations.
*/
relationDefinition?: RelationDefinition[];
/**
* The matching model for the foreignViewModel.
*/
foreignModel: ModelConstructor<BaseModel>;
}
export function isNestedRelationDefinition(obj: RelationDefinition): obj is NestedRelationDefinition<BaseViewModel> {
@ -172,7 +177,7 @@ export function isGenericRelationDefinition(obj: RelationDefinition): obj is Gen
*/
interface CustomRelationDefinition<VForeign extends BaseViewModel> {
type: 'custom';
foreignModel: ViewModelConstructor<VForeign>;
foreignViewModel: ViewModelConstructor<VForeign>;
/**
* Called, when the view model is created from the model.

View File

@ -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
}
]
}

View File

@ -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
}
]
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -153,7 +153,7 @@ export abstract class BaseRepository<V extends BaseViewModel & T, M extends Base
relation.type === 'O2M' ||
relation.type === 'custom'
) {
const collection = relation.foreignModel.COLLECTIONSTRING;
const collection = relation.foreignViewModel.COLLECTIONSTRING;
if (!this.relationsByCollection[collection]) {
this.relationsByCollection[collection] = [];
}
@ -214,9 +214,12 @@ export abstract class BaseRepository<V extends BaseViewModel & T, M extends Base
*
* @param ids All model ids.
*/
public changedModels(ids: number[]): void {
public changedModels(ids: number[], initialLoading: boolean): void {
ids.forEach(id => {
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<V extends BaseViewModel & T, M extends Base
* After creating a view model, all functions for models form the repo
* are assigned to the new view model.
*/
protected createViewModelWithTitles(model: M): V {
const viewModel = this.relationManager.createViewModel(model, this.baseViewModelCtor, this.relationDefinitions);
protected createViewModelWithTitles(model: M, initialLoading: boolean): V {
const viewModel = this.relationManager.createViewModel(
model,
this.baseViewModelCtor,
this.relationDefinitions,
initialLoading
);
viewModel.getTitle = () => this.getTitle(viewModel);
viewModel.getListTitle = () => this.getListTitle(viewModel);
viewModel.getVerboseName = this.getVerboseName;

View File

@ -154,8 +154,8 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config,
throw new Error('Config variables cannot be created');
}
public changedModels(ids: number[]): void {
super.changedModels(ids);
public changedModels(ids: number[], initialLoading: boolean): void {
super.changedModels(ids, initialLoading);
ids.forEach(id => {
this.updateConfigStructure(false, this.viewModelStore[id]);

View File

@ -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
}
];

View File

@ -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'
}
];

View File

@ -20,7 +20,7 @@ const MotionBlockRelations: RelationDefinition[] = [
type: 'O2M',
foreignIdKey: 'motion_block_id',
ownKey: 'motions',
foreignModel: ViewMotion
foreignViewModel: ViewMotion
}
];

View File

@ -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
}
];

View File

@ -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;

View File

@ -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
}
];

View File

@ -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
}
];

View File

@ -28,7 +28,7 @@ const ProjectorRelations: RelationDefinition[] = [
type: 'M2O',
ownIdKey: 'reference_projector_id',
ownKey: 'referenceProjector',
foreignModel: ViewProjector
foreignViewModel: ViewProjector
}
];

View File

@ -18,7 +18,7 @@ const TopicRelations: RelationDefinition[] = [
type: 'M2M',
ownIdKey: 'attachments_id',
ownKey: 'attachments',
foreignModel: ViewMediafile
foreignViewModel: ViewMediafile
}
];

View File

@ -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<ViewUser, User, UserTi
/**
* Adds teh short and full name to the view user.
*/
protected createViewModelWithTitles(model: User): ViewUser {
const viewModel = super.createViewModelWithTitles(model);
protected createViewModelWithTitles(model: User, initialLoading: boolean): ViewUser {
const viewModel = super.createViewModelWithTitles(model, initialLoading);
viewModel.getFullName = () => this.getFullName(viewModel);
viewModel.getShortName = () => this.getShortName(viewModel);
return viewModel;

View File

@ -15,8 +15,12 @@ export interface AssignmentOptionVote {
export class AssignmentPollOption extends BaseModel<AssignmentPollOption> {
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;

View File

@ -29,11 +29,8 @@ export class ViewAssignmentPollOption extends BaseViewModel<AssignmentPollOption
return this.option.id;
}
/**
* Note: "User" instead of "candidate" to be consistent.
*/
public get user_id(): number {
return this.option.candidate_id;
return this.option.user_id;
}
public get is_elected(): boolean {

View File

@ -186,7 +186,7 @@ class RedisCacheProvider:
if (nd > 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