Skip to content
Open
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
4 changes: 4 additions & 0 deletions app/assets/stylesheets/admin/budgets/links.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@
.results-link {
@include has-fa-icon(poll, solid);
}

.sensemaker-analyses-link {
@include has-fa-icon(microscope, solid);
}
}
72 changes: 50 additions & 22 deletions app/assets/stylesheets/sensemaker/sensemaker.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
@mixin flex-row {
align-items: center;
display: flex;
flex-direction: row;
gap: 4px;
justify-content: flex-start;
}

@mixin flex-between {
align-items: center;
display: flex;
flex-direction: row;
gap: 4px;
justify-content: space-between;
}

.sensemaker-analyses-link {
@include has-fa-icon(microscope, solid);

&::before {
left: -0.25rem;
position: relative;
top: -0.1rem;
}
}

.sensemaker-icon {
@include has-fa-icon(microscope, solid);
}

.admin .sensemaker {
.additional-context {
border: 1px solid $border;
Expand Down Expand Up @@ -178,17 +208,13 @@
list-style: none;
}

// (moved to shallower block below)

li.result-group {
list-style: none;
margin-bottom: 0.5rem;
margin-top: 0.5rem;
padding: 0;
}

// (moved to shallower block below)

li.result-row {
opacity: 0.8;
padding: 0.1rem;
Expand Down Expand Up @@ -284,7 +310,6 @@
background-color: #f8f9fa;
}

// Job links styling
.job-link {
color: $brand;
font-weight: bold;
Expand All @@ -295,7 +320,6 @@
}
}

// Job details styling
.job-details-table {
border-collapse: collapse;
width: 100%;
Expand Down Expand Up @@ -335,11 +359,25 @@
background-color: $color-info;
}
}

.filter-controls {
@include flex-between;
margin-bottom: $line-height;

select {
height: $line-height * 1.5;
margin-bottom: 0;
}
label { font-weight: normal; opacity: 0.8; }

a,
p { margin-bottom: 0; }
p { opacity: 0.8; }
}
}

.sensemaker {

// Responsive adjustments
@include breakpoint(small only) {
.hero-section {
h1 {
Expand All @@ -363,22 +401,13 @@
}

.flex-between {
align-items: center;
display: flex;
flex-direction: row;
gap: 2px;
justify-content: space-between;
@include flex-between;

button,
.button { margin-bottom: 0; }
}

.flex-row {
align-items: center;
display: flex;
flex-direction: row;
gap: 2px;
justify-content: flex-start;
}
.flex-row { @include flex-row; }
.fit-content { width: fit-content; }

.flex-grow {
flex: 1;
Expand All @@ -388,7 +417,7 @@
align-items: center;
display: flex;
flex-direction: row;
gap: 2px;
gap: 4px;
justify-content: flex-end;
}

Expand All @@ -407,7 +436,6 @@
text-transform: uppercase;
}

// Target header (quiz-header style box)
.target-header {
margin-bottom: 2.2rem;

Expand Down
3 changes: 3 additions & 0 deletions app/components/admin/budgets/show_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@
<h3 id="actions_header"><%= t("admin.budgets.edit.actions") %></h3>
<%= render Admin::Budgets::ActionsComponent.new(budget) %>
</section>

<hr>
<%= render Admin::Sensemaker::AnalysesLinkComponent.new(budget) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= link_to link_text, link_path, class: "sensemaker-analyses-link" %>
44 changes: 44 additions & 0 deletions app/components/admin/sensemaker/analyses_link_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

class Admin::Sensemaker::AnalysesLinkComponent < ApplicationComponent
attr_reader :record

def initialize(record)
@record = record
end

def render?
feature?(:sensemaker) && jobs_count.positive?
end

def jobs_count
@jobs_count ||= Sensemaker::Job.for_analysable(record, published_only: false).count
end

def link_text
t("admin.sensemaker.index.sensemaker_analyses_count", count: jobs_count)
end

def link_path
admin_sensemaker_jobs_path(resource_type: admin_resource_type, resource_id: record.id)
end

private

def admin_resource_type
case record
when Budget
"budgets"
when Debate
"debates"
when Proposal
"proposals"
when Poll
"polls"
when Legislation::Process
"legislation_processes"
else
raise ArgumentError, "Unsupported record type for admin sensemaker link: #{record.class}"
end
end
end
24 changes: 23 additions & 1 deletion app/components/admin/sensemaker/index_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,31 @@

<h3 class="flex-between">
<span><%= t("admin.sensemaker.index.past_runs") %></span>
<%= link_to t("admin.sensemaker.index.new_run"), new_admin_sensemaker_job_path, class: "button" %>
<%= link_to t("admin.sensemaker.index.new_run"), new_admin_sensemaker_job_path, class: "button success" %>
</h3>

<div class="filter-controls">
<% if target_specified? %>
<p><%= t("admin.sensemaker.index.filtered_by_target", name: filter_description) %></p>
<% else %>
<%= form_tag admin_sensemaker_jobs_path, method: :get, enforce_utf8: false, class: "js-submit-on-change" do %>
<div class="flex-row">
<%= label_tag :resource_type, t("admin.sensemaker.index.filter_by"), class: "" %>
<%= select_tag :resource_type,
options_for_select(
filter_resource_type_options.map { |type| [t("admin.sensemaker.index.resource_types.#{type}"), type] },
filter_resource_type
),
{ prompt: t("admin.sensemaker.index.filter_all_types"), class: "fit-content" } %>
</div>
<% end %>
<% end %>

<% if filter_active? %>
<%= link_to t("admin.sensemaker.index.filter_reset"), admin_sensemaker_jobs_path, class: "" %>
<% end %>
</div>

<table class="job-table">
<thead>
<tr>
Expand Down
39 changes: 37 additions & 2 deletions app/components/admin/sensemaker/index_component.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
class Admin::Sensemaker::IndexComponent < ApplicationComponent
include Header

attr_reader :sensemaker_jobs, :running_jobs
attr_reader :sensemaker_jobs, :running_jobs, :filter_target,
:filter_resource_type, :filter_resource_id, :filter_resource_type_options

def initialize(sensemaker_jobs, running_jobs)
def initialize(sensemaker_jobs, running_jobs, filter_target: nil,
filter_resource_type: nil, filter_resource_id: nil, filter_resource_type_options: [])
@sensemaker_jobs = sensemaker_jobs
@running_jobs = running_jobs
@filter_target = filter_target
@filter_resource_type = filter_resource_type
@filter_resource_id = filter_resource_id
@filter_resource_type_options = filter_resource_type_options || []
end

def title
Expand All @@ -15,4 +21,33 @@ def title
def enabled?
feature?(:sensemaker)
end

def target_specified?
filter_target.present?
end

def filter_active?
filter_target.present? || filter_resource_type.present?
end

def filter_description
return filter_target_name if filter_target.present?
return t("admin.sensemaker.index.resource_types.#{filter_resource_type}") if filter_resource_type.present?

nil
end

def filter_target_name
return nil unless filter_target

if filter_target.respond_to?(:title) && filter_target.title.present?
filter_target.title
elsif filter_target.respond_to?(:name) && filter_target.name.present?
filter_target.name
elsif filter_target.respond_to?(:value) && filter_target.value.present?
filter_target.value
else
"##{filter_target.id}"
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
</td>
</tr>
<% end %>

<tr>
<td><strong><%= t("admin.sensemaker.job_show.target_type") %></strong></td>
<td><%= sensemaker_job.analysable_type %></td>
Expand Down
36 changes: 32 additions & 4 deletions app/controllers/admin/sensemaker/jobs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
class Admin::Sensemaker::JobsController < Admin::BaseController
include Sensemaker::ResourceTypeResolution

def index
@running_jobs = Sensemaker::Job.running.includes(:children).order(created_at: :desc)
@sensemaker_jobs = Sensemaker::Job.where(parent_job_id: nil)
.includes(:children)
.where.not(id: @running_jobs.pluck(:id))
.order(created_at: :desc)

@filter_resource_type, @filter_resource_id = normalized_filter_params
if @filter_resource_type.present? && @filter_resource_id.present?
@filter_target = sensemaker_find_resource(@filter_resource_type, @filter_resource_id)
unless @filter_target
redirect_to admin_sensemaker_jobs_path, alert: t("admin.sensemaker.index.target_not_found")
return
end
base_scope = Sensemaker::Job.for_analysable(@filter_target, published_only: false)
elsif @filter_resource_type.present?
resource_class = sensemaker_model_for_resource_type(@filter_resource_type)
unless resource_class
redirect_to admin_sensemaker_jobs_path, alert: t("admin.sensemaker.index.target_not_found")
return
end
base_scope = Sensemaker::Job.by_analysable_type(resource_class.to_s)
else
base_scope = Sensemaker::Job
end

@sensemaker_jobs = base_scope.where(parent_job_id: nil)
.includes(:children)
.where.not(id: @running_jobs.pluck(:id))
.order(created_at: :desc)

@sensemaker_resource_types = Sensemaker::ResourceTypeResolution::SENSEMAKER_RESOURCE_TYPES
end

def show
Expand Down Expand Up @@ -281,6 +305,10 @@ def help

private

def normalized_filter_params
[params[:resource_type].presence, params[:resource_id].presence]
end

def sensemaker_job_params
params.require(:sensemaker_job).permit(:analysable_type, :analysable_id, :script, :additional_context)
end
Expand Down
Loading