use of teammates.common.datatransfer.questions.FeedbackQuestionDetails in project teammates by TEAMMATES.
the class FeedbackQuestionsLogicTest method testCopyQuestion.
private void testCopyQuestion() throws Exception {
InstructorAttributes instructor2OfCourse1 = dataBundle.instructors.get("instructor2OfCourse1");
______TS("Typical case: copy question successfully");
FeedbackQuestionAttributes question1 = dataBundle.feedbackQuestions.get("qn1InSession1InCourse1");
question1 = fqLogic.getFeedbackQuestion(question1.feedbackSessionName, question1.courseId, question1.questionNumber);
FeedbackQuestionAttributes copiedQuestion = fqLogic.copyFeedbackQuestion(question1.getId(), question1.feedbackSessionName, question1.courseId, instructor2OfCourse1.email);
FeedbackQuestionDetails question1Details = question1.getQuestionDetails();
FeedbackQuestionDetails copiedQuestionDetails = copiedQuestion.getQuestionDetails();
assertEquals(question1.numberOfEntitiesToGiveFeedbackTo, copiedQuestion.numberOfEntitiesToGiveFeedbackTo);
assertEquals(question1.questionType, copiedQuestion.questionType);
assertEquals(question1.giverType, copiedQuestion.giverType);
assertEquals(question1.recipientType, copiedQuestion.recipientType);
assertEquals(question1Details.getQuestionText(), copiedQuestionDetails.getQuestionText());
}
use of teammates.common.datatransfer.questions.FeedbackQuestionDetails in project teammates by TEAMMATES.
the class FeedbackQuestionsDbTest method testUpdateFeedbackQuestion.
@Test
public void testUpdateFeedbackQuestion() throws Exception {
______TS("null params");
try {
fqDb.updateFeedbackQuestion(null);
signalFailureToDetectException();
} catch (AssertionError e) {
AssertHelper.assertContains(Const.StatusCodes.DBLEVEL_NULL_INPUT, e.getLocalizedMessage());
}
______TS("invalid feedback question attributes");
FeedbackQuestionAttributes invalidFqa = getNewFeedbackQuestionAttributes();
fqDb.deleteEntity(invalidFqa);
fqDb.createEntity(invalidFqa);
invalidFqa.setId(fqDb.getFeedbackQuestion(invalidFqa.feedbackSessionName, invalidFqa.courseId, invalidFqa.questionNumber).getId());
invalidFqa.creatorEmail = "haha";
try {
fqDb.updateFeedbackQuestion(invalidFqa);
signalFailureToDetectException();
} catch (InvalidParametersException e) {
AssertHelper.assertContains("Invalid creator's email", e.getLocalizedMessage());
}
______TS("feedback session does not exist");
FeedbackQuestionAttributes nonexistantFq = getNewFeedbackQuestionAttributes();
nonexistantFq.setId("non-existent fq id");
try {
fqDb.updateFeedbackQuestion(nonexistantFq);
signalFailureToDetectException();
} catch (EntityDoesNotExistException e) {
AssertHelper.assertContains(FeedbackQuestionsDb.ERROR_UPDATE_NON_EXISTENT, e.getLocalizedMessage());
}
______TS("standard success case");
FeedbackQuestionAttributes modifiedQuestion = getNewFeedbackQuestionAttributes();
fqDb.deleteEntity(modifiedQuestion);
fqDb.createEntity(modifiedQuestion);
verifyPresentInDatastore(modifiedQuestion);
modifiedQuestion = fqDb.getFeedbackQuestion(modifiedQuestion.feedbackSessionName, modifiedQuestion.courseId, modifiedQuestion.questionNumber);
FeedbackQuestionDetails fqd = modifiedQuestion.getQuestionDetails();
fqd.setQuestionText("New question text!");
modifiedQuestion.setQuestionDetails(fqd);
fqDb.updateFeedbackQuestion(modifiedQuestion);
verifyPresentInDatastore(modifiedQuestion);
modifiedQuestion = fqDb.getFeedbackQuestion(modifiedQuestion.feedbackSessionName, modifiedQuestion.courseId, modifiedQuestion.questionNumber);
assertEquals("New question text!", modifiedQuestion.getQuestionDetails().getQuestionText());
fqDb.deleteEntity(modifiedQuestion);
}
use of teammates.common.datatransfer.questions.FeedbackQuestionDetails in project teammates by TEAMMATES.
the class InstructorFeedbackQuestionEditAction method editQuestion.
private void editQuestion(FeedbackQuestionAttributes updatedQuestion) throws InvalidParametersException, EntityDoesNotExistException {
String err = validateQuestionGiverRecipientVisibility(updatedQuestion);
if (!err.isEmpty()) {
statusToUser.add(new StatusMessage(err, StatusMessageColor.DANGER));
isError = true;
}
FeedbackQuestionDetails updatedQuestionDetails = updatedQuestion.getQuestionDetails();
List<String> questionDetailsErrors = updatedQuestionDetails.validateQuestionDetails();
List<StatusMessage> questionDetailsErrorsMessages = new ArrayList<>();
for (String error : questionDetailsErrors) {
questionDetailsErrorsMessages.add(new StatusMessage(error, StatusMessageColor.DANGER));
}
if (questionDetailsErrors.isEmpty()) {
logic.updateFeedbackQuestionNumber(updatedQuestion);
statusToUser.add(new StatusMessage(Const.StatusMessages.FEEDBACK_QUESTION_EDITED, StatusMessageColor.SUCCESS));
statusToAdmin = "Feedback Question " + updatedQuestion.questionNumber + " for session:<span class=\"bold\">(" + updatedQuestion.feedbackSessionName + ")</span> for Course <span class=\"bold\">[" + updatedQuestion.courseId + "]</span> edited.<br>" + "<span class=\"bold\">" + updatedQuestionDetails.getQuestionTypeDisplayName() + ":</span> " + SanitizationHelper.sanitizeForHtml(updatedQuestionDetails.getQuestionText());
} else {
statusToUser.addAll(questionDetailsErrorsMessages);
isError = true;
}
}
use of teammates.common.datatransfer.questions.FeedbackQuestionDetails in project teammates by TEAMMATES.
the class InstructorFeedbackQuestionEditAction method validateQuestionGiverRecipientVisibility.
/**
* Validates that the giver and recipient for the given FeedbackQuestionAttributes is valid for its question type.
* Validates that the visibility for the given FeedbackQuestionAttributes is valid for its question type.
*
* @return error message detailing the error, or an empty string if valid.
*/
public static String validateQuestionGiverRecipientVisibility(FeedbackQuestionAttributes feedbackQuestionAttributes) {
String errorMsg = "";
FeedbackQuestionDetails questionDetails = null;
Class<? extends FeedbackQuestionDetails> questionDetailsClass = feedbackQuestionAttributes.questionType.getQuestionDetailsClass();
Constructor<? extends FeedbackQuestionDetails> questionDetailsClassConstructor;
try {
questionDetailsClassConstructor = questionDetailsClass.getConstructor();
questionDetails = questionDetailsClassConstructor.newInstance();
Method m = questionDetailsClass.getMethod("validateGiverRecipientVisibility", FeedbackQuestionAttributes.class);
errorMsg = (String) m.invoke(questionDetails, feedbackQuestionAttributes);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {
log.severe(TeammatesException.toStringWithStackTrace(e));
// Assumption.fails are not tested
Assumption.fail("Failed to instantiate Feedback*QuestionDetails instance for " + feedbackQuestionAttributes.questionType.toString() + " question type.");
}
return errorMsg;
}
use of teammates.common.datatransfer.questions.FeedbackQuestionDetails in project teammates by TEAMMATES.
the class FeedbackSubmissionEditSaveAction method execute.
@Override
protected ActionResult execute() throws EntityDoesNotExistException {
courseId = getRequestParamValue(Const.ParamsNames.COURSE_ID);
feedbackSessionName = getRequestParamValue(Const.ParamsNames.FEEDBACK_SESSION_NAME);
Assumption.assertPostParamNotNull(Const.ParamsNames.COURSE_ID, courseId);
Assumption.assertPostParamNotNull(Const.ParamsNames.FEEDBACK_SESSION_NAME, feedbackSessionName);
setAdditionalParameters();
verifyAccessibleForSpecificUser();
String userEmailForCourse = getUserEmailForCourse();
data = new FeedbackSubmissionEditPageData(account, student, sessionToken);
data.bundle = getDataBundle(userEmailForCourse);
Assumption.assertNotNull("Feedback session " + feedbackSessionName + " does not exist in " + courseId + ".", data.bundle);
checkAdditionalConstraints();
setStatusToAdmin();
if (!isSessionOpenForSpecificUser(data.bundle.feedbackSession)) {
isError = true;
statusToUser.add(new StatusMessage(Const.StatusMessages.FEEDBACK_SUBMISSIONS_NOT_OPEN, StatusMessageColor.WARNING));
return createSpecificRedirectResult();
}
String userTeamForCourse = getUserTeamForCourse();
String userSectionForCourse = getUserSectionForCourse();
int numOfQuestionsToGet = data.bundle.questionResponseBundle.size();
for (int questionIndx = 1; questionIndx <= numOfQuestionsToGet; questionIndx++) {
String totalResponsesForQuestion = getRequestParamValue(Const.ParamsNames.FEEDBACK_QUESTION_RESPONSETOTAL + "-" + questionIndx);
if (totalResponsesForQuestion == null) {
// question has been skipped (not displayed).
continue;
}
List<FeedbackResponseAttributes> responsesForQuestion = new ArrayList<>();
String questionId = getRequestParamValue(Const.ParamsNames.FEEDBACK_QUESTION_ID + "-" + questionIndx);
FeedbackQuestionAttributes questionAttributes = data.bundle.getQuestionAttributes(questionId);
if (questionAttributes == null) {
statusToUser.add(new StatusMessage("The feedback session or questions may have changed " + "while you were submitting. Please check your responses " + "to make sure they are saved correctly.", StatusMessageColor.WARNING));
isError = true;
log.warning("Question not found. (deleted or invalid id passed?) id: " + questionId + " index: " + questionIndx);
continue;
}
FeedbackQuestionDetails questionDetails = questionAttributes.getQuestionDetails();
int numOfResponsesToGet = Integer.parseInt(totalResponsesForQuestion);
Set<String> emailSet = data.bundle.getRecipientEmails(questionAttributes.getId());
emailSet.add("");
emailSet = SanitizationHelper.desanitizeFromHtml(emailSet);
ArrayList<String> responsesRecipients = new ArrayList<>();
List<String> errors = new ArrayList<>();
for (int responseIndx = 0; responseIndx < numOfResponsesToGet; responseIndx++) {
FeedbackResponseAttributes response = extractFeedbackResponseData(requestParameters, questionIndx, responseIndx, questionAttributes);
if (response.feedbackQuestionType != questionAttributes.questionType) {
errors.add(String.format(Const.StatusMessages.FEEDBACK_RESPONSES_WRONG_QUESTION_TYPE, questionIndx));
}
boolean isExistingResponse = response.getId() != null;
// came from the original set of existing responses loaded on the submission page
if (isExistingResponse && !isExistingResponseValid(response)) {
errors.add(String.format(Const.StatusMessages.FEEDBACK_RESPONSES_INVALID_ID, questionIndx));
continue;
}
responsesRecipients.add(response.recipient);
// if the answer is not empty but the recipient is empty
if (response.recipient.isEmpty() && !response.responseMetaData.getValue().isEmpty()) {
errors.add(String.format(Const.StatusMessages.FEEDBACK_RESPONSES_MISSING_RECIPIENT, questionIndx));
}
if (response.responseMetaData.getValue().isEmpty()) {
// deletes the response since answer is empty
addToPendingResponses(response);
} else {
response.giver = questionAttributes.giverType.isTeam() ? userTeamForCourse : userEmailForCourse;
response.giverSection = userSectionForCourse;
responsesForQuestion.add(response);
}
}
List<String> questionSpecificErrors = questionDetails.validateResponseAttributes(responsesForQuestion, data.bundle.recipientList.get(questionId).size());
errors.addAll(questionSpecificErrors);
if (!emailSet.containsAll(responsesRecipients)) {
errors.add(String.format(Const.StatusMessages.FEEDBACK_RESPONSE_INVALID_RECIPIENT, questionIndx));
}
if (errors.isEmpty()) {
for (FeedbackResponseAttributes response : responsesForQuestion) {
addToPendingResponses(response);
}
} else {
List<StatusMessage> errorMessages = new ArrayList<>();
for (String error : errors) {
errorMessages.add(new StatusMessage(error, StatusMessageColor.DANGER));
}
statusToUser.addAll(errorMessages);
isError = true;
}
}
saveNewReponses(responsesToSave);
deleteResponses(responsesToDelete);
updateResponses(responsesToUpdate);
if (!isError) {
statusToUser.add(new StatusMessage(Const.StatusMessages.FEEDBACK_RESPONSES_SAVED, StatusMessageColor.SUCCESS));
}
if (isUserRespondentOfSession()) {
appendRespondent();
} else {
removeRespondent();
}
boolean isSubmissionEmailRequested = "on".equals(getRequestParamValue(Const.ParamsNames.SEND_SUBMISSION_EMAIL));
if (!isError && isSendSubmissionEmail && isSubmissionEmailRequested) {
FeedbackSessionAttributes session = logic.getFeedbackSession(feedbackSessionName, courseId);
Assumption.assertNotNull(session);
String user = account == null ? null : account.googleId;
String unregisteredStudentEmail = student == null ? null : student.email;
String unregisteredStudentRegisterationKey = student == null ? null : student.key;
StudentAttributes student = null;
InstructorAttributes instructor = null;
if (user != null) {
student = logic.getStudentForGoogleId(courseId, user);
instructor = logic.getInstructorForGoogleId(courseId, user);
}
if (student == null && unregisteredStudentEmail != null) {
student = StudentAttributes.builder("", unregisteredStudentEmail, unregisteredStudentEmail).withKey(unregisteredStudentRegisterationKey).build();
}
Assumption.assertFalse(student == null && instructor == null);
try {
EmailWrapper email = instructor == null ? new EmailGenerator().generateFeedbackSubmissionConfirmationEmailForStudent(session, student, Instant.now()) : new EmailGenerator().generateFeedbackSubmissionConfirmationEmailForInstructor(session, instructor, Instant.now());
emailSender.sendEmail(email);
} catch (EmailSendingException e) {
log.severe("Submission confirmation email failed to send: " + TeammatesException.toStringWithStackTrace(e));
}
}
// TODO: Refactor to AjaxResult so status messages do not have to be passed by session
return createSpecificRedirectResult();
}
Aggregations