def edit(self): """Updates the title of the agendaitem, with the one given by the request parameter `title`. """ self.require_agendalist_editable() title = safe_unicode(self.request.get('title')) description = safe_unicode(self.request.get('description')) if not title: return JSONResponse(self.request).error( _('agenda_item_update_empty_string', default=u"Agenda Item title must not be empty.")).proceed( ).dump() 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) self.agenda_item.set_description(description) 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() except SablonProcessingFailed: return JSONResponse(getRequest()).error( _('Error while processing Sablon template'), status=500).dump()
def save(self): """Save setting change """ kind = self.request.form['kind'] mail = json.loads(self.request.form['mail']) badge = json.loads(self.request.form['badge']) digest = json.loads(self.request.form['digest']) if ALIASES.get(kind): kinds = ALIASES.get(kind) else: kinds = (kind, ) for kind in kinds: try: setting = self.get_or_create_setting(kind) except InvalidUser: # User with no entry in the ogds, probably zopemaster. msg = "Cannot save setting for this user as he is not in the ogds" return JSONResponse(self.request).error(msg).proceed().dump() setting.mail_notification_roles = mail setting.badge_notification_roles = badge setting.digest_notification_roles = digest return JSONResponse(self.request).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 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 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 save_user_setting(self): """Save global configuration change """ try: self.assert_user_in_ogds() except InvalidUser: # User with no entry in the ogds, probably zopemaster. msg = "Cannot save configuration for this user as he is not in the ogds" return JSONResponse(self.request).error(msg).proceed().dump() config_name = self.request.form['config_name'] value = json.loads(self.request.form['value']) UserSettings.save_setting_for_user(api.user.get_current().getId(), config_name, value) return JSONResponse(self.request).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) 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 reset_user_setting(self): """Reset a personal configuration """ config_name = self.request.form['config_name'] default = self.get_default_setting_value(config_name) UserSettings.save_setting_for_user(api.user.get_current().getId(), config_name, default) return JSONResponse(self.request).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 schedule_paragraph(self): """Schedule the given Paragraph (request parameter `title`) for the current meeting. """ self.require_agendalist_editable() title = safe_unicode(self.request.get('title')) description = safe_unicode(self.request.get('description')) 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, description=description) return JSONResponse(self.request).info( _('paragraph_added', default=u"Paragraph successfully added.")).proceed().dump()
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 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 __call__(self): """Schedule the current proposal on the current meeting. """ proposals = map(lambda proposal: { 'link': proposal.get_submitted_link(include_icon=False), 'description': proposal.get_submitted_description(), 'schedule_url': self.schedule_url(proposal)}, self.context.get_unscheduled_proposals()) return JSONResponse(self.request).data(items=proposals).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_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`. """ 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 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 generate_excerpt(self): """Generate an excerpt of an agenda item and store it in the meeting dossier. """ self.require_editable() title = safe_unicode(self.request.form['excerpt_title']) self.agenda_item.generate_excerpt(title=title) return (JSONResponse(self.request).info( _('excerpt_generated', default=u'Excerpt was created successfully.')).proceed().dump())
def schedule_text(self): """Schedule the given Text (request parameterd `title` and description) for the current meeting. """ self.require_agendalist_editable() title = safe_unicode(self.request.get('title')) description = safe_unicode(self.request.get('description')) if not title: return JSONResponse(self.request).error( _('empty_proposal', default=u"Proposal must not be empty.")).proceed().dump() template = safe_unicode(self.request.get('template_id')) self.meeting.schedule_ad_hoc(title, template_id=template, description=description) return JSONResponse(self.request).info( _('text_added', default=u"Text successfully added.")).proceed().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': self._get_activity_class(kind), 'kind': kind, 'type_id': group.get('id') } activities.append( self.add_values(kind, item, group.get('roles'))) configurations = [] for config in GLOBAL_CONFIGURATIONS: title = translate(ACTIVITY_TRANSLATIONS[config.get('id')]['title'], context=self.request) help_text = translate( ACTIVITY_TRANSLATIONS[config.get('id')]['help_text'], context=self.request) default = self.get_default_setting_value(config.get('id')) value = UserSettings.get_setting_for_user( api.user.get_current().getId(), config.get('id')) if value == default: setting_type = 'default' else: setting_type = 'personal' configurations.append({ 'id': config.get('id'), 'title': title, 'help_text': help_text, 'value': value, 'setting_type': setting_type }) return JSONResponse(self.request).data( activities=activities, configurations=configurations, translations=self.get_role_translations()).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 return_excerpt(self): """Return an excerpt for a proposal to the dossier the proposal originated from. """ doc_uuid = self.request.get('document') if not doc_uuid: raise BadRequest("No excerpt document provided.") document = self._get_excerpt_doc_by_uuid(doc_uuid) if not document: raise NotFound( "Could not find excerpt document {}".format(doc_uuid)) self.agenda_item.return_excerpt(document) return (JSONResponse(self.request).info( _('excerpt_returned', default=u'Excerpt was returned to proposer.')).proceed().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 _checkin_proposal_document_before_deciding(self): 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 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 list(self): """Returns a json dict with the following structure. `participations`: a list of json representation of the current contexts participations. It sliced to the default tabbedview batch size depending on the `show_all` request_flag. `has_more`: a boolean value if the list is sliced. `show_all_label`: label for the show all link. """ data = {} query = self.get_particpations_query().order_by( desc(Participation.participation_id)) total = query.count() if self.request.get('show_all') != 'true': query = query.limit(self.get_slice_size()) data['participations'] = self._serialize(query) data['has_more'] = total > len(data['participations']) data['show_all_label'] = self.get_show_all_label(total) return JSONResponse(self.request).data(**data).dump()
def __call__(self): transfer_number = self.request.form['transfer_number'] IDisposition(self.context).transfer_number = transfer_number return JSONResponse(self.request).proceed().dump()
class TestUnitJSONResponse(IntegrationTestCase): 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)
def setUp(self): super(TestUnitJSONResponse, self).setUp() self.response = JSONResponse(self.request) self.info_message = _('infomessage') self.warning_message = _('warningmessage') self.error_message = _('errormessage')