def update_review(review, review_data, questions_data): paper = review.revision.paper event = paper.event changes = review.populate_from_dict(review_data) review.modified_dt = now_utc() log_fields = {} for question in event.cfp.get_questions_for_review_type(review.type): field_name = 'question_{}'.format(question.id) rating = question.get_review_rating(review, allow_create=True) old_value = rating.value rating.value = int(questions_data[field_name]) if old_value != rating.value: changes[field_name] = (old_value, rating.value) log_fields[field_name] = { 'title': question.text, 'type': 'number' } db.session.flush() notify_paper_review_submission(review) logger.info("Paper review %r modified", review) log_fields.update({ 'proposed_action': 'Action', 'comment': 'Comment' }) event.log(EventLogRealm.management, EventLogKind.change, 'Papers', 'Review for paper {} modified'.format(paper.verbose_title), session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_event_protection(event, data): assert set(data.viewkeys()) <= { 'protection_mode', 'own_no_access_contact', 'access_key', 'visibility' } changes = event.populate_from_dict(data) db.session.flush() signals.event.updated.send(event, changes=changes) logger.info('Protection of event %r updated with %r by %r', event, data, session.user) if changes: log_fields = { 'protection_mode': 'Protection mode', 'own_no_access_contact': 'No access contact', 'access_key': { 'title': 'Access key', 'type': 'string' }, 'visibility': { 'title': 'Visibility', 'type': 'string', 'convert': lambda changes: [_format_visibility(event, x) for x in changes] } } event.log(EventLogRealm.management, EventLogKind.change, 'Event', 'Protection updated', session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_review(review, review_data, questions_data): paper = review.revision.paper event = paper.event changes = review.populate_from_dict(review_data) review.modified_dt = now_utc() log_fields = {} for question in event.cfp.get_questions_for_review_type(review.type): field_name = 'question_{}'.format(question.id) rating = question.get_review_rating(review, allow_create=True) old_value = rating.value rating.value = questions_data[field_name] if old_value != rating.value: field_type = question.field_type changes[field_name] = (question.field.get_friendly_value(old_value), question.field.get_friendly_value(rating.value)) log_fields[field_name] = { 'title': question.title, 'type': field_type if field_type != 'rating' else 'number' } db.session.flush() notify_paper_review_submission(review) logger.info("Paper review %r modified", review) log_fields.update({ 'proposed_action': 'Action', 'comment': 'Comment' }) event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', 'Review for paper {} modified'.format(paper.verbose_title), session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_review(review, review_data, questions_data): paper = review.revision.paper event = paper.event changes = review.populate_from_dict(review_data) review.modified_dt = now_utc() log_fields = {} for question in event.cfp.get_questions_for_review_type(review.type): field_name = f'question_{question.id}' rating = question.get_review_rating(review, allow_create=True) old_value = rating.value rating.value = questions_data[field_name] if old_value != rating.value: field_type = question.field_type changes[field_name] = ( question.field.get_friendly_value(old_value), question.field.get_friendly_value(rating.value)) log_fields[field_name] = { 'title': question.title, 'type': field_type if field_type != 'rating' else 'number' } db.session.flush() notify_paper_review_submission(review) logger.info("Paper review %r modified", review) log_fields.update({'proposed_action': 'Action', 'comment': 'Comment'}) event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', f'Review for paper {paper.verbose_title} modified', session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_abstract_review(review, review_data, questions_data): event = review.abstract.event changes = review.populate_from_dict(review_data) review.modified_dt = now_utc() log_fields = {} for question in event.abstract_review_questions: field_name = 'question_{}'.format(question.id) rating = question.get_review_rating(review, allow_create=True) old_value = rating.value rating.value = questions_data[field_name] if old_value != rating.value: field_type = question.field_type changes[field_name] = ( question.field.get_friendly_value(old_value), question.field.get_friendly_value(rating.value)) log_fields[field_name] = { 'title': question.title, 'type': field_type if field_type != 'rating' else 'number' } db.session.flush() logger.info("Abstract review %s modified", review) log_fields.update({'proposed_action': 'Action', 'comment': 'Comment'}) if review.proposed_action in { AbstractAction.mark_as_duplicate, AbstractAction.merge }: log_fields['proposed_related_abstract'] = { 'title': 'Other abstract', 'type': 'string', 'convert': lambda change: [x.verbose_title if x else None for x in change] } elif review.proposed_action == AbstractAction.accept: log_fields['proposed_contribution_type'] = { 'title': 'Contribution type', 'type': 'string', 'convert': lambda change: [x.name if x else None for x in change] } elif review.proposed_action == AbstractAction.change_tracks: log_fields['proposed_tracks'] = { 'title': 'Other tracks', 'convert': lambda change: [sorted(t.title for t in x) for x in change] } event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Review for abstract {} modified'.format( review.abstract.verbose_title), session.user, data={ 'Track': review.track.title, 'Changes': make_diff_log(changes, log_fields) })
def update_comment(comment, text, visibility): changes = comment.populate_from_dict({'text': text, 'visibility': visibility}) comment.modified_by = session.user comment.modified_dt = now_utc() db.session.flush() logger.info("Paper comment %r modified by %r", comment, session.user) paper = comment.paper_revision.paper paper.event.log(EventLogRealm.management, EventLogKind.change, 'Papers', 'Comment on paper {} modified'.format(paper.verbose_title), session.user, data={'Changes': make_diff_log(changes, {'text': 'Text', 'visibility': 'Visibility'})})
def update_abstract_comment(comment, comment_data): changes = comment.populate_from_dict(comment_data) comment.modified_by = session.user comment.modified_dt = now_utc() db.session.flush() logger.info("Abstract comment %s modified by %s", comment, session.user) comment.abstract.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Comment on abstract {} modified'.format(comment.abstract.verbose_title), session.user, data={'Changes': make_diff_log(changes, {'text': 'Text', 'visibility': 'Visibility'})})
def update_abstract_comment(comment, comment_data): changes = comment.populate_from_dict(comment_data) comment.modified_by = session.user comment.modified_dt = now_utc() db.session.flush() logger.info("Abstract comment %s modified by %s", comment, session.user) comment.abstract.event.log(EventLogRealm.management, EventLogKind.change, 'Abstracts', 'Comment on abstract {} modified'.format(comment.abstract.verbose_title), session.user, data={'Changes': make_diff_log(changes, {'text': 'Text', 'visibility': 'Visibility'})})
def update_comment(comment, text, visibility): changes = comment.populate_from_dict({'text': text, 'visibility': visibility}) comment.modified_by = session.user comment.modified_dt = now_utc() db.session.flush() logger.info("Paper comment %r modified by %r", comment, session.user) paper = comment.paper_revision.paper paper.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', 'Comment on paper {} modified'.format(paper.verbose_title), session.user, data={'Changes': make_diff_log(changes, {'text': 'Text', 'visibility': 'Visibility'})})
def _get_update_log_data(self, updates): changes = {} fields = {} for obj, change in updates.viewitems(): title = getattr(obj, 'full_title', obj.title) friendly_id = getattr(obj, 'friendly_id', None) if friendly_id is not None: title = '#{}: {}'.format(friendly_id, title) key = 'obj_{}'.format(obj.id) fields[key] = {'type': 'string', 'title': title} changes[key] = change return {'Changes': make_diff_log(changes, fields)}
def _get_update_log_data(self, updates): changes = {} fields = {} for obj, change in updates.items(): title = getattr(obj, 'full_title', obj.title) friendly_id = getattr(obj, 'friendly_id', None) if friendly_id is not None: title = f'#{friendly_id}: {title}' key = f'obj_{obj.id}' fields[key] = {'type': 'string', 'title': title} changes[key] = change return {'Changes': make_diff_log(changes, fields)}
def _process_POST(self): old_values = layout_settings.get_all(self.event) ret = self._process_request() new_values = layout_settings.get_all(self.event) # Skip `timetable_theme_settings` as they are dynamically generated from themes.yaml changes = {k: (old_values[k], v) for k, v in new_values.iteritems() if old_values[k] != v and k != 'timetable_theme_settings'} if changes: form_cls = ConferenceLayoutForm if self.event.type_ == EventType.conference else LectureMeetingLayoutForm form = form_cls(event=self.event) self.event.log(EventLogRealm.participants, EventLogKind.change, 'Layout', summary='Layout was updated', user=session.user, data={'Changes': make_diff_log(changes, form.log_fields_metadata)}) return ret
def update_session_coordinator_privs(event, data): changes = {} for priv, enabled in data.iteritems(): setting = COORDINATOR_PRIV_SETTINGS[priv] if session_settings.get(event, setting) == enabled: continue session_settings.set(event, setting, enabled) changes[priv] = (not enabled, enabled) db.session.flush() logger.info('Session coordinator privs of event %r updated with %r by %r', event, data, session.user) if changes: log_fields = {priv: orig_string(title) for priv, title in COORDINATOR_PRIV_TITLES.iteritems()} event.log(EventLogRealm.management, EventLogKind.change, 'Sessions', 'Coordinator privileges updated', session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_event_protection(event, data): assert set(data.viewkeys()) <= {'protection_mode', 'own_no_access_contact', 'access_key', 'visibility'} changes = event.populate_from_dict(data) db.session.flush() signals.event.updated.send(event, changes=changes) logger.info('Protection of event %r updated with %r by %r', event, data, session.user) if changes: log_fields = {'protection_mode': 'Protection mode', 'own_no_access_contact': 'No access contact', 'access_key': {'title': 'Access key', 'type': 'string'}, 'visibility': {'title': 'Visibility', 'type': 'string', 'convert': lambda changes: [_format_visibility(event, x) for x in changes]}} event.log(EventLogRealm.management, EventLogKind.change, 'Event', 'Protection updated', session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_abstract(abstract, abstract_data, custom_fields_data=None): tracks = abstract_data.pop('submitted_for_tracks', None) attachments = abstract_data.pop('attachments', None) changes = {} if tracks is not None and abstract.edit_track_mode == EditTrackMode.both: changes.update(_update_tracks(abstract, tracks)) if attachments: deleted_files = {f for f in abstract.files if f.id in attachments['deleted']} abstract.files = list(set(abstract.files) - deleted_files) delete_abstract_files(abstract, deleted_files) add_abstract_files(abstract, attachments['added']) changes.update(abstract.populate_from_dict(abstract_data)) if custom_fields_data: changes.update(set_custom_fields(abstract, custom_fields_data)) db.session.flush() logger.info('Abstract %s modified by %s', abstract, session.user) log_fields = { 'title': 'Title', 'description': 'Content', 'submission_comment': 'Comment', 'submitted_for_tracks': { 'title': 'Tracks', 'convert': lambda change: [sorted(t.title for t in x) for x in change] }, 'submitted_contrib_type': { 'title': 'Contribution type', 'type': 'string', 'convert': lambda change: [t.name if t else None for t in change] } } for field_name, change in changes.iteritems(): # we skip skip None -> '' changes (editing an abstract that # did not have a value for a new field yet without filling # it out) if not field_name.startswith('custom_') or not any(changes): continue field_id = int(field_name[7:]) field = abstract.event.get_contribution_field(field_id) field_impl = field.field log_fields[field_name] = { 'title': field.title, 'type': field_impl.log_type, 'convert': lambda change, field_impl=field_impl: map(field_impl.get_friendly_value, change) } abstract.event.log(EventLogRealm.management, EventLogKind.change, 'Abstracts', 'Abstract {} modified'.format(abstract.verbose_title), session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_abstract(abstract, abstract_data, custom_fields_data=None): tracks = abstract_data.pop('submitted_for_tracks', None) attachments = abstract_data.pop('attachments', None) changes = {} if tracks is not None and abstract.edit_track_mode == EditTrackMode.both: changes.update(_update_tracks(abstract, tracks)) if attachments: deleted_files = {f for f in abstract.files if f.id in attachments['deleted']} abstract.files = list(set(abstract.files) - deleted_files) delete_abstract_files(abstract, deleted_files) add_abstract_files(abstract, attachments['added']) changes.update(abstract.populate_from_dict(abstract_data)) if custom_fields_data: changes.update(set_custom_fields(abstract, custom_fields_data)) db.session.flush() logger.info('Abstract %s modified by %s', abstract, session.user) log_fields = { 'title': 'Title', 'description': 'Content', 'submission_comment': 'Comment', 'submitted_for_tracks': { 'title': 'Tracks', 'convert': lambda change: [sorted(t.title for t in x) for x in change] }, 'submitted_contrib_type': { 'title': 'Contribution type', 'type': 'string', 'convert': lambda change: [t.name if t else None for t in change] } } for field_name, change in changes.iteritems(): # we skip skip None -> '' changes (editing an abstract that # did not have a value for a new field yet without filling # it out) if not field_name.startswith('custom_') or not any(changes): continue field_id = int(field_name[7:]) field = abstract.event.get_contribution_field(field_id) field_impl = field.field log_fields[field_name] = { 'title': field.title, 'type': field_impl.log_type, 'convert': lambda change, field_impl=field_impl: map(field_impl.get_friendly_value, change) } abstract.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Abstract {} modified'.format(abstract.verbose_title), session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_comment(comment, text=None, visibility=None): new_values = {} if text: new_values['text'] = text if visibility is not None: new_values['visibility'] = visibility changes = comment.populate_from_dict(new_values) comment.modified_by = session.user comment.modified_dt = now_utc() db.session.flush() logger.info("Paper comment %r modified by %r", comment, session.user) paper = comment.paper_revision.paper paper.event.log(EventLogRealm.reviewing, EventLogKind.change, 'Papers', f'Comment on paper {paper.verbose_title} modified', session.user, data={'Changes': make_diff_log(changes, {'text': 'Text', 'visibility': 'Visibility'})})
def _log_event_update(event, changes, visible_person_link_changes=False): log_fields = { 'title': {'title': 'Title', 'type': 'string'}, 'description': 'Description', 'url_shortcut': {'title': 'URL Shortcut', 'type': 'string'}, 'address': 'Address', 'venue_room': {'title': 'Location', 'type': 'string'}, 'keywords': 'Keywords', 'references': { 'title': 'External IDs', 'convert': lambda changes: [map(_format_ref, refs) for refs in changes] }, 'person_links': { 'title': 'Speakers' if event.type_ == EventType.lecture else 'Chairpersons', 'convert': lambda changes: [map(_format_person, persons) for persons in changes] }, 'start_dt': 'Start date', 'end_dt': 'End date', 'start_dt_override': 'Displayed start date', 'end_dt_override': 'Displayed end date', 'timezone': {'title': 'Timezone', 'type': 'string'}, 'organizer_info': 'Organizers', 'additional_info': 'Additional Info', 'contact_title': {'title': 'Contact/Support title', 'type': 'string'}, 'contact_emails': 'Contact emails', 'contact_phones': 'Contact phone numbers', } _split_location_changes(changes) if not visible_person_link_changes: # Don't log a person link change with no visible changes (changes # on an existing link or reordering). It would look quite weird in # the event log. # TODO: maybe use a separate signal for such changes to log them # anyway and allow other code to act on them? changes.pop('person_links', None) if changes: if set(changes.viewkeys()) <= {'timezone', 'start_dt', 'end_dt', 'start_dt_override', 'end_dt_override'}: what = 'Dates' elif len(changes) == 1: what = log_fields[changes.keys()[0]] if isinstance(what, dict): what = what['title'] else: what = 'Data' event.log(EventLogRealm.management, EventLogKind.change, 'Event', '{} updated'.format(what), session.user, data={'Changes': make_diff_log(changes, log_fields)})
def update_abstract_review(review, review_data, questions_data): event = review.abstract.event changes = review.populate_from_dict(review_data) review.modified_dt = now_utc() log_fields = {} for question in event.abstract_review_questions: field_name = 'question_{}'.format(question.id) rating = question.get_review_rating(review, allow_create=True) old_value = rating.value rating.value = questions_data[field_name] if old_value != rating.value: field_type = question.field_type changes[field_name] = (question.field.get_friendly_value(old_value), question.field.get_friendly_value(rating.value)) log_fields[field_name] = { 'title': question.title, 'type': field_type if field_type != 'rating' else 'number' } db.session.flush() logger.info("Abstract review %s modified", review) log_fields.update({ 'proposed_action': 'Action', 'comment': 'Comment' }) if review.proposed_action in {AbstractAction.mark_as_duplicate, AbstractAction.merge}: log_fields['proposed_related_abstract'] = { 'title': 'Other abstract', 'type': 'string', 'convert': lambda change: [x.verbose_title if x else None for x in change] } elif review.proposed_action == AbstractAction.accept: log_fields['proposed_contribution_type'] = { 'title': 'Contribution type', 'type': 'string', 'convert': lambda change: [x.name if x else None for x in change] } elif review.proposed_action == AbstractAction.change_tracks: log_fields['proposed_tracks'] = { 'title': 'Other tracks', 'convert': lambda change: [sorted(t.title for t in x) for x in change] } event.log(EventLogRealm.reviewing, EventLogKind.change, 'Abstracts', 'Review for abstract {} modified'.format(review.abstract.verbose_title), session.user, data={'Track': review.track.title, 'Changes': make_diff_log(changes, log_fields)})