def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) # apply removal of redefined attendee position for item_to_update in items_to_update: item_to_update_uid = item_to_update.UID() item_attendees_positions = self.meeting.item_attendees_positions.get( item_to_update_uid, {}) if self.person_uid in item_attendees_positions: del item_attendees_positions[self.person_uid] if not item_attendees_positions: del self.meeting.item_attendees_positions[item_to_update_uid] notifyModifiedAndReindex(item_to_update) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} hp={1} from_item_number={2} until_item_number={3}'.format( repr(self.context), self.person_uid, first_item_number, last_item_number) fplog('remove_redefined_item_attendee_position', extras=extras) api.portal.show_message(_("Redefined attendee position was removed."), request=self.request) self._finished = True
def handleSave(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return # check that user is not trying to workaround security self._check_auth(data) # save proposing_group_comment and return, make sure we do not set None self.item.adviceIndex[data['advice_uid']]['proposing_group_comment'] = \ data['proposing_group_comment'] or u"" # make sure advice cache is invalidated as proposing group comment # is displayed on advice view and does not change the advice modified date advice = self.item.getAdviceObj(data['advice_uid']) # redirect to item or advice view on correct anchor self.request.RESPONSE.redirect( self.context.absolute_url() + "#adviceAndAnnexes") # invalidate advice view cache if advice is not None: # as we use etags, we will change the _p_mtime because # doNotCache(advice, self.request, self.request.RESPONSE) # seems to work with FF but not with Chrome... # Setting an arbitrary attribute will update _p_mtime # description is not used but exists on any DX content advice.description = advice.description extras = 'item={0} advice_id={1}'.format( repr(self.item), data['advice_uid']) fplog('edit_proposing_group_comment', extras=extras)
def _doApplyItemSignatures(self): """ The method actually do the job, set the itemSignatures on self.context and following items if defined """ self._check_auth() # only apply if different from meeting item_signatures_def = item_signatures_default() if self.item_signatures != item_signatures_def: items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber( relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.context.getMeeting()) for itemToUpdate in items_to_update: itemToUpdate.setItemSignatures(self.item_signatures) first_item_number = items_to_update[0].getItemNumber( for_display=True) last_item_number = items_to_update[-1].getItemNumber( for_display=True) extras = 'item={0} from_item_number={1} until_item_number={2}'.format( repr(self.context), first_item_number, last_item_number) fplog('manage_item_signatures', extras=extras) # invalidate assembly async load on item invalidate_cachekey_volatile_for( 'Products.PloneMeeting.browser.async.AsyncLoadItemAssemblyAndSignaturesRawFields', get_again=True) api.portal.show_message(_("Item signatures have been updated."), request=self.request) self._finished = True
def __call__(self, attendee_uid, position): """ """ if not self.context._mayChangeAttendees(): raise Unauthorized # get attendee and move it to right position meeting = self.context.getMeeting() all_uids = list(self.context.get_all_attendees(the_objects=False)) attendee_uid_index = all_uids.index(attendee_uid) all_uids.insert(position - 1, all_uids.pop(attendee_uid_index)) all_uids = tuple(all_uids) context_uid = self.context.UID() # if finally the order is back to the order of the meeting # remove the item UID from item_attendees_order if all_uids == meeting.get_all_attendees(the_objects=False): meeting.item_attendees_order.pop(context_uid) else: meeting._set_item_attendees_order(context_uid, all_uids) # log extras = 'item={0} hp={1} position={2}'.format(repr(self.context), attendee_uid, position) fplog('change_item_attendees_order', extras=extras) # message api.portal.show_message(_("Attendee position was changed."), request=self.request) return True
def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) # apply redefined position for item_to_update in items_to_update: item_to_update_uid = item_to_update.UID() updated = set_meeting_item_attendee_position( self.meeting, item_to_update_uid, self.person_uid, self.position_type) if updated: notifyModifiedAndReindex(item_to_update) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} hp={1} from_item_number={2} until_item_number={3}'.format( repr(self.context), self.person_uid, first_item_number, last_item_number) fplog('redefine_item_attendee_position', extras=extras) api.portal.show_message(_("Attendee position has been redefined."), request=self.request) self._finished = True
def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized # check where is person_uid, item_absents or item_excused meeting_absent_attr = self._get_meeting_absent_attr() items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) for item_to_update in items_to_update: item_to_update_uid = item_to_update.UID() item_absents = meeting_absent_attr.get(item_to_update_uid, []) if self.person_uid in item_absents: item_absents.remove(self.person_uid) meeting_absent_attr[item_to_update_uid] = item_absents notifyModifiedAndReindex(item_to_update) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} hp={1} from_item_number={2} until_item_number={3}'.format( repr(self.context), self.person_uid, first_item_number, last_item_number) fplog('welcome_item_attendee', extras=extras) api.portal.show_message(self.attendee_welcome_msg, request=self.request) self._finished = True
def handleSaveRemoveAdviceInheritance(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return advice_infos = self._advice_infos(data) if not advice_infos.mayRemoveInheritedAdvice(): raise Unauthorized # if 'ask_localy', check if advice_id may be asked locally, if it is not the case # return a portal message but do not remove the inherited advice advice_asked_locally = False if data['inherited_advice_action'] == 'ask_locally': if self.context.showOptionalAdvisers(): advisers_vocab = get_vocab( self.context, self.context.getField( 'optionalAdvisers').vocabulary_factory, **{ 'include_selected': False, 'include_not_selectable_values': False }) if data['advice_uid'] in advisers_vocab: optionalAdvisers = list( self.context.getOptionalAdvisers(computed=True)) if data['advice_uid'] not in optionalAdvisers: optionalAdvisers.append(data['advice_uid']) self.context.setOptionalAdvisers(optionalAdvisers) advice_asked_locally = True if not advice_asked_locally: api.portal.show_message(message=_( 'remove_advice_inheritance_ask_locally_not_configured'), request=self.request, type='warning') self.request.RESPONSE.redirect(self.context.absolute_url()) return del self.context.adviceIndex[data['advice_uid']] self.context.update_local_roles() if advice_asked_locally: api.portal.show_message(message=_( 'remove_advice_inheritance_removed_and_asked_locally'), request=self.request) else: api.portal.show_message( message=_('remove_advice_inheritance_removed'), request=self.request) # in case an adviser removed inherited advice and may not # see the item anymore, we redirect him to a viewable place cleanMemoize( self.context, prefixes=['borg.localrole.workspace.checkLocalRolesAllowed']) url = findViewableURL(self.context, self.request) self.request.RESPONSE.redirect(url) # add logging message to fingerpointing log extras = 'object={0} advice_uid={1} inherited_advice_action={2}'.format( repr(self.context), data['advice_uid'], data['inherited_advice_action']) fplog('remove_advice_inheritance', extras=extras) return
def _after_reply_hook(self, serialized_obj): """ """ obj = self.context.get(serialized_obj["id"]) # add a record to the item workflow_history to specify that item was created thru SOAP WS action_name = "create_element_using_ws_rest" action_label = action_name + "_comments" # there may be several actions in the workflow_history, especially when # wf_transitions are used so we insert our event just after event 0 add_wf_history_action(obj, action_name=action_name, action_label=action_label, insert_index=0) # fingerpointing extras = "object={0}".format( repr(self.context.get(serialized_obj["id"]))) fplog("create_by_ws_rest", extras=extras)
def __call__(self): """ """ if not self.context._mayChangeAttendees(): raise Unauthorized meeting = self.context.getMeeting() meeting.item_attendees_order.pop(self.context.UID()) # log extras = 'item={0}'.format(repr(self.context)) fplog('reinit_item_attendees_order', extras=extras) # message api.portal.show_message(_( "Attendees order was reinitialized to meeting order for this item." ), request=self.request) return redirect(self.request, self.context.absolute_url())
def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) # return a portal_message if trying to byebye an attendee that is # a signatory redefined on the item # user will first have to select another signatory on meeting or item # return a portal_message if trying to set absent and item that is # already excused (and the other way round) error = self._mayByeByeAttendeePrecondition(items_to_update) if error: self._finished = True return # apply item_absents/item_excused meeting_not_present_attr = getattr( self.meeting, self.NOT_PRESENT_MAPPING[self.not_present_type]) for item_to_update in items_to_update: item_to_update_uid = item_to_update.UID() item_not_present = meeting_not_present_attr.get( item_to_update_uid, []) if self.person_uid not in item_not_present: item_not_present.append(self.person_uid) meeting_not_present_attr[item_to_update_uid] = item_not_present notifyModifiedAndReindex(item_to_update) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} hp={1} not_present_type={2} from_item_number={3} until_item_number={4}'.format( repr(self.context), self.person_uid, self.not_present_type, first_item_number, last_item_number) fplog('byebye_item_attendee', extras=extras) api.portal.show_message(_("Attendee has been set ${not_present_type}.", mapping={ 'not_present_type': _('item_not_present_type_{0}'.format( self.not_present_type)) }), request=self.request) self._finished = True
def _doApplyItemAssembly(self): """ The method actually do the job, set the itemAssembly on self.context and following items if defined """ self._check_auth() # only update if default proposed value was changed item_assembly_def = item_assembly_default() item_excused_def = item_excused_default() item_absents_def = item_absents_default() item_guests_def = item_guests_default() from_item_number = self.context.getItemNumber(relativeTo='meeting') until_item_number = self.apply_until_item_number items_to_update = _itemsToUpdate( from_item_number=from_item_number, until_item_number=until_item_number, meeting=self.meeting) for itemToUpdate in items_to_update: # only update if we changed default value if self.item_assembly != item_assembly_def: itemToUpdate.setItemAssembly(self.item_assembly) if self.item_excused != item_excused_def: itemToUpdate.setItemAssemblyExcused(self.item_excused) if self.item_absents != item_absents_def: itemToUpdate.setItemAssemblyAbsents(self.item_absents) if self.item_guests != item_guests_def: itemToUpdate.setItemAssemblyGuests(self.item_guests) notifyModifiedAndReindex(itemToUpdate) # invalidate assembly async load on item invalidate_cachekey_volatile_for( 'Products.PloneMeeting.browser.async.AsyncLoadItemAssemblyAndSignaturesRawFields', get_again=True) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} from_item_number={1} until_item_number={2}'.format( repr(self.context), first_item_number, last_item_number) fplog('manage_item_assembly', extras=extras) api.portal.show_message(_("Item assemblies have been updated."), request=self.request) self._finished = True
def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) # apply signatory for item_to_update in items_to_update: item_to_update_uid = item_to_update.UID() item_signatories = self.meeting.item_signatories.get( item_to_update_uid, {}) signature_number = [ k for k, v in item_signatories.items() if v['hp_uid'] == self.person_uid ] if signature_number: del item_signatories[signature_number[0]] # if no more redefined item signatories, # remove item UID from meeting.item_signatories if item_signatories: self.meeting.item_signatories[ item_to_update_uid] = item_signatories else: del self.meeting.item_signatories[item_to_update_uid] notifyModifiedAndReindex(item_to_update) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} hp={1} from_item_number={2} until_item_number={3}'.format( repr(self.context), self.person_uid, first_item_number, last_item_number) fplog('remove_redefined_item_signatory', extras=extras) api.portal.show_message( _("Attendee is no more defined as item signatory."), request=self.request) self._finished = True
def handleApply(self, action): """ """ if not self.available(): raise Unauthorized data, errors = self.extractData() if errors: self.status = self.formErrorsMessage else: # log in fingerpointing before executing job extras = 'action={0} number_of_elements={1}'.format( repr(self.label), len(self.brains)) fplog('apply_batch_action', extras=extras) # call the method that does the job applied = self._apply(**data) # redirect if not using an overlay if not self.request.form.get('ajax_load', ''): self.request.response.redirect( self.request.form['form.widgets.referer']) else: # make sure we return nothing, taken into account by ajax query if not applied: self.request.RESPONSE.setStatus(204) return applied or ""
def __call__(self, moveType, wishedNumber=None): """ Change the items order on a meeting. This is an unrestricted method so a MeetingManager can change items order even if some items are no more movable because decided (and so no more 'Modify portal content' on it). We double check that current user can actually may_change_items_order. Anyway, this method move an item, one level up/down or at a given position. """ # we do this unrestrictively but anyway respect the Meeting.may_change_items_order meeting = self.context.getMeeting() if not meeting.wfConditions().may_change_items_order(): raise Unauthorized oldIndex = self.context.getItemNumber() plone_utils = api.portal.get_tool('plone_utils') # Move the item up (-1), down (+1) or at a given position ? if moveType == 'number': try: float(wishedNumber) # In this case, wishedNumber specifies the new position where # the item must be moved. except (ValueError, TypeError): plone_utils.addPortalMessage(translate( msgid='item_number_invalid', domain='PloneMeeting', context=self.request), type='warning') return False nbOfItems = meeting.number_of_items(as_int=True) items = meeting.get_items(ordered=True, unrestricted=True) # Calibrate and validate moveValue if moveType == 'number': # we receive 2.1, 2.5 or 2.10 but we store 201, 205 and 210 so it is orderable integers moveNumber = _itemNumber_to_storedItemNumber(wishedNumber) moveNumberIsInteger = _is_integer(moveNumber) # Is this move allowed ? if moveNumber == oldIndex: plone_utils.addPortalMessage(translate( msgid='item_did_not_move', domain='PloneMeeting', context=self.request), type='warning') return False # check that moveNumber is not < 1 or not > next possible item # check that the moveNumber is valid, aka integer (4) or max 2 decimal number (4.1 or 4.13) # check also that if we use a subnumber, the previous exists (22.2 exists if we specified 22.3) # check finally that if we are moving an item to a subnumber, # the master exists (moving to 12.1, 12 has to exist) last_item = items[-1] last_item_number = last_item.getItemNumber() if (moveNumber < 100) or \ (moveNumber > _to_integer(last_item_number + 100)) or \ (not moveNumberIsInteger and len(wishedNumber.split('.')[1]) > 2) or \ (not moveNumberIsInteger and (not meeting.get_item_by_number(moveNumber - 1) or moveNumber - 1 == oldIndex)): plone_utils.addPortalMessage(translate( msgid='item_illegal_move', domain='PloneMeeting', context=self.request), type='warning') return False else: # down, must not be last # up, must not be first if (moveType == 'down' and self.context == items[-1]) or \ (moveType == 'up' and self.context == items[0]): plone_utils.addPortalMessage(translate( msgid='item_illegal_switch', domain='PloneMeeting', context=self.request), type='warning') return False # 'down' or 'up' may not switch an integer and a subnumber currentIsInteger = _is_integer(self.context.getItemNumber()) illegal_switch = False if moveType == 'down': nextIsInteger = _is_integer( self.context.getSiblingItem('next')) if (currentIsInteger and not nextIsInteger) or (not currentIsInteger and nextIsInteger): illegal_switch = True elif moveType == 'up': previousIsInteger = _is_integer( self.context.getSiblingItem('previous')) if (currentIsInteger and not previousIsInteger) or (not currentIsInteger and previousIsInteger): illegal_switch = True if illegal_switch: plone_utils.addPortalMessage(translate( msgid='item_illegal_switch', domain='PloneMeeting', context=self.request), type='warning') return False # Move the item if nbOfItems >= 2: if not moveType == 'number': # switch the items if moveType == 'up': if oldIndex == 100: # moving first item 'up', does not change anything # actually it is not possible in the UI because the 'up' # icon is not displayed on the first item return False otherNumber = self.context.getSiblingItem('previous') else: # moveType == 'down' otherNumber = self.context.getSiblingItem('next') otherItem = meeting.get_item_by_number(otherNumber) self.context.setItemNumber(otherItem.getItemNumber()) otherItem.setItemNumber(oldIndex) else: # Move the item to an absolute position self.context.setItemNumber(moveNumber) # get items again now that context number was updated items = meeting.get_items(ordered=True, unrestricted=True) oldIndexIsInteger = _is_integer(oldIndex) oldIndexHasSubnumbers = meeting.get_item_by_number(oldIndex + 1) if moveNumber < oldIndex: # We moved the item up for item in items: itemNumber = item.getItemNumber() # moved item if item == self.context: # moving 4 to 2 if (oldIndexIsInteger and moveNumberIsInteger): pass # moving 4.1 to 2 elif (not oldIndexIsInteger and moveNumberIsInteger): pass # moving 4 to 2.1 elif (oldIndexIsInteger and not moveNumberIsInteger): pass elif (not oldIndexIsInteger and not moveNumberIsInteger): # moving 3.1 to 2.2 pass # item that was at the moveNumber position elif itemNumber == moveNumber: # moving 4 to 2 if (oldIndexIsInteger and moveNumberIsInteger): item.setItemNumber(itemNumber + 100) # moving 4.1 to 2 elif (not oldIndexIsInteger and moveNumberIsInteger): item.setItemNumber( itemNumber + _compute_value_to_add(itemNumber)) # moving 4 to 2.1 elif (oldIndexIsInteger and not moveNumberIsInteger): item.setItemNumber( itemNumber + _compute_value_to_add(itemNumber)) elif (not oldIndexIsInteger and not moveNumberIsInteger): # moving 3.1 to 2.2 item.setItemNumber(itemNumber + 1) # other items else: # moving 4 to 2 if (oldIndexIsInteger and moveNumberIsInteger) and \ (itemNumber < oldIndex and itemNumber > moveNumber): item.setItemNumber(itemNumber + 100) # moving 4.1 to 2 elif (not oldIndexIsInteger and moveNumberIsInteger ) and itemNumber > moveNumber: # subnumbers of oldIndex (4.2, 4.3, ...) must be decreased of 0.1 if _use_same_integer( itemNumber, oldIndex) and itemNumber > oldIndex: item.setItemNumber( itemNumber + 100 - _compute_value_to_add(itemNumber)) else: item.setItemNumber(itemNumber + 100) # moving 4 to 2.1 elif (oldIndexIsInteger and not moveNumberIsInteger): # moving master, decrease old subnumbers if > oldIndex if _use_same_integer(itemNumber, oldIndex): item.setItemNumber( itemNumber - _compute_value_to_add(itemNumber)) # increase subnumbers > moveNumber if _use_same_integer( itemNumber, moveNumber ) and itemNumber > moveNumber: item.setItemNumber( itemNumber + _compute_value_to_add(itemNumber)) # decrease every number > oldIndex if oldIndex was not a master number elif not oldIndexHasSubnumbers and itemNumber > oldIndex: item.setItemNumber(itemNumber - 100) elif (not oldIndexIsInteger and not moveNumberIsInteger): # manage when moving 3.1 to 2.2 or 3.4 to 3.2 # moving to another integer (3.1 to 2.2) if not _use_same_integer(moveNumber, oldIndex): # decrease 3.2 to 3.1 if _use_same_integer(itemNumber, oldIndex): if itemNumber > oldIndex: item.setItemNumber(itemNumber - 1) # increase 2.3 to 2.4 elif _use_same_integer(itemNumber, moveNumber) and \ itemNumber > moveNumber: item.setItemNumber(itemNumber + 1) else: # moving to same integer (3.4 to 3.2) # increase itemNumber in between but itemNumber after # oldIndex does not change if _use_same_integer(itemNumber, moveNumber) and \ itemNumber > moveNumber and \ itemNumber < oldIndex: item.setItemNumber(itemNumber + 1) else: # We moved the item down for item in items: itemNumber = item.getItemNumber() if item == self.context: # moving 2 to 4 if (oldIndexIsInteger and moveNumberIsInteger): # if moving to last position, we need to remove 100 if > last_item_number if moveNumber > last_item_number: item.setItemNumber(moveNumber - 100) # moving 2.1 to 4 elif (not oldIndexIsInteger and moveNumberIsInteger): pass # moving 2 to 4.2 elif (oldIndexIsInteger and not moveNumberIsInteger): if not oldIndexHasSubnumbers: item.setItemNumber(moveNumber - 100) elif (not oldIndexIsInteger and not moveNumberIsInteger): # moving 2.1 to 3.2 # (not oldIndexIsInteger and not moveNumberIsInteger) pass elif itemNumber == moveNumber: # moving 2 to 4 if (oldIndexIsInteger and moveNumberIsInteger): item.setItemNumber( itemNumber - _compute_value_to_add(itemNumber)) # moving 2.1 to 4 elif (not oldIndexIsInteger and moveNumberIsInteger): item.setItemNumber( itemNumber + _compute_value_to_add(itemNumber)) # moving 2 to 4.2 elif (oldIndexIsInteger and not moveNumberIsInteger): item.setItemNumber( itemNumber - 100 + _compute_value_to_add(itemNumber)) elif (not oldIndexIsInteger and not moveNumberIsInteger): # moving 2.1 to 3.2 # increase 3.2 to 3.3 if not _use_same_integer(moveNumber, oldIndex): item.setItemNumber(itemNumber + 1) else: # moving 2.1 to 2.4, decrease 2.4 to 2.3 item.setItemNumber(itemNumber - 1) else: # moving 2 to 4 if (oldIndexIsInteger and moveNumberIsInteger) and \ (itemNumber > oldIndex and itemNumber < moveNumber): item.setItemNumber(itemNumber - 100) # moving 2.1 to 4 elif (not oldIndexIsInteger and moveNumberIsInteger ) and itemNumber > oldIndex: # decrease elements having same subnumber as oldIndex if (_use_same_integer(itemNumber, oldIndex)): item.setItemNumber( itemNumber - _compute_value_to_add(itemNumber)) elif itemNumber > moveNumber: item.setItemNumber(itemNumber + 100) # moving 2 to 4.2 elif (oldIndexIsInteger and not moveNumberIsInteger ) and itemNumber > oldIndex: # decrease from 1 but add + 0.1 to subnumbers > moveNumber if (_use_same_integer(itemNumber, moveNumber) ) and itemNumber > moveNumber: item.setItemNumber( itemNumber - 100 + _compute_value_to_add(itemNumber)) # decrease subnumbers of master we moved elif (_use_same_integer(itemNumber, oldIndex)): item.setItemNumber( itemNumber - _compute_value_to_add(itemNumber)) elif not oldIndexHasSubnumbers: item.setItemNumber(itemNumber - 100) elif (not oldIndexIsInteger and not moveNumberIsInteger): # manage when moving 2.1 to 3.2 or 3.2 to 3.4 # moving to another integer (2.1 to 3.2) if not _use_same_integer(moveNumber, oldIndex): # decrease 2.2 to 2.1 if _use_same_integer( itemNumber, oldIndex ) and itemNumber > oldIndex: item.setItemNumber(itemNumber - 1) # increase 3.2 to 3.3 elif _use_same_integer(itemNumber, moveNumber) and \ itemNumber > moveNumber: item.setItemNumber(itemNumber + 1) else: # moving to same integer (3.2 to 3.4) # increase itemNumber in between but itemNumber after # oldIndex does not change if _use_same_integer(itemNumber, moveNumber) and \ itemNumber < moveNumber and \ itemNumber > oldIndex: item.setItemNumber(itemNumber - 1) # when items order on meeting changed, it is considered modified, # do this before update_item_references meeting.notifyModified() # add logging message to fingerpointing log extras = 'object={0} meeting={1} original_position={2} new_position={3}'.format( repr(self.context), repr(meeting), _storedItemNumber_to_itemNumber(oldIndex, forceShowDecimal=False), self.context.getItemNumber(for_display=True)) fplog('change_item_order', extras=extras) # update item references starting from minus between oldIndex and new itemNumber meeting.update_item_references( start_number=min(oldIndex, self.context.getItemNumber())) return True
def __call__(self, object_uid, redirect=True): """ """ if not self.context._mayChangeAttendees(): raise Unauthorized # redirect can by passed by jQuery, in this case, we receive '0' or '1' redirect = boolean_value(redirect) vote_number = int(object_uid) item_uid = self.context.UID() meeting = self.context.getMeeting() if item_uid in meeting.item_votes: item_votes = meeting.item_votes[item_uid] assert self.context._voteIsDeletable(vote_number) vote_to_delete = item_votes[vote_number] if self.context.get_votes_are_secret(): originnal_vote_keys = [ str(vote_count) for vote_value, vote_count in vote_to_delete['votes'].items() ] originnal_vote_keys = "__".join(originnal_vote_keys) originnal_vote_values = [ vote_value for vote_value, vote_count in vote_to_delete['votes'].items() ] originnal_vote_values = "__".join(originnal_vote_values) fp_extras_pattern = 'item={0} vote_number={1} vote_label={2} vote_count={3} vote_values={4}' else: originnal_vote_keys = [ voter_uid for voter_uid in vote_to_delete['voters'] ] originnal_vote_keys = "__".join(originnal_vote_keys) originnal_vote_values = [ vote_value for vote_value in vote_to_delete['voters'].values() ] originnal_vote_values = "__".join(originnal_vote_values) fp_extras_pattern = 'item={0} vote_number={1} vote_label={2} voter_uids={3} vote_values={4}' # call clean_voters_linked_to with every values NOT_ENCODED_VOTE_VALUE # to liberate every values new_voters = vote_to_delete['voters'].copy() new_voters = { voter_uid: NOT_ENCODED_VOTE_VALUE for voter_uid, vote_value in new_voters.items() if vote_value != NOT_VOTABLE_LINKED_TO_VALUE } clean_voters_linked_to(self.context, meeting, vote_number, new_voters) # delete from meeting itemVote deleted_vote = meeting.item_votes[item_uid].pop(vote_number) # if deleted last existing vote (vote_number 0) remove context UID from meeting itemVotes if not meeting.item_votes[item_uid]: del meeting.item_votes[item_uid] # finish deletion label = deleted_vote['label'] or "" extras = fp_extras_pattern.format(repr(self.context), vote_number, label.encode('utf-8'), originnal_vote_keys, originnal_vote_values) fplog('delete_item_votes', extras=extras) # message api.portal.show_message(_( "Votes number ${vote_number} have been deleted for current item.", mapping={'vote_number': vote_number + 1}), request=self.request) self._finished = True
def _doApply(self): """ """ if not self.mayChangeAttendees(): raise Unauthorized # prepare Meeting.itemVotes compatible data # while datagrid used in an overlay, some <NO_VALUE> # wipeout self.votes from these values self.votes = [vote for vote in self.votes if isinstance(vote, dict)] data = {} data['label'] = self.label data['linked_to_previous'] = self.linked_to_previous data['votes'] = {} for vote in self.votes: data['votes'][vote['vote_value_id']] = vote['vote_count'] items_to_update = _itemsToUpdate( from_item_number=self.context.getItemNumber(relativeTo='meeting'), until_item_number=self.apply_until_item_number, meeting=self.meeting) updated = [] not_updated = [] for item_to_update in items_to_update: # set item secret vote if is_vote_updatable_for(self.context, item_to_update): self.meeting.set_item_secret_vote(item_to_update, data, self.vote_number) updated.append(item_to_update.getItemNumber(for_display=True)) else: not_updated.append( item_to_update.getItemNumber(for_display=True)) # finish vote_values = [vote['vote_value_id'] for vote in self.votes] vote_values = "__".join(vote_values) vote_count = [str(vote['vote_count']) for vote in self.votes] vote_count = "__".join(vote_count) first_item_number = items_to_update[0].getItemNumber(for_display=True) last_item_number = items_to_update[-1].getItemNumber(for_display=True) extras = 'item={0} vote_number={1} vote_values={2} vote_count={3} ' \ 'from_item_number={4} until_item_number={5}'.format( repr(self.context), self.vote_number, vote_values, vote_count, first_item_number, last_item_number) fplog('encode_item_secret_votes', extras=extras) if len(updated) == 1: api.portal.show_message( _("Votes have been encoded for current item."), request=self.request) else: api.portal.show_message(_( "Votes have been encoded for items \"${item_numbers}\".", mapping={'item_numbers': display_item_numbers(updated)}), request=self.request) # display items that could not be updated if not_updated: api.portal.show_message(_( "error_updating_votes_for_items", mapping={'item_numbers': display_item_numbers(not_updated)}), request=self.request, type="warning") self._finished = True