Show global votes in the single votes table
This commit is contained in:
parent
29a9a09bc6
commit
a05662a0f8
@ -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',
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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"))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user