-
Notifications
You must be signed in to change notification settings - Fork 24
Add associated records links to person edit #1889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,10 +4,14 @@ class GrantsController < ApplicationController | |
|
|
||
| def index | ||
| authorize! | ||
| @grants = authorized_scope(Grant.all) | ||
| .includes(:donor, scholarships: { allocation: :allocatable }) | ||
| .by_deadline | ||
| .page(params[:page]) | ||
| grants = authorized_scope(Grant.all) | ||
| .includes(:donor, scholarships: { allocation: :allocatable }) | ||
| .by_deadline | ||
| if params[:donor_id].present? && Grant::DONOR_TYPES.include?(params[:donor_type]) | ||
| grants = grants.where(donor_id: params[:donor_id], donor_type: params[:donor_type]) | ||
| @donor = grants.first&.donor | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π€ From Claude: Resolve the donor via |
||
| end | ||
| @grants = grants.page(params[:page]) | ||
| track_index_intent(Grant, @grants, params) | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,10 @@ def index | |
| { grant: :donor }, | ||
| { recipient: [ { affiliations: { organization: :addresses } }, { event_registrations: :event } ] } | ||
| ) | ||
| if params[:recipient_id].present? | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π€ From Claude: The scholarships index previously only grouped by funder with no per-recipient view, so this adds a |
||
| scholarships = scholarships.where(recipient_id: params[:recipient_id]) | ||
| @recipient = Person.find_by(id: params[:recipient_id]) | ||
| end | ||
| @funder_groups = ScholarshipsGrouping.new(scholarships).funder_groups | ||
| @scholarships_count = scholarships.size | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| <% content_for(:page_bg_class, "admin-only bg-blue-100") %> | ||
|
|
||
| <div class="form-submissions-index max-w-7xl mx-auto <%= DomainTheme.bg_class_for(:forms) %> border border-gray-200 rounded-xl shadow p-6"> | ||
| <div class="w-full"> | ||
| <% if @person %> | ||
| <div class="mb-4"> | ||
| <%= link_to edit_person_path(@person), class: "inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-gray-700" do %> | ||
| <i class="fa-solid fa-arrow-left text-xs"></i> Edit <%= @person.name %> | ||
| <% end %> | ||
| </div> | ||
| <% end %> | ||
|
|
||
| <div class="flex items-start gap-4 mb-6"> | ||
| <span class="hidden sm:flex h-12 w-12 shrink-0 items-center justify-center rounded-xl <%= DomainTheme.bg_class_for(:forms) %> <%= DomainTheme.text_class_for(:forms, intensity: 700) %> border <%= DomainTheme.border_class_for(:forms, intensity: 200) %> shadow-sm"> | ||
| <i class="fa-solid fa-file-signature text-xl" aria-hidden="true"></i> | ||
| </span> | ||
| <div> | ||
| <h2 class="text-2xl font-semibold text-gray-900 flex items-center gap-2"> | ||
| Form submissions | ||
| <span class="inline-flex items-center rounded-full <%= DomainTheme.bg_class_for(:forms) %> <%= DomainTheme.text_class_for(:forms, intensity: 700) %> border <%= DomainTheme.border_class_for(:forms, intensity: 200) %> px-2.5 py-0.5 text-sm font-semibold"><%= @form_submissions.size %></span> | ||
| </h2> | ||
| <p class="text-gray-600 mt-1"> | ||
| <% if @person %> | ||
| Forms submitted by <span class="font-medium text-gray-900"><%= @person.name %></span>. | ||
| <% else %> | ||
| Forms submitted across the site. | ||
| <% end %> | ||
| </p> | ||
| </div> | ||
| </div> | ||
|
|
||
| <% if @form_submissions.any? %> | ||
| <div class="overflow-x-auto bg-white rounded-xl border border-gray-200 shadow-sm"> | ||
| <table class="w-full border-collapse"> | ||
| <thead> | ||
| <tr class="border-b border-gray-200 bg-gray-50 text-left text-sm text-gray-600"> | ||
| <th class="px-4 py-3">Form</th> | ||
| <th class="px-4 py-3">Role</th> | ||
| <th class="px-4 py-3">Event</th> | ||
| <% unless @person %><th class="px-4 py-3">Person</th><% end %> | ||
| <th class="px-4 py-3">Submitted</th> | ||
| <th class="px-4 py-3"></th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <% @form_submissions.each do |submission| %> | ||
| <tr class="border-b border-gray-100 last:border-0 text-sm text-gray-800"> | ||
| <td class="px-4 py-3 font-medium"><%= submission.form&.display_name %></td> | ||
| <td class="px-4 py-3"><%= submission.role&.humanize %></td> | ||
| <td class="px-4 py-3"><%= submission.resolved_event&.name %></td> | ||
| <% unless @person %><td class="px-4 py-3"><%= submission.person&.name %></td><% end %> | ||
| <td class="px-4 py-3 whitespace-nowrap"><%= submission.created_at.to_fs(:long) %></td> | ||
| <td class="px-4 py-3 text-right"> | ||
| <%= link_to "View", form_submission_path(submission), class: "text-blue-600 hover:underline" %> | ||
| </td> | ||
| </tr> | ||
| <% end %> | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
| <% else %> | ||
| <div class="bg-white rounded-xl border border-dashed border-gray-300 py-12 text-center"> | ||
| <i class="fa-solid fa-file-signature text-3xl text-gray-300" aria-hidden="true"></i> | ||
| <p class="mt-3 text-gray-500">No form submissions found.</p> | ||
| </div> | ||
| <% end %> | ||
| </div> | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <% return unless person.persisted? %> | ||
| <% email = person.preferred_email %> | ||
| <% notifications = email.present? ? Notification.email(email) : Notification.none %> | ||
| <ul class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-x-6 gap-y-2"> | ||
| <li><%= index_button person.event_registrations, params: { registrant_id: person.id } %></li> | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π€ From Claude: Only these two records get cards because they have person-scoped destinations: registrations filter on |
||
| <li><%= index_button(person.user&.workshop_logs || WorkshopLog.none, path: workshop_logs_person_path(person)) %></li> | ||
| <li><%= index_button person.scholarships, params: { recipient_id: person.id } %></li> | ||
| <li><%= index_button person.grants, params: { donor_id: person.id, donor_type: "Person" } %></li> | ||
| <li><%= index_button person.form_submissions, params: { person_id: person.id } %></li> | ||
| <li><%= index_button notifications, params: { email: email } %></li> | ||
| </ul> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| require "rails_helper" | ||
|
|
||
| RSpec.describe "Person edit associated records", type: :request do | ||
| let(:admin) { create(:user, :admin) } | ||
|
|
||
| before { sign_in admin } | ||
|
|
||
| describe "GET /people/:id/edit" do | ||
| it "links to the person's filtered registrations, workshop logs, scholarships, grants, form submissions, and notifications" do | ||
| person = create(:person) | ||
| create(:event_registration, registrant: person) | ||
| create(:workshop_log, created_by: person.user) | ||
| create(:scholarship, recipient: person) | ||
| create(:grant, donor: person) | ||
| create(:form_submission, person: person) | ||
| create(:notification, recipient_email: person.preferred_email) | ||
|
|
||
| get edit_person_path(person) | ||
|
|
||
| expect(response).to have_http_status(:ok) | ||
| expect(response.body).to include("Associated records") | ||
| expect(response.body).to include(event_registrations_path(registrant_id: person.id)) | ||
| expect(response.body).to include(workshop_logs_person_path(person)) | ||
| expect(response.body).to include(scholarships_path(recipient_id: person.id)) | ||
| expect(response.body).to include(CGI.escapeHTML(grants_path(donor_id: person.id, donor_type: "Person"))) | ||
| expect(response.body).to include(form_submissions_path(person_id: person.id)) | ||
| expect(response.body).to include(notifications_path(email: person.preferred_email)) | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π€ From Claude: New admin-only index β form submissions had no list view before, so a person's submissions were only reachable one-off from an event registration. Not using
authorized_scopebecause FormSubmissionPolicy has no relation scope and the action is alreadyadmin?-gated.