hyrax-preservation 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +15 -0
- data/app/assets/config/preservation_manifest.js +2 -0
- data/app/assets/javascripts/hyrax/preservation/application.js +13 -0
- data/app/assets/stylesheets/hyrax/preservation/application.css +15 -0
- data/app/controllers/hyrax/preservation/events_controller.rb +133 -0
- data/app/helpers/hyrax/preservation/application_helper.rb +6 -0
- data/app/indexers/hyrax/preservation/event_indexer.rb +73 -0
- data/app/jobs/hyrax/preservation/application_job.rb +6 -0
- data/app/mailers/hyrax/preservation/application_mailer.rb +8 -0
- data/app/models/hyrax/preservation/event.rb +41 -0
- data/app/models/hyrax/preservation/premis_event_type.rb +64 -0
- data/app/presenters/hyrax/preservation/event_index_presenter.rb +12 -0
- data/app/presenters/hyrax/preservation/event_show_presenter.rb +11 -0
- data/app/search_builders/hyrax/preservation/events_search_builder.rb +105 -0
- data/app/views/hyrax/preservation/events/_event.html.erb +1 -0
- data/app/views/hyrax/preservation/events/_filter_search.html.erb +6 -0
- data/app/views/hyrax/preservation/events/_index_header_list_default.html.erb +20 -0
- data/app/views/hyrax/preservation/events/_previous_next_doc.html.erb +29 -0
- data/app/views/hyrax/preservation/events/filter_search/_date_range.html.erb +18 -0
- data/app/views/hyrax/preservation/events/filter_search/_premis_agent.html.erb +15 -0
- data/app/views/hyrax/preservation/events/filter_search/_premis_event_type.html.erb +18 -0
- data/app/views/hyrax/preservation/events/index.html.erb +10 -0
- data/app/views/layouts/hyrax/preservation/application.html.erb +14 -0
- data/config/routes.rb +3 -0
- data/lib/generators/hyrax/preservation/install_generator.rb +21 -0
- data/lib/hyrax/preservation.rb +12 -0
- data/lib/hyrax/preservation/demo.rb +80 -0
- data/lib/hyrax/preservation/engine.rb +13 -0
- data/lib/hyrax/preservation/event_logger.rb +18 -0
- data/lib/hyrax/preservation/search_state.rb +9 -0
- data/lib/hyrax/preservation/service_environment.rb +65 -0
- data/lib/hyrax/preservation/version.rb +5 -0
- metadata +307 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b640e48b5f2c1c7671aafe3cedbfa3c9eddd13e47a0b42aa710e814845bcbf6
|
4
|
+
data.tar.gz: a0046c6f6ad64f5b2ec63feb340c74699073e4d1bc47802d0ede9d59c572bbe9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d19413cfa69f75cb3e03b8c7bd83615c55e2c6859ec6f6911099a7c9851f6b2b7f094235bd11d2a71cc28e09c232f807638730485b170e51be14cdd2fb3f0abd
|
7
|
+
data.tar.gz: 4453203e60f1de3df9360fad1dbbdabba447e0c82197cd256b5bb40f35c5ad08cde371fd124d093d8b701bd9b6b30eeb6a531621682c410a33798e6163e279ae
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Andrew Myers
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'bundler/gem_tasks'
|
8
|
+
load 'rails/tasks/statistics.rake'
|
9
|
+
require 'engine_cart/rake_task'
|
10
|
+
|
11
|
+
# Load tasks for gem development
|
12
|
+
Dir.glob('gem_development_rake_tasks/*.rake').each { |r| import r }
|
13
|
+
|
14
|
+
# Set the default rake task when developing this gem.
|
15
|
+
task :default => ['ci']
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'hyrax/preservation/search_state'
|
2
|
+
|
3
|
+
module Hyrax
|
4
|
+
module Preservation
|
5
|
+
class EventsController < ActionController::Base
|
6
|
+
include Blacklight::Controller
|
7
|
+
include Hydra::Controller::ControllerBehavior
|
8
|
+
include Hydra::Catalog
|
9
|
+
include Hyrax::Controller
|
10
|
+
|
11
|
+
# Include Blacklight helpers that are needed to avoid breakage when using
|
12
|
+
# Blacklight views.
|
13
|
+
helper CatalogHelper
|
14
|
+
helper ComponentHelper
|
15
|
+
helper LayoutHelper
|
16
|
+
|
17
|
+
# Include Hyrax helpers that are needed to avoid breakage when rendering
|
18
|
+
# Hyrax views.
|
19
|
+
helper HyraxHelper
|
20
|
+
|
21
|
+
# Override Hyrax::UrlHelper#url_for_document
|
22
|
+
# helper_method :url_for_document
|
23
|
+
helper_method :display_premis_agent
|
24
|
+
helper_method :display_premis_event_date_time
|
25
|
+
helper_method :display_related_file
|
26
|
+
|
27
|
+
# TODO: We used to include CurationConcerns::ApplicationControllerBehavior
|
28
|
+
# here, but that module was merged into Sufia::Controller, which was later
|
29
|
+
# converted to Hyrax::Controller. But we're not sure if it's still needed.
|
30
|
+
# TODO: Determine whether or not we need to include Hyrax::Controller, and
|
31
|
+
# upadate (or delete) these commets accordingly.
|
32
|
+
# include Hyrax::Controller
|
33
|
+
include Hyrax::ThemedLayoutController
|
34
|
+
with_themed_layout '1_column'
|
35
|
+
|
36
|
+
# Prevent CSRF attacks by raising an exception.
|
37
|
+
# For APIs, you may want to use :null_session instead.
|
38
|
+
protect_from_forgery with: :exception
|
39
|
+
|
40
|
+
# Override rails path for the views by appending 'catalog' as a
|
41
|
+
# place to look for views. This allows using default blacklight
|
42
|
+
# views if you don't want to override each one.
|
43
|
+
def _prefixes
|
44
|
+
@_prefixes ||= super + ['catalog']
|
45
|
+
end
|
46
|
+
|
47
|
+
configure_blacklight do |config|
|
48
|
+
|
49
|
+
config.search_builder_class = EventsSearchBuilder
|
50
|
+
|
51
|
+
# Index view config
|
52
|
+
config.index.document_presenter_class = EventIndexPresenter
|
53
|
+
# NOTE: setting `config.index.title_field` here has no effect, because
|
54
|
+
# we're currently overriding the presenter class, and the partial that
|
55
|
+
# would normally be looking for it. Instead, see the overridden partial
|
56
|
+
# in app/views/preservation/events/_index_header_list_default.html.erb
|
57
|
+
# and the EventIndexPresenter#search_result_title method.
|
58
|
+
config.add_index_field solr_name(:hasEventRelatedObject, :symbol), label: "File", helper_method: :display_related_file
|
59
|
+
config.add_index_field solr_name(:premis_event_date_time, :stored_searchable, type: :date), label: "Date", helper_method: :display_premis_event_date_time
|
60
|
+
config.add_index_field solr_name(:premis_agent, :symbol), label: "Agent", helper_method: :display_premis_agent
|
61
|
+
|
62
|
+
# Show view config
|
63
|
+
config.show.document_presenter_class = EventShowPresenter
|
64
|
+
config.add_show_field solr_name(:premis_agent, :symbol), label: "PREMIS Agent"
|
65
|
+
config.add_show_field solr_name(:premis_event_date_time, :stored_searchable, type: :date), label: "Date"
|
66
|
+
config.add_show_field solr_name(:hasEventRelatedObject, :symbol), label: "File", helper_method: :display_related_file
|
67
|
+
|
68
|
+
# Remove unused actions from the show view. Enabling these breaks the
|
69
|
+
# show view because Blacklight generates urls that don't exist. Figuring
|
70
|
+
# out how to make them work will take more digging.
|
71
|
+
config.show.document_actions.delete(:bookmark)
|
72
|
+
config.show.document_actions.delete(:email)
|
73
|
+
config.show.document_actions.delete(:sms)
|
74
|
+
config.show.document_actions.delete(:citation)
|
75
|
+
|
76
|
+
# Facet config
|
77
|
+
# config.add_facet_fields_to_solr_request!
|
78
|
+
# config.add_facet_field :premis_event_date_time_ltsi, label: 'Date', range: { segments: false }
|
79
|
+
# config.add_facet_field solr_name(:premis_event_type, :symbol), label: 'Type'
|
80
|
+
end
|
81
|
+
|
82
|
+
# Overrides CatalogController::UrlHelper#url_for_document. It would be
|
83
|
+
# nice to put this method in our own Preservation::UrlHelper module but I
|
84
|
+
# couldn't get the helper to load after Hyrax::UrlHelper in
|
85
|
+
# order to overwrite the #url_for_document method. NOTE: In any event,
|
86
|
+
# this method needs to behave roughly the same way as
|
87
|
+
# CurationCocerns::UrlHelper#url_for_document, so if that method changes
|
88
|
+
# change this one accordingly.
|
89
|
+
# def url_for_document(doc, _options = {})
|
90
|
+
# polymorphic_path([preservation, doc])
|
91
|
+
# end
|
92
|
+
|
93
|
+
def search_state
|
94
|
+
@search_state ||= Hyrax::Preservation::SearchState.new(params, blacklight_config, self)
|
95
|
+
end
|
96
|
+
|
97
|
+
def display_premis_agent(opts={})
|
98
|
+
solr_doc = opts[:document]
|
99
|
+
premis_agent_mailto_uri = solr_doc[opts[:field]]
|
100
|
+
premis_agent_mailto_uri.first.sub(/^mailto\:/, '')
|
101
|
+
end
|
102
|
+
|
103
|
+
def display_premis_event_date_time(opts={})
|
104
|
+
solr_doc = opts[:document]
|
105
|
+
premis_event_date_time = solr_doc[opts[:field]]
|
106
|
+
Date.parse(premis_event_date_time.to_s).strftime('%Y-%m-%d')
|
107
|
+
end
|
108
|
+
|
109
|
+
def display_related_file(opts={})
|
110
|
+
# TODO: Is there a better way than having the controller send back HTML?
|
111
|
+
# TODO: Is there a better way to fetch the FileSet ID and Title? This way is confusing.
|
112
|
+
solr_doc = opts[:document]
|
113
|
+
file_set_id = solr_doc[:hasEventRelatedObject_ssim].first
|
114
|
+
file_set_url = Rails.application.routes.url_helpers.hyrax_file_set_path(id: file_set_id)
|
115
|
+
|
116
|
+
# TODO: this is totally klugey. We're pulling back the FileSet object from Fedora in order to get
|
117
|
+
# a good name to display it with. Originally, we were getting this value from the Solr document of
|
118
|
+
# the PreservationEvent object, but we ran into an issue where the PreservationEventIndexer does
|
119
|
+
# not know which FileSet property has been populated with a good, representative name for the FileSet
|
120
|
+
# at the time of indexing, because that is determined by configuration within the host app in any one of:
|
121
|
+
# 1. the FileSet model
|
122
|
+
# 1. the ingest configuration of the FileSet if using hyrax-ingest.
|
123
|
+
# 1. the FileSet indexer
|
124
|
+
# So either this value needs to be configurable within the host app,
|
125
|
+
# or the PreservationEventIndexer (in the hyrax-preservation gem) needs to have similar fallback logic
|
126
|
+
# when indexing a representative name for the FileSet.
|
127
|
+
file_set = ::FileSet.find(file_set_id)
|
128
|
+
file_set_title = file_set&.title&.first || file_set&.label || file_set&.filename&.first
|
129
|
+
"<a href='#{file_set_url}'>#{file_set_title}</a>".html_safe
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class EventIndexer < ActiveFedora::IndexingService
|
4
|
+
def generate_solr_document
|
5
|
+
super.tap do |solr_doc|
|
6
|
+
# TODO: Some of the conditionals checking for existence of properties
|
7
|
+
# may be removed after require those fields with validations on the
|
8
|
+
# model.
|
9
|
+
|
10
|
+
if object.premis_event_related_object
|
11
|
+
Solrizer.set_field(solr_doc,
|
12
|
+
'related_file_title',
|
13
|
+
object.premis_event_related_object.label,
|
14
|
+
:stored_searchable)
|
15
|
+
end
|
16
|
+
|
17
|
+
unless object.premis_event_type.empty?
|
18
|
+
# Index the PREMIS event type.
|
19
|
+
# NOTE: the value we index is only the last URI segment, which is a
|
20
|
+
# 3-letter abbreviation.
|
21
|
+
Solrizer.set_field(solr_doc,
|
22
|
+
'premis_event_type',
|
23
|
+
shortened_field_val = URI(object.premis_event_type.first.id).path.split('/').last,
|
24
|
+
:symbol)
|
25
|
+
end
|
26
|
+
|
27
|
+
unless object.premis_agent.empty?
|
28
|
+
# Index the PREMIS agent, under the assumption that is a mailto: URI.
|
29
|
+
# NOTE: The value we index is only the amil address, without the "mailto:" part.
|
30
|
+
Solrizer.set_field(solr_doc,
|
31
|
+
'premis_agent',
|
32
|
+
object.premis_agent.first.id.sub(/^mailto:/, ''),
|
33
|
+
:symbol)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# If the PreservationEvent's agent is found in the db,
|
38
|
+
# then index that user's full name as well.
|
39
|
+
# TODO: Not sure if this is a good idea.
|
40
|
+
# How much metadata about the agent should we index for PreservationEvents?
|
41
|
+
# if object.premis_agent_db_user
|
42
|
+
# Solrizer.set_field(solr_doc,
|
43
|
+
# 'premis_agent_full_name',
|
44
|
+
# object.premis_agent_db_user.first.id,
|
45
|
+
# :stored_searchable)
|
46
|
+
# end
|
47
|
+
|
48
|
+
unless object.premis_event_date_time.empty?
|
49
|
+
# Index the PREMIS event date time as a date.
|
50
|
+
Solrizer.set_field(solr_doc,
|
51
|
+
'premis_event_date_time',
|
52
|
+
object.premis_event_date_time.first,
|
53
|
+
:stored_searchable)
|
54
|
+
|
55
|
+
# Index the PREMIS event date time as an integer, for range queries.
|
56
|
+
Solrizer.set_field(solr_doc,
|
57
|
+
'premis_event_date_time_integer',
|
58
|
+
object.premis_event_date_time.first.strftime('%Y%m%d').to_i,
|
59
|
+
Solrizer::Descriptor.new(:long, :stored, :indexed))
|
60
|
+
end
|
61
|
+
|
62
|
+
unless object.premis_event_outcome.empty?
|
63
|
+
# Index the PREMIS event outcome.
|
64
|
+
Solrizer.set_field(solr_doc,
|
65
|
+
'premis_event_outcome',
|
66
|
+
object.premis_event_outcome.first,
|
67
|
+
:stored_searchable)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class Event < ActiveFedora::Base
|
4
|
+
type ::RDF::Vocab::PREMIS.Event
|
5
|
+
|
6
|
+
belongs_to :premis_event_related_object, predicate: ::RDF::Vocab::PREMIS.hasEventRelatedObject, class_name: ::FileSet
|
7
|
+
|
8
|
+
property :premis_event_type, predicate: ::RDF::Vocab::PREMIS.hasEventType
|
9
|
+
property :premis_agent, predicate: ::RDF::Vocab::PREMIS.hasAgent
|
10
|
+
property :premis_event_date_time, predicate: ::RDF::Vocab::PREMIS.hasEventDateTime
|
11
|
+
property :premis_event_outcome, predicate: ::RDF::Vocab::PREMIS.hasEventOutcome
|
12
|
+
property :premis_event_detail, predicate: ::RDF::Vocab::PREMIS.hasEventDetail
|
13
|
+
|
14
|
+
def user_from_db
|
15
|
+
@user_from_db ||= User.where(email: premis_agent)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] the label of the PREMIS event type that corresponds
|
19
|
+
# with the URI from the first value of the #premis_event_type property.
|
20
|
+
def premis_event_type_label
|
21
|
+
premis_event_type_object.label
|
22
|
+
end
|
23
|
+
|
24
|
+
def premis_event_type_abbr
|
25
|
+
premis_event_type_object.abbr
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.indexer
|
29
|
+
EventIndexer
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
# @return [Preservation::PremisEventType] first PremisEventType instance
|
34
|
+
# found where Preservation::PremisEventType#uri matches first value
|
35
|
+
# found in #premis_event_type property.
|
36
|
+
def premis_event_type_object
|
37
|
+
@premis_event_type_object ||= Preservation::PremisEventType.find_by_uri(premis_event_type.first.id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# A basic PORO model for PREMIS event types.
|
2
|
+
#
|
3
|
+
# The data for this model is not persisted to any data store. It is just
|
4
|
+
# hardcoded (see Preservation::PremisEventyType.all).
|
5
|
+
#
|
6
|
+
# While only the URI of a PREMIS event type is stored on the
|
7
|
+
# Preservation::Event#premis_event_type property, this PORO is used to pair
|
8
|
+
# the URI with an abbreviation and a label.
|
9
|
+
module Hyrax
|
10
|
+
module Preservation
|
11
|
+
class PremisEventType
|
12
|
+
attr_reader :abbr, :label
|
13
|
+
|
14
|
+
def initialize(abbr, label='')
|
15
|
+
@abbr = abbr
|
16
|
+
@label = label
|
17
|
+
end
|
18
|
+
|
19
|
+
def uri
|
20
|
+
::RDF::Vocab::PremisEventType.send(abbr)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Array] list of all available PremisEventType instances.
|
24
|
+
def self.all
|
25
|
+
@all ||= [
|
26
|
+
new('cap', 'PREMIS Capture'),
|
27
|
+
new('com', 'PREMIS Compression'),
|
28
|
+
new('cre', 'PREMIS Creation'),
|
29
|
+
new('dea', 'PREMIS Deaccession'),
|
30
|
+
new('dec', 'PREMIS Decryption'),
|
31
|
+
new('del', 'PREMIS Deletion'),
|
32
|
+
new('dig', 'PREMIS Digital Signature Validation'),
|
33
|
+
new('fix', 'PREMIS Fixity Check'),
|
34
|
+
new('ing', 'PREMIS Ingestion'),
|
35
|
+
new('mes', 'PREMIS Message Digest Calculation'),
|
36
|
+
new('mig', 'PREMIS Migration'),
|
37
|
+
new('nor', 'PREMIS Normalization'),
|
38
|
+
new('rep', 'PREMIS Replication'),
|
39
|
+
new('val', 'PREMIS Validation'),
|
40
|
+
new('vir', 'PREMIS Virus Check')
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [String] URI to use for comparison. Note #to_s is called on the
|
45
|
+
# param before comparing.
|
46
|
+
# @return [Preservation::PremisEventType] first found instance with URI
|
47
|
+
# that matches parameter.
|
48
|
+
def self.find_by_uri(uri)
|
49
|
+
result = all.find { |record| record.uri.to_s == uri.to_s }
|
50
|
+
raise NotFound.new("PremisEventType with URI \"#{uri.to_s}\" was not found") unless result
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.find_by_abbr(abbr)
|
55
|
+
result = all.find { |record| record.abbr == abbr }
|
56
|
+
raise NotFound.new("PremisEventType with abbreviation \"#{abbr}\" was not found") unless result
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
# Custom Error Classes
|
61
|
+
class NotFound < StandardError; end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class EventIndexPresenter < Blacklight::IndexPresenter
|
4
|
+
# Returns the value of PremisEventType#label for the PremisEventType instance
|
5
|
+
# whose #abbr value matches that which is in the solr document.
|
6
|
+
def search_result_title
|
7
|
+
premis_event_type = PremisEventType.all.find { |premis_event_type| premis_event_type.abbr == document.first(:premis_event_type_ssim) }
|
8
|
+
premis_event_type.label
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class EventShowPresenter < Blacklight::ShowPresenter
|
4
|
+
def heading
|
5
|
+
premis_event_type_abbr = document[Solrizer.solr_name(:premis_event_type, :symbol)].first
|
6
|
+
premis_event_type = Preservation::PremisEventType.all.find { |premis_event_type| premis_event_type.abbr == premis_event_type_abbr }
|
7
|
+
premis_event_type.label
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class EventsSearchBuilder < Blacklight::SearchBuilder
|
4
|
+
include Blacklight::Solr::SearchBuilderBehavior
|
5
|
+
|
6
|
+
self.default_processor_chain += [:only_models_for_preservation_events, :apply_premis_event_date_time_filter,
|
7
|
+
:apply_premis_event_type_filter, :apply_premis_agent_filter,
|
8
|
+
:apply_premis_event_related_object_filter]
|
9
|
+
|
10
|
+
|
11
|
+
def only_models_for_preservation_events(solr_params)
|
12
|
+
solr_params[:fq] ||= []
|
13
|
+
solr_params[:fq] << "{!terms f=has_model_ssim}Hyrax::Preservation::Event"
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply_premis_event_date_time_filter(solr_params)
|
17
|
+
if premis_event_date_time_filter
|
18
|
+
solr_params[:fq] ||= []
|
19
|
+
solr_params[:fq] << premis_event_date_time_filter
|
20
|
+
end
|
21
|
+
solr_params
|
22
|
+
end
|
23
|
+
|
24
|
+
def apply_premis_event_type_filter(solr_params)
|
25
|
+
if premis_event_type_filter
|
26
|
+
solr_params[:fq] ||= []
|
27
|
+
solr_params[:fq] << premis_event_type_filter
|
28
|
+
end
|
29
|
+
solr_params
|
30
|
+
end
|
31
|
+
|
32
|
+
def apply_premis_agent_filter(solr_params)
|
33
|
+
if premis_agent_filter
|
34
|
+
solr_params[:fq] ||= []
|
35
|
+
solr_params[:fq] << premis_agent_filter
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def apply_premis_event_related_object_filter(solr_params)
|
40
|
+
if premis_event_related_object_filter
|
41
|
+
solr_params[:fq] ||= []
|
42
|
+
solr_params[:fq] << premis_event_related_object_filter
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Returns a date/time range for a Solr query for the 'after' and 'before'
|
49
|
+
# URL params.
|
50
|
+
def premis_event_date_time_filter
|
51
|
+
@premis_event_date_time_filter ||= begin
|
52
|
+
if premis_event_date_time_before || premis_event_date_time_after
|
53
|
+
range = "#{premis_event_date_time_after || '*'} TO #{premis_event_date_time_before || '*'}"
|
54
|
+
"premis_event_date_time_dtsim:[#{range}]"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the 'before' date time formatted for a Solr query.
|
60
|
+
def premis_event_date_time_before
|
61
|
+
@premis_event_date_time_before ||= formatted_premis_event_date_time(blacklight_params['before'])
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the 'after' date time formatted for a Solr query.
|
65
|
+
def premis_event_date_time_after
|
66
|
+
@premis_event_date_time_after ||= formatted_premis_event_date_time(blacklight_params['after'])
|
67
|
+
end
|
68
|
+
|
69
|
+
# Converts an unformatted date (as passed in via URL) to a date formatted
|
70
|
+
# for a Solr query.
|
71
|
+
def formatted_premis_event_date_time(unformatted_date)
|
72
|
+
DateTime.parse(unformatted_date.to_s).utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
73
|
+
rescue ArgumentError => e
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def premis_event_type_filter
|
78
|
+
@premis_event_type_filter ||= begin
|
79
|
+
if blacklight_params['premis_event_type']
|
80
|
+
valid_premis_abbrs = blacklight_params['premis_event_type'] & Hyrax::Preservation::PremisEventType.all.map(&:abbr)
|
81
|
+
"(#{valid_premis_abbrs.map { |abbr| "premis_event_type_ssim:#{abbr}"}.join(" OR ")})"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def premis_agent_filter
|
87
|
+
@premis_agent_filter ||= begin
|
88
|
+
if blacklight_params['agent'].present?
|
89
|
+
# TODO: sanitize URL parameters. Do not simply trust user input.
|
90
|
+
"premis_agent_ssim:#{blacklight_params['agent']}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def premis_event_related_object_filter
|
96
|
+
@premis_event_related_object_filter ||= begin
|
97
|
+
if blacklight_params['related_object'].present?
|
98
|
+
# TODO: sanitize URL parameters. Do not simply trust user input.
|
99
|
+
"hasEventRelatedObject_ssim:#{blacklight_params['related_object']}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render 'catalog/document', document: event, document_counter: event_counter %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<div>
|
2
|
+
<%= link_to "Clear All Filters", hyrax_preservation.events_url %>
|
3
|
+
</div>
|
4
|
+
<%= render 'hyrax/preservation/events/filter_search/date_range' %>
|
5
|
+
<%= render 'hyrax/preservation/events/filter_search/premis_event_type' %>
|
6
|
+
<%= render 'hyrax/preservation/events/filter_search/premis_agent' %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%
|
2
|
+
# NOTE: This overrides Hyrax's
|
3
|
+
# app/views/catalog/_index_header_list_default.html.erb which (at the time of
|
4
|
+
# this writing) only calls `document.title_or_label`, where `document` is a
|
5
|
+
# `SolrDocument` instance. We need to use a presenter object, because we use a
|
6
|
+
# small bit of logic to return the title of a search result. Hyrax will
|
7
|
+
# probably be upgraded to use a presenter in it's own version of this view
|
8
|
+
# partial in the near future, but until then, we override it here.
|
9
|
+
|
10
|
+
# Furthermore, since we are using our own custom presenter, and our own custom
|
11
|
+
# view partial, configuring the title field using `config.index.title_file` in
|
12
|
+
# the EventsController's `configure_blacklight` block has no effect here. Instead,
|
13
|
+
# we're just overriding the default index presenter, giving it a special
|
14
|
+
# method, and calling that special method from this overridden partial.
|
15
|
+
|
16
|
+
# Confused yet? Yeah, me too.
|
17
|
+
%>
|
18
|
+
<h2>
|
19
|
+
<%= link_to index_presenter(document).search_result_title, document %>
|
20
|
+
</h2>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<%
|
2
|
+
# This is an override of a partial from Blacklight 6.7.3
|
3
|
+
# in app/views/catalog/_previous_next_doc.html.erb.
|
4
|
+
# See inline comment below for details of why the override is needed.
|
5
|
+
%>
|
6
|
+
|
7
|
+
<% #Using the Bootstrap Pagination class -%>
|
8
|
+
<% #DEPRECATED - using id="previousNextDocument" as a selector is deprecated and will be removed in Blacklight 6.0 %>
|
9
|
+
<div id='previousNextDocument' class='pagination-search-widgets'>
|
10
|
+
<% if @previous_document || @next_document %>
|
11
|
+
<div class="page_links">
|
12
|
+
<%= link_to_previous_document @previous_document %> |
|
13
|
+
|
14
|
+
<%= item_page_entry_info %> |
|
15
|
+
|
16
|
+
<%= link_to_next_document @next_document %>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
<% if current_search_session %>
|
20
|
+
<div class="pull-right search-widgets">
|
21
|
+
<%
|
22
|
+
# Calling #link_back_to_catalog here results in a routing error: no route matches "preservatio/catalog"
|
23
|
+
# Filed a detailed bug: https://github.com/projectblacklight/blacklight/issues/1647
|
24
|
+
# In the meantime, just skip the link back to the catalog.
|
25
|
+
%>
|
26
|
+
<%=link_to t('blacklight.search.start_over'), start_over_path(current_search_session.try(:query_params) || {}), id: 'startOverLink', class: 'btn' %>
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<h2>Date</h2>
|
2
|
+
<form id="date_time_range_filter" action="<%= hyrax_preservation.events_url %>">
|
3
|
+
<label>From</label>
|
4
|
+
<input name="after" value="<%= params['after'] %>" />
|
5
|
+
<label>To</label>
|
6
|
+
<input name="before" value="<%= params['before'] %>" />
|
7
|
+
|
8
|
+
<!-- TODO: This logic needs to be replicated for all filter forms. Better in a helper method? -->
|
9
|
+
<% Rack::Utils.parse_query(request.query_string).except("after", "before").each do |param, val| %>
|
10
|
+
<% # Sometimes `val` may be an array, but not always. So we just array-ify
|
11
|
+
# it here to cover both cases. %>
|
12
|
+
<% Array(val).each do |single_val| %>
|
13
|
+
<input type="hidden" name="<%= param %>" value="<%= single_val %>" />
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<button type="submit">Submit</button>
|
18
|
+
</form>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h2>PREMIS Agent</h2>
|
2
|
+
<form id="premis_agent_filter" action="<%= hyrax_preservation.events_url %>">
|
3
|
+
<label for="agent">Agent</label>
|
4
|
+
<input id="agent" name="agent" value="<%= params['agent'] %>" />
|
5
|
+
<!-- TODO: This logic needs to be replicated for all filter forms. Better in a helper method? -->
|
6
|
+
<% Rack::Utils.parse_query(request.query_string).except("agent").each do |param, val| %>
|
7
|
+
<% # Sometimes `val` may be an array, but not always. So we just array-ify
|
8
|
+
# it here to cover both cases. %>
|
9
|
+
<% Array(val).each do |single_val| %>
|
10
|
+
<input type="hidden" name="<%= param %>" value="<%= single_val %>" />
|
11
|
+
<% end %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<button type="submit">Submit</button>
|
15
|
+
</form>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<h2>PREMIS Event Type</h2>
|
2
|
+
<form id="premis_event_type_filter" action="<%= hyrax_preservation.events_url %>">
|
3
|
+
<% Hyrax::Preservation::PremisEventType.all.each do |premis_event_type| %>
|
4
|
+
<input type="checkbox" id="premis_event_type_<%= premis_event_type.abbr %>" name="premis_event_type[]" value="<%= premis_event_type.abbr %>" <%= Array(request.params['premis_event_type']).include?(premis_event_type.abbr) ? 'checked="checked"' : '' %>/>
|
5
|
+
<label for="premis_event_type_<%= premis_event_type.abbr %>"><%= premis_event_type.label.sub(/^PREMIS/ , '') %></label>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<!-- TODO: This logic needs to be replicated for all filter forms. Better in a helper method? -->
|
9
|
+
<% Rack::Utils.parse_query(request.query_string).except("premis_event_type[]").each do |param, val| %>
|
10
|
+
<% # Sometimes `val` may be an array, but not always. So we just array-ify
|
11
|
+
# it here to cover both cases. %>
|
12
|
+
<% Array(val).each do |single_val| %>
|
13
|
+
<input type="hidden" name="<%= param %>" value="<%= single_val %>" />
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<button type="submit">Submit</button>
|
18
|
+
</form>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Preservation</title>
|
5
|
+
<%= stylesheet_link_tag "preservation/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "preservation/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Hyrax
|
2
|
+
module Preservation
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
desc <<-EOS
|
6
|
+
This generator makes the following changes to your application:
|
7
|
+
1. Adds Preservation routes to your ./config/routes.rb
|
8
|
+
EOS
|
9
|
+
|
10
|
+
# def inject_search_builder_behavior
|
11
|
+
# inject_into_file 'app/models/search_builder.rb', after: "include Hyrax::SearchFilters\n" do
|
12
|
+
# "\tinclude Hydradam::SearchBuilderBehavior\n"
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
|
16
|
+
def add_routes
|
17
|
+
route "mount Hyrax::Preservation::Engine, at: '/preservation'"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require_relative 'event_logger'
|
2
|
+
|
3
|
+
|
4
|
+
module Hyrax
|
5
|
+
module Preservation
|
6
|
+
class Demo
|
7
|
+
def self.clean_slate!
|
8
|
+
delete_all_file_sets!
|
9
|
+
delete_all_preservation_events!
|
10
|
+
delete_all_hydra_access_controls!
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.delete_all_file_sets!
|
14
|
+
FileSet.all.each { |fs| fs.delete }
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.delete_all_preservation_events!
|
18
|
+
Preservation::Event.all.each { |pe| pe.delete }
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.delete_all_hydra_access_controls!
|
22
|
+
::Hydra::AccessControl.all.each { |ac| ac.delete }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.new_file_set
|
26
|
+
FileSet.new.tap do |fs|
|
27
|
+
fs.apply_depositor_metadata(User.first)
|
28
|
+
fs.save!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.run_once!
|
33
|
+
file_set = new_file_set
|
34
|
+
|
35
|
+
# NOTE: PreservationEventLogger is a stateless service object that provides a "use anywhere" interface
|
36
|
+
# for logging preservation events. We don't have to use this pattern, but it has it's advantages.
|
37
|
+
|
38
|
+
# Create two sets of people for some realistic randomness in the demo records.
|
39
|
+
preservation_people = ['jlhardes@iu.edu', 'heidowdi@indiana.edu']
|
40
|
+
ingest_people = ['akhedkar@iu.edu', 'afredmyers@gmail.com']
|
41
|
+
|
42
|
+
|
43
|
+
# Create a fake capture date of sometime between now and 90 days ago.
|
44
|
+
capture_date = DateTime.now - rand(2..90).days
|
45
|
+
# Create a fake fixity check date sometime between the capture date and now.
|
46
|
+
fixity_date = rand(capture_date..DateTime.now)
|
47
|
+
# Create a fake ingest date of sometime beetween the capture date and now.
|
48
|
+
ingest_date = rand(capture_date..DateTime.now)
|
49
|
+
|
50
|
+
# Create an event for the file's capture.
|
51
|
+
Preservation::EventLogger.log_preservation_event(
|
52
|
+
file_set: file_set,
|
53
|
+
premis_event_type: 'cap',
|
54
|
+
premis_agent: preservation_people.sample,
|
55
|
+
premis_event_date_time: capture_date
|
56
|
+
)
|
57
|
+
|
58
|
+
# Create an event for the file's fixity check.
|
59
|
+
Preservation::EventLogger.log_preservation_event(
|
60
|
+
file_set: file_set,
|
61
|
+
premis_event_type: 'fix',
|
62
|
+
premis_agent: preservation_people.sample,
|
63
|
+
premis_event_date_time: fixity_date
|
64
|
+
)
|
65
|
+
|
66
|
+
# Create an event for the file's ingestion.
|
67
|
+
Preservation::EventLogger.log_preservation_event(
|
68
|
+
file_set: file_set,
|
69
|
+
premis_event_type: 'ing',
|
70
|
+
premis_agent: ingest_people.sample,
|
71
|
+
premis_event_date_time: ingest_date
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.run!(iterations=1)
|
76
|
+
iterations.times { self.run_once! }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Hyrax::Preservation
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace Hyrax::Preservation
|
4
|
+
|
5
|
+
config.autoload_paths += %W(
|
6
|
+
#{config.root}/app/helpers
|
7
|
+
#{config.root}/app/indexers
|
8
|
+
#{config.root}/app/presenters
|
9
|
+
#{config.root}/app/search_builders
|
10
|
+
#{config.root}/lib/preservation
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# TODO: Only use this as-is for Demo. If you want to use it as a service object
|
2
|
+
# it should be moved to a different location probably.
|
3
|
+
module Hyrax
|
4
|
+
module Preservation
|
5
|
+
class EventLogger
|
6
|
+
def self.log_preservation_event(opts={})
|
7
|
+
Preservation::Event.new.tap do |pe|
|
8
|
+
pe.premis_event_type += [ Preservation::PremisEventType.all.select { |premis_event_type| premis_event_type.abbr == opts[:premis_event_type].to_sym } ]
|
9
|
+
pe.premis_event_related_object = opts[:file_set]
|
10
|
+
# Assume opts[:premis_agent] is an email address, and make a 'mailto:' RDF::URI out of it.
|
11
|
+
pe.premis_agent += [::RDF::URI.new("mailto:#{opts[:premis_agent]}")]
|
12
|
+
pe.premis_event_date_time += [opts[:premis_event_date_time]]
|
13
|
+
pe.save!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'hyrax/preservation'
|
2
|
+
require 'solr_wrapper'
|
3
|
+
require 'fcrepo_wrapper'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
|
6
|
+
module Hyrax
|
7
|
+
module Preservation
|
8
|
+
class ServiceEnvironment
|
9
|
+
attr_reader :env
|
10
|
+
|
11
|
+
def initialize(env)
|
12
|
+
@env = (env || 'development').to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
wrap do
|
17
|
+
begin
|
18
|
+
puts "\nServices started. Ctrl+C to stop.\n\n"
|
19
|
+
sleep
|
20
|
+
rescue Interrupt
|
21
|
+
# TODO: Why doesn't this message get printed?
|
22
|
+
puts "Stopping services..."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def wrap
|
28
|
+
SolrWrapper.wrap(solr_wrapper_config) do |solr_wrapper_instance|
|
29
|
+
# If a solr collection exists, but is not configured to persist,
|
30
|
+
# then we must delete it before we try to re-create it. Otherwise
|
31
|
+
# SolrWrapper with throw an error. Note this is kind of an awkward
|
32
|
+
# way to check for existence of the core, but it's due to current
|
33
|
+
# limitation of the SolrWrapper interfaces.
|
34
|
+
if !solr_wrapper_config[:collection][:persist] && SolrWrapper::Client.new(solr_wrapper_instance.url).exists?(solr_wrapper_config[:collection][:name])
|
35
|
+
solr_wrapper_instance.delete solr_wrapper_config[:collection][:name]
|
36
|
+
end
|
37
|
+
|
38
|
+
solr_wrapper_instance.with_collection(solr_wrapper_config[:collection]) do
|
39
|
+
FcrepoWrapper.wrap(fcrepo_wrapper_config) do
|
40
|
+
yield
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def solr_wrapper_config
|
49
|
+
@solr_wrapper_config ||= YAML.load(File.read(solr_wrapper_config_path)).deep_symbolize_keys
|
50
|
+
end
|
51
|
+
|
52
|
+
def solr_wrapper_config_path
|
53
|
+
File.join(Hyrax::Preservation.root, ".solr_wrapper.#{env}.yml")
|
54
|
+
end
|
55
|
+
|
56
|
+
def fcrepo_wrapper_config
|
57
|
+
@fcrepo_wrapper_config ||= YAML.load(File.read(fcrepo_wrapper_config_path)).deep_symbolize_keys
|
58
|
+
end
|
59
|
+
|
60
|
+
def fcrepo_wrapper_config_path
|
61
|
+
File.join(Hyrax::Preservation.root, ".fcrepo_wrapper.#{env}.yml")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
metadata
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hyrax-preservation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Myers
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hyrax
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.4
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.4
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: jquery-ui-rails
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '5.0'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 5.0.5
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '5.0'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 5.0.5
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: sqlite3
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.3'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.3.13
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.3'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.3.13
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: rspec-rails
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '3.6'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.6.1
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.6'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 3.6.1
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: capybara
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '2.15'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 2.15.1
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '2.15'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 2.15.1
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: solr_wrapper
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.1'
|
120
|
+
- - '='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.1.0
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.1'
|
130
|
+
- - '='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.1.0
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: fcrepo_wrapper
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.8'
|
140
|
+
type: :development
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0.8'
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: factory_girl_rails
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '4.8'
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 4.8.0
|
157
|
+
type: :development
|
158
|
+
prerelease: false
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - "~>"
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '4.8'
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 4.8.0
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: pry-rails
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.3'
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 0.3.6
|
177
|
+
type: :development
|
178
|
+
prerelease: false
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - "~>"
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0.3'
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: 0.3.6
|
187
|
+
- !ruby/object:Gem::Dependency
|
188
|
+
name: pry-byebug
|
189
|
+
requirement: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - "~>"
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '3.6'
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: 3.6.0
|
197
|
+
type: :development
|
198
|
+
prerelease: false
|
199
|
+
version_requirements: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - "~>"
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '3.6'
|
204
|
+
- - ">="
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: 3.6.0
|
207
|
+
- !ruby/object:Gem::Dependency
|
208
|
+
name: launchy
|
209
|
+
requirement: !ruby/object:Gem::Requirement
|
210
|
+
requirements:
|
211
|
+
- - "~>"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '2.4'
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: 2.4.3
|
217
|
+
type: :development
|
218
|
+
prerelease: false
|
219
|
+
version_requirements: !ruby/object:Gem::Requirement
|
220
|
+
requirements:
|
221
|
+
- - "~>"
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '2.4'
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: 2.4.3
|
227
|
+
- !ruby/object:Gem::Dependency
|
228
|
+
name: rb-readline
|
229
|
+
requirement: !ruby/object:Gem::Requirement
|
230
|
+
requirements:
|
231
|
+
- - "~>"
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: '0.5'
|
234
|
+
type: :development
|
235
|
+
prerelease: false
|
236
|
+
version_requirements: !ruby/object:Gem::Requirement
|
237
|
+
requirements:
|
238
|
+
- - "~>"
|
239
|
+
- !ruby/object:Gem::Version
|
240
|
+
version: '0.5'
|
241
|
+
description: Hyrax Preservation provides models for storing and searching for preservation
|
242
|
+
metadata.
|
243
|
+
email:
|
244
|
+
- afredmyers@gmail.com
|
245
|
+
executables: []
|
246
|
+
extensions: []
|
247
|
+
extra_rdoc_files: []
|
248
|
+
files:
|
249
|
+
- MIT-LICENSE
|
250
|
+
- README.md
|
251
|
+
- Rakefile
|
252
|
+
- app/assets/config/preservation_manifest.js
|
253
|
+
- app/assets/javascripts/hyrax/preservation/application.js
|
254
|
+
- app/assets/stylesheets/hyrax/preservation/application.css
|
255
|
+
- app/controllers/hyrax/preservation/events_controller.rb
|
256
|
+
- app/helpers/hyrax/preservation/application_helper.rb
|
257
|
+
- app/indexers/hyrax/preservation/event_indexer.rb
|
258
|
+
- app/jobs/hyrax/preservation/application_job.rb
|
259
|
+
- app/mailers/hyrax/preservation/application_mailer.rb
|
260
|
+
- app/models/hyrax/preservation/event.rb
|
261
|
+
- app/models/hyrax/preservation/premis_event_type.rb
|
262
|
+
- app/presenters/hyrax/preservation/event_index_presenter.rb
|
263
|
+
- app/presenters/hyrax/preservation/event_show_presenter.rb
|
264
|
+
- app/search_builders/hyrax/preservation/events_search_builder.rb
|
265
|
+
- app/views/hyrax/preservation/events/_event.html.erb
|
266
|
+
- app/views/hyrax/preservation/events/_filter_search.html.erb
|
267
|
+
- app/views/hyrax/preservation/events/_index_header_list_default.html.erb
|
268
|
+
- app/views/hyrax/preservation/events/_previous_next_doc.html.erb
|
269
|
+
- app/views/hyrax/preservation/events/filter_search/_date_range.html.erb
|
270
|
+
- app/views/hyrax/preservation/events/filter_search/_premis_agent.html.erb
|
271
|
+
- app/views/hyrax/preservation/events/filter_search/_premis_event_type.html.erb
|
272
|
+
- app/views/hyrax/preservation/events/index.html.erb
|
273
|
+
- app/views/layouts/hyrax/preservation/application.html.erb
|
274
|
+
- config/routes.rb
|
275
|
+
- lib/generators/hyrax/preservation/install_generator.rb
|
276
|
+
- lib/hyrax/preservation.rb
|
277
|
+
- lib/hyrax/preservation/demo.rb
|
278
|
+
- lib/hyrax/preservation/engine.rb
|
279
|
+
- lib/hyrax/preservation/event_logger.rb
|
280
|
+
- lib/hyrax/preservation/search_state.rb
|
281
|
+
- lib/hyrax/preservation/service_environment.rb
|
282
|
+
- lib/hyrax/preservation/version.rb
|
283
|
+
homepage: https://github.com/IUBLibTech/hyrax-preservation
|
284
|
+
licenses:
|
285
|
+
- MIT
|
286
|
+
metadata: {}
|
287
|
+
post_install_message:
|
288
|
+
rdoc_options: []
|
289
|
+
require_paths:
|
290
|
+
- lib
|
291
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
292
|
+
requirements:
|
293
|
+
- - ">="
|
294
|
+
- !ruby/object:Gem::Version
|
295
|
+
version: '0'
|
296
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
297
|
+
requirements:
|
298
|
+
- - ">="
|
299
|
+
- !ruby/object:Gem::Version
|
300
|
+
version: '0'
|
301
|
+
requirements: []
|
302
|
+
rubyforge_project:
|
303
|
+
rubygems_version: 2.7.6
|
304
|
+
signing_key:
|
305
|
+
specification_version: 4
|
306
|
+
summary: Preservation features for Hydra
|
307
|
+
test_files: []
|