Skip to content

Commit

Permalink
Merge branch 'master' into fix/auto-publish
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielCWT authored Aug 22, 2024
2 parents 2e74c6f + e6a9618 commit 1f44bed
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 6 deletions.
135 changes: 132 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: cr in CourseRegistration,
on: s.student_id == cr.id,
as: :cr,
left_join: user in User,
on: user.id == cr.user_id,
as: :user,
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,12 @@ defmodule Cadet.Assessments do
}
)

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

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

submissions = Repo.all(query)

count_query =
Expand All @@ -1987,6 +2008,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, cr, user, group, config] in query,
order_by: fragment("upper(?)", asst.title)
)

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

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

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

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

sort_by == "progressStatus" ->
from([s, ans, asst, cr, user, 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, cr, user, 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, cr, user, group, config] in query,
order_by: [desc: fragment("upper(?)", asst.title)]
)

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

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

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

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

sort_by == "progressStatus" ->
from([s, ans, asst, cr, user, 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, cr, user, 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
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ defmodule Cadet.Mixfile do
{:que, "~> 0.10"},
{:recase, "~> 0.7", override: true},
{:samly, "~> 1.0"},
{:sentry, "~> 8.0"},
{:sentry, "~> 10.6"},
{:sweet_xml, "~> 0.6"},
{:timex, "~> 3.7"},

Expand Down
6 changes: 4 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"nimble_ownership": {:hex, :nimble_ownership, "0.3.2", "d4fa4056ade0ae33b5a9eb64554a1b3779689282e37513260125d2d6b32e4874", [:mix], [], "hexpm", "28b9a9f4094fda1aa8ca72f732ff3223eb54aa3eda4fed9022254de2c152b138"},
"oban": {:hex, :oban, "2.18.0", "092d20bfd3d70c7ecb70960f8548d300b54bb9937c7f2e56b388f3a9ed02ec68", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aace1eff6f8227ae38d4274af967d96f051c2f0a5152f2ef9809dd1f97866745"},
"openai": {:hex, :openai, "0.4.1", "c141283d35fed72eaeee22397f0a3eaa93515283b3a698cd3aa0af9301bb5fc5", [:mix], [{:httpoison, "~> 1.8", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d958993926474362715152d5d4f68444038d53e649641fe1af2fcb26ca8bbe90"},
"openid_connect": {:hex, :openid_connect, "0.2.2", "c05055363330deab39ffd89e609db6b37752f255a93802006d83b45596189c0b", [:mix], [{:httpoison, "~> 1.2", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "735769b6d592124b58edd0582554ce638524c0214cd783d8903d33357d74cc13"},
Expand All @@ -83,13 +85,13 @@
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_cowboy": {:hex, :plug_cowboy, "2.7.1", "87677ffe3b765bc96a89be7960f81703223fe2e21efa42c125fcd0127dd9d6b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "02dbd5f9ab571b864ae39418db7811618506256f6d13b4a45037e5fe78dc5de3"},
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
"postgrex": {:hex, :postgrex, "0.19.0", "f7d50e50cb42e0a185f5b9a6095125a9ab7e4abccfbe2ab820ab9aa92b71dbab", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "dba2d2a0a8637defbf2307e8629cb2526388ba7348f67d04ec77a5d6a72ecfae"},
"postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"},
"quantum": {:hex, :quantum, "3.5.3", "ee38838a07761663468145f489ad93e16a79440bebd7c0f90dc1ec9850776d99", [:mix], [{:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.14 or ~> 1.0", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_registry, "~> 0.2", [hex: :telemetry_registry, repo: "hexpm", optional: false]}], "hexpm", "500fd3fa77dcd723ed9f766d4a175b684919ff7b6b8cfd9d7d0564d58eba8734"},
"que": {:hex, :que, "0.10.1", "788ed0ec92ed69bdf9cfb29bf41a94ca6355b8d44959bd0669cf706e557ac891", [:mix], [{:ex_utils, "~> 0.1.6", [hex: :ex_utils, repo: "hexpm", optional: false]}, {:memento, "~> 0.3.0", [hex: :memento, repo: "hexpm", optional: false]}], "hexpm", "a737b365253e75dbd24b2d51acc1d851049e87baae08cd0c94e2bc5cd65088d5"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"recase": {:hex, :recase, "0.8.1", "ab98cd35857a86fa5ca99036f575241d71d77d9c2ab0c39aacf1c9b61f6f7d1d", [:mix], [], "hexpm", "9fd8d63e7e43bd9ea385b12364e305778b2bbd92537e95c4b2e26fc507d5e4c2"},
"samly": {:hex, :samly, "1.4.0", "58397eb6ca96bf768655723d378e6468f95f752b547aac1504f126bbd7c9fde8", [:mix], [{:esaml, "~> 4.3", [hex: :esaml, repo: "hexpm", optional: false]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: false]}], "hexpm", "9cc53e043cb4508c3df2f9a4e13bc101a6835aded5cd49ee1c931158f7ce1dd6"},
"sentry": {:hex, :sentry, "8.1.0", "8d235b62fce5f8e067ea1644e30939405b71a5e1599d9529ff82899d11d03f2b", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "f9fc7641ef61e885510f5e5963c2948b9de1de597c63f781e9d3d6c9c8681ab4"},
"sentry": {:hex, :sentry, "10.6.2", "a867ab728d424e187ccb2bccc388170a740a79bc0ddccabd72d303b203acbe0e", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "31bb84247274f9262fd300df0e3eb73302e4849cc6b7a6560bb2465f03fbd446"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
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

0 comments on commit 1f44bed

Please sign in to comment.