def edit(self): """Updates the title of the agendaitem, with the one given by the request parameter `title`. """ self.require_agendalist_editable() title = self.request.get('title') if not title: return JSONResponse(self.request).error( _('agenda_item_update_empty_string', default=u"Agenda Item title must not be empty.")).proceed( ).dump() title = title.decode('utf-8') if self.agenda_item.has_proposal: if len(title) > ISubmittedProposal['title'].max_length: return JSONResponse(self.request).error( _('agenda_item_update_too_long_title', default=u"Agenda Item title is too long.")).proceed( ).dump() self.agenda_item.set_title(title) return JSONResponse(self.request).info( _('agenda_item_updated', default=u"Agenda Item updated.")).proceed().dump()
def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except (WrongAgendaItemState, CannotExecuteTransition): return JSONResponse(getRequest()).error(_( u'invalid_agenda_item_state', default=u'The agenda item is in an invalid state for ' 'this action.'), status=403).dump() except Forbidden: return JSONResponse(getRequest()).error(_( u'editing_not_allowed', default=u'Editing is not allowed.'), status=403).dump() except MissingMeetingDossierPermissions: return JSONResponse(getRequest()).error(_( 'error_no_permission_to_add_document', default=u'Insufficient privileges to add a ' u'document to the meeting dossier.'), status=403).dump() except MissingAdHocTemplate: return JSONResponse(getRequest()).error(_( 'missing_ad_hoc_template', default=u"No ad-hoc agenda-item template has been " u"configured."), status=501).dump()
def schedule_text(self): """Schedule the given Text (request parameter `title`) for the current meeting. """ self.check_editable() title = safe_unicode(self.request.get('title')) if not title: return JSONResponse(self.request).error( _('empty_proposal', default=u"Proposal must not be empty.")).proceed().dump() if is_word_meeting_implementation_enabled(): try: self.meeting.schedule_ad_hoc(title) except MissingAdHocTemplate: return JSONResponse(self.request).error( _('missing_ad_hoc_template', default=u"No ad-hoc agenda-item template has been " u"configured.")).remain().dump() except MissingMeetingDossierPermissions: return JSONResponse(self.request).error( _('error_no_permission_to_add_document', default=u'Insufficient privileges to add a' u' document to the meeting dossier.')).remain().dump() else: self.meeting.schedule_text(title) return JSONResponse(self.request).info( _('text_added', default=u"Text successfully added.")).proceed().dump()
def decide(self): """Decide the current agendaitem and move the meeting in the held state. """ self.require_editable() meeting_state = self.meeting.get_state() error_response = self._checkin_proposal_document_before_deciding() if error_response: return error_response self.agenda_item.decide() response = JSONResponse(self.request) if self.agenda_item.has_proposal: response.info( _(u'agenda_item_proposal_decided', default=u'Agenda Item decided and excerpt generated.')) else: response.info( _(u'agenda_item_decided', default=u'Agenda Item decided.')) if meeting_state != self.meeting.get_state(): response.redirect(self.context.absolute_url()) msg = _( u'agenda_item_meeting_held', default= u"Agendaitem has been decided and the meeting has been held.") api.portal.show_message(message=msg, request=self.request, type='info') return response.dump()
def decide(self): """Decide the current agendaitem and move the meeting in the held state. """ meeting_state = self.meeting.get_state() if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") self.agenda_item.decide() response = JSONResponse(self.request) if self.agenda_item.has_proposal: response.info( _(u'agenda_item_proposal_decided', default=u'Agenda Item decided and excerpt generated.')) else: response.info( _(u'agenda_item_decided', default=u'Agenda Item decided.')) if meeting_state != self.meeting.get_state(): response.redirect(self.context.absolute_url()) msg = _( u'agenda_item_meeting_held', default= u"Agendaitem has been decided and the meeting has been held.") api.portal.show_message(message=msg, request=self.request, type='info') return response.dump()
def update(self): label = to_safe_html(self.request.get('label', self.mailaddress.label)) mailaddress = to_safe_html(self.request.get('mailaddress', self.mailaddress.address)) error_msg = self._validate(label, mailaddress) if error_msg: return JSONResponse(self.request).error(error_msg).dump() self.mailaddress.update(label=label, address=mailaddress) return JSONResponse(self.request).info( _('email_address_updated', default=u"Email address updated.")).proceed().dump()
def decide(self): """Decide the current agendaitem and move the meeting in the held state. """ meeting_state = self.meeting.get_state() if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") self.agenda_item.decide() response = JSONResponse(self.request) if self.agenda_item.has_proposal: response.info( _(u'agenda_item_proposal_decided', default=u'Agenda Item decided and excerpt generated.')) else: response.info(_(u'agenda_item_decided', default=u'Agenda Item decided.')) if meeting_state != self.meeting.get_state(): response.redirect(self.context.absolute_url()) msg = _(u'agenda_item_meeting_held', default=u"Agendaitem has been decided and the meeting has been held.") api.portal.show_message(message=msg, request=self.request, type='info') return response.dump()
def schedule_text(self): """Schedule the given Text (request parameter `title`) for the current meeting. """ self.check_editable() title = self.request.get('title') if not title: return JSONResponse(self.request).error( _('empty_proposal', default=u"Proposal must not be empty.")).proceed().dump() self.meeting.schedule_text(title) return JSONResponse(self.request).info( _('text_added', default=u"Text successfully added.")).proceed().dump()
def change_presence(self): """Change the presence of a participant. """ response = JSONResponse(self.request) present = self.request.form.get('present', None) member = self.get_member() if not present or not member: return response.error(MSG_SAVE_FAILURE).remain().dump() present = json.loads(present) if present and member not in self.meeting.participants: self.meeting.participants.append(member) elif not present and member in self.meeting.participants: self.meeting.participants.remove(member) return response.proceed().dump()
def schedule_paragraph(self): """Schedule the given Paragraph (request parameter `title`) for the current meeting. """ self.require_agendalist_editable() title = self.request.get('title') if not title: return JSONResponse(self.request).error( _('empty_paragraph', default=u"Paragraph must not be empty.")).proceed().dump() self.meeting.schedule_text(title, is_paragraph=True) return JSONResponse(self.request).info( _('paragraph_added', default=u"Paragraph successfully added.") ).proceed().dump()
def list(self): """Returns json list of all agendaitems for the current context (meeting). """ return JSONResponse( self.request).data(items=self._get_agenda_items()).dump()
def list(self): """Returns settings for the current user. """ activities = [] for group in ACTIVITY_GROUPS: for kind in group.get('activities'): kind_title = translate(ACTIVITY_TRANSLATIONS[kind], context=self.request) item = { 'kind_title': kind_title, 'edit_mode': True, 'css_class': ResponseDescription.get(transition=kind).css_class, 'kind': kind, 'type_id': group.get('id') } activities.append( self.add_values(kind, item, group.get('roles'))) return JSONResponse(self.request).data( activities=activities, translations=self.get_role_translations()).dump()
def _checkin_proposal_document_before_deciding(self): if not is_word_meeting_implementation_enabled(): # old implementation: there is no proposal document return if not self.agenda_item.has_proposal: # no proposal => no document to checkin return submitted_proposal = self.agenda_item.proposal.resolve_submitted_proposal( ) document = submitted_proposal.get_proposal_document() checkout_manager = getMultiAdapter((document, self.request), ICheckinCheckoutManager) if checkout_manager.get_checked_out_by() is None: # document is not checked out return if not checkout_manager.is_checkin_allowed(): return JSONResponse(self.request).error( _('agenda_item_cannot_decide_document_checked_out', default=u'Cannot decide agenda item: someone else has' u' checked out the document.')).remain().dump() checkout_manager.checkin()
def wrapper(self, *args, **kwargs): if not self.meeting.is_editable(): return (JSONResponse(self.request) .error(MSG_NOT_ALLOWED_TO_CHANGE_MEETING) .remain() .dump()) return func(self, *args, **kwargs)
def change_role(self): """Change the role of a participant. """ response = JSONResponse(self.request) role = self.request.form.get('role', None) member = self.get_member() if role is None or member is None: return response.error(MSG_SAVE_FAILURE).remain().dump() if self.meeting.presidency == member: self.meeting.presidency = None if self.meeting.secretary == member: self.meeting.secretary = None if role == 'presidency': self.meeting.presidency = member elif role == 'secretary': self.meeting.secretary = member return response.proceed().dump()
def __call__(self): """Schedule the current proposal on the current meeting. """ proposals = map(lambda proposal: { 'title': proposal.resolve_submitted_proposal().title, 'submitted_proposal_url': proposal.get_submitted_url(), 'schedule_url': self.schedule_url(proposal)}, self.context.get_unscheduled_proposals()) return JSONResponse(self.request).data(items=proposals).dump()
def add(self): label = to_safe_html(self.request.get('label')) mailaddress = to_safe_html(self.request.get('mailaddress')) error_msg = self._validate(label, mailaddress) if error_msg: return JSONResponse(self.request).error(error_msg).dump() mail_object = MailAddress(label=label, address=mailaddress, contact_id=self.context.model.person_id) self.session.add(mail_object) msg = _(u'info_mailaddress_created', u'The email address was created successfully') return JSONResponse(self.request).info(msg).proceed().dump()
def revise(self): """Revise the current agendaitem. Set the workflow state to decided to indicate that editing is no longer possible. """ self.require_editable() self.agenda_item.revise() return JSONResponse(self.request).info( _(u'agenda_item_revised', default=u'Agenda Item revised successfully.')).dump()
def reopen(self): """Reopen the current agendaitem. Set the workflow state to revision to indicate that editing is possible again. """ self.require_editable() self.agenda_item.reopen() return JSONResponse(self.request).info( _(u'agenda_item_reopened', default=u'Agenda Item successfully reopened.')).dump()
def schedule_text(self): """Schedule the given Text (request parameter `title`) for the current meeting. """ self.require_agendalist_editable() title = safe_unicode(self.request.get('title')) if not title: return JSONResponse(self.request).error( _('empty_proposal', default=u"Proposal must not be empty.")).proceed().dump() if is_word_meeting_implementation_enabled(): self.meeting.schedule_ad_hoc(title) else: self.meeting.schedule_text(title) return JSONResponse(self.request).info( _('text_added', default=u"Text successfully added.")).proceed().dump()
def update_order(self): """Updates the order of the agendaitems. The new sortOrder is expected in the request parameter `sortOrder`. """ self.require_agendalist_editable() self.meeting.reorder_agenda_items( json.loads(self.request.get('sortOrder'))) return JSONResponse(self.request).info( _('agenda_item_order_updated', default=u"Agenda Item order updated.")).dump()
def generate_excerpt(self): """Generate an excerpt of an agenda item and store it in the meeting dossier. """ self.require_editable() self.agenda_item.generate_excerpt( title=self.request.form['excerpt_title']) return (JSONResponse(self.request).info( _('excerpt_generated', default=u'Excerpt was created successfully.')).proceed().dump())
def delete(self): """Unschedule the current agenda_item. If the agenda_item has no proposal, the agenda_item gets deleted. If there is a proposal related, the proposal is unscheduled. """ self.require_agendalist_editable() self.agenda_item.remove() return JSONResponse(self.request).info( _(u'agenda_item_deleted', default=u'Agenda Item Successfully deleted')).dump()
def render(self): if self._has_write_conflict: msg = _(u'message_write_conflict', default='Your changes were not saved, the protocol has ' 'been modified in the meantime.') return JSONResponse(self.request).data(hasConflict=True).dump() elif self._is_locked_by_another_user: msg = _(u'message_locked_by_another_user', default='Your changes were not saved, the protocol is ' 'locked by ${username}.', mapping={'username': self.get_lock_creator_user_name()}) return JSONResponse(self.request).error(msg).dump() elif self._has_successfully_saved: api.portal.show_message( _(u'message_changes_saved', default='Changes saved'), self.request) return JSONResponse(self.request).redirect(self.nextURL()).dump() return self.template()
def revise(self): """Revise the current agendaitem. Set the workflow state to decided to indicate that editing is no longer possible. """ if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") self.agenda_item.revise() return JSONResponse(self.request).info( _(u'agenda_item_revised', default=u'Agenda Item revised successfully.')).dump()
def schedule_proposal(self): """Schedule the current proposal on the current meeting. """ self.require_editable() proposal = Proposal.get(self.proposal_id) if not proposal: raise NotFound self.meeting.schedule_proposal(proposal) return JSONResponse(self.request).info( _('Scheduled Successfully')).proceed().dump()
def update_order(self): """Updates the order of the agendaitems. The new sortOrder is expected in the request parameter `sortOrder`. """ if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") self.context.model.reorder_agenda_items( json.loads(self.request.get('sortOrder'))) return JSONResponse(self.request).info( _('agenda_item_order_updated', default=u"Agenda Item order updated.")).dump()
def generate_excerpt(self): """Generate an excerpt of an agenda item and store it in the meeting dossier. """ if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") if not self.agenda_item.can_generate_excerpt(): raise Forbidden('Generating excerpt is not allowed in this state.') try: self.agenda_item.generate_excerpt( title=self.request.form['excerpt_title']) except MissingMeetingDossierPermissions: return (JSONResponse(self.request).error( _('error_no_permission_to_add_document', default=u'Insufficient privileges to add a' u' document to the meeting dossier.')).remain().dump()) return (JSONResponse(self.request).info( _('excerpt_generated', default=u'Excerpt was created successfully.')).proceed().dump())
def delete(self): """Unschedule the current agenda_item. If the agenda_item has no proposal, the agenda_item gets deleted. If there is a proposal related, the proposal is unscheduled. """ if not self.context.model.is_editable(): raise Unauthorized("Editing is not allowed") self.agenda_item.remove() return JSONResponse(self.request).info( _(u'agenda_item_deleted', default=u'Agenda Item Successfully deleted')).dump()
def reset(self): """Reset a personal setting """ kind = self.request.form['kind'] if ALIASES.get(kind): kinds = ALIASES.get(kind) else: kinds = (kind, ) for kind in kinds: setting = self.get_setting(kind) create_session().delete(setting) return JSONResponse(self.request).proceed().dump()
def __call__(self): transition = self.request.get('transition') if not self.is_valid_transition(transition): raise NotFound self.execute_transition(transition) msg = _('label_transition_executed', default='Transition ${transition} executed', mapping={ 'transition': Meeting.workflow.transitions.get(transition).title }) return JSONResponse(self.request).redirect( self.model.get_url()).info(msg).dump()
def __call__(self): transition = self.request.get('transition') response = JSONResponse(self.request) errors = self.get_transition_validation_errors(transition) if errors: map(response.error, errors) response.remain() elif not self.is_valid_transition(transition): raise BadRequest() else: self.execute_transition(transition) response.info(_('label_transition_executed', default='Transition ${transition} executed', mapping={'transition': self.model.workflow.transitions.get( transition).title})) response.redirect(self.model.get_url()) return response.dump()
def edit_document(self): """Checkout and open the document with office connector. """ self.require_editable() document = self.agenda_item.resolve_document() checkout_manager = getMultiAdapter((document, self.request), ICheckinCheckoutManager) response = JSONResponse(self.request) if not checkout_manager.is_checked_out_by_current_user() \ and not checkout_manager.is_checkout_allowed(): response.remain().error( _(u'document_checkout_not_allowed', default=u'You are not allowed to checkout the document.')) else: url = document.checkout_and_get_office_connector_url() response.proceed().data(officeConnectorURL=url) return response.dump()
def decide(self): """Decide the current agendaitem and move the meeting in the held state. """ self.require_editable() meeting_state = self.meeting.get_state() error_response = self._checkin_proposal_document_before_deciding() if error_response: return error_response self.agenda_item.decide() response = JSONResponse(self.request) response.info(_(u'agenda_item_decided', default=u'Agenda Item decided.')) if meeting_state != self.meeting.get_state(): response.redirect(self.context.absolute_url()) msg = _(u'agenda_item_meeting_held', default=u"Agendaitem has been decided and the meeting has been held.") api.portal.show_message(message=msg, request=self.request, type='info') return response.dump()
def setUp(self): super(TestUnitJSONResponse, self).setUp() self.response = JSONResponse(self.request) self.info_message = _('infomessage') self.error_message = _('errormessage')
def __call__(self): json_response = JSONResponse(self.request) self.check_consistency(json_response) return json_response.dump()
class TestUnitJSONResponse(FunctionalTestCase): def setUp(self): super(TestUnitJSONResponse, self).setUp() self.response = JSONResponse(self.request) self.info_message = _('infomessage') self.warning_message = _('warningmessage') self.error_message = _('errormessage') def test_empty_jsonresponse(self): self.assertEqual(self.response.dump(), '{}') def test_info_message(self): self.assertEqual(self.response.info(self.info_message).dump(), json.dumps({'messages': [ {'messageClass': 'info', 'messageTitle': 'Information', 'message': 'infomessage', } ]} )) def test_warning_message(self): self.assertEqual(self.response.warning(self.warning_message).dump(), json.dumps({'messages': [ {'messageClass': 'warning', 'messageTitle': 'Warning', 'message': 'warningmessage', } ]} )) def test_error_message(self): self.assertEqual(self.response.error(self.error_message).dump(), json.dumps({'messages': [ {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', } ]} )) def test_multiple_messages(self): self.assertEqual(self.response.error(self.error_message) .info(self.info_message) .error(self.error_message).dump(), json.dumps({'messages': [ {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', }, {'messageClass': 'info', 'messageTitle': 'Information', 'message': 'infomessage', }, {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', } ]} )) def test_custom_data(self): self.assertEqual(self.response.data(name='peter').dump(), json.dumps({'name': 'peter'})) def test_multiple_custom_data(self): self.assertEqual(self.response.data(name='peter', foo=123, bar=None).dump(), json.dumps({'name': 'peter', 'foo': 123, 'bar': None})) def test_protected_data_throws_assertion_error(self): with self.assertRaises(AssertionError): self.response.data(messages='peter') with self.assertRaises(AssertionError): self.response.data(proceed='peter') def test_proceed(self): self.assertEqual(self.response.proceed().dump(), json.dumps({'proceed': True})) def test_remain(self): self.assertEqual(self.response.remain().dump(), json.dumps({'proceed': False})) def test_full_response(self): self.assertEqual(self.response.data(name='peter') .info(self.info_message) .error(self.error_message) .proceed() .dump(), json.dumps({'messages': [ {'messageTitle': 'Information', 'message': 'infomessage', 'messageClass': 'info'}, {'messageTitle': 'Error', 'message': 'errormessage', 'messageClass': 'error'}], 'name': 'peter', 'proceed': True} )) def test_dump_disables_caching_by_default(self): # By default we disable chaing of all responses. # This is especially important for IE 11 support. self.response.remain().dump() self.assertEquals( {'content-type': 'application/json', 'cache-control': 'no-store', 'pragma': 'no-cache', 'expires': '0'}, self.request.response.headers) def test_dump_without_disabling_caches(self): # Dump can optionally be told to not send no-caching headers. self.response.remain().dump(no_cache=False) self.assertEquals( {'content-type': 'application/json'}, self.request.response.headers)
class TestUnitJSONResponse(FunctionalTestCase): def setUp(self): super(TestUnitJSONResponse, self).setUp() self.response = JSONResponse(self.request) self.info_message = _('infomessage') self.error_message = _('errormessage') def test_empty_jsonresponse(self): self.assertEqual(self.response.dump(), '{}') def test_info_message(self): self.assertEqual(self.response.info(self.info_message).dump(), json.dumps({'messages': [ {'messageClass': 'info', 'messageTitle': 'Information', 'message': 'infomessage', } ]} )) def test_error_message(self): self.assertEqual(self.response.error(self.error_message).dump(), json.dumps({'messages': [ {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', } ]} )) def test_multiple_messages(self): self.assertEqual(self.response.error(self.error_message) .info(self.info_message) .error(self.error_message).dump(), json.dumps({'messages': [ {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', }, {'messageClass': 'info', 'messageTitle': 'Information', 'message': 'infomessage', }, {'messageClass': 'error', 'messageTitle': 'Error', 'message': 'errormessage', } ]} )) def test_custom_data(self): self.assertEqual(self.response.data(name='peter').dump(), json.dumps({'name': 'peter'})) def test_multiple_custom_data(self): self.assertEqual(self.response.data(name='peter', foo=123, bar=None).dump(), json.dumps({'name': 'peter', 'foo': 123, 'bar': None})) def test_protected_data_throws_assertion_error(self): with self.assertRaises(AssertionError): self.response.data(messages='peter') with self.assertRaises(AssertionError): self.response.data(proceed='peter') def test_proceed(self): self.assertEqual(self.response.proceed().dump(), json.dumps({'proceed': True})) def test_remain(self): self.assertEqual(self.response.remain().dump(), json.dumps({'proceed': False})) def test_full_response(self): self.assertEqual(self.response.data(name='peter') .info(self.info_message) .error(self.error_message) .proceed() .dump(), json.dumps({'messages': [ {'messageTitle': 'Information', 'message': 'infomessage', 'messageClass': 'info'}, {'messageTitle': 'Error', 'message': 'errormessage', 'messageClass': 'error'}], 'name': 'peter', 'proceed': True} ))