Files
codeocean/app/views/exercises/statistics.html.slim
Sebastian Serth a99da79550 Disable sorttable on tables without rows
Otherwise, the first element of the table body is being fetched which might result in an error for empty tables.

Fixes CODEOCEAN-JZ
2023-03-14 18:27:38 +01:00

92 lines
4.0 KiB
Plaintext

- content_for :head do
// Force a full page reload, see https://github.com/turbolinks/turbolinks/issues/326.
Otherwise, code might not be highlighted correctly (race condition)
meta name='turbolinks-visit-control' content='reload'
- append_javascript_pack_tag('d3-tip')
h1 = @exercise
= row(label: '.participants', value: @exercise.users.distinct.count)
- [:intermediate, :final].each do |scope|
= row(label: ".#{scope}_submissions") do
= "#{@exercise.submissions.send(scope).count} (#{t('.users', count: @exercise.submissions.send(scope).distinct.count(:user_id))})"
= row(label: '.finishing_rate') do
p
- if @exercise.finishers.count
span.number
= @exercise.finishers.count
=<> t('shared.out_of')
span.number
= @exercise.users.distinct.count
=< t('exercises.statistics.external_users')
- else
= empty
- finishers_count = @exercise.users.distinct.count
- finishers_percentage = finishers_count == 0 ? 0 : (100.0 / finishers_count * @exercise.finishers.count).round(2)
p = progress_bar(finishers_percentage)
= row(label: '.average_score') do
p
- if @exercise.average_score
span.number
= @exercise.average_score.round(2)
=<> t('shared.out_of')
span.number
= @exercise.maximum_score
- else
= empty
p = progress_bar(@exercise.average_percentage)
- if policy(@exercise).detailed_statistics?
= row(label: '.average_worktime') do
p = @exercise.average_working_time
- Hash[:internal_users => t('.internal_users'), :external_users => t('.external_users')].each_pair do |symbol, label|
- if symbol==:internal_users && current_user.admin?
strong = label
- if symbol==:external_users
- working_time_array = []
- @exercise.send(symbol).distinct().each do |user|
- working_time = @exercise.average_working_time_for(user) or 0
- working_time_array.push working_time
hr
.d-none#data data-working-time=ActiveSupport::JSON.encode(working_time_array)
.working-time-graphs
div#chart_1
hr
div#chart_2
hr
- submissions = Submission.where(user: @exercise.send(symbol).distinct, exercise: @exercise).in_study_group_of(current_user)
- if !policy(@exercise).detailed_statistics?
- submissions = submissions.final
- if submissions.any?
- users = symbol.to_s.classify.constantize.where(id: submissions.joins(symbol).group(:user_id).select(:user_id).distinct)
.table-responsive
table.table.table-striped class="#{users.present? ? 'sortable' : ''}"
thead
tr
th.header = t('.user')
th.header = t('.score')
th.header = t('.deadline')
th.header = t('.runs') if policy(@exercise).detailed_statistics?
th.header = t('.worktime') if policy(@exercise).detailed_statistics?
tbody
- users.each do |user|
- if user_statistics[user.class.name][user.id] then us = user_statistics[user.class.name][user.id] else us = {"maximum_score" => nil, "runs" => nil}
- label = "#{user.displayname}"
tr
td = link_to_if symbol==:external_users && policy(user).statistics?, label, {controller: "exercises", action: "external_user_statistics", external_user_id: user.id, id: @exercise.id}
td = us['maximum_score'] or 0
td.align-middle
- latest_user_submission = submissions.where(user: user).final.latest
- if latest_user_submission.present?
- if latest_user_submission.before_deadline?
.unit-test-result.positive-result.before_deadline
- elsif latest_user_submission.within_grace_period?
.unit-test-result.unknown-result.within_grace_period
- elsif latest_user_submission.after_late_deadline?
.unit-test-result.negative-result.after_late_deadline
td = us['runs'] if policy(@exercise).detailed_statistics?
td = @exercise.average_working_time_for(user) or 0 if policy(@exercise).detailed_statistics?