Skip to content
Draft
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
8 changes: 8 additions & 0 deletions app/controllers/bulkrax/importers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ def entry_table
end
end

def statuses_table
@statuses = @importer.statuses.order(table_order).page(table_page).per(table_per_page)
@statuses = @statuses.where(status_table_search) if status_table_search.present?
respond_to do |format|
format.json { render json: format_statuses(@statuses, @importer) }
end
end

# GET /importers/new
def new
@importer = Importer.new
Expand Down
28 changes: 28 additions & 0 deletions app/controllers/concerns/bulkrax/datatables_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def format_entries(entries, item)
status_message: status_message_for(e),
type: e.type,
updated_at: e.updated_at,
# refactor this
errors: e.status_message == 'Failed' ? view_context.link_to(e.error_class, view_context.item_entry_path(item, e)) : "",
actions: entry_util_links(e, item)
}
Expand All @@ -143,6 +144,26 @@ def format_entries(entries, item)
}
end

def format_statuses(statuses, item)
result = statuses.map do |s|
{
identifier: view_context.link_to(s.identifier, view_context.item_status_path(item, s)),
id: s.id,
status_message: s.status_message,
error_class: s.error_class,
created_at: s.created_at,
updated_at: s.updated_at,
runnable_id: view_context.link_to(s.runnable_id, view_context.importer_path(item)),
actions: status_util_links(s, item)
}
end
{
data: result,
recordsTotal: item.statuses.size,
recordsFiltered: item.statuses.size
}
end

def entry_util_links(e, item)
links = []
links << view_context.link_to(view_context.raw('<span class="fa fa-info-circle"></span>'), view_context.item_entry_path(item, e))
Expand All @@ -151,6 +172,13 @@ def entry_util_links(e, item)
links.join(" ")
end

def status_util_links(_s, item)
links = []
links << view_context.link_to(view_context.raw('<span class="fa fa-info-circle"></span>'), view_context.item_status_path(item, e))
links << "<a class='fa fa-repeat' data-toggle='modal' data-target='#bulkraxItemModal' data-entry-id='#{e.id}'></a>" if view_context.an_importer?(item)
links.join(" ")
end

def status_message_for(e)
if e.status_message == "Complete"
"<td><span class='fa fa-check' style='color: green;'></span> #{e.status_message}</td>"
Expand Down
5 changes: 2 additions & 3 deletions app/matchers/bulkrax/application_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ def initialize(args)

def result(_parser, content)
return nil if self.excluded == true || Bulkrax.reserved_properties.include?(self.to)
# rubocop:disable Style/RedundantParentheses
return nil if self.if && (!self.if.is_a?(Array) && self.if.length != 2)
# rubocop:enable Style/RedundantParentheses
return nil if self.if && !self.if.is_a?(Array) && self.if.length != 2

if self.if
return unless content.send(self.if[0], Regexp.new(self.if[1]))
end
Expand Down
4 changes: 4 additions & 0 deletions app/models/bulkrax/csv_entry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ def build_metadata
add_local

self.parsed_metadata
rescue => e
self.save!
self.set_status_info(e, self)
raise => e
end

def validate_record
Expand Down
2 changes: 1 addition & 1 deletion app/models/bulkrax/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def import_objects(types_array = nil)
existing_entries? ? parser.rebuild_entries(types) : parser.create_objects(types)
mark_unseen_as_skipped
rescue StandardError => e
set_status_info(e)
set_status_info(e, self)
end

# After an import any entries we did not touch are skipped.
Expand Down
1 change: 1 addition & 0 deletions app/models/concerns/bulkrax/import_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def build_for_importer
child_jobs if self.parsed_metadata[related_children_parsed_mapping]&.join.present?
end
rescue RSolr::Error::Http, CollectionsCreatedError => e
set_status_info(e)
raise e
rescue StandardError => e
set_status_info(e)
Expand Down
37 changes: 37 additions & 0 deletions app/models/concerns/bulkrax/status_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,49 @@ def set_status_info(e = nil, current_run = nil)
else
self.statuses.create!(status_message: 'Failed', runnable: runnable, error_class: e.class.to_s, error_message: e.message, error_backtrace: e.backtrace)
end
rescue => e
save_with_placeholder_to_capture_status(e, runnable)
end

alias status_info set_status_info

deprecation_deprecate status_info: "Favor Bulkrax::StatusInfo.set_status_info. We will be removing .status_info in Bulkrax v6.0.0"

def save_with_placeholder_to_capture_status(e, runnable)
case e.class.to_s
when 'ActiveRecord::RecordInvalid'
runnable.user = current_or_placeholder_user if runnable.user.nil?
runnable.admin_set_id = placeholder_admin_set_id if runnable.admin_set_id.nil?
runnable.name = 'Placeholder Name' if runnable.name.nil?
runnable.parser_klass = Bulkrax::CsvParser if runnable.parser_klass.nil?
runnable.save!
runnable.errors.each do |error|
set_status_info(error, runnable)
end
when 'ActiveRecord::RecordNotSaved'
runnable.user = current_or_placeholder_user if runnable.user.nil?
runnable.admin_set_id = placeholder_admin_set_id if runnable.admin_set_id.nil?
runnable.name = 'Placeholder Name' if runnable.name.nil?
runnable.parser_klass = Bulkrax::CsvParser if runnable.parser_klass.nil?
runnable.save!
runnable.errors.each do |error|
set_status_info(error, runnable)
end
end
end

def current_or_placeholder_user
placeholder_user = User.new(display_name: 'Placeholder User')
placeholder_user.save!
@current_user.presence || placeholder_user
end

def placeholder_admin_set_id
placeholder_admin_set = AdminSet.new(title: ['Placeholder Admin Set'])
placeholder_admin_set.save!
placeholder_admin_set.id
end

# api compatible with previous error structure
def last_error
return unless current_status && current_status.error_class.present?
Expand Down
8 changes: 8 additions & 0 deletions app/parsers/bulkrax/bagit_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ def import_fields
raise StandardError, 'No metadata files were found' if metadata_paths.blank?
@import_fields ||= metadata_paths.sample(10).map do |path|
entry_class.fields_from_data(entry_class.read_data(path))
rescue => e
importer = Importer.find(entry_class.runnable_id)
importer.set_status_info(e, importer)
raise => e
end.flatten.compact.uniq
end

Expand All @@ -41,6 +45,10 @@ def records(_opts = {})
raise StandardError, 'No metadata files were found' if path.blank?
data = entry_class.read_data(path)
get_data(bag, data)
rescue => e
importer = Importer.find(entry_class.runnable_id)
importer.set_status_info(e, importer)
raise => e
end

@records = @records.flatten
Expand Down
3 changes: 3 additions & 0 deletions app/parsers/bulkrax/csv_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def records(_opts = {})
importer.save

@records = csv_data.map { |record_data| entry_class.data_for_entry(record_data, nil, self) }
rescue => e
importer.set_status_info(e, importer)
raise => e
end

# rubocop:disable Metrics/AbcSize
Expand Down
8 changes: 8 additions & 0 deletions app/parsers/bulkrax/xml_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,21 @@ def records(_opts = {})
# Retrieve all records
elements = entry_class.read_data(md).xpath("//#{record_element}")
r += elements.map { |el| entry_class.data_for_entry(el, source_identifier, self) }
rescue => e
importer = Importer.find(entry_class.runnable_id)
importer.set_status_info(e, importer)
raise => e
end
# Flatten because we may have multiple records per array
r.compact.flatten
elsif parser_fields['import_type'] == 'single'
metadata_paths.map do |md|
data = entry_class.read_data(md).xpath("//#{record_element}").first # Take only the first record
entry_class.data_for_entry(data, source_identifier, self)
rescue => e
importer = Importer.find(entry_class.runnable_id)
importer.set_status_info(e, importer)
raise => e
end.compact # No need to flatten because we take only the first record
end
end
Expand Down
53 changes: 43 additions & 10 deletions app/views/bulkrax/shared/_bulkrax_errors.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<% if item.failed? %>
<% if item.succeeded? %>
<p class='bulkrax-p-align'>
<strong>Succeeded At:</strong> <%= item.status_at %>
</p>
<% elsif item.failed? %>
<div class="accordion-container">
<div class="accordion-heading" role="tab" id="error-trace-heading">
<a class="accordion-title" role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
Errors:
Current Error:
</a>
<a role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
<div class="accordion-icon fa fa-times-circle" aria-hidden="true"></div>
Expand Down Expand Up @@ -41,12 +45,41 @@
</div>
</div>
</div>
<% elsif item.succeeded? %>
<p class='bulkrax-p-align'>
<strong>Succeeded At:</strong> <%= item.status_at %>
</p>
<% else %>
<p class='bulkrax-p-align'>
<strong>Succeeded At:</strong> Item has not yet been <%= @importer.present? ? 'imported' : 'exported' %> successfully
</p>
<% end %>

<div class="accordion-container">
<div class="accordion-heading" role="tab" id="error-trace-heading">
<a class="accordion-title" role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
All Statuses:
</a>
<a role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
<div class="accordion-icon fa fa-times-circle" aria-hidden="true"></div>
</a>
</div>
<div id="error-trace-show" class="accordion-collapse collapse" role="tabpanel" aria-labelledby="error-trace-show">
<div class="accordion-body">
<div class="bulkrax-nav-tab-bottom-margin">
<!-- Toggle buttons -->
<div class="btn-group pull-right" role="group" aria-label="...">
<button id="full-errors-tab" type="button" class="btn btn-default active"><a href="#bulkrax-full-toggle-1" aria-controls="bulkrax-full-toggle-1" role="tab" data-toggle="tab">Full</a></button>
<button id="raw-errors-tab" type="button" class="btn btn-default"><a href="#bulkrax-raw-toggle-1" aria-controls="bulkrax-raw-toggle-1" role="tab" data-toggle="tab">Raw</a></button>
</div>
<!-- Tab panes -->
<div class="tab-content">
<% item.statuses.map do |item_status| %>
<div role="tabpanel" class="tab-pane active" id="bulkrax-full-toggle-1">
<strong>Occured at:</strong> <%= item_status.updated_at %><br /><br />
<strong>Link to Status Page:</strong> <%= <%= link_to "Status Details", statuses_path(item_status.id) %>%>
<strong>Message:</strong> <%= item_status.error_class %> - <%= item_status.error_message %><br /><br />
</div>
<div role="tabpanel" class="tab-pane" id="bulkrax-raw-toggle-1">
<strong>Occured at:</strong> <%= item_status.updated_at %><br /><br />
<strong>Link to Status Page:</strong> <%= <%= link_to "Status Details", statuses_path(item_status.id) %>%>
<strong>Message:</strong> <%= item_status.error_class %> - <%= item_status.error_message %><br /><br />
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
85 changes: 85 additions & 0 deletions app/views/bulkrax/statuses/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<% if item.succeeded? %>
<p class='bulkrax-p-align'>
<strong>Succeeded At:</strong> <%= item.status_at %>
</p>
<% elsif item.failed? %>
<div class="accordion-container">
<div class="accordion-heading" role="tab" id="error-trace-heading">
<a class="accordion-title" role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
Current Error:
</a>
<a role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
<div class="accordion-icon fa fa-times-circle" aria-hidden="true"></div>
</a>
</div>
<div id="error-trace-show" class="accordion-collapse collapse" role="tabpanel" aria-labelledby="error-trace-show">
<div class="accordion-body">
<div class="bulkrax-nav-tab-bottom-margin">
<!-- Toggle buttons -->
<div class="btn-group pull-right" role="group" aria-label="...">
<button id="full-errors-tab" type="button" class="btn btn-default active"><a href="#bulkrax-full-toggle-1" aria-controls="bulkrax-full-toggle-1" role="tab" data-toggle="tab">Full</a></button>
<button id="raw-errors-tab" type="button" class="btn btn-default"><a href="#bulkrax-raw-toggle-1" aria-controls="bulkrax-raw-toggle-1" role="tab" data-toggle="tab">Raw</a></button>
</div>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="bulkrax-full-toggle-1">
<strong>Errored at:</strong> <%= item.status_at %><br /><br />
<strong>Error:</strong> <%= item.current_status.error_class %> - <%= item.current_status.error_message %><br /><br />
<strong>Error Trace:</strong><br/><br />
<% item.current_status.error_backtrace.each do |v| %>
<%= coderay(v, { wrap: :page, css: :class, tab_width: 200, break_lines: true }) %>
<br>
<% end %>
</div>
<div role="tabpanel" class="tab-pane" id="bulkrax-raw-toggle-1">
<strong>Errored at:</strong> <%= item.status_at %><br /><br />
<strong>Error:</strong> <%= item.current_status.error_class %> - <%= item.current_status.error_message %><br /><br />
<strong>Error Trace:</strong><br/><br />
<% item.current_status.error_backtrace.each do |v| %>
<%= coderay(v, { css: :class, tab_width: 0, break_lines: false }) %>
<br>
<% end %>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>

<div class="accordion-container">
<div class="accordion-heading" role="tab" id="error-trace-heading">
<a class="accordion-title" role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
All Statuses:
</a>
<a role="button" data-toggle="collapse" data-target="#error-trace-show" aria-expanded="true" aria-controls="error-trace-show">
<div class="accordion-icon fa fa-times-circle" aria-hidden="true"></div>
</a>
</div>
<div id="error-trace-show" class="accordion-collapse collapse" role="tabpanel" aria-labelledby="error-trace-show">
<div class="accordion-body">
<div class="bulkrax-nav-tab-bottom-margin">
<!-- Toggle buttons -->
<div class="btn-group pull-right" role="group" aria-label="...">
<button id="full-errors-tab" type="button" class="btn btn-default active"><a href="#bulkrax-full-toggle-1" aria-controls="bulkrax-full-toggle-1" role="tab" data-toggle="tab">Full</a></button>
<button id="raw-errors-tab" type="button" class="btn btn-default"><a href="#bulkrax-raw-toggle-1" aria-controls="bulkrax-raw-toggle-1" role="tab" data-toggle="tab">Raw</a></button>
</div>
<!-- Tab panes -->
<div class="tab-content">
<% item.statuses.map do |item_status| %>
<div role="tabpanel" class="tab-pane active" id="bulkrax-full-toggle-1">
<strong>Occured at:</strong> <%= item_status.updated_at %><br /><br />
<strong>Link to Status Page:</strong> <%= <%= link_to "Status Details", statuses_path(item_status.id) %>%>
<strong>Message:</strong> <%= item_status.error_class %> - <%= item_status.error_message %><br /><br />
</div>
<div role="tabpanel" class="tab-pane" id="bulkrax-raw-toggle-1">
<strong>Occured at:</strong> <%= item_status.updated_at %><br /><br />
<strong>Link to Status Page:</strong> <%= <%= link_to "Status Details", statuses_path(item_status.id) %>%>
<strong>Message:</strong> <%= item_status.error_class %> - <%= item_status.error_message %><br /><br />
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
get :exporter_table
end
resources :entries, only: %i[show update destroy]
resources :statuses, only: :show
end
resources :importers do
put :continue
Expand All @@ -19,6 +20,7 @@
post :external_sets
end
resources :entries, only: %i[show update destroy]
resources :statuses, only: :show
get :upload_corrected_entries
post :upload_corrected_entries_file
end
Expand Down
Loading
Loading