Skip to content

Commit 4664701

Browse files
committed
fix: update code based on CI comments
1 parent 05c49b9 commit 4664701

21 files changed

Lines changed: 314 additions & 228 deletions

File tree

app/controllers/course/user_invitations_controller.rb

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,20 @@ def aggregate_errors
170170
# @return [Array<String>]
171171
def invalid_course_user_errors
172172
invalid_course_users.flat_map do |course_user|
173+
email = course_user.user&.email || course_user.name
173174
errors = []
174175
if course_user.errors[:external_id].any?
175176
errors << t('errors.course.user_invitations.duplicate_external_id',
176-
external_id: course_user.external_id)
177+
email: email, external_id: course_user.external_id)
177178
end
178-
non_external_id_errors = course_user.errors.reject { |e| e.attribute.to_s == 'external_id' }
179-
if non_external_id_errors.any?
180-
user = self.class.helpers.display_course_user(course_user)
181-
errors << t('errors.course.user_invitations.duplicate_user', user: user)
179+
if course_user.errors[:user].any? || course_user.errors[:course].any?
180+
errors << t('errors.course.user_invitations.already_enrolled', email: email)
181+
end
182+
other_errors = course_user.errors.reject { |e| %w[external_id user course].include?(e.attribute.to_s) }
183+
if other_errors.any?
184+
message = other_errors.map { |e| course_user.errors.full_message(e.attribute, e.message) }.
185+
to_sentence
186+
errors << t('errors.course.user_invitations.other_error', email: email, message: message)
182187
end
183188
errors
184189
end
@@ -196,15 +201,24 @@ def invalid_course_users
196201
# @return [Array<String>]
197202
def invalid_invitation_email_errors
198203
invalid_invitations.flat_map do |invitation|
204+
email = invitation.email
199205
errors = []
200206
if invitation.errors[:external_id].any?
201207
errors << t('errors.course.user_invitations.duplicate_external_id',
202-
external_id: invitation.external_id)
208+
email: email, external_id: invitation.external_id)
209+
end
210+
if invitation.errors[:email].any?
211+
message = invitation.errors[:email].to_sentence
212+
errors << t('errors.course.user_invitations.invalid_email', email: email, message: message)
213+
end
214+
if invitation.errors[:base].any?
215+
errors << t('errors.course.user_invitations.duplicate_invitation', email: email)
203216
end
204-
non_external_id_errors = invitation.errors.reject { |e| e.attribute.to_s == 'external_id' }
205-
if non_external_id_errors.any?
206-
message = non_external_id_errors.map { |e| invitation.errors.full_message(e.attribute, e.message) }.to_sentence
207-
errors << t('errors.course.user_invitations.invalid_email', email: invitation.email, message: message)
217+
other_errors = invitation.errors.reject { |e| %w[external_id email base].include?(e.attribute.to_s) }
218+
if other_errors.any?
219+
message = other_errors.map { |e| invitation.errors.full_message(e.attribute, e.message) }.
220+
to_sentence
221+
errors << t('errors.course.user_invitations.other_error', email: email, message: message)
208222
end
209223
errors
210224
end

app/services/concerns/course/user_invitation_service/parse_invitation_concern.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ def parse_file_phantom(phantom)
182182
TRUE_VALUES.include?(phantom.downcase)
183183
end
184184

185-
# Parses file value for external ID of a student.
186-
# Sets external_id as nil if value is not specified.
185+
# Parses file value for an invitation's timeline algorithm.
186+
# Sets timeline algorithm as course default if value is not specified.
187187
#
188-
# @param [String|nil] External ID as specified in the CSV file.
188+
# @param [String|nil] Timeline algorithm as specified in the CSV file.
189189
# @return [Integer] The enum integer for +Course::UserInvitation.timeline_algorithm+ matching the input.
190190
# current_course.default_timeline_algorithm is returned by default.
191191
def parse_file_timeline_algorithm(timeline_algorithm)

app/services/course/user_registration_service.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def find_or_create_course_user!(registration, invitation = nil)
5252
role = invitation.try(:role) || :student
5353
phantom = invitation.try(:phantom) || false
5454
timeline_algorithm = invitation.try(:timeline_algorithm) || registration.course.default_timeline_algorithm
55-
external_id = invitation.try(:external_id)
55+
external_id = invitation.try(:external_id) || nil
5656

5757
registration.course_user =
5858
CourseUser.find_or_create_by!(course: registration.course, user: registration.user,

client/app/bundles/course/user-invitations/components/buttons/InvitationActionButtons.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const translations = defineMessages({
4646
id: 'course.userInvitations.InvitationActionButtons.deletionFailure',
4747
defaultMessage: 'Failed to delete user - {error}',
4848
},
49+
deletionFailureGeneric: {
50+
id: 'course.userInvitations.InvitationActionButtons.deletionFailureGeneric',
51+
defaultMessage: 'Failed to delete user.',
52+
},
4953
});
5054

5155
const InvitationActionButtons: FC<Props> = (props) => {
@@ -89,9 +93,11 @@ const InvitationActionButtons: FC<Props> = (props) => {
8993
if (Array.isArray(rawErrors)) errorList = rawErrors;
9094
else if (typeof rawErrors === 'string') errorList = [rawErrors];
9195
else errorList = [];
92-
toast.error(
93-
t(translations.deletionFailure, { error: errorList[0] ?? '' }),
94-
);
96+
if (errorList[0]) {
97+
toast.error(t(translations.deletionFailure, { error: errorList[0] }));
98+
} else {
99+
toast.error(t(translations.deletionFailureGeneric));
100+
}
95101
throw error;
96102
});
97103
};

client/app/bundles/course/user-invitations/pages/InviteUsersFileUpload/index.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ const translations = defineMessages({
8484
defaultMessage:
8585
'Failed to invite users. Please ensure your data is formatted correctly - {error}',
8686
},
87+
failureGeneric: {
88+
id: 'course.userInvitations.InviteUsersFileUpload.failureGeneric',
89+
defaultMessage:
90+
'Failed to invite users. Please ensure your data is formatted correctly.',
91+
},
8792
});
8893

8994
const InviteUsersFileUpload: FC<Props> = (props) => {
@@ -112,12 +117,16 @@ const InviteUsersFileUpload: FC<Props> = (props) => {
112117
if (Array.isArray(rawErrors)) errorList = rawErrors;
113118
else if (typeof rawErrors === 'string') errorList = [rawErrors];
114119
else errorList = [];
115-
const first = errorList[0] ?? '';
120+
const first = errorList[0];
116121
const overflow =
117122
errorList.length > 1 ? ` (and ${errorList.length - 1} more)` : '';
118-
toast.error(t(translations.failure, { error: first + overflow }), {
119-
autoClose: false,
120-
});
123+
if (first) {
124+
toast.error(t(translations.failure, { error: first + overflow }), {
125+
autoClose: false,
126+
});
127+
} else {
128+
toast.error(t(translations.failureGeneric), { autoClose: false });
129+
}
121130
});
122131
};
123132

client/app/bundles/course/users/components/tables/ManageUsersTable/ExternalIdField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const ExternalIdField = (props: ExternalIdFieldProps): JSX.Element => {
5858
<InlineEditTextField
5959
key={user.id}
6060
allowEmpty
61-
className="course_user_external_id text-neutral-400"
61+
className="course_user_external_id"
6262
onUpdate={(newId): Promise<void> => handleIdUpdate(newId)}
6363
updateValue={(): void => {}}
6464
value={user.externalId ?? ''}

client/app/bundles/course/users/components/tables/ManageUsersTable/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const ManageUsersTable = (props: ManageUsersTableProps): JSX.Element => {
6363
of: 'externalId',
6464
title: t(tableTranslations.externalId),
6565
sortable: false,
66-
searchable: false,
66+
searchable: true,
6767
cell: (user) => <ExternalIdField for={user} />,
6868
csvDownloadable: true,
6969
},

client/app/types/course/userInvitations.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export interface InvitationPostData {
3535
id?: string | undefined;
3636
name: string;
3737
email: string;
38+
externalId?: string | null;
3839
role: string;
3940
phantom: boolean;
4041
timelineAlgorithm?: string | undefined;
@@ -45,6 +46,7 @@ export interface InvitationsPostData {
4546
id?: string | undefined;
4647
name: string;
4748
email: string;
49+
externalId?: string | null;
4850
role: string;
4951
phantom: boolean;
5052
timelineAlgorithm?: string | undefined;

client/locales/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6945,6 +6945,9 @@
69456945
"course.userInvitations.InviteUsersFileUpload.failure": {
69466946
"defaultMessage": "Failed to invite users. Please ensure your data is formatted correctly - {error}"
69476947
},
6948+
"course.userInvitations.InviteUsersFileUpload.failureGeneric": {
6949+
"defaultMessage": "Failed to invite users. Please ensure your data is formatted correctly."
6950+
},
69486951
"course.userInvitations.InviteUsersFileUpload.fileUploadExample": {
69496952
"defaultMessage": "Name,Email,Role,Phantom,ExternalId{br}John,test1@example.org,student,y,A0123456{br}Mary,test2@example.org,teaching_assistant,n,A0123457"
69506953
},
@@ -6984,6 +6987,9 @@
69846987
"course.userInvitations.InvitationActionButtons.deletionFailure": {
69856988
"defaultMessage": "Failed to delete user - {error}"
69866989
},
6990+
"course.userInvitations.InvitationActionButtons.deletionFailureGeneric": {
6991+
"defaultMessage": "Failed to delete user."
6992+
},
69876993
"course.userInvitations.InvitationActionButtons.deletionSuccess": {
69886994
"defaultMessage": "Invitation for {name} was deleted."
69896995
},

client/locales/ko.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6935,6 +6935,9 @@
69356935
"course.userInvitations.InviteUsersFileUpload.failure": {
69366936
"defaultMessage": "사용자 초대에 실패했습니다. 데이터가 올바르게 형식화되었는지 확인하세요 - {error}"
69376937
},
6938+
"course.userInvitations.InviteUsersFileUpload.failureGeneric": {
6939+
"defaultMessage": "사용자 초대에 실패했습니다. 데이터가 올바르게 형식화되었는지 확인하세요."
6940+
},
69386941
"course.userInvitations.InviteUsersFileUpload.fileUploadExample": {
69396942
"defaultMessage": "이름,이메일,역할,팬텀,외부 ID{br}John,test1@example.org,학생,y,A0123456{br}Mary,test2@example.org,티칭 어시스턴트,n,A0123457"
69406943
},

0 commit comments

Comments
 (0)