class IManageItemCertifiedSignatures(interface.Interface): item_certified_signatures = schema.Text( title=_(u"Item certified signatures to apply"), description=_(u"Enter the item certified signatures to be applied."), defaultFactory=item_certified_signatures_default, required=False, )
class IBaseAdviceInfoSchema(model.Schema): directives.mode(advice_uid='hidden') advice_uid = schema.TextLine(title=_(u"Advice uid"), description=_(u""), defaultFactory=advice_uid_default, required=False)
class IAdviceProposingGroupComment(IBaseAdviceInfoSchema): proposing_group_comment = schema.Text( title=_(u"Comment"), description=_(u""), defaultFactory=proposing_group_comment_default, required=False)
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
class IRedefineAttendeePosition(IBaseAttendee): position_type = schema.Choice( title=_(u"Position type to use"), description=_(u"Position type to use for the attendee on this item."), defaultFactory=position_type_default, required=True, vocabulary="PMAttendeeRedefinePositionTypes")
class IByeByeAttendee(IBaseAttendee): not_present_type = schema.Choice( title=_(u"Not present type"), description=_(u""), vocabulary= u"Products.PloneMeeting.vocabularies.not_present_type_vocabulary", required=True)
class WelcomeNonAttendeeForm(WelcomeAttendeeForm): """ """ label = _(u"nonattendee_welcome") schema = IWelcomeNonAttendee fields = field.Fields(IWelcomeNonAttendee) attendee_welcome_msg = _("Attendee has been set back attendee.") def _get_meeting_absent_attr(self): """ """ return self.meeting.item_non_attendees
class IAdviceRemoveInheritance(IBaseAdviceInfoSchema): form.widget('inherited_advice_action', RadioFieldWidget) inherited_advice_action = schema.Choice( title=_(u"Inherited advice action"), description=_(u""), vocabulary=SimpleVocabulary([ SimpleTerm('ask_locally', 'ask_locally', _(u"Remove inherited advice and ask advice locally")), SimpleTerm('remove', 'remove', _(u"Remove inherited advice")) ]), default="ask_locally", required=True)
class IRedefineSignatory(IBaseAttendee): position_type = schema.Choice( title=_(u"Signature position type"), description=_(u"Position type to use as label for the signature."), defaultFactory=position_type_default, required=True, vocabulary="PMPositionTypes") signature_number = schema.Choice( title=_(u"Signature number"), description=_(u""), required=True, vocabulary=u"Products.PloneMeeting.vocabularies.numbersvocabulary")
class IMeetingCategory(IConfigElement): """ MeetingCategory schema """ category_id = schema.TextLine( title=_(u"PloneMeeting_label_categoryId"), description=_("category_category_id_descr"), required=False, ) form.widget('using_groups', PMCheckBoxFieldWidget, multiple='multiple') using_groups = schema.List( title=_("PloneMeeting_label_usingGroups"), description=_("category_using_groups_descr"), value_type=schema.Choice( vocabulary="collective.contact.plonegroup.browser.settings." "SortedSelectedOrganizationsElephantVocabulary"), required=False, default=[], ) form.widget('category_mapping_when_cloning_to_other_mc', PMCheckBoxFieldWidget, multiple='multiple') category_mapping_when_cloning_to_other_mc = schema.List( title=_( "PloneMeeting_label_category_mapping_when_cloning_to_other_mc"), description=_("category_mapping_when_cloning_to_other_mc_descr"), value_type=schema.Choice( vocabulary="Products.PloneMeeting.content.category." "category_mapping_when_cloning_to_other_mc_vocabulary"), required=False, default=[], constraint=validate_category_mapping_when_cloning_to_other_mc, ) form.widget('groups_in_charge', PMCheckBoxFieldWidget, multiple='multiple') groups_in_charge = schema.List( title=_("PloneMeeting_label_groupsInCharge"), description=_("groups_in_charge_descr"), value_type=schema.Choice( vocabulary="collective.contact.plonegroup.browser.settings." "SortedSelectedOrganizationsElephantVocabulary"), required=False, default=[], ) form.widget('enabled', RadioFieldWidget) enabled = schema.Bool( title=_(u'Enabled?'), default=True, required=False, )
class IBaseAttendee(Interface): person_uid = schema.TextLine(title=_(u"Person uid"), description=_(u""), defaultFactory=person_uid_default, required=False) apply_until_item_number = schema.TextLine( title=_(u"Apply until item number"), description=_(u"Specify a number to which this will be applied. " u"Field default is current item number."), required=False, defaultFactory=apply_until_item_number_default, constraint=validate_apply_until_item_number, )
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 __call__(self, uids): """ """ wfTool = api.portal.get_tool('portal_workflow') # defer call to Meeting.update_item_references self.request.set('defer_Meeting_update_item_references', True) lowest_itemNumber = 0 objs = uuidsToObjects(uids, ordered=True) for obj in objs: try: wfTool.doActionFor(obj, 'present') except WorkflowException: # sometimes an item may not be presented, # even if shown in presentable items api.portal.show_message(_( 'Item \"${item_title}\" could not be presented!', mapping={'item_title': safe_unicode(obj.Title())}), request=self.request, type='warning') if not lowest_itemNumber or obj.getItemNumber( ) < lowest_itemNumber: lowest_itemNumber = obj.getItemNumber() self.request.set('defer_Meeting_update_item_references', False) # now we may call update_item_references self.context.update_item_references(start_number=lowest_itemNumber) msg = translate('present_several_items_done', domain='PloneMeeting', context=self.request) plone_utils = api.portal.get_tool('plone_utils') plone_utils.addPortalMessage(msg)
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 validate_new_poll_type(self, old_pollType, new_value): '''Make sure the new selected value can be selected.''' # make sure new_value exists factory = queryUtility( IVocabularyFactory, 'Products.PloneMeeting.vocabularies.polltypesvocabulary') if new_value not in factory(self.context): raise KeyError( "New value '{0}' does not correspond to a value of MeetingItem.pollType" .format(new_value)) if not self.context.adapted().mayChangePollType(): raise Unauthorized # if user tries to switch from a public pollType to a secret # and vice-versa, it can not be done if some votes are encoded is_switching_vote_mode = (old_pollType.startswith('secret') and not new_value.startswith('secret')) or \ (not old_pollType.startswith('secret') and new_value.startswith('secret')) if (new_value == 'no_vote' or is_switching_vote_mode) and \ self.context.get_item_votes(include_unexisting=False): can_not_switch_polltype_msg = _( 'can_not_switch_polltype_votes_encoded') return can_not_switch_polltype_msg
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 updateWidgets(self): # hide vote_number field self.fields['vote_number'].mode = HIDDEN_MODE # do not hide it, when hidding it, value is always True??? # this is hidden using CSS # self.fields['linked_to_previous'].mode = HIDDEN_MODE super(EncodeSecretVotesForm, self).updateWidgets() self.widgets['votes'].allow_delete = False self.widgets['votes'].allow_insert = False self.widgets['votes'].allow_reorder = False self.widgets['votes'].auto_append = False self.widgets['votes'].columns[0]['mode'] = HIDDEN_MODE for row in self.widgets['votes'].widgets: for wdt in row.subform.widgets.values(): if wdt.__name__ == 'vote_value_id': wdt.mode = HIDDEN_MODE elif wdt.__name__ == 'vote_value' and wdt.value: wdt.klass += " {0}".format(wdt.context['vote_value']) # disable apply_until_item_number when using several votes if len(self.context.get_item_votes()) > 1 or self.request.get( 'vote_number', 0) > 0: apply_until_item_number = self.widgets['apply_until_item_number'] apply_until_item_number.disabled = "disabled" apply_until_item_number.title = _( u"Not available when using several votes on same item.")
class BaseAdviceInfoForm(AutoExtensibleForm, form.EditForm): """ Base form make to work also when advice is not given. """ label = _(u"") description = u'' schema = IBaseAdviceInfoSchema ignoreContext = True # don't use context to get widget data def __init__(self, context, request): self.context = context self.request = request self.label = translate(self.label, domain='PloneMeeting', context=self.request) def _advice_infos(self, data, context=None): '''Init @@advices-icons-infos and returns it.''' context = context or self.context # check if may remove inherited advice advice_infos = context.unrestrictedTraverse('@@advices-icons-infos') # initialize advice_infos advice_data = context.getAdviceDataFor(context, data['advice_uid']) advice_infos(context._shownAdviceTypeFor(advice_data)) advice_infos._initAdviceInfos(data['advice_uid']) return advice_infos
def updateWidgets(self): # hide vote_number field self.fields['vote_number'].mode = HIDDEN_MODE # add a css class corresponding to group of held positions groups = _build_voting_groups(self.context) # do not hide it, when hidding it, value is always True??? # this is hidden using CSS # self.fields['linked_to_previous'].mode = HIDDEN_MODE super(EncodeVotesForm, self).updateWidgets() self.widgets['votes'].allow_delete = False self.widgets['votes'].allow_insert = False self.widgets['votes'].allow_reorder = False self.widgets['votes'].auto_append = False self.widgets['votes'].columns[0]['mode'] = HIDDEN_MODE for row in self.widgets['votes'].widgets: if row.subform.context is None: continue voter_uid = row.subform.context['voter_uid'] group_id = [ group_id for group_id, values in groups.items() if voter_uid in values['uids'] ] if group_id: row.addClass(group_id[0]) for wdt in row.subform.widgets.values(): if wdt.__name__ == 'voter_uid': wdt.mode = HIDDEN_MODE # disable apply_until_item_number when using several votes if len(self.context.get_item_votes()) > 1 or self.request.get( 'vote_number', 0) > 0: apply_until_item_number = self.widgets['apply_until_item_number'] apply_until_item_number.disabled = "disabled" apply_until_item_number.title = _( u"Not available when using several votes on same item.")
class WelcomeAttendeeForm(BaseAttendeeForm): """ """ label = _(u"person_welcome") schema = IWelcomeAttendee fields = field.Fields(IWelcomeAttendee) attendee_welcome_msg = _("Attendee has been set back present.") def _get_meeting_absent_attr(self): """ """ attr = None if self.person_uid in self.context.get_item_absents(): attr = self.meeting.item_absents elif self.person_uid in self.context.get_item_excused(): attr = self.meeting.item_excused else: attr = self.meeting.item_non_attendees return attr 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
class ByeByeNonAttendeeForm(ByeByeAttendeeForm): """ """ label = _(u'nonattendee_byebye') schema = IByeByeNonAttendee fields = field.Fields(IByeByeNonAttendee) NOT_PRESENT_MAPPING = {'non_attendee': 'item_non_attendees'} not_present_type = 'non_attendee'
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 validate_apply_until_item_number(value): '''This method does validate the 'apply_until_item_number' field. It will check that given number is a number among existing item numbers using a correct format.''' try: _itemNumber_to_storedItemNumber(value) except ValueError: raise interface.Invalid(_(u'Please provide a valid number.')) return True
class ISecretVote(Interface): vote_value_id = schema.Choice( title=u'Vote value id', required=False, vocabulary= "Products.PloneMeeting.vocabularies.usedvotevaluesvocabulary", ) widget('vote_value', PMSelectReadonlyWidget) vote_value = schema.Choice( title=_(u"Vote value"), required=False, vocabulary= "Products.PloneMeeting.vocabularies.usedvotevaluesvocabulary", ) widget('vote_count', PMNumberFieldWidget) vote_count = schema.Int(title=_(u"Vote count"), required=False)
class IEncodeVotes(Interface): person_uid = schema.TextLine(title=_(u"Person uid"), description=_(u""), defaultFactory=person_uid_default, required=False) vote_number = schema.Int(title=_(u"Vote number"), description=_(u""), defaultFactory=vote_number_default, required=False) linked_to_previous = schema.Bool( title=_(u"Linked to previous"), description=_( u"This will link this vote with the previous one, " u"if so, voter may only vote for one of the linked votes."), defaultFactory=linked_to_previous_default, required=False) votes = schema.List(title=u'Votes', value_type=DictRow(title=u'Votes', schema=IVote), defaultFactory=votes_default, required=True) label = schema.TextLine( title=_(u"Label"), description=_(u"Free label that will identify the vote, " u"useful when several votes are defined on an item. " u"Leave empty if not used."), defaultFactory=label_default, required=False) apply_until_item_number = schema.TextLine( title=_(u"Apply until item number"), description= _(u"If you specify a number, the values entered here above will be applied from current " u"item to the item number entered. Leave empty to only apply for current item." ), required=False, constraint=validate_apply_until_item_number, )
class IManageItemSignatures(interface.Interface): item_signatures = schema.Text( title=_(u"Item signatures to apply"), description= _(u"Enter the item signatures to be applied. By default, the value of the field is what is " u"defined on the meeting. If you do not change this value, nothing will be applied on the item. " u"If you already edited this field before and you want to fallback to meeting value, " u"remove the entire value."), defaultFactory=item_signatures_default, required=False, ) apply_until_item_number = schema.TextLine( title=_(u"Apply until item number"), description= _(u"If you specify a number, the values entered here above will be applied from current " "item to the item number entered. Leave empty to only apply for current item." ), required=False, constraint=validate_apply_until_item_number, )
def validate(self, value): selected_org_uids = get_organizations(only_selected=True, the_objects=False) removed_orgs_uids = set(selected_org_uids).difference(value) # check that removed orgs are not used as groups_in_charge of an organization orgs = get_organizations(only_selected=False, the_objects=True) for org in orgs: if removed_orgs_uids.intersection(org.groups_in_charge): msgid = "can_not_unselect_plone_group_org" msg = _(msgid, mapping={'org_url': org.absolute_url()}) raise Invalid(msg)
def manage_label_assembly(the_form): ''' Depending on the fact that we use 'assembly' alone or 'assembly, excused, absents', we will translate the 'assembly' label a different way. ''' widgets = getattr(the_form, 'w', None) or the_form.widgets if 'assembly' in widgets: if 'assembly_excused' in widgets or \ 'assembly_absents' in widgets: widgets['assembly'].label = _('title_attendees')
class IManageItemAssembly(interface.Interface): item_assembly = schema.Text( title=_(u"Item assembly to apply"), description=_(USING_ONLY_ASSEMBLY_MSGID), defaultFactory=item_assembly_default, required=False, constraint=validate_item_assembly) item_excused = schema.Text( title=_(u"Item excused to apply"), description=_(u"Enter the item excused to be applied. " u"By default, the value of the field is what is defined on the meeting. " u"If you do not change this value, nothing will be applied on the item. " u"If you already edited this field before and you want to fallback to meeting value, " u"remove the entire value."), defaultFactory=item_excused_default, required=False,) item_absents = schema.Text( title=_(u"Item absents to apply"), description=_(u"Enter the item absents to be applied. " u"By default, the value of the field is what is defined on the meeting. " u"If you do not change this value, nothing will be applied on the item. " u"If you already edited this field before and you want to fallback to meeting value, " u"remove the entire value."), defaultFactory=item_absents_default, required=False,) item_guests = schema.Text( title=_(u"Item guests to apply"), description=_(u"Enter the item guests to be applied. " u"By default, the value of the field is what is defined on the meeting. " u"If you do not change this value, nothing will be applied on the item. " u"If you already edited this field before and you want to fallback to meeting value, " u"remove the entire value."), defaultFactory=item_guests_default, required=False,) apply_until_item_number = schema.TextLine( title=_(u"Apply until item number"), description=_(u"If you specify a number, the values entered here above will be applied from current " u"item to the item number entered. Leave empty to only apply for current item."), required=False, constraint=validate_apply_until_item_number,)