示例#1
0
def pronoun_in_site_settings(schema, event):
    schema.add(colander.SchemaNode(
        colander.Boolean(),
        name="pronoun_active",
        title=_("Let users select pronoun"),
        description=_("Pronoun might be shown in different contexts like the speaker list."),
        missing=False))
示例#2
0
 def __call__(self, form, values):
     exc = colander.Invalid(form)  # Raised if trouble
     pns = self.request.registry.getAdapter(self.request.meeting, IParticipantNumbers)
     numbers = tuple(pns.tickets.keys())
     start_at = values['start_at']
     if start_at not in numbers and not values['create_new']:
         exc['start_at'] = _("Not an existing participant number")
         raise exc
     existing_emails = tuple([x.email for x in pns.tickets.values()])
     found = []
     i = start_at
     emails = values['emails'].splitlines()
     for email in emails:
         if email in existing_emails:
             found.append(email)
         if not values['create_new']:
             # Check if numbers exist
             if i not in numbers:
                 exc['emails'] = _("attach_emails_pn_dont_exist_error",
                                   default="There are more email addresses than "
                                           "existing participant numbers. "
                                           "Number ${num} not found. Total emails: ${emails_count}",
                                   mapping={'num': i, 'emails_count': len(emails)})
                 raise exc
             i += 1
     if found:
         exc['emails'] = _("The following emails are already assigned to numbers: ${emails}",
                           mapping={'emails': ", ".join(found)})
         raise exc
示例#3
0
def claim_participant_number_menu(context, request, va, **kw):
    if request.meeting:
        translate = request.localizer.translate
        participant_numbers = request.registry.getAdapter(request.meeting, IParticipantNumbers)
        if request.authenticated_userid not in participant_numbers.userid_to_number:
            self_assignment = request.registry.getAdapter(request.meeting, ISelfAssignmentSettings)
            if self_assignment.enabled:
                if self_assignment.user_has_required_role(request):
                    url = request.resource_url(request.meeting, 'self_claim_participant_number')
                else:
                    # The current user don't have the required role
                    role = request.registry.roles.get(self_assignment.required_role, None)
                    if role:
                        role_title = translate(role.title)
                    else:
                        role_title = self_assignment.required_role
                    return """<li class="disabled"><a>%s<br/>%s</a></li>""" % (
                           translate(
                               _("You lack the role '${role}'",
                                 mapping={'role': role_title})
                           ),
                           translate(
                               _("which is required to request a participant number.")
                           ),
                    )

            else:
                url = request.resource_url(request.meeting, 'claim_participant_number')
            return """<li><a href="%s">%s</a></li>""" % (url,
                                                         translate(_("Claim participant number")))
        else:
            return """<li class="disabled"><a>%s: %s</a></li>""" % (
                translate(_("Your participant number")),
                participant_numbers.userid_to_number[request.authenticated_userid]
            )
示例#4
0
 def adjust_voters(self, method_name):
     method = self.request.registry.getAdapter(self.context, IElegibleVotersMethod, name = method_name)
     new_voters = method.get_voters(request = self.request)
     if not isinstance(new_voters, frozenset):
         new_voters = frozenset(new_voters)
     electoral_register = self.request.registry.getAdapter(self.context, IElectoralRegister)
     current_voters = electoral_register.currently_set_voters()
     if current_voters == new_voters:
         msg = _(u"no_update_of_perms_needed_notice",
                 default = u"Method '${method_title}' applied but it reports no change needed.",
                 mapping = {'method_title': self.request.localizer.translate(method.title)})
         self.flash_messages.add(msg)
         return
     removed_voters = current_voters - new_voters
     added_voters = new_voters - current_voters
     for userid in removed_voters:
         self.context.del_groups(userid, (ROLE_VOTER,))
     for userid in added_voters:
         self.context.add_groups(userid, (ROLE_VOTER,))
     msg = _("updated_voter_permissions_notice",
             default = "Method '${method_title}' added ${added_count} and removed ${removed_count}.",
             mapping = {'method_title': self.request.localizer.translate(method.title),
                        'added_count': len(added_voters),
                        'removed_count': len(removed_voters)})
     self.flash_messages.add(msg)
示例#5
0
 def save_success(self, appstruct):
     # Since this is a bit backwards, we need to fetch the token.
     pn = appstruct['pn']
     userid = appstruct['userid']
     found = False
     for (token, num) in self.participant_numbers.token_to_number.items():
         if num == pn:
             found = True
             break
     if not found:
         raise HTTPForbidden(_(u"Participant number not found"))
     # Clear old number?
     if userid in self.participant_numbers.userid_to_number:
         number = self.participant_numbers.userid_to_number[userid]
         msg = _("participant_number_moved_warning",
                 default = u"This user was already assigned number ${number} so that number was cleared.",
                 mapping = {'number': number})
         self.flash_messages.add(msg, type = 'warning')
         self.participant_numbers.clear_number(number)
     # Assign
     number = self.participant_numbers.claim_ticket(userid, token)
     msg = _("number_now_assigned_notice",
             default = "You're now assigned number ${number}.",
             mapping = {'number': number})
     self.flash_messages.add(msg)
     return HTTPFound(location = self.request.resource_url(self.context, "manage_participant_numbers"))
示例#6
0
 def claim_participant_number(self):
     """ This view is for participants who're already members of this meeting,
         but haven't registered their number yet.
     """
     if self.api.userid in self.participant_numbers.userid_to_number:
         number = self.participant_numbers.userid_to_number[self.api.userid]
         msg = _(u"already_assigned_number_error",
                 default = u"You've already been assigned the number ${number} so you don't need to do anything else.",
                 mapping = {'number': number})
         self.api.flash_messages.add(msg, type = 'error')
         return HTTPFound(location = self.api.meeting_url)
     schema = createSchema('ClaimParticipantNumber')
     schema = schema.bind(context = self.context, request  = self.request, api = self.api)
     form = deform.Form(schema, buttons = [deform.Button('submit', title = _(u"Submit"))])
     if 'submit' in self.request.POST:
         controls = self.request.POST.items()
         try:
             appstruct = form.validate(controls)
         except deform.ValidationFailure, e:
             self.response['form'] = e.render()
             return self.response
         number = self.participant_numbers.claim_ticket(self.api.userid, appstruct['token'])
         msg = _(u"number_now_assigned_notice",
                 default = u"You're now assigned number ${number}.",
                 mapping = {'number': number})
         self.api.flash_messages.add(msg)
         return HTTPFound(location = self.api.meeting_url)
示例#7
0
 def __call__(self, node, value):
     if value not in security.find_authorized_userids(self.context, [security.VIEW]):
         raise colander.Invalid(node, _("${userid} doesn't exist in this meeting.",
                                        mapping = {'userid': value}))
     if security.ROLE_VOTER in self.context.get_groups(value):
         raise colander.Invalid(node, _("${userid} is already a voter.",
                                        mapping = {'userid': value}))
示例#8
0
 def manage_participant_numbers(self):
     if 'back' in self.request.POST:
         return HTTPFound(location = self.request.resource_url(self.context))
     response = {}
     add = 'add' in self.request.POST
     remove = 'remove' in self.request.POST
     here_url = self.request.resource_url(self.context, 'manage_participant_numbers')
     if add or remove:
         #Basic validation
         try:
             start = self.request.POST.get('start', None)
             start = int(start)
             end = self.request.POST.get('end', None)
             if not end:
                 end = None
             else:
                 end = int(end)
                 if start > end:
                     raise HTTPForbidden(_(u"End must be higher than start"))
         except TypeError:
             raise HTTPForbidden(_(u"Must be an integer value"))
         if add:
             res = self.participant_numbers.new_tickets(self.request.authenticated_userid, start, end)
             msg = _(u"Added ${count} new numbers",
                     mapping = {'count': len(res)})
             self.flash_messages.add(msg)
         if remove:
             res = self.participant_numbers.clear_numbers(start, end)
             msg = _(u"Removed ${count} numbers",
                     mapping = {'count': len(res)})
             self.flash_messages.add(msg, type = "warning")
         return HTTPFound(location = here_url)
     response['participant_numbers'] = self.participant_numbers
     return response
示例#9
0
 def __call__(self, node, value):
     if not principal_has_permisson(self.request, value, security.VIEW, context=self.context):
         raise colander.Invalid(node, _("${userid} doesn't exist in this meeting.",
                                        mapping={'userid': value}))
     if security.ROLE_VOTER in self.context.get_groups(value):
         raise colander.Invalid(node, _("${userid} is already a voter.",
                                        mapping={'userid': value}))
示例#10
0
 def __call__(self, node, value):
     participant_numbers = self.request.registry.getAdapter(self.context, IParticipantNumbers)
     if value not in participant_numbers.token_to_number:
         raise colander.Invalid(node, _(u"No match - remember that it's case sensitive!"))
     number = participant_numbers.token_to_number[value]
     if participant_numbers.tickets[number].claimed:
         raise colander.Invalid(node, _(u"This number has already been claimed."))
示例#11
0
def includeme(config):
    config.add_portlet(MeetingPresencePortlet)
    config.scan(__name__)
    config.add_view_action(
        control_panel_category,
        'control_panel', 'meeting_presence',
        panel_group = 'control_panel_meeting_presence',
        title=_("Meeting presence"),
        description=_("meeting_presence_cp_description",
                      default="Check who's present. "
                              "Can be used as base to distribute voting rights."),
        permission = MODERATE_MEETING,
        check_active=meeting_presence_enabled,
    )
    config.add_view_action(
        control_panel_link,
        'control_panel_meeting_presence', 'check',
        title=_("Check presence"),
        view_name='check_meeting_presence',
        priority=10,
    )
    config.add_view_action(
        control_panel_link,
        'control_panel_meeting_presence', 'settings',
        title=_("Settings"),
        view_name='meeting_presence_settings',
        priority=20,
    )
示例#12
0
 def get_schema(self):
     schema = colander.Schema(title = _(u"Select discussion posts to print"),
                              description = _(u"print_discussion_description",
                                              default = u"Each post will be on its own page"))
     for post in self.context.get_content(content_type = 'DiscussionPost'):
         schema.add(colander.SchemaNode(colander.Bool(),
                                        name = post.__name__,
                                        title = strip_and_truncate(post.text, symbol = '[...]'),))
     return schema
示例#13
0
 def __call__(self):
     if security.ROLE_VOTER not in self.api.cached_effective_principals:
         raise HTTPForbidden(_("You're not a voter"))
     query = {'content_type': 'Poll',
              'path': resource_path(self.context),
              'workflow_state': 'ongoing'}
     res = self.api.search_catalog(**query)[0]
     if res.total > 0:
         raise HTTPForbidden(_("Votes can't be transfered while a poll is open."))
     return super(TransferVoteForm, self).__call__()
示例#14
0
 def __call__(self, node, value):
     parts = value.split('-')
     err = _("Must be written as 'NN-XX' where N is low nr and X high.")
     if len(parts) != 2:
         raise colander.Invalid(node, err)
     try:
         parts = [int(x) for x in parts]
     except:
         raise colander.Invalid(node, err)
     if parts[0] >= parts[1]:
         raise colander.Invalid(node, _("First value must be higher than second"))
示例#15
0
def add_gender_in_profile(schema, event):
    request = get_current_request()
    if request.context.content_type == 'Meeting' and \
        request.context.get_field_value('access_policy') != ParticipantNumberAPWithGender.name:
        return #Skip in meeting context without this AP
    schema.add(colander.SchemaNode(colander.String(),
                                   name = "gender",
                                   title = _(u"Gender"),
                                   description = _(u"Used for statistics and perhaps gender based quotas. See meeting for details."),
                                   widget = deform.widget.RadioChoiceWidget(values = GENDER_VALUES)),
                                   )
示例#16
0
    def get_schema(self):
        schema = colander.Schema(title = _(u"Select proposals to print"),
                                 description = _(u"print_proposals_description",
                                                 default = u"Each proposal will be on its own page"))

        for prop in self.context.get_content(content_type = 'Proposal'):
            schema.add(colander.SchemaNode(colander.Bool(),
                                           name = prop.__name__,
                                           title = prop.get_field_value('aid'),
                                           description = prop.title))
        return schema
示例#17
0
 def assign_success(self, appstruct):
     start_number = self.self_assignment_settings.get('start_number', None)
     if not isinstance(start_number, int):
         self.flash_messages.add(_("Meeting has bad configurartion for participant numbers, contact the moderator.",
                                   type='danger'))
         return HTTPFound(location=self.request.resource_url(self.context))
     new_pn = assign_next_free_pn(self.participant_numbers, self.request.authenticated_userid, start_number)
     if not new_pn:
         raise HTTPBadRequest("No number can be assigned.")
     msg = _("You've been assigned number ${num}", mapping={'num': new_pn})
     self.flash_messages.add(msg, type='success')
     return HTTPFound(location = self.request.resource_url(self.context))
示例#18
0
 def __call__(self):
     if not _enabled(self.request.meeting):
         raise HTTPForbidden(_('Vote transfer is not currently enabled.'))
     if security.ROLE_VOTER not in self.context.local_roles.get(
             self.request.authenticated_userid, ()):
         raise HTTPForbidden(_("You're not a voter"))
     query = Eq('type_name', 'Poll') & Eq('path', resource_path(self.context)) & Eq(
         'workflow_state', 'ongoing')
     res = self.request.root.catalog.query(query)[0]
     if res.total > 0:
         raise HTTPForbidden(_("Votes can't be transfered while a poll is open."))
     return super(TransferVoteForm, self).__call__()
示例#19
0
 def manage_participant_callbacks(self):
     if 'back' in self.request.POST:
         return HTTPFound(location = self.request.resource_url(self.context))
     add = 'add' in self.request.POST
     remove = 'remove' in self.request.POST
     if add or remove:
         #Basic validation
         try:
             start = self.request.POST.get('start', None)
             start = int(start)
             end = self.request.POST.get('end', None)
             if not end:
                 end = None
             else:
                 end = int(end)
                 if start > end:
                     raise HTTPForbidden(_("End must be higher than start"))
         except TypeError:
             raise HTTPForbidden(_("Must be an integer value"))
         
         callback = self.request.POST['callback']
         if add:
             added, existed = self.participant_callbacks.add(callback, start, end)
             msg = _(u"Added ${added} new callbacks and skipped ${existed} that already existed.",
                     mapping = {'added': len(added), 'existed': len(existed)})
             self.flash_messages.add(msg)
             if self.request.POST.get('execute_for_existing', True):
                 executed = 0
                 if end == None:
                     end = start
                 for i in range(start, end + 1): #Range  stops before end otherwise
                     if i in self.participant_numbers.number_to_userid:
                         #The method execute_callbacks_for is fault tolerant for missing callbacks, but not for
                         #failures within the actual callback.
                         self.participant_callbacks.execute_callbacks_for(i, self.participant_numbers.number_to_userid[i],
                                                                          limit = callback, request = self.request)
                         executed += 1
                 msg = _(u"Executed callback for ${num} users that had already claimed a participant number.",
                         mapping = {'num': executed})
                 self.flash_messages.add(msg)
         if remove:
             removed, nonexistent = self.participant_callbacks.remove(callback, start, end)
             msg = _(u"Removed ${removed} callbacks and skipped ${nonexistent} that wasn't registered.",
                     mapping = {'removed': len(removed), 'nonexistent': len(nonexistent)})
             self.flash_messages.add(msg)
         here_url = self.request.resource_url(self.context, 'manage_participant_callbacks')
         return HTTPFound(location = here_url)
     response = {}
     response['participant_numbers'] = self.participant_numbers
     response['participant_callbacks'] = self.participant_callbacks
     response['callback_adapters'] = [adapter for (name, adapter) in self.request.registry.getAdapters([self.request.meeting], IParticipantCallback)]
     return response
示例#20
0
def includeme(config):
    config.scan(__name__)
    config.add_view_action(
        control_panel_category,
        'control_panel', 'print_',
             panel_group='control_panel_print_btn_settings',
             title=_("Print button"),
    )
    config.add_view_action(
        control_panel_link,
        'control_panel_print_btn_settings', 'settings',
        title=_("Settings"),
        view_name='print_btn_settings',
    )
示例#21
0
def inject_in_settings(schema, event):
    schema.add(
        colander.SchemaNode(
            colander.String(),
            title = _("Voter participant number range"),
            description=_("voter_pn_range_desc",
                          default="Write number as 'NN-NN', i.e. 10-20 means that "
                                  "10 to and including 20 will be voters if they're "
                                  "marked as present."),
            name = 'elegible_voter_pn',
            missing = "",
            validator = ElegibleVoterPNRangeValidator(),
        )
    )
示例#22
0
 def presence_check_ctrl(self):
     action = self.request.GET.get('action', '')
     if action == 'start':
         self.flash_messages.add(_("Started"), type = 'success')
         self.mp_util.start_check()
     elif action == 'end':
         if self.mp_util.open:
             self.flash_messages.add(_("Closed"), type = 'warning')
             self.mp_util.end_check()
         else:
             raise HTTPForbidden("No check ongoing")
     else:
         raise HTTPForbidden("No such action %r" % action)
     came_from = self.request.GET.get('came_from', self.request.resource_url(self.request.meeting))
     return HTTPFound(location = came_from)
示例#23
0
 def save_success(self, appstruct):
     number = self.participant_numbers.claim_ticket(self.request.authenticated_userid, appstruct['token'])
     msg = _("number_now_assigned_notice",
             default = "You're now assigned number ${number}.",
             mapping = {'number': number})
     self.flash_messages.add(msg)
     return HTTPFound(location = self.request.resource_url(self.context))
示例#24
0
 def execute_callbacks_for(self, number, userid, limit = None, request = None, **kw):
     assert isinstance(number, int)
     assert isinstance(userid, basestring)
     if request is None:
         request = get_current_request()
     if isinstance(limit, basestring):
         limit = (limit,)
     errors = []
     executed = []
     for callback_name in self.get_callbacks(number):
         if limit is None:
             callback = request.registry.queryAdapter(self.context, IParticipantCallback, name = callback_name)
         else:
             if not callback_name in limit:
                 continue
             callback = request.registry.queryAdapter(self.context, IParticipantCallback, name = callback_name)
         #Check that adapter was found
         if callback is None:
             errors.append(callback_name)
         else:
             callback(number, userid, request = request, **kw)
             executed.append(callback_name)
     if errors:
         fm = request.registry.getAdapter(request, IFlashMessages)
         msg = _(u"could_not_execute_callback_error",
                 default = u"Some callbacks for the UserId '${userid}' failed. Contact the moderator about this. "
                           u"The ones that failed were: ${callback_errors}",
                 mapping = {'callback_errors': ", ".join(errors), 'userid': userid})
         fm.add(msg, type = 'error')
     return executed
示例#25
0
 def change_ownership(self, objects, schema):
     schema = schema.bind(context = self.context, request = self.request, api = self.api)
     back_url = self.request.resource_url(self.context)
     if not objects:
         self.api.flash_messages.add(_(u"No proposals here"))
         return HTTPFound(location = back_url)
     form = deform.Form(schema, buttons = (button_update, button_cancel,))
     self.api.register_form_resources(form)
     if 'cancel' in self.request.POST:
         self.api.flash_messages.add(vmf(u"Canceled"))
         return HTTPFound(location = back_url)
     if 'update' in self.request.POST:
         controls = self.request.POST.items()
         try:
             #appstruct is deforms convention. It will be the submitted data in a dict.
             appstruct = form.validate(controls)
         except deform.exception.ValidationFailure, e:
             self.response['form'] = e.render()
             return self.response
         updated = set()
         for (name, owner) in appstruct.items():
             obj = self.context[name]
             if change_ownership(obj, owner):
                 updated.add(name)
         if updated:
             self.api.flash_messages.add(vmf(u"Successfully updated"))
         else:
             self.api.flash_messages.add(vmf(u"Nothing updated"))
         return HTTPFound(location = back_url)
示例#26
0
 def set_as_present(self):
     if self.request.authenticated_userid not in self.mp_util.present_userids:
         #Add here will raise forbidden if it isn't open
         self.mp_util.add(self.request.authenticated_userid)
     if self.request.is_xhr:
         return {}
     self.flash_messages.add(_("You're now set as present"), type = 'success')
     return HTTPFound(localtion = self.request.resource_url(self.request.meeting))
示例#27
0
def elegible_voters_method_choices_widget(node, kw):
    """ Create a widget where you can choose all selectable methods to adjust elegible voters. """
    context = kw['context']
    request = kw['request']
    method_choices = [('', _('<Select>'))]
    for (name, method) in request.registry.getAdapters([context], IElegibleVotersMethod):
        method_choices.append((name, method.title))
    return deform.widget.SelectWidget(values=method_choices)
示例#28
0
 def save_success(self, appstruct):
     userid = appstruct['to_userid']
     if userid is None:
         raise HTTPBadRequest("No userid found")
     self.context.del_groups(self.request.authenticated_userid, [security.ROLE_VOTER])
     self.context.add_groups(userid, [security.ROLE_VOTER])
     self.flash_messages.add(_("Vote transfered to ${userid}", mapping={'userid': userid}))
     return HTTPFound(location=self.request.resource_url(self.context))
示例#29
0
 def diff_electoral_register_view(self):
     post = self.request.POST
     if 'back' in post:
         url = self.request.resource_url(self.context, 'electoral_register')
         return HTTPFound(location = url)
     
     schema = createSchema('ElectoralRegisterDiff').bind(context = self.context, request = self.request, api = self.api)
     form = deform.Form(schema, buttons=(deform.Button('diff', _(u"Diff")),
                                         deform.Button('back', _(u"Back")),))
     if 'diff' in post:
         controls = post.items()
         try:
             appstruct = form.validate(controls)
             self.response['form'] = form.render(appstruct = appstruct)
             self.append_diff_info(appstruct['first'], appstruct['second'])
         except deform.ValidationFailure, e:
             self.response['form'] = e.render()
示例#30
0
 def schema(self):
     schema = createSchema("ClaimParticipantNumber")
     if self.context.get_field_value('pn_ap_public_roles', False):
         schema['token'].missing = u""
         schema['token'].description = _(u"token_validator_description_when_ok_without",
                                         default = u"Enter your code to claim your participant number and all permissions associated with it. "
                                             u"If you're not supposed to have a participant number, you're allowed to proceed by clicking "
                                             u"'Request access'.")
     return schema