Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f6efd14
handled backend sorting
thortol Apr 8, 2024
7ba8681
fixed sorting by inserted_at
thortol Apr 8, 2024
5e9d582
removed unused code
thortol Apr 8, 2024
d258d80
changed inner_join to left_join
thortol Apr 8, 2024
91c9713
added new tests
thortol Apr 8, 2024
702092b
fixed formatting
thortol Apr 8, 2024
fb70883
reformatted code
thortol Apr 8, 2024
6dc40de
added more test
thortol Apr 8, 2024
c32bc42
added more tests
thortol Apr 9, 2024
b311ee5
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Apr 14, 2024
eefb1a4
updated grading sorter for progressStatus
thortol Apr 14, 2024
7bb5ad6
Merge branch 'master' into add-sorting-for-grading
InfinityTwo Apr 15, 2024
82e7833
fixed test
thortol Apr 15, 2024
853aa2a
fixed sorting by group bug and made sorting work regardless of upper …
thortol Apr 15, 2024
fc87f68
fixed formatting
thortol Apr 15, 2024
06154b6
fixed bug where xp was not sorted properly
thortol Apr 16, 2024
0412aee
fixed sorting by grading bug
thortol Apr 16, 2024
c624803
fixed test
thortol Apr 16, 2024
eb61277
Merge branch 'master' into add-sorting-for-grading
RichDom2185 May 5, 2024
8feda64
Merge branch 'master' into add-sorting-for-grading
thortol May 9, 2024
021ef57
Merge branch 'master' into add-sorting-for-grading
lhw-1 May 15, 2024
2506570
Merge branch 'master' into add-sorting-for-grading
RichDom2185 May 19, 2024
b1c1061
Merge branch 'master' into add-sorting-for-grading
thortol May 21, 2024
50682b6
Merge branch 'master' into add-sorting-for-grading
lhw-1 Aug 6, 2024
4b268fb
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Aug 11, 2024
8c884bf
Merge branch 'master' into add-sorting-for-grading
RichDom2185 Aug 19, 2024
415cdc0
Prefer piping
RichDom2185 Aug 19, 2024
a4e4858
Reduce nesting
RichDom2185 Aug 19, 2024
842cef1
Revert "Prefer piping"
RichDom2185 Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 130 additions & 3 deletions lib/cadet/assessments/assessments.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1906,7 +1906,9 @@ defmodule Cadet.Assessments do
"group" => "false",
"isFullyGraded" => "false",
"pageSize" => "10",
"offset" => "0"
"offset" => "0",
"sortBy" => "",
"sortDirection" => ""
}
) do
submission_answers_query =
Expand All @@ -1927,7 +1929,9 @@ defmodule Cadet.Assessments do
on: q.assessment_id == a.id,
select: %{
assessment_id: q.assessment_id,
question_count: count(q.id)
question_count: count(q.id),
title: max(a.title),
config_id: max(a.config_id)
}
)

Expand All @@ -1939,12 +1943,23 @@ defmodule Cadet.Assessments do
left_join: asst in subquery(question_answers_query),
on: asst.assessment_id == s.assessment_id,
as: :asst,
left_join: user in User,
on: user.id == s.student_id,
as: :user,
left_join: cr in CourseRegistration,
on: user.id == cr.user_id,
as: :cr,
left_join: group in Group,
on: cr.group_id == group.id,
as: :group,
inner_join: config in AssessmentConfig,
on: asst.config_id == config.id,
as: :config,
where: ^build_user_filter(params),
where: s.assessment_id in subquery(build_assessment_filter(params, course_id)),
where: s.assessment_id in subquery(build_assessment_config_filter(params)),
where: ^build_submission_filter(params),
where: ^build_course_registration_filter(params, grader),
order_by: [desc: s.inserted_at],
limit: ^elem(Integer.parse(Map.get(params, "pageSize", "10")), 0),
offset: ^elem(Integer.parse(Map.get(params, "offset", "0")), 0),
select: %{
Expand All @@ -1964,6 +1979,10 @@ defmodule Cadet.Assessments do
}
)

query =
sort_submission(query, Map.get(params, "sortBy", ""), Map.get(params, "sortDirection", ""))

query = from([s, ans, asst, user, cr, group] in query, order_by: [desc: s.inserted_at])
submissions = Repo.all(query)

count_query =
Expand All @@ -1987,6 +2006,114 @@ defmodule Cadet.Assessments do
{:ok, %{count: count, data: generate_grading_summary_view_model(submissions, course_id)}}
end

# Given a query from submissions_by_grader_for_index,
# sorts it by the relevant field and direction
# sort_by is a string of either "", "assessmentName", "assessmentType", "studentName",
# "studentUsername", "groupName", "progressStatus", "xp"
# sort_direction is a string of either "", "sort-asc", "sort-desc"
defp sort_submission(query, sort_by, sort_direction) do
cond do
sort_direction == "sort-asc" ->
sort_submission_asc(query, sort_by)

sort_direction == "sort-desc" ->
sort_submission_desc(query, sort_by)

true ->
query
end
end

defp sort_submission_asc(query, sort_by) do
cond do
sort_by == "assessmentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", asst.title)
)

sort_by == "assessmentType" ->
from([s, ans, asst, user, cr, group, config] in query, order_by: asst.config_id)

sort_by == "studentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", user.name)
)

sort_by == "studentUsername" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", user.username)
)

sort_by == "groupName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: fragment("upper(?)", group.name)
)

sort_by == "progressStatus" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [
asc: config.is_manually_graded,
asc: s.status,
asc: ans.graded_count - asst.question_count,
asc: s.is_grading_published
]
)

sort_by == "xp" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: ans.xp + ans.xp_adjustment
)

true ->
query
end
end

defp sort_submission_desc(query, sort_by) do
cond do
sort_by == "assessmentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", asst.title)]
)

sort_by == "assessmentType" ->
from([s, ans, asst, user, cr, group, config] in query, order_by: [desc: asst.config_id])

sort_by == "studentName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", user.name)]
)

sort_by == "studentUsername" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", user.username)]
)

sort_by == "groupName" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: fragment("upper(?)", group.name)]
)

sort_by == "progressStatus" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [
desc: config.is_manually_graded,
desc: s.status,
desc: ans.graded_count - asst.question_count,
desc: s.is_grading_published
]
)

sort_by == "xp" ->
from([s, ans, asst, user, cr, group, config] in query,
order_by: [desc: ans.xp + ans.xp_adjustment]
)

true ->
query
end
end

defp build_assessment_filter(params, course_id) do
assessments_filters =
Enum.reduce(params, dynamic(true), fn
Expand Down
182 changes: 182 additions & 0 deletions test/cadet/assessments/assessments_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2815,6 +2815,188 @@ defmodule Cadet.AssessmentsTest do
assert Enum.find(assessments_from_res, fn a -> a.id == s.assessment_id end) != nil
end)
end

test "sorting by assessment title ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentName",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_title =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_title,
fn x, y ->
assert x.title >= y.title
y
end
)
end

test "sorting by assessment title descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentName",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_title =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_title,
fn x, y ->
assert x.title <= y.title
y
end
)
end

test "sorting by assessment type ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentType",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_assessments_type =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_assessments_type,
fn x, y ->
assert x.config_id >= y.config_id
y
end
)
end

test "sorting by assessment type descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "assessmentType",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]
assessments_from_res = res[:data][:assessments]

submissions_by_assessments_type =
Enum.map(
submissions_from_res,
fn s ->
Enum.find(assessments_from_res, fn a ->
s.assessment_id == a.id
end)
end
)

Enum.reduce(
submissions_by_assessments_type,
fn x, y ->
assert x.config_id <= y.config_id
y
end
)
end

test "sorting by xp ascending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "xp",
"sortDirection" => "sort-asc"
})

submissions_from_res = res[:data][:submissions]

Enum.reduce(
submissions_from_res,
fn x, y ->
assert x.xp >= y.xp
y
end
)
end

test "sorting by xp descending", %{
course_regs: %{avenger1_cr: avenger},
assessments: _assessments,
total_submissions: total_submissions
} do
{_, res} =
Assessments.submissions_by_grader_for_index(avenger, %{
"pageSize" => total_submissions,
"sortBy" => "xp",
"sortDirection" => "sort-desc"
})

submissions_from_res = res[:data][:submissions]

Enum.reduce(
submissions_from_res,
fn x, y ->
assert x.xp <= y.xp
y
end
)
end
end

describe "is_fully_autograded? function" do
Expand Down