Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 54 additions & 2 deletions app/controllers/admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,64 @@ class BaseController < ActionController::Base
password: Rails.application.config.admin_basic_auth_password
)

helper_method :pretty_json
helper_method :pretty_json, :pagination_path_for, :pagination_items

private

def params_page_size
(params[:page_size] || 25).to_i.clamp(0, 100)
(params[:page_size] || 25).to_i.clamp(1, 100)
end

def current_page
(params[:page] || 1).to_i.clamp(1, 10_000)
end

def paginate(scope)
total_count = scope.count
records = scope.offset((current_page - 1) * params_page_size).limit(params_page_size)

[records, pagination_metadata(total_count)]
end

def pagination_metadata(total_count)
total_pages = (total_count.to_f / params_page_size).ceil
total_pages = 1 if total_pages.zero?

{
current_page: current_page,
page_size: params_page_size,
total_count: total_count,
total_pages: total_pages,
has_previous: current_page > 1,
has_next: current_page < total_pages
}
end

def pagination_path_for(page)
query_params = request.query_parameters.merge('page' => page, 'page_size' => params_page_size)
query_params = query_params.reject { |_key, value| value.blank? }
query_string = query_params.to_query
query_string.present? ? "#{request.path}?#{query_string}" : request.path
end

def pagination_items(total_pages, page)
return [1] if total_pages <= 1

pages = [1, total_pages]
((page - 2)..(page + 2)).each do |page_number|
pages << page_number if page_number.between?(1, total_pages)
end

sorted_pages = pages.uniq.sort
items = []

sorted_pages.each_with_index do |page_number, index|
previous_page_number = sorted_pages[index - 1]
items << :gap if previous_page_number && page_number - previous_page_number > 1
items << page_number
end

items
end

def pretty_json(value)
Expand Down
14 changes: 13 additions & 1 deletion app/controllers/admin/contexts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ContextsController < BaseController
end

def index
@contexts = Context.order(id: :desc).limit(params_page_size)
@contexts, @pagination = paginate(Context.order(id: :desc))
end

def show
Expand Down Expand Up @@ -51,6 +51,18 @@ def update
redirect_to admin_context_path(@context), notice: 'Context updated'
end

def trigger_prediction_job
context = Context.find(params[:id])
job_id = PredictionManifestExportJob.perform_async(context.id)
redirect_to admin_context_path(context), notice: "Prediction job with id #{job_id} triggered"
end

def trigger_training_job
context = Context.find(params[:id])
job_id = RetrainZoobotJob.perform_async(context.id)
redirect_to admin_context_path(context), notice: "Training job with id #{job_id} triggered"
end

def destroy
context = Context.find(params[:id])
context.destroy!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ValidationError < StandardError; end
end

def index
@definitions = LabelExtractorDefinition.order(updated_at: :desc).limit(params_page_size)
@definitions, @pagination = paginate(LabelExtractorDefinition.order(updated_at: :desc))
end

def new
Expand Down
13 changes: 13 additions & 0 deletions app/controllers/admin/prediction_jobs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Admin
class PredictionJobsController < BaseController
def index
@prediction_jobs, @pagination = paginate(PredictionJob.order(id: :desc))
end

def show
@prediction_job = PredictionJob.find(params[:id])
end
end
end
15 changes: 15 additions & 0 deletions app/controllers/admin/reductions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Admin
class ReductionsController < BaseController
def index
scope = Reduction.includes(:subject).order(id: :desc)
scope = scope.where(zooniverse_subject_id: params[:zooniverse_subject_id]) if params[:zooniverse_subject_id].present?
@reductions, @pagination = paginate(scope)
end

def show
@reduction = Reduction.includes(:subject).find(params[:id])
end
end
end
15 changes: 15 additions & 0 deletions app/controllers/admin/subjects_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Admin
class SubjectsController < BaseController
def index
scope = Subject.includes(:context, :reductions).order(id: :desc)
scope = scope.where(zooniverse_subject_id: params[:zooniverse_subject_id]) if params[:zooniverse_subject_id].present?
@subjects, @pagination = paginate(scope)
end

def show
@subject = Subject.includes(:context, :reductions).find(params[:id])
end
end
end
13 changes: 13 additions & 0 deletions app/controllers/admin/training_data_exports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Admin
class TrainingDataExportsController < BaseController
def index
@training_data_exports, @pagination = paginate(TrainingDataExport.order(id: :desc))
end

def show
@training_data_export = TrainingDataExport.find(params[:id])
end
end
end
13 changes: 13 additions & 0 deletions app/controllers/admin/training_jobs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Admin
class TrainingJobsController < BaseController
def index
@training_jobs, @pagination = paginate(TrainingJob.order(id: :desc))
end

def show
@training_job = TrainingJob.find(params[:id])
end
end
end
1 change: 1 addition & 0 deletions app/views/admin/contexts/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@
<% end %>
</tbody>
</table>
<%= render 'admin/shared/pagination', pagination: @pagination %>
</div>
</div>
12 changes: 12 additions & 0 deletions app/views/admin/contexts/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
<div class="col-md-12">
<div class="page-actions">
<%= link_to 'Edit context', edit_admin_context_path(@context), class: 'btn btn-default' %>
<%= button_to 'Trigger prediction job',
trigger_prediction_job_admin_context_path(@context),
method: :post,
class: 'btn btn-primary',
form_class: 'inline-form',
form: { onsubmit: "return confirm('Trigger a prediction job for this context?');" } %>
<%= button_to 'Trigger training job',
trigger_training_job_admin_context_path(@context),
method: :post,
class: 'btn btn-primary',
form_class: 'inline-form',
form: { onsubmit: "return confirm('Trigger a training job for this context?');" } %>
</div>
<h2>Context <%= @context.id %></h2>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/views/admin/label_extractor_definitions/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@
<% end %>
</tbody>
</table>
<%= render 'admin/shared/pagination', pagination: @pagination %>
</div>
</div>
30 changes: 30 additions & 0 deletions app/views/admin/prediction_jobs/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div class="row">
<div class="col-md-12">
<h2>Prediction Jobs</h2>
<table class="table table-striped table-sm">
<thead>
<tr>
<th>ID</th>
<th>State</th>
<th>Subject Set ID</th>
<th>Probability Threshold</th>
<th>Randomisation Factor</th>
<th>Updated</th>
</tr>
</thead>
<tbody>
<% @prediction_jobs.each do |prediction_job| %>
<tr>
<td><%= link_to prediction_job.id, admin_prediction_job_path(prediction_job) %></td>
<td><%= prediction_job.state %></td>
<td><%= prediction_job.subject_set_id %></td>
<td><%= prediction_job.probability_threshold %></td>
<td><%= prediction_job.randomisation_factor %></td>
<td><%= prediction_job.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
<%= render 'admin/shared/pagination', pagination: @pagination %>
</div>
</div>
26 changes: 26 additions & 0 deletions app/views/admin/prediction_jobs/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<div class="row">
<div class="col-md-12">
<div class="page-actions">
<%= link_to 'Back to prediction jobs', admin_prediction_jobs_path, class: 'btn btn-default' %>
</div>
<h2>Prediction Job <%= @prediction_job.id %></h2>
</div>
</div>

<div class="row">
<div class="col-md-12">
<table class="table table-striped table-sm">
<tbody>
<tr><th>State</th><td><%= @prediction_job.state %></td></tr>
<tr><th>Subject Set ID</th><td><%= @prediction_job.subject_set_id %></td></tr>
<tr><th>Manifest URL</th><td><%= @prediction_job.manifest_url %></td></tr>
<tr><th>Service Job URL</th><td><%= @prediction_job.service_job_url.presence || '-' %></td></tr>
<tr><th>Results URL</th><td><%= @prediction_job.results_url.presence || '-' %></td></tr>
<tr><th>Probability Threshold</th><td><%= @prediction_job.probability_threshold %></td></tr>
<tr><th>Randomisation Factor</th><td><%= @prediction_job.randomisation_factor %></td></tr>
<tr><th>Message</th><td><%= @prediction_job.message.presence || '-' %></td></tr>
<tr><th>Updated</th><td><%= @prediction_job.updated_at %></td></tr>
</tbody>
</table>
</div>
</div>
36 changes: 36 additions & 0 deletions app/views/admin/reductions/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div class="row">
<div class="col-md-12">
<h2>Reductions</h2>
<table class="table table-striped table-sm">
<thead>
<tr>
<th>ID</th>
<th>Workflow ID</th>
<th>Zooniverse Subject ID</th>
<th>Task Key</th>
<th>Subject</th>
<th>Updated</th>
</tr>
</thead>
<tbody>
<% @reductions.each do |reduction| %>
<tr>
<td><%= link_to reduction.id, admin_reduction_path(reduction) %></td>
<td><%= reduction.workflow_id %></td>
<td><%= reduction.zooniverse_subject_id %></td>
<td><%= reduction.task_key %></td>
<td>
<% if reduction.subject_id.present? %>
<%= link_to reduction.subject_id, admin_subject_path(reduction.subject_id) %>
<% else %>
<span class="text-muted">None</span>
<% end %>
</td>
<td><%= reduction.updated_at %></td>
</tr>
<% end %>
</tbody>
</table>
<%= render 'admin/shared/pagination', pagination: @pagination %>
</div>
</div>
53 changes: 53 additions & 0 deletions app/views/admin/reductions/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<div class="row">
<div class="col-md-12">
<div class="page-actions">
<%= link_to 'Back to reductions', admin_reductions_path, class: 'btn btn-default' %>
<% if @reduction.subject_id.present? %>
<%= link_to 'View subject', admin_subject_path(@reduction.subject_id), class: 'btn btn-default' %>
<% end %>
</div>
<h2>Reduction <%= @reduction.id %></h2>
</div>
</div>

<div class="row">
<div class="col-md-12">
<table class="table table-striped table-sm">
<tbody>
<tr><th>Workflow ID</th><td><%= @reduction.workflow_id %></td></tr>
<tr><th>Zooniverse Subject ID</th><td><%= @reduction.zooniverse_subject_id %></td></tr>
<tr><th>Task Key</th><td><%= @reduction.task_key %></td></tr>
<tr>
<th>Subject</th>
<td>
<% if @reduction.subject_id.present? %>
<%= link_to @reduction.subject_id, admin_subject_path(@reduction.subject_id) %>
<% else %>
None
<% end %>
</td>
</tr>
<tr><th>Unique ID</th><td><%= @reduction.unique_id %></td></tr>
<tr><th>Updated</th><td><%= @reduction.updated_at %></td></tr>
</tbody>
</table>
</div>
</div>

<div class="row">
<div class="col-md-12">
<h3>Labels</h3>
<div class="well">
<pre><%= pretty_json(@reduction.labels) %></pre>
</div>
</div>
</div>

<div class="row">
<div class="col-md-12">
<h3>Raw Payload</h3>
<div class="well">
<pre><%= pretty_json(@reduction.raw_payload) %></pre>
</div>
</div>
</div>
35 changes: 35 additions & 0 deletions app/views/admin/shared/_pagination.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<% if pagination[:total_count] > 0 %>
<div class="admin-pagination">
<div class="admin-pagination-summary text-muted">
Page <%= pagination[:current_page] %> of <%= pagination[:total_pages] %>
(<%= pagination[:total_count] %> total)
</div>
<nav class="admin-pagination-actions" aria-label="Pagination">
<% if pagination[:has_previous] %>
<%= link_to '&laquo;&laquo;'.html_safe, pagination_path_for(1), class: 'btn btn-default', aria: { label: 'First page' } %>
<%= link_to '&laquo;'.html_safe, pagination_path_for(pagination[:current_page] - 1), class: 'btn btn-default', aria: { label: 'Previous page' } %>
<% else %>
<span class="btn btn-default disabled" aria-disabled="true">&laquo;&laquo;</span>
<span class="btn btn-default disabled" aria-disabled="true">&laquo;</span>
<% end %>

<% pagination_items(pagination[:total_pages], pagination[:current_page]).each do |item| %>
<% if item == :gap %>
<span class="btn btn-default disabled admin-pagination-gap" aria-hidden="true">...</span>
<% elsif item == pagination[:current_page] %>
<span class="btn btn-primary active" aria-current="page"><%= item %></span>
<% else %>
<%= link_to item, pagination_path_for(item), class: 'btn btn-default', aria: { label: "Page #{item}" } %>
<% end %>
<% end %>

<% if pagination[:has_next] %>
<%= link_to '&raquo;'.html_safe, pagination_path_for(pagination[:current_page] + 1), class: 'btn btn-default', aria: { label: 'Next page' } %>
<%= link_to '&raquo;&raquo;'.html_safe, pagination_path_for(pagination[:total_pages]), class: 'btn btn-default', aria: { label: 'Last page' } %>
<% else %>
<span class="btn btn-default disabled" aria-disabled="true">&raquo;</span>
<span class="btn btn-default disabled" aria-disabled="true">&raquo;&raquo;</span>
<% end %>
</nav>
</div>
<% end %>
Loading
Loading