Apply automatic rubocop fixes
This commit is contained in:
@ -1,15 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ActionCableHelper
|
||||
def trigger_rfc_action_cable
|
||||
Thread.new do
|
||||
# Context: RfC
|
||||
if submission.study_group_id.present?
|
||||
ActionCable.server.broadcast(
|
||||
"la_exercises_#{exercise_id}_channel_study_group_#{submission.study_group_id}",
|
||||
type: :rfc,
|
||||
id: id,
|
||||
html: ApplicationController.render(partial: 'request_for_comments/list_entry',
|
||||
locals: {request_for_comment: self}))
|
||||
"la_exercises_#{exercise_id}_channel_study_group_#{submission.study_group_id}",
|
||||
type: :rfc,
|
||||
id: id,
|
||||
html: ApplicationController.render(partial: 'request_for_comments/list_entry',
|
||||
locals: {request_for_comment: self})
|
||||
)
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.connection_pool.release_connection
|
||||
@ -26,9 +28,10 @@ module ActionCableHelper
|
||||
# Context: Submission
|
||||
if study_group_id.present?
|
||||
ActionCable.server.broadcast(
|
||||
"la_exercises_#{exercise_id}_channel_study_group_#{study_group_id}",
|
||||
type: :working_times,
|
||||
working_time_data: exercise.get_working_times_for_study_group(study_group_id, user))
|
||||
"la_exercises_#{exercise_id}_channel_study_group_#{study_group_id}",
|
||||
type: :working_times,
|
||||
working_time_data: exercise.get_working_times_for_study_group(study_group_id, user)
|
||||
)
|
||||
end
|
||||
ensure
|
||||
ActiveRecord::Base.connection_pool.release_connection
|
||||
|
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
module DashboardHelper
|
||||
def dashboard_data
|
||||
|
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ApplicationHelper
|
||||
APPLICATION_NAME = 'CodeOcean'
|
||||
|
||||
@ -7,8 +9,8 @@ module ApplicationHelper
|
||||
|
||||
def code_tag(code, language = nil)
|
||||
if code.present?
|
||||
content_tag(:pre) do
|
||||
content_tag(:code, code, class: "language-#{language}")
|
||||
tag.pre do
|
||||
tag.code(code, class: "language-#{language}")
|
||||
end
|
||||
else
|
||||
empty
|
||||
@ -16,12 +18,12 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def empty
|
||||
content_tag(:i, nil, class: 'empty fa fa-minus')
|
||||
tag.i(nil, class: 'empty fa fa-minus')
|
||||
end
|
||||
|
||||
def label_column(label)
|
||||
content_tag(:div, class: 'col-sm-3') do
|
||||
content_tag(:strong) do
|
||||
tag.div(class: 'col-sm-3') do
|
||||
tag.strong do
|
||||
I18n.translation_present?("activerecord.attributes.#{label}") ? t("activerecord.attributes.#{label}") : t(label)
|
||||
end
|
||||
end
|
||||
@ -29,12 +31,13 @@ module ApplicationHelper
|
||||
private :label_column
|
||||
|
||||
def no
|
||||
content_tag(:i, nil, class: 'fa fa-times')
|
||||
tag.i(nil, class: 'fa fa-times')
|
||||
end
|
||||
|
||||
def progress_bar(value)
|
||||
content_tag(:div, class: value ? 'progress' : 'disabled progress') do
|
||||
content_tag(:div, value ? "#{value}%" : '', :'aria-valuemax' => 100, :'aria-valuemin' => 0, :'aria-valuenow' => value, class: 'progress-bar progress-bar-striped', role: 'progressbar', style: "width: #{[value || 0, 100].min}%;")
|
||||
tag.div(class: value ? 'progress' : 'disabled progress') do
|
||||
tag.div(value ? "#{value}%" : '', 'aria-valuemax': 100, 'aria-valuemin': 0,
|
||||
'aria-valuenow': value, class: 'progress-bar progress-bar-striped', role: 'progressbar', style: "width: #{[value || 0, 100].min}%;")
|
||||
end
|
||||
end
|
||||
|
||||
@ -43,7 +46,7 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def row(options = {}, &block)
|
||||
content_tag(:div, class: 'attribute-row row') do
|
||||
tag.div(class: 'attribute-row row') do
|
||||
label_column(options[:label]) + value_column(options[:value], &block)
|
||||
end
|
||||
end
|
||||
@ -61,13 +64,13 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def value_column(value)
|
||||
content_tag(:div, class: 'col-sm-9') do
|
||||
tag.div(class: 'col-sm-9') do
|
||||
block_given? ? yield : symbol_for(value)
|
||||
end
|
||||
end
|
||||
private :value_column
|
||||
|
||||
def yes
|
||||
content_tag(:i, nil, class: 'fa fa-check')
|
||||
tag.i(nil, class: 'fa fa-check')
|
||||
end
|
||||
end
|
||||
|
@ -1,2 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ErrorTemplateAttributesHelper
|
||||
end
|
||||
|
@ -1,2 +1,4 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ErrorTemplatesHelper
|
||||
end
|
||||
|
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ExerciseHelper
|
||||
include LtiHelper
|
||||
|
||||
@ -6,7 +8,7 @@ module ExerciseHelper
|
||||
end
|
||||
|
||||
def qa_js_tag
|
||||
javascript_include_tag qa_url + "/assets/qa_api.js"
|
||||
javascript_include_tag "#{qa_url}/assets/qa_api.js"
|
||||
end
|
||||
|
||||
def qa_url
|
||||
@ -15,8 +17,6 @@ module ExerciseHelper
|
||||
|
||||
if enabled
|
||||
config.read[:code_pilot][:url]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,3 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'oauth/request_proxy/action_controller_request' # Rails 5 changed `Rack::Request` to `ActionDispatch::Request`
|
||||
|
||||
module LtiHelper
|
||||
|
@ -16,20 +16,19 @@ class PagedownFormBuilder < ActionView::Helpers::FormBuilder
|
||||
private
|
||||
|
||||
def wmd_button_bar
|
||||
@template.content_tag :div, nil, id: "wmd-button-bar-#{base_id}"
|
||||
@template.tag.div(nil, id: "wmd-button-bar-#{base_id}")
|
||||
end
|
||||
|
||||
def wmd_textarea
|
||||
@template.text_area @object_name, @attribute_name,
|
||||
**@input_html_options,
|
||||
class: 'form-control wmd-input',
|
||||
id: "wmd-input-#{base_id}"
|
||||
**@input_html_options,
|
||||
class: 'form-control wmd-input',
|
||||
id: "wmd-input-#{base_id}"
|
||||
end
|
||||
|
||||
def wmd_preview
|
||||
@template.content_tag :div, nil,
|
||||
class: 'wmd-preview',
|
||||
id: "wmd-preview-#{base_id}"
|
||||
@template.tag.div(nil, class: 'wmd-preview',
|
||||
id: "wmd-preview-#{base_id}")
|
||||
end
|
||||
|
||||
def show_wmd_preview?
|
||||
|
@ -1,226 +1,231 @@
|
||||
module StatisticsHelper
|
||||
# frozen_string_literal: true
|
||||
|
||||
module StatisticsHelper
|
||||
WORKING_TIME_DELTA_IN_SECONDS = 5.minutes
|
||||
WORKING_TIME_DELTA_IN_SQL_INTERVAL = "'0:05:00'" # yes, a string with quotes
|
||||
|
||||
def statistics_data
|
||||
[
|
||||
{
|
||||
key: 'users',
|
||||
name: t('statistics.sections.users'),
|
||||
entries: user_statistics
|
||||
},
|
||||
{
|
||||
key: 'exercises',
|
||||
name: t('statistics.sections.exercises'),
|
||||
entries: exercise_statistics
|
||||
},
|
||||
{
|
||||
key: 'request_for_comments',
|
||||
name: t('statistics.sections.request_for_comments'),
|
||||
entries: rfc_statistics
|
||||
}
|
||||
{
|
||||
key: 'users',
|
||||
name: t('statistics.sections.users'),
|
||||
entries: user_statistics,
|
||||
},
|
||||
{
|
||||
key: 'exercises',
|
||||
name: t('statistics.sections.exercises'),
|
||||
entries: exercise_statistics,
|
||||
},
|
||||
{
|
||||
key: 'request_for_comments',
|
||||
name: t('statistics.sections.request_for_comments'),
|
||||
entries: rfc_statistics,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def user_statistics
|
||||
[
|
||||
{
|
||||
key: 'internal_users',
|
||||
name: t('activerecord.models.internal_user.other'),
|
||||
data: InternalUser.count,
|
||||
url: internal_users_path
|
||||
},
|
||||
{
|
||||
key: 'external_users',
|
||||
name: t('activerecord.models.external_user.other'),
|
||||
data: ExternalUser.count,
|
||||
url: external_users_path
|
||||
},
|
||||
{
|
||||
key: 'currently_active',
|
||||
name: t('statistics.entries.users.currently_active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
||||
.distinct('external_users.id').count,
|
||||
url: 'statistics/graphs'
|
||||
}
|
||||
{
|
||||
key: 'internal_users',
|
||||
name: t('activerecord.models.internal_user.other'),
|
||||
data: InternalUser.count,
|
||||
url: internal_users_path,
|
||||
},
|
||||
{
|
||||
key: 'external_users',
|
||||
name: t('activerecord.models.external_user.other'),
|
||||
data: ExternalUser.count,
|
||||
url: external_users_path,
|
||||
},
|
||||
{
|
||||
key: 'currently_active',
|
||||
name: t('statistics.entries.users.currently_active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
||||
.distinct('external_users.id').count,
|
||||
url: 'statistics/graphs',
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def exercise_statistics
|
||||
[
|
||||
{
|
||||
key: 'exercises',
|
||||
name: t('activerecord.models.exercise.other'),
|
||||
data: Exercise.count,
|
||||
url: exercises_path
|
||||
},
|
||||
{
|
||||
key: 'average_submissions',
|
||||
name: t('statistics.entries.exercises.average_number_of_submissions'),
|
||||
data: (Submission.count.to_f / Exercise.count).round(2)
|
||||
},
|
||||
{
|
||||
key: 'submissions_per_minute',
|
||||
name: t('statistics.entries.exercises.submissions_per_minute'),
|
||||
data: (Submission.where('created_at >= ?', DateTime.now - 1.hours).count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
url: statistics_graphs_path
|
||||
},
|
||||
{
|
||||
key: 'autosaves_per_minute',
|
||||
name: t('statistics.entries.exercises.autosaves_per_minute'),
|
||||
data: (Submission.where('created_at >= ?', DateTime.now - 1.hours).where(cause: 'autosave').count.to_f / 60).round(2),
|
||||
unit: '/min'
|
||||
},
|
||||
{
|
||||
key: 'container_requests_per_minute',
|
||||
name: t('statistics.entries.exercises.container_requests_per_minute'),
|
||||
data: (Testrun.where('created_at >= ?', DateTime.now - 1.hours).count.to_f / 60).round(2),
|
||||
unit: '/min'
|
||||
},
|
||||
{
|
||||
key: 'execution_environments',
|
||||
name: t('activerecord.models.execution_environment.other'),
|
||||
data: ExecutionEnvironment.count,
|
||||
url: execution_environments_path
|
||||
},
|
||||
{
|
||||
key: 'exercise_collections',
|
||||
name: t('activerecord.models.exercise_collection.other'),
|
||||
data: ExerciseCollection.count,
|
||||
url: exercise_collections_path
|
||||
}
|
||||
{
|
||||
key: 'exercises',
|
||||
name: t('activerecord.models.exercise.other'),
|
||||
data: Exercise.count,
|
||||
url: exercises_path,
|
||||
},
|
||||
{
|
||||
key: 'average_submissions',
|
||||
name: t('statistics.entries.exercises.average_number_of_submissions'),
|
||||
data: (Submission.count.to_f / Exercise.count).round(2),
|
||||
},
|
||||
{
|
||||
key: 'submissions_per_minute',
|
||||
name: t('statistics.entries.exercises.submissions_per_minute'),
|
||||
data: (Submission.where('created_at >= ?', DateTime.now - 1.hour).count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
url: statistics_graphs_path,
|
||||
},
|
||||
{
|
||||
key: 'autosaves_per_minute',
|
||||
name: t('statistics.entries.exercises.autosaves_per_minute'),
|
||||
data: (Submission.where('created_at >= ?',
|
||||
DateTime.now - 1.hour).where(cause: 'autosave').count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
},
|
||||
{
|
||||
key: 'container_requests_per_minute',
|
||||
name: t('statistics.entries.exercises.container_requests_per_minute'),
|
||||
data: (Testrun.where('created_at >= ?', DateTime.now - 1.hour).count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
},
|
||||
{
|
||||
key: 'execution_environments',
|
||||
name: t('activerecord.models.execution_environment.other'),
|
||||
data: ExecutionEnvironment.count,
|
||||
url: execution_environments_path,
|
||||
},
|
||||
{
|
||||
key: 'exercise_collections',
|
||||
name: t('activerecord.models.exercise_collection.other'),
|
||||
data: ExerciseCollection.count,
|
||||
url: exercise_collections_path,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def rfc_statistics
|
||||
rfc_activity_data + [
|
||||
{
|
||||
key: 'comments',
|
||||
name: t('activerecord.models.comment.other'),
|
||||
data: Comment.count
|
||||
}
|
||||
{
|
||||
key: 'comments',
|
||||
name: t('activerecord.models.comment.other'),
|
||||
data: Comment.count,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def user_activity_live_data
|
||||
[
|
||||
{
|
||||
key: 'active_in_last_hour',
|
||||
name: t('statistics.entries.users.currently_active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
||||
.distinct('external_users.id').count,
|
||||
},
|
||||
{
|
||||
key: 'submissions_per_minute',
|
||||
name: t('statistics.entries.exercises.submissions_per_minute'),
|
||||
data: (Submission.where('created_at >= ?', DateTime.now - 1.hours).count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
axis: 'right'
|
||||
}
|
||||
{
|
||||
key: 'active_in_last_hour',
|
||||
name: t('statistics.entries.users.currently_active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(['submissions.created_at >= ?', DateTime.now - 5.minutes])
|
||||
.distinct('external_users.id').count,
|
||||
},
|
||||
{
|
||||
key: 'submissions_per_minute',
|
||||
name: t('statistics.entries.exercises.submissions_per_minute'),
|
||||
data: (Submission.where('created_at >= ?', DateTime.now - 1.hour).count.to_f / 60).round(2),
|
||||
unit: '/min',
|
||||
axis: 'right',
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def rfc_activity_data(from=DateTime.new(0), to=DateTime.now)
|
||||
def rfc_activity_data(from = DateTime.new(0), to = DateTime.now)
|
||||
[
|
||||
{
|
||||
key: 'rfcs',
|
||||
name: t('activerecord.models.request_for_comment.other'),
|
||||
data: RequestForComment.in_range(from, to).count,
|
||||
url: request_for_comments_path
|
||||
},
|
||||
{
|
||||
key: 'percent_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_solved'),
|
||||
data: (100.0 / RequestForComment.in_range(from, to).count * RequestForComment.in_range(from, to).where(solved: true).count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path
|
||||
},
|
||||
{
|
||||
key: 'percent_soft_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_soft_solved'),
|
||||
data: (100.0 / RequestForComment.in_range(from, to).count * RequestForComment.in_range(from, to).unsolved.where(full_score_reached: true).count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path
|
||||
},
|
||||
{
|
||||
key: 'percent_unsolved',
|
||||
name: t('statistics.entries.request_for_comments.percent_unsolved'),
|
||||
data: (100.0 / RequestForComment.in_range(from, to).count * RequestForComment.in_range(from, to).unsolved.count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path
|
||||
},
|
||||
{
|
||||
key: 'rfcs_with_comments',
|
||||
name: t('statistics.entries.request_for_comments.with_comments'),
|
||||
data: RequestForComment.in_range(from, to).joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
{
|
||||
key: 'rfcs',
|
||||
name: t('activerecord.models.request_for_comment.other'),
|
||||
data: RequestForComment.in_range(from, to).count,
|
||||
url: request_for_comments_path,
|
||||
},
|
||||
{
|
||||
key: 'percent_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_solved'),
|
||||
data: (100.0 / RequestForComment.in_range(from,
|
||||
to).count * RequestForComment.in_range(from, to).where(solved: true).count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path,
|
||||
},
|
||||
{
|
||||
key: 'percent_soft_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_soft_solved'),
|
||||
data: (100.0 / RequestForComment.in_range(from,
|
||||
to).count * RequestForComment.in_range(from, to).unsolved.where(full_score_reached: true).count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path,
|
||||
},
|
||||
{
|
||||
key: 'percent_unsolved',
|
||||
name: t('statistics.entries.request_for_comments.percent_unsolved'),
|
||||
data: (100.0 / RequestForComment.in_range(from,
|
||||
to).count * RequestForComment.in_range(from, to).unsolved.count).round(1),
|
||||
unit: '%',
|
||||
axis: 'right',
|
||||
url: statistics_graphs_path,
|
||||
},
|
||||
{
|
||||
key: 'rfcs_with_comments',
|
||||
name: t('statistics.entries.request_for_comments.with_comments'),
|
||||
data: RequestForComment.in_range(from,
|
||||
to).joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
join "files" f on f.context_id = s.id and f.context_type = \'Submission\'
|
||||
join "comments" c on c.file_id = f.id').group('request_for_comments.id').count.size,
|
||||
url: statistics_graphs_path
|
||||
}
|
||||
url: statistics_graphs_path,
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def ranged_rfc_data(interval='year', from=DateTime.new(0), to=DateTime.now)
|
||||
def ranged_rfc_data(interval = 'year', from = DateTime.new(0), to = DateTime.now)
|
||||
[
|
||||
{
|
||||
key: 'rfcs',
|
||||
name: t('activerecord.models.request_for_comment.other'),
|
||||
data: RequestForComment.in_range(from, to)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key')
|
||||
},
|
||||
{
|
||||
key: 'rfcs_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_solved'),
|
||||
data: RequestForComment.in_range(from, to)
|
||||
.where(solved: true)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key')
|
||||
},
|
||||
{
|
||||
key: 'rfcs_soft_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_soft_solved'),
|
||||
data: RequestForComment.in_range(from, to).unsolved
|
||||
.where(full_score_reached: true)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key')
|
||||
},
|
||||
{
|
||||
key: 'rfcs_unsolved',
|
||||
name: t('statistics.entries.request_for_comments.percent_unsolved'),
|
||||
data: RequestForComment.in_range(from, to).unsolved
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key')
|
||||
}
|
||||
{
|
||||
key: 'rfcs',
|
||||
name: t('activerecord.models.request_for_comment.other'),
|
||||
data: RequestForComment.in_range(from, to)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
},
|
||||
{
|
||||
key: 'rfcs_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_solved'),
|
||||
data: RequestForComment.in_range(from, to)
|
||||
.where(solved: true)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
},
|
||||
{
|
||||
key: 'rfcs_soft_solved',
|
||||
name: t('statistics.entries.request_for_comments.percent_soft_solved'),
|
||||
data: RequestForComment.in_range(from, to).unsolved
|
||||
.where(full_score_reached: true)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
},
|
||||
{
|
||||
key: 'rfcs_unsolved',
|
||||
name: t('statistics.entries.request_for_comments.percent_unsolved'),
|
||||
data: RequestForComment.in_range(from, to).unsolved
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
def ranged_user_data(interval='year', from=DateTime.new(0), to=DateTime.now)
|
||||
def ranged_user_data(interval = 'year', from = DateTime.new(0), to = DateTime.now)
|
||||
[
|
||||
{
|
||||
key: 'active',
|
||||
name: t('statistics.entries.users.active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(submissions: {created_at: from..to})
|
||||
.select("date_trunc('#{interval}', submissions.created_at) AS \"key\", count(distinct external_users.id) AS \"value\"")
|
||||
.group('key').order('key')
|
||||
},
|
||||
{
|
||||
key: 'submissions',
|
||||
name: t('statistics.entries.exercises.submissions'),
|
||||
data: Submission.where(created_at: from..to)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
axis: 'right'
|
||||
}
|
||||
{
|
||||
key: 'active',
|
||||
name: t('statistics.entries.users.active'),
|
||||
data: ExternalUser.joins(:submissions)
|
||||
.where(submissions: {created_at: from..to})
|
||||
.select("date_trunc('#{interval}', submissions.created_at) AS \"key\", count(distinct external_users.id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
},
|
||||
{
|
||||
key: 'submissions',
|
||||
name: t('statistics.entries.exercises.submissions'),
|
||||
data: Submission.where(created_at: from..to)
|
||||
.select("date_trunc('#{interval}', created_at) AS \"key\", count(id) AS \"value\"")
|
||||
.group('key').order('key'),
|
||||
axis: 'right',
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,5 +1,6 @@
|
||||
module TimeHelper
|
||||
# frozen_string_literal: true
|
||||
|
||||
module TimeHelper
|
||||
# convert timestamps ('12:34:56.789') to seconds
|
||||
def time_to_f(timestamp)
|
||||
unless timestamp.nil?
|
||||
@ -11,7 +12,6 @@ module TimeHelper
|
||||
|
||||
# given a delta in seconds, return a "Hours:Minutes:Seconds" representation
|
||||
def format_time_difference(delta)
|
||||
Time.at(delta).utc.strftime("%H:%M:%S")
|
||||
Time.at(delta).utc.strftime('%H:%M:%S')
|
||||
end
|
||||
|
||||
end
|
||||
|
Reference in New Issue
Block a user