From 5ab41a6f7c89dd9cdcb121cc04e7790efbc93fee Mon Sep 17 00:00:00 2001 From: Melisa Bok Date: Mon, 3 Jun 2024 10:17:50 -0400 Subject: [PATCH] Fix/arr issues (#2173) * use invitations to send messages * fix start_date instead of date * add sender * add checklist count * email SACs when comments are posted * fix ARR Pc console * make field optional so tests can pass * fix test * configure edge browser links in the PC console webfield * keep using enum for custom max papers so they are editable from the edge browser --- openreview/arr/arr.py | 17 +---- openreview/arr/helpers.py | 31 ++++---- .../management/setup_proposed_assignments.py | 60 --------------- openreview/arr/process/review_process.py | 20 +++++ .../arr/webfield/programChairsWebfield.js | 75 +++++++++++++++++-- openreview/conference/helpers.py | 2 + openreview/stages/venue_stages.py | 2 + openreview/venue/group.py | 1 + openreview/venue/matching.py | 2 +- .../venue/process/chat_comment_process.py | 11 ++- .../process/chat_date_comment_process.py | 9 ++- openreview/venue/process/comment_process.py | 2 +- openreview/venue/venue.py | 6 +- openreview/venue_request/venue_request.py | 12 ++- tests/test_arr_venue_v2.py | 52 +++++++++++-- tests/test_icml_conference.py | 2 +- 16 files changed, 189 insertions(+), 115 deletions(-) diff --git a/openreview/arr/arr.py b/openreview/arr/arr.py index 313236d1d..3a55d83a5 100644 --- a/openreview/arr/arr.py +++ b/openreview/arr/arr.py @@ -476,22 +476,7 @@ def send_decision_notifications(self, decision_options, messages): return self.venue.send_decision_notifications(decision_options, messages) def setup_committee_matching(self, committee_id=None, compute_affinity_scores=False, compute_conflicts=False, compute_conflicts_n_years=None, alternate_matching_group=None, submission_track=None): - matching_value = self.venue.setup_committee_matching(committee_id, compute_affinity_scores, compute_conflicts, compute_conflicts_n_years, alternate_matching_group, submission_track) - cmp_inv = self.client.get_invitation(self.get_custom_max_papers_id(committee_id)) - cmp_inv.edit['weight']['param']['optional'] = True - if 'enum' in cmp_inv.edit['weight']['param']: - del cmp_inv.edit['weight']['param']['enum'] - cmp_inv.edit['weight']['param']['minimum'] = 0 - cmp_inv.edit['weight']['param']['default'] = 0 - - self.client.post_invitation_edit( - invitations=self.get_meta_invitation_id(), - readers=[self.venue_id], - writers=[self.venue_id], - signatures=[self.venue_id], - invitation=cmp_inv - ) - return matching_value + return self.venue.setup_committee_matching(committee_id, compute_affinity_scores, compute_conflicts, compute_conflicts_n_years, alternate_matching_group, submission_track) def set_assignments(self, assignment_title, committee_id, enable_reviewer_reassignment=False, overwrite=False): return self.venue.set_assignments(assignment_title, committee_id, enable_reviewer_reassignment, overwrite) diff --git a/openreview/arr/helpers.py b/openreview/arr/helpers.py index 8138ca567..231852a7d 100644 --- a/openreview/arr/helpers.py +++ b/openreview/arr/helpers.py @@ -765,8 +765,8 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor ], 'content': comment_v2, 'multi_reply': True, - 'notify_readers': False, - 'email_sacs': False + 'notify_readers': True, + 'email_sacs': True }, start_date=self.configuration_note.content.get('commentary_start_date'), exp_date=self.configuration_note.content.get('commentary_end_date') @@ -791,6 +791,7 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor }, due_date=self.configuration_note.content.get('reviewer_checklist_due_date'), exp_date=self.configuration_note.content.get('reviewer_checklist_exp_date'), + #start_date=self.venue.submission_stage.exp_date.strftime('%Y/%m/%d %H:%M'), Discuss with Harold process='process/checklist_process.py', preprocess='process/checklist_preprocess.py', extend=ARRWorkflow._extend_reviewer_checklist @@ -814,6 +815,7 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor }, due_date=self.configuration_note.content.get('ae_checklist_due_date'), exp_date=self.configuration_note.content.get('ae_checklist_exp_date'), + #start_date=self.venue.submission_stage.exp_date.strftime('%Y/%m/%d %H:%M'), Discuss with Harold process='process/checklist_process.py', preprocess='process/checklist_preprocess.py', extend=ARRWorkflow._extend_ae_checklist @@ -833,6 +835,7 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor 'email_sacs': False }, exp_date=self.configuration_note.content.get('form_expiration_date'), + #start_date=self.venue.submission_stage.exp_date.strftime('%Y/%m/%d %H:%M'), Discuss with Harold process='process/verification_process.py', extend=ARRWorkflow._extend_desk_reject_verification ), @@ -870,7 +873,9 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor 'Assigned Submitted Reviewers' ], 'additional_readers':['Program Chairs'], - 'email_program_chairs_about_official_comments': 'No, do not email PCs for each official comment made in the venue' + 'email_program_chairs_about_official_comments': 'No, do not email PCs for each official comment made in the venue', + 'email_senior_area_chairs_about_official_comments': 'Yes, email SACs for each official comment made in the venue' + }, 'forum': request_form_id, 'invitation': '{}/-/Request{}/Comment_Stage'.format(support_user, request_form.number), @@ -1006,20 +1011,6 @@ def __init__(self, client_v2, venue, configuration_note, request_form_id, suppor m = matching.Matching(venue, self.client_v2.get_group(role), None, None) if not openreview.tools.get_invitation(self.client_v2, venue.get_custom_max_papers_id(role)): m._create_edge_invitation(venue.get_custom_max_papers_id(m.match_group.id)) - cmp_inv = self.client_v2.get_invitation(venue.get_custom_max_papers_id(m.match_group.id)) - cmp_inv.edit['weight']['param']['optional'] = True - if 'enum' in cmp_inv.edit['weight']['param']: - del cmp_inv.edit['weight']['param']['enum'] - cmp_inv.edit['weight']['param']['minimum'] = 0 - cmp_inv.edit['weight']['param']['default'] = 0 - - self.client_v2.post_invitation_edit( - invitations=venue.get_meta_invitation_id(), - readers=[venue.id], - writers=[venue.id], - signatures=[venue.id], - invitation=cmp_inv - ) if not openreview.tools.get_invitation(self.client_v2, f"{role}/-/Status"): # Hold "Requested" or "Reassigned", head=submission ID m._create_edge_invitation(f"{role}/-/Status") @@ -1434,6 +1425,8 @@ def flag_submission( domain = client.get_group(edit.domain) venue_id = domain.id meta_invitation_id = domain.content['meta_invitation_id']['value'] + contact = domain.content['contact']['value'] + sender = domain.get_content_value('message_sender') short_name = domain.get_content_value('subtitle') forum = client.get_note(id=edit.note.forum, details='replies') @@ -1538,6 +1531,10 @@ def check_field_not_violated(note, field): To view the submission, click here: https://openreview.net/forum?id={}'''.format(forum.number, forum.id) client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + replyTo=contact, + sender=sender, recipients=[domain.content['ethics_chairs_id']['value']], ignoreRecipients=[edit.tauthor], subject=subject, diff --git a/openreview/arr/management/setup_proposed_assignments.py b/openreview/arr/management/setup_proposed_assignments.py index f7da54f48..f910cc57f 100644 --- a/openreview/arr/management/setup_proposed_assignments.py +++ b/openreview/arr/management/setup_proposed_assignments.py @@ -8,26 +8,11 @@ def process(client, invitation): print('invitation is not yet active and no child invitations created', cdate) return - from openreview.venue import matching - import random - import string - domain = client.get_group(invitation.domain) venue_id = domain.id - request_form_id = domain.content['request_form_id']['value'] meta_invitation_id = domain.content['meta_invitation_id']['value'] - reviewer_id = domain.content['reviewers_id']['value'] ac_id = domain.content['area_chairs_id']['value'] - sac_id = domain.content['senior_area_chairs_id']['value'] - pc_id = domain.content['program_chairs_id']['value'] - sac_name = domain.content['senior_area_chairs_name']['value'] - - client_v1 = openreview.Client( - baseurl=openreview.tools.get_base_urls(client)[0], - token=client.token - ) - request_form = client_v1.get_note(request_form_id) # Update webfields label_to_share = invitation.content['reviewer_assignments_title']['value'] @@ -84,49 +69,4 @@ def process(client, invitation): id = ac_id, web='\n'.join(dst_lines) ) - ) - - web = client.get_group(pc_id).web - web_lines = web.split('\n') - dst_lines = [] - for line in web_lines: - if 'const manualReviewerAssignmentUrl' in line: - browse_line = line.split(' = ')[1].split('&')[-2] - for inv in group_invs: - if f"/-/{inv}" not in browse_line: - browse_line += ';${domain.content.reviewers_id?.value}' + f"/-/{inv},head:ignore" - if '/-/Status' not in web: - browse_line += ';${domain.content.reviewers_id?.value}' + f"/-/Status" - if '/-/Research_Area' not in web: - browse_line += ';${domain.content.reviewers_id?.value}' + f"/-/Research_Area" - - after_assignment = line.split(' = ')[1] - param_list = after_assignment.split('&') - param_list[-2] = browse_line - line = line.replace(after_assignment, '&'.join(param_list)) - dst_lines.append(line) - elif 'const manualAreaChairAssignmentUrl' in line: - browse_line = line.split(' = ')[1].split('&')[-2] - for inv in group_invs: - if f"/-/{inv}" not in browse_line: - browse_line += ';${domain.content.area_chairs_id?.value}' + f"/-/{inv},head:ignore" - if '/-/Status' not in web: - browse_line += ';${domain.content.area_chairs_id?.value}' + f"/-/Status" - if '/-/Research_Area' not in web: - browse_line += ';${domain.content.area_chairs_id?.value}' + f"/-/Research_Area" - after_assignment = line.split(' = ')[1] - param_list = after_assignment.split('&') - param_list[-2] = browse_line - line = line.replace(after_assignment, '&'.join(param_list)) - dst_lines.append(line) - else: - dst_lines.append(line) - client.post_group_edit(invitation=meta_invitation_id, - readers = [venue_id], - writers = [venue_id], - signatures = [venue_id], - group = openreview.api.Group( - id = pc_id, - web='\n'.join(dst_lines) - ) ) \ No newline at end of file diff --git a/openreview/arr/process/review_process.py b/openreview/arr/process/review_process.py index c28ef9f77..5c62e6897 100644 --- a/openreview/arr/process/review_process.py +++ b/openreview/arr/process/review_process.py @@ -5,6 +5,7 @@ def process(client, edit, invitation): meta_invitation_id = domain.content['meta_invitation_id']['value'] short_name = domain.get_content_value('subtitle') contact = domain.get_content_value('contact') + sender = domain.get_content_value('message_sender') authors_name = domain.get_content_value('authors_name') submission_name = domain.get_content_value('submission_name') reviewers_name = domain.get_content_value('reviewers_name') @@ -77,6 +78,10 @@ def create_group(group_id, members=[]): if domain.get_content_value('review_email_pcs'): client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + replyTo=contact, + sender=sender, recipients=[domain.get_content_value('program_chairs_id')], ignoreRecipients=ignore_groups, subject=f'''[{short_name}] A {review_name} has been received on Paper number: {submission.number}, Paper title: "{submission.content['title']['value']}"''', @@ -87,8 +92,11 @@ def create_group(group_id, members=[]): ) client.post_message( + invitation=meta_invitation_id, + signature=venue_id, recipients=review.signatures, replyTo=contact, + sender=sender, subject=f'''[{short_name}] Your {review_name} has been received on your assigned Paper number: {submission.number}, Paper title: "{submission.content['title']['value']}"''', message=f''''We have received a review on a submission to {short_name}. @@ -101,6 +109,9 @@ def create_group(group_id, members=[]): if area_chairs_name and ('everyone' in review.readers or paper_area_chairs_id in review.readers): client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + sender=sender, recipients=[paper_area_chairs_id], ignoreRecipients=ignore_groups, replyTo=contact, @@ -118,6 +129,9 @@ def create_group(group_id, members=[]): create_group(paper_reviewers_submitted_id, [review.signatures[0]]) if 'everyone' in review.readers or paper_reviewers_id in review.readers: client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + sender=sender, recipients=[paper_reviewers_id], ignoreRecipients=ignore_groups, replyTo=contact, @@ -133,6 +147,9 @@ def create_group(group_id, members=[]): ) elif paper_reviewers_submitted_id in review.readers: client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + sender=sender, recipients=[paper_reviewers_submitted_id], ignoreRecipients=ignore_groups, replyTo=contact, @@ -150,6 +167,9 @@ def create_group(group_id, members=[]): paper_authors_id = f'{paper_group_id}/{authors_name}' if 'everyone' in review.readers or paper_authors_id in review.readers: client.post_message( + invitation=meta_invitation_id, + signature=venue_id, + sender=sender, recipients=[paper_authors_id], ignoreRecipients=ignore_groups, replyTo=contact, diff --git a/openreview/arr/webfield/programChairsWebfield.js b/openreview/arr/webfield/programChairsWebfield.js index e781114de..011298ffb 100644 --- a/openreview/arr/webfield/programChairsWebfield.js +++ b/openreview/arr/webfield/programChairsWebfield.js @@ -2,8 +2,31 @@ // loaded properly const automaticAssignment = domain.content.automatic_reviewer_assignment?.value const assignmentUrls = {} +const areaChairsId = domain.content.area_chairs_id?.value +const reviewersId = domain.content.reviewers_id?.value -const manualReviewerAssignmentUrl = `/edges/browse?traverse=${domain.content.reviewers_assignment_id?.value}&edit=${domain.content.reviewers_assignment_id?.value};${domain.content.reviewers_custom_max_papers_id?.value},tail:ignore&browse=${domain.content.reviewers_affinity_score_id?.value};${domain.content.reviewers_conflict_id?.value}&version=2` +const browseInvitations = [ + domain.content.reviewers_affinity_score_id?.value, + domain.content.reviewers_conflict_id?.value, + `${reviewersId}/-/Research_Area`, + `${reviewersId}/-/Status`, +].join(';') + +const headBrowseInvitations = [ + `${reviewersId}/-/Registered_Load`, + `${reviewersId}/-/Emergency_Load`, + `${reviewersId}/-/Emergency_Area`, + `${reviewersId}/-/Reviewing_Resubmissions`, + `${reviewersId}/-/Author_In_Current_Cycle`, + `${reviewersId}/-/Seniority`, +].map(invitationId => `${invitationId},head:ignore`).join(';') + +const allBrowseInvitations = [ + browseInvitations, + headBrowseInvitations, +].join(';') + +const manualReviewerAssignmentUrl = `/edges/browse?traverse=${domain.content.reviewers_assignment_id?.value}&edit=${domain.content.reviewers_assignment_id?.value};${domain.content.reviewers_custom_max_papers_id?.value},head:ignore&browse=${allBrowseInvitations}&version=2` assignmentUrls[domain.content.reviewers_name?.value] = { manualAssignmentUrl: manualReviewerAssignmentUrl, automaticAssignment: automaticAssignment @@ -11,7 +34,29 @@ assignmentUrls[domain.content.reviewers_name?.value] = { const areaChairName = domain.content.area_chairs_name?.value if (areaChairName) { - const manualAreaChairAssignmentUrl = `/edges/browse?traverse=${domain.content.area_chairs_assignment_id?.value}&edit=${domain.content.area_chairs_assignment_id?.value};${domain.content.area_chairs_custom_max_papers_id?.value},tail:ignore&browse=${domain.content.area_chairs_affinity_score_id?.value};${domain.content.area_chairs_conflict_id?.value}&version=2` + + const browseInvitations = [ + domain.content.area_chairs_affinity_score_id?.value, + domain.content.area_chairs_conflict_id?.value, + `${areaChairsId}/-/Research_Area`, + `${areaChairsId}/-/Status`, + ].join(';') + + const headBrowseInvitations = [ + `${areaChairsId}/-/Registered_Load`, + `${areaChairsId}/-/Emergency_Load`, + `${areaChairsId}/-/Emergency_Area`, + `${areaChairsId}/-/Reviewing_Resubmissions`, + `${areaChairsId}/-/Author_In_Current_Cycle`, + `${areaChairsId}/-/Seniority`, + ].map(invitationId => `${invitationId},head:ignore`).join(';') + + const allBrowseInvitations = [ + browseInvitations, + headBrowseInvitations, + ].join(';') + + const manualAreaChairAssignmentUrl = `/edges/browse?traverse=${domain.content.area_chairs_assignment_id?.value}&edit=${domain.content.area_chairs_assignment_id?.value};${domain.content.area_chairs_custom_max_papers_id?.value},head:ignore&browse=${allBrowseInvitations}&version=2` assignmentUrls[areaChairName] = { manualAssignmentUrl: manualAreaChairAssignmentUrl, automaticAssignment: automaticAssignment @@ -27,9 +72,9 @@ return { instructions: `This page provides information and status updates for the ${domain.content.subtitle?.value}. It will be regularly updated as the conference progresses, so please check back frequently.` }, venueId: domain.id, - areaChairsId: domain.content.area_chairs_id?.value, + areaChairsId: areaChairsId, seniorAreaChairsId: domain.content.senior_area_chairs_id?.value, - reviewersId: domain.content.reviewers_id?.value, + reviewersId: reviewersId, programChairsId: domain.content.program_chairs_id?.value, authorsId: domain.content.authors_id?.value, paperReviewsCompleteThreshold: 3, @@ -80,6 +125,24 @@ return { 'author_identity_guess': [5] } } - ] + ], + propertiesAllowed: { + reviewerChecklistCount: ` + const invitationToCheck="Reviewer_Checklist"; + const checklistReplies = row.note?.details?.replies.filter(reply => { + const hasReply = reply.invitations.some(invitation => invitation.includes(invitationToCheck)); + return hasReply; + }) + return checklistReplies?.length??0; + `, + actionEditorChecklistCount: ` + const invitationToCheck="Action_Editor_Checklist"; + const checklistReplies = row.note?.details?.replies.filter(reply => { + const hasReply = reply.invitations.some(invitation => invitation.includes(invitationToCheck)); + return hasReply; + }) + return checklistReplies?.length??0; + ` + } } -} +} \ No newline at end of file diff --git a/openreview/conference/helpers.py b/openreview/conference/helpers.py index b0676e4a9..2f5657b66 100644 --- a/openreview/conference/helpers.py +++ b/openreview/conference/helpers.py @@ -927,6 +927,7 @@ def get_comment_stage(request_forum): readers.append(openreview.stages.CommentStage.Readers.EVERYONE) email_pcs = request_forum.content.get('email_program_chairs_about_official_comments', '') == 'Yes, email PCs for each official comment made in the venue' + email_sacs = request_forum.content.get('email_senior_area_chairs_about_official_comments', '') == 'Yes, email SACs for each official comment made in the venue' enable_chat = request_forum.content.get('enable_chat_between_committee_members', '') == 'Yes, enable chat between committee members' @@ -937,6 +938,7 @@ def get_comment_stage(request_forum): anonymous=anonymous, reader_selection=True, email_pcs=email_pcs, + email_sacs=email_sacs, check_mandatory_readers=True, readers=readers, invitees=invitees, diff --git a/openreview/stages/venue_stages.py b/openreview/stages/venue_stages.py index ad6f8b651..d0e13aee2 100644 --- a/openreview/stages/venue_stages.py +++ b/openreview/stages/venue_stages.py @@ -958,6 +958,7 @@ def __init__(self, anonymous=False, reader_selection=False, email_pcs=False, + email_sacs = False, only_accepted=False, check_mandatory_readers=False, readers=[], @@ -972,6 +973,7 @@ def __init__(self, self.anonymous = anonymous self.reader_selection = reader_selection self.email_pcs = email_pcs + self.email_sacs = email_sacs self.only_accepted=only_accepted self.check_mandatory_readers=check_mandatory_readers self.readers = readers diff --git a/openreview/venue/group.py b/openreview/venue/group.py index 19e134005..ff521e10c 100644 --- a/openreview/venue/group.py +++ b/openreview/venue/group.py @@ -248,6 +248,7 @@ def create_venue_group(self): if self.venue.comment_stage: content['comment_mandatory_readers'] = { 'value': self.venue.comment_stage.get_mandatory_readers(self.venue, '{number}') } content['comment_email_pcs'] = { 'value': self.venue.comment_stage.email_pcs } + content['comment_email_sacs'] = { 'value': self.venue.comment_stage.email_sacs } if self.venue.review_rebuttal_stage: content['rebuttal_email_pcs'] = { 'value': self.venue.review_rebuttal_stage.email_pcs} diff --git a/openreview/venue/matching.py b/openreview/venue/matching.py index b91d358ec..cf7297dd5 100644 --- a/openreview/venue/matching.py +++ b/openreview/venue/matching.py @@ -202,7 +202,7 @@ def _create_edge_invitation(self, edge_id, any_tail=False, default_label=None): edge_weight = { 'param': { - 'enum': list(range(0, 51)) + 'enum': list(range(0, 101)) } } edge_label = None diff --git a/openreview/venue/process/chat_comment_process.py b/openreview/venue/process/chat_comment_process.py index 307555ec9..0d4a9b3fe 100644 --- a/openreview/venue/process/chat_comment_process.py +++ b/openreview/venue/process/chat_comment_process.py @@ -6,12 +6,19 @@ def process(client, edit, invitation): contact = domain.get_content_value('contact') meta_invitation_id = domain.get_content_value('meta_invitation_id') sender = domain.get_content_value('message_sender') + submission_name = domain.get_content_value('submission_name') comment_email_pcs = domain.get_content_value('comment_email_pcs') + comment_email_sacs = domain.get_content_value('comment_email_sacs') program_chairs_id = domain.get_content_value('program_chairs_id') + senior_area_chairs_name = domain.get_content_value('senior_area_chairs_name') submission = client.get_note(edit.note.forum) comment = client.get_note(edit.note.id) + ignore_recipients = comment.signatures + ([program_chairs_id] if not comment_email_pcs else []) + if not comment_email_sacs and senior_area_chairs_name: + ignore_recipients.append(f'{venue_id}/{submission_name}{submission.number}/{senior_area_chairs_name}') + invitation = client.get_invitation(invitation.id) if invitation.date_processes[0].get('cron') is None: ## Activate date process to run every 4 hours @@ -42,7 +49,7 @@ def process(client, edit, invitation): You can view the conversation here: https://openreview.net/forum?id={submission.id}¬eId={comment.id}#committee-chat ''', replyTo = contact, - ignoreRecipients = comment.signatures + ([program_chairs_id] if not comment_email_pcs else []), + ignoreRecipients = ignore_recipients, signature=venue_id, sender=sender ) @@ -96,7 +103,7 @@ def process(client, edit, invitation): You can view the conversation here: https://openreview.net/forum?id={submission.id}¬eId={new_comments[0].id}#committee-chat ''', replyTo = contact, - ignoreRecipients = comment.signatures + ([program_chairs_id] if not comment_email_pcs else []), + ignoreRecipients = ignore_recipients, signature=venue_id, sender=sender ) diff --git a/openreview/venue/process/chat_date_comment_process.py b/openreview/venue/process/chat_date_comment_process.py index f338ab1d9..775a46ae6 100644 --- a/openreview/venue/process/chat_date_comment_process.py +++ b/openreview/venue/process/chat_date_comment_process.py @@ -6,8 +6,11 @@ def process(client, invitation): contact = domain.get_content_value('contact') meta_invitation_id = domain.get_content_value('meta_invitation_id') sender = domain.get_content_value('message_sender') + submission_name = domain.get_content_value('submission_name') comment_email_pcs = domain.get_content_value('comment_email_pcs') + comment_email_sacs = domain.get_content_value('comment_email_sacs') program_chairs_id = domain.get_content_value('program_chairs_id') + senior_area_chairs_name = domain.get_content_value('senior_area_chairs_name') last_notified_id = invitation.content.get('last_notified_id', {}).get('value') if invitation.content else None @@ -24,6 +27,10 @@ def process(client, invitation): if len(new_comments) == 0: return + ignore_recipients = new_comments[-1].signatures + ([program_chairs_id] if not comment_email_pcs else []) + if not comment_email_sacs and senior_area_chairs_name: + ignore_recipients.append(f'{venue_id}/{submission_name}{submission.number}/{senior_area_chairs_name}') + client.post_message( invitation = meta_invitation_id, subject = f'[{short_name}] New message{"s" if len(new_comments) > 1 else ""} in committee members chat for submission {submission.number}: {submission.content["title"]["value"]}', @@ -35,7 +42,7 @@ def process(client, invitation): You can view the conversation here: https://openreview.net/forum?id={submission.id}¬eId={new_comments[0].id}#committee-chat ''', replyTo = contact, - ignoreRecipients = new_comments[-1].signatures + ([program_chairs_id] if not comment_email_pcs else []), + ignoreRecipients = ignore_recipients, signature=venue_id, sender = sender ) diff --git a/openreview/venue/process/comment_process.py b/openreview/venue/process/comment_process.py index 5ca08bfef..70d960295 100644 --- a/openreview/venue/process/comment_process.py +++ b/openreview/venue/process/comment_process.py @@ -53,7 +53,7 @@ def process(client, edit, invitation): senior_area_chairs_name = domain.get_content_value('senior_area_chairs_name') paper_senior_area_chairs_id = f'{paper_group_id}/{senior_area_chairs_name}' paper_senior_area_chairs_group = openreview.tools.get_group(client, paper_senior_area_chairs_id) - email_SAC = len(comment.readers)==3 and paper_senior_area_chairs_id in comment.readers and program_chairs_id in comment.readers + email_SAC = ((len(comment.readers)==3 and paper_senior_area_chairs_id in comment.readers and program_chairs_id in comment.readers) or domain.get_content_value('comment_email_sacs')) if paper_senior_area_chairs_group and senior_area_chairs_name and email_SAC: client.post_message( invitation=meta_invitation_id, diff --git a/openreview/venue/venue.py b/openreview/venue/venue.py index 9fd6708b6..390e22e6d 100644 --- a/openreview/venue/venue.py +++ b/openreview/venue/venue.py @@ -91,11 +91,11 @@ def get_message_sender(self): def get_edges_archive_date(self): archive_date = datetime.datetime.utcnow() - if self.date: + if self.start_date: try: - archive_date = datetime.datetime.strptime(self.date, '%Y/%m/%d') + archive_date = datetime.datetime.strptime(self.start_date, '%Y/%m/%d') except ValueError: - print(f'Error parsing venue date {self.date}') + print(f'Error parsing venue date {self.start_date}') return openreview.tools.datetime_millis(archive_date + datetime.timedelta(weeks=52)) ## archive edges after 1 year diff --git a/openreview/venue_request/venue_request.py b/openreview/venue_request/venue_request.py index d59900501..a1d543e1d 100644 --- a/openreview/venue_request/venue_request.py +++ b/openreview/venue_request/venue_request.py @@ -491,6 +491,16 @@ def setup_comment_stage(self): 'default': 'No, do not email PCs for each official comment made in the venue', 'order': 31 }, + 'email_senior_area_chairs_about_official_comments': { + 'description': 'Should the SACs(if applicable) receive an email for each official comment made in the venue? Default is "No, do not email SACs for each official comment in the venue"', + 'value-radio': [ + 'Yes, email SACs for each official comment made in the venue', + 'No, do not email SACs for each official comment made in the venue' + ], + 'required': False, + 'default': 'No, do not email SACs for each official comment made in the venue', + 'order': 32 + }, 'enable_chat_between_committee_members': { 'description': 'An experimental feature that allows committee members to chat with each other. Only the selected participants that are members of the reviewing committee will be using this feature. Default is "Yes, enable chat between committee members". More information: https://docs.openreview.net/getting-started/live-chat-on-the-forum-page', 'value-radio': [ @@ -499,7 +509,7 @@ def setup_comment_stage(self): ], 'required': False, 'default': 'Yes, enable chat between committee members', - 'order': 32 + 'order': 33 } } diff --git a/tests/test_arr_venue_v2.py b/tests/test_arr_venue_v2.py index 8fd92ac1d..3d049b9b1 100644 --- a/tests/test_arr_venue_v2.py +++ b/tests/test_arr_venue_v2.py @@ -1847,6 +1847,15 @@ def test_post_submission(self, client, openreview_client, helpers, test_client, )) helpers.await_queue() + helpers.await_queue_edit(openreview_client, 'aclweb.org/ACL/ARR/2023/August/-/Post_Submission-0-1', count=3) + pc_client_v2=openreview.api.OpenReviewClient(username='pc@aclrollingreview.org', password=helpers.strong_password) + + assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Withdrawal')) == 101 + assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Desk_Rejection')) == 101 + # Discuss with Harold + #assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Reviewer_Checklist')) == 101 + #assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Action_Editor_Checklist')) == 101 + #assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Desk_Reject_Verification')) == 101 # Open comments now = datetime.datetime.utcnow() @@ -1870,12 +1879,13 @@ def test_post_submission(self, client, openreview_client, helpers, test_client, helpers.await_queue() helpers.await_queue_edit(openreview_client, 'aclweb.org/ACL/ARR/2023/August/-/Official_Comment-0-1', count=1) - pc_client_v2=openreview.api.OpenReviewClient(username='pc@aclrollingreview.org', password=helpers.strong_password) submission_invitation = pc_client_v2.get_invitation('aclweb.org/ACL/ARR/2023/August/-/Submission') assert submission_invitation.expdate < openreview.tools.datetime_millis(now) assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Withdrawal')) == 101 assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Desk_Rejection')) == 101 + #assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Reviewer_Checklist')) == 101 + #assert len(pc_client_v2.get_all_invitations(invitation='aclweb.org/ACL/ARR/2023/August/-/Action_Editor_Checklist')) == 101 assert pc_client_v2.get_invitation('aclweb.org/ACL/ARR/2023/August/-/PC_Revision') submissions = pc_client_v2.get_notes(invitation='aclweb.org/ACL/ARR/2023/August/-/Submission', sort='number:asc') @@ -2026,7 +2036,7 @@ def test_post_submission(self, client, openreview_client, helpers, test_client, # Post comment as PCs to all submissions for submission in submissions: - pc_client_v2.post_note_edit( + comment_edit = pc_client_v2.post_note_edit( invitation=f"aclweb.org/ACL/ARR/2023/August/Submission{submission.number}/-/Official_Comment", writers=['aclweb.org/ACL/ARR/2023/August'], signatures=['aclweb.org/ACL/ARR/2023/August/Program_Chairs'], @@ -2043,10 +2053,12 @@ def test_post_submission(self, client, openreview_client, helpers, test_client, ) ) + helpers.await_queue_edit(openreview_client, edit_id=comment_edit['id']) + # Post comment as authors to chairs test_client = openreview.api.OpenReviewClient(token=test_client.token) for submission in submissions: - pc_client_v2.post_note_edit( + comment_edit = pc_client_v2.post_note_edit( invitation=f"aclweb.org/ACL/ARR/2023/August/Submission{submission.number}/-/Author-Editor_Confidential_Comment", writers=['aclweb.org/ACL/ARR/2023/August', f'aclweb.org/ACL/ARR/2023/August/Submission{submission.number}/Authors'], signatures=[f'aclweb.org/ACL/ARR/2023/August/Submission{submission.number}/Authors'], @@ -2064,6 +2076,10 @@ def test_post_submission(self, client, openreview_client, helpers, test_client, ) ) + helpers.await_queue_edit(openreview_client, edit_id=comment_edit['id']) + + assert openreview_client.get_messages(subject=f'[ARR - August 2023] An author-editor confidential comment has been received on your Paper Number: {submission.number}, Paper Title: "Paper title {submission.number}"') + def test_setup_matching(self, client, openreview_client, helpers, test_client, request_page, selenium): @@ -2392,7 +2408,7 @@ def test_resubmission_and_track_matching_data(self, client, openreview_client, h anon_groups = ac_client_3.get_groups(prefix='aclweb.org/ACL/ARR/2023/June/Submission2/Area_Chair_', signatory='~AC_ARRThree1') anon_group_id_ac = anon_groups[0].id - reviewer_client_1.post_note_edit( + review_edit = reviewer_client_1.post_note_edit( invitation='aclweb.org/ACL/ARR/2023/June/Submission2/-/Official_Review', signatures=[anon_group_id_1], note=openreview.api.Note( @@ -2417,8 +2433,9 @@ def test_resubmission_and_track_matching_data(self, client, openreview_client, h } ) ) + helpers.await_queue_edit(openreview_client, edit_id=review_edit['id']) - reviewer_client_2.post_note_edit( + review_edit = reviewer_client_2.post_note_edit( invitation='aclweb.org/ACL/ARR/2023/June/Submission3/-/Official_Review', signatures=[anon_group_id_2], note=openreview.api.Note( @@ -2443,8 +2460,9 @@ def test_resubmission_and_track_matching_data(self, client, openreview_client, h } ) ) + helpers.await_queue_edit(openreview_client, edit_id=review_edit['id']) - reviewer_client_5.post_note_edit( + review_edit = reviewer_client_5.post_note_edit( invitation='aclweb.org/ACL/ARR/2023/June/Submission2/-/Official_Review', signatures=[anon_group_id_5], note=openreview.api.Note( @@ -2469,6 +2487,7 @@ def test_resubmission_and_track_matching_data(self, client, openreview_client, h } ) ) + helpers.await_queue_edit(openreview_client, edit_id=review_edit['id']) ac_edit = ac_client_3.post_note_edit( invitation='aclweb.org/ACL/ARR/2023/June/Submission2/-/Meta_Review', @@ -3321,6 +3340,27 @@ def test_author_response(self, client, openreview_client, helpers, test_client, assert f"aclweb.org/ACL/ARR/2023/August/Submission{s.number}/Authors" in comment_invitees assert f"aclweb.org/ACL/ARR/2023/August/Submission{s.number}/Authors" in comment_readers + comment_edit = pc_client_v2.post_note_edit( + invitation=f"aclweb.org/ACL/ARR/2023/August/Submission{submissions[0].number}/-/Official_Comment", + writers=['aclweb.org/ACL/ARR/2023/August'], + signatures=['aclweb.org/ACL/ARR/2023/August/Program_Chairs'], + note=openreview.api.Note( + replyto=submissions[0].id, + readers=[ + 'aclweb.org/ACL/ARR/2023/August/Program_Chairs', + f'aclweb.org/ACL/ARR/2023/August/Submission{submissions[0].number}/Senior_Area_Chairs', + f'aclweb.org/ACL/ARR/2023/August/Submission{submissions[0].number}/Area_Chairs' + ], + content={ + "comment": { "value": "This is a comment"} + } + ) + ) + + helpers.await_queue_edit(openreview_client, edit_id=comment_edit['id']) + + assert openreview_client.get_messages(to='sac2@aclrollingreview.com', subject='[ARR - August 2023] Program Chairs commented on a paper in your area. Paper Number: 3, Paper Title: "Paper title 3"') + # Close author response pc_client.post_note( openreview.Note( diff --git a/tests/test_icml_conference.py b/tests/test_icml_conference.py index 669e12719..4a2c7cbb3 100644 --- a/tests/test_icml_conference.py +++ b/tests/test_icml_conference.py @@ -5352,7 +5352,7 @@ def test_forum_chat(self, openreview_client, helpers): assert len(openreview_client.get_messages(to='reviewer4@yahoo.com', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 1 assert len(openreview_client.get_messages(to='rachel_bis@icml.cc', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 1 assert len(openreview_client.get_messages(to='ac2@icml.cc', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 1 - assert len(openreview_client.get_messages(to='sac2@icml.cc', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 1 + assert len(openreview_client.get_messages(to='sac2@icml.cc', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 0 assert len(openreview_client.get_messages(to='pc@icml.cc', subject='[ICML 2023] New conversation in committee members chat for submission 1: Paper title 1 Version 2')) == 0 pc_client=openreview.api.OpenReviewClient(username='pc@icml.cc', password=helpers.strong_password)