Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show Answer Details in Assessment Statistics Page (Part 3: Past Answers View) #7135

Open
wants to merge 7 commits into
base: bivan/teacher-stats-past-answer-2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 15 additions & 15 deletions app/controllers/concerns/course/statistics/submissions_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,6 @@ def fetch_hash_for_ancestor_assessment(submissions, students)
def answer_statistics_hash
submission_answer_statistics = Course::Assessment::Answer.find_by_sql(<<-SQL.squish
WITH
attempt_count AS (
SELECT
caa.question_id,
caa.submission_id,
COUNT(*) AS attempt_count
FROM course_assessment_answers caa
JOIN course_assessment_submissions cas ON caa.submission_id = cas.id
WHERE cas.assessment_id = #{assessment_params[:id]}
GROUP BY caa.question_id, caa.submission_id
),

attempt_info AS (
SELECT
caa_ranked.question_id,
Expand All @@ -59,23 +48,34 @@ def answer_statistics_hash
) AS caa_ranked
WHERE caa_ranked.row_num <= 2
GROUP BY caa_ranked.question_id, caa_ranked.submission_id
),

attempt_count AS (
SELECT
caa.question_id,
caa.submission_id,
COUNT(*) AS attempt_count
FROM course_assessment_answers caa
JOIN course_assessment_submissions cas ON caa.submission_id = cas.id
WHERE cas.assessment_id = #{assessment_params[:id]} AND caa.workflow_state != 'attempting'
GROUP BY caa.question_id, caa.submission_id
)

SELECT
CASE WHEN jsonb_array_length(attempt_info.submission_info) = 1 OR attempt_info.submission_info->0->>3 != 'attempting'
THEN attempt_info.submission_info->0->>0 ELSE attempt_info.submission_info->1->>0
END AS last_attempt_answer_id,
attempt_count.question_id,
attempt_count.submission_id,
attempt_info.question_id,
attempt_info.submission_id,
attempt_count.attempt_count,
CASE WHEN jsonb_array_length(attempt_info.submission_info) = 1 OR attempt_info.submission_info->0->>3 != 'attempting'
THEN attempt_info.submission_info->0->>1 ELSE attempt_info.submission_info->1->>1
END AS grade,
CASE WHEN jsonb_array_length(attempt_info.submission_info) = 1 OR attempt_info.submission_info->0->>3 != 'attempting'
THEN attempt_info.submission_info->0->>2 ELSE attempt_info.submission_info->1->>2
END AS correct
FROM attempt_count
JOIN attempt_info
FROM attempt_info
LEFT JOIN attempt_count
ON attempt_count.question_id = attempt_info.question_id AND attempt_count.submission_id = attempt_info.submission_id
SQL
)
Expand Down
53 changes: 53 additions & 0 deletions app/controllers/course/statistics/answers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,68 @@
class Course::Statistics::AnswersController < Course::Statistics::Controller
helper Course::Assessment::Submission::SubmissionsHelper.name.sub(/Helper$/, '')

MAX_ANSWERS_COUNT = 10

def question_answer_details
@answer = Course::Assessment::Answer.find(answer_params[:id])
@submission = @answer.submission
@assessment = @submission.assessment

@submission_question = Course::Assessment::SubmissionQuestion.
where(submission_id: @answer.submission_id, question_id: @answer.question_id).
includes({ discussion_topic: :posts }).first

@all_answers = fetch_all_answers(@answer.submission_id, @answer.question_id)
end

def all_answers
@submission_question = Course::Assessment::SubmissionQuestion.find(submission_question_params[:id])
question_id = @submission_question.question_id
submission_id = @submission_question.submission_id

@question = Course::Assessment::Question.find(question_id)
@submission = Course::Assessment::Submission.find(submission_id)
@assessment = @submission.assessment

@submission_question = Course::Assessment::SubmissionQuestion.
where(submission_id: submission_id, question_id: question_id).
includes({ discussion_topic: :posts }).first
@question_index = question_index(question_id)
@all_answers = Course::Assessment::Answer.
unscope(:order).
order(:created_at).
where(submission_id: submission_id, question_id: question_id)
end

private

def answer_params
params.permit(:id)
end

def submission_question_params
params.permit(:id)
end

def question_index(question_id)
question_ids = Course::QuestionAssessment.
where(assessment_id: @assessment.id).
order(:weight).
pluck(:question_id)

question_ids.index(question_id)
end

def fetch_all_answers(submission_id, question_id)
answers = Course::Assessment::Answer.
unscope(:order).
order(created_at: :desc).
where(submission_id: submission_id, question_id: question_id)

current_answer = answers.find(&:current_answer?)
past_answers = answers.where(current_answer: false).limit(MAX_ANSWERS_COUNT - 1).to_a
past_answers.unshift(current_answer)

past_answers
end
end
7 changes: 7 additions & 0 deletions app/views/course/statistics/answers/_answer.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
specific_answer = answer.specific

json.id answer.id
json.grade answer.grade
json.questionType question.question_type
json.partial! specific_answer, answer: specific_answer, can_grade: false
26 changes: 26 additions & 0 deletions app/views/course/statistics/answers/all_answers.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true
json.question do
json.id @question.id
json.title @question.title
json.maximumGrade @question.maximum_grade
json.description format_ckeditor_rich_text(@question.description)
json.type @question.question_type
json.questionNumber @question_index + 1

json.partial! @question, question: @question.specific, can_grade: false, answer: @all_answers.first
end

json.allAnswers @all_answers do |answer|
json.partial! 'answer', answer: answer, question: @question
json.createdAt answer.created_at&.iso8601
json.currentAnswer answer.current_answer
json.workflowState answer.workflow_state
end

json.submissionId @submission.id

posts = @submission_question.discussion_topic.posts

json.comments posts do |post|
json.partial! post, post: post if post.published?
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,22 @@ json.question do
json.partial! question, question: question.specific, can_grade: false, answer: @answer
end

specific_answer = @answer.specific
json.answer do
json.id @answer.id
json.grade @answer.grade
json.questionType question.question_type
json.partial! specific_answer, answer: specific_answer, can_grade: false
json.partial! 'answer', answer: @answer, question: question
end

json.allAnswers @all_answers do |answer|
json.partial! 'answer', answer: answer, question: question
json.createdAt answer.created_at&.iso8601
json.currentAnswer answer.current_answer
json.workflowState answer.workflow_state
end

posts = @submission_question.discussion_topic.posts

json.comments posts do |post|
json.partial! post, post: post if post.published?
end

json.submissionId @submission.id
json.submissionQuestionId @submission_question.id
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ json.submissions @student_submissions_hash.each do |course_user, (submission, an
json.submissionExists !submission.nil?

unless submission.nil?
json.id submission.id
json.workflowState submission.workflow_state
json.submittedAt submission.submitted_at&.iso8601
json.endAt end_at&.iso8601
Expand All @@ -32,7 +33,7 @@ json.submissions @student_submissions_hash.each do |course_user, (submission, an

json.lastAttemptAnswerId answer.last_attempt_answer_id
json.isAutograded auto_gradable
json.attemptCount answer.attempt_count
json.attemptCount answer.attempt_count || 0
json.correct answer.correct
end

Expand Down
18 changes: 18 additions & 0 deletions client/app/api/course/Statistics/AllAnswerStatistics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { QuestionType } from 'types/course/assessment/question';
import { QuestionAllAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

import { APIResponse } from 'api/types';

import BaseCourseAPI from '../Base';

export default class AllAnswerStatisticsAPI extends BaseCourseAPI {
get #urlPrefix(): string {
return `/courses/${this.courseId}/statistics/submission_question`;
}

fetchAllAnswers(
submissionQuestionId: number,
): APIResponse<QuestionAllAnswerDisplayDetails<keyof typeof QuestionType>> {
return this.client.get(`${this.#urlPrefix}/${submissionQuestionId}`);
}
}
2 changes: 2 additions & 0 deletions client/app/api/course/Statistics/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import AllAnswerStatisticsAPI from './AllAnswerStatistics';
import AnswerStatisticsAPI from './AnswerStatistics';
import AssessmentStatisticsAPI from './AssessmentStatistics';
import CourseStatisticsAPI from './CourseStatistics';
Expand All @@ -6,6 +7,7 @@ import UserStatisticsAPI from './UserStatistics';
const StatisticsAPI = {
assessment: new AssessmentStatisticsAPI(),
answer: new AnswerStatisticsAPI(),
allAnswer: new AllAnswerStatisticsAPI(),
course: new CourseStatisticsAPI(),
user: new UserStatisticsAPI(),
};
Expand Down
10 changes: 10 additions & 0 deletions client/app/bundles/course/assessment/operations/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Operation } from 'store';
import { QuestionType } from 'types/course/assessment/question';
import {
AncestorAssessmentStats,
QuestionAllAnswerDisplayDetails,
QuestionAnswerDetails,
} from 'types/course/statistics/assessmentStatistics';

Expand Down Expand Up @@ -45,3 +46,12 @@ export const fetchQuestionAnswerDetails = async (

return response.data;
};

export const fetchAllAnswers = async (
submissionQuestionId: number,
): Promise<QuestionAllAnswerDisplayDetails<keyof typeof QuestionType>> => {
const response =
await CourseAPI.statistics.allAnswer.fetchAllAnswers(submissionQuestionId);

return response.data;
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { QuestionAnswerDetails } from 'types/course/statistics/assessmentStatistics';
import { QuestionAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

import AttachmentDetails from './AttachmentDetails';

const FileUploadDetails = (
props: QuestionAnswerDetails<'FileUpload'>,
props: QuestionAnswerDisplayDetails<'FileUpload'>,
): JSX.Element => {
const { answer } = props;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineMessages, FormattedMessage } from 'react-intl';
import { Typography } from '@mui/material';
import { QuestionAnswerDetails } from 'types/course/statistics/assessmentStatistics';
import { QuestionAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

import PostPack from './ForumPostResponseComponent/PostPack';

Expand All @@ -13,7 +13,7 @@ const translations = defineMessages({
});

const ForumPostResponseDetails = (
props: QuestionAnswerDetails<'ForumPostResponse'>,
props: QuestionAnswerDisplayDetails<'ForumPostResponse'>,
): JSX.Element => {
const { answer } = props;
const postPacks = answer.fields.selected_post_packs;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { FormControlLabel, Radio, Typography } from '@mui/material';
import { green } from '@mui/material/colors';
import { QuestionAnswerDetails } from 'types/course/statistics/assessmentStatistics';
import { QuestionAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

const MultipleChoiceDetails = (
props: QuestionAnswerDetails<'MultipleChoice'>,
props: QuestionAnswerDisplayDetails<'MultipleChoice'>,
): JSX.Element => {
const { question, answer } = props;
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Checkbox, FormControlLabel, Typography } from '@mui/material';
import { green } from '@mui/material/colors';
import { QuestionAnswerDetails } from 'types/course/statistics/assessmentStatistics';
import { QuestionAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

const MultipleResponseDetails = (
props: QuestionAnswerDetails<'MultipleResponse'>,
props: QuestionAnswerDisplayDetails<'MultipleResponse'>,
): JSX.Element => {
const { question, answer } = props;
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Annotation } from 'types/course/statistics/answer';
import { QuestionAnswerDetails } from 'types/course/statistics/assessmentStatistics';
import { QuestionAnswerDisplayDetails } from 'types/course/statistics/assessmentStatistics';

import CodaveriFeedbackStatus from './ProgrammingComponent/CodaveriFeedbackStatus';
import FileContent from './ProgrammingComponent/FileContent';
import TestCases from './ProgrammingComponent/TestCases';

const ProgrammingAnswerDetails = (
props: QuestionAnswerDetails<'Programming'>,
props: QuestionAnswerDisplayDetails<'Programming'>,
): JSX.Element => {
const { answer } = props;
const annotations = answer.latestAnswer?.annotations ?? ([] as Annotation[]);
Expand Down