Show global votes in the single votes table

This commit is contained in:
FinnStutzenstein 2020-03-12 15:42:41 +01:00
parent 29a9a09bc6
commit a05662a0f8
13 changed files with 53 additions and 48 deletions

View File

@ -22,12 +22,6 @@ const AssignmentOptionRelations: RelationDefinition[] = [
ownKey: 'votes', ownKey: 'votes',
foreignViewModel: ViewAssignmentVote foreignViewModel: ViewAssignmentVote
}, },
{
type: 'M2M',
ownIdKey: 'voted_id',
ownKey: 'voted',
foreignViewModel: ViewUser
},
{ {
type: 'M2O', type: 'M2O',
ownIdKey: 'poll_id', ownIdKey: 'poll_id',

View File

@ -14,6 +14,7 @@ import { ViewAssignmentOption } from 'app/site/assignments/models/view-assignmen
import { AssignmentPollTitleInformation, ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll'; import { AssignmentPollTitleInformation, ViewAssignmentPoll } from 'app/site/assignments/models/view-assignment-poll';
import { BasePollRepositoryService } from 'app/site/polls/services/base-poll-repository.service'; import { BasePollRepositoryService } from 'app/site/polls/services/base-poll-repository.service';
import { ViewGroup } from 'app/site/users/models/view-group'; import { ViewGroup } from 'app/site/users/models/view-group';
import { ViewUser } from 'app/site/users/models/view-user';
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service'; import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
import { DataStoreService } from '../../core-services/data-store.service'; import { DataStoreService } from '../../core-services/data-store.service';
@ -35,6 +36,12 @@ const AssignmentPollRelations: RelationDefinition[] = [
ownIdKey: 'assignment_id', ownIdKey: 'assignment_id',
ownKey: 'assignment', ownKey: 'assignment',
foreignViewModel: ViewAssignment foreignViewModel: ViewAssignment
},
{
type: 'M2M',
ownIdKey: 'voted_id',
ownKey: 'voted',
foreignViewModel: ViewUser
} }
]; ];

View File

@ -10,7 +10,6 @@ import { MotionOption } from 'app/shared/models/motions/motion-option';
import { ViewMotionOption } from 'app/site/motions/models/view-motion-option'; import { ViewMotionOption } from 'app/site/motions/models/view-motion-option';
import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll'; import { ViewMotionPoll } from 'app/site/motions/models/view-motion-poll';
import { ViewMotionVote } from 'app/site/motions/models/view-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 { BaseRepository } from '../base-repository';
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service'; import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
import { DataStoreService } from '../../core-services/data-store.service'; import { DataStoreService } from '../../core-services/data-store.service';
@ -22,12 +21,6 @@ const MotionOptionRelations: RelationDefinition[] = [
ownKey: 'votes', ownKey: 'votes',
foreignViewModel: ViewMotionVote foreignViewModel: ViewMotionVote
}, },
{
type: 'M2M',
ownIdKey: 'voted_id',
ownKey: 'voted',
foreignViewModel: ViewUser
},
{ {
type: 'M2O', type: 'M2O',
ownIdKey: 'poll_id', ownIdKey: 'poll_id',

View File

@ -14,6 +14,7 @@ import { ViewMotionOption } from 'app/site/motions/models/view-motion-option';
import { MotionPollTitleInformation, ViewMotionPoll } from 'app/site/motions/models/view-motion-poll'; import { MotionPollTitleInformation, ViewMotionPoll } from 'app/site/motions/models/view-motion-poll';
import { BasePollRepositoryService } from 'app/site/polls/services/base-poll-repository.service'; import { BasePollRepositoryService } from 'app/site/polls/services/base-poll-repository.service';
import { ViewGroup } from 'app/site/users/models/view-group'; import { ViewGroup } from 'app/site/users/models/view-group';
import { ViewUser } from 'app/site/users/models/view-user';
import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service'; import { CollectionStringMapperService } from '../../core-services/collection-string-mapper.service';
import { DataStoreService } from '../../core-services/data-store.service'; import { DataStoreService } from '../../core-services/data-store.service';
@ -35,6 +36,12 @@ const MotionPollRelations: RelationDefinition[] = [
ownIdKey: 'motion_id', ownIdKey: 'motion_id',
ownKey: 'motion', ownKey: 'motion',
foreignViewModel: ViewMotion foreignViewModel: ViewMotion
},
{
type: 'M2M',
ownIdKey: 'voted_id',
ownKey: 'voted',
foreignViewModel: ViewUser
} }
]; ];

View File

@ -94,6 +94,14 @@ export class AssignmentPollDetailComponent extends BasePollDetailComponent<ViewA
} }
} }
} }
for (const user of this.poll.voted) {
if (!votes[user.id]) {
votes[user.id] = {
user: user,
votes: [this.translate.instant('empty vote')]
};
}
}
this.setVotesData(Object.values(votes)); this.setVotesData(Object.values(votes));
this.candidatesLabels = this.pollService.getChartLabels(this.poll); this.candidatesLabels = this.pollService.getChartLabels(this.poll);

View File

@ -259,9 +259,12 @@ export abstract class PollService {
public generateChartData(poll: PollData | ViewBasePoll): ChartData { public generateChartData(poll: PollData | ViewBasePoll): ChartData {
let fields: CalculablePollKey[]; let fields: CalculablePollKey[];
let isAssignment: boolean;
// TODO: PollData should either be `ViewBasePoll` or `BasePoll` to get SOLID if (poll instanceof ViewBasePoll) {
const isAssignment = Object.keys(poll.options[0]).includes('user'); isAssignment = poll.pollClassType === 'assignment';
} else {
isAssignment = Object.keys(poll.options[0]).includes('user');
}
if (isAssignment) { if (isAssignment) {
if (poll.pollmethod === AssignmentPollMethod.YNA) { if (poll.pollmethod === AssignmentPollMethod.YNA) {

View File

@ -44,7 +44,8 @@ export const allSlides: SlideManifest[] = [
{ {
slide: 'motions/motion-poll', slide: 'motions/motion-poll',
path: 'motions/motion-poll', path: 'motions/motion-poll',
loadChildren: './slides/motions/motion-poll/motion-poll-slide.module#MotionPollSlideModule', loadChildren: () =>
import('./motions/motion-poll/motion-poll-slide.module').then(m => m.MotionPollSlideModule),
verboseName: 'Motion Poll', verboseName: 'Motion Poll',
elementIdentifiers: ['name', 'id'], elementIdentifiers: ['name', 'id'],
canBeMappedToModel: true canBeMappedToModel: true
@ -136,7 +137,7 @@ export const allSlides: SlideManifest[] = [
{ {
slide: 'assignments/assignment-poll', slide: 'assignments/assignment-poll',
path: 'assignments/assignment-poll', path: 'assignments/assignment-poll',
loadChildren: () => import('./assignments/poll/poll-slide.module').then(m => m.PollSlideModule), loadChildren: () => import('./assignments/assignment-poll/assignment-poll-slide.module').then(m => m.AssignmentPollSlideModule),
verboseName: 'Assignment Poll', verboseName: 'Assignment Poll',
elementIdentifiers: ['name', 'id'], elementIdentifiers: ['name', 'id'],
canBeMappedToModel: true canBeMappedToModel: true

View File

@ -54,7 +54,7 @@ class AssignmentsAppConfig(AppConfig):
required_users_assignments, required_users_assignments,
) )
required_user.add_collection_string( required_user.add_collection_string(
self.get_model("AssignmentOption").get_collection_string(), self.get_model("AssignmentPoll").get_collection_string(),
required_users_options, required_users_options,
) )

View File

@ -374,20 +374,16 @@ class AssignmentPoll(RESTModelMixin, BasePoll):
def get_amount_global_abstain(self): def get_amount_global_abstain(self):
if not self.global_abstain: if not self.global_abstain:
return None return None
elif ( elif self.type == self.TYPE_ANALOG:
self.type == self.TYPE_ANALOG
or self.pollmethod == AssignmentPoll.POLLMETHOD_VOTES
):
return self.db_amount_global_abstain return self.db_amount_global_abstain
elif self.pollmethod == AssignmentPoll.POLLMETHOD_VOTES:
return sum(option.abstain for option in self.options.all())
else: else:
return None return None
def set_amount_global_abstain(self, value): def set_amount_global_abstain(self, value):
if ( if self.type != self.TYPE_ANALOG:
self.type != self.TYPE_ANALOG raise ValueError("Do not set amount_global_abstain for non analog polls")
and self.pollmethod != AssignmentPoll.POLLMETHOD_VOTES
):
raise ValueError("Do not set amount_global_abstain YN/YNA polls")
self.db_amount_global_abstain = value self.db_amount_global_abstain = value
amount_global_abstain = property( amount_global_abstain = property(
@ -397,20 +393,16 @@ class AssignmentPoll(RESTModelMixin, BasePoll):
def get_amount_global_no(self): def get_amount_global_no(self):
if not self.global_no: if not self.global_no:
return None return None
elif ( elif self.type == self.TYPE_ANALOG:
self.type == self.TYPE_ANALOG
or self.pollmethod == AssignmentPoll.POLLMETHOD_VOTES
):
return self.db_amount_global_no return self.db_amount_global_no
elif self.pollmethod == AssignmentPoll.POLLMETHOD_VOTES:
return sum(option.no for option in self.options.all())
else: else:
return None return None
def set_amount_global_no(self, value): def set_amount_global_no(self, value):
if ( if self.type != self.TYPE_ANALOG:
self.type != self.TYPE_ANALOG raise ValueError("Do not set amount_global_no for non analog polls")
and self.pollmethod != AssignmentPoll.POLLMETHOD_VOTES
):
raise ValueError("Do not set amount_global_no YN/YNA polls")
self.db_amount_global_no = value self.db_amount_global_no = value
amount_global_no = property(get_amount_global_no, set_amount_global_no) amount_global_no = property(get_amount_global_no, set_amount_global_no)

View File

@ -2,7 +2,6 @@ from decimal import Decimal
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import transaction from django.db import transaction
from django.db.models import F
from openslides.poll.views import BaseOptionViewSet, BasePollViewSet, BaseVoteViewSet from openslides.poll.views import BaseOptionViewSet, BasePollViewSet, BaseVoteViewSet
from openslides.utils.auth import has_perm from openslides.utils.auth import has_perm
@ -495,13 +494,13 @@ class AssignmentPollViewSet(BasePollViewSet):
) )
inform_changed_data(vote, no_delete_on_restriction=True) inform_changed_data(vote, no_delete_on_restriction=True)
else: # global_no or global_abstain else: # global_no or global_abstain
if data == "A": option = options[0]
poll.amount_global_abstain = F("db_amount_global_abstain") + 1 vote = AssignmentVote.objects.create(
elif data == "N": option=option, user=user, weight=Decimal(1), value=data
poll.amount_global_no = F("db_amount_global_no") + 1 )
else: inform_changed_data(vote, no_delete_on_restriction=True)
raise RuntimeError("This should not happen") inform_changed_data(option)
poll.save() inform_changed_data(poll)
poll.voted.add(user) poll.voted.add(user)

View File

@ -82,7 +82,7 @@ class MotionsAppConfig(AppConfig):
) )
required_user.add_collection_string( required_user.add_collection_string(
self.get_model("MotionOption").get_collection_string(), self.get_model("MotionPoll").get_collection_string(),
required_users_options, required_users_options,
) )

View File

@ -934,6 +934,7 @@ class MotionPollManager(BaseManager):
class MotionPoll(RESTModelMixin, BasePoll): class MotionPoll(RESTModelMixin, BasePoll):
access_permissions = MotionPollAccessPermissions() access_permissions = MotionPollAccessPermissions()
can_see_permission = "motions.can_see"
option_class = MotionOption option_class = MotionOption
objects = MotionPollManager() objects = MotionPollManager()

View File

@ -1218,7 +1218,7 @@ class VoteAssignmentPollNamedVotes(VoteAssignmentPollBaseTestClass):
poll = AssignmentPoll.objects.get() poll = AssignmentPoll.objects.get()
option = poll.options.get(pk=1) option = poll.options.get(pk=1)
self.assertEqual(option.yes, Decimal("0")) self.assertEqual(option.yes, Decimal("0"))
self.assertEqual(option.no, Decimal("0")) self.assertEqual(option.no, Decimal("1"))
self.assertEqual(option.abstain, Decimal("0")) self.assertEqual(option.abstain, Decimal("0"))
self.assertEqual(poll.amount_global_no, Decimal("1")) self.assertEqual(poll.amount_global_no, Decimal("1"))
self.assertEqual(poll.amount_global_abstain, Decimal("0")) self.assertEqual(poll.amount_global_abstain, Decimal("0"))
@ -1246,7 +1246,7 @@ class VoteAssignmentPollNamedVotes(VoteAssignmentPollBaseTestClass):
option = poll.options.get(pk=1) option = poll.options.get(pk=1)
self.assertEqual(option.yes, Decimal("0")) self.assertEqual(option.yes, Decimal("0"))
self.assertEqual(option.no, Decimal("0")) self.assertEqual(option.no, Decimal("0"))
self.assertEqual(option.abstain, Decimal("0")) self.assertEqual(option.abstain, Decimal("1"))
self.assertEqual(poll.amount_global_no, Decimal("0")) self.assertEqual(poll.amount_global_no, Decimal("0"))
self.assertEqual(poll.amount_global_abstain, Decimal("1")) self.assertEqual(poll.amount_global_abstain, Decimal("1"))