Relations in the client
This commit is contained in:
parent
ced40cab74
commit
ce171980e8
@ -5,12 +5,61 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||
import { RelationManagerService } from 'app/core/core-services/relation-manager.service';
|
||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||
import { RelationDefinition } from 'app/core/definitions/relations';
|
||||
import { AssignmentOption } from 'app/shared/models/assignments/assignment-option';
|
||||
import { AssignmentPoll } from 'app/shared/models/assignments/assignment-poll';
|
||||
import { ViewAssignmentOption } from 'app/site/assignments/models/view-assignment-option';
|
||||
import { AssignmentPollTitleInformation, ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll';
|
||||
import { BaseRepository } from '../base-repository';
|
||||
import { ViewAssignmentVote } from 'app/site/assignments/models/view-assignment-vote';
|
||||
import { ViewGroup } from 'app/site/users/models/view-group';
|
||||
import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { BaseRepository, NestedModelDescriptors } from '../base-repository';
|
||||
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||
import { DataStoreService } from '../../core-services/data-store.service';
|
||||
|
||||
const AssignmentPollRelations: RelationDefinition[] = [
|
||||
{
|
||||
type: 'M2M',
|
||||
ownIdKey: 'groups_id',
|
||||
ownKey: 'groups',
|
||||
foreignViewModel: ViewGroup
|
||||
},
|
||||
{
|
||||
type: 'M2M',
|
||||
ownIdKey: 'voted_id',
|
||||
ownKey: 'voted',
|
||||
foreignViewModel: ViewUser
|
||||
}
|
||||
];
|
||||
|
||||
const AssignmentPollNestedModelDescriptors: NestedModelDescriptors = {
|
||||
'assignments/assignment-poll': [
|
||||
{
|
||||
ownKey: 'options',
|
||||
foreignViewModel: ViewAssignmentOption,
|
||||
foreignModel: AssignmentOption,
|
||||
order: 'weight',
|
||||
relationDefinitionsByKey: {
|
||||
user: {
|
||||
type: 'M2O',
|
||||
ownIdKey: 'user_id',
|
||||
ownKey: 'user',
|
||||
foreignViewModel: ViewUser
|
||||
},
|
||||
votes: {
|
||||
type: 'O2M',
|
||||
foreignIdKey: 'option_id',
|
||||
ownKey: 'votes',
|
||||
foreignViewModel: ViewAssignmentVote
|
||||
}
|
||||
},
|
||||
titles: {
|
||||
getTitle: (viewOption: ViewAssignmentOption) => (viewOption.user ? viewOption.user.getTitle() : '')
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
* Repository Service for Assignments.
|
||||
*
|
||||
@ -49,8 +98,9 @@ export class AssignmentPollRepositoryService extends BaseRepository<
|
||||
viewModelStoreService,
|
||||
translate,
|
||||
relationManager,
|
||||
AssignmentPoll
|
||||
// TODO: relations
|
||||
AssignmentPoll,
|
||||
AssignmentPollRelations,
|
||||
AssignmentPollNestedModelDescriptors
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,8 @@ 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 { Assignment } from 'app/shared/models/assignments/assignment';
|
||||
import { AssignmentOption } from 'app/shared/models/assignments/assignment-option';
|
||||
import { AssignmentPoll } from 'app/shared/models/assignments/assignment-poll';
|
||||
import { AssignmentRelatedUser } from 'app/shared/models/assignments/assignment-related-user';
|
||||
import { AssignmentTitleInformation, ViewAssignment } from 'app/site/assignments/models/view-assignment';
|
||||
import { ViewAssignmentOption } from 'app/site/assignments/models/view-assignment-option';
|
||||
import { ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll';
|
||||
import { ViewAssignmentRelatedUser } from 'app/site/assignments/models/view-assignment-related-user';
|
||||
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
|
||||
@ -35,6 +32,12 @@ const AssignmentRelations: RelationDefinition[] = [
|
||||
ownIdKey: 'attachments_id',
|
||||
ownKey: 'attachments',
|
||||
foreignViewModel: ViewMediafile
|
||||
},
|
||||
{
|
||||
type: 'O2M',
|
||||
ownKey: 'polls',
|
||||
foreignIdKey: 'assignment_id',
|
||||
foreignViewModel: ViewAssignmentPoll
|
||||
}
|
||||
];
|
||||
|
||||
@ -57,28 +60,6 @@ const AssignmentNestedModelDescriptors: NestedModelDescriptors = {
|
||||
getTitle: (viewAssignmentRelatedUser: ViewAssignmentRelatedUser) =>
|
||||
viewAssignmentRelatedUser.user ? viewAssignmentRelatedUser.user.getFullName() : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
ownKey: 'polls',
|
||||
foreignViewModel: ViewAssignmentPoll,
|
||||
foreignModel: AssignmentPoll,
|
||||
relationDefinitionsByKey: {}
|
||||
}
|
||||
],
|
||||
'assignments/assignment-poll': [
|
||||
{
|
||||
ownKey: 'options',
|
||||
foreignViewModel: ViewAssignmentOption,
|
||||
foreignModel: AssignmentOption,
|
||||
order: 'weight',
|
||||
relationDefinitionsByKey: {
|
||||
user: {
|
||||
type: 'M2O',
|
||||
ownIdKey: 'candidate_id',
|
||||
ownKey: 'user',
|
||||
foreignViewModel: ViewUser
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -5,12 +5,23 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||
import { RelationManagerService } from 'app/core/core-services/relation-manager.service';
|
||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||
import { RelationDefinition } from 'app/core/definitions/relations';
|
||||
import { AssignmentVote } from 'app/shared/models/assignments/assignment-vote';
|
||||
import { ViewAssignmentVote } from 'app/site/assignments/models/view-assignment-vote';
|
||||
import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { BaseRepository } from '../base-repository';
|
||||
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||
import { DataStoreService } from '../../core-services/data-store.service';
|
||||
|
||||
const AssignmentVoteRelations: RelationDefinition[] = [
|
||||
{
|
||||
type: 'M2O',
|
||||
ownIdKey: 'user_id',
|
||||
ownKey: 'user',
|
||||
foreignViewModel: ViewUser
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Repository Service for Assignments.
|
||||
*
|
||||
@ -43,8 +54,8 @@ export class AssignmentVoteRepositoryService extends BaseRepository<ViewAssignme
|
||||
viewModelStoreService,
|
||||
translate,
|
||||
relationManager,
|
||||
AssignmentVote
|
||||
// TODO: relations
|
||||
AssignmentVote,
|
||||
AssignmentVoteRelations
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,54 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||
import { RelationManagerService } from 'app/core/core-services/relation-manager.service';
|
||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||
import { RelationDefinition } from 'app/core/definitions/relations';
|
||||
import { MotionOption } from 'app/shared/models/motions/motion-option';
|
||||
import { MotionPoll } from 'app/shared/models/motions/motion-poll';
|
||||
import { ViewMotionOption } from 'app/site/motions/models/view-motion-option';
|
||||
import { MotionPollTitleInformation, ViewMotionPoll } from 'app/site/motions/models/view-motion-poll';
|
||||
import { BaseRepository } from '../base-repository';
|
||||
import { ViewMotionVote } from 'app/site/motions/models/view-motion-vote';
|
||||
import { ViewGroup } from 'app/site/users/models/view-group';
|
||||
import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { BaseRepository, NestedModelDescriptors } from '../base-repository';
|
||||
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||
import { DataStoreService } from '../../core-services/data-store.service';
|
||||
|
||||
const MotionPollRelations: RelationDefinition[] = [
|
||||
{
|
||||
type: 'M2M',
|
||||
ownIdKey: 'groups_id',
|
||||
ownKey: 'groups',
|
||||
foreignViewModel: ViewGroup
|
||||
},
|
||||
{
|
||||
type: 'M2M',
|
||||
ownIdKey: 'voted_id',
|
||||
ownKey: 'voted',
|
||||
foreignViewModel: ViewUser
|
||||
}
|
||||
];
|
||||
|
||||
const MotionPollNestedModelDescriptors: NestedModelDescriptors = {
|
||||
'motions/motion-poll': [
|
||||
{
|
||||
ownKey: 'options',
|
||||
foreignViewModel: ViewMotionOption,
|
||||
foreignModel: MotionOption,
|
||||
relationDefinitionsByKey: {
|
||||
votes: {
|
||||
type: 'O2M',
|
||||
foreignIdKey: 'option_id',
|
||||
ownKey: 'votes',
|
||||
foreignViewModel: ViewMotionVote
|
||||
}
|
||||
},
|
||||
titles: {
|
||||
getTitle: (viewOption: ViewMotionOption) => ''
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
* Repository Service for Assignments.
|
||||
*
|
||||
@ -39,8 +81,9 @@ export class MotionPollRepositoryService extends BaseRepository<
|
||||
viewModelStoreService,
|
||||
translate,
|
||||
relationManager,
|
||||
MotionPoll
|
||||
// TODO: relations
|
||||
MotionPoll,
|
||||
MotionPollRelations,
|
||||
MotionPollNestedModelDescriptors
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ import { MotionTitleInformation, ViewMotion } from 'app/site/motions/models/view
|
||||
import { ViewMotionAmendedParagraph } from 'app/site/motions/models/view-motion-amended-paragraph';
|
||||
import { ViewMotionBlock } from 'app/site/motions/models/view-motion-block';
|
||||
import { ViewMotionChangeRecommendation } from 'app/site/motions/models/view-motion-change-recommendation';
|
||||
import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll';
|
||||
import { ViewState } from 'app/site/motions/models/view-state';
|
||||
import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-paragraph';
|
||||
import { ViewSubmitter } from 'app/site/motions/models/view-submitter';
|
||||
@ -125,12 +126,17 @@ const MotionRelations: RelationDefinition[] = [
|
||||
ownKey: 'amendments',
|
||||
foreignViewModel: ViewMotion
|
||||
},
|
||||
// TMP:
|
||||
{
|
||||
type: 'M2O',
|
||||
ownIdKey: 'parent_id',
|
||||
ownKey: 'parent',
|
||||
foreignViewModel: ViewMotion
|
||||
},
|
||||
{
|
||||
type: 'O2M',
|
||||
foreignIdKey: 'motion_id',
|
||||
ownKey: 'polls',
|
||||
foreignViewModel: ViewMotionPoll
|
||||
}
|
||||
// Personal notes are dynamically added in the repo.
|
||||
];
|
||||
|
@ -5,12 +5,23 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||
import { RelationManagerService } from 'app/core/core-services/relation-manager.service';
|
||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||
import { RelationDefinition } from 'app/core/definitions/relations';
|
||||
import { MotionVote } from 'app/shared/models/motions/motion-vote';
|
||||
import { ViewMotionVote } from 'app/site/motions/models/view-motion-vote';
|
||||
import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { BaseRepository } from '../base-repository';
|
||||
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
|
||||
import { DataStoreService } from '../../core-services/data-store.service';
|
||||
|
||||
const MotionVoteRelations: RelationDefinition[] = [
|
||||
{
|
||||
type: 'M2O',
|
||||
ownIdKey: 'user_id',
|
||||
ownKey: 'user',
|
||||
foreignViewModel: ViewUser
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Repository Service for Assignments.
|
||||
*
|
||||
@ -43,8 +54,8 @@ export class MotionVoteRepositoryService extends BaseRepository<ViewMotionVote,
|
||||
viewModelStoreService,
|
||||
translate,
|
||||
relationManager,
|
||||
MotionVote
|
||||
// TODO: relations
|
||||
MotionVote,
|
||||
MotionVoteRelations
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ export class AssignmentOption extends BaseOption<AssignmentOption> {
|
||||
public static COLLECTIONSTRING = 'assignments/assignment-option';
|
||||
|
||||
public user_id: number;
|
||||
public weight: number;
|
||||
|
||||
public constructor(input?: any) {
|
||||
super(AssignmentOption.COLLECTIONSTRING, input);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { AssignmentPoll } from './assignment-poll';
|
||||
import { AssignmentRelatedUser } from './assignment-related-user';
|
||||
import { BaseModelWithAgendaItemAndListOfSpeakers } from '../base/base-model-with-agenda-item-and-list-of-speakers';
|
||||
|
||||
@ -22,18 +21,9 @@ export class Assignment extends BaseModelWithAgendaItemAndListOfSpeakers<Assignm
|
||||
|
||||
public id: number;
|
||||
public assignment_related_users: AssignmentRelatedUser[];
|
||||
public polls: AssignmentPoll[];
|
||||
|
||||
public constructor(input?: any) {
|
||||
super(Assignment.COLLECTIONSTRING, input);
|
||||
}
|
||||
|
||||
public get candidates_id(): number[] {
|
||||
return this.assignment_related_users
|
||||
.sort((a: AssignmentRelatedUser, b: AssignmentRelatedUser) => {
|
||||
return a.weight - b.weight;
|
||||
})
|
||||
.map((candidate: AssignmentRelatedUser) => candidate.user_id);
|
||||
}
|
||||
}
|
||||
export interface Assignment extends AssignmentWithoutNestedModels {}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { BaseModel } from './base-model';
|
||||
|
||||
export abstract class BaseDecimalModel<T = any> extends BaseModel<T> {
|
||||
protected abstract decimalFields: (keyof this)[];
|
||||
protected abstract getDecimalFields(): (keyof this)[];
|
||||
|
||||
public deserialize(input: any): void {
|
||||
if (input && typeof input === 'object') {
|
||||
this.decimalFields.forEach(field => (input[field] = parseInt(input[field], 10)));
|
||||
this.getDecimalFields().forEach(field => (input[field] = parseInt(input[field], 10)));
|
||||
}
|
||||
super.deserialize(input);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { BaseModelWithAgendaItemAndListOfSpeakers } from '../base/base-model-with-agenda-item-and-list-of-speakers';
|
||||
import { MotionPoll } from './motion-poll';
|
||||
import { Submitter } from './submitter';
|
||||
|
||||
export interface MotionComment {
|
||||
@ -33,7 +32,6 @@ export interface MotionWithoutNestedModels extends BaseModelWithAgendaItemAndLis
|
||||
recommendation_extension: string;
|
||||
tags_id: number[];
|
||||
attachments_id: number[];
|
||||
polls: MotionPoll[];
|
||||
weight: number;
|
||||
sort_parent_id: number;
|
||||
created: string;
|
||||
|
@ -5,7 +5,8 @@ export abstract class BaseOption<T> extends BaseDecimalModel<T> {
|
||||
public yes: number;
|
||||
public no: number;
|
||||
public abstain: number;
|
||||
public votes_id: number[];
|
||||
|
||||
protected decimalFields: (keyof BaseOption<T>)[] = ['yes', 'no', 'abstain'];
|
||||
protected getDecimalFields(): (keyof BaseOption<T>)[] {
|
||||
return ['yes', 'no', 'abstain'];
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ export interface BasePollWithoutNestedModels {
|
||||
export abstract class BasePoll<T, O extends BaseOption<any>> extends BaseDecimalModel<T> {
|
||||
public options: O[];
|
||||
|
||||
protected decimalFields: (keyof BasePoll<T, O>)[] = ['votesvalid', 'votesinvalid', 'votescast'];
|
||||
protected getDecimalFields(): (keyof BasePoll<T, O>)[] {
|
||||
return ['votesvalid', 'votesinvalid', 'votescast'];
|
||||
}
|
||||
}
|
||||
export interface BasePoll<T, O extends BaseOption<any>> extends BasePollWithoutNestedModels {}
|
||||
|
@ -3,7 +3,10 @@ import { BaseDecimalModel } from '../base/base-decimal-model';
|
||||
export abstract class BaseVote<T> extends BaseDecimalModel<T> {
|
||||
public weight: number;
|
||||
public value: 'Y' | 'N' | 'A';
|
||||
public option_id: number;
|
||||
public user_id?: number;
|
||||
|
||||
protected decimalFields: (keyof BaseVote<T>)[] = ['weight'];
|
||||
protected getDecimalFields(): (keyof BaseVote<T>)[] {
|
||||
return ['weight'];
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { AssignmentOption } from 'app/shared/models/assignments/assignment-option';
|
||||
import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { BaseViewModel } from '../../base/base-view-model';
|
||||
import { ViewAssignmentVote } from './view-assignment-vote';
|
||||
|
||||
export class ViewAssignmentOption extends BaseViewModel<AssignmentOption> {
|
||||
public get option(): AssignmentOption {
|
||||
@ -9,4 +11,9 @@ export class ViewAssignmentOption extends BaseViewModel<AssignmentOption> {
|
||||
protected _collectionString = AssignmentOption.COLLECTIONSTRING;
|
||||
}
|
||||
|
||||
export interface ViewAssignmentOption extends AssignmentOption {}
|
||||
interface TIMotionOptionRelations {
|
||||
votes: ViewAssignmentVote[];
|
||||
user: ViewUser;
|
||||
}
|
||||
|
||||
export interface ViewAssignmentOption extends AssignmentOption, TIMotionOptionRelations {}
|
||||
|
@ -104,7 +104,7 @@ export class ViewAssignment extends BaseViewModelWithAgendaItemAndListOfSpeakers
|
||||
}
|
||||
interface IAssignmentRelations {
|
||||
assignment_related_users: ViewAssignmentRelatedUser[];
|
||||
polls?: ViewAssignmentPoll[];
|
||||
polls: ViewAssignmentPoll[];
|
||||
tags?: ViewTag[];
|
||||
attachments?: ViewMediafile[];
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { MotionOption } from 'app/shared/models/motions/motion-option';
|
||||
import { BaseViewModel } from '../../base/base-view-model';
|
||||
import { ViewMotionVote } from './view-motion-vote';
|
||||
|
||||
export class ViewMotionOption extends BaseViewModel<MotionOption> {
|
||||
public get option(): MotionOption {
|
||||
@ -9,4 +10,8 @@ export class ViewMotionOption extends BaseViewModel<MotionOption> {
|
||||
protected _collectionString = MotionOption.COLLECTIONSTRING;
|
||||
}
|
||||
|
||||
export interface ViewMotionPoll extends MotionOption {}
|
||||
interface TIMotionOptionRelations {
|
||||
votes: ViewMotionVote[];
|
||||
}
|
||||
|
||||
export interface ViewMotionOption extends MotionOption, TIMotionOptionRelations {}
|
||||
|
@ -16,6 +16,7 @@ import { ViewCategory } from './view-category';
|
||||
import { ViewMotionBlock } from './view-motion-block';
|
||||
import { ViewMotionChangeRecommendation } from './view-motion-change-recommendation';
|
||||
import { ViewMotionCommentSection } from './view-motion-comment-section';
|
||||
import { ViewMotionPoll } from './view-motion-poll';
|
||||
import { ViewState } from './view-state';
|
||||
import { ViewSubmitter } from './view-submitter';
|
||||
import { ViewWorkflow } from './view-workflow';
|
||||
@ -359,6 +360,7 @@ interface TIMotionRelations {
|
||||
amendments?: ViewMotion[];
|
||||
changeRecommendations?: ViewMotionChangeRecommendation[];
|
||||
diffLines?: DiffLinesInParagraph[];
|
||||
polls: ViewMotionPoll[];
|
||||
}
|
||||
|
||||
export interface ViewMotion extends MotionWithoutNestedModels, TIMotionRelations {}
|
||||
|
@ -3,10 +3,14 @@ import { CategoryRepositoryService } from 'app/core/repositories/motions/categor
|
||||
import { ChangeRecommendationRepositoryService } from 'app/core/repositories/motions/change-recommendation-repository.service';
|
||||
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
||||
import { MotionCommentSectionRepositoryService } from 'app/core/repositories/motions/motion-comment-section-repository.service';
|
||||
import { MotionPollRepositoryService } from 'app/core/repositories/motions/motion-poll-repository.service';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
import { MotionVoteRepositoryService } from 'app/core/repositories/motions/motion-vote-repository.service';
|
||||
import { StateRepositoryService } from 'app/core/repositories/motions/state-repository.service';
|
||||
import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service';
|
||||
import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
|
||||
import { MotionPoll } from 'app/shared/models/motions/motion-poll';
|
||||
import { MotionVote } from 'app/shared/models/motions/motion-vote';
|
||||
import { State } from 'app/shared/models/motions/state';
|
||||
import { Category } from '../../shared/models/motions/category';
|
||||
import { Motion } from '../../shared/models/motions/motion';
|
||||
@ -19,6 +23,8 @@ import { ViewMotion } from './models/view-motion';
|
||||
import { ViewMotionBlock } from './models/view-motion-block';
|
||||
import { ViewMotionChangeRecommendation } from './models/view-motion-change-recommendation';
|
||||
import { ViewMotionCommentSection } from './models/view-motion-comment-section';
|
||||
import { ViewMotionPoll } from './models/view-motion-poll';
|
||||
import { ViewMotionVote } from './models/view-motion-vote';
|
||||
import { ViewState } from './models/view-state';
|
||||
import { ViewStatuteParagraph } from './models/view-statute-paragraph';
|
||||
import { ViewWorkflow } from './models/view-workflow';
|
||||
@ -70,7 +76,9 @@ export const MotionsAppConfig: AppConfig = {
|
||||
viewModel: ViewStatuteParagraph,
|
||||
searchOrder: 9,
|
||||
repository: StatuteParagraphRepositoryService
|
||||
}
|
||||
},
|
||||
{ model: MotionPoll, viewModel: ViewMotionPoll, repository: MotionPollRepositoryService },
|
||||
{ model: MotionVote, viewModel: ViewMotionVote, repository: MotionVoteRepositoryService }
|
||||
],
|
||||
mainMenuEntries: [
|
||||
{
|
||||
|
@ -358,11 +358,11 @@ export class MotionPdfService {
|
||||
}
|
||||
|
||||
// voting results
|
||||
if (motion.motion.polls.length && (!infoToExport || infoToExport.includes('polls'))) {
|
||||
if (motion.polls.length && (!infoToExport || infoToExport.includes('polls'))) {
|
||||
const column1 = [];
|
||||
const column2 = [];
|
||||
const column3 = [];
|
||||
motion.motion.polls.map((poll, index) => {
|
||||
motion.polls.map((poll, index) => {
|
||||
/*if (poll.has_votes) {
|
||||
if (motion.motion.polls.length > 1) {
|
||||
column1.push(index + 1 + '. ' + this.translate.instant('Vote'));
|
||||
|
@ -71,8 +71,8 @@ export class MotionPollPdfService extends PollPdfService {
|
||||
)}`;
|
||||
if (!title) {
|
||||
title = `${this.translate.instant('Motion')} - ${motion.identifier}`;
|
||||
if (motion.motion.polls.length > 1) {
|
||||
title += ` (${this.translate.instant('Vote')} ${motion.motion.polls.length})`;
|
||||
if (motion.polls.length > 1) {
|
||||
title += ` (${this.translate.instant('Vote')} ${motion.polls.length})`;
|
||||
}
|
||||
}
|
||||
if (!subtitle) {
|
||||
|
@ -51,3 +51,12 @@ class AssignmentPollAccessPermissions(BaseAccessPermissions):
|
||||
self, full_data: List[Dict[str, Any]], user_id: int
|
||||
) -> List[Dict[str, Any]]:
|
||||
return full_data
|
||||
|
||||
|
||||
class AssignmentVoteAccessPermissions(BaseAccessPermissions):
|
||||
base_permission = "assignments.can_see"
|
||||
|
||||
async def get_restricted_data(
|
||||
self, full_data: List[Dict[str, Any]], user_id: int
|
||||
) -> List[Dict[str, Any]]:
|
||||
return full_data
|
||||
|
@ -19,6 +19,7 @@ from ..utils.models import CASCADE_AND_AUTOUPDATE, SET_NULL_AND_AUTOUPDATE
|
||||
from .access_permissions import (
|
||||
AssignmentAccessPermissions,
|
||||
AssignmentPollAccessPermissions,
|
||||
AssignmentVoteAccessPermissions,
|
||||
)
|
||||
|
||||
|
||||
@ -268,6 +269,7 @@ class Assignment(RESTModelMixin, AgendaItemWithListOfSpeakersMixin, models.Model
|
||||
|
||||
|
||||
class AssignmentVote(RESTModelMixin, BaseVote):
|
||||
access_permissions = AssignmentVoteAccessPermissions()
|
||||
option = models.ForeignKey(
|
||||
"AssignmentOption", on_delete=models.CASCADE, related_name="votes"
|
||||
)
|
||||
|
@ -74,12 +74,10 @@ class AssignmentOptionSerializer(ModelSerializer):
|
||||
max_digits=15, decimal_places=6, min_value=-2, read_only=True
|
||||
)
|
||||
|
||||
votes = IdPrimaryKeyRelatedField(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = AssignmentOption
|
||||
fields = ("user",) + BASE_OPTION_FIELDS
|
||||
read_only_fields = ("user",) + BASE_OPTION_FIELDS
|
||||
fields = ("user", "weight") + BASE_OPTION_FIELDS
|
||||
read_only_fields = ("user", "weight") + BASE_OPTION_FIELDS
|
||||
|
||||
|
||||
class AssignmentPollSerializer(ModelSerializer):
|
||||
@ -133,7 +131,6 @@ class AssignmentSerializer(ModelSerializer):
|
||||
assignment_related_users = AssignmentRelatedUserSerializer(
|
||||
many=True, read_only=True
|
||||
)
|
||||
polls = IdPrimaryKeyRelatedField(many=True, read_only=True)
|
||||
agenda_create = BooleanField(write_only=True, required=False, allow_null=True)
|
||||
agenda_type = IntegerField(
|
||||
write_only=True, required=False, min_value=1, max_value=3, allow_null=True
|
||||
@ -150,7 +147,6 @@ class AssignmentSerializer(ModelSerializer):
|
||||
"phase",
|
||||
"assignment_related_users",
|
||||
"poll_description_default",
|
||||
"polls",
|
||||
"agenda_item_id",
|
||||
"list_of_speakers_id",
|
||||
"agenda_create",
|
||||
|
@ -246,22 +246,6 @@ class AssignmentViewSet(ModelViewSet):
|
||||
message = "User {0} was successfully unelected."
|
||||
return Response({"detail": message, "args": [str(user)]})
|
||||
|
||||
@detail_route(methods=["post"])
|
||||
def create_poll(self, request, pk=None):
|
||||
"""
|
||||
View to create a poll. It is a POST request without any data.
|
||||
"""
|
||||
assignment = self.get_object()
|
||||
if not assignment.candidates.exists():
|
||||
raise ValidationError(
|
||||
{"detail": "Can not create ballot because there are no candidates."}
|
||||
)
|
||||
with transaction.atomic():
|
||||
poll = assignment.create_poll()
|
||||
return Response(
|
||||
{"detail": "Ballot created successfully.", "createdPollId": poll.pk}
|
||||
)
|
||||
|
||||
@detail_route(methods=["post"])
|
||||
def sort_related_users(self, request, pk=None):
|
||||
"""
|
||||
|
@ -243,8 +243,6 @@ class MotionOptionSerializer(ModelSerializer):
|
||||
max_digits=15, decimal_places=6, min_value=-2, read_only=True
|
||||
)
|
||||
|
||||
votes = IdPrimaryKeyRelatedField(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = MotionOption
|
||||
fields = BASE_OPTION_FIELDS
|
||||
@ -371,7 +369,6 @@ class MotionSerializer(ModelSerializer):
|
||||
"""
|
||||
|
||||
comments = MotionCommentSerializer(many=True, read_only=True)
|
||||
polls = IdPrimaryKeyRelatedField(many=True, read_only=True)
|
||||
modified_final_version = CharField(allow_blank=True, required=False)
|
||||
reason = CharField(allow_blank=True, required=False)
|
||||
state_restriction = SerializerMethodField()
|
||||
@ -419,7 +416,6 @@ class MotionSerializer(ModelSerializer):
|
||||
"recommendation_extension",
|
||||
"tags",
|
||||
"attachments",
|
||||
"polls",
|
||||
"agenda_item_id",
|
||||
"list_of_speakers_id",
|
||||
"agenda_create",
|
||||
|
@ -11,6 +11,6 @@ BASE_POLL_FIELDS = (
|
||||
"id",
|
||||
)
|
||||
|
||||
BASE_OPTION_FIELDS = ("id", "yes", "no", "abstain", "votes")
|
||||
BASE_OPTION_FIELDS = ("id", "yes", "no", "abstain")
|
||||
|
||||
BASE_VOTE_FIELDS = ("id", "weight", "value", "user")
|
||||
BASE_VOTE_FIELDS = ("id", "weight", "value", "user", "option")
|
||||
|
@ -419,7 +419,7 @@ class RetrieveMotion(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
def test_user_without_can_see_user_permission_to_see_motion_and_submitter_data(
|
||||
self
|
||||
self,
|
||||
):
|
||||
admin = get_user_model().objects.get(username="admin")
|
||||
Submitter.objects.add(admin, self.motion)
|
||||
|
@ -582,7 +582,6 @@ class VoteMotionPollNamedAutoupdates(TestCase):
|
||||
"yes": "0.000000",
|
||||
"no": "0.000000",
|
||||
"abstain": "1.000000",
|
||||
"votes_id": [vote.id],
|
||||
}
|
||||
],
|
||||
"voted_id": [self.user1.id],
|
||||
@ -594,6 +593,7 @@ class VoteMotionPollNamedAutoupdates(TestCase):
|
||||
"weight": "1.000000",
|
||||
"value": "A",
|
||||
"user_id": self.user1.id,
|
||||
"option_id": 1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -605,6 +605,7 @@ class VoteMotionPollNamedAutoupdates(TestCase):
|
||||
autoupdate[0]["motions/motion-vote:1"],
|
||||
{
|
||||
"pollstate": 2,
|
||||
"option_id": 1,
|
||||
"id": 1,
|
||||
"weight": "1.000000",
|
||||
"value": "A",
|
||||
@ -626,7 +627,7 @@ class VoteMotionPollNamedAutoupdates(TestCase):
|
||||
"type": "named",
|
||||
"title": "test_title_tho8PhiePh8upaex6phi",
|
||||
"groups_id": [GROUP_DELEGATE_PK],
|
||||
"options": [{"id": 1, "votes_id": [vote.id]}],
|
||||
"options": [{"id": 1}],
|
||||
"id": 1,
|
||||
},
|
||||
)
|
||||
@ -653,12 +654,12 @@ class VoteMotionPollPseudoanonymousAutoupdates(TestCase):
|
||||
self.other_user, _ = self.create_user()
|
||||
inform_changed_data(self.other_user)
|
||||
|
||||
self.user, user1_password = self.create_user()
|
||||
self.user, user_password = self.create_user()
|
||||
self.user.groups.add(self.delegate_group)
|
||||
self.user.is_present = True
|
||||
self.user.save()
|
||||
self.user_client = APIClient()
|
||||
self.user_client.login(username=self.user.username, password=user1_password)
|
||||
self.user_client.login(username=self.user.username, password=user_password)
|
||||
|
||||
self.poll = MotionPoll.objects.create(
|
||||
motion=self.motion,
|
||||
@ -699,7 +700,6 @@ class VoteMotionPollPseudoanonymousAutoupdates(TestCase):
|
||||
"yes": "0.000000",
|
||||
"no": "0.000000",
|
||||
"abstain": "1.000000",
|
||||
"votes_id": [vote.id],
|
||||
}
|
||||
],
|
||||
"voted_id": [self.user.id],
|
||||
@ -707,6 +707,7 @@ class VoteMotionPollPseudoanonymousAutoupdates(TestCase):
|
||||
},
|
||||
"motions/motion-vote:1": {
|
||||
"pollstate": 2,
|
||||
"option_id": 1,
|
||||
"id": 1,
|
||||
"weight": "1.000000",
|
||||
"value": "A",
|
||||
@ -730,7 +731,7 @@ class VoteMotionPollPseudoanonymousAutoupdates(TestCase):
|
||||
"type": "pseudoanonymous",
|
||||
"title": "test_title_cahP1umooteehah2jeey",
|
||||
"groups_id": [GROUP_DELEGATE_PK],
|
||||
"options": [{"id": 1, "votes_id": [vote.id]}],
|
||||
"options": [{"id": 1}],
|
||||
"id": 1,
|
||||
},
|
||||
)
|
||||
@ -953,7 +954,6 @@ class PublishMotionPoll(TestCase):
|
||||
"yes": "0.000000",
|
||||
"no": "2.000000",
|
||||
"abstain": "0.000000",
|
||||
"votes_id": [1],
|
||||
}
|
||||
],
|
||||
"voted_id": [],
|
||||
@ -961,6 +961,7 @@ class PublishMotionPoll(TestCase):
|
||||
},
|
||||
"motions/motion-vote:1": {
|
||||
"pollstate": 4,
|
||||
"option_id": 1,
|
||||
"id": 1,
|
||||
"weight": "2.000000",
|
||||
"value": "N",
|
||||
|
Loading…
Reference in New Issue
Block a user