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
2 changes: 2 additions & 0 deletions app/assets/images/icons/reports-fill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/components/sidebar_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def build_admin_section
path: helpers.projects_path, icon: "journal-text"),
SIDEBAR_ITEM.new(name: t("new_report", scope: "components.sidebar_component.build_admin_section"),
path: helpers.new_report_path, icon: "add"),
SIDEBAR_ITEM.new(name: t("reports", scope: "components.sidebar_component.build_admin_section"),
path: helpers.reports_path, icon: "reports-fill"),
SIDEBAR_ITEM.new(name: t("users", scope: "components.sidebar_component.build_admin_section"),
path: helpers.users_path, icon: "person-gear"),
SIDEBAR_ITEM.new(name: t("regions", scope: "components.sidebar_component.build_admin_section"),
Expand Down
14 changes: 14 additions & 0 deletions app/controllers/reports_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
class ReportsController < ApplicationController
def index
@reports = Report.order(created_at: :desc)
end

def show
@report = Report.find(params[:id])
end
Expand Down Expand Up @@ -98,6 +102,16 @@ def filter
render :new
end

def destroy
@report = Report.find(params[:id])

if @report.destroy
redirect_to reports_path, flash: { success: t(".success") }
else
redirect_to reports_path, flash: { error: @report.errors.full_messages.to_sentence }
end
end

private

def load_edit_context
Expand Down
22 changes: 22 additions & 0 deletions app/views/reports/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="mx-8 my-10">
<div class="flex items-center justify-between mb-4">
<h1 class="text-4xl font-bold"><%= t(".title") %></h1>
<%= render ActionButtonComponent.new(to: new_report_path, icon: "add", colour: :primary, size: :large, turbo_stream: true) do %>
<%= t(".actions.create") %>
<% end %>
Comment on lines +4 to +6
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActionButtonComponent is rendering this link with data-turbo-stream, but ReportsController#new doesn’t declare a turbo_stream response and there’s no app/views/reports/new.turbo_stream.erb. This will cause a MissingTemplate (or an unexpected turbo_stream format) when the button is clicked. Either remove turbo_stream: true here, or add respond_to + a new.turbo_stream.erb template (as done in Projects/Regions/Users).

Copilot uses AI. Check for mistakes.
</div>
<%= render ContentCardComponent.new do %>
<%= render Shared::IndexTableComponent.new(records: @reports) do |table| %>
<% table.column :id, header: t(".columns.id"), col_size: "80px" %>
<% table.column :start_date, header: t(".columns.start_date") %>
<% table.column :end_date, header: t(".columns.end_date") %>
<% table.column :actions, header: t("shared.index_table_component.actions"), col_size: "90px" do |report| %>
<div class="flex items-center gap-2">
<%= render ActionButtonComponent.new(to: report_path(report), icon: "view") %>
<%= render ActionButtonComponent.new(to: edit_report_path(report), icon: "edit", colour: :info, turbo_stream: true) %>
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This edit action button is sent as a Turbo Stream request (turbo_stream: true), but ReportsController#edit currently doesn’t respond_to :turbo_stream and there’s no edit.turbo_stream.erb template under app/views/reports/. This can raise MissingTemplate when navigating to edit from the index.

Suggested change
<%= render ActionButtonComponent.new(to: edit_report_path(report), icon: "edit", colour: :info, turbo_stream: true) %>
<%= render ActionButtonComponent.new(to: edit_report_path(report), icon: "edit", colour: :info) %>

Copilot uses AI. Check for mistakes.
<%= render ActionButtonComponent.new(to: report_path(report), method: :delete, icon: "delete", colour: :error, confirm: t("reports.destroy.confirm")) %>
</div>
<% end %>
<% end %>
<% end %>
</div>
1 change: 1 addition & 0 deletions config/locales/en/components.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ en:
new_report: New Report
projects: Projects
regions: Regions
reports: Reports
users: Users
build_projects_section:
projects: Projects
Expand Down
16 changes: 16 additions & 0 deletions config/locales/en/reports.en.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
---
en:
activerecord:
attributes:
report:
end_date: End date
start_date: Start date
reports:
create:
invalid: Please provide valid dates and select at least one subproject.
success: Report was successfully generated.
destroy:
confirm: Are you sure you want to delete this report?
success: Report deleted successfully.
edit:
add_aggregated_datum: Add Aggregated Data Box
add_journal: Add Journal
Expand All @@ -18,6 +26,14 @@ en:
save: Save Changes
selected_journals: Selected Journals
title: Edit Report
index:
actions:
create: Create Report
columns:
end_date: End date
id: ID
start_date: Start date
title: Reports
journal_card_component:
author: Author
new:
Expand Down
1 change: 1 addition & 0 deletions config/locales/es/components.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ es:
new_report: Nuevo Reporte
projects: Proyectos
regions: Regiones
reports: Reportes
users: Usuarios
build_projects_section:
projects: Proyectos
Expand Down
16 changes: 16 additions & 0 deletions config/locales/es/reports.es.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
---
es:
activerecord:
attributes:
report:
end_date: Fecha de fin
start_date: Fecha de inicio
reports:
create:
invalid: Por favor proporcione fechas válidas y seleccione al menos un subproyecto.
success: El reporte fue generado exitosamente.
destroy:
confirm: "¿Estás seguro que deseas eliminar este reporte?"
success: Reporte eliminado exitosamente.
edit:
add_aggregated_datum: Agregar Caja de Datos Agregados
add_journal: Agregar Diario
Expand All @@ -18,6 +26,14 @@ es:
save: Guardar Cambios
selected_journals: Diarios Seleccionados
title: Editar Reporte
index:
actions:
create: Crear reporte
columns:
end_date: Fecha de fin
id: ID
start_date: Fecha de inicio
title: Reportes
journal_card_component:
author: Autor
new:
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
delete "/logout", to: "sessions#destroy"

# Report routes
resources :reports, only: %i[show new create edit update] do
resources :reports, only: %i[index show new create edit update destroy] do
collection do
get :filter
end
Expand Down
29 changes: 28 additions & 1 deletion test/controllers/reports_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest
end

[
{ route: "index", method: :get, url_helper: :reports_url, needs_report: false },
{ route: "show", method: :get, url_helper: :report_url, needs_report: true },
{ route: "new", method: :get, url_helper: :new_report_url, needs_report: false },
{ route: "edit", method: :get, url_helper: :edit_report_url, needs_report: true },
{ route: "filter", method: :get, url_helper: :filter_reports_url, needs_report: false },
{ route: "update", method: :patch, url_helper: :report_url, needs_report: true }
{ route: "update", method: :patch, url_helper: :report_url, needs_report: true },
{ route: "destroy", method: :delete, url_helper: :report_url, needs_report: true }
].each do |hash|
test "##{hash[:route]} redirects to login route when a user is not authenticated" do
log_out_user
Expand All @@ -34,6 +36,7 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest
end

[
{ route: "index", method: :get, url_helper: :reports_url, needs_report: false },
{ route: "show", method: :get, url_helper: :report_url, needs_report: true },
{ route: "new", method: :get, url_helper: :new_report_url, needs_report: false },
{ route: "edit", method: :get, url_helper: :edit_report_url, needs_report: true }
Expand Down Expand Up @@ -64,6 +67,19 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest
assert_match aggregated_datum.additional_text, response.body
end

test "#index displays all reports" do
report_a = create(:report, start_date: Date.new(2025, 1, 1), end_date: Date.new(2025, 1, 31))
report_b = create(:report, start_date: Date.new(2025, 2, 1), end_date: Date.new(2025, 2, 28))

get reports_path
assert_response :success

assert_select "div", text: report_a.id.to_s
assert_select "div", text: report_b.id.to_s
assert_select "div", text: report_a.start_date.to_s
assert_select "div", text: report_b.start_date.to_s
end

test "#filter displays projects when valid dates are provided" do
subproject = create(:subproject)
create(:log_entry, subproject: subproject, created_at: 1.day.ago)
Expand Down Expand Up @@ -226,4 +242,15 @@ class ReportsControllerTest < ActionDispatch::IntegrationTest
assert_equal [report_journal.id], report.journal_ids
assert_equal [retained_datum.id], report.aggregated_data.ids
end

test "#destroy deletes report when user is an admin" do
report = create(:report)

assert_difference("Report.count", -1) do
delete report_path(report)
end

assert_redirected_to reports_path
assert_equal I18n.t("reports.destroy.success"), flash[:success]
end
end
Loading