Skip to content

Commit

Permalink
Merge pull request #906 from pulibrary/datatables_source
Browse files Browse the repository at this point in the history
Load folder data asynchronously.
  • Loading branch information
escowles authored Mar 14, 2018
2 parents f333066 + 9e3733d commit 029d609
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 48 deletions.
9 changes: 9 additions & 0 deletions app/controllers/ephemera_boxes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ class EphemeraBoxesController < BaseResourceController
before_action :load_collections, only: [:new, :edit]
before_action :cache_project, only: :destroy

def folders
authorize! :read, resource
render json: { data: datatables_folders }
end

def datatables_folders
FolderDataSource.new(resource: resource.decorate, helper: self).data
end

def attach_drive
edit
end
Expand Down
8 changes: 8 additions & 0 deletions app/controllers/ephemera_projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ def index
render 'index'
end

def folders
render json: { data: datatables_folders }
end

def datatables_folders
FolderDataSource.new(resource: resource.decorate, helper: self).data
end

def manifest
@resource = find_resource(params[:id])
respond_to do |f|
Expand Down
4 changes: 4 additions & 0 deletions app/decorators/ephemera_box_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def folders
@folders ||= members.select { |r| r.is_a?(EphemeraFolder) }.map(&:decorate).to_a
end

def folders_count
@folders_count ||= query_service.custom_queries.count_members(resource: model, model: EphemeraFolder)
end

def ephemera_projects
@ephemera_projects ||= query_service.find_parents(resource: model).map(&:decorate).to_a
end
Expand Down
10 changes: 7 additions & 3 deletions app/decorators/ephemera_project_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ def members
end

def boxes
@boxes ||= members.select { |r| r.is_a?(EphemeraBox) }.map(&:decorate).to_a
@boxes ||= query_service.find_members(resource: model, model: EphemeraBox).map(&:decorate).to_a
end

def fields
@fields ||= members.select { |r| r.is_a?(EphemeraField) }.map(&:decorate).to_a
@fields ||= query_service.find_members(resource: model, model: EphemeraField).map(&:decorate).to_a
end

def folders
@folders ||= members.select { |r| r.is_a?(EphemeraFolder) }.map(&:decorate).to_a
@folders ||= query_service.find_members(resource: model, model: EphemeraFolder).map(&:decorate).to_a
end

def folders_count
@folders_count ||= query_service.custom_queries.count_members(resource: model, model: EphemeraFolder)
end

def templates
Expand Down
22 changes: 22 additions & 0 deletions app/models/folder_data_source.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true
class FolderDataSource
attr_reader :resource, :helper
delegate :folders, to: :resource
def initialize(resource:, helper:)
@resource = resource
@helper = helper
end

def data
@data ||= folders.map do |folder|
{
folder_number: folder.folder_number,
workflow_state: folder.rendered_state,
title: folder.title,
barcode: folder.barcode,
genre: folder.genre.try(:label) || folder.genre,
actions: helper.render_to_string(partial: "catalog/folder_actions", locals: { resource: resource, folder: folder }, formats: [:html])
}
end
end
end
42 changes: 42 additions & 0 deletions app/queries/count_members.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true
class CountMembers
def self.queries
[:count_members]
end

attr_reader :query_service
delegate :orm_class, to: :resource_factory
delegate :resource_factory, to: :query_service
def initialize(query_service:)
@query_service = query_service
end

def count_members(resource:, model: nil)
if model
orm_class.connection.execute(find_members_with_resource_query(resource, model)).first["count"]
else
orm_class.connection.execute(find_members_query(resource)).first["count"]
end
end

def find_members_query(resource)
<<-SQL
SELECT COUNT(*) FROM orm_resources a,
jsonb_array_elements(a.metadata->'member_ids') AS b(member)
JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = '#{resource.id}'
SQL
end

def find_members_with_resource_query(resource, model)
<<-SQL
SELECT COUNT(*) FROM orm_resources a,
jsonb_array_elements(a.metadata->'member_ids') AS b(member)
JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = '#{resource.id}'
AND member.internal_resource = '#{model}'
SQL
end

def id_type
@id_type ||= orm_class.columns_hash["id"].type
end
end
5 changes: 5 additions & 0 deletions app/views/catalog/_folder_actions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<td>
<% folder_url = parent_solr_document_path("#{resource.id}", "#{folder.id}") %>
<%= link_to 'View', folder_url, class: 'btn btn-default' %>
<%= link_to 'Edit', main_app.polymorphic_path([:edit, folder]), class: 'btn btn-default' %>
</td>
33 changes: 8 additions & 25 deletions app/views/catalog/_members_ephemera_box.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,21 @@
<%# DataTable looks for certain data attributes on initialization
# https://datatables.net/examples/advanced_init/html5-data-options.html
# here we sort descending by folder number %>
<table id="members" class="table table-striped datatable" data-order='[[0, "desc"]]'>
<table id="members" class="table table-striped datatable" data-ajax='<%= polymorphic_path([:folders, resource], format: :json) %>' data-order='[[0, "desc"]]'>
<thead>
<tr>
<% if decorated_resource.is_a?(EphemeraBox) %>
<th>Folder Number</th>
<th data-data="folder_number">Folder Number</th>
<% end %>
<th>Workflow State</th>
<th>Title</th>
<th>Barcode</th>
<th>Genre</th>
<th>Actions</th>
<th data-data="workflow_state">Workflow State</th>
<th data-data="title">Title</th>
<th data-data="barcode">Barcode</th>
<th data-data="genre">Genre</th>
<th data-data="actions">Actions</th>
</tr>
</thead>
<tbody>
<% unless decorated_resource.folders.empty? %>
<% decorated_resource.folders.each do |folder| %>
<% folder_url = parent_solr_document_path("#{resource.id}", "#{folder.id}") %>
<tr>
<% if decorated_resource.is_a?(EphemeraBox) %>
<td class="folder_number"><%= link_to folder.folder_number, folder_url %></td>
<% end %>
<td><%= folder.rendered_state %></td>
<td><%= folder.header %></td>
<td class="barcode"><%= folder.barcode %></td>
<td class="genre"><%= folder.genre %></td>
<td>
<%= link_to 'View', folder_url, class: 'btn btn-default' %>
<%= link_to 'Edit', main_app.polymorphic_path([:edit, folder]), class: 'btn btn-default' %>
</td>
</tr>
<% end %>
<% else %>
<% if decorated_resource.folders_count == 0 %>
<td>This work has no folders attached. Click "Attach Folder" to attach folders.</td>
<% end %>
</tbody>
Expand Down
3 changes: 2 additions & 1 deletion config/initializers/valkyrie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@
FindProjectFolders,
FindIdentifiersToReconcile,
FileSetsSortedByUpdated,
FindFixityFailures
FindFixityFailures,
CountMembers
].each do |query_handler|
Valkyrie.config.metadata_adapter.query_service.custom_queries.register_query_handler(query_handler)
end
Expand Down
6 changes: 6 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
resources :ephemera_projects do
resources :templates, only: [:new, :create, :destroy]
resources :ephemera_fields
member do
get :folders, defaults: { format: :json }
end
member do
get :manifest, defaults: { format: :json }
end
Expand All @@ -106,6 +109,9 @@
member do
get :attach_drive
end
member do
get :folders, defaults: { format: :json }
end
end

resources :ephemera_folders do
Expand Down
32 changes: 32 additions & 0 deletions spec/controllers/ephemera_boxes_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,38 @@
end
end

describe "folders" do
context "when not logged in" do
let(:user) { nil }
it "redirects CanCan::AccessDenied error to login" do
box = FactoryBot.create_for_repository(:private_ephemera_box)
get :folders, params: { id: box.id }
expect(response).to redirect_to('/users/auth/cas')
end
end
context "when they have permission" do
let(:user) { FactoryBot.create(:admin) }
render_views
it "renders a JSON list of a project's folders" do
folder = FactoryBot.create_for_repository(:ephemera_folder)
box = FactoryBot.create_for_repository(:ephemera_box, member_ids: folder.id)

get :folders, params: { id: box.id.to_s, formats: :json }

json = JSON.parse(response.body)
expect(json["data"].length).to eq 1
expect(json["data"][0]["folder_number"]).to eq folder.folder_number.first
expect(json["data"][0]["workflow_state"]).to eq "<span class=\"label label-info\">Needs QA</span>"
expect(json["data"][0]["title"]).to eq folder.title
expect(json["data"][0]["barcode"]).to eq folder.barcode.first
expect(json["data"][0]["genre"]).to eq folder.genre.first
expect(json["data"][0]["actions"]).to have_link "View", href: "/catalog/parent/#{box.id}/#{folder.id}"
expect(json["data"][0]["actions"]).to have_link "Edit", href: "/concern/ephemera_folders/#{folder.id}/edit"
expect(json["data"][0]["actions"]).not_to have_link "Delete"
end
end
end

describe "create" do
let(:user) { FactoryBot.create(:admin) }
let(:valid_params) do
Expand Down
22 changes: 22 additions & 0 deletions spec/controllers/ephemera_projects_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@
end
end

describe "folders" do
context "when they have permission" do
let(:user) { FactoryBot.create(:admin) }
render_views
it "renders a JSON list of a project's folders" do
folder = FactoryBot.create_for_repository(:ephemera_folder)
project = FactoryBot.create_for_repository(:ephemera_project, member_ids: folder.id)

get :folders, params: { id: project.id.to_s, formats: :json }

json = JSON.parse(response.body)
expect(json["data"].length).to eq 1
expect(json["data"][0]["folder_number"]).to eq folder.folder_number.first
expect(json["data"][0]["workflow_state"]).to eq "<span class=\"label label-info\">Needs QA</span>"
expect(json["data"][0]["title"]).to eq folder.title
expect(json["data"][0]["barcode"]).to eq folder.barcode.first
expect(json["data"][0]["genre"]).to eq folder.genre.first
expect(json["data"][0]["actions"]).not_to be_blank
end
end
end

describe "destroy" do
let(:user) { FactoryBot.create(:admin) }
context "access control" do
Expand Down
19 changes: 19 additions & 0 deletions spec/queries/count_members_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'rails_helper'

RSpec.describe CountMembers do
subject(:query) { described_class.new(query_service: query_service) }
let(:box) { FactoryBot.create_for_repository(:ephemera_box, member_ids: folder.id) }
let(:folder) { FactoryBot.create_for_repository(:ephemera_folder) }
let(:query_service) { Valkyrie.config.metadata_adapter.query_service }

describe "#count_members" do
it "can give a count of all members" do
expect(query.count_members(resource: box)).to eq 1
end
it "can give a count of all members of a specific type" do
expect(query.count_members(resource: box, model: EphemeraFolder)).to eq 1
expect(query.count_members(resource: box, model: ScannedResource)).to eq 0
end
end
end
16 changes: 2 additions & 14 deletions spec/views/catalog/_members_ephemera_box.html.erb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,7 @@
it 'shows them' do
expect(rendered).to have_selector 'h2', text: 'Folders'
expect(rendered).to have_selector 'th', text: 'Folder Number'
expect(rendered).to have_selector 'td.folder_number', text: "one"
expect(rendered).to have_link "one", href: "/catalog/parent/#{parent.id}/#{child.id}"
expect(rendered).not_to have_selector 'td.folder_number', text: "[\"one\"]"
expect(rendered).to have_selector 'td.barcode', text: child.barcode.first
expect(rendered).not_to have_selector 'td.barcode', text: "[\"#{child.barcode.first}\"]"
expect(rendered).to have_selector 'td.genre', text: child.genre.first
expect(rendered).not_to have_selector 'td.genre', text: "[\"#{child.genre.first}\"]"
expect(rendered).to have_link "View", href: "/catalog/parent/#{parent.id}/#{child.id}"
expect(rendered).to have_link "Edit", href: "/concern/ephemera_folders/#{child.id}/edit"
expect(rendered).not_to have_link "Delete", href: "/concern/ephemera_folders/#{child.id}"
expect(rendered).to have_selector "table.datatable[data-ajax='/concern/ephemera_boxes/#{parent.id}/folders']"
end
end
context "when it's a project with folders" do
Expand All @@ -40,10 +31,7 @@
it 'shows them' do
expect(rendered).to have_selector 'h2', text: 'Folders'
expect(rendered).not_to have_selector 'th', text: 'Folder Number'
expect(rendered).to have_selector 'td', text: 'test folder'
expect(rendered).to have_link "View", href: "/catalog/parent/#{parent.id}/#{child.id}"
expect(rendered).to have_link "Edit", href: "/concern/ephemera_folders/#{child.id}/edit"
expect(rendered).not_to have_link "Delete", href: "/concern/ephemera_folders/#{child.id}"
expect(rendered).to have_selector "table.datatable[data-ajax='/concern/ephemera_projects/#{parent.id}/folders']"
end
end
end
5 changes: 0 additions & 5 deletions spec/views/catalog/_members_ephemera_project.html.erb_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@
expect(rendered).to have_link 'Edit', href: edit_ephemera_box_path(child.id)

expect(rendered).to have_selector 'h2', text: 'Folders'
expect(rendered).to have_selector 'span.label-info', text: 'Needs QA'
expect(rendered).to have_selector 'td', text: 'test folder'
expect(rendered).to have_selector 'td', text: '12345678901234'
expect(rendered).to have_link 'View', href: parent_solr_document_path(parent.id, child_folder.id)
expect(rendered).to have_link 'Edit', href: edit_ephemera_folder_path(child_folder.id)
end
end
context "when it's a project with templates" do
Expand Down

0 comments on commit 029d609

Please sign in to comment.