From b2fb8a8cb5dbdf35510c732c263b2bda3ff3dfa4 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Tue, 21 Feb 2023 09:10:37 -0500 Subject: [PATCH 01/16] Change request button to direct to new box picker form. --- public/views/aeon/_aeon_request_action.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/views/aeon/_aeon_request_action.html.erb b/public/views/aeon/_aeon_request_action.html.erb index 8972af6..6416c97 100644 --- a/public/views/aeon/_aeon_request_action.html.erb +++ b/public/views/aeon/_aeon_request_action.html.erb @@ -9,7 +9,7 @@ mapper = AeonRecordMapper.mapper_for(record) <% unless mapper.hide_button? %> <% if mapper.show_action? %> - <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?action=11&type=200", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> + <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?action=11&form=35", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> <% mapper.map.each do |name, value| %> <% if name.casecmp('requests').zero? %> <% value.each do |request| %> From 5d43b401136ae3a9244540432055cf8c58a62e14 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Tue, 21 Feb 2023 16:30:58 -0500 Subject: [PATCH 02/16] Update plugin to request only top containers, and to include locations when available --- public/models/aeon_record_mapper.rb | 64 +++++++++++-------- public/models/extended_request_client.rb | 7 ++ .../views/aeon/_aeon_request_action.html.erb | 7 +- 3 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 public/models/extended_request_client.rb diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 9c82f88..3fa622b 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -11,8 +11,10 @@ def initialize(record) @container_instances = find_container_instances(record['json'] || {}) end + ExtendedRequestClient.init + def archivesspace - ArchivesSpaceClient.instance + ExtendedRequestClient.instance end def self.register_for_record_type(type) @@ -89,9 +91,9 @@ def hide_button? return true if self.repo_settings[:hide_button_for_accessions] && record.is_a?(Accession) if (types = self.repo_settings[:hide_button_for_access_restriction_types]) - notes = (record.json['notes'] || []).select {|n| n['type'] == 'accessrestrict' && n.has_key?('rights_restriction')} - .map {|n| n['rights_restriction']['local_access_restriction_type']} - .flatten.uniq + notes = (record.json['notes'] || []).select {|n| n['type'] == 'accessrestrict' && n.has_key?('rights_restriction')} + .map {|n| n['rights_restriction']['local_access_restriction_type']} + .flatten.uniq # hide if the record notes have any of the restriction types listed in config return true if (notes - types).length < notes.length @@ -101,7 +103,7 @@ def hide_button? end # Determines if the :requestable_archival_record_levels setting is present - # and exlcudes the 'level' property of the current record. This method is + # and excludes the 'level' property of the current record. This method is # not used by this class, because not all implementations of "abstract_archival_object" # have a "level" property that uses the "archival_record_level" enumeration. def requestable_based_on_archival_record_level? @@ -149,15 +151,17 @@ def show_action? if !self.repo_settings Rails.logger.info("Aeon Fulfillment Plugin") { "Could not find plugin settings for the repository: \"#{self.repo_code}\"." } else + # If this is an accession, and we're hiding the request button for thise, then we should always return false + if (record.is_a?(Accession) && self.repo_settings.fetch(:hide_button_for_accessions, false)) + Rails.logger.debug("Aeon Fulfillment Plugin") { "Hiding button for accession." } + return false + end + Rails.logger.debug("Aeon Fulfillment Plugin") { "Checking for top containers" } has_top_container = record.is_a?(Container) || self.container_instances.any? - only_top_containers = self.repo_settings[:requests_permitted_for_containers_only] || false - - # if we're showing the button for accessions, and this is an accession, - # then don't require containers - only_top_containers = self.repo_settings.fetch(:hide_button_for_accessions, false) if record.is_a?(Accession) + only_top_containers = self.repo_settings[:requests_permitted_for_containers_only] || self.repo_settings[:top_container_mode] || false Rails.logger.debug("Aeon Fulfillment Plugin") { "Containers found? #{has_top_container}" } Rails.logger.debug("Aeon Fulfillment Plugin") { "only_top_containers? #{only_top_containers}" } @@ -362,6 +366,12 @@ def json_fields request["instance_top_container_type_#{instance_count}"] = top_container_resolved['type'] request["instance_top_container_uri_#{instance_count}"] = top_container_resolved['uri'] + locations = top_container_resolved["container_locations"] + if locations.any? + location_id = locations.sort_by { |l| l["start_date"]}.last()["ref"] + location = archivesspace.get_location(location_id) + request["instance_top_container_location"] = location["title"] + end collection = top_container_resolved['collection'] if collection @@ -401,7 +411,7 @@ def json_fields # method will recurse up the record's resource tree, until it finds a record that does # have top container instances, and will pull the list of instances from there. def find_container_instances (record_json) - + current_uri = record_json['uri'] Rails.logger.info("Aeon Fulfillment Plugin") { "Checking \"#{current_uri}\" for Top Container instances..." } @@ -415,21 +425,25 @@ def find_container_instances (record_json) return instances end - parent_uri = '' - - if record_json['parent'].present? - parent_uri = record_json['parent']['ref'] - parent_uri = record_json['parent'] unless parent_uri.present? - elsif record_json['resource'].present? - parent_uri = record_json['resource']['ref'] - parent_uri = record_json['resource'] unless parent_uri.present? - end + # If we're in top container mode, we can skip this step, + # since we only want to present containers associated with the current record. + if (!self.repo_settings[:top_container_mode]) + parent_uri = '' + + if record_json['parent'].present? + parent_uri = record_json['parent']['ref'] + parent_uri = record_json['parent'] unless parent_uri.present? + elsif record_json['resource'].present? + parent_uri = record_json['resource']['ref'] + parent_uri = record_json['resource'] unless parent_uri.present? + end - if parent_uri.present? - Rails.logger.debug("Aeon Fulfillment Plugin") { "No Top Container instances found. Checking parent. (#{parent_uri})" } - parent = archivesspace.get_record(parent_uri) - parent_json = parent['json'] - return find_container_instances(parent_json) + if parent_uri.present? + Rails.logger.debug("Aeon Fulfillment Plugin") { "No Top Container instances found. Checking parent. (#{parent_uri})" } + parent = archivesspace.get_record(parent_uri) + parent_json = parent['json'] + return find_container_instances(parent_json) + end end Rails.logger.debug("Aeon Fulfillment Plugin") { "No Top Container instances found." } diff --git a/public/models/extended_request_client.rb b/public/models/extended_request_client.rb new file mode 100644 index 0000000..c288822 --- /dev/null +++ b/public/models/extended_request_client.rb @@ -0,0 +1,7 @@ +class ExtendedRequestClient < ArchivesSpaceClient + def get_location(location_id) + url = build_url("#{location_id}") + results = do_search(url, true) + results + end +end \ No newline at end of file diff --git a/public/views/aeon/_aeon_request_action.html.erb b/public/views/aeon/_aeon_request_action.html.erb index 8972af6..3b113df 100644 --- a/public/views/aeon/_aeon_request_action.html.erb +++ b/public/views/aeon/_aeon_request_action.html.erb @@ -4,12 +4,17 @@ Rails.logger.info("Aeon Fulfillment Plugin") { "Initializing Plugin..." } mapper = AeonRecordMapper.mapper_for(record) %> + + + <%= javascript_include_tag "#{@base_url}/assets/js/aeon_request_action.js" %> <% unless mapper.hide_button? %> <% if mapper.show_action? %> - <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?action=11&type=200", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> + <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?#{mapper.repo_settings.fetch(:top_container_mode, false) ? "action=10&form=35" : "action=11&type=200"}", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> <% mapper.map.each do |name, value| %> <% if name.casecmp('requests').zero? %> <% value.each do |request| %> From fb4d4addaad5c5d41659019802e5806d8b8b4cc2 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Wed, 22 Feb 2023 16:49:52 -0500 Subject: [PATCH 03/16] Handle mapping for location, restrictions, digital objects --- public/models/aeon_record_mapper.rb | 48 +++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 3fa622b..6fdb1ee 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -273,6 +273,34 @@ def record_fields .join("; ") end + resolved_top_container = self.record.resolved_top_container + mappings['userestrict'] = '' + if (resolved_top_container) + resolved_top_container['active_restrictions'].each do |ar| + if (ar['linked_records']['_resolved']) + userestrict = ar['linked_records']['_resolved']['notes'] + .select { |note| note['type'] == 'userestrict' and note['subnotes'] } + .map { |note| note['subnotes'] }.flatten + .select { |subnote| subnote['content'].present? } + .map { |subnote| subnote['content'] }.flatten + .join("; ") + mappings['userestrict'] = userestrict + end + # TODO remove once Valerie confirms it's not needed + # ar['linked_records'] + # .select{ |lr| lr['_resolved'] } + # .each do |lr| + # userestrict = lr['_resolved']['notes'] + # .select { |note| note['type'] == 'userestrict' and note['subnotes'] } + # .map { |note| note['subnotes'] }.flatten + # .select { |subnote| subnote['content'].present? } + # .map { |subnote| subnote['content'] }.flatten + # .join("; ") + # end + end + end + #resolved_top_container.active_restrictions[*].linked_records[*]._resolved.notes[type=userestrict].subnotes[*].content + mappings end @@ -318,6 +346,15 @@ def json_fields } end + if json['rights_statements'] + mappings['rights_type'] = json['rights_statements'].map{ |r| r['rights_type']}.uniq.join(',') + end + + digital_instances = json['instances'].select { |instance| instance['instance_type'] == 'digital_object'} + if (digital_instances.any?) + mappings["digital_objects"] = digital_instances.map{|d| d['digital_object']['ref']}.join(';') + end + mappings['restrictions_apply'] = json['restrictions_apply'] mappings['display_string'] = json['display_string'] @@ -328,7 +365,7 @@ def json_fields .each_with_index .map { |instance, i| request = {} - + instance_count = i + 1 request['Request'] = "#{instance_count}" @@ -366,11 +403,18 @@ def json_fields request["instance_top_container_type_#{instance_count}"] = top_container_resolved['type'] request["instance_top_container_uri_#{instance_count}"] = top_container_resolved['uri'] + request["requestable_#{instance_count}"] = (top_container_resolved['active_restrictions'] || []) + .select{ |ar| ar['local_access_restriction_type'] } + .flatten.uniq + .select{ |ar| (self.repo_settings[:hide_button_for_access_restriction_types] || []).include?(ar)} + .empty? + locations = top_container_resolved["container_locations"] if locations.any? location_id = locations.sort_by { |l| l["start_date"]}.last()["ref"] location = archivesspace.get_location(location_id) - request["instance_top_container_location"] = location["title"] + request["instance_top_container_location_#{instance_count}"] = location["title"] + request["instance_top_container_location_id_#{instance_count}"] = location_id end collection = top_container_resolved['collection'] From c5947bf4c01e5d9cfa2682f5c133ec8d08a929d3 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Thu, 23 Feb 2023 16:04:01 -0500 Subject: [PATCH 04/16] Improve display logic when button is disabled --- public/models/aeon_archival_object_mapper.rb | 5 - public/models/aeon_record_mapper.rb | 125 ++++++++++-------- public/models/aeon_resource_mapper.rb | 7 - .../views/aeon/_aeon_request_action.html.erb | 42 +++--- 4 files changed, 87 insertions(+), 92 deletions(-) diff --git a/public/models/aeon_archival_object_mapper.rb b/public/models/aeon_archival_object_mapper.rb index 19c74ad..cced8c5 100644 --- a/public/models/aeon_archival_object_mapper.rb +++ b/public/models/aeon_archival_object_mapper.rb @@ -6,11 +6,6 @@ def initialize(archival_object) super(archival_object) end - # Override of #show_action? from AeonRecordMapper - def show_action? - return false if !super - return self.requestable_based_on_archival_record_level? - end # Override for AeonRecordMapper json_fields method. def json_fields diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 6fdb1ee..2ce083a 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -81,25 +81,88 @@ def user_defined_fields mappings end + def unrequestable_display_message + if !self.requestable_based_on_archival_record_level? + if (message = self.repo_settings[:disallowed_record_level_message]) + return message + else + return "Records of this type cannot be requested." + end + elsif !self.record_has_top_containers? + if (message = self.repo_settings[:no_containers_message]) + return message + else + return "No requestable containers are associated with this record." + end + elsif self.record_has_restrictions? + if (message = self.repo_settings[:restrictions_message]) + return message + else + return "Restrictions prevent access to this material." + end + end + return "" + end + # This method tests whether the button should be hidden. This determination is based # on the settings for the repository and defaults to false. def hide_button? # returning false to maintain the original behavior return false unless self.repo_settings - return true if self.repo_settings[:hide_request_button] - return true if self.repo_settings[:hide_button_for_accessions] && record.is_a?(Accession) + if self.repo_settings[:hide_request_button] + return true + elsif (self.repo_settings[:hide_button_for_accessions] == true && record.is_a?(Accession)) + return true + elsif self.requestable_based_on_archival_record_level? == false + return true + elsif self.record_has_top_containers? == false + return true + elsif self.record_has_restrictions? == true + return true + end + return false + end + + def record_has_top_containers? + return record.is_a?(Container) || self.container_instances.any? + end + def record_has_restrictions? if (types = self.repo_settings[:hide_button_for_access_restriction_types]) notes = (record.json['notes'] || []).select {|n| n['type'] == 'accessrestrict' && n.has_key?('rights_restriction')} .map {|n| n['rights_restriction']['local_access_restriction_type']} .flatten.uniq - # hide if the record notes have any of the restriction types listed in config - return true if (notes - types).length < notes.length + # hide if the record notes have any of the restriction types listed in config + access_restrictions = true if (notes - types).length < notes.length + + # check each top container for restrictions + # if all of them are unrequestable, we should hide the request button for this record + has_requestable_container = false + if (instances = self.container_instances) + instances.each do |instance| + if (container = instance['sub_container']) + if (top_container = container['top_container']) + if (top_container_resolved = top_container['_resolved']) + tc_has_restrictions = (top_container_resolved['active_restrictions'] || []) + .map{ |ar| ar['local_access_restriction_type'] } + .flatten.uniq + .select{ |ar| types.include?(ar)} + .any? + if tc_has_restrictions == false + has_requestable_container = true + end + end + end + end + end + end + + return access_restrictions || !has_requestable_container end - false + return false end # Determines if the :requestable_archival_record_levels setting is present @@ -143,42 +206,6 @@ def requestable_based_on_archival_record_level? true end - # If #show_action? returns false, then the button is shown disabled - def show_action? - begin - Rails.logger.debug("Aeon Fulfillment Plugin") { "Checking for plugin settings for the repository" } - - if !self.repo_settings - Rails.logger.info("Aeon Fulfillment Plugin") { "Could not find plugin settings for the repository: \"#{self.repo_code}\"." } - else - # If this is an accession, and we're hiding the request button for thise, then we should always return false - if (record.is_a?(Accession) && self.repo_settings.fetch(:hide_button_for_accessions, false)) - Rails.logger.debug("Aeon Fulfillment Plugin") { "Hiding button for accession." } - return false - end - - Rails.logger.debug("Aeon Fulfillment Plugin") { "Checking for top containers" } - - has_top_container = record.is_a?(Container) || self.container_instances.any? - - only_top_containers = self.repo_settings[:requests_permitted_for_containers_only] || self.repo_settings[:top_container_mode] || false - - Rails.logger.debug("Aeon Fulfillment Plugin") { "Containers found? #{has_top_container}" } - Rails.logger.debug("Aeon Fulfillment Plugin") { "only_top_containers? #{only_top_containers}" } - - return (has_top_container || !only_top_containers) - end - - rescue Exception => e - Rails.logger.error("Aeon Fulfillment Plugin") { "Failed to create Aeon Request action." } - Rails.logger.error(e.message) - Rails.logger.error(e.backtrace.inspect) - - end - - false - end - # Pulls data from the contained record def map @@ -286,20 +313,8 @@ def record_fields .join("; ") mappings['userestrict'] = userestrict end - # TODO remove once Valerie confirms it's not needed - # ar['linked_records'] - # .select{ |lr| lr['_resolved'] } - # .each do |lr| - # userestrict = lr['_resolved']['notes'] - # .select { |note| note['type'] == 'userestrict' and note['subnotes'] } - # .map { |note| note['subnotes'] }.flatten - # .select { |subnote| subnote['content'].present? } - # .map { |subnote| subnote['content'] }.flatten - # .join("; ") - # end end end - #resolved_top_container.active_restrictions[*].linked_records[*]._resolved.notes[type=userestrict].subnotes[*].content mappings end @@ -402,9 +417,9 @@ def json_fields request["instance_top_container_barcode_#{instance_count}"] = top_container_resolved['barcode'] request["instance_top_container_type_#{instance_count}"] = top_container_resolved['type'] request["instance_top_container_uri_#{instance_count}"] = top_container_resolved['uri'] - + request["requestable_#{instance_count}"] = (top_container_resolved['active_restrictions'] || []) - .select{ |ar| ar['local_access_restriction_type'] } + .map{ |ar| ar['local_access_restriction_type'] } .flatten.uniq .select{ |ar| (self.repo_settings[:hide_button_for_access_restriction_types] || []).include?(ar)} .empty? diff --git a/public/models/aeon_resource_mapper.rb b/public/models/aeon_resource_mapper.rb index 64038b1..36d8e20 100644 --- a/public/models/aeon_resource_mapper.rb +++ b/public/models/aeon_resource_mapper.rb @@ -8,13 +8,6 @@ def initialize(resource) super(resource) end - # Override of #show_action? from AeonRecordMapper - def show_action? - return false if !super - - self.requestable_based_on_archival_record_level? - end - # Override for AeonRecordMapper json_fields method. def json_fields mappings = super diff --git a/public/views/aeon/_aeon_request_action.html.erb b/public/views/aeon/_aeon_request_action.html.erb index 3b113df..424cd0b 100644 --- a/public/views/aeon/_aeon_request_action.html.erb +++ b/public/views/aeon/_aeon_request_action.html.erb @@ -11,36 +11,28 @@ END OF PUI RECORD MODEL --> <%= javascript_include_tag "#{@base_url}/assets/js/aeon_request_action.js" %> -<% unless mapper.hide_button? %> - - <% if mapper.show_action? %> - <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?#{mapper.repo_settings.fetch(:top_container_mode, false) ? "action=10&form=35" : "action=11&type=200"}", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> - <% mapper.map.each do |name, value| %> - <% if name.casecmp('requests').zero? %> - <% value.each do |request| %> - <% request.each do |request_param, request_value| %> - - <% end %> +<% if mapper.hide_button? %> +
+ <%= mapper.unrequestable_display_message %> +
+<% else %> + + <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?#{mapper.repo_settings.fetch(:top_container_mode, false) ? "action=10&form=35" : "action=11&type=200"}", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> + <% mapper.map.each do |name, value| %> + <% if name.casecmp('requests').zero? %> + <% value.each do |request| %> + <% request.each do |request_param, request_value| %> + <% end %> - <% else %> - <% end %> + <% else %> + <% end %> - - <% end %> - <% else %> - -
- -
- + <% end %> <% end %> From d48dd140ea355704f2244b7d6b75615805d251f8 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Thu, 23 Feb 2023 16:36:23 -0500 Subject: [PATCH 05/16] Shorten default messageS --- public/models/aeon_record_mapper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 2ce083a..7ee8c94 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -86,19 +86,19 @@ def unrequestable_display_message if (message = self.repo_settings[:disallowed_record_level_message]) return message else - return "Records of this type cannot be requested." + return "Not requestable" end elsif !self.record_has_top_containers? if (message = self.repo_settings[:no_containers_message]) return message else - return "No requestable containers are associated with this record." + return "No requestable containers" end elsif self.record_has_restrictions? if (message = self.repo_settings[:restrictions_message]) return message else - return "Restrictions prevent access to this material." + return "Access restricted" end end return "" From 4fb1df500c2b2ab15e82d75d9a66dbed90a00a26 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Fri, 24 Feb 2023 15:19:02 -0500 Subject: [PATCH 06/16] Fix mappings --- public/models/aeon_record_mapper.rb | 52 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 7ee8c94..00b4468 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -293,27 +293,26 @@ def record_fields mappings['repo_name'] = resolved_repository['name'] end - if record['creators'] + if self.record['creators'] mappings['creators'] = self.record['creators'] .select { |cr| cr.present? } .map { |cr| cr.strip } .join("; ") end - resolved_top_container = self.record.resolved_top_container - mappings['userestrict'] = '' - if (resolved_top_container) - resolved_top_container['active_restrictions'].each do |ar| - if (ar['linked_records']['_resolved']) - userestrict = ar['linked_records']['_resolved']['notes'] - .select { |note| note['type'] == 'userestrict' and note['subnotes'] } - .map { |note| note['subnotes'] }.flatten - .select { |subnote| subnote['content'].present? } - .map { |subnote| subnote['content'] }.flatten - .join("; ") - mappings['userestrict'] = userestrict - end - end + if self.record.dates + mappings['date_expression'] = self.record.dates + .select{ |date| date['date_type'] == 'single' or date['date_type'] == 'inclusive'} + .map{ |date| date['final_expression'] } + .join(';') + end + + if (self.record.notes['userestrict']) + mappings['userestrict'] = self.record.notes['userestrict'] + .map { |note| note['subnotes'] }.flatten + .select { |subnote| subnote['content'].present? and subnote['publish'] == true } + .map { |subnote| subnote['content'] }.flatten + .join("; ") end mappings @@ -335,7 +334,7 @@ def json_fields notes = json['notes'] if notes mappings['physical_location_note'] = notes - .select { |note| note['type'] == 'physloc' and note['content'].present? } + .select { |note| note['type'] == 'physloc' and note['content'].present? and note['publish'] == true } .map { |note| note['content'] } .flatten .join("; ") @@ -344,21 +343,19 @@ def json_fields .select { |note| note['type'] == 'accessrestrict' and note['subnotes'] } .map { |note| note['subnotes'] } .flatten - .select { |subnote| subnote['content'].present? } + .select { |subnote| subnote['content'].present? and subnote['publish'] == true} .map { |subnote| subnote['content'] } .flatten .join("; ") end - if json['dates'] - json['dates'] - .select { |date| date['expression'].present? } - .group_by { |date| date['label'] } - .each { |label, dates| - mappings["#{label}_date"] = dates - .map { |date| date['expression'] } - .join("; ") - } + if json['linked_agents'] + mappings['creators'] = json['linked_agents'] + .select { |l| l['role'] == 'creator' and l['_resolved'] } + .map { |l| l['_resolved']['names'] }.flatten + .select { |n| n['is_display_name'] == true} + .map { |n| n['sort_name']} + .join("; ") end if json['rights_statements'] @@ -428,8 +425,9 @@ def json_fields if locations.any? location_id = locations.sort_by { |l| l["start_date"]}.last()["ref"] location = archivesspace.get_location(location_id) - request["instance_top_container_location_#{instance_count}"] = location["title"] + request["instance_top_container_location_#{instance_count}"] = location['title'] request["instance_top_container_location_id_#{instance_count}"] = location_id + request["instance_top_container_location_building_#{instance_count}"] = location['building'] end collection = top_container_resolved['collection'] From 6a9d62f443c756755459ca36637d7db9a44147f1 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Mon, 27 Feb 2023 11:53:52 -0500 Subject: [PATCH 07/16] Map location notes, old restrictions checkbox --- public/models/aeon_archival_object_mapper.rb | 22 ++++++++++++++++++++ public/models/aeon_record_mapper.rb | 6 +++++- public/models/aeon_resource_mapper.rb | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/public/models/aeon_archival_object_mapper.rb b/public/models/aeon_archival_object_mapper.rb index cced8c5..07800e8 100644 --- a/public/models/aeon_archival_object_mapper.rb +++ b/public/models/aeon_archival_object_mapper.rb @@ -20,6 +20,8 @@ def json_fields mappings['repository_processing_note'] = json['repository_processing_note'] end + mappings['restrictions_apply'] = restrictions_apply? + mappings end @@ -31,4 +33,24 @@ def record_fields mappings end + + def restrictions_apply? + + if self.record.json['restrictions_apply'] + return true + end + + self.record['ancestors'].each do |ancestor| + Rails.logger.info("Aeon Fulfillment Plugin") { "Logging ancestor #{ancestor}" } + ancestor_record = archivesspace.get_record(ancestor) + Rails.logger.info("Aeon Fulfillment Plugin") { ancestor_record.to_yaml } + + + + if (ancestor_record.json['restrictions_apply'] == true or ancestor_record.json['restrictions'] == true) + return true + end + end + return false + end end diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 00b4468..842a71d 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -414,7 +414,11 @@ def json_fields request["instance_top_container_barcode_#{instance_count}"] = top_container_resolved['barcode'] request["instance_top_container_type_#{instance_count}"] = top_container_resolved['type'] request["instance_top_container_uri_#{instance_count}"] = top_container_resolved['uri'] - + + if (top_container_resolved['container_locations']) + request["instance_top_container_location_note_#{instance_count}"] = top_container_resolved['container_locations'].map{ |l| l['note']}.join{';'} + end + request["requestable_#{instance_count}"] = (top_container_resolved['active_restrictions'] || []) .map{ |ar| ar['local_access_restriction_type'] } .flatten.uniq diff --git a/public/models/aeon_resource_mapper.rb b/public/models/aeon_resource_mapper.rb index 36d8e20..dfd2a4a 100644 --- a/public/models/aeon_resource_mapper.rb +++ b/public/models/aeon_resource_mapper.rb @@ -41,6 +41,7 @@ def json_fields mappings['finding_aid_series_statement'] = json['finding_aid_series_statement'] mappings['finding_aid_status'] = json['finding_aid_status'] mappings['finding_aid_note'] = json['finding_aid_note'] + mappings['restrictions_apply'] = json['restrictions'] mappings end From 62ec7fb88341b330d6dc06fed7e6edd92bb2bb36 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Thu, 2 Mar 2023 08:57:08 -0500 Subject: [PATCH 08/16] Replace date logic --- public/models/aeon_record_mapper.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 842a71d..0aa0a73 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -349,6 +349,18 @@ def json_fields .join("; ") end + if json['dates'] + json['dates'] + .select { |date| date['expression'].present? } + .group_by { |date| date['label'] } + .each { |label, dates| + mappings["#{label}_date"] = dates + .map { |date| date['expression'] } + .join("; ") + } + end + + if json['linked_agents'] mappings['creators'] = json['linked_agents'] .select { |l| l['role'] == 'creator' and l['_resolved'] } @@ -359,7 +371,7 @@ def json_fields end if json['rights_statements'] - mappings['rights_type'] = json['rights_statements'].map{ |r| r['rights_type']}.uniq.join(',') + mappings['rights_type'] = json['rights_statements'].map{ |r| r['rights_type']}.uniq.join(';') end digital_instances = json['instances'].select { |instance| instance['instance_type'] == 'digital_object'} From ba3ace6deca3bad1481cc488483650ef764845a0 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Thu, 2 Mar 2023 08:57:18 -0500 Subject: [PATCH 09/16] Update Readme --- Readme.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 2e1ac12..e67d5d6 100644 --- a/Readme.md +++ b/Readme.md @@ -23,7 +23,11 @@ 8. [`:aeon_site_code`](#aeonsitecode) 9. [`:hide_button_for_access_restriction_types`](#hidebuttonforaccessrestrictiontypes) 10. [`:requestable_archival_record_levels`](#requestablearchivalrecordlevels) - 11. [`:user_defined_fields`](#userdefinedfields) + 11. [`:top_container_mode`](#topcontainermode) + 12. [`:disallowed_record_level_message`](#disallowedrecordlevelmessage) + 13. [`:no_containers_message`](#nocontainersmessage) + 14. [`:restrictions_message`](#restrictionsmessage) + 15. [`:user_defined_fields`](#userdefinedfields) 2. [Other Configuration Options](#other-configuration-options) 1. [`:aeon_fulfillment_record_types`](#aeonfulfillmentrecordtypes) 2. [`:aeon_fulfillment_button_position`](#aeonfulfillmentbuttonposition) @@ -268,8 +272,8 @@ sent. #### `:hide_button_for_access_restriction_types` This setting allows the request button to be hidden for any records that have -any of the listed local access restriction types. The value of this config item -should be an array of restriction types, for example: +any of the listed values in the local_access_restriction_type field of the rights_restriction +of the accessrestrict note. The value of this config item should be an array of restriction types, for example: `:hide_button_for_access_restriction_types => ['RestrictedSpecColl']` @@ -337,6 +341,30 @@ AppConfig[:aeon_fulfillment] = { } ``` +#### `:top_container_mode` + +This true/false setting controls whether or not the new top container mode is active for the given repository. This mode has two effects: + +- Only top containers associated with the current record are requestable. If no top containers are associated with the current record, then the request button will be replaced by a message (see :no_containers_message setting below). + +- When the user clicks the Aeon Request button, they will be taken to the new Aeon Box-Picker form to submit their request(s). + +If this setting is true, then the :requests_permitted_for_containers_only should also be set to true. + +#### `:disallowed_record_level_message` + +This is the message that will be displayed instead of the Aeon Request button if the current record cannot be requested due to the values listed in the :requestable_archival_record_levels setting. If no value is provided, the default value will be "Not requestable". The message should be kept short (30 characters or less) for best appearance. + + +#### `:no_containers_message` + +This is the message that will be displayed instead of the Aeon Request button if the current record has no associated topcontainers and :top_container_mode is active. If no value is provided, the default value will be "No requestable containers". The message should be kept short (30 characters or less) for best appearance. + +#### `:restrictions_message` + +This is the message that will be displayed instead of the Aeon Request button if the current record cannot be requested because it has active restrictions matching the values in the :hide_button_for_access_restriction_types setting. If no value is provided, the default value will be "Access Restricted". The message should be kept short (30 characters or less) for best appearance. + + #### `:user_defined_fields` This setting allows sites to specify which user defined fields are imported. @@ -535,6 +563,18 @@ records. of values that could appear in place of the `{date_label}` placeholder is controlled by the `date_label` enumeration of your ArchivesSpace installation. +- `date_expression` + - semi-colon (`;`) separated string list + - contains the combined final_expressions of the single and inclusive dates associated with the record. +- `userestrict` + - semi-colon (`;`) separated string list + - contains the combined contents of all published userestrict notes associated with the record. +- `rights_type` + - semi-colon (`;`) separated string list + - contains the combined rights_type values of all rights statements associated with the record. +- `digital_objects` + - semi-colon (`;`) separated string list + - contains the IDs of all digital objects associated with the record. The following fields are common to both Accession records and Archival Object records, but are based on the number of instances associated with the record. @@ -567,6 +607,10 @@ and the values of each may differ from instance to instance. - `instance_top_container_collection_display_string` (semi-colon (`;`) separated string list) - `instance_top_container_series_identifer` (semi-colon (`;`) separated string list) - `instance_top_container_series_display_string` (semi-colon (`;`) separated string list) +- `instance_top_container_location_note` +- `instance_top_container_location_title` +- `instance_top_container_location_id` +- `instance_top_container_location_building` ### Archival Object Fields From 9645150f41c9fc35fe9a1a0422a63335205583ea Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Thu, 2 Mar 2023 16:23:09 -0500 Subject: [PATCH 10/16] Update changelog --- Readme.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index e67d5d6..a72dfc1 100644 --- a/Readme.md +++ b/Readme.md @@ -1,8 +1,8 @@ # ArchivesSpace Request Fulfillment via Aeon -**Version:** 20190529 +**Version:** 20230302 -**Last Updated:** May 29, 2019 +**Last Updated:** March 2, 2023 ## Table of Contents @@ -147,6 +147,9 @@ ArchivesSpace may cause changes in the functionality of this plugin. - Added the `:user_defined_fields` setting - **20190529** - Bug fixes for compatibility with ArchivesSpace v2.6.0 RC1 +- **20230302** + - Added `:top_container_mode` setting to support new Aeon Archival Request form. + - Added some additional mapping options. ## Configuring Plugin Settings From 33c799eda22b9c4124c93e5138b5855d4f7034d0 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Mon, 3 Apr 2023 16:41:45 -0400 Subject: [PATCH 11/16] Update readme --- Readme.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Readme.md b/Readme.md index a72dfc1..8a42d78 100644 --- a/Readme.md +++ b/Readme.md @@ -11,7 +11,8 @@ 1. [Table of Contents](#table-of-contents) 2. [Overview](#overview) 3. [Changelog](#changelog) - 4. [Configuring Plugin Settings](#configuring-plugin-settings) + 4. [Requirements](#requirements) + 5. [Configuring Plugin Settings](#configuring-plugin-settings) 1. [Per Repository Configuration Options](#per-repository-configuration-options) 1. [`:aeon_web_url`](#aeonweburl) 2. [`:aeon_return_link_label`](#aeonreturnlinklabel) @@ -32,16 +33,16 @@ 1. [`:aeon_fulfillment_record_types`](#aeonfulfillmentrecordtypes) 2. [`:aeon_fulfillment_button_position`](#aeonfulfillmentbuttonposition) 3. [Example Configuration](#example-configuration) - 5. [Aeon Remote Authentication Configurations](#aeon-remote-authentication-configurations) - 6. [Imported Fields](#imported-fields) + 6. [Aeon Remote Authentication Configurations](#aeon-remote-authentication-configurations) + 7. [Imported Fields](#imported-fields) 1. [Common Fields](#common-fields) 2. [Archival Object Fields](#archival-object-fields) 3. [Accession Fields](#accession-fields) 4. [Resource Fields](#resource-fields) 5. [User Defined Fields](#user-defined-fields) - 7. [OpenURL Mappings](#openurl-mappings) - 8. [Custom Mappers](#custom-mappers) - 9. [Configuring the Aeon Request Form Used](#configuring-the-aeon-request-form-used) + 8. [OpenURL Mappings](#openurl-mappings) + 9. [Custom Mappers](#custom-mappers) + 10. [Configuring the Aeon Request Form Used](#configuring-the-aeon-request-form-used) ## Overview @@ -62,7 +63,7 @@ options for the built in PUI requesting functionality, it is also possible to configure some repositories to continue using the built in PUI requesting feature for archival objects while allowing other repositories to use Aeon. -This plugin has been tested on ArchivesSpace version 2.2.0. Future releases of +This plugin has been tested on ArchivesSpace version 3.3.1, and requires Aeon Server version 5.2.0 or greater. Future releases of ArchivesSpace may cause changes in the functionality of this plugin. @@ -150,7 +151,11 @@ ArchivesSpace may cause changes in the functionality of this plugin. - **20230302** - Added `:top_container_mode` setting to support new Aeon Archival Request form. - Added some additional mapping options. - + +## Requirements + + + ## Configuring Plugin Settings ***Please note that the Aeon OpenURLMapping table must be configured in the Customization Manager From c56bfc947e9d2577dac114b511a09898ee0689b8 Mon Sep 17 00:00:00 2001 From: asmith-atlas Date: Mon, 3 Apr 2023 16:56:01 -0400 Subject: [PATCH 12/16] Apply unsaved changes --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 8a42d78..b013263 100644 --- a/Readme.md +++ b/Readme.md @@ -154,7 +154,8 @@ ArchivesSpace may cause changes in the functionality of this plugin. ## Requirements - +- Aeon Server 5.2.0 or greater +- ArchivesSpace 3.3.1 ## Configuring Plugin Settings From 9fc7ebd86cb7057b52fb627aa7a0e796725606b8 Mon Sep 17 00:00:00 2001 From: asmith-atlas <59025599+asmith-atlas@users.noreply.github.com> Date: Fri, 5 May 2023 09:25:42 -0400 Subject: [PATCH 13/16] Add language field mapping --- public/models/aeon_accession_mapper.rb | 8 ++++++-- public/models/aeon_record_mapper.rb | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/public/models/aeon_accession_mapper.rb b/public/models/aeon_accession_mapper.rb index 1711f80..fa18d0a 100644 --- a/public/models/aeon_accession_mapper.rb +++ b/public/models/aeon_accession_mapper.rb @@ -17,6 +17,12 @@ def json_fields .reject {|id_comp| id_comp.blank?} .join('-') + language = json['language'] + if language + Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping language JSON: #{language}" } + mappings['language'] = language + end + mappings end @@ -32,8 +38,6 @@ def record_fields mappings['access_restrictions_note'] = record.access_restrictions_note end - mappings['language'] = self.record['language'] - mappings end end diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 0aa0a73..eb588ca 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -329,7 +329,23 @@ def json_fields Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping Record JSON: #{json}" } - mappings['language'] = json['language'] + lang_materials = json['lang_materials'] + if lang_materials + Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping Language JSON: #{lang_materials}" } + + mappings['language'] = lang_materials + .select { |lm| lm['language_and_script'].present? and lm['language_and_script']['language'].present?} + .map{ |lm| lm['language_and_script']['language'] } + .flatten + .join(";") + end + + language = json['language'] + if language + Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping language JSON: #{language}" } + mappings['language'] = language + end + notes = json['notes'] if notes From 148ffacf0c89158cb55e76a268a2e6c88200b0c3 Mon Sep 17 00:00:00 2001 From: asmith-atlas <59025599+asmith-atlas@users.noreply.github.com> Date: Fri, 5 May 2023 09:31:56 -0400 Subject: [PATCH 14/16] Remove extra logging --- public/models/aeon_accession_mapper.rb | 1 - public/models/aeon_record_mapper.rb | 5 ----- 2 files changed, 6 deletions(-) diff --git a/public/models/aeon_accession_mapper.rb b/public/models/aeon_accession_mapper.rb index fa18d0a..8c0bc75 100644 --- a/public/models/aeon_accession_mapper.rb +++ b/public/models/aeon_accession_mapper.rb @@ -19,7 +19,6 @@ def json_fields language = json['language'] if language - Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping language JSON: #{language}" } mappings['language'] = language end diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index eb588ca..28758c4 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -327,12 +327,8 @@ def json_fields json = self.record.json return mappings unless json - Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping Record JSON: #{json}" } - lang_materials = json['lang_materials'] if lang_materials - Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping Language JSON: #{lang_materials}" } - mappings['language'] = lang_materials .select { |lm| lm['language_and_script'].present? and lm['language_and_script']['language'].present?} .map{ |lm| lm['language_and_script']['language'] } @@ -342,7 +338,6 @@ def json_fields language = json['language'] if language - Rails.logger.debug("Aeon Fulfillment Plugin") { "Mapping language JSON: #{language}" } mappings['language'] = language end From fd4bfea7dfcace38a7710c717ee2524ecf0a79bd Mon Sep 17 00:00:00 2001 From: asmith-atlas <59025599+asmith-atlas@users.noreply.github.com> Date: Tue, 9 May 2023 10:30:46 -0400 Subject: [PATCH 15/16] Fix logic for handling unconfigured repository --- public/models/aeon_record_mapper.rb | 8 +++ .../views/aeon/_aeon_request_action.html.erb | 52 ++++++++++--------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/public/models/aeon_record_mapper.rb b/public/models/aeon_record_mapper.rb index 0aa0a73..b0f4d11 100644 --- a/public/models/aeon_record_mapper.rb +++ b/public/models/aeon_record_mapper.rb @@ -82,6 +82,10 @@ def user_defined_fields end def unrequestable_display_message + if !(self.repo_settings) + return ""; + end + if !self.requestable_based_on_archival_record_level? if (message = self.repo_settings[:disallowed_record_level_message]) return message @@ -104,6 +108,10 @@ def unrequestable_display_message return "" end + def configured? + return true if self.repo_settings + end + # This method tests whether the button should be hidden. This determination is based # on the settings for the repository and defaults to false. def hide_button? diff --git a/public/views/aeon/_aeon_request_action.html.erb b/public/views/aeon/_aeon_request_action.html.erb index 424cd0b..3ccc5df 100644 --- a/public/views/aeon/_aeon_request_action.html.erb +++ b/public/views/aeon/_aeon_request_action.html.erb @@ -4,37 +4,39 @@ Rails.logger.info("Aeon Fulfillment Plugin") { "Initializing Plugin..." } mapper = AeonRecordMapper.mapper_for(record) %> - - - -<%= javascript_include_tag "#{@base_url}/assets/js/aeon_request_action.js" %> - -<% if mapper.hide_button? %> -
- <%= mapper.unrequestable_display_message %> -
-<% else %> - - <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?#{mapper.repo_settings.fetch(:top_container_mode, false) ? "action=10&form=35" : "action=11&type=200"}", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> - <% mapper.map.each do |name, value| %> - <% if name.casecmp('requests').zero? %> - <% value.each do |request| %> - <% request.each do |request_param, request_value| %> - +<% if mapper.configured? %> + + <%= javascript_include_tag "#{@base_url}/assets/js/aeon_request_action.js" %> + + <% if mapper.hide_button? %> +
+ <%= mapper.unrequestable_display_message %> +
+ <% else %> + + <%= form_tag "#{mapper.repo_settings[:aeon_web_url]}?#{mapper.repo_settings.fetch(:top_container_mode, false) ? "action=10&form=35" : "action=11&type=200"}", :id => 'aeon_request_sub', :target => (mapper.repo_settings.fetch(:request_in_new_tab, false) ? 'aeon_request' : '_self') do |f| %> + <% mapper.map.each do |name, value| %> + <% if name.casecmp('requests').zero? %> + <% value.each do |request| %> + <% request.each do |request_param, request_value| %> + + <% end %> <% end %> + <% else %> + <% end %> - <% else %> - <% end %> + + <% end %> - <% end %> - +<% else %> +<% + Rails.logger.info("Aeon Fulfillment Plugin") { "Plugin not configured." } +%> <% end %> <% From 657d35359be0632cd43b344a93318e78c79e61f0 Mon Sep 17 00:00:00 2001 From: asmith-atlas <59025599+asmith-atlas@users.noreply.github.com> Date: Wed, 10 May 2023 11:32:09 -0400 Subject: [PATCH 16/16] Update readme to describe language mapping --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index b013263..19dbca8 100644 --- a/Readme.md +++ b/Readme.md @@ -550,6 +550,9 @@ records. - `repo_code` - `repo_name` - `language` + - semi-colon (`;`) separated string list + - contains the content from the `language` elements listed in `lang_materials` + - for accessions, contains the single value in the `language` element - `restrictions_apply` (true/false value) - `display_string` - `creators`