From ff0f4ef1a9a37bac828cf39c34b4b0069b4458bc Mon Sep 17 00:00:00 2001 From: alex-obi Date: Thu, 17 Oct 2013 18:36:57 +0200 Subject: [PATCH] Instance option to disable voting --- src/adhocracy/controllers/instance.py | 14 ++++++++++++-- src/adhocracy/controllers/poll.py | 3 +++ src/adhocracy/lib/cache/__init__.py | 3 ++- src/adhocracy/lib/cache/invalidate.py | 7 +++++++ .../versions/079_add_voting_disabled_option.py | 13 +++++++++++++ src/adhocracy/model/instance.py | 1 + src/adhocracy/templates/comment/tiles.html | 2 ++ .../templates/instance/settings_voting.html | 2 ++ src/adhocracy/templates/poll/tiles.html | 3 +++ src/adhocracy/templates/proposal/show.html | 2 ++ src/adhocracy/templates/proposal/tiles.html | 4 ++++ 11 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/adhocracy/migration/versions/079_add_voting_disabled_option.py diff --git a/src/adhocracy/controllers/instance.py b/src/adhocracy/controllers/instance.py index 300f70c33..140cd1ccb 100644 --- a/src/adhocracy/controllers/instance.py +++ b/src/adhocracy/controllers/instance.py @@ -129,6 +129,9 @@ class InstanceVotingEditForm(formencode.Schema): allow_extra_fields = True allow_delegate = validators.StringBool(not_empty=False, if_empty=False, if_missing=False) + + voting_disabled = validators.StringBool(not_empty=False, if_empty=False, + if_missing=False) if not config.get_bool('adhocracy.hide_final_adoption_votings'): allow_adopt = validators.StringBool(not_empty=False, if_empty=False, if_missing=False) @@ -664,6 +667,7 @@ def settings_voting(self, id): 'activation_delay': c.page_instance.activation_delay, 'allow_adopt': c.page_instance.allow_adopt, 'allow_delegate': c.page_instance.allow_delegate, + 'voting_disabled': c.page_instance.voting_disabled, '_tok': csrf.token_id()} if votedetail.is_enabled(): defaults['votedetail_badges'] = [ @@ -681,13 +685,19 @@ def settings_voting_update(self, id, format='html'): c.page_instance = self._get_current_instance(id) require.instance.edit(c.page_instance) - updated_attributes = ['allow_delegate'] + old_voting_disabled = getattr(c.page_instance, 'voting_disabled') + + updated_attributes = ['allow_delegate', 'voting_disabled'] if not config.get_bool('adhocracy.hide_final_adoption_votings'): updated_attributes.extend( ['required_majority', 'activation_delay', 'allow_adopt']) updated = update_attributes( c.page_instance, self.form_result, updated_attributes) - + + if old_voting_disabled != getattr(c.page_instance, 'voting_disabled'): + from adhocracy.lib.cache import invalidate_instance_polls + invalidate_instance_polls(c.page_instance) + if votedetail.is_enabled(): new_badges = self.form_result['votedetail_badges'] updated_vd = c.page_instance.votedetail_userbadges != new_badges diff --git a/src/adhocracy/controllers/poll.py b/src/adhocracy/controllers/poll.py index 8167c49b0..53b082aac 100644 --- a/src/adhocracy/controllers/poll.py +++ b/src/adhocracy/controllers/poll.py @@ -100,6 +100,9 @@ def rate(self, id, format): # rating is like polling but steps via abstention, i.e. if you have # first voted "for", rating will first go to "abstain" and only # then produce "against"- + if c.instance.voting_disabled: + abort(403, _("Voting disabled.")) + c.poll = self._get_open_poll(id) if c.poll.action not in [model.Poll.RATE, model.Poll.SELECT]: abort(400, _("This is not a rating poll.")) diff --git a/src/adhocracy/lib/cache/__init__.py b/src/adhocracy/lib/cache/__init__.py index 8a7df84d5..ae681c732 100644 --- a/src/adhocracy/lib/cache/__init__.py +++ b/src/adhocracy/lib/cache/__init__.py @@ -6,7 +6,8 @@ from invalidate import (invalidate_user, invalidate_vote, invalidate_page, invalidate_delegateable, invalidate_delegation, invalidate_revision, invalidate_comment, - invalidate_poll, invalidate_tagging, invalidate_text, + invalidate_poll, invalidate_instance_polls, + invalidate_tagging, invalidate_text, invalidate_selection, invalidate_badge, invalidate_userbadges, invalidate_delegateablebadges, invalidate_instance) diff --git a/src/adhocracy/lib/cache/invalidate.py b/src/adhocracy/lib/cache/invalidate.py index 98b41e10e..048458996 100644 --- a/src/adhocracy/lib/cache/invalidate.py +++ b/src/adhocracy/lib/cache/invalidate.py @@ -83,6 +83,13 @@ def invalidate_poll(poll): invalidate_comment(poll.subject) +def invalidate_instance_polls(instance): + # invalidates all polls of an instance + for deleg in instance.delegateables: + for poll in deleg.polls: + invalidate_poll(poll) + + def invalidate_instance(instance): # muharhar cache epic fail clear_tag(instance) diff --git a/src/adhocracy/migration/versions/079_add_voting_disabled_option.py b/src/adhocracy/migration/versions/079_add_voting_disabled_option.py new file mode 100644 index 000000000..6252061bf --- /dev/null +++ b/src/adhocracy/migration/versions/079_add_voting_disabled_option.py @@ -0,0 +1,13 @@ +from sqlalchemy import MetaData, Table, Boolean, Column + +from sqlalchemy import Integer + + +def upgrade(migrate_engine): + meta = MetaData(bind=migrate_engine) + + instance_table = Table('instance', meta, autoload=True) + col = Column('voting_disabled', Boolean, nullable=False, default=False, + server_default="0") + col.create(instance_table) + diff --git a/src/adhocracy/model/instance.py b/src/adhocracy/model/instance.py index 0d98df622..516b178ab 100644 --- a/src/adhocracy/model/instance.py +++ b/src/adhocracy/model/instance.py @@ -50,6 +50,7 @@ Column('editable_comments_default', Boolean, nullable=True, default=True), Column('editable_proposals_default', Boolean, nullable=True, default=True), Column('require_valid_email', Boolean, nullable=True, default=True), + Column('voting_disabled', Boolean, nullable=True, default=False), Column('allow_thumbnailbadges', Boolean, default=False), Column('thumbnailbadges_height', Integer, nullable=True), Column('thumbnailbadges_width', Integer, nullable=True), diff --git a/src/adhocracy/templates/comment/tiles.html b/src/adhocracy/templates/comment/tiles.html index 54345a18a..32f07daf3 100644 --- a/src/adhocracy/templates/comment/tiles.html +++ b/src/adhocracy/templates/comment/tiles.html @@ -154,9 +154,11 @@
${_("(deleted)")}
+ %if not c.instance.voting_disabled:
${tiles.poll.widget(comment.poll)}
+ %endif ## comment text diff --git a/src/adhocracy/templates/instance/settings_voting.html b/src/adhocracy/templates/instance/settings_voting.html index 0da5d1682..603d9349d 100644 --- a/src/adhocracy/templates/instance/settings_voting.html +++ b/src/adhocracy/templates/instance/settings_voting.html @@ -32,6 +32,8 @@

${c.settings_menu.current['label']}

%endif ${forms.checkbox(_("Enable vote delegation"), 'allow_delegate', 15)} + + ${forms.checkbox(_("Disable voting"), 'voting_disabled', 20)} %if c.votedetail_all_userbadges is not None:

${_('Break down Voting Result by Badge')}

diff --git a/src/adhocracy/templates/poll/tiles.html b/src/adhocracy/templates/poll/tiles.html index e30acb3b9..aff469e3e 100644 --- a/src/adhocracy/templates/poll/tiles.html +++ b/src/adhocracy/templates/poll/tiles.html @@ -12,6 +12,8 @@ con = tile.widget_action_attrs(model.Vote.NO) %>
+ +%if not c.instance.voting_disabled:
%if tile.can_show:
+%endif %if delegate_url: ${_('or:')} diff --git a/src/adhocracy/templates/proposal/show.html b/src/adhocracy/templates/proposal/show.html index dfc2c5d66..4eafb5643 100644 --- a/src/adhocracy/templates/proposal/show.html +++ b/src/adhocracy/templates/proposal/show.html @@ -231,8 +231,10 @@
${_('Last Activity')}
<% tally = c.proposal.rate_poll.tally %> + %if not c.instance.voting_disabled: ${sidebar_defs.votes(c.proposal.rate_poll)} ${sidebar_defs.votedetail(c.votedetail)} + %endif
${_('Category')}

diff --git a/src/adhocracy/templates/proposal/tiles.html b/src/adhocracy/templates/proposal/tiles.html index c4d7ab1ec..a4331998b 100644 --- a/src/adhocracy/templates/proposal/tiles.html +++ b/src/adhocracy/templates/proposal/tiles.html @@ -33,6 +33,8 @@

${proposal.title} %endif %endif

+ + %if not c.instance.voting_disabled:
%if proposal.is_adopt_polling(): ${_("%s%% approval") % int(proposal.adopt_poll.tally.rel_for * 100)|n} @@ -46,6 +48,8 @@

${proposal.title} ยท %endif

+ %endif +